From fd722f6a4dd7807c38912ee230a7b1f528e0ee09 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Wed, 6 Apr 2022 09:27:42 +0200 Subject: [PATCH] allow to use bundled downloader to download attachments --- .../desktop/com.github.rssguard.appdata.xml | 2 +- src/librssguard/CMakeLists.txt | 3 - .../webviewers/webengine/webengineviewer.cpp | 1 + .../network-web/downloadmanager.cpp | 51 ++++++++---- src/librssguard/network-web/downloadmanager.h | 16 +++- .../services/gmail/gmailnetworkfactory.cpp | 37 ++++----- .../services/gmail/gmailnetworkfactory.h | 2 +- .../services/gmail/gmailserviceroot.cpp | 3 +- .../services/gmail/gui/emailpreviewer.cpp | 83 +++++++++++++++---- .../services/gmail/gui/emailpreviewer.h | 9 +- .../services/gmail/gui/emailpreviewer.ui | 3 - .../gmail/gui/formdownloadattachment.cpp | 53 ------------ .../gmail/gui/formdownloadattachment.h | 26 ------ .../gmail/gui/formdownloadattachment.ui | 55 ------------ 14 files changed, 141 insertions(+), 203 deletions(-) delete mode 100644 src/librssguard/services/gmail/gui/formdownloadattachment.cpp delete mode 100644 src/librssguard/services/gmail/gui/formdownloadattachment.h delete mode 100644 src/librssguard/services/gmail/gui/formdownloadattachment.ui diff --git a/resources/desktop/com.github.rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml index 33f5b23b6..fad4d8d1a 100644 --- a/resources/desktop/com.github.rssguard.appdata.xml +++ b/resources/desktop/com.github.rssguard.appdata.xml @@ -26,7 +26,7 @@ https://github.com/sponsors/martinrotter - + none diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt index ce4a6fd65..203e032f8 100644 --- a/src/librssguard/CMakeLists.txt +++ b/src/librssguard/CMakeLists.txt @@ -289,8 +289,6 @@ set(SOURCES services/gmail/gui/emailrecipientcontrol.h services/gmail/gui/formaddeditemail.cpp services/gmail/gui/formaddeditemail.h - services/gmail/gui/formdownloadattachment.cpp - services/gmail/gui/formdownloadattachment.h services/gmail/gui/formeditgmailaccount.cpp services/gmail/gui/formeditgmailaccount.h services/gmail/gui/gmailaccountdetails.cpp @@ -541,7 +539,6 @@ set(UI_FILES services/abstract/gui/formfeeddetails.ui services/feedly/gui/feedlyaccountdetails.ui services/gmail/gui/formaddeditemail.ui - services/gmail/gui/formdownloadattachment.ui services/gmail/gui/gmailaccountdetails.ui services/gmail/gui/emailpreviewer.ui services/greader/gui/greaderaccountdetails.ui diff --git a/src/librssguard/gui/webviewers/webengine/webengineviewer.cpp b/src/librssguard/gui/webviewers/webengine/webengineviewer.cpp index 36d279ace..f6ef11415 100644 --- a/src/librssguard/gui/webviewers/webengine/webengineviewer.cpp +++ b/src/librssguard/gui/webviewers/webengine/webengineviewer.cpp @@ -166,6 +166,7 @@ void WebEngineViewer::bindToBrowser(WebBrowser* browser) { browser->m_actionReload = pageAction(QWebEnginePage::WebAction::Reload); browser->m_actionStop = pageAction(QWebEnginePage::WebAction::Stop); + // NOTE: Just forwar QtWebEngine signals, it's all there. connect(this, &QWebEngineView::loadStarted, this, &WebEngineViewer::loadStarted); connect(this, &QWebEngineView::loadProgress, this, &WebEngineViewer::loadProgress); connect(this, &QWebEngineView::loadFinished, this, &WebEngineViewer::loadFinished); diff --git a/src/librssguard/network-web/downloadmanager.cpp b/src/librssguard/network-web/downloadmanager.cpp index c627fbdae..9e1421976 100644 --- a/src/librssguard/network-web/downloadmanager.cpp +++ b/src/librssguard/network-web/downloadmanager.cpp @@ -23,10 +23,13 @@ #include #include -DownloadItem::DownloadItem(QNetworkReply* reply, QWidget* parent) : QWidget(parent), - m_ui(new Ui::DownloadItem), m_reply(reply), - m_bytesReceived(0), m_requestFileName(false), m_startedSaving(false), m_finishedDownloading(false), - m_gettingFileName(false), m_canceledFileSelect(false) { +DownloadItem::DownloadItem(QNetworkReply* reply, + const QString& preferred_file_name, + const std::function& run_on_finish, + QWidget* parent) : QWidget(parent), + m_ui(new Ui::DownloadItem), m_reply(reply), m_preferredFileName(preferred_file_name), + m_runOnFinish(run_on_finish), m_bytesReceived(0), m_requestFileName(false), m_startedSaving(false), + m_finishedDownloading(false), m_gettingFileName(false), m_canceledFileSelect(false) { m_ui->setupUi(this); m_ui->m_btnTryAgain->hide(); m_requestFileName = qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::AlwaysPromptForFilename)).toBool(); @@ -40,6 +43,7 @@ DownloadItem::DownloadItem(QNetworkReply* reply, QWidget* parent) : QWidget(pare connect(m_ui->m_btnOpenFile, &QPushButton::clicked, this, &DownloadItem::openFile); connect(m_ui->m_btnTryAgain, &QPushButton::clicked, this, &DownloadItem::tryAgain); connect(m_ui->m_btnOpenFolder, &QPushButton::clicked, this, &DownloadItem::openFolder); + init(); } @@ -151,7 +155,10 @@ QString DownloadItem::saveFileName(const QString& directory) const { } } - if (path.isEmpty()) { + if (!m_preferredFileName.isEmpty()) { + path = m_preferredFileName; + } + else if (path.isEmpty()) { path = m_url.path(); } @@ -181,6 +188,11 @@ QString DownloadItem::saveFileName(const QString& directory) const { return name; } +const QFile& DownloadItem::output() const +{ + return m_output; +} + void DownloadItem::stop() { setUpdatesEnabled(false); m_ui->m_btnStopDownload->setEnabled(false); @@ -205,11 +217,11 @@ void DownloadItem::openFolder() { if (m_output.exists()) { if (!SystemFactory::openFolderFile(m_output.fileName())) { MsgBox::show(this, - QMessageBox::Icon::Warning, - tr("Cannot open directory"), - tr("Cannot open output directory. Open it manually."), - QString(), - m_output.fileName()); + QMessageBox::Icon::Warning, + tr("Cannot open directory"), + tr("Cannot open output directory. Open it manually."), + QString(), + m_output.fileName()); } } } @@ -413,6 +425,10 @@ void DownloadItem::finished() { emit statusChanged(); emit downloadFinished(); + if (m_runOnFinish) { + m_runOnFinish(this); + } + if (downloadedSuccessfully()) { qApp->showGuiMessage(Notification::Event::GeneralEvent, { tr("Download finished"), @@ -487,9 +503,11 @@ int DownloadManager::downloadProgress() const { } } -void DownloadManager::download(const QNetworkRequest& request) { +void DownloadManager::download(const QNetworkRequest& request, + const QString& preferred_file_name, + const std::function& run_on_finish) { if (!request.url().isEmpty()) { - handleUnsupportedContent(m_networkManager->get(request)); + handleUnsupportedContent(m_networkManager->get(request), preferred_file_name, run_on_finish); } } @@ -497,7 +515,9 @@ void DownloadManager::download(const QUrl& url) { download(QNetworkRequest(url)); } -void DownloadManager::handleUnsupportedContent(QNetworkReply* reply) { +void DownloadManager::handleUnsupportedContent(QNetworkReply* reply, + const QString& preferred_file_name, + const std::function& run_on_finish) { if (reply == nullptr || reply->url().isEmpty()) { return; } @@ -510,7 +530,7 @@ void DownloadManager::handleUnsupportedContent(QNetworkReply* reply) { return; } - auto* item = new DownloadItem(reply, this); + auto* item = new DownloadItem(reply, preferred_file_name, run_on_finish, this); addItem(item); @@ -660,7 +680,7 @@ void DownloadManager::load() { bool done = settings->value(GROUP(Downloads), QString(Downloads::ItemDone).arg(i), true).toBool(); if (!url.isEmpty() && !file_name.isEmpty()) { - auto* item = new DownloadItem(nullptr, this); + auto* item = new DownloadItem(nullptr, {}, {}, this); item->m_output.setFileName(file_name); item->m_url = url; @@ -670,6 +690,7 @@ void DownloadManager::load() { item->m_ui->m_btnTryAgain->setVisible(!done); item->m_ui->m_btnTryAgain->setEnabled(!done); item->m_ui->m_progressDownload->setVisible(false); + addItem(item); } diff --git a/src/librssguard/network-web/downloadmanager.h b/src/librssguard/network-web/downloadmanager.h index 4e82fadbe..2bf4f0490 100644 --- a/src/librssguard/network-web/downloadmanager.h +++ b/src/librssguard/network-web/downloadmanager.h @@ -25,7 +25,10 @@ class DownloadItem : public QWidget { friend class DownloadModel; public: - explicit DownloadItem(QNetworkReply* reply = 0, QWidget* parent = nullptr); + explicit DownloadItem(QNetworkReply* reply = nullptr, + const QString& preferred_file_name = {}, + const std::function& run_on_finish = {}, + QWidget* parent = nullptr); virtual ~DownloadItem(); bool downloading() const; @@ -35,6 +38,7 @@ class DownloadItem : public QWidget { qint64 bytesReceived() const; double remainingTime() const; double currentSpeed() const; + const QFile& output() const; private slots: void stop(); @@ -64,6 +68,8 @@ class DownloadItem : public QWidget { QUrl m_url; QFile m_output; QNetworkReply* m_reply; + QString m_preferredFileName; + std::function m_runOnFinish; qint64 m_bytesReceived; QElapsedTimer m_downloadTime; QTime m_lastProgressTime; @@ -113,9 +119,10 @@ class DownloadManager : public TabContent { static QString dataString(qint64 size); public slots: - void download(const QNetworkRequest& request); + void download(const QNetworkRequest& request, + const QString& preferred_file_name = {}, + const std::function& run_on_finish = {}); void download(const QUrl& url); - void handleUnsupportedContent(QNetworkReply* reply); void cleanup(); private slots: @@ -133,6 +140,9 @@ class DownloadManager : public TabContent { void downloadFinished(); private: + void handleUnsupportedContent(QNetworkReply* reply, + const QString& preferred_file_name, + const std::function& run_on_finish); void addItem(DownloadItem* item); QScopedPointer m_ui; diff --git a/src/librssguard/services/gmail/gmailnetworkfactory.cpp b/src/librssguard/services/gmail/gmailnetworkfactory.cpp index 7285026c6..650d35c4a 100644 --- a/src/librssguard/services/gmail/gmailnetworkfactory.cpp +++ b/src/librssguard/services/gmail/gmailnetworkfactory.cpp @@ -147,6 +147,20 @@ void GmailNetworkFactory::setDownloadOnlyUnreadMessages(bool download_only_unrea m_downloadOnlyUnreadMessages = download_only_unread_messages; } +QNetworkRequest GmailNetworkFactory::requestForAttachment(const QString& email_id, const QString& attachment_id) { + QString target_url = QSL(GMAIL_API_GET_ATTACHMENT).arg(email_id, attachment_id); + QNetworkRequest req(target_url); + QByteArray bearer = m_oauth2->bearer().toLocal8Bit(); + + if (bearer.isEmpty()) { + throw NetworkException(QNetworkReply::NetworkError::AuthenticationRequiredError); + } + + req.setRawHeader(QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer); + + return req; +} + void GmailNetworkFactory::setOauth(OAuth2Service* oauth) { m_oauth2 = oauth; } @@ -155,29 +169,6 @@ void GmailNetworkFactory::setUsername(const QString& username) { m_username = username; } -Downloader* GmailNetworkFactory::downloadAttachment(const QString& msg_id, - const QString& attachment_id, - const QNetworkProxy& custom_proxy) { - QString bearer = m_oauth2->bearer().toLocal8Bit(); - - if (bearer.isEmpty()) { - return nullptr; - } - else { - auto* downloader = new Downloader(); - QString target_url = QSL(GMAIL_API_GET_ATTACHMENT).arg(msg_id, attachment_id); - - if (custom_proxy.type() != QNetworkProxy::ProxyType::DefaultProxy) { - downloader->setProxy(custom_proxy); - } - - downloader->appendRawHeader(QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit()); - downloader->downloadFile(target_url); - - return downloader; - } -} - QList GmailNetworkFactory::messages(const QString& stream_id, const QHash& stated_messages, Feed::Status& error, diff --git a/src/librssguard/services/gmail/gmailnetworkfactory.h b/src/librssguard/services/gmail/gmailnetworkfactory.h index 7f34ce22a..c55aa3697 100644 --- a/src/librssguard/services/gmail/gmailnetworkfactory.h +++ b/src/librssguard/services/gmail/gmailnetworkfactory.h @@ -40,8 +40,8 @@ class GmailNetworkFactory : public QObject { void setDownloadOnlyUnreadMessages(bool download_only_unread_messages); // API methods. + QNetworkRequest requestForAttachment(const QString& email_id, const QString& attachment_id); QString sendEmail(Mimesis::Message msg, const QNetworkProxy& custom_proxy, Message* reply_to_message = nullptr); - Downloader* downloadAttachment(const QString& msg_id, const QString& attachment_id, const QNetworkProxy& custom_proxy); QList messages(const QString& stream_id, const QHash& stated_messages, Feed::Status& error, const QNetworkProxy& custom_proxy); QNetworkReply::NetworkError markMessagesRead(RootItem::ReadStatus status, diff --git a/src/librssguard/services/gmail/gmailserviceroot.cpp b/src/librssguard/services/gmail/gmailserviceroot.cpp index ac30d08b2..4b62f17c5 100644 --- a/src/librssguard/services/gmail/gmailserviceroot.cpp +++ b/src/librssguard/services/gmail/gmailserviceroot.cpp @@ -14,7 +14,6 @@ #include "services/gmail/gmailnetworkfactory.h" #include "services/gmail/gui/emailpreviewer.h" #include "services/gmail/gui/formaddeditemail.h" -#include "services/gmail/gui/formdownloadattachment.h" #include "services/gmail/gui/formeditgmailaccount.h" #include @@ -106,7 +105,7 @@ bool GmailServiceRoot::wantsBaggedIdsOfExistingMessages() const { CustomMessagePreviewer* GmailServiceRoot::customMessagePreviewer() { if (m_emailPreview.isNull()) { - m_emailPreview = new EmailPreviewer(); + m_emailPreview = new EmailPreviewer(this); } return m_emailPreview.data(); diff --git a/src/librssguard/services/gmail/gui/emailpreviewer.cpp b/src/librssguard/services/gmail/gui/emailpreviewer.cpp index c6446a844..16be2deb8 100644 --- a/src/librssguard/services/gmail/gui/emailpreviewer.cpp +++ b/src/librssguard/services/gmail/gui/emailpreviewer.cpp @@ -2,10 +2,19 @@ #include "services/gmail/gui/emailpreviewer.h" +#include "exceptions/networkexception.h" +#include "gui/messagebox.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" +#include "network-web/oauth2service.h" +#include "services/gmail/definitions.h" +#include "services/gmail/gmailnetworkfactory.h" +#include "services/gmail/gmailserviceroot.h" -EmailPreviewer::EmailPreviewer(QWidget* parent) : CustomMessagePreviewer(parent), m_webView(new WebBrowser(nullptr, this)) { +#include + +EmailPreviewer::EmailPreviewer(GmailServiceRoot* account, QWidget* parent) + : CustomMessagePreviewer(parent), m_account(account), m_webView(new WebBrowser(nullptr, this)) { m_ui.setupUi(this); m_ui.m_mainLayout->addWidget(dynamic_cast(m_webView.data()), 3, 0, 1, -1); @@ -13,22 +22,13 @@ EmailPreviewer::EmailPreviewer(QWidget* parent) : CustomMessagePreviewer(parent) m_ui.m_btnForward->setIcon(qApp->icons()->fromTheme(QSL("mail-forward"))); m_ui.m_btnReply->setIcon(qApp->icons()->fromTheme(QSL("mail-reply-sender"))); + QMenu* menu_attachments = new QMenu(this); + + m_ui.m_btnAttachments->setMenu(menu_attachments); + m_webView->setNavigationBarVisible(false); - // TODO: stahovani attachmentu - - /* - if (!file.isEmpty() && parts.size() == 3) { - Downloader* down = network()->downloadAttachment(parts.at(1), parts.at(2), networkProxy()); - FormDownloadAttachment form(file, down, qApp->mainFormWidget()); - - form.exec(); - return true; - } - else { - return false; - } - */ + connect(menu_attachments, &QMenu::triggered, this, &EmailPreviewer::downloadAttachment); } EmailPreviewer::~EmailPreviewer() { @@ -40,10 +40,59 @@ void EmailPreviewer::clear() { } void EmailPreviewer::loadMessage(const Message& msg, RootItem* selected_item) { + Q_UNUSED(selected_item) + + m_message = msg; m_webView->setHtml(msg.m_contents); + m_ui.m_tbFrom->setText(msg.m_author); m_ui.m_tbSubject->setText(msg.m_title); - - // TODO: todo m_ui.m_tbTo->setText(QSL("-")); + + m_ui.m_btnAttachments->menu()->clear(); + + for (const Enclosure& att : msg.m_enclosures) { + const QStringList att_id_name = att.m_url.split(QSL(GMAIL_ATTACHMENT_SEP)); + + m_ui.m_btnAttachments->menu()->addAction(att.m_mimeType)->setData(att_id_name); + } + + m_ui.m_btnAttachments->setDisabled(m_ui.m_btnAttachments->menu()->isEmpty()); +} + +void EmailPreviewer::downloadAttachment(QAction* act) { + const QString attachment_id = act->data().toStringList().at(1); + const QString file_name = act->data().toStringList().at(0); + + try { + + const QNetworkRequest req = m_account->network()->requestForAttachment(m_message.m_customId, attachment_id); + + qApp->downloadManager()->download(req, file_name, [this](DownloadItem* it) { + if (it->downloadedSuccessfully()) { + const QByteArray raw_json = IOFactory::readFile(it->output().fileName()); + const QString data = QJsonDocument::fromJson(raw_json).object()[QSL("data")].toString(); + + if (!data.isEmpty()) { + IOFactory::writeFile(it->output().fileName(), + QByteArray::fromBase64(data.toLocal8Bit(), + QByteArray::Base64Option::Base64UrlEncoding)); + } + } + }); + } + catch (const NetworkException&) { + MsgBox::show({}, + QMessageBox::Icon::Critical, + tr("Cannot download attachment"), + tr("Attachment cannot be downloaded because you are not logged-in.")); + } + catch (const ApplicationException& ex) { + MsgBox::show({}, + QMessageBox::Icon::Critical, + tr("Cannot download attachment"), + tr("Attachment cannot be downloaded because some general error happened."), + {}, + ex.message()); + } } diff --git a/src/librssguard/services/gmail/gui/emailpreviewer.h b/src/librssguard/services/gmail/gui/emailpreviewer.h index a9f037041..b63a5075a 100644 --- a/src/librssguard/services/gmail/gui/emailpreviewer.h +++ b/src/librssguard/services/gmail/gui/emailpreviewer.h @@ -9,19 +9,26 @@ #include "ui_emailpreviewer.h" +class GmailServiceRoot; + class EmailPreviewer : public CustomMessagePreviewer { Q_OBJECT public: - explicit EmailPreviewer(QWidget* parent = nullptr); + explicit EmailPreviewer(GmailServiceRoot* account, QWidget* parent = nullptr); virtual ~EmailPreviewer(); virtual void clear(); virtual void loadMessage(const Message& msg, RootItem* selected_item); + private slots: + void downloadAttachment(QAction* act); + private: Ui::EmailPreviewer m_ui; + GmailServiceRoot* m_account; QScopedPointer m_webView; + Message m_message; }; #endif // EMAILPREVIEWER_H diff --git a/src/librssguard/services/gmail/gui/emailpreviewer.ui b/src/librssguard/services/gmail/gui/emailpreviewer.ui index 0892889f9..d6c2ac962 100644 --- a/src/librssguard/services/gmail/gui/emailpreviewer.ui +++ b/src/librssguard/services/gmail/gui/emailpreviewer.ui @@ -64,9 +64,6 @@ Qt::ToolButtonTextBesideIcon - - Qt::DownArrow - diff --git a/src/librssguard/services/gmail/gui/formdownloadattachment.cpp b/src/librssguard/services/gmail/gui/formdownloadattachment.cpp deleted file mode 100644 index 5bec371f6..000000000 --- a/src/librssguard/services/gmail/gui/formdownloadattachment.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// For license of this file, see /LICENSE.md. - -#include "formdownloadattachment.h" - -#include "gui/guiutilities.h" -#include "miscellaneous/application.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/iofactory.h" -#include "network-web/downloader.h" - -#include -#include -#include - -FormDownloadAttachment::FormDownloadAttachment(const QString& target_file, Downloader* downloader, QWidget* parent) : QDialog(parent) { - m_ui.setupUi(this); - - GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("mail-attachment")), tr("Downloading attachment...")); - - connect(m_ui.m_btnBox->button(QDialogButtonBox::StandardButton::Abort), &QPushButton::clicked, downloader, &Downloader::cancel); - connect(downloader, - &Downloader::completed, - this, - [this, downloader, target_file](QNetworkReply::NetworkError status, const QByteArray& contents) { - if (status == QNetworkReply::NetworkError::NoError) { - QString data = QJsonDocument::fromJson(contents).object()[QSL("data")].toString(); - - if (!data.isEmpty()) { - IOFactory::writeFile(target_file, QByteArray::fromBase64(data.toLocal8Bit(), - QByteArray::Base64Option::Base64UrlEncoding)); - } - } - - downloader->deleteLater(); - close(); - }); - connect(downloader, &Downloader::progress, this, [this](qint64 bytes_received, qint64 bytes_total) { - m_ui.m_lblInfo->setText(tr("Downloaded: %1 kB").arg(bytes_received / 1000.0)); - - if (m_ui.m_progressBar->maximum() == 0) { - return; - } - - if (bytes_total <= 0) { - m_ui.m_progressBar->setMinimum(0); - m_ui.m_progressBar->setMaximum(0); - m_ui.m_progressBar->setValue(0); - } - else { - m_ui.m_progressBar->setValue(int((bytes_received * 100.0) / bytes_total)); - } - }); -} diff --git a/src/librssguard/services/gmail/gui/formdownloadattachment.h b/src/librssguard/services/gmail/gui/formdownloadattachment.h deleted file mode 100644 index 89815da54..000000000 --- a/src/librssguard/services/gmail/gui/formdownloadattachment.h +++ /dev/null @@ -1,26 +0,0 @@ -// For license of this file, see /LICENSE.md. - -#ifndef FORMDOWNLOADATTACHMENT_H -#define FORMDOWNLOADATTACHMENT_H - -#include - -#include "ui_formdownloadattachment.h" - -namespace Ui { - class FormDownloadAttachment; -} - -class Downloader; - -class FormDownloadAttachment : public QDialog { - Q_OBJECT - - public: - explicit FormDownloadAttachment(const QString& target_file, Downloader* downloader, QWidget* parent = nullptr); - - private: - Ui::FormDownloadAttachment m_ui; -}; - -#endif // FORMDOWNLOADATTACHMENT_H diff --git a/src/librssguard/services/gmail/gui/formdownloadattachment.ui b/src/librssguard/services/gmail/gui/formdownloadattachment.ui deleted file mode 100644 index 4663d36f3..000000000 --- a/src/librssguard/services/gmail/gui/formdownloadattachment.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - FormDownloadAttachment - - - - 0 - 0 - 275 - 106 - - - - - - - 0 - - - - - - - Qt::Vertical - - - - 20 - 100 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Abort - - - - - - - - - - - - - - -