diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 7ebadf2..520058a 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -167,5 +167,6 @@ "no-details": "Introduction only", "no-pictures": "No Pictures", "no-videos": "No Videos", - "open-previous-tabs-at-startup": "Open previous tabs at startup" + "open-previous-tabs-at-startup": "Open previous tabs at startup", + "preview-book-in-web-browser": "Preview book in web browser" } diff --git a/resources/i18n/qqq.json b/resources/i18n/qqq.json index ba5c300..9305fd2 100644 --- a/resources/i18n/qqq.json +++ b/resources/i18n/qqq.json @@ -50,5 +50,6 @@ "monitor-clear-dir-dialog-title": "\"Monitor\" means \"watch\" in this context. The monitor directory is monitored/watched for new ZIM files.", "monitor-clear-dir-dialog-msg": "\"Monitor\" means \"watch\" in this context. The monitor directory is monitored/watched for new ZIM files.", "open-book": "\"Open\" is a imperative, not an adjective.", - "open-previous-tabs-at-startup": "The tabs that were open when the user closed the application is opened again when the application is restarted." + "open-previous-tabs-at-startup": "The tabs that were open when the user closed the application is opened again when the application is restarted.", + "preview-book-in-web-browser": "Preview this book by opening the link to its preview website in the native web browser" } diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index 2634a3f..8953742 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -217,17 +217,20 @@ void ContentManager::onCustomContextMenu(const QPoint &point) QAction menuResumeBook(gt("resume-download"), this); QAction menuCancelBook(gt("cancel-download"), this); QAction menuOpenFolder(gt("open-folder"), this); + QAction menuPreviewBook(gt("preview-book-in-web-browser"), this); const auto bookState = getBookState(id); switch ( bookState ) { case BookState::DOWNLOAD_PAUSED: contextMenu.addAction(&menuResumeBook); contextMenu.addAction(&menuCancelBook); + contextMenu.addAction(&menuPreviewBook); break; case BookState::DOWNLOADING: contextMenu.addAction(&menuPauseBook); contextMenu.addAction(&menuCancelBook); + contextMenu.addAction(&menuPreviewBook); break; case BookState::AVAILABLE_LOCALLY_AND_HEALTHY: @@ -249,6 +252,7 @@ void ContentManager::onCustomContextMenu(const QPoint &point) case BookState::AVAILABLE_ONLINE: contextMenu.addAction(&menuDownloadBook); + contextMenu.addAction(&menuPreviewBook); break; default: break; @@ -272,6 +276,9 @@ void ContentManager::onCustomContextMenu(const QPoint &point) connect(&menuResumeBook, &QAction::triggered, [=]() { resumeBook(id, index); }); + connect(&menuPreviewBook, &QAction::triggered, [=]() { + openBookPreview(id); + }); contextMenu.exec(mp_view->getView()->viewport()->mapToGlobal(point)); } @@ -501,6 +508,25 @@ void ContentManager::openBook(const QString &id) } } +void ContentManager::openBookPreview(const QString &id) +{ + try { + QMutexLocker locker(&remoteLibraryLocker); + const std::string &downloadUrl = + mp_remoteLibrary->getBookById(id.toStdString()).getUrl(); + locker.unlock(); + + /* Extract the Zim name from the book's download URL */ + const auto zimNameStartIndex = downloadUrl.find_last_of('/') + 1; + const std::string& zimName = downloadUrl.substr( + zimNameStartIndex, + downloadUrl.find(".zim", zimNameStartIndex) - zimNameStartIndex); + + const QUrl previewUrl = getRemoteLibraryUrl() + "/viewer#" + zimName.c_str(); + QDesktopServices::openUrl(previewUrl); + } catch (...) {} +} + namespace { @@ -642,6 +668,14 @@ const kiwix::Book& ContentManager::getRemoteOrLocalBook(const QString &id) } } +QString ContentManager::getRemoteLibraryUrl() const +{ + auto host = m_remoteLibraryManager.getCatalogHost(); + auto port = m_remoteLibraryManager.getCatalogPort(); + return port == 443 ? "https://" + host + : "http://" + host + ":" + QString::number(port); +} + std::string ContentManager::startDownload(const kiwix::Book& book) { auto downloadPath = getSettingsManager()->getDownloadDir(); @@ -887,27 +921,12 @@ void ContentManager::updateLibrary() { } catch (std::runtime_error&) {} } -namespace -{ - -QString makeHttpUrl(QString host, int port) -{ - return port == 443 - ? "https://" + host - : "http://" + host + ":" + QString::number(port); -} - -} // unnamed namespace - void ContentManager::updateRemoteLibrary(const QString& content) { (void) QtConcurrent::run([=]() { QMutexLocker locker(&remoteLibraryLocker); mp_remoteLibrary = kiwix::Library::create(); kiwix::Manager manager(mp_remoteLibrary); - const auto catalogHost = m_remoteLibraryManager.getCatalogHost(); - const auto catalogPort = m_remoteLibraryManager.getCatalogPort(); - const auto catalogUrl = makeHttpUrl(catalogHost, catalogPort); - manager.readOpds(content.toStdString(), catalogUrl.toStdString()); + manager.readOpds(content.toStdString(), getRemoteLibraryUrl().toStdString()); emit(this->booksChanged()); emit(this->pendingRequest(false)); }); diff --git a/src/contentmanager.h b/src/contentmanager.h index cf1869c..b3afed7 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -88,6 +88,7 @@ public slots: BookInfo getBookInfos(QString id, const QStringList &keys); BookState getBookState(QString id); void openBook(const QString& id); + void openBookPreview(const QString& id); void downloadBook(const QString& id); void downloadBook(const QString& id, QModelIndex index); void updateLibrary(); @@ -121,6 +122,7 @@ private: // functions // Get the book with the specified id from // the remote or local library (in that order). const kiwix::Book& getRemoteOrLocalBook(const QString &id); + QString getRemoteLibraryUrl() const; void startDownloadUpdaterThread(); std::string startDownload(const kiwix::Book& book);