feat: add delete subkey function
This commit is contained in:
parent
94281700b1
commit
a5d7cc6aa2
@ -94,60 +94,55 @@ auto GpgFrontend::GpgKeyManager::SetExpire(
|
||||
|
||||
auto GpgFrontend::GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key,
|
||||
int trust_level) -> bool {
|
||||
if (trust_level < 0 || trust_level > 5) {
|
||||
if (trust_level < 1 || trust_level > 5) {
|
||||
FLOG_W("illegal owner trust level: %d", trust_level);
|
||||
}
|
||||
|
||||
AutomatonNextStateHandler next_state_handler = [](AutomatonState state,
|
||||
QString status,
|
||||
QString args) {
|
||||
LOG_D() << "next_state_handler state: " << static_cast<unsigned int>(state)
|
||||
<< ", gpg_status: " << status << ", args: " << args;
|
||||
AutomatonNextStateHandler next_state_handler =
|
||||
[](AutomatonState state, QString status, QString args) {
|
||||
auto tokens = args.split(' ');
|
||||
|
||||
auto tokens = args.split(' ');
|
||||
|
||||
switch (state) {
|
||||
case AS_START:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_COMMAND;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_COMMAND:
|
||||
if (status == "GET_LINE" && args == "edit_ownertrust.value") {
|
||||
return AS_VALUE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_VALUE:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
} else if (status == "GET_BOOL" &&
|
||||
args == "edit_ownertrust.set_ultimate.okay") {
|
||||
return AS_REALLY_ULTIMATE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_REALLY_ULTIMATE:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_QUIT:
|
||||
if (status == "GET_LINE" && args == "keyedit.save.okay") {
|
||||
return AS_SAVE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_ERROR:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
default:
|
||||
return AS_ERROR;
|
||||
};
|
||||
};
|
||||
switch (state) {
|
||||
case AS_START:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_COMMAND;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_COMMAND:
|
||||
if (status == "GET_LINE" && args == "edit_ownertrust.value") {
|
||||
return AS_VALUE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_VALUE:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
} else if (status == "GET_BOOL" &&
|
||||
args == "edit_ownertrust.set_ultimate.okay") {
|
||||
return AS_REALLY_ULTIMATE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_REALLY_ULTIMATE:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_QUIT:
|
||||
if (status == "GET_BOOL" && args == "keyedit.save.okay") {
|
||||
return AS_SAVE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_ERROR:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
default:
|
||||
return AS_ERROR;
|
||||
};
|
||||
};
|
||||
|
||||
AutomatonActionHandler action_handler =
|
||||
[trust_level](AutomatonHandelStruct& handler, AutomatonState state) {
|
||||
FLOG_D("action_handler state: %d", static_cast<unsigned int>(state));
|
||||
switch (state) {
|
||||
case AS_COMMAND:
|
||||
return QString("trust");
|
||||
@ -210,11 +205,15 @@ auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle,
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_D() << "current state" << handle_struct->CurrentStatus()
|
||||
<< "gpg status: " << status_s << ", args: " << args_s;
|
||||
|
||||
AutomatonState next_state = handle_struct->NextState(status_s, args_s);
|
||||
if (next_state == AS_ERROR) {
|
||||
FLOG_D("handle struct next state caught error, skipping...");
|
||||
return GPG_ERR_FALSE;
|
||||
FLOG_D("handle struct next state caught error, abort...");
|
||||
return -1;
|
||||
}
|
||||
LOG_D() << "next state" << next_state;
|
||||
|
||||
if (next_state == AS_SAVE) {
|
||||
handle_struct->SetSuccess(true);
|
||||
@ -224,6 +223,8 @@ auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle,
|
||||
handle_struct->SetStatus(next_state);
|
||||
Command cmd = handle_struct->Action();
|
||||
|
||||
LOG_D() << "next action, cmd:" << cmd;
|
||||
|
||||
if (!cmd.isEmpty()) {
|
||||
auto btye_array = cmd.toUtf8();
|
||||
gpgme_io_write(fd, btye_array, btye_array.size());
|
||||
@ -234,4 +235,89 @@ auto GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
auto GpgFrontend::GpgKeyManager::DeleteSubkey(const GpgKey& key,
|
||||
int subkey_index) -> bool {
|
||||
if (subkey_index < 0 || subkey_index >= key.GetSubKeys()->size()) {
|
||||
LOG_W() << "illegal subkey index: " << subkey_index;
|
||||
}
|
||||
|
||||
AutomatonNextStateHandler next_state_handler =
|
||||
[](AutomatonState state, QString status, QString args) {
|
||||
auto tokens = args.split(' ');
|
||||
|
||||
switch (state) {
|
||||
case AS_START:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_SELECT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_SELECT:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_COMMAND;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_COMMAND:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
} else if (status == "GET_BOOL" &&
|
||||
args == "keyedit.remove.subkey.okay") {
|
||||
return AS_REALLY_ULTIMATE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_REALLY_ULTIMATE:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_QUIT:
|
||||
if (status == "GET_BOOL" && args == "keyedit.save.okay") {
|
||||
return AS_SAVE;
|
||||
}
|
||||
return AS_ERROR;
|
||||
case AS_ERROR:
|
||||
if (status == "GET_LINE" && args == "keyedit.prompt") {
|
||||
return AS_QUIT;
|
||||
}
|
||||
return AS_ERROR;
|
||||
default:
|
||||
return AS_ERROR;
|
||||
};
|
||||
};
|
||||
|
||||
AutomatonActionHandler action_handler =
|
||||
[subkey_index](AutomatonHandelStruct& handler, AutomatonState state) {
|
||||
switch (state) {
|
||||
case AS_SELECT:
|
||||
return QString("key %1").arg(subkey_index);
|
||||
case AS_COMMAND:
|
||||
return QString("delkey");
|
||||
case AS_REALLY_ULTIMATE:
|
||||
handler.SetSuccess(true);
|
||||
return QString("Y");
|
||||
case AS_QUIT:
|
||||
return QString("quit");
|
||||
case AS_SAVE:
|
||||
handler.SetSuccess(true);
|
||||
return QString("Y");
|
||||
case AS_START:
|
||||
case AS_ERROR:
|
||||
return QString("");
|
||||
default:
|
||||
return QString("");
|
||||
}
|
||||
return QString("");
|
||||
};
|
||||
|
||||
auto key_fpr = key.GetFingerprint();
|
||||
AutomatonHandelStruct handel_struct(key_fpr);
|
||||
handel_struct.SetHandler(next_state_handler, action_handler);
|
||||
|
||||
GpgData data_out;
|
||||
|
||||
auto err =
|
||||
gpgme_op_interact(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), 0,
|
||||
GpgKeyManager::interactor_cb_fnc,
|
||||
static_cast<void*>(&handel_struct), data_out);
|
||||
return CheckGpgError(err) == GPG_ERR_NO_ERROR && handel_struct.Success();
|
||||
}
|
||||
|
@ -91,6 +91,16 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
|
||||
*/
|
||||
auto SetOwnerTrustLevel(const GpgKey& key, int trust_level) -> bool;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param key
|
||||
* @param subkey_index
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
auto DeleteSubkey(const GpgKey& key, int subkey_index) -> bool;
|
||||
|
||||
private:
|
||||
static auto interactor_cb_fnc(void* handle, const char* status,
|
||||
const char* args, int fd) -> gpgme_error_t;
|
||||
@ -98,6 +108,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
|
||||
using Command = QString;
|
||||
using AutomatonState = enum {
|
||||
AS_START,
|
||||
AS_SELECT,
|
||||
AS_COMMAND,
|
||||
AS_VALUE,
|
||||
AS_REALLY_ULTIMATE,
|
||||
@ -115,7 +126,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
|
||||
|
||||
struct AutomatonHandelStruct {
|
||||
void SetStatus(AutomatonState next_state) { current_state_ = next_state; }
|
||||
auto CuurentStatus() -> AutomatonState { return current_state_; }
|
||||
auto CurrentStatus() -> AutomatonState { return current_state_; }
|
||||
void SetHandler(AutomatonNextStateHandler next_state_handler,
|
||||
AutomatonActionHandler action_handler) {
|
||||
next_state_handler_ = std::move(next_state_handler);
|
||||
|
216
src/test/core/GpgCoreTestKeyManagement.cpp
Normal file
216
src/test/core/GpgCoreTestKeyManagement.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Copyright (C) 2021-2024 Saturneric <eric@bktus.com>
|
||||
*
|
||||
* 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 <eric@bktus.com> starting on May 12, 2021.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GpgCoreTest.h"
|
||||
#include "core/GpgConstants.h"
|
||||
#include "core/function/gpg/GpgKeyGetter.h"
|
||||
#include "core/function/gpg/GpgKeyImportExporter.h"
|
||||
#include "core/function/gpg/GpgKeyManager.h"
|
||||
#include "core/function/gpg/GpgKeyOpera.h"
|
||||
#include "core/model/GpgImportInformation.h"
|
||||
#include "core/utils/GpgUtils.h"
|
||||
|
||||
const char *TEST_PRIVATE_KEY_DATA = R"(
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
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
|
||||
=OHnq
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
)";
|
||||
|
||||
namespace GpgFrontend::Test {
|
||||
TEST_F(GpgCoreTest, CoreDeleteSubkeyTestA) {
|
||||
auto info = GpgKeyImportExporter::GetInstance().ImportKey(
|
||||
GFBuffer(QString::fromLatin1(TEST_PRIVATE_KEY_DATA)));
|
||||
|
||||
ASSERT_EQ(info->not_imported, 0);
|
||||
ASSERT_EQ(info->imported, 1);
|
||||
|
||||
auto key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
auto subkeys = key.GetSubKeys();
|
||||
|
||||
ASSERT_EQ(subkeys->size(), 5);
|
||||
ASSERT_EQ((*subkeys)[2].GetID(), "2D1F9FC59B568A8C");
|
||||
|
||||
auto res = GpgKeyManager::GetInstance().DeleteSubkey(key, 2);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
subkeys = key.GetSubKeys();
|
||||
|
||||
ASSERT_EQ(subkeys->size(), 4);
|
||||
ASSERT_EQ((*subkeys)[2].GetID(), "CE038203C4D03C3D");
|
||||
|
||||
GpgKeyOpera::GetInstance().DeleteKey(key.GetId());
|
||||
}
|
||||
|
||||
TEST_F(GpgCoreTest, CoreSetOwnerTrustA) {
|
||||
auto info = GpgKeyImportExporter::GetInstance().ImportKey(
|
||||
GFBuffer(QString::fromLatin1(TEST_PRIVATE_KEY_DATA)));
|
||||
|
||||
ASSERT_EQ(info->not_imported, 0);
|
||||
ASSERT_EQ(info->imported, 1);
|
||||
|
||||
auto key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
auto res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 1);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
GpgKeyGetter::GetInstance().FlushKeyCache();
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
// why?
|
||||
ASSERT_EQ(key.GetOwnerTrustLevel(), 0);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 2);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
GpgKeyGetter::GetInstance().FlushKeyCache();
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
ASSERT_EQ(key.GetOwnerTrustLevel(), 2);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 3);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
GpgKeyGetter::GetInstance().FlushKeyCache();
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
ASSERT_EQ(key.GetOwnerTrustLevel(), 3);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 4);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
GpgKeyGetter::GetInstance().FlushKeyCache();
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
ASSERT_EQ(key.GetOwnerTrustLevel(), 4);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 5);
|
||||
ASSERT_TRUE(res);
|
||||
|
||||
GpgKeyGetter::GetInstance().FlushKeyCache();
|
||||
key = GpgKeyGetter::GetInstance(kGpgFrontendDefaultChannel)
|
||||
.GetKey("822D7E13F5B85D7D");
|
||||
ASSERT_TRUE(key.IsGood());
|
||||
|
||||
ASSERT_EQ(key.GetOwnerTrustLevel(), 5);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 0);
|
||||
ASSERT_FALSE(res);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, -1);
|
||||
ASSERT_FALSE(res);
|
||||
|
||||
res = GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, 6);
|
||||
ASSERT_FALSE(res);
|
||||
|
||||
GpgKeyOpera::GetInstance().DeleteKey(key.GetId());
|
||||
}
|
||||
|
||||
} // namespace GpgFrontend::Test
|
@ -31,6 +31,7 @@
|
||||
#include "core/GpgModel.h"
|
||||
#include "core/function/gpg/GpgKeyGetter.h"
|
||||
#include "core/function/gpg/GpgKeyImportExporter.h"
|
||||
#include "core/function/gpg/GpgKeyManager.h"
|
||||
#include "core/utils/CommonUtils.h"
|
||||
#include "core/utils/GpgUtils.h"
|
||||
#include "core/utils/IOUtils.h"
|
||||
@ -149,6 +150,11 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(int channel, const QString& key_id,
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
slot_refresh_subkey_list();
|
||||
|
||||
// set up signal
|
||||
connect(this, &KeyPairSubkeyTab::SignalKeyDatabaseRefresh,
|
||||
UISignalStation::GetInstance(),
|
||||
&UISignalStation::SignalKeyDatabaseRefresh);
|
||||
}
|
||||
|
||||
void KeyPairSubkeyTab::create_subkey_list() {
|
||||
@ -338,8 +344,13 @@ void KeyPairSubkeyTab::create_subkey_opera_menu() {
|
||||
connect(export_subkey_act_, &QAction::triggered, this,
|
||||
&KeyPairSubkeyTab::slot_export_subkey);
|
||||
|
||||
delete_subkey_act_ = new QAction(tr("Delete"));
|
||||
connect(delete_subkey_act_, &QAction::triggered, this,
|
||||
&KeyPairSubkeyTab::slot_delete_subkey);
|
||||
|
||||
subkey_opera_menu_->addAction(export_subkey_act_);
|
||||
subkey_opera_menu_->addAction(edit_subkey_act_);
|
||||
subkey_opera_menu_->addAction(delete_subkey_act_);
|
||||
}
|
||||
|
||||
void KeyPairSubkeyTab::slot_edit_subkey() {
|
||||
@ -359,6 +370,7 @@ void KeyPairSubkeyTab::contextMenuEvent(QContextMenuEvent* event) {
|
||||
|
||||
export_subkey_act_->setDisabled(!subkey.IsSecretKey());
|
||||
edit_subkey_act_->setDisabled(!subkey.IsSecretKey());
|
||||
delete_subkey_act_->setDisabled(!subkey.IsSecretKey());
|
||||
|
||||
subkey_opera_menu_->exec(event->globalPos());
|
||||
}
|
||||
@ -391,11 +403,7 @@ void KeyPairSubkeyTab::slot_export_subkey() {
|
||||
tr("Do you want to proceed with exporting this subkey?"),
|
||||
QMessageBox::Cancel | QMessageBox::Yes, QMessageBox::Cancel);
|
||||
|
||||
if (ret != QMessageBox::Yes) {
|
||||
QMessageBox::information(this, tr("Export Cancelled"),
|
||||
tr("The subkey export has been cancelled."));
|
||||
return;
|
||||
}
|
||||
if (ret != QMessageBox::Yes) return;
|
||||
|
||||
const auto& subkey = get_selected_subkey();
|
||||
|
||||
@ -431,4 +439,51 @@ void KeyPairSubkeyTab::slot_export_subkey() {
|
||||
}
|
||||
}
|
||||
|
||||
void KeyPairSubkeyTab::slot_delete_subkey() {
|
||||
const auto& subkey = get_selected_subkey();
|
||||
const auto subkeys = key_.GetSubKeys();
|
||||
|
||||
QString message = tr("<h3>You are about to delete the subkey:</h3><br />"
|
||||
"<b>KeyID:</b> %1<br /><br />"
|
||||
"This action is irreversible. Please confirm.")
|
||||
.arg(subkey.GetID());
|
||||
|
||||
int ret = QMessageBox::warning(
|
||||
this, tr("Delete Subkey Confirmation"), message,
|
||||
QMessageBox::Cancel | QMessageBox::Yes, QMessageBox::Cancel);
|
||||
|
||||
if (ret != QMessageBox::Yes) return;
|
||||
|
||||
int index = 0;
|
||||
for (const auto& sk : *subkeys) {
|
||||
if (sk.GetFingerprint() == subkey.GetFingerprint()) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
QMessageBox::critical(
|
||||
this, tr("Illegal Operation"),
|
||||
tr("Cannot delete the primary key or an invalid subkey."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto res = GpgKeyManager::GetInstance(current_gpg_context_channel_)
|
||||
.DeleteSubkey(key_, index);
|
||||
|
||||
if (!res) {
|
||||
QMessageBox::critical(this, tr("Operation Failed"),
|
||||
tr("The selected subkey could not be deleted. "
|
||||
"Please check your permissions or try again."));
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(
|
||||
this, tr("Operation Successful"),
|
||||
tr("The subkey with KeyID %1 has been successfully deleted.")
|
||||
.arg(subkey.GetID()));
|
||||
|
||||
emit SignalKeyDatabaseRefresh();
|
||||
}
|
||||
} // namespace GpgFrontend::UI
|
||||
|
@ -93,6 +93,7 @@ class KeyPairSubkeyTab : public QWidget {
|
||||
QAction* export_subkey_act_;
|
||||
|
||||
QAction* edit_subkey_act_;
|
||||
QAction* delete_subkey_act_;
|
||||
|
||||
private slots:
|
||||
|
||||
@ -138,6 +139,20 @@ class KeyPairSubkeyTab : public QWidget {
|
||||
*/
|
||||
void slot_export_subkey();
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
void slot_delete_subkey();
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
void SignalKeyDatabaseRefresh();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief
|
||||
|
@ -47,8 +47,8 @@ auto SetOwnerTrustLevel::Exec(int channel, const QString& key_id) -> bool {
|
||||
|
||||
QStringList items;
|
||||
|
||||
items << tr("Unknown") << tr("Undefined") << tr("Never") << tr("Marginal")
|
||||
<< tr("Full") << tr("Ultimate");
|
||||
items << tr("Undefined") << tr("Never") << tr("Marginal") << tr("Full")
|
||||
<< tr("Ultimate");
|
||||
bool ok;
|
||||
QString item = QInputDialog::getItem(this, tr("Modify Owner Trust Level"),
|
||||
tr("Trust for the Key Pair:"), items,
|
||||
@ -69,11 +69,6 @@ auto SetOwnerTrustLevel::Exec(int channel, const QString& key_id) -> bool {
|
||||
}
|
||||
|
||||
if (trust_level == 0) {
|
||||
QMessageBox::warning(
|
||||
this, tr("Warning"),
|
||||
QString(
|
||||
tr("Owner Trust Level cannot set to Unknown level, automately "
|
||||
"changing it into Undefined level.")));
|
||||
trust_level = 1;
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,8 @@ void MainWindow::recover_editor_unsaved_pages_from_cache() {
|
||||
auto title = unsaved_page_json["title"].toString();
|
||||
auto content = unsaved_page_json["content"].toString();
|
||||
|
||||
LOG_D() << "restoring tab, title: " << title;
|
||||
|
||||
if (first) {
|
||||
edit_->SlotCloseTab();
|
||||
first = false;
|
||||
|
Loading…
Reference in New Issue
Block a user