]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blobdiff - src/views/BrowserView.cpp
Add a download location setting.
[PrivacyBrowserPC.git] / src / views / BrowserView.cpp
index ef69db4f784002bcd01978b62981533645b4e681..f17a237d6d33d962db9315eb3a9602504f79bddc 100644 (file)
 #include "ui_BrowserView.h"
 #include "databases/CookiesDatabase.h"
 #include "databases/DomainsDatabase.h"
+#include "dialogs/SaveDialog.h"
 #include "filters/MouseEventFilter.h"
 #include "helpers/SearchEngineHelper.h"
 #include "helpers/UserAgentHelper.h"
 #include "interceptors/UrlRequestInterceptor.h"
 #include "windows/BrowserWindow.h"
 
-// Qt framework headers.
+// KDE Framework headers.
+#include <KIO/FileCopyJob>
+#include <KIO/JobUiDelegate>
+
+// Qt toolkit headers.
 #include <QAction>
+#include <QFileDialog>
+#include <QPrintDialog>
+#include <QPrintPreviewDialog>
+#include <QPrinter>
 
 // Initialize the public static variables.
 QString BrowserView::webEngineDefaultUserAgent = QStringLiteral("");
@@ -59,6 +68,9 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     // Set the WebEngine page.
     webEngineViewPointer->setPage(webEnginePagePointer);
 
+    // Handle full screen requests.
+    connect(webEnginePagePointer, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest)));
+
     // Get handles for the aspects of the WebEngine.
     webEngineHistoryPointer = webEnginePagePointer->history();
     webEngineSettingsPointer = webEngineViewPointer->settings();
@@ -155,6 +167,9 @@ BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
     // Set the URL request interceptor.
     webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
 
+    // Handle file downloads.
+    connect(webEngineProfilePointer, SIGNAL(downloadRequested(QWebEngineDownloadItem *)), this, SLOT(showSaveDialog(QWebEngineDownloadItem *)));
+
     // Reapply the domain settings when the host changes.
     connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(QString)), this, SLOT(applyDomainSettingsWithoutReloading(QString)));
 
@@ -210,7 +225,7 @@ void BrowserView::applyApplicationSettings()
     searchEngineUrl = SearchEngineHelper::getSearchUrl(Settings::searchEngine());
 
     // Emit the update search engine actions signal.
-    emit updateSearchEngineActions(Settings::searchEngine());
+    emit updateSearchEngineActions(Settings::searchEngine(), true);
 }
 
 // This exists as a separate function from `applyDomainSettings()` so it can be listed as a slot and function without the need for a boolean argument.
@@ -374,14 +389,12 @@ void BrowserView::applyDomainSettings(const QString &hostname, const bool reload
     emit updateJavaScriptAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
     emit updateLocalStorageAction(currentPrivacyWebEnginePointer->localStorageEnabled);
     emit updateDomStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
-    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent());
+    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), true);
     emit updateZoomFactorAction(webEngineViewPointer->zoomFactor());
 
     // Reload the website if requested.
     if (reloadWebsite)
-    {
         webEngineViewPointer->reload();
-    }
 }
 
 void BrowserView::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
@@ -394,6 +407,9 @@ void BrowserView::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
 
     // Store the search engine string.
     searchEngineUrl = SearchEngineHelper::getSearchUrl(searchEngineName);
+
+    // Update the search engine actionas.
+    emit updateSearchEngineActions(searchEngineName, false);
 }
 
 void BrowserView::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
@@ -407,6 +423,9 @@ void BrowserView::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
     // Apply the user agent.
     webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromTranslatedName(userAgentName));
 
+    // Update the user agent actions.
+    emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), false);
+
     // Reload the website.
     webEngineViewPointer->reload();
 }
@@ -457,6 +476,15 @@ void BrowserView::forward() const
     webEngineViewPointer->forward();
 }
 
+void BrowserView::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const
+{
+    // Make it so.
+    emit fullScreenRequested(fullScreenRequest.toggleOn());
+
+    // Accept the request.
+    fullScreenRequest.accept();
+}
+
 void BrowserView::home() const
 {
     // Load the homepage.
@@ -561,12 +589,121 @@ void BrowserView::pageLinkHovered(const QString &linkUrl) const
     emit linkHovered(linkUrl);
 }
 
