/*
- * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2022-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc/>.
*
* Privacy Browser PC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
// Application headers.
+#include "DevToolsWebEngineView.h"
#include "TabWidget.h"
#include "Settings.h"
#include "ui_AddTabWidget.h"
+#include "ui_Tab.h"
#include "ui_TabWidget.h"
#include "databases/CookiesDatabase.h"
#include "dialogs/SaveDialog.h"
// Manually delete each WebEngine page.
for (int i = 0; i < numberOfTabs; ++i)
{
- // Get the privacy WebEngine view.
- PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+ // Get the tab splitter widget.
+ QWidget *tabSplitterWidgetPointer = qTabWidgetPointer->widget(i);
- // Deletion the WebEngine page to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+ // Get the WebEngine views.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = tabSplitterWidgetPointer->findChild<PrivacyWebEngineView *>();
+ DevToolsWebEngineView *devToolsWebEngineViewPointer = tabSplitterWidgetPointer->findChild<DevToolsWebEngineView *>();
+
+ // Deletion the WebEngine pages to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
delete privacyWebEngineViewPointer->page();
+ delete devToolsWebEngineViewPointer->page();
}
}
qTabWidgetPointer->currentWidget()->setFocus();
}
-PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const bool backgroundTab)
+PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const bool adjacent, const bool backgroundTab, const QString urlString)
{
- // Create a privacy WebEngine view.
+ // Create a splitter widget.
+ QSplitter *splitterPointer = new QSplitter();
+
+ // Set the splitter to be vertical.
+ splitterPointer->setOrientation(Qt::Vertical);
+
+ // Set the splitter handle size.
+ splitterPointer->setHandleWidth(5);
+
+ // Create the WebEngines.
PrivacyWebEngineView *privacyWebEngineViewPointer = new PrivacyWebEngineView();
+ DevToolsWebEngineView *devToolsWebEngineViewPointer = new DevToolsWebEngineView();
+
+ // Add the WebEngines to the splitter.
+ splitterPointer->addWidget(privacyWebEngineViewPointer);
+ splitterPointer->addWidget(devToolsWebEngineViewPointer);
+
+ // Initialize the new tab index.
+ int newTabIndex = 0;
// Add a new tab.
- int newTabIndex = qTabWidgetPointer->addTab(privacyWebEngineViewPointer, i18nc("New tab label.", "New Tab"));
+ if (adjacent) // Add the new tab adjacent to the current tab.
+ newTabIndex = qTabWidgetPointer->insertTab((qTabWidgetPointer->currentIndex() + 1), splitterPointer, i18nc("New tab label.", "New Tab"));
+ else // Add the new tab at the end of the list.
+ newTabIndex = qTabWidgetPointer->addTab(splitterPointer, i18nc("New tab label.", "New Tab"));
// Set the default tab icon.
qTabWidgetPointer->setTabIcon(newTabIndex, defaultFavoriteIcon);
- // Get handles for the WebEngine page and profile.
+ // Get handles for the WebEngine components.
QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
QWebEngineProfile *webEngineProfilePointer = webEnginePagePointer->profile();
-
- // Get handles for the web engine elements.
QWebEngineCookieStore *webEngineCookieStorePointer = webEngineProfilePointer->cookieStore();
QWebEngineSettings *webEngineSettingsPointer = webEnginePagePointer->settings();
+ // Set the development tools WebEngine. This must be done here to preserve the bottom half of the window as the initial development tools size.
+ webEnginePagePointer->setDevToolsPage(devToolsWebEngineViewPointer->page());
+
+ // Initially hide the development tools WebEngine.
+ devToolsWebEngineViewPointer->setVisible(false);
+
+ // Initially disable the development tools WebEngine.
+ webEnginePagePointer->setDevToolsPage(nullptr);
+
+ // Disable JavaScript on the development tools WebEngine to prevent error messages from being written to the console.
+ devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
// Update the URL line edit when the URL changes.
connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::urlChanged, [this, privacyWebEngineViewPointer] (const QUrl &newUrl)
{
});
// Update the title when it changes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, privacyWebEngineViewPointer] (const QString &title)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, splitterPointer] (const QString &title)
{
// Get the index for this tab.
- int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+ int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
// Update the title for this tab.
qTabWidgetPointer->setTabText(tabIndex, title);
});
// Connect the loading favorite icon movie to the tab icon.
- connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [this, privacyWebEngineViewPointer]
+ connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [this, splitterPointer, privacyWebEngineViewPointer]
{
// Get the index for this tab.
- int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+ int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
// Display the loading favorite icon if this tab is loading.
if (privacyWebEngineViewPointer->isLoading)
});
// Update the icon when it changes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [this, privacyWebEngineViewPointer] (const QIcon &newFavoriteIcon)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [this, splitterPointer, privacyWebEngineViewPointer] (const QIcon &newFavoriteIcon)
{
// Store the favorite icon in the privacy web engine view.
if (newFavoriteIcon.isNull())
privacyWebEngineViewPointer->favoriteIcon = newFavoriteIcon;
// Get the index for this tab.
- int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+ int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
// Update the icon for this tab.
if (newFavoriteIcon.isNull())
});
// Update the progress bar when a load finishes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [this, privacyWebEngineViewPointer] ()
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [this, splitterPointer, privacyWebEngineViewPointer] ()
{
// Set the privacy web engine view to be not loading.
privacyWebEngineViewPointer->isLoading = false;
emit hideProgressBar();
// Get the index for this tab.
- int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+ int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
// Display the current favorite icon
qTabWidgetPointer->setTabIcon(tabIndex, privacyWebEngineViewPointer->favoriteIcon);
for (int i = 0; i < numberOfTabs; i++)
{
// Get the privacy WebEngine view for the tab.
- PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView*>(qTabWidgetPointer->widget(i));
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
// Check to see if it is currently loading. If at least one tab is loading, this flag will end up being marked `false` when the for loop has finished.
if (privacyWebEngineViewPointer->isLoading)
}
});
- // Update the zoom factor when changed by CTRL-Scrolling. This can be modified when <https://redmine.stoutner.com/issues/845> is fixed.
+ // Update the zoom actions when changed by CTRL-Scrolling. This can be modified when <https://redmine.stoutner.com/issues/845> is fixed.
connect(webEnginePagePointer, &QWebEnginePage::contentsSizeChanged, [webEnginePagePointer, this] ()
{
- // Only update the zoom factor action text if this is the current tab.
+ // Only update the zoom actions if this is the current tab.
if (webEnginePagePointer == currentWebEnginePagePointer)
- emit updateZoomFactorAction(webEnginePagePointer->zoomFactor());
+ emit updateZoomActions(webEnginePagePointer->zoomFactor());
});
// Display find text results.
// Plugins must be enabled for the PDF viewer to work. <https://doc.qt.io/qt-5/qtwebengine-features.html#pdf-file-viewing>
webEngineSettingsPointer->setAttribute(QWebEngineSettings::PluginsEnabled, true);
+ // Update the blocked requests action.
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::requestBlocked, [this, privacyWebEngineViewPointer] (const int blockedRequests)
+ {
+ // Update the blocked requests action if the specified privacy WebEngine view is the current privacy WebEngine view.
+ if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
+ emit blockedRequestsUpdated(blockedRequests);
+ });
+
// Update the cookies action.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::updateCookiesAction, [this, privacyWebEngineViewPointer] (const int numberOfCookies)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::numberOfCookiesChanged, [this, privacyWebEngineViewPointer] (const int numberOfCookies)
{
// Update the cookie action if the specified privacy WebEngine view is the current privacy WebEngine view.
if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
- emit updateCookiesAction(numberOfCookies);
+ emit cookiesChanged(numberOfCookies);
});
// Process cookie changes.
if (removeUrlLineEditFocus)
emit clearUrlLineEditFocus();
+ if (urlString != nullptr)
+ privacyWebEngineViewPointer->load(QUrl::fromUserInput(urlString));
+
// Return the privacy WebEngine view pointer.
return privacyWebEngineViewPointer;
}
// Apply the spatial navigation settings to each WebEngine.
for (int i = 0; i < numberOfTabs; ++i) {
// Get the WebEngine view pointer.
- PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
// Apply the spatial navigation settings to each page.
privacyWebEngineViewPointer->page()->settings()->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, Settings::spatialNavigation());
void TabWidget::applyDomainSettingsAndReload()
{
- // Apply the domain settings. `true` reloads the website.
- currentPrivacyWebEngineViewPointer->applyDomainSettings(currentPrivacyWebEngineViewPointer->url().host(), true);
+ // Get the number of tabs.
+ int numberOfTabs = qTabWidgetPointer->count();
+
+ // Apply the domain settings to each WebEngine.
+ for (int i = 0; i < numberOfTabs; ++i) {
+ // Get the WebEngine view pointer.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
+
+ // Apply the spatial navigation settings to each page.
+ privacyWebEngineViewPointer->applyDomainSettings(privacyWebEngineViewPointer->url().host(), true);
+ }
}
void TabWidget::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
currentPrivacyWebEngineViewPointer->reload();
}
-void TabWidget::applyOnTheFlyZoomFactor(const double &zoomFactor) const
+void TabWidget::applyOnTheFlyZoomFactor(const double zoomFactorDouble) const
{
// Set the zoom factor.
- currentPrivacyWebEngineViewPointer->setZoomFactor(zoomFactor);
+ currentPrivacyWebEngineViewPointer->setZoomFactor(zoomFactorDouble);
}
void TabWidget::applySpellCheckLanguages() const
for (int i = 0; i < numberOfTabs; ++i)
{
// Get the WebEngine view pointer.
- PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
// Get the WebEngine page pointer.
QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
void TabWidget::deleteTab(const int tabIndex)
{
- // Get the privacy WebEngine view.
- PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(tabIndex));
+ // Get the tab splitter widget.
+ QWidget *tabSplitterWidgetPointer = qTabWidgetPointer->widget(tabIndex);
+
+ // Get the WebEngine views.
+ PrivacyWebEngineView *privacyWebEngineViewPointer = tabSplitterWidgetPointer->findChild<PrivacyWebEngineView *>();
+ DevToolsWebEngineView *devToolsWebEngineViewPointer = tabSplitterWidgetPointer->findChild<DevToolsWebEngineView *>();
// Process the tab delete according to the number of tabs.
if (qTabWidgetPointer->count() > 1) // There is more than one tab.
{
- // Delete the tab.
+ // Remove the tab.
qTabWidgetPointer->removeTab(tabIndex);
- // Delete the WebEngine page to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+ // Delete the WebEngine pages to prevent the following error: `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
delete privacyWebEngineViewPointer->page();
+ delete devToolsWebEngineViewPointer->page();
- // Delete the privacy WebEngine view.
+ // Delete the WebEngine views.
delete privacyWebEngineViewPointer;
+ delete devToolsWebEngineViewPointer;
+
+ // Delete the tab splitter widget.
+ delete tabSplitterWidgetPointer;
}
else // There is only one tab.
{
return currentPrivacyWebEngineViewPointer->cookieListPointer;
}
+QIcon TabWidget::getCurrentTabFavoritIcon() const
+{
+ // Return the current Privacy WebEngine favorite icon.
+ return currentPrivacyWebEngineViewPointer->favoriteIcon;
+}
+
+QString TabWidget::getCurrentTabTitle() const
+{
+ // Return the current Privacy WebEngine title.
+ return currentPrivacyWebEngineViewPointer->title();
+}
+
+QString TabWidget::getCurrentTabUrl() const
+{
+ // Return the current Privacy WebEngine URL as a string.
+ return currentPrivacyWebEngineViewPointer->url().toString();
+}
+
+QString TabWidget::getCurrentUserAgent() const
+{
+ // Return the current WebEngine user agent.
+ return currentWebEngineProfilePointer->httpUserAgent();
+}
+
QString& TabWidget::getDomainSettingsName() const
{
// Return the domain settings name.
void TabWidget::loadUrlFromLineEdit(QString url) const
{
// Decide if the text is more likely to be a URL or a search.
- if (url.startsWith("file://")) // The text is likely a file URL.
+ if (url.startsWith("file://") || url.startsWith("view-source:")) // The text is likely a file or view source URL.
{
// Load the URL.
currentPrivacyWebEngineViewPointer->load(QUrl::fromUserInput(url));
void TabWidget::refresh() const
{
+ // Reset the HTTP authentication dialog counter.
+ currentPrivacyWebEngineViewPointer->httpAuthenticationDialogsDisplayed = 0;
+
// Reload the website.
currentPrivacyWebEngineViewPointer->reload();
}
+void TabWidget::reloadAndBypassCache() const
+{
+ // Reload the website, bypassing the cache.
+ currentWebEnginePagePointer->triggerAction(QWebEnginePage::ReloadAndBypassCache);
+}
+
+void TabWidget::saveArchive()
+{
+ // Get the suggested file name.
+ QString suggestedFileName = currentPrivacyWebEngineViewPointer->title() + ".mht";
+
+ // Get the download directory.
+ QString downloadDirectory = Settings::downloadDirectory();
+
+ // Resolve the system download directory if specified.
+ if (downloadDirectory == QLatin1String("System Download Directory"))
+ downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+
+ // Get a file path from the file picker.
+ QString saveFilePath = QFileDialog::getSaveFileName(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory + QLatin1Char('/') + suggestedFileName);
+
+ // Save the webpage as an archive if the file save path is populated.
+ if (!saveFilePath.isEmpty())
+ {
+ // Update the download directory if specified.
+ if (Settings::autoUpateDownloadDirectory())
+ updateDownloadDirectory(saveFilePath);
+
+ // Set the saving archive flag. Otherwise, a second download tries to run.
+ savingArchive = true;
+
+ // Save the archive.
+ currentWebEnginePagePointer->save(saveFilePath);
+ }
+}
+
void TabWidget::setTabBarVisible(const bool visible) const
{
// Set the tab bar visibility.
void TabWidget::showSaveDialog(QWebEngineDownloadItem *webEngineDownloadItemPointer)
{
- // Get the download attributes.
- QUrl downloadUrl = webEngineDownloadItemPointer->url();
- QString mimeTypeString = webEngineDownloadItemPointer->mimeType();
- QString suggestedFileName = webEngineDownloadItemPointer->suggestedFileName();
- int totalBytes = webEngineDownloadItemPointer->totalBytes();
-
- // Check to see if Privacy Browser is not running KDE or if local storage (cookies) is enabled.
- if (!isRunningKde || currentPrivacyWebEngineViewPointer->localStorageEnabled) // KDE is not running or local storage (cookies) is enabled. Use WebEngine's downloader.
+ // Only show the save dialog if an archive is not currently being saved. Otherwise, two save dialogs will be shown.
+ if (!savingArchive)
{
- // Instantiate the save dialog.
- SaveDialog *saveDialogPointer = new SaveDialog(downloadUrl, mimeTypeString, totalBytes);
+ // Get the download attributes.
+ QUrl downloadUrl = webEngineDownloadItemPointer->url();
+ QString mimeTypeString = webEngineDownloadItemPointer->mimeType();
+ QString suggestedFileName = webEngineDownloadItemPointer->suggestedFileName();
+ int totalBytes = webEngineDownloadItemPointer->totalBytes();
+
+ // Check to see if Privacy Browser is not running KDE or if local storage (cookies) is enabled.
+ if (!isRunningKde || currentPrivacyWebEngineViewPointer->localStorageEnabled) // KDE is not running or local storage (cookies) is enabled. Use WebEngine's downloader.
+ {
+ // Instantiate the save dialog.
+ SaveDialog *saveDialogPointer = new SaveDialog(this, downloadUrl, mimeTypeString, totalBytes);
- // Display the save dialog.
- int saveDialogResult = saveDialogPointer->exec();
+ // Display the save dialog.
+ int saveDialogResult = saveDialogPointer->exec();
- // Process the save dialog results.
- if (saveDialogResult == QDialog::Accepted) // Save was selected.
- {
- // Get the download directory.
- QString downloadDirectory = Settings::downloadLocation();
+ // Process the save dialog results.
+ if (saveDialogResult == QDialog::Accepted) // Save was selected.
+ {
+ // Get the download directory.
+ QString downloadDirectory = Settings::downloadDirectory();
- // Resolve the system download directory if specified.
- if (downloadDirectory == QLatin1String("System Download Directory"))
- downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ // Resolve the system download directory if specified.
+ if (downloadDirectory == QLatin1String("System Download Directory"))
+ downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
- // Get a file path from the file picker.
- QString saveFilePath = QFileDialog::getSaveFileName(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory + QLatin1Char('/') + suggestedFileName);
+ // Get a file path from the file picker.
+ QString saveFilePath = QFileDialog::getSaveFileName(this, i18nc("Save file dialog caption", "Save File"), downloadDirectory + QLatin1Char('/') + suggestedFileName);
- // Process the save file path.
- if (!saveFilePath.isEmpty()) // The file save path is populated.
- {
- // Create a save file path file info.
- QFileInfo saveFilePathFileInfo = QFileInfo(saveFilePath);
+ // Process the save file path.
+ if (!saveFilePath.isEmpty()) // The file save path is populated.
+ {
+ // Update the download directory if specified.
+ if (Settings::autoUpateDownloadDirectory())
+ updateDownloadDirectory(saveFilePath);
- // Get the canonical save path and file name.
- QString absoluteSavePath = saveFilePathFileInfo.absolutePath();
- QString saveFileName = saveFilePathFileInfo.fileName();
+ // Create a save file path file info.
+ QFileInfo saveFilePathFileInfo = QFileInfo(saveFilePath);
- // Set the download directory and file name.
- webEngineDownloadItemPointer->setDownloadDirectory(absoluteSavePath);
- webEngineDownloadItemPointer->setDownloadFileName(saveFileName);
+ // Get the canonical save path and file name.
+ QString absoluteSavePath = saveFilePathFileInfo.absolutePath();
+ QString saveFileName = saveFilePathFileInfo.fileName();
- // Create a file download notification.
- KNotification *fileDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
+ // Set the download directory and file name.
+ webEngineDownloadItemPointer->setDownloadDirectory(absoluteSavePath);
+ webEngineDownloadItemPointer->setDownloadFileName(saveFileName);
- // Set the notification title.
- fileDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
+ // Create a file download notification.
+ KNotification *fileDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
- // Set the notification text.
- fileDownloadNotificationPointer->setText(i18nc("Downloading notification text", "Downloading %1", saveFileName));
+ // Set the notification title.
+ fileDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
- // Set the notification icon.
- fileDownloadNotificationPointer->setIconName(QLatin1String("download"));
+ // Set the notification text.
+ fileDownloadNotificationPointer->setText(i18nc("Downloading notification text", "Downloading %1", saveFileName));
- // Set the action list cancel button.
- fileDownloadNotificationPointer->setActions(QStringList({i18nc("Download notification action","Cancel")}));
+ // Get the download icon from the theme.
+ QIcon downloadIcon = QIcon::fromTheme(QLatin1String("download"), QIcon::fromTheme(QLatin1String("document-save")));
- // Set the notification to display indefinitely.
- fileDownloadNotificationPointer->setFlags(KNotification::Persistent);
+ // Set the notification icon.
+ fileDownloadNotificationPointer->setIconName(downloadIcon.name());
- // Prevent the notification from being autodeleted if it is closed. Otherwise, the updates to the notification below cause a crash.
- fileDownloadNotificationPointer->setAutoDelete(false);
+ // Set the action list cancel button.
+ fileDownloadNotificationPointer->setActions(QStringList({i18nc("Download notification action","Cancel")}));
- // Display the notification.
- fileDownloadNotificationPointer->sendEvent();
+ // Prevent the notification from being autodeleted if it is closed. Otherwise, the updates to the notification below cause a crash.
+ fileDownloadNotificationPointer->setAutoDelete(false);
- // Handle clicks on the cancel button.
- connect(fileDownloadNotificationPointer, &KNotification::action1Activated, [webEngineDownloadItemPointer, saveFileName] ()
- {
- // Cancel the download.
- webEngineDownloadItemPointer->cancel();
+ // Handle clicks on the cancel button.
+ connect(fileDownloadNotificationPointer, &KNotification::action1Activated, [webEngineDownloadItemPointer, saveFileName] ()
+ {
+ // Cancel the download.
+ webEngineDownloadItemPointer->cancel();
- // Create a file download notification.
- KNotification *canceledDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
+ // Create a file download notification.
+ KNotification *canceledDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
- // Set the notification title.
- canceledDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
+ // Set the notification title.
+ canceledDownloadNotificationPointer->setTitle(i18nc("Download notification title", "Download"));
- // Set the new text.
- canceledDownloadNotificationPointer->setText(i18nc("Download canceled notification", "%1 download canceled", saveFileName));
+ // Set the new text.
+ canceledDownloadNotificationPointer->setText(i18nc("Download canceled notification", "%1 download canceled", saveFileName));
- // Set the notification icon.
- canceledDownloadNotificationPointer->setIconName(QLatin1String("download"));
+ // Set the notification icon.
+ canceledDownloadNotificationPointer->setIconName(QLatin1String("download"));
- // Display the notification.
- canceledDownloadNotificationPointer->sendEvent();
- });
+ // Display the notification.
+ canceledDownloadNotificationPointer->sendEvent();
+ });
- // Update the notification when the download progresses.
- connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::downloadProgress, [fileDownloadNotificationPointer, saveFileName] (qint64 bytesReceived, qint64 totalBytes)
- {
- // Set the new text. Total bytes will be 0 if the download size is unknown.
- if (totalBytes > 0)
+ // Update the notification when the download progresses.
+ connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::downloadProgress, [fileDownloadNotificationPointer, saveFileName] (qint64 bytesReceived, qint64 totalBytes)
{
- // Calculate the download percentage.
- int downloadPercentage = 100 * bytesReceived / totalBytes;
-
- // Set the file download notification text.
- fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1\% of %2 downloaded (%3 of %4 bytes)", downloadPercentage, saveFileName,
- bytesReceived, totalBytes));
- }
- else
+ // Set the new text. Total bytes will be 0 if the download size is unknown.
+ if (totalBytes > 0)
+ {
+ // Calculate the download percentage.
+ int downloadPercentage = 100 * bytesReceived / totalBytes;
+
+ // Set the file download notification text.
+ fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1\% of %2 downloaded (%3 of %4 bytes)", downloadPercentage, saveFileName,
+ bytesReceived, totalBytes));
+ }
+ else
+ {
+ // Set the file download notification text.
+ fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1: %2 bytes downloaded", saveFileName, bytesReceived));
+ }
+
+ // Display the updated notification.
+ fileDownloadNotificationPointer->update();
+ });
+
+ // Update the notification when the download finishes. The save file name must be copied into the lambda or a crash occurs.
+ connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::finished, [fileDownloadNotificationPointer, saveFileName, saveFilePath] ()
{
- // Set the file download notification text.
- fileDownloadNotificationPointer->setText(i18nc("Download progress notification text", "%1: %2 bytes downloaded", saveFileName, bytesReceived));
- }
-
- // Display the updated notification.
- fileDownloadNotificationPointer->update();
- });
+ // Set the new text.
+ fileDownloadNotificationPointer->setText(i18nc("Download finished notification text", "%1 download finished", saveFileName));
- // Update the notification when the download finishes. The save file name must be copied into the lambda or a crash occurs.
- connect(webEngineDownloadItemPointer, &QWebEngineDownloadItem::finished, [fileDownloadNotificationPointer, saveFileName, saveFilePath] ()
- {
- // Set the new text.
- fileDownloadNotificationPointer->setText(i18nc("Download finished notification text", "%1 download finished", saveFileName));
+ // Set the URL so the file options will be displayed.
+ fileDownloadNotificationPointer->setUrls(QList<QUrl> {QUrl(saveFilePath)});
- // Set the URL so the file options will be displayed.
- fileDownloadNotificationPointer->setUrls(QList<QUrl> {QUrl(saveFilePath)});
+ // Remove the actions from the notification.
+ fileDownloadNotificationPointer->setActions(QStringList());
- // Remove the actions from the notification.
- fileDownloadNotificationPointer->setActions(QStringList());
+ // Set the notification to disappear after a timeout.
+ fileDownloadNotificationPointer->setFlags(KNotification::CloseOnTimeout);
- // Set the notification to disappear after a timeout.
- fileDownloadNotificationPointer->setFlags(KNotification::CloseOnTimeout);
+ // Display the updated notification.
+ fileDownloadNotificationPointer->update();
+ });
- // Display the updated notification.
- fileDownloadNotificationPointer->update();
- });
+ // Display the notification.
+ fileDownloadNotificationPointer->sendEvent();
- // Start the download.
- webEngineDownloadItemPointer->accept();
+ // Start the download.
+ webEngineDownloadItemPointer->accept();
+ }
+ else // The file save path is not populated.
+ {
+ // Cancel the download.
+ webEngineDownloadItemPointer->cancel();
+ }
}
- else // The file save path is not populated.
+ else // Cancel was selected.
{
// Cancel the download.
webEngineDownloadItemPointer->cancel();
}
}
- else // Cancel was selected.
+ else // KDE is running and local storage (cookies) is disabled. Use KDE's native downloader.
+ // This must use the show command to launch a separate dialog which cancels WebEngine's automatic background download of the file to a temporary location.
{
- // Cancel the download.
- webEngineDownloadItemPointer->cancel();
+ // Instantiate the save dialog. `true` instructs it to use the native downloader
+ SaveDialog *saveDialogPointer = new SaveDialog(this, downloadUrl, mimeTypeString, totalBytes, suggestedFileName, true);
+
+ // Connect the save button.
+ connect(saveDialogPointer, SIGNAL(useNativeKdeDownloader(QUrl &, QString &)), this, SLOT(useNativeKdeDownloader(QUrl &, QString &)));
+
+ // Show the dialog.
+ saveDialogPointer->show();
}
}
- else // KDE is running and local storage (cookies) is disabled. Use KDE's native downloader.
- // This must use the show command to launch a separate dialog which cancels WebEngine's automatic background download of the file to a temporary location.
+
+ // Reset the saving archive flag.
+ savingArchive = false;
+}
+
+void TabWidget::stop() const
+{
+ // Stop the loading of the current privacy WebEngine.
+ currentPrivacyWebEngineViewPointer->stop();
+}
+
+void TabWidget::toggleDeveloperTools(const bool enabled) const
+{
+ // Get a handle for the current developer tools WebEngine.
+ DevToolsWebEngineView *devToolsWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<DevToolsWebEngineView *>();
+
+ if (enabled)
+ {
+ // Set the zoom factor on the development tools WebEngine.
+ devToolsWebEngineViewPointer->setZoomFactor(currentWebEnginePagePointer->zoomFactor());
+
+ // Enable the development tools.
+ currentWebEnginePagePointer->setDevToolsPage(devToolsWebEngineViewPointer->page());
+
+ // Enable JavaScript on the development tools WebEngine.
+ devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+
+ // Display the developer tools.
+ devToolsWebEngineViewPointer->setVisible(true);
+ }
+ else
{
- // Instantiate the save dialog. `true` instructs it to use the native downloader
- SaveDialog *saveDialogPointer = new SaveDialog(downloadUrl, mimeTypeString, totalBytes, suggestedFileName, true);
+ // Disable JavaScript on the development tools WebEngine to prevent error messages from being written to the console.
+ devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
- // Connect the save button.
- connect(saveDialogPointer, SIGNAL(useNativeKdeDownloader(QUrl &, QString &)), this, SLOT(useNativeKdeDownloader(QUrl &, QString &)));
+ // Disable the development tools.
+ currentWebEnginePagePointer->setDevToolsPage(nullptr);
- // Show the dialog.
- saveDialogPointer->show();
+ // Hide the developer tools.
+ devToolsWebEngineViewPointer->setVisible(false);
}
}
currentPrivacyWebEngineViewPointer->reload();
}
+void TabWidget::updateDownloadDirectory(QString newDownloadDirectory) const
+{
+ // Remove the file name from the save file path.
+ newDownloadDirectory.truncate(newDownloadDirectory.lastIndexOf(QLatin1Char('/')));
+
+ // Update the download location.
+ Settings::setDownloadDirectory(newDownloadDirectory);
+
+ // Get a handle for the KConfig skeleton.
+ KConfigSkeleton *kConfigSkeletonPointer = Settings::self();
+
+ // Write the settings to disk.
+ kConfigSkeletonPointer->save();
+}
+
void TabWidget::updateUiFromWebEngineView(const PrivacyWebEngineView *privacyWebEngineViewPointer) const
{
// Only update the UI if the signal was emitted from the current privacy WebEngine.
if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
{
// Update the UI.
+ emit updateDefaultZoomFactor(currentPrivacyWebEngineViewPointer->defaultZoomFactor);
emit updateDomainSettingsIndicator(currentPrivacyWebEngineViewPointer->domainSettingsName != QLatin1String(""));
emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), true);
- emit updateZoomFactorAction(currentPrivacyWebEngineViewPointer->zoomFactor());
+ emit updateZoomActions(currentPrivacyWebEngineViewPointer->zoomFactor());
}
}
void TabWidget::updateUiWithTabSettings()
{
// Update the current WebEngine pointers.
- currentPrivacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->currentWidget());
+ currentPrivacyWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<PrivacyWebEngineView *>();
currentWebEngineSettingsPointer = currentPrivacyWebEngineViewPointer->settings();
currentWebEnginePagePointer = currentPrivacyWebEngineViewPointer->page();
currentWebEngineProfilePointer = currentWebEnginePagePointer->profile();
// Clear the URL line edit focus.
emit clearUrlLineEditFocus();
+ // Get a handle for the development tools WebEngine view.
+ DevToolsWebEngineView *devToolsWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<DevToolsWebEngineView *>();
+
// Update the actions.
+ emit blockedRequestsUpdated(currentPrivacyWebEngineViewPointer->blockedRequests);
+ emit cookiesChanged(currentPrivacyWebEngineViewPointer->cookieListPointer->size());
+ emit updateDefaultZoomFactor(currentPrivacyWebEngineViewPointer->defaultZoomFactor);
emit updateBackAction(currentWebEngineHistoryPointer->canGoBack());
- emit updateCookiesAction(currentPrivacyWebEngineViewPointer->cookieListPointer->size());
+ emit updateDeveloperToolsAction(devToolsWebEngineViewPointer->isVisible());
emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
emit updateForwardAction(currentWebEngineHistoryPointer->canGoForward());
emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
emit updateLocalStorageAction(currentPrivacyWebEngineViewPointer->localStorageEnabled);
emit updateUserAgentActions(currentWebEngineProfilePointer->httpUserAgent(), true);
- emit updateZoomFactorAction(currentPrivacyWebEngineViewPointer->zoomFactor());
+ emit updateZoomActions(currentPrivacyWebEngineViewPointer->zoomFactor());
// Update the URL.
emit updateWindowTitle(currentPrivacyWebEngineViewPointer->title());
void TabWidget::useNativeKdeDownloader(QUrl &downloadUrl, QString &suggestedFileName)
{
// Get the download directory.
- QString downloadDirectory = Settings::downloadLocation();
+ QString downloadDirectory = Settings::downloadDirectory();
// Resolve the system download directory if specified.
if (downloadDirectory == QLatin1String("System Download Directory"))
saveFileDialogPointer->setWindowModality(Qt::WindowModal);
// Process the saving of the file. The save file dialog pointer must be captured directly instead of by reference or nasty crashes occur.
- auto saveFile = [saveFileDialogPointer, downloadUrl] ()
+ auto saveFile = [saveFileDialogPointer, downloadUrl, this] ()
{
// Get the save location. The dialog box should only allow the selecting of one file location.
QUrl saveLocation = saveFileDialogPointer->selectedUrls().value(0);
+ // Update the download directory if specified.
+ if (Settings::autoUpateDownloadDirectory())
+ updateDownloadDirectory(saveLocation.toLocalFile());
+
// Create a file copy job. `-1` creates the file with default permissions.
KIO::FileCopyJob *fileCopyJobPointer = KIO::file_copy(downloadUrl, saveLocation, -1, KIO::Overwrite);