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