]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Enable downloading of files that require login cookies. https://redmine.stoutner...
authorSoren Stoutner <soren@stoutner.com>
Sat, 31 Dec 2022 20:09:18 +0000 (13:09 -0700)
committerSoren Stoutner <soren@stoutner.com>
Sat, 31 Dec 2022 20:12:35 +0000 (13:12 -0700)
32 files changed:
CMakeLists.txt
src/CMakeLists.txt
src/com.stoutner.privacybrowser.appdata.xml
src/com.stoutner.privacybrowser.desktop
src/dialogs/DomainSettingsDialog.cpp
src/dialogs/DomainSettingsDialog.h
src/dialogs/DurableCookiesDialog.h
src/dialogs/SaveDialog.cpp
src/dialogs/SaveDialog.h
src/helpers/UserAgentHelper.cpp
src/helpers/UserAgentHelper.h
src/icons/javascript-warning.svg
src/icons/privacy-mode.svg
src/icons/sc-apps-privacy-browser.svg
src/privacybrowser.notifyrc [new file with mode: 0644]
src/resources.qrc
src/settings/Settings.kcfg
src/ui.rcs/CMakeLists.txt
src/ui.rcs/browser_window_ui.rc [deleted file]
src/ui.rcs/browserwindowui.rc [new file with mode: 0644]
src/uis/AddOrEditCookieDialog.ui
src/uis/AddTabWidget.ui
src/uis/CookiesDialog.ui
src/uis/DomainSettingsDialog.ui
src/uis/DurableCookiesDialog.ui
src/uis/SaveDialog.ui
src/uis/SettingsGeneral.ui
src/uis/SettingsPrivacy.ui
src/uis/TabWidget.ui
src/widgets/TabWidget.cpp
src/widgets/TabWidget.h
src/windows/BrowserWindow.cpp

index ff4b909c293507591cd1496f227b2478fe12b05e..528e6ffe166b3a7d25f406c2ac15feff84195b60 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -61,6 +61,7 @@ find_package(KF5 ${KDE_FRAMEWORKS_MIN_VERSION} REQUIRED COMPONENTS
     DBusAddons
     DocTools
     I18n
+    Notifications
     KIO
     XmlGui
 )
