QString TabWidget::webEngineDefaultUserAgent = QLatin1String("");
// Construct the class.
-TabWidget::TabWidget(QWidget *parent) : QWidget(parent)
+TabWidget::TabWidget(QWidget *windowPointer) : QWidget(windowPointer)
{
+ // Create a QProcess to check if KDE is running.
+ QProcess *checkIfRunningKdeQProcessPointer = new QProcess();
+
+ // Create an argument string list that contains `ksmserver` (KDE Session Manager).
+ QStringList argument = QStringList(QLatin1String("ksmserver"));
+
+ // Run `pidof` to check for the presence of `ksmserver`.
+ checkIfRunningKdeQProcessPointer->start(QLatin1String("pidof"), argument);
+
+ // Monitor any standard output.
+ connect(checkIfRunningKdeQProcessPointer, &QProcess::readyReadStandardOutput, [this]
+ {
+ // If there is any standard output, `ksmserver` is running.
+ isRunningKde = true;
+ });
+
// Instantiate the user agent helper.
userAgentHelperPointer = new UserAgentHelper();
// Set the loading favorite icon movie file name.
loadingFavoriteIconMoviePointer->setFileName(QStringLiteral(":/icons/loading.gif"));
+ // Stop the loading favorite icon movie if the window is destroyed. Otherwise, the app will crash if there is more than one window open and a window is closed while at tab is loading.
+ connect(windowPointer, SIGNAL(destroyed()), this, SLOT(stopLoadingFavoriteIconMovie()));
+
// Add the first tab.
addFirstTab();
TabWidget::~TabWidget()
{
+ // Get the number of tabs.
+ int numberOfTabs = qTabWidgetPointer->count();
+
// Manually delete each WebEngine page.
- for (int i = 0; i < qTabWidgetPointer->count(); ++i)
+ for (int i = 0; i < numberOfTabs; ++i)
{
// Get the privacy WebEngine view.
PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
qTabWidgetPointer->currentWidget()->setFocus();
}
-PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const bool backgroundTab)
+PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const bool backgroundTab, const QString urlString)
{
// Create a privacy WebEngine view.
PrivacyWebEngineView *privacyWebEngineViewPointer = new PrivacyWebEngineView();
QWebEngineSettings *webEngineSettingsPointer = webEnginePagePointer->settings();
// Update the URL line edit when the URL changes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::urlChanged, [privacyWebEngineViewPointer, this] (const QUrl &newUrl)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::urlChanged, [this, privacyWebEngineViewPointer] (const QUrl &newUrl)
{
// Only update the UI if this is the current tab.
if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
});
// Connect the loading favorite icon movie to the tab icon.
- connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [privacyWebEngineViewPointer, this]
+ connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [this, privacyWebEngineViewPointer]
{
// Get the index for this tab.
int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
});
// Update the icon when it changes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [privacyWebEngineViewPointer, this] (const QIcon &newFavoriteIcon)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [this, privacyWebEngineViewPointer] (const QIcon &newFavoriteIcon)
{
// Store the favorite icon in the privacy web engine view.
if (newFavoriteIcon.isNull())
});
// Update the progress bar and the favorite icon when a load is started.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadStarted, [privacyWebEngineViewPointer, this] ()
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadStarted, [this, privacyWebEngineViewPointer] ()
{
// Set the privacy web engine view to be loading.
privacyWebEngineViewPointer->isLoading = true;
});
// Update the progress bar when a load progresses.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadProgress, [privacyWebEngineViewPointer, this] (const int progress)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadProgress, [this, privacyWebEngineViewPointer] (const int progress)
{
// Store the load progress.
privacyWebEngineViewPointer->loadProgressInt = progress;
});
// Update the progress bar when a load finishes.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [privacyWebEngineViewPointer, this] ()
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [this, privacyWebEngineViewPointer] ()
{
// Set the privacy web engine view to be not loading.
privacyWebEngineViewPointer->isLoading = false;
// Create a no tabs loading variable.
bool noTabsLoading = true;
+ // Get the number of tabs.
+ int numberOfTabs = qTabWidgetPointer->count();
+
// Check to see if any other tabs are loading.
- for (int i = 0; i < qTabWidgetPointer->count(); i++)
+ for (int i = 0; i < numberOfTabs; i++)
{
// Get the privacy WebEngine view for the tab.
- PrivacyWebEngineView *webEngineViewPointer = qobject_cast<PrivacyWebEngineView*>(qTabWidgetPointer->widget(i));
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView*>(qTabWidgetPointer->widget(i));
- // Check to see if it is currently loading.
- if (webEngineViewPointer->isLoading)
+ // 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)
noTabsLoading = false;
}
});
// Display HTTP Ping blocked dialogs.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::displayHttpPingBlockedDialog, [privacyWebEngineViewPointer, this] (const QString &httpPingUrl)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::displayHttpPingBlockedDialog, [this, privacyWebEngineViewPointer] (const QString &httpPingUrl)
{
// Only display the HTTP Ping blocked dialog if this is the current tab.
if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
}
});
- // 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.
// Don't allow JavaScript to open windows.
webEngineSettingsPointer->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
- // Allow keyboard navigation.
- webEngineSettingsPointer->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, true);
+ // Allow keyboard navigation between links and input fields.
+ webEngineSettingsPointer->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, Settings::spatialNavigation());
// Enable full screen support.
webEngineSettingsPointer->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
webEngineSettingsPointer->setAttribute(QWebEngineSettings::PluginsEnabled, true);
// Update the cookies action.
- connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::updateCookiesAction, [privacyWebEngineViewPointer, this] (const int numberOfCookies)
+ connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::updateCookiesAction, [this, privacyWebEngineViewPointer] (const int numberOfCookies)
{
// Update the cookie action if the specified privacy WebEngine view is the current privacy WebEngine view.
if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
if (removeUrlLineEditFocus)
emit clearUrlLineEditFocus();
+ if (urlString != nullptr)
+ privacyWebEngineViewPointer->load(QUrl::fromUserInput(urlString));
+
// Return the privacy WebEngine view pointer.
return privacyWebEngineViewPointer;
}
else
qTabWidgetPointer->setTabPosition(QTabWidget::South);
+ // Get the number of tabs.
+ int numberOfTabs = qTabWidgetPointer->count();
+
+ // 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));
+
+ // Apply the spatial navigation settings to each page.
+ privacyWebEngineViewPointer->page()->settings()->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, Settings::spatialNavigation());
+ }
+
// Set the search engine URL.
searchEngineUrl = SearchEngineHelper::getSearchUrl(Settings::searchEngine());
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 = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+
+ // Apply the spatial navigation settings to each page.
+ privacyWebEngineViewPointer->applyDomainSettings(privacyWebEngineViewPointer->url().host(), true);
+ }
}
void TabWidget::applyOnTheFlySearchEngine(QAction *searchEngineActionPointer)
for (int i = 0; i < numberOfTabs; ++i)
{
// Get the WebEngine view pointer.
- PrivacyWebEngineView *webEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->currentWidget());
+ PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
// Get the WebEngine page pointer.
- QWebEnginePage *webEnginePagePointer = webEngineViewPointer->page();
+ QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
// Get the WebEngine profile pointer.
QWebEngineProfile *webEngineProfilePointer = webEnginePagePointer->profile();
void TabWidget::findTextFinished(const QWebEngineFindTextResult &findTextResult)
{
- // Update the find text UI if it wasn't simply wiping the current find text selection. Otherwise the UI temporarially flashes `0/0`.
+ // Update the find text UI if it wasn't simply wiping the current find text selection. Otherwise the UI temporarily flashes `0/0`.
if (wipingCurrentFindTextSelection) // The current selection is being wiped.
{
// Reset the flag.
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::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));
emit linkHovered(linkUrl);
}
+void TabWidget::stopLoadingFavoriteIconMovie() const
+{
+ // Stop the loading favorite icon movie. Otherwise, the browser will crash if a second window is closed while a tab in it is loading. <https://redmine.stoutner.com/issues/1010>
+ loadingFavoriteIconMoviePointer->stop();
+}
+
void TabWidget::print() const
{
// Create a printer.
currentPrivacyWebEngineViewPointer->reload();
}
+void TabWidget::reloadAndBypassCache() const
+{
+ // Reload the website, bypassing the cache.
+ currentWebEnginePagePointer->triggerAction(QWebEnginePage::ReloadAndBypassCache);
+}
+
+
void TabWidget::setTabBarVisible(const bool visible) const
{
// Set the tab bar visibility.
QString suggestedFileName = webEngineDownloadItemPointer->suggestedFileName();
int totalBytes = webEngineDownloadItemPointer->totalBytes();
- // Check to see if local storage (cookies) is enabled.
- if (currentPrivacyWebEngineViewPointer->localStorageEnabled) // Local storage (cookies) is enabled. Use WebEngine's downloader.
+ // 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(downloadUrl, mimeTypeString, totalBytes);
if (downloadDirectory == QLatin1String("System Download Directory"))
downloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
- // Display a save file dialog.
+ // 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.
// Set the notification text.
fileDownloadNotificationPointer->setText(i18nc("Downloading notification text", "Downloading %1", saveFileName));
+ // Get the download icon from the theme.
+ QIcon downloadIcon = QIcon::fromTheme(QLatin1String("download"), QIcon::fromTheme(QLatin1String("document-save")));
+
// Set the notification icon.
- fileDownloadNotificationPointer->setIconName(QLatin1String("download"));
+ fileDownloadNotificationPointer->setIconName(downloadIcon.name());
// Set the action list cancel button.
fileDownloadNotificationPointer->setActions(QStringList({i18nc("Download notification action","Cancel")}));
- // Set the notification to display indefinitely.
- fileDownloadNotificationPointer->setFlags(KNotification::Persistent);
-
// Prevent the notification from being autodeleted if it is closed. Otherwise, the updates to the notification below cause a crash.
fileDownloadNotificationPointer->setAutoDelete(false);
- // Display the notification.
- fileDownloadNotificationPointer->sendEvent();
-
// Handle clicks on the cancel button.
connect(fileDownloadNotificationPointer, &KNotification::action1Activated, [webEngineDownloadItemPointer, saveFileName] ()
{
fileDownloadNotificationPointer->update();
});
+ // Display the notification.
+ fileDownloadNotificationPointer->sendEvent();
+
// Start the download.
webEngineDownloadItemPointer->accept();
}
webEngineDownloadItemPointer->cancel();
}
}
- else // Local storage (cookies) is disabled. Use KDE's native downloader.
+ 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.
{
// Instantiate the save dialog. `true` instructs it to use the native downloader
SaveDialog *saveDialogPointer = new SaveDialog(downloadUrl, mimeTypeString, totalBytes, suggestedFileName, true);
// Connect the save button.
- connect(saveDialogPointer, SIGNAL(useNativeDownloader(QUrl &, QString &)), this, SLOT(useNativeDownloader(QUrl &, QString &)));
+ connect(saveDialogPointer, SIGNAL(useNativeKdeDownloader(QUrl &, QString &)), this, SLOT(useNativeKdeDownloader(QUrl &, QString &)));
// Show the dialog.
saveDialogPointer->show();
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());
}
}
emit clearUrlLineEditFocus();
// Update the actions.
+ emit updateDefaultZoomFactor(currentPrivacyWebEngineViewPointer->defaultZoomFactor);
emit updateBackAction(currentWebEngineHistoryPointer->canGoBack());
emit updateCookiesAction(currentPrivacyWebEngineViewPointer->cookieListPointer->size());
emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
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());
emit hideProgressBar();
}
-void TabWidget::useNativeDownloader(QUrl &downloadUrl, QString &suggestedFileName)
+void TabWidget::useNativeKdeDownloader(QUrl &downloadUrl, QString &suggestedFileName)
{
// Get the download directory.
QString downloadDirectory = Settings::downloadLocation();
// Create a file copy job. `-1` creates the file with default permissions.
KIO::FileCopyJob *fileCopyJobPointer = KIO::file_copy(downloadUrl, saveLocation, -1, KIO::Overwrite);
- // Set the download job to display any error messages.
+ // Set the download job to display any warning and error messages.
+ fileCopyJobPointer->uiDelegate()->setAutoWarningHandlingEnabled(true);
fileCopyJobPointer->uiDelegate()->setAutoErrorHandlingEnabled(true);
// Start the download.