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