]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/windows/BrowserWindow.cpp
d3800ad8e1674c93b7c54e77c0be5618c62eed6f
[PrivacyBrowserPC.git] / src / windows / BrowserWindow.cpp
1 /*
2  * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
5  *
6  * Privacy Browser PC is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser PC is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 // Application headers.
21 #include "BrowserWindow.h"
22 #include "Settings.h"
23 #include "ui_SettingsPrivacy.h"
24 #include "ui_SettingsGeneral.h"
25 #include "databases/CookiesDatabase.h"
26 #include "dialogs/CookiesDialog.h"
27 #include "dialogs/DomainSettingsDialog.h"
28 #include "helpers/SearchEngineHelper.h"
29 #include "helpers/UserAgentHelper.h"
30
31 // KDE Frameworks headers.
32 #include <KActionCollection>
33 #include <KToolBar>
34
35 // Qt toolkit headers.
36 #include <QInputDialog>
37 #include <QNetworkCookie>
38 #include <QMenuBar>
39 #include <QStatusBar>
40
41 // Construct the class.
42 BrowserWindow::BrowserWindow() : KXmlGuiWindow()
43 {
44     // Initialize the variables.
45     cookieListPointer = new std::list<QNetworkCookie>;
46     javaScriptEnabled = false;
47     localStorageEnabled = false;
48
49     // Instantiate the main view pointer.
50     browserViewPointer = new BrowserView(this);
51
52     // Set the main view as the central widget.
53     setCentralWidget(browserViewPointer);
54
55     // Get a handle for the action collection.
56     KActionCollection *actionCollectionPointer = this->actionCollection();
57
58     // Add the standard actions.
59     QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
60     QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
61     KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
62     KStandardAction::openNew(this, SLOT(fileNew()), actionCollectionPointer);
63     KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
64     KStandardAction::preferences(this, SLOT(settingsConfigure()), actionCollectionPointer);
65     KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
66
67     // Add the custom actions.
68     userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_privacy_browser"));
69     userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_webengine_default"));
70     userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_firefox_linux"));
71     userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_chromium_linux"));
72     userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_firefox_windows"));
73     userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_chrome_windows"));
74     userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_edge_windows"));
75     userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_safari_macos"));
76     userAgentCustomActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_custom"));
77     zoomFactorActionPointer = actionCollectionPointer->addAction(QStringLiteral("zoom_factor"));
78     searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_mojeek"));
79     searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_monocles"));
80     searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_metager"));
81     searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_google"));
82     searchEngineBingActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_bing"));
83     searchEngineYahooActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_yahoo"));
84     searchEngineCustomActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_custom"));
85     QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QStringLiteral("domain_settings"));
86     cookiesActionPointer = actionCollectionPointer->addAction(QStringLiteral("cookies"));
87     javaScriptActionPointer = actionCollectionPointer->addAction(QStringLiteral("javascript"));
88     localStorageActionPointer = actionCollectionPointer->addAction(QStringLiteral("local_storage"));
89     domStorageActionPointer = actionCollectionPointer->addAction(QStringLiteral("dom_storage"));
90
91     // Create the action groups
92     QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
93     QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
94
95     // Add the actions to the groups.
96     userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
97     userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
98     userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
99     userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
100     userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
101     userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
102     userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
103     userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
104     userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
105     searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
106     searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
107     searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
108     searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
109     searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
110     searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
111     searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
112
113     // Set some actions to be checkable.
114     javaScriptActionPointer->setCheckable(true);
115     localStorageActionPointer->setCheckable(true);
116     domStorageActionPointer->setCheckable(true);
117     userAgentPrivacyBrowserActionPointer->setCheckable(true);
118     userAgentWebEngineDefaultActionPointer->setCheckable(true);
119     userAgentFirefoxLinuxActionPointer->setCheckable(true);
120     userAgentChromiumLinuxActionPointer->setCheckable(true);
121     userAgentFirefoxWindowsActionPointer->setCheckable(true);
122     userAgentChromeWindowsActionPointer->setCheckable(true);
123     userAgentEdgeWindowsActionPointer->setCheckable(true);
124     userAgentSafariMacosActionPointer->setCheckable(true);
125     userAgentCustomActionPointer->setCheckable(true);
126     searchEngineMojeekActionPointer->setCheckable(true);
127     searchEngineMonoclesActionPointer->setCheckable(true);
128     searchEngineMetagerActionPointer->setCheckable(true);
129     searchEngineGoogleActionPointer->setCheckable(true);
130     searchEngineBingActionPointer->setCheckable(true);
131     searchEngineYahooActionPointer->setCheckable(true);
132     searchEngineCustomActionPointer->setCheckable(true);
133
134     // Set the action text.
135     userAgentPrivacyBrowserActionPointer->setText(UserAgentHelper::PRIVACY_BROWSER_TRANSLATED);
136     userAgentWebEngineDefaultActionPointer->setText(UserAgentHelper::WEB_ENGINE_DEFAULT_TRANSLATED);
137     userAgentFirefoxLinuxActionPointer->setText(UserAgentHelper::FIREFOX_LINUX_TRANSLATED);
138     userAgentChromiumLinuxActionPointer->setText(UserAgentHelper::CHROMIUM_LINUX_TRANSLATED);
139     userAgentFirefoxWindowsActionPointer->setText(UserAgentHelper::FIREFOX_WINDOWS_TRANSLATED);
140     userAgentChromeWindowsActionPointer->setText(UserAgentHelper::CHROME_WINDOWS_TRANSLATED);
141     userAgentEdgeWindowsActionPointer->setText(UserAgentHelper::EDGE_WINDOWS_TRANSLATED);
142     userAgentSafariMacosActionPointer->setText(UserAgentHelper::SAFARI_MACOS_TRANSLATED);
143     searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
144     searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
145     searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
146     searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
147     searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
148     searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
149     domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
150     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
151     javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
152     localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
153     domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
154
155     // Set the action icons.
156     userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode"));
157     userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
158     userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("firefox-esr")));
159     userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("chromium")));
160     userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("firefox-esr")));
161     userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("chromium")));
162     userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
163     userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
164     userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
165     searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
166     searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
167     searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
168     searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("im-google")));
169     searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
170     searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("im-yahoo")));
171     searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
172     zoomFactorActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("zoom")));
173     domainSettingsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("settings-configure")));
174     cookiesActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("preferences-web-browser-cookies")));
175     domStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("view-web-browser-dom-tree")));
176
177     // Update the on-the-fly menus.
178     connect(browserViewPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
179     connect(browserViewPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
180     connect(browserViewPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
181
182     // Apply the on-the-fly settings when selected.
183     connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), browserViewPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
184     connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), browserViewPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
185
186     // Display dialogs.
187     connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
188     connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(openCookiesDialog()));
189     connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(openDomainSettings()));
190
191     // Connect the URL toolbar actions.
192     connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
193     connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
194     connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
195
196     // Update the URL toolbar actions.
197     connect(browserViewPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
198     connect(browserViewPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
199     connect(browserViewPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
200     connect(browserViewPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
201     connect(browserViewPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
202
203     // Setup the GUI based on the browser_ui.rc file.
204     setupGUI(StandardWindowOption::Default, ("browser_ui.rc"));
205
206     // Get lists of the actions' associated widgets.
207     QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
208     QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
209
210     // Get the menu widget pointers.  It is the second entry, after the main window.
211     QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
212     QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
213
214     // Get the menu pointers.
215     QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
216     QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
217
218     // Get the menu actions.
219     userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
220     searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
221
222     // Get a handle for the URL toolbar.
223     KToolBar *urlToolBarPointer = toolBar(QStringLiteral("url_toolbar"));
224
225     // Create a URL line edit.
226     urlLineEditPointer = new KLineEdit();
227
228     // Add an edit or add domain settings action to the URL line edit.
229     QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure"), QLineEdit::TrailingPosition);
230
231     // Add or edit the current domain settings.
232     connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
233
234     // Populate the URL toolbar.
235     urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
236
237     // Load a new URL from the URL line edit.
238     connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
239
240     // Update the URL line edit on page loads.
241     connect(browserViewPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
242
243     // Get a handle for the status bar.
244     QStatusBar *statusBarPointer = statusBar();
245
246     // Create a progress bar.
247     progressBarPointer = new QProgressBar();
248
249     // Add the progress bar to to the status bar.
250     statusBarPointer->addPermanentWidget(progressBarPointer);
251
252     // Update the status bar with the URL when a link is hovered.
253     connect(browserViewPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
254
255     // Update the progress bar.
256     connect(browserViewPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
257     connect(browserViewPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
258
259     // Clear the URL line edit focus when requested.
260     connect(browserViewPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
261
262     // Get the URL line edit palettes.
263     noDomainSettingsPalette = urlLineEditPointer->palette();
264     domainSettingsPalette = urlLineEditPointer->palette();
265
266     // Modify the domain settings palette.
267     domainSettingsPalette.setColor(QPalette::Base, QColor("#C8E6C9"));
268
269     // Update the applied palette.
270     connect(browserViewPointer, SIGNAL(updateDomainSettingsIndicator(bool, QString)), this, SLOT(updateDomainSettingsIndicator(bool, QString)));
271
272     // Process cookie changes.
273     connect(browserViewPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieToList(QNetworkCookie)));
274     connect(browserViewPointer, SIGNAL(removeCookie(QNetworkCookie)), this, SLOT(removeCookieFromList(QNetworkCookie)));
275
276     // Load the initial website.
277     browserViewPointer->loadInitialWebsite();
278 }
279
280 void BrowserWindow::addCookieToList(const QNetworkCookie &newCookie) const
281 {
282     //qDebug() << "Add cookie:  " << newCookie.toRawForm();
283
284     // Add the new cookie to the list.
285     cookieListPointer->push_front(newCookie);
286
287     // Update the action text.
288     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
289
290     // Update the cookie if it is durable and has new data.
291     if (CookiesDatabase::isUpdate(newCookie))
292         CookiesDatabase::updateCookie(newCookie);
293 }
294
295 void BrowserWindow::addOrEditDomainSettings() const
296 {
297     // Remove the focus from the URL line edit.
298     urlLineEditPointer->clearFocus();
299
300     // Create the domain settings dialog pointer.
301     DomainSettingsDialog *domainSettingsDialogPointer;
302
303     // Run the commands according to the current domain settings status.
304     if (currentDomainSettingsDomain == "")  // Domain settings are not currently applied.
305     {
306         // Instruct the domain settings dialog to add a new domain.
307         domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
308     }
309     else  // Domain settings are currently applied.
310     {
311         // Instruct the domain settings dialog to edit the current domain.
312         domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsDomain);
313     }
314
315     // Set the dialog window title.
316     domainSettingsDialogPointer->setWindowTitle(i18nc("The domain settings dialog title", "Domain Settings"));
317
318     // Set the modality.
319     domainSettingsDialogPointer->setWindowModality(Qt::WindowModality::WindowModal);;
320
321     // Show the dialog.
322     domainSettingsDialogPointer->show();
323
324     // Reload the tabs when domain settings are updated.
325     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
326 }
327
328 void BrowserWindow::back() const
329 {
330     // Remove the focus from the URL line edit.
331     urlLineEditPointer->clearFocus();
332
333     // Go back.
334     browserViewPointer->back();
335 }
336
337 void BrowserWindow::clearUrlLineEditFocus() const
338 {
339     // Remove the focus from the URL line edit.
340     urlLineEditPointer->clearFocus();
341 }
342
343 void BrowserWindow::fileNew() const
344 {
345     // Display a new instance of Privacy Browser.
346     (new BrowserWindow)->show();
347 }
348
349 void BrowserWindow::forward() const
350 {
351     // Remove the focus from the URL line edit.
352     urlLineEditPointer->clearFocus();
353
354     // Go forward.
355     browserViewPointer->forward();
356 }
357
358 void BrowserWindow::getZoomFactorFromUser()
359 {
360     // Create an OK flag.
361     bool okClicked;
362
363     // Display a dialog to get the new zoom factor from the user.  Format the double to display two decimals and have a 0.25 step.
364     double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
365                                                    i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
366                                                    currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
367
368     // Update the zoom factor if the user clicked OK.
369     if (okClicked)
370     {
371         // Update the current zoom factor.
372         currentZoomFactor = newZoomFactor;
373
374         // Set the new zoom factor.
375         browserViewPointer->applyOnTheFlyZoomFactor(newZoomFactor);
376
377         // Update the on-the-fly action text.
378         updateZoomFactorAction(newZoomFactor);
379     }
380 }
381
382 void BrowserWindow::home() const
383 {
384     // Remove the focus from the URL line edit.
385     urlLineEditPointer->clearFocus();
386
387     // Go home.
388     browserViewPointer->home();
389 }
390
391 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
392 {
393     // Remove the focus from the URL line edit.
394     urlLineEditPointer->clearFocus();
395
396     // Load the URL.
397     browserViewPointer->loadUrlFromLineEdit(url);
398 }
399
400 void BrowserWindow::openCookiesDialog()
401 {
402     // Remove the focus from the URL line edit.
403     urlLineEditPointer->clearFocus();
404
405     // Instantiate the cookie settings dialog.
406     CookiesDialog *cookiesDialogPointer = new CookiesDialog(cookieListPointer);
407
408     // Show the dialog.
409     cookiesDialogPointer->show();
410
411     // Connect the dialog signals.
412     connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), browserViewPointer, SLOT(addCookieToStore(QNetworkCookie)));
413     connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), browserViewPointer, SLOT(deleteAllCookies()));
414     connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), browserViewPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
415 }
416
417 void BrowserWindow::openDomainSettings() const
418 {
419     // Remove the focus from the URL line edit.
420     urlLineEditPointer->clearFocus();
421
422     // Instantiate the domain settings dialog.
423     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
424
425     // Show the dialog.
426     domainSettingsDialogPointer->show();
427
428     // Reload the tabs when domain settings are updated.
429     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
430 }
431
432 void BrowserWindow::refresh() const
433 {
434     // Remove the focus from the URL line edit.
435     urlLineEditPointer->clearFocus();
436
437     // Refresh the web page.
438     browserViewPointer->refresh();
439 }
440
441 void BrowserWindow::removeCookieFromList(const QNetworkCookie &cookie) const
442 {
443     //qDebug() << "Remove cookie:  " << cookie.toRawForm();
444
445     // Remove the cookie from the list.
446     cookieListPointer->remove(cookie);
447
448     // Update the action text.
449     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", cookieListPointer->size()));
450 }
451
452 void BrowserWindow::showProgressBar(const int &progress) const
453 {
454     // Set the progress bar value.
455     progressBarPointer->setValue(progress);
456
457     // Show the progress bar.
458     progressBarPointer->show();
459 }
460
461 QSize BrowserWindow::sizeHint() const
462 {
463     // Return the default window size.
464     return QSize(1500, 1200);
465 }
466
467 void BrowserWindow::settingsConfigure()
468 {
469     // Check to make sure the dialog box isn't already displayed.
470     if (KConfigDialog::exists(QStringLiteral("settings")))
471     {
472         // Show the existing config dialog if it is hidden.
473         configDialogPointer->show();
474
475         // Raise the existing config dialog if it is below other windows.
476         configDialogPointer->raise();
477
478         // Restore the existing config dialog if it has been minimized.
479         if (configDialogPointer->isMinimized()) {
480             configDialogPointer->showNormal();
481         }
482
483         // Activate the existing config dialog, which brings its virtual desktop into focus.
484         configDialogPointer->activateWindow();
485     }
486     else
487     {
488         // Create the settings widgets.
489         QWidget *privacySettingsWidgetPointer = new QWidget;
490         QWidget *generalSettingsWidgetPointer = new QWidget;
491
492         // Instantiate the settings UI.
493         Ui::PrivacySettings privacySettingsUi;
494         Ui::GeneralSettings generalSettingsUi;
495
496         // Setup the UI to display the settings widgets.
497         privacySettingsUi.setupUi(privacySettingsWidgetPointer);
498         generalSettingsUi.setupUi(generalSettingsWidgetPointer);
499
500         // Get handles for the widgets.
501         QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
502         userAgentLabelPointer = privacySettingsUi.userAgentLabel;
503         QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
504         searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
505
506         // Populate the combo box labels.
507         updateUserAgentLabel(userAgentComboBoxPointer->currentText());
508         updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
509
510         // Update the labels when the combo boxes change.
511         connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
512         connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
513
514         // Instantiate a settings config dialog from the settings.kcfg file.
515         configDialogPointer = new KConfigDialog(this, QStringLiteral("settings"), Settings::self());
516
517         // Add the settings widgets as config dialog pages.
518         configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("@title:tab", "Privacy"), QStringLiteral("privacy-browser"));
519         configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("@title:tab", "General"), QStringLiteral("breeze-settings"));
520
521         // Delete the config dialog when it is closed.
522         configDialogPointer->setAttribute(Qt::WA_DeleteOnClose);
523
524         // Make it so.
525         configDialogPointer->show();
526
527         // TODO.  KConfigDialog does not respect expanding size policies.  <https://redmine.stoutner.com/issues/823>
528         //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
529         //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
530         //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
531         //configDialogPointer->adjustSize();
532
533         // Expand the config dialog.
534         configDialogPointer->resize(1000, 500);
535
536         // Apply the settings when they are updated.
537         connect(configDialogPointer, SIGNAL(settingsChanged(QString)), browserViewPointer, SLOT(applyApplicationSettings()));
538         connect(configDialogPointer, SIGNAL(settingsChanged(QString)), browserViewPointer, SLOT(applyDomainSettingsAndReload()));
539     }
540 }
541
542 void BrowserWindow::toggleLocalStorage() const
543 {
544     // Remove the focus from teh URL line edit.
545     urlLineEditPointer->clearFocus();
546
547     // Toggle local storage.
548     browserViewPointer->toggleLocalStorage();
549 }
550
551 void BrowserWindow::toggleJavaScript() const
552 {
553     // Remove the focus from the URL line edit.
554     urlLineEditPointer->clearFocus();
555
556     // Toggle JavaScript.
557     browserViewPointer->toggleJavaScript();
558 }
559
560 void BrowserWindow::toggleDomStorage() const
561 {
562     // Remove the focus from the URL line edit.
563     urlLineEditPointer->clearFocus();
564
565     // Toggle DOM storage.
566     browserViewPointer->toggleDomStorage();
567 }
568
569 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
570 {
571     // Set the action checked status.
572     domStorageActionPointer->setChecked(isEnabled);
573 }
574
575 void BrowserWindow::updateDomainSettingsIndicator(const bool &status, const QString &domainSettingsDomain)
576 {
577     // Set the domain palette according to the status.
578     if (status)
579         urlLineEditPointer->setPalette(domainSettingsPalette);
580     else
581         urlLineEditPointer->setPalette(noDomainSettingsPalette);
582
583     // Store the domain.
584     currentDomainSettingsDomain = domainSettingsDomain;
585 }
586
587 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
588 {
589     // Update the JavaScript status.
590     javaScriptEnabled = isEnabled;
591
592     // Set the icon according to the status.
593     if (javaScriptEnabled)
594         javaScriptActionPointer->setIcon(QIcon(QStringLiteral(":/icons/javascript-warning")));
595     else
596         javaScriptActionPointer->setIcon(QIcon(QStringLiteral(":/icons/privacy-mode")));
597
598     // Set the action checked status.
599     javaScriptActionPointer->setChecked(javaScriptEnabled);
600
601     // Update the status of the DOM storage action.
602     domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
603 }
604
605 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
606 {
607     // Update the local storage status.
608     localStorageEnabled = isEnabled;
609
610     // Update the icon.
611     if (localStorageEnabled)
612         localStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("disk-quota-high")));
613     else
614         localStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("disk-quota")));
615
616     // Set the action checked status.
617     localStorageActionPointer->setChecked(localStorageEnabled);
618
619     // Update the status of the DOM storage action.
620     domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
621 }
622
623 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
624 {
625     // Initialize the custom search engine flag.
626     bool customSearchEngine = false;
627
628     if (searchEngine == "Mojeek")  // Mojeek.
629     {
630         // Check the Mojeek user agent action.
631         searchEngineMojeekActionPointer->setChecked(true);
632
633         // Update the search engine menu action text.
634         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
635     }
636     else if (searchEngine == "Monocles")  // Monocles.
637     {
638         // Check the Monocles user agent action.
639         searchEngineMonoclesActionPointer->setChecked(true);
640
641         // Update the search engine menu action text.
642         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
643     }
644     else if (searchEngine == "MetaGer")  // MetaGer.
645     {
646         // Check the MetaGer user agent action.
647         searchEngineMetagerActionPointer->setChecked(true);
648
649         // Update the search engine menu action text.
650         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
651     }
652     else if (searchEngine == "Google")  // Google.
653     {
654         // Check the Google user agent action.
655         searchEngineGoogleActionPointer->setChecked(true);
656
657         // Update the search engine menu action text.
658         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
659     }
660     else if (searchEngine == "Bing")  // Bing.
661     {
662         // Check the Bing user agent action.
663         searchEngineBingActionPointer->setChecked(true);
664
665         // Update the search engine menu action text.
666         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
667     }
668     else if (searchEngine == "Yahoo")  // Yahoo.
669     {
670         // Check the Yahoo user agent action.
671         searchEngineYahooActionPointer->setChecked(true);
672
673         // Update the search engine menu action text.
674         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
675     }
676     else  // Custom search engine.
677     {
678         // Check the user agent.
679         searchEngineCustomActionPointer->setChecked(true);
680
681         // Update the search engine menu action text.
682         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
683
684         // Set the custom search engine text.
685         searchEngineCustomActionPointer->setText(searchEngine);
686
687         // Set the custom search engine flag.
688         customSearchEngine = true;
689     }
690
691     // Update the custom search engine enabled boolean.
692     if (updateCustomSearchEngineStatus)
693         customSearchEngineEnabled = customSearchEngine;
694
695     // Format the custom search engine.
696     if (customSearchEngineEnabled)
697     {
698         // Enable the custom search engine.
699         searchEngineCustomActionPointer->setEnabled(true);
700     }
701     else
702     {
703         // Disable the custom search engine.
704         searchEngineCustomActionPointer->setEnabled(false);
705
706         // Reset the custom search engine text.
707         searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
708     }
709 }
710
711 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
712 {
713     // Initialize the custom user agent flag.
714     bool customUserAgent = false;
715
716     // Check the indicated on-the-fly user agent.
717     if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT)  // Privacy Browser.
718     {
719         // Check the Privacy Browser user agent action.
720         userAgentPrivacyBrowserActionPointer->setChecked(true);
721
722         // Update the user agent menu action text.
723         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
724     }
725     else if (userAgent == BrowserView::webEngineDefaultUserAgent)  // WebEngine default.
726     {
727         // check the WebEngine default user agent action.
728         userAgentWebEngineDefaultActionPointer->setChecked(true);
729
730         // Update the user agent menu action text.
731         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
732     }
733     else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT)  // Firefox on Linux.
734     {
735         // Check the Firefox on Linux user agent action.
736         userAgentFirefoxLinuxActionPointer->setChecked(true);
737
738         // Update the user agent menu action text.
739         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
740     }
741     else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT)  // Chromium on Linux.
742     {
743         // Check the Chromium on Linux user agent action.
744         userAgentChromiumLinuxActionPointer->setChecked(true);
745
746         // Update the user agent menu action text.
747         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
748     }
749     else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT)  // Firefox on Windows.
750     {
751         // Check the Firefox on Windows user agent action.
752         userAgentFirefoxWindowsActionPointer->setChecked(true);
753
754         // Update the user agent menu action text.
755         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
756     }
757     else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT)  // Chrome on Windows.
758     {
759         // Check the Chrome on Windows user agent action.
760         userAgentChromeWindowsActionPointer->setChecked(true);
761
762         // Update the user agent menu action text.
763         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
764     }
765     else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT)  // Edge on Windows.
766     {
767         // Check the Edge on Windows user agent action.
768         userAgentEdgeWindowsActionPointer->setChecked(true);
769
770         // Update the user agent menu action text.
771         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
772     }
773     else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT)  // Safari on macOS.
774     {
775         // Check the Safari on macOS user agent action.
776         userAgentSafariMacosActionPointer->setChecked(true);
777
778         // Update the user agent menu action text.
779         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
780     }
781     else  // Custom user agent.
782     {
783         // Check the user agent.
784         userAgentCustomActionPointer->setChecked(true);
785
786         // Update the user agent menu action text.
787         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
788
789         // Set the custom user agent text.
790         userAgentCustomActionPointer->setText(userAgent);
791
792         // Set the custom user agent flag.
793         customUserAgent = true;
794     }
795
796     // Update the custom user agent enabled boolean.
797     if (updateCustomUserAgentStatus)
798         customUserAgentEnabled = customUserAgent;
799
800
801     // Format the custom user agent.
802     if (customUserAgentEnabled)
803     {
804         // Enable the custom user agent.
805         userAgentCustomActionPointer->setEnabled(true);
806     }
807     else
808     {
809         // Disable the custom user agent.
810         userAgentCustomActionPointer->setEnabled(false);
811
812         // Reset the custom user agent text.
813         userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
814     }
815 }
816
817 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
818 {
819     // Set the current zoom factor.
820     currentZoomFactor = zoomFactor;
821
822     // Update the zoom factor action text, formatting the double with 2 decimal places.
823     zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
824 }
825
826 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
827 {
828     // Update the search engine label.
829     searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
830 }
831
832 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
833 {
834     // Update the URL line edit if it does not have focus.
835     if (!urlLineEditPointer->hasFocus())
836     {
837         // Update the URL line edit.
838         urlLineEditPointer->setText(newUrl.toString());
839     }
840
841     // Store the current URL.
842     currentUrl = newUrl;
843 }
844
845 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
846 {
847     // Update the user agent label.
848     userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
849 }