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