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