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