]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/windows/BrowserWindow.cpp
716f2e0c58f57dea8d676a00c660ebf697ac58c1
[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 "dialogs/CookiesDialog.h"
26 #include "dialogs/DomainSettingsDialog.h"
27 #include "helpers/SearchEngineHelper.h"
28 #include "helpers/UserAgentHelper.h"
29
30 // KDE Frameworks headers.
31 #include <KActionCollection>
32 #include <KColorScheme>
33 #include <KToolBar>
34
35 // Qt toolkit headers.
36 #include <QFileDialog>
37 #include <QInputDialog>
38 #include <QNetworkCookie>
39 #include <QMenuBar>
40 #include <QShortcut>
41 #include <QStatusBar>
42 #include <QWebEngineFindTextResult>
43
44 // Construct the class.
45 BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
46 {
47     // Initialize the variables.
48     javaScriptEnabled = false;
49     localStorageEnabled = false;
50
51     // Instantiate the privacy tab widget pointer.
52     tabWidgetPointer = new TabWidget(this);
53
54     // Set the privacy tab widget as the central widget.
55     setCentralWidget(tabWidgetPointer);
56
57     // Get a handle for the action collection.
58     KActionCollection *actionCollectionPointer = this->actionCollection();
59
60     // Add the standard actions.
61     KStandardAction::openNew(this, SLOT(fileNew()), actionCollectionPointer);
62     KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
63     KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
64     KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
65     KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
66     fullScreenActionPointer = KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollectionPointer);
67     QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
68     QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
69     KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
70     KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollectionPointer);
71     KStandardAction::find(this, SLOT(focusFindLineEdit()), actionCollectionPointer);
72     QAction *findNextActionPointer = KStandardAction::findNext(this, SLOT(findNext()), actionCollectionPointer);
73     KStandardAction::findPrev(this, SLOT(findPrevious()), actionCollectionPointer);
74
75     // Add the custom actions.
76     userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_privacy_browser"));
77     userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_webengine_default"));
78     userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_firefox_linux"));
79     userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_chromium_linux"));
80     userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_firefox_windows"));
81     userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_chrome_windows"));
82     userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_edge_windows"));
83     userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_safari_macos"));
84     userAgentCustomActionPointer = actionCollectionPointer->addAction(QStringLiteral("user_agent_custom"));
85     zoomFactorActionPointer = actionCollectionPointer->addAction(QStringLiteral("zoom_factor"));
86     searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_mojeek"));
87     searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_monocles"));
88     searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_metager"));
89     searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_google"));
90     searchEngineBingActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_bing"));
91     searchEngineYahooActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_yahoo"));
92     searchEngineCustomActionPointer = actionCollectionPointer->addAction(QStringLiteral("search_engine_custom"));
93     QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QStringLiteral("domain_settings"));
94     cookiesActionPointer = actionCollectionPointer->addAction(QStringLiteral("cookies"));
95     javaScriptActionPointer = actionCollectionPointer->addAction(QStringLiteral("javascript"));
96     localStorageActionPointer = actionCollectionPointer->addAction(QStringLiteral("local_storage"));
97     domStorageActionPointer = actionCollectionPointer->addAction(QStringLiteral("dom_storage"));
98     findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QStringLiteral("find_case_sensitive"));
99
100     // Create the action groups
101     QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
102     QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
103
104     // Add the actions to the groups.
105     userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
106     userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
107     userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
108     userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
109     userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
110     userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
111     userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
112     userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
113     userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
114     searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
115     searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
116     searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
117     searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
118     searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
119     searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
120     searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
121
122     // Set some actions to be checkable.
123     javaScriptActionPointer->setCheckable(true);
124     localStorageActionPointer->setCheckable(true);
125     domStorageActionPointer->setCheckable(true);
126     findCaseSensitiveActionPointer->setCheckable(true);
127     userAgentPrivacyBrowserActionPointer->setCheckable(true);
128     userAgentWebEngineDefaultActionPointer->setCheckable(true);
129     userAgentFirefoxLinuxActionPointer->setCheckable(true);
130     userAgentChromiumLinuxActionPointer->setCheckable(true);
131     userAgentFirefoxWindowsActionPointer->setCheckable(true);
132     userAgentChromeWindowsActionPointer->setCheckable(true);
133     userAgentEdgeWindowsActionPointer->setCheckable(true);
134     userAgentSafariMacosActionPointer->setCheckable(true);
135     userAgentCustomActionPointer->setCheckable(true);
136     searchEngineMojeekActionPointer->setCheckable(true);
137     searchEngineMonoclesActionPointer->setCheckable(true);
138     searchEngineMetagerActionPointer->setCheckable(true);
139     searchEngineGoogleActionPointer->setCheckable(true);
140     searchEngineBingActionPointer->setCheckable(true);
141     searchEngineYahooActionPointer->setCheckable(true);
142     searchEngineCustomActionPointer->setCheckable(true);
143
144     // Set the action text.
145     userAgentPrivacyBrowserActionPointer->setText(UserAgentHelper::PRIVACY_BROWSER_TRANSLATED);
146     userAgentWebEngineDefaultActionPointer->setText(UserAgentHelper::WEB_ENGINE_DEFAULT_TRANSLATED);
147     userAgentFirefoxLinuxActionPointer->setText(UserAgentHelper::FIREFOX_LINUX_TRANSLATED);
148     userAgentChromiumLinuxActionPointer->setText(UserAgentHelper::CHROMIUM_LINUX_TRANSLATED);
149     userAgentFirefoxWindowsActionPointer->setText(UserAgentHelper::FIREFOX_WINDOWS_TRANSLATED);
150     userAgentChromeWindowsActionPointer->setText(UserAgentHelper::CHROME_WINDOWS_TRANSLATED);
151     userAgentEdgeWindowsActionPointer->setText(UserAgentHelper::EDGE_WINDOWS_TRANSLATED);
152     userAgentSafariMacosActionPointer->setText(UserAgentHelper::SAFARI_MACOS_TRANSLATED);
153     searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
154     searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
155     searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
156     searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
157     searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
158     searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
159     domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
160     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
161     javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
162     localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
163     domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
164     findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
165
166     // Set the action icons.
167     userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode"));
168     userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
169     userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("firefox-esr")));
170     userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("chromium")));
171     userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("firefox-esr")));
172     userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("chromium")));
173     userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
174     userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
175     userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("user-group-properties")));
176     searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
177     searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
178     searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
179     searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("im-google")));
180     searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
181     searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("im-yahoo")));
182     searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("search")));
183     zoomFactorActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("zoom")));
184     domainSettingsActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("settings-configure")));
185     cookiesActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("preferences-web-browser-cookies")));
186     domStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("code-class")));
187     findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("format-text-lowercase")));
188
189     // Update the on-the-fly menus.
190     connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
191     connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
192     connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
193
194     // Apply the on-the-fly settings when selected.
195     connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
196     connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
197
198     // Process cookie changes.
199     connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
200
201     // Display dialogs.
202     connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
203     connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
204     connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
205
206     // Connect the URL toolbar actions.
207     connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
208     connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
209     connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
210
211     // Update the URL toolbar actions.
212     connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
213     connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
214     connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
215     connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
216     connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
217
218     // Connect the find text actions.
219     connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
220
221     // Setup the GUI based on the browser_window_ui.rc file.
222     setupGUI(StandardWindowOption::Default, ("browser_window_ui.rc"));
223
224     // Get lists of the actions' associated widgets.
225     QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
226     QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
227
228     // Get the menu widget pointers.  It is the second entry, after the main window.
229     QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
230     QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
231
232     // Get the menu pointers.
233     QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
234     QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
235
236     // Get the menu actions.
237     userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
238     searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
239
240     // Get handles for the toolbars.
241     navigationToolBarPointer = toolBar(QStringLiteral("navigation_toolbar"));
242     urlToolBarPointer = toolBar(QStringLiteral("url_toolbar"));
243
244     // Create the line edits.
245     urlLineEditPointer = new KLineEdit();
246     findTextLineEditPointer = new KLineEdit();
247
248     // Get the line edit size policies.
249     QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
250     QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
251
252     // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
253     urlLineEditSizePolicy.setHorizontalStretch(5);
254     findTextLineEditSizePolicy.setHorizontalStretch(1);
255
256     // Set the policies.
257     urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
258     findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
259
260     // Set the widths.
261     urlLineEditPointer->setMinimumWidth(350);
262     findTextLineEditPointer->setMinimumWidth(200);
263     findTextLineEditPointer->setMaximumWidth(350);
264
265     // Set the placehold text.
266     urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
267     findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
268
269     // Show the clear button on the find line edit.
270     findTextLineEditPointer->setClearButtonEnabled(true);
271
272     // Add an edit or add domain settings action to the URL line edit.
273     QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure"), QLineEdit::TrailingPosition);
274
275     // Add or edit the current domain settings.
276     connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
277
278     // Create a find text label pointer.
279     findTextLabelPointer = new QLabel();
280
281     // Set the default label text.
282     findTextLabelPointer->setText(QStringLiteral("  ") + i18nc("Default find results.", "0/0") + QStringLiteral("  "));
283
284     // Insert the widgets into the toolbars.
285     urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
286     urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
287     urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
288
289     // Load a new URL from the URL line edit.
290     connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
291
292     // Find text as it is typed.
293     connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
294
295     // Find next if the enter key is pressed.
296     connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
297
298     // Update find text when switching tabs.
299     connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
300
301     // Update the find text results.
302     connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
303
304     // Update the URL line edit on page loads.
305     connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
306
307     // Update the window title.
308     connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
309
310     // Get a handle for the status bar.
311     QStatusBar *statusBarPointer = statusBar();
312
313     // Create a progress bar.
314     progressBarPointer = new QProgressBar();
315
316     // Add the progress bar to to the status bar.
317     statusBarPointer->addPermanentWidget(progressBarPointer);
318
319     // Update the status bar with the URL when a link is hovered.
320     connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
321
322     // Update the progress bar.
323     connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
324     connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
325
326     // Update the URL line edit focus.
327     connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
328
329     // Get the URL line edit palettes.
330     normalBackgroundPalette = urlLineEditPointer->palette();
331     negativeBackgroundPalette = normalBackgroundPalette;
332     positiveBackgroundPalette = normalBackgroundPalette;
333
334     // Modify the palettes.
335     KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
336     KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
337
338     // Update the applied palette.
339     connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
340
341     // Process full screen requests.
342     connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
343
344     // Create keyboard shortcuts.
345     QShortcut *ctrlTShortcutPointer = new QShortcut(QKeySequence(i18nc("The open new tab shortcut.", "Ctrl+t")), this);
346     QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
347     QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
348
349     // Connect the keyboard shortcuts to the actions.
350     connect(ctrlTShortcutPointer, SIGNAL(activated()), tabWidgetPointer, SLOT(addTab()));
351     connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
352     connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
353
354     // Load the initial website if this is the first window.
355     if (firstWindow)
356         tabWidgetPointer->loadInitialWebsite();
357 }
358
359 void BrowserWindow::addOrEditDomainSettings() const
360 {
361     // Remove the focus from the URL line edit.
362     urlLineEditPointer->clearFocus();
363
364     // Create the domain settings dialog pointer.
365     DomainSettingsDialog *domainSettingsDialogPointer;
366
367     // Get the current domain settings name.
368     QString &currentDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
369
370     // Run the commands according to the current domain settings status.
371     if (currentDomainSettingsName == QStringLiteral(""))  // Domain settings are not currently applied.
372     {
373         // Instruct the domain settings dialog to add a new domain.
374         domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
375     }
376     else  // Domain settings are currently applied.
377     {
378         // Instruct the domain settings dialog to edit the current domain.
379         domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
380     }
381
382     // Set the dialog window title.
383     domainSettingsDialogPointer->setWindowTitle(i18nc("The domain settings dialog title", "Domain Settings"));
384
385     // Set the modality.
386     domainSettingsDialogPointer->setWindowModality(Qt::WindowModality::WindowModal);;
387
388     // Show the dialog.
389     domainSettingsDialogPointer->show();
390
391     // Reload the tabs when domain settings are updated.
392     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
393 }
394
395 void BrowserWindow::back() const
396 {
397     // Remove the focus from the URL line edit.
398     urlLineEditPointer->clearFocus();
399
400     // Go back.
401     tabWidgetPointer->back();
402 }
403
404 void BrowserWindow::clearUrlLineEditFocus() const
405 {
406     // Remove the focus from the URL line edit.
407     urlLineEditPointer->clearFocus();
408 }
409
410 void BrowserWindow::escape() const
411 {
412     // Process the excape according to the status of the browser.
413     if (fullScreenActionPointer->isChecked())  // Full screen browsing is enabled.
414     {
415         // Exit full screen browsing.
416         fullScreenActionPointer->trigger();
417     }
418     else if (!findTextLineEditPointer->text().isEmpty())  // Find text is activated.
419     {
420         // Clear the text in the line edit.
421         findTextLineEditPointer->clear();
422
423         // Clear the search in the WebEngine.
424         tabWidgetPointer->findText(QStringLiteral(""));
425     }
426 }
427
428 void BrowserWindow::fileNew() const
429 {
430     // Display a new instance of Privacy Browser.
431     (new BrowserWindow)->show();
432 }
433
434 void BrowserWindow::findNext() const
435 {
436     // Get the find string.
437     const QString findString = findTextLineEditPointer->text();
438
439     // Search for the text if it is not empty.
440     if (!findString.isEmpty())
441         tabWidgetPointer->findText(findString);
442 }
443
444 void BrowserWindow::findPrevious() const
445 {
446     // Get the find string.
447     const QString findString = findTextLineEditPointer->text();
448
449     // Search for the text if it is not empty.
450     if (!findString.isEmpty())
451         tabWidgetPointer->findPrevious(findString);
452 }
453
454 void BrowserWindow::focusFindLineEdit() const
455 {
456     // Set the focus on the find line edit.
457     findTextLineEditPointer->setFocus();
458
459     // Select all the text in the find line edit.
460     findTextLineEditPointer->selectAll();
461 }
462
463 void BrowserWindow::forward() const
464 {
465     // Remove the focus from the URL line edit.
466     urlLineEditPointer->clearFocus();
467
468     // Go forward.
469     tabWidgetPointer->forward();
470 }
471
472 void BrowserWindow::fullScreenRequested(const bool toggleOn)
473 {
474     // Toggle full screen mode.
475     if (toggleOn)  // Turn full screen mode on.
476     {
477         // Set the window to be full screen.
478         fullScreenActionPointer->setFullScreen(window(), true);
479
480         // Hide all the bars.
481         menuBar()->setVisible(false);
482         navigationToolBarPointer->setVisible(false);
483         urlToolBarPointer->setVisible(false);
484         tabWidgetPointer->setTabBarVisible(false);
485         statusBar()->setVisible(false);
486     }
487     else  // Turn full screen mode off.
488     {
489         // Set the window to not be full screen.
490         fullScreenActionPointer->setFullScreen(window(), false);
491
492         // Show all the bars.
493         menuBar()->setVisible(true);
494         navigationToolBarPointer->setVisible(true);
495         urlToolBarPointer->setVisible(true);
496         tabWidgetPointer->setTabBarVisible(true);
497         statusBar()->setVisible(true);
498     }
499 }
500
501 void BrowserWindow::getZoomFactorFromUser()
502 {
503     // Create an OK flag.
504     bool okClicked;
505
506     // 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.
507     double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
508                                                    i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
509                                                    currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
510
511     // Update the zoom factor if the user clicked OK.
512     if (okClicked)
513     {
514         // Update the current zoom factor.
515         currentZoomFactor = newZoomFactor;
516
517         // Set the new zoom factor.
518         tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
519
520         // Update the on-the-fly action text.
521         updateZoomFactorAction(newZoomFactor);
522     }
523 }
524
525 void BrowserWindow::home() const
526 {
527     // Remove the focus from the URL line edit.
528     urlLineEditPointer->clearFocus();
529
530     // Go home.
531     tabWidgetPointer->home();
532 }
533
534 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
535 {
536     // Remove the focus from the URL line edit.
537     urlLineEditPointer->clearFocus();
538
539     // Load the URL.
540     tabWidgetPointer->loadUrlFromLineEdit(url);
541 }
542
543 void BrowserWindow::refresh() const
544 {
545     // Remove the focus from the URL line edit.
546     urlLineEditPointer->clearFocus();
547
548     // Refresh the web page.
549     tabWidgetPointer->refresh();
550 }
551
552 void BrowserWindow::showCookiesDialog()
553 {
554     // Remove the focus from the URL line edit.
555     urlLineEditPointer->clearFocus();
556
557     // Instantiate the cookie settings dialog.
558     CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
559
560     // Show the dialog.
561     cookiesDialogPointer->show();
562
563     // Connect the dialog signals.
564     connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
565     connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
566     connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
567 }
568
569 void BrowserWindow::showDownloadLocationBrowseDialog() const
570 {
571     // Get the current download location.
572     QString currentDownloadLocation = downloadLocationComboBoxPointer->currentText();
573
574     // Resolve the system download directory if specified.
575     if (currentDownloadLocation == QStringLiteral("System Download Directory"))
576         currentDownloadLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
577
578     // Get the new download location.
579     QString newDownloadLocation = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download location dialog caption", "Select Download Location"), currentDownloadLocation);
580
581     // Populate the download location combo box according to the new download location.
582     if (newDownloadLocation == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))  // The default download location was selected.
583     {
584         // Populate the download location with the default text.
585         downloadLocationComboBoxPointer->setCurrentText("System Download Directory");
586     }
587     else if (newDownloadLocation != QStringLiteral(""))  // A different directory was selected.
588     {
589         // Populate the download location.
590         downloadLocationComboBoxPointer->setCurrentText(newDownloadLocation);
591     }
592 }
593
594 void BrowserWindow::showDomainSettingsDialog() const
595 {
596     // Remove the focus from the URL line edit.
597     urlLineEditPointer->clearFocus();
598
599     // Instantiate the domain settings dialog.
600     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
601
602     // Show the dialog.
603     domainSettingsDialogPointer->show();
604
605     // Reload the tabs when domain settings are updated.
606     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
607 }
608
609 void BrowserWindow::showProgressBar(const int &progress) const
610 {
611     // Set the progress bar value.
612     progressBarPointer->setValue(progress);
613
614     // Show the progress bar.
615     progressBarPointer->show();
616 }
617
618 void BrowserWindow::showSettingsDialog()
619 {
620     // Create the settings widgets.
621     QWidget *privacySettingsWidgetPointer = new QWidget;
622     QWidget *generalSettingsWidgetPointer = new QWidget;
623
624     // Instantiate the settings UI.
625     Ui::PrivacySettings privacySettingsUi;
626     Ui::GeneralSettings generalSettingsUi;
627
628     // Setup the UI to display the settings widgets.
629     privacySettingsUi.setupUi(privacySettingsWidgetPointer);
630     generalSettingsUi.setupUi(generalSettingsWidgetPointer);
631
632     // Get handles for the widgets.
633     QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
634     userAgentLabelPointer = privacySettingsUi.userAgentLabel;
635     QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
636     searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
637     downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
638     QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
639
640     // Populate the combo box labels.
641     updateUserAgentLabel(userAgentComboBoxPointer->currentText());
642     updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
643
644     // Update the labels when the combo boxes change.
645     connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
646     connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
647
648     // Connect the download location directory browse button.
649     connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
650
651     // Instantiate a settings config dialog from the settings.kcfg file.
652     configDialogPointer = new KConfigDialog(this, QStringLiteral("settings"), Settings::self());
653
654     // Add the settings widgets as config dialog pages.
655     configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("@title:tab", "Privacy"), QStringLiteral("privacy-browser"));
656     configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("@title:tab", "General"), QStringLiteral("breeze-settings"));
657
658     // Prevent interaction with the parent window while the dialog is open.
659     configDialogPointer->setWindowModality(Qt::WindowModal);
660
661     // Make it so.
662     configDialogPointer->show();
663
664     // TODO.  KConfigDialog does not respect expanding size policies.  <https://redmine.stoutner.com/issues/823>
665     //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
666     //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
667     //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
668     //configDialogPointer->adjustSize();
669
670     // Expand the config dialog.
671     configDialogPointer->resize(1000, 500);
672
673     // Apply the settings when they are updated.
674     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
675     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
676 }
677
678 QSize BrowserWindow::sizeHint() const
679 {
680     // Return the default window size.
681     return QSize(1500, 1200);
682 }
683
684 void BrowserWindow::toggleDomStorage() const
685 {
686     // Remove the focus from the URL line edit.
687     urlLineEditPointer->clearFocus();
688
689     // Toggle DOM storage.
690     tabWidgetPointer->toggleDomStorage();
691 }
692
693 void BrowserWindow::toggleFindCaseSensitive() const
694 {
695     // Get the current find string.
696     const QString findString = findTextLineEditPointer->text();
697
698     // Toggle find case sensitive.
699     tabWidgetPointer->toggleFindCaseSensitive(findString);
700 }
701
702 void BrowserWindow::toggleJavaScript() const
703 {
704     // Remove the focus from the URL line edit.
705     urlLineEditPointer->clearFocus();
706
707     // Toggle JavaScript.
708     tabWidgetPointer->toggleJavaScript();
709 }
710
711 void BrowserWindow::toggleLocalStorage() const
712 {
713     // Remove the focus from the URL line edit.
714     urlLineEditPointer->clearFocus();
715
716     // Toggle local storage.
717     tabWidgetPointer->toggleLocalStorage();
718 }
719
720 void BrowserWindow::toggleFullScreen()
721 {
722     // Toggle the full screen status.
723     if (fullScreenActionPointer->isChecked())  // Enable full screen browsing mode.
724     {
725         // Enable full screen mode.
726         fullScreenActionPointer->setFullScreen(window(), true);
727
728         // Hide the menu bar if specified.
729         if (Settings::fullScreenHideMenuBar())
730             menuBar()->setVisible(false);
731
732         // Hide the toolbars if specified.
733         if (Settings::fullScreenHideToolBars())
734         {
735             navigationToolBarPointer->setVisible(false);
736             urlToolBarPointer->setVisible(false);
737         }
738
739         // Hide the tab bar if specified.
740         if (Settings::fullScreenHideTabBar())
741             tabWidgetPointer->setTabBarVisible(false);
742
743         // Hide the status bar if specified.
744         if (Settings::fullScreenHideStatusBar())
745             statusBar()->setVisible(false);
746     }
747     else  // Disable full screen browsing mode.
748     {
749         // Disable full screen mode.
750         fullScreenActionPointer->setFullScreen(window(), false);
751
752         // Show the menu bar.
753         menuBar()->setVisible(true);
754
755         // Show the toolbars.
756         navigationToolBarPointer->setVisible(true);
757         urlToolBarPointer->setVisible(true);
758
759         // Show the tab bar.
760         tabWidgetPointer->setTabBarVisible(true);
761
762         // Show the status bar.
763         statusBar()->setVisible(true);
764     }
765 }
766
767 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
768 {
769     // Update the action text.
770     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
771 }
772
773 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
774 {
775     // Set the action checked status.
776     domStorageActionPointer->setChecked(isEnabled);
777 }
778
779 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
780 {
781     // Set the domain palette according to the status.
782     if (status)
783         urlLineEditPointer->setPalette(positiveBackgroundPalette);
784     else
785         urlLineEditPointer->setPalette(normalBackgroundPalette);
786 }
787
788 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
789 {
790     // Set the text.
791     findTextLineEditPointer->setText(text);
792
793     // Set the find case sensitive action checked status.
794     findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
795 }
796
797 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
798 {
799     // Update the find text label.
800     findTextLabelPointer->setText(QStringLiteral("  %1/%2  ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
801
802     // Set the background color according to the find status.
803     if (findTextLineEditPointer->text().isEmpty())
804         findTextLineEditPointer->setPalette(normalBackgroundPalette);
805     else if (findTextResult.numberOfMatches() == 0)
806         findTextLineEditPointer->setPalette(negativeBackgroundPalette);
807     else
808         findTextLineEditPointer->setPalette(positiveBackgroundPalette);
809 }
810
811 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
812 {
813     // Update the JavaScript status.
814     javaScriptEnabled = isEnabled;
815
816     // Set the icon according to the status.
817     if (javaScriptEnabled)
818         javaScriptActionPointer->setIcon(QIcon(QStringLiteral(":/icons/javascript-warning")));
819     else
820         javaScriptActionPointer->setIcon(QIcon(QStringLiteral(":/icons/privacy-mode")));
821
822     // Set the action checked status.
823     javaScriptActionPointer->setChecked(javaScriptEnabled);
824
825     // Update the status of the DOM storage action.
826     domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
827 }
828
829 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
830 {
831     // Update the local storage status.
832     localStorageEnabled = isEnabled;
833
834     // Update the icon.
835     if (localStorageEnabled)
836         localStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("disk-quota-high")));
837     else
838         localStorageActionPointer->setIcon(QIcon::fromTheme(QStringLiteral("disk-quota")));
839
840     // Set the action checked status.
841     localStorageActionPointer->setChecked(localStorageEnabled);
842
843     // Update the status of the DOM storage action.
844     domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
845 }
846
847 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
848 {
849     // Initialize the custom search engine flag.
850     bool customSearchEngine = false;
851
852     if (searchEngine == "Mojeek")  // Mojeek.
853     {
854         // Check the Mojeek user agent action.
855         searchEngineMojeekActionPointer->setChecked(true);
856
857         // Update the search engine menu action text.
858         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
859     }
860     else if (searchEngine == "Monocles")  // Monocles.
861     {
862         // Check the Monocles user agent action.
863         searchEngineMonoclesActionPointer->setChecked(true);
864
865         // Update the search engine menu action text.
866         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
867     }
868     else if (searchEngine == "MetaGer")  // MetaGer.
869     {
870         // Check the MetaGer user agent action.
871         searchEngineMetagerActionPointer->setChecked(true);
872
873         // Update the search engine menu action text.
874         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
875     }
876     else if (searchEngine == "Google")  // Google.
877     {
878         // Check the Google user agent action.
879         searchEngineGoogleActionPointer->setChecked(true);
880
881         // Update the search engine menu action text.
882         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
883     }
884     else if (searchEngine == "Bing")  // Bing.
885     {
886         // Check the Bing user agent action.
887         searchEngineBingActionPointer->setChecked(true);
888
889         // Update the search engine menu action text.
890         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
891     }
892     else if (searchEngine == "Yahoo")  // Yahoo.
893     {
894         // Check the Yahoo user agent action.
895         searchEngineYahooActionPointer->setChecked(true);
896
897         // Update the search engine menu action text.
898         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
899     }
900     else  // Custom search engine.
901     {
902         // Check the user agent.
903         searchEngineCustomActionPointer->setChecked(true);
904
905         // Update the search engine menu action text.
906         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
907
908         // Set the custom search engine text.
909         searchEngineCustomActionPointer->setText(searchEngine);
910
911         // Set the custom search engine flag.
912         customSearchEngine = true;
913     }
914
915     // Update the custom search engine enabled boolean.
916     if (updateCustomSearchEngineStatus)
917         customSearchEngineEnabled = customSearchEngine;
918
919     // Format the custom search engine.
920     if (customSearchEngineEnabled)
921     {
922         // Enable the custom search engine.
923         searchEngineCustomActionPointer->setEnabled(true);
924     }
925     else
926     {
927         // Disable the custom search engine.
928         searchEngineCustomActionPointer->setEnabled(false);
929
930         // Reset the custom search engine text.
931         searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
932     }
933 }
934
935 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
936 {
937     // Initialize the custom user agent flag.
938     bool customUserAgent = false;
939
940     // Check the indicated on-the-fly user agent.
941     if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT)  // Privacy Browser.
942     {
943         // Check the Privacy Browser user agent action.
944         userAgentPrivacyBrowserActionPointer->setChecked(true);
945
946         // Update the user agent menu action text.
947         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
948     }
949     else if (userAgent == TabWidget::webEngineDefaultUserAgent)  // WebEngine default.
950     {
951         // check the WebEngine default user agent action.
952         userAgentWebEngineDefaultActionPointer->setChecked(true);
953
954         // Update the user agent menu action text.
955         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
956     }
957     else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT)  // Firefox on Linux.
958     {
959         // Check the Firefox on Linux user agent action.
960         userAgentFirefoxLinuxActionPointer->setChecked(true);
961
962         // Update the user agent menu action text.
963         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
964     }
965     else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT)  // Chromium on Linux.
966     {
967         // Check the Chromium on Linux user agent action.
968         userAgentChromiumLinuxActionPointer->setChecked(true);
969
970         // Update the user agent menu action text.
971         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
972     }
973     else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT)  // Firefox on Windows.
974     {
975         // Check the Firefox on Windows user agent action.
976         userAgentFirefoxWindowsActionPointer->setChecked(true);
977
978         // Update the user agent menu action text.
979         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
980     }
981     else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT)  // Chrome on Windows.
982     {
983         // Check the Chrome on Windows user agent action.
984         userAgentChromeWindowsActionPointer->setChecked(true);
985
986         // Update the user agent menu action text.
987         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
988     }
989     else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT)  // Edge on Windows.
990     {
991         // Check the Edge on Windows user agent action.
992         userAgentEdgeWindowsActionPointer->setChecked(true);
993
994         // Update the user agent menu action text.
995         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
996     }
997     else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT)  // Safari on macOS.
998     {
999         // Check the Safari on macOS user agent action.
1000         userAgentSafariMacosActionPointer->setChecked(true);
1001
1002         // Update the user agent menu action text.
1003         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
1004     }
1005     else  // Custom user agent.
1006     {
1007         // Check the user agent.
1008         userAgentCustomActionPointer->setChecked(true);
1009
1010         // Update the user agent menu action text.
1011         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
1012
1013         // Set the custom user agent text.
1014         userAgentCustomActionPointer->setText(userAgent);
1015
1016         // Set the custom user agent flag.
1017         customUserAgent = true;
1018     }
1019
1020     // Update the custom user agent enabled boolean.
1021     if (updateCustomUserAgentStatus)
1022         customUserAgentEnabled = customUserAgent;
1023
1024
1025     // Format the custom user agent.
1026     if (customUserAgentEnabled)
1027     {
1028         // Enable the custom user agent.
1029         userAgentCustomActionPointer->setEnabled(true);
1030     }
1031     else
1032     {
1033         // Disable the custom user agent.
1034         userAgentCustomActionPointer->setEnabled(false);
1035
1036         // Reset the custom user agent text.
1037         userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
1038     }
1039 }
1040
1041 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
1042 {
1043     // Set the current zoom factor.
1044     currentZoomFactor = zoomFactor;
1045
1046     // Update the zoom factor action text, formatting the double with 2 decimal places.
1047     zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
1048 }
1049
1050 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
1051 {
1052     // Update the search engine label.
1053     searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
1054 }
1055
1056 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1057 {
1058     // Update the URL line edit if it does not have focus.
1059     if (!urlLineEditPointer->hasFocus())
1060     {
1061         // Get the new URL string.
1062         QString newUrlString = newUrl.toString();
1063
1064         // Update the URL line edit.
1065         urlLineEditPointer->setText(newUrlString);
1066
1067         // Set the focus if the new URL is blank.
1068         if (newUrlString == QStringLiteral(""))
1069             urlLineEditPointer->setFocus();
1070     }
1071
1072     // Store the current URL.
1073     currentUrl = newUrl;
1074 }
1075
1076 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
1077 {
1078     // Update the user agent label.
1079     userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
1080 }
1081
1082 void BrowserWindow::updateWindowTitle(const QString &title)
1083 {
1084     // Update the window title.
1085     setWindowTitle(title);
1086 }