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 userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
80 userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
81 userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
82 userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chromium_linux"));
83 userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_windows"));
84 userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chrome_windows"));
85 userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_edge_windows"));
86 userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_safari_macos"));
87 userAgentCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_custom"));
88 zoomFactorActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_factor"));
89 searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_mojeek"));
90 searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_monocles"));
91 searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_metager"));
92 searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_google"));
93 searchEngineBingActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_bing"));
94 searchEngineYahooActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_yahoo"));
95 searchEngineCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_custom"));
96 QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QLatin1String("domain_settings"));
97 cookiesActionPointer = actionCollectionPointer->addAction(QLatin1String("cookies"));
98 javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
99 localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
100 domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
101 findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QLatin1String("find_case_sensitive"));
102 hideFindTextActionPointer = actionCollectionPointer->addAction(QLatin1String("hide_find_actions"));
104 // Create the action groups
105 QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
106 QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
108 // Add the actions to the groups.
109 userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
110 userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
111 userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
112 userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
113 userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
114 userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
115 userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
116 userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
117 userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
118 searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
119 searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
120 searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
121 searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
122 searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
123 searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
124 searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
126 // Set some actions to be checkable.
127 javaScriptActionPointer->setCheckable(true);
128 localStorageActionPointer->setCheckable(true);
129 domStorageActionPointer->setCheckable(true);
130 findCaseSensitiveActionPointer->setCheckable(true);
131 userAgentPrivacyBrowserActionPointer->setCheckable(true);
132 userAgentWebEngineDefaultActionPointer->setCheckable(true);
133 userAgentFirefoxLinuxActionPointer->setCheckable(true);
134 userAgentChromiumLinuxActionPointer->setCheckable(true);
135 userAgentFirefoxWindowsActionPointer->setCheckable(true);
136 userAgentChromeWindowsActionPointer->setCheckable(true);
137 userAgentEdgeWindowsActionPointer->setCheckable(true);
138 userAgentSafariMacosActionPointer->setCheckable(true);
139 userAgentCustomActionPointer->setCheckable(true);
140 searchEngineMojeekActionPointer->setCheckable(true);
141 searchEngineMonoclesActionPointer->setCheckable(true);
142 searchEngineMetagerActionPointer->setCheckable(true);
143 searchEngineGoogleActionPointer->setCheckable(true);
144 searchEngineBingActionPointer->setCheckable(true);
145 searchEngineYahooActionPointer->setCheckable(true);
146 searchEngineCustomActionPointer->setCheckable(true);
148 // Instantiate the user agent helper.
149 UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
151 // Set the action text.
152 newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
153 newWindowActionPointer->setText(i18nc("New window action", "New Window"));
154 reloadAndBypassCacheActionPointer->setText(i18nc("Reload and bypass cache action", "Reload and Bypass Cache"));
155 userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
156 userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
157 userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
158 userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
159 userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
160 userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
161 userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
162 userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
163 searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
164 searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
165 searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
166 searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
167 searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
168 searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
169 domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
170 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
171 javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
172 localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
173 domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
174 findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
175 hideFindTextActionPointer->setText(i18nc("Hide Find Text action", "Hide Find Text"));
177 // Set the action icons. Gnome doesn't contain some of the icons that KDE has.
178 // The toolbar icons don't pick up unless the size is explicit, probably because the toolbar ends up being an intermediate size.
179 newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
180 newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
181 reloadAndBypassCacheActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
182 userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
183 userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"),
184 QIcon::fromTheme(QLatin1String("contact-new")))));
185 userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
186 QIcon::fromTheme(QLatin1String("contact-new")))));
187 userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"),
188 QIcon::fromTheme(QLatin1String("contact-new")))));
189 userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
190 QIcon::fromTheme(QLatin1String("contact-new")))));
191 userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"),
192 QIcon::fromTheme(QLatin1String("contact-new")))));
193 userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
194 userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
195 userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
196 searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
197 searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
198 searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
199 searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
200 searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
201 searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
202 searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
203 zoomFactorActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
204 domainSettingsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("settings-configure"), QIcon::fromTheme(QLatin1String("preferences-desktop"))));
205 cookiesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-cookies"), QIcon::fromTheme(QLatin1String("appointment-new"))));
206 domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
207 findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase"), QIcon::fromTheme(QLatin1String("/usr/share/icons/gnome/32x32/apps/fonts.png"))));
208 hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
210 // Create the key sequences.
211 QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
212 QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
213 QKeySequence ctrlF5KeySequence = QKeySequence(i18nc("The reload and bypass cache key sequence.", "Ctrl+F5"));
214 QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
215 QKeySequence ctrlAltPKeySequence = QKeySequence(i18nc("The Privacy Browser user agent key sequence.", "Ctrl+Alt+P"));
216 QKeySequence ctrlAltWKeySequence = QKeySequence(i18nc("The WebEngine Default user agent key sequence.", "Ctrl+Alt+W"));
217 QKeySequence ctrlAltFKeySequence = QKeySequence(i18nc("The Firefox on Linux user agent key sequence.", "Ctrl+Alt+F"));
218 QKeySequence ctrlAltCKeySequence = QKeySequence(i18nc("The Chromium on Linux user agent key sequence.", "Ctrl+Alt+C"));
219 QKeySequence ctrlAltShiftFKeySequence = QKeySequence(i18nc("The Firefox on Windows user agent key sequence.", "Ctrl+Alt+Shift+F"));
220 QKeySequence ctrlAltShiftCKeySequence = QKeySequence(i18nc("The Chrome on Windows user agent key sequence.", "Ctrl+Alt+Shift+C"));
221 QKeySequence ctrlAltEKeySequence = QKeySequence(i18nc("The Edge on Windows user agent key sequence.", "Ctrl+Alt+E"));
222 QKeySequence ctrlAltSKeySequence = QKeySequence(i18nc("The Safari on macOS user agent key sequence.", "Ctrl+Alt+S"));
223 QKeySequence altShiftCKeySequence = QKeySequence(i18nc("The custom user agent key sequence.", "Alt+Shift+C"));
224 QKeySequence ctrlAltZKeySequence = QKeySequence(i18nc("The zoom factor key sequence.", "Ctrl+Alt+Z"));
225 QKeySequence ctrlShiftMKeySequence = QKeySequence(i18nc("The Mojeek search engine key sequence.", "Ctrl+Shift+M"));
226 QKeySequence ctrlShiftOKeySequence = QKeySequence(i18nc("The Monocles search engine key sequence.", "Ctrl+Shift+O"));
227 QKeySequence ctrlShiftEKeySequence = QKeySequence(i18nc("The MetaGer search engine key sequence.", "Ctrl+Shift+E"));
228 QKeySequence ctrlShiftGKeySequence = QKeySequence(i18nc("The Google search engine key sequence.", "Ctrl+Shift+G"));
229 QKeySequence ctrlShiftBKeySequence = QKeySequence(i18nc("The Bing search engine key sequence.", "Ctrl+Shift+B"));
230 QKeySequence ctrlShiftYKeySequence = QKeySequence(i18nc("The Yahoo search engine key sequence.", "Ctrl+Shift+Y"));
231 QKeySequence ctrlShiftCKeySequence = QKeySequence(i18nc("The custom search engine key sequence.", "Ctrl+Shift+C"));
232 QKeySequence ctrlDKeySequence = QKeySequence(i18nc("The domain settings key sequence.", "Ctrl+D"));
233 QKeySequence ctrlSemicolonKeySequence = QKeySequence(i18nc("The cookies dialog key sequence.", "Ctrl+;"));
235 // Set the action key sequences.
236 actionCollectionPointer->setDefaultShortcut(newTabActionPointer, ctrlTKeySequence);
237 actionCollectionPointer->setDefaultShortcut(newWindowActionPointer, ctrlNKeySequence);
238 actionCollectionPointer->setDefaultShortcut(reloadAndBypassCacheActionPointer, ctrlF5KeySequence);
239 actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
240 actionCollectionPointer->setDefaultShortcut(userAgentPrivacyBrowserActionPointer, ctrlAltPKeySequence);
241 actionCollectionPointer->setDefaultShortcut(userAgentWebEngineDefaultActionPointer, ctrlAltWKeySequence);
242 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxLinuxActionPointer, ctrlAltFKeySequence);
243 actionCollectionPointer->setDefaultShortcut(userAgentChromiumLinuxActionPointer, ctrlAltCKeySequence);
244 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxWindowsActionPointer, ctrlAltShiftFKeySequence);
245 actionCollectionPointer->setDefaultShortcut(userAgentChromeWindowsActionPointer, ctrlAltShiftCKeySequence);
246 actionCollectionPointer->setDefaultShortcut(userAgentEdgeWindowsActionPointer, ctrlAltEKeySequence);
247 actionCollectionPointer->setDefaultShortcut(userAgentSafariMacosActionPointer, ctrlAltSKeySequence);
248 actionCollectionPointer->setDefaultShortcut(userAgentCustomActionPointer, altShiftCKeySequence);
249 actionCollectionPointer->setDefaultShortcut(zoomFactorActionPointer, ctrlAltZKeySequence);
250 actionCollectionPointer->setDefaultShortcut(searchEngineMojeekActionPointer, ctrlShiftMKeySequence);
251 actionCollectionPointer->setDefaultShortcut(searchEngineMonoclesActionPointer, ctrlShiftOKeySequence);
252 actionCollectionPointer->setDefaultShortcut(searchEngineMetagerActionPointer, ctrlShiftEKeySequence);
253 actionCollectionPointer->setDefaultShortcut(searchEngineGoogleActionPointer, ctrlShiftGKeySequence);
254 actionCollectionPointer->setDefaultShortcut(searchEngineBingActionPointer, ctrlShiftBKeySequence);
255 actionCollectionPointer->setDefaultShortcut(searchEngineYahooActionPointer, ctrlShiftYKeySequence);
256 actionCollectionPointer->setDefaultShortcut(searchEngineCustomActionPointer, ctrlShiftCKeySequence);
257 actionCollectionPointer->setDefaultShortcut(domainSettingsActionPointer, ctrlDKeySequence);
258 actionCollectionPointer->setDefaultShortcut(cookiesActionPointer, ctrlSemicolonKeySequence);
260 // Execute the actions.
261 connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
262 connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
263 connect(reloadAndBypassCacheActionPointer, SIGNAL(triggered()), this, SLOT(reloadAndBypassCache()));
264 connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
265 connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
266 connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
268 // Update the on-the-fly menus.
269 connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
270 connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
271 connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
273 // Apply the on-the-fly settings when selected.
274 connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
275 connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
277 // Process cookie changes.
278 connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
280 // Connect the URL toolbar actions.
281 connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
282 connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
283 connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
285 // Update the URL toolbar actions.
286 connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
287 connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
288 connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
289 connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
290 connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
292 // Connect the find text actions.
293 connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
294 connect(hideFindTextActionPointer, SIGNAL(triggered()), this, SLOT(hideFindTextActions()));
296 // Setup the GUI based on the browserwindowui.rc file.
297 setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
299 // Get lists of the actions' associated widgets.
300 QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
301 QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
303 // Get the menu widget pointers. It is the second entry, after the main window.
304 QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
305 QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
307 // Get the menu pointers.
308 QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
309 QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
311 // Get the menu actions.
312 userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
313 searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
315 // Get handles for the toolbars.
316 navigationToolBarPointer = toolBar(QLatin1String("navigation_toolbar"));
317 urlToolBarPointer = toolBar(QLatin1String("url_toolbar"));
319 // Create the line edits.
320 urlLineEditPointer = new KLineEdit();
321 findTextLineEditPointer = new KLineEdit();
323 // Get the line edit size policies.
324 QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
325 QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
327 // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
328 urlLineEditSizePolicy.setHorizontalStretch(5);
329 findTextLineEditSizePolicy.setHorizontalStretch(1);
332 urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
333 findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
336 urlLineEditPointer->setMinimumWidth(350);
337 findTextLineEditPointer->setMinimumWidth(200);
338 findTextLineEditPointer->setMaximumWidth(350);
340 // Set the place holder text.
341 urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
342 findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
344 // Show the clear button on the find line edit.
345 findTextLineEditPointer->setClearButtonEnabled(true);
347 // Add an edit or add domain settings action to the URL line edit.
348 QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure", QIcon::fromTheme(QLatin1String("preferences-desktop"))),
349 QLineEdit::TrailingPosition);
351 // Add or edit the current domain settings.
352 connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
354 // Create a find text label pointer.
355 findTextLabelPointer = new QLabel();
357 // Set the default label text.
358 findTextLabelPointer->setText(QLatin1String(" ") + i18nc("Default find results.", "0/0") + QLatin1String(" "));
360 // Insert the widgets into the toolbars.
361 urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
362 findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
363 findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
365 // Initially hide the find text actions.
366 hideFindTextActions();
368 // Load a new URL from the URL line edit.
369 connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
371 // Find text as it is typed.
372 connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
374 // Find next if the enter key is pressed.
375 connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
377 // Update find text when switching tabs.
378 connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
380 // Update the find text results.
381 connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
383 // Update the URL line edit on page loads.
384 connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
386 // Update the window title.
387 connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
389 // Get a handle for the status bar.
390 QStatusBar *statusBarPointer = statusBar();
392 // Create a progress bar.
393 progressBarPointer = new QProgressBar();
395 // Add the progress bar to to the status bar.
396 statusBarPointer->addPermanentWidget(progressBarPointer);
398 // Update the status bar with the URL when a link is hovered.
399 connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
401 // Update the progress bar.
402 connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
403 connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
405 // Update the URL line edit focus.
406 connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
408 // Get the URL line edit palettes.
409 normalBackgroundPalette = urlLineEditPointer->palette();
410 negativeBackgroundPalette = normalBackgroundPalette;
411 positiveBackgroundPalette = normalBackgroundPalette;
413 // Modify the palettes.
414 KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
415 KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
417 // Update the applied palette.
418 connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
420 // Process full screen requests.
421 connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
423 // Create keyboard shortcuts.
424 QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
425 QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
427 // Connect the keyboard shortcuts.
428 connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
429 connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
432 // 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.
433 updateJavaScriptAction(Settings::javaScriptEnabled());
434 updateLocalStorageAction(Settings::localStorageEnabled());
435 updateDomStorageAction(Settings::domStorageEnabled());
436 updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
437 updateZoomFactorAction(Settings::zoomFactor());
439 // Load the initial website if this is the first window.
441 tabWidgetPointer->loadInitialWebsite();
444 void BrowserWindow::addOrEditDomainSettings() const
446 // Remove the focus from the URL line edit.
447 urlLineEditPointer->clearFocus();
449 // Create the domain settings dialog pointer.
450 DomainSettingsDialog *domainSettingsDialogPointer;
452 // Get the current domain settings name.
453 QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
455 // Run the commands according to the current domain settings status.
456 if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
458 // Instruct the domain settings dialog to add a new domain.
459 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
461 else // Domain settings are currently applied.
463 // Instruct the domain settings dialog to edit the current domain.
464 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
467 // Set the dialog window title.
468 domainSettingsDialogPointer->setWindowTitle(i18nc("The domain settings dialog title", "Domain Settings"));
471 domainSettingsDialogPointer->setWindowModality(Qt::WindowModality::WindowModal);;
474 domainSettingsDialogPointer->show();
476 // Reload the tabs when domain settings are updated.
477 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
480 void BrowserWindow::back() const
482 // Remove the focus from the URL line edit.
483 urlLineEditPointer->clearFocus();
486 tabWidgetPointer->back();
489 void BrowserWindow::clearUrlLineEditFocus() const
491 // Remove the focus from the URL line edit.
492 urlLineEditPointer->clearFocus();
495 void BrowserWindow::escape() const
497 // Process the escape according to the status of the browser.
498 if (fullScreenActionPointer->isChecked()) // Full screen browsing is enabled.
500 // Exit full screen browsing.
501 fullScreenActionPointer->trigger();
503 else if (!findTextLineEditPointer->text().isEmpty()) // Find text is populated.
505 // Clear the find text line edit.
506 findTextLineEditPointer->clear();
508 // Clear the search in the WebEngine.
509 tabWidgetPointer->findText(QStringLiteral(""));
511 else if (findTextLineEditActionPointer->isVisible()) // Find text actions are visible.
513 // Hide the find text actions.
514 hideFindTextActions();
518 void BrowserWindow::findNext() const
520 // Get the find string.
521 const QString findString = findTextLineEditPointer->text();
523 // Search for the text if it is not empty.
524 if (!findString.isEmpty())
525 tabWidgetPointer->findText(findString);
528 void BrowserWindow::findPrevious() const
530 // Get the find string.
531 const QString findString = findTextLineEditPointer->text();
533 // Search for the text if it is not empty.
534 if (!findString.isEmpty())
535 tabWidgetPointer->findPrevious(findString);
538 void BrowserWindow::forward() const
540 // Remove the focus from the URL line edit.
541 urlLineEditPointer->clearFocus();
544 tabWidgetPointer->forward();
547 void BrowserWindow::fullScreenRequested(const bool toggleOn)
549 // Toggle full screen mode.
550 if (toggleOn) // Turn full screen mode on.
552 // Set the window to be full screen.
553 fullScreenActionPointer->setFullScreen(window(), true);
555 // Hide all the bars.
556 menuBar()->setVisible(false);
557 navigationToolBarPointer->setVisible(false);
558 urlToolBarPointer->setVisible(false);
559 tabWidgetPointer->setTabBarVisible(false);
560 statusBar()->setVisible(false);
562 else // Turn full screen mode off.
564 // Set the window to not be full screen.
565 fullScreenActionPointer->setFullScreen(window(), false);
567 // Show all the bars.
568 menuBar()->setVisible(true);
569 navigationToolBarPointer->setVisible(true);
570 urlToolBarPointer->setVisible(true);
571 tabWidgetPointer->setTabBarVisible(true);
572 statusBar()->setVisible(true);
576 void BrowserWindow::getZoomFactorFromUser()
578 // Create an OK flag.
581 // 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.
582 double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
583 i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
584 currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
586 // Update the zoom factor if the user clicked OK.
589 // Update the current zoom factor.
590 currentZoomFactor = newZoomFactor;
592 // Set the new zoom factor.
593 tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
595 // Update the on-the-fly action text.
596 updateZoomFactorAction(newZoomFactor);
600 void BrowserWindow::hideFindTextActions() const
602 // Hide the find text actions.
603 findTextLineEditActionPointer->setVisible(false);
604 findTextLabelActionPointer->setVisible(false);
605 findNextActionPointer->setVisible(false);
606 findPreviousActionPointer->setVisible(false);
607 findCaseSensitiveActionPointer->setVisible(false);
608 hideFindTextActionPointer->setVisible(false);
611 void BrowserWindow::home() const
613 // Remove the focus from the URL line edit.
614 urlLineEditPointer->clearFocus();
617 tabWidgetPointer->home();
620 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
622 // Remove the focus from the URL line edit.
623 urlLineEditPointer->clearFocus();
626 tabWidgetPointer->loadUrlFromLineEdit(url);
629 void BrowserWindow::newWindow() const
631 // Display a new instance of Privacy Browser.
632 (new BrowserWindow)->show();
635 void BrowserWindow::refresh() const
637 // Remove the focus from the URL line edit.
638 urlLineEditPointer->clearFocus();
640 // Refresh the web page.
641 tabWidgetPointer->refresh();
644 void BrowserWindow::reloadAndBypassCache() const
646 // Remove the focus from the URL line edit.
647 urlLineEditPointer->clearFocus();
649 // Refresh the web page.
650 tabWidgetPointer->refresh();
653 void BrowserWindow::showCookiesDialog()
655 // Remove the focus from the URL line edit.
656 urlLineEditPointer->clearFocus();
658 // Instantiate the cookie settings dialog.
659 CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
662 cookiesDialogPointer->show();
664 // Connect the dialog signals.
665 connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
666 connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
667 connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
670 void BrowserWindow::showDownloadLocationBrowseDialog() const
672 // Get the current download location.
673 QString currentDownloadLocation = downloadLocationComboBoxPointer->currentText();
675 // Resolve the system download directory if specified.
676 if (currentDownloadLocation == QStringLiteral("System Download Directory"))
677 currentDownloadLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
679 // Get the new download location.
680 QString newDownloadLocation = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download location dialog caption", "Select Download Location"), currentDownloadLocation);
682 // Populate the download location combo box according to the new download location.
683 if (newDownloadLocation == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) // The default download location was selected.
685 // Populate the download location with the default text.
686 downloadLocationComboBoxPointer->setCurrentText("System Download Directory");
688 else if (newDownloadLocation != QStringLiteral("")) // A different directory was selected.
690 // Populate the download location.
691 downloadLocationComboBoxPointer->setCurrentText(newDownloadLocation);
695 void BrowserWindow::showDomainSettingsDialog() const
697 // Remove the focus from the URL line edit.
698 urlLineEditPointer->clearFocus();
700 // Instantiate the domain settings dialog.
701 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
704 domainSettingsDialogPointer->show();
706 // Reload the tabs when domain settings are updated.
707 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
710 void BrowserWindow::showFindTextActions() const
712 // Show the find text actions.
713 findTextLineEditActionPointer->setVisible(true);
714 findTextLabelActionPointer->setVisible(true);
715 findNextActionPointer->setVisible(true);
716 findPreviousActionPointer->setVisible(true);
717 findCaseSensitiveActionPointer->setVisible(true);
718 hideFindTextActionPointer->setVisible(true);
720 // Set the focus on the find line edit.
721 findTextLineEditPointer->setFocus();
723 // Select all the text in the find line edit.
724 findTextLineEditPointer->selectAll();
727 void BrowserWindow::showProgressBar(const int &progress) const
729 // Set the progress bar value.
730 progressBarPointer->setValue(progress);
732 // Show the progress bar.
733 progressBarPointer->show();
736 void BrowserWindow::showSettingsDialog()
738 // Create the settings widgets.
739 QWidget *privacySettingsWidgetPointer = new QWidget;
740 QWidget *generalSettingsWidgetPointer = new QWidget;
741 QWidget *spellCheckSettingsWidgetPointer = new QWidget;
743 // Instantiate the settings UI.
744 Ui::PrivacySettings privacySettingsUi;
745 Ui::GeneralSettings generalSettingsUi;
746 Ui::SpellCheckSettings spellCheckSettingsUi;
748 // Setup the UI to display the settings widgets.
749 privacySettingsUi.setupUi(privacySettingsWidgetPointer);
750 generalSettingsUi.setupUi(generalSettingsWidgetPointer);
751 spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
753 // Get handles for the widgets.
754 QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
755 userAgentLabelPointer = privacySettingsUi.userAgentLabel;
756 QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
757 searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
758 downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
759 QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
760 QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
762 // Populate the combo box labels.
763 updateUserAgentLabel(userAgentComboBoxPointer->currentText());
764 updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
766 // Update the labels when the combo boxes change.
767 connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
768 connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
770 // Connect the download location directory browse button.
771 connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
773 // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
774 QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
776 // Get a dictionaries string list.
777 QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
779 // Remove the `.bdic` file extensions from the dictionaries list.
780 dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
782 // Get a list of the enabled spell check languages.
783 QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
785 // Add each dictionary to the spell check list widget.
786 foreach(QString dictionaryString, dictionariesStringList)
788 // Create a new list widget item pointer.
789 QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
791 // Create a dictionary check box widget with the name of the dictionary string.
792 QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
794 // Check the language if it is currently enabled.
795 if (enabledSpellCheckLanguagesList.contains(dictionaryString))
796 dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
798 dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
800 // Add the list widget item to the spell check list widget.
801 spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
803 // Set the list widget item check box widget.
804 spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
807 // Get a handle for the KConfig skeleton.
808 KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
810 // Instantiate a settings config dialog from the settings.kcfg file.
811 configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
813 // Create a settings icon string.
814 QString settingsIconString;
816 // Get a settings icon that matches the theme.
817 if (QIcon::hasThemeIcon("breeze-settings"))
819 // KDE uses breeze-settings.
820 settingsIconString = QLatin1String("breeze-settings");
824 // Gnome uses preferences-desktop.
825 settingsIconString = QLatin1String("preferences-desktop");
828 // Add the settings widgets as config dialog pages.
829 configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
830 configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
831 configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
833 // Get handles for the buttons.
834 QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
835 QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
837 // Prevent interaction with the parent window while the dialog is open.
838 configDialogPointer->setWindowModality(Qt::WindowModal);
841 configDialogPointer->show();
843 // TODO. KConfigDialog does not respect expanding size policies. <https://redmine.stoutner.com/issues/823>
844 //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
845 //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
846 //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
847 //configDialogPointer->adjustSize();
849 // Expand the config dialog.
850 configDialogPointer->resize(1000, 500);
852 // Create a save spell check languages lambda.
853 auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
855 // Create a list of enabled languages.
856 QStringList newSpellCheckLanguages = QStringList();
858 // Get a count of all the languages.
859 int allLanguagesCount = spellCheckListWidgetPointer->count();
861 // Get a list of all the checked languages.
862 for (int i = 0; i < allLanguagesCount; ++i) {
863 // Get the language item.
864 QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
866 // Get the language check box.
867 QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
869 // Add the item to the enabled languages if it is checked.
870 if (languageCheckBoxPointer->checkState() == Qt::Checked)
873 QString languageString = languageCheckBoxPointer->text();
875 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
876 languageString.remove(QChar('&'));
878 // Add the language string to the list.
879 newSpellCheckLanguages.append(languageString);
883 // Update the spell check languages.
884 if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
886 // Update the spell check languages.
887 Settings::setSpellCheckLanguages(newSpellCheckLanguages);
889 // Write the settings to disk.
890 kConfigSkeletonPointer->save();
893 // Apply the spell check languages.
894 tabWidgetPointer->applySpellCheckLanguages();
898 connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
899 connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
901 // Apply the settings handled by KConfig.
902 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
903 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
906 QSize BrowserWindow::sizeHint() const
908 // Return the default window size.
909 return QSize(1500, 1200);
912 void BrowserWindow::toggleDomStorage() const
914 // Remove the focus from the URL line edit.
915 urlLineEditPointer->clearFocus();
917 // Toggle DOM storage.
918 tabWidgetPointer->toggleDomStorage();
921 void BrowserWindow::toggleFindCaseSensitive() const
923 // Get the current find string.
924 const QString findString = findTextLineEditPointer->text();
926 // Toggle find case sensitive.
927 tabWidgetPointer->toggleFindCaseSensitive(findString);
930 void BrowserWindow::toggleJavaScript() const
932 // Remove the focus from the URL line edit.
933 urlLineEditPointer->clearFocus();
935 // Toggle JavaScript.
936 tabWidgetPointer->toggleJavaScript();
939 void BrowserWindow::toggleLocalStorage() const
941 // Remove the focus from the URL line edit.
942 urlLineEditPointer->clearFocus();
944 // Toggle local storage.
945 tabWidgetPointer->toggleLocalStorage();
948 void BrowserWindow::toggleFullScreen()
950 // Toggle the full screen status.
951 if (fullScreenActionPointer->isChecked()) // Enable full screen browsing mode.
953 // Enable full screen mode.
954 fullScreenActionPointer->setFullScreen(window(), true);
956 // Hide the menu bar if specified.
957 if (Settings::fullScreenHideMenuBar())
958 menuBar()->setVisible(false);
960 // Hide the toolbars if specified.
961 if (Settings::fullScreenHideToolBars())
963 navigationToolBarPointer->setVisible(false);
964 urlToolBarPointer->setVisible(false);
967 // Hide the tab bar if specified.
968 if (Settings::fullScreenHideTabBar())
969 tabWidgetPointer->setTabBarVisible(false);
971 // Hide the status bar if specified.
972 if (Settings::fullScreenHideStatusBar())
973 statusBar()->setVisible(false);
975 else // Disable full screen browsing mode.
977 // Disable full screen mode.
978 fullScreenActionPointer->setFullScreen(window(), false);
980 // Show the menu bar.
981 menuBar()->setVisible(true);
983 // Show the toolbars.
984 navigationToolBarPointer->setVisible(true);
985 urlToolBarPointer->setVisible(true);
988 tabWidgetPointer->setTabBarVisible(true);
990 // Show the status bar.
991 statusBar()->setVisible(true);
995 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
997 // Update the action text.
998 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
1001 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
1003 // Set the action checked status.
1004 domStorageActionPointer->setChecked(isEnabled);
1007 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
1009 // Set the domain palette according to the status.
1011 urlLineEditPointer->setPalette(positiveBackgroundPalette);
1013 urlLineEditPointer->setPalette(normalBackgroundPalette);
1016 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1019 findTextLineEditPointer->setText(text);
1021 // Set the find case sensitive action checked status.
1022 findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1025 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1027 // Update the find text label.
1028 findTextLabelPointer->setText(QStringLiteral(" %1/%2 ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1030 // Set the background color according to the find status.
1031 if (findTextLineEditPointer->text().isEmpty())
1032 findTextLineEditPointer->setPalette(normalBackgroundPalette);
1033 else if (findTextResult.numberOfMatches() == 0)
1034 findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1036 findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1039 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1041 // Update the JavaScript status.
1042 javaScriptEnabled = isEnabled;
1044 // Set the icon according to the status.
1045 if (javaScriptEnabled)
1046 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1048 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1050 // Set the action checked status.
1051 javaScriptActionPointer->setChecked(javaScriptEnabled);
1053 // Update the status of the DOM storage action.
1054 domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1057 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1059 // Update the local storage status.
1060 localStorageEnabled = isEnabled;
1062 // 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.
1063 if (localStorageEnabled)
1064 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/filesaveas.png"))));
1066 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1068 // Set the action checked status.
1069 localStorageActionPointer->setChecked(localStorageEnabled);
1071 // Update the status of the DOM storage action.
1072 domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1075 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1077 // Initialize the custom search engine flag.
1078 bool customSearchEngine = false;
1080 if (searchEngine == "Mojeek") // Mojeek.
1082 // Check the Mojeek user agent action.
1083 searchEngineMojeekActionPointer->setChecked(true);
1085 // Update the search engine menu action icon.
1086 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1088 // Update the search engine menu action text.
1089 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1091 else if (searchEngine == "Monocles") // Monocles.
1093 // Check the Monocles user agent action.
1094 searchEngineMonoclesActionPointer->setChecked(true);
1096 // Update the search engine menu action icon.
1097 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1099 // Update the search engine menu action text.
1100 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1102 else if (searchEngine == "MetaGer") // MetaGer.
1104 // Check the MetaGer user agent action.
1105 searchEngineMetagerActionPointer->setChecked(true);
1107 // Update the search engine menu action icon.
1108 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1110 // Update the search engine menu action text.
1111 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1113 else if (searchEngine == "Google") // Google.
1115 // Check the Google user agent action.
1116 searchEngineGoogleActionPointer->setChecked(true);
1118 // Update the search engine menu action icon.
1119 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
1121 // Update the search engine menu action text.
1122 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
1124 else if (searchEngine == "Bing") // Bing.
1126 // Check the Bing user agent action.
1127 searchEngineBingActionPointer->setChecked(true);
1129 // Update the search engine menu action icon.
1130 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1132 // Update the search engine menu action text.
1133 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
1135 else if (searchEngine == "Yahoo") // Yahoo.
1137 // Check the Yahoo user agent action.
1138 searchEngineYahooActionPointer->setChecked(true);
1140 // Update the search engine menu action icon.
1141 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
1143 // Update the search engine menu action text.
1144 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
1146 else // Custom search engine.
1148 // Check the user agent.
1149 searchEngineCustomActionPointer->setChecked(true);
1151 // Update the search engine menu action icon.
1152 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1154 // Update the search engine menu action text.
1155 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
1157 // Set the custom search engine text.
1158 searchEngineCustomActionPointer->setText(searchEngine);
1160 // Set the custom search engine flag.
1161 customSearchEngine = true;
1164 // Update the custom search engine enabled boolean.
1165 if (updateCustomSearchEngineStatus)
1166 customSearchEngineEnabled = customSearchEngine;
1168 // Format the custom search engine.
1169 if (customSearchEngineEnabled)
1171 // Enable the custom search engine.
1172 searchEngineCustomActionPointer->setEnabled(true);
1176 // Disable the custom search engine.
1177 searchEngineCustomActionPointer->setEnabled(false);
1179 // Reset the custom search engine text.
1180 searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
1184 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
1186 // Initialize the custom user agent flag.
1187 bool customUserAgent = false;
1189 // Check the indicated on-the-fly user agent.
1190 if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT) // Privacy Browser.
1192 // Check the Privacy Browser user agent action.
1193 userAgentPrivacyBrowserActionPointer->setChecked(true);
1195 // Update the user agent menu action icon.
1196 userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
1198 // Update the user agent menu action text.
1199 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
1201 else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
1203 // check the WebEngine default user agent action.
1204 userAgentWebEngineDefaultActionPointer->setChecked(true);
1206 // Update the user agent menu action icon.
1207 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1209 // Update the user agent menu action text.
1210 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
1212 else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT) // Firefox on Linux.
1214 // Check the Firefox on Linux user agent action.
1215 userAgentFirefoxLinuxActionPointer->setChecked(true);
1217 // Update the user agent menu action icon.
1218 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1220 // Update the user agent menu action text.
1221 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
1223 else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT) // Chromium on Linux.
1225 // Check the Chromium on Linux user agent action.
1226 userAgentChromiumLinuxActionPointer->setChecked(true);
1228 // Update the user agent menu action icon.
1229 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1231 // Update the user agent menu action text.
1232 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
1234 else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT) // Firefox on Windows.
1236 // Check the Firefox on Windows user agent action.
1237 userAgentFirefoxWindowsActionPointer->setChecked(true);
1239 // Update the user agent menu action icon.
1240 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1242 // Update the user agent menu action text.
1243 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
1245 else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT) // Chrome on Windows.
1247 // Check the Chrome on Windows user agent action.
1248 userAgentChromeWindowsActionPointer->setChecked(true);
1250 // Update the user agent menu action icon.
1251 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1253 // Update the user agent menu action text.
1254 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
1256 else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT) // Edge on Windows.
1258 // Check the Edge on Windows user agent action.
1259 userAgentEdgeWindowsActionPointer->setChecked(true);
1261 // Update the user agent menu action icon.
1262 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1264 // Update the user agent menu action text.
1265 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
1267 else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT) // Safari on macOS.
1269 // Check the Safari on macOS user agent action.
1270 userAgentSafariMacosActionPointer->setChecked(true);
1272 // Update the user agent menu action icon.
1273 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1275 // Update the user agent menu action text.
1276 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
1278 else // Custom user agent.
1280 // Check the user agent.
1281 userAgentCustomActionPointer->setChecked(true);
1283 // Update the user agent menu action icon.
1284 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1286 // Update the user agent menu action text.
1287 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
1289 // Set the custom user agent text.
1290 userAgentCustomActionPointer->setText(userAgent);
1292 // Set the custom user agent flag.
1293 customUserAgent = true;
1296 // Update the custom user agent enabled boolean.
1297 // 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.
1298 if (updateCustomUserAgentStatus)
1299 customUserAgentEnabled = customUserAgent;
1302 // Format the custom user agent.
1303 if (customUserAgentEnabled)
1305 // Enable the custom user agent.
1306 userAgentCustomActionPointer->setEnabled(true);
1310 // Disable the custom user agent.
1311 userAgentCustomActionPointer->setEnabled(false);
1313 // Reset the custom user agent text.
1314 userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
1318 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
1320 // Set the current zoom factor.
1321 currentZoomFactor = zoomFactor;
1323 // Update the zoom factor action text, formatting the double with 2 decimal places.
1324 zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
1327 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
1329 // Update the search engine label.
1330 searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
1333 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1335 // Update the URL line edit if it does not have focus.
1336 if (!urlLineEditPointer->hasFocus())
1338 // Get the new URL string.
1339 QString newUrlString = newUrl.toString();
1341 // Update the URL line edit.
1342 urlLineEditPointer->setText(newUrlString);
1344 // Set the focus if the new URL is blank.
1345 if (newUrlString == QStringLiteral(""))
1346 urlLineEditPointer->setFocus();
1349 // Store the current URL.
1350 currentUrl = newUrl;
1353 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
1355 // Update the user agent label.
1356 userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
1359 void BrowserWindow::updateWindowTitle(const QString &title)
1361 // Update the window title.
1362 setWindowTitle(title);