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