diff --git a/YACReader/main_window_viewer.cpp b/YACReader/main_window_viewer.cpp index f5abf669..07e75f17 100644 --- a/YACReader/main_window_viewer.cpp +++ b/YACReader/main_window_viewer.cpp @@ -1683,6 +1683,7 @@ void MainWindowViewer::sendComic() { YACReaderLocalClient * client = new YACReaderLocalClient; currentComicDB.info.hasBeenOpened = true; + currentComicDB.info.lastTimeOpened = QDateTime::currentSecsSinceEpoch(); viewer->updateComic(currentComicDB); int retries = 1; while(!client->sendComicInfo(libraryId,currentComicDB) && retries!=0) diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index 88a2c851..bc00bf00 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -1,325 +1,327 @@ -TEMPLATE = app -TARGET = YACReaderLibrary - -QMAKE_TARGET_BUNDLE_PREFIX = "com.yacreader" - -DEPENDPATH += . -INCLUDEPATH += . \ - ../common \ - ./server \ - ./db \ - ../custom_widgets \ - ./comic_vine \ - ./comic_vine/model - -DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY -QMAKE_MAC_SDK = macosx10.12 - -# load default build flags -include (../config.pri) -include (../dependencies/pdf_backend.pri) - -unix:haiku { - DEFINES += _BSD_SOURCE - LIBS += -lnetwork -lbsd -} - -CONFIG(legacy_gl_widget) { - INCLUDEPATH += ../common/gl_legacy \ -} else { - INCLUDEPATH += ../common/gl \ -} - -# there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based -win32 { - CONFIG(force_angle) { - message("using ANGLE") - LIBS += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32 - # linking extra libs are necesary for a successful compilation, a better approach should be - # to remove any OpenGL (desktop) dependencies - # the OpenGL stuff should be migrated to OpenGL ES - DEFINES += FORCE_ANGLE - } else { - LIBS += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32 - } - - QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL - QMAKE_LFLAGS_RELEASE += /LTCG - CONFIG -= embed_manifest_exe -} - -CONFIG(force_angle) { - contains(QMAKE_TARGET.arch, x86_64) { - Release:DESTDIR = ../release64_angle - Debug:DESTDIR = ../debug64_angle - } else { - Release:DESTDIR = ../release_angle - Debug:DESTDIR = ../debug_angle - } -} else { - contains(QMAKE_TARGET.arch, x86_64) { - Release:DESTDIR = ../release64 - Debug:DESTDIR = ../debug64 - } else { - Release:DESTDIR = ../release - Debug:DESTDIR = ../debug - } -} - -unix:!macx:!CONFIG(no_opengl) { - LIBS += -lGLU -} - -macx { - LIBS += -framework Foundation -framework ApplicationServices -framework AppKit - CONFIG += objective_c - QT += macextras gui-private -} - -unix:!macx { - CONFIG += c++11 -} - -#CONFIG += release -CONFIG -= flat -QT += sql network widgets script -!CONFIG(no_opengl) { - QT += opengl -} - -# Input -HEADERS += comic_flow.h \ - create_library_dialog.h \ - library_creator.h \ - library_window.h \ - add_library_dialog.h \ - rename_library_dialog.h \ - properties_dialog.h \ - options_dialog.h \ - export_library_dialog.h \ - import_library_dialog.h \ - package_manager.h \ - bundle_creator.h \ - export_comics_info_dialog.h \ - import_comics_info_dialog.h \ - server_config_dialog.h \ - comic_flow_widget.h \ - db_helper.h \ - ./db/data_base_management.h \ - ./db/folder_item.h \ - ./db/folder_model.h \ - ./db/comic_model.h \ - ./db/comic_item.h \ - ../common/comic_db.h \ - ../common/folder.h \ - ../common/library_item.h \ - ../common/comic.h \ - ../common/bookmarks.h \ - ../common/pictureflow.h \ - ../common/custom_widgets.h \ - ../common/qnaturalsorting.h \ - ../common/yacreader_global.h \ - ../common/yacreader_global_gui.h \ - ../common/onstart_flow_selection_dialog.h \ - ../common/pdf_comic.h \ - no_libraries_widget.h \ - import_widget.h \ - yacreader_local_server.h \ - yacreader_main_toolbar.h \ - comics_remover.h \ - ../common/http_worker.h \ - yacreader_libraries.h \ - ../common/exit_check.h \ - comics_view.h \ - classic_comics_view.h \ - empty_folder_widget.h \ - no_search_results_widget.h \ - comic_files_manager.h \ - db/reading_list_model.h \ - db/reading_list_item.h \ - yacreader_folders_view.h \ - yacreader_reading_lists_view.h \ - add_label_dialog.h \ - yacreader_history_controller.h \ - yacreader_navigation_controller.h \ - empty_label_widget.h \ - empty_container_info.h \ - empty_special_list.h \ - empty_reading_list_widget.h \ - ../common/scroll_management.h \ - ../common/opengl_checker.h \ - yacreader_comics_views_manager.h \ - info_comics_view.h \ - yacreader_comics_selection_helper.h \ - yacreader_comic_info_helper.h - -!CONFIG(no_opengl) { - CONFIG(legacy_gl_widget) { - message("using legacy YACReaderFlowGL (QGLWidget) header") - HEADERS += ../common/gl_legacy/yacreader_flow_gl.h - } else { - HEADERS += ../common/gl/yacreader_flow_gl.h - } -} - -SOURCES += comic_flow.cpp \ - create_library_dialog.cpp \ - library_creator.cpp \ - library_window.cpp \ - main.cpp \ - add_library_dialog.cpp \ - rename_library_dialog.cpp \ - properties_dialog.cpp \ - options_dialog.cpp \ - export_library_dialog.cpp \ - import_library_dialog.cpp \ - package_manager.cpp \ - bundle_creator.cpp \ - export_comics_info_dialog.cpp \ - import_comics_info_dialog.cpp \ - server_config_dialog.cpp \ - comic_flow_widget.cpp \ - db_helper.cpp \ - ./db/data_base_management.cpp \ - ./db/folder_item.cpp \ - ./db/folder_model.cpp \ - ./db/comic_model.cpp \ - ./db/comic_item.cpp \ - ../common/comic_db.cpp \ - ../common/folder.cpp \ - ../common/library_item.cpp \ - ../common/comic.cpp \ - ../common/bookmarks.cpp \ - ../common/pictureflow.cpp \ - ../common/custom_widgets.cpp \ - ../common/qnaturalsorting.cpp \ - ../common/onstart_flow_selection_dialog.cpp \ - no_libraries_widget.cpp \ - import_widget.cpp \ - yacreader_local_server.cpp \ - yacreader_main_toolbar.cpp \ - comics_remover.cpp \ - ../common/http_worker.cpp \ - ../common/yacreader_global.cpp \ - ../common/yacreader_global_gui.cpp \ - yacreader_libraries.cpp \ - ../common/exit_check.cpp \ - comics_view.cpp \ - classic_comics_view.cpp \ - empty_folder_widget.cpp \ - no_search_results_widget.cpp \ - comic_files_manager.cpp \ - db/reading_list_model.cpp \ - db/reading_list_item.cpp \ - yacreader_folders_view.cpp \ - yacreader_reading_lists_view.cpp \ - add_label_dialog.cpp \ - yacreader_history_controller.cpp \ - yacreader_navigation_controller.cpp \ - empty_label_widget.cpp \ - empty_container_info.cpp \ - empty_special_list.cpp \ - empty_reading_list_widget.cpp \ - ../common/scroll_management.cpp \ - ../common/opengl_checker.cpp \ - yacreader_comics_views_manager.cpp \ - info_comics_view.cpp \ - yacreader_comics_selection_helper.cpp \ - yacreader_comic_info_helper.cpp - -!CONFIG(no_opengl) { - CONFIG(legacy_gl_widget) { - message("using legacy YACReaderFlowGL (QGLWidget) source code") - SOURCES += ../common/gl_legacy/yacreader_flow_gl.cpp - } else { - SOURCES += ../common/gl/yacreader_flow_gl.cpp - } -} - - -include(./server/server.pri) -include(../custom_widgets/custom_widgets_yacreaderlibrary.pri) - -CONFIG(7zip){ -include(../compressed_archive/wrapper.pri) -} else:CONFIG(unarr) { -include(../compressed_archive/unarr/unarr-wrapper.pri) -} else { - error(No compression backend specified. Did you mess with the build system?) -} - -include(./comic_vine/comic_vine.pri) -include(../QsLog/QsLog.pri) -include(../shortcuts_management/shortcuts_management.pri) - -RESOURCES += images.qrc files.qrc -win32:RESOURCES += images_win.qrc -unix:!macx:RESOURCES += images_win.qrc -macx:RESOURCES += images_osx.qrc - -RC_FILE = icon.rc - -macx { - ICON = YACReaderLibrary.icns -} - -TRANSLATIONS = yacreaderlibrary_es.ts \ - yacreaderlibrary_ru.ts \ - yacreaderlibrary_pt.ts \ - yacreaderlibrary_fr.ts \ - yacreaderlibrary_nl.ts \ - yacreaderlibrary_tr.ts \ - yacreaderlibrary_de.ts \ - yacreaderlibrary_source.ts - -#QML/GridView -QT += quick qml - -HEADERS += grid_comics_view.h \ - comics_view_transition.h - -SOURCES += grid_comics_view.cpp \ - comics_view_transition.cpp - -RESOURCES += qml.qrc -win32:RESOURCES += qml_win.qrc -unix:!macx:RESOURCES += qml_win.qrc -macx:RESOURCES += qml_osx.qrc - -unix:!macx { -#set install prefix if it's empty -isEmpty(PREFIX) { - PREFIX = /usr -} - -BINDIR = $$PREFIX/bin -LIBDIR = $$PREFIX/lib -DATADIR = $$PREFIX/share - -DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\"" - -#MAKE INSTALL -INSTALLS += bin icon desktop server translation manpage - -bin.path = $$BINDIR -isEmpty(DESTDIR) { - bin.files = YACReaderLibrary -} else { - bin.files = $$DESTDIR/YACReaderLibrary -} - -server.path = $$DATADIR/yacreader -server.files = ../release/server - -icon.path = $$DATADIR/icons/hicolor/scalable/apps -icon.files = ../YACReaderLibrary.svg - -desktop.path = $$DATADIR/applications -desktop.files = ../YACReaderLibrary.desktop - -translation.path = $$DATADIR/yacreader/languages -translation.files = ../release/languages/yacreaderlibrary_* - -manpage.path = $$DATADIR/man/man1 -manpage.files = ../YACReaderLibrary.1 -} +TEMPLATE = app +TARGET = YACReaderLibrary + +QMAKE_TARGET_BUNDLE_PREFIX = "com.yacreader" + +DEPENDPATH += . +INCLUDEPATH += . \ + ../common \ + ./server \ + ./db \ + ../custom_widgets \ + ./comic_vine \ + ./comic_vine/model + +DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY +QMAKE_MAC_SDK = macosx10.12 + +# load default build flags +include (../config.pri) +include (../dependencies/pdf_backend.pri) + +unix:haiku { + DEFINES += _BSD_SOURCE + LIBS += -lnetwork -lbsd +} + +CONFIG(legacy_gl_widget) { + INCLUDEPATH += ../common/gl_legacy \ +} else { + INCLUDEPATH += ../common/gl \ +} + +# there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based +win32 { + CONFIG(force_angle) { + message("using ANGLE") + LIBS += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32 + # linking extra libs are necesary for a successful compilation, a better approach should be + # to remove any OpenGL (desktop) dependencies + # the OpenGL stuff should be migrated to OpenGL ES + DEFINES += FORCE_ANGLE + } else { + LIBS += -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32 + } + + QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL + QMAKE_LFLAGS_RELEASE += /LTCG + CONFIG -= embed_manifest_exe +} + +CONFIG(force_angle) { + contains(QMAKE_TARGET.arch, x86_64) { + Release:DESTDIR = ../release64_angle + Debug:DESTDIR = ../debug64_angle + } else { + Release:DESTDIR = ../release_angle + Debug:DESTDIR = ../debug_angle + } +} else { + contains(QMAKE_TARGET.arch, x86_64) { + Release:DESTDIR = ../release64 + Debug:DESTDIR = ../debug64 + } else { + Release:DESTDIR = ../release + Debug:DESTDIR = ../debug + } +} + +unix:!macx:!CONFIG(no_opengl) { + LIBS += -lGLU +} + +macx { + LIBS += -framework Foundation -framework ApplicationServices -framework AppKit + CONFIG += objective_c + QT += macextras gui-private +} + +unix:!macx { + CONFIG += c++11 +} + +#CONFIG += release +CONFIG -= flat +QT += sql network widgets script +!CONFIG(no_opengl) { + QT += opengl +} + +# Input +HEADERS += comic_flow.h \ + create_library_dialog.h \ + library_creator.h \ + library_window.h \ + add_library_dialog.h \ + rename_library_dialog.h \ + properties_dialog.h \ + options_dialog.h \ + export_library_dialog.h \ + import_library_dialog.h \ + package_manager.h \ + bundle_creator.h \ + export_comics_info_dialog.h \ + import_comics_info_dialog.h \ + server_config_dialog.h \ + comic_flow_widget.h \ + db_helper.h \ + ./db/data_base_management.h \ + ./db/folder_item.h \ + ./db/folder_model.h \ + ./db/comic_model.h \ + ./db/comic_item.h \ + ../common/comic_db.h \ + ../common/folder.h \ + ../common/library_item.h \ + ../common/comic.h \ + ../common/bookmarks.h \ + ../common/pictureflow.h \ + ../common/custom_widgets.h \ + ../common/qnaturalsorting.h \ + ../common/yacreader_global.h \ + ../common/yacreader_global_gui.h \ + ../common/onstart_flow_selection_dialog.h \ + ../common/pdf_comic.h \ + no_libraries_widget.h \ + import_widget.h \ + yacreader_local_server.h \ + yacreader_main_toolbar.h \ + comics_remover.h \ + ../common/http_worker.h \ + yacreader_libraries.h \ + ../common/exit_check.h \ + comics_view.h \ + classic_comics_view.h \ + empty_folder_widget.h \ + no_search_results_widget.h \ + comic_files_manager.h \ + db/reading_list_model.h \ + db/reading_list_item.h \ + yacreader_folders_view.h \ + yacreader_reading_lists_view.h \ + add_label_dialog.h \ + yacreader_history_controller.h \ + yacreader_navigation_controller.h \ + empty_label_widget.h \ + empty_container_info.h \ + empty_special_list.h \ + empty_reading_list_widget.h \ + ../common/scroll_management.h \ + ../common/opengl_checker.h \ + yacreader_comics_views_manager.h \ + info_comics_view.h \ + yacreader_comics_selection_helper.h \ + yacreader_comic_info_helper.h \ + db/reading_list.h + +!CONFIG(no_opengl) { + CONFIG(legacy_gl_widget) { + message("using legacy YACReaderFlowGL (QGLWidget) header") + HEADERS += ../common/gl_legacy/yacreader_flow_gl.h + } else { + HEADERS += ../common/gl/yacreader_flow_gl.h + } +} + +SOURCES += comic_flow.cpp \ + create_library_dialog.cpp \ + library_creator.cpp \ + library_window.cpp \ + main.cpp \ + add_library_dialog.cpp \ + rename_library_dialog.cpp \ + properties_dialog.cpp \ + options_dialog.cpp \ + export_library_dialog.cpp \ + import_library_dialog.cpp \ + package_manager.cpp \ + bundle_creator.cpp \ + export_comics_info_dialog.cpp \ + import_comics_info_dialog.cpp \ + server_config_dialog.cpp \ + comic_flow_widget.cpp \ + db_helper.cpp \ + ./db/data_base_management.cpp \ + ./db/folder_item.cpp \ + ./db/folder_model.cpp \ + ./db/comic_model.cpp \ + ./db/comic_item.cpp \ + ../common/comic_db.cpp \ + ../common/folder.cpp \ + ../common/library_item.cpp \ + ../common/comic.cpp \ + ../common/bookmarks.cpp \ + ../common/pictureflow.cpp \ + ../common/custom_widgets.cpp \ + ../common/qnaturalsorting.cpp \ + ../common/onstart_flow_selection_dialog.cpp \ + no_libraries_widget.cpp \ + import_widget.cpp \ + yacreader_local_server.cpp \ + yacreader_main_toolbar.cpp \ + comics_remover.cpp \ + ../common/http_worker.cpp \ + ../common/yacreader_global.cpp \ + ../common/yacreader_global_gui.cpp \ + yacreader_libraries.cpp \ + ../common/exit_check.cpp \ + comics_view.cpp \ + classic_comics_view.cpp \ + empty_folder_widget.cpp \ + no_search_results_widget.cpp \ + comic_files_manager.cpp \ + db/reading_list_model.cpp \ + db/reading_list_item.cpp \ + yacreader_folders_view.cpp \ + yacreader_reading_lists_view.cpp \ + add_label_dialog.cpp \ + yacreader_history_controller.cpp \ + yacreader_navigation_controller.cpp \ + empty_label_widget.cpp \ + empty_container_info.cpp \ + empty_special_list.cpp \ + empty_reading_list_widget.cpp \ + ../common/scroll_management.cpp \ + ../common/opengl_checker.cpp \ + yacreader_comics_views_manager.cpp \ + info_comics_view.cpp \ + yacreader_comics_selection_helper.cpp \ + yacreader_comic_info_helper.cpp \ + db/reading_list.cpp + +!CONFIG(no_opengl) { + CONFIG(legacy_gl_widget) { + message("using legacy YACReaderFlowGL (QGLWidget) source code") + SOURCES += ../common/gl_legacy/yacreader_flow_gl.cpp + } else { + SOURCES += ../common/gl/yacreader_flow_gl.cpp + } +} + + +include(./server/server.pri) +include(../custom_widgets/custom_widgets_yacreaderlibrary.pri) + +CONFIG(7zip){ +include(../compressed_archive/wrapper.pri) +} else:CONFIG(unarr) { +include(../compressed_archive/unarr/unarr-wrapper.pri) +} else { + error(No compression backend specified. Did you mess with the build system?) +} + +include(./comic_vine/comic_vine.pri) +include(../QsLog/QsLog.pri) +include(../shortcuts_management/shortcuts_management.pri) + +RESOURCES += images.qrc files.qrc +win32:RESOURCES += images_win.qrc +unix:!macx:RESOURCES += images_win.qrc +macx:RESOURCES += images_osx.qrc + +RC_FILE = icon.rc + +macx { + ICON = YACReaderLibrary.icns +} + +TRANSLATIONS = yacreaderlibrary_es.ts \ + yacreaderlibrary_ru.ts \ + yacreaderlibrary_pt.ts \ + yacreaderlibrary_fr.ts \ + yacreaderlibrary_nl.ts \ + yacreaderlibrary_tr.ts \ + yacreaderlibrary_de.ts \ + yacreaderlibrary_source.ts + +#QML/GridView +QT += quick qml + +HEADERS += grid_comics_view.h \ + comics_view_transition.h + +SOURCES += grid_comics_view.cpp \ + comics_view_transition.cpp + +RESOURCES += qml.qrc +win32:RESOURCES += qml_win.qrc +unix:!macx:RESOURCES += qml_win.qrc +macx:RESOURCES += qml_osx.qrc + +unix:!macx { +#set install prefix if it's empty +isEmpty(PREFIX) { + PREFIX = /usr +} + +BINDIR = $$PREFIX/bin +LIBDIR = $$PREFIX/lib +DATADIR = $$PREFIX/share + +DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\"" + +#MAKE INSTALL +INSTALLS += bin icon desktop server translation manpage + +bin.path = $$BINDIR +isEmpty(DESTDIR) { + bin.files = YACReaderLibrary +} else { + bin.files = $$DESTDIR/YACReaderLibrary +} + +server.path = $$DATADIR/yacreader +server.files = ../release/server + +icon.path = $$DATADIR/icons/hicolor/scalable/apps +icon.files = ../YACReaderLibrary.svg + +desktop.path = $$DATADIR/applications +desktop.files = ../YACReaderLibrary.desktop + +translation.path = $$DATADIR/yacreader/languages +translation.files = ../release/languages/yacreaderlibrary_* + +manpage.path = $$DATADIR/man/man1 +manpage.files = ../YACReaderLibrary.1 +} 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 06fd397a..fd6f1a6d 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -582,7 +582,7 @@ void ComicModel::setupFavoritesModelData(const QString &databasePath) "ORDER BY cdrl.ordering"); selectQuery.bindValue(":parentDefaultListId", 1); selectQuery.exec(); - setupModelData(selectQuery); + setupModelDataForList(selectQuery); } db.close(); QSqlDatabase::removeDatabase(_databasePath); @@ -607,9 +607,11 @@ void ComicModel::setupReadingModelData(const QString &databasePath) QSqlQuery selectQuery(db); selectQuery.prepare("SELECT ci.number,ci.title,c.fileName,ci.numPages,c.id,c.parentId,c.path,ci.hash,ci.read,ci.isBis,ci.currentPage,ci.rating,ci.hasBeenOpened " "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " - "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1"); + "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1 " + "ORDER BY ci.lastTimeOpened DESC"); selectQuery.exec(); - setupModelData(selectQuery); + + setupModelDataForList(selectQuery); } db.close(); QSqlDatabase::removeDatabase(_databasePath); @@ -928,7 +930,7 @@ void ComicModel::removeInTransaction(int row) endRemoveRows(); } - +/* void ComicModel::remove(ComicDB * comic, int row) { beginRemoveRows(QModelIndex(),row,row); @@ -944,7 +946,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 bf517298..b23750c3 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/data_base_management.cpp b/YACReaderLibrary/db/data_base_management.cpp index 8d18d478..25edf1d3 100644 --- a/YACReaderLibrary/db/data_base_management.cpp +++ b/YACReaderLibrary/db/data_base_management.cpp @@ -124,99 +124,103 @@ 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," + //new 8.6 fields + "lastTimeOpened INTEGER" - ")"); - 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 + //new 8.6 fields + "numChildren INTEGER," + "firstChildHash TEXT," + "customImage TEXT," + "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; @@ -415,7 +419,9 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest) "edited = :edited," - "comicVineID = :comicVineID" + "comicVineID = :comicVineID," + + "lastTimeOpened = :lastTimeOpened" " WHERE hash = :hash "); @@ -449,6 +455,7 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest) "read," "edited," "comicVineID," + "lastTimeOpened," "hash)" "VALUES (:title," @@ -486,6 +493,8 @@ bool DataBaseManagement::importComicsInfo(QString source, QString dest) ":edited," ":comicVineID," + ":lastTimeOpened," + ":hash )"); QSqlRecord record = newInfo.record(); @@ -596,6 +605,8 @@ void DataBaseManagement::bindValuesFromRecord(const QSqlRecord & record, QSqlQue bindString("comicVineID",record,query); + bindString("lastTimeOpened",record,query); + bindString("hash",record,query); } @@ -616,6 +627,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()) @@ -686,6 +710,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 +718,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 +772,27 @@ bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath) { returnValue = returnValue && createV8Tables(db); } + + if(pre8_6) + { + {//folder + QStringList columnDefs; + //a full library update is needed after updating the table + columnDefs << "numChildren INTEGER"; + columnDefs << "firstChildHash TEXT"; + columnDefs << "customImage TEXT"; + returnValue = returnValue && addColumns("folder", columnDefs, db); + } + + {//comic_info + QStringList columnDefs; + columnDefs << "lastTimeOpened INTEGER"; + returnValue = returnValue && addColumns("comic_info", columnDefs, db); + + QSqlQuery queryIndexLastTimeOpened(db); + returnValue = returnValue && queryIndexLastTimeOpened.exec("CREATE INDEX last_time_opened_index ON comic_info (lastTimeOpened)"); + } + } } db.close(); 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(); diff --git a/YACReaderLibrary/db/folder_model.cpp b/YACReaderLibrary/db/folder_model.cpp index a2d4b1d6..48eebe51 100644 --- a/YACReaderLibrary/db/folder_model.cpp +++ b/YACReaderLibrary/db/folder_model.cpp @@ -184,6 +184,9 @@ 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(); @@ -315,7 +318,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); QSqlRecord record = sqlquery.record(); @@ -562,6 +565,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; @@ -600,11 +604,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/reading_list.cpp b/YACReaderLibrary/db/reading_list.cpp new file mode 100644 index 00000000..b27b6650 --- /dev/null +++ b/YACReaderLibrary/db/reading_list.cpp @@ -0,0 +1,44 @@ +#include "reading_list.h" + +ReadingList::ReadingList(const QString &name, qulonglong id, int ordering) + :name(name), id(id), ordering(ordering) +{ + +} + +qulonglong ReadingList::getId() const +{ + return id; +} + +QString ReadingList::getName() const +{ + return name; +} + +int ReadingList::getOrdering() const +{ + return ordering; +} + + +Label::Label(const QString &name, qulonglong id, YACReader::LabelColors colorid) + :name(name), id(id), colorid(colorid) +{ + +} + +YACReader::LabelColors Label::getColorID() const +{ + return colorid; +} + +QString Label::getName() const +{ + return name; +} + +qulonglong Label::getId() const +{ + return id; +} diff --git a/YACReaderLibrary/db/reading_list.h b/YACReaderLibrary/db/reading_list.h new file mode 100644 index 00000000..84e41846 --- /dev/null +++ b/YACReaderLibrary/db/reading_list.h @@ -0,0 +1,36 @@ +#ifndef READING_LIST_H +#define READING_LIST_H + +#include "yacreader_global.h" + +class ReadingList +{ +public: + ReadingList(const QString &name, qulonglong id, int ordering); + + qulonglong getId() const; + QString getName() const; + int getOrdering() const; +private: + QString name; + qulonglong id; + int ordering; +}; + +class Label +{ +public: + Label(const QString &name, qulonglong id, YACReader::LabelColors colorid); + + YACReader::LabelColors getColorID() const; + QString getName() const; + qulonglong getId() const; + +private: + QString name; + qulonglong id; + YACReader::LabelColors colorid; + +}; + +#endif // READING_LIST_H diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index 381de0e6..89a9fe96 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -14,6 +14,7 @@ #include +#include "reading_list.h" #include "library_item.h" #include "comic_db.h" #include "data_base_management.h" @@ -58,6 +59,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); @@ -107,8 +140,7 @@ QString DBHelper::getFolderName(qulonglong libraryId, qulonglong id) if(selectQuery.next()) { - QSqlRecord record = selectQuery.record(); - name = record.value(0).toString(); + name = selectQuery.value(0).toString(); } } @@ -126,14 +158,222 @@ QString DBHelper::getLibraryName(int id) { return getLibraries().getName(id); } + +QList DBHelper::getLabelComics(qulonglong libraryId, qulonglong labelId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QList list; + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_label cl ON (c.id == cl.comic_id) " + "WHERE cl.label_id = :parentLabelId " + "ORDER BY cl.ordering"); + selectQuery.bindValue(":parentLabelId", labelId); + selectQuery.exec(); + + while (selectQuery.next()) + { + ComicDB comic; + + comic.id = selectQuery.value(0).toULongLong(); + comic.parentId = labelId; + comic.name = selectQuery.value(1).toString(); + comic.info.title = selectQuery.value(2).toString(); + comic.info.currentPage = selectQuery.value(3).toInt(); + comic.info.numPages = selectQuery.value(4).toInt(); + comic.info.hash = selectQuery.value(5).toString(); + comic.info.read = selectQuery.value(6).toBool(); + + list.append(comic); + } + + db.close(); + } + + return list; +} + +QList DBHelper::getFavorites(qulonglong libraryId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QList list; + + const int FAV_ID = 1; + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT c.id,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_default_reading_list cdrl ON (c.id == cdrl.comic_id) " + "WHERE cdrl.default_reading_list_id = :parentDefaultListId " + "ORDER BY cdrl.ordering"); + selectQuery.bindValue(":parentDefaultListId", FAV_ID); + selectQuery.exec(); + + while (selectQuery.next()) + { + ComicDB comic; + + comic.id = selectQuery.value(0).toULongLong(); + comic.parentId = FAV_ID; + comic.name = selectQuery.value(1).toString(); + comic.info.title = selectQuery.value(2).toString(); + comic.info.currentPage = selectQuery.value(3).toInt(); + comic.info.numPages = selectQuery.value(4).toInt(); + comic.info.hash = selectQuery.value(5).toString(); + comic.info.read = selectQuery.value(6).toBool(); + + list.append(comic); + } + + db.close(); + } + + return list; +} + +QList DBHelper::getReading(qulonglong libraryId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QList list; + + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "WHERE ci.hasBeenOpened = 1 AND ci.read = 0 AND ci.currentPage != ci.numPages AND ci.currentPage != 1 " + "ORDER BY ci.lastTimeOpened DESC"); + selectQuery.exec(); + + while (selectQuery.next()) + { + ComicDB comic; + + comic.id = selectQuery.value(0).toULongLong(); + comic.parentId = selectQuery.value(1).toULongLong(); + comic.name = selectQuery.value(2).toString(); + comic.info.title = selectQuery.value(3).toString(); + comic.info.currentPage = selectQuery.value(4).toInt(); + comic.info.numPages = selectQuery.value(5).toInt(); + comic.info.hash = selectQuery.value(6).toString(); + comic.info.read = selectQuery.value(7).toBool(); + + list.append(comic); + } + + db.close(); + } + + return list; +} + +QList DBHelper::getReadingLists(qulonglong libraryId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QList list; + + QSqlQuery selectQuery("SELECT * from reading_list WHERE parentId IS NULL ORDER BY name DESC",db); + + selectQuery.exec(); + + QSqlRecord record = selectQuery.record(); + + int name = record.indexOf("name"); + int id = record.indexOf("id"); + int ordering = record.indexOf("ordering"); + + while (selectQuery.next()) + { + ReadingList item(selectQuery.value(name).toString(), selectQuery.value(id).toLongLong(),selectQuery.value(ordering).toInt()); + + if(list.isEmpty()) + { + list.append(item); + } + else + { + int i= 0; + while(i DBHelper::getReadingListFullContent(qulonglong libraryId, qulonglong readingListId) +{ + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath+"/.yacreaderlibrary"); + + QList list; + + { + QList ids; + ids << readingListId; + + QSqlQuery subfolders(db); + subfolders.prepare("SELECT id " + "FROM reading_list " + "WHERE parentId = :parentId " + "ORDER BY ordering ASC"); + subfolders.bindValue(":parentId", readingListId); + subfolders.exec(); + while(subfolders.next()) + ids << subfolders.value(0).toULongLong(); + + foreach(qulonglong id, ids) + { + QSqlQuery selectQuery(db); + selectQuery.prepare("SELECT c.id,c.parentId,c.fileName,ci.title,ci.currentPage,ci.numPages,ci.hash,ci.read " + "FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) " + "INNER JOIN comic_reading_list crl ON (c.id == crl.comic_id) " + "WHERE crl.reading_list_id = :parentReadingList " + "ORDER BY crl.ordering"); + selectQuery.bindValue(":parentReadingList", id); + selectQuery.exec(); + + while (selectQuery.next()) + { + ComicDB comic; + + comic.id = selectQuery.value(0).toULongLong(); + comic.parentId = selectQuery.value(1).toULongLong(); + comic.name = selectQuery.value(2).toString(); + comic.info.title = selectQuery.value(3).toString(); + comic.info.currentPage = selectQuery.value(4).toInt(); + comic.info.numPages = selectQuery.value(5).toInt(); + comic.info.hash = selectQuery.value(6).toString(); + comic.info.read = selectQuery.value(7).toBool(); + + list.append(comic); + } + } + } + + return list; +} + //objects management //deletes void DBHelper::removeFromDB(LibraryItem * item, QSqlDatabase & db) { if(item->isDir()) - DBHelper::removeFromDB(dynamic_cast(item),db); + DBHelper::removeFromDB(dynamic_cast(item),db); else - DBHelper::removeFromDB(dynamic_cast(item),db); + DBHelper::removeFromDB(dynamic_cast(item),db); } void DBHelper::removeFromDB(Folder * folder, QSqlDatabase & db) { @@ -296,7 +536,10 @@ void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db) "rating = :rating," //new 7.1 fields - "comicVineID = :comicVineID" + "comicVineID = :comicVineID," + + //new 8.6 fields + "lastTimeOpened = :lastTimeOpened" //-- " WHERE id = :id "); @@ -351,6 +594,8 @@ void DBHelper::update(ComicInfo * comicInfo, QSqlDatabase & db) updateComicInfo.bindValue(":comicVineID", comicInfo->comicVineID); + updateComicInfo.bindValue(":lastTimeOpened", comicInfo->lastTimeOpened); + updateComicInfo.exec(); } @@ -379,6 +624,51 @@ 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, " + "firstChildHash = :firstChildHash " + "WHERE id = :id "); + updateFolderInfo.bindValue(":numChildren", folder.getNumChildren()); + updateFolderInfo.bindValue(":firstChildHash", folder.getFirstChildHash()); + 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, " + "firstChildHash = :firstChildHash " + "WHERE id = :id "); + updateFolderInfo.bindValue(":numChildren", subfolders.count() + comics.count()); + updateFolderInfo.bindValue(":firstChildHash", firstComic != NULL ? firstComic->info.hash : ""); + updateFolderInfo.bindValue(":id", folderId); + 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.value(0).toULongLong(), db); + } +} + void DBHelper::updateProgress(qulonglong libraryId, const ComicInfo &comicInfo) { QString libraryPath = DBHelper::getLibraries().getPath(libraryId); @@ -402,12 +692,14 @@ void DBHelper::updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatab "read = :read, " "currentPage = :currentPage, " "hasBeenOpened = :hasBeenOpened, " + "lastTimeOpened = :lastTimeOpened" "rating = :rating" " WHERE id = :id "); updateComicInfo.bindValue(":read", comicInfo.read?1:0); updateComicInfo.bindValue(":currentPage", comicInfo.currentPage); updateComicInfo.bindValue(":hasBeenOpened", comicInfo.hasBeenOpened?1:0); + updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentSecsSinceEpoch()); updateComicInfo.bindValue(":id", comicInfo.id); updateComicInfo.bindValue(":rating", comicInfo.rating); updateComicInfo.exec(); @@ -492,7 +784,7 @@ void DBHelper::reasignOrderToComicsInFavorites(QList comicIds, QSqlD QSqlQuery updateOrdering(db); updateOrdering.prepare("UPDATE comic_default_reading_list SET " "ordering = :ordering " - "WHERE comic_id = :comic_id AND default_reading_list_id = 0"); + "WHERE comic_id = :comic_id AND default_reading_list_id = 1"); db.transaction(); int order = 0; foreach(qulonglong id, comicIds) @@ -554,6 +846,7 @@ qulonglong DBHelper::insert(Folder * folder, QSqlDatabase & db) query.bindValue(":name", folder->name); query.bindValue(":path", folder->path); query.exec(); + return query.lastInsertId().toULongLong(); } @@ -581,6 +874,7 @@ qulonglong DBHelper::insert(ComicDB * comic, QSqlDatabase & db) query.bindValue(":name", comic->name); query.bindValue(":path", comic->path); query.exec(); + return query.lastInsertId().toULongLong(); } @@ -703,13 +997,22 @@ QList DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat int name = record.indexOf("name"); int path = record.indexOf("path"); int id = record.indexOf("id"); + int numChildren = record.indexOf("numChildren"); + int firstChildHash = record.indexOf("firstChildHash"); + int customImage = record.indexOf("customImage"); Folder * currentItem; while (selectQuery.next()) { //TODO sort by sort indicator and name - currentItem = new Folder(selectQuery.value(id).toULongLong(),parentId,selectQuery.value(name).toString(),selectQuery.value(path).toString()); - int lessThan = 0; + currentItem = new Folder(selectQuery.value(id).toULongLong(),parentId,selectQuery.value(name).toString(),selectQuery.value(path).toString()); + + if(!selectQuery.value(numChildren).isNull() && selectQuery.value(numChildren).isValid()) + currentItem->setNumChildren(selectQuery.value(numChildren).toInt()); + currentItem->setFirstChildHash(selectQuery.value(firstChildHash).toString()); + currentItem->setCustomImage(selectQuery.value(customImage).toString()); + + int lessThan = 0; if(list.isEmpty() || !sort) list.append(currentItem); @@ -721,7 +1024,7 @@ QList DBHelper::getFoldersFromParent(qulonglong parentId, QSqlDat QList::iterator i; i = list.end(); i--; - while ((0 > (lessThan = naturalSortLessThanCI(nameCurrent,nameLast))) && i != list.begin()) + while ((0 > (lessThan = naturalCompare(nameCurrent,nameLast,Qt::CaseInsensitive))) && i != list.begin()) { i--; nameLast = (*i)->name; @@ -929,6 +1232,63 @@ QList DBHelper::getComicsFromParent(qulonglong parentId, QSqlData return list; } +QList