+void BrowserView::print() const
+{
+    // Create a printer.
+    QPrinter printer;
+
+    // Set the resolution to be 300 dpi.
+    printer.setResolution(300);
+
+    // Create a printer dialog.
+    QPrintDialog printDialog(&printer, webEngineViewPointer);
+
+    // Display the dialog and print the page if instructed.
+    if (printDialog.exec() == QDialog::Accepted)
+        printWebpage(&printer);
+}
+
+void BrowserView::printPreview() const
+{
+    // Create a printer.
+    QPrinter printer;
+
+    // Set the resolution to be 300 dpi.
+    printer.setResolution(300);
+
+    // Create a print preview dialog.
+    QPrintPreviewDialog printPreviewDialog(&printer, webEngineViewPointer);
+
+    // Generate the print preview.
+    connect(&printPreviewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(printWebpage(QPrinter *)));
+
+    // Display the dialog.
+    printPreviewDialog.exec();
+}
+
+void BrowserView::printWebpage(QPrinter *printerPointer) const
+{
+    // Create an event loop.  For some reason, the print preview doesn't produce any output unless it is run inside an event loop.
+    QEventLoop eventLoop;
+
+    // Print the webpage, converting the callback above into a `QWebEngineCallback<bool>`.
+    // Printing requires that the printer be a pointer, not a reference, or it will crash with much cursing.
+    webEnginePagePointer->print(printerPointer, [&eventLoop](bool printSuccess)
+    {
+        // Instruct the compiler to ignore the unused parameter.
+        (void) printSuccess;
+
+        // Quit the loop.
+        eventLoop.quit();
+    });
+
+    // Execute the loop.
+    eventLoop.exec();
+}
+
 void BrowserView::refresh() const
 {
     // Reload the website.
     webEngineViewPointer->reload();
 }
 
+void BrowserView::showSaveDialog(QWebEngineDownloadItem *downloadItemPointer) const
+{
+    // Instantiate the save dialog.
+    SaveDialog *saveDialogPointer = new SaveDialog(downloadItemPointer);
+
+    // Connect the save button.
+    connect(saveDialogPointer, SIGNAL(showSaveFilePickerDialog(QUrl &, QString &)), this, SLOT(showSaveFilePickerDialog(QUrl &, QString &)));
+
+    // Show the dialog.
+    saveDialogPointer->show();
+}
+
+void BrowserView::showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName)
+{
+    // Get the download location.
+    QString downloadDirectory = Settings::downloadLocation();
+
+    // Resolve the system download directory if specified.
+    if (downloadDirectory == QStringLiteral("System Download Directory"))
+        downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+
+    // Create a save file dialog.
+    QFileDialog *saveFileDialogPointer = new QFileDialog(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory);
+
+    // Tell the dialog to use a save button.
+    saveFileDialogPointer->setAcceptMode(QFileDialog::AcceptSave);
+
+    // Populate the file name from the download item pointer.
+    saveFileDialogPointer->selectFile(suggestedFileName);
+
+    // Prevent interaction with the parent window while the dialog is open.
+    saveFileDialogPointer->setWindowModality(Qt::WindowModal);
+
+    // Process the saving of the file.  The save file dialog pointer must be captured directly instead of by reference or nasty crashes occur.
+    auto saveFile = [saveFileDialogPointer, &downloadUrl] () {
+        // Get the save location.  The dialog box should only allow the selecting of one file location.
+        QUrl saveLocation = saveFileDialogPointer->selectedUrls().value(0);
+
+        // Create a file copy job.  `-1` creates the file with default permissions.
+        KIO::FileCopyJob *fileCopyJobPointer = KIO::file_copy(downloadUrl, saveLocation, -1, KIO::Overwrite);
+
+        // Set the download job to display any error messages.
+        fileCopyJobPointer->uiDelegate()->setAutoErrorHandlingEnabled(true);
+
+        // Start the download.
+        fileCopyJobPointer->start();
+    };
+
+    // Handle clicks on the save button.
+    connect(saveFileDialogPointer, &QDialog::accepted, this, saveFile);
+
+    // Show the dialog.
+    saveFileDialogPointer->show();
+}
+
 void BrowserView::toggleDomStorage() const
 {
     // Toggle DOM storage.