aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSaturn&Eric <[email protected]>2021-12-13 14:50:57 +0000
committerGitHub <[email protected]>2021-12-13 14:50:57 +0000
commitee4752ed756e3114f740efddf63ce987ac154d03 (patch)
tree27653d56c88849c99c70b8fc7223f8ae98090f0b /src
parentUpdate CI for Release and Debug. (diff)
parentAdded & Fixed (diff)
downloadGpgFrontend-ee4752ed756e3114f740efddf63ce987ac154d03.tar.gz
GpgFrontend-ee4752ed756e3114f740efddf63ce987ac154d03.zip
Merge pull request #31 from saturneric/develop-ui
v2.0.2-beta.1
Diffstat (limited to 'src')
-rw-r--r--src/gpg/GpgConstants.cpp36
-rw-r--r--src/gpg/function/BasicOperator.cpp20
-rw-r--r--src/gpg/function/BasicOperator.h3
-rw-r--r--src/gpg/function/GpgFileOpera.cpp6
-rw-r--r--src/gpg/function/GpgKeyImportExportor.cpp28
-rw-r--r--src/gpg/function/GpgKeyImportExportor.h5
-rw-r--r--src/gpg/result_analyse/DecryptResultAnalyse.cpp3
-rw-r--r--src/main.cpp47
-rw-r--r--src/ui/CMakeLists.txt7
-rwxr-xr-xsrc/ui/KeyMgmt.cpp52
-rwxr-xr-xsrc/ui/KeyMgmt.h3
-rw-r--r--src/ui/MainWindow.cpp14
-rw-r--r--src/ui/keypair_details/KeyPairDetailTab.cpp106
-rw-r--r--src/ui/keypair_details/KeyPairDetailTab.h5
-rw-r--r--src/ui/keypair_details/KeyPairSubkeyTab.cpp27
-rw-r--r--src/ui/main_window/MainWindowFileSlotFunction.cpp40
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp76
-rw-r--r--src/ui/widgets/FilePage.cpp256
-rw-r--r--src/ui/widgets/FilePage.h18
-rw-r--r--src/ui/widgets/InfoBoardWidget.cpp134
-rw-r--r--src/ui/widgets/InfoBoardWidget.h31
-rw-r--r--src/ui/widgets/KeyList.cpp1
-rw-r--r--src/ui/widgets/TextEdit.cpp6
23 files changed, 593 insertions, 331 deletions
diff --git a/src/gpg/GpgConstants.cpp b/src/gpg/GpgConstants.cpp
index e3de1d06..2454daa2 100644
--- a/src/gpg/GpgConstants.cpp
+++ b/src/gpg/GpgConstants.cpp
@@ -28,6 +28,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
+#include <string>
const char* GpgFrontend::GpgConstants::PGP_CRYPT_BEGIN =
"-----BEGIN PGP MESSAGE-----";
@@ -110,16 +111,17 @@ static inline std::string trim(std::string& s) {
return s;
}
-std::string GpgFrontend::read_all_data_in_file(const std::string& path) {
+std::string GpgFrontend::read_all_data_in_file(const std::string& utf8_path) {
using namespace boost::filesystem;
- class path file_info(path.c_str());
-
- if (!exists(file_info) || !is_regular_file(path))
- throw std::runtime_error("no permission");
-
+ class path file_info(utf8_path.c_str());
+ if (!exists(file_info) || !is_regular_file(file_info)) return {};
std::ifstream in_file;
- in_file.open(path, std::ios::in);
- if (!in_file.good()) throw std::runtime_error("cannot open file");
+#ifndef WINDOWS
+ in_file.open(file_info.string(), std::ios::in);
+#else
+ in_file.open(file_info.wstring().c_str(), std::ios::in);
+#endif
+ if (!in_file.good()) return {};
std::istreambuf_iterator<char> begin(in_file);
std::istreambuf_iterator<char> end;
std::string in_buffer(begin, end);
@@ -127,9 +129,16 @@ std::string GpgFrontend::read_all_data_in_file(const std::string& path) {
return in_buffer;
}
-bool GpgFrontend::write_buffer_to_file(const std::string& path,
+bool GpgFrontend::write_buffer_to_file(const std::string& utf8_path,
const std::string& out_buffer) {
- std::ofstream out_file(boost::filesystem::path(path).string(), std::ios::out);
+ using namespace boost::filesystem;
+ class path file_info(utf8_path.c_str());
+#ifndef WINDOWS
+ std::ofstream out_file(file_info.string(), std::ios::out | std::ios::trunc);
+#else
+ std::ofstream out_file(file_info.wstring().c_str(),
+ std::ios::out | std::ios::trunc);
+#endif
if (!out_file.good()) return false;
out_file.write(out_buffer.c_str(), out_buffer.size());
out_file.close();
@@ -137,8 +146,9 @@ bool GpgFrontend::write_buffer_to_file(const std::string& path,
}
std::string GpgFrontend::get_file_extension(const std::string& path) {
- // Create a Path object from given string
+ // Create a path object from given string
boost::filesystem::path path_obj(path);
+
// Check if file name in the path object has extension
if (path_obj.has_extension()) {
// Fetch the extension from path object and return
@@ -149,7 +159,7 @@ std::string GpgFrontend::get_file_extension(const std::string& path) {
}
std::string GpgFrontend::get_only_file_name_with_path(const std::string& path) {
- // Create a Path object from given string
+ // Create a path object from given string
boost::filesystem::path path_obj(path);
// Check if file name in the path object has extension
if (path_obj.has_filename()) {
@@ -157,7 +167,7 @@ std::string GpgFrontend::get_only_file_name_with_path(const std::string& path) {
return (path_obj.parent_path() / path_obj.stem()).string();
}
// In case of no extension return empty string
- throw std::runtime_error("invalid file path");
+ return {};
}
/*
diff --git a/src/gpg/function/BasicOperator.cpp b/src/gpg/function/BasicOperator.cpp
index 912119e2..5f6ffb85 100644
--- a/src/gpg/function/BasicOperator.cpp
+++ b/src/gpg/function/BasicOperator.cpp
@@ -76,13 +76,15 @@ GpgFrontend::GpgError GpgFrontend::BasicOperator::Verify(
GpgVerifyResult& result) const {
gpgme_error_t err;
+ LOG(INFO) << "in buffer size" << in_buffer.size();
GpgData data_in(in_buffer.data(), in_buffer.size());
+ GpgData data_out;
if (sig_buffer != nullptr) {
GpgData sig_data(sig_buffer->data(), sig_buffer->size());
err = check_gpg_error(gpgme_op_verify(ctx, sig_data, data_in, nullptr));
} else
- err = check_gpg_error(gpgme_op_verify(ctx, data_in, nullptr, data_in));
+ err = check_gpg_error(gpgme_op_verify(ctx, data_in, nullptr, data_out));
auto temp_result = GpgVerifyResult(gpgme_op_verify_result(ctx));
std::swap(result, temp_result);
@@ -204,3 +206,19 @@ GpgFrontend::BasicOperator::GetSigners() {
}
return signers;
}
+gpg_error_t GpgFrontend::BasicOperator::EncryptSymmetric(
+ GpgFrontend::ByteArray& in_buffer, GpgFrontend::ByteArrayPtr& out_buffer,
+ GpgFrontend::GpgEncrResult& result) {
+ GpgData data_in(in_buffer.data(), in_buffer.size()), data_out;
+
+ gpgme_error_t err = check_gpg_error(gpgme_op_encrypt(
+ ctx, nullptr, GPGME_ENCRYPT_SYMMETRIC, data_in, data_out));
+
+ auto temp_data_out = data_out.Read2Buffer();
+ std::swap(temp_data_out, out_buffer);
+
+ auto temp_result = GpgEncrResult(gpgme_op_encrypt_result(ctx));
+ std::swap(result, temp_result);
+
+ return err;
+}
diff --git a/src/gpg/function/BasicOperator.h b/src/gpg/function/BasicOperator.h
index 39f93668..4ea70eea 100644
--- a/src/gpg/function/BasicOperator.h
+++ b/src/gpg/function/BasicOperator.h
@@ -37,6 +37,9 @@ class BasicOperator : public SingletonFunctionObject<BasicOperator> {
gpg_error_t Encrypt(KeyListPtr keys, BypeArrayRef in_buffer,
ByteArrayPtr& out_buffer, GpgEncrResult& result);
+ gpg_error_t EncryptSymmetric(BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
+ GpgEncrResult& result);
+
gpgme_error_t EncryptSign(KeyListPtr keys, KeyListPtr signers,
BypeArrayRef in_buffer, ByteArrayPtr& out_buffer,
GpgEncrResult& encr_result,
diff --git a/src/gpg/function/GpgFileOpera.cpp b/src/gpg/function/GpgFileOpera.cpp
index c3f75cf8..42b37c71 100644
--- a/src/gpg/function/GpgFileOpera.cpp
+++ b/src/gpg/function/GpgFileOpera.cpp
@@ -41,7 +41,7 @@ GpgFrontend::GpgError GpgFrontend::GpgFileOpera::EncryptFile(
if (!write_buffer_to_file(path + ".asc", *out_buffer)) {
throw std::runtime_error("write_buffer_to_file error");
};
-
+
return err;
}
@@ -94,7 +94,6 @@ gpgme_error_t GpgFrontend::GpgFileOpera::VerifyFile(const std::string& path,
if (get_file_extension(path) == ".gpg") {
auto err =
BasicOperator::GetInstance().Verify(in_buffer, sign_buffer, result);
- assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR);
return err;
} else {
sign_buffer =
@@ -150,8 +149,7 @@ gpg_error_t GpgFrontend::GpgFileOpera::DecryptVerifyFile(
if (!(file_extension == ".asc" || file_extension == ".gpg"))
out_file_name = path + ".out";
- LOG(INFO) << "GpgFrontend::GpgFileOpera::DecryptVerifyFile out_file_name"
- << out_file_name;
+ LOG(INFO) << "out_file_name" << out_file_name;
if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR)
if (!write_buffer_to_file(out_file_name, *out_buffer)) {
diff --git a/src/gpg/function/GpgKeyImportExportor.cpp b/src/gpg/function/GpgKeyImportExportor.cpp
index d8812839..89d3b002 100644
--- a/src/gpg/function/GpgKeyImportExportor.cpp
+++ b/src/gpg/function/GpgKeyImportExportor.cpp
@@ -130,3 +130,31 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKey(
std::swap(out_buffer, temp_out_buffer);
return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
}
+
+bool GpgFrontend::GpgKeyImportExportor::ExportKeyOpenSSH(
+ const GpgFrontend::GpgKey& key,
+ GpgFrontend::ByteArrayPtr& out_buffer) const {
+ GpgData data_out;
+ auto err =
+ gpgme_op_export(ctx, key.id().c_str(), GPGME_EXPORT_MODE_SSH, data_out);
+
+ DLOG(INFO) << "read_bytes" << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
+
+bool GpgFrontend::GpgKeyImportExportor::ExportSecretKeyShortest(
+ const GpgFrontend::GpgKey& key,
+ GpgFrontend::ByteArrayPtr& out_buffer) const {
+ GpgData data_out;
+ auto err = gpgme_op_export(ctx, key.id().c_str(), GPGME_EXPORT_MODE_MINIMAL,
+ data_out);
+
+ DLOG(INFO) << "read_bytes" << gpgme_data_seek(data_out, 0, SEEK_END);
+
+ auto temp_out_buffer = data_out.Read2Buffer();
+ std::swap(out_buffer, temp_out_buffer);
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
+}
diff --git a/src/gpg/function/GpgKeyImportExportor.h b/src/gpg/function/GpgKeyImportExportor.h
index 35a237ba..ad43d539 100644
--- a/src/gpg/function/GpgKeyImportExportor.h
+++ b/src/gpg/function/GpgKeyImportExportor.h
@@ -90,8 +90,13 @@ class GpgKeyImportExportor
bool ExportKey(const GpgKey& key, ByteArrayPtr& out_buffer) const;
+ bool ExportKeyOpenSSH(const GpgKey& key, ByteArrayPtr& out_buffer) const;
+
bool ExportSecretKey(const GpgKey& key, ByteArrayPtr& outBuffer) const;
+ bool ExportSecretKeyShortest(const GpgKey& key,
+ ByteArrayPtr& outBuffer) const;
+
private:
GpgContext& ctx =
GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel());
diff --git a/src/gpg/result_analyse/DecryptResultAnalyse.cpp b/src/gpg/result_analyse/DecryptResultAnalyse.cpp
index 4ff32c59..f7fc70fe 100644
--- a/src/gpg/result_analyse/DecryptResultAnalyse.cpp
+++ b/src/gpg/result_analyse/DecryptResultAnalyse.cpp
@@ -51,6 +51,9 @@ void GpgFrontend::DecryptResultAnalyse::do_analyse() {
stream << _("File Name") << ": " << result->file_name << std::endl;
stream << std::endl;
}
+ if (result->is_mime) {
+ stream << _("MIME") << ": " << _("true") << std::endl;
+ }
auto reci = result->recipients;
if (reci != nullptr) stream << _("Recipient(s)") << ": " << std::endl;
diff --git a/src/main.cpp b/src/main.cpp
index 1dbf1d5e..aad4b8fd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -25,7 +25,9 @@
#include <cstdlib>
#include "GpgFrontendBuildInfo.h"
+#include "gpg/GpgContext.h"
#include "ui/MainWindow.h"
+#include "ui/WaitingDialog.h"
#include "ui/settings/GlobalSettingStation.h"
// Easy Logging Cpp
@@ -40,7 +42,10 @@ int main(int argc, char* argv[]) {
// Qt App
QApplication app(argc, argv);
+
+#ifndef MACOS
QApplication::setWindowIcon(QIcon(":gpgfrontend.png"));
+#endif
#ifdef MACOS
// support retina screen
@@ -60,7 +65,7 @@ int main(int argc, char* argv[]) {
// unicode in source
QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8"));
-#if !defined(RELEASE)
+#if !defined(RELEASE) && defined(WINDOWS)
// css
QFile file(RESOURCE_DIR(qApp->applicationDirPath()) + "/css/default.qss");
file.open(QFile::ReadOnly);
@@ -75,17 +80,37 @@ int main(int argc, char* argv[]) {
*/
int return_from_event_loop_code;
- do {
- // i18n
- init_locale();
-
- QApplication::setQuitOnLastWindowClosed(true);
-
- auto main_window = std::make_unique<GpgFrontend::UI::MainWindow>();
- main_window->init();
- main_window->show();
- return_from_event_loop_code = QApplication::exec();
+ // Create & Check Gnupg Context Status
+ if (!GpgFrontend::GpgContext::GetInstance().good()) {
+ QMessageBox::critical(
+ nullptr, _("ENV Loading Failed"),
+ _("Gnupg(gpg) is not installed correctly, please follow the "
+ "ReadME "
+ "instructions in Github to install Gnupg and then open "
+ "GpgFrontend."));
+ QCoreApplication::quit();
+ exit(0);
+ }
+ do {
+ try {
+ // i18n
+ init_locale();
+
+ QApplication::setQuitOnLastWindowClosed(true);
+
+ auto main_window = std::make_unique<GpgFrontend::UI::MainWindow>();
+ main_window->init();
+ main_window->show();
+ return_from_event_loop_code = QApplication::exec();
+
+ } catch (...) {
+ QMessageBox::information(nullptr, _("Unhandled Exception Thrown"),
+ _("Oops, an unhandled exception was thrown "
+ "during the running of the "
+ "program, and now it needs to be restarted."));
+ continue;
+ }
} while (return_from_event_loop_code == RESTART_CODE);
return return_from_event_loop_code;
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index f4b00d22..7c6bf732 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -13,10 +13,11 @@ if (SMTP_SUPPORT)
aux_source_directory(./smtp UI_SOURCE)
endif ()
-
add_library(gpgfrontend-ui STATIC ${UI_SOURCE})
-
-target_link_libraries(gpgfrontend-ui
+set(GPGFRONTEND_UI_LIB_NAME gpgfrontend-ui)
+target_link_libraries(${GPGFRONTEND_UI_LIB_NAME}
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core)
+target_include_directories(gpgfrontend-ui PUBLIC
+ ${CMAKE_CURRENT_BINARY_DIR}/${GPGFRONTEND_UI_LIB_NAME}_autogen/include)
target_compile_features(gpgfrontend-ui PUBLIC cxx_std_17) \ No newline at end of file
diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp
index aa6df120..f28e6587 100755
--- a/src/ui/KeyMgmt.cpp
+++ b/src/ui/KeyMgmt.cpp
@@ -207,6 +207,13 @@ void KeyMgmt::createActions() {
connect(exportKeyToFileAct, SIGNAL(triggered()), this,
SLOT(slotExportKeyToFile()));
+ exportKeyAsOpenSSHFormat = new QAction(_("Export As OpenSSH"), this);
+ exportKeyAsOpenSSHFormat->setIcon(QIcon(":ssh-key.png"));
+ exportKeyAsOpenSSHFormat->setToolTip(
+ _("Export Selected Key(s) As OpenSSH Format to File"));
+ connect(exportKeyAsOpenSSHFormat, SIGNAL(triggered()), this,
+ SLOT(slotExportAsOpenSSHFormat()));
+
deleteSelectedKeysAct = new QAction(_("Delete Selected Key(s)"), this);
deleteSelectedKeysAct->setToolTip(_("Delete the Selected keys"));
connect(deleteSelectedKeysAct, SIGNAL(triggered()), this,
@@ -240,6 +247,7 @@ void KeyMgmt::createMenus() {
importKeyMenu->addAction(importKeyFromKeyServerAct);
keyMenu->addAction(exportKeyToFileAct);
keyMenu->addAction(exportKeyToClipboardAct);
+ keyMenu->addAction(exportKeyAsOpenSSHFormat);
keyMenu->addSeparator();
keyMenu->addAction(deleteCheckedKeysAct);
}
@@ -273,6 +281,7 @@ void KeyMgmt::createToolBars() {
keyToolBar->addSeparator();
keyToolBar->addAction(exportKeyToFileAct);
keyToolBar->addAction(exportKeyToClipboardAct);
+ keyToolBar->addAction(exportKeyAsOpenSSHFormat);
}
void KeyMgmt::slotDeleteSelectedKeys() {
@@ -446,4 +455,47 @@ void KeyMgmt::slotSaveWindowState() {
GlobalSettingStation::GetInstance().Sync();
}
+void KeyMgmt::slotExportAsOpenSSHFormat() {
+ ByteArrayPtr key_export_data = nullptr;
+ auto keys_checked = mKeyList->getChecked();
+
+ if (keys_checked->empty()) {
+ QMessageBox::critical(nullptr, _("Error"), _("No Key Checked."));
+ return;
+ }
+
+ auto key = GpgKeyGetter::GetInstance().GetKey(keys_checked->front());
+ if (!GpgKeyImportExportor::GetInstance().ExportKeyOpenSSH(key,
+ key_export_data)) {
+ QMessageBox::critical(nullptr, _("Error"),
+ _("An error occur in exporting."));
+ return;
+ }
+
+ if (key_export_data->empty()) {
+ QMessageBox::critical(
+ nullptr, _("Error"),
+ _("This key may not be able to export as OpenSSH format. Please check "
+ "the key-size of the subkey(s) used to sign."));
+ return;
+ }
+
+ key = GpgKeyGetter::GetInstance().GetKey(keys_checked->front());
+ if (!key.good()) {
+ QMessageBox::critical(nullptr, _("Error"), _("Key Not Found."));
+ return;
+ }
+ QString fileString = QString::fromStdString(key.name() + " " + key.email() +
+ "(" + key.id() + ").pub");
+
+ QString file_name = QFileDialog::getSaveFileName(
+ this, _("Export OpenSSH Key To File"), fileString,
+ QString(_("OpenSSH Public Key Files")) + " (*.pub);;All Files (*)");
+
+ if (!file_name.isEmpty()) {
+ write_buffer_to_file(file_name.toStdString(), *key_export_data);
+ emit signalStatusBarChanged(QString(_("key(s) exported")));
+ }
+}
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/KeyMgmt.h b/src/ui/KeyMgmt.h
index bf1c9b5a..7edb1b5c 100755
--- a/src/ui/KeyMgmt.h
+++ b/src/ui/KeyMgmt.h
@@ -48,6 +48,8 @@ class KeyMgmt : public QMainWindow {
void slotExportKeyToClipboard();
+ void slotExportAsOpenSSHFormat();
+
void slotDeleteSelectedKeys();
void slotDeleteCheckedKeys();
@@ -80,6 +82,7 @@ class KeyMgmt : public QMainWindow {
QMenu* importKeyMenu{};
QAction* openKeyFileAct{};
QAction* exportKeyToFileAct{};
+ QAction* exportKeyAsOpenSSHFormat{};
QAction* exportKeyToClipboardAct{};
QAction* deleteCheckedKeysAct{};
QAction* deleteSelectedKeysAct{};
diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp
index 9aceed96..6d55aeb5 100644
--- a/src/ui/MainWindow.cpp
+++ b/src/ui/MainWindow.cpp
@@ -38,18 +38,7 @@ MainWindow::MainWindow() {
}
void MainWindow::init() noexcept {
- LOG(INFO) << _("Called");
try {
- // Check Context Status
- if (!GpgContext::GetInstance().good()) {
- QMessageBox::critical(
- nullptr, _("ENV Loading Failed"),
- _("Gnupg is not installed correctly, please follow the ReadME "
- "instructions to install gnupg and then open GpgFrontend."));
- QCoreApplication::quit();
- exit(0);
- }
-
networkAccessManager = new QNetworkAccessManager(this);
/* get path where app was started */
@@ -64,7 +53,7 @@ void MainWindow::init() noexcept {
mKeyList->slotRefresh();
- infoBoard = new InfoBoardWidget(this, mKeyList);
+ infoBoard = new InfoBoardWidget(this);
/* List of binary Attachments */
attachmentDockCreated = false;
@@ -139,7 +128,6 @@ void MainWindow::init() noexcept {
version_thread->start();
#endif
-
} catch (...) {
LOG(FATAL) << _("Critical error occur while loading GpgFrontend.");
QMessageBox::critical(nullptr, _("Loading Failed"),
diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp
index de16ccf7..3de83e38 100644
--- a/src/ui/keypair_details/KeyPairDetailTab.cpp
+++ b/src/ui/keypair_details/KeyPairDetailTab.cpp
@@ -81,15 +81,24 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
vboxKD->addWidget(new QLabel(QString(_("Master Key Existence")) + ": "), 8,
0);
- vboxKD->addWidget(keyidVarLabel, 0, 1);
- vboxKD->addWidget(algorithmVarLabel, 1, 1);
- vboxKD->addWidget(keySizeVarLabel, 2, 1);
- vboxKD->addWidget(usageVarLabel, 3, 1);
- vboxKD->addWidget(actualUsageVarLabel, 4, 1);
- vboxKD->addWidget(createdVarLabel, 5, 1);
- vboxKD->addWidget(expireVarLabel, 6, 1);
- vboxKD->addWidget(lastUpdateVarLabel, 7, 1);
- vboxKD->addWidget(masterKeyExistVarLabel, 8, 1);
+ vboxKD->addWidget(keyidVarLabel, 0, 1, 1, 1);
+ vboxKD->addWidget(algorithmVarLabel, 1, 1, 1, 2);
+ vboxKD->addWidget(keySizeVarLabel, 2, 1, 1, 2);
+ vboxKD->addWidget(usageVarLabel, 3, 1, 1, 2);
+ vboxKD->addWidget(actualUsageVarLabel, 4, 1, 1, 2);
+ vboxKD->addWidget(createdVarLabel, 5, 1, 1, 2);
+ vboxKD->addWidget(expireVarLabel, 6, 1, 1, 2);
+ vboxKD->addWidget(lastUpdateVarLabel, 7, 1, 1, 2);
+ vboxKD->addWidget(masterKeyExistVarLabel, 8, 1, 1, 2);
+
+ auto* copyKeyIdButton = new QPushButton(_("Copy"));
+ copyKeyIdButton->setFlat(true);
+ vboxKD->addWidget(copyKeyIdButton, 0, 2);
+ connect(copyKeyIdButton, &QPushButton::clicked, this, [=]() {
+ QString fpr = keyidVarLabel->text().trimmed();
+ QClipboard* cb = QApplication::clipboard();
+ cb->setText(fpr);
+ });
ownerBox->setLayout(vboxOD);
mvbox->addWidget(ownerBox);
@@ -119,6 +128,9 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
mvbox->addStretch();
mvbox->addWidget(fingerprintBox);
+ // Set Menu
+ createOperaMenu();
+
auto* opera_key_box = new QGroupBox(_("Operations"));
auto* vbox_p_k = new QVBoxLayout();
@@ -131,10 +143,9 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
SLOT(slotExportPublicKey()));
if (mKey.is_private_key()) {
- auto* export_private_button =
- new QPushButton(_("Export Private Key (Include Subkey)"));
- connect(export_private_button, SIGNAL(clicked()), this,
- SLOT(slotExportPrivateKey()));
+ auto* export_private_button = new QPushButton(_("Export Private Key"));
+ export_private_button->setStyleSheet("text-align:center;");
+ export_private_button->setMenu(secretKeyExportOperaMenu);
export_h_box_layout->addWidget(export_private_button);
if (mKey.has_master_key()) {
@@ -157,10 +168,6 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
auto* key_server_opera_button =
new QPushButton(_("Key Server Operation (Pubkey)"));
key_server_opera_button->setStyleSheet("text-align:center;");
- connect(key_server_opera_button, SIGNAL(clicked()), this,
- SLOT(slotModifyEditDatetime()));
- // Set Menu
- createKeyServerOperaMenu();
key_server_opera_button->setMenu(keyServerOperaMenu);
advance_h_box_layout->addWidget(key_server_opera_button);
@@ -230,6 +237,48 @@ void KeyPairDetailTab::slotExportPublicKey() {
}
}
+void KeyPairDetailTab::slotExportShortPrivateKey() {
+ // Show a information box with explanation about private key
+ int ret = QMessageBox::information(
+ this, _("Exporting short private Key"),
+ "<h3>" + QString(_("You are about to export your")) +
+ "<font color=\"red\">" + _(" PRIVATE KEY ") + "</font>!</h3>\n" +
+ _("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
+ _("Do you REALLY want to export your PRIVATE KEY in a Minimum "
+ "Size?") +
+ "<br />" +
+ _("For OpenPGP keys it removes all signatures except for the latest "
+ "self-signatures."),
+ QMessageBox::Cancel | QMessageBox::Ok);
+
+ // export key, if ok was clicked
+ if (ret == QMessageBox::Ok) {
+ ByteArrayPtr keyArray = nullptr;
+
+ if (!GpgKeyImportExportor::GetInstance().ExportSecretKeyShortest(
+ mKey, keyArray)) {
+ QMessageBox::critical(
+ this, _("Error"),
+ _("An error occurred during the export operation."));
+ return;
+ }
+ auto fileString = mKey.name() + " " + mKey.email() + "(" + mKey.id() +
+ ")_short_secret.asc";
+ auto fileName =
+ QFileDialog::getSaveFileName(
+ this, _("Export Key To File"), QString::fromStdString(fileString),
+ QString(_("Key Files")) + " (*.asc *.txt);;All Files (*)")
+ .toStdString();
+
+ if (!write_buffer_to_file(fileName, *keyArray)) {
+ QMessageBox::critical(
+ this, _("Export Error"),
+ QString(_("Couldn't open %1 for writing")).arg(fileName.c_str()));
+ return;
+ }
+ }
+}
+
void KeyPairDetailTab::slotExportPrivateKey() {
// Show a information box with explanation about private key
int ret = QMessageBox::information(
@@ -250,8 +299,8 @@ void KeyPairDetailTab::slotExportPrivateKey() {
_("An error occurred during the export operation."));
return;
}
- auto fileString =
- mKey.name() + " " + mKey.email() + "(" + mKey.id() + ")_secret.asc";
+ auto fileString = mKey.name() + " " + mKey.email() + "(" + mKey.id() +
+ ")_full_secret.asc";
auto fileName =
QFileDialog::getSaveFileName(
this, _("Export Key To File"), QString::fromStdString(fileString),
@@ -370,7 +419,7 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
}
}
-void KeyPairDetailTab::createKeyServerOperaMenu() {
+void KeyPairDetailTab::createOperaMenu() {
keyServerOperaMenu = new QMenu(this);
auto* uploadKeyPair = new QAction(_("Upload Key Pair to Key Server"), this);
@@ -384,6 +433,21 @@ void KeyPairDetailTab::createKeyServerOperaMenu() {
keyServerOperaMenu->addAction(uploadKeyPair);
keyServerOperaMenu->addAction(updateKeyPair);
+
+ secretKeyExportOperaMenu = new QMenu(this);
+
+ auto* exportFullSecretKey = new QAction(_("Export Full Secret Key"), this);
+ connect(exportFullSecretKey, SIGNAL(triggered()), this,
+ SLOT(slotExportPrivateKey()));
+ if (!mKey.is_private_key()) exportFullSecretKey->setDisabled(true);
+
+ auto* exportShortestSecretKey =
+ new QAction(_("Export Shortest Secret Key"), this);
+ connect(exportShortestSecretKey, SIGNAL(triggered()), this,
+ SLOT(slotExportShortPrivateKey()));
+
+ secretKeyExportOperaMenu->addAction(exportFullSecretKey);
+ secretKeyExportOperaMenu->addAction(exportShortestSecretKey);
}
void KeyPairDetailTab::slotUploadKeyToServer() {
@@ -403,7 +467,7 @@ void KeyPairDetailTab::slotUpdateKeyFromServer() {
}
void KeyPairDetailTab::slotGenRevokeCert() {
- auto literal = QStringLiteral("%1 (*.rev)").arg(_("Revocation Certificates"));
+ auto literal = QString("%1 (*.rev)").arg(_("Revocation Certificates"));
QString m_output_file_name;
QFileDialog dialog(this, "Generate revocation certificate", QString(),
diff --git a/src/ui/keypair_details/KeyPairDetailTab.h b/src/ui/keypair_details/KeyPairDetailTab.h
index 68ca1ebd..3e2f2298 100644
--- a/src/ui/keypair_details/KeyPairDetailTab.h
+++ b/src/ui/keypair_details/KeyPairDetailTab.h
@@ -36,7 +36,7 @@ namespace GpgFrontend::UI {
class KeyPairDetailTab : public QWidget {
Q_OBJECT
- void createKeyServerOperaMenu();
+ void createOperaMenu();
private slots:
@@ -45,6 +45,8 @@ class KeyPairDetailTab : public QWidget {
*/
void slotExportPrivateKey();
+ void slotExportShortPrivateKey();
+
void slotExportPublicKey();
/**
@@ -95,6 +97,7 @@ class KeyPairDetailTab : public QWidget {
QLabel* expLabel;
QMenu* keyServerOperaMenu{};
+ QMenu* secretKeyExportOperaMenu{};
public:
explicit KeyPairDetailTab(const std::string& key_id,
diff --git a/src/ui/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
index 93e07875..cb71c09f 100644
--- a/src/ui/keypair_details/KeyPairSubkeyTab.cpp
+++ b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
@@ -64,7 +64,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(const std::string& key_id, QWidget* parent)
subkeyDetailLayout->addWidget(new QLabel(QString(_("Usage")) + ": "), 3, 0);
subkeyDetailLayout->addWidget(new QLabel(QString(_("Expires On")) + ": "), 4,
0);
- subkeyDetailLayout->addWidget(new QLabel(QString(_("Last Update")) + ": "), 5,
+ subkeyDetailLayout->addWidget(new QLabel(QString(_("Create Date")) + ": "), 5,
0);
subkeyDetailLayout->addWidget(new QLabel(QString(_("Existence")) + ": "), 6,
0);
@@ -80,14 +80,23 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(const std::string& key_id, QWidget* parent)
masterKeyExistVarLabel = new QLabel();
fingerPrintVarLabel = new QLabel();
- subkeyDetailLayout->addWidget(keyidVarLabel, 0, 1);
- subkeyDetailLayout->addWidget(keySizeVarLabel, 2, 1);
- subkeyDetailLayout->addWidget(expireVarLabel, 4, 1);
- subkeyDetailLayout->addWidget(algorithmVarLabel, 1, 1);
- subkeyDetailLayout->addWidget(createdVarLabel, 5, 1);
- subkeyDetailLayout->addWidget(usageVarLabel, 3, 1);
- subkeyDetailLayout->addWidget(masterKeyExistVarLabel, 6, 1);
- subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1);
+ subkeyDetailLayout->addWidget(keyidVarLabel, 0, 1, 1, 1);
+ subkeyDetailLayout->addWidget(keySizeVarLabel, 2, 1, 1, 2);
+ subkeyDetailLayout->addWidget(expireVarLabel, 4, 1, 1, 2);
+ subkeyDetailLayout->addWidget(algorithmVarLabel, 1, 1, 1, 2);
+ subkeyDetailLayout->addWidget(createdVarLabel, 5, 1, 1, 2);
+ subkeyDetailLayout->addWidget(usageVarLabel, 3, 1, 1, 2);
+ subkeyDetailLayout->addWidget(masterKeyExistVarLabel, 6, 1, 1, 2);
+ subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1, 1, 2);
+
+ auto* copyKeyIdButton = new QPushButton(_("Copy"));
+ copyKeyIdButton->setFlat(true);
+ subkeyDetailLayout->addWidget(copyKeyIdButton, 0, 2);
+ connect(copyKeyIdButton, &QPushButton::clicked, this, [=]() {
+ QString fpr = keyidVarLabel->text().trimmed();
+ QClipboard* cb = QApplication::clipboard();
+ cb->setText(fpr);
+ });
listBox->setLayout(subkeyListLayout);
listBox->setContentsMargins(0, 12, 0, 0);
diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp
index 19be9769..133a7820 100644
--- a/src/ui/main_window/MainWindowFileSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp
@@ -245,14 +245,16 @@ void MainWindow::slotFileVerify() {
signFilePath = path + ".sig";
}
- bool ok;
- QString text =
- QInputDialog::getText(this, _("Origin file to verify"), _("Filepath"),
- QLineEdit::Normal, dataFilePath, &ok);
- if (ok && !text.isEmpty()) {
- dataFilePath = text;
- } else {
- return;
+ if (fileInfo.suffix() != "gpg") {
+ bool ok;
+ QString text =
+ QInputDialog::getText(this, _("Origin file to verify"), _("Filepath"),
+ QLineEdit::Normal, dataFilePath, &ok);
+ if (ok && !text.isEmpty()) {
+ dataFilePath = text;
+ } else {
+ return;
+ }
}
QFileInfo dataFileInfo(dataFilePath), signFileInfo(signFilePath);
@@ -395,13 +397,23 @@ void MainWindow::slotFileDecryptVerify() {
if (!file_pre_check(this, path)) return;
- QString outFileName, fileExtension = QFileInfo(path).suffix();
-
- if (fileExtension == "asc" || fileExtension == "gpg") {
- int pos = path.lastIndexOf(QChar('.'));
- outFileName = path.left(pos);
+ boost::filesystem::path out_path(path.toStdString());
+ if (out_path.extension() == ".asc" || out_path.extension() == ".gpg") {
+ out_path = out_path.parent_path() / out_path.filename();
} else {
- outFileName = path + ".out";
+ out_path = out_path.replace_extension(".out").string();
+ }
+ LOG(INFO) << "out path" << out_path;
+
+ if (QFile::exists(out_path.string().c_str())) {
+ auto ret =
+ QMessageBox::warning(this, _("Warning"),
+ QString(_("The output file %1 already exists, do "
+ "you need to overwrite it?"))
+ .arg(out_path.filename().string().c_str()),
+ QMessageBox::Ok | QMessageBox::Cancel);
+
+ if (ret == QMessageBox::Cancel) return;
}
GpgDecrResult d_result = nullptr;
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 4ad33ac3..41549182 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -51,40 +51,56 @@ void MainWindow::slotEncrypt() {
auto key_ids = mKeyList->getChecked();
- if (key_ids->empty()) {
- QMessageBox::critical(nullptr, _("No Key Selected"), _("No Key Selected"));
- return;
- }
-
- auto key_getter = GpgFrontend::GpgKeyGetter::GetInstance();
- auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids);
- for (const auto& key : *keys) {
- if (!key.CanEncrActual()) {
- QMessageBox::information(
- nullptr, _("Invalid Operation"),
- QString(
- _("The selected key contains a key that does not actually have a "
- "encrypt usage.")) +
- "<br/><br/>" + _("For example the Following Key:") + " <br/>" +
- QString::fromStdString(key.uids()->front().uid()));
- return;
- }
- }
-
- auto tmp = std::make_unique<ByteArray>();
-
GpgEncrResult result = nullptr;
GpgError error;
bool if_error = false;
- process_operation(this, _("Encrypting"), [&]() {
- try {
- auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
- error = GpgFrontend::BasicOperator::GetInstance().Encrypt(
- std::move(keys), buffer, tmp, result);
- } catch (const std::runtime_error& e) {
- if_error = true;
+ auto tmp = std::make_unique<ByteArray>();
+
+ if (key_ids->empty()) {
+ // Symmetric Encrypt
+ auto ret =
+ QMessageBox::warning(this, _("Warning"),
+ _("No Key Selected. Do you want to encrypt with a "
+ "symmetric cipher using a passphrase?"),
+ QMessageBox::Ok | QMessageBox::Cancel);
+
+ if (ret == QMessageBox::Cancel) return;
+
+ process_operation(this, _("Symmetrically Encrypting"), [&]() {
+ try {
+ auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ error = GpgFrontend::BasicOperator::GetInstance().EncryptSymmetric(
+ buffer, tmp, result);
+ } catch (const std::runtime_error& e) {
+ if_error = true;
+ }
+ });
+ } else {
+ auto key_getter = GpgFrontend::GpgKeyGetter::GetInstance();
+ auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids);
+ for (const auto& key : *keys) {
+ if (!key.CanEncrActual()) {
+ QMessageBox::information(
+ nullptr, _("Invalid Operation"),
+ QString(_(
+ "The selected key contains a key that does not actually have a "
+ "encrypt usage.")) +
+ "<br/><br/>" + _("For example the Following Key:") + " <br/>" +
+ QString::fromStdString(key.uids()->front().uid()));
+ return;
+ }
}
- });
+
+ process_operation(this, _("Encrypting"), [&]() {
+ try {
+ auto buffer = edit->curTextPage()->toPlainText().toUtf8().toStdString();
+ error = GpgFrontend::BasicOperator::GetInstance().Encrypt(
+ std::move(keys), buffer, tmp, result);
+ } catch (const std::runtime_error& e) {
+ if_error = true;
+ }
+ });
+ }
if (!if_error) {
auto resultAnalyse = EncryptResultAnalyse(error, std::move(result));
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index c51e0c76..ca6dedc1 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -25,94 +25,55 @@
#include "ui/widgets/FilePage.h"
#include <boost/filesystem.hpp>
+#include <string>
#include "ui/MainWindow.h"
#include "ui/SignalStation.h"
+#include "ui_FilePage.h"
namespace GpgFrontend::UI {
-FilePage::FilePage(QWidget* parent) : QWidget(parent) {
+FilePage::FilePage(QWidget* parent)
+ : QWidget(parent), ui(std::make_shared<Ui_FilePage>()) {
+ ui->setupUi(this);
+
firstParent = parent;
dirModel = new QFileSystemModel();
dirModel->setRootPath(QDir::currentPath());
+ dirModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
- dirTreeView = new QTreeView();
- dirTreeView->setModel(dirModel);
- dirTreeView->setAnimated(true);
- dirTreeView->setIndentation(20);
- dirTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
- dirTreeView->setColumnWidth(0, 320);
- dirTreeView->setRootIndex(dirModel->index(QDir::currentPath()));
+ ui->fileTreeView->setModel(dirModel);
+ ui->fileTreeView->setColumnWidth(0, 320);
+ ui->fileTreeView->sortByColumn(0, Qt::AscendingOrder);
mPath = boost::filesystem::path(dirModel->rootPath().toStdString());
createPopupMenu();
- upLevelButton = new QPushButton();
- connect(upLevelButton, SIGNAL(clicked(bool)), this, SLOT(slotUpLevel()));
-
- QString buttonStyle =
- "QPushButton{border:none;background-color:rgba(255, 255, 255, 0);}";
-
- auto upPixmap = QPixmap(":up.png");
- upPixmap =
- upPixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
- QIcon upButtonIcon(upPixmap);
- upLevelButton->setIcon(upButtonIcon);
- upLevelButton->setIconSize(upPixmap.rect().size());
- upLevelButton->setStyleSheet(buttonStyle);
-
- refreshButton = new QPushButton(_("Refresh"));
- connect(refreshButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
-
- goPathButton = new QPushButton();
- connect(goPathButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
+ connect(ui->upPathButton, &QPushButton::clicked, this,
+ &FilePage::slotUpLevel);
+ connect(ui->refreshButton, &QPushButton::clicked, this,
+ &FilePage::slotGoPath);
+ ui->optionsButton->setMenu(optionPopUpMenu);
- auto updatePixmap = QPixmap(":refresh.png");
- updatePixmap = updatePixmap.scaled(18, 18, Qt::KeepAspectRatio,
- Qt::SmoothTransformation);
- QIcon updateButtonIcon(updatePixmap);
- goPathButton->setIcon(updateButtonIcon);
- goPathButton->setIconSize(updatePixmap.rect().size());
- goPathButton->setStyleSheet(buttonStyle);
-
- pathEdit = new QLineEdit();
- pathEdit->setText(dirModel->rootPath());
+ ui->pathEdit->setText(dirModel->rootPath());
pathEditCompleter = new QCompleter(this);
pathCompleteModel = new QStringListModel();
pathEditCompleter->setModel(pathCompleteModel);
pathEditCompleter->setCaseSensitivity(Qt::CaseInsensitive);
pathEditCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
- pathEdit->setCompleter(pathEditCompleter);
-
- auto* menuLayout = new QHBoxLayout();
- menuLayout->addWidget(upLevelButton);
- menuLayout->setStretchFactor(upLevelButton, 1);
- menuLayout->addWidget(pathEdit);
- menuLayout->setStretchFactor(pathEdit, 10);
- menuLayout->addWidget(goPathButton);
- menuLayout->setStretchFactor(goPathButton, 1);
-
- auto* layout = new QVBoxLayout();
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- layout->addLayout(menuLayout);
- layout->setStretchFactor(menuLayout, 1);
- layout->addWidget(dirTreeView);
- layout->setStretchFactor(dirTreeView, 8);
-
- this->setLayout(layout);
-
- connect(dirTreeView, &QTreeView::clicked, this,
+ ui->pathEdit->setCompleter(pathEditCompleter);
+
+ connect(ui->fileTreeView, &QTreeView::clicked, this,
&FilePage::fileTreeViewItemClicked);
- connect(dirTreeView, &QTreeView::doubleClicked, this,
+ connect(ui->fileTreeView, &QTreeView::doubleClicked, this,
&FilePage::fileTreeViewItemDoubleClicked);
- connect(dirTreeView, &QTreeView::customContextMenuRequested, this,
+ connect(ui->fileTreeView, &QTreeView::customContextMenuRequested, this,
&FilePage::onCustomContextMenu);
- connect(pathEdit, &QLineEdit::textChanged, [=]() {
- auto path = pathEdit->text();
+ connect(ui->pathEdit, &QLineEdit::textChanged, [=]() {
+ auto path = ui->pathEdit->text();
auto dir = QDir(path);
if (path.endsWith("/") && dir.isReadable()) {
auto dir_list = dir.entryInfoList(QDir::AllEntries);
@@ -139,22 +100,30 @@ void FilePage::fileTreeViewItemClicked(const QModelIndex& index) {
}
void FilePage::slotUpLevel() {
- QModelIndex currentRoot = dirTreeView->rootIndex();
+ QModelIndex currentRoot = ui->fileTreeView->rootIndex();
- mPath = boost::filesystem::path(
- dirModel->fileInfo(currentRoot).absoluteFilePath().toStdString());
+ auto utf8_path =
+ dirModel->fileInfo(currentRoot).absoluteFilePath().toStdString();
+ boost::filesystem::path path_obj(utf8_path);
+
+ mPath = path_obj;
LOG(INFO) << "get path" << mPath;
- if (mPath.has_parent_path()) {
+ if (mPath.has_parent_path() && !mPath.parent_path().empty()) {
mPath = mPath.parent_path();
LOG(INFO) << "parent path" << mPath;
- pathEdit->setText(mPath.string().c_str());
- slotGoPath();
+ ui->pathEdit->setText(mPath.string().c_str());
+ this->slotGoPath();
}
}
void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex& index) {
- pathEdit->setText(dirModel->fileInfo(index).absoluteFilePath());
- slotGoPath();
+ QFileInfo file_info(dirModel->fileInfo(index).absoluteFilePath());
+ if (file_info.isFile()) {
+ slotOpenItem();
+ } else {
+ ui->pathEdit->setText(file_info.filePath());
+ slotGoPath();
+ }
}
QString FilePage::getSelected() const {
@@ -162,19 +131,20 @@ QString FilePage::getSelected() const {
}
void FilePage::slotGoPath() {
- const auto path_edit = pathEdit->text().toStdString();
- LOG(INFO) << "get path edit" << path_edit;
- if (mPath.string() != path_edit) mPath = path_edit;
+ const auto path_edit = ui->pathEdit->text().toStdString();
+ boost::filesystem::path path_obj(path_edit);
+
+ if (mPath.string() != path_edit) mPath = path_obj;
auto fileInfo = QFileInfo(mPath.string().c_str());
if (fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) {
mPath = boost::filesystem::path(fileInfo.filePath().toStdString());
LOG(INFO) << "set path" << mPath;
- dirTreeView->setRootIndex(dirModel->index(fileInfo.filePath()));
+ ui->fileTreeView->setRootIndex(dirModel->index(fileInfo.filePath()));
+ dirModel->setRootPath(fileInfo.filePath());
for (int i = 1; i < dirModel->columnCount(); ++i) {
- dirTreeView->resizeColumnToContents(i);
+ ui->fileTreeView->resizeColumnToContents(i);
}
- pathEdit->setText(mPath.generic_path().string().c_str());
-
+ ui->pathEdit->setText(mPath.generic_path().string().c_str());
} else {
QMessageBox::critical(
this, _("Error"),
@@ -186,26 +156,35 @@ void FilePage::slotGoPath() {
void FilePage::createPopupMenu() {
popUpMenu = new QMenu();
- auto openItemAct = new QAction(_("Open"), this);
- connect(openItemAct, SIGNAL(triggered()), this, SLOT(slotOpenItem()));
- auto renameItemAct = new QAction(_("Rename"), this);
- connect(renameItemAct, SIGNAL(triggered()), this, SLOT(slotRenameItem()));
- auto deleteItemAct = new QAction(_("Delete"), this);
- connect(deleteItemAct, SIGNAL(triggered()), this, SLOT(slotDeleteItem()));
+ openItemAct = new QAction(_("Open"), this);
+ connect(openItemAct, &QAction::triggered, this, &FilePage::slotOpenItem);
+ renameItemAct = new QAction(_("Rename"), this);
+ connect(renameItemAct, &QAction::triggered, this, &FilePage::slotRenameItem);
+ deleteItemAct = new QAction(_("Delete"), this);
+ connect(deleteItemAct, &QAction::triggered, this, &FilePage::slotDeleteItem);
encryptItemAct = new QAction(_("Encrypt Sign"), this);
- connect(encryptItemAct, SIGNAL(triggered()), this, SLOT(slotEncryptItem()));
+ connect(encryptItemAct, &QAction::triggered, this,
+ &FilePage::slotEncryptItem);
decryptItemAct =
new QAction(QString(_("Decrypt Verify")) + " " + _("(.gpg .asc)"), this);
- connect(decryptItemAct, SIGNAL(triggered()), this, SLOT(slotDecryptItem()));
+ connect(decryptItemAct, &QAction::triggered, this,
+ &FilePage::slotDecryptItem);
signItemAct = new QAction(_("Sign"), this);
- connect(signItemAct, SIGNAL(triggered()), this, SLOT(slotSignItem()));
+ connect(signItemAct, &QAction::triggered, this, &FilePage::slotSignItem);
verifyItemAct =
new QAction(QString(_("Verify")) + " " + _("(.sig .gpg .asc)"), this);
- connect(verifyItemAct, SIGNAL(triggered()), this, SLOT(slotVerifyItem()));
+ connect(verifyItemAct, &QAction::triggered, this, &FilePage::slotVerifyItem);
hashCalculateAct = new QAction(_("Calculate Hash"), this);
- connect(hashCalculateAct, SIGNAL(triggered()), this,
- SLOT(slotCalculateHash()));
+ connect(hashCalculateAct, &QAction::triggered, this,
+ &FilePage::slotCalculateHash);
+
+ mkdirAct = new QAction(_("Make New Directory"), this);
+ connect(mkdirAct, &QAction::triggered, this, &FilePage::slotMkdir);
+
+ createEmptyFileAct = new QAction(_("Create Empty File"), this);
+ connect(createEmptyFileAct, &QAction::triggered, this,
+ &FilePage::slotCreateEmptyFile);
popUpMenu->addAction(openItemAct);
popUpMenu->addAction(renameItemAct);
@@ -216,15 +195,47 @@ void FilePage::createPopupMenu() {
popUpMenu->addAction(signItemAct);
popUpMenu->addAction(verifyItemAct);
popUpMenu->addSeparator();
+ popUpMenu->addAction(mkdirAct);
+ popUpMenu->addAction(createEmptyFileAct);
popUpMenu->addAction(hashCalculateAct);
+
+ optionPopUpMenu = new QMenu();
+
+ auto showHiddenAct = new QAction(_("Show Hidden File"), this);
+ showHiddenAct->setCheckable(true);
+ connect(showHiddenAct, &QAction::triggered, this, [&](bool checked) {
+ LOG(INFO) << "Set Hidden" << checked;
+ if (checked)
+ dirModel->setFilter(dirModel->filter() | QDir::Hidden);
+ else
+ dirModel->setFilter(dirModel->filter() & ~QDir::Hidden);
+ dirModel->setRootPath(mPath.string().c_str());
+ });
+ optionPopUpMenu->addAction(showHiddenAct);
+
+ auto showSystemAct = new QAction(_("Show System File"), this);
+ showSystemAct->setCheckable(true);
+ connect(showSystemAct, &QAction::triggered, this, [&](bool checked) {
+ LOG(INFO) << "Set Hidden" << checked;
+ if (checked)
+ dirModel->setFilter(dirModel->filter() | QDir::System);
+ else
+ dirModel->setFilter(dirModel->filter() & ~QDir::System);
+ dirModel->setRootPath(mPath.string().c_str());
+ });
+ optionPopUpMenu->addAction(showSystemAct);
}
void FilePage::onCustomContextMenu(const QPoint& point) {
- QModelIndex index = dirTreeView->indexAt(point);
+ QModelIndex index = ui->fileTreeView->indexAt(point);
selectedPath = boost::filesystem::path(
dirModel->fileInfo(index).absoluteFilePath().toStdString());
LOG(INFO) << "right click" << selectedPath;
if (index.isValid()) {
+ openItemAct->setEnabled(true);
+ renameItemAct->setEnabled(true);
+ deleteItemAct->setEnabled(true);
+
QFileInfo info(QString::fromStdString(selectedPath.string()));
encryptItemAct->setEnabled(
info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig"));
@@ -236,9 +247,19 @@ void FilePage::onCustomContextMenu(const QPoint& point) {
verifyItemAct->setEnabled(
info.isFile() && (info.suffix() == "sig" || info.suffix() == "gpg"));
hashCalculateAct->setEnabled(info.isFile() && info.isReadable());
-
- popUpMenu->exec(dirTreeView->viewport()->mapToGlobal(point));
+ } else {
+ openItemAct->setEnabled(false);
+ renameItemAct->setEnabled(false);
+ deleteItemAct->setEnabled(false);
+
+ encryptItemAct->setEnabled(false);
+ encryptItemAct->setEnabled(false);
+ decryptItemAct->setEnabled(false);
+ signItemAct->setEnabled(false);
+ verifyItemAct->setEnabled(false);
+ hashCalculateAct->setEnabled(false);
}
+ popUpMenu->exec(ui->fileTreeView->viewport()->mapToGlobal(point));
}
void FilePage::slotOpenItem() {
@@ -247,7 +268,7 @@ void FilePage::slotOpenItem() {
if (info.isReadable() && info.isExecutable()) {
const auto file_path = info.filePath().toStdString();
LOG(INFO) << "set path" << file_path;
- pathEdit->setText(info.filePath());
+ ui->pathEdit->setText(info.filePath());
slotGoPath();
} else {
QMessageBox::critical(this, _("Error"),
@@ -291,8 +312,8 @@ void FilePage::slotRenameItem() {
}
void FilePage::slotDeleteItem() {
- QModelIndex index = dirTreeView->currentIndex();
- QVariant data = dirTreeView->model()->data(index);
+ QModelIndex index = ui->fileTreeView->currentIndex();
+ QVariant data = ui->fileTreeView->model()->data(index);
auto ret = QMessageBox::warning(this, _("Warning"),
_("Are you sure you want to delete it?"),
@@ -300,7 +321,7 @@ void FilePage::slotDeleteItem() {
if (ret == QMessageBox::Cancel) return;
- qDebug() << "Delete Item" << data.toString();
+ LOG(INFO) << "Delete Item" << data.toString().toStdString();
if (!dirModel->remove(index)) {
QMessageBox::critical(this, _("Error"),
@@ -377,10 +398,49 @@ void FilePage::slotCalculateHash() {
}
}
+void FilePage::slotMkdir() {
+ auto index = ui->fileTreeView->rootIndex();
+
+ QString new_dir_name;
+ bool ok;
+ new_dir_name =
+ QInputDialog::getText(this, _("Make New Directory"), _("Directory Name"),
+ QLineEdit::Normal, new_dir_name, &ok);
+ if (ok && !new_dir_name.isEmpty()) {
+ dirModel->mkdir(index, new_dir_name);
+ }
+}
+
+void FilePage::slotCreateEmptyFile() {
+ auto root_path_str = dirModel->rootPath().toStdString();
+ boost::filesystem::path root_path(root_path_str);
+
+ QString new_file_name;
+ bool ok;
+ new_file_name = QInputDialog::getText(this, _("Create Empty File"),
+ _("Filename (you can given extension)"),
+ QLineEdit::Normal, new_file_name, &ok);
+ if (ok && !new_file_name.isEmpty()) {
+ auto file_path = root_path / new_file_name.toStdString();
+ QFile new_file(file_path.string().c_str());
+ if (!new_file.open(QIODevice::WriteOnly | QIODevice::NewOnly)) {
+ QMessageBox::critical(this, _("Error"), _("Unable to create the file."));
+ }
+ new_file.close();
+ }
+}
+
void FilePage::keyPressEvent(QKeyEvent* event) {
- qDebug() << "Key Press" << event->key();
- if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+ LOG(INFO) << "Key Press" << event->key();
+ if (ui->pathEdit->hasFocus() &&
+ (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) {
slotGoPath();
+ } else if (ui->fileTreeView->currentIndex().isValid()) {
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
+ slotOpenItem();
+ else if (event->key() == Qt::Key_Delete ||
+ event->key() == Qt::Key_Backspace)
+ slotDeleteItem();
}
}
diff --git a/src/ui/widgets/FilePage.h b/src/ui/widgets/FilePage.h
index 2a9f5b57..03caf36b 100644
--- a/src/ui/widgets/FilePage.h
+++ b/src/ui/widgets/FilePage.h
@@ -30,6 +30,8 @@
#include "ui/GpgFrontendUI.h"
#include "ui/widgets/InfoBoardWidget.h"
+class Ui_FilePage;
+
namespace GpgFrontend::UI {
class FilePage : public QWidget {
@@ -63,6 +65,8 @@ class FilePage : public QWidget {
void slotSignItem();
void slotVerifyItem();
void slotCalculateHash();
+ void slotMkdir();
+ void slotCreateEmptyFile();
void onCustomContextMenu(const QPoint& point);
@@ -72,9 +76,9 @@ class FilePage : public QWidget {
private:
void createPopupMenu();
+ std::shared_ptr<Ui_FilePage> ui;
+
QFileSystemModel* dirModel;
- QTreeView* dirTreeView;
- QLineEdit* pathEdit;
QCompleter* pathEditCompleter;
QStringListModel* pathCompleteModel;
@@ -82,16 +86,18 @@ class FilePage : public QWidget {
boost::filesystem::path mPath;
boost::filesystem::path selectedPath;
- QPushButton* upLevelButton;
- QPushButton* goPathButton;
- QPushButton* refreshButton;
-
QMenu* popUpMenu{};
+ QMenu* optionPopUpMenu{};
QAction* encryptItemAct{};
QAction* decryptItemAct{};
QAction* signItemAct{};
QAction* verifyItemAct{};
QAction* hashCalculateAct{};
+ QAction* mkdirAct{};
+ QAction* openItemAct{};
+ QAction* renameItemAct{};
+ QAction* deleteItemAct{};
+ QAction* createEmptyFileAct{};
QWidget* firstParent;
};
diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp
index e0de75f9..1b7dbda0 100644
--- a/src/ui/widgets/InfoBoardWidget.cpp
+++ b/src/ui/widgets/InfoBoardWidget.cpp
@@ -26,87 +26,35 @@
#include "ui/SignalStation.h"
#include "ui/settings/GlobalSettingStation.h"
+#include "ui_InfoBoard.h"
namespace GpgFrontend::UI {
-InfoBoardWidget::InfoBoardWidget(QWidget* parent, KeyList* keyList)
- : QWidget(parent), mKeyList(keyList) {
- infoBoard = new QTextEdit(this);
- infoBoard->setReadOnly(true);
- infoBoard->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
- infoBoard->setMinimumWidth(480);
- infoBoard->setContentsMargins(0, 0, 0, 0);
-
- importFromKeyserverAct =
- new QAction(_("Import missing key from Keyserver"), this);
- connect(importFromKeyserverAct, SIGNAL(triggered()), this,
- SLOT(slotImportFromKeyserver()));
-
- detailMenu = new QMenu(this);
- detailMenu->addAction(importFromKeyserverAct);
- importFromKeyserverAct->setVisible(false);
-
- auto* action_button_menu = new QWidget();
- action_button_menu->setContentsMargins(0, 0, 0, 0);
- action_button_menu->setSizePolicy(QSizePolicy::Preferred,
- QSizePolicy::Minimum);
- action_button_menu->setFixedHeight(40);
-
- actionButtonLayout = new QHBoxLayout();
- actionButtonLayout->setContentsMargins(0, 0, 0, 0);
- actionButtonLayout->setSpacing(0);
-
- auto* label = new QLabel(_("Actions"));
- label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- label->setContentsMargins(0, 0, 0, 0);
- mButtonGroup = new QButtonGroup(this);
-
- auto* bottom_layout = new QHBoxLayout(this);
- bottom_layout->addWidget(label);
- actionButtonLayout->addStretch();
- bottom_layout->addLayout(actionButtonLayout);
- action_button_menu->setLayout(bottom_layout);
-
- QFrame* line;
- line = new QFrame(this);
- line->setFrameShape(QFrame::HLine);
- line->setFrameShadow(QFrame::Sunken);
- line->setContentsMargins(0, 0, 0, 0);
-
- auto* notificationWidgetLayout = new QVBoxLayout(this);
- notificationWidgetLayout->setContentsMargins(0, 0, 0, 0);
- notificationWidgetLayout->setSpacing(0);
-
- notificationWidgetLayout->addWidget(infoBoard);
- notificationWidgetLayout->setStretchFactor(infoBoard, 10);
- notificationWidgetLayout->addWidget(action_button_menu);
- notificationWidgetLayout->setStretchFactor(action_button_menu, 1);
- notificationWidgetLayout->addWidget(line);
- notificationWidgetLayout->setStretchFactor(line, 1);
- notificationWidgetLayout->addStretch(0);
- this->setLayout(notificationWidgetLayout);
+InfoBoardWidget::InfoBoardWidget(QWidget* parent)
+ : QWidget(parent), ui(std::make_shared<Ui_InfoBoard>()) {
+ ui->setupUi(this);
- connect(SignalStation::GetInstance(), &SignalStation::signalRefreshInfoBoard,
- this, &InfoBoardWidget::slotRefresh);
+ ui->actionButtonLayout->addStretch();
+ ui->actionLabel->setText(_("InfoBoard's Actions Menu"));
+ ui->copyButton->setText(_("Copy"));
+ ui->saveButton->setText(_("Save"));
+ ui->clearButton->setText(_("Clear"));
- // set default size
- infoBoard->resize(480, 120);
- resize(480, 120);
-}
+ connect(ui->copyButton, &QPushButton::clicked, this,
+ &InfoBoardWidget::slotCopy);
+ connect(ui->saveButton, &QPushButton::clicked, this,
+ &InfoBoardWidget::slotSave);
+ connect(ui->clearButton, &QPushButton::clicked, this,
+ &InfoBoardWidget::slotReset);
-void InfoBoardWidget::slotImportFromKeyserver() {
- auto* importDialog = new KeyServerImportDialog(false, this);
- auto key_ids = std::make_unique<KeyIdArgsList>();
- for (const auto& key_id : *keysNotInList) {
- key_ids->push_back(key_id.toStdString());
- }
- importDialog->slotImport(key_ids);
+ connect(SignalStation::GetInstance(), &SignalStation::signalRefreshInfoBoard,
+ this, &InfoBoardWidget::slotRefresh);
}
void InfoBoardWidget::setInfoBoard(const QString& text,
InfoBoardStatus verifyLabelStatus) {
QString color;
- infoBoard->clear();
+ ui->infoBoard->clear();
switch (verifyLabelStatus) {
case INFO_ERROR_OK:
color = "#008000";
@@ -120,12 +68,12 @@ void InfoBoardWidget::setInfoBoard(const QString& text,
default:
break;
}
- infoBoard->append(text);
+ ui->infoBoard->append(text);
- infoBoard->setAutoFillBackground(true);
- QPalette status = infoBoard->palette();
+ ui->infoBoard->setAutoFillBackground(true);
+ QPalette status = ui->infoBoard->palette();
status.setColor(QPalette::Text, color);
- infoBoard->setPalette(status);
+ ui->infoBoard->setPalette(status);
auto& settings = GlobalSettingStation::GetInstance().GetUISettings();
@@ -137,13 +85,13 @@ void InfoBoardWidget::setInfoBoard(const QString& text,
} catch (...) {
LOG(ERROR) << _("Setting Operation Error") << _("info_font_size");
}
- infoBoard->setFont(QFont("Times", info_font_size));
+ ui->infoBoard->setFont(QFont("Times", info_font_size));
}
void InfoBoardWidget::slotRefresh(const QString& text, InfoBoardStatus status) {
- infoBoard->clear();
+ ui->infoBoard->clear();
setInfoBoard(text, status);
- infoBoard->verticalScrollBar()->setValue(0);
+ ui->infoBoard->verticalScrollBar()->setValue(0);
}
void InfoBoardWidget::associateTextEdit(QTextEdit* edit) {
@@ -156,9 +104,6 @@ void InfoBoardWidget::associateTextEdit(QTextEdit* edit) {
void InfoBoardWidget::associateTabWidget(QTabWidget* tab) {
if (mTextPage != nullptr)
disconnect(mTextPage, SIGNAL(textChanged()), this, SLOT(slotReset()));
- // if (mFileTreeView != nullptr)
- // disconnect(mFileTreeView, &FilePage::pathChanged, this,
- // &InfoBoardWidget::slotReset);
if (mTabWidget != nullptr) {
disconnect(mTabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset()));
connect(mTabWidget, SIGNAL(tabCloseRequested(int)), this,
@@ -173,13 +118,14 @@ void InfoBoardWidget::associateTabWidget(QTabWidget* tab) {
void InfoBoardWidget::addOptionalAction(const QString& name,
const std::function<void()>& action) {
+ LOG(INFO) << "add option" << name.toStdString();
auto actionButton = new QPushButton(name);
auto layout = new QHBoxLayout();
layout->setContentsMargins(5, 0, 5, 0);
- infoBoard->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ ui->infoBoard->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
// set margin from surroundings
layout->addWidget(actionButton);
- actionButtonLayout->addLayout(layout);
+ ui->actionButtonLayout->addLayout(layout);
connect(actionButton, &QPushButton::clicked, this, [=]() { action(); });
}
@@ -188,11 +134,11 @@ void InfoBoardWidget::addOptionalAction(const QString& name,
*/
void InfoBoardWidget::resetOptionActionsMenu() {
// skip stretch
- deleteWidgetsInLayout(actionButtonLayout, 1);
+ deleteWidgetsInLayout(ui->actionButtonLayout, 1);
}
void InfoBoardWidget::slotReset() {
- this->infoBoard->clear();
+ ui->infoBoard->clear();
resetOptionActionsMenu();
}
@@ -214,4 +160,24 @@ void InfoBoardWidget::deleteWidgetsInLayout(QLayout* layout, int start_index) {
}
}
+void InfoBoardWidget::slotCopy() {
+ auto* clipboard = QGuiApplication::clipboard();
+ clipboard->setText(ui->infoBoard->toPlainText());
+}
+
+void InfoBoardWidget::slotSave() {
+ auto file_path = QFileDialog::getSaveFileName(
+ this, _("Save Information Board's Content"), {}, tr("Text (*.txt)"));
+ LOG(INFO) << "file path" << file_path.toStdString();
+ QFile file(file_path);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ file.write(ui->infoBoard->toPlainText().toUtf8());
+ } else {
+ QMessageBox::critical(
+ this, _("Error"),
+ _("The file path is not exists, unprivileged or unreachable."));
+ }
+ file.close();
+}
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/InfoBoardWidget.h b/src/ui/widgets/InfoBoardWidget.h
index b7239adb..8d37be6c 100644
--- a/src/ui/widgets/InfoBoardWidget.h
+++ b/src/ui/widgets/InfoBoardWidget.h
@@ -29,6 +29,8 @@
#include "gpg/result_analyse/VerifyResultAnalyse.h"
#include "ui/details/VerifyDetailsDialog.h"
+class Ui_InfoBoard;
+
namespace GpgFrontend::UI {
/**
@@ -53,7 +55,7 @@ class InfoBoardWidget : public QWidget {
* @param ctx The GPGme-Context
* @param parent The parent widget
*/
- explicit InfoBoardWidget(QWidget* parent, KeyList* keyList);
+ explicit InfoBoardWidget(QWidget* parent);
void associateTextEdit(QTextEdit* edit);
@@ -72,17 +74,8 @@ class InfoBoardWidget : public QWidget {
*/
void setInfoBoard(const QString& text, InfoBoardStatus verifyLabelStatus);
- QStringList* keysNotInList; /** List with keys, which are in signature but not
- in keylist */
-
public slots:
- /**
- * @details Import the keys contained in keysNotInList from keyserver
- *
- */
- void slotImportFromKeyserver();
-
void slotReset();
/**
@@ -90,19 +83,17 @@ class InfoBoardWidget : public QWidget {
*/
void slotRefresh(const QString& text, InfoBoardStatus status);
+ private slots:
+
+ void slotCopy();
+
+ void slotSave();
+
private:
- QMenu* detailMenu; /** Menu for te Button in verfiyNotification */
- QAction* importFromKeyserverAct; /** Action for importing keys from keyserver
- which are notin keylist */
- QTextEdit* infoBoard;
- KeyList* mKeyList; /** Table holding the keys */
+ std::shared_ptr<Ui_InfoBoard> ui;
QTextEdit* mTextPage{nullptr}; /** TextEdit associated to the notification */
- QTabWidget* mTabWidget{
- nullptr}; /** TreeView associated to the notification */
-
- QHBoxLayout* actionButtonLayout;
- QButtonGroup* mButtonGroup;
+ QTabWidget* mTabWidget{nullptr};
void deleteWidgetsInLayout(QLayout* layout, int start_index = 0);
};
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index 5931e337..02a12e80 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -46,6 +46,7 @@ void KeyList::init() {
mGroupTab = new QTabWidget();
mGroupTab->setMovable(true);
mGroupTab->setTabsClosable(false);
+ mGroupTab->setDocumentMode(true);
auto* layout = new QVBoxLayout;
layout->addWidget(mGroupTab);
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index ec6c6c7a..036c69d4 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -77,12 +77,13 @@ void TextEdit::slotNewFileTab() const {
void TextEdit::slotOpenFile(QString& path) {
QFile file(path);
- LOG(INFO) << " path" << path.toStdString();
+ LOG(INFO) << "path" << path.toStdString();
auto result = file.open(QIODevice::ReadOnly | QIODevice::Text);
if (result) {
auto* page = new EditorPage(path);
QApplication::setOverrideCursor(Qt::WaitCursor);
- tabWidget->addTab(page, strippedName(path));
+ auto index = tabWidget->addTab(page, strippedName(path));
+ tabWidget->setTabIcon(index, QIcon(":file.png"));
tabWidget->setCurrentIndex(tabWidget->count() - 1);
QApplication::restoreOverrideCursor();
page->getTextPage()->setFocus();
@@ -96,7 +97,6 @@ void TextEdit::slotOpenFile(QString& path) {
}
file.close();
- LOG(INFO) << "done";
}
void TextEdit::slotOpen() {