]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/windows/BrowserWindow.cpp
Create new domain settings with the currently applied settings. https://redmine...
[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 "ui_SettingsGeneral.h"
24 #include "ui_SettingsPrivacy.h"
25 #include "ui_SettingsSpellCheck.h"
26 #include "databases/BookmarksDatabase.h"
27 #include "databases/DomainsDatabase.h"
28 #include "dialogs/AddBookmarkDialog.h"
29 #include "dialogs/AddFolderDialog.h"
30 #include "dialogs/BookmarksDialog.h"
31 #include "dialogs/CookiesDialog.h"
32 #include "dialogs/DomainSettingsDialog.h"
33 #include "dialogs/EditBookmarkDialog.h"
34 #include "dialogs/EditFolderDialog.h"
35 #include "helpers/SearchEngineHelper.h"
36 #include "helpers/UserAgentHelper.h"
37 #include "structs/BookmarkStruct.h"
38
39 // KDE Frameworks headers.
40 #include <KActionCollection>
41 #include <KColorScheme>
42 #include <KXMLGUIFactory>
43
44 // Qt toolkit headers.
45 #include <QClipboard>
46 #include <QContextMenuEvent>
47 #include <QDBusConnection>
48 #include <QDBusConnectionInterface>
49 #include <QDBusMessage>
50 #include <QFileDialog>
51 #include <QInputDialog>
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 KLineEdit();
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 current bookmarks lists.
547     finalBookmarkFolderMenuActionList = 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 void BrowserWindow::addFinalBookmarkFolderMenuActions(QMenu *menuPointer, double folderId)
584 {
585     // Get the database ID.
586     int folderDatabaseId = BookmarksDatabase::getFolderDatabaseId(folderId);
587
588     // Add a separator.
589     menuPointer->addSeparator();
590
591     // Add the add bookmark action to the menu.
592     QAction *addBookmarkActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("bookmark-new")), i18nc("The add bookmark action", "Add Bookmark"), [=]
593         {
594             // Instantiate an add bookmark dialog.
595             AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(),
596                                                                                 tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
597
598             // Update the displayed bookmarks when a new one is added.
599             connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(populateBookmarksInAllWindows()));
600
601             // Show the dialog.
602             addBookmarkDialogPointer->show();
603         }
604     );
605
606     // Add the add folder action to the menu.
607     QAction *addFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("folder-add")), i18nc("The add folder action", "Add Folder"), [=]
608         {
609             // Instantiate an add folder dialog.
610             AddFolderDialog *addFolderDialogPointer = new AddFolderDialog(tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
611
612             // Update the displayed bookmarks when a folder is added.
613             connect(addFolderDialogPointer, SIGNAL(folderAdded()), this, SLOT(populateBookmarksInAllWindows()));
614
615             // Show the dialog.
616             addFolderDialogPointer->show();
617         }
618     );
619
620     // Add a separator.
621     menuPointer->addSeparator();
622
623     // Add the open folder in new tabs action to the menu.
624     QAction *openFolderInNewTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("The open folder in new tabs action", "Open Folder in New Tabs"), [=]
625         {
626             // Get all the folder URLs.
627             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
628
629             // 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.
630             for (QString url : *folderUrlsListPointer)
631                 tabWidgetPointer->addTab(true, true, false, url);
632         }
633     );
634
635     // Add the open folder in background tabs action to the menu.
636     QAction *openFolderInBackgroundTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")),
637                                                                               i18nc("The open folder in background tabs action", "Open Folder in Background Tabs"), [=]
638         {
639             // Get all the folder URLs.
640             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
641
642             // 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.
643             for (QString url : *folderUrlsListPointer)
644                 tabWidgetPointer->addTab(true, true, true, url);
645         }
646     );
647
648     // Add the open folder in new window action to the menu.
649     QAction *openFolderInNewWindowActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("The open folder in new window action", "Open Folder in New Window"), [=]
650         {
651             // Get all the folder URLs.
652             QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
653
654             // Create a new browser window.
655             BrowserWindow *browserWindowPointer = new BrowserWindow(false, &folderUrlsListPointer->first());
656
657             // Get a count of the folder URLs.
658             const int folderUrls = folderUrlsListPointer->count();
659
660             // 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.
661             for (int i = 1; i < folderUrls; ++i)
662                 browserWindowPointer->tabWidgetPointer->addTab(true, false, true, folderUrlsListPointer->value(i));
663
664             // Show the new browser window.
665             browserWindowPointer->show();
666         }
667     );
668
669     // Add a separator.
670     menuPointer->addSeparator();
671
672     // Add the edit folder action to the menu if this is not the root bookmark menu.
673     if (folderId != 0)
674     {
675         QAction *editFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("The edit folder action", "Edit Folder"), [=]
676             {
677                 // Get the current tab favorite icon.
678                 QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
679
680                 // Instantiate an edit folder dialog.
681                 QDialog *editFolderDialogPointer = new EditFolderDialog(folderDatabaseId, currentTabFavoriteIcon);
682
683                 // Show the dialog.
684                 editFolderDialogPointer->show();
685
686                 // Process bookmark events.
687                 connect(editFolderDialogPointer, SIGNAL(folderSaved()), this, SLOT(populateBookmarksInAllWindows()));
688             }
689         );
690
691         // Add the action to the beginning of the final bookmark folder menu action list.
692         finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, editFolderActionPointer));
693     }
694
695     // Add the delete folder action to the menu.
696     QAction *deleteFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete folder context menu entry", "Delete Folder"), [=]
697         {
698             // Create an items to delete list.
699             QList<int>* itemsToDeleteListPointer = new QList<int>;
700
701             // Add the folder to the list of items to delete if it is not the root folder.
702             if (folderId != 0)
703                 itemsToDeleteListPointer->append(folderDatabaseId);
704
705             // Add the folder contents to the list of items to delete.
706             itemsToDeleteListPointer->append(*BookmarksDatabase::getFolderContentsDatabaseIdsRecursively(folderId));
707
708             // Instantiate a delete dialog message box.
709             QMessageBox deleteDialogMessageBox;
710
711             // Set the icon.
712             deleteDialogMessageBox.setIcon(QMessageBox::Warning);
713
714             // Set the window title.
715             deleteDialogMessageBox.setWindowTitle(i18nc("Delete bookmarks dialog title", "Delete Bookmarks"));
716
717             // Set the text.
718             deleteDialogMessageBox.setText(i18ncp("Delete bookmarks dialog main message", "Delete %1 bookmark item?", "Delete %1 bookmark items?", itemsToDeleteListPointer->count()));
719
720             // Set the informative text.
721             deleteDialogMessageBox.setInformativeText(i18nc("Delete bookmarks dialog secondary message", "This cannot be undone."));
722
723             // Set the standard buttons.
724             deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
725
726             // Set the default button.
727             deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
728
729             // Display the dialog and capture the return value.
730             int returnValue = deleteDialogMessageBox.exec();
731
732             // Delete the domain if instructed.
733             if (returnValue == QMessageBox::Yes)
734             {
735                 // Get the parent folder ID.
736                 double parentFolderId = BookmarksDatabase::getParentFolderId(folderDatabaseId);
737
738                 // Delete the folder and its contents.
739                 for (const int databaseId : *itemsToDeleteListPointer)
740                     BookmarksDatabase::deleteBookmark(databaseId);
741
742                 // Update the display order of the bookmarks in the parent folder.
743                 BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
744
745                 // Repopulate the bookmarks.
746                 populateBookmarksInAllWindows();
747             }
748         }
749     );
750
751     // Add the key sequences if this is the root bookmarks menu.
752     if (folderId == 0)
753     {
754         // Create the key sequences.
755         QKeySequence ctrlBKeySequence = QKeySequence(i18nc("The add bookmark key sequence.", "Ctrl+B"));
756         QKeySequence metaFKeySequence = QKeySequence(i18nc("The add folder key sequence.", "Meta+F"));
757
758         // Set the action key sequences.
759         actionCollectionPointer->setDefaultShortcut(addBookmarkActionPointer, ctrlBKeySequence);
760         actionCollectionPointer->setDefaultShortcut(addFolderActionPointer, metaFKeySequence);
761     }
762
763     // Add the actions to the beginning of the final bookmark folder menu action list.
764     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addBookmarkActionPointer));
765     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addFolderActionPointer));
766     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewTabsActionPointer));
767     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInBackgroundTabsActionPointer));
768     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewWindowActionPointer));
769     finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, deleteFolderActionPointer));
770 }
771
772 void BrowserWindow::addOrEditDomainSettings() const
773 {
774     // Remove the focus from the URL line edit.
775     urlLineEditPointer->clearFocus();
776
777     // Get the current domain settings name.
778     QString &currentDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
779
780     // Run the commands according to the current domain settings status.
781     if (currentDomainSettingsName == QStringLiteral(""))  // Domain settings are not currently applied.
782     {
783         // Get the current settings status.
784         int javaScriptInt = calculateSettingsInt(javaScriptEnabled, Settings::javaScriptEnabled());
785         int localStorageInt = calculateSettingsInt(localStorageActionPointer->isChecked(), Settings::localStorageEnabled());
786         int domStorageInt = calculateSettingsInt(domStorageActionPointer->isChecked(), Settings::domStorageEnabled());
787
788         // Get the current user agent string.
789         QString currentUserAgentString = tabWidgetPointer->getCurrentUserAgent();
790
791         // Get the current user agent database string.
792         QString currentUserAgentDatabaseString = UserAgentHelper::getDatabaseUserAgentNameFromUserAgent(currentUserAgentString);
793
794         // Initialize the user agent database string.
795         QString userAgentDatabaseString = UserAgentHelper::SYSTEM_DEFAULT_DATABASE;
796
797         // Replace the user agent database string if the current user agent is not the default.
798         if (currentUserAgentDatabaseString != Settings::userAgent())
799             userAgentDatabaseString = currentUserAgentDatabaseString;
800
801         // Initialize the zoom factor variables.
802         int zoomFactorInt = DomainsDatabase::SYSTEM_DEFAULT;
803
804         // Use a custom zoom factor if currently applied.  Doubles cannot be reliably compared using `==`, so a mathematical workaround is used.
805         if (abs(currentZoomFactorDouble - defaultZoomFactorDouble ) > 0.01)
806             zoomFactorInt = DomainsDatabase::CUSTOM;
807
808         // Add the domain.
809         DomainsDatabase::addDomain(currentUrl.host(), javaScriptInt, localStorageInt, domStorageInt, userAgentDatabaseString, zoomFactorInt, currentZoomFactorDouble);
810
811         // Apply the domain settings.
812         tabWidgetPointer->applyDomainSettingsAndReload();
813     }
814
815     // Create the domain settings dialog pointer.
816     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
817
818     // Reload the tabs when domain settings are updated.
819     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
820
821     // Show the dialog.
822     domainSettingsDialogPointer->show();
823 }
824
825 void BrowserWindow::back() const
826 {
827     // Remove the focus from the URL line edit.
828     urlLineEditPointer->clearFocus();
829
830     // Go back.
831     tabWidgetPointer->back();
832 }
833
834 int BrowserWindow::calculateSettingsInt(const bool settingCurrentlyEnabled, const bool settingEnabledByDefault) const
835 {
836     // Return the int that matches the current state.
837     if (settingCurrentlyEnabled == settingEnabledByDefault)  // The current system default is used.
838         return DomainsDatabase::SYSTEM_DEFAULT;
839     else if (settingCurrentlyEnabled)  // The setting is enabled, which is different from the system default.
840         return DomainsDatabase::ENABLED;
841     else  // The setting is disabled, which is different from the system default.
842         return DomainsDatabase::DISABLED;
843 }
844
845 void BrowserWindow::clearUrlLineEditFocus() const
846 {
847     // Remove the focus from the URL line edit.
848     urlLineEditPointer->clearFocus();
849 }
850
851 void BrowserWindow::decrementZoom()
852 {
853     // Update the current zoom factor.
854     currentZoomFactorDouble = currentZoomFactorDouble - 0.25;
855
856     // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
857     if (currentZoomFactorDouble < 0.25)
858         currentZoomFactorDouble = 0.25;
859
860     // Set the new zoom factor.
861     tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
862
863     // Update the on-the-fly action text.
864     updateZoomActions(currentZoomFactorDouble);
865 }
866
867 void BrowserWindow::editBookmarks() const
868 {
869     // Instantiate an edit bookmarks dialog.
870     BookmarksDialog *bookmarksDialogPointer = new BookmarksDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(), tabWidgetPointer->getCurrentTabFavoritIcon());
871
872     // Update the displayed bookmarks when edited.
873     connect(bookmarksDialogPointer, SIGNAL(bookmarkUpdated()), this, SLOT(populateBookmarksInAllWindows()));
874
875     // Show the dialog.
876     bookmarksDialogPointer->show();
877 }
878
879 void BrowserWindow::escape() const
880 {
881     // Process the escape according to the status of the browser.
882     if (fullScreenActionPointer->isChecked())  // Full screen browsing is enabled.
883     {
884         // Exit full screen browsing.
885         fullScreenActionPointer->trigger();
886     }
887     else if (!findTextLineEditPointer->text().isEmpty())  // Find text is populated.
888     {
889         // Clear the find text line edit.
890         findTextLineEditPointer->clear();
891
892         // Clear the search in the WebEngine.
893         tabWidgetPointer->findText(QStringLiteral(""));
894     }
895     else if (findTextLineEditActionPointer->isVisible())  // Find text actions are visible.
896     {
897         // Hide the find text actions.
898         hideFindTextActions();
899     }
900 }
901
902 void BrowserWindow::findNext() const
903 {
904     // Get the find string.
905     const QString findString = findTextLineEditPointer->text();
906
907     // Search for the text if it is not empty.
908     if (!findString.isEmpty())
909         tabWidgetPointer->findText(findString);
910 }
911
912 void BrowserWindow::findPrevious() const
913 {
914     // Get the find string.
915     const QString findString = findTextLineEditPointer->text();
916
917     // Search for the text if it is not empty.
918     if (!findString.isEmpty())
919         tabWidgetPointer->findPrevious(findString);
920 }
921
922 void BrowserWindow::forward() const
923 {
924     // Remove the focus from the URL line edit.
925     urlLineEditPointer->clearFocus();
926
927     // Go forward.
928     tabWidgetPointer->forward();
929 }
930
931 void BrowserWindow::fullScreenRequested(const bool toggleOn)
932 {
933     // Toggle full screen mode.
934     if (toggleOn)  // Turn full screen mode on.
935     {
936         // Enable full screen mode.
937         fullScreenActionPointer->setFullScreen(window(), true);
938
939         // Hide the menu bar if specified.
940         if (Settings::fullScreenHideMenuBar())
941             menuBar()->setVisible(false);
942
943         // Hide the toolbars if specified.
944         if (Settings::fullScreenHideToolBars())
945         {
946             navigationToolBarPointer->setVisible(false);
947             urlToolBarPointer->setVisible(false);
948             bookmarksToolBarPointer->setVisible(false);
949         }
950
951         // Hide the tab bar if specified.
952         if (Settings::fullScreenHideTabBar())
953             tabWidgetPointer->setTabBarVisible(false);
954
955         // Hide the status bar if specified.
956         if (Settings::fullScreenHideStatusBar())
957             statusBar()->setVisible(false);
958     }
959     else  // Disable full screen browsing mode.
960     {
961         // Disable full screen mode.
962         fullScreenActionPointer->setFullScreen(window(), false);
963
964         // Show the menu bar.
965         menuBar()->setVisible(true);
966
967         // Show the toolbars.
968         navigationToolBarPointer->setVisible(true);
969         urlToolBarPointer->setVisible(true);
970
971         // Only show the bookmarks toolbar if it was previously visible.
972         if (bookmarksToolBarIsVisible)
973             bookmarksToolBarPointer->setVisible(true);
974
975         // Show the tab bar.
976         tabWidgetPointer->setTabBarVisible(true);
977
978         // Show the status bar.
979         statusBar()->setVisible(true);
980     }
981 }
982
983 void BrowserWindow::getZoomFactorFromUser()
984 {
985     // Create an OK flag.
986     bool okClicked;
987
988     // 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.
989     double newZoomFactorDouble = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
990                                                    i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
991                                                    currentZoomFactorDouble, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
992
993     // Update the zoom factor if the user clicked OK.
994     if (okClicked)
995     {
996         // Set the new zoom factor.
997         tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactorDouble);
998
999         // Update the on-the-fly action text.
1000         updateZoomActions(newZoomFactorDouble);
1001     }
1002 }
1003
1004 void BrowserWindow::hideFindTextActions() const
1005 {
1006     // Hide the find text actions.
1007     findTextLineEditActionPointer->setVisible(false);
1008     findTextLabelActionPointer->setVisible(false);
1009     findNextActionPointer->setVisible(false);
1010     findPreviousActionPointer->setVisible(false);
1011     findCaseSensitiveActionPointer->setVisible(false);
1012     hideFindTextActionPointer->setVisible(false);
1013 }
1014
1015 void BrowserWindow::home() const
1016 {
1017     // Remove the focus from the URL line edit.
1018     urlLineEditPointer->clearFocus();
1019
1020     // Go home.
1021     tabWidgetPointer->home();
1022 }
1023
1024 void BrowserWindow::hideProgressBar() const
1025 {
1026     // Hide the progress bar.
1027     progressBarPointer->hide();
1028
1029     // Disable and hide the stop action.
1030     stopActionPointer->setEnabled(false);
1031     stopActionPointer->setVisible(false);
1032
1033     // Enable and show the refresh action.
1034     refreshActionPointer->setEnabled(true);
1035     refreshActionPointer->setVisible(true);
1036 }
1037
1038 void BrowserWindow::incrementZoom()
1039 {
1040     // Update the current zoom factor.
1041     currentZoomFactorDouble = currentZoomFactorDouble + 0.25;
1042
1043     // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
1044     if (currentZoomFactorDouble > 5.0)
1045         currentZoomFactorDouble = 5.0;
1046
1047     // Set the new zoom factor.
1048     tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
1049
1050     // Update the on-the-fly action text.
1051     updateZoomActions(currentZoomFactorDouble);
1052 }
1053
1054 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
1055 {
1056     // Remove the focus from the URL line edit.
1057     urlLineEditPointer->clearFocus();
1058
1059     // Load the URL.
1060     tabWidgetPointer->loadUrlFromLineEdit(url);
1061 }
1062
1063 void BrowserWindow::newWindow() const
1064 {
1065     // Create a new browser window.
1066     BrowserWindow *browserWindowPointer = new BrowserWindow();
1067
1068     // Show the new browser window.
1069     browserWindowPointer->show();
1070 }
1071
1072 void BrowserWindow::populateBookmarksInAllWindows() const
1073 {
1074     // Get a list of all the registered service names.
1075     QStringList registeredServiceNames = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
1076
1077     // Get a list of all the Privacy Browser windows, which will be `com.stoutner.privacybrowser-` with the PID appended.
1078     QStringList privacyBrowserServiceNames = registeredServiceNames.filter("com.stoutner.privacybrowser");
1079
1080     // Repopulate the bookmarks in each window.
1081     for (QString privacyBrowserServiceName : privacyBrowserServiceNames)
1082     {
1083         // Prepare the D-Bus message.
1084         QDBusMessage dBusMessage = QDBusMessage::createMethodCall(privacyBrowserServiceName, "/privacybrowser/MainWindow_1", "com.stoutner.privacybrowser.BrowserWindow", "populateBookmarksInThisWindow");
1085
1086         // Make it so.
1087         QDBusConnection::sessionBus().send(dBusMessage);
1088     }
1089 }
1090
1091 void BrowserWindow::populateBookmarksInThisWindow()
1092 {
1093     // Remove all the final bookmark folder menu actions.
1094     for (QPair<QMenu *, QAction *> *finalBookmarkFolderMenuActionPair : finalBookmarkFolderMenuActionList)
1095     {
1096         // Remove the action.
1097         finalBookmarkFolderMenuActionPair->first->removeAction(finalBookmarkFolderMenuActionPair->second);
1098     }
1099
1100     // Remove all the current menu bookmarks.
1101     for (QPair<QMenu *, QAction *> *bookmarkMenuActionPairPointer : bookmarksMenuActionList)
1102     {
1103         // Remove the bookmark.
1104         bookmarkMenuActionPairPointer->first->removeAction(bookmarkMenuActionPairPointer->second);
1105     }
1106
1107     // Remove all the current menu subfolders.
1108     for (QPair<QMenu *, QMenu *> *submenuPairPointer : bookmarksMenuSubmenuList)
1109     {
1110         // Remove the submenu from the parent menu.
1111         submenuPairPointer->first->removeAction(submenuPairPointer->second->menuAction());
1112     }
1113
1114     // Remove all the current toolbar subfolders.
1115     for (QPair<QMenu *, QAction *> *subfolderActionPairPointer : bookmarksToolBarSubfolderActionList)
1116     {
1117         // Remove the action from the subfolder.
1118         subfolderActionPairPointer->first->removeAction(subfolderActionPairPointer->second);
1119     }
1120
1121     // Remove all the current toolbar bookmarks.
1122     for (QAction *bookmarkAction : bookmarksToolBarActionList)
1123     {
1124         // Remove the bookmark.
1125         bookmarksToolBarPointer->removeAction(bookmarkAction);
1126     }
1127
1128     // Clear the current bookmark lists.
1129     bookmarksMenuActionList.clear();
1130     bookmarksMenuSubmenuList.clear();
1131     bookmarksToolBarActionList.clear();
1132     bookmarksToolBarSubfolderActionList.clear();
1133
1134     // Populate the bookmarks subfolders, beginning with the root folder (`0`);
1135     populateBookmarksMenuSubfolders(0, bookmarksMenuPointer);
1136
1137     // Populate the bookmarks toolbar.
1138     populateBookmarksToolBar();
1139
1140     // Get a handle for the bookmark toolbar layout.
1141     QLayout *bookmarksToolBarLayoutPointer = bookmarksToolBarPointer->layout();
1142
1143     // Get the count of the bookmarks.
1144     int bookmarkCount = bookmarksToolBarLayoutPointer->count();
1145
1146     // Set the layout of each bookmark to be left aligned.
1147     for(int i = 0; i < bookmarkCount; ++i)
1148         bookmarksToolBarLayoutPointer->itemAt(i)->setAlignment(Qt::AlignLeft);
1149
1150     // Update the bookmarked action.
1151     updateBookmarkedAction();
1152 }
1153
1154 void BrowserWindow::populateBookmarksMenuSubfolders(const double folderId, QMenu *menuPointer)
1155 {
1156     // Get the folder contents.
1157     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1158
1159     // Populate the bookmarks menu and toolbar.
1160     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1161     {
1162         // Process the item according to the type.
1163         if (bookmarkStruct.isFolder)  // This item is a folder.
1164         {
1165             // Add a submenu to the menu.
1166             QMenu *submenuPointer = menuPointer->addMenu(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1167
1168             // Add the submenu to the beginning of the list of menus to be deleted on repopulate.
1169             bookmarksMenuSubmenuList.prepend(new QPair<QMenu *, QMenu *>(menuPointer, submenuPointer));
1170
1171             // Populate any subfolders.
1172             populateBookmarksMenuSubfolders(bookmarkStruct.folderId, submenuPointer);
1173         }
1174         else  // This item is a bookmark.
1175         {
1176             // Add the bookmark to the menu.
1177             QAction *menuBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1178                 {
1179                     // Remove the focus from the URL line edit.
1180                     urlLineEditPointer->clearFocus();
1181
1182                     // Load the URL.
1183                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1184                 }
1185             );
1186
1187             // Add the actions to the beginning of the list of bookmarks to be deleted on repopulate.
1188             bookmarksMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, menuBookmarkActionPointer));
1189         }
1190     }
1191
1192     // Add the extra items at the bottom of the menu.
1193     addFinalBookmarkFolderMenuActions(menuPointer, folderId);
1194 }
1195
1196 void BrowserWindow::populateBookmarksToolBar()
1197 {
1198     // Get the root folder contents (which has a folder ID of `0`).
1199     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(0);
1200
1201     // Populate the bookmarks toolbar.
1202     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1203     {
1204         // Process the item according to the type.
1205         if (bookmarkStruct.isFolder)  // This item is a folder.
1206         {
1207             // Add the subfolder action.
1208             QAction *toolBarSubfolderActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1209
1210             // Add the bookmark database ID to the toolbar action.
1211             toolBarSubfolderActionPointer->setData(bookmarkStruct.databaseId);
1212
1213             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1214             bookmarksToolBarActionList.prepend(toolBarSubfolderActionPointer);
1215
1216             // Create a subfolder menu.
1217             QMenu *subfolderMenuPointer = new QMenu();
1218
1219             // Add the menu to the action.
1220             toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1221
1222             // Add the submenu to the toolbar menu list.
1223             bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1224
1225             // Set the popup mode for the menu.
1226             dynamic_cast<QToolButton *>(bookmarksToolBarPointer->widgetForAction(toolBarSubfolderActionPointer))->setPopupMode(QToolButton::InstantPopup);
1227
1228             // Populate the subfolder.
1229             populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1230         }
1231         else  // This item is a bookmark.
1232         {
1233             // Add the bookmark to the toolbar.
1234             QAction *toolBarBookmarkActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1235                 {
1236                     // Remove the focus from the URL line edit.
1237                     urlLineEditPointer->clearFocus();
1238
1239                     // Load the URL.
1240                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1241                 }
1242             );
1243
1244             // Add the bookmark database ID to the toolbar action.
1245             toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1246
1247             // Add the actions to the beginning of the current bookmarks lists.
1248             bookmarksToolBarActionList.prepend(toolBarBookmarkActionPointer);
1249         }
1250     }
1251
1252     // 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.
1253     for (QPair<QMenu *, const double> *menuAndFolderIdPairPointer : bookmarksToolBarMenuList)
1254     {
1255         // Populate the final bookmarks menu entries.
1256         addFinalBookmarkFolderMenuActions(menuAndFolderIdPairPointer->first, menuAndFolderIdPairPointer->second);
1257     }
1258 }
1259
1260 void BrowserWindow::populateBookmarksToolBarSubfolders(const double folderId, QMenu *menuPointer)
1261 {
1262     // Get the folder contents.
1263     QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1264
1265     // Populate the bookmarks folder.
1266     for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1267     {
1268         // Get the bookmark URL.
1269         QString bookmarkUrl = bookmarkStruct.url;
1270
1271         // Process the item according to the type.
1272         if (bookmarkStruct.isFolder)  // This item is a folder.
1273         {
1274             // Add the subfolder action.
1275             QAction *toolBarSubfolderActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1276
1277             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1278             bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarSubfolderActionPointer));
1279
1280             // Create a subfolder menu.
1281             QMenu *subfolderMenuPointer = new QMenu();
1282
1283             // Add the submenu to the action.
1284             toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1285
1286             // Add the submenu to the toolbar menu list.
1287             bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1288
1289             // Populate the subfolder menu.
1290             populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1291         }
1292         else  // This item is a bookmark.
1293         {
1294             // Add the bookmark to the folder.
1295             QAction *toolBarBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1296                 {
1297                     // Remove the focus from the URL line edit.
1298                     urlLineEditPointer->clearFocus();
1299
1300                     // Load the URL.
1301                     tabWidgetPointer->loadUrlFromLineEdit(bookmarkUrl);
1302                 }
1303             );
1304
1305             // Add the bookmark database ID to the toolbar action.
1306             toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1307
1308             // Add the action to the beginning of the list of actions to be deleted on repopulate.
1309             bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarBookmarkActionPointer));
1310         }
1311     }
1312 }
1313
1314 void BrowserWindow::refresh() const
1315 {
1316     // Remove the focus from the URL line edit.
1317     urlLineEditPointer->clearFocus();
1318
1319     // Refresh the web page.
1320     tabWidgetPointer->refresh();
1321 }
1322
1323 void BrowserWindow::reloadAndBypassCache() const
1324 {
1325     // Remove the focus from the URL line edit.
1326     urlLineEditPointer->clearFocus();
1327
1328     // Refresh the web page.
1329     tabWidgetPointer->refresh();
1330 }
1331
1332 void BrowserWindow::showBookmarkContextMenu(const QPoint &point)
1333 {
1334     // Get the bookmark action.
1335     QAction *bookmarkActionPointer = bookmarksToolBarPointer->actionAt(point);
1336
1337     // Check to see if an action was clicked.
1338     if (bookmarkActionPointer)  // An action was clicked.
1339     {
1340         // Create a bookmark context menu.
1341         QMenu *bookmarkContextMenuPointer = new QMenu();
1342
1343         // Get the database ID from the action.
1344         int databaseId = bookmarkActionPointer->data().toInt();
1345
1346         // Create the menu according to the type.
1347         if (BookmarksDatabase::isFolder(databaseId))  // A folder was clicked.
1348         {
1349             // Populate the final bookmarks menu entries.
1350             addFinalBookmarkFolderMenuActions(bookmarkContextMenuPointer, BookmarksDatabase::getFolderId(databaseId));
1351         }
1352         else  // A bookmark was clicked.
1353         {
1354             // Add the open in new tab action to the menu.
1355             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in new tab context menu entry", "Open in New Tab"), [=]
1356                 {
1357                     // Get the bookmark.
1358                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1359
1360                     // 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.
1361                     tabWidgetPointer->addTab(true, true, false, bookmarkStructPointer->url);
1362                 }
1363             );
1364
1365             // Add the open in background tab action to the menu.
1366             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in background tab context menu entry", "Open in Background Tab"), [=]
1367                 {
1368                     // Get the bookmark.
1369                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1370
1371                     // 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.
1372                     tabWidgetPointer->addTab(true, true, true, bookmarkStructPointer->url);
1373                 }
1374             );
1375
1376             // Add the open in new window action to the menu.
1377             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("Open bookmark in new window context menu entry", "Open in New Window"), [=]
1378                 {
1379                     // Get the bookmark.
1380                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1381
1382                     // Create a new browser window and load the first URL.  `false` indicates it is not the first browser window.
1383                     BrowserWindow *browserWindowPointer = new BrowserWindow(false, &bookmarkStructPointer->url);
1384
1385                     // Show the new browser window.
1386                     browserWindowPointer->show();
1387                 }
1388             );
1389
1390             // Add a separator.
1391             bookmarkContextMenuPointer->addSeparator();
1392
1393             // Add the edit action to the menu.
1394             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("Edit bookmark context menu entry", "Edit"), [=]
1395                 {
1396                     // Get the current tab favorite icon.
1397                     QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1398
1399                     // Instantiate an edit bookmark dialog.
1400                     QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(databaseId, currentTabFavoriteIcon);
1401
1402                     // Show the dialog.
1403                     editBookmarkDialogPointer->show();
1404
1405                     // Process bookmark events.
1406                     connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(populateBookmarksInAllWindows()));
1407                 }
1408             );
1409
1410             // Add the copy URL action to the menu.
1411             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18nc("Copy bookmark URL context menu entry", "Copy URL"), [=]
1412                 {
1413                     // Get the bookmark.
1414                     BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1415
1416                     // Get a handle for the clipboard.
1417                     QClipboard *clipboard = QGuiApplication::clipboard();
1418
1419                     // Place the URL on the keyboard.
1420                     clipboard->setText(bookmarkStructPointer->url);
1421                 }
1422             );
1423
1424             // Add a separator.
1425             bookmarkContextMenuPointer->addSeparator();
1426
1427             // Add the delete action to the menu.
1428             bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete bookmark context menu entry", "Delete"), [=]
1429                 {
1430                     // Get the parent folder ID.
1431                     double parentFolderId = BookmarksDatabase::getParentFolderId(databaseId);
1432
1433                     // Delete the bookmark.
1434                     BookmarksDatabase::deleteBookmark(databaseId);
1435
1436                     // Update the display order of the bookmarks in the parent folder.
1437                     BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
1438
1439                     // Repopulate the bookmarks.
1440                     populateBookmarksInAllWindows();
1441                 }
1442             );
1443         }
1444
1445         // Delete the menu from memory when it is closed.
1446         bookmarkContextMenuPointer->setAttribute(Qt::WA_DeleteOnClose);
1447
1448         // Display the context menu.
1449         bookmarkContextMenuPointer->popup(bookmarksToolBarPointer->mapToGlobal(point));
1450     }
1451     else  // The toolbar background was clicked.
1452     {
1453         // Temporarily set the context menu policy to the default.
1454         bookmarksToolBarPointer->setContextMenuPolicy(Qt::DefaultContextMenu);
1455
1456         // Create a context menu event with the same position.
1457         QContextMenuEvent *contextMenuEventPointer = new QContextMenuEvent(QContextMenuEvent::Mouse, point);
1458
1459         // Send the context menu event to the toolbar.
1460         QCoreApplication::sendEvent(bookmarksToolBarPointer, contextMenuEventPointer);
1461
1462         // Reset the context menu policy.
1463         bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
1464     }
1465 }
1466
1467 void BrowserWindow::showCookiesDialog()
1468 {
1469     // Remove the focus from the URL line edit.
1470     urlLineEditPointer->clearFocus();
1471
1472     // Instantiate the cookie settings dialog.
1473     CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
1474
1475     // Show the dialog.
1476     cookiesDialogPointer->show();
1477
1478     // Connect the dialog signals.
1479     connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
1480     connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
1481     connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
1482 }
1483
1484 void BrowserWindow::showDownloadDirectoryBrowseDialog() const
1485 {
1486     // Get the current download directory.
1487     QString currentDownloadDirectory = downloadDirectoryComboBoxPointer->currentText();
1488
1489     // Resolve the system download directory if specified.
1490     if (currentDownloadDirectory == QStringLiteral("System Download Directory"))
1491         currentDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
1492
1493     // Get the new download directory.
1494     QString newDownloadDirectory = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download directory dialog caption", "Select Download Directory"),
1495                                                                      currentDownloadDirectory);
1496
1497     // Populate the download directory combo box according to the new download location.
1498     if (newDownloadDirectory == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))  // The default download location was selected.
1499     {
1500         // Populate the download location with the default text.
1501         downloadDirectoryComboBoxPointer->setCurrentText("System Download Directory");
1502     }
1503     else if (newDownloadDirectory != QStringLiteral(""))  // A different directory was selected.
1504     {
1505         // Populate the download location.
1506         downloadDirectoryComboBoxPointer->setCurrentText(newDownloadDirectory);
1507     }
1508 }
1509
1510 void BrowserWindow::showDomainSettingsDialog() const
1511 {
1512     // Remove the focus from the URL line edit.
1513     urlLineEditPointer->clearFocus();
1514
1515     // Instantiate the domain settings dialog.
1516     DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
1517
1518     // Reload the tabs when domain settings are updated.
1519     connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1520
1521     // Show the dialog.
1522     domainSettingsDialogPointer->show();
1523 }
1524
1525 void BrowserWindow::showFindTextActions() const
1526 {
1527     // Show the find text actions.
1528     findTextLineEditActionPointer->setVisible(true);
1529     findTextLabelActionPointer->setVisible(true);
1530     findNextActionPointer->setVisible(true);
1531     findPreviousActionPointer->setVisible(true);
1532     findCaseSensitiveActionPointer->setVisible(true);
1533     hideFindTextActionPointer->setVisible(true);
1534
1535     // Set the focus on the find line edit.
1536     findTextLineEditPointer->setFocus();
1537
1538     // Select all the text in the find line edit.
1539     findTextLineEditPointer->selectAll();
1540 }
1541
1542 void BrowserWindow::showProgressBar(const int &progress) const
1543 {
1544     // Set the progress bar value.
1545     progressBarPointer->setValue(progress);
1546
1547     // Show the progress bar.
1548     progressBarPointer->show();
1549
1550     // Disable and hide the refresh action.
1551     refreshActionPointer->setEnabled(false);
1552     refreshActionPointer->setVisible(false);
1553
1554     // Enable and show the stop action.
1555     stopActionPointer->setEnabled(true);
1556     stopActionPointer->setVisible(true);
1557 }
1558
1559 void BrowserWindow::showSettingsDialog()
1560 {
1561     // Create the settings widgets.
1562     QWidget *privacySettingsWidgetPointer = new QWidget;
1563     QWidget *generalSettingsWidgetPointer = new QWidget;
1564     QWidget *spellCheckSettingsWidgetPointer = new QWidget;
1565
1566     // Instantiate the settings UI.
1567     Ui::PrivacySettings privacySettingsUi;
1568     Ui::GeneralSettings generalSettingsUi;
1569     Ui::SpellCheckSettings spellCheckSettingsUi;
1570
1571     // Setup the UI to display the settings widgets.
1572     privacySettingsUi.setupUi(privacySettingsWidgetPointer);
1573     generalSettingsUi.setupUi(generalSettingsWidgetPointer);
1574     spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
1575
1576     // Get handles for the widgets.
1577     QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
1578     userAgentLabelPointer = privacySettingsUi.userAgentLabel;
1579     QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
1580     searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
1581     downloadDirectoryComboBoxPointer = generalSettingsUi.kcfg_downloadDirectory;
1582     QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
1583     QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
1584
1585     // Populate the combo box labels.
1586     updateUserAgentLabel(userAgentComboBoxPointer->currentText());
1587     updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
1588
1589     // Update the labels when the combo boxes change.
1590     connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
1591     connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
1592
1593     // Connect the download directory directory browse button.
1594     connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadDirectoryBrowseDialog()));
1595
1596     // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
1597     QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
1598
1599     // Get a dictionaries string list.
1600     QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
1601
1602     // Remove the `.bdic` file extensions from the dictionaries list.
1603     dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
1604
1605     // Get a list of the enabled spell check languages.
1606     QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
1607
1608     // Add each dictionary to the spell check list widget.
1609     foreach(QString dictionaryString, dictionariesStringList)
1610     {
1611         // Create a new list widget item pointer.
1612         QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
1613
1614         // Create a dictionary check box widget with the name of the dictionary string.
1615         QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
1616
1617         // Check the language if it is currently enabled.
1618         if (enabledSpellCheckLanguagesList.contains(dictionaryString))
1619             dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
1620         else
1621             dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
1622
1623         // Add the list widget item to the spell check list widget.
1624         spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
1625
1626         // Set the list widget item check box widget.
1627         spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
1628     }
1629
1630     // Get a handle for the KConfig skeleton.
1631     KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
1632
1633     // Instantiate a settings config dialog from the settings.kcfg file.
1634     configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
1635
1636     // Create a settings icon string.
1637     QString settingsIconString;
1638
1639     // Get a settings icon that matches the theme.
1640     if (QIcon::hasThemeIcon("breeze-settings"))
1641     {
1642         // KDE uses breeze-settings.
1643         settingsIconString = QLatin1String("breeze-settings");
1644     }
1645     else
1646     {
1647         // Gnome uses preferences-desktop.
1648         settingsIconString = QLatin1String("preferences-desktop");
1649     }
1650
1651     // Add the settings widgets as config dialog pages.
1652     configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
1653     configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
1654     configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
1655
1656     // Get handles for the buttons.
1657     QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
1658     QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
1659
1660     // Prevent interaction with the parent window while the dialog is open.
1661     configDialogPointer->setWindowModality(Qt::WindowModal);
1662
1663     // Make it so.
1664     configDialogPointer->show();
1665
1666     // TODO.  KConfigDialog does not respect expanding size policies.  <https://redmine.stoutner.com/issues/823>
1667     //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1668     //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1669     //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1670     //configDialogPointer->adjustSize();
1671
1672     // Expand the config dialog.
1673     configDialogPointer->resize(1000, 500);
1674
1675     // Create a save spell check languages lambda.
1676     auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
1677     {
1678         // Create a list of enabled languages.
1679         QStringList newSpellCheckLanguages = QStringList();
1680
1681         // Get a count of all the languages.
1682         int allLanguagesCount = spellCheckListWidgetPointer->count();
1683
1684         // Get a list of all the checked languages.
1685         for (int i = 0; i < allLanguagesCount; ++i) {
1686             // Get the language item.
1687             QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
1688
1689             // Get the language check box.
1690             QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
1691
1692             // Add the item to the enabled languages if it is checked.
1693             if (languageCheckBoxPointer->checkState() == Qt::Checked)
1694             {
1695                 // Get the text.
1696                 QString languageString = languageCheckBoxPointer->text();
1697
1698                 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
1699                 languageString.remove(QChar('&'));
1700
1701                 // Add the language string to the list.
1702                 newSpellCheckLanguages.append(languageString);
1703             }
1704         }
1705
1706         // Update the spell check languages.
1707         if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
1708         {
1709             // Update the spell check languages.
1710             Settings::setSpellCheckLanguages(newSpellCheckLanguages);
1711
1712             // Write the settings to disk.
1713             kConfigSkeletonPointer->save();
1714         }
1715
1716         // Apply the spell check languages.
1717         tabWidgetPointer->applySpellCheckLanguages();
1718     };
1719
1720     // Process
1721     connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1722     connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1723
1724     // Apply the settings handled by KConfig.
1725     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
1726     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1727 }
1728
1729 QSize BrowserWindow::sizeHint() const
1730 {
1731     // Return the default window size.
1732     return QSize(1500, 1200);
1733 }
1734
1735 void BrowserWindow::toggleBookmark()
1736 {
1737     // Remove the focus from the URL line edit, which will have been focused when the user clicked on the bookmarked icon.
1738     urlLineEditPointer->clearFocus();
1739
1740     // Create or delete the bookmark
1741     if (bookmarkedActionPointer->isChecked())  // The user checked the toggle.  Create a bookmark.
1742     {
1743         // Create a bookmark struct.
1744         BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
1745
1746         // Populate the bookmark struct.
1747         bookmarkStructPointer->name = tabWidgetPointer->getCurrentTabTitle();
1748         bookmarkStructPointer->url = tabWidgetPointer->getCurrentTabUrl();
1749         bookmarkStructPointer->parentFolderId = 0;
1750         bookmarkStructPointer->favoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1751
1752         // Add the bookmark.
1753         BookmarksDatabase::addBookmark(bookmarkStructPointer);
1754     }
1755     else  // The user unchecked the toggle.  Delete all related bookmarks.
1756     {
1757         // Delete the bookmarks.
1758         BookmarksDatabase::deleteBookmarks(urlLineEditPointer->text());
1759
1760
1761     }
1762
1763     // Repopulate the bookmarks.
1764     populateBookmarksInAllWindows();
1765 }
1766
1767 void BrowserWindow::toggleDeveloperTools() const
1768 {
1769     // Toggle the developer tools.
1770     tabWidgetPointer->toggleDeveloperTools(developerToolsActionPointer->isChecked());
1771 }
1772
1773 void BrowserWindow::toggleDomStorage() const
1774 {
1775     // Remove the focus from the URL line edit.
1776     urlLineEditPointer->clearFocus();
1777
1778     // Toggle DOM storage.
1779     tabWidgetPointer->toggleDomStorage();
1780 }
1781
1782 void BrowserWindow::toggleFindCaseSensitive() const
1783 {
1784     // Get the current find string.
1785     const QString findString = findTextLineEditPointer->text();
1786
1787     // Toggle find case sensitive.
1788     tabWidgetPointer->toggleFindCaseSensitive(findString);
1789 }
1790
1791 void BrowserWindow::toggleJavaScript() const
1792 {
1793     // Remove the focus from the URL line edit.
1794     urlLineEditPointer->clearFocus();
1795
1796     // Toggle JavaScript.
1797     tabWidgetPointer->toggleJavaScript();
1798 }
1799
1800 void BrowserWindow::toggleLocalStorage() const
1801 {
1802     // Remove the focus from the URL line edit.
1803     urlLineEditPointer->clearFocus();
1804
1805     // Toggle local storage.
1806     tabWidgetPointer->toggleLocalStorage();
1807 }
1808
1809 void BrowserWindow::toggleFullScreen()
1810 {
1811     // Toggle the full screen status.
1812     fullScreenRequested(fullScreenActionPointer->isChecked());
1813 }
1814
1815 void BrowserWindow::toggleViewSource() const
1816 {
1817     // Get the current URL.
1818     QString url = urlLineEditPointer->text();
1819
1820     // Toggle the URL.
1821     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1822     {
1823         // Remove `view-source:` from the URL.
1824         url = url.remove(0, 12);
1825     }
1826     else  // The source is not currently being viewed.
1827     {
1828         // Prepend `view-source:` from the URL.
1829         url = url.prepend(QLatin1String("view-source:"));
1830     }
1831
1832     // Make it so.
1833     loadUrlFromLineEdit(url);
1834 }
1835
1836 void BrowserWindow::toggleViewBookmarksToolBar()
1837 {
1838     // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
1839     bookmarksToolBarIsVisible = viewBookmarksToolBarActionPointer->isChecked();
1840
1841     // Update the visibility of the bookmarks toolbar.
1842     bookmarksToolBarPointer->setVisible(bookmarksToolBarIsVisible);
1843 }
1844
1845 void BrowserWindow::toggleViewSourceInNewTab() const
1846 {
1847     // Get the current URL.
1848     QString url = urlLineEditPointer->text();
1849
1850     // Toggle the URL.
1851     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1852     {
1853         // Remove `view-source:` from the URL.
1854         url = url.remove(0, 12);
1855     }
1856     else  // The source is not currently being viewed.
1857     {
1858         // Prepend `view-source:` from the URL.
1859         url = url.prepend(QLatin1String("view-source:"));
1860     }
1861
1862     // 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.
1863     tabWidgetPointer->addTab(true, true, false, url);
1864 }
1865
1866 void BrowserWindow::updateBookmarkedAction() const
1867 {
1868     // Update the bookmarked action to reflect the current state.
1869     if (bookmarkedActionPointer->isChecked())
1870         bookmarkedActionPointer->setIcon(QIcon::fromTheme("starred-symbolic"));
1871     else
1872         bookmarkedActionPointer->setIcon(QIcon::fromTheme("non-starred-symbolic"));
1873 }
1874
1875 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
1876 {
1877     // Update the action text.
1878     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1879 }
1880
1881 void BrowserWindow::updateDefaultZoomFactor(const double newDefaultZoomFactorDouble)
1882 {
1883     // Store the new default zoom factor.
1884     defaultZoomFactorDouble = newDefaultZoomFactorDouble;
1885 }
1886
1887 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1888 {
1889     // Set the action checked status.
1890     domStorageActionPointer->setChecked(isEnabled);
1891 }
1892
1893 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1894 {
1895     // Set the domain palette according to the status.
1896     if (status)
1897         urlLineEditPointer->setPalette(positiveBackgroundPalette);
1898     else
1899         urlLineEditPointer->setPalette(normalBackgroundPalette);
1900 }
1901
1902 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1903 {
1904     // Set the text.
1905     findTextLineEditPointer->setText(text);
1906
1907     // Set the find case sensitive action checked status.
1908     findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1909 }
1910
1911 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1912 {
1913     // Update the find text label.
1914     findTextLabelPointer->setText(QStringLiteral("  %1/%2  ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1915
1916     // Set the background color according to the find status.
1917     if (findTextLineEditPointer->text().isEmpty())
1918         findTextLineEditPointer->setPalette(normalBackgroundPalette);
1919     else if (findTextResult.numberOfMatches() == 0)
1920         findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1921     else
1922         findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1923 }
1924
1925 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1926 {
1927     // Update the JavaScript status.
1928     javaScriptEnabled = isEnabled;
1929
1930     // Set the icon according to the status.
1931     if (javaScriptEnabled)
1932         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1933     else
1934         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1935
1936     // Set the action checked status.
1937     javaScriptActionPointer->setChecked(javaScriptEnabled);
1938
1939     // Update the status of the DOM storage action.
1940     domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1941 }
1942
1943 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1944 {
1945     // Update the local storage status.
1946     localStorageEnabled = isEnabled;
1947
1948     // 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.
1949     if (localStorageEnabled)
1950         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/document-save-as.png"))));
1951     else
1952         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1953
1954     // Set the action checked status.
1955     localStorageActionPointer->setChecked(localStorageEnabled);
1956
1957     // Update the status of the DOM storage action.
1958     domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1959 }
1960
1961 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1962 {
1963     // Initialize the custom search engine flag.
1964     bool customSearchEngine = false;
1965
1966     if (searchEngine == "Mojeek")  // Mojeek.
1967     {
1968         // Check the Mojeek user agent action.
1969         searchEngineMojeekActionPointer->setChecked(true);
1970
1971         // Update the search engine menu action icon.
1972         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1973
1974         // Update the search engine menu action text.
1975         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1976     }
1977     else if (searchEngine == "Monocles")  // Monocles.
1978     {
1979         // Check the Monocles user agent action.
1980         searchEngineMonoclesActionPointer->setChecked(true);
1981
1982         // Update the search engine menu action icon.
1983         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1984
1985         // Update the search engine menu action text.
1986         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1987     }
1988     else if (searchEngine == "MetaGer")  // MetaGer.
1989     {
1990         // Check the MetaGer user agent action.
1991         searchEngineMetagerActionPointer->setChecked(true);
1992
1993         // Update the search engine menu action icon.
1994         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1995
1996         // Update the search engine menu action text.
1997         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1998     }
1999     else if (searchEngine == "Google")  // Google.
2000     {
2001         // Check the Google user agent action.
2002         searchEngineGoogleActionPointer->setChecked(true);
2003
2004         // Update the search engine menu action icon.
2005         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
2006
2007         // Update the search engine menu action text.
2008         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
2009     }
2010     else if (searchEngine == "Bing")  // Bing.
2011     {
2012         // Check the Bing user agent action.
2013         searchEngineBingActionPointer->setChecked(true);
2014
2015         // Update the search engine menu action icon.
2016         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2017
2018         // Update the search engine menu action text.
2019         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
2020     }
2021     else if (searchEngine == "Yahoo")  // Yahoo.
2022     {
2023         // Check the Yahoo user agent action.
2024         searchEngineYahooActionPointer->setChecked(true);
2025
2026         // Update the search engine menu action icon.
2027         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
2028
2029         // Update the search engine menu action text.
2030         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
2031     }
2032     else  // Custom search engine.
2033     {
2034         // Check the user agent.
2035         searchEngineCustomActionPointer->setChecked(true);
2036
2037         // Update the search engine menu action icon.
2038         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2039
2040         // Update the search engine menu action text.
2041         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
2042
2043         // Set the custom search engine text.
2044         searchEngineCustomActionPointer->setText(searchEngine);
2045
2046         // Set the custom search engine flag.
2047         customSearchEngine = true;
2048     }
2049
2050     // Update the custom search engine enabled boolean.
2051     if (updateCustomSearchEngineStatus)
2052         customSearchEngineEnabled = customSearchEngine;
2053
2054     // Format the custom search engine.
2055     if (customSearchEngineEnabled)
2056     {
2057         // Enable the custom search engine.
2058         searchEngineCustomActionPointer->setEnabled(true);
2059     }
2060     else
2061     {
2062         // Disable the custom search engine.
2063         searchEngineCustomActionPointer->setEnabled(false);
2064
2065         // Reset the custom search engine text.
2066         searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
2067     }
2068 }
2069
2070 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
2071 {
2072     // Update the search engine label.
2073     searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
2074 }
2075
2076 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
2077 {
2078     // Get the new URL string in encoded form, which displays punycode.
2079     QString newUrlString = newUrl.toEncoded();
2080
2081     // Update the view source actions.
2082     if (newUrlString.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
2083     {
2084         // Mark the view source checkbox.
2085         viewSourceActionPointer->setChecked(true);
2086
2087         // Update the view in new tab action text.
2088         viewSourceInNewTabActionPointer->setText(i18nc("View rendered website in new tab action", "View Rendered Website in New Tab"));
2089     }
2090     else  // The source is not currently being viewed.
2091     {
2092         // Unmark the view source checkbox.
2093         viewSourceActionPointer->setChecked(false);
2094
2095         // Update the view in new tab action text.
2096         viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
2097     }
2098
2099     // Update the URL line edit if it does not have focus.
2100     if (!urlLineEditPointer->hasFocus())
2101     {
2102         // Update the URL line edit.
2103         urlLineEditPointer->setText(newUrlString);
2104
2105         // Set the bookmarked action status.
2106         bookmarkedActionPointer->setChecked(BookmarksDatabase::isBookmarked(newUrlString));
2107
2108         // Update the bookmarked action.
2109         updateBookmarkedAction();
2110
2111         // Set the focus if the new URL is blank.
2112         if (newUrlString == QStringLiteral(""))
2113             urlLineEditPointer->setFocus();
2114     }
2115
2116     // Store the current URL.
2117     currentUrl = newUrl;
2118 }
2119
2120 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
2121 {
2122     // Initialize the custom user agent flag.
2123     bool customUserAgent = false;
2124
2125     // Check the indicated on-the-fly user agent.
2126     if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT)  // Privacy Browser.
2127     {
2128         // Check the Privacy Browser user agent action.
2129         userAgentPrivacyBrowserActionPointer->setChecked(true);
2130
2131         // Update the user agent menu action icon.
2132         userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
2133
2134         // Update the user agent menu action text.
2135         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
2136     }
2137     else if (userAgent == TabWidget::webEngineDefaultUserAgent)  // WebEngine default.
2138     {
2139         // check the WebEngine default user agent action.
2140         userAgentWebEngineDefaultActionPointer->setChecked(true);
2141
2142         // Update the user agent menu action icon.
2143         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2144
2145         // Update the user agent menu action text.
2146         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
2147     }
2148     else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT)  // Firefox on Linux.
2149     {
2150         // Check the Firefox on Linux user agent action.
2151         userAgentFirefoxLinuxActionPointer->setChecked(true);
2152
2153         // Update the user agent menu action icon.
2154         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2155
2156         // Update the user agent menu action text.
2157         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
2158     }
2159     else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT)  // Chromium on Linux.
2160     {
2161         // Check the Chromium on Linux user agent action.
2162         userAgentChromiumLinuxActionPointer->setChecked(true);
2163
2164         // Update the user agent menu action icon.
2165         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2166
2167         // Update the user agent menu action text.
2168         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
2169     }
2170     else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT)  // Firefox on Windows.
2171     {
2172         // Check the Firefox on Windows user agent action.
2173         userAgentFirefoxWindowsActionPointer->setChecked(true);
2174
2175         // Update the user agent menu action icon.
2176         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2177
2178         // Update the user agent menu action text.
2179         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
2180     }
2181     else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT)  // Chrome on Windows.
2182     {
2183         // Check the Chrome on Windows user agent action.
2184         userAgentChromeWindowsActionPointer->setChecked(true);
2185
2186         // Update the user agent menu action icon.
2187         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2188
2189         // Update the user agent menu action text.
2190         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
2191     }
2192     else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT)  // Edge on Windows.
2193     {
2194         // Check the Edge on Windows user agent action.
2195         userAgentEdgeWindowsActionPointer->setChecked(true);
2196
2197         // Update the user agent menu action icon.
2198         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2199
2200         // Update the user agent menu action text.
2201         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
2202     }
2203     else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT)  // Safari on macOS.
2204     {
2205         // Check the Safari on macOS user agent action.
2206         userAgentSafariMacosActionPointer->setChecked(true);
2207
2208         // Update the user agent menu action icon.
2209         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2210
2211         // Update the user agent menu action text.
2212         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
2213     }
2214     else  // Custom user agent.
2215     {
2216         // Check the user agent.
2217         userAgentCustomActionPointer->setChecked(true);
2218
2219         // Update the user agent menu action icon.
2220         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2221
2222         // Update the user agent menu action text.
2223         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
2224
2225         // Set the custom user agent text.
2226         userAgentCustomActionPointer->setText(userAgent);
2227
2228         // Set the custom user agent flag.
2229         customUserAgent = true;
2230     }
2231
2232     // Update the custom user agent enabled boolean.
2233     // 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.
2234     if (updateCustomUserAgentStatus)
2235         customUserAgentEnabled = customUserAgent;
2236
2237
2238     // Format the custom user agent.
2239     if (customUserAgentEnabled)
2240     {
2241         // Enable the custom user agent.
2242         userAgentCustomActionPointer->setEnabled(true);
2243     }
2244     else
2245     {
2246         // Disable the custom user agent.
2247         userAgentCustomActionPointer->setEnabled(false);
2248
2249         // Reset the custom user agent text.
2250         userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
2251     }
2252 }
2253
2254 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
2255 {
2256     // Update the user agent label.
2257     userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
2258 }
2259
2260 void BrowserWindow::updateViewBookmarksToolBarCheckbox(const bool visible)
2261 {
2262     // Update the view bookmarks toolbar checkbox.
2263     viewBookmarksToolBarActionPointer->setChecked(visible);
2264
2265     // Initialize the bookmarks toolbar visibility tracker if Privacy Browser has just launched.
2266     if (bookmarksToolBarUninitialized)
2267     {
2268         // Set the initialization flag.
2269         bookmarksToolBarUninitialized = false;
2270
2271         // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
2272         bookmarksToolBarIsVisible = visible;
2273     }
2274 }
2275
2276 void BrowserWindow::updateWindowTitle(const QString &title)
2277 {
2278     // Update the window title.
2279     setWindowTitle(title);
2280 }
2281
2282 void BrowserWindow::updateZoomActions(const double zoomFactorDouble)
2283 {
2284     // Set the current zoom factor.
2285     currentZoomFactorDouble = zoomFactorDouble;
2286
2287     // Set the status of the default zoom action.
2288     zoomDefaultActionPointer->setEnabled(currentZoomFactorDouble != defaultZoomFactorDouble);
2289
2290     // Set the status of the zoom in action and button.
2291     zoomInActionPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2292     zoomPlusButtonPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2293
2294     // Set the status of the zoom out action and button.
2295     zoomMinusButtonPointer->setEnabled(currentZoomFactorDouble > 0.25);
2296     zoomOutActionPointer->setEnabled(currentZoomFactorDouble > 0.25);
2297
2298
2299     // 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.
2300     zoomFactorActionPointer->setText(ki18nc("The zoom factor action", "Zoom Factor - %1").subs(zoomFactorDouble, 0, '0', 2).toString());
2301
2302     // Update the status bar zoom factor label.
2303     currentZoomButtonPointer->setText(ki18nc("The status bar zoom, which is just the formatted zoom factor", "%1").subs(zoomFactorDouble, 0, '0', 2).toString());
2304 }
2305
2306 void BrowserWindow::zoomDefault()
2307 {
2308     // Set the new zoom factor.
2309     tabWidgetPointer->applyOnTheFlyZoomFactor(defaultZoomFactorDouble);
2310
2311     // Update the on-the-fly action text.
2312     updateZoomActions(defaultZoomFactorDouble);
2313 }