From 2f64e4300b77f74cc4a7f0f50dbfe87862b72b95 Mon Sep 17 00:00:00 2001 From: Saturneric Date: Tue, 4 Jan 2022 06:10:04 +0800 Subject: [PATCH] (core, ui): version system upgrade. 1. can notice user withdraw version now. 2. fix software not restart when signal caught. 3. improve ui. --- src/main.cpp | 1 + src/ui/CMakeLists.txt | 1 + src/ui/KeyMgmt.cpp | 10 +- src/ui/MainWindow.cpp | 7 +- src/ui/MainWindow.h | 3 +- src/ui/data_struct/SoftwareVersion.cpp | 25 ++++ src/ui/data_struct/SoftwareVersion.h | 53 +++++++++ src/ui/function/VersionCheckThread.cpp | 109 +++++++++++++----- src/ui/function/VersionCheckThread.h | 8 +- src/ui/help/AboutDialog.cpp | 41 ++++--- src/ui/help/AboutDialog.h | 4 +- src/ui/main_window/MainWindowSlotFunction.cpp | 27 ++--- ui/SendMailDialog.ui | 10 -- 13 files changed, 215 insertions(+), 84 deletions(-) create mode 100644 src/ui/data_struct/SoftwareVersion.cpp create mode 100644 src/ui/data_struct/SoftwareVersion.h diff --git a/src/main.cpp b/src/main.cpp index ae04d7db..149d9b9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -177,6 +177,7 @@ int main(int argc, char* argv[]) { } } else { + QApplication::exit(RESTART_CODE); QMessageBox::information( nullptr, _("A serious error has occurred"), _("Oh no! GpgFrontend caught a serious error in the software, so it " diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index d61519d9..3e44a0d6 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -8,6 +8,7 @@ aux_source_directory(./help UI_SOURCE) aux_source_directory(./settings UI_SOURCE) aux_source_directory(./function UI_SOURCE) aux_source_directory(./details UI_SOURCE) +aux_source_directory(./data_struct UI_SOURCE) if (SMTP_SUPPORT) aux_source_directory(./smtp UI_SOURCE) diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index 18a076c7..3715b01a 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -371,8 +371,16 @@ void KeyMgmt::slotExportKeyToKeyPackage() { } void KeyMgmt::slotExportKeyToClipboard() { - ByteArrayPtr key_export_data = nullptr; + auto keys_checked = key_list_->getChecked(); + if (keys_checked->empty()) { + QMessageBox::critical( + this, _("Forbidden"), + _("Please check some keys before doing this operation.")); + return; + } + + ByteArrayPtr key_export_data = nullptr; if (!GpgKeyImportExporter::GetInstance().ExportKeys(keys_checked, key_export_data)) { return; diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index fd3e6820..44d8103d 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -117,12 +117,7 @@ void MainWindow::init() noexcept { emit loaded(); #ifdef RELEASE - QString baseUrl = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - QNetworkRequest request; - request.setUrl(QUrl(baseUrl)); - auto* replay = networkAccessManager->get(request); - auto version_thread = new VersionCheckThread(replay); + auto version_thread = new VersionCheckThread(); connect(version_thread, SIGNAL(finished()), version_thread, SLOT(deleteLater())); diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 60a6240a..f5e644b3 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -244,8 +244,7 @@ class MainWindow : public QMainWindow { /** * @details called when need to upgrade. */ - void slotVersionUpgrade(const QString& currentVersion, - const QString& latestVersion); + void slotVersionUpgrade(const SoftwareVersion& version); private: /** diff --git a/src/ui/data_struct/SoftwareVersion.cpp b/src/ui/data_struct/SoftwareVersion.cpp new file mode 100644 index 00000000..2e814cb9 --- /dev/null +++ b/src/ui/data_struct/SoftwareVersion.cpp @@ -0,0 +1,25 @@ +/** + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric starting on May 12, 2021. + * + */ + +#include "SoftwareVersion.h" diff --git a/src/ui/data_struct/SoftwareVersion.h b/src/ui/data_struct/SoftwareVersion.h new file mode 100644 index 00000000..942f22ce --- /dev/null +++ b/src/ui/data_struct/SoftwareVersion.h @@ -0,0 +1,53 @@ +/** + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Foobar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric starting on May 12, 2021. + * + */ + +#ifndef GPGFRONTEND_SOFTWAREVERSION_H +#define GPGFRONTEND_SOFTWAREVERSION_H + +#include + +namespace GpgFrontend::UI { +struct SoftwareVersion { + std::string latest_version; + std::string current_version; + bool latest_prerelease = false; + bool latest_draft = false; + bool current_prerelease = false; + bool current_draft = false; + bool load_info_done = false; + std::string publish_date; + std::string release_note; + + [[nodiscard]] bool NeedUpgrade() const { + return load_info_done && !latest_prerelease && !latest_draft && + current_version < latest_version; + } + + [[nodiscard]] bool VersionWithDrawn() const { + return load_info_done && current_prerelease && !current_draft; + } +}; +} // namespace GpgFrontend::UI + +#endif // GPGFRONTEND_SOFTWAREVERSION_H diff --git a/src/ui/function/VersionCheckThread.cpp b/src/ui/function/VersionCheckThread.cpp index bad60ef4..e038ab97 100644 --- a/src/ui/function/VersionCheckThread.cpp +++ b/src/ui/function/VersionCheckThread.cpp @@ -24,8 +24,7 @@ #include "VersionCheckThread.h" -#include -#include +#include #include "GpgFrontendBuildInfo.h" #include "json/json.hpp" @@ -33,45 +32,97 @@ namespace GpgFrontend::UI { void VersionCheckThread::run() { - using namespace nlohmann; - - LOG(INFO) << "get latest version from Github"; - auto current_version = std::string("v") + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH); - while (mNetworkReply->isRunning()) { - QApplication::processEvents(); - } + auto manager = new QNetworkAccessManager(nullptr); - if (mNetworkReply->error() != QNetworkReply::NoError) { + LOG(INFO) << "current version" << current_version; + + std::string latest_version_url = + "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; + + std::string current_version_url = + "https://api.github.com/repos/saturneric/gpgfrontend/releases/tags/" + + current_version; + + QNetworkRequest latest_request, current_request; + latest_request.setUrl(QUrl(latest_version_url.c_str())); + current_request.setUrl(QUrl(current_version_url.c_str())); + auto reply = manager->get(latest_request); + while (reply->isRunning()) QApplication::processEvents(); + if (reply->error() != QNetworkReply::NoError) { LOG(ERROR) << "network error"; + manager->deleteLater(); return; } - auto bytes = mNetworkReply->readAll(); - - auto reply_json = nlohmann::json::parse(bytes.toStdString()); - - std::string latest_version = reply_json["tag_name"]; - - LOG(INFO) << "latest version from Github" << latest_version; - - QRegularExpression re(R"(^[vV](\d+\.)?(\d+\.)?(\*|\d+))"); - auto version_match = re.match(latest_version.c_str()); - if (version_match.hasMatch()) { - latest_version = version_match.captured(0).toStdString(); - LOG(INFO) << "latest version matched" << latest_version; - } else { - latest_version = current_version; - LOG(WARNING) << "latest version unknown"; + latest_reply_bytes_ = reply->readAll(); + reply = manager->get(current_request); + while (reply->isRunning()) QApplication::processEvents(); + current_reply_bytes_ = reply->readAll(); + if (reply->error() != QNetworkReply::NoError) { + LOG(ERROR) << "network error"; + manager->deleteLater(); + return; } - emit upgradeVersion(current_version.c_str(), latest_version.c_str()); + SoftwareVersion version; + version.current_version = current_version; + + try { + using namespace nlohmann; + + auto latest_reply_json = + nlohmann::json::parse(latest_reply_bytes_.toStdString()); + auto current_reply_json = + nlohmann::json::parse(current_reply_bytes_.toStdString()); + + std::string latest_version = latest_reply_json["tag_name"]; + + LOG(INFO) << "latest version from Github" << latest_version; + + QRegularExpression re(R"(^[vV](\d+\.)?(\d+\.)?(\*|\d+))"); + auto version_match = re.match(latest_version.c_str()); + if (version_match.hasMatch()) { + latest_version = version_match.captured(0).toStdString(); + LOG(INFO) << "latest version matched" << latest_version; + } else { + latest_version = current_version; + LOG(WARNING) << "latest version unknown"; + } + + bool prerelease = latest_reply_json["prerelease"], + draft = latest_reply_json["draft"]; + std::string publish_date = latest_reply_json["published_at"]; + std::string release_note = latest_reply_json["body"]; + version.latest_version = latest_version; + version.latest_prerelease = prerelease; + version.latest_draft = draft; + version.publish_date = publish_date; + version.release_note = release_note; + + bool current_prerelease = current_reply_json["prerelease"], + current_draft = current_reply_json["draft"]; + version.latest_prerelease = current_prerelease; + version.latest_draft = current_draft; + + // loading done + version.load_info_done = true; + + } catch (...) { + LOG(INFO) << "error occurred"; + version.load_info_done = false; + } + + manager->deleteLater(); + + emit upgradeVersion(version); } -VersionCheckThread::VersionCheckThread(QNetworkReply* networkReply) - : mNetworkReply(networkReply) {} +VersionCheckThread::VersionCheckThread() : QThread(nullptr) { + qRegisterMetaType("SoftwareVersion"); +}; } // namespace GpgFrontend::UI diff --git a/src/ui/function/VersionCheckThread.h b/src/ui/function/VersionCheckThread.h index 181ee947..0db9770c 100644 --- a/src/ui/function/VersionCheckThread.h +++ b/src/ui/function/VersionCheckThread.h @@ -26,6 +26,7 @@ #define GPGFRONTEND_VERSIONCHECKTHREAD_H #include "ui/GpgFrontendUI.h" +#include "ui/data_struct/SoftwareVersion.h" namespace GpgFrontend::UI { @@ -33,18 +34,17 @@ class VersionCheckThread : public QThread { Q_OBJECT public: - explicit VersionCheckThread(QNetworkReply* networkReply); + explicit VersionCheckThread(); signals: - void upgradeVersion(const QString& currentVersion, - const QString& latestVersion); + void upgradeVersion(SoftwareVersion version); protected: void run() override; private: - QNetworkReply* mNetworkReply; + QByteArray latest_reply_bytes_, current_reply_bytes_; }; } // namespace GpgFrontend::UI diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp index 5ee90e23..a3db6eda 100644 --- a/src/ui/help/AboutDialog.cpp +++ b/src/ui/help/AboutDialog.cpp @@ -163,14 +163,6 @@ UpdateTab::UpdateTab(QWidget* parent) : QWidget(parent) { latestVersionLabel->setWordWrap(true); upgradeLabel = new QLabel(); - upgradeLabel->setText( - "
" + - QString(_("The current version is less than the latest version on " - "github.")) + - "
" + _("Please click") + - " " + - _("Here") + " " + _("to download the latest version.") + "
"); upgradeLabel->setWordWrap(true); upgradeLabel->setOpenExternalLinks(true); upgradeLabel->setHidden(true); @@ -196,11 +188,7 @@ void UpdateTab::getLatestVersion() { LOG(INFO) << _("try to get latest version"); - QString base_url = - "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest"; - QNetworkRequest request; - request.setUrl(QUrl(base_url)); - auto version_thread = new VersionCheckThread(manager->get(request)); + auto version_thread = new VersionCheckThread(); connect(version_thread, SIGNAL(finished()), version_thread, SLOT(deleteLater())); @@ -210,16 +198,33 @@ void UpdateTab::getLatestVersion() { version_thread->start(); } -void UpdateTab::slotShowVersionStatus(const QString& current, - const QString& server) { +void UpdateTab::slotShowVersionStatus(const SoftwareVersion& version) { this->pb->setHidden(true); - latestVersionLabel->setText("
" + QString(_("Latest Version From Github")) + ": " + - server + "
"); + version.latest_version.c_str() + ""); - if (current < server) { + if (version.NeedUpgrade()) { + upgradeLabel->setText( + "
" + + QString(_("The current version is less than the latest version on " + "github.")) + + "
" + _("Please click") + + " " + + _("Here") + " " + _("to download the latest stable version.") + + "
"); upgradeLabel->show(); + } else if (version.VersionWithDrawn()) { + upgradeLabel->setText( + "
" + + QString(_("This version has serious problems and has been withdrawn. " + "Please stop using it immediately.")) + + "
" + _("Please click") + + " " + + _("Here") + " " + _("to download the latest stable version.") + + "
"); } } diff --git a/src/ui/help/AboutDialog.h b/src/ui/help/AboutDialog.h index 78c98149..44ab0e3c 100644 --- a/src/ui/help/AboutDialog.h +++ b/src/ui/help/AboutDialog.h @@ -27,6 +27,8 @@ #include "gpg/GpgContext.h" #include "ui/GpgFrontendUI.h" +#include "ui/data_struct/SoftwareVersion.h" + namespace GpgFrontend::UI { /** @@ -73,7 +75,7 @@ class UpdateTab : public QWidget { void getLatestVersion(); private slots: - void slotShowVersionStatus(const QString& current, const QString& server); + void slotShowVersionStatus(const SoftwareVersion& version); signals: void replyFromUpdateServer(QByteArray data); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 53f7dd9c..09f29958 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -499,13 +499,12 @@ void MainWindow::uploadKeyToServer() { void MainWindow::slotOpenFile(QString& path) { edit->slotOpenFile(path); } -void MainWindow::slotVersionUpgrade(const QString& currentVersion, - const QString& latestVersion) { +void MainWindow::slotVersionUpgrade(const SoftwareVersion& version) { LOG(INFO) << _("called"); - if (currentVersion < latestVersion) { + if (version.NeedUpgrade()) { statusBar()->showMessage( QString(_("GpgFrontend Upgradeable (New Version: %1).")) - .arg(latestVersion), + .arg(version.latest_version.c_str()), 30000); auto update_button = new QPushButton("Update GpgFrontend", this); connect(update_button, &QPushButton::clicked, [=]() { @@ -513,17 +512,19 @@ void MainWindow::slotVersionUpgrade(const QString& currentVersion, about_dialog->show(); }); statusBar()->addPermanentWidget(update_button, 0); - } else if (currentVersion > latestVersion) { + } else if (version.VersionWithDrawn()) { QMessageBox::warning( - this, _("Unreleased Version"), + this, _("Withdrawn Version"), QString( - _("This version(%1) has not been officially released and is not " - "recommended for use in a production environment.
")) - .arg(currentVersion) + - QString( - _("You can download the latest version(%1) on Github Releases " - "Page.
")) - .arg(latestVersion)); + _("This version(%1) may have been withdrawn by the developer due " + "to serious problems. Please stop using this version " + "immediately and use the latest stable version.")) + .arg(version.current_version.c_str()) + + "
" + + QString(_("You can download the latest stable version(%1) on " + "Github Releases " + "Page.
")) + .arg(version.latest_version.c_str())); } } diff --git a/ui/SendMailDialog.ui b/ui/SendMailDialog.ui index c01c4701..245798da 100644 --- a/ui/SendMailDialog.ui +++ b/ui/SendMailDialog.ui @@ -451,16 +451,6 @@ - - - - false - - - Save Draft - - -