index d80c89d7ca56e3fde102f18fe7c8ab14a0ff5d9a..8278a21d38fb71d90ca7699b197eaf1c07a8b32a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -61,6 +61,7 @@ target_link_libraries(privacy-browser
     KF5::DBusAddons
     KF5::DocTools
     KF5::I18n
+    KF5::Notifications
     KF5::KIOCore
     KF5::KIOWidgets
     KF5::XmlGui
@@ -86,5 +87,8 @@ install(PROGRAMS com.stoutner.privacybrowser.desktop DESTINATION ${KDE_INSTALL_A
 # Install Privacy Browser's metadata file.
 install(FILES com.stoutner.privacybrowser.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
 
+# Install Privacy Browser's notifyrc file.
+install(FILES privacybrowser.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFYRCDIR})
+
 # Install Privacy Browser's icon.
 ecm_install_icons(ICONS icons/sc-apps-privacy-browser.svg DESTINATION ${KDE_INSTALL_ICONDIR})
index 49704a95f0367fa19e84fb9d20c48c313d2232c1..3b74d25fe9747667e2af171948bdbf882867426f 100644 (file)
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Permission is granted to copy, distribute and/or modify this document
   under the terms of the GNU Free Documentation License, Version 1.3
index a7ca9d61b0a7433b8d48efdf3297092a4aa45ed8..dc54c91c8912c0cbb012e1034f05b2d3a2f94993 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
index 34ff70e592bf988a8bdc3eb8d69f617361983ad7..ea5558c1fd267491dd8bfd3617bff89642611b86 100644 (file)
@@ -22,7 +22,6 @@
 #include "Settings.h"
 #include "ui_DomainSettingsDialog.h"
 #include "databases/DomainsDatabase.h"
-#include "helpers/UserAgentHelper.h"
 
 // Qt toolkit headers.
 #include <QInputDialog>
@@ -41,7 +40,10 @@ DomainSettingsDialog::DomainSettingsDialog(const int &startType, const QString &
     setWindowTitle(i18nc("The domain settings dialog window title", "Domain Settings"));
 
     // Set the window modality.
-    setWindowModality(Qt::WindowModality::ApplicationModal);;
+    setWindowModality(Qt::WindowModality::ApplicationModal);
+
+    // Instantiate the user agent helper.
+    userAgentHelperPointer = new UserAgentHelper();
 
     // Instantiate the domain settings dialog UI.
     Ui::DomainSettingsDialog domainSettingsDialogUi;
@@ -501,10 +503,10 @@ void DomainSettingsDialog::populateLocalStorageLabel() const
 void DomainSettingsDialog::populateUserAgentLabel(const QString &userAgentName) const
 {
     // Populate the label according to the type.
-    if (userAgentName == UserAgentHelper::SYSTEM_DEFAULT_TRANSLATED)
+    if (userAgentName == userAgentHelperPointer->SYSTEM_DEFAULT_TRANSLATED)
     {
         // Display the system default user agent name.
-        userAgentLabelPointer->setText(UserAgentHelper::getTranslatedUserAgentNameFromDatabaseName(Settings::userAgent()));
+        userAgentLabelPointer->setText(userAgentHelperPointer->getTranslatedUserAgentNameFromDatabaseName(Settings::userAgent()));
 
         // Reset the palette.
         userAgentWidgetPointer->setPalette(defaultPalette);
@@ -628,7 +630,7 @@ void DomainSettingsDialog::userAgentChanged(const QString &updatedUserAgent) con
 {
     // Update the domains table model.
     domainsTableModelPointer->setData(domainsSelectionModelPointer->currentIndex().siblingAtColumn(domainsTableModelPointer->fieldIndex(DomainsDatabase::USER_AGENT)),
-                                      UserAgentHelper::getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
+                                      userAgentHelperPointer->getDatabaseUserAgentNameFromTranslatedName(updatedUserAgent));
 
     // Populate the user agent label.
     populateUserAgentLabel(updatedUserAgent);
index 7680a0323252b109ed27f78369837c11e3182af4..7163458cb125f9c28bc7ced6339fc7790b2f2403 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef DOMAINSETTINGSDIALOG_H
 #define DOMAINSETTINGSDIALOG_H
 
+// Application headers.
+#include "helpers/UserAgentHelper.h"
+
 // KDE Frameworks headers.
 #include <KLineEdit>
 
@@ -87,6 +90,7 @@ private:
     QPushButton *resetButtonPointer;
     QWidget *userAgentWidgetPointer;
     QComboBox *userAgentComboBoxPointer;
+    UserAgentHelper *userAgentHelperPointer;
     QLabel *userAgentLabelPointer;
     QWidget *zoomFactorWidgetPointer;
     QComboBox *zoomFactorComboBoxPointer;
index 61ffe5fb202a0123bd39c3ea95d1d982bb802eb6..e611d58fa44a58e3b5030baa143e58f939817c82 100644 (file)
@@ -60,7 +60,7 @@ private:
     QPushButton *deleteAllCookiesButtonPointer;
     QPushButton *deleteCookieButtonPointer;
     QSqlTableModel *durableCookiesTableModelPointer;
-    QItemSelectionModel *tableSelectionModelPointer;
     QPushButton *resetButtonPointer;
+    QItemSelectionModel *tableSelectionModelPointer;
 };
 #endif
index 281cc77c79a4c4ff97e606e4ce50402159c38242..39d2b1855bbb9d83a3dcd25909c7fa9717d9149d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
@@ -30,7 +30,7 @@
 #include <QShortcut>
 #include <QStandardPaths>
 
-SaveDialog::SaveDialog(QWebEngineDownloadItem *downloadItemPointer)
+SaveDialog::SaveDialog(QUrl &url, QString &mimeTypeString, int totalBytes, QString fileName, bool nativeDownloader): downloadUrl(url), suggestedFileName(fileName)
 {
     // Set the dialog window title.
     setWindowTitle(i18nc("The save dialog window title", "Save"));
@@ -53,11 +53,6 @@ SaveDialog::SaveDialog(QWebEngineDownloadItem *downloadItemPointer)
     QDialogButtonBox *dialogButtonBoxPointer = saveDialogUi.dialogButtonBox;
     QPushButton *saveButtonPointer = dialogButtonBoxPointer->button(QDialogButtonBox::Save);
 
-    // Get the URL and the suggested file name.
-    downloadUrl = downloadItemPointer->url();
-    suggestedFileName = downloadItemPointer->suggestedFileName();
-    QString mimeTypeString = downloadItemPointer->mimeType();
-
     // Get a MIME type database.
     QMimeDatabase mimeDatabase;
 
@@ -85,29 +80,40 @@ SaveDialog::SaveDialog(QWebEngineDownloadItem *downloadItemPointer)
     mimeTypeLabelPointer->setText("<b>" + mimeTypeString + "</b>");
 
     // Populate the download size label.
-    if (downloadItemPointer->totalBytes() == -1)  // The file size is unknown.
+    if (totalBytes == -1)  // The file size is unknown.
         sizeLabelPointer->setText(i18nc("Unknown download file size.  The bold style should be preserved.", "<b>unknown</b>"));
     else  // The file size is known.  Format it according to the locale.
-        sizeLabelPointer->setText(ki18nc("Download file size.  The bold style should be preserved.", "<b>%1 bytes</b>").subs(downloadItemPointer->totalBytes()).toString());
-
-    // Connect the buttons.
-    connect(saveButtonPointer, SIGNAL(clicked()), this, SLOT(showFileDialog()));
-    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
+        sizeLabelPointer->setText(ki18nc("Download file size.  The bold style should be preserved.", "<b>%1 bytes</b>").subs(totalBytes).toString());
 
     // Create the keyboard shortcuts.
     QShortcut *sShortcutPointer = new QShortcut(QKeySequence(i18nc("The save key shortcut.", "s")), this);
     QShortcut *cShortcutPointer = new QShortcut(QKeySequence(i18nc("The close key shortcut.", "c")), this);
 
-    // Connect the shortcuts.
-    connect(sShortcutPointer, SIGNAL(activated()), this, SLOT(showFileDialog()));
+    // Connect the save buttons.
+    if (nativeDownloader)
+    {
+        // Show the file picker for the native download.
+        connect(saveButtonPointer, SIGNAL(clicked()), this, SLOT(showFilePicker()));
+        connect(sShortcutPointer, SIGNAL(activated()), this, SLOT(showFilePicker()));
+    }
+    else
+    {
+        // Use WebEngine's downloader
+        connect(saveButtonPointer, SIGNAL(clicked()), this, SLOT(accept()));
+        connect(sShortcutPointer, SIGNAL(activated()), this, SLOT(accept()));
+    }
+
+    // Connect the cancel button.
+    connect(dialogButtonBoxPointer, SIGNAL(rejected()), this, SLOT(reject()));
     connect(cShortcutPointer, SIGNAL(activated()), this, SLOT(reject()));
 }
 
-void SaveDialog::showFileDialog()
+void SaveDialog::showFilePicker()
 {
     // Show the file picker dialog.
-    emit showSaveFilePickerDialog(downloadUrl, suggestedFileName);
+    emit useNativeDownloader(downloadUrl, suggestedFileName);
 
     // Close the dialog.
     reject();
 }
+
index 36354c190a4c84b4ea135629ddc76744d49d4bb2..1f4ae2e418d94ea968d92a7e262e3ee4305749d8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
@@ -32,15 +32,15 @@ class SaveDialog : public QDialog
 
 public:
     // The primary constructor.
-    explicit SaveDialog(QWebEngineDownloadItem *downloadItemPointer);
+    explicit SaveDialog(QUrl &url, QString &mimeTypeString, int totalBytes, QString fileName = QString(), bool nativeDownloader = false);
 
 signals:
     // The signals.
-    void showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName);
+    void useNativeDownloader(QUrl &downloadUrl, QString &suggestedFileName);
 
 private Q_SLOTS:
     // The private slots.
-    void showFileDialog();
+    void showFilePicker();
 
 private:
     // The private variables.
index 63baca9c56aaf0c315a17b87c5261be7d1a1707a..2aa498b565edb1d6223dedc294d2a64d3d47e609 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
 #include <KLocalizedString>
 
 // Define the public database constants.
-const QString UserAgentHelper::SYSTEM_DEFAULT_DATABASE = QStringLiteral("System Default");
-const QString UserAgentHelper::PRIVACY_BROWSER_DATABASE = QStringLiteral("Privacy Browser");
-const QString UserAgentHelper::WEB_ENGINE_DEFAULT_DATABASE = QStringLiteral("WebEngine Default");
-const QString UserAgentHelper::FIREFOX_LINUX_DATABASE = QStringLiteral("Firefox Linux");
-const QString UserAgentHelper::CHROMIUM_LINUX_DATABASE = QStringLiteral("Chromium Linux");
-const QString UserAgentHelper::FIREFOX_WINDOWS_DATABASE = QStringLiteral("Firefox Windows");
-const QString UserAgentHelper::CHROME_WINDOWS_DATABASE = QStringLiteral("Chrome Windows");
-const QString UserAgentHelper::EDGE_WINDOWS_DATABASE = QStringLiteral("Edge Windows");
-const QString UserAgentHelper::SAFARI_MACOS_DATABASE = QStringLiteral("Safari macOS");
-
-// Define the public translated constants.
-const QString UserAgentHelper::SYSTEM_DEFAULT_TRANSLATED = i18n("System default");
-const QString UserAgentHelper::PRIVACY_BROWSER_TRANSLATED = i18n("Privacy Browser");
-const QString UserAgentHelper::WEB_ENGINE_DEFAULT_TRANSLATED = i18n("WebEngine default");
-const QString UserAgentHelper::FIREFOX_LINUX_TRANSLATED = i18n("Firefox on Linux");
-const QString UserAgentHelper::CHROMIUM_LINUX_TRANSLATED = i18n("Chromium on Linux");
-const QString UserAgentHelper::FIREFOX_WINDOWS_TRANSLATED = i18n("Firefox on Windows");
-const QString UserAgentHelper::CHROME_WINDOWS_TRANSLATED = i18n("Chrome on Windows");
-const QString UserAgentHelper::EDGE_WINDOWS_TRANSLATED = i18n("Edge on Windows");
-const QString UserAgentHelper::SAFARI_MACOS_TRANSLATED = i18n("Safari on macOS");
+const QString UserAgentHelper::SYSTEM_DEFAULT_DATABASE = QLatin1String("System Default");
+const QString UserAgentHelper::PRIVACY_BROWSER_DATABASE = QLatin1String("Privacy Browser");
+const QString UserAgentHelper::WEB_ENGINE_DEFAULT_DATABASE = QLatin1String("WebEngine Default");
+const QString UserAgentHelper::FIREFOX_LINUX_DATABASE = QLatin1String("Firefox Linux");
+const QString UserAgentHelper::CHROMIUM_LINUX_DATABASE = QLatin1String("Chromium Linux");
+const QString UserAgentHelper::FIREFOX_WINDOWS_DATABASE = QLatin1String("Firefox Windows");
+const QString UserAgentHelper::CHROME_WINDOWS_DATABASE = QLatin1String("Chrome Windows");
+const QString UserAgentHelper::EDGE_WINDOWS_DATABASE = QLatin1String("Edge Windows");
+const QString UserAgentHelper::SAFARI_MACOS_DATABASE = QLatin1String("Safari macOS");
 
 // Define the public user agent constants.
-const QString UserAgentHelper::PRIVACY_BROWSER_USER_AGENT = QStringLiteral("PrivacyBrowser/1.0");
-const QString UserAgentHelper::FIREFOX_LINUX_USER_AGENT = QStringLiteral("Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0");
-const QString UserAgentHelper::CHROMIUM_LINUX_USER_AGENT = QStringLiteral("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
-const QString UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT = QStringLiteral("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0");
-const QString UserAgentHelper::CHROME_WINDOWS_USER_AGENT = QStringLiteral("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
-const QString UserAgentHelper::EDGE_WINDOWS_USER_AGENT = QStringLiteral("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54");
-const QString UserAgentHelper::SAFARI_MACOS_USER_AGENT = QStringLiteral("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15");
+const QString UserAgentHelper::PRIVACY_BROWSER_USER_AGENT = QLatin1String("PrivacyBrowser/1.0");
+const QString UserAgentHelper::FIREFOX_LINUX_USER_AGENT = QLatin1String("Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0");
+const QString UserAgentHelper::CHROMIUM_LINUX_USER_AGENT = QLatin1String("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
+const QString UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0");
+const QString UserAgentHelper::CHROME_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36");
+const QString UserAgentHelper::EDGE_WINDOWS_USER_AGENT = QLatin1String("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54");
+const QString UserAgentHelper::SAFARI_MACOS_USER_AGENT = QLatin1String("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15");
 
 // Construct the class.
-UserAgentHelper::UserAgentHelper() {};
+UserAgentHelper::UserAgentHelper() {
+    // Populate the translated user agents.  Translated entries cannot be public static const.
+    SYSTEM_DEFAULT_TRANSLATED = i18nc("User agents", "System default");
+    PRIVACY_BROWSER_TRANSLATED = i18nc("User agents", "Privacy Browser");
+    WEB_ENGINE_DEFAULT_TRANSLATED = i18nc("User agents", "WebEngine default");
+    FIREFOX_LINUX_TRANSLATED = i18nc("User agents", "Firefox on Linux");
+    CHROMIUM_LINUX_TRANSLATED = i18nc("User agents", "Chromium on Linux");
+    FIREFOX_WINDOWS_TRANSLATED = i18nc("User agents", "Firefox on Windows");
+    CHROME_WINDOWS_TRANSLATED = i18nc("User agents", "Chrome on Windows");
+    EDGE_WINDOWS_TRANSLATED = i18nc("User agents", "Edge on Windows");
+    SAFARI_MACOS_TRANSLATED = i18nc("User agents", "Safari on macOS");
+};
 
 QString UserAgentHelper::getDatabaseUserAgentNameFromTranslatedName(const QString &translatedUserAgentName)
 {
index 5c8286afdedccbf87577b6e309140a081e74f297..aee7bc900124112b4c3933251de61bc600e5c8b6 100644 (file)
@@ -29,39 +29,46 @@ public:
     // The default constructor.
     UserAgentHelper();
 
+    // The destructor.
+    ~UserAgentHelper();
+
     // The public static constants.
     static const QString CHROMIUM_LINUX_DATABASE;
-    static const QString CHROMIUM_LINUX_TRANSLATED;
     static const QString CHROMIUM_LINUX_USER_AGENT;
     static const QString CHROME_WINDOWS_DATABASE;
-    static const QString CHROME_WINDOWS_TRANSLATED;
     static const QString CHROME_WINDOWS_USER_AGENT;
     static const QString EDGE_WINDOWS_DATABASE;
-    static const QString EDGE_WINDOWS_TRANSLATED;
     static const QString EDGE_WINDOWS_USER_AGENT;
     static const QString FIREFOX_LINUX_DATABASE;
-    static const QString FIREFOX_LINUX_TRANSLATED;
     static const QString FIREFOX_LINUX_USER_AGENT;
     static const QString FIREFOX_WINDOWS_DATABASE;
-    static const QString FIREFOX_WINDOWS_TRANSLATED;
     static const QString FIREFOX_WINDOWS_USER_AGENT;
     static const QString PRIVACY_BROWSER_DATABASE;
-    static const QString PRIVACY_BROWSER_TRANSLATED;
     static const QString PRIVACY_BROWSER_USER_AGENT;
     static const QString SAFARI_MACOS_DATABASE;
-    static const QString SAFARI_MACOS_TRANSLATED;
     static const QString SAFARI_MACOS_USER_AGENT;
     static const QString SYSTEM_DEFAULT_DATABASE;
-    static const QString SYSTEM_DEFAULT_TRANSLATED;
     static const QString WEB_ENGINE_DEFAULT_DATABASE;
-    static const QString WEB_ENGINE_DEFAULT_TRANSLATED;
 
     // The public static functions.
-    static QString getDatabaseUserAgentNameFromTranslatedName(const QString &translatedUserAgentName);
     static int getDomainSettingsUserAgentIndex(const QString &userAgentName);
     static QString getUserAgentFromDatabaseName(const QString &userAgentDatabaseName);
-    static QString getUserAgentFromTranslatedName(const QString &userAgentTranslatedName);
     static QString getResultingDomainSettingsUserAgent(const QString &rawUserAgent);
-    static QString getTranslatedUserAgentNameFromDatabaseName(const QString &userAgentName);
+
+    // The public variables.
+    QString SYSTEM_DEFAULT_TRANSLATED;
+    QString PRIVACY_BROWSER_TRANSLATED;
+    QString WEB_ENGINE_DEFAULT_TRANSLATED;
+    QString FIREFOX_LINUX_TRANSLATED;
+    QString CHROMIUM_LINUX_TRANSLATED;
+    QString FIREFOX_WINDOWS_TRANSLATED;
+    QString CHROME_WINDOWS_TRANSLATED;
+    QString EDGE_WINDOWS_TRANSLATED;
+    QString SAFARI_MACOS_TRANSLATED;
+
+    // The public functions.
+    QString getDatabaseUserAgentNameFromTranslatedName(const QString &translatedUserAgentName);
+    QString getUserAgentFromTranslatedName(const QString &userAgentTranslatedName);
+    QString getTranslatedUserAgentNameFromDatabaseName(const QString &userAgentName);
 };
 #endif
index 39245a7c4006fcf2368ffdcf013bd9fa478bdbf5..c9e4542595ab018b30268d7be315a2e201c6ec63 100644 (file)
@@ -5,7 +5,7 @@
 
   This file is derived from `security` and `language`, which are part of the Android Material icon set.  They are released under the Apache License 2.0.  <https://fonts.google.com/icons>
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 428d50771f089dd52e31307a999f5edbbb3b2d47..d799bd8fb1b6bba2512fe52598e0c1e005d27468 100644 (file)
@@ -5,7 +5,7 @@
 
   This file is derived from `security` and `language`, which are part of the Android Material icon set.  They are released under the Apache License 2.0.  <https://fonts.google.com/icons>
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 428d50771f089dd52e31307a999f5edbbb3b2d47..d799bd8fb1b6bba2512fe52598e0c1e005d27468 100644 (file)
@@ -5,7 +5,7 @@
 
   This file is derived from `security` and `language`, which are part of the Android Material icon set.  They are released under the Apache License 2.0.  <https://fonts.google.com/icons>
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
diff --git a/src/privacybrowser.notifyrc b/src/privacybrowser.notifyrc
new file mode 100644 (file)
index 0000000..bffb787
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
+#
+# This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+#
+# Privacy Browser PC is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Privacy Browser PC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+
+[Global]
+IconName=sc-apps-privacy-browser
+Name=Privacy Browser
+Comment=A browser that respects your privacy.
+DesktopEntry=com.stoutner.privacybrowser.desktop
+
+[Event/FileDownload]
+Name=File Download
+Comment=The file has started downloading
+Action=Popup
index cfa6f792ba5ffb28989605ecb2ed2f8579d989f4..a6400ddd29ff707d186834b73c18f21130473ff1 100644 (file)
@@ -1,7 +1,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 04a74ca534d9f62a8de0e50560fed339115ea144..9b46d73a1ef8455e8fe2491a484981c7f97a551b 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 2ac4766fd0b6b83a5b5e61dee8c102c71e4989c0..dc4dcc8926c2caf5ad2a62a05d4e7cc61e5a8076 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+# Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 #
 # This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 #
@@ -18,5 +18,5 @@
 
 # Install Privacy Browser's RC (Runtime Configuration) files.
 install(FILES
-    browser_window_ui.rc
+    browserwindowui.rc
     DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/privacybrowser)
diff --git a/src/ui.rcs/browser_window_ui.rc b/src/ui.rcs/browser_window_ui.rc
deleted file mode 100644 (file)
index 6722426..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
-
-  Privacy Browser PC is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser PC is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<!-- Documentation at <https://techbase.kde.org/Development/Architecture/KDE4/XMLGUI_Technology>. -->
-<!-- Better documentation at <https://invent.kde.org/frameworks/kxmlgui/-/blob/master/src/kxmlgui.xsd>. -->
-<!-- This file interacts with the default template located at /etc/xdg/ui/ui_standards.rc, which is part of the libkf5xmlgui-data package. -->
-<gui
-    name="privacybrowser"
-    version="1"
-    xmlns="http://www.kde.org/standards/kxmlgui/1.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
-
-    <!-- The menu bar. -->
-    <MenuBar>
-        <!-- On-the-fly Settings. -->
-        <Menu name="on_the_fly_settings"> <text>On-The-Fly Settings</text>
-            <Menu name="user_agent" icon="user-group-properties">
-                <Action name="user_agent_privacy_browser" />
-                <Action name="user_agent_webengine_default" />
-                <Action name="user_agent_firefox_linux" />
-                <Action name="user_agent_chromium_linux" />
-                <Action name="user_agent_firefox_windows" />
-                <Action name="user_agent_chrome_windows" />
-                <Action name="user_agent_edge_windows" />
-                <Action name="user_agent_safari_macos" />
-                <Action name="user_agent_custom" />
-            </Menu>
-
-            <Action name="zoom_factor" />
-
-            <Separator />
-
-            <Menu name="search_engine" icon="search">
-                <Action name="search_engine_mojeek" />
-                <Action name="search_engine_monocles" />
-                <Action name="search_engine_metager" />
-                <Action name="search_engine_google" />
-                <Action name="search_engine_bing" />
-                <Action name="search_engine_yahoo" />
-                <Action name="search_engine_custom" />
-            </Menu>
-        </Menu>
-
-        <!-- Settings. -->
-        <Menu name="settings">
-            <Action name="domain_settings" />
-            <Action name="cookies" />
-        </Menu>
-    </MenuBar>
-
-    <!-- The main toolbar is removed. -->
-    <ToolBar name="mainToolBar" deleted="true" />
-
-    <!-- The navigation toolbar. -->
-    <ToolBar name="navigation_toolbar" iconText="icononly"> <text>Navigation Toolbar</text>
-        <Action name="go_back" />
-        <Action name="go_forward" />
-        <Action name="view_redisplay" />
-        <Action name="go_home" />
-    </ToolBar>
-
-    <!-- The URL toolbar. -->
-    <ToolBar name="url_toolbar" iconText="icononly"> <text>URL Toolbar</text>
-        <Action name="javascript" />
-        <Action name="local_storage" />
-        <Action name="dom_storage" />
-        <Action name="edit_find_next" />
-        <Action name="edit_find_prev" />
-        <Action name="find_case_sensitive" />
-    </ToolBar>
-</gui>
diff --git a/src/ui.rcs/browserwindowui.rc b/src/ui.rcs/browserwindowui.rc
new file mode 100644 (file)
index 0000000..d0e664d
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+
+  Privacy Browser PC is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser PC is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- Documentation at <https://techbase.kde.org/Development/Architecture/KDE4/XMLGUI_Technology>. -->
+<!-- Better documentation at <https://invent.kde.org/frameworks/kxmlgui/-/blob/master/src/kxmlgui.xsd>. -->
+<!-- This file interacts with the default template located at /etc/xdg/ui/ui_standards.rc, which is part of the libkf5xmlgui-data package. -->
+<gui
+    name="privacybrowser"
+    version="1"
+    xmlns="http://www.kde.org/standards/kxmlgui/1.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
+
+    <!-- The menu bar. -->
+    <MenuBar>
+        <!-- On-the-fly Settings. -->
+        <Menu name="on_the_fly_settings"> <text>On-The-Fly Settings</text>
+            <Menu name="user_agent" icon="user-group-properties">
+                <Action name="user_agent_privacy_browser" />
+                <Action name="user_agent_webengine_default" />
+                <Action name="user_agent_firefox_linux" />
+                <Action name="user_agent_chromium_linux" />
+                <Action name="user_agent_firefox_windows" />
+                <Action name="user_agent_chrome_windows" />
+                <Action name="user_agent_edge_windows" />
+                <Action name="user_agent_safari_macos" />
+                <Action name="user_agent_custom" />
+            </Menu>
+
+            <Action name="zoom_factor" />
+
+            <Separator />
+
+            <Menu name="search_engine" icon="search">
+                <Action name="search_engine_mojeek" />
+                <Action name="search_engine_monocles" />
+                <Action name="search_engine_metager" />
+                <Action name="search_engine_google" />
+                <Action name="search_engine_bing" />
+                <Action name="search_engine_yahoo" />
+                <Action name="search_engine_custom" />
+            </Menu>
+        </Menu>
+
+        <!-- Settings. -->
+        <Menu name="settings">
+            <Action name="domain_settings" />
+            <Action name="cookies" />
+        </Menu>
+    </MenuBar>
+
+    <!-- The main toolbar is removed. -->
+    <ToolBar name="mainToolBar" deleted="true" />
+
+    <!-- The navigation toolbar. -->
+    <ToolBar name="navigation_toolbar" iconText="icononly"> <text>Navigation Toolbar</text>
+        <Action name="go_back" />
+        <Action name="go_forward" />
+        <Action name="view_redisplay" />
+        <Action name="go_home" />
+    </ToolBar>
+
+    <!-- The URL toolbar. -->
+    <ToolBar name="url_toolbar" iconText="icononly"> <text>URL Toolbar</text>
+        <Action name="javascript" />
+        <Action name="local_storage" />
+        <Action name="dom_storage" />
+        <Action name="edit_find_next" />
+        <Action name="edit_find_prev" />
+        <Action name="find_case_sensitive" />
+    </ToolBar>
+</gui>
index 3595e741af800902ad792101fba358d7a51f7ca5..658cb8d596715be8ea7ab1f1fb81c26a9fcbe408 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 1a7177f51788070c0bd823b2d99f05056cea42f4..74d3c5713b11fea3c5ef4011e6205619e08a31d6 100644 (file)
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index bd2c24fce32202929ab759140c3708909162e67e..78492451b6a5d2b8e82602fbc6dda585a00d069e 100644 (file)
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index f0893630a760fb3c70f825efc597c04b6a166859..addcbdee473c97cf8911a96959f13b6b47d11e60 100644 (file)
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index d1ee5222d91608e75855d224f812749dc23ea6ea..65fea7448039c323e3e2228b8ec036e023a03b0d 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index b8e3dfa4b0ae95dcd1fece7f104bf1884ea7a7ef..d9d2ceff1f3fa043e88e4481e533655523858093 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 223ec5b355781170960ff04b55b5221be1e69da4..38fcfd47318b3a8fc88b75da02fde079a9fc5809 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 0affb07f524cd43c1c216cd5acf3235aa6c831da..2103b6e3f4b9fde1a2ab03171a8f482e28364cf8 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index 2aad7efd4d8b1e9bd860285b043e76a60f73d6ba..521526db433df80ee3ee78098b659ae49898d611 100644 (file)
@@ -3,7 +3,7 @@
 <!--
   Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
 
-  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-android>.
+  This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
   Privacy Browser PC is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
index bd62f83beaa521343768bb9355fa3922359cd1f3..4edb304d0db6c45ed5d757a6d4a5f6cd20ad5596 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
 #include "dialogs/SaveDialog.h"
 #include "filters/MouseEventFilter.h"
 #include "helpers/SearchEngineHelper.h"
-#include "helpers/UserAgentHelper.h"
 #include "interceptors/UrlRequestInterceptor.h"
 #include "windows/BrowserWindow.h"
 
 // KDE Framework headers.
 #include <KIO/FileCopyJob>
 #include <KIO/JobUiDelegate>
+#include <KNotification>
 
 // Qt toolkit headers.
 #include <QAction>
 #include <QPrinter>
 
 // Initialize the public static variables.
-QString TabWidget::webEngineDefaultUserAgent = QStringLiteral("");
+QString TabWidget::webEngineDefaultUserAgent = QLatin1String("");
 
 // Construct the class.
 TabWidget::TabWidget(QWidget *parent) : QWidget(parent)
 {
+    // Instantiate the user agent helper.
+    userAgentHelperPointer = new UserAgentHelper();
+
     // Instantiate the UIs.
     Ui::TabWidget tabWidgetUi;
     Ui::AddTabWidget addTabWidgetUi;
@@ -112,14 +115,14 @@ void TabWidget::addCookieToStore(QNetworkCookie cookie, QWebEngineCookieStore *w
     QUrl url;
 
     // Check to see if the domain does not start with a `.` because Qt makes this harder than it should be.  <https://doc.qt.io/qt-5/qwebenginecookiestore.html#setCookie>
-    if (!cookie.domain().startsWith(QStringLiteral(".")))
+    if (!cookie.domain().startsWith(QLatin1String(".")))
     {
         // Populate the URL.
         url.setHost(cookie.domain());
-        url.setScheme(QStringLiteral("https"));
+        url.setScheme(QLatin1String("https"));
 
         // Clear the domain from the cookie.
-        cookie.setDomain(QStringLiteral(""));
+        cookie.setDomain(QLatin1String(""));
     }
 
     // Add the cookie to the store.
@@ -153,7 +156,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     tabWidgetPointer->setTabIcon(newTabIndex, defaultTabIcon);
 
     // Create an off-the-record profile (the default when no profile name is specified).
-    QWebEngineProfile *webEngineProfilePointer = new QWebEngineProfile(QStringLiteral(""));
+    QWebEngineProfile *webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
 
     // Create a WebEngine page.
     QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
@@ -332,7 +335,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     webEngineProfilePointer->setSpellCheckEnabled(true);
 
     // Set the spell check language.
-    webEngineProfilePointer->setSpellCheckLanguages({QStringLiteral("en_US")});
+    webEngineProfilePointer->setSpellCheckLanguages({QLatin1String("en_US")});
 
     // Populate the zoom factor.  This is necessary if a URL is being loaded, like a local URL, that does not trigger `applyDomainSettings()`.
     privacyWebEngineViewPointer->setZoomFactor(Settings::zoomFactor());
@@ -454,7 +457,7 @@ void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWe
         // Set the DOM storage status.
         switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
         {
-            // Set the default DOM storage status.
+            // Set the default DOM storage status.  QWebEngineSettings confusingly calls this local storage.
             case (DomainsDatabase::SYSTEM_DEFAULT):
             {
                 currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
@@ -462,7 +465,7 @@ void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWe
                 break;
             }
 
-            // Disable DOM storage.
+            // Disable DOM storage.  QWebEngineSettings confusingly calls this local storage.
             case (DomainsDatabase::DISABLED):
             {
                 currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
@@ -470,7 +473,7 @@ void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWe
                 break;
             }
 
-            // Enable DOM storage.
+            // Enable DOM storage.  QWebEngineSettings confusingly calls this local storage.
             case (DomainsDatabase::ENABLED):
             {
                 currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
@@ -500,7 +503,7 @@ void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWe
     else  // The hostname does not have domain settings.
     {
         // Reset the domain settings name.
-        currentPrivacyWebEngineViewPointer->domainSettingsName = QStringLiteral("");
+        currentPrivacyWebEngineViewPointer->domainSettingsName = QLatin1String("");
 
         // Set the JavaScript status.
         currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
@@ -522,7 +525,7 @@ void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWe
     }
 
     // Update the UI.
-    emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QStringLiteral(""));
+    emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QLatin1String(""));
     emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
     emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
     emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
@@ -558,7 +561,7 @@ void TabWidget::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
     userAgentName.remove('&');
 
     // Apply the user agent.
-    currentWebEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromTranslatedName(userAgentName));
+    currentWebEngineProfilePointer->setHttpUserAgent(userAgentHelperPointer->getUserAgentFromTranslatedName(userAgentName));
 
     // Update the user agent actions.
     emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), false);
@@ -853,59 +856,159 @@ void TabWidget::setTabBarVisible(const bool visible) const
     tabWidgetPointer->tabBar()->setVisible(visible);
 }
 
-void TabWidget::showSaveDialog(QWebEngineDownloadItem *downloadItemPointer) const
+void TabWidget::showSaveDialog(QWebEngineDownloadItem *webEngineDownloadItemPointer)
 {
-    // Instantiate the save dialog.
-    SaveDialog *saveDialogPointer = new SaveDialog(downloadItemPointer);
+    // Get the download attributes.
+    QUrl downloadUrl = webEngineDownloadItemPointer->url();
+    QString mimeTypeString = webEngineDownloadItemPointer->mimeType();
+    QString suggestedFileName = webEngineDownloadItemPointer->suggestedFileName();
+    int totalBytes = webEngineDownloadItemPointer->totalBytes();
+
+    // Check to see if local storage (cookies) is enabled.
+    if (currentPrivacyWebEngineViewPointer->localStorageEnabled)  // Local storage (cookies) is enabled.  Use WebEngine's downloader.
+    {
+        // Instantiate the save dialog.
+        SaveDialog *saveDialogPointer = new SaveDialog(downloadUrl, mimeTypeString, totalBytes);
 
-    // Connect the save button.
-    connect(saveDialogPointer, SIGNAL(showSaveFilePickerDialog(QUrl &, QString &)), this, SLOT(showSaveFilePickerDialog(QUrl &, QString &)));
+        // Display the save dialog.
+        int saveDialogResult = saveDialogPointer->exec();
 
-    // Show the dialog.
-    saveDialogPointer->show();
-}
+        // Process the save dialog results.
+        if (saveDialogResult == QDialog::Accepted)  // Save was selected.
+        {
+            // Get the download directory.
+            QString downloadDirectory = Settings::downloadLocation();
 
-void TabWidget::showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName)
-{
-    // Get the download location.
-    QString downloadDirectory = Settings::downloadLocation();
+            // Resolve the system download directory if specified.
+            if (downloadDirectory == QLatin1String("System Download Directory"))
+                downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
 
-    // Resolve the system download directory if specified.
-    if (downloadDirectory == QStringLiteral("System Download Directory"))
-        downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+            // Display a save file dialog.
+            QString saveFilePath = QFileDialog::getSaveFileName(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory + QLatin1Char('/') + suggestedFileName);
 
-    // Create a save file dialog.
-    QFileDialog *saveFileDialogPointer = new QFileDialog(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory);
+            // Process the save file path.
+            if (!saveFilePath.isEmpty())  // The file save path is populated.
+            {
+                // Create a save file path file info.
+                QFileInfo saveFilePathFileInfo = QFileInfo(saveFilePath);
 
-    // Tell the dialog to use a save button.
-    saveFileDialogPointer->setAcceptMode(QFileDialog::AcceptSave);
+                // Get the canonical save path and file name.
+                QString absoluteSavePath = saveFilePathFileInfo.absolutePath();
+                QString saveFileName = saveFilePathFileInfo.fileName();
 
-    // Populate the file name from the download item pointer.
-    saveFileDialogPointer->selectFile(suggestedFileName);
+                // Set the download directory and file name.
+                webEngineDownloadItemPointer->setDownloadDirectory(absoluteSavePath);
+                webEngineDownloadItemPointer->setDownloadFileName(saveFileName);
 
-    // Prevent interaction with the parent window while the dialog is open.
-    saveFileDialogPointer->setWindowModality(Qt::WindowModal);
+                // Create a file download notification.
+                KNotification *fileDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
 
-    // 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);
+                // Set the notification title.
+                fileDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
 
-        // 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 notification text.
+                fileDownloadNotificationPointer->setText(i18nc("Downloading notification text", "Downloading %1", saveFileName));
 
-        // Set the download job to display any error messages.
-        fileCopyJobPointer->uiDelegate()->setAutoErrorHandlingEnabled(true);
+                // Set the notification icon.
+                fileDownloadNotificationPointer->setIconName(QLatin1String("download"));
 
-        // Start the download.
-        fileCopyJobPointer->start();
-    };
+                // Set the action list cancel button.
+                fileDownloadNotificationPointer->setActions(QStringList({i18nc("Download notification action","Cancel")}));
 
-    // Handle clicks on the save button.
-    connect(saveFileDialogPointer, &QDialog::accepted, this, saveFile);
+                // Set the notification to display indefinitely.
+                fileDownloadNotificationPointer->setFlags(KNotification::Persistent);
 
-    // Show the dialog.
-    saveFileDialogPointer->show();
+                // Prevent the notification from being autodeleted if it is closed.  Otherwise, the updates to the notification below cause a crash.
+                fileDownloadNotificationPointer->setAutoDelete(false);
+
+                // Display the notification.
+                fileDownloadNotificationPointer->sendEvent();
+
+                // Handle clicks on the cancel button.
+                connect(fileDownloadNotificationPointer, &KNotification::action1Activated, [webEngineDownloadItemPointer, saveFileName] ()
+                {
+                    // Cancel the download.
+                    webEngineDownloadItemPointer->cancel();
+
+                    // Create a file download notification.
+                    KNotification *canceledDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
+
+                    // Set the notification title.
+                    canceledDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
+
+                    // Set the new text.
+                    canceledDownloadNotificationPointer->setText(i18nc("Download canceled notification", "%1 download canceled", saveFileName));
+
+                    // Set the notification icon.
+                    canceledDownloadNotificationPointer->setIconName(QLatin1String("download"));
+
+                    // Display the notification.
+                    canceledDownloadNotificationPointer->sendEvent();
+                });
+
+                // Update the notification when the download progresses.
+                connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::downloadProgress, [fileDownloadNotificationPointer, saveFileName] (qint64 bytesReceived, qint64 totalBytes)
+                {
+                    // Calculate the download percentage.
+                    int downloadPercentage = 100 * bytesReceived / totalBytes;
+
+                    // Set the new text.  Total bytes will be 0 if the download size is unknown.
+                    if (totalBytes > 0)
+                        fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1\% of %2 downloaded (%3 of %4 bytes)", downloadPercentage, saveFileName,
+                                                                    bytesReceived, totalBytes));
+                    else
+                        fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1:  %2 bytes downloaded", saveFileName, bytesReceived));
+
+                    // Display the updated notification.
+                    fileDownloadNotificationPointer->update();
+                });
+
+                // Update the notification when the download finishes.  The save file name must be copied into the lambda or a crash occurs.
+                connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::finished, [fileDownloadNotificationPointer, saveFileName, saveFilePath] ()
+                {
+                    // Set the new text.
+                    fileDownloadNotificationPointer->setText(i18nc("Download finished notification text", "%1 download finished", saveFileName));
+
+                    // Set the URL so the file options will be displayed.
+                    fileDownloadNotificationPointer->setUrls(QList<QUrl> {QUrl(saveFilePath)});
+
+                    // Remove the actions from the notification.
+                    fileDownloadNotificationPointer->setActions(QStringList());
+
+                    // Set the notification to disappear after a timeout.
+                    fileDownloadNotificationPointer->setFlags(KNotification::CloseOnTimeout);
+
+                    // Display the updated notification.
+                    fileDownloadNotificationPointer->update();
+                });
+
+                // Start the download.
+                webEngineDownloadItemPointer->accept();
+            }
+            else  // The file save path is not populated.
+            {
+                // Cancel the download.
+                webEngineDownloadItemPointer->cancel();
+            }
+        }
+        else  // Cancel was selected.
+        {
+            // Cancel the download.
+            webEngineDownloadItemPointer->cancel();
+        }
+    }
+    else  // Local storage (cookies) is disabled.  Use KDE's native downloader.
+          // This must use the show command to launch a separate dialog which cancels WebEngine's automatic background download of the file to a temporary location.
+    {
+        // Instantiate the save dialog.  `true` instructs it to use the native downloader
+        SaveDialog *saveDialogPointer = new SaveDialog(downloadUrl, mimeTypeString, totalBytes, suggestedFileName, true);
+
+        // Connect the save button.
+        connect(saveDialogPointer, SIGNAL(useNativeDownloader(QUrl &, QString &)), this, SLOT(useNativeDownloader(QUrl &, QString &)));
+
+        // Show the dialog.
+        saveDialogPointer->show();
+    }
 }
 
 void TabWidget::toggleDomStorage() const
