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 userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
79 userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
80 userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
81 userAgentChromiumLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chromium_linux"));
82 userAgentFirefoxWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_windows"));
83 userAgentChromeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_chrome_windows"));
84 userAgentEdgeWindowsActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_edge_windows"));
85 userAgentSafariMacosActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_safari_macos"));
86 userAgentCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_custom"));
87 zoomFactorActionPointer = actionCollectionPointer->addAction(QLatin1String("zoom_factor"));
88 searchEngineMojeekActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_mojeek"));
89 searchEngineMonoclesActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_monocles"));
90 searchEngineMetagerActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_metager"));
91 searchEngineGoogleActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_google"));
92 searchEngineBingActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_bing"));
93 searchEngineYahooActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_yahoo"));
94 searchEngineCustomActionPointer = actionCollectionPointer->addAction(QLatin1String("search_engine_custom"));
95 QAction *domainSettingsActionPointer = actionCollectionPointer->addAction(QLatin1String("domain_settings"));
96 cookiesActionPointer = actionCollectionPointer->addAction(QLatin1String("cookies"));
97 javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
98 localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
99 domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
100 findCaseSensitiveActionPointer = actionCollectionPointer->addAction(QLatin1String("find_case_sensitive"));
101 hideFindTextActionPointer = actionCollectionPointer->addAction(QLatin1String("hide_find_actions"));
103 // Create the action groups
104 QActionGroup *userAgentActionGroupPointer = new QActionGroup(this);
105 QActionGroup *searchEngineActionGroupPointer = new QActionGroup(this);
107 // Add the actions to the groups.
108 userAgentActionGroupPointer->addAction(userAgentPrivacyBrowserActionPointer);
109 userAgentActionGroupPointer->addAction(userAgentWebEngineDefaultActionPointer);
110 userAgentActionGroupPointer->addAction(userAgentFirefoxLinuxActionPointer);
111 userAgentActionGroupPointer->addAction(userAgentChromiumLinuxActionPointer);
112 userAgentActionGroupPointer->addAction(userAgentFirefoxWindowsActionPointer);
113 userAgentActionGroupPointer->addAction(userAgentChromeWindowsActionPointer);
114 userAgentActionGroupPointer->addAction(userAgentEdgeWindowsActionPointer);
115 userAgentActionGroupPointer->addAction(userAgentSafariMacosActionPointer);
116 userAgentActionGroupPointer->addAction(userAgentCustomActionPointer);
117 searchEngineActionGroupPointer->addAction(searchEngineMojeekActionPointer);
118 searchEngineActionGroupPointer->addAction(searchEngineMonoclesActionPointer);
119 searchEngineActionGroupPointer->addAction(searchEngineMetagerActionPointer);
120 searchEngineActionGroupPointer->addAction(searchEngineGoogleActionPointer);
121 searchEngineActionGroupPointer->addAction(searchEngineBingActionPointer);
122 searchEngineActionGroupPointer->addAction(searchEngineYahooActionPointer);
123 searchEngineActionGroupPointer->addAction(searchEngineCustomActionPointer);
125 // Set some actions to be checkable.
126 javaScriptActionPointer->setCheckable(true);
127 localStorageActionPointer->setCheckable(true);
128 domStorageActionPointer->setCheckable(true);
129 findCaseSensitiveActionPointer->setCheckable(true);
130 userAgentPrivacyBrowserActionPointer->setCheckable(true);
131 userAgentWebEngineDefaultActionPointer->setCheckable(true);
132 userAgentFirefoxLinuxActionPointer->setCheckable(true);
133 userAgentChromiumLinuxActionPointer->setCheckable(true);
134 userAgentFirefoxWindowsActionPointer->setCheckable(true);
135 userAgentChromeWindowsActionPointer->setCheckable(true);
136 userAgentEdgeWindowsActionPointer->setCheckable(true);
137 userAgentSafariMacosActionPointer->setCheckable(true);
138 userAgentCustomActionPointer->setCheckable(true);
139 searchEngineMojeekActionPointer->setCheckable(true);
140 searchEngineMonoclesActionPointer->setCheckable(true);
141 searchEngineMetagerActionPointer->setCheckable(true);
142 searchEngineGoogleActionPointer->setCheckable(true);
143 searchEngineBingActionPointer->setCheckable(true);
144 searchEngineYahooActionPointer->setCheckable(true);
145 searchEngineCustomActionPointer->setCheckable(true);
147 // Instantiate the user agent helper.
148 UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
150 // Set the action text.
151 newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
152 newWindowActionPointer->setText(i18nc("New window action", "New Window"));
153 userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
154 userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
155 userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
156 userAgentChromiumLinuxActionPointer->setText(userAgentHelperPointer->CHROMIUM_LINUX_TRANSLATED);
157 userAgentFirefoxWindowsActionPointer->setText(userAgentHelperPointer->FIREFOX_WINDOWS_TRANSLATED);
158 userAgentChromeWindowsActionPointer->setText(userAgentHelperPointer->CHROME_WINDOWS_TRANSLATED);
159 userAgentEdgeWindowsActionPointer->setText(userAgentHelperPointer->EDGE_WINDOWS_TRANSLATED);
160 userAgentSafariMacosActionPointer->setText(userAgentHelperPointer->SAFARI_MACOS_TRANSLATED);
161 searchEngineMojeekActionPointer->setText(i18nc("Search engine", "Mojeek"));
162 searchEngineMonoclesActionPointer->setText(i18nc("Search engine", "Monocles"));
163 searchEngineMetagerActionPointer->setText(i18nc("Search engine", "MetaGer"));
164 searchEngineGoogleActionPointer->setText(i18nc("Search engine", "Google"));
165 searchEngineBingActionPointer->setText(i18nc("Search engine", "Bing"));
166 searchEngineYahooActionPointer->setText(i18nc("Search engine", "Yahoo"));
167 domainSettingsActionPointer->setText(i18nc("Domain Settings action", "Domain Settings"));
168 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", 0));
169 javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
170 localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
171 domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
172 findCaseSensitiveActionPointer->setText(i18nc("Find Case Sensitive action", "Find Case Sensitive"));
173 hideFindTextActionPointer->setText(i18nc("Hide Find Text action", "Hide Find Text"));
175 // Set the action icons. Gnome doesn't contain some of the icons that KDE has.
176 // The toolbar icons don't pick up unless the size is explicit, probably because the toolbar ends up being an intermediate size.
177 newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
178 newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
179 userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
180 userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"),
181 QIcon::fromTheme(QLatin1String("contact-new")))));
182 userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
183 QIcon::fromTheme(QLatin1String("contact-new")))));
184 userAgentChromiumLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"),
185 QIcon::fromTheme(QLatin1String("contact-new")))));
186 userAgentFirefoxWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"),
187 QIcon::fromTheme(QLatin1String("contact-new")))));
188 userAgentChromeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"),
189 QIcon::fromTheme(QLatin1String("contact-new")))));
190 userAgentEdgeWindowsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
191 userAgentSafariMacosActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
192 userAgentCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
193 searchEngineMojeekActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
194 searchEngineMonoclesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
195 searchEngineMetagerActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
196 searchEngineGoogleActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
197 searchEngineBingActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
198 searchEngineYahooActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
199 searchEngineCustomActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
200 zoomFactorActionPointer->setIcon(QIcon::fromTheme(QLatin1String("zoom-fit-best")));
201 domainSettingsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("settings-configure"), QIcon::fromTheme(QLatin1String("preferences-desktop"))));
202 cookiesActionPointer->setIcon(QIcon::fromTheme(QLatin1String("preferences-web-browser-cookies"), QIcon::fromTheme(QLatin1String("appointment-new"))));
203 domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
204 findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase"), QIcon::fromTheme(QLatin1String("/usr/share/icons/gnome/32x32/apps/fonts.png"))));
205 hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
207 // Create the key sequences.
208 QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
209 QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
210 QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
211 QKeySequence ctrlAltPKeySequence = QKeySequence(i18nc("The Privacy Browser user agent key sequence.", "Ctrl+Alt+P"));
212 QKeySequence ctrlAltWKeySequence = QKeySequence(i18nc("The WebEngine Default user agent key sequence.", "Ctrl+Alt+W"));
213 QKeySequence ctrlAltFKeySequence = QKeySequence(i18nc("The Firefox on Linux user agent key sequence.", "Ctrl+Alt+F"));
214 QKeySequence ctrlAltCKeySequence = QKeySequence(i18nc("The Chromium on Linux user agent key sequence.", "Ctrl+Alt+C"));
215 QKeySequence ctrlAltShiftFKeySequence = QKeySequence(i18nc("The Firefox on Windows user agent key sequence.", "Ctrl+Alt+Shift+F"));
216 QKeySequence ctrlAltShiftCKeySequence = QKeySequence(i18nc("The Chrome on Windows user agent key sequence.", "Ctrl+Alt+Shift+C"));
217 QKeySequence ctrlAltEKeySequence = QKeySequence(i18nc("The Edge on Windows user agent key sequence.", "Ctrl+Alt+E"));
218 QKeySequence ctrlAltSKeySequence = QKeySequence(i18nc("The Safari on macOS user agent key sequence.", "Ctrl+Alt+S"));
219 QKeySequence altShiftCKeySequence = QKeySequence(i18nc("The custom user agent key sequence.", "Alt+Shift+C"));
220 QKeySequence ctrlAltZKeySequence = QKeySequence(i18nc("The zoom factor key sequence.", "Ctrl+Alt+Z"));
221 QKeySequence ctrlShiftMKeySequence = QKeySequence(i18nc("The Mojeek search engine key sequence.", "Ctrl+Shift+M"));
222 QKeySequence ctrlShiftOKeySequence = QKeySequence(i18nc("The Monocles search engine key sequence.", "Ctrl+Shift+O"));
223 QKeySequence ctrlShiftEKeySequence = QKeySequence(i18nc("The MetaGer search engine key sequence.", "Ctrl+Shift+E"));
224 QKeySequence ctrlShiftGKeySequence = QKeySequence(i18nc("The Google search engine key sequence.", "Ctrl+Shift+G"));
225 QKeySequence ctrlShiftBKeySequence = QKeySequence(i18nc("The Bing search engine key sequence.", "Ctrl+Shift+B"));
226 QKeySequence ctrlShiftYKeySequence = QKeySequence(i18nc("The Yahoo search engine key sequence.", "Ctrl+Shift+Y"));
227 QKeySequence ctrlShiftCKeySequence = QKeySequence(i18nc("The custom search engine key sequence.", "Ctrl+Shift+C"));
228 QKeySequence ctrlDKeySequence = QKeySequence(i18nc("The domain settings key sequence.", "Ctrl+D"));
229 QKeySequence ctrlSemicolonKeySequence = QKeySequence(i18nc("The cookies dialog key sequence.", "Ctrl+;"));
231 // Set the action key sequences.
232 actionCollectionPointer->setDefaultShortcut(newTabActionPointer, ctrlTKeySequence);
233 actionCollectionPointer->setDefaultShortcut(newWindowActionPointer, ctrlNKeySequence);
234 actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
235 actionCollectionPointer->setDefaultShortcut(userAgentPrivacyBrowserActionPointer, ctrlAltPKeySequence);
236 actionCollectionPointer->setDefaultShortcut(userAgentWebEngineDefaultActionPointer, ctrlAltWKeySequence);
237 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxLinuxActionPointer, ctrlAltFKeySequence);
238 actionCollectionPointer->setDefaultShortcut(userAgentChromiumLinuxActionPointer, ctrlAltCKeySequence);
239 actionCollectionPointer->setDefaultShortcut(userAgentFirefoxWindowsActionPointer, ctrlAltShiftFKeySequence);
240 actionCollectionPointer->setDefaultShortcut(userAgentChromeWindowsActionPointer, ctrlAltShiftCKeySequence);
241 actionCollectionPointer->setDefaultShortcut(userAgentEdgeWindowsActionPointer, ctrlAltEKeySequence);
242 actionCollectionPointer->setDefaultShortcut(userAgentSafariMacosActionPointer, ctrlAltSKeySequence);
243 actionCollectionPointer->setDefaultShortcut(userAgentCustomActionPointer, altShiftCKeySequence);
244 actionCollectionPointer->setDefaultShortcut(zoomFactorActionPointer, ctrlAltZKeySequence);
245 actionCollectionPointer->setDefaultShortcut(searchEngineMojeekActionPointer, ctrlShiftMKeySequence);
246 actionCollectionPointer->setDefaultShortcut(searchEngineMonoclesActionPointer, ctrlShiftOKeySequence);
247 actionCollectionPointer->setDefaultShortcut(searchEngineMetagerActionPointer, ctrlShiftEKeySequence);
248 actionCollectionPointer->setDefaultShortcut(searchEngineGoogleActionPointer, ctrlShiftGKeySequence);
249 actionCollectionPointer->setDefaultShortcut(searchEngineBingActionPointer, ctrlShiftBKeySequence);
250 actionCollectionPointer->setDefaultShortcut(searchEngineYahooActionPointer, ctrlShiftYKeySequence);
251 actionCollectionPointer->setDefaultShortcut(searchEngineCustomActionPointer, ctrlShiftCKeySequence);
252 actionCollectionPointer->setDefaultShortcut(domainSettingsActionPointer, ctrlDKeySequence);
253 actionCollectionPointer->setDefaultShortcut(cookiesActionPointer, ctrlSemicolonKeySequence);
255 // Execute the actions.
256 connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
257 connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
258 connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
259 connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
260 connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
262 // Update the on-the-fly menus.
263 connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
264 connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
265 connect(tabWidgetPointer, SIGNAL(updateSearchEngineActions(QString, bool)), this, SLOT(updateSearchEngineActions(QString, bool)));
267 // Apply the on-the-fly settings when selected.
268 connect(userAgentActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlyUserAgent(QAction*)));
269 connect(searchEngineActionGroupPointer, SIGNAL(triggered(QAction*)), tabWidgetPointer, SLOT(applyOnTheFlySearchEngine(QAction*)));
271 // Process cookie changes.
272 connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
274 // Connect the URL toolbar actions.
275 connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
276 connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
277 connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
279 // Update the URL toolbar actions.
280 connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
281 connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
282 connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
283 connect(tabWidgetPointer, SIGNAL(updateLocalStorageAction(bool)), this, SLOT(updateLocalStorageAction(bool)));
284 connect(tabWidgetPointer, SIGNAL(updateDomStorageAction(bool)), this, SLOT(updateDomStorageAction(bool)));
286 // Connect the find text actions.
287 connect(findCaseSensitiveActionPointer, SIGNAL(triggered()), this, SLOT(toggleFindCaseSensitive()));
288 connect(hideFindTextActionPointer, SIGNAL(triggered()), this, SLOT(hideFindTextActions()));
290 // Setup the GUI based on the browserwindowui.rc file.
291 setupGUI(StandardWindowOption::Default, ("browserwindowui.rc"));
293 // Get lists of the actions' associated widgets.
294 QList<QWidget*> userAgentAssociatedWidgetsPointerList = userAgentPrivacyBrowserActionPointer->associatedWidgets();
295 QList<QWidget*> searchEngineAssociatedWidgetsPointerList = searchEngineMojeekActionPointer->associatedWidgets();
297 // Get the menu widget pointers. It is the second entry, after the main window.
298 QWidget *userAgentMenuWidgetPointer = userAgentAssociatedWidgetsPointerList[1];
299 QWidget *searchEngineMenuWidgetPointer = searchEngineAssociatedWidgetsPointerList[1];
301 // Get the menu pointers.
302 QMenu *userAgentMenuPointer = qobject_cast<QMenu*>(userAgentMenuWidgetPointer);
303 QMenu *searchEngineMenuPointer = qobject_cast<QMenu*>(searchEngineMenuWidgetPointer);
305 // Get the menu actions.
306 userAgentMenuActionPointer = userAgentMenuPointer->menuAction();
307 searchEngineMenuActionPointer = searchEngineMenuPointer->menuAction();
309 // Get handles for the toolbars.
310 navigationToolBarPointer = toolBar(QLatin1String("navigation_toolbar"));
311 urlToolBarPointer = toolBar(QLatin1String("url_toolbar"));
313 // Create the line edits.
314 urlLineEditPointer = new KLineEdit();
315 findTextLineEditPointer = new KLineEdit();
317 // Get the line edit size policies.
318 QSizePolicy urlLineEditSizePolicy = urlLineEditPointer->sizePolicy();
319 QSizePolicy findTextLineEditSizePolicy = findTextLineEditPointer->sizePolicy();
321 // Set the URL line edit horizontal stretch to be five times the find text line edit stretch.
322 urlLineEditSizePolicy.setHorizontalStretch(5);
323 findTextLineEditSizePolicy.setHorizontalStretch(1);
326 urlLineEditPointer->setSizePolicy(urlLineEditSizePolicy);
327 findTextLineEditPointer->setSizePolicy(findTextLineEditSizePolicy);
330 urlLineEditPointer->setMinimumWidth(350);
331 findTextLineEditPointer->setMinimumWidth(200);
332 findTextLineEditPointer->setMaximumWidth(350);
334 // Set the place holder text.
335 urlLineEditPointer->setPlaceholderText(i18nc("The URL line edit placeholder text", "URL or Search Terms"));
336 findTextLineEditPointer->setPlaceholderText(i18nc("The find line edit placeholder text", "Find Text"));
338 // Show the clear button on the find line edit.
339 findTextLineEditPointer->setClearButtonEnabled(true);
341 // Add an edit or add domain settings action to the URL line edit.
342 QAction *addOrEditDomainSettingsActionPointer = urlLineEditPointer->addAction(QIcon::fromTheme("settings-configure"), QLineEdit::TrailingPosition);
344 // Add or edit the current domain settings.
345 connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
347 // Create a find text label pointer.
348 findTextLabelPointer = new QLabel();
350 // Set the default label text.
351 findTextLabelPointer->setText(QLatin1String(" ") + i18nc("Default find results.", "0/0") + QLatin1String(" "));
353 // Insert the widgets into the toolbars.
354 urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
355 findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
356 findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
358 // Initially hide the find text actions.
359 hideFindTextActions();
361 // Load a new URL from the URL line edit.
362 connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
364 // Find text as it is typed.
365 connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
367 // Find next if the enter key is pressed.
368 connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
370 // Update find text when switching tabs.
371 connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
373 // Update the find text results.
374 connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
376 // Update the URL line edit on page loads.
377 connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
379 // Update the window title.
380 connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
382 // Get a handle for the status bar.
383 QStatusBar *statusBarPointer = statusBar();
385 // Create a progress bar.
386 progressBarPointer = new QProgressBar();
388 // Add the progress bar to to the status bar.
389 statusBarPointer->addPermanentWidget(progressBarPointer);
391 // Update the status bar with the URL when a link is hovered.
392 connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
394 // Update the progress bar.
395 connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
396 connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
398 // Update the URL line edit focus.
399 connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
401 // Get the URL line edit palettes.
402 normalBackgroundPalette = urlLineEditPointer->palette();
403 negativeBackgroundPalette = normalBackgroundPalette;
404 positiveBackgroundPalette = normalBackgroundPalette;
406 // Modify the palettes.
407 KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
408 KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
410 // Update the applied palette.
411 connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
413 // Process full screen requests.
414 connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
416 // Create keyboard shortcuts.
417 QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
418 QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
420 // Connect the keyboard shortcuts.
421 connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
422 connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
425 // 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.
426 updateJavaScriptAction(Settings::javaScriptEnabled());
427 updateLocalStorageAction(Settings::localStorageEnabled());
428 updateDomStorageAction(Settings::domStorageEnabled());
429 updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
430 updateZoomFactorAction(Settings::zoomFactor());
432 // Load the initial website if this is the first window.
434 tabWidgetPointer->loadInitialWebsite();
437 void BrowserWindow::addOrEditDomainSettings() const
439 // Remove the focus from the URL line edit.
440 urlLineEditPointer->clearFocus();
442 // Create the domain settings dialog pointer.
443 DomainSettingsDialog *domainSettingsDialogPointer;
445 // Get the current domain settings name.
446 QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
448 // Run the commands according to the current domain settings status.
449 if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
451 // Instruct the domain settings dialog to add a new domain.
452 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
454 else // Domain settings are currently applied.
456 // Instruct the domain settings dialog to edit the current domain.
457 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
460 // Set the dialog window title.
461 domainSettingsDialogPointer->setWindowTitle(i18nc("The domain settings dialog title", "Domain Settings"));
464 domainSettingsDialogPointer->setWindowModality(Qt::WindowModality::WindowModal);;
467 domainSettingsDialogPointer->show();
469 // Reload the tabs when domain settings are updated.
470 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
473 void BrowserWindow::back() const
475 // Remove the focus from the URL line edit.
476 urlLineEditPointer->clearFocus();
479 tabWidgetPointer->back();
482 void BrowserWindow::clearUrlLineEditFocus() const
484 // Remove the focus from the URL line edit.
485 urlLineEditPointer->clearFocus();
488 void BrowserWindow::escape() const
490 // Process the escape according to the status of the browser.
491 if (fullScreenActionPointer->isChecked()) // Full screen browsing is enabled.
493 // Exit full screen browsing.
494 fullScreenActionPointer->trigger();
496 else if (!findTextLineEditPointer->text().isEmpty()) // Find text is populated.
498 // Clear the find text line edit.
499 findTextLineEditPointer->clear();
501 // Clear the search in the WebEngine.
502 tabWidgetPointer->findText(QStringLiteral(""));
504 else if (findTextLineEditActionPointer->isVisible()) // Find text actions are visible.
506 // Hide the find text actions.
507 hideFindTextActions();
511 void BrowserWindow::findNext() const
513 // Get the find string.
514 const QString findString = findTextLineEditPointer->text();
516 // Search for the text if it is not empty.
517 if (!findString.isEmpty())
518 tabWidgetPointer->findText(findString);
521 void BrowserWindow::findPrevious() const
523 // Get the find string.
524 const QString findString = findTextLineEditPointer->text();
526 // Search for the text if it is not empty.
527 if (!findString.isEmpty())
528 tabWidgetPointer->findPrevious(findString);
531 void BrowserWindow::forward() const
533 // Remove the focus from the URL line edit.
534 urlLineEditPointer->clearFocus();
537 tabWidgetPointer->forward();
540 void BrowserWindow::fullScreenRequested(const bool toggleOn)
542 // Toggle full screen mode.
543 if (toggleOn) // Turn full screen mode on.
545 // Set the window to be full screen.
546 fullScreenActionPointer->setFullScreen(window(), true);
548 // Hide all the bars.
549 menuBar()->setVisible(false);
550 navigationToolBarPointer->setVisible(false);
551 urlToolBarPointer->setVisible(false);
552 tabWidgetPointer->setTabBarVisible(false);
553 statusBar()->setVisible(false);
555 else // Turn full screen mode off.
557 // Set the window to not be full screen.
558 fullScreenActionPointer->setFullScreen(window(), false);
560 // Show all the bars.
561 menuBar()->setVisible(true);
562 navigationToolBarPointer->setVisible(true);
563 urlToolBarPointer->setVisible(true);
564 tabWidgetPointer->setTabBarVisible(true);
565 statusBar()->setVisible(true);
569 void BrowserWindow::getZoomFactorFromUser()
571 // Create an OK flag.
574 // 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.
575 double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
576 i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
577 currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
579 // Update the zoom factor if the user clicked OK.
582 // Update the current zoom factor.
583 currentZoomFactor = newZoomFactor;
585 // Set the new zoom factor.
586 tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
588 // Update the on-the-fly action text.
589 updateZoomFactorAction(newZoomFactor);
593 void BrowserWindow::hideFindTextActions() const
595 // Hide the find text actions.
596 findTextLineEditActionPointer->setVisible(false);
597 findTextLabelActionPointer->setVisible(false);
598 findNextActionPointer->setVisible(false);
599 findPreviousActionPointer->setVisible(false);
600 findCaseSensitiveActionPointer->setVisible(false);
601 hideFindTextActionPointer->setVisible(false);
604 void BrowserWindow::home() const
606 // Remove the focus from the URL line edit.
607 urlLineEditPointer->clearFocus();
610 tabWidgetPointer->home();
613 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
615 // Remove the focus from the URL line edit.
616 urlLineEditPointer->clearFocus();
619 tabWidgetPointer->loadUrlFromLineEdit(url);
622 void BrowserWindow::newWindow() const
624 // Display a new instance of Privacy Browser.
625 (new BrowserWindow)->show();
628 void BrowserWindow::refresh() const
630 // Remove the focus from the URL line edit.
631 urlLineEditPointer->clearFocus();
633 // Refresh the web page.
634 tabWidgetPointer->refresh();
637 void BrowserWindow::showCookiesDialog()
639 // Remove the focus from the URL line edit.
640 urlLineEditPointer->clearFocus();
642 // Instantiate the cookie settings dialog.
643 CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
646 cookiesDialogPointer->show();
648 // Connect the dialog signals.
649 connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
650 connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
651 connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
654 void BrowserWindow::showDownloadLocationBrowseDialog() const
656 // Get the current download location.
657 QString currentDownloadLocation = downloadLocationComboBoxPointer->currentText();
659 // Resolve the system download directory if specified.
660 if (currentDownloadLocation == QStringLiteral("System Download Directory"))
661 currentDownloadLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
663 // Get the new download location.
664 QString newDownloadLocation = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download location dialog caption", "Select Download Location"), currentDownloadLocation);
666 // Populate the download location combo box according to the new download location.
667 if (newDownloadLocation == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) // The default download location was selected.
669 // Populate the download location with the default text.
670 downloadLocationComboBoxPointer->setCurrentText("System Download Directory");
672 else if (newDownloadLocation != QStringLiteral("")) // A different directory was selected.
674 // Populate the download location.
675 downloadLocationComboBoxPointer->setCurrentText(newDownloadLocation);
679 void BrowserWindow::showDomainSettingsDialog() const
681 // Remove the focus from the URL line edit.
682 urlLineEditPointer->clearFocus();
684 // Instantiate the domain settings dialog.
685 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
688 domainSettingsDialogPointer->show();
690 // Reload the tabs when domain settings are updated.
691 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
694 void BrowserWindow::showFindTextActions() const
696 // Show the find text actions.
697 findTextLineEditActionPointer->setVisible(true);
698 findTextLabelActionPointer->setVisible(true);
699 findNextActionPointer->setVisible(true);
700 findPreviousActionPointer->setVisible(true);
701 findCaseSensitiveActionPointer->setVisible(true);
702 hideFindTextActionPointer->setVisible(true);
704 // Set the focus on the find line edit.
705 findTextLineEditPointer->setFocus();
707 // Select all the text in the find line edit.
708 findTextLineEditPointer->selectAll();
711 void BrowserWindow::showProgressBar(const int &progress) const
713 // Set the progress bar value.
714 progressBarPointer->setValue(progress);
716 // Show the progress bar.
717 progressBarPointer->show();
720 void BrowserWindow::showSettingsDialog()
722 // Create the settings widgets.
723 QWidget *privacySettingsWidgetPointer = new QWidget;
724 QWidget *generalSettingsWidgetPointer = new QWidget;
725 QWidget *spellCheckSettingsWidgetPointer = new QWidget;
727 // Instantiate the settings UI.
728 Ui::PrivacySettings privacySettingsUi;
729 Ui::GeneralSettings generalSettingsUi;
730 Ui::SpellCheckSettings spellCheckSettingsUi;
732 // Setup the UI to display the settings widgets.
733 privacySettingsUi.setupUi(privacySettingsWidgetPointer);
734 generalSettingsUi.setupUi(generalSettingsWidgetPointer);
735 spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
737 // Get handles for the widgets.
738 QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
739 userAgentLabelPointer = privacySettingsUi.userAgentLabel;
740 QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
741 searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
742 downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
743 QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
744 QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
746 // Populate the combo box labels.
747 updateUserAgentLabel(userAgentComboBoxPointer->currentText());
748 updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
750 // Update the labels when the combo boxes change.
751 connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
752 connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
754 // Connect the download location directory browse button.
755 connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
757 // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
758 QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
760 // Get a dictionaries string list.
761 QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
763 // Remove the `.bdic` file extensions from the dictionaries list.
764 dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
766 // Get a list of the enabled spell check languages.
767 QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
769 // Add each dictionary to the spell check list widget.
770 foreach(QString dictionaryString, dictionariesStringList)
772 // Create a new list widget item pointer.
773 QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
775 // Create a dictionary check box widget with the name of the dictionary string.
776 QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
778 // Check the language if it is currently enabled.
779 if (enabledSpellCheckLanguagesList.contains(dictionaryString))
780 dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
782 dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
784 // Add the list widget item to the spell check list widget.
785 spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
787 // Set the list widget item check box widget.
788 spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
791 // Get a handle for the KConfig skeleton.
792 KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
794 // Instantiate a settings config dialog from the settings.kcfg file.
795 configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
797 // Create a settings icon string.
798 QString settingsIconString;
800 // Get a settings icon that matches the theme.
801 if (QIcon::hasThemeIcon("breeze-settings"))
803 // KDE uses breeze-settings.
804 settingsIconString = QLatin1String("breeze-settings");
808 // Gnome uses preferences-desktop.
809 settingsIconString = QLatin1String("preferences-desktop");
812 // Add the settings widgets as config dialog pages.
813 configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
814 configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
815 configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
817 // Get handles for the buttons.
818 QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
819 QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
821 // Prevent interaction with the parent window while the dialog is open.
822 configDialogPointer->setWindowModality(Qt::WindowModal);
825 configDialogPointer->show();
827 // TODO. KConfigDialog does not respect expanding size policies. <https://redmine.stoutner.com/issues/823>
828 //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
829 //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
830 //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
831 //configDialogPointer->adjustSize();
833 // Expand the config dialog.
834 configDialogPointer->resize(1000, 500);
836 // Create a save spell check languages lambda.
837 auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
839 // Create a list of enabled languages.
840 QStringList newSpellCheckLanguages = QStringList();
842 // Get a count of all the languages.
843 int allLanguagesCount = spellCheckListWidgetPointer->count();
845 // Get a list of all the checked languages.
846 for (int i = 0; i < allLanguagesCount; ++i) {
847 // Get the language item.
848 QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
850 // Get the language check box.
851 QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
853 // Add the item to the enabled languages if it is checked.
854 if (languageCheckBoxPointer->checkState() == Qt::Checked)
857 QString languageString = languageCheckBoxPointer->text();
859 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
860 languageString.remove(QChar('&'));
862 // Add the language string to the list.
863 newSpellCheckLanguages.append(languageString);
867 // Update the spell check languages.
868 if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
870 // Update the spell check languages.
871 Settings::setSpellCheckLanguages(newSpellCheckLanguages);
873 // Write the settings to disk.
874 kConfigSkeletonPointer->save();
877 // Apply the spell check languages.
878 tabWidgetPointer->applySpellCheckLanguages();
882 connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
883 connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
885 // Apply the settings handled by KConfig.
886 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
887 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
890 QSize BrowserWindow::sizeHint() const
892 // Return the default window size.
893 return QSize(1500, 1200);
896 void BrowserWindow::toggleDomStorage() const
898 // Remove the focus from the URL line edit.
899 urlLineEditPointer->clearFocus();
901 // Toggle DOM storage.
902 tabWidgetPointer->toggleDomStorage();
905 void BrowserWindow::toggleFindCaseSensitive() const
907 // Get the current find string.
908 const QString findString = findTextLineEditPointer->text();
910 // Toggle find case sensitive.
911 tabWidgetPointer->toggleFindCaseSensitive(findString);
914 void BrowserWindow::toggleJavaScript() const
916 // Remove the focus from the URL line edit.
917 urlLineEditPointer->clearFocus();
919 // Toggle JavaScript.
920 tabWidgetPointer->toggleJavaScript();
923 void BrowserWindow::toggleLocalStorage() const
925 // Remove the focus from the URL line edit.
926 urlLineEditPointer->clearFocus();
928 // Toggle local storage.
929 tabWidgetPointer->toggleLocalStorage();
932 void BrowserWindow::toggleFullScreen()
934 // Toggle the full screen status.
935 if (fullScreenActionPointer->isChecked()) // Enable full screen browsing mode.
937 // Enable full screen mode.
938 fullScreenActionPointer->setFullScreen(window(), true);
940 // Hide the menu bar if specified.
941 if (Settings::fullScreenHideMenuBar())
942 menuBar()->setVisible(false);
944 // Hide the toolbars if specified.
945 if (Settings::fullScreenHideToolBars())
947 navigationToolBarPointer->setVisible(false);
948 urlToolBarPointer->setVisible(false);
951 // Hide the tab bar if specified.
952 if (Settings::fullScreenHideTabBar())
953 tabWidgetPointer->setTabBarVisible(false);
955 // Hide the status bar if specified.
956 if (Settings::fullScreenHideStatusBar())
957 statusBar()->setVisible(false);
959 else // Disable full screen browsing mode.
961 // Disable full screen mode.
962 fullScreenActionPointer->setFullScreen(window(), false);
964 // Show the menu bar.
965 menuBar()->setVisible(true);
967 // Show the toolbars.
968 navigationToolBarPointer->setVisible(true);
969 urlToolBarPointer->setVisible(true);
972 tabWidgetPointer->setTabBarVisible(true);
974 // Show the status bar.
975 statusBar()->setVisible(true);
979 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
981 // Update the action text.
982 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
985 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
987 // Set the action checked status.
988 domStorageActionPointer->setChecked(isEnabled);
991 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
993 // Set the domain palette according to the status.
995 urlLineEditPointer->setPalette(positiveBackgroundPalette);
997 urlLineEditPointer->setPalette(normalBackgroundPalette);
1000 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1003 findTextLineEditPointer->setText(text);
1005 // Set the find case sensitive action checked status.
1006 findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1009 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1011 // Update the find text label.
1012 findTextLabelPointer->setText(QStringLiteral(" %1/%2 ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1014 // Set the background color according to the find status.
1015 if (findTextLineEditPointer->text().isEmpty())
1016 findTextLineEditPointer->setPalette(normalBackgroundPalette);
1017 else if (findTextResult.numberOfMatches() == 0)
1018 findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1020 findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1023 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1025 // Update the JavaScript status.
1026 javaScriptEnabled = isEnabled;
1028 // Set the icon according to the status.
1029 if (javaScriptEnabled)
1030 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1032 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1034 // Set the action checked status.
1035 javaScriptActionPointer->setChecked(javaScriptEnabled);
1037 // Update the status of the DOM storage action.
1038 domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1041 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1043 // Update the local storage status.
1044 localStorageEnabled = isEnabled;
1046 // 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.
1047 if (localStorageEnabled)
1048 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/filesaveas.png"))));
1050 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1052 // Set the action checked status.
1053 localStorageActionPointer->setChecked(localStorageEnabled);
1055 // Update the status of the DOM storage action.
1056 domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1059 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1061 // Initialize the custom search engine flag.
1062 bool customSearchEngine = false;
1064 if (searchEngine == "Mojeek") // Mojeek.
1066 // Check the Mojeek user agent action.
1067 searchEngineMojeekActionPointer->setChecked(true);
1069 // Update the search engine menu action icon.
1070 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1072 // Update the search engine menu action text.
1073 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1075 else if (searchEngine == "Monocles") // Monocles.
1077 // Check the Monocles user agent action.
1078 searchEngineMonoclesActionPointer->setChecked(true);
1080 // Update the search engine menu action icon.
1081 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1083 // Update the search engine menu action text.
1084 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1086 else if (searchEngine == "MetaGer") // MetaGer.
1088 // Check the MetaGer user agent action.
1089 searchEngineMetagerActionPointer->setChecked(true);
1091 // Update the search engine menu action icon.
1092 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1094 // Update the search engine menu action text.
1095 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1097 else if (searchEngine == "Google") // Google.
1099 // Check the Google user agent action.
1100 searchEngineGoogleActionPointer->setChecked(true);
1102 // Update the search engine menu action icon.
1103 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
1105 // Update the search engine menu action text.
1106 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
1108 else if (searchEngine == "Bing") // Bing.
1110 // Check the Bing user agent action.
1111 searchEngineBingActionPointer->setChecked(true);
1113 // Update the search engine menu action icon.
1114 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1116 // Update the search engine menu action text.
1117 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
1119 else if (searchEngine == "Yahoo") // Yahoo.
1121 // Check the Yahoo user agent action.
1122 searchEngineYahooActionPointer->setChecked(true);
1124 // Update the search engine menu action icon.
1125 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
1127 // Update the search engine menu action text.
1128 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
1130 else // Custom search engine.
1132 // Check the user agent.
1133 searchEngineCustomActionPointer->setChecked(true);
1135 // Update the search engine menu action icon.
1136 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1138 // Update the search engine menu action text.
1139 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
1141 // Set the custom search engine text.
1142 searchEngineCustomActionPointer->setText(searchEngine);
1144 // Set the custom search engine flag.
1145 customSearchEngine = true;
1148 // Update the custom search engine enabled boolean.
1149 if (updateCustomSearchEngineStatus)
1150 customSearchEngineEnabled = customSearchEngine;
1152 // Format the custom search engine.
1153 if (customSearchEngineEnabled)
1155 // Enable the custom search engine.
1156 searchEngineCustomActionPointer->setEnabled(true);
1160 // Disable the custom search engine.
1161 searchEngineCustomActionPointer->setEnabled(false);
1163 // Reset the custom search engine text.
1164 searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
1168 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
1170 // Initialize the custom user agent flag.
1171 bool customUserAgent = false;
1173 // Check the indicated on-the-fly user agent.
1174 if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT) // Privacy Browser.
1176 // Check the Privacy Browser user agent action.
1177 userAgentPrivacyBrowserActionPointer->setChecked(true);
1179 // Update the user agent menu action icon.
1180 userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
1182 // Update the user agent menu action text.
1183 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
1185 else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
1187 // check the WebEngine default user agent action.
1188 userAgentWebEngineDefaultActionPointer->setChecked(true);
1190 // Update the user agent menu action icon.
1191 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1193 // Update the user agent menu action text.
1194 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
1196 else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT) // Firefox on Linux.
1198 // Check the Firefox on Linux user agent action.
1199 userAgentFirefoxLinuxActionPointer->setChecked(true);
1201 // Update the user agent menu action icon.
1202 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1204 // Update the user agent menu action text.
1205 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
1207 else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT) // Chromium on Linux.
1209 // Check the Chromium on Linux user agent action.
1210 userAgentChromiumLinuxActionPointer->setChecked(true);
1212 // Update the user agent menu action icon.
1213 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1215 // Update the user agent menu action text.
1216 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
1218 else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT) // Firefox on Windows.
1220 // Check the Firefox on Windows user agent action.
1221 userAgentFirefoxWindowsActionPointer->setChecked(true);
1223 // Update the user agent menu action icon.
1224 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1226 // Update the user agent menu action text.
1227 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
1229 else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT) // Chrome on Windows.
1231 // Check the Chrome on Windows user agent action.
1232 userAgentChromeWindowsActionPointer->setChecked(true);
1234 // Update the user agent menu action icon.
1235 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1237 // Update the user agent menu action text.
1238 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
1240 else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT) // Edge on Windows.
1242 // Check the Edge on Windows user agent action.
1243 userAgentEdgeWindowsActionPointer->setChecked(true);
1245 // Update the user agent menu action icon.
1246 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1248 // Update the user agent menu action text.
1249 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
1251 else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT) // Safari on macOS.
1253 // Check the Safari on macOS user agent action.
1254 userAgentSafariMacosActionPointer->setChecked(true);
1256 // Update the user agent menu action icon.
1257 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1259 // Update the user agent menu action text.
1260 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
1262 else // Custom user agent.
1264 // Check the user agent.
1265 userAgentCustomActionPointer->setChecked(true);
1267 // Update the user agent menu action icon.
1268 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1270 // Update the user agent menu action text.
1271 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
1273 // Set the custom user agent text.
1274 userAgentCustomActionPointer->setText(userAgent);
1276 // Set the custom user agent flag.
1277 customUserAgent = true;
1280 // Update the custom user agent enabled boolean.
1281 // 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.
1282 if (updateCustomUserAgentStatus)
1283 customUserAgentEnabled = customUserAgent;
1286 // Format the custom user agent.
1287 if (customUserAgentEnabled)
1289 // Enable the custom user agent.
1290 userAgentCustomActionPointer->setEnabled(true);
1294 // Disable the custom user agent.
1295 userAgentCustomActionPointer->setEnabled(false);
1297 // Reset the custom user agent text.
1298 userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
1302 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
1304 // Set the current zoom factor.
1305 currentZoomFactor = zoomFactor;
1307 // Update the zoom factor action text, formatting the double with 2 decimal places.
1308 zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
1311 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
1313 // Update the search engine label.
1314 searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
1317 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1319 // Update the URL line edit if it does not have focus.
1320 if (!urlLineEditPointer->hasFocus())
1322 // Get the new URL string.
1323 QString newUrlString = newUrl.toString();
1325 // Update the URL line edit.
1326 urlLineEditPointer->setText(newUrlString);
1328 // Set the focus if the new URL is blank.
1329 if (newUrlString == QStringLiteral(""))
1330 urlLineEditPointer->setFocus();
1333 // Store the current URL.
1334 currentUrl = newUrl;
1337 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
1339 // Update the user agent label.
1340 userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
1343 void BrowserWindow::updateWindowTitle(const QString &title)
1345 // Update the window title.
1346 setWindowTitle(title);