+ // 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] ()
+ {
+ // Cancel the download.
+ webEngineDownloadItemPointer->cancel();
+
+ // Create a file download notification.
+ KNotification *canceledDownloadNotificationPointer = new KNotification(QLatin1String("FileDownload"));
+
+ // 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 notification icon.
+ canceledDownloadNotificationPointer->setIconName(QLatin1String("download"));
+
+ // 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)
+ {
+ // 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 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)});
+
+ // Remove the actions from the notification.
+ fileDownloadNotificationPointer->setActions(QStringList());
+
+ // Set the notification to disappear after a timeout.
+ fileDownloadNotificationPointer->setFlags(KNotification::CloseOnTimeout);
+
+ // Display the updated notification.
+ fileDownloadNotificationPointer->update();
+ });
+
+ // Start the download.
+ webEngineDownloadItemPointer->accept();
+ }
+ else // The file save path is not populated.
+ {
+ // Cancel the download.
+ webEngineDownloadItemPointer->cancel();
+ }
+ }
+ else // Cancel was selected.
+ {
+ // Cancel the download.
+ webEngineDownloadItemPointer->cancel();
+ }
+ }
+ 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(useNativeKdeDownloader(QUrl &, QString &)), this, SLOT(useNativeKdeDownloader(QUrl &, QString &)));
+
+ // Show the dialog.
+ saveDialogPointer->show();
+ }