diff options
author | Saturneric <[email protected]> | 2021-05-28 19:21:46 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-05-28 19:21:46 +0000 |
commit | a5c3aa5ceff300cad9203f3620f16920e726a762 (patch) | |
tree | bb375530f126f29746f4f4aa10985831beefec79 | |
parent | Adjust part of the text of the UI interface of the UID operation tab. (diff) | |
download | GpgFrontend-a5c3aa5ceff300cad9203f3620f16920e726a762.tar.gz GpgFrontend-a5c3aa5ceff300cad9203f3620f16920e726a762.zip |
Make eligible keys enter the signature candidate list.
Added delete UID interface and function.
Added setting as the main UID function.
Added the delete key signature menu and function (there is a problem).
Improve the presentation of key list items
Improve the page function of KeyList.
Added pop-up menu for UID list operation on UIDTab interface.
Signed-off-by: Saturneric <[email protected]>
Diffstat (limited to '')
-rw-r--r-- | include/gpg/GpgContext.h | 6 | ||||
-rw-r--r-- | include/gpg/Signature.h | 10 | ||||
-rw-r--r-- | include/gpg/UID.h | 4 | ||||
-rw-r--r-- | include/ui/keypair_details/KeyPairUIDTab.h | 32 | ||||
-rw-r--r-- | include/ui/widgets/KeyList.h | 6 | ||||
-rw-r--r-- | src/gpg/GpgContext.cpp | 43 | ||||
-rw-r--r-- | src/gpg/Signature.cpp | 3 | ||||
-rw-r--r-- | src/gpg/UID.cpp | 3 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyNewUIDDialog.cpp | 2 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyPairDetailTab.cpp | 28 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyPairUIDTab.cpp | 320 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyUIDSignDialog.cpp | 10 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.cpp | 29 |
13 files changed, 422 insertions, 74 deletions
diff --git a/include/gpg/GpgContext.h b/include/gpg/GpgContext.h index ff4a9d20..a68c6490 100644 --- a/include/gpg/GpgContext.h +++ b/include/gpg/GpgContext.h @@ -110,12 +110,18 @@ namespace GpgME { bool signKey(const GpgKey &target, const QString& uid, const QDateTime *expires); + bool revSign(const GpgKey &key, const Signature &signature); + gpgme_signature_t verify(QByteArray *inBuffer, QByteArray *sigBuffer = nullptr); bool sign(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached = false); bool addUID(const GpgKey &key, const UID &uid); + bool revUID(const GpgKey &key, const UID &uid); + + bool setPrimaryUID(const GpgKey &key, const UID &uid); + /** * @details If text contains PGP-message, put a linebreak before the message, * so that gpgme can decrypt correctly diff --git a/include/gpg/Signature.h b/include/gpg/Signature.h index 3fa4414b..4d69c90b 100644 --- a/include/gpg/Signature.h +++ b/include/gpg/Signature.h @@ -30,25 +30,21 @@ struct Signature { bool revoked{}; - bool expired{}; - bool invalid{}; - bool exportable{}; + gpgme_error_t status{}; + + QString keyid; QString pubkey_algo; QDateTime create_time; - QDateTime expire_time; QString uid; - QString name; - QString email; - QString comment; Signature() = default; diff --git a/include/gpg/UID.h b/include/gpg/UID.h index d7a0f3bd..c048c7ad 100644 --- a/include/gpg/UID.h +++ b/include/gpg/UID.h @@ -41,6 +41,10 @@ struct UID { QString uid{}; + bool revoked; + + bool invalid; + QVector<Signature> signatures; UID() = default; diff --git a/include/ui/keypair_details/KeyPairUIDTab.h b/include/ui/keypair_details/KeyPairUIDTab.h index 70e657cd..0dd73f7b 100644 --- a/include/ui/keypair_details/KeyPairUIDTab.h +++ b/include/ui/keypair_details/KeyPairUIDTab.h @@ -46,17 +46,25 @@ private: void createManageUIDMenu(); + void createUIDPopupMenu(); + + void createSignPopupMenu(); + void getUIDChecked(QVector<UID> &uids); - GpgME::GpgContext *mCtx; + bool getUIDSelected(UID &uid); - const GpgKey &mKey; + bool getSignSelected(Signature &signature); + GpgME::GpgContext *mCtx; + const GpgKey &mKey; QTableWidget *uidList{}; - QTableWidget *sigList{}; - - QMenu *manageUIDMenu; + QMenu *manageSelectedUIDMenu; + QMenu *uidPopupMenu; + QMenu *signPopupMenu; + QVector<const UID *> buffered_uids; + QVector<const Signature *> buffered_signatures; private slots: @@ -66,10 +74,24 @@ private slots: void slotAddSign(); + void slotAddSignSingle(); + void slotAddUID(); + void slotDelUID(); + + void slotDelUIDSingle(); + + void slotSetPrimaryUID(); + + void slotDelSign(); + static void slotAddUIDResult(int result); +protected: + + void contextMenuEvent(QContextMenuEvent *event) override; + }; diff --git a/include/ui/widgets/KeyList.h b/include/ui/widgets/KeyList.h index 4bdafc17..0d9b07dc 100644 --- a/include/ui/widgets/KeyList.h +++ b/include/ui/widgets/KeyList.h @@ -65,6 +65,8 @@ public: void setExcludeKeys(std::initializer_list<QString> key_ids); + void setFilter(std::function<bool(const GpgKey&)> filter); + void setColumnWidth(int row, int size); void addMenuAction(QAction *act); @@ -93,6 +95,7 @@ public slots: void uploadKeyToServer(QByteArray *keys); private: + void importKeys(QByteArray inBuffer); GpgME::GpgContext *mCtx; @@ -104,6 +107,8 @@ private: KeyListColumn::InfoType mInfoType; QVector<QString> excluded_key_ids; + std::function<bool(const GpgKey &)> mFilter = nullptr; + private slots: @@ -111,6 +116,7 @@ private slots: protected: + void contextMenuEvent(QContextMenuEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override; diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index b72eda73..51ee07b5 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -982,6 +982,49 @@ namespace GpgME { } + bool GpgContext::revUID(const GpgKey &key, const UID &uid) { + auto gpgmeError = gpgme_op_revuid(mCtx, key.key_refer, uid.uid.toUtf8().constData(), 0); + if(gpgmeError == GPG_ERR_NO_ERROR) { + emit signalKeyUpdated(key.id); + return true; + } + else { + checkErr(gpgmeError); + return false; + } + } + + bool GpgContext::setPrimaryUID(const GpgKey &key, const UID &uid) { + auto gpgmeError = gpgme_op_set_uid_flag(mCtx, key.key_refer, + uid.uid.toUtf8().constData(), "primary", nullptr); + if(gpgmeError == GPG_ERR_NO_ERROR) { + emit signalKeyUpdated(key.id); + return true; + } + else { + checkErr(gpgmeError); + return false; + } + } + + bool GpgContext::revSign(const GpgKey &key, const Signature &signature) { + + auto signing_key = getKeyById(signature.keyid); + + auto gpgmeError = gpgme_op_revsig(mCtx, key.key_refer, + signing_key.key_refer, + signature.uid.toUtf8().constData(), 0); + if(gpgmeError == GPG_ERR_NO_ERROR) { + emit signalKeyUpdated(key.id); + return true; + } + else { + checkErr(gpgmeError); + return false; + } + return false; + } + } diff --git a/src/gpg/Signature.cpp b/src/gpg/Signature.cpp index 8e82c507..079f8a05 100644 --- a/src/gpg/Signature.cpp +++ b/src/gpg/Signature.cpp @@ -26,7 +26,8 @@ Signature::Signature(gpgme_key_sig_t key_sig) : revoked(key_sig->revoked), expired(key_sig->expired), invalid(key_sig->invalid), - exportable(key_sig->exportable), pubkey_algo(gpgme_pubkey_algo_name(key_sig->pubkey_algo)), + exportable(key_sig->exportable), status(key_sig->status), + keyid(key_sig->keyid), pubkey_algo(gpgme_pubkey_algo_name(key_sig->pubkey_algo)), uid(key_sig->uid), name(key_sig->name), email(key_sig->email), comment(key_sig->comment), create_time(QDateTime::fromTime_t(key_sig->timestamp)), expire_time(QDateTime::fromTime_t(key_sig->expires)){ diff --git a/src/gpg/UID.cpp b/src/gpg/UID.cpp index 62632e8f..a4e6f342 100644 --- a/src/gpg/UID.cpp +++ b/src/gpg/UID.cpp @@ -5,7 +5,8 @@ #include "gpg/UID.h" UID::UID(gpgme_user_id_t user_id) : - uid(user_id->uid), name(user_id->name), email(user_id->email), comment(user_id->comment) { + uid(user_id->uid), name(user_id->name), email(user_id->email), comment(user_id->comment), + revoked(user_id->revoked), invalid(user_id->invalid) { auto sig = user_id->signatures; diff --git a/src/ui/keypair_details/KeyNewUIDDialog.cpp b/src/ui/keypair_details/KeyNewUIDDialog.cpp index 9a70b102..a132bdf9 100644 --- a/src/ui/keypair_details/KeyNewUIDDialog.cpp +++ b/src/ui/keypair_details/KeyNewUIDDialog.cpp @@ -60,7 +60,7 @@ void KeyNewUIDDialog::slotCreateNewUID() { emit finished(1); } else { - emit finished(0); + emit finished(-1); } } else { diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index 873b478c..441fae77 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -67,18 +67,20 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &key, QW vboxOD->addWidget(emailVarLabel, 1, 1); vboxOD->addWidget(commentVarLabel, 2, 1); - vboxKD->addWidget(new QLabel(tr("Key size:")), 0, 0); - vboxKD->addWidget(new QLabel(tr("Expires on: ")), 1, 0); - vboxKD->addWidget(new QLabel(tr("Algorithm: ")), 3, 0); - vboxKD->addWidget(new QLabel(tr("Last Update: ")), 4, 0); - vboxKD->addWidget(new QLabel(tr("Key ID: ")), 5, 0); - vboxKD->addWidget(new QLabel(tr("Usage: ")), 6, 0); - vboxKD->addWidget(keySizeVarLabel, 0, 1); - vboxKD->addWidget(expireVarLabel, 1, 1); - vboxKD->addWidget(algorithmVarLabel, 3, 1); - vboxKD->addWidget(createdVarLabel, 4, 1); - vboxKD->addWidget(keyidVarLabel, 5, 1); - vboxKD->addWidget(usageVarLabel, 6, 1); + vboxKD->addWidget(new QLabel(tr("Key ID: ")), 0, 0); + vboxKD->addWidget(new QLabel(tr("Algorithm: ")), 1, 0); + vboxKD->addWidget(new QLabel(tr("Key size:")), 2, 0); + vboxKD->addWidget(new QLabel(tr("Usage: ")), 3, 0); + vboxKD->addWidget(new QLabel(tr("Expires on: ")), 4, 0); + vboxKD->addWidget(new QLabel(tr("Last Update: ")), 5, 0); + + + vboxKD->addWidget(keySizeVarLabel, 2, 1); + vboxKD->addWidget(expireVarLabel, 4, 1); + vboxKD->addWidget(algorithmVarLabel, 1, 1); + vboxKD->addWidget(createdVarLabel, 5, 1); + vboxKD->addWidget(keyidVarLabel, 0, 1); + vboxKD->addWidget(usageVarLabel, 3, 1); ownerBox->setLayout(vboxOD); mvbox->addWidget(ownerBox); @@ -88,7 +90,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &key, QW fingerPrintVarLabel = new QLabel(beautifyFingerprint(key.fpr)); fingerPrintVarLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - fingerPrintVarLabel->setStyleSheet("margin-left: 5; margin-right: 5;"); + fingerPrintVarLabel->setStyleSheet("margin-left: 0; margin-right: 5;"); auto *hboxFP = new QHBoxLayout(); hboxFP->addWidget(fingerPrintVarLabel); diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp index 82d27262..40316163 100644 --- a/src/ui/keypair_details/KeyPairUIDTab.cpp +++ b/src/ui/keypair_details/KeyPairUIDTab.cpp @@ -11,13 +11,15 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget createUIDList(); createSignList(); createManageUIDMenu(); + createUIDPopupMenu(); + createSignPopupMenu(); auto uidButtonsLayout = new QGridLayout(); auto addUIDButton = new QPushButton(tr("New UID")); auto manageUIDButton = new QPushButton(tr("UID Management")); - manageUIDButton->setMenu(manageUIDMenu); + manageUIDButton->setMenu(manageSelectedUIDMenu); uidButtonsLayout->addWidget(addUIDButton, 0, 1); uidButtonsLayout->addWidget(manageUIDButton, 0, 2); @@ -28,16 +30,14 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget gridLayout->addWidget(sigList, 2, 0); - setLayout(gridLayout); - connect(addUIDButton, SIGNAL(clicked(bool)), this, SLOT(slotAddUID())); - connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshUIDList())); - connect(uidList, SIGNAL(itemSelectionChanged()), this, SLOT(slotRefreshSigList())); - slotRefreshUIDList(); + setLayout(gridLayout); setAttribute(Qt::WA_DeleteOnClose, true); + + slotRefreshUIDList(); } void KeyPairUIDTab::createUIDList() { @@ -73,16 +73,16 @@ void KeyPairUIDTab::createSignList() { sigList->setShowGrid(false); sigList->setSelectionBehavior(QAbstractItemView::SelectRows); - // tableitems not editable + // table items not editable sigList->setEditTriggers(QAbstractItemView::NoEditTriggers); - // no focus (rectangle around tableitems) + // no focus (rectangle around table items) // may be it should focus on whole row sigList->setFocusPolicy(Qt::NoFocus); sigList->setAlternatingRowColors(true); QStringList labels; - labels << tr("Type") << tr("Name") << tr("Email") << tr("Create Time") << tr("Valid Time"); + labels << tr("Key ID") << tr("Name") << tr("Email") << tr("Create Time") << tr("Valid Time"); sigList->setHorizontalHeaderLabels(labels); sigList->horizontalHeader()->setStretchLastSection(true); @@ -92,18 +92,28 @@ void KeyPairUIDTab::slotRefreshUIDList() { int row = 0; - uidList->setRowCount(mKey.uids.size()); uidList->setSelectionMode(QAbstractItemView::SingleSelection); - for(const auto& uid : mKey.uids) { + this->buffered_uids.clear(); + + for(const auto &uid : mKey.uids) { + if(uid.invalid || uid.revoked) { + continue; + } + this->buffered_uids.push_back(&uid); + } + + uidList->setRowCount(buffered_uids.size()); + + for(const auto& uid : buffered_uids) { - auto *tmp0 = new QTableWidgetItem(uid.name); + auto *tmp0 = new QTableWidgetItem(uid->name); uidList->setItem(row, 1, tmp0); - auto *tmp1 = new QTableWidgetItem(uid.email); + auto *tmp1 = new QTableWidgetItem(uid->email); uidList->setItem(row, 2, tmp1); - auto *tmp2 = new QTableWidgetItem(uid.comment); + auto *tmp2 = new QTableWidgetItem(uid->comment); uidList->setItem(row, 3, tmp2); auto *tmp3 = new QTableWidgetItem(QString::number(row)); @@ -120,29 +130,47 @@ void KeyPairUIDTab::slotRefreshUIDList() { void KeyPairUIDTab::slotRefreshSigList() { int uidRow = 0, sigRow = 0; - for(const auto& uid : mKey.uids) { + for(const auto& uid : buffered_uids) { - // Only Show Selected UID's Signatures + // Only Show Selected UID Signatures if(!uidList->item(uidRow++, 0)->isSelected()) { continue; } - sigList->setRowCount(uid.signatures.size()); + buffered_signatures.clear(); - for(const auto &sig : uid.signatures) { - auto *tmp0 = new QTableWidgetItem(sig.pubkey_algo); + for(const auto &sig : uid->signatures) { + if(sig.invalid || sig.revoked) { + continue; + } + buffered_signatures.push_back(&sig); + } + + sigList->setRowCount(buffered_signatures.size()); + + for(const auto &sig : buffered_signatures) { + + auto *tmp0 = new QTableWidgetItem(sig->keyid); sigList->setItem(sigRow, 0, tmp0); - auto *tmp2 = new QTableWidgetItem(sig.name); - sigList->setItem(sigRow, 1, tmp2); + if(gpgme_err_code(sig->status) == GPG_ERR_NO_PUBKEY) { + auto *tmp2 = new QTableWidgetItem("<Unknown>"); + sigList->setItem(sigRow, 1, tmp2); - auto *tmp3 = new QTableWidgetItem(sig.email); - sigList->setItem(sigRow, 2, tmp3); + auto *tmp3 = new QTableWidgetItem("<Unknown>"); + sigList->setItem(sigRow, 2, tmp3); + } else { + auto *tmp2 = new QTableWidgetItem(sig->name); + sigList->setItem(sigRow, 1, tmp2); - auto *tmp4 = new QTableWidgetItem(sig.create_time.toString()); + auto *tmp3 = new QTableWidgetItem(sig->email); + sigList->setItem(sigRow, 2, tmp3); + } + + auto *tmp4 = new QTableWidgetItem(sig->create_time.toString()); sigList->setItem(sigRow, 3, tmp4); - auto *tmp5 = new QTableWidgetItem(sig.expire_time.toString()); + auto *tmp5 = new QTableWidgetItem(sig->expire_time.toString()); sigList->setItem(sigRow, 4, tmp5); sigRow++; @@ -155,13 +183,12 @@ void KeyPairUIDTab::slotRefreshSigList() { void KeyPairUIDTab::slotAddSign() { QVector<UID> selected_uids; - getUIDChecked(selected_uids); if(selected_uids.isEmpty()) { - auto emptyUIDMsg = new QMessageBox(); - emptyUIDMsg->setText("Please select one or more UIDs before doing this operation."); - emptyUIDMsg->exec(); + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("Please select one or more UIDs before doing this operation.")); return; } @@ -169,25 +196,30 @@ void KeyPairUIDTab::slotAddSign() { keySignDialog->show(); } + + void KeyPairUIDTab::getUIDChecked(QVector<UID> &selected_uids) { - auto &uids = mKey.uids; + auto &uids = buffered_uids; for (int i = 0; i < uidList->rowCount(); i++) { if (uidList->item(i, 0)->checkState() == Qt::Checked) { - selected_uids.push_back(uids[i]); + selected_uids.push_back(*uids[i]); } } } void KeyPairUIDTab::createManageUIDMenu() { - manageUIDMenu = new QMenu(this); + manageSelectedUIDMenu = new QMenu(this); auto *signUIDAct = new QAction(tr("Sign Selected UID(s)"), this); connect(signUIDAct, SIGNAL(triggered()), this, SLOT(slotAddSign())); + auto *delUIDAct = new QAction(tr("Delete Selected UID(s)"), this); + connect(delUIDAct, SIGNAL(triggered()), this, SLOT(slotDelUID())); - manageUIDMenu->addAction(signUIDAct); + manageSelectedUIDMenu->addAction(signUIDAct); + manageSelectedUIDMenu->addAction(delUIDAct); } void KeyPairUIDTab::slotAddUID() { @@ -198,13 +230,231 @@ void KeyPairUIDTab::slotAddUID() { } void KeyPairUIDTab::slotAddUIDResult(int result) { - if(result) { + if(result == 1) { QMessageBox::information(nullptr, tr("Successful Operation"), tr("Successfully added a new UID.")); - } else { + } else if (result == -1) { QMessageBox::critical(nullptr, tr("Operation Failed"), tr("An error occurred during the operation.")); } } + +void KeyPairUIDTab::slotDelUID() { + + QVector<UID> selected_uids; + getUIDChecked(selected_uids); + + if(selected_uids.isEmpty()) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("Please select one or more UIDs before doing this operation.")); + return; + } + + QString keynames; + for (const auto &uid : selected_uids) { + keynames.append(uid.name); + keynames.append("<i> <"); + keynames.append(uid.email); + keynames.append("> </i><br/>"); + } + + int ret = QMessageBox::warning(this, tr("Deleting UIDs"), + "<b>"+tr("Are you sure that you want to delete the following uids?")+"</b><br/><br/>"+keynames+ + +"<br/>"+tr("The action can not be undone."), + QMessageBox::No | QMessageBox::Yes); + + + bool if_success = true; + + if (ret == QMessageBox::Yes) { + for(const auto &uid : selected_uids) { + if(!mCtx->revUID(mKey, uid)) { + if_success = false; + } + } + + if(!if_success) { + QMessageBox::critical(nullptr, + tr("Operation Failed"), + tr("An error occurred during the operation.")); + } + + } +} + +void KeyPairUIDTab::slotSetPrimaryUID() { + + UID selected_uid; + + if(!getUIDSelected(selected_uid)) { + auto emptyUIDMsg = new QMessageBox(); + emptyUIDMsg->setText("Please select one UID before doing this operation."); + emptyUIDMsg->exec(); + return; + } + + QString keynames; + + keynames.append(selected_uid.name); + keynames.append("<i> <"); + keynames.append(selected_uid.email); + keynames.append("> </i><br/>"); + + int ret = QMessageBox::warning(this, tr("Set Primary UID"), + "<b>"+tr("Are you sure that you want to set the Primary UID to?")+"</b><br/><br/>"+keynames+ + +"<br/>"+tr("The action can not be undone."), + QMessageBox::No | QMessageBox::Yes); + + if (ret == QMessageBox::Yes) { + if(!mCtx->setPrimaryUID(mKey, selected_uid)) { + QMessageBox::critical(nullptr, + tr("Operation Failed"), + tr("An error occurred during the operation.")); + } + } +} + +bool KeyPairUIDTab::getUIDSelected(UID &uid) { + auto &uids = buffered_uids; + for (int i = 0; i < uidList->rowCount(); i++) { + if (uidList->item(i, 0)->isSelected()) { + uid = *uids[i]; + return true; + } + } + return false; +} + +bool KeyPairUIDTab::getSignSelected(Signature &signature) { + auto &signatures = buffered_signatures; + for (int i = 0; i < sigList->rowCount(); i++) { + if (sigList->item(i, 0)->isSelected()) { + signature = *signatures[i]; + return true; + } + } + return false; +} + +void KeyPairUIDTab::createUIDPopupMenu() { + + uidPopupMenu = new QMenu(this); + + auto *serPrimaryUIDAct = new QAction(tr("Set As Primary"), this); + connect(serPrimaryUIDAct, SIGNAL(triggered()), this, SLOT(slotSetPrimaryUID())); + auto *signUIDAct = new QAction(tr("Sign UID"), this); + connect(signUIDAct, SIGNAL(triggered()), this, SLOT(slotAddSignSingle())); + auto *delUIDAct = new QAction(tr("Delete UID"), this); + connect(delUIDAct, SIGNAL(triggered()), this, SLOT(slotDelUIDSingle())); + + uidPopupMenu->addAction(serPrimaryUIDAct); + uidPopupMenu->addAction(signUIDAct); + uidPopupMenu->addAction(delUIDAct); +} + +void KeyPairUIDTab::contextMenuEvent(QContextMenuEvent *event) { + if (uidList->selectedItems().length() > 0 && sigList->selectedItems().isEmpty()) { + uidPopupMenu->exec(event->globalPos()); + } + + if (!sigList->selectedItems().isEmpty()) { + signPopupMenu->exec(event->globalPos()); + } +} + +void KeyPairUIDTab::slotAddSignSingle() { + + UID selected_uid; + + if(!getUIDSelected(selected_uid)) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("Please select one UID before doing this operation.")); + return; + } + + auto selected_uids = QVector<UID>({ selected_uid }); + auto keySignDialog = new KeyUIDSignDialog(mCtx, mKey, selected_uids, this); + keySignDialog->show(); +} + +void KeyPairUIDTab::slotDelUIDSingle() { + UID selected_uid; + + if(!getUIDSelected(selected_uid)) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("Please select one UID before doing this operation.")); + return; + } + + QString keynames; + + keynames.append(selected_uid.name); + keynames.append("<i> <"); + keynames.append(selected_uid.email); + keynames.append("> </i><br/>"); + + int ret = QMessageBox::warning(this, tr("Deleting UID"), + "<b>"+tr("Are you sure that you want to delete the following uid?")+"</b><br/><br/>"+keynames+ + +"<br/>"+tr("The action can not be undone."), + QMessageBox::No | QMessageBox::Yes); + + if (ret == QMessageBox::Yes) { + if(!mCtx->revUID(mKey, selected_uid)) { + QMessageBox::critical(nullptr, + tr("Operation Failed"), + tr("An error occurred during the operation.")); + } + } +} + +void KeyPairUIDTab::createSignPopupMenu() { + signPopupMenu = new QMenu(this); + + auto *delSignAct = new QAction(tr("Delete Signature"), this); + connect(delSignAct, SIGNAL(triggered()), this, SLOT(slotDelSign())); + + signPopupMenu->addAction(delSignAct); +} + +void KeyPairUIDTab::slotDelSign() { + Signature selected_sign; + + if(!getSignSelected(selected_sign)) { + QMessageBox::information(nullptr, + tr("Invalid Operation"), + tr("Please select one Signature before doing this operation.")); + return; + } + + if(gpgme_err_code(selected_sign.status) == GPG_ERR_NO_PUBKEY) { + QMessageBox::critical(nullptr, + tr("Invalid Operation"), + tr("To delete the signature, you need to have its corresponding public key in the local database.")); + return; + } + + QString keynames; + + keynames.append(selected_sign.name); + keynames.append("<i> <"); + keynames.append(selected_sign.email); + keynames.append("> </i><br/>"); + + int ret = QMessageBox::warning(this, tr("Deleting Signature"), + "<b>"+tr("Are you sure that you want to delete the following signature?")+"</b><br/><br/>"+keynames+ + +"<br/>"+tr("The action can not be undone."), + QMessageBox::No | QMessageBox::Yes); + + if (ret == QMessageBox::Yes) { + if(!mCtx->revSign(mKey, selected_sign)) { + QMessageBox::critical(nullptr, + tr("Operation Failed"), + tr("An error occurred during the operation.")); + } + } +} diff --git a/src/ui/keypair_details/KeyUIDSignDialog.cpp b/src/ui/keypair_details/KeyUIDSignDialog.cpp index 64a15865..cb4056b3 100644 --- a/src/ui/keypair_details/KeyUIDSignDialog.cpp +++ b/src/ui/keypair_details/KeyUIDSignDialog.cpp @@ -12,6 +12,10 @@ KeyUIDSignDialog::KeyUIDSignDialog(GpgME::GpgContext *ctx, const GpgKey &key, co KeyListColumn::NAME | KeyListColumn::EmailAddress, this); + mKeyList->setFilter([](const GpgKey &key) -> bool { + if(key.disabled || !key.can_sign) return false; + else return true; + }); mKeyList->setExcludeKeys({key.id}); mKeyList->slotRefresh(); @@ -73,9 +77,9 @@ void KeyUIDSignDialog::slotSignKey(bool clicked) { // Sign For mKey if (!mCtx->signKey(mKey, uid.uid, &expires)) { QMessageBox::critical(nullptr, - tr("Operation Unsuccessful"), - QString("%1 <%2>"+tr(" signature operation failed for UID ") + "%3") - .arg(mKey.name, mKey.email, uid.uid)); + tr("Unsuccessful Operation"), + QString(tr("Signature operation failed for UID ") + "%1") + .arg(uid.uid)); } } diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index d8e4a094..2082bbc9 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -42,6 +42,7 @@ KeyList::KeyList(GpgME::GpgContext *ctx, mKeyList->setShowGrid(false); mKeyList->sortByColumn(2, Qt::AscendingOrder); mKeyList->setSelectionBehavior(QAbstractItemView::SelectRows); + mKeyList->setSelectionMode( QAbstractItemView::SingleSelection ); // tableitems not editable mKeyList->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -105,16 +106,24 @@ void KeyList::slotRefresh() int row_count = 0; while (it != keys.end()) { + if(mFilter != nullptr) { + if(!mFilter(*it)) { + it = keys.erase(it); + continue; + } + } if(!excluded_key_ids.isEmpty()){ - bool if_find = false; - for(const auto &key_id : excluded_key_ids) { - if(it->id == key_id) { - it = keys.erase(it); - if_find = true; - break; - } + + auto iterator = std::find_if(excluded_key_ids.begin(), excluded_key_ids.end(), + [it] (const auto &key_id) -> bool { + if(it->id == key_id) return true; + else return false; + }); + + if(iterator != excluded_key_ids.end()) { + it = keys.erase(it); + continue; } - if(if_find) continue; } if (mSelectType == KeyListRow::ONLY_SECRET_KEY && !it->is_private_key) { it = keys.erase(it); @@ -423,3 +432,7 @@ void KeyList::setExcludeKeys(std::initializer_list<QString> key_ids) { excluded_key_ids.push_back(key_id); } } + +void KeyList::setFilter(std::function<bool(const GpgKey &)> filter) { + this->mFilter = filter; +} |