diff --git a/resources/i18n/en.json b/resources/i18n/en.json index bf89c78..1bbee47 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -181,5 +181,6 @@ "export-reading-list-error": "An error has occured during export of the reading list.", "import-reading-list": "Import reading list", "import-reading-list-error": "An error has occured during import of the reading list.", - "disable-sandbox": "Application was launched from a network drive. This is known to cause compatibility issues due to the sandbox. Do you want to take the risks and disable it?" + "disable-sandbox": "Application was launched from a network drive. This is known to cause compatibility issues due to the sandbox. Do you want to take the risks and disable it?", + "save-page-as": "Save As..." } diff --git a/resources/i18n/qqq.json b/resources/i18n/qqq.json index f79f280..03d4c07 100644 --- a/resources/i18n/qqq.json +++ b/resources/i18n/qqq.json @@ -188,5 +188,6 @@ "export-reading-list": "Represents the action of exporting the reading list to a file.", "export-reading-list-error": "Error description text for when exporting the reading list to a file failed.", "import-reading-list": "Represents the action of importing a reading list from a file.", - "import-reading-list-error": "Error description text for when importing a reading list from a file failed." + "import-reading-list-error": "Error description text for when importing a reading list from a file failed.", + "save-page-as": "Represents the action of saving the current tab content to a file chosen by the user." } diff --git a/src/kiwixapp.cpp b/src/kiwixapp.cpp index b5f31c4..e2e7510 100644 --- a/src/kiwixapp.cpp +++ b/src/kiwixapp.cpp @@ -19,6 +19,8 @@ #include #endif +const QString DEFAULT_SAVE_DIR = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + //////////////////////////////////////////////////////////////////////////////// // KiwixApp //////////////////////////////////////////////////////////////////////////////// @@ -427,11 +429,7 @@ void KiwixApp::createActions() CREATE_ACTION(OpenRecentAction, gt("open-recent")); HIDE_ACTION(OpenRecentAction); - /* TODO See https://github.com/kiwix/kiwix-desktop/issues/77 - CREATE_ACTION(SavePageAsAction, tr("Save page as ...")); - // SET_SHORTCUT(SavePageAsAction, QKeySequence::SaveAs); - HIDE_ACTION(SavePageAsAction); - */ + CREATE_ACTION_SHORTCUT(SavePageAsAction, gt("save-page-as"), QKeySequence::Save); CREATE_ACTION_SHORTCUTS(SearchArticleAction, gt("search-article"), QList({QKeySequence(Qt::Key_F6), QKeySequence(Qt::CTRL | Qt::Key_L), QKeySequence(Qt::ALT | Qt::Key_D)})); @@ -569,3 +567,15 @@ void KiwixApp::saveCurrentTabIndex() { return mp_session->setValue("currentTabIndex", getTabWidget()->currentIndex()); } + +void KiwixApp::savePrevSaveDir(const QString &prevSaveDir) +{ + mp_session->setValue("prevSaveDir", prevSaveDir); +} + +QString KiwixApp::getPrevSaveDir() const +{ + QString prevSaveDir = mp_session->value("prevSaveDir", DEFAULT_SAVE_DIR).toString(); + QDir dir(prevSaveDir); + return dir.exists() ? prevSaveDir : DEFAULT_SAVE_DIR; +} diff --git a/src/kiwixapp.h b/src/kiwixapp.h index 8c74229..aa5738d 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -93,6 +93,8 @@ public: void saveWindowState(); void restoreWindowState(); void saveCurrentTabIndex(); + void savePrevSaveDir(const QString& prevSaveDir); + QString getPrevSaveDir() const; public slots: void newTab(); diff --git a/src/kprofile.cpp b/src/kprofile.cpp index fa09dc5..d1297c2 100644 --- a/src/kprofile.cpp +++ b/src/kprofile.cpp @@ -24,16 +24,32 @@ void KProfile::startDownload(QWebEngineDownloadItem* download) void KProfile::startDownload(QWebEngineDownloadRequest* download) #endif { - QString defaultFileName = download->url().fileName(); - QString fileName = QFileDialog::getSaveFileName(KiwixApp::instance()->getMainWindow(), - gt("save-file-as-window-title"), defaultFileName); + auto app = KiwixApp::instance(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) + QString defaultFileName = QUrl(download->path()).fileName(); +#else + QString defaultFileName = download->downloadFileName(); +#endif + QString suggestedPath = app->getPrevSaveDir() + "/" + defaultFileName; + QString extension = defaultFileName.section('.', -1); + QString filter = extension != '.' ? "(*" + extension + ")" : ""; + + QString fileName = QFileDialog::getSaveFileName( + app->getMainWindow(), gt("save-file-as-window-title"), + suggestedPath, filter); + if (fileName.isEmpty()) { return; } - QString extension = "." + download->url().url().section('.', -1); if (!fileName.endsWith(extension)) { fileName.append(extension); } + app->savePrevSaveDir(QFileInfo(fileName).absolutePath()); + + if (download->isSavePageDownload()) { + download->page()->printToPdf(fileName); + return; + } #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) download->setPath(fileName); #else diff --git a/src/mainmenu.cpp b/src/mainmenu.cpp index 53adeb4..0766671 100644 --- a/src/mainmenu.cpp +++ b/src/mainmenu.cpp @@ -26,10 +26,7 @@ MainMenu::MainMenu(QWidget *parent) : m_fileMenu.ADD_ACTION(OpenRecentAction); m_fileMenu.ADD_ACTION(ExportReadingListAction); m_fileMenu.ADD_ACTION(ImportReadingListAction); - - /* TODO See https://github.com/kiwix/kiwix-desktop/issues/77 m_fileMenu.ADD_ACTION(SavePageAsAction); - */ addMenu(&m_fileMenu); diff --git a/src/urlschemehandler.cpp b/src/urlschemehandler.cpp index 52936d7..a5434e3 100644 --- a/src/urlschemehandler.cpp +++ b/src/urlschemehandler.cpp @@ -18,8 +18,12 @@ UrlSchemeHandler::UrlSchemeHandler() { } -zim::Entry getEntryFromPath(const zim::Archive& archive, const std::string& path) +zim::Entry getArchiveEntryFromUrl(const zim::Archive& archive, const QUrl& url) { + std::string path = url.path().toUtf8().constData(); + if (path[0] == '/') + path = path.substr(1); + try { return archive.getEntryByPath(path); } catch (zim::EntryNotFound& e) { @@ -34,9 +38,6 @@ void UrlSchemeHandler::handleContentRequest(QWebEngineUrlRequestJob *request) { auto qurl = request->requestUrl(); - std::string url = qurl.path().toUtf8().constData(); - if (url[0] == '/') - url = url.substr(1); auto library = KiwixApp::instance()->getLibrary(); auto zim_id = qurl.host(); zim_id.resize(zim_id.length()-4); @@ -48,7 +49,7 @@ UrlSchemeHandler::handleContentRequest(QWebEngineUrlRequestJob *request) return; } try { - auto entry = getEntryFromPath(*archive, url); + auto entry = getArchiveEntryFromUrl(*archive, qurl); auto item = entry.getItem(true); if (entry.isRedirect()) { auto path = QString("/") + QString::fromStdString(item.getPath()); diff --git a/src/webview.cpp b/src/webview.cpp index de17f61..28b979b 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -11,8 +11,12 @@ class QMenu; #include #include #include +#include #include #include +#include + +zim::Entry getArchiveEntryFromUrl(const zim::Archive& archive, const QUrl& url); void WebViewBackMenu::showEvent(QShowEvent *) { @@ -131,6 +135,32 @@ QMenu* WebView::getHistoryForwardMenu() const return ret; } +void WebView::saveViewContent() +{ + try { + auto app = KiwixApp::instance(); + auto library = app->getLibrary(); + auto archive = library->getArchive(m_currentZimId); + auto entry = getArchiveEntryFromUrl(*archive, this->url()); + if (entry.isRedirect()) + return; + + auto item = entry.getItem(true); + auto mimeType = QByteArray::fromStdString(item.getMimetype()); + mimeType = mimeType.split(';')[0]; + + /* We have to sanitize here, as parsing will start once we pass the file + name to either save or download method. + */ + QString suggestedFileName = QString::fromStdString(kiwix::getSlugifiedFileName(item.getTitle())); + if (mimeType == "text/html") + page()->save(suggestedFileName + ".pdf"); + else + page()->download(this->url(), suggestedFileName); + } + catch (...) { /* Blank */} +} + void WebView::addHistoryItemAction(QMenu *menu, const QWebEngineHistoryItem &item, int n) const { QAction *a = menu->addAction(item.title()); @@ -241,6 +271,7 @@ QMenu* WebView::createStandardContextMenu() { KiwixApp::instance()->getTabWidget()->triggerWebPageAction(QWebEnginePage::Forward); }); + menu->addAction(app->getAction(KiwixApp::SavePageAsAction)); return menu; } diff --git a/src/webview.h b/src/webview.h index ca1f560..e241994 100644 --- a/src/webview.h +++ b/src/webview.h @@ -45,6 +45,8 @@ public: QMenu* getHistoryBackMenu() const; QMenu* getHistoryForwardMenu() const; + void saveViewContent(); + public slots: void onUrlChanged(const QUrl& url); diff --git a/src/zimview.cpp b/src/zimview.cpp index 53876d3..3e7af77 100644 --- a/src/zimview.cpp +++ b/src/zimview.cpp @@ -49,6 +49,11 @@ ZimView::ZimView(TabBar *tabBar, QWidget *parent) auto key = mp_webView->zimId() + "/zoomFactor"; settingsManager->deleteSettings(key); }); + connect(app->getAction(KiwixApp::SavePageAsAction), &QAction::triggered, + this, [=](){ + if (mp_tabBar->currentZimView() == this) + mp_webView->saveViewContent(); + }); connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::zoomChanged, this, [=]() { auto key = mp_webView->zimId() + "/zoomFactor"; auto zimZoomFactor = KiwixApp::instance()->getSettingsManager()->getSettings(key);