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