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