2 * Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
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.
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.
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/>.
20 // Application headers.
21 #include "BrowserWindow.h"
23 #include "ui_SettingsGeneral.h"
24 #include "ui_SettingsPrivacy.h"
25 #include "ui_SettingsSpellCheck.h"
26 #include "databases/BookmarksDatabase.h"
27 #include "databases/DomainsDatabase.h"
28 #include "dialogs/AddBookmarkDialog.h"
29 #include "dialogs/AddFolderDialog.h"
30 #include "dialogs/BookmarksDialog.h"
31 #include "dialogs/CookiesDialog.h"
32 #include "dialogs/DomainSettingsDialog.h"
33 #include "dialogs/EditBookmarkDialog.h"
34 #include "dialogs/EditFolderDialog.h"
35 #include "helpers/SearchEngineHelper.h"
36 #include "helpers/UserAgentHelper.h"
37 #include "structs/BookmarkStruct.h"
39 // KDE Frameworks headers.
40 #include <KActionCollection>
41 #include <KColorScheme>
42 #include <KXMLGUIFactory>
44 // Qt toolkit headers.
46 #include <QContextMenuEvent>
47 #include <QDBusConnection>
48 #include <QDBusConnectionInterface>
49 #include <QDBusMessage>
50 #include <QFileDialog>
51 #include <QInputDialog>
52 #include <QNetworkCookie>
54 #include <QMessageBox>
57 #include <QWebEngineFindTextResult>
59 // Construct the class.
60 BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer) : KXmlGuiWindow()
62 // Initialize the variables.
63 javaScriptEnabled = false;
64 localStorageEnabled = false;
66 // Instantiate the privacy tab widget pointer.
67 tabWidgetPointer = new TabWidget(this);
69 // Set the privacy tab widget as the central widget.
70 setCentralWidget(tabWidgetPointer);
72 // Get a handle for the action collection.
73 actionCollectionPointer = this->actionCollection();
75 // Add the standard actions.
76 KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
77 QAction *printPreviewActionPointer = KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
78 KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
79 zoomInActionPointer = KStandardAction::zoomIn(this, SLOT(incrementZoom()), actionCollectionPointer);
80 zoomOutActionPointer = KStandardAction::zoomOut(this, SLOT(decrementZoom()), actionCollectionPointer);
81 refreshActionPointer = KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
82 fullScreenActionPointer = KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollectionPointer);
83 QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
84 QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
85 KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
86 QAction *editBookmarksActionPointer = KStandardAction::editBookmarks(this, SLOT(editBookmarks()), actionCollectionPointer);
87 KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollectionPointer);
88 KStandardAction::find(this, SLOT(showFindTextActions()), actionCollectionPointer);
89 findNextActionPointer = KStandardAction::findNext(this, SLOT(findNext()), actionCollectionPointer);
90 findPreviousActionPointer = KStandardAction::findPrev(this, SLOT(findPrevious()), actionCollectionPointer);
92 // Add the custom actions.
93 QAction *newTabActionPointer = actionCollectionPointer->addAction(QLatin1String("new_tab"));
94 QAction *newWindowActionPointer = actionCollectionPointer->addAction(QLatin1String("new_window"));
95 QAction *saveArchiveActionPointer = actionCollectionPointer->addAction(QLatin1String("save_archive"));
96 zoomDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_default"));
97 QAction *reloadAndBypassCacheActionPointer = actionCollectionPointer->addAction(QLatin1String("reload_and_bypass_cache"));
98 stopActionPointer = actionCollectionPointer->addAction(QLatin1String("stop"));
99 viewSourceActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source"));
100 viewSourceInNewTabActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source_in_new_tab"));
101 developerToolsActionPointer = actionCollectionPointer->addAction(QLatin1String("developer_tools"));
102 javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
103 localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
104 domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
105 userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
106 userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
107 userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
108 userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chromium_linux"));
109 userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_windows"));
110 userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chrome_windows"));
111 userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_edge_windows"));
112 userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_safari_macos"));
113 userAgentCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_custom"));
114 zoomFactorActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_factor"));
115 searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_mojeek"));
116 searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_monocles"));
117 searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_metager"));
118 searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_google"));
119 searchEngineBingActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_bing"));
120 searchEngineYahooActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_yahoo"));
121 searchEngineCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_custom"));
122 viewBookmarksToolBarActionPointer = actionCollectionPointer->addAction(QLatin1String("view_bookmarks_toolbar"));
123 QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QLatin1String("domain_settings"));
124 cookiesActionPointer = actionCollectionPointer->addAction(QLatin1String("cookies"));
125 findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QLatin1String("find_case_sensitive"));
126 hideFindTextActionPointer = actionCollectionPointer->addAction(QLatin1String("hide_find_actions"));
128 // Create the action groups
129 QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
130 QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
132 // Add the actions to the groups.
133 userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
134 userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
135 userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
136 userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
137 userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
138 userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
139 userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
140 userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
141 userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
142 searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
143 searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
144 searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
145 searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
146 searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
147 searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
148 searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
150 // Set some actions to be checkable.
151 javaScriptActionPointer->setCheckable(true);
152 localStorageActionPointer->setCheckable(true);
153 domStorageActionPointer->setCheckable(true);
154 findCaseSensitiveActionPointer->setCheckable(true);
155 viewSourceActionPointer->setCheckable(true);
156 developerToolsActionPointer->setCheckable(true);
157 userAgentPrivacyBrowserActionPointer->setCheckable(true);
158 userAgentWebEngineDefaultActionPointer->setCheckable(true);
159 userAgentFirefoxLinuxActionPointer->setCheckable(true);
160 userAgentChromiumLinuxActionPointer->setCheckable(true);
161 userAgentFirefoxWindowsActionPointer->setCheckable(true);
162 userAgentChromeWindowsActionPointer->setCheckable(true);
163 userAgentEdgeWindowsActionPointer->setCheckable(true);
164 userAgentSafariMacosActionPointer->setCheckable(true);
165 userAgentCustomActionPointer->setCheckable(true);
166 searchEngineMojeekActionPointer->setCheckable(true);
167 searchEngineMonoclesActionPointer->setCheckable(true);
168 searchEngineMetagerActionPointer->setCheckable(true);
169 searchEngineGoogleActionPointer->setCheckable(true);
170 searchEngineBingActionPointer->setCheckable(true);
171 searchEngineYahooActionPointer->setCheckable(true);
172 searchEngineCustomActionPointer->setCheckable(true);
173 viewBookmarksToolBarActionPointer->setCheckable(true);
175 // Instantiate the user agent helper.
176 UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
178 // Set the action text.
179 newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
180 newWindowActionPointer->setText(i18nc("New window action", "New Window"));
181 saveArchiveActionPointer->setText(i18nc("Save archive action", "Save Archive"));
182 zoomDefaultActionPointer->setText(i18nc("Zoom default action", "Zoom Default"));
183 reloadAndBypassCacheActionPointer->setText(i18nc("Reload and bypass cache action", "Reload and Bypass Cache"));
184 stopActionPointer->setText(i18nc("Stop action", "Stop"));
185 viewSourceActionPointer->setText(i18nc("View source action", "View Source"));
186 viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
187 developerToolsActionPointer->setText(i18nc("Developer tools action", "Developer Tools"));
188 javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
189 localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
190 domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
191 userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
192 userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
193 userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
194 userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
195 userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
196 userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
197 userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
198 userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
199 searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
200 searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
201 searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
202 searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
203 searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
204 searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
205 viewBookmarksToolBarActionPointer->setText(i18nc("View bookmarks toolbar", "View Bookmarks Toolbar"));
206 domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
207 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
208 findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
209 hideFindTextActionPointer->setText(i18nc("Hide Find Text action (the text should include the language-specific escape keyboard shortcut).", "Hide Find Text (Esc)"));
211 // Set the action icons. Gnome doesn't contain some of the icons that KDE has.
212 // The toolbar icons don't pick up unless the size is explicit, probably because the toolbar ends up being an intermediate size.
213 newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
214 newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
215 saveArchiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("document-save")));
216 zoomDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
217 reloadAndBypassCacheActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
218 stopActionPointer->setIcon(QIcon::fromTheme(QLatin1String("process-stop")));
219 viewSourceActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
220 viewSourceInNewTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
221 developerToolsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("add-subtitle"), QIcon::fromTheme("system-run")));
222 domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
223 userAgentPrivacyBrowserActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
224 userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"),
225 QIcon::fromTheme(QLatin1String("contact-new")))));
226 userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
227 QIcon::fromTheme(QLatin1String("contact-new")))));
228 userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
229 userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
230 QIcon::fromTheme(QLatin1String("contact-new")))));
231 userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
232 userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
233 userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
234 userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
235 searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
236 searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
237 searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
238 searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
239 searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
240 searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
241 searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
242 zoomFactorActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
243 editBookmarksActionPointer->setIcon(QIcon::fromTheme(QLatin1String("bookmark-edit"), QIcon::fromTheme(QLatin1String("bookmark-new"))));
244 viewBookmarksToolBarActionPointer->setIcon(QIcon::fromTheme(QLatin1String("bookmarks"), QIcon::fromTheme(QLatin1String("bookmark-new"))));
245 domainSettingsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("settings-configure"), QIcon::fromTheme(QLatin1String("preferences-desktop"))));
246 cookiesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-cookies"), QIcon::fromTheme(QLatin1String("appointment-new"))));
247 findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase"), QIcon::fromTheme(QLatin1String("/usr/share/icons/gnome/32x32/apps/fonts.png"))));
248 hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
250 // Create the key sequences.
251 QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
252 QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
253 QKeySequence ctrlAKeySequence = QKeySequence(i18nc("The save archive key sequence.", "Ctrl+A"));
254 QKeySequence ctrl0KeySequence = QKeySequence(i18nc("The zoom default key sequence.", "Ctrl+0"));
255 QKeySequence ctrlF5KeySequence = QKeySequence(i18nc("The reload and bypass cache key sequence.", "Ctrl+F5"));
256 QKeySequence ctrlShiftXKeySequence = QKeySequence(i18nc("The stop key sequence.", "Ctrl+Shift+X"));
257 QKeySequence ctrlUKeySequence = QKeySequence(i18nc("The view source key sequence.", "Ctrl+U"));
258 QKeySequence ctrlShiftUKeySequence = QKeySequence(i18nc("The view source in new tab key sequence.", "Ctrl+Shift+U"));
259 QKeySequence f12KeySequence = QKeySequence(i18nc("The developer tools key sequence.", "F12"));
260 QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
261 QKeySequence ctrlJKeySequence = QKeySequence(i18nc("The JavaScript key sequence.", "Ctrl+J"));
262 QKeySequence ctrlLKeySequence = QKeySequence(i18nc("The local storage key sequence.", "Ctrl+L"));
263 QKeySequence ctrlDKeySequence = QKeySequence(i18nc("The DOM storage key sequence.", "Ctrl+D"));
264 QKeySequence ctrlSKeySequence = QKeySequence(i18nc("The find case sensitive key sequence.", "Ctrl+S"));
265 QKeySequence ctrlAltPKeySequence = QKeySequence(i18nc("The Privacy Browser user agent key sequence.", "Ctrl+Alt+P"));
266 QKeySequence ctrlAltWKeySequence = QKeySequence(i18nc("The WebEngine Default user agent key sequence.", "Ctrl+Alt+W"));
267 QKeySequence ctrlAltFKeySequence = QKeySequence(i18nc("The Firefox on Linux user agent key sequence.", "Ctrl+Alt+F"));
268 QKeySequence ctrlAltCKeySequence = QKeySequence(i18nc("The Chromium on Linux user agent key sequence.", "Ctrl+Alt+C"));
269 QKeySequence ctrlAltShiftFKeySequence = QKeySequence(i18nc("The Firefox on Windows user agent key sequence.", "Ctrl+Alt+Shift+F"));
270 QKeySequence ctrlAltShiftCKeySequence = QKeySequence(i18nc("The Chrome on Windows user agent key sequence.", "Ctrl+Alt+Shift+C"));
271 QKeySequence ctrlAltEKeySequence = QKeySequence(i18nc("The Edge on Windows user agent key sequence.", "Ctrl+Alt+E"));
272 QKeySequence ctrlAltSKeySequence = QKeySequence(i18nc("The Safari on macOS user agent key sequence.", "Ctrl+Alt+S"));
273 QKeySequence altShiftCKeySequence = QKeySequence(i18nc("The custom user agent key sequence.", "Alt+Shift+C"));
274 QKeySequence ctrlAltZKeySequence = QKeySequence(i18nc("The zoom factor key sequence.", "Ctrl+Alt+Z"));
275 QKeySequence ctrlShiftMKeySequence = QKeySequence(i18nc("The Mojeek search engine key sequence.", "Ctrl+Shift+M"));
276 QKeySequence ctrlShiftOKeySequence = QKeySequence(i18nc("The Monocles search engine key sequence.", "Ctrl+Shift+O"));
277 QKeySequence ctrlShiftEKeySequence = QKeySequence(i18nc("The MetaGer search engine key sequence.", "Ctrl+Shift+E"));
278 QKeySequence ctrlShiftGKeySequence = QKeySequence(i18nc("The Google search engine key sequence.", "Ctrl+Shift+G"));
279 QKeySequence ctrlShiftBKeySequence = QKeySequence(i18nc("The Bing search engine key sequence.", "Ctrl+Shift+B"));
280 QKeySequence ctrlShiftYKeySequence = QKeySequence(i18nc("The Yahoo search engine key sequence.", "Ctrl+Shift+Y"));
281 QKeySequence ctrlShiftCKeySequence = QKeySequence(i18nc("The custom search engine key sequence.", "Ctrl+Shift+C"));
282 QKeySequence ctrlAltShiftBKeySequence = QKeySequence(i18nc("The edit bookmarks key sequence.", "Ctrl+Alt+Shift+B"));
283 QKeySequence ctrlAltBKeySequence = QKeySequence(i18nc("The view bookmarks toolbar key sequence.", "Ctrl+Alt+B"));
284 QKeySequence ctrlShiftDKeySequence = QKeySequence(i18nc("The domain settings key sequence.", "Ctrl+Shift+D"));
285 QKeySequence ctrlSemicolonKeySequence = QKeySequence(i18nc("The cookies dialog key sequence.", "Ctrl+;"));
287 // Set the action key sequences.
288 actionCollectionPointer->setDefaultShortcut(newTabActionPointer, ctrlTKeySequence);
289 actionCollectionPointer->setDefaultShortcut(newWindowActionPointer, ctrlNKeySequence);
290 actionCollectionPointer->setDefaultShortcut(saveArchiveActionPointer, ctrlAKeySequence);
291 actionCollectionPointer->setDefaultShortcut(zoomDefaultActionPointer, ctrl0KeySequence);
292 actionCollectionPointer->setDefaultShortcut(reloadAndBypassCacheActionPointer, ctrlF5KeySequence);
293 actionCollectionPointer->setDefaultShortcut(stopActionPointer, ctrlShiftXKeySequence);
294 actionCollectionPointer->setDefaultShortcut(viewSourceActionPointer, ctrlUKeySequence);
295 actionCollectionPointer->setDefaultShortcut(viewSourceInNewTabActionPointer, ctrlShiftUKeySequence);
296 actionCollectionPointer->setDefaultShortcut(developerToolsActionPointer, f12KeySequence);
297 actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
298 actionCollectionPointer->setDefaultShortcut(javaScriptActionPointer, ctrlJKeySequence);
299 actionCollectionPointer->setDefaultShortcut(localStorageActionPointer, ctrlLKeySequence);
300 actionCollectionPointer->setDefaultShortcut(domStorageActionPointer, ctrlDKeySequence);
301 actionCollectionPointer->setDefaultShortcut(findCaseSensitiveActionPointer, ctrlSKeySequence);
302 actionCollectionPointer->setDefaultShortcut(userAgentPrivacyBrowserActionPointer, ctrlAltPKeySequence);
303 actionCollectionPointer->setDefaultShortcut(userAgentWebEngineDefaultActionPointer, ctrlAltWKeySequence);
304 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxLinuxActionPointer, ctrlAltFKeySequence);
305 actionCollectionPointer->setDefaultShortcut(userAgentChromiumLinuxActionPointer, ctrlAltCKeySequence);
306 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxWindowsActionPointer, ctrlAltShiftFKeySequence);
307 actionCollectionPointer->setDefaultShortcut(userAgentChromeWindowsActionPointer, ctrlAltShiftCKeySequence);
308 actionCollectionPointer->setDefaultShortcut(userAgentEdgeWindowsActionPointer, ctrlAltEKeySequence);
309 actionCollectionPointer->setDefaultShortcut(userAgentSafariMacosActionPointer, ctrlAltSKeySequence);
310 actionCollectionPointer->setDefaultShortcut(userAgentCustomActionPointer, altShiftCKeySequence);
311 actionCollectionPointer->setDefaultShortcut(zoomFactorActionPointer, ctrlAltZKeySequence);
312 actionCollectionPointer->setDefaultShortcut(searchEngineMojeekActionPointer, ctrlShiftMKeySequence);
313 actionCollectionPointer->setDefaultShortcut(searchEngineMonoclesActionPointer, ctrlShiftOKeySequence);
314 actionCollectionPointer->setDefaultShortcut(searchEngineMetagerActionPointer, ctrlShiftEKeySequence);
315 actionCollectionPointer->setDefaultShortcut(searchEngineGoogleActionPointer, ctrlShiftGKeySequence);
316 actionCollectionPointer->setDefaultShortcut(searchEngineBingActionPointer, ctrlShiftBKeySequence);
317 actionCollectionPointer->setDefaultShortcut(searchEngineYahooActionPointer, ctrlShiftYKeySequence);
318 actionCollectionPointer->setDefaultShortcut(searchEngineCustomActionPointer, ctrlShiftCKeySequence);
319 actionCollectionPointer->setDefaultShortcut(editBookmarksActionPointer, ctrlAltShiftBKeySequence);
320 actionCollectionPointer->setDefaultShortcut(viewBookmarksToolBarActionPointer, ctrlAltBKeySequence);
321 actionCollectionPointer->setDefaultShortcut(domainSettingsActionPointer, ctrlShiftDKeySequence);
322 actionCollectionPointer->setDefaultShortcut(cookiesActionPointer, ctrlSemicolonKeySequence);
324 // Execute the actions.
325 connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
326 connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
327 connect(saveArchiveActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(saveArchive()));
328 connect(zoomDefaultActionPointer, SIGNAL(triggered()), this, SLOT(zoomDefault()));
329 connect(reloadAndBypassCacheActionPointer, SIGNAL(triggered()), this, SLOT(reloadAndBypassCache()));
330 connect(stopActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(stop()));
331 connect(viewSourceActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSource()));
332 connect(viewSourceInNewTabActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSourceInNewTab()));
333 connect(developerToolsActionPointer, SIGNAL(triggered()), this, SLOT(toggleDeveloperTools()));
334 connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
335 connect(viewBookmarksToolBarActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewBookmarksToolBar()));
336 connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
337 connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
339 // Update the on-the-fly menus.
340 connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
341 connect(tabWidgetPointer, SIGNAL(updateZoomActions(double)), this, SLOT(updateZoomActions(double)));
342 connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
344 // Apply the on-the-fly settings when selected.
345 connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
346 connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
348 // Process cookie changes.
349 connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
351 // Store the default zoom factor.
352 connect(tabWidgetPointer, SIGNAL(updateDefaultZoomFactor(double)), this, SLOT(updateDefaultZoomFactor(double)));
354 // Connect the URL toolbar actions.
355 connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
356 connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
357 connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
359 // Update the actions from the tab widget.
360 connect(tabWidgetPointer, SIGNAL(updateDeveloperToolsAction(bool)), developerToolsActionPointer, SLOT(setChecked(bool)));
361 connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
362 connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
363 connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
364 connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
365 connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
367 // Connect the find text actions.
368 connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
369 connect(hideFindTextActionPointer, SIGNAL(triggered()), this, SLOT(hideFindTextActions()));
373 // Setup the GUI based on the browserwindowui.rc file.
374 setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
376 // Get lists of the actions' associated widgets.
377 QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
378 QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
380 // Get the menu widget pointers. It is the second entry, after the main window.
381 QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
382 QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
384 // Get the menu pointers.
385 QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
386 QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
388 // Get the menu actions.
389 userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
390 searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
392 // Get handles for the toolbars.
393 navigationToolBarPointer = toolBar(QLatin1String("navigation_toolbar"));
394 urlToolBarPointer = toolBar(QLatin1String("url_toolbar"));
395 bookmarksToolBarPointer = toolBar(QLatin1String("bookmarks_toolbar"));
397 // Populate the view bookmarks toolbar checkbox.
398 connect(bookmarksToolBarPointer, SIGNAL(visibilityChanged(bool)), this, SLOT(updateViewBookmarksToolBarCheckbox(bool)));
400 // Create the line edits.
401 urlLineEditPointer = new KLineEdit();
402 findTextLineEditPointer = new KLineEdit();
404 // Get the line edit size policies.
405 QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
406 QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
408 // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
409 urlLineEditSizePolicy.setHorizontalStretch(5);
410 findTextLineEditSizePolicy.setHorizontalStretch(1);
413 urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
414 findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
417 urlLineEditPointer->setMinimumWidth(350);
418 findTextLineEditPointer->setMinimumWidth(200);
419 findTextLineEditPointer->setMaximumWidth(350);
421 // Set the place holder text.
422 urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
423 findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
425 // Show the clear button on the find line edit.
426 findTextLineEditPointer->setClearButtonEnabled(true);
428 // Add the actions to the URL line edit.
429 bookmarkedActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("non-starred-symbolic"), QLineEdit::LeadingPosition);
430 QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure", QIcon::fromTheme(QLatin1String("preferences-desktop"))),
431 QLineEdit::TrailingPosition);
433 // Set the bookmarked action pointer to be checkable.
434 bookmarkedActionPointer->setCheckable(true);
436 // Connect the URL line edit actions.
437 connect(bookmarkedActionPointer, SIGNAL(triggered()), this, SLOT(toggleBookmark()));
438 connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
440 // Create a find text label pointer.
441 findTextLabelPointer = new QLabel();
443 // Set the default label text.
444 findTextLabelPointer->setText(QLatin1String(" ") + i18nc("Default find results.", "0/0") + QLatin1String(" "));
446 // Insert the widgets into the toolbars.
447 urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
448 findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
449 findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
451 // Initially hide the find text actions.
452 hideFindTextActions();
454 // Load a new URL from the URL line edit.
455 connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
457 // Find text as it is typed.
458 connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
460 // Find next if the enter key is pressed.
461 connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
463 // Update find text when switching tabs.
464 connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
466 // Update the find text results.
467 connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
469 // Update the URL line edit on page loads.
470 connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
472 // Update the window title.
473 connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
475 // Get a handle for the status bar.
476 QStatusBar *statusBarPointer = statusBar();
478 // Create the status bar widgets.
479 progressBarPointer = new QProgressBar();
480 zoomMinusButtonPointer = new QPushButton();
481 currentZoomButtonPointer = new QPushButton();
482 zoomPlusButtonPointer = new QPushButton();
484 // Set the button icons.
485 zoomMinusButtonPointer->setIcon(QIcon::fromTheme(QStringLiteral("list-remove-symbolic")));
486 zoomPlusButtonPointer->setIcon(QIcon::fromTheme(QStringLiteral("list-add-symbolic")));
488 // Set the button icons to be flat (no borders).
489 zoomMinusButtonPointer->setFlat(true);
490 currentZoomButtonPointer->setFlat(true);
491 zoomPlusButtonPointer->setFlat(true);
493 // Handle clicks on the zoom buttons.
494 connect(zoomMinusButtonPointer, SIGNAL(clicked()), this, SLOT(decrementZoom()));
495 connect(currentZoomButtonPointer, SIGNAL(clicked()), this, SLOT(getZoomFactorFromUser()));
496 connect(zoomPlusButtonPointer, SIGNAL(clicked()), this, SLOT(incrementZoom()));
498 // Remove the padding around the current zoom button text.
499 currentZoomButtonPointer->setStyleSheet("padding: 0px;");
501 // Add the widgets to the far right of the status bar.
502 statusBarPointer->addPermanentWidget(progressBarPointer);
503 statusBarPointer->addPermanentWidget(zoomMinusButtonPointer);
504 statusBarPointer->addPermanentWidget(currentZoomButtonPointer);
505 statusBarPointer->addPermanentWidget(zoomPlusButtonPointer);
507 // Update the status bar with the URL when a link is hovered.
508 connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
510 // Update the progress bar.
511 connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
512 connect(tabWidgetPointer, SIGNAL(hideProgressBar()), this, SLOT(hideProgressBar()));
514 // Update the URL line edit focus.
515 connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
517 // Get the URL line edit palettes.
518 normalBackgroundPalette = urlLineEditPointer->palette();
519 negativeBackgroundPalette = normalBackgroundPalette;
520 positiveBackgroundPalette = normalBackgroundPalette;
522 // Modify the palettes.
523 KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
524 KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
526 // Update the applied palette.
527 connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
529 // Process full screen requests.
530 connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
532 // Create keyboard shortcuts.
533 QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
534 QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
536 // Connect the keyboard shortcuts.
537 connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
538 connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
540 // Get a handle for the Bookmarks menu.
541 bookmarksMenuPointer = qobject_cast<QMenu*>(guiFactory()->container("bookmarks", this));
543 // Add a separator to the bookmarks menu.
544 bookmarksMenuPointer->addSeparator();
546 // Initialize the current bookmarks lists.
547 finalBookmarkFolderMenuActionList = QList<QPair<QMenu *, QAction *> *>();
548 bookmarksMenuActionList = QList<QPair<QMenu *, QAction *> *>();
549 bookmarksMenuSubmenuList = QList<QPair<QMenu *, QMenu *> *>();
550 bookmarksToolBarActionList = QList<QAction*>();
551 bookmarksToolBarSubfolderActionList = QList<QPair<QMenu *, QAction * > *>();
553 // Set the bookmarks toolbar context menu policy.
554 bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
556 // Show the custom bookmark context menu when requested.
557 connect(bookmarksToolBarPointer, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBookmarkContextMenu(const QPoint&)));
559 // Populate the bookmarks in this window.
560 populateBookmarksInThisWindow();
563 // 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.
564 updateJavaScriptAction(Settings::javaScriptEnabled());
565 updateLocalStorageAction(Settings::localStorageEnabled());
566 updateDomStorageAction(Settings::domStorageEnabled());
567 updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
568 updateZoomActions(Settings::zoomFactor());
570 // Populate the first tab.
571 if (firstWindow) // This is the first window.
573 // Load the initial website.
574 tabWidgetPointer->loadInitialWebsite();
576 else if (initialUrlStringPointer) // An initial URL was specified.
578 // Load the initial URL.
579 tabWidgetPointer->loadUrlFromLineEdit(*initialUrlStringPointer);
583 void BrowserWindow::addFinalBookmarkFolderMenuActions(QMenu *menuPointer, double folderId)
585 // Get the database ID.
586 int folderDatabaseId = BookmarksDatabase::getFolderDatabaseId(folderId);
589 menuPointer->addSeparator();
591 // Add the add bookmark action to the menu.
592 QAction *addBookmarkActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("bookmark-new")), i18nc("The add bookmark action", "Add Bookmark"), [=]
594 // Instantiate an add bookmark dialog.
595 AddBookmarkDialog *addBookmarkDialogPointer = new AddBookmarkDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(),
596 tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
598 // Update the displayed bookmarks when a new one is added.
599 connect(addBookmarkDialogPointer, SIGNAL(bookmarkAdded()), this, SLOT(populateBookmarksInAllWindows()));
602 addBookmarkDialogPointer->show();
606 // Add the add folder action to the menu.
607 QAction *addFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("folder-add")), i18nc("The add folder action", "Add Folder"), [=]
609 // Instantiate an add folder dialog.
610 AddFolderDialog *addFolderDialogPointer = new AddFolderDialog(tabWidgetPointer->getCurrentTabFavoritIcon(), folderId);
612 // Update the displayed bookmarks when a folder is added.
613 connect(addFolderDialogPointer, SIGNAL(folderAdded()), this, SLOT(populateBookmarksInAllWindows()));
616 addFolderDialogPointer->show();
621 menuPointer->addSeparator();
623 // Add the open folder in new tabs action to the menu.
624 QAction *openFolderInNewTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("The open folder in new tabs action", "Open Folder in New Tabs"), [=]
626 // Get all the folder URLs.
627 QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
629 // Open the URLs in new tabs. `true` removes the URL line edit focus, `true` opens the new tabs in an adjacent tab. `false` does not load a background tab.
630 for (QString url : *folderUrlsListPointer)
631 tabWidgetPointer->addTab(true, true, false, url);
635 // Add the open folder in background tabs action to the menu.
636 QAction *openFolderInBackgroundTabsActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")),
637 i18nc("The open folder in background tabs action", "Open Folder in Background Tabs"), [=]
639 // Get all the folder URLs.
640 QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
642 // Open the URLs in new tabs. `true` removes the URL line edit focus, `true` opens the new tabs in an adjacent tab. `true` loads a background tab.
643 for (QString url : *folderUrlsListPointer)
644 tabWidgetPointer->addTab(true, true, true, url);
648 // Add the open folder in new window action to the menu.
649 QAction *openFolderInNewWindowActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("The open folder in new window action", "Open Folder in New Window"), [=]
651 // Get all the folder URLs.
652 QList<QString> *folderUrlsListPointer = BookmarksDatabase::getAllFolderUrls(folderId);
654 // Create a new browser window.
655 BrowserWindow *browserWindowPointer = new BrowserWindow(false, &folderUrlsListPointer->first());
657 // Get a count of the folder URLs.
658 const int folderUrls = folderUrlsListPointer->count();
660 // Load all the other URLs. `true` removes the URL line edit focus, `false` does not load the new tabs in adjacent tabs. `true` loads a background tab.
661 for (int i = 1; i < folderUrls; ++i)
662 browserWindowPointer->tabWidgetPointer->addTab(true, false, true, folderUrlsListPointer->value(i));
664 // Show the new browser window.
665 browserWindowPointer->show();
670 menuPointer->addSeparator();
672 // Add the edit folder action to the menu if this is not the root bookmark menu.
675 QAction *editFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("The edit folder action", "Edit Folder"), [=]
677 // Get the current tab favorite icon.
678 QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
680 // Instantiate an edit folder dialog.
681 QDialog *editFolderDialogPointer = new EditFolderDialog(folderDatabaseId, currentTabFavoriteIcon);
684 editFolderDialogPointer->show();
686 // Process bookmark events.
687 connect(editFolderDialogPointer, SIGNAL(folderSaved()), this, SLOT(populateBookmarksInAllWindows()));
691 // Add the action to the beginning of the final bookmark folder menu action list.
692 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, editFolderActionPointer));
695 // Add the delete folder action to the menu.
696 QAction *deleteFolderActionPointer = menuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete folder context menu entry", "Delete Folder"), [=]
698 // Create an items to delete list.
699 QList<int>* itemsToDeleteListPointer = new QList<int>;
701 // Add the folder to the list of items to delete if it is not the root folder.
703 itemsToDeleteListPointer->append(folderDatabaseId);
705 // Add the folder contents to the list of items to delete.
706 itemsToDeleteListPointer->append(*BookmarksDatabase::getFolderContentsDatabaseIdsRecursively(folderId));
708 // Instantiate a delete dialog message box.
709 QMessageBox deleteDialogMessageBox;
712 deleteDialogMessageBox.setIcon(QMessageBox::Warning);
714 // Set the window title.
715 deleteDialogMessageBox.setWindowTitle(i18nc("Delete bookmarks dialog title", "Delete Bookmarks"));
718 deleteDialogMessageBox.setText(i18ncp("Delete bookmarks dialog main message", "Delete %1 bookmark item?", "Delete %1 bookmark items?", itemsToDeleteListPointer->count()));
720 // Set the informative text.
721 deleteDialogMessageBox.setInformativeText(i18nc("Delete bookmarks dialog secondary message", "This cannot be undone."));
723 // Set the standard buttons.
724 deleteDialogMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
726 // Set the default button.
727 deleteDialogMessageBox.setDefaultButton(QMessageBox::No);
729 // Display the dialog and capture the return value.
730 int returnValue = deleteDialogMessageBox.exec();
732 // Delete the domain if instructed.
733 if (returnValue == QMessageBox::Yes)
735 // Get the parent folder ID.
736 double parentFolderId = BookmarksDatabase::getParentFolderId(folderDatabaseId);
738 // Delete the folder and its contents.
739 for (const int databaseId : *itemsToDeleteListPointer)
740 BookmarksDatabase::deleteBookmark(databaseId);
742 // Update the display order of the bookmarks in the parent folder.
743 BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
745 // Repopulate the bookmarks.
746 populateBookmarksInAllWindows();
751 // Add the key sequences if this is the root bookmarks menu.
754 // Create the key sequences.
755 QKeySequence ctrlBKeySequence = QKeySequence(i18nc("The add bookmark key sequence.", "Ctrl+B"));
756 QKeySequence metaFKeySequence = QKeySequence(i18nc("The add folder key sequence.", "Meta+F"));
758 // Set the action key sequences.
759 actionCollectionPointer->setDefaultShortcut(addBookmarkActionPointer, ctrlBKeySequence);
760 actionCollectionPointer->setDefaultShortcut(addFolderActionPointer, metaFKeySequence);
763 // Add the actions to the beginning of the final bookmark folder menu action list.
764 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addBookmarkActionPointer));
765 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, addFolderActionPointer));
766 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewTabsActionPointer));
767 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInBackgroundTabsActionPointer));
768 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, openFolderInNewWindowActionPointer));
769 finalBookmarkFolderMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, deleteFolderActionPointer));
772 void BrowserWindow::addOrEditDomainSettings() const
774 // Remove the focus from the URL line edit.
775 urlLineEditPointer->clearFocus();
777 // Get the current domain settings name.
778 QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
780 // Run the commands according to the current domain settings status.
781 if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
783 // Get the current settings status.
784 int javaScriptInt = calculateSettingsInt(javaScriptEnabled, Settings::javaScriptEnabled());
785 int localStorageInt = calculateSettingsInt(localStorageActionPointer->isChecked(), Settings::localStorageEnabled());
786 int domStorageInt = calculateSettingsInt(domStorageActionPointer->isChecked(), Settings::domStorageEnabled());
788 // Get the current user agent string.
789 QString currentUserAgentString = tabWidgetPointer->getCurrentUserAgent();
791 // Get the current user agent database string.
792 QString currentUserAgentDatabaseString = UserAgentHelper::getDatabaseUserAgentNameFromUserAgent(currentUserAgentString);
794 // Initialize the user agent database string.
795 QString userAgentDatabaseString = UserAgentHelper::SYSTEM_DEFAULT_DATABASE;
797 // Replace the user agent database string if the current user agent is not the default.
798 if (currentUserAgentDatabaseString != Settings::userAgent())
799 userAgentDatabaseString = currentUserAgentDatabaseString;
801 // Initialize the zoom factor variables.
802 int zoomFactorInt = DomainsDatabase::SYSTEM_DEFAULT;
804 // Use a custom zoom factor if currently applied. Doubles cannot be reliably compared using `==`, so a mathematical workaround is used.
805 if (abs(currentZoomFactorDouble - defaultZoomFactorDouble ) > 0.01)
806 zoomFactorInt = DomainsDatabase::CUSTOM;
809 DomainsDatabase::addDomain(currentUrl.host(), javaScriptInt, localStorageInt, domStorageInt, userAgentDatabaseString, zoomFactorInt, currentZoomFactorDouble);
811 // Apply the domain settings.
812 tabWidgetPointer->applyDomainSettingsAndReload();
815 // Create the domain settings dialog pointer.
816 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
818 // Reload the tabs when domain settings are updated.
819 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
822 domainSettingsDialogPointer->show();
825 void BrowserWindow::back() const
827 // Remove the focus from the URL line edit.
828 urlLineEditPointer->clearFocus();
831 tabWidgetPointer->back();
834 int BrowserWindow::calculateSettingsInt(const bool settingCurrentlyEnabled, const bool settingEnabledByDefault) const
836 // Return the int that matches the current state.
837 if (settingCurrentlyEnabled == settingEnabledByDefault) // The current system default is used.
838 return DomainsDatabase::SYSTEM_DEFAULT;
839 else if (settingCurrentlyEnabled) // The setting is enabled, which is different from the system default.
840 return DomainsDatabase::ENABLED;
841 else // The setting is disabled, which is different from the system default.
842 return DomainsDatabase::DISABLED;
845 void BrowserWindow::clearUrlLineEditFocus() const
847 // Remove the focus from the URL line edit.
848 urlLineEditPointer->clearFocus();
851 void BrowserWindow::decrementZoom()
853 // Update the current zoom factor.
854 currentZoomFactorDouble = currentZoomFactorDouble - 0.25;
856 // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
857 if (currentZoomFactorDouble < 0.25)
858 currentZoomFactorDouble = 0.25;
860 // Set the new zoom factor.
861 tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
863 // Update the on-the-fly action text.
864 updateZoomActions(currentZoomFactorDouble);
867 void BrowserWindow::editBookmarks() const
869 // Instantiate an edit bookmarks dialog.
870 BookmarksDialog *bookmarksDialogPointer = new BookmarksDialog(tabWidgetPointer->getCurrentTabTitle(), tabWidgetPointer->getCurrentTabUrl(), tabWidgetPointer->getCurrentTabFavoritIcon());
872 // Update the displayed bookmarks when edited.
873 connect(bookmarksDialogPointer, SIGNAL(bookmarkUpdated()), this, SLOT(populateBookmarksInAllWindows()));
876 bookmarksDialogPointer->show();
879 void BrowserWindow::escape() const
881 // Process the escape according to the status of the browser.
882 if (fullScreenActionPointer->isChecked()) // Full screen browsing is enabled.
884 // Exit full screen browsing.
885 fullScreenActionPointer->trigger();
887 else if (!findTextLineEditPointer->text().isEmpty()) // Find text is populated.
889 // Clear the find text line edit.
890 findTextLineEditPointer->clear();
892 // Clear the search in the WebEngine.
893 tabWidgetPointer->findText(QStringLiteral(""));
895 else if (findTextLineEditActionPointer->isVisible()) // Find text actions are visible.
897 // Hide the find text actions.
898 hideFindTextActions();
902 void BrowserWindow::findNext() const
904 // Get the find string.
905 const QString findString = findTextLineEditPointer->text();
907 // Search for the text if it is not empty.
908 if (!findString.isEmpty())
909 tabWidgetPointer->findText(findString);
912 void BrowserWindow::findPrevious() const
914 // Get the find string.
915 const QString findString = findTextLineEditPointer->text();
917 // Search for the text if it is not empty.
918 if (!findString.isEmpty())
919 tabWidgetPointer->findPrevious(findString);
922 void BrowserWindow::forward() const
924 // Remove the focus from the URL line edit.
925 urlLineEditPointer->clearFocus();
928 tabWidgetPointer->forward();
931 void BrowserWindow::fullScreenRequested(const bool toggleOn)
933 // Toggle full screen mode.
934 if (toggleOn) // Turn full screen mode on.
936 // Enable full screen mode.
937 fullScreenActionPointer->setFullScreen(window(), true);
939 // Hide the menu bar if specified.
940 if (Settings::fullScreenHideMenuBar())
941 menuBar()->setVisible(false);
943 // Hide the toolbars if specified.
944 if (Settings::fullScreenHideToolBars())
946 navigationToolBarPointer->setVisible(false);
947 urlToolBarPointer->setVisible(false);
948 bookmarksToolBarPointer->setVisible(false);
951 // Hide the tab bar if specified.
952 if (Settings::fullScreenHideTabBar())
953 tabWidgetPointer->setTabBarVisible(false);
955 // Hide the status bar if specified.
956 if (Settings::fullScreenHideStatusBar())
957 statusBar()->setVisible(false);
959 else // Disable full screen browsing mode.
961 // Disable full screen mode.
962 fullScreenActionPointer->setFullScreen(window(), false);
964 // Show the menu bar.
965 menuBar()->setVisible(true);
967 // Show the toolbars.
968 navigationToolBarPointer->setVisible(true);
969 urlToolBarPointer->setVisible(true);
971 // Only show the bookmarks toolbar if it was previously visible.
972 if (bookmarksToolBarIsVisible)
973 bookmarksToolBarPointer->setVisible(true);
976 tabWidgetPointer->setTabBarVisible(true);
978 // Show the status bar.
979 statusBar()->setVisible(true);
983 void BrowserWindow::getZoomFactorFromUser()
985 // Create an OK flag.
988 // 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.
989 double newZoomFactorDouble = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
990 i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
991 currentZoomFactorDouble, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
993 // Update the zoom factor if the user clicked OK.
996 // Set the new zoom factor.
997 tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactorDouble);
999 // Update the on-the-fly action text.
1000 updateZoomActions(newZoomFactorDouble);
1004 void BrowserWindow::hideFindTextActions() const
1006 // Hide the find text actions.
1007 findTextLineEditActionPointer->setVisible(false);
1008 findTextLabelActionPointer->setVisible(false);
1009 findNextActionPointer->setVisible(false);
1010 findPreviousActionPointer->setVisible(false);
1011 findCaseSensitiveActionPointer->setVisible(false);
1012 hideFindTextActionPointer->setVisible(false);
1015 void BrowserWindow::home() const
1017 // Remove the focus from the URL line edit.
1018 urlLineEditPointer->clearFocus();
1021 tabWidgetPointer->home();
1024 void BrowserWindow::hideProgressBar() const
1026 // Hide the progress bar.
1027 progressBarPointer->hide();
1029 // Disable and hide the stop action.
1030 stopActionPointer->setEnabled(false);
1031 stopActionPointer->setVisible(false);
1033 // Enable and show the refresh action.
1034 refreshActionPointer->setEnabled(true);
1035 refreshActionPointer->setVisible(true);
1038 void BrowserWindow::incrementZoom()
1040 // Update the current zoom factor.
1041 currentZoomFactorDouble = currentZoomFactorDouble + 0.25;
1043 // Check to make sure the zoom factor is in the valid range (0.25 to 5.00).
1044 if (currentZoomFactorDouble > 5.0)
1045 currentZoomFactorDouble = 5.0;
1047 // Set the new zoom factor.
1048 tabWidgetPointer->applyOnTheFlyZoomFactor(currentZoomFactorDouble);
1050 // Update the on-the-fly action text.
1051 updateZoomActions(currentZoomFactorDouble);
1054 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
1056 // Remove the focus from the URL line edit.
1057 urlLineEditPointer->clearFocus();
1060 tabWidgetPointer->loadUrlFromLineEdit(url);
1063 void BrowserWindow::newWindow() const
1065 // Create a new browser window.
1066 BrowserWindow *browserWindowPointer = new BrowserWindow();
1068 // Show the new browser window.
1069 browserWindowPointer->show();
1072 void BrowserWindow::populateBookmarksInAllWindows() const
1074 // Get a list of all the registered service names.
1075 QStringList registeredServiceNames = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
1077 // Get a list of all the Privacy Browser windows, which will be `com.stoutner.privacybrowser-` with the PID appended.
1078 QStringList privacyBrowserServiceNames = registeredServiceNames.filter("com.stoutner.privacybrowser");
1080 // Repopulate the bookmarks in each window.
1081 for (QString privacyBrowserServiceName : privacyBrowserServiceNames)
1083 // Prepare the D-Bus message.
1084 QDBusMessage dBusMessage = QDBusMessage::createMethodCall(privacyBrowserServiceName, "/privacybrowser/MainWindow_1", "com.stoutner.privacybrowser.BrowserWindow", "populateBookmarksInThisWindow");
1087 QDBusConnection::sessionBus().send(dBusMessage);
1091 void BrowserWindow::populateBookmarksInThisWindow()
1093 // Remove all the final bookmark folder menu actions.
1094 for (QPair<QMenu *, QAction *> *finalBookmarkFolderMenuActionPair : finalBookmarkFolderMenuActionList)
1096 // Remove the action.
1097 finalBookmarkFolderMenuActionPair->first->removeAction(finalBookmarkFolderMenuActionPair->second);
1100 // Remove all the current menu bookmarks.
1101 for (QPair<QMenu *, QAction *> *bookmarkMenuActionPairPointer : bookmarksMenuActionList)
1103 // Remove the bookmark.
1104 bookmarkMenuActionPairPointer->first->removeAction(bookmarkMenuActionPairPointer->second);
1107 // Remove all the current menu subfolders.
1108 for (QPair<QMenu *, QMenu *> *submenuPairPointer : bookmarksMenuSubmenuList)
1110 // Remove the submenu from the parent menu.
1111 submenuPairPointer->first->removeAction(submenuPairPointer->second->menuAction());
1114 // Remove all the current toolbar subfolders.
1115 for (QPair<QMenu *, QAction *> *subfolderActionPairPointer : bookmarksToolBarSubfolderActionList)
1117 // Remove the action from the subfolder.
1118 subfolderActionPairPointer->first->removeAction(subfolderActionPairPointer->second);
1121 // Remove all the current toolbar bookmarks.
1122 for (QAction *bookmarkAction : bookmarksToolBarActionList)
1124 // Remove the bookmark.
1125 bookmarksToolBarPointer->removeAction(bookmarkAction);
1128 // Clear the current bookmark lists.
1129 bookmarksMenuActionList.clear();
1130 bookmarksMenuSubmenuList.clear();
1131 bookmarksToolBarActionList.clear();
1132 bookmarksToolBarSubfolderActionList.clear();
1134 // Populate the bookmarks subfolders, beginning with the root folder (`0`);
1135 populateBookmarksMenuSubfolders(0, bookmarksMenuPointer);
1137 // Populate the bookmarks toolbar.
1138 populateBookmarksToolBar();
1140 // Get a handle for the bookmark toolbar layout.
1141 QLayout *bookmarksToolBarLayoutPointer = bookmarksToolBarPointer->layout();
1143 // Get the count of the bookmarks.
1144 int bookmarkCount = bookmarksToolBarLayoutPointer->count();
1146 // Set the layout of each bookmark to be left aligned.
1147 for(int i = 0; i < bookmarkCount; ++i)
1148 bookmarksToolBarLayoutPointer->itemAt(i)->setAlignment(Qt::AlignLeft);
1150 // Update the bookmarked action.
1151 updateBookmarkedAction();
1154 void BrowserWindow::populateBookmarksMenuSubfolders(const double folderId, QMenu *menuPointer)
1156 // Get the folder contents.
1157 QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1159 // Populate the bookmarks menu and toolbar.
1160 for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1162 // Process the item according to the type.
1163 if (bookmarkStruct.isFolder) // This item is a folder.
1165 // Add a submenu to the menu.
1166 QMenu *submenuPointer = menuPointer->addMenu(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1168 // Add the submenu to the beginning of the list of menus to be deleted on repopulate.
1169 bookmarksMenuSubmenuList.prepend(new QPair<QMenu *, QMenu *>(menuPointer, submenuPointer));
1171 // Populate any subfolders.
1172 populateBookmarksMenuSubfolders(bookmarkStruct.folderId, submenuPointer);
1174 else // This item is a bookmark.
1176 // Add the bookmark to the menu.
1177 QAction *menuBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1179 // Remove the focus from the URL line edit.
1180 urlLineEditPointer->clearFocus();
1183 tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1187 // Add the actions to the beginning of the list of bookmarks to be deleted on repopulate.
1188 bookmarksMenuActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, menuBookmarkActionPointer));
1192 // Add the extra items at the bottom of the menu.
1193 addFinalBookmarkFolderMenuActions(menuPointer, folderId);
1196 void BrowserWindow::populateBookmarksToolBar()
1198 // Get the root folder contents (which has a folder ID of `0`).
1199 QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(0);
1201 // Populate the bookmarks toolbar.
1202 for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1204 // Process the item according to the type.
1205 if (bookmarkStruct.isFolder) // This item is a folder.
1207 // Add the subfolder action.
1208 QAction *toolBarSubfolderActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1210 // Add the bookmark database ID to the toolbar action.
1211 toolBarSubfolderActionPointer->setData(bookmarkStruct.databaseId);
1213 // Add the action to the beginning of the list of actions to be deleted on repopulate.
1214 bookmarksToolBarActionList.prepend(toolBarSubfolderActionPointer);
1216 // Create a subfolder menu.
1217 QMenu *subfolderMenuPointer = new QMenu();
1219 // Add the menu to the action.
1220 toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1222 // Add the submenu to the toolbar menu list.
1223 bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1225 // Set the popup mode for the menu.
1226 dynamic_cast<QToolButton *>(bookmarksToolBarPointer->widgetForAction(toolBarSubfolderActionPointer))->setPopupMode(QToolButton::InstantPopup);
1228 // Populate the subfolder.
1229 populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1231 else // This item is a bookmark.
1233 // Add the bookmark to the toolbar.
1234 QAction *toolBarBookmarkActionPointer = bookmarksToolBarPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1236 // Remove the focus from the URL line edit.
1237 urlLineEditPointer->clearFocus();
1240 tabWidgetPointer->loadUrlFromLineEdit(bookmarkStruct.url);
1244 // Add the bookmark database ID to the toolbar action.
1245 toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1247 // Add the actions to the beginning of the current bookmarks lists.
1248 bookmarksToolBarActionList.prepend(toolBarBookmarkActionPointer);
1252 // Add the extra items to the toolbar folder menus. The first item in the pair is the menu pointer. The second is the folder ID.
1253 for (QPair<QMenu *, const double> *menuAndFolderIdPairPointer : bookmarksToolBarMenuList)
1255 // Populate the final bookmarks menu entries.
1256 addFinalBookmarkFolderMenuActions(menuAndFolderIdPairPointer->first, menuAndFolderIdPairPointer->second);
1260 void BrowserWindow::populateBookmarksToolBarSubfolders(const double folderId, QMenu *menuPointer)
1262 // Get the folder contents.
1263 QList<BookmarkStruct> *folderContentsListPointer = BookmarksDatabase::getFolderContents(folderId);
1265 // Populate the bookmarks folder.
1266 for (BookmarkStruct bookmarkStruct : *folderContentsListPointer)
1268 // Get the bookmark URL.
1269 QString bookmarkUrl = bookmarkStruct.url;
1271 // Process the item according to the type.
1272 if (bookmarkStruct.isFolder) // This item is a folder.
1274 // Add the subfolder action.
1275 QAction *toolBarSubfolderActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name);
1277 // Add the action to the beginning of the list of actions to be deleted on repopulate.
1278 bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarSubfolderActionPointer));
1280 // Create a subfolder menu.
1281 QMenu *subfolderMenuPointer = new QMenu();
1283 // Add the submenu to the action.
1284 toolBarSubfolderActionPointer->setMenu(subfolderMenuPointer);
1286 // Add the submenu to the toolbar menu list.
1287 bookmarksToolBarMenuList.append(new QPair<QMenu *, const double>(subfolderMenuPointer, bookmarkStruct.folderId));
1289 // Populate the subfolder menu.
1290 populateBookmarksToolBarSubfolders(bookmarkStruct.folderId, subfolderMenuPointer);
1292 else // This item is a bookmark.
1294 // Add the bookmark to the folder.
1295 QAction *toolBarBookmarkActionPointer = menuPointer->addAction(bookmarkStruct.favoriteIcon, bookmarkStruct.name, [=]
1297 // Remove the focus from the URL line edit.
1298 urlLineEditPointer->clearFocus();
1301 tabWidgetPointer->loadUrlFromLineEdit(bookmarkUrl);
1305 // Add the bookmark database ID to the toolbar action.
1306 toolBarBookmarkActionPointer->setData(bookmarkStruct.databaseId);
1308 // Add the action to the beginning of the list of actions to be deleted on repopulate.
1309 bookmarksToolBarSubfolderActionList.prepend(new QPair<QMenu *, QAction *>(menuPointer, toolBarBookmarkActionPointer));
1314 void BrowserWindow::refresh() const
1316 // Remove the focus from the URL line edit.
1317 urlLineEditPointer->clearFocus();
1319 // Refresh the web page.
1320 tabWidgetPointer->refresh();
1323 void BrowserWindow::reloadAndBypassCache() const
1325 // Remove the focus from the URL line edit.
1326 urlLineEditPointer->clearFocus();
1328 // Refresh the web page.
1329 tabWidgetPointer->refresh();
1332 void BrowserWindow::showBookmarkContextMenu(const QPoint &point)
1334 // Get the bookmark action.
1335 QAction *bookmarkActionPointer = bookmarksToolBarPointer->actionAt(point);
1337 // Check to see if an action was clicked.
1338 if (bookmarkActionPointer) // An action was clicked.
1340 // Create a bookmark context menu.
1341 QMenu *bookmarkContextMenuPointer = new QMenu();
1343 // Get the database ID from the action.
1344 int databaseId = bookmarkActionPointer->data().toInt();
1346 // Create the menu according to the type.
1347 if (BookmarksDatabase::isFolder(databaseId)) // A folder was clicked.
1349 // Populate the final bookmarks menu entries.
1350 addFinalBookmarkFolderMenuActions(bookmarkContextMenuPointer, BookmarksDatabase::getFolderId(databaseId));
1352 else // A bookmark was clicked.
1354 // Add the open in new tab action to the menu.
1355 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in new tab context menu entry", "Open in New Tab"), [=]
1357 // Get the bookmark.
1358 BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1360 // Open the bookmark in a new tab. `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab. `false` does not load a background tab.
1361 tabWidgetPointer->addTab(true, true, false, bookmarkStructPointer->url);
1365 // Add the open in background tab action to the menu.
1366 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("tab-new")), i18nc("Open bookmark in background tab context menu entry", "Open in Background Tab"), [=]
1368 // Get the bookmark.
1369 BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1371 // Open the bookmark in a new tab. `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab. `true` loads a background tab.
1372 tabWidgetPointer->addTab(true, true, true, bookmarkStructPointer->url);
1376 // Add the open in new window action to the menu.
1377 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("window-new")), i18nc("Open bookmark in new window context menu entry", "Open in New Window"), [=]
1379 // Get the bookmark.
1380 BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1382 // Create a new browser window and load the first URL. `false` indicates it is not the first browser window.
1383 BrowserWindow *browserWindowPointer = new BrowserWindow(false, &bookmarkStructPointer->url);
1385 // Show the new browser window.
1386 browserWindowPointer->show();
1391 bookmarkContextMenuPointer->addSeparator();
1393 // Add the edit action to the menu.
1394 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("document-edit")), i18nc("Edit bookmark context menu entry", "Edit"), [=]
1396 // Get the current tab favorite icon.
1397 QIcon currentTabFavoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1399 // Instantiate an edit bookmark dialog.
1400 QDialog *editBookmarkDialogPointer = new EditBookmarkDialog(databaseId, currentTabFavoriteIcon);
1403 editBookmarkDialogPointer->show();
1405 // Process bookmark events.
1406 connect(editBookmarkDialogPointer, SIGNAL(bookmarkSaved()), this, SLOT(populateBookmarksInAllWindows()));
1410 // Add the copy URL action to the menu.
1411 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-copy")), i18nc("Copy bookmark URL context menu entry", "Copy URL"), [=]
1413 // Get the bookmark.
1414 BookmarkStruct *bookmarkStructPointer = BookmarksDatabase::getBookmark(databaseId);
1416 // Get a handle for the clipboard.
1417 QClipboard *clipboard = QGuiApplication::clipboard();
1419 // Place the URL on the keyboard.
1420 clipboard->setText(bookmarkStructPointer->url);
1425 bookmarkContextMenuPointer->addSeparator();
1427 // Add the delete action to the menu.
1428 bookmarkContextMenuPointer->addAction(QIcon::fromTheme(QLatin1String("edit-delete")), i18nc("Delete bookmark context menu entry", "Delete"), [=]
1430 // Get the parent folder ID.
1431 double parentFolderId = BookmarksDatabase::getParentFolderId(databaseId);
1433 // Delete the bookmark.
1434 BookmarksDatabase::deleteBookmark(databaseId);
1436 // Update the display order of the bookmarks in the parent folder.
1437 BookmarksDatabase::updateFolderContentsDisplayOrder(parentFolderId);
1439 // Repopulate the bookmarks.
1440 populateBookmarksInAllWindows();
1445 // Delete the menu from memory when it is closed.
1446 bookmarkContextMenuPointer->setAttribute(Qt::WA_DeleteOnClose);
1448 // Display the context menu.
1449 bookmarkContextMenuPointer->popup(bookmarksToolBarPointer->mapToGlobal(point));
1451 else // The toolbar background was clicked.
1453 // Temporarily set the context menu policy to the default.
1454 bookmarksToolBarPointer->setContextMenuPolicy(Qt::DefaultContextMenu);
1456 // Create a context menu event with the same position.
1457 QContextMenuEvent *contextMenuEventPointer = new QContextMenuEvent(QContextMenuEvent::Mouse, point);
1459 // Send the context menu event to the toolbar.
1460 QCoreApplication::sendEvent(bookmarksToolBarPointer, contextMenuEventPointer);
1462 // Reset the context menu policy.
1463 bookmarksToolBarPointer->setContextMenuPolicy(Qt::CustomContextMenu);
1467 void BrowserWindow::showCookiesDialog()
1469 // Remove the focus from the URL line edit.
1470 urlLineEditPointer->clearFocus();
1472 // Instantiate the cookie settings dialog.
1473 CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
1476 cookiesDialogPointer->show();
1478 // Connect the dialog signals.
1479 connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
1480 connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
1481 connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
1484 void BrowserWindow::showDownloadDirectoryBrowseDialog() const
1486 // Get the current download directory.
1487 QString currentDownloadDirectory = downloadDirectoryComboBoxPointer->currentText();
1489 // Resolve the system download directory if specified.
1490 if (currentDownloadDirectory == QStringLiteral("System Download Directory"))
1491 currentDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
1493 // Get the new download directory.
1494 QString newDownloadDirectory = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download directory dialog caption", "Select Download Directory"),
1495 currentDownloadDirectory);
1497 // Populate the download directory combo box according to the new download location.
1498 if (newDownloadDirectory == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) // The default download location was selected.
1500 // Populate the download location with the default text.
1501 downloadDirectoryComboBoxPointer->setCurrentText("System Download Directory");
1503 else if (newDownloadDirectory != QStringLiteral("")) // A different directory was selected.
1505 // Populate the download location.
1506 downloadDirectoryComboBoxPointer->setCurrentText(newDownloadDirectory);
1510 void BrowserWindow::showDomainSettingsDialog() const
1512 // Remove the focus from the URL line edit.
1513 urlLineEditPointer->clearFocus();
1515 // Instantiate the domain settings dialog.
1516 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
1518 // Reload the tabs when domain settings are updated.
1519 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1522 domainSettingsDialogPointer->show();
1525 void BrowserWindow::showFindTextActions() const
1527 // Show the find text actions.
1528 findTextLineEditActionPointer->setVisible(true);
1529 findTextLabelActionPointer->setVisible(true);
1530 findNextActionPointer->setVisible(true);
1531 findPreviousActionPointer->setVisible(true);
1532 findCaseSensitiveActionPointer->setVisible(true);
1533 hideFindTextActionPointer->setVisible(true);
1535 // Set the focus on the find line edit.
1536 findTextLineEditPointer->setFocus();
1538 // Select all the text in the find line edit.
1539 findTextLineEditPointer->selectAll();
1542 void BrowserWindow::showProgressBar(const int &progress) const
1544 // Set the progress bar value.
1545 progressBarPointer->setValue(progress);
1547 // Show the progress bar.
1548 progressBarPointer->show();
1550 // Disable and hide the refresh action.
1551 refreshActionPointer->setEnabled(false);
1552 refreshActionPointer->setVisible(false);
1554 // Enable and show the stop action.
1555 stopActionPointer->setEnabled(true);
1556 stopActionPointer->setVisible(true);
1559 void BrowserWindow::showSettingsDialog()
1561 // Create the settings widgets.
1562 QWidget *privacySettingsWidgetPointer = new QWidget;
1563 QWidget *generalSettingsWidgetPointer = new QWidget;
1564 QWidget *spellCheckSettingsWidgetPointer = new QWidget;
1566 // Instantiate the settings UI.
1567 Ui::PrivacySettings privacySettingsUi;
1568 Ui::GeneralSettings generalSettingsUi;
1569 Ui::SpellCheckSettings spellCheckSettingsUi;
1571 // Setup the UI to display the settings widgets.
1572 privacySettingsUi.setupUi(privacySettingsWidgetPointer);
1573 generalSettingsUi.setupUi(generalSettingsWidgetPointer);
1574 spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
1576 // Get handles for the widgets.
1577 QCheckBox *javaScriptCheckBoxPointer = privacySettingsUi.kcfg_javaScriptEnabled;
1578 QCheckBox *localStorageCheckBoxPointer = privacySettingsUi.kcfg_localStorageEnabled;
1579 QCheckBox *domStorageCheckBoxPointer = privacySettingsUi.kcfg_domStorageEnabled;
1580 QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
1581 userAgentLabelPointer = privacySettingsUi.userAgentLabel;
1582 QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
1583 searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
1584 downloadDirectoryComboBoxPointer = generalSettingsUi.kcfg_downloadDirectory;
1585 QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
1586 QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
1588 // Create a save spell check languages lambda.
1589 auto updateCheckBoxes = [javaScriptCheckBoxPointer, localStorageCheckBoxPointer, domStorageCheckBoxPointer] ()
1591 // Only enable the DOM storage check box if both JavaScript and local storage are checked.
1592 domStorageCheckBoxPointer->setEnabled(javaScriptCheckBoxPointer->isChecked() && localStorageCheckBoxPointer->isChecked());
1595 // Update the status of the DOM storage check box when either JavaScript or local storage are changed.
1596 connect(javaScriptCheckBoxPointer, &QCheckBox::stateChanged, this, updateCheckBoxes);
1597 connect(localStorageCheckBoxPointer, &QCheckBox::stateChanged, this, updateCheckBoxes);
1599 // Populate the combo box labels.
1600 updateUserAgentLabel(userAgentComboBoxPointer->currentText());
1601 updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
1603 // Update the labels when the combo boxes change.
1604 connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
1605 connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
1607 // Connect the download directory directory browse button.
1608 connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadDirectoryBrowseDialog()));
1610 // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
1611 QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
1613 // Get a dictionaries string list.
1614 QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
1616 // Remove the `.bdic` file extensions from the dictionaries list.
1617 dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
1619 // Get a list of the enabled spell check languages.
1620 QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
1622 // Add each dictionary to the spell check list widget.
1623 foreach(QString dictionaryString, dictionariesStringList)
1625 // Create a new list widget item pointer.
1626 QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
1628 // Create a dictionary check box widget with the name of the dictionary string.
1629 QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
1631 // Check the language if it is currently enabled.
1632 if (enabledSpellCheckLanguagesList.contains(dictionaryString))
1633 dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
1635 dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
1637 // Add the list widget item to the spell check list widget.
1638 spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
1640 // Set the list widget item check box widget.
1641 spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
1644 // Get a handle for the KConfig skeleton.
1645 KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
1647 // Instantiate a settings config dialog from the settings.kcfg file.
1648 configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
1650 // Create a settings icon string.
1651 QString settingsIconString;
1653 // Get a settings icon that matches the theme.
1654 if (QIcon::hasThemeIcon("breeze-settings"))
1656 // KDE uses breeze-settings.
1657 settingsIconString = QLatin1String("breeze-settings");
1661 // Gnome uses preferences-desktop.
1662 settingsIconString = QLatin1String("preferences-desktop");
1665 // Add the settings widgets as config dialog pages.
1666 configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
1667 configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
1668 configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
1670 // Get handles for the buttons.
1671 QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
1672 QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
1674 // Prevent interaction with the parent window while the dialog is open.
1675 configDialogPointer->setWindowModality(Qt::WindowModal);
1678 configDialogPointer->show();
1680 // TODO. KConfigDialog does not respect expanding size policies. <https://redmine.stoutner.com/issues/823>
1681 //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1682 //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1683 //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
1684 //configDialogPointer->adjustSize();
1686 // Expand the config dialog.
1687 configDialogPointer->resize(1000, 500);
1689 // Create a save spell check languages lambda.
1690 auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
1692 // Create a list of enabled languages.
1693 QStringList newSpellCheckLanguages = QStringList();
1695 // Get a count of all the languages.
1696 int allLanguagesCount = spellCheckListWidgetPointer->count();
1698 // Get a list of all the checked languages.
1699 for (int i = 0; i < allLanguagesCount; ++i) {
1700 // Get the language item.
1701 QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
1703 // Get the language check box.
1704 QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
1706 // Add the item to the enabled languages if it is checked.
1707 if (languageCheckBoxPointer->checkState() == Qt::Checked)
1710 QString languageString = languageCheckBoxPointer->text();
1712 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
1713 languageString.remove(QChar('&'));
1715 // Add the language string to the list.
1716 newSpellCheckLanguages.append(languageString);
1720 // Update the spell check languages.
1721 if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
1723 // Update the spell check languages.
1724 Settings::setSpellCheckLanguages(newSpellCheckLanguages);
1726 // Write the settings to disk.
1727 kConfigSkeletonPointer->save();
1730 // Apply the spell check languages.
1731 tabWidgetPointer->applySpellCheckLanguages();
1735 connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1736 connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
1738 // Apply the settings handled by KConfig.
1739 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
1740 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
1743 QSize BrowserWindow::sizeHint() const
1745 // Return the default window size.
1746 return QSize(1500, 1200);
1749 void BrowserWindow::toggleBookmark()
1751 // Remove the focus from the URL line edit, which will have been focused when the user clicked on the bookmarked icon.
1752 urlLineEditPointer->clearFocus();
1754 // Create or delete the bookmark
1755 if (bookmarkedActionPointer->isChecked()) // The user checked the toggle. Create a bookmark.
1757 // Create a bookmark struct.
1758 BookmarkStruct *bookmarkStructPointer = new BookmarkStruct;
1760 // Populate the bookmark struct.
1761 bookmarkStructPointer->name = tabWidgetPointer->getCurrentTabTitle();
1762 bookmarkStructPointer->url = tabWidgetPointer->getCurrentTabUrl();
1763 bookmarkStructPointer->parentFolderId = 0;
1764 bookmarkStructPointer->favoriteIcon = tabWidgetPointer->getCurrentTabFavoritIcon();
1766 // Add the bookmark.
1767 BookmarksDatabase::addBookmark(bookmarkStructPointer);
1769 else // The user unchecked the toggle. Delete all related bookmarks.
1771 // Delete the bookmarks.
1772 BookmarksDatabase::deleteBookmarks(urlLineEditPointer->text());
1777 // Repopulate the bookmarks.
1778 populateBookmarksInAllWindows();
1781 void BrowserWindow::toggleDeveloperTools() const
1783 // Toggle the developer tools.
1784 tabWidgetPointer->toggleDeveloperTools(developerToolsActionPointer->isChecked());
1787 void BrowserWindow::toggleDomStorage() const
1789 // Remove the focus from the URL line edit.
1790 urlLineEditPointer->clearFocus();
1792 // Toggle DOM storage.
1793 tabWidgetPointer->toggleDomStorage();
1796 void BrowserWindow::toggleFindCaseSensitive() const
1798 // Get the current find string.
1799 const QString findString = findTextLineEditPointer->text();
1801 // Toggle find case sensitive.
1802 tabWidgetPointer->toggleFindCaseSensitive(findString);
1805 void BrowserWindow::toggleJavaScript() const
1807 // Remove the focus from the URL line edit.
1808 urlLineEditPointer->clearFocus();
1810 // Toggle JavaScript.
1811 tabWidgetPointer->toggleJavaScript();
1814 void BrowserWindow::toggleLocalStorage() const
1816 // Remove the focus from the URL line edit.
1817 urlLineEditPointer->clearFocus();
1819 // Toggle local storage.
1820 tabWidgetPointer->toggleLocalStorage();
1823 void BrowserWindow::toggleFullScreen()
1825 // Toggle the full screen status.
1826 fullScreenRequested(fullScreenActionPointer->isChecked());
1829 void BrowserWindow::toggleViewSource() const
1831 // Get the current URL.
1832 QString url = urlLineEditPointer->text();
1835 if (url.startsWith(QLatin1String("view-source:"))) // The source is currently being viewed.
1837 // Remove `view-source:` from the URL.
1838 url = url.remove(0, 12);
1840 else // The source is not currently being viewed.
1842 // Prepend `view-source:` from the URL.
1843 url = url.prepend(QLatin1String("view-source:"));
1847 loadUrlFromLineEdit(url);
1850 void BrowserWindow::toggleViewBookmarksToolBar()
1852 // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
1853 bookmarksToolBarIsVisible = viewBookmarksToolBarActionPointer->isChecked();
1855 // Update the visibility of the bookmarks toolbar.
1856 bookmarksToolBarPointer->setVisible(bookmarksToolBarIsVisible);
1859 void BrowserWindow::toggleViewSourceInNewTab() const
1861 // Get the current URL.
1862 QString url = urlLineEditPointer->text();
1865 if (url.startsWith(QLatin1String("view-source:"))) // The source is currently being viewed.
1867 // Remove `view-source:` from the URL.
1868 url = url.remove(0, 12);
1870 else // The source is not currently being viewed.
1872 // Prepend `view-source:` from the URL.
1873 url = url.prepend(QLatin1String("view-source:"));
1876 // Add the new tab. `true` removes the URL line edit focus, `true` opens the new tab in an adjacent tab. `false` does not open a background tab.
1877 tabWidgetPointer->addTab(true, true, false, url);
1880 void BrowserWindow::updateBookmarkedAction() const
1882 // Update the bookmarked action to reflect the current state.
1883 if (bookmarkedActionPointer->isChecked())
1884 bookmarkedActionPointer->setIcon(QIcon::fromTheme("starred-symbolic"));
1886 bookmarkedActionPointer->setIcon(QIcon::fromTheme("non-starred-symbolic"));
1889 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
1891 // Update the action text.
1892 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1895 void BrowserWindow::updateDefaultZoomFactor(const double newDefaultZoomFactorDouble)
1897 // Store the new default zoom factor.
1898 defaultZoomFactorDouble = newDefaultZoomFactorDouble;
1901 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1903 // Set the action checked status.
1904 domStorageActionPointer->setChecked(isEnabled);
1907 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1909 // Set the domain palette according to the status.
1911 urlLineEditPointer->setPalette(positiveBackgroundPalette);
1913 urlLineEditPointer->setPalette(normalBackgroundPalette);
1916 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1919 findTextLineEditPointer->setText(text);
1921 // Set the find case sensitive action checked status.
1922 findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1925 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1927 // Update the find text label.
1928 findTextLabelPointer->setText(QStringLiteral(" %1/%2 ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1930 // Set the background color according to the find status.
1931 if (findTextLineEditPointer->text().isEmpty())
1932 findTextLineEditPointer->setPalette(normalBackgroundPalette);
1933 else if (findTextResult.numberOfMatches() == 0)
1934 findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1936 findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1939 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1941 // Update the JavaScript status.
1942 javaScriptEnabled = isEnabled;
1944 // Set the icon according to the status.
1945 if (javaScriptEnabled)
1946 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1948 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1950 // Set the action checked status.
1951 javaScriptActionPointer->setChecked(javaScriptEnabled);
1953 // Update the status of the DOM storage action.
1954 domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1957 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1959 // Update the local storage status.
1960 localStorageEnabled = isEnabled;
1962 // 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.
1963 if (localStorageEnabled)
1964 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/document-save-as.png"))));
1966 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1968 // Set the action checked status.
1969 localStorageActionPointer->setChecked(localStorageEnabled);
1971 // Update the status of the DOM storage action.
1972 domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1975 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1977 // Initialize the custom search engine flag.
1978 bool customSearchEngine = false;
1980 if (searchEngine == "Mojeek") // Mojeek.
1982 // Check the Mojeek user agent action.
1983 searchEngineMojeekActionPointer->setChecked(true);
1985 // Update the search engine menu action icon.
1986 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1988 // Update the search engine menu action text.
1989 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1991 else if (searchEngine == "Monocles") // Monocles.
1993 // Check the Monocles user agent action.
1994 searchEngineMonoclesActionPointer->setChecked(true);
1996 // Update the search engine menu action icon.
1997 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1999 // Update the search engine menu action text.
2000 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
2002 else if (searchEngine == "MetaGer") // MetaGer.
2004 // Check the MetaGer user agent action.
2005 searchEngineMetagerActionPointer->setChecked(true);
2007 // Update the search engine menu action icon.
2008 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2010 // Update the search engine menu action text.
2011 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
2013 else if (searchEngine == "Google") // Google.
2015 // Check the Google user agent action.
2016 searchEngineGoogleActionPointer->setChecked(true);
2018 // Update the search engine menu action icon.
2019 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
2021 // Update the search engine menu action text.
2022 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
2024 else if (searchEngine == "Bing") // Bing.
2026 // Check the Bing user agent action.
2027 searchEngineBingActionPointer->setChecked(true);
2029 // Update the search engine menu action icon.
2030 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2032 // Update the search engine menu action text.
2033 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
2035 else if (searchEngine == "Yahoo") // Yahoo.
2037 // Check the Yahoo user agent action.
2038 searchEngineYahooActionPointer->setChecked(true);
2040 // Update the search engine menu action icon.
2041 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
2043 // Update the search engine menu action text.
2044 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
2046 else // Custom search engine.
2048 // Check the user agent.
2049 searchEngineCustomActionPointer->setChecked(true);
2051 // Update the search engine menu action icon.
2052 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
2054 // Update the search engine menu action text.
2055 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
2057 // Set the custom search engine text.
2058 searchEngineCustomActionPointer->setText(searchEngine);
2060 // Set the custom search engine flag.
2061 customSearchEngine = true;
2064 // Update the custom search engine enabled boolean.
2065 if (updateCustomSearchEngineStatus)
2066 customSearchEngineEnabled = customSearchEngine;
2068 // Format the custom search engine.
2069 if (customSearchEngineEnabled)
2071 // Enable the custom search engine.
2072 searchEngineCustomActionPointer->setEnabled(true);
2076 // Disable the custom search engine.
2077 searchEngineCustomActionPointer->setEnabled(false);
2079 // Reset the custom search engine text.
2080 searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
2084 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
2086 // Update the search engine label.
2087 searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
2090 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
2092 // Get the new URL string in encoded form, which displays punycode.
2093 QString newUrlString = newUrl.toEncoded();
2095 // Update the view source actions.
2096 if (newUrlString.startsWith(QLatin1String("view-source:"))) // The source is currently being viewed.
2098 // Mark the view source checkbox.
2099 viewSourceActionPointer->setChecked(true);
2101 // Update the view in new tab action text.
2102 viewSourceInNewTabActionPointer->setText(i18nc("View rendered website in new tab action", "View Rendered Website in New Tab"));
2104 else // The source is not currently being viewed.
2106 // Unmark the view source checkbox.
2107 viewSourceActionPointer->setChecked(false);
2109 // Update the view in new tab action text.
2110 viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
2113 // Update the URL line edit if it does not have focus.
2114 if (!urlLineEditPointer->hasFocus())
2116 // Update the URL line edit.
2117 urlLineEditPointer->setText(newUrlString);
2119 // Set the bookmarked action status.
2120 bookmarkedActionPointer->setChecked(BookmarksDatabase::isBookmarked(newUrlString));
2122 // Update the bookmarked action.
2123 updateBookmarkedAction();
2125 // Set the focus if the new URL is blank.
2126 if (newUrlString == QStringLiteral(""))
2127 urlLineEditPointer->setFocus();
2130 // Store the current URL.
2131 currentUrl = newUrl;
2134 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
2136 // Initialize the custom user agent flag.
2137 bool customUserAgent = false;
2139 // Check the indicated on-the-fly user agent.
2140 if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT) // Privacy Browser.
2142 // Check the Privacy Browser user agent action.
2143 userAgentPrivacyBrowserActionPointer->setChecked(true);
2145 // Update the user agent menu action icon.
2146 userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
2148 // Update the user agent menu action text.
2149 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
2151 else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
2153 // check the WebEngine default user agent action.
2154 userAgentWebEngineDefaultActionPointer->setChecked(true);
2156 // Update the user agent menu action icon.
2157 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2159 // Update the user agent menu action text.
2160 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
2162 else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT) // Firefox on Linux.
2164 // Check the Firefox on Linux user agent action.
2165 userAgentFirefoxLinuxActionPointer->setChecked(true);
2167 // Update the user agent menu action icon.
2168 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2170 // Update the user agent menu action text.
2171 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
2173 else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT) // Chromium on Linux.
2175 // Check the Chromium on Linux user agent action.
2176 userAgentChromiumLinuxActionPointer->setChecked(true);
2178 // Update the user agent menu action icon.
2179 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2181 // Update the user agent menu action text.
2182 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
2184 else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT) // Firefox on Windows.
2186 // Check the Firefox on Windows user agent action.
2187 userAgentFirefoxWindowsActionPointer->setChecked(true);
2189 // Update the user agent menu action icon.
2190 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2192 // Update the user agent menu action text.
2193 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
2195 else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT) // Chrome on Windows.
2197 // Check the Chrome on Windows user agent action.
2198 userAgentChromeWindowsActionPointer->setChecked(true);
2200 // Update the user agent menu action icon.
2201 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
2203 // Update the user agent menu action text.
2204 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
2206 else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT) // Edge on Windows.
2208 // Check the Edge on Windows user agent action.
2209 userAgentEdgeWindowsActionPointer->setChecked(true);
2211 // Update the user agent menu action icon.
2212 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2214 // Update the user agent menu action text.
2215 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
2217 else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT) // Safari on macOS.
2219 // Check the Safari on macOS user agent action.
2220 userAgentSafariMacosActionPointer->setChecked(true);
2222 // Update the user agent menu action icon.
2223 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2225 // Update the user agent menu action text.
2226 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
2228 else // Custom user agent.
2230 // Check the user agent.
2231 userAgentCustomActionPointer->setChecked(true);
2233 // Update the user agent menu action icon.
2234 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
2236 // Update the user agent menu action text.
2237 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
2239 // Set the custom user agent text.
2240 userAgentCustomActionPointer->setText(userAgent);
2242 // Set the custom user agent flag.
2243 customUserAgent = true;
2246 // Update the custom user agent enabled boolean.
2247 // 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.
2248 if (updateCustomUserAgentStatus)
2249 customUserAgentEnabled = customUserAgent;
2252 // Format the custom user agent.
2253 if (customUserAgentEnabled)
2255 // Enable the custom user agent.
2256 userAgentCustomActionPointer->setEnabled(true);
2260 // Disable the custom user agent.
2261 userAgentCustomActionPointer->setEnabled(false);
2263 // Reset the custom user agent text.
2264 userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
2268 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
2270 // Update the user agent label.
2271 userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
2274 void BrowserWindow::updateViewBookmarksToolBarCheckbox(const bool visible)
2276 // Update the view bookmarks toolbar checkbox.
2277 viewBookmarksToolBarActionPointer->setChecked(visible);
2279 // Initialize the bookmarks toolbar visibility tracker if Privacy Browser has just launched.
2280 if (bookmarksToolBarUninitialized)
2282 // Set the initialization flag.
2283 bookmarksToolBarUninitialized = false;
2285 // Store the current status of the bookmarks toolbar, which is used when exiting full screen browsing.
2286 bookmarksToolBarIsVisible = visible;
2290 void BrowserWindow::updateWindowTitle(const QString &title)
2292 // Update the window title.
2293 setWindowTitle(title);
2296 void BrowserWindow::updateZoomActions(const double zoomFactorDouble)
2298 // Set the current zoom factor.
2299 currentZoomFactorDouble = zoomFactorDouble;
2301 // Set the status of the default zoom action.
2302 zoomDefaultActionPointer->setEnabled(currentZoomFactorDouble != defaultZoomFactorDouble);
2304 // Set the status of the zoom in action and button.
2305 zoomInActionPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2306 zoomPlusButtonPointer->setEnabled(currentZoomFactorDouble <= 4.99);
2308 // Set the status of the zoom out action and button.
2309 zoomMinusButtonPointer->setEnabled(currentZoomFactorDouble > 0.25);
2310 zoomOutActionPointer->setEnabled(currentZoomFactorDouble > 0.25);
2313 // 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.
2314 zoomFactorActionPointer->setText(ki18nc("The zoom factor action", "Zoom Factor - %1").subs(zoomFactorDouble, 0, '0', 2).toString());
2316 // Update the status bar zoom factor label.
2317 currentZoomButtonPointer->setText(ki18nc("The status bar zoom, which is just the formatted zoom factor", "%1").subs(zoomFactorDouble, 0, '0', 2).toString());
2320 void BrowserWindow::zoomDefault()
2322 // Set the new zoom factor.
2323 tabWidgetPointer->applyOnTheFlyZoomFactor(defaultZoomFactorDouble);
2325 // Update the on-the-fly action text.
2326 updateZoomActions(defaultZoomFactorDouble);