aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSaturneric <[email protected]>2021-07-12 09:03:12 +0000
committerSaturneric <[email protected]>2021-07-12 09:03:12 +0000
commit4ada913c515cf090c65d9d155aa9880a50501591 (patch)
tree72043033991b643a2cce437f22497a961d73a745 /src
parentUpdate Documents; Update UI (diff)
downloadGpgFrontend-4ada913c515cf090c65d9d155aa9880a50501591.tar.gz
GpgFrontend-4ada913c515cf090c65d9d155aa9880a50501591.zip
Project structure adjustment;
Project configuration adjustment; Add version detection; UI interface improvements; Introduce JSON processing library; Update Documents;
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/MainWindow.cpp388
-rw-r--r--src/main.cpp1
-rw-r--r--src/ui/AboutDialog.cpp94
-rw-r--r--src/ui/CMakeLists.txt1
-rw-r--r--src/ui/help/AboutDialog.cpp208
-rw-r--r--src/ui/help/VersionCheckThread.cpp50
-rw-r--r--src/ui/keygen/SubkeyGenerateThread.cpp2
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp42
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp6
-rw-r--r--src/ui/main_window/MainWindowUI.cpp14
-rw-r--r--src/ui/widgets/EditorPage.cpp3
-rw-r--r--src/ui/widgets/FilePage.cpp7
-rw-r--r--src/ui/widgets/TextEdit.cpp7
14 files changed, 526 insertions, 298 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index deeabadb..eadce626 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -44,6 +44,7 @@ add_custom_target(translations DEPENDS ${QON_QM_FILES})
# Set Build Information
configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontend.h @ONLY)
+configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h @ONLY)
# Copy Resource Files
file(COPY ${CMAKE_SOURCE_DIR}/resource/css DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN)
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index eeedad7c..08433da9 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -23,209 +23,223 @@
*/
#include "MainWindow.h"
+#include "ui/help/VersionCheckThread.h"
MainWindow::MainWindow()
- : appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
-
- auto waitingDialog = new WaitingDialog("Loading Gnupg", this);
-
- auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
-
- ctx_thread->start();
-
- while (ctx_thread->isRunning())
- QApplication::processEvents();
-
- waitingDialog->close();
-
-
- if (!mCtx->isGood()) {
- QMessageBox::critical(
- nullptr, tr("ENV Loading Failed"),
- tr("Gnupg is not installed correctly, please follow the ReadME "
- "instructions to install gnupg and then open GPGFrontend."));
- QCoreApplication::quit();
- exit(0);
- }
-
- /* get path were app was started */
- setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
- setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
- qDebug() << "Main Window" << this;
-
- edit = new TextEdit(this);
- setCentralWidget(edit);
-
- /* the list of Keys available*/
- mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
- KeyListColumn::TYPE | KeyListColumn::NAME |
- KeyListColumn::EmailAddress |
- KeyListColumn::Usage | KeyListColumn::Validity,
- this);
- mKeyList->setFilter([](const GpgKey &key) -> bool {
- if (key.revoked || key.disabled || key.expired)
- return false;
- else
- return true;
- });
- mKeyList->slotRefresh();
-
- infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
-
- /* List of binary Attachments */
- attachmentDockCreated = false;
-
- /* Variable containing if restart is needed */
- this->slotSetRestartNeeded(false);
-
- keyMgmt = new KeyMgmt(mCtx, this);
- keyMgmt->hide();
- /* test attachmentdir for files alll 15s */
- auto *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
- timer->start(5000);
-
- createActions();
- createMenus();
- createToolBars();
- createStatusBar();
- createDockWindows();
-
- connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
- SLOT(slotDisableTabActions(int)));
-
- mKeyList->addMenuAction(appendSelectedKeysAct);
- mKeyList->addMenuAction(copyMailAddressToClipboardAct);
- mKeyList->addMenuAction(showKeyDetailsAct);
- mKeyList->addSeparator();
- mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
- mKeyList->addMenuAction(uploadKeyToServerAct);
-
- restoreSettings();
-
- // open filename if provided as first command line parameter
- QStringList args = qApp->arguments();
- if (args.size() > 1) {
- if (!args[1].startsWith("-")) {
- if (QFile::exists(args[1]))
- edit->loadFile(args[1]);
+ : appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ networkAccessManager = new QNetworkAccessManager(this);
+
+ auto waitingDialog = new WaitingDialog("Loading Gnupg", this);
+
+ // Init Gnupg
+ auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
+ ctx_thread->start();
+ while (ctx_thread->isRunning())
+ QApplication::processEvents();
+ waitingDialog->close();
+ ctx_thread->deleteLater();
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = networkAccessManager->get(request);
+
+ auto version_thread = new VersionCheckThread(replay);
+
+ connect(version_thread, SIGNAL(finished(QPrivateSignal)), version_thread, SLOT(deleteLater()));
+ connect(version_thread, SIGNAL(upgradeVersion(const QString &, const QString &)), this, SLOT(slotVersionUpgrade(const QString &, const QString &)));
+
+ version_thread->start();
+
+ // Check Context Status
+ if (!mCtx->isGood()) {
+ QMessageBox::critical(
+ nullptr, tr("ENV Loading Failed"),
+ tr("Gnupg is not installed correctly, please follow the ReadME "
+ "instructions to install gnupg and then open GPGFrontend."));
+ QCoreApplication::quit();
+ exit(0);
+ }
+
+ /* get path were app was started */
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+ edit = new TextEdit(this);
+ setCentralWidget(edit);
+
+ /* the list of Keys available*/
+ mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
+ KeyListColumn::TYPE | KeyListColumn::NAME |
+ KeyListColumn::EmailAddress |
+ KeyListColumn::Usage | KeyListColumn::Validity,
+ this);
+ mKeyList->setFilter([](const GpgKey &key) -> bool {
+ if (key.revoked || key.disabled || key.expired)
+ return false;
+ else
+ return true;
+ });
+ mKeyList->slotRefresh();
+
+ infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
+
+ /* List of binary Attachments */
+ attachmentDockCreated = false;
+
+ /* Variable containing if restart is needed */
+ this->slotSetRestartNeeded(false);
+
+ keyMgmt = new KeyMgmt(mCtx, this);
+ keyMgmt->hide();
+ /* test attachmentdir for files alll 15s */
+ auto *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
+ timer->start(5000);
+
+ createActions();
+ createMenus();
+ createToolBars();
+ createStatusBar();
+ createDockWindows();
+
+ connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
+ SLOT(slotDisableTabActions(int)));
+
+ mKeyList->addMenuAction(appendSelectedKeysAct);
+ mKeyList->addMenuAction(copyMailAddressToClipboardAct);
+ mKeyList->addMenuAction(showKeyDetailsAct);
+ mKeyList->addSeparator();
+ mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
+ mKeyList->addMenuAction(uploadKeyToServerAct);
+
+ restoreSettings();
+
+ // open filename if provided as first command line parameter
+ QStringList args = qApp->arguments();
+ if (args.size() > 1) {
+ if (!args[1].startsWith("-")) {
+ if (QFile::exists(args[1]))
+ edit->loadFile(args[1]);
+ }
+ }
+ edit->curTextPage()->setFocus();
+ this->setMinimumSize(1200, 700);
+ this->setWindowTitle(qApp->applicationName());
+ this->show();
+
+ // Show wizard, if the don't show wizard message box wasn't checked
+ // and keylist doesn't contain a private key
+ qDebug() << "wizard/showWizard"
+ << settings.value("wizard/showWizard", true).toBool();
+ qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
+ if (settings.value("wizard/showWizard", true).toBool() ||
+ !settings.value("wizard/nextPage").isNull()) {
+ slotStartWizard();
}
- }
- edit->curTextPage()->setFocus();
- this->setMinimumSize(1200, 700);
- this->setWindowTitle(qApp->applicationName());
- this->show();
-
- // Show wizard, if the don't show wizard message box wasn't checked
- // and keylist doesn't contain a private key
- qDebug() << "wizard/showWizard"
- << settings.value("wizard/showWizard", true).toBool();
- qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
- if (settings.value("wizard/showWizard", true).toBool() ||
- !settings.value("wizard/nextPage").isNull()) {
- slotStartWizard();
- }
}
void MainWindow::restoreSettings() {
- // state sets pos & size of dock-widgets
- this->restoreState(settings.value("window/windowState").toByteArray());
-
- // Restore window size & location
- if (settings.value("window/windowSave").toBool()) {
- QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
- QSize size = settings.value("window/size", QSize(800, 450)).toSize();
- this->resize(size);
- this->move(pos);
- } else {
- this->resize(QSize(800, 450));
- this->move(QPoint(100, 100));
- }
-
- // Iconsize
- QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
- this->setIconSize(iconSize);
-
- importButton->setIconSize(iconSize);
- fileEncButton->setIconSize(iconSize);
- // set list of keyserver if not defined
- QStringList *keyServerDefaultList;
- keyServerDefaultList = new QStringList("http://keys.gnupg.net");
- keyServerDefaultList->append("https://keyserver.ubuntu.com");
- keyServerDefaultList->append("http://pool.sks-keyservers.net");
-
- QStringList keyServerList =
- settings.value("keyserver/keyServerList", *keyServerDefaultList)
- .toStringList();
- settings.setValue("keyserver/keyServerList", keyServerList);
-
- // set default keyserver, if it's not set
- QString defaultKeyServer = settings
- .value("keyserver/defaultKeyServer",
- QString("https://keyserver.ubuntu.com"))
- .toString();
- settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
-
- // Iconstyle
- Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
- settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
- .toUInt());
- this->setToolButtonStyle(buttonStyle);
- importButton->setToolButtonStyle(buttonStyle);
- fileEncButton->setToolButtonStyle(buttonStyle);
-
- // Checked Keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList keyIds =
- settings.value("keys/savedCheckedKeyList").toStringList();
- mKeyList->setChecked(&keyIds);
- }
+ // state sets pos & size of dock-widgets
+ this->restoreState(settings.value("window/windowState").toByteArray());
+
+ // Restore window size & location
+ if (settings.value("window/windowSave").toBool()) {
+ QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
+ QSize size = settings.value("window/size", QSize(800, 450)).toSize();
+ this->resize(size);
+ this->move(pos);
+ } else {
+ this->resize(QSize(800, 450));
+ this->move(QPoint(100, 100));
+ }
+
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ this->setIconSize(iconSize);
+
+ importButton->setIconSize(iconSize);
+ fileEncButton->setIconSize(iconSize);
+ // set list of keyserver if not defined
+ QStringList *keyServerDefaultList;
+ keyServerDefaultList = new QStringList("http://keys.gnupg.net");
+ keyServerDefaultList->append("https://keyserver.ubuntu.com");
+ keyServerDefaultList->append("http://pool.sks-keyservers.net");
+
+ QStringList keyServerList =
+ settings.value("keyserver/keyServerList", *keyServerDefaultList)
+ .toStringList();
+ settings.setValue("keyserver/keyServerList", keyServerList);
+
+ // set default keyserver, if it's not set
+ QString defaultKeyServer = settings
+ .value("keyserver/defaultKeyServer",
+ QString("https://keyserver.ubuntu.com"))
+ .toString();
+ settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
+
+ // Iconstyle
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
+ settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
+ .toUInt());
+ this->setToolButtonStyle(buttonStyle);
+ importButton->setToolButtonStyle(buttonStyle);
+ fileEncButton->setToolButtonStyle(buttonStyle);
+
+ // Checked Keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList keyIds =
+ settings.value("keys/savedCheckedKeyList").toStringList();
+ mKeyList->setChecked(&keyIds);
+ }
}
void MainWindow::saveSettings() {
- // window position and size
- settings.setValue("window/windowState", saveState());
- settings.setValue("window/pos", pos());
- settings.setValue("window/size", size());
-
- // keyid-list of private checked keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList *keyIds = mKeyList->getChecked();
- if (!keyIds->isEmpty()) {
- settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ // window position and size
+ settings.setValue("window/windowState", saveState());
+ settings.setValue("window/pos", pos());
+ settings.setValue("window/size", size());
+
+ // keyid-list of private checked keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList *keyIds = mKeyList->getChecked();
+ if (!keyIds->isEmpty()) {
+ settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ } else {
+ settings.setValue("keys/savedCheckedKeyList", "");
+ }
} else {
- settings.setValue("keys/savedCheckedKeyList", "");
+ settings.remove("keys/savedCheckedKeyList");
}
- } else {
- settings.remove("keys/savedCheckedKeyList");
- }
}
void MainWindow::closeAttachmentDock() {
- if (!attachmentDockCreated) {
- return;
- }
- attachmentDock->close();
- attachmentDock->deleteLater();
- attachmentDockCreated = false;
+ if (!attachmentDockCreated) {
+ return;
+ }
+ attachmentDock->close();
+ attachmentDock->deleteLater();
+ attachmentDockCreated = false;
}
void MainWindow::closeEvent(QCloseEvent *event) {
- /*
- * ask to save changes, if there are
- * modified documents in any tab
- */
- if (edit->maybeSaveAnyTab()) {
- saveSettings();
- event->accept();
- } else {
- event->ignore();
- }
-
- // clear password from memory
- mCtx->clearPasswordCache();
+ /*
+ * ask to save changes, if there are
+ * modified documents in any tab
+ */
+ if (edit->maybeSaveAnyTab()) {
+ saveSettings();
+ event->accept();
+ } else {
+ event->ignore();
+ }
+
+ // clear password from memory
+ mCtx->clearPasswordCache();
}
diff --git a/src/main.cpp b/src/main.cpp
index 00ab2738..3e14a425 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@
*/
#include "MainWindow.h"
+#include "GpgFrontendBuildInfo.h"
int main(int argc, char *argv[]) {
diff --git a/src/ui/AboutDialog.cpp b/src/ui/AboutDialog.cpp
deleted file mode 100644
index e51f225d..00000000
--- a/src/ui/AboutDialog.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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 <https://www.gnu.org/licenses/>.
- *
- * 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<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AboutDialog.h"
-
-AboutDialog::AboutDialog(QWidget *parent)
- : QDialog(parent) {
- this->setWindowTitle(tr("About ") + qApp->applicationName());
-
- auto *tabWidget = new QTabWidget;
- auto *infoTab = new InfoTab;
- auto *translatorsTab = new TranslatorsTab;
-
- tabWidget->addTab(infoTab, tr("General"));
- tabWidget->addTab(translatorsTab, tr("Translators"));
-
- auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(tabWidget);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-
- this->exec();
-}
-
-InfoTab::InfoTab(QWidget *parent)
- : QWidget(parent) {
- auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
- auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
- + "<center><b>" + qApp->applicationVersion() + "</b></center>"
- + "<center>" + GIT_VERSION + "</center>"
- + tr("<br><center>GPGFrontend is an easy-to-use, compact, <br>"
- "cross-platform, and installation-free gpg front-end tool.<br>"
- "It visualizes most of the common operations of gpg commands.<br>"
- "It's licensed under the GPL v3<br><br>"
- "<b>Developer:</b><br>"
- "Saturneric<br><br>"
- "If you have any questions or suggestions, raise an issue<br/>"
- "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
- tr("<br><br> Built with Qt ") + qVersion()
- + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
- tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
-
- auto *layout = new QGridLayout();
- auto *pixmapLabel = new QLabel();
- pixmapLabel->setPixmap(*pixmap);
- layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
- auto *aboutLabel = new QLabel();
- aboutLabel->setText(*text);
- aboutLabel->setOpenExternalLinks(true);
- layout->addWidget(aboutLabel, 1, 0, 1, -1);
- layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
- QSizePolicy::Fixed), 2, 1, 1, 1);
-
- setLayout(layout);
-}
-
-TranslatorsTab::TranslatorsTab(QWidget *parent)
- : QWidget(parent) {
- QFile translatorsFile;
- translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
- translatorsFile.open(QIODevice::ReadOnly);
- QByteArray inBuffer = translatorsFile.readAll();
-
- auto *label = new QLabel(inBuffer);
- auto *mainLayout = new QVBoxLayout(this);
- mainLayout->addWidget(label);
-
- setLayout(mainLayout);
-}
-
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 68f57b81..618b5d28 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,6 +3,7 @@ aux_source_directory(./keypair_details UI_SOURCE)
aux_source_directory(./widgets UI_SOURCE)
aux_source_directory(./keygen UI_SOURCE)
aux_source_directory(./main_window UI_SOURCE)
+aux_source_directory(./help UI_SOURCE)
add_library(gpgfrontend-ui STATIC ${UI_SOURCE})
diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp
new file mode 100644
index 00000000..4c9b54c9
--- /dev/null
+++ b/src/ui/help/AboutDialog.cpp
@@ -0,0 +1,208 @@
+/**
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ * 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<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/help/AboutDialog.h"
+#include "GpgFrontendBuildInfo.h"
+
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+AboutDialog::AboutDialog(int defaultIndex, QWidget *parent)
+ : QDialog(parent) {
+ this->setWindowTitle(tr("About ") + qApp->applicationName());
+
+ auto *tabWidget = new QTabWidget;
+ auto *infoTab = new InfoTab();
+ auto *translatorsTab = new TranslatorsTab();
+ auto *updateTab = new UpdateTab();
+
+ tabWidget->addTab(infoTab, tr("General"));
+ tabWidget->addTab(translatorsTab, tr("Translators"));
+ tabWidget->addTab(updateTab, tr("Update"));
+
+ connect(tabWidget, &QTabWidget::currentChanged, this, [&](int index) {
+ qDebug() << "Current Index" << index;
+ if(index == 2) {
+ updateTab->getLatestVersion();
+ }
+ });
+
+ if(defaultIndex < tabWidget->count() && defaultIndex >= 0) {
+ tabWidget->setCurrentIndex(defaultIndex);
+ }
+
+ auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ this->exec();
+}
+
+InfoTab::InfoTab(QWidget *parent)
+ : QWidget(parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
+ + "<center><b>" + qApp->applicationVersion() + "</b></center>"
+ + "<center>" + GIT_VERSION + "</center>"
+ + tr("<br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>"
+ "and installation-free gpg front-end tool.<br>"
+ "It visualizes most of the common operations of gpg commands.<br>"
+ "It's licensed under the GPL v3<br><br>"
+ "<b>Developer:</b><br>"
+ "Saturneric<br><br>"
+ "If you have any questions or suggestions, raise an issue<br/>"
+ "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
+ tr("<br><br> Built with Qt ") + qVersion()
+ + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
+ tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
+
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ auto *aboutLabel = new QLabel();
+ aboutLabel->setText(*text);
+ aboutLabel->setOpenExternalLinks(true);
+ layout->addWidget(aboutLabel, 1, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+TranslatorsTab::TranslatorsTab(QWidget *parent)
+ : QWidget(parent) {
+ QFile translatorsFile;
+ translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
+ translatorsFile.open(QIODevice::ReadOnly);
+ QByteArray inBuffer = translatorsFile.readAll();
+
+ auto *label = new QLabel(inBuffer);
+ auto *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(label);
+
+ setLayout(mainLayout);
+}
+
+UpdateTab::UpdateTab(QWidget *parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+
+ currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ auto tipsLabel = new QLabel();
+ tipsLabel->setText("<center>" +
+ tr("It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.") +
+ "</center><br><center>" +
+ tr("New versions not only represent new features, but also often represent functional and security fixes.") + "</center>");
+ tipsLabel->setWordWrap(true);
+
+ currentVersionLabel = new QLabel();
+ currentVersionLabel->setText("<center>" + tr("Current Version: ") + "<b>" + currentVersion + "</b></center>");
+ currentVersionLabel->setWordWrap(true);
+
+ latestVersionLabel = new QLabel();
+ latestVersionLabel->setWordWrap(true);
+
+ upgradeLabel = new QLabel();
+ upgradeLabel->setText("<center>" +
+ tr("The current version is inconsistent with the latest version on github.") +
+ "</center><br><center>" +
+ tr("Please click <a href=\"https://github.com/saturneric/GpgFrontend/releases\">here</a> to download the latest version.") + "</center>");
+ upgradeLabel->setWordWrap(true);
+ upgradeLabel->setOpenExternalLinks(true);
+ upgradeLabel->setHidden(true);
+
+ pb = new QProgressBar();
+ pb->setRange(0, 0);
+ pb->setTextVisible(false);
+
+ layout->addWidget(tipsLabel, 1, 0, 1, -1);
+ layout->addWidget(currentVersionLabel, 2, 0, 1, -1);
+ layout->addWidget(latestVersionLabel, 3, 0, 1, -1);
+ layout->addWidget(upgradeLabel, 4, 0, 1, -1);
+ layout->addWidget(pb, 5, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+void UpdateTab::getLatestVersion() {
+
+ this->pb->setHidden(false);
+
+ qDebug() << "Try to get latest version";
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ auto manager = new QNetworkAccessManager(this);
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = manager->get(request);
+
+ while(replay->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ this->pb->setHidden(true);
+
+ QByteArray bytes = replay->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = "Unknown";
+ }
+
+ latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>");
+
+ if(latestVersion > currentVersion) {
+ upgradeLabel->setHidden(false);
+ }
+
+}
diff --git a/src/ui/help/VersionCheckThread.cpp b/src/ui/help/VersionCheckThread.cpp
new file mode 100644
index 00000000..7bd0eb8f
--- /dev/null
+++ b/src/ui/help/VersionCheckThread.cpp
@@ -0,0 +1,50 @@
+//
+// Created by Administrator on 2021/7/12.
+//
+
+#include "ui/help/VersionCheckThread.h"
+#include "GpgFrontendBuildInfo.h"
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+void VersionCheckThread::run() {
+ qDebug() << "Start Version Thread to get latest version from Github";
+
+ auto currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ while(mNetworkReply->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ QByteArray bytes = mNetworkReply->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = currentVersion;
+ qDebug() << "Latest Version Unknown" << latestVersion;
+ }
+
+ if(latestVersion != currentVersion) {
+ emit upgradeVersion(currentVersion, latestVersion);
+ }
+
+}
+
+VersionCheckThread::VersionCheckThread(QNetworkReply *networkReply):mNetworkReply(networkReply) {
+
+}
diff --git a/src/ui/keygen/SubkeyGenerateThread.cpp b/src/ui/keygen/SubkeyGenerateThread.cpp
index 4f19ac1f..125f35f8 100644
--- a/src/ui/keygen/SubkeyGenerateThread.cpp
+++ b/src/ui/keygen/SubkeyGenerateThread.cpp
@@ -24,8 +24,6 @@
#include "ui/keygen/SubkeyGenerateThread.h"
-#include <utility>
-
SubkeyGenerateThread::SubkeyGenerateThread(GpgKey key, GenKeyInfo *keyGenParams, GpgME::GpgContext *ctx)
: mKey(std::move(key)), keyGenParams(keyGenParams) , mCtx(ctx) {
connect(this, &SubkeyGenerateThread::finished, this, &SubkeyGenerateThread::deleteLater);
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 21d0af0d..0bddb9b2 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -58,7 +58,7 @@ void MainWindow::slotEncrypt() {
auto thread = QThread::create([&]() {
error = mCtx->encrypt(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &result);
});
-
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Encrypting"), this);
@@ -122,6 +122,7 @@ void MainWindow::slotSign() {
auto thread = QThread::create([&]() {
error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Signing"), this);
@@ -165,6 +166,7 @@ void MainWindow::slotDecrypt() {
// try decrypt, if fail do nothing, especially don't replace text
error = mCtx->decrypt(text, decrypted, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Decrypting"), this);
@@ -224,6 +226,7 @@ void MainWindow::slotVerify() {
auto thread = QThread::create([&]() {
error = mCtx->verify(&text, nullptr, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Verifying"), this);
@@ -312,6 +315,7 @@ void MainWindow::slotEncryptSign() {
error = mCtx->encryptSign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &encr_result,
&sign_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
@@ -364,6 +368,7 @@ void MainWindow::slotDecryptVerify() {
auto thread = QThread::create([&]() {
error = mCtx->decryptVerify(text, decrypted, &d_result, &v_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
WaitingDialog *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
@@ -516,6 +521,7 @@ void MainWindow::slotFileEncrypt() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Encrypting"), this);
@@ -524,7 +530,7 @@ void MainWindow::slotFileEncrypt() {
}
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyse = new EncryptResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -596,6 +602,7 @@ void MainWindow::slotFileDecrypt() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog("Decrypting", this);
@@ -605,7 +612,7 @@ void MainWindow::slotFileDecrypt() {
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyse = new DecryptResultAnalyse(mCtx, error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -691,6 +698,7 @@ void MainWindow::slotFileSign() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Signing"), this);
@@ -700,7 +708,7 @@ void MainWindow::slotFileSign() {
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyse = new SignResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
@@ -775,6 +783,7 @@ void MainWindow::slotFileVerify() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
auto *dialog = new WaitingDialog(tr("Verifying"), this);
@@ -894,6 +903,7 @@ void MainWindow::slotFileEncryptSign() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
WaitingDialog *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
@@ -902,7 +912,7 @@ void MainWindow::slotFileEncryptSign() {
}
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyseEncr = new EncryptResultAnalyse(error, encr_result);
auto resultAnalyseSign = new SignResultAnalyse(error, sign_result);
@@ -970,15 +980,17 @@ void MainWindow::slotFileDecryptVerify() {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
+
auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
while (thread->isRunning()) {
QApplication::processEvents();
}
dialog->close();
- if(!if_error) {
+ if (!if_error) {
infoBoard->associateFileTreeView(edit->curFilePage());
auto resultAnalyseDecrypt = new DecryptResultAnalyse(mCtx, error, d_result);
@@ -1036,3 +1048,21 @@ void MainWindow::slotFileVerifyCustom() {
void MainWindow::slotOpenFile(QString &path) {
edit->slotOpenFile(path);
}
+
+void MainWindow::slotVersionUpgrade(const QString &currentVersion, const QString &latestVersion) {
+ if(currentVersion < latestVersion) {
+ QMessageBox::warning(this,
+ tr("Outdated Version"),
+ tr("This version(%1) is out of date, please update the latest version in time. ").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ } else if(currentVersion > latestVersion) {
+ QMessageBox::warning(this,
+ tr("Unreleased Version"),
+ tr("This version(%1) has not been officially released and is not recommended for use in a production environment. <br/>").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ }
+}
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index 189ead53..d95a9bfe 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -25,7 +25,11 @@
#include "MainWindow.h"
void MainWindow::slotAbout() {
- new AboutDialog(this);
+ new AboutDialog(0, this);
+}
+
+void MainWindow::slotCheckUpdate() {
+ new AboutDialog(2, this);
}
void MainWindow::slotSetStatusBarText(const QString &text) {
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 01c9fdde..0f7f1040 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -209,18 +209,27 @@ void MainWindow::createActions() {
importKeyFromEditAct->setToolTip(tr("Import New Key From Editor"));
connect(importKeyFromEditAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromEdit()));
- openKeyManagementAct = new QAction(tr("Manage &keys"), this);
+ openKeyManagementAct = new QAction(tr("Manage &Keys"), this);
openKeyManagementAct->setIcon(QIcon(":keymgmt.png"));
openKeyManagementAct->setToolTip(tr("Open Keymanagement"));
connect(openKeyManagementAct, SIGNAL(triggered()), this, SLOT(slotOpenKeyManagement()));
- /* About Menu
+ /*
+ * About Menu
*/
aboutAct = new QAction(tr("&About"), this);
aboutAct->setIcon(QIcon(":help.png"));
aboutAct->setToolTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout()));
+ /*
+ * Check Update Menu
+ */
+ checkUpdateAct = new QAction(tr("&Check for Updates"), this);
+ checkUpdateAct->setIcon(QIcon(":help.png"));
+ checkUpdateAct->setToolTip(tr("Check for updates"));
+ connect(checkUpdateAct, SIGNAL(triggered()), this, SLOT(slotCheckUpdate()));
+
startWizardAct = new QAction(tr("Open &Wizard"), this);
startWizardAct->setToolTip(tr("Open the wizard"));
connect(startWizardAct, SIGNAL(triggered()), this, SLOT(slotStartWizard()));
@@ -340,6 +349,7 @@ void MainWindow::createMenus() {
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(startWizardAct);
helpMenu->addSeparator();
+ helpMenu->addAction(checkUpdateAct);
helpMenu->addAction(aboutAct);
}
diff --git a/src/ui/widgets/EditorPage.cpp b/src/ui/widgets/EditorPage.cpp
index 8a51b721..05d5cbea 100644
--- a/src/ui/widgets/EditorPage.cpp
+++ b/src/ui/widgets/EditorPage.cpp
@@ -42,6 +42,9 @@ EditorPage::EditorPage(QString filePath, QWidget *parent) : QWidget(parent),
setAttribute(Qt::WA_DeleteOnClose);
textPage->setFocus();
+ // Front in same width
+ this->setFont({"Courier"});
+
connect(textPage, SIGNAL(textChanged()), this, SLOT(formatGpgHeader()));
}
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index e330eb68..65755509 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -50,11 +50,15 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
upLevelButton = new QPushButton();
connect(upLevelButton, SIGNAL(clicked(bool)), this, SLOT(slotUpLevel()));
+ QString buttonStyle = "QPushButton{border:none;background-color:rgba(255, 255, 255,100);}";
+
+
auto upPixmap = QPixmap(":up.png");
upPixmap = upPixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QIcon upButtonIcon(upPixmap);
upLevelButton->setIcon(upButtonIcon);
upLevelButton->setIconSize(upPixmap.rect().size());
+ upLevelButton->setStyleSheet(buttonStyle);
refreshButton = new QPushButton("Refresh");
connect(refreshButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
@@ -67,6 +71,7 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
QIcon updateButtonIcon(updatePixmap);
goPathButton->setIcon(updateButtonIcon);
goPathButton->setIconSize(updatePixmap.rect().size());
+ goPathButton->setStyleSheet(buttonStyle);
pathEdit = new QLineEdit();
pathEdit->setText(dirModel->rootPath());
@@ -75,7 +80,7 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
menuLayout->addWidget(upLevelButton);
menuLayout->setStretchFactor(upLevelButton, 1);
menuLayout->addWidget(pathEdit);
- menuLayout->setStretchFactor(pathEdit, 8);
+ menuLayout->setStretchFactor(pathEdit, 10);
menuLayout->addWidget(goPathButton);
menuLayout->setStretchFactor(goPathButton, 1);
// menuLayout->addWidget(refreshButton);
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index f06b3a45..c9968565 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -37,9 +37,6 @@ TextEdit::TextEdit(QWidget *parent) : QWidget(parent) {
layout->setSpacing(0);
setLayout(layout);
- // Front in same width
- this->setFont({"Courier"});
-
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
SLOT(removeTab(int)));
connect(this, &TextEdit::insertTargetTextPage, this,
@@ -73,7 +70,7 @@ void TextEdit::slotNewHelpTab(const QString &title, const QString &path) const {
void TextEdit::slotNewFileTab() const {
auto *page = new FilePage(qobject_cast<QWidget *>(parent()));
- tabWidget->addTab(page, "[File Browser]");
+ tabWidget->addTab(page, "[Browser]");
tabWidget->setCurrentIndex(tabWidget->count() - 1);
connect(page, SIGNAL(pathChanged(const QString &)), this,
SLOT(slotFilePagePathChanged(const QString &)));
@@ -646,7 +643,7 @@ void TextEdit::slotFilePagePathChanged(const QString &path) {
} else {
mPath = tPath;
}
- mPath.prepend("[File Browser] ");
+ mPath.prepend("[Browser] ");
mPath.append("/");
tabWidget->setTabText(index, mPath);
}