diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 4d47b56..f2bd5fd 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -849,3 +849,62 @@ void ContentManager::setSortBy(const QString& sortBy, const bool sortOrderAsc) m_sortOrderAsc = sortOrderAsc; emit(booksChanged()); } + +void ContentManager::setMonitorDirZims(QString monitorDir, Library::QStringSet zimList) +{ + m_knownZimsInDir[monitorDir] = zimList; +} + +void ContentManager::asyncUpdateLibraryFromDir(QString dir) +{ + (void) QtConcurrent::run([=]() { + updateLibraryFromDir(dir); + }); +} + +void ContentManager::updateLibraryFromDir(QString monitorDir) +{ + typedef Library::QStringSet QStringSet; + + QMutexLocker locker(&m_updateFromDirMutex); + const QDir dir(monitorDir); + const QStringSet oldDirEntries = m_knownZimsInDir[monitorDir]; + QStringSet newDirEntries; + for (const auto &file : dir.entryList({"*.zim"})) { + newDirEntries.insert(QDir::toNativeSeparators(monitorDir + "/" + file)); + } + const QStringSet addedZims = newDirEntries - oldDirEntries; + const QStringSet removedZims = oldDirEntries - newDirEntries; + const auto kiwixLib = mp_library->getKiwixLibrary(); + kiwix::Manager manager(kiwixLib); + bool needsRefresh = !removedZims.empty(); + for (auto bookPath : removedZims) { + try { + // qDebug() << "DBG: ContentManager::updateLibraryFromDir(): " + // << "file disappeared: " << bookPath; + const auto book = kiwixLib->getBookByPath(bookPath.toStdString()); + handleDisappearedZimFile(QString::fromStdString(book.getId())); + } catch (...) {} + } + for (auto bookPath : addedZims) { + if ( mp_library->isBeingDownloadedByUs(bookPath) ) { + // qDebug() << "DBG: ContentManager::updateLibraryFromDir(): " + // << bookPath + // << " ignored since it is being downloaded by us."; + } else { + // qDebug() << "DBG: ContentManager::updateLibraryFromDir(): " + // << "file appeared: " << bookPath; + needsRefresh |= manager.addBookFromPath(bookPath.toStdString()); + } + } + if (needsRefresh) { + mp_library->save(); + emit(booksChanged()); + setMonitorDirZims(monitorDir, newDirEntries); + } +} + +void ContentManager::handleDisappearedZimFile(QString bookId) +{ + mp_library->removeBookFromLibraryById(bookId); +} diff --git a/src/contentmanager.h b/src/contentmanager.h index 4569715..61cad8f 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -69,6 +69,9 @@ public: // functions QStringList getCategories() const { return m_categories; } LanguageList getLanguages() const { return m_languages; } + void setMonitorDirZims(QString monitorDir, Library::QStringSet zimList); + void asyncUpdateLibraryFromDir(QString dir); + signals: void filterParamsChanged(); void booksChanged(); @@ -113,6 +116,8 @@ private: // functions void updateModel(); void setCategories(); void setLanguages(); + void updateLibraryFromDir(QString dir); + void handleDisappearedZimFile(QString bookId); // Get the book with the specified id from // the remote or local library (in that order). @@ -141,6 +146,9 @@ private: // data ContentManagerModel *managerModel; QMutex remoteLibraryLocker; + + QMutex m_updateFromDirMutex; + QMap m_knownZimsInDir; }; #endif // CONTENTMANAGER_H diff --git a/src/kiwixapp.cpp b/src/kiwixapp.cpp index 1079c84..878824f 100644 --- a/src/kiwixapp.cpp +++ b/src/kiwixapp.cpp @@ -103,21 +103,28 @@ void KiwixApp::init() } }); connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, [=](QString monitorDir) { - m_library.asyncUpdateFromDir(monitorDir); + mp_manager->asyncUpdateLibraryFromDir(monitorDir); }); + + setupDirectoryMonitoring(); + + restoreTabs(); + restoreWindowState(); +} + +void KiwixApp::setupDirectoryMonitoring() +{ QString monitorDir = m_settingsManager.getMonitorDir(); QString downloadDir = m_settingsManager.getDownloadDir(); auto dirList = QSet({monitorDir, downloadDir}); for (auto dir : dirList) { if (dir != "") { - m_library.setMonitorDirZims(dir, m_library.getLibraryZimsFromDir(dir)); + const auto zimsInDir = m_library.getLibraryZimsFromDir(dir); + mp_manager->setMonitorDirZims(dir, zimsInDir); m_watcher.addPath(dir); - m_library.asyncUpdateFromDir(dir); + mp_manager->asyncUpdateLibraryFromDir(dir); } } - - restoreTabs(); - restoreWindowState(); } KiwixApp::~KiwixApp() @@ -336,15 +343,10 @@ bool KiwixApp::isCurrentArticleBookmarked() void KiwixApp::setMonitorDir(const QString &dir) { m_settingsManager.setMonitorDir(dir); - m_library.setMonitorDirZims(dir, QStringList()); for (auto path : m_watcher.directories()) { m_watcher.removePath(path); } - if (dir != "") { - m_watcher.addPath(dir); - m_watcher.addPath(m_settingsManager.getDownloadDir()); - m_library.asyncUpdateFromDir(dir); - } + setupDirectoryMonitoring(); } #define CREATE_ACTION(ID, TEXT) \ diff --git a/src/kiwixapp.h b/src/kiwixapp.h index ae5342d..898d2f3 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -123,6 +123,7 @@ private: QAction* mpa_actions[MAX_ACTION]; + void setupDirectoryMonitoring(); QString findLibraryDirectory(); void restoreTabs(); void loadAndInstallTranslations(QTranslator& translator, const QString& filename, const QString& directory); diff --git a/src/library.cpp b/src/library.cpp index 8ce7451..a79bcd7 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -194,74 +194,21 @@ void Library::save() mp_library->writeBookmarksToFile(kiwix::appendToDirectory(m_libraryDirectory.toStdString(), "library.bookmarks.xml")); } -void Library::setMonitorDirZims(QString monitorDir, QStringList zimList) +Library::QStringSet Library::getLibraryZimsFromDir(QString dir) const { - m_knownZimsInDir[monitorDir] = zimList; -} - -QStringList Library::getLibraryZimsFromDir(QString dir) const -{ - QStringList zimsInDir; + QStringSet zimsInDir; for (auto str : getBookIds()) { auto filePath = QString::fromStdString(getBookById(str).getPath()); if ( filePath.endsWith(BEINGDOWNLOADEDSUFFIX) ) continue; QDir absoluteDir = QFileInfo(filePath).absoluteDir(); if (absoluteDir == dir) { - zimsInDir.push_back(filePath); + zimsInDir.insert(filePath); } } return zimsInDir; } -void Library::updateFromDir(QString monitorDir) -{ - QMutexLocker locker(&m_updateFromDirMutex); - const QDir dir(monitorDir); - QStringList newDirEntries = dir.entryList({"*.zim"}); - QStringList oldDirEntries = m_knownZimsInDir[monitorDir]; - for (auto &str : newDirEntries) { - str = QDir::toNativeSeparators(monitorDir + "/" + str); - } - QSet newDir, oldDir; -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - newDir = QSet::fromList(newDirEntries); - oldDir = QSet::fromList(oldDirEntries); -#else - newDir = QSet(newDirEntries.begin(), newDirEntries.end()); - oldDir = QSet(oldDirEntries.begin(), oldDirEntries.end()); -#endif - QStringList addedZims = (newDir - oldDir).values(); - QStringList removedZims = (oldDir - newDir).values(); - auto manager = kiwix::Manager(LibraryManipulator(this)); - bool needsRefresh = !removedZims.empty(); - for (auto bookPath : addedZims) { - if ( isBeingDownloadedByUs(bookPath) ) { - // qDebug() << "DBG: Library::updateFromDir(): " - // << bookPath - // << " ignored since it is being downloaded by us."; - } else { - needsRefresh |= manager.addBookFromPath(bookPath.toStdString()); - } - } - for (auto bookPath : removedZims) { - try { - removeBookFromLibraryById(QString::fromStdString(mp_library->getBookByPath(bookPath.toStdString()).getId())); - } catch (...) {} - } - if (needsRefresh) { - emit(booksChanged()); - setMonitorDirZims(monitorDir, newDir.values()); - } -} - -void Library::asyncUpdateFromDir(QString dir) -{ - (void) QtConcurrent::run([=]() { - updateFromDir(dir); - }); -} - const kiwix::Book &Library::getBookById(QString id) const { return mp_library->getBookById(id.toStdString()); diff --git a/src/library.h b/src/library.h index b6af1be..0ca75fb 100644 --- a/src/library.h +++ b/src/library.h @@ -26,6 +26,8 @@ class Library : public QObject Q_OBJECT Q_PROPERTY(QStringList bookIds READ getBookIds NOTIFY booksChanged) public: + typedef QSet QStringSet; + Library(const QString& libraryDirectory); virtual ~Library(); QString openBookFromPath(const QString& zimPath); @@ -34,8 +36,7 @@ public: QStringList getBookIds() const; QStringList listBookIds(const kiwix::Filter& filter, kiwix::supportedListSortBy sortBy, bool ascending) const; const std::vector getBookmarks(bool onlyValidBookmarks = false) const { return mp_library->getBookmarks(onlyValidBookmarks); } - QStringList getLibraryZimsFromDir(QString dir) const; - void setMonitorDirZims(QString monitorDir, QStringList zimList); + QStringSet getLibraryZimsFromDir(QString dir) const; void addBookToLibrary(kiwix::Book& book); void addBookBeingDownloaded(const kiwix::Book& book, QString downloadDir); bool isBeingDownloadedByUs(QString path) const; @@ -45,8 +46,6 @@ public: void addBookmark(kiwix::Bookmark& bookmark); void removeBookmark(const QString& zimId, const QString& url); void save(); - void updateFromDir(QString dir); - void asyncUpdateFromDir(QString dir); kiwix::LibraryPtr getKiwixLibrary() { return mp_library; } public slots: const kiwix::Book& getBookById(QString id) const; @@ -56,10 +55,8 @@ signals: void bookmarksChanged(); private: - QMutex m_updateFromDirMutex; kiwix::LibraryPtr mp_library; QString m_libraryDirectory; - QMap m_knownZimsInDir; friend class LibraryManipulator; };