From 1009b843632897fe81ae1e35750525eb24cdce25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sat, 23 Jan 2016 16:06:47 +0100 Subject: [PATCH 01/23] added new web controller for knowing the version of the web api --- YACReaderLibrary/headless/main.cpp | 11 +++++- .../server/controllers/versioncontroller.cpp | 10 ++++++ .../server/controllers/versioncontroller.h | 21 ++++++++++++ YACReaderLibrary/server/requestmapper.cpp | 34 ++++++++++++------- YACReaderLibrary/server/server.pri | 10 ++++-- 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 YACReaderLibrary/server/controllers/versioncontroller.cpp create mode 100644 YACReaderLibrary/server/controllers/versioncontroller.h diff --git a/YACReaderLibrary/headless/main.cpp b/YACReaderLibrary/headless/main.cpp index 20fe8a6e..a488174e 100644 --- a/YACReaderLibrary/headless/main.cpp +++ b/YACReaderLibrary/headless/main.cpp @@ -9,6 +9,8 @@ #include "console_ui_library_creator.h" +#include + #include "QsLog.h" #include "QsLogDest.h" @@ -118,7 +120,7 @@ int main( int argc, char ** argv ) QCommandLineParser parser; parser.setApplicationDescription(QCoreApplication::tr("\nYACReaderLibraryServer is the headless (no gui) version of YACReaderLibrary")); parser.addHelpOption(); - parser.addVersionOption(); + const QCommandLineOption versionOption = parser.addVersionOption(); parser.addPositionalArgument("command", "The command to execute. [start, create-library, update-library, add-library, remove-library, list-libraries]"); parser.parse(QCoreApplication::arguments()); @@ -126,6 +128,13 @@ int main( int argc, char ** argv ) const QStringList args = parser.positionalArguments(); const QString command = args.isEmpty() ? QString() : args.first(); + if(parser.isSet(versionOption)) + { + qout << "YACReaderLibraryServer" << " " << VERSION << endl; + + return 0; + } + if(command == "start") { QString destLog = YACReader::getSettingsPath()+"/yacreaderlibrary.log"; diff --git a/YACReaderLibrary/server/controllers/versioncontroller.cpp b/YACReaderLibrary/server/controllers/versioncontroller.cpp new file mode 100644 index 00000000..341923c7 --- /dev/null +++ b/YACReaderLibrary/server/controllers/versioncontroller.cpp @@ -0,0 +1,10 @@ +#include "versioncontroller.h" + +VersionController::VersionController() {} + +void VersionController::service(HttpRequest& request, HttpResponse& response) +{ + Q_UNUSED(request); + + response.writeText(SERVER_VERSION_NUMBER,true); +} diff --git a/YACReaderLibrary/server/controllers/versioncontroller.h b/YACReaderLibrary/server/controllers/versioncontroller.h new file mode 100644 index 00000000..d645b110 --- /dev/null +++ b/YACReaderLibrary/server/controllers/versioncontroller.h @@ -0,0 +1,21 @@ +#ifndef VERSIONCONTROLLER_H +#define VERSIONCONTROLLER_H + +#include "httprequest.h" +#include "httpresponse.h" +#include "httprequesthandler.h" + +#include + +class VersionController : public HttpRequestHandler { + Q_OBJECT + Q_DISABLE_COPY(VersionController); +public: + /** Constructor */ + VersionController(); + + /** Generates the response */ + void service(HttpRequest& request, HttpResponse& response); +}; + +#endif // VERSIONCONTROLLER_H diff --git a/YACReaderLibrary/server/requestmapper.cpp b/YACReaderLibrary/server/requestmapper.cpp index 66b03413..75bbe613 100644 --- a/YACReaderLibrary/server/requestmapper.cpp +++ b/YACReaderLibrary/server/requestmapper.cpp @@ -22,6 +22,7 @@ #include "controllers/errorcontroller.h" #include "controllers/comicdownloadinfocontroller.h" #include "controllers/synccontroller.h" +#include "controllers/versioncontroller.h" #include "db_helper.h" #include "yacreader_libraries.h" @@ -95,20 +96,21 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QByteArray path=request.getPath(); qDebug("RequestMapper: path=%s",path.data()); - QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content - QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info - QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info) - QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info) - QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic - QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info - QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory - QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation) - QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page - QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) + static const QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content + static const QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info + static const QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info) + static const QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info) + static const QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic + static const QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info + static const QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory + static const QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation) + static const QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page + static const QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) + static const QRegExp serverVersion("/version/?"); - QRegExp sync("/sync"); + static const QRegExp sync("/sync"); - QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe + static const QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe path = QUrl::fromPercentEncoding(path).toUtf8(); @@ -122,8 +124,14 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { } else { - if(sync.exactMatch(path)) + if(serverVersion.exactMatch(path)) + { + VersionController().service(request, response); + } + else if(sync.exactMatch(path)) + { SyncController().service(request, response); + } else { //se comprueba que la sesión sea la correcta con el fin de evitar accesos no autorizados diff --git a/YACReaderLibrary/server/server.pri b/YACReaderLibrary/server/server.pri index 4be20612..19eb50a8 100644 --- a/YACReaderLibrary/server/server.pri +++ b/YACReaderLibrary/server/server.pri @@ -15,7 +15,9 @@ HEADERS += \ $$PWD/controllers/covercontroller.h \ $$PWD/controllers/updatecomiccontroller.h \ $$PWD/controllers/comicdownloadinfocontroller.h \ - $$PWD/controllers/synccontroller.h + $$PWD/controllers/synccontroller.h \ + #v2 + $$PWD/controllers/versioncontroller.h SOURCES += \ $$PWD/static.cpp \ @@ -31,8 +33,12 @@ SOURCES += \ $$PWD/controllers/covercontroller.cpp \ $$PWD/controllers/updatecomiccontroller.cpp \ $$PWD/controllers/comicdownloadinfocontroller.cpp \ - $$PWD/controllers/synccontroller.cpp + $$PWD/controllers/synccontroller.cpp \ + #v2 + $$PWD/controllers/versioncontroller.cpp include(lib/bfLogging/bfLogging.pri) include(lib/bfHttpServer/bfHttpServer.pri) include(lib/bfTemplateEngine/bfTemplateEngine.pri) + +DEFINES += SERVER_VERSION_NUMBER=\\\"2.0\\\" From e9210bb366d4c10afc965fafe45c5b71a4483c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:04:40 +0100 Subject: [PATCH 02/23] added a new db helper method for knowing the number of elements in a folder --- YACReaderLibrary/db_helper.cpp | 32 ++++++++++++++++++++++++++++++++ YACReaderLibrary/db_helper.h | 1 + 2 files changed, 33 insertions(+) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index f46b589f..c781d01e 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -58,6 +58,38 @@ QList DBHelper::getFolderComicsFromLibrary(qulonglong libraryId, QSqlDatabase::removeDatabase(libraryPath); return list; } + +quint32 DBHelper::getNumChildrenFromFolder(qulonglong libraryId, qulonglong folderId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + quint32 result = 0; + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT count(*) FROM folder WHERE parentId = :parentId and id <> 1"); + selectQuery.bindValue(":parentId", folderId); + selectQuery.exec(); + + result += selectQuery.record().value(0).toULongLong(); + } + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT count(*) FROM comic c WHERE c.parentId = :parentId"); + selectQuery.bindValue(":parentId", folderId); + selectQuery.exec(); + + result += selectQuery.record().value(0).toULongLong(); + } + + db.close(); + QSqlDatabase::removeDatabase(libraryPath); + + return result; +} + qulonglong DBHelper::getParentFromComicFolderId(qulonglong libraryId, qulonglong id) { QString libraryPath = DBHelper::getLibraries().getPath(libraryId); diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h index 5eb2eae3..19611dc7 100644 --- a/YACReaderLibrary/db_helper.h +++ b/YACReaderLibrary/db_helper.h @@ -23,6 +23,7 @@ public: static QList getFolderSubfoldersFromLibrary(qulonglong libraryId, qulonglong folderId); static QList getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId); static QList getFolderComicsFromLibrary(qulonglong libraryId, qulonglong folderId, bool sort); + static quint32 getNumChildrenFromFolder(qulonglong libraryId, qulonglong folderId); static qulonglong getParentFromComicFolderId(qulonglong libraryId, qulonglong id); static ComicDB getComicInfo(qulonglong libraryId, qulonglong id); static QList getSiblings(qulonglong libraryId, qulonglong parentId); From e130698ee9b64118ed97e06da5bcd28f23c8e39e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:34:54 +0100 Subject: [PATCH 03/23] prepare db update for future 8.6 version --- YACReaderLibrary/db/data_base_management.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 8d18d478..3e343cda 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -686,6 +686,7 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) bool pre7 = false; bool pre7_1 = false; bool pre8 = false; + bool pre8_6 = false; if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.0")<0) pre7 = true; @@ -693,6 +694,8 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) pre7_1 = true; if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.0.0")<0) pre8 = true; + if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.6.0")<0) + pre8_6 = true; QSqlDatabase db = loadDatabaseFromFile(fullPath); bool returnValue = false; @@ -745,6 +748,13 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) { returnValue = returnValue && createV8Tables(db); } + + if(pre8_6) + { + QStringList columnDefs; + //TODO + //returnValue = returnValue && addColumns("folder", columnDefs, db); + } } db.close(); From b8031268d050f8bec7cd8563105cc223b2a9c1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:36:19 +0100 Subject: [PATCH 04/23] resort db tables creation --- YACReaderLibrary/db/data_base_management.cpp | 155 +++++++++---------- 1 file changed, 77 insertions(+), 78 deletions(-) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 3e343cda..1c29814c 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -124,99 +124,98 @@ QSqlDatabase DataBaseManagement::loadDatabaseFromFile(QString filePath) bool DataBaseManagement::createTables(QSqlDatabase & database) { - bool success = true; + bool success = true; - //FOLDER (representa una carpeta en disco) - { - QSqlQuery queryFolder(database); - queryFolder.prepare("CREATE TABLE folder (" - "id INTEGER PRIMARY KEY," - "parentId INTEGER NOT NULL," - "name TEXT NOT NULL," - "path TEXT NOT NULL," - //new 7.1 fields - "finished BOOLEAN DEFAULT 0," //reading - "completed BOOLEAN DEFAULT 1," //collecting - //-- - "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); - success = success && queryFolder.exec(); + { + //COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes) + QSqlQuery queryComicInfo(database); + queryComicInfo.prepare("CREATE TABLE comic_info (" + "id INTEGER PRIMARY KEY," + "title TEXT," - //COMIC INFO (representa la información de un cómic, cada cómic tendrá un idéntificador único formado por un hash sha1'de los primeros 512kb' + su tamaño en bytes) - QSqlQuery queryComicInfo(database); - queryComicInfo.prepare("CREATE TABLE comic_info (" - "id INTEGER PRIMARY KEY," - "title TEXT," + "coverPage INTEGER DEFAULT 1," + "numPages INTEGER," - "coverPage INTEGER DEFAULT 1," - "numPages INTEGER," + "number INTEGER," + "isBis BOOLEAN," + "count INTEGER," - "number INTEGER," - "isBis BOOLEAN," - "count INTEGER," + "volume TEXT," + "storyArc TEXT," + "arcNumber INTEGER," + "arcCount INTEGER," - "volume TEXT," - "storyArc TEXT," - "arcNumber INTEGER," - "arcCount INTEGER," + "genere TEXT," - "genere TEXT," + "writer TEXT," + "penciller TEXT," + "inker TEXT," + "colorist TEXT," + "letterer TEXT," + "coverArtist TEXT," - "writer TEXT," - "penciller TEXT," - "inker TEXT," - "colorist TEXT," - "letterer TEXT," - "coverArtist TEXT," + "date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes + "publisher TEXT," + "format TEXT," + "color BOOLEAN," + "ageRating BOOLEAN," - "date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes - "publisher TEXT," - "format TEXT," - "color BOOLEAN," - "ageRating BOOLEAN," + "synopsis TEXT," + "characters TEXT," + "notes TEXT," - "synopsis TEXT," - "characters TEXT," - "notes TEXT," + "hash TEXT UNIQUE NOT NULL," + "edited BOOLEAN DEFAULT 0," + "read BOOLEAN DEFAULT 0," + //new 7.0 fields - "hash TEXT UNIQUE NOT NULL," - "edited BOOLEAN DEFAULT 0," - "read BOOLEAN DEFAULT 0," -//new 7.0 fields - - "hasBeenOpened BOOLEAN DEFAULT 0," - "rating INTEGER DEFAULT 0," - "currentPage INTEGER DEFAULT 1, " - "bookmark1 INTEGER DEFAULT -1, " - "bookmark2 INTEGER DEFAULT -1, " - "bookmark3 INTEGER DEFAULT -1, " - "brightness INTEGER DEFAULT -1, " - "contrast INTEGER DEFAULT -1, " - "gamma INTEGER DEFAULT -1, " -//new 7.1 fields - "comicVineID TEXT" + "hasBeenOpened BOOLEAN DEFAULT 0," + "rating INTEGER DEFAULT 0," + "currentPage INTEGER DEFAULT 1, " + "bookmark1 INTEGER DEFAULT -1, " + "bookmark2 INTEGER DEFAULT -1, " + "bookmark3 INTEGER DEFAULT -1, " + "brightness INTEGER DEFAULT -1, " + "contrast INTEGER DEFAULT -1, " + "gamma INTEGER DEFAULT -1, " + //new 7.1 fields + "comicVineID TEXT" - ")"); - success = success && queryComicInfo.exec(); - //queryComicInfo.finish(); + ")"); + success = success && queryComicInfo.exec(); + //queryComicInfo.finish(); - //COMIC (representa un cómic en disco, contiene el nombre de fichero) - QSqlQuery queryComic(database); - queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))"); - success = success && queryComic.exec(); - //queryComic.finish(); - //DB INFO - QSqlQuery queryDBInfo(database); - queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)"); - success = success && queryDBInfo.exec(); - //queryDBInfo.finish(); + //FOLDER (representa una carpeta en disco) + QSqlQuery queryFolder(database); + queryFolder.prepare("CREATE TABLE folder (" + "id INTEGER PRIMARY KEY," + "parentId INTEGER NOT NULL," + "name TEXT NOT NULL," + "path TEXT NOT NULL," + //new 7.1 fields + "finished BOOLEAN DEFAULT 0," //reading + "completed BOOLEAN DEFAULT 1," //collecting + //-- + "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); + success = success && queryFolder.exec(); - QSqlQuery query("INSERT INTO db_info (version) " - "VALUES ('" VERSION "')",database); - //query.finish(); + //COMIC (representa un cómic en disco, contiene el nombre de fichero) + QSqlQuery queryComic(database); + queryComic.prepare("CREATE TABLE comic (id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, comicInfoId INTEGER NOT NULL, fileName TEXT NOT NULL, path TEXT, FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, FOREIGN KEY(comicInfoId) REFERENCES comic_info(id))"); + success = success && queryComic.exec(); + //queryComic.finish(); + //DB INFO + QSqlQuery queryDBInfo(database); + queryDBInfo.prepare("CREATE TABLE db_info (version TEXT NOT NULL)"); + success = success && queryDBInfo.exec(); + //queryDBInfo.finish(); - //8.0> tables - success = success && DataBaseManagement::createV8Tables(database); + QSqlQuery query("INSERT INTO db_info (version) " + "VALUES ('" VERSION "')",database); + //query.finish(); + //8.0> tables + success = success && DataBaseManagement::createV8Tables(database); } return success; From 37d177e65a7d0f4377e8e02166454723aacb6e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:45:07 +0100 Subject: [PATCH 05/23] removed extra comma --- YACReaderLibrary/db/data_base_management.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 1c29814c..5a31ce94 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -195,8 +195,13 @@ bool DataBaseManagement::createTables(QSqlDatabase & database) //new 7.1 fields "finished BOOLEAN DEFAULT 0," //reading "completed BOOLEAN DEFAULT 1," //collecting - //-- - "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); + //new 8.6 fields + "numChildren INTEGER," + "firstChildId INTEGER," + "customImage TEXT," + "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE), " + //8.6 + "FOREIGN KEY(firstChildId) REFERENCES comic_info(id))"); success = success && queryFolder.exec(); //COMIC (representa un cómic en disco, contiene el nombre de fichero) From b0060795b5ea68f27530dc06f59eae333161cd03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:52:12 +0100 Subject: [PATCH 06/23] added new method for adding constraints to an existing table --- YACReaderLibrary/db/data_base_management.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 5a31ce94..be008518 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -620,6 +620,19 @@ bool DataBaseManagement::addColumns(const QString &tableName, const QStringList return returnValue; } +bool DataBaseManagement::addConstraint(const QString &tableName, const QString &constraint, const QSqlDatabase &db) +{ + QString sql = "ALTER TABLE %1 ADD %2"; + bool returnValue = true; + + QSqlQuery alterTable(db); + alterTable.prepare(sql.arg(tableName).arg(constraint)); + alterTable.exec(); + returnValue = returnValue && (alterTable.numRowsAffected() > 0); + + return returnValue; +} + void DataBaseManagement::bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query) { if(!record.value(name).isNull()) From cf79dbad9110aa84472a5b82f201f9434894aff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 10:52:55 +0100 Subject: [PATCH 07/23] update the folder table properly in 8.6 version --- YACReaderLibrary/db/data_base_management.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index be008518..d2c2cc2d 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -770,7 +770,11 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) { QStringList columnDefs; //TODO + columnDefs << "numChildren INTEGER"; + columnDefs << "firstChildId INTEGER"; + columnDefs << "customImage TEXT"; //returnValue = returnValue && addColumns("folder", columnDefs, db); + //returnValue = returnValue && addConstraint("folder", FOREIGN KEY(firstChildId) REFERENCES comic_info(id), db); } } From 865026e46ffcaad4d2e24bdc0e293e178cac8908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 11:36:12 +0100 Subject: [PATCH 08/23] added new fields to Folder class --- common/folder.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/folder.h b/common/folder.h index 862c05de..22db77e5 100644 --- a/common/folder.h +++ b/common/folder.h @@ -10,6 +10,10 @@ class Folder : public LibraryItem public: bool knownParent; bool knownId; + + qint32 numChildren; //-1 for unknown number of children + qulonglong firstChildId; //0 for unknown first child + QString customImage; //empty for none custom image Folder():knownParent(false), knownId(false){}; Folder(qulonglong sid, qulonglong pid,QString fn, QString fp):knownParent(true), knownId(true){id = sid; parentId = pid;name = fn; path = fp;}; From 2703219a0a38d91787458e41fd1e4fc786e48fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 12:14:31 +0100 Subject: [PATCH 09/23] map new fields on folder table to model class --- YACReaderLibrary/db_helper.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index c781d01e..29ed4a87 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -929,6 +929,10 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db) //new 7.1 folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); + //new 8.6 + folder.numChildren = record.value("numChildren").toInt(); + folder.firstChildId = record.value("firstChildId").toULongLong(); + folder.customImage = record.value("customImage").toString(); } return folder; @@ -957,6 +961,11 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql //new 7.1 folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); + //new 8.6 + folder.numChildren = record.value("numChildren").toInt(); + folder.firstChildId = record.value("firstChildId").toULongLong(); + folder.customImage = record.value("customImage").toString(); + QLOG_DEBUG() << "FOUND!!"; } From 35b87a9f5931a36c47114313750cc2392bb51101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 12:56:54 +0100 Subject: [PATCH 10/23] added missing method declaration --- YACReaderLibrary/db/data_base_management.h | 1 + 1 file changed, 1 insertion(+) diff --git a/YACReaderLibrary/db/data_base_management.h b/YACReaderLibrary/db/data_base_management.h index 68540339..3d7139e2 100644 --- a/YACReaderLibrary/db/data_base_management.h +++ b/YACReaderLibrary/db/data_base_management.h @@ -38,6 +38,7 @@ private: static void bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query); static bool addColumns(const QString & tableName, const QStringList & columnDefs, const QSqlDatabase & db); + static bool addConstraint(const QString &tableName, const QString & constraint, const QSqlDatabase & db); public: DataBaseManagement(); From 4b3ffdc665816531fbb51f8fca6d270d11a172d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 14:12:38 +0100 Subject: [PATCH 11/23] set numChildren to -1 if there is no value in the data base --- YACReaderLibrary/db_helper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 29ed4a87..10829cd5 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -930,7 +930,7 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db) folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); //new 8.6 - folder.numChildren = record.value("numChildren").toInt(); + folder.numChildren = record.value("numChildren").isNull() ? -1 : record.value("numChildren").toInt(); folder.firstChildId = record.value("firstChildId").toULongLong(); folder.customImage = record.value("customImage").toString(); } @@ -962,7 +962,7 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); //new 8.6 - folder.numChildren = record.value("numChildren").toInt(); + folder.numChildren = record.value("numChildren").isNull() ? -1 : record.value("numChildren").toInt(); folder.firstChildId = record.value("firstChildId").toULongLong(); folder.customImage = record.value("customImage").toString(); From 37328edc6448b53fdf718558e55781c4e205799b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 14:15:18 +0100 Subject: [PATCH 12/23] added a new web controller for providing the content information of a folder --- .../controllers/foldercontentcontroller.cpp | 70 +++++++++++++++++++ .../controllers/foldercontentcontroller.h | 22 ++++++ YACReaderLibrary/server/requestmapper.cpp | 6 ++ YACReaderLibrary/server/server.pri | 6 +- 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 YACReaderLibrary/server/controllers/foldercontentcontroller.cpp create mode 100644 YACReaderLibrary/server/controllers/foldercontentcontroller.h diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp new file mode 100644 index 00000000..2fcaf8a4 --- /dev/null +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp @@ -0,0 +1,70 @@ +#include "foldercontentcontroller.h" + +#include + +#include "db_helper.h" +#include "comic_db.h" +#include "folder.h" + +#include "qnaturalsorting.h" + +#include +using namespace std; + +struct LibraryItemSorter +{ + bool operator()(const LibraryItem * a,const LibraryItem * b) const + { + return naturalSortLessThanCI(a->name,b->name); + } +}; + +FolderContentController::FolderContentController() {} + +void FolderContentController::service(HttpRequest& request, HttpResponse& response) +{ + response.setHeader("Content-Type", "plain/text; charset=utf-8"); + + QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8(); + QStringList pathElements = path.split('/'); + int libraryId = pathElements.at(2).toInt(); + qulonglong parentId = pathElements.at(4).toULongLong(); + + serviceContent(libraryId, parentId, response); + + response.writeText("",true); +} + +void FolderContentController::serviceContent(const int &library, const qulonglong &folderId, HttpResponse &response) +{ + clock_t begin = clock(); + + QList folderContent = DBHelper::getFolderSubfoldersFromLibrary(library,folderId); + QList folderComics = DBHelper::getFolderComicsFromLibrary(library,folderId); + + folderContent.append(folderComics); + qSort(folderContent.begin(),folderContent.end(),LibraryItemSorter()); + + folderComics.clear(); + + ComicDB * currentComic; + Folder * currentFolder; + for(QList::const_iterator itr = folderContent.constBegin();itr!=folderContent.constEnd();itr++) + { + if((*itr)->isDir()) + { + currentFolder = (Folder *)(*itr); + response.writeText(QString("f:%1:%2:%3:%4\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->numChildren)); + } + else + { + currentComic = (ComicDB *)(*itr); + response.writeText(QString("c:%1:%2:%3:%4:%5\r\n").arg(library).arg(currentComic->id).arg(currentComic->getFileName()).arg(currentComic->getFileSize()).arg(currentComic->info.hash)); + } + } + + clock_t end = clock(); + double msecs = double(end - begin); + + response.writeText(QString("%1ms").arg(msecs)); +} diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.h b/YACReaderLibrary/server/controllers/foldercontentcontroller.h new file mode 100644 index 00000000..aa986042 --- /dev/null +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.h @@ -0,0 +1,22 @@ +#ifndef FOLDERCONTENTCONTROLLER_H +#define FOLDERCONTENTCONTROLLER_H + +#include "httprequest.h" +#include "httpresponse.h" +#include "httprequesthandler.h" + +class FolderContentController : public HttpRequestHandler { + Q_OBJECT + Q_DISABLE_COPY(FolderContentController); +public: + /** Constructor */ + FolderContentController(); + + /** Generates the response */ + void service(HttpRequest& request, HttpResponse& response); + +private: + void serviceContent(const int &library, const qulonglong &folderId, HttpResponse &response); +}; + +#endif // FOLDERCONTENTCONTROLLER_H diff --git a/YACReaderLibrary/server/requestmapper.cpp b/YACReaderLibrary/server/requestmapper.cpp index 75bbe613..97213261 100644 --- a/YACReaderLibrary/server/requestmapper.cpp +++ b/YACReaderLibrary/server/requestmapper.cpp @@ -23,6 +23,7 @@ #include "controllers/comicdownloadinfocontroller.h" #include "controllers/synccontroller.h" #include "controllers/versioncontroller.h" +#include "controllers/foldercontentcontroller.h" #include "db_helper.h" #include "yacreader_libraries.h" @@ -107,6 +108,7 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { static const QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page static const QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) static const QRegExp serverVersion("/version/?"); + static const QRegExp folderContent("/library/.+/folder/[0-9]+/content/?"); static const QRegExp sync("/sync"); @@ -169,6 +171,10 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { { UpdateComicController().service(request, response); } + else if(folderContent.exactMatch(path)) + { + FolderContentController().service(request, response); + } } else { diff --git a/YACReaderLibrary/server/server.pri b/YACReaderLibrary/server/server.pri index 19eb50a8..6f1588b4 100644 --- a/YACReaderLibrary/server/server.pri +++ b/YACReaderLibrary/server/server.pri @@ -17,7 +17,8 @@ HEADERS += \ $$PWD/controllers/comicdownloadinfocontroller.h \ $$PWD/controllers/synccontroller.h \ #v2 - $$PWD/controllers/versioncontroller.h + $$PWD/controllers/versioncontroller.h \ + $$PWD/controllers/foldercontentcontroller.h SOURCES += \ $$PWD/static.cpp \ @@ -35,7 +36,8 @@ SOURCES += \ $$PWD/controllers/comicdownloadinfocontroller.cpp \ $$PWD/controllers/synccontroller.cpp \ #v2 - $$PWD/controllers/versioncontroller.cpp + $$PWD/controllers/versioncontroller.cpp \ + $$PWD/controllers/foldercontentcontroller.cpp include(lib/bfLogging/bfLogging.pri) include(lib/bfHttpServer/bfHttpServer.pri) From bac7fe13512b55442ff90ed58f9d920096797d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 17:41:26 +0100 Subject: [PATCH 13/23] updated Folder class --- YACReaderLibrary/db_helper.cpp | 22 +++-- .../controllers/foldercontentcontroller.cpp | 2 +- common/comic_db.cpp | 2 +- common/comic_db.h | 2 +- common/folder.cpp | 30 +++++++ common/folder.h | 89 ++++++++++++++++--- common/library_item.h | 4 +- 7 files changed, 125 insertions(+), 26 deletions(-) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 10829cd5..14277d91 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -733,7 +733,13 @@ QList DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat data << record.value(i); //TODO sort by sort indicator and name currentItem = new Folder(record.value("id").toULongLong(),record.value("parentId").toULongLong(),record.value("name").toString(),record.value("path").toString()); - int lessThan = 0; + + if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) + currentItem->setNumChildren(record.value("numChildren").toInt()); + currentItem->setFirstChildId(record.value("firstChildId").toULongLong()); + currentItem->setCustomImage(record.value("customImage").toString()); + + int lessThan = 0; if(list.isEmpty() || !sort) list.append(currentItem); @@ -930,9 +936,10 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db) folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); //new 8.6 - folder.numChildren = record.value("numChildren").isNull() ? -1 : record.value("numChildren").toInt(); - folder.firstChildId = record.value("firstChildId").toULongLong(); - folder.customImage = record.value("customImage").toString(); + if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) + folder.setNumChildren(record.value("numChildren").toInt()); + folder.setFirstChildId(record.value("firstChildId").toULongLong()); + folder.setCustomImage(record.value("customImage").toString()); } return folder; @@ -962,9 +969,10 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql folder.setFinished(record.value("finished").toBool()); folder.setCompleted(record.value("completed").toBool()); //new 8.6 - folder.numChildren = record.value("numChildren").isNull() ? -1 : record.value("numChildren").toInt(); - folder.firstChildId = record.value("firstChildId").toULongLong(); - folder.customImage = record.value("customImage").toString(); + if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) + folder.setNumChildren(record.value("numChildren").toInt()); + folder.setFirstChildId(record.value("firstChildId").toULongLong()); + folder.setCustomImage(record.value("customImage").toString()); QLOG_DEBUG() << "FOUND!!"; } diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp index 2fcaf8a4..a9eae52f 100644 --- a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp @@ -54,7 +54,7 @@ void FolderContentController::serviceContent(const int &library, const qulonglon if((*itr)->isDir()) { currentFolder = (Folder *)(*itr); - response.writeText(QString("f:%1:%2:%3:%4\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->numChildren)); + response.writeText(QString("f:%1:%2:%3:%4\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->getNumChildren())); } else { diff --git a/common/comic_db.cpp b/common/comic_db.cpp index 6e92b85a..2cefa5d5 100644 --- a/common/comic_db.cpp +++ b/common/comic_db.cpp @@ -11,7 +11,7 @@ ComicDB::ComicDB() } -bool ComicDB::isDir() +bool ComicDB::isDir() const { return false; } diff --git a/common/comic_db.h b/common/comic_db.h index 417efa4d..e396e718 100644 --- a/common/comic_db.h +++ b/common/comic_db.h @@ -124,7 +124,7 @@ class ComicDB : public LibraryItem public: ComicDB(); - bool isDir(); + bool isDir() const; bool _hasCover; diff --git a/common/folder.cpp b/common/folder.cpp index e69de29b..9a7d3eba 100644 --- a/common/folder.cpp +++ b/common/folder.cpp @@ -0,0 +1,30 @@ +#include "folder.h" + +Folder::Folder() + :knownParent(false), + knownId(false), + numChildren(-1), + firstChildId(0) +{} + +Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath) + :knownParent(true), + knownId(true), + numChildren(-1), + firstChildId(0) +{ + this->id = folderId; + this->parentId = parentId; + this->name = folderName; + this->path = folderPath; +} + +Folder::Folder(const QString & folderName, const QString & folderPath) + :knownParent(false), + knownId(false), + numChildren(-1), + firstChildId(0) +{ + this->name = folderName; + this->path = folderPath; +} diff --git a/common/folder.h b/common/folder.h index 22db77e5..9739a6d6 100644 --- a/common/folder.h +++ b/common/folder.h @@ -10,25 +10,86 @@ class Folder : public LibraryItem public: bool knownParent; bool knownId; - - qint32 numChildren; //-1 for unknown number of children - qulonglong firstChildId; //0 for unknown first child - QString customImage; //empty for none custom image - Folder():knownParent(false), knownId(false){}; - Folder(qulonglong sid, qulonglong pid,QString fn, QString fp):knownParent(true), knownId(true){id = sid; parentId = pid;name = fn; path = fp;}; - Folder(QString fn, QString fp):knownParent(false), knownId(false){name = fn; path = fp;}; - void setId(qulonglong sid){id = sid;knownId = true;}; - void setFather(qulonglong pid){parentId = pid;knownParent = true;}; - bool isDir() {return true;}; - bool isFinished() const {return finished;}; - bool isCompleted() const {return completed;}; - void setFinished(bool b) {finished = b;}; - void setCompleted(bool b) {completed = b;}; + Folder(); + Folder(qulonglong folderId, qulonglong parentId,const QString & folderName, const QString & folderPath); + Folder(const QString & folderName, const QString & folderPath); + + inline void setId(qulonglong sid) + { + id = sid; + knownId = true; + } + + inline void setFather(qulonglong pid) + { + parentId = pid; + knownParent = true; + } + + inline bool isDir() const + { + return true; + } + + inline bool isFinished() const + { + return finished; + } + + inline bool isCompleted() const + { + return completed; + } + + inline void setFinished(bool b) + { + finished = b; + } + + inline void setCompleted(bool b) + { + completed = b; + } + + inline qint32 getNumChildren() const + { + return numChildren; + } + + inline void setNumChildren(const qint32 v) + { + numChildren = v; + } + + inline qulonglong getFirstChildId() const + { + return firstChildId; + } + + inline void setFirstChildId(const qulonglong v) + { + firstChildId = v; + } + + inline qulonglong getCustomImage() const + { + return firstChildId; + } + + inline void setCustomImage(const QString & s) + { + customImage = s; + } private: bool finished; bool completed; + + qint32 numChildren; //-1 for unknown number of children + qulonglong firstChildId; //0 for unknown first child + QString customImage; //empty for none custom image + }; #endif diff --git a/common/library_item.h b/common/library_item.h index 2f6b8d9f..fcc194eb 100644 --- a/common/library_item.h +++ b/common/library_item.h @@ -6,11 +6,11 @@ class LibraryItem { public: - virtual bool isDir() = 0; + virtual bool isDir() const = 0; QString name; QString path; qulonglong parentId; qulonglong id; }; -#endif \ No newline at end of file +#endif From 3cda11eec71b3e33aec4b15f7f317bf66b778527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 18:47:09 +0100 Subject: [PATCH 14/23] fixed db creation --- YACReaderLibrary/db/data_base_management.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index d2c2cc2d..5d331440 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -199,7 +199,7 @@ bool DataBaseManagement::createTables(QSqlDatabase & database) "numChildren INTEGER," "firstChildId INTEGER," "customImage TEXT," - "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE), " + "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, " //8.6 "FOREIGN KEY(firstChildId) REFERENCES comic_info(id))"); success = success && queryFolder.exec(); From b9e7dbe41ea3b03940479253a51181dd691e163e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 18:52:25 +0100 Subject: [PATCH 15/23] Everytime the content of a folder changes, update numChildren and firstChildId. This could cause performance issues, but the initial tests look good, and it seems that the overhead could be considered negligible. On the other hand, client queries are several times faster. --- YACReaderLibrary/db_helper.cpp | 61 ++++++++++++++++++++++++++++++---- YACReaderLibrary/db_helper.h | 12 ++++--- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 14277d91..2fcb6d98 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -160,26 +160,32 @@ QString DBHelper::getLibraryName(int id) } //objects management //deletes -void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db) +void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db, bool updateParent) { if(item->isDir()) - DBHelper::removeFromDB(dynamic_cast(item),db); + DBHelper::removeFromDB(dynamic_cast(item),db, updateParent); else - DBHelper::removeFromDB(dynamic_cast(item),db); + DBHelper::removeFromDB(dynamic_cast(item),db, updateParent); } -void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db) +void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db, bool updateParent) { QSqlQuery query(db); query.prepare("DELETE FROM folder WHERE id = :id"); query.bindValue(":id", folder->id); query.exec(); + + if(updateParent) + DBHelper::updateChildrenInfo(folder->parentId, db); } -void DBHelper::removeFromDB(ComicDB * comic, QSqlDatabase & db) +void DBHelper::removeFromDB(ComicDB * comic, QSqlDatabase & db, bool updateParent) { QSqlQuery query(db); query.prepare("DELETE FROM comic WHERE id = :id"); query.bindValue(":id", comic->id); query.exec(); + + if(updateParent) + DBHelper::updateChildrenInfo(comic->parentId, db); } void DBHelper::removeLabelFromDB(qulonglong id, QSqlDatabase &db) @@ -408,6 +414,39 @@ void DBHelper::update(const Folder & folder, QSqlDatabase &db) updateFolderInfo.exec(); } +void DBHelper::updateChildrenInfo(const Folder & folder, QSqlDatabase & db) +{ + QSqlQuery updateFolderInfo(db); + updateFolderInfo.prepare("UPDATE folder SET " + "numChildren = :numChildren, " + "firstChildId = :firstChildId " + "WHERE id = :id "); + updateFolderInfo.bindValue(":numChildren", folder.getNumChildren()); + updateFolderInfo.bindValue(":firstChildId", folder.getFirstChildId()); + updateFolderInfo.bindValue(":id", folder.id); + updateFolderInfo.exec(); +} + +void DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase & db) +{ + QList subfolders = DBHelper::getFoldersFromParent(folderId,db,false); + QList comics = DBHelper::getComicsFromParent(folderId,db,true); + + ComicDB * firstComic = NULL; + if(comics.count() > 0) + firstComic = static_cast(comics.first()); + + QSqlQuery updateFolderInfo(db); + updateFolderInfo.prepare("UPDATE folder SET " + "numChildren = :numChildren, " + "firstChildId = :firstChildId " + "WHERE id = :id "); + updateFolderInfo.bindValue(":numChildren", subfolders.count() + comics.count()); + updateFolderInfo.bindValue(":firstChildId", firstComic != NULL ? firstComic->info.id : 0); + updateFolderInfo.bindValue(":id", folderId); + updateFolderInfo.exec(); +} + void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo) { QString libraryPath = DBHelper::getLibraries().getPath(libraryId); @@ -571,7 +610,7 @@ void DBHelper::reasignOrderToComicsInReadingList(qulonglong readingListId, QList } //inserts -qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db) +qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db, bool updateParent) { QSqlQuery query(db); query.prepare("INSERT INTO folder (parentId, name, path) " @@ -580,10 +619,14 @@ qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db) query.bindValue(":name", folder->name); query.bindValue(":path", folder->path); query.exec(); + + if(updateParent) + DBHelper::updateChildrenInfo(folder->parentId, db); + return query.lastInsertId().toULongLong(); } -qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db) +qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db, bool updateParent) { if(!comic->info.existOnDb) { @@ -607,6 +650,10 @@ qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db) query.bindValue(":name", comic->name); query.bindValue(":path", comic->path); query.exec(); + + if(updateParent) + DBHelper::updateChildrenInfo(comic->parentId, db); + return query.lastInsertId().toULongLong(); } diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h index 19611dc7..e7f4d6fe 100644 --- a/YACReaderLibrary/db_helper.h +++ b/YACReaderLibrary/db_helper.h @@ -33,9 +33,9 @@ public: //objects management //deletes - static void removeFromDB(LibraryItem * item, QSqlDatabase & db); - static void removeFromDB(Folder * folder, QSqlDatabase & db); - static void removeFromDB(ComicDB * comic, QSqlDatabase & db); + static void removeFromDB(LibraryItem * item, QSqlDatabase & db, bool updateParent = true); + static void removeFromDB(Folder * folder, QSqlDatabase & db, bool updateParent = true); + static void removeFromDB(ComicDB * comic, QSqlDatabase & db, bool updateParent = true); static void removeLabelFromDB(qulonglong id, QSqlDatabase & db); static void removeListFromDB(qulonglong id, QSqlDatabase & db); //logic deletes @@ -43,8 +43,8 @@ public: static void deleteComicsFromLabel(const QList & comicsList, qulonglong labelId, QSqlDatabase & db); static void deleteComicsFromReadingList(const QList & comicsList, qulonglong readingListId, QSqlDatabase & db); //inserts - static qulonglong insert(Folder * folder, QSqlDatabase & db); - static qulonglong insert(ComicDB * comic, QSqlDatabase & db); + static qulonglong insert(Folder * folder, QSqlDatabase & db, bool updateParent = true); + static qulonglong insert(ComicDB * comic, QSqlDatabase & db, bool updateParent = true); static qulonglong insertLabel(const QString & name, YACReader::LabelColors color , QSqlDatabase & db); static qulonglong insertReadingList(const QString & name, QSqlDatabase & db); static qulonglong insertReadingSubList(const QString & name, qulonglong parentId, int ordering, QSqlDatabase & db); @@ -57,6 +57,8 @@ public: static void update(ComicInfo * comicInfo, QSqlDatabase & db); static void updateRead(ComicInfo * comicInfo, QSqlDatabase & db); static void update(const Folder & folder, QSqlDatabase & db); + static void updateChildrenInfo(const Folder & folder, QSqlDatabase & db); + static void updateChildrenInfo(qulonglong folderId, QSqlDatabase & db); static void updateProgress(qulonglong libraryId,const ComicInfo & comicInfo); static void updateReadingRemoteProgress(const ComicInfo & comicInfo, QSqlDatabase & db); static void updateFromRemoteClient(qulonglong libraryId,const ComicInfo & comicInfo); From e23f6b0bc374412d33d1ee27dae08c3fa977fcc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 19:14:16 +0100 Subject: [PATCH 16/23] store the hash of the first comic in a folder, this is more useful than storing the id --- YACReaderLibrary/db/data_base_management.cpp | 9 +++------ YACReaderLibrary/db_helper.cpp | 14 +++++++------- common/folder.cpp | 9 +++------ common/folder.h | 14 +++++++------- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/YACReaderLibrary/db/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 5d331440..fa5dfa0b 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -197,11 +197,9 @@ bool DataBaseManagement::createTables(QSqlDatabase & database) "completed BOOLEAN DEFAULT 1," //collecting //new 8.6 fields "numChildren INTEGER," - "firstChildId INTEGER," + "firstChildHash TEXT," "customImage TEXT," - "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE, " - //8.6 - "FOREIGN KEY(firstChildId) REFERENCES comic_info(id))"); + "FOREIGN KEY(parentId) REFERENCES folder(id) ON DELETE CASCADE)"); success = success && queryFolder.exec(); //COMIC (representa un cómic en disco, contiene el nombre de fichero) @@ -771,10 +769,9 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) QStringList columnDefs; //TODO columnDefs << "numChildren INTEGER"; - columnDefs << "firstChildId INTEGER"; + columnDefs << "firstChildHash TEXT"; columnDefs << "customImage TEXT"; //returnValue = returnValue && addColumns("folder", columnDefs, db); - //returnValue = returnValue && addConstraint("folder", FOREIGN KEY(firstChildId) REFERENCES comic_info(id), db); } } diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 2fcb6d98..321cb35e 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -419,10 +419,10 @@ void DBHelper::updateChildrenInfo(const Folder & folder, QSqlDatabase & db) QSqlQuery updateFolderInfo(db); updateFolderInfo.prepare("UPDATE folder SET " "numChildren = :numChildren, " - "firstChildId = :firstChildId " + "firstChildHash = :firstChildHash " "WHERE id = :id "); updateFolderInfo.bindValue(":numChildren", folder.getNumChildren()); - updateFolderInfo.bindValue(":firstChildId", folder.getFirstChildId()); + updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash()); updateFolderInfo.bindValue(":id", folder.id); updateFolderInfo.exec(); } @@ -439,10 +439,10 @@ void DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase & db) QSqlQuery updateFolderInfo(db); updateFolderInfo.prepare("UPDATE folder SET " "numChildren = :numChildren, " - "firstChildId = :firstChildId " + "firstChildHash = :firstChildHash " "WHERE id = :id "); updateFolderInfo.bindValue(":numChildren", subfolders.count() + comics.count()); - updateFolderInfo.bindValue(":firstChildId", firstComic != NULL ? firstComic->info.id : 0); + updateFolderInfo.bindValue(":firstChildHash", firstComic != NULL ? firstComic->info.hash : ""); updateFolderInfo.bindValue(":id", folderId); updateFolderInfo.exec(); } @@ -783,7 +783,7 @@ QList DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) currentItem->setNumChildren(record.value("numChildren").toInt()); - currentItem->setFirstChildId(record.value("firstChildId").toULongLong()); + currentItem->setFirstChildHash(record.value("firstChildHash").toString()); currentItem->setCustomImage(record.value("customImage").toString()); int lessThan = 0; @@ -985,7 +985,7 @@ Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db) //new 8.6 if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) folder.setNumChildren(record.value("numChildren").toInt()); - folder.setFirstChildId(record.value("firstChildId").toULongLong()); + folder.setFirstChildHash(record.value("firstChildHash").toString()); folder.setCustomImage(record.value("customImage").toString()); } @@ -1018,7 +1018,7 @@ Folder DBHelper::loadFolder(const QString &folderName, qulonglong parentId, QSql //new 8.6 if(!record.value("numChildren").isNull() && record.value("numChildren").isValid()) folder.setNumChildren(record.value("numChildren").toInt()); - folder.setFirstChildId(record.value("firstChildId").toULongLong()); + folder.setFirstChildHash(record.value("firstChildHash").toString()); folder.setCustomImage(record.value("customImage").toString()); QLOG_DEBUG() << "FOUND!!"; diff --git a/common/folder.cpp b/common/folder.cpp index 9a7d3eba..f3b486c7 100644 --- a/common/folder.cpp +++ b/common/folder.cpp @@ -3,15 +3,13 @@ Folder::Folder() :knownParent(false), knownId(false), - numChildren(-1), - firstChildId(0) + numChildren(-1) {} Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderName, const QString &folderPath) :knownParent(true), knownId(true), - numChildren(-1), - firstChildId(0) + numChildren(-1) { this->id = folderId; this->parentId = parentId; @@ -22,8 +20,7 @@ Folder::Folder(qulonglong folderId, qulonglong parentId, const QString &folderNa Folder::Folder(const QString & folderName, const QString & folderPath) :knownParent(false), knownId(false), - numChildren(-1), - firstChildId(0) + numChildren(-1) { this->name = folderName; this->path = folderPath; diff --git a/common/folder.h b/common/folder.h index 9739a6d6..6dd660a6 100644 --- a/common/folder.h +++ b/common/folder.h @@ -62,19 +62,19 @@ public: numChildren = v; } - inline qulonglong getFirstChildId() const + inline QString getFirstChildHash() const { - return firstChildId; + return firstChildHash; } - inline void setFirstChildId(const qulonglong v) + inline void setFirstChildHash(const QString & v) { - firstChildId = v; + firstChildHash = v; } - inline qulonglong getCustomImage() const + inline QString getCustomImage() const { - return firstChildId; + return customImage; } inline void setCustomImage(const QString & s) @@ -87,7 +87,7 @@ private: bool completed; qint32 numChildren; //-1 for unknown number of children - qulonglong firstChildId; //0 for unknown first child + QString firstChildHash; //empty for unknown first child QString customImage; //empty for none custom image }; From 74c64e0280e868420edb53a5812a1316b5a274dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 19:14:54 +0100 Subject: [PATCH 17/23] use the hash of the first comic in a folder for displaying and image for the folder --- YACReaderLibrary/server/controllers/foldercontroller.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/YACReaderLibrary/server/controllers/foldercontroller.cpp b/YACReaderLibrary/server/controllers/foldercontroller.cpp index 30aa657f..3ec241a2 100644 --- a/YACReaderLibrary/server/controllers/foldercontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontroller.cpp @@ -167,11 +167,11 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) { t.setVariable(QString("element%1.class").arg(i),"folder"); - QList children = DBHelper::getFolderComicsFromLibrary(libraryId, item->id); - if(children.length()>0) + const Folder * folder = static_cast(item); + + if(folder->getFirstChildHash().length()>0) { - const ComicDB * comic = static_cast(children.at(0)); - t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg?folderCover=true").arg(libraryId).arg(comic->info.hash)); + t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg?folderCover=true").arg(libraryId).arg(folder->getFirstChildHash())); } else t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png"); From d5d9e5206f0466afbe1f8719a93155c7a3b2075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Sun, 24 Jan 2016 19:20:00 +0100 Subject: [PATCH 18/23] send the hash of the first comic in a folder, so the client can display an image for that folder --- YACReaderLibrary/server/controllers/foldercontentcontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp index a9eae52f..776d99cb 100644 --- a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp @@ -54,7 +54,7 @@ void FolderContentController::serviceContent(const int &library, const qulonglon if((*itr)->isDir()) { currentFolder = (Folder *)(*itr); - response.writeText(QString("f:%1:%2:%3:%4\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->getNumChildren())); + response.writeText(QString("f:%1:%2:%3:%4:%5\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->getNumChildren()).arg(currentFolder->getFirstChildHash())); } else { From 00f45b9a273fef1b7f5913feaee61d469149cc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 25 Jan 2016 18:40:28 +0100 Subject: [PATCH 19/23] using static regular expresions was a bad idea --- YACReaderLibrary/server/requestmapper.cpp | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/YACReaderLibrary/server/requestmapper.cpp b/YACReaderLibrary/server/requestmapper.cpp index 97213261..2e887956 100644 --- a/YACReaderLibrary/server/requestmapper.cpp +++ b/YACReaderLibrary/server/requestmapper.cpp @@ -97,22 +97,22 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QByteArray path=request.getPath(); qDebug("RequestMapper: path=%s",path.data()); - static const QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content - static const QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info - static const QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info) - static const QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info) - static const QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic - static const QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info - static const QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory - static const QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation) - static const QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page - static const QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) - static const QRegExp serverVersion("/version/?"); - static const QRegExp folderContent("/library/.+/folder/[0-9]+/content/?"); + QRegExp folder("/library/.+/folder/[0-9]+/?");//get comic content + QRegExp folderInfo("/library/.+/folder/[0-9]+/info/?"); //get folder info + QRegExp comicDownloadInfo("/library/.+/comic/[0-9]+/?"); //get comic info (basic/download info) + QRegExp comicFullInfo("/library/.+/comic/[0-9]+/info/?"); //get comic info (full info) + QRegExp comicOpen("/library/.+/comic/[0-9]+/remote/?"); //the server will open for reading the comic + QRegExp comicUpdate("/library/.+/comic/[0-9]+/update/?"); //get comic info + QRegExp comicClose("/library/.+/comic/[0-9]+/close/?"); //the server will close the comic and free memory + QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); //get comic cover (navigation) + QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); //get comic page + QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) + QRegExp serverVersion("/version/?"); + QRegExp folderContent("/library/.+/folder/[0-9]+/content/?"); - static const QRegExp sync("/sync"); + QRegExp sync("/sync"); - static const QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe + QRegExp library("/library/([0-9]+)/.+"); //permite verificar que la biblioteca solicitada existe path = QUrl::fromPercentEncoding(path).toUtf8(); From 88056c819f01212152368b5cc443076668ef3500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 25 Jan 2016 18:45:50 +0100 Subject: [PATCH 20/23] updating folders' children info for every insert/delete in the db causes big performance issues, so that info is going to be updated explicitly --- YACReaderLibrary/comics_remover.cpp | 5 ++-- YACReaderLibrary/comics_remover.h | 4 ++- YACReaderLibrary/db/comic_model.cpp | 4 +-- YACReaderLibrary/db/comic_model.h | 2 +- YACReaderLibrary/db/folder_model.cpp | 15 ++++++++--- YACReaderLibrary/db/folder_model.h | 4 ++- YACReaderLibrary/db_helper.cpp | 38 ++++++++++++++-------------- YACReaderLibrary/db_helper.h | 11 ++++---- YACReaderLibrary/library_creator.cpp | 11 +++++++- YACReaderLibrary/library_window.cpp | 6 +++-- 10 files changed, 63 insertions(+), 37 deletions(-) diff --git a/YACReaderLibrary/comics_remover.cpp b/YACReaderLibrary/comics_remover.cpp index ef3fd009..7b4eadd7 100644 --- a/YACReaderLibrary/comics_remover.cpp +++ b/YACReaderLibrary/comics_remover.cpp @@ -5,8 +5,8 @@ #include "QsLog.h" -ComicsRemover::ComicsRemover(QModelIndexList & il, QList & ps, QObject *parent) - :QObject(parent),indexList(il), paths(ps) +ComicsRemover::ComicsRemover(QModelIndexList & il, QList & ps, qulonglong parentId, QObject *parent) + :QObject(parent),indexList(il), paths(ps), parentId(parentId) { } @@ -29,6 +29,7 @@ void ComicsRemover::process() } emit finished(); + emit removedItemsFromFolder(parentId); } diff --git a/YACReaderLibrary/comics_remover.h b/YACReaderLibrary/comics_remover.h index ff9d0a21..c844afbb 100644 --- a/YACReaderLibrary/comics_remover.h +++ b/YACReaderLibrary/comics_remover.h @@ -10,12 +10,13 @@ class ComicsRemover : public QObject { Q_OBJECT public: - explicit ComicsRemover(QModelIndexList & indexList, QList & paths, QObject *parent = 0); + explicit ComicsRemover(QModelIndexList & indexList, QList & paths, qulonglong parentId, QObject *parent = 0); signals: void remove(int); void removeError(); void finished(); + void removedItemsFromFolder(qulonglong); public slots: void process(); @@ -23,6 +24,7 @@ public slots: private: QModelIndexList indexList; QList paths; + qulonglong parentId; }; class FoldersRemover : public QObject diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index 33ddf459..7c3fa3ab 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -965,7 +965,7 @@ void ComicModel::removeInTransaction(int row) endRemoveRows(); } - +/* void ComicModel::remove(ComicDB * comic, int row) { beginRemoveRows(QModelIndex(),row,row); @@ -981,7 +981,7 @@ void ComicModel::remove(ComicDB * comic, int row) QSqlDatabase::removeDatabase(_databasePath); endRemoveRows(); } - +*/ /*ComicDB TableModel::getComic(int row) { return getComic(index(row,0)); diff --git a/YACReaderLibrary/db/comic_model.h b/YACReaderLibrary/db/comic_model.h index ce0de290..bb040a0d 100644 --- a/YACReaderLibrary/db/comic_model.h +++ b/YACReaderLibrary/db/comic_model.h @@ -65,7 +65,7 @@ public: //setComicInfoForSelectedComis(QList list); -->inserta la información común para los comics seleccionados QVector setComicsRead(QList list,YACReaderComicReadStatus read); qint64 asignNumbers(QList list,int startingNumber); - void remove(ComicDB * comic, int row); + //void remove(ComicDB * comic, int row); void removeInTransaction(int row); void reload(const ComicDB & comic); void resetComicRating(const QModelIndex & mi); diff --git a/YACReaderLibrary/db/folder_model.cpp b/YACReaderLibrary/db/folder_model.cpp index 1df7b199..700ca367 100644 --- a/YACReaderLibrary/db/folder_model.cpp +++ b/YACReaderLibrary/db/folder_model.cpp @@ -172,11 +172,12 @@ QVariant FolderModel::data(const QModelIndex &index, int role) const if(role == FolderModel::FinishedRole) return item->data(FolderModel::Finished); + if(role == FolderModel::IdRole) + return item->id; + if (role != Qt::DisplayRole) return QVariant(); - - return item->data(index.column()); } //! [3] @@ -305,7 +306,7 @@ void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent) //el diccionario permitir� encontrar cualquier nodo del �rbol r�pidamente, de forma que a�adir un hijo a un padre sea O(1) items.clear(); //se a�ade el nodo 0 - items.insert(parent->id,parent); + items.insert(parent->id,parent); while (sqlquery.next()) { QList data; @@ -535,6 +536,7 @@ QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QMod QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); newFolder.id = DBHelper::insert(&newFolder, db); + DBHelper::updateChildrenInfo(parentItem->id, db); QSqlDatabase::removeDatabase(_databasePath); int destRow = 0; @@ -573,11 +575,18 @@ void FolderModel::deleteFolder(const QModelIndex &mi) QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); DBHelper::removeFromDB(&f,db); + DBHelper::updateChildrenInfo(item->parent()->id, db); QSqlDatabase::removeDatabase(_databasePath); endRemoveRows(); } +void FolderModel::updateFolderChildrenInfo(qulonglong folderId) +{ + QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath); + DBHelper::updateChildrenInfo(folderId, db); + QSqlDatabase::removeDatabase(_databasePath); +} //PROXY diff --git a/YACReaderLibrary/db/folder_model.h b/YACReaderLibrary/db/folder_model.h index 4d0f16bb..ae28a33c 100644 --- a/YACReaderLibrary/db/folder_model.h +++ b/YACReaderLibrary/db/folder_model.h @@ -127,11 +127,13 @@ public: enum Roles { FinishedRole = Qt::UserRole + 1, - CompletedRole + CompletedRole, + IdRole }; public slots: void deleteFolder(const QModelIndex & mi); + void updateFolderChildrenInfo(qulonglong folderId); private: void setupModelData( QSqlQuery &sqlquery, FolderItem *parent); diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 321cb35e..5869a15f 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -160,32 +160,26 @@ QString DBHelper::getLibraryName(int id) } //objects management //deletes -void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db, bool updateParent) +void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db) { if(item->isDir()) - DBHelper::removeFromDB(dynamic_cast(item),db, updateParent); + DBHelper::removeFromDB(dynamic_cast(item),db); else - DBHelper::removeFromDB(dynamic_cast(item),db, updateParent); + DBHelper::removeFromDB(dynamic_cast(item),db); } -void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db, bool updateParent) +void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db) { QSqlQuery query(db); query.prepare("DELETE FROM folder WHERE id = :id"); query.bindValue(":id", folder->id); query.exec(); - - if(updateParent) - DBHelper::updateChildrenInfo(folder->parentId, db); } -void DBHelper::removeFromDB(ComicDB * comic, QSqlDatabase & db, bool updateParent) +void DBHelper::removeFromDB(ComicDB * comic, QSqlDatabase & db) { QSqlQuery query(db); query.prepare("DELETE FROM comic WHERE id = :id"); query.bindValue(":id", comic->id); query.exec(); - - if(updateParent) - DBHelper::updateChildrenInfo(comic->parentId, db); } void DBHelper::removeLabelFromDB(qulonglong id, QSqlDatabase &db) @@ -447,6 +441,18 @@ void DBHelper::updateChildrenInfo(qulonglong folderId, QSqlDatabase & db) updateFolderInfo.exec(); } +void DBHelper::updateChildrenInfo(QSqlDatabase & db) +{ + QSqlQuery selectQuery(db); //TODO check + selectQuery.prepare("SELECT id FROM folder"); + selectQuery.exec(); + + while (selectQuery.next()) + { + DBHelper::updateChildrenInfo(selectQuery.record().value(0).toULongLong(), db); + } +} + void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo) { QString libraryPath = DBHelper::getLibraries().getPath(libraryId); @@ -610,7 +616,7 @@ void DBHelper::reasignOrderToComicsInReadingList(qulonglong readingListId, QList } //inserts -qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db, bool updateParent) +qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db) { QSqlQuery query(db); query.prepare("INSERT INTO folder (parentId, name, path) " @@ -620,13 +626,10 @@ qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db, bool updateParen query.bindValue(":path", folder->path); query.exec(); - if(updateParent) - DBHelper::updateChildrenInfo(folder->parentId, db); - return query.lastInsertId().toULongLong(); } -qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db, bool updateParent) +qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db) { if(!comic->info.existOnDb) { @@ -651,9 +654,6 @@ qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db, bool updateParen query.bindValue(":path", comic->path); query.exec(); - if(updateParent) - DBHelper::updateChildrenInfo(comic->parentId, db); - return query.lastInsertId().toULongLong(); } diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h index e7f4d6fe..27c412e1 100644 --- a/YACReaderLibrary/db_helper.h +++ b/YACReaderLibrary/db_helper.h @@ -33,9 +33,9 @@ public: //objects management //deletes - static void removeFromDB(LibraryItem * item, QSqlDatabase & db, bool updateParent = true); - static void removeFromDB(Folder * folder, QSqlDatabase & db, bool updateParent = true); - static void removeFromDB(ComicDB * comic, QSqlDatabase & db, bool updateParent = true); + static void removeFromDB(LibraryItem * item, QSqlDatabase & db); + static void removeFromDB(Folder * folder, QSqlDatabase & db); + static void removeFromDB(ComicDB * comic, QSqlDatabase & db); static void removeLabelFromDB(qulonglong id, QSqlDatabase & db); static void removeListFromDB(qulonglong id, QSqlDatabase & db); //logic deletes @@ -43,8 +43,8 @@ public: static void deleteComicsFromLabel(const QList & comicsList, qulonglong labelId, QSqlDatabase & db); static void deleteComicsFromReadingList(const QList & comicsList, qulonglong readingListId, QSqlDatabase & db); //inserts - static qulonglong insert(Folder * folder, QSqlDatabase & db, bool updateParent = true); - static qulonglong insert(ComicDB * comic, QSqlDatabase & db, bool updateParent = true); + static qulonglong insert(Folder * folder, QSqlDatabase & db); + static qulonglong insert(ComicDB * comic, QSqlDatabase & db); static qulonglong insertLabel(const QString & name, YACReader::LabelColors color , QSqlDatabase & db); static qulonglong insertReadingList(const QString & name, QSqlDatabase & db); static qulonglong insertReadingSubList(const QString & name, qulonglong parentId, int ordering, QSqlDatabase & db); @@ -59,6 +59,7 @@ public: static void update(const Folder & folder, QSqlDatabase & db); static void updateChildrenInfo(const Folder & folder, QSqlDatabase & db); static void updateChildrenInfo(qulonglong folderId, QSqlDatabase & db); + static void updateChildrenInfo(QSqlDatabase & db); static void updateProgress(qulonglong libraryId,const ComicInfo & comicInfo); static void updateReadingRemoteProgress(const ComicInfo & comicInfo, QSqlDatabase & db); static void updateFromRemoteClient(qulonglong libraryId,const ComicInfo & comicInfo); diff --git a/YACReaderLibrary/library_creator.cpp b/YACReaderLibrary/library_creator.cpp index 9ff6c47b..8fbc14c3 100644 --- a/YACReaderLibrary/library_creator.cpp +++ b/YACReaderLibrary/library_creator.cpp @@ -162,6 +162,9 @@ void LibraryCreator::run() _database.transaction(); //se crea la librería create(QDir(_source)); + + DBHelper::updateChildrenInfo(_database); + _database.commit(); _database.close(); QSqlDatabase::removeDatabase(_database.connectionName()); @@ -199,6 +202,12 @@ void LibraryCreator::run() { update(QDir(_source)); } + + if(partialUpdate) + DBHelper::updateChildrenInfo(folderDestinationModelIndex.data(FolderModel::IdRole).toULongLong(),_database); + else + DBHelper::updateChildrenInfo(_database); + _database.commit(); _database.close(); QSqlDatabase::removeDatabase(_target); @@ -243,7 +252,7 @@ qulonglong LibraryCreator::insertFolders() if(!(i->knownId)) { i->setFather(currentId); - currentId = DBHelper::insert(&(*i),_database);//insertFolder(currentId,*i); + currentId = DBHelper::insert(&(*i),_database);//insertFolder(currentId,*i); i->setId(currentId); } else diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index f89dfa23..000b9aaa 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -1291,7 +1291,7 @@ void LibraryWindow::loadLibrary(const QString & name) if(d.exists(path+"/library.ydb")) { - QSqlDatabase db = DataBaseManagement::loadDatabase(path); + QSqlDatabase db = DataBaseManagement::loadDatabase(path); manageOpeningLibraryError(db.lastError().databaseText() + "-" + db.lastError().driverText()); //será possible renombrar y borrar estas bibliotecas renameLibraryAction->setEnabled(true); @@ -2579,7 +2579,7 @@ void LibraryWindow::deleteComicsFromDisk() QLOG_INFO() << comic.parentId; } - ComicsRemover * remover = new ComicsRemover(indexList,paths); + ComicsRemover * remover = new ComicsRemover(indexList,paths,comics.at(0).parentId); QThread * thread = NULL; thread = new QThread(this); @@ -2592,6 +2592,8 @@ void LibraryWindow::deleteComicsFromDisk() connect(remover, SIGNAL(remove(int)), comicsModel, SLOT(remove(int))); connect(remover, SIGNAL(removeError()),this,SLOT(setRemoveError())); connect(remover, SIGNAL(finished()), comicsModel, SLOT(finishTransaction())); + connect(remover, SIGNAL(finished()), comicsModel, SLOT(finishTransaction())); + connect(remover, SIGNAL(removedItemsFromFolder(qulonglong)), foldersModel, SLOT(updateFolderChildrenInfo(qulonglong))); connect(remover, SIGNAL(finished()),this,SLOT(checkEmptyFolder())); connect(remover, SIGNAL(finished()),this,SLOT(checkRemoveError())); From cfffc1bae8ad51682bf7dda18326708bd2a9d294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 25 Jan 2016 21:22:39 +0100 Subject: [PATCH 21/23] fixed Content-Type for various controllers --- YACReaderLibrary/server/controllers/comiccontroller.cpp | 2 +- .../server/controllers/comicdownloadinfocontroller.cpp | 2 +- YACReaderLibrary/server/controllers/foldercontentcontroller.cpp | 2 +- YACReaderLibrary/server/controllers/folderinfocontroller.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/YACReaderLibrary/server/controllers/comiccontroller.cpp b/YACReaderLibrary/server/controllers/comiccontroller.cpp index 52ae4e00..f00461ca 100644 --- a/YACReaderLibrary/server/controllers/comiccontroller.cpp +++ b/YACReaderLibrary/server/controllers/comiccontroller.cpp @@ -79,7 +79,7 @@ void ComicController::service(HttpRequest& request, HttpResponse& response) session.setCurrentComic(comic.id, comicFile); } - response.setHeader("Content-Type", "plain/text; charset=utf-8"); + response.setHeader("Content-Type", "text/plain; charset=utf-8"); //TODO this field is not used by the client! response.writeText(QString("library:%1\r\n").arg(libraryName)); response.writeText(QString("libraryId:%1\r\n").arg(libraryId)); diff --git a/YACReaderLibrary/server/controllers/comicdownloadinfocontroller.cpp b/YACReaderLibrary/server/controllers/comicdownloadinfocontroller.cpp index aeab979a..8143ec82 100644 --- a/YACReaderLibrary/server/controllers/comicdownloadinfocontroller.cpp +++ b/YACReaderLibrary/server/controllers/comicdownloadinfocontroller.cpp @@ -10,7 +10,7 @@ ComicDownloadInfoController::ComicDownloadInfoController() {} void ComicDownloadInfoController::service(HttpRequest& request, HttpResponse& response) { - response.setHeader("Content-Type", "plain/text; charset=utf-8"); + response.setHeader("Content-Type", "text/plain; charset=utf-8"); QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8(); QStringList pathElements = path.split('/'); diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp index 776d99cb..f07439ba 100644 --- a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp @@ -23,7 +23,7 @@ FolderContentController::FolderContentController() {} void FolderContentController::service(HttpRequest& request, HttpResponse& response) { - response.setHeader("Content-Type", "plain/text; charset=utf-8"); + response.setHeader("Content-Type", "text/plain; charset=utf-8"); QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8(); QStringList pathElements = path.split('/'); diff --git a/YACReaderLibrary/server/controllers/folderinfocontroller.cpp b/YACReaderLibrary/server/controllers/folderinfocontroller.cpp index 0d8f333f..6aaf9029 100644 --- a/YACReaderLibrary/server/controllers/folderinfocontroller.cpp +++ b/YACReaderLibrary/server/controllers/folderinfocontroller.cpp @@ -12,7 +12,7 @@ FolderInfoController::FolderInfoController() {} void FolderInfoController::service(HttpRequest& request, HttpResponse& response) { - response.setHeader("Content-Type", "plain/text; charset=utf-8"); + response.setHeader("Content-Type", "text/plain; charset=utf-8"); QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8(); QStringList pathElements = path.split('/'); From 4350d6797e9bad37f6ab34f4fd3726bb16f3dfc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 25 Jan 2016 22:23:49 +0100 Subject: [PATCH 22/23] added a new controller for serving the tags in a library --- YACReaderLibrary/db_helper.cpp | 54 +++++++++++++++++++ YACReaderLibrary/db_helper.h | 4 +- .../server/controllers/tagscontroller.cpp | 30 +++++++++++ .../server/controllers/tagscontroller.h | 22 ++++++++ YACReaderLibrary/server/requestmapper.cpp | 6 +++ YACReaderLibrary/server/server.pri | 6 ++- 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 YACReaderLibrary/server/controllers/tagscontroller.cpp create mode 100644 YACReaderLibrary/server/controllers/tagscontroller.h diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 5869a15f..bd633439 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -14,6 +14,7 @@ #include +#include "reading_list_item.h" #include "library_item.h" #include "comic_db.h" #include "data_base_management.h" @@ -961,6 +962,59 @@ QList DBHelper::getComicsFromParent(qulonglong parentId, QSqlData return list; } +QList DBHelper::getLabelItems(qulonglong libraryId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name",db); //TODO add some kind of + QList labels; + + while(selectQuery.next()) + { + QSqlRecord record = selectQuery.record(); + LabelItem *item = new LabelItem(QList() + << record.value("name") + << record.value("color") + << record.value("id") + << record.value("ordering")); + + if(labels.isEmpty()) + { + labels << item; + } + else + { + int i = 0; + + while (i < labels.count() && (labels.at(i)->colorid() < item->colorid()) ) + i++; + + if(i < labels.count()) + { + if(labels.at(i)->colorid() == item->colorid()) //sort by name + { + while( i < labels.count() && labels.at(i)->colorid() == item->colorid() && naturalSortLessThanCI(labels.at(i)->name(),item->name())) + i++; + } + } + if(i >= labels.count()) + { + labels << item; + } + else + { + labels.insert(i,item); + } + } + } + + db.close(); + QSqlDatabase::removeDatabase(libraryPath); + + return labels; +} + //loads Folder DBHelper::loadFolder(qulonglong id, QSqlDatabase & db) { diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h index 27c412e1..be2e323e 100644 --- a/YACReaderLibrary/db_helper.h +++ b/YACReaderLibrary/db_helper.h @@ -9,6 +9,7 @@ class QString; class ComicDB; class Folder; class LibraryItem; +class LabelItem; class QSqlDatabase; class ComicInfo; class QSqlRecord; @@ -73,7 +74,8 @@ public: static QList getFoldersFromParent(qulonglong parentId, QSqlDatabase & db, bool sort = true); static QList getSortedComicsFromParent(qulonglong parentId, QSqlDatabase & db); static QList getComicsFromParent(qulonglong parentId, QSqlDatabase & db, bool sort = true); - //load + static QList getLabelItems(qulonglong libraryId); + //load static Folder loadFolder(qulonglong id, QSqlDatabase & db); static Folder loadFolder(const QString & folderName, qulonglong parentId, QSqlDatabase & db); static ComicDB loadComic(qulonglong id, QSqlDatabase & db); diff --git a/YACReaderLibrary/server/controllers/tagscontroller.cpp b/YACReaderLibrary/server/controllers/tagscontroller.cpp new file mode 100644 index 00000000..d1aa877f --- /dev/null +++ b/YACReaderLibrary/server/controllers/tagscontroller.cpp @@ -0,0 +1,30 @@ +#include "tagscontroller.h" + +#include "db_helper.h" +#include "yacreader_libraries.h" + +#include "reading_list_item.h" +#include "../static.h" +#include "yacreader_global.h" + +#include "QsLog.h" + +TagsController::TagsController() {} + +void TagsController::service(HttpRequest& request, HttpResponse& response) +{ + response.setHeader("Content-Type", "text/plain; charset=utf-8"); + + QString path = QUrl::fromPercentEncoding(request.getPath()).toUtf8(); + QStringList pathElements = path.split('/'); + int libraryId = pathElements.at(2).toInt(); + + QList tags = DBHelper::getLabelItems(libraryId); + + foreach(LabelItem * tag, tags) + { + response.writeText(QString("%1\t%2\t%3\r\n").arg(tag->getId()).arg(tag->name()).arg(labelColorToRGBString(tag->colorid()))); + } + + response.writeText("",true); +} diff --git a/YACReaderLibrary/server/controllers/tagscontroller.h b/YACReaderLibrary/server/controllers/tagscontroller.h new file mode 100644 index 00000000..eb97ee04 --- /dev/null +++ b/YACReaderLibrary/server/controllers/tagscontroller.h @@ -0,0 +1,22 @@ +#ifndef TAGSCONTROLLER_H +#define TAGSCONTROLLER_H + +#include "httprequest.h" +#include "httpresponse.h" +#include "httprequesthandler.h" + + + +class TagsController : public HttpRequestHandler { + Q_OBJECT + Q_DISABLE_COPY(TagsController) +public: + + /** Constructor */ + TagsController(); + + /** Generates the response */ + void service(HttpRequest& request, HttpResponse& response); +}; + +#endif // TAGSCONTROLLER_H diff --git a/YACReaderLibrary/server/requestmapper.cpp b/YACReaderLibrary/server/requestmapper.cpp index 2e887956..d9a98162 100644 --- a/YACReaderLibrary/server/requestmapper.cpp +++ b/YACReaderLibrary/server/requestmapper.cpp @@ -24,6 +24,7 @@ #include "controllers/synccontroller.h" #include "controllers/versioncontroller.h" #include "controllers/foldercontentcontroller.h" +#include "controllers/tagscontroller.h" #include "db_helper.h" #include "yacreader_libraries.h" @@ -109,6 +110,7 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QRegExp comicPageRemote("/library/.+/comic/[0-9]+/page/[0-9]+/remote?"); //get comic page (remote reading) QRegExp serverVersion("/version/?"); QRegExp folderContent("/library/.+/folder/[0-9]+/content/?"); + QRegExp tags("/library/.+/tags/?"); QRegExp sync("/sync"); @@ -175,6 +177,10 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { { FolderContentController().service(request, response); } + else if(tags.exactMatch(path)) + { + TagsController().service(request, response); + } } else { diff --git a/YACReaderLibrary/server/server.pri b/YACReaderLibrary/server/server.pri index 6f1588b4..5b903135 100644 --- a/YACReaderLibrary/server/server.pri +++ b/YACReaderLibrary/server/server.pri @@ -18,7 +18,8 @@ HEADERS += \ $$PWD/controllers/synccontroller.h \ #v2 $$PWD/controllers/versioncontroller.h \ - $$PWD/controllers/foldercontentcontroller.h + $$PWD/controllers/foldercontentcontroller.h \ + $$PWD/controllers/tagscontroller.h SOURCES += \ $$PWD/static.cpp \ @@ -37,7 +38,8 @@ SOURCES += \ $$PWD/controllers/synccontroller.cpp \ #v2 $$PWD/controllers/versioncontroller.cpp \ - $$PWD/controllers/foldercontentcontroller.cpp + $$PWD/controllers/foldercontentcontroller.cpp \ + $$PWD/controllers/tagscontroller.cpp include(lib/bfLogging/bfLogging.pri) include(lib/bfHttpServer/bfHttpServer.pri) From 3df1e99929c408d9fc6f18ed312e3c2efd9417df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Mon, 25 Jan 2016 22:28:15 +0100 Subject: [PATCH 23/23] replaced separator char --- .../server/controllers/foldercontentcontroller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp index f07439ba..8d88c96a 100644 --- a/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontentcontroller.cpp @@ -54,12 +54,12 @@ void FolderContentController::serviceContent(const int &library, const qulonglon if((*itr)->isDir()) { currentFolder = (Folder *)(*itr); - response.writeText(QString("f:%1:%2:%3:%4:%5\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->getNumChildren()).arg(currentFolder->getFirstChildHash())); + response.writeText(QString("f\t%1\t%2\t%3\t%4\t%5\r\n").arg(library).arg(currentFolder->id).arg(currentFolder->name).arg(currentFolder->getNumChildren()).arg(currentFolder->getFirstChildHash())); } else { currentComic = (ComicDB *)(*itr); - response.writeText(QString("c:%1:%2:%3:%4:%5\r\n").arg(library).arg(currentComic->id).arg(currentComic->getFileName()).arg(currentComic->getFileSize()).arg(currentComic->info.hash)); + response.writeText(QString("c\t%1\t%2\t%3\t%4\t%5\r\n").arg(library).arg(currentComic->id).arg(currentComic->getFileName()).arg(currentComic->getFileSize()).arg(currentComic->info.hash)); } }