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