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