@@ -929,7 +1032,7 @@ void TabWidget::toggleFindCaseSensitive(const QString &text)
     wipingCurrentFindTextSelection = true;
 
     // Wipe the previous search.  Otherwise currently highlighted words will remain highlighted.
-    findText(QStringLiteral(""));
+    findText(QLatin1String(""));
 
     // Update the find text.
     findText(text);
@@ -984,7 +1087,7 @@ void TabWidget::updateUiWithTabSettings()
 
     // Update the URL.
     emit updateWindowTitle(currentPrivacyWebEngineViewPointer->title());
-    emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QStringLiteral(""));
+    emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QLatin1String(""));
     emit updateUrlLineEdit(currentPrivacyWebEngineViewPointer->url());
 
     // Update the find text.
@@ -997,3 +1100,47 @@ void TabWidget::updateUiWithTabSettings()
     else
         emit hideProgressBar();
 }
+
+void TabWidget::useNativeDownloader(QUrl &downloadUrl, QString &suggestedFileName)
+{
+    // Get the download directory.
+    QString downloadDirectory = Settings::downloadLocation();
+
+    // Resolve the system download directory if specified.
+    if (downloadDirectory == QLatin1String("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();
+}
index 246daa41cf4860c9c080426309a815e7de3c69f6..6130fc3ee75fc27b987c26c1e726a4933e159b7d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
@@ -22,6 +22,7 @@
 
 // Application headers.
 #include "PrivacyWebEngineView.h"
+#include "helpers/UserAgentHelper.h"
 
 // KDE Framework headers.
 #include <KLineEdit>
@@ -118,9 +119,9 @@ private Q_SLOTS:
     void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const;
     void pageLinkHovered(const QString &linkUrl) const;
     void printWebpage(QPrinter *printerPointer) const;
-    void showSaveDialog(QWebEngineDownloadItem *downloadItemPointer) const;
-    void showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName);
+    void showSaveDialog(QWebEngineDownloadItem *downloadItemPointer);
     void updateUiWithTabSettings();
+    void useNativeDownloader(QUrl &downloadUrl, QString &suggestedFileName);
 
 private:
     // The private variables.
@@ -134,6 +135,7 @@ private:
     QIcon defaultTabIcon = QIcon::fromTheme(QStringLiteral("globe"));
     QString searchEngineUrl;
     QTabWidget *tabWidgetPointer;
+    UserAgentHelper *userAgentHelperPointer;
     bool wipingCurrentFindTextSelection = false;
 
     // The private functions.
index 6df64f3ee95c558882c20d54f33dd1848712ae3b..5960393f1da4b4fb535b4383463ce4ff46f08a3c 100644 (file)
@@ -141,15 +141,18 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     searchEngineYahooActionPointer->setCheckable(true);
     searchEngineCustomActionPointer->setCheckable(true);
 
+    // Instantiate the user agent helper.
+    UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
+
     // Set the action text.
-    userAgentPrivacyBrowserActionPointer->setText(UserAgentHelper::PRIVACY_BROWSER_TRANSLATED);
-    userAgentWebEngineDefaultActionPointer->setText(UserAgentHelper::WEB_ENGINE_DEFAULT_TRANSLATED);
-    userAgentFirefoxLinuxActionPointer->setText(UserAgentHelper::FIREFOX_LINUX_TRANSLATED);
-    userAgentChromiumLinuxActionPointer->setText(UserAgentHelper::CHROMIUM_LINUX_TRANSLATED);
-    userAgentFirefoxWindowsActionPointer->setText(UserAgentHelper::FIREFOX_WINDOWS_TRANSLATED);
-    userAgentChromeWindowsActionPointer->setText(UserAgentHelper::CHROME_WINDOWS_TRANSLATED);
-    userAgentEdgeWindowsActionPointer->setText(UserAgentHelper::EDGE_WINDOWS_TRANSLATED);
-    userAgentSafariMacosActionPointer->setText(UserAgentHelper::SAFARI_MACOS_TRANSLATED);
+    userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
+    userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
+    userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
+    userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
+    userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
+    userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
+    userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
+    userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
     searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
     searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
     searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
@@ -219,7 +222,7 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
 
     // Setup the GUI based on the browser_window_ui.rc file.
-    setupGUI(StandardWindowOption::Default, ("browser_window_ui.rc"));
+    setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
 
     // Get lists of the actions' associated widgets.
     QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();