DBusAddons
DocTools
I18n
+ KIO
XmlGui
)
uis/CookiesDialog.ui
uis/DomainSettingsDialog.ui
uis/DurableCookiesDialog.ui
+ uis/SaveDialog.ui
uis/SettingsGeneral.ui
uis/SettingsPrivacy.ui
)
KF5::DBusAddons
KF5::DocTools
KF5::I18n
+ KF5::KIOCore
+ KF5::KIOWidgets
KF5::XmlGui
)
CookiesDialog.cpp
DomainSettingsDialog.cpp
DurableCookiesDialog.cpp
+ SaveDialog.cpp
)
--- /dev/null
+/*
+ * 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/>.
+ */
+
+// Application headers.
+#include "SaveDialog.h"
+#include "ui_SaveDialog.h"
+
+// KDE Frameworks headers.
+#include <KLocalizedString>
+
+// Qt toolkit headers.
+#include <QMimeDatabase>
+#include <QPushButton>
+#include <QShortcut>
+#include <QStandardPaths>
+
+SaveDialog::SaveDialog(QWebEngineDownloadItem *downloadItemPointer)
+{
+ // Set the dialog window title.
+ setWindowTitle(i18nc("The save dialog window title", "Save"));
+
+ // Set the window modality.
+ setWindowModality(Qt::WindowModality::ApplicationModal);
+
+ // Instantiate the save dialog UI.
+ Ui::SaveDialog saveDialogUi;
+
+ // Setup the UI.
+ saveDialogUi.setupUi(this);
+
+ // Get handles for the widgets.
+ QLabel *urlLabelPointer = saveDialogUi.urlLabel;
+ QLabel *filetypeLabelPointer = saveDialogUi.fileTypeLabel;
+ QLabel *mimeTypeLabelPointer = saveDialogUi.mimeTypeLabel;
+ QLabel *sizeLabelPointer = saveDialogUi.sizeLabel;
+ 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 mimeType = downloadItemPointer->mimeType();
+
+ // Get a MIME type database.
+ QMimeDatabase mimeDatabase;
+
+ // Populate the labels.
+ urlLabelPointer->setText("<b>" + downloadUrl.toString() + "</b>");
+ filetypeLabelPointer->setText("<b>" + mimeDatabase.mimeTypeForName(mimeType).comment() + "</b>");
+ mimeTypeLabelPointer->setText("<b>" + mimeType + "</b>");
+
+ // Populate the download size label.
+ if (downloadItemPointer->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()));
+
+ // 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(cShortcutPointer, SIGNAL(activated()), this, SLOT(reject()));
+}
+
+void SaveDialog::showFileDialog()
+{
+ // Show the file picker dialog.
+ emit showSaveFilePickerDialog(downloadUrl, suggestedFileName);
+
+ // Close the dialog.
+ reject();
+}
--- /dev/null
+/*
+ * 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/>.
+ */
+
+#ifndef SAVEDIALOG_H
+#define SAVEDIALOG_H
+
+// Qt toolkit headers.
+#include <QDialog>
+#include <QUrl>
+#include <QWebEngineDownloadItem>
+
+class SaveDialog : public QDialog
+{
+ // Include the Q_OBJECT macro.
+ Q_OBJECT
+
+public:
+ // The primary constructor.
+ explicit SaveDialog(QWebEngineDownloadItem *downloadItemPointer);
+
+signals:
+ // The signals.
+ void showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName);
+
+private Q_SLOTS:
+ // The private slots.
+ void showFileDialog();
+
+private:
+ // The private variables.
+ QUrl downloadUrl;
+ QString suggestedFileName;
+};
+#endif
<layout class="QFormLayout">
<!-- Domain name. -->
<item row="0" column="0">
- <widget class="QLabel" name="domainNameLabel">
+ <widget class="QLabel">
<property name="text">
<string>Domain name</string>
</property>
--- /dev/null
+<?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/>. -->
+
+<ui version="4.0">
+ <class>SaveDialog</class>
+
+ <widget class="QWidget">
+ <layout class="QVBoxLayout">
+ <!-- Header question. -->
+ <item>
+ <widget class="QLabel">
+ <property name="text">
+ <string><b>Would you like to download the following file?</b></string>
+ </property>
+
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+
+ <property name="margin">
+ <number>10</number>
+ </property>
+ </widget>
+ </item>
+
+ <!-- File details. -->
+ <item>
+ <widget class="QGroupBox">
+ <property name="title">
+ <string>File details</string>
+ </property>
+
+ <!-- Labels. -->
+ <layout class="QFormLayout">
+ <!-- URL. -->
+ <item row="0" column="0">
+ <widget class="QLabel">
+ <property name="text">
+ <string>URL:</string>
+ </property>
+ </widget>
+ </item>
+
+ <item row="0" column="1">
+ <widget class="QLabel" name="urlLabel">
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+
+ <!-- File type. -->
+ <item row="1" column="0">
+ <widget class="QLabel">
+ <property name="text">
+ <string>File type:</string>
+ </property>
+ </widget>
+ </item>
+
+ <item row="1" column="1">
+ <widget class="QLabel" name="fileTypeLabel">
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+
+ <!-- MIME type. -->
+ <item row="2" column="0">
+ <widget class="QLabel">
+ <property name="text">
+ <string>MIME type:</string>
+ </property>
+ </widget>
+ </item>
+
+ <item row="2" column="1">
+ <widget class="QLabel" name="mimeTypeLabel">
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+
+ <!-- Size. -->
+ <item row="3" column="0">
+ <widget class="QLabel">
+ <property name="text">
+ <string>Size:</string>
+ </property>
+ </widget>
+ </item>
+
+ <item row="3" column="1">
+ <widget class="QLabel" name="sizeLabel">
+ <property name="textFormat">
+ <enum>Qt::RichText</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+
+ <!-- Dialog buttons. -->
+ <item>
+ <widget class="QDialogButtonBox" name="dialogButtonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Save | QDialogButtonBox::Cancel</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+</ui>
#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>
// 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)));
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)
+{
+ // Create a save file dialog.
+ QFileDialog *saveFileDialogPointer = new QFileDialog(this, i18nc("Save file dialog caption", "Save File"), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+
+ // 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 windows 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.
void loadStarted() const;
void pageLinkHovered(const QString &linkUrl) const;
void printWebpage(QPrinter *printerPointer) const;
+ void showSaveDialog(QWebEngineDownloadItem *downloadItemPointer) const;
+ void showSaveFilePickerDialog(QUrl &downloadUrl, QString &suggestedFileName);
void updateUrl(const QUrl &url) const;
private:
// Display dialogs.
connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
- connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(openCookiesDialog()));
- connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(openDomainSettings()));
+ connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
+ connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
// Connect the URL toolbar actions.
connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
browserViewPointer->loadUrlFromLineEdit(url);
}
-void BrowserWindow::openCookiesDialog()
+void BrowserWindow::refresh() const
+{
+ // Remove the focus from the URL line edit.
+ urlLineEditPointer->clearFocus();
+
+ // Refresh the web page.
+ browserViewPointer->refresh();
+}
+
+void BrowserWindow::removeCookieFromList(const QNetworkCookie &cookie) const
+{
+ //qDebug() << "Remove cookie: " << cookie.toRawForm();
+
+ // Remove the cookie from the list.
+ cookieListPointer->remove(cookie);
+
+ // Update the action text.
+ cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
+}
+
+void BrowserWindow::showCookiesDialog()
{
// Remove the focus from the URL line edit.
urlLineEditPointer->clearFocus();
connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), browserViewPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
}
-void BrowserWindow::openDomainSettings() const
+void BrowserWindow::showDomainSettingsDialog() const
{
// Remove the focus from the URL line edit.
urlLineEditPointer->clearFocus();
connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
}
-void BrowserWindow::refresh() const
-{
- // Remove the focus from the URL line edit.
- urlLineEditPointer->clearFocus();
-
- // Refresh the web page.
- browserViewPointer->refresh();
-}
-
-void BrowserWindow::removeCookieFromList(const QNetworkCookie &cookie) const
-{
- //qDebug() << "Remove cookie: " << cookie.toRawForm();
-
- // Remove the cookie from the list.
- cookieListPointer->remove(cookie);
-
- // Update the action text.
- cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
-}
-
void BrowserWindow::showProgressBar(const int &progress) const
{
// Set the progress bar value.
void getZoomFactorFromUser();
void home() const;
void loadUrlFromLineEdit(const QString &url) const;
- void openCookiesDialog();
- void openDomainSettings() const;
void refresh() const;
void removeCookieFromList(const QNetworkCookie &cookie) const;
void settingsConfigure();
+ void showCookiesDialog();
+ void showDomainSettingsDialog() const;
void showProgressBar(const int &progress) const;
void toggleDomStorage() const;
void toggleJavaScript() const;