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