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", QIcon::fromTheme(QLatin1String("preferences-desktop"))),
343 QLineEdit::TrailingPosition);
345 // Add or edit the current domain settings.
346 connect(addOrEditDomainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(addOrEditDomainSettings()));
348 // Create a find text label pointer.
349 findTextLabelPointer = new QLabel();
351 // Set the default label text.
352 findTextLabelPointer->setText(QLatin1String(" ") + i18nc("Default find results.", "0/0") + QLatin1String(" "));
354 // Insert the widgets into the toolbars.
355 urlToolBarPointer->insertWidget(javaScriptActionPointer, urlLineEditPointer);
356 findTextLineEditActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLineEditPointer);
357 findTextLabelActionPointer = urlToolBarPointer->insertWidget(findNextActionPointer, findTextLabelPointer);
359 // Initially hide the find text actions.
360 hideFindTextActions();
362 // Load a new URL from the URL line edit.
363 connect(urlLineEditPointer, SIGNAL(returnKeyPressed(const QString)), this, SLOT(loadUrlFromLineEdit(const QString)));
365 // Find text as it is typed.
366 connect(findTextLineEditPointer, SIGNAL(textEdited(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
368 // Find next if the enter key is pressed.
369 connect(findTextLineEditPointer, SIGNAL(returnKeyPressed(const QString &)), tabWidgetPointer, SLOT(findText(const QString &)));
371 // Update find text when switching tabs.
372 connect(tabWidgetPointer, SIGNAL(updateFindText(const QString &, const bool)), this, SLOT(updateFindText(const QString &, const bool)));
374 // Update the find text results.
375 connect(tabWidgetPointer, SIGNAL(updateFindTextResults(const QWebEngineFindTextResult &)), this, SLOT(updateFindTextResults(const QWebEngineFindTextResult &)));
377 // Update the URL line edit on page loads.
378 connect(tabWidgetPointer, SIGNAL(updateUrlLineEdit(QUrl)), this, SLOT(updateUrlLineEdit(QUrl)));
380 // Update the window title.
381 connect(tabWidgetPointer, SIGNAL(updateWindowTitle(const QString)), this, SLOT(updateWindowTitle(const QString)));
383 // Get a handle for the status bar.
384 QStatusBar *statusBarPointer = statusBar();
386 // Create a progress bar.
387 progressBarPointer = new QProgressBar();
389 // Add the progress bar to to the status bar.
390 statusBarPointer->addPermanentWidget(progressBarPointer);
392 // Update the status bar with the URL when a link is hovered.
393 connect(tabWidgetPointer, SIGNAL(linkHovered(QString)), statusBarPointer, SLOT(showMessage(QString)));
395 // Update the progress bar.
396 connect(tabWidgetPointer, SIGNAL(showProgressBar(const int)), this, SLOT(showProgressBar(const int)));
397 connect(tabWidgetPointer, SIGNAL(hideProgressBar()), progressBarPointer, SLOT(hide()));
399 // Update the URL line edit focus.
400 connect(tabWidgetPointer, SIGNAL(clearUrlLineEditFocus()), this, SLOT(clearUrlLineEditFocus()));
402 // Get the URL line edit palettes.
403 normalBackgroundPalette = urlLineEditPointer->palette();
404 negativeBackgroundPalette = normalBackgroundPalette;
405 positiveBackgroundPalette = normalBackgroundPalette;
407 // Modify the palettes.
408 KColorScheme::adjustBackground(negativeBackgroundPalette, KColorScheme::NegativeBackground);
409 KColorScheme::adjustBackground(positiveBackgroundPalette, KColorScheme::PositiveBackground);
411 // Update the applied palette.
412 connect(tabWidgetPointer, SIGNAL(updateDomainSettingsIndicator(const bool)), this, SLOT(updateDomainSettingsIndicator(const bool)));
414 // Process full screen requests.
415 connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
417 // Create keyboard shortcuts.
418 QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
419 QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
421 // Connect the keyboard shortcuts.
422 connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
423 connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
426 // 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.
427 updateJavaScriptAction(Settings::javaScriptEnabled());
428 updateLocalStorageAction(Settings::localStorageEnabled());
429 updateDomStorageAction(Settings::domStorageEnabled());
430 updateUserAgentActions(UserAgentHelper::getUserAgentFromDatabaseName(Settings::userAgent()), true);
431 updateZoomFactorAction(Settings::zoomFactor());
433 // Load the initial website if this is the first window.
435 tabWidgetPointer->loadInitialWebsite();
438 void BrowserWindow::addOrEditDomainSettings() const
440 // Remove the focus from the URL line edit.
441 urlLineEditPointer->clearFocus();
443 // Create the domain settings dialog pointer.
444 DomainSettingsDialog *domainSettingsDialogPointer;
446 // Get the current domain settings name.
447 QString ¤tDomainSettingsName = tabWidgetPointer->getDomainSettingsName();
449 // Run the commands according to the current domain settings status.
450 if (currentDomainSettingsName == QStringLiteral("")) // Domain settings are not currently applied.
452 // Instruct the domain settings dialog to add a new domain.
453 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::ADD_DOMAIN, currentUrl.host());
455 else // Domain settings are currently applied.
457 // Instruct the domain settings dialog to edit the current domain.
458 domainSettingsDialogPointer = new DomainSettingsDialog(DomainSettingsDialog::EDIT_DOMAIN, currentDomainSettingsName);
461 // Set the dialog window title.
462 domainSettingsDialogPointer->setWindowTitle(i18nc("The domain settings dialog title", "Domain Settings"));
465 domainSettingsDialogPointer->setWindowModality(Qt::WindowModality::WindowModal);;
468 domainSettingsDialogPointer->show();
470 // Reload the tabs when domain settings are updated.
471 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
474 void BrowserWindow::back() const
476 // Remove the focus from the URL line edit.
477 urlLineEditPointer->clearFocus();
480 tabWidgetPointer->back();
483 void BrowserWindow::clearUrlLineEditFocus() const
485 // Remove the focus from the URL line edit.
486 urlLineEditPointer->clearFocus();
489 void BrowserWindow::escape() const
491 // Process the escape according to the status of the browser.
492 if (fullScreenActionPointer->isChecked()) // Full screen browsing is enabled.
494 // Exit full screen browsing.
495 fullScreenActionPointer->trigger();
497 else if (!findTextLineEditPointer->text().isEmpty()) // Find text is populated.
499 // Clear the find text line edit.
500 findTextLineEditPointer->clear();
502 // Clear the search in the WebEngine.
503 tabWidgetPointer->findText(QStringLiteral(""));
505 else if (findTextLineEditActionPointer->isVisible()) // Find text actions are visible.
507 // Hide the find text actions.
508 hideFindTextActions();
512 void BrowserWindow::findNext() const
514 // Get the find string.
515 const QString findString = findTextLineEditPointer->text();
517 // Search for the text if it is not empty.
518 if (!findString.isEmpty())
519 tabWidgetPointer->findText(findString);
522 void BrowserWindow::findPrevious() const
524 // Get the find string.
525 const QString findString = findTextLineEditPointer->text();
527 // Search for the text if it is not empty.
528 if (!findString.isEmpty())
529 tabWidgetPointer->findPrevious(findString);
532 void BrowserWindow::forward() const
534 // Remove the focus from the URL line edit.
535 urlLineEditPointer->clearFocus();
538 tabWidgetPointer->forward();
541 void BrowserWindow::fullScreenRequested(const bool toggleOn)
543 // Toggle full screen mode.
544 if (toggleOn) // Turn full screen mode on.
546 // Set the window to be full screen.
547 fullScreenActionPointer->setFullScreen(window(), true);
549 // Hide all the bars.
550 menuBar()->setVisible(false);
551 navigationToolBarPointer->setVisible(false);
552 urlToolBarPointer->setVisible(false);
553 tabWidgetPointer->setTabBarVisible(false);
554 statusBar()->setVisible(false);
556 else // Turn full screen mode off.
558 // Set the window to not be full screen.
559 fullScreenActionPointer->setFullScreen(window(), false);
561 // Show all the bars.
562 menuBar()->setVisible(true);
563 navigationToolBarPointer->setVisible(true);
564 urlToolBarPointer->setVisible(true);
565 tabWidgetPointer->setTabBarVisible(true);
566 statusBar()->setVisible(true);
570 void BrowserWindow::getZoomFactorFromUser()
572 // Create an OK flag.
575 // 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.
576 double newZoomFactor = QInputDialog::getDouble(this, i18nc("The on-the-fly zoom factor dialog title", "On-The-Fly Zoom Factor"),
577 i18nc("The instruction text of the on-the-fly zoom factor dialog", "Enter a zoom factor between 0.25 and 5.00"),
578 currentZoomFactor, .025, 5.00, 2, &okClicked, Qt::WindowFlags(), 0.25);
580 // Update the zoom factor if the user clicked OK.
583 // Update the current zoom factor.
584 currentZoomFactor = newZoomFactor;
586 // Set the new zoom factor.
587 tabWidgetPointer->applyOnTheFlyZoomFactor(newZoomFactor);
589 // Update the on-the-fly action text.
590 updateZoomFactorAction(newZoomFactor);
594 void BrowserWindow::hideFindTextActions() const
596 // Hide the find text actions.
597 findTextLineEditActionPointer->setVisible(false);
598 findTextLabelActionPointer->setVisible(false);
599 findNextActionPointer->setVisible(false);
600 findPreviousActionPointer->setVisible(false);
601 findCaseSensitiveActionPointer->setVisible(false);
602 hideFindTextActionPointer->setVisible(false);
605 void BrowserWindow::home() const
607 // Remove the focus from the URL line edit.
608 urlLineEditPointer->clearFocus();
611 tabWidgetPointer->home();
614 void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
616 // Remove the focus from the URL line edit.
617 urlLineEditPointer->clearFocus();
620 tabWidgetPointer->loadUrlFromLineEdit(url);
623 void BrowserWindow::newWindow() const
625 // Display a new instance of Privacy Browser.
626 (new BrowserWindow)->show();
629 void BrowserWindow::refresh() const
631 // Remove the focus from the URL line edit.
632 urlLineEditPointer->clearFocus();
634 // Refresh the web page.
635 tabWidgetPointer->refresh();
638 void BrowserWindow::showCookiesDialog()
640 // Remove the focus from the URL line edit.
641 urlLineEditPointer->clearFocus();
643 // Instantiate the cookie settings dialog.
644 CookiesDialog *cookiesDialogPointer = new CookiesDialog(tabWidgetPointer->getCookieList());
647 cookiesDialogPointer->show();
649 // Connect the dialog signals.
650 connect(cookiesDialogPointer, SIGNAL(addCookie(QNetworkCookie)), tabWidgetPointer, SLOT(addCookieToStore(QNetworkCookie)));
651 connect(cookiesDialogPointer, SIGNAL(deleteAllCookies()), tabWidgetPointer, SLOT(deleteAllCookies()));
652 connect(cookiesDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), tabWidgetPointer, SLOT(deleteCookieFromStore(QNetworkCookie)));
655 void BrowserWindow::showDownloadLocationBrowseDialog() const
657 // Get the current download location.
658 QString currentDownloadLocation = downloadLocationComboBoxPointer->currentText();
660 // Resolve the system download directory if specified.
661 if (currentDownloadLocation == QStringLiteral("System Download Directory"))
662 currentDownloadLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
664 // Get the new download location.
665 QString newDownloadLocation = QFileDialog::getExistingDirectory(configDialogPointer, i18nc("Select download location dialog caption", "Select Download Location"), currentDownloadLocation);
667 // Populate the download location combo box according to the new download location.
668 if (newDownloadLocation == QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)) // The default download location was selected.
670 // Populate the download location with the default text.
671 downloadLocationComboBoxPointer->setCurrentText("System Download Directory");
673 else if (newDownloadLocation != QStringLiteral("")) // A different directory was selected.
675 // Populate the download location.
676 downloadLocationComboBoxPointer->setCurrentText(newDownloadLocation);
680 void BrowserWindow::showDomainSettingsDialog() const
682 // Remove the focus from the URL line edit.
683 urlLineEditPointer->clearFocus();
685 // Instantiate the domain settings dialog.
686 DomainSettingsDialog *domainSettingsDialogPointer = new DomainSettingsDialog();
689 domainSettingsDialogPointer->show();
691 // Reload the tabs when domain settings are updated.
692 connect(domainSettingsDialogPointer, SIGNAL(domainSettingsUpdated()), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
695 void BrowserWindow::showFindTextActions() const
697 // Show the find text actions.
698 findTextLineEditActionPointer->setVisible(true);
699 findTextLabelActionPointer->setVisible(true);
700 findNextActionPointer->setVisible(true);
701 findPreviousActionPointer->setVisible(true);
702 findCaseSensitiveActionPointer->setVisible(true);
703 hideFindTextActionPointer->setVisible(true);
705 // Set the focus on the find line edit.
706 findTextLineEditPointer->setFocus();
708 // Select all the text in the find line edit.
709 findTextLineEditPointer->selectAll();
712 void BrowserWindow::showProgressBar(const int &progress) const
714 // Set the progress bar value.
715 progressBarPointer->setValue(progress);
717 // Show the progress bar.
718 progressBarPointer->show();
721 void BrowserWindow::showSettingsDialog()
723 // Create the settings widgets.
724 QWidget *privacySettingsWidgetPointer = new QWidget;
725 QWidget *generalSettingsWidgetPointer = new QWidget;
726 QWidget *spellCheckSettingsWidgetPointer = new QWidget;
728 // Instantiate the settings UI.
729 Ui::PrivacySettings privacySettingsUi;
730 Ui::GeneralSettings generalSettingsUi;
731 Ui::SpellCheckSettings spellCheckSettingsUi;
733 // Setup the UI to display the settings widgets.
734 privacySettingsUi.setupUi(privacySettingsWidgetPointer);
735 generalSettingsUi.setupUi(generalSettingsWidgetPointer);
736 spellCheckSettingsUi.setupUi(spellCheckSettingsWidgetPointer);
738 // Get handles for the widgets.
739 QComboBox *userAgentComboBoxPointer = privacySettingsUi.kcfg_userAgent;
740 userAgentLabelPointer = privacySettingsUi.userAgentLabel;
741 QComboBox *searchEngineComboBoxPointer = generalSettingsUi.kcfg_searchEngine;
742 searchEngineLabelPointer = generalSettingsUi.searchEngineLabel;
743 downloadLocationComboBoxPointer = generalSettingsUi.kcfg_downloadLocation;
744 QPushButton *browseButtonPointer = generalSettingsUi.browseButton;
745 QListWidget *spellCheckListWidgetPointer = spellCheckSettingsUi.spellCheckListWidget;
747 // Populate the combo box labels.
748 updateUserAgentLabel(userAgentComboBoxPointer->currentText());
749 updateSearchEngineLabel(searchEngineComboBoxPointer->currentText());
751 // Update the labels when the combo boxes change.
752 connect(userAgentComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateUserAgentLabel(const QString)));
753 connect(searchEngineComboBoxPointer, SIGNAL(currentTextChanged(const QString)), this, SLOT(updateSearchEngineLabel(const QString)));
755 // Connect the download location directory browse button.
756 connect(browseButtonPointer, SIGNAL(clicked()), this, SLOT(showDownloadLocationBrowseDialog()));
758 // Create a dictionaries QDir from the `QTWEBENGINE_DICTIONARIES_PATH` environment variable.
759 QDir dictionariesDir = QDir(qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"));
761 // Get a dictionaries string list.
762 QStringList dictionariesStringList = dictionariesDir.entryList(QStringList(QLatin1String("*.bdic")), QDir::Files | QDir::NoSymLinks);
764 // Remove the `.bdic` file extensions from the dictionaries list.
765 dictionariesStringList.replaceInStrings(QLatin1String(".bdic"), QLatin1String(""));
767 // Get a list of the enabled spell check languages.
768 QStringList enabledSpellCheckLanguagesList = Settings::spellCheckLanguages();
770 // Add each dictionary to the spell check list widget.
771 foreach(QString dictionaryString, dictionariesStringList)
773 // Create a new list widget item pointer.
774 QListWidgetItem *listWidgetItemPointer = new QListWidgetItem();
776 // Create a dictionary check box widget with the name of the dictionary string.
777 QCheckBox *dictionaryCheckBoxWidget = new QCheckBox(dictionaryString);
779 // Check the language if it is currently enabled.
780 if (enabledSpellCheckLanguagesList.contains(dictionaryString))
781 dictionaryCheckBoxWidget->setCheckState(Qt::Checked);
783 dictionaryCheckBoxWidget->setCheckState(Qt::Unchecked);
785 // Add the list widget item to the spell check list widget.
786 spellCheckListWidgetPointer->addItem(listWidgetItemPointer);
788 // Set the list widget item check box widget.
789 spellCheckListWidgetPointer->setItemWidget(listWidgetItemPointer, dictionaryCheckBoxWidget);
792 // Get a handle for the KConfig skeleton.
793 KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
795 // Instantiate a settings config dialog from the settings.kcfg file.
796 configDialogPointer = new KConfigDialog(this, QLatin1String("settings"), kConfigSkeletonPointer);
798 // Create a settings icon string.
799 QString settingsIconString;
801 // Get a settings icon that matches the theme.
802 if (QIcon::hasThemeIcon("breeze-settings"))
804 // KDE uses breeze-settings.
805 settingsIconString = QLatin1String("breeze-settings");
809 // Gnome uses preferences-desktop.
810 settingsIconString = QLatin1String("preferences-desktop");
813 // Add the settings widgets as config dialog pages.
814 configDialogPointer->addPage(privacySettingsWidgetPointer, i18nc("Settings tab title", "Privacy"), QLatin1String("privacybrowser"));
815 configDialogPointer->addPage(generalSettingsWidgetPointer, i18nc("Settings tab title", "General"), settingsIconString);
816 configDialogPointer->addPage(spellCheckSettingsWidgetPointer, i18nc("Settings tab title", "Spell Check"), QLatin1String("tools-check-spelling"));
818 // Get handles for the buttons.
819 QPushButton *applyButtonPointer = configDialogPointer->button(QDialogButtonBox::Apply);
820 QPushButton *okButtonPointer = configDialogPointer->button(QDialogButtonBox::Ok);
822 // Prevent interaction with the parent window while the dialog is open.
823 configDialogPointer->setWindowModality(Qt::WindowModal);
826 configDialogPointer->show();
828 // TODO. KConfigDialog does not respect expanding size policies. <https://redmine.stoutner.com/issues/823>
829 //configDialogPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
830 //privacySettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
831 //generalSettingsWidgetPointer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
832 //configDialogPointer->adjustSize();
834 // Expand the config dialog.
835 configDialogPointer->resize(1000, 500);
837 // Create a save spell check languages lambda.
838 auto saveSpellCheckLanguages = [spellCheckListWidgetPointer, kConfigSkeletonPointer, this] ()
840 // Create a list of enabled languages.
841 QStringList newSpellCheckLanguages = QStringList();
843 // Get a count of all the languages.
844 int allLanguagesCount = spellCheckListWidgetPointer->count();
846 // Get a list of all the checked languages.
847 for (int i = 0; i < allLanguagesCount; ++i) {
848 // Get the language item.
849 QListWidgetItem *languageItemPointer = spellCheckListWidgetPointer->item(i);
851 // Get the language check box.
852 QCheckBox *languageCheckBoxPointer = qobject_cast<QCheckBox*>(spellCheckListWidgetPointer->itemWidget(languageItemPointer));
854 // Add the item to the enabled languages if it is checked.
855 if (languageCheckBoxPointer->checkState() == Qt::Checked)
858 QString languageString = languageCheckBoxPointer->text();
860 // Remove all instances of `&`, which may have been added automatically when creating the check box text.
861 languageString.remove(QChar('&'));
863 // Add the language string to the list.
864 newSpellCheckLanguages.append(languageString);
868 // Update the spell check languages.
869 if (Settings::spellCheckLanguages() != newSpellCheckLanguages)
871 // Update the spell check languages.
872 Settings::setSpellCheckLanguages(newSpellCheckLanguages);
874 // Write the settings to disk.
875 kConfigSkeletonPointer->save();
878 // Apply the spell check languages.
879 tabWidgetPointer->applySpellCheckLanguages();
883 connect(applyButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
884 connect(okButtonPointer, &QPushButton::clicked, this, saveSpellCheckLanguages);
886 // Apply the settings handled by KConfig.
887 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyApplicationSettings()));
888 connect(configDialogPointer, SIGNAL(settingsChanged(QString)), tabWidgetPointer, SLOT(applyDomainSettingsAndReload()));
891 QSize BrowserWindow::sizeHint() const
893 // Return the default window size.
894 return QSize(1500, 1200);
897 void BrowserWindow::toggleDomStorage() const
899 // Remove the focus from the URL line edit.
900 urlLineEditPointer->clearFocus();
902 // Toggle DOM storage.
903 tabWidgetPointer->toggleDomStorage();
906 void BrowserWindow::toggleFindCaseSensitive() const
908 // Get the current find string.
909 const QString findString = findTextLineEditPointer->text();
911 // Toggle find case sensitive.
912 tabWidgetPointer->toggleFindCaseSensitive(findString);
915 void BrowserWindow::toggleJavaScript() const
917 // Remove the focus from the URL line edit.
918 urlLineEditPointer->clearFocus();
920 // Toggle JavaScript.
921 tabWidgetPointer->toggleJavaScript();
924 void BrowserWindow::toggleLocalStorage() const
926 // Remove the focus from the URL line edit.
927 urlLineEditPointer->clearFocus();
929 // Toggle local storage.
930 tabWidgetPointer->toggleLocalStorage();
933 void BrowserWindow::toggleFullScreen()
935 // Toggle the full screen status.
936 if (fullScreenActionPointer->isChecked()) // Enable full screen browsing mode.
938 // Enable full screen mode.
939 fullScreenActionPointer->setFullScreen(window(), true);
941 // Hide the menu bar if specified.
942 if (Settings::fullScreenHideMenuBar())
943 menuBar()->setVisible(false);
945 // Hide the toolbars if specified.
946 if (Settings::fullScreenHideToolBars())
948 navigationToolBarPointer->setVisible(false);
949 urlToolBarPointer->setVisible(false);
952 // Hide the tab bar if specified.
953 if (Settings::fullScreenHideTabBar())
954 tabWidgetPointer->setTabBarVisible(false);
956 // Hide the status bar if specified.
957 if (Settings::fullScreenHideStatusBar())
958 statusBar()->setVisible(false);
960 else // Disable full screen browsing mode.
962 // Disable full screen mode.
963 fullScreenActionPointer->setFullScreen(window(), false);
965 // Show the menu bar.
966 menuBar()->setVisible(true);
968 // Show the toolbars.
969 navigationToolBarPointer->setVisible(true);
970 urlToolBarPointer->setVisible(true);
973 tabWidgetPointer->setTabBarVisible(true);
975 // Show the status bar.
976 statusBar()->setVisible(true);
980 void BrowserWindow::updateCookiesAction(const int numberOfCookies) const
982 // Update the action text.
983 cookiesActionPointer->setText(i18nc("The Cookies action, which also displays the number of cookies", "Cookies - %1", numberOfCookies));
986 void BrowserWindow::updateDomStorageAction(const bool &isEnabled) const
988 // Set the action checked status.
989 domStorageActionPointer->setChecked(isEnabled);
992 void BrowserWindow::updateDomainSettingsIndicator(const bool status)
994 // Set the domain palette according to the status.
996 urlLineEditPointer->setPalette(positiveBackgroundPalette);
998 urlLineEditPointer->setPalette(normalBackgroundPalette);
1001 void BrowserWindow::updateFindText(const QString &text, const bool findCaseSensitive) const
1004 findTextLineEditPointer->setText(text);
1006 // Set the find case sensitive action checked status.
1007 findCaseSensitiveActionPointer->setChecked(findCaseSensitive);
1010 void BrowserWindow::updateFindTextResults(const QWebEngineFindTextResult &findTextResult) const
1012 // Update the find text label.
1013 findTextLabelPointer->setText(QStringLiteral(" %1/%2 ").arg(findTextResult.activeMatch()).arg(findTextResult.numberOfMatches()));
1015 // Set the background color according to the find status.
1016 if (findTextLineEditPointer->text().isEmpty())
1017 findTextLineEditPointer->setPalette(normalBackgroundPalette);
1018 else if (findTextResult.numberOfMatches() == 0)
1019 findTextLineEditPointer->setPalette(negativeBackgroundPalette);
1021 findTextLineEditPointer->setPalette(positiveBackgroundPalette);
1024 void BrowserWindow::updateJavaScriptAction(const bool &isEnabled)
1026 // Update the JavaScript status.
1027 javaScriptEnabled = isEnabled;
1029 // Set the icon according to the status.
1030 if (javaScriptEnabled)
1031 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/javascript-warning.svg")));
1033 javaScriptActionPointer->setIcon(QIcon(QLatin1String(":/icons/privacy-mode.svg")));
1035 // Set the action checked status.
1036 javaScriptActionPointer->setChecked(javaScriptEnabled);
1038 // Update the status of the DOM storage action.
1039 domStorageActionPointer->setEnabled(javaScriptEnabled & localStorageEnabled);
1042 void BrowserWindow::updateLocalStorageAction(const bool &isEnabled)
1044 // Update the local storage status.
1045 localStorageEnabled = isEnabled;
1047 // 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.
1048 if (localStorageEnabled)
1049 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota-high"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/filesaveas.png"))));
1051 localStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("disk-quota"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/apps/kfm.png"))));
1053 // Set the action checked status.
1054 localStorageActionPointer->setChecked(localStorageEnabled);
1056 // Update the status of the DOM storage action.
1057 domStorageActionPointer->setEnabled(localStorageEnabled & javaScriptEnabled);
1060 void BrowserWindow::updateSearchEngineActions(const QString &searchEngine, const bool &updateCustomSearchEngineStatus)
1062 // Initialize the custom search engine flag.
1063 bool customSearchEngine = false;
1065 if (searchEngine == "Mojeek") // Mojeek.
1067 // Check the Mojeek user agent action.
1068 searchEngineMojeekActionPointer->setChecked(true);
1070 // Update the search engine menu action icon.
1071 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1073 // Update the search engine menu action text.
1074 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Mojeek"));
1076 else if (searchEngine == "Monocles") // Monocles.
1078 // Check the Monocles user agent action.
1079 searchEngineMonoclesActionPointer->setChecked(true);
1081 // Update the search engine menu action icon.
1082 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1084 // Update the search engine menu action text.
1085 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Monocles"));
1087 else if (searchEngine == "MetaGer") // MetaGer.
1089 // Check the MetaGer user agent action.
1090 searchEngineMetagerActionPointer->setChecked(true);
1092 // Update the search engine menu action icon.
1093 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1095 // Update the search engine menu action text.
1096 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - MetaGer"));
1098 else if (searchEngine == "Google") // Google.
1100 // Check the Google user agent action.
1101 searchEngineGoogleActionPointer->setChecked(true);
1103 // Update the search engine menu action icon.
1104 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-google"), QIcon::fromTheme(QLatin1String("edit-find"))));
1106 // Update the search engine menu action text.
1107 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Google"));
1109 else if (searchEngine == "Bing") // Bing.
1111 // Check the Bing user agent action.
1112 searchEngineBingActionPointer->setChecked(true);
1114 // Update the search engine menu action icon.
1115 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1117 // Update the search engine menu action text.
1118 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Bing"));
1120 else if (searchEngine == "Yahoo") // Yahoo.
1122 // Check the Yahoo user agent action.
1123 searchEngineYahooActionPointer->setChecked(true);
1125 // Update the search engine menu action icon.
1126 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("im-yahoo"), QIcon::fromTheme(QLatin1String("edit-find"))));
1128 // Update the search engine menu action text.
1129 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Yahoo"));
1131 else // Custom search engine.
1133 // Check the user agent.
1134 searchEngineCustomActionPointer->setChecked(true);
1136 // Update the search engine menu action icon.
1137 searchEngineMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("edit-find")));
1139 // Update the search engine menu action text.
1140 searchEngineMenuActionPointer->setText(i18nc("The main search engine menu action", "Search Engine - Custom"));
1142 // Set the custom search engine text.
1143 searchEngineCustomActionPointer->setText(searchEngine);
1145 // Set the custom search engine flag.
1146 customSearchEngine = true;
1149 // Update the custom search engine enabled boolean.
1150 if (updateCustomSearchEngineStatus)
1151 customSearchEngineEnabled = customSearchEngine;
1153 // Format the custom search engine.
1154 if (customSearchEngineEnabled)
1156 // Enable the custom search engine.
1157 searchEngineCustomActionPointer->setEnabled(true);
1161 // Disable the custom search engine.
1162 searchEngineCustomActionPointer->setEnabled(false);
1164 // Reset the custom search engine text.
1165 searchEngineCustomActionPointer->setText(i18nc("@action", "Custom"));
1169 void BrowserWindow::updateUserAgentActions(const QString &userAgent, const bool &updateCustomUserAgentStatus)
1171 // Initialize the custom user agent flag.
1172 bool customUserAgent = false;
1174 // Check the indicated on-the-fly user agent.
1175 if (userAgent == UserAgentHelper::PRIVACY_BROWSER_USER_AGENT) // Privacy Browser.
1177 // Check the Privacy Browser user agent action.
1178 userAgentPrivacyBrowserActionPointer->setChecked(true);
1180 // Update the user agent menu action icon.
1181 userAgentMenuActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
1183 // Update the user agent menu action text.
1184 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Privacy Browser"));
1186 else if (userAgent == TabWidget::webEngineDefaultUserAgent) // WebEngine default.
1188 // check the WebEngine default user agent action.
1189 userAgentWebEngineDefaultActionPointer->setChecked(true);
1191 // Update the user agent menu action icon.
1192 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1194 // Update the user agent menu action text.
1195 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - WebEngine default"));
1197 else if (userAgent == UserAgentHelper::FIREFOX_LINUX_USER_AGENT) // Firefox on Linux.
1199 // Check the Firefox on Linux user agent action.
1200 userAgentFirefoxLinuxActionPointer->setChecked(true);
1202 // Update the user agent menu action icon.
1203 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1205 // Update the user agent menu action text.
1206 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Linux"));
1208 else if (userAgent == UserAgentHelper::CHROMIUM_LINUX_USER_AGENT) // Chromium on Linux.
1210 // Check the Chromium on Linux user agent action.
1211 userAgentChromiumLinuxActionPointer->setChecked(true);
1213 // Update the user agent menu action icon.
1214 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1216 // Update the user agent menu action text.
1217 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chromium on Linux"));
1219 else if (userAgent == UserAgentHelper::FIREFOX_WINDOWS_USER_AGENT) // Firefox on Windows.
1221 // Check the Firefox on Windows user agent action.
1222 userAgentFirefoxWindowsActionPointer->setChecked(true);
1224 // Update the user agent menu action icon.
1225 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1227 // Update the user agent menu action text.
1228 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Firefox on Windows"));
1230 else if (userAgent == UserAgentHelper::CHROME_WINDOWS_USER_AGENT) // Chrome on Windows.
1232 // Check the Chrome on Windows user agent action.
1233 userAgentChromeWindowsActionPointer->setChecked(true);
1235 // Update the user agent menu action icon.
1236 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("chromium"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
1238 // Update the user agent menu action text.
1239 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Chrome on Windows"));
1241 else if (userAgent == UserAgentHelper::EDGE_WINDOWS_USER_AGENT) // Edge on Windows.
1243 // Check the Edge on Windows user agent action.
1244 userAgentEdgeWindowsActionPointer->setChecked(true);
1246 // Update the user agent menu action icon.
1247 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1249 // Update the user agent menu action text.
1250 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Edge on Windows"));
1252 else if (userAgent == UserAgentHelper::SAFARI_MACOS_USER_AGENT) // Safari on macOS.
1254 // Check the Safari on macOS user agent action.
1255 userAgentSafariMacosActionPointer->setChecked(true);
1257 // Update the user agent menu action icon.
1258 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1260 // Update the user agent menu action text.
1261 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Safari on macOS"));
1263 else // Custom user agent.
1265 // Check the user agent.
1266 userAgentCustomActionPointer->setChecked(true);
1268 // Update the user agent menu action icon.
1269 userAgentMenuActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new"))));
1271 // Update the user agent menu action text.
1272 userAgentMenuActionPointer->setText(i18nc("The main user agent menu action", "User Agent - Custom"));
1274 // Set the custom user agent text.
1275 userAgentCustomActionPointer->setText(userAgent);
1277 // Set the custom user agent flag.
1278 customUserAgent = true;
1281 // Update the custom user agent enabled boolean.
1282 // 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.
1283 if (updateCustomUserAgentStatus)
1284 customUserAgentEnabled = customUserAgent;
1287 // Format the custom user agent.
1288 if (customUserAgentEnabled)
1290 // Enable the custom user agent.
1291 userAgentCustomActionPointer->setEnabled(true);
1295 // Disable the custom user agent.
1296 userAgentCustomActionPointer->setEnabled(false);
1298 // Reset the custom user agent text.
1299 userAgentCustomActionPointer->setText(i18nc("@action", "Custom"));
1303 void BrowserWindow::updateZoomFactorAction(const double &zoomFactor)
1305 // Set the current zoom factor.
1306 currentZoomFactor = zoomFactor;
1308 // Update the zoom factor action text, formatting the double with 2 decimal places.
1309 zoomFactorActionPointer->setText(ki18nc("@action", "Zoom Factor - %1").subs(zoomFactor, 0, '0', 2).toString());
1312 void BrowserWindow::updateSearchEngineLabel(const QString &searchEngineString) const
1314 // Update the search engine label.
1315 searchEngineLabelPointer->setText(SearchEngineHelper::getSearchUrl(searchEngineString));
1318 void BrowserWindow::updateUrlLineEdit(const QUrl &newUrl)
1320 // Update the URL line edit if it does not have focus.
1321 if (!urlLineEditPointer->hasFocus())
1323 // Get the new URL string.
1324 QString newUrlString = newUrl.toString();
1326 // Update the URL line edit.
1327 urlLineEditPointer->setText(newUrlString);
1329 // Set the focus if the new URL is blank.
1330 if (newUrlString == QStringLiteral(""))
1331 urlLineEditPointer->setFocus();
1334 // Store the current URL.
1335 currentUrl = newUrl;
1338 void BrowserWindow::updateUserAgentLabel(const QString &userAgentDatabaseName) const
1340 // Update the user agent label.
1341 userAgentLabelPointer->setText(UserAgentHelper::getUserAgentFromDatabaseName(userAgentDatabaseName));
1344 void BrowserWindow::updateWindowTitle(const QString &title)
1346 // Update the window title.
1347 setWindowTitle(title);