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