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