]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blob - src/windows/BrowserWindow.cpp
Ghost DOM storage in Settings and Domain Settings unless both JavaScript and local...
[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     QCheckBox *javaScriptCheckBoxPointer = privacySettingsUi.kcfg_javaScriptEnabled;
1578     QCheckBox *localStorageCheckBoxPointer = privacySettingsUi.kcfg_localStorageEnabled;
1579     QCheckBox *domStorageCheckBoxPointer = privacySettingsUi.kcfg_domStorageEnabled;
1580     QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
1581     userAgentLabelPointer = privacySettingsUi.userAgentLabel;
1582     QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
1583     searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
1584     downloadDirectoryComboBoxPointer = generalSettingsUi.kcfg_downloadDirectory;
1585     QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
1586     QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
1587
1588     // Create a save spell check languages lambda.
1589     auto updateCheckBoxes = [javaScriptCheckBoxPointer, localStorageCheckBoxPointer, domStorageCheckBoxPointer] ()
1590     {
1591         // Only enable the DOM storage check box if both JavaScript and local storage are checked.
1592         domStorageCheckBoxPointer->setEnabled(javaScriptCheckBoxPointer->isChecked() && localStorageCheckBoxPointer->isChecked());
1593     };
1594
1595     // Update the status of the DOM storage check box when either JavaScript or local storage are changed.
1596     connect(javaScriptCheckBoxPointer, &QCheckBox::stateChanged, this, updateCheckBoxes);
1597     connect(localStorageCheckBoxPointer, &QCheckBox::stateChanged, this, updateCheckBoxes);
1598
1599     // Populate the combo box labels.
1600     updateUserAgentLabel(userAgentComboBoxPointer->currentText());
1601     updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
1602
1603     // Update the labels when the combo boxes change.
1604     connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
1605     connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
1606
1607     // Connect the download directory directory browse button.
1608     connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadDirectoryBrowseDialog()));
1609
1610     // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
1611     QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
1612
1613     // Get a dictionaries string list.
1614     QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
1615
1616     // Remove the `.bdic` file extensions from the dictionaries list.
1617     dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
1618
1619     // Get a list of the enabled spell check languages.
1620     QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
1621
1622     // Add each dictionary to the spell check list widget.
1623     foreach(QString dictionaryString, dictionariesStringList)
1624     {
1625         // Create a new list widget item pointer.
1626         QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
1627
1628         // Create a dictionary check box widget with the name of the dictionary string.
1629         QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
1630
1631         // Check the language if it is currently enabled.
1632         if (enabledSpellCheckLanguagesList.contains(dictionaryString))
1633             dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
1634         else
1635             dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
1636
1637         // Add the list widget item to the spell check list widget.
1638         spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
1639
1640         // Set the list widget item check box widget.
1641         spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
1642     }
1643
1644     // Get a handle for the KConfig skeleton.
1645     KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
1646
1647     // Instantiate a settings config dialog from the settings.kcfg file.
1648     configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
1649
1650     // Create a settings icon string.
1651     QString settingsIconString;
1652
1653     // Get a settings icon that matches the theme.
1654     if (QIcon::hasThemeIcon("breeze-settings"))
1655     {
1656         // KDE uses breeze-settings.
1657         settingsIconString = QLatin1String("breeze-settings");
1658     }
1659     else
1660     {
1661         // Gnome uses preferences-desktop.
1662         settingsIconString = QLatin1String("preferences-desktop");
1663     }
1664
1665     // Add the settings widgets as config dialog pages.
1666     configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
1667     configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
1668     configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
1669
1670     // Get handles for the buttons.
1671     QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
1672     QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
1673
1674     // Prevent interaction with the parent window while the dialog is open.
1675     configDialogPointer->setWindowModality(Qt::WindowModal);
1676
1677     // Make it so.
1678     configDialogPointer->show();
1679
1680     // TODO.  KConfigDialog does not respect expanding size policies.  <https://redmine.stoutner.com/issues/823>
1681     //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1682     //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1683     //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1684     //configDialogPointer->adjustSize();
1685
1686     // Expand the config dialog.
1687     configDialogPointer->resize(1000, 500);
1688
1689     // Create a save spell check languages lambda.
1690     auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
1691     {
1692         // Create a list of enabled languages.
1693         QStringList newSpellCheckLanguages = QStringList();
1694
1695         // Get a count of all the languages.
1696         int allLanguagesCount = spellCheckListWidgetPointer->count();
1697
1698         // Get a list of all the checked languages.
1699         for (int i = 0; i < allLanguagesCount; ++i) {
1700             // Get the language item.
1701             QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
1702
1703             // Get the language check box.
1704             QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
1705
1706             // Add the item to the enabled languages if it is checked.
1707             if (languageCheckBoxPointer->checkState() == Qt::Checked)
1708             {
1709                 // Get the text.
1710                 QString languageString = languageCheckBoxPointer->text();
1711
1712                 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
1713                 languageString.remove(QChar('&'));
1714
1715                 // Add the language string to the list.
1716                 newSpellCheckLanguages.append(languageString);
1717             }
1718         }
1719
1720         // Update the spell check languages.
1721         if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
1722         {
1723             // Update the spell check languages.
1724             Settings::setSpellCheckLanguages(newSpellCheckLanguages);
1725
1726             // Write the settings to disk.
1727             kConfigSkeletonPointer->save();
1728         }
1729
1730         // Apply the spell check languages.
1731         tabWidgetPointer->applySpellCheckLanguages();
1732     };
1733
1734     // Process
1735     connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1736     connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1737
1738     // Apply the settings handled by KConfig.
1739     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
1740     connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1741 }
1742
1743 QSize BrowserWindow::sizeHint() const
1744 {
1745     // Return the default window size.
1746     return QSize(1500, 1200);
1747 }
1748
1749 void BrowserWindow::toggleBookmark()
1750 {
1751     // Remove the focus from the URL line edit, which will have been focused when the user clicked on the bookmarked icon.
1752     urlLineEditPointer->clearFocus();
1753
1754     // Create or delete the bookmark
1755     if (bookmarkedActionPointer->isChecked())  // The user checked the toggle.  Create a bookmark.
1756     {
1757         // Create a bookmark struct.
1758         BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
1759
1760         // Populate the bookmark struct.
1761         bookmarkStructPointer->name = tabWidgetPointer->getCurrentTabTitle();
1762         bookmarkStructPointer->url = tabWidgetPointer->getCurrentTabUrl();
1763         bookmarkStructPointer->parentFolderId = 0;
1764         bookmarkStructPointer->favoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1765
1766         // Add the bookmark.
1767         BookmarksDatabase::addBookmark(bookmarkStructPointer);
1768     }
1769     else  // The user unchecked the toggle.  Delete all related bookmarks.
1770     {
1771         // Delete the bookmarks.
1772         BookmarksDatabase::deleteBookmarks(urlLineEditPointer->text());
1773
1774
1775     }
1776
1777     // Repopulate the bookmarks.
1778     populateBookmarksInAllWindows();
1779 }
1780
1781 void BrowserWindow::toggleDeveloperTools() const
1782 {
1783     // Toggle the developer tools.
1784     tabWidgetPointer->toggleDeveloperTools(developerToolsActionPointer->isChecked());
1785 }
1786
1787 void BrowserWindow::toggleDomStorage() const
1788 {
1789     // Remove the focus from the URL line edit.
1790     urlLineEditPointer->clearFocus();
1791
1792     // Toggle DOM storage.
1793     tabWidgetPointer->toggleDomStorage();
1794 }
1795
1796 void BrowserWindow::toggleFindCaseSensitive() const
1797 {
1798     // Get the current find string.
1799     const QString findString = findTextLineEditPointer->text();
1800
1801     // Toggle find case sensitive.
1802     tabWidgetPointer->toggleFindCaseSensitive(findString);
1803 }
1804
1805 void BrowserWindow::toggleJavaScript() const
1806 {
1807     // Remove the focus from the URL line edit.
1808     urlLineEditPointer->clearFocus();
1809
1810     // Toggle JavaScript.
1811     tabWidgetPointer->toggleJavaScript();
1812 }
1813
1814 void BrowserWindow::toggleLocalStorage() const
1815 {
1816     // Remove the focus from the URL line edit.
1817     urlLineEditPointer->clearFocus();
1818
1819     // Toggle local storage.
1820     tabWidgetPointer->toggleLocalStorage();
1821 }
1822
1823 void BrowserWindow::toggleFullScreen()
1824 {
1825     // Toggle the full screen status.
1826     fullScreenRequested(fullScreenActionPointer->isChecked());
1827 }
1828
1829 void BrowserWindow::toggleViewSource() const
1830 {
1831     // Get the current URL.
1832     QString url = urlLineEditPointer->text();
1833
1834     // Toggle the URL.
1835     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1836     {
1837         // Remove `view-source:` from the URL.
1838         url = url.remove(0, 12);
1839     }
1840     else  // The source is not currently being viewed.
1841     {
1842         // Prepend `view-source:` from the URL.
1843         url = url.prepend(QLatin1String("view-source:"));
1844     }
1845
1846     // Make it so.
1847     loadUrlFromLineEdit(url);
1848 }
1849
1850 void BrowserWindow::toggleViewBookmarksToolBar()
1851 {
1852     // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
1853     bookmarksToolBarIsVisible = viewBookmarksToolBarActionPointer->isChecked();
1854
1855     // Update the visibility of the bookmarks toolbar.
1856     bookmarksToolBarPointer->setVisible(bookmarksToolBarIsVisible);
1857 }
1858
1859 void BrowserWindow::toggleViewSourceInNewTab() const
1860 {
1861     // Get the current URL.
1862     QString url = urlLineEditPointer->text();
1863
1864     // Toggle the URL.
1865     if (url.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
1866     {
1867         // Remove `view-source:` from the URL.
1868         url = url.remove(0, 12);
1869     }
1870     else  // The source is not currently being viewed.
1871     {
1872         // Prepend `view-source:` from the URL.
1873         url = url.prepend(QLatin1String("view-source:"));
1874     }
1875
1876     // 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.
1877     tabWidgetPointer->addTab(true, true, false, url);
1878 }
1879
1880 void BrowserWindow::updateBookmarkedAction() const
1881 {
1882     // Update the bookmarked action to reflect the current state.
1883     if (bookmarkedActionPointer->isChecked())
1884         bookmarkedActionPointer->setIcon(QIcon::fromTheme("starred-symbolic"));
1885     else
1886         bookmarkedActionPointer->setIcon(QIcon::fromTheme("non-starred-symbolic"));
1887 }
1888
1889 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
1890 {
1891     // Update the action text.
1892     cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1893 }
1894
1895 void BrowserWindow::updateDefaultZoomFactor(const double newDefaultZoomFactorDouble)
1896 {
1897     // Store the new default zoom factor.
1898     defaultZoomFactorDouble = newDefaultZoomFactorDouble;
1899 }
1900
1901 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1902 {
1903     // Set the action checked status.
1904     domStorageActionPointer->setChecked(isEnabled);
1905 }
1906
1907 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1908 {
1909     // Set the domain palette according to the status.
1910     if (status)
1911         urlLineEditPointer->setPalette(positiveBackgroundPalette);
1912     else
1913         urlLineEditPointer->setPalette(normalBackgroundPalette);
1914 }
1915
1916 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1917 {
1918     // Set the text.
1919     findTextLineEditPointer->setText(text);
1920
1921     // Set the find case sensitive action checked status.
1922     findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1923 }
1924
1925 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1926 {
1927     // Update the find text label.
1928     findTextLabelPointer->setText(QStringLiteral("  %1/%2  ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1929
1930     // Set the background color according to the find status.
1931     if (findTextLineEditPointer->text().isEmpty())
1932         findTextLineEditPointer->setPalette(normalBackgroundPalette);
1933     else if (findTextResult.numberOfMatches() == 0)
1934         findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1935     else
1936         findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1937 }
1938
1939 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1940 {
1941     // Update the JavaScript status.
1942     javaScriptEnabled = isEnabled;
1943
1944     // Set the icon according to the status.
1945     if (javaScriptEnabled)
1946         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1947     else
1948         javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1949
1950     // Set the action checked status.
1951     javaScriptActionPointer->setChecked(javaScriptEnabled);
1952
1953     // Update the status of the DOM storage action.
1954     domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1955 }
1956
1957 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1958 {
1959     // Update the local storage status.
1960     localStorageEnabled = isEnabled;
1961
1962     // 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.
1963     if (localStorageEnabled)
1964         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/document-save-as.png"))));
1965     else
1966         localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1967
1968     // Set the action checked status.
1969     localStorageActionPointer->setChecked(localStorageEnabled);
1970
1971     // Update the status of the DOM storage action.
1972     domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1973 }
1974
1975 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1976 {
1977     // Initialize the custom search engine flag.
1978     bool customSearchEngine = false;
1979
1980     if (searchEngine == "Mojeek")  // Mojeek.
1981     {
1982         // Check the Mojeek user agent action.
1983         searchEngineMojeekActionPointer->setChecked(true);
1984
1985         // Update the search engine menu action icon.
1986         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1987
1988         // Update the search engine menu action text.
1989         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1990     }
1991     else if (searchEngine == "Monocles")  // Monocles.
1992     {
1993         // Check the Monocles user agent action.
1994         searchEngineMonoclesActionPointer->setChecked(true);
1995
1996         // Update the search engine menu action icon.
1997         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1998
1999         // Update the search engine menu action text.
2000         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
2001     }
2002     else if (searchEngine == "MetaGer")  // MetaGer.
2003     {
2004         // Check the MetaGer user agent action.
2005         searchEngineMetagerActionPointer->setChecked(true);
2006
2007         // Update the search engine menu action icon.
2008         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2009
2010         // Update the search engine menu action text.
2011         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
2012     }
2013     else if (searchEngine == "Google")  // Google.
2014     {
2015         // Check the Google user agent action.
2016         searchEngineGoogleActionPointer->setChecked(true);
2017
2018         // Update the search engine menu action icon.
2019         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
2020
2021         // Update the search engine menu action text.
2022         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
2023     }
2024     else if (searchEngine == "Bing")  // Bing.
2025     {
2026         // Check the Bing user agent action.
2027         searchEngineBingActionPointer->setChecked(true);
2028
2029         // Update the search engine menu action icon.
2030         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2031
2032         // Update the search engine menu action text.
2033         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
2034     }
2035     else if (searchEngine == "Yahoo")  // Yahoo.
2036     {
2037         // Check the Yahoo user agent action.
2038         searchEngineYahooActionPointer->setChecked(true);
2039
2040         // Update the search engine menu action icon.
2041         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
2042
2043         // Update the search engine menu action text.
2044         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
2045     }
2046     else  // Custom search engine.
2047     {
2048         // Check the user agent.
2049         searchEngineCustomActionPointer->setChecked(true);
2050
2051         // Update the search engine menu action icon.
2052         searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2053
2054         // Update the search engine menu action text.
2055         searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
2056
2057         // Set the custom search engine text.
2058         searchEngineCustomActionPointer->setText(searchEngine);
2059
2060         // Set the custom search engine flag.
2061         customSearchEngine = true;
2062     }
2063
2064     // Update the custom search engine enabled boolean.
2065     if (updateCustomSearchEngineStatus)
2066         customSearchEngineEnabled = customSearchEngine;
2067
2068     // Format the custom search engine.
2069     if (customSearchEngineEnabled)
2070     {
2071         // Enable the custom search engine.
2072         searchEngineCustomActionPointer->setEnabled(true);
2073     }
2074     else
2075     {
2076         // Disable the custom search engine.
2077         searchEngineCustomActionPointer->setEnabled(false);
2078
2079         // Reset the custom search engine text.
2080         searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
2081     }
2082 }
2083
2084 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
2085 {
2086     // Update the search engine label.
2087     searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
2088 }
2089
2090 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
2091 {
2092     // Get the new URL string in encoded form, which displays punycode.
2093     QString newUrlString = newUrl.toEncoded();
2094
2095     // Update the view source actions.
2096     if (newUrlString.startsWith(QLatin1String("view-source:")))  // The source is currently being viewed.
2097     {
2098         // Mark the view source checkbox.
2099         viewSourceActionPointer->setChecked(true);
2100
2101         // Update the view in new tab action text.
2102         viewSourceInNewTabActionPointer->setText(i18nc("View rendered website in new tab action", "View Rendered Website in New Tab"));
2103     }
2104     else  // The source is not currently being viewed.
2105     {
2106         // Unmark the view source checkbox.
2107         viewSourceActionPointer->setChecked(false);
2108
2109         // Update the view in new tab action text.
2110         viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
2111     }
2112
2113     // Update the URL line edit if it does not have focus.
2114     if (!urlLineEditPointer->hasFocus())
2115     {
2116         // Update the URL line edit.
2117         urlLineEditPointer->setText(newUrlString);
2118
2119         // Set the bookmarked action status.
2120         bookmarkedActionPointer->setChecked(BookmarksDatabase::isBookmarked(newUrlString));
2121
2122         // Update the bookmarked action.
2123         updateBookmarkedAction();
2124
2125         // Set the focus if the new URL is blank.
2126         if (newUrlString == QStringLiteral(""))
2127             urlLineEditPointer->setFocus();
2128     }
2129
2130     // Store the current URL.
2131     currentUrl = newUrl;
2132 }
2133
2134 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
2135 {
2136     // Initialize the custom user agent flag.
2137     bool customUserAgent = false;
2138
2139     // Check the indicated on-the-fly user agent.
2140     if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT)  // Privacy Browser.
2141     {
2142         // Check the Privacy Browser user agent action.
2143         userAgentPrivacyBrowserActionPointer->setChecked(true);
2144
2145         // Update the user agent menu action icon.
2146         userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
2147
2148         // Update the user agent menu action text.
2149         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
2150     }
2151     else if (userAgent == TabWidget::webEngineDefaultUserAgent)  // WebEngine default.
2152     {
2153         // check the WebEngine default user agent action.
2154         userAgentWebEngineDefaultActionPointer->setChecked(true);
2155
2156         // Update the user agent menu action icon.
2157         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2158
2159         // Update the user agent menu action text.
2160         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
2161     }
2162     else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT)  // Firefox on Linux.
2163     {
2164         // Check the Firefox on Linux user agent action.
2165         userAgentFirefoxLinuxActionPointer->setChecked(true);
2166
2167         // Update the user agent menu action icon.
2168         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2169
2170         // Update the user agent menu action text.
2171         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
2172     }
2173     else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT)  // Chromium on Linux.
2174     {
2175         // Check the Chromium on Linux user agent action.
2176         userAgentChromiumLinuxActionPointer->setChecked(true);
2177
2178         // Update the user agent menu action icon.
2179         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2180
2181         // Update the user agent menu action text.
2182         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
2183     }
2184     else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT)  // Firefox on Windows.
2185     {
2186         // Check the Firefox on Windows user agent action.
2187         userAgentFirefoxWindowsActionPointer->setChecked(true);
2188
2189         // Update the user agent menu action icon.
2190         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2191
2192         // Update the user agent menu action text.
2193         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
2194     }
2195     else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT)  // Chrome on Windows.
2196     {
2197         // Check the Chrome on Windows user agent action.
2198         userAgentChromeWindowsActionPointer->setChecked(true);
2199
2200         // Update the user agent menu action icon.
2201         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2202
2203         // Update the user agent menu action text.
2204         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
2205     }
2206     else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT)  // Edge on Windows.
2207     {
2208         // Check the Edge on Windows user agent action.
2209         userAgentEdgeWindowsActionPointer->setChecked(true);
2210
2211         // Update the user agent menu action icon.
2212         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2213
2214         // Update the user agent menu action text.
2215         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
2216     }
2217     else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT)  // Safari on macOS.
2218     {
2219         // Check the Safari on macOS user agent action.
2220         userAgentSafariMacosActionPointer->setChecked(true);
2221
2222         // Update the user agent menu action icon.
2223         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2224
2225         // Update the user agent menu action text.
2226         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
2227     }
2228     else  // Custom user agent.
2229     {
2230         // Check the user agent.
2231         userAgentCustomActionPointer->setChecked(true);
2232
2233         // Update the user agent menu action icon.
2234         userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2235
2236         // Update the user agent menu action text.
2237         userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
2238
2239         // Set the custom user agent text.
2240         userAgentCustomActionPointer->setText(userAgent);
2241
2242         // Set the custom user agent flag.
2243         customUserAgent = true;
2244     }
2245
2246     // Update the custom user agent enabled boolean.
2247     // 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.
2248     if (updateCustomUserAgentStatus)
2249         customUserAgentEnabled = customUserAgent;
2250
2251
2252     // Format the custom user agent.
2253     if (customUserAgentEnabled)
2254     {
2255         // Enable the custom user agent.
2256         userAgentCustomActionPointer->setEnabled(true);
2257     }
2258     else
2259     {
2260         // Disable the custom user agent.
2261         userAgentCustomActionPointer->setEnabled(false);
2262
2263         // Reset the custom user agent text.
2264         userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
2265     }
2266 }
2267
2268 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
2269 {
2270     // Update the user agent label.
2271     userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
2272 }
2273
2274 void BrowserWindow::updateViewBookmarksToolBarCheckbox(const bool visible)
2275 {
2276     // Update the view bookmarks toolbar checkbox.
2277     viewBookmarksToolBarActionPointer->setChecked(visible);
2278
2279     // Initialize the bookmarks toolbar visibility tracker if Privacy Browser has just launched.
2280     if (bookmarksToolBarUninitialized)
2281     {
2282         // Set the initialization flag.
2283         bookmarksToolBarUninitialized = false;
2284
2285         // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
2286         bookmarksToolBarIsVisible = visible;
2287     }
2288 }
2289
2290 void BrowserWindow::updateWindowTitle(const QString &title)
2291 {
2292     // Update the window title.
2293     setWindowTitle(title);
2294 }
2295
2296 void BrowserWindow::updateZoomActions(const double zoomFactorDouble)
2297 {
2298     // Set the current zoom factor.
2299     currentZoomFactorDouble = zoomFactorDouble;
2300
2301     // Set the status of the default zoom action.
2302     zoomDefaultActionPointer->setEnabled(currentZoomFactorDouble != defaultZoomFactorDouble);
2303
2304     // Set the status of the zoom in action and button.
2305     zoomInActionPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2306     zoomPlusButtonPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2307
2308     // Set the status of the zoom out action and button.
2309     zoomMinusButtonPointer->setEnabled(currentZoomFactorDouble > 0.25);
2310     zoomOutActionPointer->setEnabled(currentZoomFactorDouble > 0.25);
2311
2312
2313     // 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.
2314     zoomFactorActionPointer->setText(ki18nc("The zoom factor action", "Zoom Factor - %1").subs(zoomFactorDouble, 0, '0', 2).toString());
2315
2316     // Update the status bar zoom factor label.
2317     currentZoomButtonPointer->setText(ki18nc("The status bar zoom, which is just the formatted zoom factor", "%1").subs(zoomFactorDouble, 0, '0', 2).toString());
2318 }
2319
2320 void BrowserWindow::zoomDefault()
2321 {
2322     // Set the new zoom factor.
2323     tabWidgetPointer->applyOnTheFlyZoomFactor(defaultZoomFactorDouble);
2324
2325     // Update the on-the-fly action text.
2326     updateZoomActions(defaultZoomFactorDouble);
2327 }