aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-01-26 18:17:20 +0000
committersaturneric <[email protected]>2025-01-26 18:18:10 +0000
commit92e1ed7b3fd5360278d41db087518b6c5af80b3e (patch)
tree577edfa58889d97a0b3ec1f2c045b9d6fe9cff70
parentfix: 'std::future' is defined in header '<future>' (diff)
downloadGpgFrontend-92e1ed7b3fd5360278d41db087518b6c5af80b3e.tar.gz
GpgFrontend-92e1ed7b3fd5360278d41db087518b6c5af80b3e.zip
feat: allow file batch operations
-rw-r--r--gpgfrontend.qrc1
-rw-r--r--resource/lfs/icons/batch.pngbin0 -> 5761 bytes
-rw-r--r--src/core/function/gpg/GpgFileOpera.cpp4
-rw-r--r--src/core/function/gpg/GpgFileOpera.h4
-rw-r--r--src/core/function/result_analyse/GpgResultAnalyse.h4
-rw-r--r--src/ui/UISignalStation.h2
-rw-r--r--src/ui/UserInterfaceUtils.cpp37
-rw-r--r--src/ui/UserInterfaceUtils.h13
-rw-r--r--src/ui/dialog/WaitingDialog.cpp17
-rw-r--r--src/ui/dialog/WaitingDialog.h23
-rw-r--r--src/ui/main_window/MainWindow.cpp2
-rw-r--r--src/ui/main_window/MainWindow.h189
-rw-r--r--src/ui/main_window/MainWindowFileSlotFunction.cpp1590
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp84
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp54
-rw-r--r--src/ui/struct/GpgOperaResult.h44
-rw-r--r--src/ui/struct/GpgOperaResultContext.h115
-rw-r--r--src/ui/widgets/FilePage.cpp93
-rw-r--r--src/ui/widgets/FilePage.h20
-rw-r--r--src/ui/widgets/FileTreeView.cpp61
-rw-r--r--src/ui/widgets/FileTreeView.h12
-rw-r--r--src/ui/widgets/TextEditTabWidget.cpp4
-rw-r--r--ui/FilePage.ui32
23 files changed, 1434 insertions, 971 deletions
diff --git a/gpgfrontend.qrc b/gpgfrontend.qrc
index 51f5b2b7..d82a47fa 100644
--- a/gpgfrontend.qrc
+++ b/gpgfrontend.qrc
@@ -108,6 +108,7 @@
<file alias="export-email.png">resource/lfs/icons/export-email.png</file>
<file alias="warning-filling.png">resource/lfs/icons/warning-filling.png</file>
<file alias="upgrade.png">resource/lfs/icons/upgrade.png</file>
+ <file alias="batch.png">resource/lfs/icons/batch.png</file>
</qresource>
<qresource prefix="/test/key">
<file alias="pv1.key">resource/lfs/test/data/pv1.key</file>
diff --git a/resource/lfs/icons/batch.png b/resource/lfs/icons/batch.png
new file mode 100644
index 00000000..ac3e77bd
--- /dev/null
+++ b/resource/lfs/icons/batch.png
Binary files differ
diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp
index 9dea413d..0a321b14 100644
--- a/src/core/function/gpg/GpgFileOpera.cpp
+++ b/src/core/function/gpg/GpgFileOpera.cpp
@@ -521,7 +521,7 @@ auto GpgFileOpera::EncryptFileSymmetricSync(const QString& in_path, bool ascii,
"gpgme_op_encrypt_symmetric", "2.1.0");
}
-void GpgFileOpera::EncryptDerectorySymmetric(const QString& in_path, bool ascii,
+void GpgFileOpera::EncryptDirectorySymmetric(const QString& in_path, bool ascii,
const QString& out_path,
const GpgOperationCallback& cb) {
auto ex = std::make_shared<GFDataExchanger>(kDataExchangerSize);
@@ -548,7 +548,7 @@ void GpgFileOpera::EncryptDerectorySymmetric(const QString& in_path, bool ascii,
});
}
-auto GpgFileOpera::EncryptDerectorySymmetricSync(
+auto GpgFileOpera::EncryptDirectorySymmetricSync(
const QString& in_path, bool ascii,
const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> {
auto ex = std::make_shared<GFDataExchanger>(kDataExchangerSize);
diff --git a/src/core/function/gpg/GpgFileOpera.h b/src/core/function/gpg/GpgFileOpera.h
index 939ddc2d..8bb08567 100644
--- a/src/core/function/gpg/GpgFileOpera.h
+++ b/src/core/function/gpg/GpgFileOpera.h
@@ -123,7 +123,7 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param out_path
* @param cb
*/
- void EncryptDerectorySymmetric(const QString& in_path, bool ascii,
+ void EncryptDirectorySymmetric(const QString& in_path, bool ascii,
const QString& out_path,
const GpgOperationCallback& cb);
@@ -134,7 +134,7 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera
* @param ascii
* @param out_path
*/
- auto EncryptDerectorySymmetricSync(const QString& in_path, bool ascii,
+ auto EncryptDirectorySymmetricSync(const QString& in_path, bool ascii,
const QString& out_path)
-> std::tuple<GpgError, DataObjectPtr>;
diff --git a/src/core/function/result_analyse/GpgResultAnalyse.h b/src/core/function/result_analyse/GpgResultAnalyse.h
index ce47764c..fa84ddb4 100644
--- a/src/core/function/result_analyse/GpgResultAnalyse.h
+++ b/src/core/function/result_analyse/GpgResultAnalyse.h
@@ -27,10 +27,6 @@
*/
#pragma once
-#include <sstream>
-
-#include "core/typedef/GpgTypedef.h"
-
namespace GpgFrontend {
class GPGFRONTEND_CORE_EXPORT GpgResultAnalyse : public QObject {
diff --git a/src/ui/UISignalStation.h b/src/ui/UISignalStation.h
index d89ef91b..dfafca93 100644
--- a/src/ui/UISignalStation.h
+++ b/src/ui/UISignalStation.h
@@ -75,7 +75,7 @@ class UISignalStation : public QObject {
* @brief
*
*/
- void SignalMainWindowlUpdateBasicalOperaMenu(unsigned int);
+ void SignalMainWindowUpdateBasicOperaMenu(unsigned int);
/**
* @brief
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index 33d72d8d..ea5bb3d9 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -216,6 +216,41 @@ void CommonUtils::WaitForOpera(QWidget *parent,
looper.exec();
}
+void CommonUtils::WaitForMultipleOperas(
+ QWidget *parent, const QString &waiting_dialog_title,
+ const QContainer<OperaWaitingCb> &operas) {
+ QEventLoop looper;
+ QPointer<WaitingDialog> const dialog =
+ new WaitingDialog(waiting_dialog_title, true, parent);
+ connect(dialog, &QDialog::finished, &looper, &QEventLoop::quit);
+ connect(dialog, &QDialog::finished, dialog, &QDialog::deleteLater);
+ dialog->show();
+
+ std::atomic<int> remaining_tasks(static_cast<int>(operas.size()));
+ const auto tasks_count = operas.size();
+
+ for (const auto &opera : operas) {
+ QTimer::singleShot(64, parent, [=, &remaining_tasks]() {
+ opera([dialog, &remaining_tasks, tasks_count]() {
+ if (dialog == nullptr) return;
+
+ const auto pg_value =
+ static_cast<double>(tasks_count - remaining_tasks + 1) * 100.0 /
+ static_cast<double>(tasks_count);
+ emit dialog->SignalUpdateValue(static_cast<int>(pg_value));
+ QCoreApplication::processEvents();
+
+ if (--remaining_tasks == 0) {
+ dialog->close();
+ dialog->accept();
+ }
+ });
+ });
+ }
+
+ looper.exec();
+}
+
void CommonUtils::RaiseMessageBox(QWidget *parent, GpgError err) {
GpgErrorDesc desc = DescribeGpgErrCode(err);
GpgErrorCode err_code = CheckGpgError2ErrCode(err);
@@ -326,7 +361,7 @@ void CommonUtils::SlotExecuteGpgCommand(
const QStringList &arguments,
const std::function<void(QProcess *)> &interact_func) {
QEventLoop looper;
- auto *dialog = new WaitingDialog(tr("Processing"), nullptr);
+ auto *dialog = new WaitingDialog(tr("Processing"), false);
dialog->show();
auto *gpg_process = new QProcess(&looper);
gpg_process->setProcessChannelMode(QProcess::MergedChannels);
diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h
index 6aae75ba..81de99ed 100644
--- a/src/ui/UserInterfaceUtils.h
+++ b/src/ui/UserInterfaceUtils.h
@@ -44,7 +44,7 @@ class InfoBoardWidget;
class TextEdit;
using OperaWaitingHd = std::function<void()>;
-using OperaWaitingCb = const std::function<void(OperaWaitingHd)>;
+using OperaWaitingCb = std::function<void(OperaWaitingHd)>;
/**
* @brief
@@ -116,6 +116,17 @@ class CommonUtils : public QWidget {
/**
* @brief
*
+ * @param parent
+ * @param waiting_dialog_title
+ * @param operas
+ */
+ static void WaitForMultipleOperas(QWidget* parent,
+ const QString& waiting_dialog_title,
+ const QContainer<OperaWaitingCb>& operas);
+
+ /**
+ * @brief
+ *
* @param err
*/
static void RaiseMessageBox(QWidget* parent, GpgError err);
diff --git a/src/ui/dialog/WaitingDialog.cpp b/src/ui/dialog/WaitingDialog.cpp
index da620ebf..6fdd3a70 100644
--- a/src/ui/dialog/WaitingDialog.cpp
+++ b/src/ui/dialog/WaitingDialog.cpp
@@ -32,15 +32,14 @@
namespace GpgFrontend::UI {
-WaitingDialog::WaitingDialog(const QString& title, QWidget* parent)
- : GeneralDialog("WaitingDialog", parent) {
- auto* pb = new QProgressBar();
- pb->setRange(0, 0);
- pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
- pb->setTextVisible(false);
+WaitingDialog::WaitingDialog(const QString& title, bool range, QWidget* parent)
+ : GeneralDialog("WaitingDialog", parent), pb_(new QProgressBar()) {
+ pb_->setRange(0, range ? 100 : 0);
+ pb_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb_->setTextVisible(false);
auto* layout = new QVBoxLayout();
- layout->addWidget(pb);
+ layout->addWidget(pb_);
this->setLayout(layout);
this->setModal(true);
@@ -50,8 +49,12 @@ WaitingDialog::WaitingDialog(const QString& title, QWidget* parent)
this->setAttribute(Qt::WA_DeleteOnClose);
this->setFixedSize(240, 42);
+ connect(this, &WaitingDialog::SignalUpdateValue, this,
+ &WaitingDialog::SlotUpdateValue);
+
this->movePosition2CenterOfParent();
this->show();
}
+void WaitingDialog::SlotUpdateValue(int value) { pb_->setValue(value); }
} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/WaitingDialog.h b/src/ui/dialog/WaitingDialog.h
index 6b0877fe..1fb9fe17 100644
--- a/src/ui/dialog/WaitingDialog.h
+++ b/src/ui/dialog/WaitingDialog.h
@@ -46,7 +46,28 @@ class WaitingDialog : public GeneralDialog {
* @param title
* @param parent
*/
- WaitingDialog(const QString& title, QWidget* parent);
+ explicit WaitingDialog(const QString& title, bool range,
+ QWidget* parent = nullptr);
+
+ public slots:
+
+ /**
+ * @brief max 100, min 0
+ *
+ */
+ void SlotUpdateValue(int value);
+
+ signals:
+
+ /**
+ * @brief
+ *
+ * @param value
+ */
+ void SignalUpdateValue(int value);
+
+ private:
+ QProgressBar* pb_;
};
} // namespace GpgFrontend::UI
diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp
index d191e268..f9d5d8be 100644
--- a/src/ui/main_window/MainWindow.cpp
+++ b/src/ui/main_window/MainWindow.cpp
@@ -104,7 +104,7 @@ void MainWindow::Init() noexcept {
statusBar()->showMessage(message, timeout);
});
connect(UISignalStation::GetInstance(),
- &UISignalStation::SignalMainWindowlUpdateBasicalOperaMenu, this,
+ &UISignalStation::SignalMainWindowUpdateBasicOperaMenu, this,
&MainWindow::SlotUpdateCryptoMenuStatus);
connect(UISignalStation::GetInstance(),
&UISignalStation::SignalMainWindowOpenFile, this,
diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h
index f397b755..357a3ed5 100644
--- a/src/ui/main_window/MainWindow.h
+++ b/src/ui/main_window/MainWindow.h
@@ -28,7 +28,10 @@
#pragma once
+#include "core/typedef/CoreTypedef.h"
+#include "core/typedef/GpgTypedef.h"
#include "ui/main_window/GeneralMainWindow.h"
+#include "ui/struct/GpgOperaResult.h"
namespace GpgFrontend {
class GpgPassphraseContext;
@@ -41,6 +44,8 @@ namespace GpgFrontend::UI {
class KeyList;
class TextEdit;
class InfoBoardWidget;
+struct GpgOperaContext;
+struct GpgOperaContexts;
/**
* @brief
@@ -209,41 +214,28 @@ class MainWindow : public GeneralMainWindow {
/**
* @details Open dialog for encrypting file.
*/
- void SlotFileEncrypt(const QString&);
-
- /**
- * @brief
- *
- */
- void SlotDirectoryEncrypt(const QString&);
-
- /**
- * @brief
- *
- * @param path
- */
- void SlotFileDecrypt(const QString& path);
+ void SlotFileEncrypt(const QContainer<QString>& paths);
/**
* @brief
*
* @param path
*/
- void SlotArchiveDecrypt(const QString& path);
+ void SlotFileDecrypt(const QContainer<QString>& paths);
/**
* @brief
*
* @param path
*/
- void SlotFileSign(const QString& path);
+ void SlotFileSign(const QContainer<QString>& paths);
/**
* @brief
*
* @param path
*/
- void SlotFileVerify(const QString& path);
+ void SlotFileVerify(const QContainer<QString>& paths);
/**
* @brief
@@ -257,28 +249,14 @@ class MainWindow : public GeneralMainWindow {
*
* @param path
*/
- void SlotFileEncryptSign(const QString& path);
+ void SlotFileEncryptSign(const QContainer<QString>& paths);
/**
* @brief
*
* @param path
*/
- void SlotDirectoryEncryptSign(const QString& path);
-
- /**
- * @brief
- *
- * @param path
- */
- void SlotFileDecryptVerify(const QString& path);
-
- /**
- * @brief
- *
- * @param path
- */
- void SlotArchiveDecryptVerify(const QString& path);
+ void SlotFileDecryptVerify(const QContainer<QString>& paths);
/**
* @details get value of member restartNeeded to needed.
@@ -498,6 +476,14 @@ class MainWindow : public GeneralMainWindow {
/**
* @brief
*
+ * @param opera_results
+ */
+ void slot_result_analyse_show_helper(
+ const QContainer<GpgOperaResult>& opera_results);
+
+ /**
+ * @brief
+ *
* @param result_analyse
*/
void slot_eml_verify_show_helper(const QString& email_info,
@@ -611,6 +597,135 @@ class MainWindow : public GeneralMainWindow {
*/
auto handle_module_error(QMap<QString, QString> p) -> bool;
+ /**
+ * @brief
+ *
+ * @param paths
+ * @return true
+ * @return false
+ */
+ auto check_read_file_paths_helper(const QContainer<QString>& paths) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param paths
+ * @return true
+ * @return false
+ */
+ auto check_write_file_paths_helper(const QContainer<QString>& paths) -> bool;
+
+ /**
+ * @brief
+ *
+ * @param key_ids
+ * @param capability_check
+ * @param capability_err_string
+ * @return GpgKeyList
+ */
+ auto check_keys_helper(
+ const KeyIdArgsList& key_ids,
+ const std::function<bool(const GpgKey&)>& capability_check,
+ const QString& capability_err_string) -> GpgKeyList;
+
+ /**
+ * @brief
+ *
+ * @param context
+ * @return auto
+ */
+ auto execute_operas_helper(const QString& task,
+ const QSharedPointer<GpgOperaContexts>& contexts);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_symmetric_encrypt(
+ QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_encrypt(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_directory_symmetric_encrypt(
+ QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_directory_encrypt(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_decrypt(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_archive_decrypt(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_sign(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_verify(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_encrypt_sign(QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_directory_encrypt_sign(
+ QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_file_decrypt_verify(
+ QSharedPointer<GpgOperaContext>& context);
+
+ /**
+ * @brief
+ *
+ * @param context
+ */
+ void build_operas_archive_decrypt_verify(
+ QSharedPointer<GpgOperaContext>& context);
+
TextEdit* edit_{}; ///< Tabwidget holding the edit-windows
QMenu* file_menu_{}; ///< Submenu for file-operations
QMenu* edit_menu_{}; ///< Submenu for text-operations
@@ -651,8 +766,8 @@ class MainWindow : public GeneralMainWindow {
QAction* sign_act_{}; ///< Action to sign text
QAction* verify_act_{}; ///< Action to verify text
QAction* import_key_from_edit_act_{}; ///< Action to import key from edit
- QAction* clean_double_line_breaks_act_{}; ///< Action to remove double line
- ///< breaks
+ QAction* clean_double_line_breaks_act_{}; ///< Action to remove double
+ ///< line breaks
QAction* gnupg_controller_open_act_{}; ///<
QAction* module_controller_open_act_{}; ///<
@@ -660,8 +775,8 @@ class MainWindow : public GeneralMainWindow {
QAction* reload_components_act_{}; ///<
QAction* restart_components_act_{}; ///<
- QAction*
- append_selected_keys_act_{}; ///< Action to append selected keys to edit
+ QAction* append_selected_keys_act_{}; ///< Action to append selected keys
+ ///< to edit
QAction* append_key_fingerprint_to_editor_act_{}; ///<
QAction* append_key_create_date_to_editor_act_{}; ///<
QAction* append_key_expire_date_to_editor_act_{}; ///<
diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp
index e2fe86bd..bfda5a8b 100644
--- a/src/ui/main_window/MainWindowFileSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp
@@ -39,589 +39,747 @@
#include "core/utils/IOUtils.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/dialog/SignersPicker.h"
+#include "ui/struct/GpgOperaResult.h"
+#include "ui/struct/GpgOperaResultContext.h"
#include "ui/widgets/KeyList.h"
namespace GpgFrontend::UI {
-void MainWindow::SlotFileEncrypt(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Cannot read from file: %1").arg(QFileInfo(path).fileName()));
- return;
+auto MainWindow::check_read_file_paths_helper(const QContainer<QString>& paths)
+ -> bool {
+ QStringList invalid_files;
+ for (const auto& path : paths) {
+ auto result = TargetFilePreCheck(path, true);
+ if (!std::get<0>(result)) {
+ invalid_files.append(path);
+ }
}
- bool const non_ascii_at_file_operation =
- GlobalSettingStation::GetInstance()
- .GetSettings()
- .value("gnupg/non_ascii_at_file_operation", true)
- .toBool();
- auto out_path =
- SetExtensionOfOutputFile(path, kENCRYPT, !non_ascii_at_file_operation);
+ if (!invalid_files.empty()) {
+ QString error_file_names;
+ for (const auto& file_path : invalid_files) {
+ error_file_names += QFileInfo(file_path).fileName() + "\n";
+ }
+
+ QMessageBox::critical(this, tr("Error"),
+ tr("Cannot read from the following files:\n\n%1")
+ .arg(error_file_names.trimmed()));
+ return false;
+ }
- if (QFile::exists(out_path)) {
- auto out_file_name = tr("The target file %1 already exists, "
- "do you need to overwrite it?")
- .arg(out_path);
- auto ret = QMessageBox::warning(this, tr("Warning"), out_file_name,
- QMessageBox::Ok | QMessageBox::Cancel);
+ return true;
+}
- if (ret == QMessageBox::Cancel) return;
+auto MainWindow::check_write_file_paths_helper(
+ const QContainer<QString>& o_paths) -> bool {
+ for (const auto& o_path : o_paths) {
+ if (QFile::exists(o_path)) {
+ auto out_file_name = tr("The target file %1 already exists, "
+ "do you need to overwrite it?")
+ .arg(QFileInfo(o_path).fileName());
+ auto ret = QMessageBox::warning(this, tr("Warning"), out_file_name,
+ QMessageBox::Ok | QMessageBox::Cancel);
+
+ if (ret == QMessageBox::Cancel) return false;
+ }
}
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
+ QStringList invalid_output_files;
+ for (const auto& path : o_paths) {
+ auto result = TargetFilePreCheck(path, false);
+ if (!std::get<0>(result)) {
+ invalid_output_files.append(path);
+ }
}
- // check selected keys
- auto key_ids = m_key_list_->GetChecked();
- if (key_ids.empty()) {
- // Symmetric Encrypt
- auto ret = QMessageBox::information(
- this, tr("Symmetric Encryption"),
- tr("No Key Selected. Do you want to encrypt with a "
- "symmetric cipher using a passphrase?"),
- QMessageBox::Ok | QMessageBox::Cancel);
- if (ret == QMessageBox::Cancel) return;
+ if (!invalid_output_files.empty()) {
+ QString error_file_names;
+ for (const auto& file_path : invalid_output_files) {
+ error_file_names += QFileInfo(file_path).fileName() + "\n";
+ }
- CommonUtils::WaitForOpera(
- this, tr("Symmetrically Encrypting"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptFileSymmetric(
- path, !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
+ QMessageBox::critical(this, tr("Error"),
+ tr("Cannot write to the following files:\n\n%1")
+ .arg(error_file_names.trimmed()));
+ return false;
+ }
- return;
+ return true;
+}
+
+auto MainWindow::check_keys_helper(
+ const KeyIdArgsList& key_ids,
+ const std::function<bool(const GpgKey&)>& capability_check,
+ const QString& capability_err_string) -> GpgKeyList {
+ if (key_ids.empty()) {
+ QMessageBox::critical(
+ this, tr("No Key Checked"),
+ tr("Please check the key in the key toolbox on the right."));
+ return {};
}
- auto p_keys =
+ auto keys =
GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
.GetKeys(key_ids);
- assert(std::all_of(p_keys.begin(), p_keys.end(),
+ assert(std::all_of(keys.begin(), keys.end(),
[](const auto& key) { return key.IsGood(); }));
// check key abilities
- for (const auto& key : p_keys) {
- bool const key_can_encrypt = key.IsHasActualEncryptionCapability();
-
- if (!key_can_encrypt) {
- QMessageBox::critical(
- nullptr, tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for encryption.") +
- "<br/><br/>" + tr("For example the Following Key:") + " <br/>" +
- key.GetUIDs()->front().GetUID());
- return;
+ for (const auto& key : keys) {
+ if (!capability_check(key)) {
+ QMessageBox::critical(nullptr, tr("Invalid KeyPair"),
+ capability_err_string + "<br/><br/>" +
+ tr("For example the Following Key:") +
+ " <br/>" + key.GetUIDs()->front().GetUID());
+ return {};
}
}
- CommonUtils::WaitForOpera(
- this, tr("Encrypting"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptFile(
- {p_keys.begin(), p_keys.end()}, path,
- !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err, result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
+ return keys;
}
-void MainWindow::SlotDirectoryEncrypt(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Cannot read from file: %1").arg(QFileInfo(path).fileName()));
- return;
+auto MainWindow::execute_operas_helper(
+ const QString& task, const QSharedPointer<GpgOperaContexts>& contexts) {
+ CommonUtils::WaitForMultipleOperas(this, task, contexts->operas);
+ slot_result_analyse_show_helper(contexts->opera_results);
+}
+
+void MainWindow::build_operas_file_symmetric_encrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptFileSymmetric(
+ path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
+
+void MainWindow::build_operas_file_encrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptFile(
+ context->keys, path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
+ }
+}
+
+void MainWindow::build_operas_directory_symmetric_encrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptDirectorySymmetric(
+ path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
+ }
+}
+
+void MainWindow::build_operas_directory_encrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptDirectory(
+ context->keys, path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
+ }
+}
+
+void MainWindow::SlotFileEncrypt(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
bool const non_ascii_at_file_operation =
GlobalSettingStation::GetInstance()
.GetSettings()
.value("gnupg/non_ascii_at_file_operation", true)
.toBool();
- auto out_path = SetExtensionOfOutputFileForArchive(
- path, kENCRYPT, !non_ascii_at_file_operation);
- if (QFile::exists(out_path)) {
- auto out_file_name = tr("The target file %1 already exists, "
- "do you need to overwrite it?")
- .arg(out_path);
- auto ret = QMessageBox::warning(this, tr("Warning"), out_file_name,
- QMessageBox::Ok | QMessageBox::Cancel);
+ contexts->ascii = !non_ascii_at_file_operation;
- if (ret == QMessageBox::Cancel) return;
- }
-
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
-
- // check selected keys
+ bool is_symmetric = false;
auto key_ids = m_key_list_->GetChecked();
- // symmetric encrypt
- if (key_ids.empty()) {
+
+ // Symmetric Encrypt
+ if (key_ids.isEmpty()) {
auto ret = QMessageBox::information(
this, tr("Symmetric Encryption"),
tr("No Key Selected. Do you want to encrypt with a "
"symmetric cipher using a passphrase?"),
QMessageBox::Ok | QMessageBox::Cancel);
if (ret == QMessageBox::Cancel) return;
-
- CommonUtils::WaitForOpera(
- this, tr("Archiving & Symmetrically Encrypting"),
- [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptDerectorySymmetric(
- path, !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
-
- return;
+ is_symmetric = true;
+ } else {
+ contexts->keys = check_keys_helper(
+ key_ids,
+ [](const GpgKey& key) { return key.IsHasActualEncryptionCapability(); },
+ tr("The selected keypair cannot be used for encryption."));
+ if (contexts->keys.empty()) return;
+ }
+
+ if (!check_read_file_paths_helper(paths)) return;
+
+ for (const auto& path : paths) {
+ QFileInfo info(path);
+ if (info.isDir()) {
+ contexts->GetContextPath(1).append(path);
+ contexts->GetContextOutPath(1).append(
+ SetExtensionOfOutputFileForArchive(path, kENCRYPT, contexts->ascii));
+ } else {
+ contexts->GetContextPath(0).append(path);
+ contexts->GetContextOutPath(0).append(
+ SetExtensionOfOutputFile(path, kENCRYPT, contexts->ascii));
+ }
}
- auto p_keys =
- GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .GetKeys(key_ids);
- assert(std::all_of(p_keys.begin(), p_keys.end(),
- [](const auto& key) { return key.IsGood(); }));
+ if (!check_write_file_paths_helper(contexts->GetAllOutPath())) return;
- // check key abilities
- for (const auto& key : p_keys) {
- bool const key_can_encrypt = key.IsHasActualEncryptionCapability();
-
- if (!key_can_encrypt) {
- QMessageBox::critical(
- nullptr, tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for encryption.") +
- "<br/><br/>" + tr("For example the Following Key:") + " <br/>" +
- key.GetUIDs()->front().GetUID());
- return;
+ // Symmetric Encrypt
+ if (is_symmetric) {
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_symmetric_encrypt(f_context);
+
+ auto d_context = contexts->GetContext(1);
+ if (d_context != nullptr) {
+ build_operas_directory_symmetric_encrypt(d_context);
}
+ } else {
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_encrypt(f_context);
+
+ auto d_context = contexts->GetContext(1);
+ if (d_context != nullptr) build_operas_directory_encrypt(d_context);
}
- CommonUtils::WaitForOpera(
- this, tr("Archiving & Encrypting"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptDirectory(
- {p_keys.begin(), p_keys.end()}, path,
- !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err, result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
+ execute_operas_helper(tr("Encrypting"), contexts);
}
-void MainWindow::SlotFileDecrypt(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Cannot read from file: %1").arg(QFileInfo(path).fileName()));
- return;
+/**
+ * @brief
+ *
+ * @param context
+ */
+void MainWindow::build_operas_file_decrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .DecryptFile(
+ path, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgDecryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgDecryptResult>(data_obj, 0);
+ auto result_analyse = GpgDecryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- auto out_path = SetExtensionOfOutputFile(path, kDECRYPT, true);
- if (QFileInfo(out_path).exists()) {
- auto ret = QMessageBox::warning(
- this, tr("Warning"),
- tr("The target file already exists, do you need to overwrite it?"),
- QMessageBox::Ok | QMessageBox::Cancel);
-
- if (ret == QMessageBox::Cancel) return;
+void MainWindow::build_operas_archive_decrypt(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .DecryptArchive(
+ path, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgDecryptResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgDecryptResult>(data_obj, 0);
+ auto result_analyse = GpgDecryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+void MainWindow::SlotFileDecrypt(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
- CommonUtils::WaitForOpera(
- this, tr("Decrypting"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .DecryptFile(
- path, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgDecryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgDecryptResult>(data_obj, 0);
- auto result_analyse = GpgDecryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err, result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
-}
+ contexts->ascii = true;
-void MainWindow::SlotArchiveDecrypt(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot read from file: %1").arg(path));
- return;
- }
+ if (!check_read_file_paths_helper(paths)) return;
- auto out_path = SetExtensionOfOutputFileForArchive(path, kDECRYPT, true);
- if (QFileInfo(out_path).exists()) {
- auto ret = QMessageBox::warning(
- this, tr("Warning"),
- tr("The target file already exists, do you need to overwrite it?"),
- QMessageBox::Ok | QMessageBox::Cancel);
+ for (const auto& path : paths) {
+ QFileInfo info(path);
+ const auto extension = info.completeSuffix();
- if (ret == QMessageBox::Cancel) return;
+ if (extension == "tar.gpg" || extension == "tar.asc") {
+ contexts->GetContextPath(1).append(path);
+ contexts->GetContextOutPath(1).append(
+ SetExtensionOfOutputFileForArchive(path, kDECRYPT, contexts->ascii));
+ } else {
+ contexts->GetContextPath(0).append(path);
+ contexts->GetContextOutPath(0).append(
+ SetExtensionOfOutputFile(path, kDECRYPT, contexts->ascii));
+ }
}
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+ if (!check_write_file_paths_helper(contexts->GetAllOutPath())) return;
- CommonUtils::WaitForOpera(
- this, tr("Decrypting & Extrating"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .DecryptArchive(
- path, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgDecryptResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgDecryptResult>(data_obj, 0);
- auto result_analyse = GpgDecryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err, result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
-}
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_decrypt(f_context);
-void MainWindow::SlotFileSign(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Cannot read from file: %1").arg(QFileInfo(path).fileName()));
- return;
+ auto d_context = contexts->GetContext(1);
+ if (d_context != nullptr) {
+ build_operas_archive_decrypt(d_context);
}
- auto key_ids = m_key_list_->GetChecked();
- auto keys =
- GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .GetKeys(key_ids);
- assert(std::all_of(keys.begin(), keys.end(),
- [](const auto& key) { return key.IsGood(); }));
+ execute_operas_helper(tr("Decrypting"), contexts);
+}
- if (keys.empty()) {
- QMessageBox::critical(
- this, tr("No Key Checked"),
- tr("Please check the key in the key toolbox on the right."));
- return;
+void MainWindow::build_operas_file_sign(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .SignFile(
+ context->keys, path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr || !data_obj->Check<GpgSignResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgSignResult>(data_obj, 0);
+ auto result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ opera_results.append({result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- for (const auto& key : keys) {
- if (!key.IsHasActualSigningCapability()) {
- QMessageBox::information(
- this, tr("Invalid Operation"),
- tr("The selected key contains a key that does not actually "
- "have a sign usage.") +
- "<br/><br/>" + tr("for example the Following Key:") + " <br/>" +
- key.GetUIDs()->front().GetUID());
- return;
- }
- }
+void MainWindow::SlotFileSign(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
bool const non_ascii_at_file_operation =
GlobalSettingStation::GetInstance()
.GetSettings()
.value("gnupg/non_ascii_at_file_operation", true)
.toBool();
- auto sig_file_path =
- SetExtensionOfOutputFile(path, kSIGN, !non_ascii_at_file_operation);
- if (QFileInfo(sig_file_path).exists()) {
- auto ret = QMessageBox::warning(this, tr("Warning"),
- tr("The signature file \"%1\" exists, "
- "do you need to overwrite it?")
- .arg(sig_file_path),
- QMessageBox::Ok | QMessageBox::Cancel);
+ contexts->ascii = !non_ascii_at_file_operation;
- if (ret == QMessageBox::Cancel) return;
+ auto key_ids = m_key_list_->GetChecked();
+
+ contexts->keys = check_keys_helper(
+ key_ids,
+ [](const GpgKey& key) { return key.IsHasActualSigningCapability(); },
+ tr("The selected key contains a key that does not actually have a sign "
+ "usage."));
+ if (contexts->keys.empty()) return;
+
+ if (!check_read_file_paths_helper(paths)) return;
+
+ for (const auto& path : paths) {
+ QFileInfo info(path);
+ contexts->GetContextPath(0).append(path);
+ contexts->GetContextOutPath(0).append(
+ SetExtensionOfOutputFile(path, kSIGN, contexts->ascii));
}
- CommonUtils::WaitForOpera(
- this, tr("Signing"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .SignFile({keys.begin(), keys.end()}, path,
- !non_ascii_at_file_operation, sig_file_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgSignResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgSignResult>(data_obj, 0);
- auto result_analyse = GpgSignResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
- this->slot_refresh_current_file_view();
- });
- });
+ if (!check_write_file_paths_helper(contexts->GetAllOutPath())) return;
+
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_sign(f_context);
+
+ execute_operas_helper(tr("Signing"), contexts);
}
-void MainWindow::SlotFileVerify(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Cannot read from file: %1").arg(QFileInfo(path).fileName()));
- return;
+void MainWindow::build_operas_file_verify(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .VerifyFile(
+ o_path, path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgVerifyResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+
+ auto result = ExtractParams<GpgVerifyResult>(data_obj, 0);
+ auto result_analyse = GpgVerifyResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err, result);
+ result_analyse.Analyse();
+
+ slot_result_analyse_show_helper(result_analyse);
+
+ if (!result_analyse.GetUnknownSignatures().isEmpty() &&
+ Module::IsModuleActivate(kKeyServerSyncModuleID)) {
+ slot_verifying_unknown_signature_helper(result_analyse);
+ }
+
+ opera_results.append(
+ {result_analyse.GetStatus(),
+ result_analyse.GetResultReport(),
+ QFileInfo(path.isEmpty() ? o_path : path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- auto file_info = QFileInfo(path);
- QString sign_file_path = path;
- QString data_file_path;
+void MainWindow::SlotFileVerify(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
- bool const prossible_singleton_target =
- file_info.suffix() == "gpg" || file_info.suffix() == "pgp";
- if (prossible_singleton_target) {
- swap(data_file_path, sign_file_path);
- } else {
- data_file_path = file_info.path() + "/" + file_info.completeBaseName();
- }
+ if (!check_read_file_paths_helper(paths)) return;
- auto data_file_info = QFileInfo(data_file_path);
- if (!prossible_singleton_target && !data_file_info.exists()) {
- bool ok;
- QString const text = QInputDialog::getText(
- this, tr("File to be Verified"),
- tr("Please provide An ABSOLUTE Path \n"
- "If Data And Signature is COMBINED within a single file, "
- "KEEP THIS EMPTY: "),
- QLineEdit::Normal, data_file_path, &ok);
+ for (const auto& path : paths) {
+ QFileInfo info(path);
- if (!ok) return;
+ QString sign_file_path = path;
+ QString data_file_path;
- data_file_path = text.isEmpty() ? data_file_path : text;
- data_file_info = QFileInfo(data_file_path);
- }
+ bool const possible_singleton_target =
+ info.suffix() == "gpg" || info.suffix() == "pgp";
+ if (possible_singleton_target) {
+ swap(data_file_path, sign_file_path);
+ } else {
+ data_file_path = info.path() + "/" + info.completeBaseName();
+ }
- if (!data_file_info.isFile() ||
- (!sign_file_path.isEmpty() && !QFileInfo(sign_file_path).isFile())) {
- QMessageBox::critical(
- this, tr("Error"),
- tr("Please select the appropriate origin file or signature file. "
- "Ensure that both are in this directory."));
- return;
- }
+ auto data_file_info = QFileInfo(data_file_path);
+ if (!possible_singleton_target && !data_file_info.exists()) {
+ bool ok;
+ QString const text = QInputDialog::getText(
+ this, tr("File to be Verified"),
+ tr("Please provide An ABSOLUTE Path \n"
+ "If Data And Signature is COMBINED within a single file, "
+ "KEEP THIS EMPTY: "),
+ QLineEdit::Normal, data_file_path, &ok);
- CommonUtils::WaitForOpera(
- this, tr("Verifying"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .VerifyFile(
- data_file_path, sign_file_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgVerifyResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
-
- auto result = ExtractParams<GpgVerifyResult>(data_obj, 0);
- auto result_analyse = GpgVerifyResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err, result);
- result_analyse.Analyse();
-
- slot_result_analyse_show_helper(result_analyse);
-
- if (!result_analyse.GetUnknownSignatures().isEmpty() &&
- Module::IsModuleActivate(kKeyServerSyncModuleID)) {
- slot_verifying_unknown_signature_helper(result_analyse);
- }
-
- this->slot_refresh_current_file_view();
- });
- });
-}
+ if (!ok) return;
-void MainWindow::SlotFileEncryptSign(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot read from file: %1").arg(path));
- return;
+ data_file_path = text.isEmpty() ? data_file_path : text;
+ data_file_info = QFileInfo(data_file_path);
+ }
+
+ contexts->GetContextPath(0).append(sign_file_path);
+ contexts->GetContextOutPath(0).append(data_file_path);
}
- // check selected keys
- auto key_ids = m_key_list_->GetChecked();
- auto p_keys =
- GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .GetKeys(key_ids);
- assert(std::all_of(p_keys.begin(), p_keys.end(),
- [](const auto& key) { return key.IsGood(); }));
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_verify(f_context);
- if (p_keys.empty()) {
- QMessageBox::critical(
- this, tr("No Key Checked"),
- tr("Please check the key in the key toolbox on the right."));
- return;
+ execute_operas_helper(tr("Verifying"), contexts);
+}
+
+void MainWindow::build_operas_file_encrypt_sign(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptSignFile(
+ context->keys, context->singer_keys, path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult, GpgSignResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+ auto encrypt_result =
+ ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto sign_result = ExtractParams<GpgSignResult>(data_obj, 1);
+
+ auto encrypt_result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ encrypt_result);
+ encrypt_result_analyse.Analyse();
+
+ auto sign_result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ sign_result);
+ sign_result_analyse.Analyse();
+
+ opera_results.append(
+ {std::min(encrypt_result_analyse.GetStatus(),
+ sign_result_analyse.GetStatus()),
+ encrypt_result_analyse.GetResultReport() +
+ sign_result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- // check key abilities
- for (const auto& key : p_keys) {
- bool const key_can_encrypt = key.IsHasActualEncryptionCapability();
-
- if (!key_can_encrypt) {
- QMessageBox::critical(
- nullptr, tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for encryption.") +
- "<br/><br/>" + tr("For example the Following Key:") + " <br/>" +
- key.GetUIDs()->front().GetUID());
- return;
- }
+void MainWindow::build_operas_directory_encrypt_sign(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .EncryptSignDirectory(
+ context->keys, context->singer_keys, path, context->ascii, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgEncryptResult, GpgSignResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+ auto encrypt_result =
+ ExtractParams<GpgEncryptResult>(data_obj, 0);
+ auto sign_result = ExtractParams<GpgSignResult>(data_obj, 1);
+
+ auto encrypt_result_analyse = GpgEncryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ encrypt_result);
+ encrypt_result_analyse.Analyse();
+
+ auto sign_result_analyse = GpgSignResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ sign_result);
+ sign_result_analyse.Analyse();
+
+ opera_results.append(
+ {std::min(encrypt_result_analyse.GetStatus(),
+ sign_result_analyse.GetStatus()),
+ encrypt_result_analyse.GetResultReport() +
+ sign_result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
+
+void MainWindow::SlotFileEncryptSign(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
bool const non_ascii_at_file_operation =
GlobalSettingStation::GetInstance()
.GetSettings()
.value("gnupg/non_ascii_at_file_operation", true)
.toBool();
- auto out_path = SetExtensionOfOutputFile(path, kENCRYPT_SIGN,
- !non_ascii_at_file_operation);
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+ contexts->ascii = !non_ascii_at_file_operation;
- if (QFile::exists(out_path)) {
- auto ret = QMessageBox::warning(
- this, tr("Warning"),
- tr("The target file already exists, do you need to overwrite it?"),
- QMessageBox::Ok | QMessageBox::Cancel);
+ auto key_ids = m_key_list_->GetChecked();
- if (ret == QMessageBox::Cancel) return;
- }
+ contexts->keys = check_keys_helper(
+ key_ids,
+ [](const GpgKey& key) { return key.IsHasActualEncryptionCapability(); },
+ tr("The selected keypair cannot be used for encryption."));
+ if (contexts->keys.empty()) return;
auto* signers_picker =
new SignersPicker(m_key_list_->GetCurrentGpgContextChannel(), this);
@@ -633,350 +791,190 @@ void MainWindow::SlotFileEncryptSign(const QString& path) {
if (!signers_picker->GetStatus()) return;
auto signer_key_ids = signers_picker->GetCheckedSigners();
- auto p_signer_keys =
+ auto signer_keys =
GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
.GetKeys(signer_key_ids);
- assert(std::all_of(p_signer_keys.begin(), p_signer_keys.end(),
+ assert(std::all_of(signer_keys.begin(), signer_keys.end(),
[](const auto& key) { return key.IsGood(); }));
- CommonUtils::WaitForOpera(
- this, tr("Encrypting and Signing"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptSignFile(
- {p_keys.begin(), p_keys.end()},
- {p_signer_keys.begin(), p_signer_keys.end()}, path,
- !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult, GpgSignResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
- auto encrypt_result =
- ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto sign_result = ExtractParams<GpgSignResult>(data_obj, 1);
-
- auto encrypt_result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- encrypt_result);
- encrypt_result_analyse.Analyse();
-
- auto sign_result_analyse = GpgSignResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- sign_result);
- sign_result_analyse.Analyse();
-
- slot_result_analyse_show_helper(encrypt_result_analyse,
- sign_result_analyse);
-
- this->slot_refresh_current_file_view();
- });
- });
-}
+ contexts->singer_keys = signer_keys;
-void MainWindow::SlotDirectoryEncryptSign(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot read from file: %1").arg(path));
- return;
- }
+ if (!check_read_file_paths_helper(paths)) return;
- // check selected keys
- auto key_ids = m_key_list_->GetChecked();
- auto p_keys =
- GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .GetKeys(key_ids);
- assert(std::all_of(p_keys.begin(), p_keys.end(),
- [](const auto& key) { return key.IsGood(); }));
-
- if (p_keys.empty()) {
- QMessageBox::critical(
- this, tr("No Key Checked"),
- tr("Please check the key in the key toolbox on the right."));
- return;
- }
-
- // check key abilities
- for (const auto& key : p_keys) {
- bool const key_can_encrypt = key.IsHasActualEncryptionCapability();
-
- if (!key_can_encrypt) {
- QMessageBox::critical(
- nullptr, tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for encryption.") +
- "<br/><br/>" + tr("For example the Following Key:") + " <br/>" +
- key.GetUIDs()->front().GetUID());
- return;
+ for (const auto& path : paths) {
+ QFileInfo info(path);
+ if (info.isDir()) {
+ contexts->GetContextPath(1).append(path);
+ contexts->GetContextOutPath(1).append(
+ SetExtensionOfOutputFileForArchive(path, kENCRYPT, contexts->ascii));
+ } else {
+ contexts->GetContextPath(0).append(path);
+ contexts->GetContextOutPath(0).append(
+ SetExtensionOfOutputFile(path, kENCRYPT, contexts->ascii));
}
}
- bool const non_ascii_at_file_operation =
- GlobalSettingStation::GetInstance()
- .GetSettings()
- .value("gnupg/non_ascii_at_file_operation", true)
- .toBool();
- auto out_path = SetExtensionOfOutputFileForArchive(
- path, kENCRYPT_SIGN, !non_ascii_at_file_operation);
-
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+ if (!check_write_file_paths_helper(contexts->GetAllOutPath())) return;
- if (QFile::exists(out_path)) {
- auto ret = QMessageBox::warning(
- this, tr("Warning"),
- tr("The target file already exists, do you need to overwrite it?"),
- QMessageBox::Ok | QMessageBox::Cancel);
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_encrypt_sign(f_context);
- if (ret == QMessageBox::Cancel) return;
- }
-
- auto* signers_picker =
- new SignersPicker(m_key_list_->GetCurrentGpgContextChannel(), this);
- QEventLoop loop;
- connect(signers_picker, &SignersPicker::finished, &loop, &QEventLoop::quit);
- loop.exec();
+ auto d_context = contexts->GetContext(1);
+ if (d_context != nullptr) build_operas_directory_encrypt_sign(d_context);
- // return when canceled
- if (!signers_picker->GetStatus()) return;
+ execute_operas_helper(tr("Encrypting and Signing"), contexts);
+}
- auto signer_key_ids = signers_picker->GetCheckedSigners();
- auto p_signer_keys =
- GpgKeyGetter::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .GetKeys(signer_key_ids);
-#ifndef NDEBUG
- for (const auto& key : p_signer_keys) {
- assert(key.IsGood());
+void MainWindow::build_operas_file_decrypt_verify(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .DecryptVerifyFile(
+ path, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgDecryptResult, GpgVerifyResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+ auto decrypt_result =
+ ExtractParams<GpgDecryptResult>(data_obj, 0);
+ auto verify_result =
+ ExtractParams<GpgVerifyResult>(data_obj, 1);
+
+ auto decrypt_result_analyse = GpgDecryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ decrypt_result);
+ decrypt_result_analyse.Analyse();
+
+ auto verify_result_analyse = GpgVerifyResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ verify_result);
+ verify_result_analyse.Analyse();
+
+ opera_results.append(
+ {std::min(decrypt_result_analyse.GetStatus(),
+ verify_result_analyse.GetStatus()),
+ decrypt_result_analyse.GetResultReport() +
+ verify_result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+
+ if (!verify_result_analyse.GetUnknownSignatures().isEmpty() &&
+ Module::IsModuleActivate(kKeyServerSyncModuleID)) {
+ slot_verifying_unknown_signature_helper(
+ verify_result_analyse);
+ }
+ });
+ };
+
+ context->operas.push_back(opera);
}
-#endif
-
- CommonUtils::WaitForOpera(
- this, tr("Archiving & Encrypting & Signing"),
- [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .EncryptSignDirectory(
- {p_keys.begin(), p_keys.end()},
- {p_signer_keys.begin(), p_signer_keys.end()}, path,
- !non_ascii_at_file_operation, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgEncryptResult, GpgSignResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
- auto encrypt_result =
- ExtractParams<GpgEncryptResult>(data_obj, 0);
- auto sign_result = ExtractParams<GpgSignResult>(data_obj, 1);
-
- auto encrypt_result_analyse = GpgEncryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- encrypt_result);
- encrypt_result_analyse.Analyse();
-
- auto sign_result_analyse = GpgSignResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- sign_result);
- sign_result_analyse.Analyse();
-
- slot_result_analyse_show_helper(encrypt_result_analyse,
- sign_result_analyse);
-
- this->slot_refresh_current_file_view();
- });
- });
}
-void MainWindow::SlotFileDecryptVerify(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot read from file: %1").arg(path));
- return;
+void MainWindow::build_operas_archive_decrypt_verify(
+ QSharedPointer<GpgOperaContext>& context) {
+ assert(context->paths.size() == context->o_paths.size());
+
+ for (int i = 0; i < context->paths.size(); i++) {
+ const auto& path = context->paths[i];
+ const auto& o_path = context->o_paths[i];
+
+ auto opera = [=, &opera_results =
+ context->opera_results](const OperaWaitingHd& op_hd) {
+ GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
+ .DecryptVerifyArchive(
+ path, o_path,
+ [=, &opera_results](GpgError err, const DataObjectPtr& data_obj) {
+ // stop waiting
+ op_hd();
+
+ if (CheckGpgError(err) == GPG_ERR_USER_1 ||
+ data_obj == nullptr ||
+ !data_obj->Check<GpgDecryptResult, GpgVerifyResult>()) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Unknown error occurred"));
+ return;
+ }
+ auto decrypt_result =
+ ExtractParams<GpgDecryptResult>(data_obj, 0);
+ auto verify_result =
+ ExtractParams<GpgVerifyResult>(data_obj, 1);
+
+ auto decrypt_result_analyse = GpgDecryptResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ decrypt_result);
+ decrypt_result_analyse.Analyse();
+
+ auto verify_result_analyse = GpgVerifyResultAnalyse(
+ m_key_list_->GetCurrentGpgContextChannel(), err,
+ verify_result);
+ verify_result_analyse.Analyse();
+
+ opera_results.append(
+ {std::min(decrypt_result_analyse.GetStatus(),
+ verify_result_analyse.GetStatus()),
+ decrypt_result_analyse.GetResultReport() +
+ verify_result_analyse.GetResultReport(),
+ QFileInfo(path).fileName()});
+
+ if (!verify_result_analyse.GetUnknownSignatures().isEmpty() &&
+ Module::IsModuleActivate(kKeyServerSyncModuleID)) {
+ slot_verifying_unknown_signature_helper(
+ verify_result_analyse);
+ }
+ });
+ };
+
+ context->operas.push_back(opera);
}
+}
- auto out_path = SetExtensionOfOutputFile(path, kDECRYPT_VERIFY, true);
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+void MainWindow::SlotFileDecryptVerify(const QContainer<QString>& paths) {
+ auto contexts = QSharedPointer<GpgOperaContexts>::create();
- if (QFile::exists(out_path)) {
- auto ret = QMessageBox::warning(this, tr("Warning"),
- tr("The output file %1 already exists, do "
- "you need to overwrite it?")
- .arg(out_path),
- QMessageBox::Ok | QMessageBox::Cancel);
+ contexts->ascii = true;
- if (ret == QMessageBox::Cancel) return;
- }
+ if (!check_read_file_paths_helper(paths)) return;
- CommonUtils::WaitForOpera(
- this, tr("Decrypting and Verifying"), [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .DecryptVerifyFile(
- path, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgDecryptResult, GpgVerifyResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
- auto decrypt_result =
- ExtractParams<GpgDecryptResult>(data_obj, 0);
- auto verify_result =
- ExtractParams<GpgVerifyResult>(data_obj, 1);
-
- auto decrypt_result_analyse = GpgDecryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- decrypt_result);
- decrypt_result_analyse.Analyse();
-
- auto verify_result_analyse = GpgVerifyResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- verify_result);
- verify_result_analyse.Analyse();
-
- slot_result_analyse_show_helper(decrypt_result_analyse,
- verify_result_analyse);
-
- this->slot_refresh_current_file_view();
-
- if (!verify_result_analyse.GetUnknownSignatures().isEmpty() &&
- Module::IsModuleActivate(kKeyServerSyncModuleID)) {
- LOG_D() << "try to sync missing key info from server"
- << verify_result_analyse.GetUnknownSignatures();
-
- QString fingerprint_list;
- for (const auto& fingerprint :
- verify_result_analyse.GetUnknownSignatures()) {
- fingerprint_list += fingerprint + "\n";
- }
-
- // Interaction with user
- auto user_response = QMessageBox::question(
- this, tr("Missing Keys"),
- tr("Some signatures cannot be verified because the "
- "corresponding keys are missing.\n\n"
- "The following fingerprints are missing:\n%1\n\n"
- "Would you like to fetch these keys from the key "
- "server?")
- .arg(fingerprint_list),
- QMessageBox::Yes | QMessageBox::No);
-
- if (user_response == QMessageBox::Yes) {
- CommonUtils::GetInstance()
- ->ImportKeyByKeyServerSyncModule(
- this, m_key_list_->GetCurrentGpgContextChannel(),
- verify_result_analyse.GetUnknownSignatures());
- } else {
- QMessageBox::information(
- this, tr("Verification Incomplete"),
- tr("Verification was incomplete due to missing "
- "keys. You can manually import the keys later."));
- }
- }
- });
- });
-}
+ for (const auto& path : paths) {
+ QFileInfo info(path);
+ const auto extension = info.completeSuffix();
-void MainWindow::SlotArchiveDecryptVerify(const QString& path) {
- auto check_result = TargetFilePreCheck(path, true);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot read from file: %1").arg(path));
- return;
+ if (extension == "tar.gpg" || extension == "tar.asc") {
+ contexts->GetContextPath(1).append(path);
+ contexts->GetContextOutPath(1).append(
+ SetExtensionOfOutputFileForArchive(path, kDECRYPT, contexts->ascii));
+ } else {
+ contexts->GetContextPath(0).append(path);
+ contexts->GetContextOutPath(0).append(
+ SetExtensionOfOutputFile(path, kDECRYPT, contexts->ascii));
+ }
}
- auto out_path =
- SetExtensionOfOutputFileForArchive(path, kDECRYPT_VERIFY, true);
- check_result = TargetFilePreCheck(out_path, false);
- if (!std::get<0>(check_result)) {
- QMessageBox::critical(this, tr("Error"),
- tr("Cannot write to file: %1").arg(out_path));
- return;
- }
+ if (!check_write_file_paths_helper(contexts->GetAllOutPath())) return;
- if (QFile::exists(out_path)) {
- auto ret = QMessageBox::warning(this, tr("Warning"),
- tr("The output file %1 already exists, do "
- "you need to overwrite it?")
- .arg(out_path),
- QMessageBox::Ok | QMessageBox::Cancel);
+ auto f_context = contexts->GetContext(0);
+ if (f_context != nullptr) build_operas_file_decrypt_verify(f_context);
- if (ret == QMessageBox::Cancel) return;
+ auto d_context = contexts->GetContext(1);
+ if (d_context != nullptr) {
+ build_operas_archive_decrypt_verify(d_context);
}
- CommonUtils::WaitForOpera(
- this, tr("Decrypting & Verifying & Extracting"),
- [=](const OperaWaitingHd& op_hd) {
- GpgFileOpera::GetInstance(m_key_list_->GetCurrentGpgContextChannel())
- .DecryptVerifyArchive(
- path, out_path,
- [=](GpgError err, const DataObjectPtr& data_obj) {
- // stop waiting
- op_hd();
-
- if (CheckGpgError(err) == GPG_ERR_USER_1 ||
- data_obj == nullptr ||
- !data_obj->Check<GpgDecryptResult, GpgVerifyResult>()) {
- QMessageBox::critical(this, tr("Error"),
- tr("Unknown error occurred"));
- return;
- }
- auto decrypt_result =
- ExtractParams<GpgDecryptResult>(data_obj, 0);
- auto verify_result =
- ExtractParams<GpgVerifyResult>(data_obj, 1);
-
- auto decrypt_result_analyse = GpgDecryptResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- decrypt_result);
- decrypt_result_analyse.Analyse();
-
- auto verify_result_analyse = GpgVerifyResultAnalyse(
- m_key_list_->GetCurrentGpgContextChannel(), err,
- verify_result);
- verify_result_analyse.Analyse();
-
- slot_result_analyse_show_helper(decrypt_result_analyse,
- verify_result_analyse);
-
- // pause this feature
- // if (verify_result_analyse.GetStatus() == -2) {
- // import_unknown_key_from_keyserver(this,
- // verify_result_analyse);
- // }
- // pause this feature
- // if (verify_result_analyse.GetStatus() >= 0) {
- // show_verify_details(this, info_board_, err,
- // verify_result);
- // }
-
- this->slot_refresh_current_file_view();
- });
- });
-}
+ execute_operas_helper(tr("Decrypting and Verifying"), contexts);
+};
void MainWindow::SlotFileVerifyEML(const QString& path) {
auto check_result = TargetFilePreCheck(path, true);
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 03f51298..ee66aebb 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -48,6 +48,7 @@
#include "ui/dialog/import_export/KeyUploadDialog.h"
#include "ui/dialog/keypair_details/KeyDetailsDialog.h"
#include "ui/function/SetOwnerTrustLevel.h"
+#include "ui/struct/GpgOperaResult.h"
#include "ui/widgets/FindWidget.h"
#include "ui/widgets/KeyList.h"
#include "ui/widgets/TextEdit.h"
@@ -464,13 +465,11 @@ void MainWindow::slot_verifying_unknown_signature_helper(
auto user_response =
QMessageBox::question(this, tr("Missing Keys"),
tr("Some signatures cannot be verified because "
- "the "
- "corresponding keys are missing.\n\n"
+ "the corresponding keys are missing.\n\n"
"The following fingerprints are "
"missing:\n%1\n\n"
"Would you like to fetch these keys from "
- "the key "
- "server?")
+ "the key server?")
.arg(fingerprint_list),
QMessageBox::Yes | QMessageBox::No);
@@ -479,11 +478,11 @@ void MainWindow::slot_verifying_unknown_signature_helper(
this, m_key_list_->GetCurrentGpgContextChannel(),
result_analyse.GetUnknownSignatures());
} else {
- QMessageBox::information(this, tr("Verification Incomplete"),
- tr("Verification was incomplete due to "
- "missing "
- "keys. You can manually import the keys "
- "later."));
+ QMessageBox::information(
+ this, tr("Verification Incomplete"),
+ tr("Verification was incomplete due to "
+ "missing keys. You can manually import the keys "
+ "later."));
}
}
@@ -556,6 +555,73 @@ void MainWindow::slot_result_analyse_show_helper(
result_analyse.GetResultReport());
}
+void MainWindow::slot_result_analyse_show_helper(
+ const QContainer<GpgOperaResult>& opera_results) {
+ if (opera_results.empty()) {
+ slot_refresh_info_board(0, "");
+ }
+
+ int overall_status = 1; // Initialize to OK
+ QStringList report;
+ QStringList summary;
+
+ QStringList failed_tags;
+ QStringList warning_tags;
+
+ int success_count = 0;
+ int fail_count = 0;
+ int warn_count = 0;
+
+ for (const auto& opera_result : opera_results) {
+ // Update overall status
+ overall_status = std::min(overall_status, opera_result.status);
+
+ QString status_text;
+ if (opera_result.status < 0) {
+ status_text = tr("FAIL");
+ failed_tags << opera_result.tag;
+ fail_count++;
+ } else if (opera_result.status > 0) {
+ status_text = tr("OK");
+ success_count++;
+ } else {
+ status_text = tr("WARN");
+ warning_tags << opera_result.tag;
+ warn_count++;
+ }
+
+ // Append detailed report for each operation
+ report.append(QString("[ %1 ] %2\n\n%3\n")
+ .arg(status_text, opera_result.tag, opera_result.report));
+ }
+
+ // Prepare summary section
+ summary.append("# " + tr("Summary Report") + "\n\n");
+ summary.append("- " + tr("Total Operations: %1\n").arg(opera_results.size()));
+ summary.append("- " + tr("Successful: %1\n").arg(success_count));
+ summary.append("- " + tr("Warnings: %1\n").arg(warn_count));
+ summary.append("- " + tr("Failures: %1\n").arg(fail_count));
+
+ if (!failed_tags.isEmpty()) {
+ summary.append("- " +
+ tr("Failed Objects: %1\n").arg(failed_tags.join(", ")));
+ }
+
+ if (!warning_tags.isEmpty()) {
+ summary.append("- " +
+ tr("Warning Objects: %1\n").arg(warning_tags.join(", ")));
+ }
+
+ // Display the final report in the info board
+ if (opera_results.size() == 1) {
+ slot_refresh_info_board(overall_status, report.join(""));
+
+ } else {
+ slot_refresh_info_board(overall_status,
+ summary.join("") + "\n\n" + report.join(""));
+ }
+}
+
void MainWindow::slot_refresh_info_board(int status, const QString& text) {
info_board_->SlotReset();
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index d3ba32b6..40df7dbc 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -208,14 +208,9 @@ void MainWindow::SlotUpdateCryptoMenuStatus(unsigned int type) {
void MainWindow::SlotGeneralEncrypt(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
+ const auto paths = file_tree_view->GetSelected();
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) {
- this->SlotFileEncrypt(path);
- } else if (file_info.isDir()) {
- this->SlotDirectoryEncrypt(path);
- }
+ this->SlotFileEncrypt(paths);
}
if (edit_->CurEMailPage() != nullptr) {
@@ -231,18 +226,9 @@ void MainWindow::SlotGeneralEncrypt(bool) {
void MainWindow::SlotGeneralDecrypt(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
-
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) {
- const QString extension = file_info.completeSuffix();
+ const auto paths = file_tree_view->GetSelected();
- if (extension == "tar.gpg" || extension == "tar.asc") {
- this->SlotArchiveDecrypt(path);
- } else {
- this->SlotFileDecrypt(path);
- }
- }
+ this->SlotFileDecrypt(paths);
}
if (edit_->CurEMailPage() != nullptr) {
@@ -258,10 +244,9 @@ void MainWindow::SlotGeneralDecrypt(bool) {
void MainWindow::SlotGeneralSign(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
+ const auto paths = file_tree_view->GetSelected();
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) this->SlotFileSign(path);
+ this->SlotFileSign(paths);
}
if (edit_->CurEMailPage() != nullptr) {
@@ -275,10 +260,9 @@ void MainWindow::SlotGeneralSign(bool) {
void MainWindow::SlotGeneralVerify(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
+ const auto paths = file_tree_view->GetSelected();
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) this->SlotFileVerify(path);
+ this->SlotFileVerify(paths);
}
if (edit_->CurEMailPage() != nullptr) {
@@ -292,14 +276,9 @@ void MainWindow::SlotGeneralVerify(bool) {
void MainWindow::SlotGeneralEncryptSign(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
+ const auto paths = file_tree_view->GetSelected();
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) {
- this->SlotFileEncryptSign(path);
- } else if (file_info.isDir()) {
- this->SlotDirectoryEncryptSign(path);
- }
+ this->SlotFileEncryptSign(paths);
}
if (edit_->CurEMailPage() != nullptr) {
@@ -315,18 +294,9 @@ void MainWindow::SlotGeneralEncryptSign(bool) {
void MainWindow::SlotGeneralDecryptVerify(bool) {
if (edit_->CurPageFileTreeView() != nullptr) {
const auto* file_tree_view = edit_->CurPageFileTreeView();
- const auto path = file_tree_view->GetSelected();
-
- const auto file_info = QFileInfo(path);
- if (file_info.isFile()) {
- const QString extension = file_info.completeSuffix();
+ const auto paths = file_tree_view->GetSelected();
- if (extension == "tar.gpg" || extension == "tar.asc") {
- this->SlotArchiveDecryptVerify(path);
- } else {
- this->SlotFileDecryptVerify(path);
- }
- }
+ this->SlotFileDecryptVerify(paths);
}
if (edit_->CurEMailPage() != nullptr) {
diff --git a/src/ui/struct/GpgOperaResult.h b/src/ui/struct/GpgOperaResult.h
new file mode 100644
index 00000000..e3bfd61a
--- /dev/null
+++ b/src/ui/struct/GpgOperaResult.h
@@ -0,0 +1,44 @@
+#include <utility>
+
+/**
+ * Copyright (C) 2021-2024 Saturneric <[email protected]>
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+namespace GpgFrontend::UI {
+
+struct GpgOperaResult {
+ int status;
+ QString report;
+ QString tag;
+
+ GpgOperaResult(int status, QString report, QString tag)
+ : status(status), report(std::move(report)), tag(std::move(tag)) {}
+};
+
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/struct/GpgOperaResultContext.h b/src/ui/struct/GpgOperaResultContext.h
new file mode 100644
index 00000000..f0073c7e
--- /dev/null
+++ b/src/ui/struct/GpgOperaResultContext.h
@@ -0,0 +1,115 @@
+#include <utility>
+
+/**
+ * Copyright (C) 2021-2024 Saturneric <[email protected]>
+ *
+ * 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.
+ *
+ * GpgFrontend 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 GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include "ui/UserInterfaceUtils.h"
+#include "ui/struct/GpgOperaResult.h"
+
+namespace GpgFrontend::UI {
+
+struct GpgOperaCategory {
+ QContainer<QString> paths;
+ QContainer<QString> o_paths;
+};
+
+struct GpgOperaContext {
+ QContainer<OperaWaitingCb>& operas;
+ QContainer<GpgOperaResult>& opera_results;
+ GpgKeyList& keys;
+ GpgKeyList& singer_keys;
+ QContainer<QString>& unknown_fprs;
+ bool ascii;
+
+ QContainer<QString> paths;
+ QContainer<QString> o_paths;
+
+ GpgOperaContext(QContainer<OperaWaitingCb>& operas,
+ QContainer<GpgOperaResult>& opera_results, GpgKeyList& keys,
+ GpgKeyList& singer_keys, QContainer<QString>& unknown_fprs)
+ : operas(operas),
+ opera_results(opera_results),
+ keys(keys),
+ singer_keys(singer_keys),
+ unknown_fprs(unknown_fprs) {}
+};
+
+struct GpgOperaContexts {
+ QContainer<OperaWaitingCb> operas;
+ QContainer<GpgOperaResult> opera_results;
+ GpgKeyList keys;
+ GpgKeyList singer_keys;
+ QContainer<QString> unknown_fprs;
+ bool ascii;
+
+ QMap<int, GpgOperaCategory> categories;
+
+ auto GetContextPath(int category) -> QContainer<QString>& {
+ if (!categories.contains(category)) categories[category] = {};
+ return categories[category].paths;
+ }
+
+ auto GetContextOutPath(int category) -> QContainer<QString>& {
+ if (!categories.contains(category)) categories[category] = {};
+ return categories[category].o_paths;
+ }
+
+ auto GetAllPath() -> QContainer<QString> {
+ QContainer<QString> res;
+
+ for (auto& category : categories) {
+ res.append(category.paths);
+ }
+ return res;
+ }
+
+ auto GetAllOutPath() -> QContainer<QString> {
+ QContainer<QString> res;
+
+ for (auto& category : categories) {
+ res.append(category.o_paths);
+ }
+ return res;
+ }
+
+ auto GetContext(int category) -> QSharedPointer<GpgOperaContext> {
+ if (GetContextPath(category).empty()) return nullptr;
+
+ auto context = QSharedPointer<GpgOperaContext>::create(
+ operas, opera_results, keys, singer_keys, unknown_fprs);
+ context->ascii = ascii;
+
+ context->paths = GetContextPath(category);
+ context->o_paths = GetContextOutPath(category);
+ return context;
+ }
+};
+
+} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index 998b4245..5f6fbae0 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -73,6 +73,9 @@ FilePage::FilePage(QWidget* parent, const QString& target_path)
option_popup_menu_->addAction(show_system_act);
ui_->optionsButton->setMenu(option_popup_menu_);
+ connect(ui_->batchModeButton, &QToolButton::toggled, this,
+ [this](bool checked) { emit SignalSetBatchMode(checked); });
+
connect(ui_->pathEdit, &QLineEdit::textChanged, [=]() {
auto path = ui_->pathEdit->text();
auto dir = QDir(path);
@@ -100,16 +103,16 @@ FilePage::FilePage(QWidget* parent, const QString& target_path)
UISignalStation::GetInstance(),
&UISignalStation::SignalMainWindowOpenFile);
connect(file_tree_view_, &FileTreeView::SignalSelectedChanged, this,
- &FilePage::update_main_basical_opera_menu);
+ &FilePage::update_main_basic_opera_menu);
connect(this, &FilePage::SignalCurrentTabChanged, this,
- [this]() { update_main_basical_opera_menu(GetSelected()); });
- connect(this, &FilePage::SignalMainWindowlUpdateBasicalOperaMenu,
+ [this]() { update_main_basic_opera_menu(GetSelected()); });
+ connect(this, &FilePage::SignalMainWindowUpdateBasicOperaMenu,
UISignalStation::GetInstance(),
- &UISignalStation::SignalMainWindowlUpdateBasicalOperaMenu);
+ &UISignalStation::SignalMainWindowUpdateBasicOperaMenu);
}
-auto FilePage::GetSelected() const -> QString {
- return file_tree_view_->GetSelectedPath();
+auto FilePage::GetSelected() const -> QContainer<QString> {
+ return file_tree_view_->GetSelectedPaths();
}
void FilePage::SlotGoPath() {
@@ -123,43 +126,71 @@ void FilePage::keyPressEvent(QKeyEvent* event) {
}
}
-void FilePage::update_main_basical_opera_menu(const QString& selected_path) {
+void FilePage::update_main_basic_opera_menu(
+ const QContainer<QString>& selected_paths) {
+ if (selected_paths.isEmpty()) {
+ emit SignalMainWindowUpdateBasicOperaMenu(MainWindow::OperationMenu::kNone);
+ return;
+ }
+
MainWindow::OperationMenu::OperationType operation_type =
MainWindow::OperationMenu::kNone;
- // abort...
- if (selected_path.isEmpty()) return;
+ LOG_D() << "selected path size: " << selected_paths.size();
+ LOG_D() << "selected paths: " << selected_paths;
- QFileInfo const info(selected_path);
+ QContainer<QFileInfo> infos;
- if ((info.isDir() || info.isFile()) &&
- (info.suffix() != "gpg" && info.suffix() != "pgp" &&
- info.suffix() != "sig" && info.suffix() != "asc")) {
- operation_type |= MainWindow::OperationMenu::kEncrypt;
+ for (const auto& path : selected_paths) {
+ infos.append(QFileInfo(path));
}
- if ((info.isDir() || info.isFile()) &&
- (info.suffix() != "gpg" && info.suffix() != "pgp" &&
- info.suffix() != "sig" && info.suffix() != "asc")) {
- operation_type |= MainWindow::OperationMenu::kEncryptAndSign;
- }
+ bool c_encr =
+ std::all_of(infos.cbegin(), infos.cend(), [](const QFileInfo& info) {
+ return (info.isDir() || info.isFile()) &&
+ (info.suffix() != "gpg" && info.suffix() != "pgp" &&
+ info.suffix() != "sig" && info.suffix() != "asc");
+ });
- if (info.isFile() && (info.suffix() == "gpg" || info.suffix() == "pgp" ||
- info.suffix() == "asc")) {
- operation_type |= MainWindow::OperationMenu::kDecrypt;
- operation_type |= MainWindow::OperationMenu::kDecryptAndVerify;
+ if (c_encr) {
+ operation_type |= MainWindow::OperationMenu::kEncrypt |
+ MainWindow::OperationMenu::kEncryptAndSign;
}
- if (info.isFile() && (info.suffix() != "gpg" && info.suffix() != "pgp" &&
- info.suffix() != "sig" && info.suffix() != "asc")) {
- operation_type |= MainWindow::OperationMenu::kSign;
- }
+ bool c_decr =
+ std::all_of(infos.cbegin(), infos.cend(), [](const QFileInfo& info) {
+ return info.isFile() &&
+ (info.suffix() == "gpg" || info.suffix() == "pgp" ||
+ info.suffix() == "asc");
+ });
- if (info.isFile() && (info.suffix() == "sig" || info.suffix() == "gpg" ||
- info.suffix() == "pgp" || info.suffix() == "asc")) {
- operation_type |= MainWindow::OperationMenu::kVerify;
+ if (c_decr) {
+ operation_type |= MainWindow::OperationMenu::kDecrypt |
+ MainWindow::OperationMenu::kDecryptAndVerify;
}
- emit SignalMainWindowlUpdateBasicalOperaMenu(operation_type);
+ bool c_sign =
+ std::all_of(infos.cbegin(), infos.cend(), [](const QFileInfo& info) {
+ return info.isFile() &&
+ (info.suffix() != "gpg" && info.suffix() != "pgp" &&
+ info.suffix() != "sig" && info.suffix() != "asc");
+ });
+
+ if (c_sign) operation_type |= MainWindow::OperationMenu::kSign;
+
+ bool c_verify =
+ std::all_of(infos.cbegin(), infos.cend(), [](const QFileInfo& info) {
+ return info.isFile() &&
+ (info.suffix() == "sig" || info.suffix() == "gpg" ||
+ info.suffix() == "pgp" || info.suffix() == "asc");
+ });
+
+ if (c_verify) operation_type |= MainWindow::OperationMenu::kVerify;
+
+ emit SignalMainWindowUpdateBasicOperaMenu(operation_type);
+}
+
+auto FilePage::IsBatchMode() const -> bool {
+ return ui_->batchModeButton->isChecked();
}
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/FilePage.h b/src/ui/widgets/FilePage.h
index aaa61589..c6d9ec99 100644
--- a/src/ui/widgets/FilePage.h
+++ b/src/ui/widgets/FilePage.h
@@ -55,7 +55,15 @@ class FilePage : public QWidget {
*
* @return QString
*/
- [[nodiscard]] auto GetSelected() const -> QString;
+ [[nodiscard]] auto GetSelected() const -> QContainer<QString>;
+
+ /**
+ * @brief
+ *
+ * @return true
+ * @return false
+ */
+ [[nodiscard]] auto IsBatchMode() const -> bool;
public slots:
/**
@@ -92,7 +100,13 @@ class FilePage : public QWidget {
*
* @param int
*/
- void SignalMainWindowlUpdateBasicalOperaMenu(unsigned int);
+ void SignalMainWindowUpdateBasicOperaMenu(unsigned int);
+
+ /**
+ * @brief
+ *
+ */
+ void SignalSetBatchMode(bool);
protected:
/**
@@ -118,7 +132,7 @@ class FilePage : public QWidget {
* @brief
*
*/
- void update_main_basical_opera_menu(const QString&);
+ void update_main_basic_opera_menu(const QContainer<QString>&);
};
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/FileTreeView.cpp b/src/ui/widgets/FileTreeView.cpp
index 500d9787..aa29d040 100644
--- a/src/ui/widgets/FileTreeView.cpp
+++ b/src/ui/widgets/FileTreeView.cpp
@@ -37,7 +37,7 @@ namespace GpgFrontend::UI {
FileTreeView::FileTreeView(QWidget* parent, const QString& target_path)
: QTreeView(parent) {
- dir_model_ = new QFileSystemModel();
+ dir_model_ = new QFileSystemModel(this);
dir_model_->setRootPath(target_path.isEmpty() ? QDir::currentPath()
: target_path);
dir_model_->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
@@ -49,6 +49,7 @@ FileTreeView::FileTreeView(QWidget* parent, const QString& target_path)
slot_create_popup_menu();
this->setContextMenuPolicy(Qt::CustomContextMenu);
+ this->setSelectionMode(QAbstractItemView::MultiSelection);
connect(this, &QWidget::customContextMenuRequested, this,
&FileTreeView::slot_show_custom_context_menu);
@@ -64,16 +65,19 @@ void FileTreeView::selectionChanged(const QItemSelection& selected,
const QItemSelection& deselected) {
QTreeView::selectionChanged(selected, deselected);
- if (!selected.indexes().empty()) {
- selected_path_ = dir_model_->filePath(selected.indexes().first());
- emit SignalSelectedChanged(selected_path_);
- } else {
- selected_path_ = QString();
- if (!this->selectedIndexes().isEmpty()) {
- selected_path_ = dir_model_->filePath(this->selectedIndexes().front());
- emit SignalSelectedChanged(selected_path_);
+ selected_paths_.clear();
+ if (!this->selectedIndexes().isEmpty()) {
+ QSet<QString> paths;
+ for (const auto& index : this->selectedIndexes()) {
+ const auto path = dir_model_->filePath(index);
+ if (path == current_path_) continue;
+
+ paths.insert(path);
}
+ selected_paths_.append(paths.values());
}
+
+ emit SignalSelectedChanged(selected_paths_);
}
void FileTreeView::SlotGoPath(const QString& target_path) {
@@ -143,7 +147,9 @@ auto FileTreeView::GetPathByClickPoint(const QPoint& point) -> QString {
return dir_model_->fileInfo(index).absoluteFilePath();
}
-auto FileTreeView::GetSelectedPath() -> QString { return selected_path_; }
+auto FileTreeView::GetSelectedPaths() -> QContainer<QString> {
+ return selected_paths_;
+}
auto FileTreeView::SlotDeleteSelectedItem() -> void {
QModelIndex const index = this->currentIndex();
@@ -209,7 +215,9 @@ void FileTreeView::SlotTouch() {
}
void FileTreeView::SlotTouchBelowAtSelectedItem() {
- auto root_path(selected_path_);
+ if (selected_paths_.size() != 1) return;
+
+ auto root_path(selected_paths_.front());
if (root_path.isEmpty()) root_path = dir_model_->rootPath();
QString new_file_name;
@@ -243,23 +251,29 @@ void FileTreeView::keyPressEvent(QKeyEvent* event) {
}
void FileTreeView::SlotOpenSelectedItemBySystemApplication() {
- QFileInfo const info(selected_path_);
+ if (selected_paths_.size() != 1) return;
+
+ auto selected_path = selected_paths_.front();
+ QFileInfo const info(selected_path);
if (info.isDir()) {
const auto file_path = info.filePath().toUtf8();
- QDesktopServices::openUrl(QUrl::fromLocalFile(selected_path_));
+ QDesktopServices::openUrl(QUrl::fromLocalFile(selected_path));
} else {
- QDesktopServices::openUrl(QUrl::fromLocalFile(selected_path_));
+ QDesktopServices::openUrl(QUrl::fromLocalFile(selected_path));
}
}
void FileTreeView::SlotRenameSelectedItem() {
+ if (selected_paths_.size() != 1) return;
+
bool ok;
+ auto selected_path = selected_paths_.front();
auto text = QInputDialog::getText(this, tr("Rename"), tr("New Filename"),
QLineEdit::Normal,
- QFileInfo(selected_path_).fileName(), &ok);
+ QFileInfo(selected_path).fileName(), &ok);
if (ok && !text.isEmpty()) {
- auto file_info = QFileInfo(selected_path_);
+ auto file_info = QFileInfo(selected_path);
auto new_name_path = file_info.absolutePath() + "/" + text;
if (!QDir().rename(file_info.absoluteFilePath(), new_name_path)) {
@@ -282,8 +296,9 @@ void FileTreeView::slot_create_popup_menu() {
action_open_file_ = new QAction(this);
action_open_file_->setText(tr("Open"));
- connect(action_open_file_, &QAction::triggered, this,
- [this](bool) { emit SignalOpenFile(GetSelectedPath()); });
+ connect(action_open_file_, &QAction::triggered, this, [this](bool) {
+ for (const auto& path : GetSelectedPaths()) emit SignalOpenFile(path);
+ });
action_rename_file_ = new QAction(this);
action_rename_file_->setText(tr("Rename"));
@@ -342,8 +357,11 @@ void FileTreeView::slot_create_popup_menu() {
void FileTreeView::slot_show_custom_context_menu(const QPoint& point) {
auto target_path = this->GetPathByClickPoint(point);
- auto select_path = GetSelectedPath();
+ auto select_paths = GetSelectedPaths();
+ if (select_paths.size() != 1) return;
+
+ auto select_path = select_paths.front();
if (target_path.isEmpty() && !select_path.isEmpty()) {
target_path = select_path;
}
@@ -378,11 +396,14 @@ void FileTreeView::slot_show_custom_context_menu(const QPoint& point) {
}
void FileTreeView::slot_calculate_hash() {
+ if (GetSelectedPaths().empty()) return;
+ auto selected_path = GetSelectedPaths().front();
+
CommonUtils::WaitForOpera(
this->parentWidget(), tr("Calculating"), [=](const OperaWaitingHd& hd) {
RunOperaAsync(
[=](const DataObjectPtr& data_object) {
- data_object->Swap({CalculateHash(this->GetSelectedPath())});
+ data_object->Swap({CalculateHash(selected_path)});
return 0;
},
[hd](int rtn, const DataObjectPtr& data_object) {
diff --git a/src/ui/widgets/FileTreeView.h b/src/ui/widgets/FileTreeView.h
index d99ff605..aa6c85dc 100644
--- a/src/ui/widgets/FileTreeView.h
+++ b/src/ui/widgets/FileTreeView.h
@@ -28,6 +28,8 @@
#pragma once
+#include "core/typedef/CoreTypedef.h"
+
namespace GpgFrontend::UI {
class FileTreeView : public QTreeView {
@@ -53,7 +55,7 @@ class FileTreeView : public QTreeView {
*
* @return QString
*/
- auto GetSelectedPath() -> QString;
+ auto GetSelectedPaths() -> QContainer<QString>;
/**
* @brief Get the Path By Click Point object
@@ -114,7 +116,7 @@ class FileTreeView : public QTreeView {
* @brief
*
*/
- void SignalSelectedChanged(const QString&);
+ void SignalSelectedChanged(const QContainer<QString>&);
/**
* @brief
@@ -232,9 +234,9 @@ class FileTreeView : public QTreeView {
void slot_adjust_column_widths();
private:
- QFileSystemModel* dir_model_; ///<
- QString current_path_; ///<
- QString selected_path_; ///<
+ QFileSystemModel* dir_model_; ///<
+ QString current_path_; ///<
+ QContainer<QString> selected_paths_; ///<
QMenu* popup_menu_;
QMenu* new_item_action_menu_;
diff --git a/src/ui/widgets/TextEditTabWidget.cpp b/src/ui/widgets/TextEditTabWidget.cpp
index fbf1a3e7..69f95b1f 100644
--- a/src/ui/widgets/TextEditTabWidget.cpp
+++ b/src/ui/widgets/TextEditTabWidget.cpp
@@ -324,8 +324,8 @@ void TextEditTabWidget::slot_file_page_path_changed(const QString& path) {
}
this->setTabText(index, m_path);
- emit UISignalStation::GetInstance()
- -> SignalMainWindowlUpdateBasicalOperaMenu(0);
+ emit UISignalStation::GetInstance() -> SignalMainWindowUpdateBasicOperaMenu(
+ 0);
}
} // namespace GpgFrontend::UI
diff --git a/ui/FilePage.ui b/ui/FilePage.ui
index 5ee3058e..69143680 100644
--- a/ui/FilePage.ui
+++ b/ui/FilePage.ui
@@ -44,20 +44,20 @@
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
- <enum>QLayout::SetMaximumSize</enum>
+ <enum>QLayout::SizeConstraint::SetMaximumSize</enum>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
- <enum>QLayout::SetMaximumSize</enum>
+ <enum>QLayout::SizeConstraint::SetMaximumSize</enum>
</property>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0,0">
+ <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,0,0,0,0,0">
<property name="spacing">
<number>5</number>
</property>
<property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
+ <enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>5</number>
@@ -142,6 +142,26 @@
</widget>
</item>
<item>
+ <widget class="QToolButton" name="batchModeButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../gpgfrontend.qrc">
+ <normaloff>:/icons/batch.png</normaloff>:/icons/batch.png</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QToolButton" name="optionsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -157,10 +177,10 @@
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="popupMode">
- <enum>QToolButton::InstantPopup</enum>
+ <enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="toolButtonStyle">
- <enum>Qt::ToolButtonIconOnly</enum>
+ <enum>Qt::ToolButtonStyle::ToolButtonIconOnly</enum>
</property>
</widget>
</item>