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