# Use KDE Frameworks to handle internationalization of the following UI files.
ki18n_wrap_ui(privacy-browser
uis/AddOrEditCookieDialog.ui
- uis/BrowserView.ui
+ uis/AddTabWidget.ui
uis/CookiesDialog.ui
uis/DomainSettingsDialog.ui
uis/DurableCookiesDialog.ui
uis/SaveDialog.ui
uis/SettingsGeneral.ui
uis/SettingsPrivacy.ui
+ uis/TabWidget.ui
)
# Link the following libraries.
add_subdirectory(filters)
add_subdirectory(helpers)
add_subdirectory(interceptors)
-add_subdirectory(structs)
add_subdirectory(ui.rcs)
-add_subdirectory(views)
+add_subdirectory(widgets)
add_subdirectory(windows)
# Install Privacy Browser using the default KDE arguments.
// Execute the query.
countCookiesQuery.exec();
+ // Move to the last row.
+ countCookiesQuery.last();
+
// Initialize a number of cookies variable.
int numberOfCookies = 0;
// Check to see if the query is valid (there is at least one cookie).
if (countCookiesQuery.isValid())
{
- // Move to the last row.
- countCookiesQuery.last();
-
// Get the number of rows (which is zero based) and add one to calculate the number of cookies.
numberOfCookies = countCookiesQuery.at() + 1;
}
// Application headers.
#include "Settings.h"
#include "UserAgentHelper.h"
-#include "views/BrowserView.h"
+#include "widgets/TabWidget.h"
// KDE Framework headers.
#include <KLocalizedString>
QString UserAgentHelper::getUserAgentFromDatabaseName(const QString &userAgentDatabaseName)
{
if (userAgentDatabaseName == PRIVACY_BROWSER_DATABASE) return PRIVACY_BROWSER_USER_AGENT; // Privacy Browser.
- else if (userAgentDatabaseName == WEB_ENGINE_DEFAULT_DATABASE) return BrowserView::webEngineDefaultUserAgent; // WebEngine default.
+ else if (userAgentDatabaseName == WEB_ENGINE_DEFAULT_DATABASE) return TabWidget::webEngineDefaultUserAgent; // WebEngine default.
else if (userAgentDatabaseName == FIREFOX_LINUX_DATABASE) return FIREFOX_LINUX_USER_AGENT; // Firefox Linux.
else if (userAgentDatabaseName == CHROMIUM_LINUX_DATABASE) return CHROMIUM_LINUX_USER_AGENT; // Chromium Linux.
else if (userAgentDatabaseName == FIREFOX_WINDOWS_DATABASE) return FIREFOX_WINDOWS_USER_AGENT; // Firefox Windows.
QString UserAgentHelper::getUserAgentFromTranslatedName(const QString &userAgentTranslatedName)
{
if (userAgentTranslatedName == PRIVACY_BROWSER_TRANSLATED) return PRIVACY_BROWSER_USER_AGENT; // Privacy Browser.
- else if (userAgentTranslatedName == WEB_ENGINE_DEFAULT_TRANSLATED) return BrowserView::webEngineDefaultUserAgent; // WebEngine default.
+ else if (userAgentTranslatedName == WEB_ENGINE_DEFAULT_TRANSLATED) return TabWidget::webEngineDefaultUserAgent; // WebEngine default.
else if (userAgentTranslatedName == FIREFOX_LINUX_TRANSLATED) return FIREFOX_LINUX_USER_AGENT; // Firefox on Linux.
else if (userAgentTranslatedName == CHROMIUM_LINUX_TRANSLATED) return CHROMIUM_LINUX_USER_AGENT; // Chromium on Linux.
else if (userAgentTranslatedName == FIREFOX_WINDOWS_TRANSLATED) return FIREFOX_WINDOWS_USER_AGENT; // Firefox on Windows.
<default>System Download Directory</default>
</entry>
+ <entry name="tabsOnTop" type="Bool">
+ <default>true</default>
+ </entry>
+
<entry name="fullScreenHideMenuBar" type="Bool">
<default>true</default>
</entry>
<default>true</default>
</entry>
+ <entry name="fullScreenHideTabBar" type="Bool">
+ <default>true</default>
+ </entry>
+
<entry name="fullScreenHideStatusBar" type="Bool">
<default>true</default>
</entry>
+++ /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/>.
-
-
-# List the sources to include in the executable.
-target_sources(privacy-browser PRIVATE
- PrivacyWebEngine.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 "PrivacyWebEngine.h"
-
-// Construct the struct.
-PrivacyWebEngine::PrivacyWebEngine(QWebEngineView *inputWebEngineViewPointer) : webEngineViewPointer(inputWebEngineViewPointer)
-{
- // Initialize the local storage status.
- localStorageEnabled = false;
-}
+++ /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 PRIVACYWEBENGINE_H
-#define PRIVACYWEBENGINE_H
-
-// Qt toolkit headers.
-#include <QWebEngineView>
-
-struct PrivacyWebEngine
-{
-public:
- // The primary constructor.
- PrivacyWebEngine(QWebEngineView *inputWebEngineViewPointer);
-
- // The public variables.
- bool localStorageEnabled;
- QWebEngineView *webEngineViewPointer;
-};
-#endif
--- /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>AddTabWidget</class>
+
+ <!-- Base widget. -->
+ <widget class="QWidget">
+ <layout class="QHBoxLayout">
+
+
+ <!-- Add tab widget. -->
+ <item>
+ <widget class="QWidget" name="addTabQWidget">
+ <layout class="QHBoxLayout">
+ <!-- Set the margins to 0. -->
+ <property name="topMargin">
+ <number>5</number>
+ </property>
+
+ <property name="bottomMargin">
+ <number>5</number>
+ </property>
+
+ <property name="leftMargin">
+ <number>5</number>
+ </property>
+
+ <property name="rightMargin">
+ <number>5</number>
+ </property>
+
+ <!-- Add tab button. -->
+ <item>
+ <widget class="QPushButton" name="addTabButton">
+ <property name="icon">
+ <iconset theme="list-add-symbolic" />
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+</ui>
+++ /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>BrowserView</class>
- <!-- Main widget. -->
- <widget class="QWidget">
- <!-- Main layout. -->
- <layout class="QVBoxLayout">
- <!-- Set the spacing between items to 0. -->
- <property name="spacing">
- <number>0</number>
- </property>
-
- <!-- Set the margins to 0. -->
- <property name="topMargin">
- <number>0</number>
- </property>
-
- <property name="bottomMargin">
- <number>0</number>
- </property>
-
- <property name="leftMargin">
- <number>0</number>
- </property>
-
- <property name="rightMargin">
- <number>0</number>
- </property>
-
- <!-- WebEngine view. -->
- <item>
- <widget class="QWebEngineView" name="webEngineView" />
- </item>
- </layout>
- </widget>
-</ui>
<item>
<widget class="QPushButton" name="addCookieButton">
<property name="text">
- <string>&Add cookie</string>
+ <string>Add cookie</string>
</property>
<property name="icon">
<item>
<widget class="QPushButton" name="editCookieButton">
<property name="text">
- <string>&Edit cookie</string>
+ <string>Edit cookie</string>
</property>
<property name="icon">
<item>
<widget class="QPushButton" name="deleteCookieButton">
<property name="text">
- <string>&Delete cookie</string>
+ <string>Delete cookie</string>
</property>
<property name="icon">
<item>
<widget class="QPushButton" name="deleteAllCookiesButton">
<property name="text">
- <string>Delete &all</string>
+ <string>Delete all</string>
</property>
<property name="icon">
</layout>
</item>
+ <!-- Tabs on top. -->
+ <item>
+ <widget class="QCheckBox" name="kcfg_tabsOnTop">
+ <property name="text">
+ <string>Tabs on top</string>
+ </property>
+
+ <property name="toolTip">
+ <string>Display the tabs at the top of the screen. The default is enabled.</string>
+ </property>
+ </widget>
+ </item>
+
<!-- Full screen browsing. -->
<item>
<widget class="QGroupBox">
</widget>
</item>
+ <!-- Hide tab bar. -->
+ <item>
+ <widget class="QCheckBox" name="kcfg_fullScreenHideTabBar">
+ <property name="text">
+ <string>Hide tab bar</string>
+ </property>
+
+ <property name="toolTip">
+ <string>Hide the tab bar when browsing full screen. The default is enabled.</string>
+ </property>
+ </widget>
+ </item>
+
<!-- Hide status bar. -->
<item>
<widget class="QCheckBox" name="kcfg_fullScreenHideStatusBar">
--- /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>TabWidget</class>
+
+ <!-- Tab QWidget. -->
+ <widget class="QWidget">
+
+ <!-- Main layout. -->
+ <layout class="QVBoxLayout">
+ <!-- Set the margins to 0. -->
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+
+ <!-- Tab widget. -->
+ <item>
+ <widget class="QTabWidget" name="tabWidget" >
+ <property name="iconSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+
+ <property name="documentMode">
+ <bool>true</bool>
+ </property>
+
+ <property name="tabsClosable">
+ <bool>true</bool>
+ </property>
+
+ <property name="movable">
+ <bool>true</bool>
+ </property>
+
+ <property name="elideMode">
+ <enum>Qt::ElideRight</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+</ui>
+++ /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 "BrowserView.h"
-#include "Settings.h"
-#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"
-
-// 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("");
-
-// Construct the class.
-BrowserView::BrowserView(QWidget *parent) : QWidget(parent)
-{
- // Initialize the variables.
- privacyWebEngineListPointer = new QList<PrivacyWebEngine*>;
-
- // Instantiate the browser view UI.
- Ui::BrowserView browserViewUi;
-
- // Setup the UI.
- browserViewUi.setupUi(this);
-
- // Get handles for the views.
- webEngineViewPointer = browserViewUi.webEngineView;
-
- // Create an off-the-record profile (the default when no profile name is specified).
- webEngineProfilePointer = new QWebEngineProfile(QStringLiteral(""));
-
- // Create a WebEngine page.
- webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
-
- // 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();
- webEngineCookieStorePointer = webEngineProfilePointer->cookieStore();
-
- // Initialize the current privacy web engine pointer.
- currentPrivacyWebEnginePointer = new PrivacyWebEngine(webEngineViewPointer);
-
- // Populate the privacy web engine list.
- privacyWebEngineListPointer->append(currentPrivacyWebEnginePointer);
-
- // Set the local storage filter.
- webEngineCookieStorePointer->setCookieFilter([this](const QWebEngineCookieStore::FilterRequest &filterRequest)
- {
- //qDebug().noquote().nospace() << "Page URL: " << filterRequest.firstPartyUrl << ", Local storage URL: " << filterRequest.origin << ", Is third-party: " << filterRequest.thirdParty;
-
- // Block all third party local storage requests, including the sneaky ones that don't register a first party URL.
- if (filterRequest.thirdParty || (filterRequest.firstPartyUrl == QStringLiteral("")))
- {
- //qDebug() << "Request blocked.";
-
- // Return false.
- return false;
- }
-
- /* TODO. Waiting for a solution to <https://redmine.stoutner.com/issues/857>.
- // Check each tab to see if this local storage request should be allowed.
- for (PrivacyWebEngine *privacyWebEnginePointer : *privacyWebEngineListPointer)
- {
- //qDebug().noquote().nospace() << "Local storage: " << privacyWebEnginePointer->localStorageEnabled << ". WebEngine URL: " << webEngineViewPointer->url().host() << ". Request Host: " << filterRequest.firstPartyUrl.host();
-
- // Allow this local storage request if it comes from a tab with local storage enabled.
- if (privacyWebEnginePointer->localStorageEnabled && (webEngineViewPointer->url().host() == filterRequest.firstPartyUrl.host()))
- {
- //qDebug() << "Request allowed.";
-
- // Return true.
- return true;
- }
- }
- */
-
- // Allow the request if it is first party and local storage is enabled.
- if (!filterRequest.thirdParty && currentPrivacyWebEnginePointer->localStorageEnabled)
- {
- // Return true.
- return true;
- }
-
- //qDebug() << "Request blocked.";
-
- // Block any remaining local storage requests.
- return false;
- });
-
- // Process cookie changes.
- connect(webEngineCookieStorePointer, SIGNAL(cookieAdded(QNetworkCookie)), this, SLOT(cookieAdded(QNetworkCookie)));
- connect(webEngineCookieStorePointer, SIGNAL(cookieRemoved(QNetworkCookie)), this, SLOT(cookieRemoved(QNetworkCookie)));
-
- // Get a list of durable cookies.
- QList<QNetworkCookie*> *durableCookiesListPointer = CookiesDatabase::getCookies();
-
- // Add the durable cookies to the store.
- for (QNetworkCookie *cookiePointer : *durableCookiesListPointer)
- addCookieToStore(*cookiePointer);
-
- // Store a copy of the WebEngine default user agent.
- webEngineDefaultUserAgent = webEngineProfilePointer->httpUserAgent();
-
- // Update the URL line edit when the URL changes.
- connect(webEngineViewPointer, SIGNAL(urlChanged(const QUrl)), this, SLOT(updateUrl(const QUrl)));
-
- // Update the progress bar.
- connect(webEngineViewPointer, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
- connect(webEngineViewPointer, SIGNAL(loadProgress(const int)), this, SLOT(loadProgress(const int)));
- connect(webEngineViewPointer, SIGNAL(loadFinished(const bool)), this, SLOT(loadFinished()));
-
- // Instantiate the mouse event filter pointer.
- MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter();
-
- // Install the mouse event filter.
- qApp->installEventFilter(mouseEventFilterPointer);
-
- // Process mouse forward and back commands.
- connect(mouseEventFilterPointer, SIGNAL(mouseBack()), this, SLOT(mouseBack()));
- connect(mouseEventFilterPointer, SIGNAL(mouseForward()), this, SLOT(mouseForward()));
-
- // Listen for hovered link URLs.
- connect(webEnginePagePointer, SIGNAL(linkHovered(const QString)), this, SLOT(pageLinkHovered(const QString)));
-
- // Instantiate the URL request interceptor.
- UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
-
- // 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)));
-
- // Don't allow JavaScript to open windows.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
-
- // Allow keyboard navigation.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, true);
-
- // Enable full screen support.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
-
- // Require user interaction to play media.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, true);
-
- // Limit WebRTC to public IP addresses.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly, true);
-
- // Set the focus on the WebEngine view.
- webEngineViewPointer->setFocus();
-}
-
-BrowserView::~BrowserView()
-{
- // Delay the deletion of the WebEngine page to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
- webEnginePagePointer->deleteLater();
-}
-
-// The cookie is copied instead of referenced so that changes made to the cookie do not create a race condition with the display of the cookie in the dialog.
-void BrowserView::addCookieToStore(QNetworkCookie cookie) const
-{
- // Create a url.
- 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(".")))
- {
- // Populate the URL.
- url.setHost(cookie.domain());
- url.setScheme(QStringLiteral("https"));
-
- // Clear the domain from the cookie.
- cookie.setDomain(QStringLiteral(""));
- }
-
- // Add the cookie to the store.
- webEngineCookieStorePointer->setCookie(cookie, url);
-}
-
-void BrowserView::applyApplicationSettings()
-{
- // Set the search engine URL.
- searchEngineUrl = SearchEngineHelper::getSearchUrl(Settings::searchEngine());
-
- // Emit the update search engine actions signal.
- 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.
-// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
-void BrowserView::applyDomainSettingsAndReload()
-{
- // Apply the domain settings. `true` reloads the website.
- applyDomainSettings(webEngineViewPointer->url().host(), 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.
-// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
-void BrowserView::applyDomainSettingsWithoutReloading(const QString &hostname)
-{
- // Apply the domain settings `false` does not reload the website.
- applyDomainSettings(hostname, false);
-}
-
-// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
-void BrowserView::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
-{
- // Get the record for the hostname.
- QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
-
- // Check if the hostname has domain settings.
- if (domainQuery.isValid()) // The hostname has domain settings.
- {
- // Get the domain record.
- QSqlRecord domainRecord = domainQuery.record();
-
- // Set the JavaScript status.
- switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
- {
- // Set the default JavaScript status.
- case (DomainsDatabase::SYSTEM_DEFAULT):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
-
- break;
- }
-
- // Disable JavaScript.
- case (DomainsDatabase::DISABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
-
- break;
- }
-
- // Enable JavaScript.
- case (DomainsDatabase::ENABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
-
- break;
- }
- }
-
- // Set the local storage status.
- switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
- {
- // Set the default local storage status.
- case (DomainsDatabase::SYSTEM_DEFAULT):
- {
- currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled();
-
- break;
- }
-
- // Disable local storage.
- case (DomainsDatabase::DISABLED):
- {
- currentPrivacyWebEnginePointer->localStorageEnabled = false;
-
- break;
- }
-
- // Enable local storage.
- case (DomainsDatabase::ENABLED):
- {
- currentPrivacyWebEnginePointer->localStorageEnabled = true;
-
- break;
- }
- }
-
- // Set the DOM storage status.
- switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
- {
- // Set the default DOM storage status.
- case (DomainsDatabase::SYSTEM_DEFAULT):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
-
- break;
- }
-
- // Disable DOM storage.
- case (DomainsDatabase::DISABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
-
- break;
- }
-
- // Enable DOM storage.
- case (DomainsDatabase::ENABLED):
- {
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
-
- break;
- }
- }
-
- // Set the user agent.
- webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
-
- // Check if a custom zoom factor is set.
- if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
- {
- // Store the current zoom factor.
- currentZoomFactor = domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble();
- }
- else
- {
- // Reset the current zoom factor.
- currentZoomFactor = Settings::zoomFactor();
- }
-
- // Set the zoom factor. The use of `currentZoomFactor` can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
- webEngineViewPointer->setZoomFactor(currentZoomFactor);
-
- // Apply the domain settings palette to the URL line edit.
- emit updateDomainSettingsIndicator(true, domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString());
- }
- else // The hostname does not have domain settings.
- {
- // Set the JavaScript status.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
-
- // Set the local storage status.
- currentPrivacyWebEnginePointer->localStorageEnabled = Settings::localStorageEnabled();
-
- // Set DOM storage.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
-
- // Set the user agent.
- webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
-
- // Store the current zoom factor. This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
- currentZoomFactor = Settings::zoomFactor();
-
- // Set the zoom factor.
- webEngineViewPointer->setZoomFactor(Settings::zoomFactor());
-
- // Apply the no domain settings palette to the URL line edit.
- emit updateDomainSettingsIndicator(false, QStringLiteral(""));
- }
-
- // Emit the update actions signals.
- emit updateJavaScriptAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
- emit updateLocalStorageAction(currentPrivacyWebEnginePointer->localStorageEnabled);
- emit updateDomStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
- emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), true);
- emit updateZoomFactorAction(webEngineViewPointer->zoomFactor());
-
- // Reload the website if requested.
- if (reloadWebsite)
- webEngineViewPointer->reload();
-}
-
-void BrowserView::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
-{
- // Store the search engine name.
- QString searchEngineName = searchEngineActionPointer->text();
-
- // Strip out any `&` characters.
- searchEngineName.remove('&');
-
- // Store the search engine string.
- searchEngineUrl = SearchEngineHelper::getSearchUrl(searchEngineName);
-
- // Update the search engine actionas.
- emit updateSearchEngineActions(searchEngineName, false);
-}
-
-void BrowserView::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
-{
- // Get the user agent name.
- QString userAgentName = userAgentActionPointer->text();
-
- // Strip out any `&` characters.
- userAgentName.remove('&');
-
- // Apply the user agent.
- webEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromTranslatedName(userAgentName));
-
- // Update the user agent actions.
- emit updateUserAgentActions(webEngineProfilePointer->httpUserAgent(), false);
-
- // Reload the website.
- webEngineViewPointer->reload();
-}
-
-// This can be const once <https://redmine.stoutner.com/issues/799> has been resolved.
-void BrowserView::applyOnTheFlyZoomFactor(const double &zoomFactor)
-{
- // Update the current zoom factor. This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
- currentZoomFactor = zoomFactor;
-
- // Set the zoom factor.
- webEngineViewPointer->setZoomFactor(zoomFactor);
-}
-
-void BrowserView::back() const
-{
- // Go back.
- webEngineViewPointer->back();
-}
-
-void BrowserView::cookieAdded(const QNetworkCookie &cookie) const
-{
- // Add the cookie to the cookie list.
- emit addCookie(cookie);
-}
-
-void BrowserView::cookieRemoved(const QNetworkCookie &cookie) const
-{
- // Remove the cookie from the cookie list.
- emit removeCookie(cookie);
-}
-
-void BrowserView::deleteAllCookies() const
-{
- // Delete all the cookies.
- webEngineCookieStorePointer->deleteAllCookies();
-}
-
-void BrowserView::deleteCookieFromStore(const QNetworkCookie &cookie) const
-{
- // Delete the cookie.
- webEngineCookieStorePointer->deleteCookie(cookie);
-}
-
-void BrowserView::forward() const
-{
- // Go forward.
- 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.
- webEngineViewPointer->load(QUrl::fromUserInput(Settings::homepage()));
-}
-
-void BrowserView::loadFinished() const
-{
- // Hide the progress bar.
- emit hideProgressBar();
-}
-
-void BrowserView::loadInitialWebsite()
-{
- // Apply the application settings.
- applyApplicationSettings();
-
- // Get the arguments.
- QStringList argumentsStringList = qApp->arguments();
-
- // Check to see if the arguments lists contains a URL.
- if (argumentsStringList.size() > 1)
- {
- // Load the URL from the arguments list.
- webEngineViewPointer->load(QUrl::fromUserInput(argumentsStringList.at(1)));
- }
- else
- {
- // Load the homepage.
- home();
- }
-}
-
-void BrowserView::loadProgress(const int &progress) const
-{
- // Show the progress bar.
- emit showProgressBar(progress);
-}
-
-void BrowserView::loadStarted() const
-{
- // Show the progress bar.
- emit showProgressBar(0);
-}
-
-void BrowserView::loadUrlFromLineEdit(QString url) const
-{
- // Decide if the text is more likely to be a URL or a search.
- if (url.startsWith("file://")) // The text is likely a file URL.
- {
- // Load the URL.
- webEngineViewPointer->load(QUrl::fromUserInput(url));
- }
- else if (url.contains(".")) // The text is likely a URL.
- {
- // Check if the URL does not start with a valid protocol.
- if (!url.startsWith("http"))
- {
- // Add `https://` to the beginning of the URL.
- url = "https://" + url;
- }
-
- // Load the URL.
- webEngineViewPointer->load(QUrl::fromUserInput(url));
- }
- else // The text is likely a search.
- {
- // Load the search.
- webEngineViewPointer->load(QUrl::fromUserInput(searchEngineUrl + url));
- }
-}
-
-void BrowserView::mouseBack() const
-{
- // Go back if possible.
- if (webEngineViewPointer->isActiveWindow() && webEngineHistoryPointer->canGoBack())
- {
- // Clear the URL line edit focus.
- emit clearUrlLineEditFocus();
-
- // Go back.
- webEngineViewPointer->back();
- }
-}
-
-void BrowserView::mouseForward() const
-{
- // Go forward if possible.
- if (webEngineViewPointer->isActiveWindow() && webEngineHistoryPointer->canGoForward())
- {
- // Clear the URL line edit focus.
- emit clearUrlLineEditFocus();
-
- // Go forward.
- webEngineViewPointer->forward();
- }
-}
-
-void BrowserView::pageLinkHovered(const QString &linkUrl) const
-{
- // Emit a signal so that the browser window can update the status bar.
- 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.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
-
- // Update the DOM storage action.
- emit updateDomStorageAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
-
- // Reload the website.
- webEngineViewPointer->reload();
-}
-
-void BrowserView::toggleJavaScript() const
-{
- // Toggle JavaScript.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, !webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
-
- // Update the JavaScript action.
- emit updateJavaScriptAction(webEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
-
- // Reload the website.
- webEngineViewPointer->reload();
-}
-
-void BrowserView::toggleLocalStorage()
-{
- // Toggle local storeage.
- currentPrivacyWebEnginePointer->localStorageEnabled = !currentPrivacyWebEnginePointer->localStorageEnabled;
-
- // Update the local storage action.
- emit updateLocalStorageAction(currentPrivacyWebEnginePointer->localStorageEnabled);
-
- // Reload the website.
- webEngineViewPointer->reload();
-}
-
-void BrowserView::updateUrl(const QUrl &url) const
-{
- // Update the URL line edit.
- emit updateUrlLineEdit(url);
-
- // Update the status of the forward and back buttons.
- emit updateBackAction(webEngineHistoryPointer->canGoBack());
- emit updateForwardAction(webEngineHistoryPointer->canGoForward());
-
- // Reapply the zoom factor. This is a bug in QWebEngineView that resets the zoom with every load. <https://redmine.stoutner.com/issues/799>
- webEngineViewPointer->setZoomFactor(currentZoomFactor);
-}
+++ /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 BROWSERVIEW_H
-#define BROWSERVIEW_H
-
-// Application headers.
-#include "structs/PrivacyWebEngine.h"
-
-// KDE Framework headers.
-#include <KLineEdit>
-
-// Qt toolkit headers.
-#include <QPushButton>
-#include <QWebEngineFullScreenRequest>
-#include <QWebEngineHistory>
-#include <QWebEngineProfile>
-#include <QWebEngineSettings>
-#include <QWebEngineView>
-
-class BrowserView : public QWidget
-{
- // Include the Q_OBJECT macro.
- Q_OBJECT
-
-public:
- // The primary contructor.
- explicit BrowserView(QWidget *parent);
-
- // The destructor.
- ~BrowserView();
-
- // The public functions.
- void applyOnTheFlyZoomFactor(const double &zoomFactor);
- void loadInitialWebsite();
- void toggleDomStorage() const;
- void toggleJavaScript() const;
- void toggleLocalStorage();
-
- // The public static variables.
- static QString webEngineDefaultUserAgent;
-
-signals:
- // The signals.
- void addCookie(const QNetworkCookie &cookie) const;
- void removeCookie(const QNetworkCookie &cookie) const;
- void clearUrlLineEditFocus() const;
- void fullScreenRequested(const bool toggleOn) const;
- void hideProgressBar() const;
- void linkHovered(const QString &linkUrl) const;
- void showProgressBar(const int &progress) const;
- void updateBackAction(const bool &isEnabled) const;
- void updateDomStorageAction(const bool &isEnabled) const;
- void updateDomainSettingsIndicator(const bool &status, const QString &domainSettingsDomain) const;
- void updateForwardAction(const bool &isEnabled) const;
- void updateJavaScriptAction(const bool &isEnabled) const;
- void updateLocalStorageAction(const bool &isEnabled) const;
- void updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus) const;
- void updateUrlLineEdit(const QUrl &newUrl) const;
- void updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus) const;
- void updateZoomFactorAction(const double &zoomFactor) const;
-
-public Q_SLOTS:
- // The public slots.
- void addCookieToStore(QNetworkCookie cookie) const;
- void applyApplicationSettings();
- void applyDomainSettingsAndReload();
- void applyDomainSettingsWithoutReloading(const QString &hostname);
- void applyOnTheFlySearchEngine(QAction *searchEngineActionPointer);
- void applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const;
- void back() const;
- void deleteAllCookies() const;
- void deleteCookieFromStore(const QNetworkCookie &cookie) const;
- void forward() const;
- void home() const;
- void loadUrlFromLineEdit(QString url) const;
- void mouseBack() const;
- void mouseForward() const;
- void print() const;
- void printPreview() const;
- void refresh() const;
-
-private Q_SLOTS:
- // The private slots.
- void cookieAdded(const QNetworkCookie &cookie) const;
- void cookieRemoved(const QNetworkCookie &cookie) const;
- void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const;
- void loadFinished() const;
- void loadProgress(const int &progress) const;
- 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:
- // The private variables.
- double currentZoomFactor; // This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
- PrivacyWebEngine *currentPrivacyWebEnginePointer;
- QList<PrivacyWebEngine*> *privacyWebEngineListPointer;
- QString searchEngineUrl;
- QWebEngineCookieStore *webEngineCookieStorePointer;
- QWebEngineHistory *webEngineHistoryPointer;
- QWebEnginePage *webEnginePagePointer;
- QWebEngineProfile *webEngineProfilePointer;
- QWebEngineSettings *webEngineSettingsPointer;
- QWebEngineView *webEngineViewPointer;
-
- // The private functions.
- void applyDomainSettings(const QString &hostname, const bool reloadWebsite);
-};
-#endif
+++ /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/>.
-
-
-# List the sources to include in the executable.
-target_sources(privacy-browser PRIVATE
- BrowserView.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/>.
+
+
+# List the sources to include in the executable.
+target_sources(privacy-browser PRIVATE
+ TabWidget.cpp
+ PrivacyWebEngineView.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 "PrivacyWebEngineView.h"
+#include "databases/CookiesDatabase.h"
+
+// Construct the class.
+PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr) {}
+
+void PrivacyWebEngineView::addCookieToList(const QNetworkCookie &cookie) const
+{
+ //qDebug() << "Add cookie: " << cookie.toRawForm();
+
+ // Add the new cookie to the list.
+ cookieListPointer->push_front(cookie);
+
+ // Update the cookie if it is durable and has new data.
+ if (CookiesDatabase::isUpdate(cookie))
+ CookiesDatabase::updateCookie(cookie);
+
+ // Update the cookies action.
+ emit updateCookiesAction(cookieListPointer->size());
+}
+
+void PrivacyWebEngineView::removeCookieFromList(const QNetworkCookie &cookie) const
+{
+ //qDebug() << "Remove cookie: " << cookie.toRawForm();
+
+ // Remove the cookie from the list.
+ cookieListPointer->remove(cookie);
+
+ // Update the cookies action.
+ emit updateCookiesAction(cookieListPointer->size());
+}
--- /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 PRIVACYWEBENGINEVIEW_H
+#define PRIVACYWEBENGINEVIEW_H
+
+// Qt toolkit headers.
+#include <QNetworkCookie>
+#include <QWebEngineView>
+
+class PrivacyWebEngineView : public QWebEngineView
+{
+ // Include the Q_OBJECT macro.
+ Q_OBJECT
+
+public:
+ // The default constructor.
+ explicit PrivacyWebEngineView();
+
+ // The public variables.
+ std::list<QNetworkCookie> *cookieListPointer = new std::list<QNetworkCookie>;
+ QString domainSettingsName = QStringLiteral("");
+ bool localStorageEnabled = false;
+
+signals:
+ // The signals.
+ void updateCookiesAction(const int numberOfCookies) const;
+
+public Q_SLOTS:
+ // The public slots.
+ void addCookieToList(const QNetworkCookie &cookie) const;
+ void removeCookieFromList(const QNetworkCookie &cookie) const;
+};
+#endif
--- /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 "TabWidget.h"
+#include "Settings.h"
+#include "ui_AddTabWidget.h"
+#include "ui_TabWidget.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"
+
+// KDE Framework headers.
+#include <KIO/FileCopyJob>
+#include <KIO/JobUiDelegate>
+
+// Qt toolkit headers.
+#include <QAction>
+#include <QFileDialog>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QPrintDialog>
+#include <QPrintPreviewDialog>
+#include <QPrinter>
+
+// Initialize the public static variables.
+QString TabWidget::webEngineDefaultUserAgent = QStringLiteral("");
+
+// Construct the class.
+TabWidget::TabWidget(QWidget *parent) : QWidget(parent)
+{
+ // Instantiate the UIs.
+ Ui::TabWidget tabWidgetUi;
+ Ui::AddTabWidget addTabWidgetUi;
+
+ // Setup the main UI.
+ tabWidgetUi.setupUi(this);
+
+ // Get a handle for the tab widget.
+ tabWidgetPointer = tabWidgetUi.tabWidget;
+
+ // Setup the add tab UI.
+ addTabWidgetUi.setupUi(tabWidgetPointer);
+
+ // Get handles for the add tab widgets.
+ QWidget *addTabWidgetPointer = addTabWidgetUi.addTabQWidget;
+ QPushButton *addTabButtonPointer = addTabWidgetUi.addTabButton;
+
+ // Display the add tab widget.
+ tabWidgetPointer->setCornerWidget(addTabWidgetPointer);
+
+ // Add the first tab.
+ addFirstTab();
+
+ // Process tab events.
+ connect(tabWidgetPointer, SIGNAL(currentChanged(int)), this, SLOT(updateUiWithTabSettings()));
+ connect(addTabButtonPointer, SIGNAL(clicked()), this, SLOT(addTab()));
+ connect(tabWidgetPointer, SIGNAL(tabCloseRequested(int)), this, SLOT(deleteTab(int)));
+
+ // Store a copy of the WebEngine default user agent.
+ webEngineDefaultUserAgent = currentWebEngineProfilePointer->httpUserAgent();
+
+ // Instantiate the mouse event filter pointer.
+ MouseEventFilter *mouseEventFilterPointer = new MouseEventFilter();
+
+ // Install the mouse event filter.
+ qApp->installEventFilter(mouseEventFilterPointer);
+
+ // Process mouse forward and back commands.
+ connect(mouseEventFilterPointer, SIGNAL(mouseBack()), this, SLOT(mouseBack()));
+ connect(mouseEventFilterPointer, SIGNAL(mouseForward()), this, SLOT(mouseForward()));
+}
+
+TabWidget::~TabWidget()
+{
+ // Manually delete each WebEngine page.
+ for (int i = 0; i < tabWidgetPointer->count(); ++i)
+ {
+ // Get the privacy WebEngine view.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(tabWidgetPointer->widget(i));
+
+ // Deletion the WebEngine page to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+ delete privacyWebEngineViewPointer->page();
+ }
+}
+
+// The cookie is copied instead of referenced so that changes made to the cookie do not create a race condition with the display of the cookie in the dialog.
+void TabWidget::addCookieToStore(QNetworkCookie cookie, QWebEngineCookieStore *webEngineCookieStorePointer) const
+{
+ // Create a url.
+ 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(".")))
+ {
+ // Populate the URL.
+ url.setHost(cookie.domain());
+ url.setScheme(QStringLiteral("https"));
+
+ // Clear the domain from the cookie.
+ cookie.setDomain(QStringLiteral(""));
+ }
+
+ // Add the cookie to the store.
+ if (webEngineCookieStorePointer == nullptr)
+ currentWebEngineCookieStorePointer->setCookie(cookie, url);
+ else
+ webEngineCookieStorePointer->setCookie(cookie, url);
+}
+
+void TabWidget::addFirstTab()
+{
+ // Create the first tab.
+ addTab();
+
+ // Update the UI with the tab settings.
+ updateUiWithTabSettings();
+
+ // Set the focus on the current tab widget. This prevents the tab bar from showing a blue bar under the label of the first tab.
+ tabWidgetPointer->currentWidget()->setFocus();
+}
+
+void TabWidget::addTab()
+{
+ // Create a privacy WebEngine view.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = new PrivacyWebEngineView();
+
+ // Add a new tab.
+ int newTabIndex = tabWidgetPointer->addTab(privacyWebEngineViewPointer, i18nc("New tab label.", "New Tab"));
+
+ // Set the default tab icon.
+ tabWidgetPointer->setTabIcon(newTabIndex, defaultTabIcon);
+
+ // Create an off-the-record profile (the default when no profile name is specified).
+ QWebEngineProfile *webEngineProfilePointer = new QWebEngineProfile(QStringLiteral(""));
+
+ // Create a WebEngine page.
+ QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
+
+ // Set the WebEngine page.
+ privacyWebEngineViewPointer->setPage(webEnginePagePointer);
+
+ // Get handles for the web engine elements.
+ QWebEngineCookieStore *webEngineCookieStorePointer = webEngineProfilePointer->cookieStore();
+ QWebEngineSettings *webEngineSettingsPointer = webEnginePagePointer->settings();
+
+ // Update the URL line edit when the URL changes.
+ connect(privacyWebEngineViewPointer, SIGNAL(urlChanged(const QUrl)), this, SLOT(updateUrl(const QUrl)));
+
+
+ // Update the progress bar.
+ connect(privacyWebEngineViewPointer, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
+ connect(privacyWebEngineViewPointer, SIGNAL(loadProgress(const int)), this, SLOT(loadProgress(const int)));
+ connect(privacyWebEngineViewPointer, SIGNAL(loadFinished(const bool)), this, SLOT(loadFinished()));
+
+ // Handle full screen requests.
+ connect(webEnginePagePointer, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest)));
+
+ // Listen for hovered link URLs.
+ connect(webEnginePagePointer, SIGNAL(linkHovered(const QString)), this, SLOT(pageLinkHovered(const QString)));
+
+ // Handle file downloads.
+ connect(webEngineProfilePointer, SIGNAL(downloadRequested(QWebEngineDownloadItem *)), this, SLOT(showSaveDialog(QWebEngineDownloadItem *)));
+
+ // Instantiate the URL request interceptor.
+ UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
+
+ // Set the URL request interceptor.
+ webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
+
+ // Reapply the domain settings when the host changes.
+ connect(urlRequestInterceptorPointer, SIGNAL(applyDomainSettings(QString)), this, SLOT(applyDomainSettingsWithoutReloading(QString)));
+
+ // Set the local storage filter.
+ webEngineCookieStorePointer->setCookieFilter([privacyWebEngineViewPointer](const QWebEngineCookieStore::FilterRequest &filterRequest)
+ {
+ // Block all third party local storage requests, including the sneaky ones that don't register a first party URL.
+ if (filterRequest.thirdParty || (filterRequest.firstPartyUrl == QStringLiteral("")))
+ {
+ //qDebug().noquote().nospace() << "Third-party request blocked: " << filterRequest.origin;
+
+ // Return false.
+ return false;
+ }
+
+ // Allow the request if local storage is enabled.
+ if (privacyWebEngineViewPointer->localStorageEnabled)
+ {
+ //qDebug().noquote().nospace() << "Request allowed by local storage: " << filterRequest.origin;
+
+ // Return true.
+ return true;
+ }
+
+ //qDebug().noquote().nospace() << "Request blocked by default: " << filterRequest.origin;
+
+ // Block any remaining local storage requests.
+ return false;
+ });
+
+ // Disable JavaScript by default (this prevetns JavaScript from being enabled on a new tab before domain settings are loaded).
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
+ // Don't allow JavaScript to open windows.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
+
+ // Allow keyboard navigation.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, true);
+
+ // Enable full screen support.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
+
+ // Require user interaction to play media.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, true);
+
+ // Limit WebRTC to public IP addresses.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly, true);
+
+ // Define an update cookie count lambda.
+ auto updateCookieCount = [privacyWebEngineViewPointer, this] (const int numberOfCookies)
+ {
+ // Update the cookie action if the specified privacy WebEngine view is the current privacy WebEngine view.
+ if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
+ emit updateCookiesAction(numberOfCookies);
+ };
+
+ // Update the cookies action.
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::updateCookiesAction, this, updateCookieCount);
+
+ // Process cookie changes.
+ connect(webEngineCookieStorePointer, SIGNAL(cookieAdded(QNetworkCookie)), privacyWebEngineViewPointer, SLOT(addCookieToList(QNetworkCookie)));
+ connect(webEngineCookieStorePointer, SIGNAL(cookieRemoved(QNetworkCookie)), privacyWebEngineViewPointer, SLOT(removeCookieFromList(QNetworkCookie)));
+
+ // Get a list of durable cookies.
+ QList<QNetworkCookie*> *durableCookiesListPointer = CookiesDatabase::getCookies();
+
+ // Add the durable cookies to the store.
+ for (QNetworkCookie *cookiePointer : *durableCookiesListPointer)
+ addCookieToStore(*cookiePointer, webEngineCookieStorePointer);
+
+ // Define an update tab title lambda.
+ auto updateTabTitle = [privacyWebEngineViewPointer, this] (const QString &title)
+ {
+ // Get the index for this tab.
+ int tabIndex = tabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+ // Update the title for this tab.
+ tabWidgetPointer->setTabText(tabIndex, title);
+ };
+
+ // Update the title when it changes.
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, this, updateTabTitle);
+
+ // Define an update tab icon lambda.
+ auto updateTabIcon = [privacyWebEngineViewPointer, this] (const QIcon &icon)
+ {
+ // Get the index for this tab.
+ int tabIndex = tabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+ // Update the icon for this tab.
+ if (icon.isNull())
+ tabWidgetPointer->setTabIcon(tabIndex, defaultTabIcon);
+ else
+ tabWidgetPointer->setTabIcon(tabIndex, icon);
+ };
+
+ // Update the icon when it changes.
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, this, updateTabIcon);
+
+ // Move to the new tab.
+ tabWidgetPointer->setCurrentIndex(newTabIndex);
+}
+
+void TabWidget::applyApplicationSettings()
+{
+ // Set the tab position.
+ if (Settings::tabsOnTop())
+ tabWidgetPointer->setTabPosition(QTabWidget::North);
+ else
+ tabWidgetPointer->setTabPosition(QTabWidget::South);
+
+ // Set the search engine URL.
+ searchEngineUrl = SearchEngineHelper::getSearchUrl(Settings::searchEngine());
+
+ // Emit the update search engine actions signal.
+ 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.
+// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
+void TabWidget::applyDomainSettingsAndReload()
+{
+ // Apply the domain settings. `true` reloads the website.
+ applyDomainSettings(currentPrivacyWebEngineViewPointer->url().host(), 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.
+// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
+void TabWidget::applyDomainSettingsWithoutReloading(const QString &hostname)
+{
+ // Apply the domain settings `false` does not reload the website.
+ applyDomainSettings(hostname, false);
+}
+
+// Once <https://redmine.stoutner.com/issues/799> has been resolved this can be `const`.
+void TabWidget::applyDomainSettings(const QString &hostname, const bool reloadWebsite)
+{
+ // Get the record for the hostname.
+ QSqlQuery domainQuery = DomainsDatabase::getDomainQuery(hostname);
+
+ // Check if the hostname has domain settings.
+ if (domainQuery.isValid()) // The hostname has domain settings.
+ {
+ // Get the domain record.
+ QSqlRecord domainRecord = domainQuery.record();
+
+ // Store the domain settings name.
+ currentPrivacyWebEngineViewPointer->domainSettingsName = domainRecord.field(DomainsDatabase::DOMAIN_NAME).value().toString();
+
+ // Set the JavaScript status.
+ switch (domainRecord.field(DomainsDatabase::JAVASCRIPT).value().toInt())
+ {
+ // Set the default JavaScript status.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
+
+ break;
+ }
+
+ // Disable JavaScript.
+ case (DomainsDatabase::DISABLED):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
+ break;
+ }
+
+ // Enable JavaScript.
+ case (DomainsDatabase::ENABLED):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+
+ break;
+ }
+ }
+
+ // Set the local storage status.
+ switch (domainRecord.field(DomainsDatabase::LOCAL_STORAGE).value().toInt())
+ {
+ // Set the default local storage status.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ currentPrivacyWebEngineViewPointer->localStorageEnabled = Settings::localStorageEnabled();
+
+ break;
+ }
+
+ // Disable local storage.
+ case (DomainsDatabase::DISABLED):
+ {
+ currentPrivacyWebEngineViewPointer->localStorageEnabled = false;
+
+ break;
+ }
+
+ // Enable local storage.
+ case (DomainsDatabase::ENABLED):
+ {
+ currentPrivacyWebEngineViewPointer->localStorageEnabled = true;
+
+ break;
+ }
+ }
+
+ // Set the DOM storage status.
+ switch (domainRecord.field(DomainsDatabase::DOM_STORAGE).value().toInt())
+ {
+ // Set the default DOM storage status.
+ case (DomainsDatabase::SYSTEM_DEFAULT):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
+
+ break;
+ }
+
+ // Disable DOM storage.
+ case (DomainsDatabase::DISABLED):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
+
+ break;
+ }
+
+ // Enable DOM storage.
+ case (DomainsDatabase::ENABLED):
+ {
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
+
+ break;
+ }
+ }
+
+ // Set the user agent.
+ currentWebEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getResultingDomainSettingsUserAgent(domainRecord.field(DomainsDatabase::USER_AGENT).value().toString()));
+
+ // Check if a custom zoom factor is set.
+ if (domainRecord.field(DomainsDatabase::ZOOM_FACTOR).value().toInt())
+ {
+ // Store the current zoom factor.
+ currentZoomFactor = domainRecord.field(DomainsDatabase::CUSTOM_ZOOM_FACTOR).value().toDouble();
+ }
+ else
+ {
+ // Reset the current zoom factor.
+ currentZoomFactor = Settings::zoomFactor();
+ }
+
+ // Set the zoom factor. The use of `currentZoomFactor` can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
+ currentPrivacyWebEngineViewPointer->setZoomFactor(currentZoomFactor);
+ }
+ else // The hostname does not have domain settings.
+ {
+ // Reset the domain settings name.
+ currentPrivacyWebEngineViewPointer->domainSettingsName = QStringLiteral("");
+
+ // Set the JavaScript status.
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, Settings::javaScriptEnabled());
+
+ // Set the local storage status.
+ //currentPrivacyWebEngineViewPointer->localStorageEnabled = Settings::localStorageEnabled();
+
+ // Set DOM storage.
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, Settings::domStorageEnabled());
+
+ // Set the user agent.
+ currentWebEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()));
+
+ // Store the current zoom factor. This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
+ currentZoomFactor = Settings::zoomFactor();
+
+ // Set the zoom factor.
+ currentPrivacyWebEngineViewPointer->setZoomFactor(Settings::zoomFactor());
+ }
+
+ // Update the UI.
+ emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QStringLiteral(""));
+ emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
+ emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
+ emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+ emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), true);
+ emit updateZoomFactorAction(currentPrivacyWebEngineViewPointer->zoomFactor());
+
+ // Reload the website if requested.
+ if (reloadWebsite)
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+void TabWidget::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
+{
+ // Store the search engine name.
+ QString searchEngineName = searchEngineActionPointer->text();
+
+ // Strip out any `&` characters.
+ searchEngineName.remove('&');
+
+ // Store the search engine string.
+ searchEngineUrl = SearchEngineHelper::getSearchUrl(searchEngineName);
+
+ // Update the search engine actionas.
+ emit updateSearchEngineActions(searchEngineName, false);
+}
+
+void TabWidget::applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const
+{
+ // Get the user agent name.
+ QString userAgentName = userAgentActionPointer->text();
+
+ // Strip out any `&` characters.
+ userAgentName.remove('&');
+
+ // Apply the user agent.
+ currentWebEngineProfilePointer->setHttpUserAgent(UserAgentHelper::getUserAgentFromTranslatedName(userAgentName));
+
+ // Update the user agent actions.
+ emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), false);
+
+ // Reload the website.
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+// This can be const once <https://redmine.stoutner.com/issues/799> has been resolved.
+void TabWidget::applyOnTheFlyZoomFactor(const double &zoomFactor)
+{
+ // Update the current zoom factor. This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
+ currentZoomFactor = zoomFactor;
+
+ // Set the zoom factor.
+ currentPrivacyWebEngineViewPointer->setZoomFactor(zoomFactor);
+}
+
+void TabWidget::back() const
+{
+ // Go back.
+ currentPrivacyWebEngineViewPointer->back();
+}
+
+void TabWidget::deleteAllCookies() const
+{
+ // Delete all the cookies.
+ currentWebEngineCookieStorePointer->deleteAllCookies();
+}
+
+void TabWidget::deleteCookieFromStore(const QNetworkCookie &cookie) const
+{
+ // Delete the cookie.
+ currentWebEngineCookieStorePointer->deleteCookie(cookie);
+}
+
+void TabWidget::deleteTab(const int tabIndex)
+{
+ // Get the privacy WebEngine view.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(tabWidgetPointer->widget(tabIndex));
+
+ // Proccess the tab delete according to the number of tabs.
+ if (tabWidgetPointer->count() > 1) // There is more than one tab.
+ {
+ // Delete the tab.
+ tabWidgetPointer->removeTab(tabIndex);
+
+ // Delete the WebEngine page to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+ delete privacyWebEngineViewPointer->page();
+
+ // Delete the privacy WebEngine view.
+ delete privacyWebEngineViewPointer;
+ }
+ else // There is only one tab.
+ {
+ // Close Privacy Browser.
+ window()->close();
+ }
+}
+
+void TabWidget::forward() const
+{
+ // Go forward.
+ currentPrivacyWebEngineViewPointer->forward();
+}
+
+void TabWidget::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const
+{
+ // Make it so.
+ emit fullScreenRequested(fullScreenRequest.toggleOn());
+
+ // Accept the request.
+ fullScreenRequest.accept();
+}
+
+std::list<QNetworkCookie>* TabWidget::getCookieList() const
+{
+ // Return the current cookie list.
+ return currentPrivacyWebEngineViewPointer->cookieListPointer;
+}
+
+QString& TabWidget::getDomainSettingsName() const
+{
+ // Return the domain settings name.
+ return currentPrivacyWebEngineViewPointer->domainSettingsName;
+}
+
+void TabWidget::home() const
+{
+ // Load the homepage.
+ currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(Settings::homepage()));
+}
+
+void TabWidget::loadFinished() const
+{
+ // Hide the progress bar.
+ emit hideProgressBar();
+}
+
+void TabWidget::loadInitialWebsite()
+{
+ // Apply the application settings.
+ applyApplicationSettings();
+
+ // Get the arguments.
+ QStringList argumentsStringList = qApp->arguments();
+
+ // Check to see if the arguments lists contains a URL.
+ if (argumentsStringList.size() > 1)
+ {
+ // Load the URL from the arguments list.
+ currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(argumentsStringList.at(1)));
+ }
+ else
+ {
+ // Load the homepage.
+ home();
+ }
+}
+
+void TabWidget::loadProgress(const int &progress) const
+{
+ // Show the progress bar.
+ emit showProgressBar(progress);
+}
+
+void TabWidget::loadStarted() const
+{
+ // Show the progress bar.
+ emit showProgressBar(0);
+}
+
+void TabWidget::loadUrlFromLineEdit(QString url) const
+{
+ // Decide if the text is more likely to be a URL or a search.
+ if (url.startsWith("file://")) // The text is likely a file URL.
+ {
+ // Load the URL.
+ currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(url));
+ }
+ else if (url.contains(".")) // The text is likely a URL.
+ {
+ // Check if the URL does not start with a valid protocol.
+ if (!url.startsWith("http"))
+ {
+ // Add `https://` to the beginning of the URL.
+ url = "https://" + url;
+ }
+
+ // Load the URL.
+ currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(url));
+ }
+ else // The text is likely a search.
+ {
+ // Load the search.
+ currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(searchEngineUrl + url));
+ }
+}
+
+void TabWidget::mouseBack() const
+{
+ // Go back if possible.
+ if (currentPrivacyWebEngineViewPointer->isActiveWindow() && currentWebEngineHistoryPointer->canGoBack())
+ {
+ // Clear the URL line edit focus.
+ emit clearUrlLineEditFocus();
+
+ // Go back.
+ currentPrivacyWebEngineViewPointer->back();
+ }
+}
+
+void TabWidget::mouseForward() const
+{
+ // Go forward if possible.
+ if (currentPrivacyWebEngineViewPointer->isActiveWindow() && currentWebEngineHistoryPointer->canGoForward())
+ {
+ // Clear the URL line edit focus.
+ emit clearUrlLineEditFocus();
+
+ // Go forward.
+ currentPrivacyWebEngineViewPointer->forward();
+ }
+}
+
+void TabWidget::pageLinkHovered(const QString &linkUrl) const
+{
+ // Emit a signal so that the browser window can update the status bar.
+ emit linkHovered(linkUrl);
+}
+
+void TabWidget::print() const
+{
+ // Create a printer.
+ QPrinter printer;
+
+ // Set the resolution to be 300 dpi.
+ printer.setResolution(300);
+
+ // Create a printer dialog.
+ QPrintDialog printDialog(&printer, currentPrivacyWebEngineViewPointer);
+
+ // Display the dialog and print the page if instructed.
+ if (printDialog.exec() == QDialog::Accepted)
+ printWebpage(&printer);
+}
+
+void TabWidget::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, currentPrivacyWebEngineViewPointer);
+
+ // Generate the print preview.
+ connect(&printPreviewDialog, SIGNAL(paintRequested(QPrinter *)), this, SLOT(printWebpage(QPrinter *)));
+
+ // Display the dialog.
+ printPreviewDialog.exec();
+}
+
+void TabWidget::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.
+ currentWebEnginePagePointer->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 TabWidget::refresh() const
+{
+ // Reload the website.
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+void TabWidget::setTabBarVisible(const bool visible) const
+{
+ // Set the tab bar visibility.
+ tabWidgetPointer->tabBar()->setVisible(visible);
+}
+
+void TabWidget::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 TabWidget::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 TabWidget::toggleDomStorage() const
+{
+ // Toggle DOM storage.
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::LocalStorageEnabled, !currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+
+ // Update the DOM storage action.
+ emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+
+ // Reload the website.
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+void TabWidget::toggleJavaScript() const
+{
+ // Toggle JavaScript.
+ currentWebEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptEnabled, !currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ // Update the JavaScript action.
+ emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ // Reload the website.
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+void TabWidget::toggleLocalStorage()
+{
+ // Toggle local storeage.
+ currentPrivacyWebEngineViewPointer->localStorageEnabled = !currentPrivacyWebEngineViewPointer->localStorageEnabled;
+
+ // Update the local storage action.
+ emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
+
+ // Reload the website.
+ currentPrivacyWebEngineViewPointer->reload();
+}
+
+void TabWidget::updateUiWithTabSettings()
+{
+ // Update the current WebEngine pointers.
+ currentPrivacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(tabWidgetPointer->currentWidget());
+ currentWebEngineSettingsPointer = currentPrivacyWebEngineViewPointer->settings();
+ currentWebEnginePagePointer = currentPrivacyWebEngineViewPointer->page();
+ currentWebEngineProfilePointer = currentWebEnginePagePointer->profile();
+ currentWebEngineHistoryPointer = currentWebEnginePagePointer->history();
+ currentWebEngineCookieStorePointer = currentWebEngineProfilePointer->cookieStore();
+
+ // Clear the URL line edit focus.
+ emit clearUrlLineEditFocus();
+
+ // Update the UI.
+ emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QStringLiteral(""));
+ emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
+ emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
+ emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+ emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), true);
+ emit updateZoomFactorAction(currentPrivacyWebEngineViewPointer->zoomFactor());
+ emit updateUrlLineEdit(currentPrivacyWebEngineViewPointer->url());
+ emit updateCookiesAction(currentPrivacyWebEngineViewPointer->cookieListPointer->size());
+}
+
+void TabWidget::updateUrl(const QUrl &url) const
+{
+ // Update the URL line edit.
+ emit updateUrlLineEdit(url);
+
+ // Update the status of the forward and back buttons.
+ emit updateBackAction(currentWebEngineHistoryPointer->canGoBack());
+ emit updateForwardAction(currentWebEngineHistoryPointer->canGoForward());
+
+ // Reapply the zoom factor. This is a bug in QWebEngineView that resets the zoom with every load. <https://redmine.stoutner.com/issues/799>
+ currentPrivacyWebEngineViewPointer->setZoomFactor(currentZoomFactor);
+}
--- /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 TABWIDGET_H
+#define TABWIDGET_H
+
+// Application headers.
+#include "PrivacyWebEngineView.h"
+
+// KDE Framework headers.
+#include <KLineEdit>
+
+// Qt toolkit headers.
+#include <QPushButton>
+#include <QTabWidget>
+#include <QWebEngineCookieStore>
+#include <QWebEngineFullScreenRequest>
+#include <QWebEngineHistory>
+#include <QWebEngineProfile>
+#include <QWebEngineSettings>
+#include <QWebEngineView>
+
+class TabWidget : public QWidget
+{
+ // Include the Q_OBJECT macro.
+ Q_OBJECT
+
+public:
+ // The primary contructor.
+ explicit TabWidget(QWidget *parent);
+
+ // The destructor.
+ ~TabWidget();
+
+ // The public functions.
+ void applyOnTheFlyZoomFactor(const double &zoomFactor);
+ void loadInitialWebsite();
+ std::list<QNetworkCookie>* getCookieList() const;
+ QString& getDomainSettingsName() const;
+ void setTabBarVisible(const bool visible) const;
+ void toggleDomStorage() const;
+ void toggleJavaScript() const;
+ void toggleLocalStorage();
+
+ // The public static variables.
+ static QString webEngineDefaultUserAgent;
+
+signals:
+ // The signals.
+ void addCookie(const QNetworkCookie &cookie) const;
+ void removeCookie(const QNetworkCookie &cookie) const;
+ void clearUrlLineEditFocus() const;
+ void fullScreenRequested(const bool toggleOn) const;
+ void hideProgressBar() const;
+ void linkHovered(const QString &linkUrl) const;
+ void showProgressBar(const int &progress) const;
+ void updateBackAction(const bool &isEnabled) const;
+ void updateCookiesAction(const int numberOfCookies) const;
+ void updateDomStorageAction(const bool &isEnabled) const;
+ void updateDomainSettingsIndicator(const bool status) const;
+ void updateForwardAction(const bool &isEnabled) const;
+ void updateJavaScriptAction(const bool &isEnabled) const;
+ void updateLocalStorageAction(const bool &isEnabled) const;
+ void updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus) const;
+ void updateUrlLineEdit(const QUrl &newUrl) const;
+ void updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus) const;
+ void updateZoomFactorAction(const double &zoomFactor) const;
+
+public Q_SLOTS:
+ // The public slots.
+ void addTab();
+ void addCookieToStore(QNetworkCookie cookie, QWebEngineCookieStore *webEngineCookieStorePointer = nullptr) const;
+ void applyApplicationSettings();
+ void applyDomainSettingsAndReload();
+ void applyDomainSettingsWithoutReloading(const QString &hostname);
+ void applyOnTheFlySearchEngine(QAction *searchEngineActionPointer);
+ void applyOnTheFlyUserAgent(QAction *userAgentActionPointer) const;
+ void back() const;
+ void deleteAllCookies() const;
+ void deleteCookieFromStore(const QNetworkCookie &cookie) const;
+ void forward() const;
+ void home() const;
+ void loadUrlFromLineEdit(QString url) const;
+ void mouseBack() const;
+ void mouseForward() const;
+ void print() const;
+ void printPreview() const;
+ void refresh() const;
+
+private Q_SLOTS:
+ // The private slots.
+ void addFirstTab();
+ void deleteTab(const int tabIndex);
+ void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest) const;
+ void loadFinished() const;
+ void loadProgress(const int &progress) const;
+ 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 updateUiWithTabSettings();
+ void updateUrl(const QUrl &url) const;
+
+private:
+ // The private variables.
+ double currentZoomFactor; // This can be removed once <https://redmine.stoutner.com/issues/799> has been resolved.
+ PrivacyWebEngineView *currentPrivacyWebEngineViewPointer;
+ QWebEngineCookieStore *currentWebEngineCookieStorePointer;
+ QWebEngineHistory *currentWebEngineHistoryPointer;
+ QWebEnginePage *currentWebEnginePagePointer;
+ QWebEngineProfile *currentWebEngineProfilePointer;
+ QWebEngineSettings *currentWebEngineSettingsPointer;
+ QIcon defaultTabIcon = QIcon::fromTheme(QStringLiteral("globe"));
+ QString searchEngineUrl;
+ QTabWidget *tabWidgetPointer;
+
+ // The private functions.
+ void applyDomainSettings(const QString &hostname, const bool reloadWebsite);
+};
+#endif
#include "Settings.h"
#include "ui_SettingsPrivacy.h"
#include "ui_SettingsGeneral.h"
-#include "databases/CookiesDatabase.h"
#include "dialogs/CookiesDialog.h"
#include "dialogs/DomainSettingsDialog.h"
#include "helpers/SearchEngineHelper.h"
BrowserWindow::BrowserWindow() : KXmlGuiWindow()
{
// Initialize the variables.
- cookieListPointer = new std::list<QNetworkCookie>;
javaScriptEnabled = false;
localStorageEnabled = false;
- // Instantiate the main view pointer.
- browserViewPointer = new BrowserView(this);
+ // Instantiate the privacy tab widget pointer.
+ tabWidgetPointer = new TabWidget(this);
- // Set the main view as the central widget.
- setCentralWidget(browserViewPointer);
+ // Set the privacy tab widget as the central widget.
+ setCentralWidget(tabWidgetPointer);
// Get a handle for the action collection.
KActionCollection *actionCollectionPointer = this->actionCollection();
// Add the standard actions.
KStandardAction::openNew(this, SLOT(fileNew()), actionCollectionPointer);
- KStandardAction::print(browserViewPointer, SLOT(print()), actionCollectionPointer);
- KStandardAction::printPreview(browserViewPointer, SLOT(printPreview()), actionCollectionPointer);
+ KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
+ KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
fullScreenActionPointer = KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollectionPointer);
searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
- cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
+ cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
domStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("view-web-browser-dom-tree")));
// Update the on-the-fly menus.
- connect(browserViewPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
- connect(browserViewPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
- connect(browserViewPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
+ connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
+ connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
+ connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
// Apply the on-the-fly settings when selected.
- connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), browserViewPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
- connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), browserViewPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
+ connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
+ connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
+
+ // Process cookie changes.
+ connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
// Display dialogs.
connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
// Update the URL toolbar actions.
- connect(browserViewPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
- connect(browserViewPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
- connect(browserViewPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
- connect(browserViewPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
- connect(browserViewPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
+ connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
+ connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
+ connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
+ connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
+ connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
// Setup the GUI based on the browser_ui.rc file.
setupGUI(StandardWindowOption::Default, ("browser_ui.rc"));
connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
// Update the URL line edit on page loads.
- connect(browserViewPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
+ connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
// Get a handle for the status bar.
QStatusBar *statusBarPointer = statusBar();
statusBarPointer->addPermanentWidget(progressBarPointer);
// Update the status bar with the URL when a link is hovered.
- connect(browserViewPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
+ connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
// Update the progress bar.
- connect(browserViewPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
- connect(browserViewPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
+ connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
+ connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
- // Clear the URL line edit focus when requested.
- connect(browserViewPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
+ // Update the URL line edit focus.
+ connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
// Get the URL line edit palettes.
noDomainSettingsPalette = urlLineEditPointer->palette();
domainSettingsPalette.setColor(QPalette::Base, QColor("#C8E6C9"));
// Update the applied palette.
- connect(browserViewPointer, SIGNAL(updateDomainSettingsIndicator(bool, QString)), this, SLOT(updateDomainSettingsIndicator(bool, QString)));
-
- // Process cookie changes.
- connect(browserViewPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieToList(QNetworkCookie)));
- connect(browserViewPointer, SIGNAL(removeCookie(QNetworkCookie)), this, SLOT(removeCookieFromList(QNetworkCookie)));
+ connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
// Process full screen requests.
- connect(browserViewPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
+ connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
// Create keyboard shortcuts.
+ QShortcut *ctrlTShortcutPointer = new QShortcut(QKeySequence(i18nc("The open new tab shortcut.", "Ctrl+t")), this);
QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
// Connect the keyboard shortcuts to the actions.
+ connect(ctrlTShortcutPointer, SIGNAL(activated()), tabWidgetPointer, SLOT(addTab()));
connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
// Load the initial website.
- browserViewPointer->loadInitialWebsite();
-}
-
-void BrowserWindow::addCookieToList(const QNetworkCookie &newCookie) const
-{
- //qDebug() << "Add cookie: " << newCookie.toRawForm();
-
- // Add the new cookie to the list.
- cookieListPointer->push_front(newCookie);
-
- // Update the action text.
- cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
-
- // Update the cookie if it is durable and has new data.
- if (CookiesDatabase::isUpdate(newCookie))
- CookiesDatabase::updateCookie(newCookie);
+ tabWidgetPointer->loadInitialWebsite();
}
void BrowserWindow::addOrEditDomainSettings() const
// Create the domain settings dialog pointer.
DomainSettingsDialog *domainSettingsDialogPointer;
+ // Get the current domain settings name.
+ QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
+
// Run the commands according to the current domain settings status.
- if (currentDomainSettingsDomain == "") // Domain settings are not currently applied.
+ if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
{
// Instruct the domain settings dialog to add a new domain.
domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
else // Domain settings are currently applied.
{
// Instruct the domain settings dialog to edit the current domain.
- domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsDomain);
+ domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
}
// Set the dialog window title.
domainSettingsDialogPointer->show();
// Reload the tabs when domain settings are updated.
- connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
+ connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
}
void BrowserWindow::back() const
urlLineEditPointer->clearFocus();
// Go back.
- browserViewPointer->back();
+ tabWidgetPointer->back();
}
void BrowserWindow::clearUrlLineEditFocus() const
urlLineEditPointer->clearFocus();
// Go forward.
- browserViewPointer->forward();
+ tabWidgetPointer->forward();
}
void BrowserWindow::fullScreenRequested(const bool toggleOn)
menuBar()->setVisible(false);
navigationToolBarPointer->setVisible(false);
urlToolBarPointer->setVisible(false);
+ tabWidgetPointer->setTabBarVisible(false);
statusBar()->setVisible(false);
}
else // Turn full screen mode off.
menuBar()->setVisible(true);
navigationToolBarPointer->setVisible(true);
urlToolBarPointer->setVisible(true);
+ tabWidgetPointer->setTabBarVisible(true);
statusBar()->setVisible(true);
}
}
currentZoomFactor = newZoomFactor;
// Set the new zoom factor.
- browserViewPointer->applyOnTheFlyZoomFactor(newZoomFactor);
+ tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
// Update the on-the-fly action text.
updateZoomFactorAction(newZoomFactor);
urlLineEditPointer->clearFocus();
// Go home.
- browserViewPointer->home();
+ tabWidgetPointer->home();
}
void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
urlLineEditPointer->clearFocus();
// Load the URL.
- browserViewPointer->loadUrlFromLineEdit(url);
+ tabWidgetPointer->loadUrlFromLineEdit(url);
}
void BrowserWindow::refresh() const
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()));
+ tabWidgetPointer->refresh();
}
void BrowserWindow::showCookiesDialog()
urlLineEditPointer->clearFocus();
// Instantiate the cookie settings dialog.
- CookiesDialog *cookiesDialogPointer = new CookiesDialog(cookieListPointer);
+ CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
// Show the dialog.
cookiesDialogPointer->show();
// Connect the dialog signals.
- connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), browserViewPointer, SLOT(addCookieToStore(QNetworkCookie)));
- connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), browserViewPointer, SLOT(deleteAllCookies()));
- connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), browserViewPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
+ connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
+ connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
+ connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
}
void BrowserWindow::showDownloadLocationBrowseDialog() const
domainSettingsDialogPointer->show();
// Reload the tabs when domain settings are updated.
- connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
+ connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
}
void BrowserWindow::showProgressBar(const int &progress) const
configDialogPointer->resize(1000, 500);
// Apply the settings when they are updated.
- connect(configDialogPointer, SIGNAL(settingsChanged(QString)), browserViewPointer, SLOT(applyApplicationSettings()));
- connect(configDialogPointer, SIGNAL(settingsChanged(QString)), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
+ connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
+ connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
}
QSize BrowserWindow::sizeHint() const
urlLineEditPointer->clearFocus();
// Toggle DOM storage.
- browserViewPointer->toggleDomStorage();
+ tabWidgetPointer->toggleDomStorage();
}
void BrowserWindow::toggleJavaScript() const
urlLineEditPointer->clearFocus();
// Toggle JavaScript.
- browserViewPointer->toggleJavaScript();
+ tabWidgetPointer->toggleJavaScript();
}
void BrowserWindow::toggleLocalStorage() const
urlLineEditPointer->clearFocus();
// Toggle local storage.
- browserViewPointer->toggleLocalStorage();
+ tabWidgetPointer->toggleLocalStorage();
}
void BrowserWindow::toggleFullScreen()
urlToolBarPointer->setVisible(false);
}
+ // Hide the tab bar if specified.
+ if (Settings::fullScreenHideTabBar())
+ tabWidgetPointer->setTabBarVisible(false);
+
// Hide the status bar if specified.
if (Settings::fullScreenHideStatusBar())
statusBar()->setVisible(false);
navigationToolBarPointer->setVisible(true);
urlToolBarPointer->setVisible(true);
+ // Show the tab bar.
+ tabWidgetPointer->setTabBarVisible(true);
+
// Show the status bar.
statusBar()->setVisible(true);
}
}
+void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
+{
+ // Update the action text.
+ cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
+}
+
void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
{
// Set the action checked status.
domStorageActionPointer->setChecked(isEnabled);
}
-void BrowserWindow::updateDomainSettingsIndicator(const bool &status, const QString &domainSettingsDomain)
+void BrowserWindow::updateDomainSettingsIndicator(const bool status)
{
// Set the domain palette according to the status.
if (status)
urlLineEditPointer->setPalette(domainSettingsPalette);
else
urlLineEditPointer->setPalette(noDomainSettingsPalette);
-
- // Store the domain.
- currentDomainSettingsDomain = domainSettingsDomain;
}
void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
// Update the user agent menu action text.
userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
}
- else if (userAgent == BrowserView::webEngineDefaultUserAgent) // WebEngine default.
+ else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
{
// check the WebEngine default user agent action.
userAgentWebEngineDefaultActionPointer->setChecked(true);
// Update the URL line edit if it does not have focus.
if (!urlLineEditPointer->hasFocus())
{
+ // Get the new URL string.
+ QString newUrlString = newUrl.toString();
+
// Update the URL line edit.
- urlLineEditPointer->setText(newUrl.toString());
+ urlLineEditPointer->setText(newUrlString);
+
+ // Set the focus if the new URL is blank.
+ if (newUrlString == QStringLiteral(""))
+ urlLineEditPointer->setFocus();
}
// Store the current URL.
#define BROWSERWINDOW_H
// Application headers.
-#include "views/BrowserView.h"
+#include "widgets/TabWidget.h"
// KDE Frameworks headers.
#include <KConfigDialog>
#include <QLabel>
#include <QProgressBar>
-// C++ headers.
-#include <list>
-
class BrowserWindow : public KXmlGuiWindow
{
// Include the Q_OBJECT macro.
private Q_SLOTS:
// The private slots.
- void addCookieToList(const QNetworkCookie &newCookie) const;
void addOrEditDomainSettings() const;
void back() const;
void clearUrlLineEditFocus() const;
void home() const;
void loadUrlFromLineEdit(const QString &url) const;
void refresh() const;
- void removeCookieFromList(const QNetworkCookie &cookie) const;
void showCookiesDialog();
void showDownloadLocationBrowseDialog() const;
void showDomainSettingsDialog() const;
void toggleJavaScript() const;
void toggleLocalStorage() const;
void toggleFullScreen();
+ void updateCookiesAction(const int numberOfCookies) const;
void updateDomStorageAction(const bool &isEnabled) const;
- void updateDomainSettingsIndicator(const bool &status, const QString &domainSettingsDomain);
+ void updateDomainSettingsIndicator(const bool status);
void updateJavaScriptAction(const bool &isEnabled);
void updateLocalStorageAction(const bool &isEnabled);
void updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus);
private:
// The private variables.
- BrowserView *browserViewPointer;
KConfigDialog *configDialogPointer;
- std::list<QNetworkCookie> *cookieListPointer;
QAction *cookiesActionPointer;
- QString currentDomainSettingsDomain;
QUrl currentUrl;
double currentZoomFactor;
bool customSearchEngineEnabled;
QAction *searchEngineBingActionPointer;
QAction *searchEngineYahooActionPointer;
QAction *searchEngineCustomActionPointer;
+ TabWidget *tabWidgetPointer;
QLabel *userAgentLabelPointer;
QAction *userAgentMenuActionPointer;
QAction *userAgentPrivacyBrowserActionPointer;