]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/windows/BrowserWindow.cpp
Add a default folder icon to the edit folder dialog. https://redmine.stoutner.com...
[PrivacyBrowserPC.git] / src / windows / BrowserWindow.cpp
1 /*
2  * Copyright 2022-2024 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 "databases/BookmarksDatabase.h"
24 #include "databases/DomainsDatabase.h"
25 #include "dialogs/AddBookmarkDialog.h"
26 #include "dialogs/AddFolderDialog.h"
27 #include "dialogs/BookmarksDialog.h"
28 #include "dialogs/CookiesDialog.h"
29 #include "dialogs/DomainSettingsDialog.h"
30 #include "dialogs/EditBookmarkDialog.h"
31 #include "dialogs/EditFolderDialog.h"
32 #include "dialogs/SettingsDialog.h"
33 #include "helpers/SearchEngineHelper.h"
34 #include "helpers/UserAgentHelper.h"
35 #include "structs/BookmarkStruct.h"
36
37 // KDE Frameworks headers.
38 #include <KActionCollection>
39 #include <KColorScheme>
40 #include <KLocalizedString>
41 #include <KXMLGUIFactory>
42
43 // Qt toolkit headers.
44 #include <QClipboard>
45 #include <QContextMenuEvent>
46 #include <QDBusConnection>
47 #include <QDBusConnectionInterface>
48 #include <QDBusMessage>
49 #include <QGuiApplication>
50 #include <QInputDialog>
51 #include <QLayout>
52 #include <QNetworkCookie>
53 #include <QMenuBar>
54 #include <QMessageBox>
55 #include <QShortcut>
56 #include <QStatusBar>
57 #include <QWebEngineFindTextResult>
58
59 // Construct the class.
60 BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer) : KXmlGuiWindow()
61 {
62     // Initialize the variables.
63     javaScriptEnabled = false;
64     localStorageEnabled = false;
65
66     // Instantiate the privacy tab widget pointer.
67     tabWidgetPointer = new TabWidget(this);
68
69     // Set the privacy tab widget as the central widget.
70     setCentralWidget(tabWidgetPointer);
71
72     // Get a handle for the action collection.
73     actionCollectionPointer = this->actionCollection();
74
75     // Add the standard actions.
76     KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
77     QAction *printPreviewActionPointer = KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
78     KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
79     zoomInActionPointer = KStandardAction::zoomIn(this, SLOT(incrementZoom()), actionCollectionPointer);
80     zoomOutActionPointer = KStandardAction::zoomOut(this, SLOT(decrementZoom()), actionCollectionPointer);
81     refreshActionPointer = KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
82     fullScreenActionPointer = KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollectionPointer);
83     QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
84     QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
85     KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
86     QAction *editBookmarksActionPointer = KStandardAction::editBookmarks(this, SLOT(editBookmarks()), actionCollectionPointer);
87     KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollectionPointer);
88     KStandardAction::find(this, SLOT(showFindTextActions()), actionCollectionPointer);
89     findNextActionPointer = KStandardAction::findNext(this, SLOT(findNext()), actionCollectionPointer);
90     findPreviousActionPointer = KStandardAction::findPrev(this, SLOT(findPrevious()), actionCollectionPointer);
91
92     // Add the custom actions.
93     QAction *newTabActionPointer = actionCollectionPointer->addAction(QLatin1String("new_tab"));
94     QAction *newWindowActionPointer = actionCollectionPointer->addAction(QLatin1String("new_window"));
95     QAction *saveArchiveActionPointer = actionCollectionPointer->addAction(QLatin1String("save_archive"));
96     zoomDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_default"));
97     QAction *reloadAndBypassCacheActionPointer = actionCollectionPointer->addAction(QLatin1String("reload_and_bypass_cache"));
98     stopActionPointer = actionCollectionPointer->addAction(QLatin1String("stop"));
99     viewSourceActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source"));
100     viewSourceInNewTabActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source_in_new_tab"));
101     developerToolsActionPointer = actionCollectionPointer->addAction(QLatin1String("developer_tools"));
102     javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
103     localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
104     domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
105     userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
106     userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
107     userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
108     userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chromium_linux"));
109     userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_windows"));
110     userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chrome_windows"));
111     userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_edge_windows"));
112     userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_safari_macos"));
113     userAgentCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_custom"));
114     zoomFactorActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_factor"));
115     searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_mojeek"));
116     searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_monocles"));
117     searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_metager"));
118     searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_google"));
119     searchEngineBingActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_bing"));
120     searchEngineYahooActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_yahoo"));
121     searchEngineCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_custom"));
122     viewBookmarksToolBarActionPointer = actionCollectionPointer->addAction(QLatin1String("view_bookmarks_toolbar"));
123     QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QLatin1String("domain_settings"));
124     cookiesActionPointer = actionCollectionPointer->addAction(QLatin1String("cookies"));
125     findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QLatin1String("find_case_sensitive"));
126     hideFindTextActionPointer = actionCollectionPointer->addAction(QLatin1String("hide_find_actions"));
127
128     // Create the action groups
129     QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
130     QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
131
132     // Add the actions to the groups.
133     userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
134     userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
135     userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
136     userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
137     userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
138     userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
139     userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
140     userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
141     userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
142     searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
143     searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
144     searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
145     searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
146     searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
147     searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
148     searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
149
150     // Set some actions to be checkable.
151     javaScriptActionPointer->setCheckable(true);
152     localStorageActionPointer->setCheckable(true);
153     domStorageActionPointer->setCheckable(true);
154     findCaseSensitiveActionPointer->setCheckable(true);
155     viewSourceActionPointer->setCheckable(true);
156     developerToolsActionPointer->setCheckable(true);
157     userAgentPrivacyBrowserActionPointer->setCheckable(true);
158     userAgentWebEngineDefaultActionPointer->setCheckable(true);
159     userAgentFirefoxLinuxActionPointer->setCheckable(true);
160     userAgentChromiumLinuxActionPointer->setCheckable(true);
161     userAgentFirefoxWindowsActionPointer->setCheckable(true);
162     userAgentChromeWindowsActionPointer->setCheckable(true);
163     userAgentEdgeWindowsActionPointer->setCheckable(true);
164     userAgentSafariMacosActionPointer->setCheckable(true);
165     userAgentCustomActionPointer->setCheckable(true);
166     searchEngineMojeekActionPointer->setCheckable(true);
167     searchEngineMonoclesActionPointer->setCheckable(true);
168     searchEngineMetagerActionPointer->setCheckable(true);
169     searchEngineGoogleActionPointer->setCheckable(true);
170     searchEngineBingActionPointer->setCheckable(true);
171     searchEngineYahooActionPointer->setCheckable(true);
172     searchEngineCustomActionPointer->setCheckable(true);
173     viewBookmarksToolBarActionPointer->setCheckable(true);
174
175     // Instantiate the user agent helper.
176     UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
177
178     // Set the action text.
179     newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
180     newWindowActionPointer->setText(i18nc("New window action", "New Window"));
181     saveArchiveActionPointer->setText(i18nc("Save archive action", "Save Archive"));
182     zoomDefaultActionPointer->setText(i18nc("Zoom default action", "Zoom Default"));
183     reloadAndBypassCacheActionPointer->setText(i18nc("Reload and bypass cache action", "Reload and Bypass Cache"));
184     stopActionPointer->setText(i18nc("Stop action", "Stop"));
185     viewSourceActionPointer->setText(i18nc("View source action", "View Source"));
186     viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
187     developerToolsActionPointer->setText(i18nc("Developer tools action", "Developer Tools"));
188     javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
189     localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
190     domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
191     userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
192     userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
193     userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
194     userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
195     userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
196     userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
197     userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
198     userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
199     searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
200     searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
201     searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
202     searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
203     searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
204     searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
205     viewBookmarksToolBarActionPointer->setText(i18nc("View bookmarks toolbar", "View Bookmarks Toolbar"));
206     domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
207     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
208     findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
209     hideFindTextActionPointer->setText(i18nc("Hide Find Text action (the text should include the language-specific escape keyboard shortcut).", "Hide Find Text (Esc)"));
210
211     // Set the action icons.  Gnome doesn't contain some of the icons that KDE has.
212     // The toolbar icons don't pick up unless the size is explicit, probably because the toolbar ends up being an intermediate size.
213     newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
214     newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
215     saveArchiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("document-save")));
216     zoomDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
217     reloadAndBypassCacheActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
218     stopActionPointer->setIcon(QIcon::fromTheme(QLatin1String("process-stop")));
219     viewSourceActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
220     viewSourceInNewTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
221     developerToolsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("add-subtitle"), QIcon::fromTheme("system-run")));
222     domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
223     userAgentPrivacyBrowserActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
224     userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"),
225                                                                                                                QIcon::fromTheme(QLatin1String("contact-new")))));
226     userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
227                                                                                                                 QIcon::fromTheme(QLatin1String("contact-new")))));
228     userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
229     userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
230                                                                                                                   QIcon::fromTheme(QLatin1String("contact-new")))));
231     userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
232     userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
233     userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
234     userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
235     searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
236     searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
237     searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
238     searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
239     searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
240     searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
241     searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
242     zoomFactorActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
243     editBookmarksActionPointer->setIcon(QIcon::fromTheme(QLatin1String("bookmark-edit"), QIcon::fromTheme(QLatin1String("bookmark-new"))));
244     viewBookmarksToolBarActionPointer->setIcon(QIcon::fromTheme(QLatin1String("bookmarks"), QIcon::fromTheme(QLatin1String("bookmark-new"))));
245     domainSettingsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("settings-configure"), QIcon::fromTheme(QLatin1String("preferences-desktop"))));
246     cookiesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-cookies"), QIcon::fromTheme(QLatin1String("appointment-new"))));
247     findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase"), QIcon::fromTheme(QLatin1String("/usr/share/icons/gnome/32x32/apps/fonts.png"))));
248     hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
249
250     // Create the key sequences.
251     QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
252     QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
253     QKeySequence ctrlAKeySequence = QKeySequence(i18nc("The save archive key sequence.", "Ctrl+A"));
254     QKeySequence ctrl0KeySequence = QKeySequence(i18nc("The zoom default key sequence.", "Ctrl+0"));
255     QKeySequence ctrlF5KeySequence = QKeySequence(i18nc("The reload and bypass cache key sequence.", "Ctrl+F5"));
256     QKeySequence ctrlShiftXKeySequence = QKeySequence(i18nc("The stop key sequence.", "Ctrl+Shift+X"));
257     QKeySequence ctrlUKeySequence = QKeySequence(i18nc("The view source key sequence.", "Ctrl+U"));
258     QKeySequence ctrlShiftUKeySequence = QKeySequence(i18nc("The view source in new tab key sequence.", "Ctrl+Shift+U"));
259     QKeySequence f12KeySequence = QKeySequence(i18nc("The developer tools key sequence.", "F12"));
260     QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
261     QKeySequence ctrlJKeySequence = QKeySequence(i18nc("The JavaScript key sequence.", "Ctrl+J"));
262     QKeySequence ctrlLKeySequence = QKeySequence(i18nc("The local storage key sequence.", "Ctrl+L"));
263     QKeySequence ctrlDKeySequence = QKeySequence(i18nc("The DOM storage key sequence.", "Ctrl+D"));
264     QKeySequence ctrlSKeySequence = QKeySequence(i18nc("The find case sensitive key sequence.", "Ctrl+S"));
265     QKeySequence ctrlAltPKeySequence = QKeySequence(i18nc("The Privacy Browser user agent key sequence.", "Ctrl+Alt+P"));
266     QKeySequence ctrlAltWKeySequence = QKeySequence(i18nc("The WebEngine Default user agent key sequence.", "Ctrl+Alt+W"));
267     QKeySequence ctrlAltFKeySequence = QKeySequence(i18nc("The Firefox on Linux user agent key sequence.", "Ctrl+Alt+F"));
268     QKeySequence ctrlAltCKeySequence = QKeySequence(i18nc("The Chromium on Linux user agent key sequence.", "Ctrl+Alt+C"));
269     QKeySequence ctrlAltShiftFKeySequence = QKeySequence(i18nc("The Firefox on Windows user agent key sequence.", "Ctrl+Alt+Shift+F"));
270     QKeySequence ctrlAltShiftCKeySequence = QKeySequence(i18nc("The Chrome on Windows user agent key sequence.", "Ctrl+Alt+Shift+C"));
271     QKeySequence ctrlAltEKeySequence = QKeySequence(i18nc("The Edge on Windows user agent key sequence.", "Ctrl+Alt+E"));
272     QKeySequence ctrlAltSKeySequence = QKeySequence(i18nc("The Safari on macOS user agent key sequence.", "Ctrl+Alt+S"));
273     QKeySequence altShiftCKeySequence = QKeySequence(i18nc("The custom user agent key sequence.", "Alt+Shift+C"));
274     QKeySequence ctrlAltZKeySequence = QKeySequence(i18nc("The zoom factor key sequence.", "Ctrl+Alt+Z"));
275     QKeySequence ctrlShiftMKeySequence = QKeySequence(i18nc("The Mojeek search engine key sequence.", "Ctrl+Shift+M"));
276     QKeySequence ctrlShiftOKeySequence = QKeySequence(i18nc("The Monocles search engine key sequence.", "Ctrl+Shift+O"));
277     QKeySequence ctrlShiftEKeySequence = QKeySequence(i18nc("The MetaGer search engine key sequence.", "Ctrl+Shift+E"));
278     QKeySequence ctrlShiftGKeySequence = QKeySequence(i18nc("The Google search engine key sequence.", "Ctrl+Shift+G"));
279     QKeySequence ctrlShiftBKeySequence = QKeySequence(i18nc("The Bing search engine key sequence.", "Ctrl+Shift+B"));
280     QKeySequence ctrlShiftYKeySequence = QKeySequence(i18nc("The Yahoo search engine key sequence.", "Ctrl+Shift+Y"));
281     QKeySequence ctrlShiftCKeySequence = QKeySequence(i18nc("The custom search engine key sequence.", "Ctrl+Shift+C"));
282     QKeySequence ctrlAltShiftBKeySequence = QKeySequence(i18nc("The edit bookmarks key sequence.", "Ctrl+Alt+Shift+B"));
283     QKeySequence ctrlAltBKeySequence = QKeySequence(i18nc("The view bookmarks toolbar key sequence.", "Ctrl+Alt+B"));
284     QKeySequence ctrlShiftDKeySequence = QKeySequence(i18nc("The domain settings key sequence.", "Ctrl+Shift+D"));
285     QKeySequence ctrlSemicolonKeySequence = QKeySequence(i18nc("The cookies dialog key sequence.", "Ctrl+;"));
286
287     // Set the action key sequences.
288     actionCollectionPointer->setDefaultShortcut(newTabActionPointer, ctrlTKeySequence);
289     actionCollectionPointer->setDefaultShortcut(newWindowActionPointer, ctrlNKeySequence);
290     actionCollectionPointer->setDefaultShortcut(saveArchiveActionPointer, ctrlAKeySequence);
291     actionCollectionPointer->setDefaultShortcut(zoomDefaultActionPointer, ctrl0KeySequence);
292     actionCollectionPointer->setDefaultShortcut(reloadAndBypassCacheActionPointer, ctrlF5KeySequence);
293     actionCollectionPointer->setDefaultShortcut(stopActionPointer, ctrlShiftXKeySequence);
294     actionCollectionPointer->setDefaultShortcut(viewSourceActionPointer, ctrlUKeySequence);
295     actionCollectionPointer->setDefaultShortcut(viewSourceInNewTabActionPointer, ctrlShiftUKeySequence);
296     actionCollectionPointer->setDefaultShortcut(developerToolsActionPointer, f12KeySequence);
297     actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
298     actionCollectionPointer->setDefaultShortcut(javaScriptActionPointer, ctrlJKeySequence);
299     actionCollectionPointer->setDefaultShortcut(localStorageActionPointer, ctrlLKeySequence);
300     actionCollectionPointer->setDefaultShortcut(domStorageActionPointer, ctrlDKeySequence);
301     actionCollectionPointer->setDefaultShortcut(findCaseSensitiveActionPointer, ctrlSKeySequence);
302     actionCollectionPointer->setDefaultShortcut(userAgentPrivacyBrowserActionPointer, ctrlAltPKeySequence);
303     actionCollectionPointer->setDefaultShortcut(userAgentWebEngineDefaultActionPointer, ctrlAltWKeySequence);
304     actionCollectionPointer->setDefaultShortcut(userAgentFirefoxLinuxActionPointer, ctrlAltFKeySequence);
305     actionCollectionPointer->setDefaultShortcut(userAgentChromiumLinuxActionPointer, ctrlAltCKeySequence);
306     actionCollectionPointer->setDefaultShortcut(userAgentFirefoxWindowsActionPointer, ctrlAltShiftFKeySequence);
307     actionCollectionPointer->setDefaultShortcut(userAgentChromeWindowsActionPointer, ctrlAltShiftCKeySequence);
308     actionCollectionPointer->setDefaultShortcut(userAgentEdgeWindowsActionPointer, ctrlAltEKeySequence);
309     actionCollectionPointer->setDefaultShortcut(userAgentSafariMacosActionPointer, ctrlAltSKeySequence);
310     actionCollectionPointer->setDefaultShortcut(userAgentCustomActionPointer, altShiftCKeySequence);
311     actionCollectionPointer->setDefaultShortcut(zoomFactorActionPointer, ctrlAltZKeySequence);
312     actionCollectionPointer->setDefaultShortcut(searchEngineMojeekActionPointer, ctrlShiftMKeySequence);
313     actionCollectionPointer->setDefaultShortcut(searchEngineMonoclesActionPointer, ctrlShiftOKeySequence);
314     actionCollectionPointer->setDefaultShortcut(searchEngineMetagerActionPointer, ctrlShiftEKeySequence);
315     actionCollectionPointer->setDefaultShortcut(searchEngineGoogleActionPointer, ctrlShiftGKeySequence);
316     actionCollectionPointer->setDefaultShortcut(searchEngineBingActionPointer, ctrlShiftBKeySequence);
317     actionCollectionPointer->setDefaultShortcut(searchEngineYahooActionPointer, ctrlShiftYKeySequence);
318     actionCollectionPointer->setDefaultShortcut(searchEngineCustomActionPointer, ctrlShiftCKeySequence);
319     actionCollectionPointer->setDefaultShortcut(editBookmarksActionPointer, ctrlAltShiftBKeySequence);
320     actionCollectionPointer->setDefaultShortcut(viewBookmarksToolBarActionPointer, ctrlAltBKeySequence);
321     actionCollectionPointer->setDefaultShortcut(domainSettingsActionPointer, ctrlShiftDKeySequence);
322     actionCollectionPointer->setDefaultShortcut(cookiesActionPointer, ctrlSemicolonKeySequence);
323
324     // Execute the actions.
325     connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
326     connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
327     connect(saveArchiveActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(saveArchive()));
328     connect(zoomDefaultActionPointer, SIGNAL(triggered()), this, SLOT(zoomDefault()));
329     connect(reloadAndBypassCacheActionPointer, SIGNAL(triggered()), this, SLOT(reloadAndBypassCache()));
330     connect(stopActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(stop()));
331     connect(viewSourceActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSource()));
332     connect(viewSourceInNewTabActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSourceInNewTab()));
333     connect(developerToolsActionPointer, SIGNAL(triggered()), this, SLOT(toggleDeveloperTools()));
334     connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
335     connect(viewBookmarksToolBarActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewBookmarksToolBar()));
336     connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
337     connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
338
339     // Update the on-the-fly menus.
340     connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
341     connect(tabWidgetPointer, SIGNAL(updateZoomActions(double)), this, SLOT(updateZoomActions(double)));
342     connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
343
344     // Apply the on-the-fly settings when selected.
345     connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
346     connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
347
348     // Process cookie changes.
349     connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
350
351     // Store the default zoom factor.
352     connect(tabWidgetPointer, SIGNAL(updateDefaultZoomFactor(double)), this, SLOT(updateDefaultZoomFactor(double)));
353
354     // Connect the URL toolbar actions.
355     connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
356     connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
357     connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
358
359     // Update the actions from the tab widget.
360     connect(tabWidgetPointer, SIGNAL(updateDeveloperToolsAction(bool)), developerToolsActionPointer, SLOT(setChecked(bool)));
361     connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
362     connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
363     connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
364     connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
365     connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
366
367     // Connect the find text actions.
368     connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
369     connect(hideFindTextActionPointer, SIGNAL(triggered()), this, SLOT(hideFindTextActions()));
370
371
372
373     // Setup the GUI based on the browserwindowui.rc file.
374     setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
375
376     // Get lists of the actions' associated widgets.
377     QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
378     QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
379
380     // Get the menu widget pointers.  It is the second entry, after the main window.
381     QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
382     QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
383
384     // Get the menu pointers.
385     QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
386     QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
387
388     // Get the menu actions.
389     userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
390     searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
391
392     // Get handles for the toolbars.
393     navigationToolBarPointer = toolBar(QLatin1String("navigation_toolbar"));
394     urlToolBarPointer = toolBar(QLatin1String("url_toolbar"));
395     bookmarksToolBarPointer = toolBar(QLatin1String("bookmarks_toolbar"));
396
397     // Populate the view bookmarks toolbar checkbox.
398     connect(bookmarksToolBarPointer, SIGNAL(visibilityChanged(bool)), this, SLOT(updateViewBookmarksToolBarCheckbox(bool)));
399
400     // Create the line edits.
401     urlLineEditPointer = new UrlLineEdit();
402     findTextLineEditPointer = new KLineEdit();
403
404     // Get the line edit size policies.
405     QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
406     QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
407
408     // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
409     urlLineEditSizePolicy.setHorizontalStretch(5);
410     findTextLineEditSizePolicy.setHorizontalStretch(1);
411
412     // Set the policies.
413     urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
414     findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
415
416     // Set the widths.
417     urlLineEditPointer->setMinimumWidth(350);
418     findTextLineEditPointer->setMinimumWidth(200);
419     findTextLineEditPointer->setMaximumWidth(350);
420
421     // Set the place holder text.
422     urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
423     findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
424
425     // Show the clear button on the find line edit.
426     findTextLineEditPointer->setClearButtonEnabled(true);
427
428     // Add the actions to the URL line edit.
429     bookmarkedActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("non-starred-symbolic"), QLineEdit::LeadingPosition);
430     QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure", QIcon::fromTheme(QLatin1String("preferences-desktop"))),
431                                                                                   QLineEdit::TrailingPosition);
432
433     // Set the bookmarked action pointer to be checkable.
434     bookmarkedActionPointer->setCheckable(true);
435
436     // Connect the URL line edit actions.
437     connect(bookmarkedActionPointer, SIGNAL(triggered()), this, SLOT(toggleBookmark()));
438     connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
439
440     // Create a find text label pointer.
441     findTextLabelPointer = new QLabel();
442
443     // Set the default label text.
444     findTextLabelPointer->setText(QLatin1String("  ") + i18nc("Default find results.", "0/0") + QLatin1String("  "));
445
446     // Insert the widgets into the toolbars.
447     urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
448     findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
449     findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
450
451     // Initially hide the find text actions.
452     hideFindTextActions();
453
454     // Load a new URL from the URL line edit.
455     connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
456
457     // Find text as it is typed.
458     connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
459
460     // Find next if the enter key is pressed.
461     connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
462
463     // Update find text when switching tabs.
464     connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
465
466     // Update the find text results.
467     connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
468
469     // Update the URL line edit on page loads.
470     connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
471
472     // Update the window title.
473     connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
474
475     // Get a handle for the status bar.
476     QStatusBar *statusBarPointer = statusBar();
477
478     // Create the status bar widgets.
479     progressBarPointer = new QProgressBar();
480     zoomMinusButtonPointer = new QPushButton();
481     currentZoomButtonPointer = new QPushButton();
482     zoomPlusButtonPointer = new QPushButton();
483
484     // Set the button icons.
485     zoomMinusButtonPointer->setIcon(QIcon::fromTheme(QStringLiteral("list-remove-symbolic")));
486     zoomPlusButtonPointer->setIcon(QIcon::fromTheme(QStringLiteral("list-add-symbolic")));
487
488     // Set the button icons to be flat (no borders).
489     zoomMinusButtonPointer->setFlat(true);
490     currentZoomButtonPointer->setFlat(true);
491     zoomPlusButtonPointer->setFlat(true);
492
493     // Handle clicks on the zoom buttons.
494     connect(zoomMinusButtonPointer, SIGNAL(clicked()), this, SLOT(decrementZoom()));
495     connect(currentZoomButtonPointer, SIGNAL(clicked()), this, SLOT(getZoomFactorFromUser()));
496     connect(zoomPlusButtonPointer, SIGNAL(clicked()), this, SLOT(incrementZoom()));
497
498     // Remove the padding around the current zoom button text.
499     currentZoomButtonPointer->setStyleSheet("padding: 0px;");
500
501     // Add the widgets to the far right of the status bar.
502     statusBarPointer->addPermanentWidget(progressBarPointer);
503     statusBarPointer->addPermanentWidget(zoomMinusButtonPointer);
504     statusBarPointer->addPermanentWidget(currentZoomButtonPointer);
505     statusBarPointer->addPermanentWidget(zoomPlusButtonPointer);
506
507     // Update the status bar with the URL when a link is hovered.
508     connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
509
510     // Update the progress bar.
511     connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
512     connect(tabWidgetPointer, SIGNAL(hideProgressBar()), this, SLOT(hideProgressBar()));
513
514     // Update the URL line edit focus.
515     connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
516
517     // Get the URL line edit palettes.
518     normalBackgroundPalette = urlLineEditPointer->palette();
519     negativeBackgroundPalette = normalBackgroundPalette;
520     positiveBackgroundPalette = normalBackgroundPalette;
521
522     // Modify the palettes.
523     KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
524     KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
525
526     // Update the applied palette.
527     connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
528
529     // Process full screen requests.
530     connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
531
532     // Create keyboard shortcuts.
533     QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
534     QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
535
536     // Connect the keyboard shortcuts.
537     connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
538     connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
539
540     // Get a handle for the Bookmarks menu.
541     bookmarksMenuPointer = qobject_cast<QMenu*>(guiFactory()->container("bookmarks", this));
542
543     // Add a separator to the bookmarks menu.
544     bookmarksMenuPointer->addSeparator();
545
546     // Initialize the bookmark action lists.
547     bookmarkFolderFinalActionList = QList<QPair<QMenu *, QAction *> *>();
548     bookmarksMenuActionList = QList<QPair<QMenu *, QAction *> *>();
549     bookmarksMenuSubmenuList = QList<QPair<QMenu *, QMenu *> *>();
550     bookmarksToolBarActionList = QList<QAction*>();
551     bookmarksToolBarSubfolderActionList = QList<QPair<QMenu *, QAction *> *>();
552
553     // Set the bookmarks toolbar context menu policy.
554     bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
555
556     // Show the custom bookmark context menu when requested.
557     connect(bookmarksToolBarPointer, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBookmarkContextMenu(const QPoint&)));
558
559     // Populate the bookmarks in this window.
560     populateBookmarksInThisWindow();
561
562     // Populate the UI.
563     // 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.
564     updateJavaScriptAction(Settings::javaScriptEnabled());
565     updateLocalStorageAction(Settings::localStorageEnabled());
566     updateDomStorageAction(Settings::domStorageEnabled());
567     updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
568     updateZoomActions(Settings::zoomFactor());
569
570     // Populate the first tab.
571     if (firstWindow)  // This is the first window.
572     {
573         // Load the initial website.
574         tabWidgetPointer->loadInitialWebsite();
575     }
576     else if (initialUrlStringPointer)  // An initial URL was specified.
577     {
578         // Load the initial URL.
579         tabWidgetPointer->loadUrlFromLineEdit(*initialUrlStringPointer);
580     }
581 }
582
583 // If actions are part of a context menu they do not need to be added to the list as they will be deleted automatically when the context menu closes.
584 void BrowserWindow::addBookmarkFolderFinalActions(QMenu *menuPointer, const double folderId, const bool addToList)
585 {
586     // Get the database ID.
587     int folderDatabaseId = BookmarksDatabase::getFolderDatabaseId(folderId);
588
589     // Add a separator.
590     menuPointer->addSeparator();
591
592     // Add the add bookmark action to the menu.
593     QAction *addBookmarkActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("bookmark-new")), i18nc("The add bookmark action", "Add Bookmark"), [=]
594         {
595             // Instantiate an add bookmark dialog.
596             AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(this, tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(),
597                                                                                 tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
598
599             // Update the displayed bookmarks when a new one is added.
600             connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(populateBookmarksInAllWindows()));
601
602             // Show the dialog.
603             addBookmarkDialogPointer->show();
604         }
605     );
606
607     // Add the add folder action to the menu.
608     QAction *addFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("folder-add")), i18nc("The add folder action", "Add Folder"), [=]
609         {
610             // Instantiate an add folder dialog.
611             AddFolderDialog *addFolderDialogPointer = new AddFolderDialog(this, tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
612
613             // Update the displayed bookmarks when a folder is added.
614             connect(addFolderDialogPointer, SIGNAL(folderAdded()), this, SLOT(populateBookmarksInAllWindows()));
615
616             // Show the dialog.
617             addFolderDialogPointer->show();
618         }
619     );
620
621     // Add a separator.
622     menuPointer->addSeparator();
623
624     // Add the open folder in new tabs action to the menu.
625     QAction *openFolderInNewTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("The open folder in new tabs action", "Open Folder in New Tabs"), [=]
626         {
627             // Get all the folder URLs.
628             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
629
630             // Open the URLs in new tabs.  `true` removes the URL line edit focus, `true` opens the new tabs in an adjacent tab.  `false` does not load a background tab.
631             for (QString url : *folderUrlsListPointer)
632                 tabWidgetPointer->addTab(true, true, false, url);
633         }
634     );
635
636     // Add the open folder in background tabs action to the menu.
637     QAction *openFolderInBackgroundTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")),
638                                                                               i18nc("The open folder in background tabs action", "Open Folder in Background Tabs"), [=]
639         {
640             // Get all the folder URLs.
641             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
642
643             // Open the URLs in new tabs.  `true` removes the URL line edit focus, `true` opens the new tabs in an adjacent tab.  `true` loads a background tab.
644             for (QString url : *folderUrlsListPointer)
645                 tabWidgetPointer->addTab(true, true, true, url);
646         }
647     );
648
649     // Add the open folder in new window action to the menu.
650     QAction *openFolderInNewWindowActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("The open folder in new window action", "Open Folder in New Window"), [=]
651         {
652             // Get all the folder URLs.
653             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
654
655             // Create a new browser window.
656             BrowserWindow *browserWindowPointer = new BrowserWindow(false, &folderUrlsListPointer->first());
657
658             // Get a count of the folder URLs.
659             const int folderUrls = folderUrlsListPointer->count();
660
661             // Load all the other URLs.  `true` removes the URL line edit focus, `false` does not load the new tabs in adjacent tabs.  `true` loads a background tab.
662             for (int i = 1; i < folderUrls; ++i)
663                 browserWindowPointer->tabWidgetPointer->addTab(true, false, true, folderUrlsListPointer->value(i));
664
665             // Show the new browser window.
666             browserWindowPointer->show();
667         }
668     );
669
670     // Add a separator.
671     menuPointer->addSeparator();
672
673     // Add the edit folder action to the menu if this is not the root bookmark menu.
674     if (folderId != 0)
675     {
676         QAction *editFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("The edit folder action", "Edit Folder"), [=]
677             {
678                 // Get the current tab favorite icon.
679                 QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
680
681                 // Instantiate an edit folder dialog.
682                 QDialog *editFolderDialogPointer = new EditFolderDialog(this, folderDatabaseId, currentTabFavoriteIcon);
683
684                 // Show the dialog.
685                 editFolderDialogPointer->show();
686
687                 // Process bookmark events.
688                 connect(editFolderDialogPointer, SIGNAL(folderSaved()), this, SLOT(populateBookmarksInAllWindows()));
689             }
690         );
691
692         // Add the action to the beginning of the bookmark folder final action list if requsted.
693         if (addToList)
694             bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, editFolderActionPointer));
695     }
696
697     // Add the delete folder action to the menu.
698     QAction *deleteFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete folder context menu entry", "Delete Folder"), [=]
699         {
700             // Create an items to delete list.
701             QList<int>* itemsToDeleteListPointer = new QList<int>;
702
703             // Add the folder to the list of items to delete if it is not the root folder.
704             if (folderId != 0)
705                 itemsToDeleteListPointer->append(folderDatabaseId);
706
707             // Add the folder contents to the list of items to delete.
708             itemsToDeleteListPointer->append(*BookmarksDatabase::getFolderContentsDatabaseIdsRecursively(folderId));
709
710             // Instantiate a delete dialog message box.
711             QMessageBox deleteDialogMessageBox;
712
713             // Set the icon.
714             deleteDialogMessageBox.setIcon(QMessageBox::Warning);
715
716             // Set the window title.
717             deleteDialogMessageBox.setWindowTitle(i18nc("Delete bookmarks dialog title", "Delete Bookmarks"));
718
719             // Set the text.
720             deleteDialogMessageBox.setText(i18ncp("Delete bookmarks dialog main message", "Delete %1 bookmark item?", "Delete %1 bookmark items?", itemsToDeleteListPointer->count()));
721
722             // Set the informative text.
723             deleteDialogMessageBox.setInformativeText(i18nc("Delete bookmarks dialog secondary message", "This cannot be undone."));
724
725             // Set the standard buttons.
726             deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
727
728             // Set the default button.
729             deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
730
731             // Display the dialog and capture the return value.
732             int returnValue = deleteDialogMessageBox.exec();
733
734             // Delete the domain if instructed.
735             if (returnValue == QMessageBox::Yes)
736             {
737                 // Get the parent folder ID.
738                 double parentFolderId = BookmarksDatabase::getParentFolderId(folderDatabaseId);
739
740                 // Delete the folder and its contents.
741                 for (const int databaseId : *itemsToDeleteListPointer)
742                     BookmarksDatabase::deleteBookmark(databaseId);
743
744                 // Update the display order of the bookmarks in the parent folder.
745                 BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
746
747                 // Repopulate the bookmarks.
748                 populateBookmarksInAllWindows();
749             }
750         }
751     );
752
753     // Add the key sequences if this is the root bookmarks menu.
754     if (folderId == 0)
755     {
756         // Create the key sequences.
757         QKeySequence ctrlBKeySequence = QKeySequence(i18nc("The add bookmark key sequence.", "Ctrl+B"));
758         QKeySequence metaFKeySequence = QKeySequence(i18nc("The add folder key sequence.", "Meta+F"));
759
760         // Set the action key sequences.
761         actionCollectionPointer->setDefaultShortcut(addBookmarkActionPointer, ctrlBKeySequence);
762         actionCollectionPointer->setDefaultShortcut(addFolderActionPointer, metaFKeySequence);
763     }
764
765     // Add the actions to the beginning of the bookmark folder final action list if requested.
766     if (addToList) {
767         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addBookmarkActionPointer));
768         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addFolderActionPointer));
769         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewTabsActionPointer));
770         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInBackgroundTabsActionPointer));
771         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewWindowActionPointer));
772         bookmarkFolderFinalActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, deleteFolderActionPointer));
773     }
774 }
775
776 void BrowserWindow::addOrEditDomainSettings()
777 {
778     // Remove the focus from the URL line edit.
779     urlLineEditPointer->clearFocus();
780
781     // Get the current domain settings name.
782     QString &currentDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
783
784     // Run the commands according to the current domain settings status.
785     if (currentDomainSettingsName == QStringLiteral(""))  // Domain settings are not currently applied.
786     {
787         // Get the current settings status.
788         int javaScriptInt = calculateSettingsInt(javaScriptEnabled, Settings::javaScriptEnabled());
789         int localStorageInt = calculateSettingsInt(localStorageActionPointer->isChecked(), Settings::localStorageEnabled());
790         int domStorageInt = calculateSettingsInt(domStorageActionPointer->isChecked(), Settings::domStorageEnabled());
791
792         // Get the current user agent string.
793         QString currentUserAgentString = tabWidgetPointer->getCurrentUserAgent();
794
795         // Get the current user agent database string.
796         QString currentUserAgentDatabaseString = UserAgentHelper::getDatabaseUserAgentNameFromUserAgent(currentUserAgentString);
797
798         // Initialize the user agent database string.
799         QString userAgentDatabaseString = UserAgentHelper::SYSTEM_DEFAULT_DATABASE;
800
801         // Replace the user agent database string if the current user agent is not the default.
802         if (currentUserAgentDatabaseString != Settings::userAgent())
803             userAgentDatabaseString = currentUserAgentDatabaseString;
804
805         // Initialize the zoom factor variables.
806         int zoomFactorInt = DomainsDatabase::SYSTEM_DEFAULT;
807
808         // Use a custom zoom factor if currently applied.  Doubles cannot be reliably compared using `==`, so a mathematical workaround is used.
809         if (abs(currentZoomFactorDouble - defaultZoomFactorDouble ) > 0.01)
810             zoomFactorInt = DomainsDatabase::CUSTOM;
811
812         // Add the domain.
813         DomainsDatabase::addDomain(currentUrl.host(), javaScriptInt, localStorageInt, domStorageInt, userAgentDatabaseString, zoomFactorInt, currentZoomFactorDouble);
814
815         // Apply the domain settings.
816         tabWidgetPointer->applyDomainSettingsAndReload();
817     }
818
819     // Create the domain settings dialog pointer.
820     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog(this, DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
821
822     // Reload the tabs when domain settings are updated.
823     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
824
825     // Show the dialog.
826     domainSettingsDialogPointer->show();
827 }
828
829 void BrowserWindow::back() const
830 {
831     // Remove the focus from the URL line edit.
832     urlLineEditPointer->clearFocus();
833
834     // Go back.
835     tabWidgetPointer->back();
836 }
837
838 int BrowserWindow::calculateSettingsInt(const bool settingCurrentlyEnabled, const bool settingEnabledByDefault) const
839 {
840     // Return the int that matches the current state.
841     if (settingCurrentlyEnabled == settingEnabledByDefault)  // The current system default is used.
842         return DomainsDatabase::SYSTEM_DEFAULT;
843     else if (settingCurrentlyEnabled)  // The setting is enabled, which is different from the system default.
844         return DomainsDatabase::ENABLED;
845     else  // The setting is disabled, which is different from the system default.
846         return DomainsDatabase::DISABLED;
847 }
848
849 void BrowserWindow::clearUrlLineEditFocus() const
850 {
851     // Remove the focus from the URL line edit.
852     urlLineEditPointer->clearFocus();
853 }
854
855 void BrowserWindow::decrementZoom()
856 {
857     // Update the current zoom factor.
858     currentZoomFactorDouble = currentZoomFactorDouble - 0.25;
859
860     // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
861     if (currentZoomFactorDouble < 0.25)
862         currentZoomFactorDouble = 0.25;
863
864     // Set the new zoom factor.
865     tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
866
867     // Update the on-the-fly action text.
868     updateZoomActions(currentZoomFactorDouble);
869 }
870
871 void BrowserWindow::editBookmarks()
872 {
873     // Instantiate an edit bookmarks dialog.
874     BookmarksDialog *bookmarksDialogPointer = new BookmarksDialog(this, tabWidgetPointer->getCurrentTabFavoritIcon(), tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl());
875
876     // Update the displayed bookmarks when edited.
877     connect(bookmarksDialogPointer, SIGNAL(bookmarkUpdated()), this, SLOT(populateBookmarksInAllWindows()));
878
879     // Show the dialog.
880     bookmarksDialogPointer->show();
881 }
882
883 void BrowserWindow::escape() const
884 {
885     // Process the escape according to the status of the browser.
886     if (fullScreenActionPointer->isChecked())  // Full screen browsing is enabled.
887     {
888         // Exit full screen browsing.
889         fullScreenActionPointer->trigger();
890     }
891     else if (!findTextLineEditPointer->text().isEmpty())  // Find text is populated.
892     {
893         // Clear the find text line edit.
894         findTextLineEditPointer->clear();
895
896         // Clear the search in the WebEngine.
897         tabWidgetPointer->findText(QStringLiteral(""));
898     }
899     else if (findTextLineEditActionPointer->isVisible())  // Find text actions are visible.
900     {
901         // Hide the find text actions.
902         hideFindTextActions();
903     }
904 }
905
906 void BrowserWindow::findNext() const
907 {
908     // Get the find string.
909     const QString findString = findTextLineEditPointer->text();
910
911     // Search for the text if it is not empty.
912     if (!findString.isEmpty())
913         tabWidgetPointer->findText(findString);
914 }
915
916 void BrowserWindow::findPrevious() const
917 {
918     // Get the find string.
919     const QString findString = findTextLineEditPointer->text();
920
921     // Search for the text if it is not empty.
922     if (!findString.isEmpty())
923         tabWidgetPointer->findPrevious(findString);
924 }
925
926 void BrowserWindow::forward() const
927 {
928     // Remove the focus from the URL line edit.
929     urlLineEditPointer->clearFocus();
930
931     // Go forward.
932     tabWidgetPointer->forward();
933 }
934
935 void BrowserWindow::fullScreenRequested(const bool toggleOn)
936 {
937     // Toggle full screen mode.
938     if (toggleOn)  // Turn full screen mode on.
939     {
940         // Enable full screen mode.
941         fullScreenActionPointer->setFullScreen(window(), true);
942
943         // Hide the menu bar if specified.
944         if (Settings::fullScreenHideMenuBar())
945             menuBar()->setVisible(false);
946
947         // Hide the toolbars if specified.
948         if (Settings::fullScreenHideToolBars())
949         {
950             navigationToolBarPointer->setVisible(false);
951             urlToolBarPointer->setVisible(false);
952             bookmarksToolBarPointer->setVisible(false);
953         }
954
955         // Hide the tab bar if specified.
956         if (Settings::fullScreenHideTabBar())
957             tabWidgetPointer->setTabBarVisible(false);
958
959         // Hide the status bar if specified.
960         if (Settings::fullScreenHideStatusBar())
961             statusBar()->setVisible(false);
962     }
963     else  // Disable full screen browsing mode.
964     {
965         // Disable full screen mode.
966         fullScreenActionPointer->setFullScreen(window(), false);
967
968         // Show the menu bar.
969         menuBar()->setVisible(true);
970
971         // Show the toolbars.
972         navigationToolBarPointer->setVisible(true);
973         urlToolBarPointer->setVisible(true);
974
975         // Only show the bookmarks toolbar if it was previously visible.
976         if (bookmarksToolBarIsVisible)
977             bookmarksToolBarPointer->setVisible(true);
978
979         // Show the tab bar.
980         tabWidgetPointer->setTabBarVisible(true);
981
982         // Show the status bar.
983         statusBar()->setVisible(true);
984     }
985 }
986
987 void BrowserWindow::getZoomFactorFromUser()
988 {
989     // Create an OK flag.
990     bool okClicked;
991
992     // 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.
993     double newZoomFactorDouble = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
994                                                    i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
995                                                    currentZoomFactorDouble, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
996
997     // Update the zoom factor if the user clicked OK.
998     if (okClicked)
999     {
1000         // Set the new zoom factor.
1001         tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactorDouble);
1002
1003         // Update the on-the-fly action text.
1004         updateZoomActions(newZoomFactorDouble);
1005     }
1006 }
1007
1008 void BrowserWindow::hideFindTextActions() const
1009 {
1010     // Hide the find text actions.
1011     findTextLineEditActionPointer->setVisible(false);
1012     findTextLabelActionPointer->setVisible(false);
1013     findNextActionPointer->setVisible(false);
1014     findPreviousActionPointer->setVisible(false);
1015     findCaseSensitiveActionPointer->setVisible(false);
1016     hideFindTextActionPointer->setVisible(false);
1017 }
1018
1019 void BrowserWindow::home() const
1020 {
1021     // Remove the focus from the URL line edit.
1022     urlLineEditPointer->clearFocus();
1023
1024     // Go home.
1025     tabWidgetPointer->home();
1026 }
1027
1028 void BrowserWindow::hideProgressBar() const
1029 {
1030     // Hide the progress bar.
1031     progressBarPointer->hide();
1032
1033     // Disable and hide the stop action.
1034     stopActionPointer->setEnabled(false);
1035     stopActionPointer->setVisible(false);
1036
1037     // Enable and show the refresh action.
1038     refreshActionPointer->setEnabled(true);
1039     refreshActionPointer->setVisible(true);
1040 }
1041
1042 void BrowserWindow::incrementZoom()
1043 {
1044     // Update the current zoom factor.
1045     currentZoomFactorDouble = currentZoomFactorDouble + 0.25;
1046
1047     // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
1048     if (currentZoomFactorDouble > 5.0)
1049         currentZoomFactorDouble = 5.0;
1050
1051     // Set the new zoom factor.
1052     tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
1053
1054     // Update the on-the-fly action text.
1055     updateZoomActions(currentZoomFactorDouble);
1056 }
1057
1058 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
1059 {
1060     // Remove the focus from the URL line edit.
1061     urlLineEditPointer->clearFocus();
1062
1063     // Load the URL.
1064     tabWidgetPointer->loadUrlFromLineEdit(url);
1065 }
1066
1067 void BrowserWindow::newWindow() const
1068 {
1069     // Create a new browser window.
1070     BrowserWindow *browserWindowPointer = new BrowserWindow();
1071
1072     // Show the new browser window.
1073     browserWindowPointer->show();
1074 }
1075
1076 void BrowserWindow::populateBookmarksInAllWindows() const
1077 {
1078     // Get a list of all the registered service names.
1079     QStringList registeredServiceNames = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
1080
1081     // Get a list of all the Privacy Browser windows, which will be `com.stoutner.privacybrowser-` with the PID appended.
1082     QStringList privacyBrowserServiceNames = registeredServiceNames.filter("com.stoutner.privacybrowser");
1083
1084     // Repopulate the bookmarks in each window.
1085     for (QString privacyBrowserServiceName : privacyBrowserServiceNames)
1086     {
1087         // Prepare the D-Bus message.
1088         QDBusMessage dBusMessage = QDBusMessage::createMethodCall(privacyBrowserServiceName, "/privacybrowser/MainWindow_1", "com.stoutner.privacybrowser.BrowserWindow", "populateBookmarksInThisWindow");
1089
1090         // Make it so.
1091         QDBusConnection::sessionBus().send(dBusMessage);
1092     }
1093 }
1094
1095 void BrowserWindow::populateBookmarksInThisWindow()
1096 {
1097     // Remove all the final bookmark folder menu actions.
1098     for (QPair<QMenu *, QAction *> *bookmarkFolderFinalActionPairPointer : bookmarkFolderFinalActionList)
1099     {
1100         // Remove the action.
1101         bookmarkFolderFinalActionPairPointer->first->removeAction(bookmarkFolderFinalActionPairPointer->second);
1102     }
1103
1104     // Remove all the current menu bookmarks.
1105     for (QPair<QMenu *, QAction *> *bookmarkMenuActionPairPointer : bookmarksMenuActionList)
1106     {
1107         // Remove the bookmark.
1108         bookmarkMenuActionPairPointer->first->removeAction(bookmarkMenuActionPairPointer->second);
1109     }
1110
1111     // Remove all the current menu subfolders.
1112     for (QPair<QMenu *, QMenu *> *submenuPairPointer : bookmarksMenuSubmenuList)
1113     {
1114         // Remove the submenu from the parent menu.
1115         submenuPairPointer->first->removeAction(submenuPairPointer->second->menuAction());
1116     }
1117
1118     // Remove all the current toolbar subfolders.
1119     for (QPair<QMenu *, QAction *> *subfolderActionPairPointer : bookmarksToolBarSubfolderActionList)
1120     {
1121         // Remove the action from the subfolder.
1122         subfolderActionPairPointer->first->removeAction(subfolderActionPairPointer->second);
1123     }
1124
1125     // Remove all the current toolbar bookmarks.
1126     for (QAction *bookmarkAction : bookmarksToolBarActionList)
1127     {
1128         // Remove the bookmark.
1129         bookmarksToolBarPointer->removeAction(bookmarkAction);
1130     }
1131
1132     // Clear the action lists.
1133     bookmarkFolderFinalActionList.clear();
1134     bookmarksMenuActionList.clear();
1135     bookmarksMenuSubmenuList.clear();
1136     bookmarksToolBarSubfolderActionList.clear();
1137     bookmarksToolBarActionList.clear();
1138
1139     // Populate the bookmarks subfolders, beginning with the root folder (`0`);
1140     populateBookmarksMenuSubfolders(0, bookmarksMenuPointer);
1141
1142     // Populate the bookmarks toolbar.
1143     populateBookmarksToolBar();
1144
1145     // Get a handle for the bookmark toolbar layout.
1146     QLayout *bookmarksToolBarLayoutPointer = bookmarksToolBarPointer->layout();
1147
1148     // Get the count of the bookmarks.
1149     int bookmarkCount = bookmarksToolBarLayoutPointer->count();
1150
1151     // Set the layout of each bookmark to be left aligned.
1152     for(int i = 0; i < bookmarkCount; ++i)
1153         bookmarksToolBarLayoutPointer->itemAt(i)->setAlignment(Qt::AlignLeft);
1154
1155     // Update the bookmarked action.
1156     updateBookmarkedAction();
1157 }
1158
1159 void BrowserWindow::populateBookmarksMenuSubfolders(const double folderId, QMenu *menuPointer)
1160 {
1161     // Get the folder contents.
1162     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1163
1164     // Populate the bookmarks menu and toolbar.
1165     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1166     {
1167         // Process the item according to the type.
1168         if (bookmarkStruct.isFolder)  // This item is a folder.
1169         {
1170             // Add a submenu to the menu.
1171             QMenu *submenuPointer = menuPointer->addMenu(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1172
1173             // Add the submenu to the beginning of the list of menus to be deleted on repopulate.
1174             bookmarksMenuSubmenuList.prepend(new QPair<QMenu *, QMenu *>(menuPointer, submenuPointer));
1175
1176             // Populate any subfolders.
1177             populateBookmarksMenuSubfolders(bookmarkStruct.folderId, submenuPointer);
1178         }
1179         else  // This item is a bookmark.
1180         {
1181             // Add the bookmark to the menu.
1182             QAction *menuBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1183                 {
1184                     // Remove the focus from the URL line edit.
1185                     urlLineEditPointer->clearFocus();
1186
1187                     // Load the URL.
1188                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1189                 }
1190             );
1191
1192             // Add the actions to the beginning of the list of bookmarks to be deleted on repopulate.
1193             bookmarksMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, menuBookmarkActionPointer));
1194         }
1195     }
1196
1197     // Add the extra items at the bottom of the menu.  `true` adds them to the list of actions to be deleted on repopulate.
1198     addBookmarkFolderFinalActions(menuPointer, folderId, true);
1199 }
1200
1201 void BrowserWindow::populateBookmarksToolBar()
1202 {
1203     // Get the root folder contents (which has a folder ID of `0`).
1204     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(0);
1205
1206     // Populate the bookmarks toolbar.
1207     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1208     {
1209         // Process the item according to the type.
1210         if (bookmarkStruct.isFolder)  // This item is a folder.
1211         {
1212             // Add the subfolder action.
1213             QAction *toolBarSubfolderActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1214
1215             // Add the bookmark database ID to the toolbar action.
1216             toolBarSubfolderActionPointer->setData(bookmarkStruct.databaseId);
1217
1218             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1219             bookmarksToolBarActionList.prepend(toolBarSubfolderActionPointer);
1220
1221             // Create a subfolder menu.
1222             QMenu *subfolderMenuPointer = new QMenu();
1223
1224             // Add the menu to the action.
1225             toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1226
1227             // Add the submenu to the toolbar menu list.
1228             bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1229
1230             // Set the popup mode for the menu.
1231             dynamic_cast<QToolButton *>(bookmarksToolBarPointer->widgetForAction(toolBarSubfolderActionPointer))->setPopupMode(QToolButton::InstantPopup);
1232
1233             // Populate the subfolder.
1234             populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1235         }
1236         else  // This item is a bookmark.
1237         {
1238             // Add the bookmark to the toolbar.
1239             QAction *toolBarBookmarkActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1240                 {
1241                     // Remove the focus from the URL line edit.
1242                     urlLineEditPointer->clearFocus();
1243
1244                     // Load the URL.
1245                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1246                 }
1247             );
1248
1249             // Add the bookmark database ID to the toolbar action.
1250             toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1251
1252             // Add the actions to the beginning of the current bookmarks lists.
1253             bookmarksToolBarActionList.prepend(toolBarBookmarkActionPointer);
1254         }
1255     }
1256
1257     // Add the extra items to the toolbar folder menus.  The first item in the pair is the menu pointer.  The second is the folder ID.
1258     for (QPair<QMenu *, const double> *menuAndFolderIdPairPointer : bookmarksToolBarMenuList)
1259     {
1260         // Populate the final bookmarks menu entries.  `true` adds them to the list of actions to be deleted on repopulate.
1261         addBookmarkFolderFinalActions(menuAndFolderIdPairPointer->first, menuAndFolderIdPairPointer->second, true);
1262     }
1263 }
1264
1265 void BrowserWindow::populateBookmarksToolBarSubfolders(const double folderId, QMenu *menuPointer)
1266 {
1267     // Get the folder contents.
1268     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1269
1270     // Populate the bookmarks folder.
1271     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1272     {
1273         // Get the bookmark URL.
1274         QString bookmarkUrl = bookmarkStruct.url;
1275
1276         // Process the item according to the type.
1277         if (bookmarkStruct.isFolder)  // This item is a folder.
1278         {
1279             // Add the subfolder action.
1280             QAction *toolBarSubfolderActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1281
1282             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1283             bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarSubfolderActionPointer));
1284
1285             // Create a subfolder menu.
1286             QMenu *subfolderMenuPointer = new QMenu();
1287
1288             // Add the submenu to the action.
1289             toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1290
1291             // Add the submenu to the toolbar menu list.
1292             bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1293
1294             // Populate the subfolder menu.
1295             populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1296         }
1297         else  // This item is a bookmark.
1298         {
1299             // Add the bookmark to the folder.
1300             QAction *toolBarBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1301                 {
1302                     // Remove the focus from the URL line edit.
1303                     urlLineEditPointer->clearFocus();
1304
1305                     // Load the URL.
1306                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkUrl);
1307                 }
1308             );
1309
1310             // Add the bookmark database ID to the toolbar action.
1311             toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1312
1313             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1314             bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarBookmarkActionPointer));
1315         }
1316     }
1317 }
1318
1319 void BrowserWindow::refresh() const
1320 {
1321     // Remove the focus from the URL line edit.
1322     urlLineEditPointer->clearFocus();
1323
1324     // Refresh the web page.
1325     tabWidgetPointer->refresh();
1326 }
1327
1328 void BrowserWindow::reloadAndBypassCache() const
1329 {
1330     // Remove the focus from the URL line edit.
1331     urlLineEditPointer->clearFocus();
1332
1333     // Refresh the web page.
1334     tabWidgetPointer->refresh();
1335 }
1336
1337 void BrowserWindow::showBookmarkContextMenu(const QPoint &point)
1338 {
1339     // Get the bookmark action.
1340     QAction *bookmarkActionPointer = bookmarksToolBarPointer->actionAt(point);
1341
1342     // Check to see if an action was clicked.
1343     if (bookmarkActionPointer)  // An action was clicked.
1344     {
1345         // Create a bookmark context menu.
1346         QMenu *bookmarkContextMenuPointer = new QMenu();
1347
1348         // Get the database ID from the action.
1349         int databaseId = bookmarkActionPointer->data().toInt();
1350
1351         // Create the menu according to the type.
1352         if (BookmarksDatabase::isFolder(databaseId))  // A folder was clicked.
1353         {
1354             // Populate the final bookmarks menu entries.  `false` does not add the actions to the delete list, as they will be automatically deleted when the menu closes.
1355             addBookmarkFolderFinalActions(bookmarkContextMenuPointer, BookmarksDatabase::getFolderId(databaseId), false);
1356         }
1357         else  // A bookmark was clicked.
1358         {
1359             // Add the open in new tab action to the menu.
1360             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in new tab context menu entry", "Open in New Tab"), [=]
1361                 {
1362                     // Get the bookmark.
1363                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1364
1365                     // Open the bookmark in a new tab.  `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab.  `false` does not load a background tab.
1366                     tabWidgetPointer->addTab(true, true, false, bookmarkStructPointer->url);
1367                 }
1368             );
1369
1370             // Add the open in background tab action to the menu.
1371             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in background tab context menu entry", "Open in Background Tab"), [=]
1372                 {
1373                     // Get the bookmark.
1374                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1375
1376                     // Open the bookmark in a new tab.  `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab.  `true` loads a background tab.
1377                     tabWidgetPointer->addTab(true, true, true, bookmarkStructPointer->url);
1378                 }
1379             );
1380
1381             // Add the open in new window action to the menu.
1382             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("Open bookmark in new window context menu entry", "Open in New Window"), [=]
1383                 {
1384                     // Get the bookmark.
1385                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1386
1387                     // Create a new browser window and load the first URL.  `false` indicates it is not the first browser window.
1388                     BrowserWindow *browserWindowPointer = new BrowserWindow(false, &bookmarkStructPointer->url);
1389
1390                     // Show the new browser window.
1391                     browserWindowPointer->show();
1392                 }
1393             );
1394
1395             // Add a separator.
1396             bookmarkContextMenuPointer->addSeparator();
1397
1398             // Add the edit action to the menu.
1399             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("Edit bookmark context menu entry", "Edit"), [=]
1400                 {
1401                     // Get the current tab favorite icon.
1402                     QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1403
1404                     // Instantiate an edit bookmark dialog.
1405                     QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(this, databaseId, currentTabFavoriteIcon);
1406
1407                     // Show the dialog.
1408                     editBookmarkDialogPointer->show();
1409
1410                     // Process bookmark events.
1411                     connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(populateBookmarksInAllWindows()));
1412                 }
1413             );
1414
1415             // Add the copy URL action to the menu.
1416             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18nc("Copy bookmark URL context menu entry", "Copy URL"), [=]
1417                 {
1418                     // Get the bookmark.
1419                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1420
1421                     // Get a handle for the clipboard.
1422                     QClipboard *clipboard = QGuiApplication::clipboard();
1423
1424                     // Place the URL on the keyboard.
1425                     clipboard->setText(bookmarkStructPointer->url);
1426                 }
1427             );
1428
1429             // Add a separator.
1430             bookmarkContextMenuPointer->addSeparator();
1431
1432             // Add the delete action to the menu.
1433             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete bookmark context menu entry", "Delete"), [=]
1434                 {
1435                     // Get the parent folder ID.
1436                     double parentFolderId = BookmarksDatabase::getParentFolderId(databaseId);
1437
1438                     // Delete the bookmark.
1439                     BookmarksDatabase::deleteBookmark(databaseId);
1440
1441                     // Update the display order of the bookmarks in the parent folder.
1442                     BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
1443
1444                     // Repopulate the bookmarks.
1445                     populateBookmarksInAllWindows();
1446                 }
1447             );
1448         }
1449
1450         // Delete the menu from memory when it is closed.
1451         bookmarkContextMenuPointer->setAttribute(Qt::WA_DeleteOnClose);
1452
1453         // Display the context menu.
1454         bookmarkContextMenuPointer->popup(bookmarksToolBarPointer->mapToGlobal(point));
1455     }
1456     else  // The toolbar background was clicked.
1457     {
1458         // Temporarily set the context menu policy to the default.
1459         bookmarksToolBarPointer->setContextMenuPolicy(Qt::DefaultContextMenu);
1460
1461         // Create a context menu event with the same position.
1462         QContextMenuEvent *contextMenuEventPointer = new QContextMenuEvent(QContextMenuEvent::Mouse, point);
1463
1464         // Send the context menu event to the toolbar.
1465         QCoreApplication::sendEvent(bookmarksToolBarPointer, contextMenuEventPointer);
1466
1467         // Reset the context menu policy.
1468         bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
1469     }
1470 }
1471
1472 void BrowserWindow::showCookiesDialog()
1473 {
1474     // Remove the focus from the URL line edit.
1475     urlLineEditPointer->clearFocus();
1476
1477     // Instantiate the cookie settings dialog.
1478     CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
1479
1480     // Show the dialog.
1481     cookiesDialogPointer->show();
1482
1483     // Connect the dialog signals.
1484     connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
1485     connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
1486     connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
1487 }
1488
1489 void BrowserWindow::showDomainSettingsDialog()
1490 {
1491     // Remove the focus from the URL line edit.
1492     urlLineEditPointer->clearFocus();
1493
1494     // Instantiate the domain settings dialog.
1495     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog(this);
1496
1497     // Reload the tabs when domain settings are updated.
1498     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1499
1500     // Show the dialog.
1501     domainSettingsDialogPointer->show();
1502 }
1503
1504 void BrowserWindow::showFindTextActions() const
1505 {
1506     // Show the find text actions.
1507     findTextLineEditActionPointer->setVisible(true);
1508     findTextLabelActionPointer->setVisible(true);
1509     findNextActionPointer->setVisible(true);
1510     findPreviousActionPointer->setVisible(true);
1511     findCaseSensitiveActionPointer->setVisible(true);
1512     hideFindTextActionPointer->setVisible(true);
1513
1514     // Set the focus on the find line edit.
1515     findTextLineEditPointer->setFocus();
1516
1517     // Select all the text in the find line edit.
1518     findTextLineEditPointer->selectAll();
1519 }
1520
1521 void BrowserWindow::showProgressBar(const int &progress) const
1522 {
1523     // Set the progress bar value.
1524     progressBarPointer->setValue(progress);
1525
1526     // Show the progress bar.
1527     progressBarPointer->show();
1528
1529     // Disable and hide the refresh action.
1530     refreshActionPointer->setEnabled(false);
1531     refreshActionPointer->setVisible(false);
1532
1533     // Enable and show the stop action.
1534     stopActionPointer->setEnabled(true);
1535     stopActionPointer->setVisible(true);
1536 }
1537
1538 void BrowserWindow::showSettingsDialog()
1539 {
1540     // Get a handle for the KConfig skeleton.
1541     KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
1542
1543     // Instantiate a settings dialog.
1544     SettingsDialog *settingsDialogPointer = new SettingsDialog(this, kConfigSkeletonPointer);
1545
1546     // Show the dialog
1547     settingsDialogPointer->show();
1548
1549     // TODO.  KConfigDialog does not respect expanding size policies.  <https://redmine.stoutner.com/issues/823>
1550     //settingsDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1551     //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1552     //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1553     //settingsDialogPointer->adjustSize();
1554
1555     // Expand the config dialog.
1556     settingsDialogPointer->resize(1000, 500);
1557
1558     // Apply the settings handled by KConfig.
1559     connect(settingsDialogPointer, SIGNAL(spellCheckLanguagesUpdated()), tabWidgetPointer, SLOT(applySpellCheckLanguages()));
1560     connect(settingsDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
1561     connect(settingsDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1562 }
1563
1564 QSize BrowserWindow::sizeHint() const
1565 {
1566     // Return the default window size.
1567     return QSize(1500, 1200);
1568 }
1569
1570 void BrowserWindow::toggleBookmark()
1571 {
1572     // Remove the focus from the URL line edit, which will have been focused when the user clicked on the bookmarked icon.
1573     urlLineEditPointer->clearFocus();
1574
1575     // Create or delete the bookmark
1576     if (bookmarkedActionPointer->isChecked())  // The user checked the toggle.  Create a bookmark.
1577     {
1578         // Create a bookmark struct.
1579         BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
1580
1581         // Populate the bookmark struct.
1582         bookmarkStructPointer->name = tabWidgetPointer->getCurrentTabTitle();
1583         bookmarkStructPointer->url = tabWidgetPointer->getCurrentTabUrl();
1584         bookmarkStructPointer->parentFolderId = 0;
1585         bookmarkStructPointer->favoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1586
1587         // Add the bookmark.
1588         BookmarksDatabase::addBookmark(bookmarkStructPointer);
1589     }
1590     else  // The user unchecked the toggle.  Delete all related bookmarks.
1591     {
1592         // Delete the bookmarks.
1593         BookmarksDatabase::deleteBookmarks(urlLineEditPointer->text());
1594
1595
1596     }
1597
1598     // Repopulate the bookmarks.
1599     populateBookmarksInAllWindows();
1600 }
1601
1602 void BrowserWindow::toggleDeveloperTools() const
1603 {
1604     // Toggle the developer tools.
1605     tabWidgetPointer->toggleDeveloperTools(developerToolsActionPointer->isChecked());
1606 }
1607
1608 void BrowserWindow::toggleDomStorage() const
1609 {
1610     // Remove the focus from the URL line edit.
1611     urlLineEditPointer->clearFocus();
1612
1613     // Toggle DOM storage.
1614     tabWidgetPointer->toggleDomStorage();
1615 }
1616
1617 void BrowserWindow::toggleFindCaseSensitive() const
1618 {
1619     // Get the current find string.
1620     const QString findString = findTextLineEditPointer->text();
1621
1622     // Toggle find case sensitive.
1623     tabWidgetPointer->toggleFindCaseSensitive(findString);
1624 }
1625
1626 void BrowserWindow::toggleJavaScript() const
1627 {
1628     // Remove the focus from the URL line edit.
1629     urlLineEditPointer->clearFocus();
1630
1631     // Toggle JavaScript.
1632     tabWidgetPointer->toggleJavaScript();
1633 }
1634
1635 void BrowserWindow::toggleLocalStorage() const
1636 {
1637     // Remove the focus from the URL line edit.
1638     urlLineEditPointer->clearFocus();
1639
1640     // Toggle local storage.
1641     tabWidgetPointer->toggleLocalStorage();
1642 }
1643
1644 void BrowserWindow::toggleFullScreen()
1645 {
1646     // Toggle the full screen status.
1647     fullScreenRequested(fullScreenActionPointer->isChecked());
1648 }
1649
1650 void BrowserWindow::toggleViewSource() const
1651 {
1652     // Get the current URL.
1653     QString url = urlLineEditPointer->text();
1654
1655     // Toggle the URL.
1656     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1657     {
1658         // Remove `view-source:` from the URL.
1659         url = url.remove(0, 12);
1660     }
1661     else  // The source is not currently being viewed.
1662     {
1663         // Prepend `view-source:` from the URL.
1664         url = url.prepend(QLatin1String("view-source:"));
1665     }
1666
1667     // Make it so.
1668     loadUrlFromLineEdit(url);
1669 }
1670
1671 void BrowserWindow::toggleViewBookmarksToolBar()
1672 {
1673     // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
1674     bookmarksToolBarIsVisible = viewBookmarksToolBarActionPointer->isChecked();
1675
1676     // Update the visibility of the bookmarks toolbar.
1677     bookmarksToolBarPointer->setVisible(bookmarksToolBarIsVisible);
1678 }
1679
1680 void BrowserWindow::toggleViewSourceInNewTab() const
1681 {
1682     // Get the current URL.
1683     QString url = urlLineEditPointer->text();
1684
1685     // Toggle the URL.
1686     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1687     {
1688         // Remove `view-source:` from the URL.
1689         url = url.remove(0, 12);
1690     }
1691     else  // The source is not currently being viewed.
1692     {
1693         // Prepend `view-source:` from the URL.
1694         url = url.prepend(QLatin1String("view-source:"));
1695     }
1696
1697     // Add the new tab.  `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab.  `false` does not open a background tab.
1698     tabWidgetPointer->addTab(true, true, false, url);
1699 }
1700
1701 void BrowserWindow::updateBookmarkedAction() const
1702 {
1703     // Update the bookmarked action to reflect the current state.
1704     if (bookmarkedActionPointer->isChecked())
1705         bookmarkedActionPointer->setIcon(QIcon::fromTheme("starred-symbolic"));
1706     else
1707         bookmarkedActionPointer->setIcon(QIcon::fromTheme("non-starred-symbolic"));
1708 }
1709
1710 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
1711 {
1712     // Update the action text.
1713     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1714 }
1715
1716 void BrowserWindow::updateDefaultZoomFactor(const double newDefaultZoomFactorDouble)
1717 {
1718     // Store the new default zoom factor.
1719     defaultZoomFactorDouble = newDefaultZoomFactorDouble;
1720 }
1721
1722 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1723 {
1724     // Set the action checked status.
1725     domStorageActionPointer->setChecked(isEnabled);
1726 }
1727
1728 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1729 {
1730     // Set the domain palette according to the status.
1731     if (status)
1732         urlLineEditPointer->setPalette(positiveBackgroundPalette);
1733     else
1734         urlLineEditPointer->setPalette(normalBackgroundPalette);
1735 }
1736
1737 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1738 {
1739     // Set the text.
1740     findTextLineEditPointer->setText(text);
1741
1742     // Set the find case sensitive action checked status.
1743     findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1744 }
1745
1746 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1747 {
1748     // Update the find text label.
1749     findTextLabelPointer->setText(QStringLiteral("  %1/%2  ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1750
1751     // Set the background color according to the find status.
1752     if (findTextLineEditPointer->text().isEmpty())
1753         findTextLineEditPointer->setPalette(normalBackgroundPalette);
1754     else if (findTextResult.numberOfMatches() == 0)
1755         findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1756     else
1757         findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1758 }
1759
1760 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1761 {
1762     // Update the JavaScript status.
1763     javaScriptEnabled = isEnabled;
1764
1765     // Set the icon according to the status.
1766     if (javaScriptEnabled)
1767         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1768     else
1769         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1770
1771     // Set the action checked status.
1772     javaScriptActionPointer->setChecked(javaScriptEnabled);
1773
1774     // Update the status of the DOM storage action.
1775     domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1776 }
1777
1778 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1779 {
1780     // Update the local storage status.
1781     localStorageEnabled = isEnabled;
1782
1783     // 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.
1784     if (localStorageEnabled)
1785         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/document-save-as.png"))));
1786     else
1787         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1788
1789     // Set the action checked status.
1790     localStorageActionPointer->setChecked(localStorageEnabled);
1791
1792     // Update the status of the DOM storage action.
1793     domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1794 }
1795
1796 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1797 {
1798     // Initialize the custom search engine flag.
1799     bool customSearchEngine = false;
1800
1801     if (searchEngine == "Mojeek")  // Mojeek.
1802     {
1803         // Check the Mojeek user agent action.
1804         searchEngineMojeekActionPointer->setChecked(true);
1805
1806         // Update the search engine menu action icon.
1807         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1808
1809         // Update the search engine menu action text.
1810         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1811     }
1812     else if (searchEngine == "Monocles")  // Monocles.
1813     {
1814         // Check the Monocles user agent action.
1815         searchEngineMonoclesActionPointer->setChecked(true);
1816
1817         // Update the search engine menu action icon.
1818         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1819
1820         // Update the search engine menu action text.
1821         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1822     }
1823     else if (searchEngine == "MetaGer")  // MetaGer.
1824     {
1825         // Check the MetaGer user agent action.
1826         searchEngineMetagerActionPointer->setChecked(true);
1827
1828         // Update the search engine menu action icon.
1829         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1830
1831         // Update the search engine menu action text.
1832         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1833     }
1834     else if (searchEngine == "Google")  // Google.
1835     {
1836         // Check the Google user agent action.
1837         searchEngineGoogleActionPointer->setChecked(true);
1838
1839         // Update the search engine menu action icon.
1840         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
1841
1842         // Update the search engine menu action text.
1843         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
1844     }
1845     else if (searchEngine == "Bing")  // Bing.
1846     {
1847         // Check the Bing user agent action.
1848         searchEngineBingActionPointer->setChecked(true);
1849
1850         // Update the search engine menu action icon.
1851         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1852
1853         // Update the search engine menu action text.
1854         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
1855     }
1856     else if (searchEngine == "Yahoo")  // Yahoo.
1857     {
1858         // Check the Yahoo user agent action.
1859         searchEngineYahooActionPointer->setChecked(true);
1860
1861         // Update the search engine menu action icon.
1862         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
1863
1864         // Update the search engine menu action text.
1865         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
1866     }
1867     else  // Custom search engine.
1868     {
1869         // Check the user agent.
1870         searchEngineCustomActionPointer->setChecked(true);
1871
1872         // Update the search engine menu action icon.
1873         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1874
1875         // Update the search engine menu action text.
1876         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
1877
1878         // Set the custom search engine text.
1879         searchEngineCustomActionPointer->setText(searchEngine);
1880
1881         // Set the custom search engine flag.
1882         customSearchEngine = true;
1883     }
1884
1885     // Update the custom search engine enabled boolean.
1886     if (updateCustomSearchEngineStatus)
1887         customSearchEngineEnabled = customSearchEngine;
1888
1889     // Format the custom search engine.
1890     if (customSearchEngineEnabled)
1891     {
1892         // Enable the custom search engine.
1893         searchEngineCustomActionPointer->setEnabled(true);
1894     }
1895     else
1896     {
1897         // Disable the custom search engine.
1898         searchEngineCustomActionPointer->setEnabled(false);
1899
1900         // Reset the custom search engine text.
1901         searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
1902     }
1903 }
1904
1905 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1906 {
1907     // Get the new URL string in encoded form, which displays punycode.
1908     QString newUrlString = newUrl.toEncoded();
1909
1910     // Update the view source actions.
1911     if (newUrlString.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1912     {
1913         // Mark the view source checkbox.
1914         viewSourceActionPointer->setChecked(true);
1915
1916         // Update the view in new tab action text.
1917         viewSourceInNewTabActionPointer->setText(i18nc("View rendered website in new tab action", "View Rendered Website in New Tab"));
1918     }
1919     else  // The source is not currently being viewed.
1920     {
1921         // Unmark the view source checkbox.
1922         viewSourceActionPointer->setChecked(false);
1923
1924         // Update the view in new tab action text.
1925         viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
1926     }
1927
1928     // Update the URL line edit if it does not have focus.
1929     if (!urlLineEditPointer->hasFocus())
1930     {
1931         // Update the URL line edit.
1932         urlLineEditPointer->setText(newUrlString);
1933
1934         // Set the bookmarked action status.
1935         bookmarkedActionPointer->setChecked(BookmarksDatabase::isBookmarked(newUrlString));
1936
1937         // Update the bookmarked action.
1938         updateBookmarkedAction();
1939
1940         // Set the focus if the new URL is blank.
1941         if (newUrlString == QStringLiteral(""))
1942             urlLineEditPointer->setFocus();
1943     }
1944
1945     // Store the current URL.
1946     currentUrl = newUrl;
1947 }
1948
1949 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
1950 {
1951     // Initialize the custom user agent flag.
1952     bool customUserAgent = false;
1953
1954     // Check the indicated on-the-fly user agent.
1955     if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT)  // Privacy Browser.
1956     {
1957         // Check the Privacy Browser user agent action.
1958         userAgentPrivacyBrowserActionPointer->setChecked(true);
1959
1960         // Update the user agent menu action icon.
1961         userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
1962
1963         // Update the user agent menu action text.
1964         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
1965     }
1966     else if (userAgent == TabWidget::webEngineDefaultUserAgent)  // WebEngine default.
1967     {
1968         // check the WebEngine default user agent action.
1969         userAgentWebEngineDefaultActionPointer->setChecked(true);
1970
1971         // Update the user agent menu action icon.
1972         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1973
1974         // Update the user agent menu action text.
1975         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
1976     }
1977     else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT)  // Firefox on Linux.
1978     {
1979         // Check the Firefox on Linux user agent action.
1980         userAgentFirefoxLinuxActionPointer->setChecked(true);
1981
1982         // Update the user agent menu action icon.
1983         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1984
1985         // Update the user agent menu action text.
1986         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
1987     }
1988     else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT)  // Chromium on Linux.
1989     {
1990         // Check the Chromium on Linux user agent action.
1991         userAgentChromiumLinuxActionPointer->setChecked(true);
1992
1993         // Update the user agent menu action icon.
1994         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1995
1996         // Update the user agent menu action text.
1997         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
1998     }
1999     else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT)  // Firefox on Windows.
2000     {
2001         // Check the Firefox on Windows user agent action.
2002         userAgentFirefoxWindowsActionPointer->setChecked(true);
2003
2004         // Update the user agent menu action icon.
2005         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2006
2007         // Update the user agent menu action text.
2008         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
2009     }
2010     else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT)  // Chrome on Windows.
2011     {
2012         // Check the Chrome on Windows user agent action.
2013         userAgentChromeWindowsActionPointer->setChecked(true);
2014
2015         // Update the user agent menu action icon.
2016         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2017
2018         // Update the user agent menu action text.
2019         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
2020     }
2021     else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT)  // Edge on Windows.
2022     {
2023         // Check the Edge on Windows user agent action.
2024         userAgentEdgeWindowsActionPointer->setChecked(true);
2025
2026         // Update the user agent menu action icon.
2027         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2028
2029         // Update the user agent menu action text.
2030         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
2031     }
2032     else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT)  // Safari on macOS.
2033     {
2034         // Check the Safari on macOS user agent action.
2035         userAgentSafariMacosActionPointer->setChecked(true);
2036
2037         // Update the user agent menu action icon.
2038         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2039
2040         // Update the user agent menu action text.
2041         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
2042     }
2043     else  // Custom user agent.
2044     {
2045         // Check the user agent.
2046         userAgentCustomActionPointer->setChecked(true);
2047
2048         // Update the user agent menu action icon.
2049         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2050
2051         // Update the user agent menu action text.
2052         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
2053
2054         // Set the custom user agent text.
2055         userAgentCustomActionPointer->setText(userAgent);
2056
2057         // Set the custom user agent flag.
2058         customUserAgent = true;
2059     }
2060
2061     // Update the custom user agent enabled boolean.
2062     // 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.
2063     if (updateCustomUserAgentStatus)
2064         customUserAgentEnabled = customUserAgent;
2065
2066
2067     // Format the custom user agent.
2068     if (customUserAgentEnabled)
2069     {
2070         // Enable the custom user agent.
2071         userAgentCustomActionPointer->setEnabled(true);
2072     }
2073     else
2074     {
2075         // Disable the custom user agent.
2076         userAgentCustomActionPointer->setEnabled(false);
2077
2078         // Reset the custom user agent text.
2079         userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
2080     }
2081 }
2082
2083 void BrowserWindow::updateViewBookmarksToolBarCheckbox(const bool visible)
2084 {
2085     // Update the view bookmarks toolbar checkbox.
2086     viewBookmarksToolBarActionPointer->setChecked(visible);
2087
2088     // Initialize the bookmarks toolbar visibility tracker if Privacy Browser has just launched.
2089     if (bookmarksToolBarUninitialized)
2090     {
2091         // Set the initialization flag.
2092         bookmarksToolBarUninitialized = false;
2093
2094         // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
2095         bookmarksToolBarIsVisible = visible;
2096     }
2097 }
2098
2099 void BrowserWindow::updateWindowTitle(const QString &title)
2100 {
2101     // Update the window title.
2102     setWindowTitle(title);
2103 }
2104
2105 void BrowserWindow::updateZoomActions(const double zoomFactorDouble)
2106 {
2107     // Set the current zoom factor.
2108     currentZoomFactorDouble = zoomFactorDouble;
2109
2110     // Set the status of the default zoom action.
2111     zoomDefaultActionPointer->setEnabled(currentZoomFactorDouble != defaultZoomFactorDouble);
2112
2113     // Set the status of the zoom in action and button.
2114     zoomInActionPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2115     zoomPlusButtonPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2116
2117     // Set the status of the zoom out action and button.
2118     zoomMinusButtonPointer->setEnabled(currentZoomFactorDouble > 0.25);
2119     zoomOutActionPointer->setEnabled(currentZoomFactorDouble > 0.25);
2120
2121
2122     // 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.
2123     zoomFactorActionPointer->setText(ki18nc("The zoom factor action", "Zoom Factor - %1").subs(zoomFactorDouble, 0, '0', 2).toString());
2124
2125     // Update the status bar zoom factor label.
2126     currentZoomButtonPointer->setText(ki18nc("The status bar zoom, which is just the formatted zoom factor", "%1").subs(zoomFactorDouble, 0, '0', 2).toString());
2127 }
2128
2129 void BrowserWindow::zoomDefault()
2130 {
2131     // Set the new zoom factor.
2132     tabWidgetPointer->applyOnTheFlyZoomFactor(defaultZoomFactorDouble);
2133
2134     // Update the on-the-fly action text.
2135     updateZoomActions(defaultZoomFactorDouble);
2136 }