2 * Copyright 2022-2023 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 "dialogs/CookiesDialog.h"
27 #include "dialogs/DomainSettingsDialog.h"
28 #include "helpers/SearchEngineHelper.h"
29 #include "helpers/UserAgentHelper.h"
31 // KDE Frameworks headers.
32 #include <KActionCollection>
33 #include <KColorScheme>
36 // Qt toolkit headers.
37 #include <QFileDialog>
38 #include <QInputDialog>
39 #include <QNetworkCookie>
43 #include <QWebEngineFindTextResult>
45 // Construct the class.
46 BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
48 // Initialize the variables.
49 javaScriptEnabled = false;
50 localStorageEnabled = false;
52 // Instantiate the privacy tab widget pointer.
53 tabWidgetPointer = new TabWidget(this);
55 // Set the privacy tab widget as the central widget.
56 setCentralWidget(tabWidgetPointer);
58 // Get a handle for the action collection.
59 KActionCollection *actionCollectionPointer = this->actionCollection();
61 // Add the standard actions.
62 KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
63 QAction *printPreviewActionPointer = KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
64 KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
65 KStandardAction::redisplay(this, SLOT(refresh()), actionCollectionPointer);
66 fullScreenActionPointer = KStandardAction::fullScreen(this, SLOT(toggleFullScreen()), this, actionCollectionPointer);
67 QAction *backActionPointer = KStandardAction::back(this, SLOT(back()), actionCollectionPointer);
68 QAction *forwardActionPointer = KStandardAction::forward(this, SLOT(forward()), actionCollectionPointer);
69 KStandardAction::home(this, SLOT(home()), actionCollectionPointer);
70 KStandardAction::preferences(this, SLOT(showSettingsDialog()), actionCollectionPointer);
71 KStandardAction::find(this, SLOT(showFindTextActions()), actionCollectionPointer);
72 findNextActionPointer = KStandardAction::findNext(this, SLOT(findNext()), actionCollectionPointer);
73 findPreviousActionPointer = KStandardAction::findPrev(this, SLOT(findPrevious()), actionCollectionPointer);
75 // Add the custom actions.
76 QAction *newTabActionPointer = actionCollectionPointer->addAction(QLatin1String("new_tab"));
77 QAction *newWindowActionPointer = actionCollectionPointer->addAction(QLatin1String("new_window"));
78 QAction *reloadAndBypassCacheActionPointer = actionCollectionPointer->addAction(QLatin1String("reload_and_bypass_cache"));
79 viewSourceActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source"));
80 QAction *viewSourceInNewTabActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source_in_new_tab"));
81 userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
82 userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
83 userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
84 userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chromium_linux"));
85 userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_windows"));
86 userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chrome_windows"));
87 userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_edge_windows"));
88 userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_safari_macos"));
89 userAgentCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_custom"));
90 zoomFactorActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_factor"));
91 searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_mojeek"));
92 searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_monocles"));
93 searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_metager"));
94 searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_google"));
95 searchEngineBingActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_bing"));
96 searchEngineYahooActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_yahoo"));
97 searchEngineCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_custom"));
98 QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QLatin1String("domain_settings"));
99 cookiesActionPointer = actionCollectionPointer->addAction(QLatin1String("cookies"));
100 javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
101 localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
102 domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
103 findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QLatin1String("find_case_sensitive"));
104 hideFindTextActionPointer = actionCollectionPointer->addAction(QLatin1String("hide_find_actions"));
106 // Create the action groups
107 QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
108 QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
110 // Add the actions to the groups.
111 userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
112 userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
113 userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
114 userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
115 userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
116 userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
117 userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
118 userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
119 userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
120 searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
121 searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
122 searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
123 searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
124 searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
125 searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
126 searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
128 // Set some actions to be checkable.
129 javaScriptActionPointer->setCheckable(true);
130 localStorageActionPointer->setCheckable(true);
131 domStorageActionPointer->setCheckable(true);
132 findCaseSensitiveActionPointer->setCheckable(true);
133 viewSourceActionPointer->setCheckable(true);
134 userAgentPrivacyBrowserActionPointer->setCheckable(true);
135 userAgentWebEngineDefaultActionPointer->setCheckable(true);
136 userAgentFirefoxLinuxActionPointer->setCheckable(true);
137 userAgentChromiumLinuxActionPointer->setCheckable(true);
138 userAgentFirefoxWindowsActionPointer->setCheckable(true);
139 userAgentChromeWindowsActionPointer->setCheckable(true);
140 userAgentEdgeWindowsActionPointer->setCheckable(true);
141 userAgentSafariMacosActionPointer->setCheckable(true);
142 userAgentCustomActionPointer->setCheckable(true);
143 searchEngineMojeekActionPointer->setCheckable(true);
144 searchEngineMonoclesActionPointer->setCheckable(true);
145 searchEngineMetagerActionPointer->setCheckable(true);
146 searchEngineGoogleActionPointer->setCheckable(true);
147 searchEngineBingActionPointer->setCheckable(true);
148 searchEngineYahooActionPointer->setCheckable(true);
149 searchEngineCustomActionPointer->setCheckable(true);
151 // Instantiate the user agent helper.
152 UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
154 // Set the action text.
155 viewSourceActionPointer->setText(i18nc("View source action", "View Source"));
156 viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
157 newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
158 newWindowActionPointer->setText(i18nc("New window action", "New Window"));
159 reloadAndBypassCacheActionPointer->setText(i18nc("Reload and bypass cache action", "Reload and Bypass Cache"));
160 userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
161 userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
162 userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
163 userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
164 userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
165 userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
166 userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
167 userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
168 searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
169 searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
170 searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
171 searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
172 searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
173 searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
174 domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
175 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
176 javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
177 localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
178 domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
179 findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
180 hideFindTextActionPointer->setText(i18nc("Hide Find Text action", "Hide Find Text"));
182 // Set the action icons. Gnome doesn't contain some of the icons that KDE has.
183 // The toolbar icons don't pick up unless the size is explicit, probably because the toolbar ends up being an intermediate size.
184 newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
185 newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
186 reloadAndBypassCacheActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
187 viewSourceActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
188 viewSourceInNewTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
189 userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
190 userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
191 userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
192 QIcon::fromTheme(QLatin1String("contact-new")))));
193 userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
194 userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
195 QIcon::fromTheme(QLatin1String("contact-new")))));
196 userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
197 userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
198 userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
199 userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
200 searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
201 searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
202 searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
203 searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
204 searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
205 searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
206 searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
207 zoomFactorActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
208 domainSettingsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("settings-configure"), QIcon::fromTheme(QLatin1String("preferences-desktop"))));
209 cookiesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-cookies"), QIcon::fromTheme(QLatin1String("appointment-new"))));
210 domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
211 findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase"), QIcon::fromTheme(QLatin1String("/usr/share/icons/gnome/32x32/apps/fonts.png"))));
212 hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
214 // Create the key sequences.
215 QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
216 QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
217 QKeySequence ctrlF5KeySequence = QKeySequence(i18nc("The reload and bypass cache key sequence.", "Ctrl+F5"));
218 QKeySequence ctrlUKeySequence = QKeySequence(i18nc("The view source key sequence.", "Ctrl+U"));
219 QKeySequence ctrlShiftUKeySequence = QKeySequence(i18nc("The view source in new tab key sequence.", "Ctrl+Shift+U"));
220 QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
221 QKeySequence ctrlAltPKeySequence = QKeySequence(i18nc("The Privacy Browser user agent key sequence.", "Ctrl+Alt+P"));
222 QKeySequence ctrlAltWKeySequence = QKeySequence(i18nc("The WebEngine Default user agent key sequence.", "Ctrl+Alt+W"));
223 QKeySequence ctrlAltFKeySequence = QKeySequence(i18nc("The Firefox on Linux user agent key sequence.", "Ctrl+Alt+F"));
224 QKeySequence ctrlAltCKeySequence = QKeySequence(i18nc("The Chromium on Linux user agent key sequence.", "Ctrl+Alt+C"));
225 QKeySequence ctrlAltShiftFKeySequence = QKeySequence(i18nc("The Firefox on Windows user agent key sequence.", "Ctrl+Alt+Shift+F"));
226 QKeySequence ctrlAltShiftCKeySequence = QKeySequence(i18nc("The Chrome on Windows user agent key sequence.", "Ctrl+Alt+Shift+C"));
227 QKeySequence ctrlAltEKeySequence = QKeySequence(i18nc("The Edge on Windows user agent key sequence.", "Ctrl+Alt+E"));
228 QKeySequence ctrlAltSKeySequence = QKeySequence(i18nc("The Safari on macOS user agent key sequence.", "Ctrl+Alt+S"));
229 QKeySequence altShiftCKeySequence = QKeySequence(i18nc("The custom user agent key sequence.", "Alt+Shift+C"));
230 QKeySequence ctrlAltZKeySequence = QKeySequence(i18nc("The zoom factor key sequence.", "Ctrl+Alt+Z"));
231 QKeySequence ctrlShiftMKeySequence = QKeySequence(i18nc("The Mojeek search engine key sequence.", "Ctrl+Shift+M"));
232 QKeySequence ctrlShiftOKeySequence = QKeySequence(i18nc("The Monocles search engine key sequence.", "Ctrl+Shift+O"));
233 QKeySequence ctrlShiftEKeySequence = QKeySequence(i18nc("The MetaGer search engine key sequence.", "Ctrl+Shift+E"));
234 QKeySequence ctrlShiftGKeySequence = QKeySequence(i18nc("The Google search engine key sequence.", "Ctrl+Shift+G"));
235 QKeySequence ctrlShiftBKeySequence = QKeySequence(i18nc("The Bing search engine key sequence.", "Ctrl+Shift+B"));
236 QKeySequence ctrlShiftYKeySequence = QKeySequence(i18nc("The Yahoo search engine key sequence.", "Ctrl+Shift+Y"));
237 QKeySequence ctrlShiftCKeySequence = QKeySequence(i18nc("The custom search engine key sequence.", "Ctrl+Shift+C"));
238 QKeySequence ctrlDKeySequence = QKeySequence(i18nc("The domain settings key sequence.", "Ctrl+D"));
239 QKeySequence ctrlSemicolonKeySequence = QKeySequence(i18nc("The cookies dialog key sequence.", "Ctrl+;"));
241 // Set the action key sequences.
242 actionCollectionPointer->setDefaultShortcut(newTabActionPointer, ctrlTKeySequence);
243 actionCollectionPointer->setDefaultShortcut(newWindowActionPointer, ctrlNKeySequence);
244 actionCollectionPointer->setDefaultShortcut(reloadAndBypassCacheActionPointer, ctrlF5KeySequence);
245 actionCollectionPointer->setDefaultShortcut(viewSourceActionPointer, ctrlUKeySequence);
246 actionCollectionPointer->setDefaultShortcut(viewSourceInNewTabActionPointer, ctrlShiftUKeySequence);
247 actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
248 actionCollectionPointer->setDefaultShortcut(userAgentPrivacyBrowserActionPointer, ctrlAltPKeySequence);
249 actionCollectionPointer->setDefaultShortcut(userAgentWebEngineDefaultActionPointer, ctrlAltWKeySequence);
250 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxLinuxActionPointer, ctrlAltFKeySequence);
251 actionCollectionPointer->setDefaultShortcut(userAgentChromiumLinuxActionPointer, ctrlAltCKeySequence);
252 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxWindowsActionPointer, ctrlAltShiftFKeySequence);
253 actionCollectionPointer->setDefaultShortcut(userAgentChromeWindowsActionPointer, ctrlAltShiftCKeySequence);
254 actionCollectionPointer->setDefaultShortcut(userAgentEdgeWindowsActionPointer, ctrlAltEKeySequence);
255 actionCollectionPointer->setDefaultShortcut(userAgentSafariMacosActionPointer, ctrlAltSKeySequence);
256 actionCollectionPointer->setDefaultShortcut(userAgentCustomActionPointer, altShiftCKeySequence);
257 actionCollectionPointer->setDefaultShortcut(zoomFactorActionPointer, ctrlAltZKeySequence);
258 actionCollectionPointer->setDefaultShortcut(searchEngineMojeekActionPointer, ctrlShiftMKeySequence);
259 actionCollectionPointer->setDefaultShortcut(searchEngineMonoclesActionPointer, ctrlShiftOKeySequence);
260 actionCollectionPointer->setDefaultShortcut(searchEngineMetagerActionPointer, ctrlShiftEKeySequence);
261 actionCollectionPointer->setDefaultShortcut(searchEngineGoogleActionPointer, ctrlShiftGKeySequence);
262 actionCollectionPointer->setDefaultShortcut(searchEngineBingActionPointer, ctrlShiftBKeySequence);
263 actionCollectionPointer->setDefaultShortcut(searchEngineYahooActionPointer, ctrlShiftYKeySequence);
264 actionCollectionPointer->setDefaultShortcut(searchEngineCustomActionPointer, ctrlShiftCKeySequence);
265 actionCollectionPointer->setDefaultShortcut(domainSettingsActionPointer, ctrlDKeySequence);
266 actionCollectionPointer->setDefaultShortcut(cookiesActionPointer, ctrlSemicolonKeySequence);
268 // Execute the actions.
269 connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
270 connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
271 connect(reloadAndBypassCacheActionPointer, SIGNAL(triggered()), this, SLOT(reloadAndBypassCache()));
272 connect(viewSourceActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSource()));
273 connect(viewSourceInNewTabActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSourceInNewTab()));
274 connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
275 connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
276 connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
278 // Update the on-the-fly menus.
279 connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
280 connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
281 connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
283 // Apply the on-the-fly settings when selected.
284 connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
285 connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
287 // Process cookie changes.
288 connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
290 // Connect the URL toolbar actions.
291 connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
292 connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
293 connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
295 // Update the URL toolbar actions.
296 connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
297 connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
298 connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
299 connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
300 connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
302 // Connect the find text actions.
303 connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
304 connect(hideFindTextActionPointer, SIGNAL(triggered()), this, SLOT(hideFindTextActions()));
306 // Setup the GUI based on the browserwindowui.rc file.
307 setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
309 // Get lists of the actions' associated widgets.
310 QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
311 QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
313 // Get the menu widget pointers. It is the second entry, after the main window.
314 QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
315 QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
317 // Get the menu pointers.
318 QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
319 QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
321 // Get the menu actions.
322 userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
323 searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
325 // Get handles for the toolbars.
326 navigationToolBarPointer = toolBar(QLatin1String("navigation_toolbar"));
327 urlToolBarPointer = toolBar(QLatin1String("url_toolbar"));
329 // Create the line edits.
330 urlLineEditPointer = new KLineEdit();
331 findTextLineEditPointer = new KLineEdit();
333 // Get the line edit size policies.
334 QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
335 QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
337 // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
338 urlLineEditSizePolicy.setHorizontalStretch(5);
339 findTextLineEditSizePolicy.setHorizontalStretch(1);
342 urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
343 findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
346 urlLineEditPointer->setMinimumWidth(350);
347 findTextLineEditPointer->setMinimumWidth(200);
348 findTextLineEditPointer->setMaximumWidth(350);
350 // Set the place holder text.
351 urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
352 findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
354 // Show the clear button on the find line edit.
355 findTextLineEditPointer->setClearButtonEnabled(true);
357 // Add an edit or add domain settings action to the URL line edit.
358 QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure", QIcon::fromTheme(QLatin1String("preferences-desktop"))),
359 QLineEdit::TrailingPosition);
361 // Add or edit the current domain settings.
362 connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
364 // Create a find text label pointer.
365 findTextLabelPointer = new QLabel();
367 // Set the default label text.
368 findTextLabelPointer->setText(QLatin1String(" ") + i18nc("Default find results.", "0/0") + QLatin1String(" "));
370 // Insert the widgets into the toolbars.
371 urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
372 findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
373 findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
375 // Initially hide the find text actions.
376 hideFindTextActions();
378 // Load a new URL from the URL line edit.
379 connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
381 // Find text as it is typed.
382 connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
384 // Find next if the enter key is pressed.
385 connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
387 // Update find text when switching tabs.
388 connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
390 // Update the find text results.
391 connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
393 // Update the URL line edit on page loads.
394 connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
396 // Update the window title.
397 connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
399 // Get a handle for the status bar.
400 QStatusBar *statusBarPointer = statusBar();
402 // Create a progress bar.
403 progressBarPointer = new QProgressBar();
405 // Add the progress bar to to the status bar.
406 statusBarPointer->addPermanentWidget(progressBarPointer);
408 // Update the status bar with the URL when a link is hovered.
409 connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
411 // Update the progress bar.
412 connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
413 connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
415 // Update the URL line edit focus.
416 connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
418 // Get the URL line edit palettes.
419 normalBackgroundPalette = urlLineEditPointer->palette();
420 negativeBackgroundPalette = normalBackgroundPalette;
421 positiveBackgroundPalette = normalBackgroundPalette;
423 // Modify the palettes.
424 KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
425 KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
427 // Update the applied palette.
428 connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
430 // Process full screen requests.
431 connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
433 // Create keyboard shortcuts.
434 QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
435 QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
437 // Connect the keyboard shortcuts.
438 connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
439 connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
442 // 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.
443 updateJavaScriptAction(Settings::javaScriptEnabled());
444 updateLocalStorageAction(Settings::localStorageEnabled());
445 updateDomStorageAction(Settings::domStorageEnabled());
446 updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
447 updateZoomFactorAction(Settings::zoomFactor());
449 // Load the initial website if this is the first window.
451 tabWidgetPointer->loadInitialWebsite();
454 void BrowserWindow::addOrEditDomainSettings() const
456 // Remove the focus from the URL line edit.
457 urlLineEditPointer->clearFocus();
459 // Create the domain settings dialog pointer.
460 DomainSettingsDialog *domainSettingsDialogPointer;
462 // Get the current domain settings name.
463 QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
465 // Run the commands according to the current domain settings status.
466 if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
468 // Instruct the domain settings dialog to add a new domain.
469 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
471 else // Domain settings are currently applied.
473 // Instruct the domain settings dialog to edit the current domain.
474 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
477 // Reload the tabs when domain settings are updated.
478 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
481 domainSettingsDialogPointer->show();
484 void BrowserWindow::back() const
486 // Remove the focus from the URL line edit.
487 urlLineEditPointer->clearFocus();
490 tabWidgetPointer->back();
493 void BrowserWindow::clearUrlLineEditFocus() const
495 // Remove the focus from the URL line edit.
496 urlLineEditPointer->clearFocus();
499 void BrowserWindow::escape() const
501 // Process the escape according to the status of the browser.
502 if (fullScreenActionPointer->isChecked()) // Full screen browsing is enabled.
504 // Exit full screen browsing.
505 fullScreenActionPointer->trigger();
507 else if (!findTextLineEditPointer->text().isEmpty()) // Find text is populated.
509 // Clear the find text line edit.
510 findTextLineEditPointer->clear();
512 // Clear the search in the WebEngine.
513 tabWidgetPointer->findText(QStringLiteral(""));
515 else if (findTextLineEditActionPointer->isVisible()) // Find text actions are visible.
517 // Hide the find text actions.
518 hideFindTextActions();
522 void BrowserWindow::findNext() const
524 // Get the find string.
525 const QString findString = findTextLineEditPointer->text();
527 // Search for the text if it is not empty.
528 if (!findString.isEmpty())
529 tabWidgetPointer->findText(findString);
532 void BrowserWindow::findPrevious() const
534 // Get the find string.
535 const QString findString = findTextLineEditPointer->text();
537 // Search for the text if it is not empty.
538 if (!findString.isEmpty())
539 tabWidgetPointer->findPrevious(findString);
542 void BrowserWindow::forward() const
544 // Remove the focus from the URL line edit.
545 urlLineEditPointer->clearFocus();
548 tabWidgetPointer->forward();
551 void BrowserWindow::fullScreenRequested(const bool toggleOn)
553 // Toggle full screen mode.
554 if (toggleOn) // Turn full screen mode on.
556 // Set the window to be full screen.
557 fullScreenActionPointer->setFullScreen(window(), true);
559 // Hide all the bars.
560 menuBar()->setVisible(false);
561 navigationToolBarPointer->setVisible(false);
562 urlToolBarPointer->setVisible(false);
563 tabWidgetPointer->setTabBarVisible(false);
564 statusBar()->setVisible(false);
566 else // Turn full screen mode off.
568 // Set the window to not be full screen.
569 fullScreenActionPointer->setFullScreen(window(), false);
571 // Show all the bars.
572 menuBar()->setVisible(true);
573 navigationToolBarPointer->setVisible(true);
574 urlToolBarPointer->setVisible(true);
575 tabWidgetPointer->setTabBarVisible(true);
576 statusBar()->setVisible(true);
580 void BrowserWindow::getZoomFactorFromUser()
582 // Create an OK flag.
585 // 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.
586 double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
587 i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
588 currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
590 // Update the zoom factor if the user clicked OK.
593 // Update the current zoom factor.
594 currentZoomFactor = newZoomFactor;
596 // Set the new zoom factor.
597 tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
599 // Update the on-the-fly action text.
600 updateZoomFactorAction(newZoomFactor);
604 void BrowserWindow::hideFindTextActions() const
606 // Hide the find text actions.
607 findTextLineEditActionPointer->setVisible(false);
608 findTextLabelActionPointer->setVisible(false);
609 findNextActionPointer->setVisible(false);
610 findPreviousActionPointer->setVisible(false);
611 findCaseSensitiveActionPointer->setVisible(false);
612 hideFindTextActionPointer->setVisible(false);
615 void BrowserWindow::home() const
617 // Remove the focus from the URL line edit.
618 urlLineEditPointer->clearFocus();
621 tabWidgetPointer->home();
624 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
626 // Remove the focus from the URL line edit.
627 urlLineEditPointer->clearFocus();
630 tabWidgetPointer->loadUrlFromLineEdit(url);
633 void BrowserWindow::newWindow() const
635 // Display a new instance of Privacy Browser.
636 (new BrowserWindow)->show();
639 void BrowserWindow::refresh() const
641 // Remove the focus from the URL line edit.
642 urlLineEditPointer->clearFocus();
644 // Refresh the web page.
645 tabWidgetPointer->refresh();
648 void BrowserWindow::reloadAndBypassCache() const
650 // Remove the focus from the URL line edit.
651 urlLineEditPointer->clearFocus();
653 // Refresh the web page.
654 tabWidgetPointer->refresh();
657 void BrowserWindow::showCookiesDialog()
659 // Remove the focus from the URL line edit.
660 urlLineEditPointer->clearFocus();
662 // Instantiate the cookie settings dialog.
663 CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
666 cookiesDialogPointer->show();
668 // Connect the dialog signals.
669 connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
670 connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
671 connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
674 void BrowserWindow::showDownloadLocationBrowseDialog() const
676 // Get the current download location.
677 QString currentDownloadLocation = downloadLocationComboBoxPointer->currentText();
679 // Resolve the system download directory if specified.
680 if (currentDownloadLocation == QStringLiteral("System Download Directory"))
681 currentDownloadLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
683 // Get the new download location.
684 QString newDownloadLocation = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download location dialog caption", "Select Download Location"), currentDownloadLocation);
686 // Populate the download location combo box according to the new download location.
687 if (newDownloadLocation == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) // The default download location was selected.
689 // Populate the download location with the default text.
690 downloadLocationComboBoxPointer->setCurrentText("System Download Directory");
692 else if (newDownloadLocation != QStringLiteral("")) // A different directory was selected.
694 // Populate the download location.
695 downloadLocationComboBoxPointer->setCurrentText(newDownloadLocation);
699 void BrowserWindow::showDomainSettingsDialog() const
701 // Remove the focus from the URL line edit.
702 urlLineEditPointer->clearFocus();
704 // Instantiate the domain settings dialog.
705 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
707 // Reload the tabs when domain settings are updated.
708 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
711 domainSettingsDialogPointer->show();
714 void BrowserWindow::showFindTextActions() const
716 // Show the find text actions.
717 findTextLineEditActionPointer->setVisible(true);
718 findTextLabelActionPointer->setVisible(true);
719 findNextActionPointer->setVisible(true);
720 findPreviousActionPointer->setVisible(true);
721 findCaseSensitiveActionPointer->setVisible(true);
722 hideFindTextActionPointer->setVisible(true);
724 // Set the focus on the find line edit.
725 findTextLineEditPointer->setFocus();
727 // Select all the text in the find line edit.
728 findTextLineEditPointer->selectAll();
731 void BrowserWindow::showProgressBar(const int &progress) const
733 // Set the progress bar value.
734 progressBarPointer->setValue(progress);
736 // Show the progress bar.
737 progressBarPointer->show();
740 void BrowserWindow::showSettingsDialog()
742 // Create the settings widgets.
743 QWidget *privacySettingsWidgetPointer = new QWidget;
744 QWidget *generalSettingsWidgetPointer = new QWidget;
745 QWidget *spellCheckSettingsWidgetPointer = new QWidget;
747 // Instantiate the settings UI.
748 Ui::PrivacySettings privacySettingsUi;
749 Ui::GeneralSettings generalSettingsUi;
750 Ui::SpellCheckSettings spellCheckSettingsUi;
752 // Setup the UI to display the settings widgets.
753 privacySettingsUi.setupUi(privacySettingsWidgetPointer);
754 generalSettingsUi.setupUi(generalSettingsWidgetPointer);
755 spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
757 // Get handles for the widgets.
758 QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
759 userAgentLabelPointer = privacySettingsUi.userAgentLabel;
760 QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
761 searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
762 downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
763 QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
764 QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
766 // Populate the combo box labels.
767 updateUserAgentLabel(userAgentComboBoxPointer->currentText());
768 updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
770 // Update the labels when the combo boxes change.
771 connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
772 connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
774 // Connect the download location directory browse button.
775 connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
777 // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
778 QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
780 // Get a dictionaries string list.
781 QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
783 // Remove the `.bdic` file extensions from the dictionaries list.
784 dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
786 // Get a list of the enabled spell check languages.
787 QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
789 // Add each dictionary to the spell check list widget.
790 foreach(QString dictionaryString, dictionariesStringList)
792 // Create a new list widget item pointer.
793 QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
795 // Create a dictionary check box widget with the name of the dictionary string.
796 QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
798 // Check the language if it is currently enabled.
799 if (enabledSpellCheckLanguagesList.contains(dictionaryString))
800 dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
802 dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
804 // Add the list widget item to the spell check list widget.
805 spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
807 // Set the list widget item check box widget.
808 spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
811 // Get a handle for the KConfig skeleton.
812 KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
814 // Instantiate a settings config dialog from the settings.kcfg file.
815 configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
817 // Create a settings icon string.
818 QString settingsIconString;
820 // Get a settings icon that matches the theme.
821 if (QIcon::hasThemeIcon("breeze-settings"))
823 // KDE uses breeze-settings.
824 settingsIconString = QLatin1String("breeze-settings");
828 // Gnome uses preferences-desktop.
829 settingsIconString = QLatin1String("preferences-desktop");
832 // Add the settings widgets as config dialog pages.
833 configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
834 configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
835 configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
837 // Get handles for the buttons.
838 QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
839 QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
841 // Prevent interaction with the parent window while the dialog is open.
842 configDialogPointer->setWindowModality(Qt::WindowModal);
845 configDialogPointer->show();
847 // TODO. KConfigDialog does not respect expanding size policies. <https://redmine.stoutner.com/issues/823>
848 //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
849 //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
850 //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
851 //configDialogPointer->adjustSize();
853 // Expand the config dialog.
854 configDialogPointer->resize(1000, 500);
856 // Create a save spell check languages lambda.
857 auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
859 // Create a list of enabled languages.
860 QStringList newSpellCheckLanguages = QStringList();
862 // Get a count of all the languages.
863 int allLanguagesCount = spellCheckListWidgetPointer->count();
865 // Get a list of all the checked languages.
866 for (int i = 0; i < allLanguagesCount; ++i) {
867 // Get the language item.
868 QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
870 // Get the language check box.
871 QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
873 // Add the item to the enabled languages if it is checked.
874 if (languageCheckBoxPointer->checkState() == Qt::Checked)
877 QString languageString = languageCheckBoxPointer->text();
879 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
880 languageString.remove(QChar('&'));
882 // Add the language string to the list.
883 newSpellCheckLanguages.append(languageString);
887 // Update the spell check languages.
888 if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
890 // Update the spell check languages.
891 Settings::setSpellCheckLanguages(newSpellCheckLanguages);
893 // Write the settings to disk.
894 kConfigSkeletonPointer->save();
897 // Apply the spell check languages.
898 tabWidgetPointer->applySpellCheckLanguages();
902 connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
903 connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
905 // Apply the settings handled by KConfig.
906 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
907 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
910 QSize BrowserWindow::sizeHint() const
912 // Return the default window size.
913 return QSize(1500, 1200);
916 void BrowserWindow::toggleDomStorage() const
918 // Remove the focus from the URL line edit.
919 urlLineEditPointer->clearFocus();
921 // Toggle DOM storage.
922 tabWidgetPointer->toggleDomStorage();
925 void BrowserWindow::toggleFindCaseSensitive() const
927 // Get the current find string.
928 const QString findString = findTextLineEditPointer->text();
930 // Toggle find case sensitive.
931 tabWidgetPointer->toggleFindCaseSensitive(findString);
934 void BrowserWindow::toggleJavaScript() const
936 // Remove the focus from the URL line edit.
937 urlLineEditPointer->clearFocus();
939 // Toggle JavaScript.
940 tabWidgetPointer->toggleJavaScript();
943 void BrowserWindow::toggleLocalStorage() const
945 // Remove the focus from the URL line edit.
946 urlLineEditPointer->clearFocus();
948 // Toggle local storage.
949 tabWidgetPointer->toggleLocalStorage();
952 void BrowserWindow::toggleFullScreen()
954 // Toggle the full screen status.
955 if (fullScreenActionPointer->isChecked()) // Enable full screen browsing mode.
957 // Enable full screen mode.
958 fullScreenActionPointer->setFullScreen(window(), true);
960 // Hide the menu bar if specified.
961 if (Settings::fullScreenHideMenuBar())
962 menuBar()->setVisible(false);
964 // Hide the toolbars if specified.
965 if (Settings::fullScreenHideToolBars())
967 navigationToolBarPointer->setVisible(false);
968 urlToolBarPointer->setVisible(false);
971 // Hide the tab bar if specified.
972 if (Settings::fullScreenHideTabBar())
973 tabWidgetPointer->setTabBarVisible(false);
975 // Hide the status bar if specified.
976 if (Settings::fullScreenHideStatusBar())
977 statusBar()->setVisible(false);
979 else // Disable full screen browsing mode.
981 // Disable full screen mode.
982 fullScreenActionPointer->setFullScreen(window(), false);
984 // Show the menu bar.
985 menuBar()->setVisible(true);
987 // Show the toolbars.
988 navigationToolBarPointer->setVisible(true);
989 urlToolBarPointer->setVisible(true);
992 tabWidgetPointer->setTabBarVisible(true);
994 // Show the status bar.
995 statusBar()->setVisible(true);
999 void BrowserWindow::toggleViewSource() const
1001 // Get the current URL.
1002 QString url = urlLineEditPointer->text();
1005 if (url.startsWith(QLatin1String("view-source:"))) // The source is currently being viewed.
1007 // Remove `view-source:` from the URL.
1008 url = url.remove(0, 12);
1010 else // The source is not currently being viewed.
1012 // Prepend `view-source:` from the URL.
1013 url = url.prepend(QLatin1String("view-source:"));
1017 loadUrlFromLineEdit(url);
1020 void BrowserWindow::toggleViewSourceInNewTab() const
1022 // Get the current URL.
1023 QString url = urlLineEditPointer->text();
1026 if (url.startsWith(QLatin1String("view-source:"))) // The source is currently being viewed.
1028 // Remove `view-source:` from the URL.
1029 url = url.remove(0, 12);
1031 else // The source is not currently being viewed.
1033 // Prepend `view-source:` from the URL.
1034 url = url.prepend(QLatin1String("view-source:"));
1037 // Add the new tab. `true` removes the URL line edit focus, `false` does not open a background tab.
1038 tabWidgetPointer->addTab(true, false, url);
1041 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
1043 // Update the action text.
1044 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1047 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1049 // Set the action checked status.
1050 domStorageActionPointer->setChecked(isEnabled);
1053 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1055 // Set the domain palette according to the status.
1057 urlLineEditPointer->setPalette(positiveBackgroundPalette);
1059 urlLineEditPointer->setPalette(normalBackgroundPalette);
1062 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1065 findTextLineEditPointer->setText(text);
1067 // Set the find case sensitive action checked status.
1068 findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1071 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1073 // Update the find text label.
1074 findTextLabelPointer->setText(QStringLiteral(" %1/%2 ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1076 // Set the background color according to the find status.
1077 if (findTextLineEditPointer->text().isEmpty())
1078 findTextLineEditPointer->setPalette(normalBackgroundPalette);
1079 else if (findTextResult.numberOfMatches() == 0)
1080 findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1082 findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1085 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1087 // Update the JavaScript status.
1088 javaScriptEnabled = isEnabled;
1090 // Set the icon according to the status.
1091 if (javaScriptEnabled)
1092 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1094 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1096 // Set the action checked status.
1097 javaScriptActionPointer->setChecked(javaScriptEnabled);
1099 // Update the status of the DOM storage action.
1100 domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1103 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1105 // Update the local storage status.
1106 localStorageEnabled = isEnabled;
1108 // 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.
1109 if (localStorageEnabled)
1110 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/document-save-as.png"))));
1112 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1114 // Set the action checked status.
1115 localStorageActionPointer->setChecked(localStorageEnabled);
1117 // Update the status of the DOM storage action.
1118 domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1121 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1123 // Initialize the custom search engine flag.
1124 bool customSearchEngine = false;
1126 if (searchEngine == "Mojeek") // Mojeek.
1128 // Check the Mojeek user agent action.
1129 searchEngineMojeekActionPointer->setChecked(true);
1131 // Update the search engine menu action icon.
1132 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1134 // Update the search engine menu action text.
1135 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1137 else if (searchEngine == "Monocles") // Monocles.
1139 // Check the Monocles user agent action.
1140 searchEngineMonoclesActionPointer->setChecked(true);
1142 // Update the search engine menu action icon.
1143 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1145 // Update the search engine menu action text.
1146 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1148 else if (searchEngine == "MetaGer") // MetaGer.
1150 // Check the MetaGer user agent action.
1151 searchEngineMetagerActionPointer->setChecked(true);
1153 // Update the search engine menu action icon.
1154 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1156 // Update the search engine menu action text.
1157 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1159 else if (searchEngine == "Google") // Google.
1161 // Check the Google user agent action.
1162 searchEngineGoogleActionPointer->setChecked(true);
1164 // Update the search engine menu action icon.
1165 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
1167 // Update the search engine menu action text.
1168 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
1170 else if (searchEngine == "Bing") // Bing.
1172 // Check the Bing user agent action.
1173 searchEngineBingActionPointer->setChecked(true);
1175 // Update the search engine menu action icon.
1176 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1178 // Update the search engine menu action text.
1179 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
1181 else if (searchEngine == "Yahoo") // Yahoo.
1183 // Check the Yahoo user agent action.
1184 searchEngineYahooActionPointer->setChecked(true);
1186 // Update the search engine menu action icon.
1187 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
1189 // Update the search engine menu action text.
1190 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
1192 else // Custom search engine.
1194 // Check the user agent.
1195 searchEngineCustomActionPointer->setChecked(true);
1197 // Update the search engine menu action icon.
1198 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1200 // Update the search engine menu action text.
1201 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
1203 // Set the custom search engine text.
1204 searchEngineCustomActionPointer->setText(searchEngine);
1206 // Set the custom search engine flag.
1207 customSearchEngine = true;
1210 // Update the custom search engine enabled boolean.
1211 if (updateCustomSearchEngineStatus)
1212 customSearchEngineEnabled = customSearchEngine;
1214 // Format the custom search engine.
1215 if (customSearchEngineEnabled)
1217 // Enable the custom search engine.
1218 searchEngineCustomActionPointer->setEnabled(true);
1222 // Disable the custom search engine.
1223 searchEngineCustomActionPointer->setEnabled(false);
1225 // Reset the custom search engine text.
1226 searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
1230 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
1232 // Initialize the custom user agent flag.
1233 bool customUserAgent = false;
1235 // Check the indicated on-the-fly user agent.
1236 if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT) // Privacy Browser.
1238 // Check the Privacy Browser user agent action.
1239 userAgentPrivacyBrowserActionPointer->setChecked(true);
1241 // Update the user agent menu action icon.
1242 userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
1244 // Update the user agent menu action text.
1245 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
1247 else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
1249 // check the WebEngine default user agent action.
1250 userAgentWebEngineDefaultActionPointer->setChecked(true);
1252 // Update the user agent menu action icon.
1253 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1255 // Update the user agent menu action text.
1256 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
1258 else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT) // Firefox on Linux.
1260 // Check the Firefox on Linux user agent action.
1261 userAgentFirefoxLinuxActionPointer->setChecked(true);
1263 // Update the user agent menu action icon.
1264 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1266 // Update the user agent menu action text.
1267 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
1269 else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT) // Chromium on Linux.
1271 // Check the Chromium on Linux user agent action.
1272 userAgentChromiumLinuxActionPointer->setChecked(true);
1274 // Update the user agent menu action icon.
1275 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1277 // Update the user agent menu action text.
1278 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
1280 else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT) // Firefox on Windows.
1282 // Check the Firefox on Windows user agent action.
1283 userAgentFirefoxWindowsActionPointer->setChecked(true);
1285 // Update the user agent menu action icon.
1286 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1288 // Update the user agent menu action text.
1289 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
1291 else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT) // Chrome on Windows.
1293 // Check the Chrome on Windows user agent action.
1294 userAgentChromeWindowsActionPointer->setChecked(true);
1296 // Update the user agent menu action icon.
1297 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1299 // Update the user agent menu action text.
1300 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
1302 else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT) // Edge on Windows.
1304 // Check the Edge on Windows user agent action.
1305 userAgentEdgeWindowsActionPointer->setChecked(true);
1307 // Update the user agent menu action icon.
1308 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1310 // Update the user agent menu action text.
1311 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
1313 else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT) // Safari on macOS.
1315 // Check the Safari on macOS user agent action.
1316 userAgentSafariMacosActionPointer->setChecked(true);
1318 // Update the user agent menu action icon.
1319 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1321 // Update the user agent menu action text.
1322 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
1324 else // Custom user agent.
1326 // Check the user agent.
1327 userAgentCustomActionPointer->setChecked(true);
1329 // Update the user agent menu action icon.
1330 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1332 // Update the user agent menu action text.
1333 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
1335 // Set the custom user agent text.
1336 userAgentCustomActionPointer->setText(userAgent);
1338 // Set the custom user agent flag.
1339 customUserAgent = true;
1342 // Update the custom user agent enabled boolean.
1343 // 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.
1344 if (updateCustomUserAgentStatus)
1345 customUserAgentEnabled = customUserAgent;
1348 // Format the custom user agent.
1349 if (customUserAgentEnabled)
1351 // Enable the custom user agent.
1352 userAgentCustomActionPointer->setEnabled(true);
1356 // Disable the custom user agent.
1357 userAgentCustomActionPointer->setEnabled(false);
1359 // Reset the custom user agent text.
1360 userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
1364 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
1366 // Set the current zoom factor.
1367 currentZoomFactor = zoomFactor;
1369 // Update the zoom factor action text, formatting the double with 2 decimal places.
1370 zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
1373 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
1375 // Update the search engine label.
1376 searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
1379 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1381 // Get the new URL string.
1382 QString newUrlString = newUrl.toString();
1384 // Update the view source checkbox.
1385 viewSourceActionPointer->setChecked(newUrlString.startsWith(QLatin1String("view-source:")));
1387 // Update the URL line edit if it does not have focus.
1388 if (!urlLineEditPointer->hasFocus())
1390 // Update the URL line edit.
1391 urlLineEditPointer->setText(newUrlString);
1393 // Set the focus if the new URL is blank.
1394 if (newUrlString == QStringLiteral(""))
1395 urlLineEditPointer->setFocus();
1398 // Store the current URL.
1399 currentUrl = newUrl;
1402 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
1404 // Update the user agent label.
1405 userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
1408 void BrowserWindow::updateWindowTitle(const QString &title)
1410 // Update the window title.
1411 setWindowTitle(title);