Commit 7dc62e3c authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Factor widget displaying OpenPGP keys out of PGPCardWidget

GnuPG-bug-id: 4876
parent 6ca23e05
......@@ -115,6 +115,7 @@ set(_kleopatra_SRCS
view/keytreeview.cpp
view/searchbar.cpp
view/smartcardwidget.cpp
view/openpgpkeycardwidget.cpp
view/padwidget.cpp
view/pgpcardwidget.cpp
view/pivcardwidget.cpp
......
/* view/openpgpkeycardwidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "openpgpkeycardwidget.h"
#include "smartcard/card.h"
#include "smartcard/keypairinfo.h"
#include "smartcard/openpgpcard.h"
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <KLocalizedString>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <gpgme++/key.h>
using namespace Kleo;
using namespace SmartCard;
namespace
{
struct KeyWidgets {
std::string keyGrip;
QLabel *keyFingerprint = nullptr;
QPushButton *createCSRButton = nullptr;
};
KeyWidgets createKeyWidgets(const KeyPairInfo &keyInfo, QWidget *parent)
{
KeyWidgets keyWidgets;
keyWidgets.keyFingerprint = new QLabel{parent};
keyWidgets.keyFingerprint->setTextInteractionFlags(Qt::TextBrowserInteraction);
if (keyInfo.canCertify() || keyInfo.canSign() || keyInfo.canAuthenticate())
{
keyWidgets.createCSRButton = new QPushButton{i18nc("@action:button", "Create CSR"), parent};
keyWidgets.createCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for this key"));
keyWidgets.createCSRButton->setEnabled(false);
}
return keyWidgets;
}
}
class OpenPGPKeyCardWidget::Private
{
public:
explicit Private(OpenPGPKeyCardWidget *q);
~Private() = default;
void update(const Card *card);
private:
void updateKeyWidgets(const std::string &keyRef, const Card *card);
private:
OpenPGPKeyCardWidget *const q;
std::map<std::string, KeyWidgets> mKeyWidgets;
};
OpenPGPKeyCardWidget::Private::Private(OpenPGPKeyCardWidget *q)
: q{q}
{
auto grid = new QGridLayout{q};
grid->setContentsMargins(0, 0, 0, 0);
for (const auto &keyInfo : OpenPGPCard::supportedKeys()) {
const KeyWidgets keyWidgets = createKeyWidgets(keyInfo, q);
if (keyWidgets.createCSRButton) {
const std::string keyRef = keyInfo.keyRef;
connect(keyWidgets.createCSRButton, &QPushButton::clicked,
q, [q, keyRef] () { Q_EMIT q->createCSRRequested(keyRef); });
}
const int row = grid->rowCount();
grid->addWidget(new QLabel{OpenPGPCard::keyDisplayName(keyInfo.keyRef)}, row, 0);
grid->addWidget(keyWidgets.keyFingerprint, row, 1);
if (keyWidgets.createCSRButton) {
grid->addWidget(keyWidgets.createCSRButton, row, 2);
}
mKeyWidgets.insert({keyInfo.keyRef, keyWidgets});
}
grid->setColumnStretch(grid->columnCount(), 1);
}
void OpenPGPKeyCardWidget::Private::update(const Card *card)
{
updateKeyWidgets(OpenPGPCard::pgpSigKeyRef(), card);
updateKeyWidgets(OpenPGPCard::pgpEncKeyRef(), card);
updateKeyWidgets(OpenPGPCard::pgpAuthKeyRef(), card);
}
void OpenPGPKeyCardWidget::Private::updateKeyWidgets(const std::string &keyRef, const Card *card)
{
KeyWidgets widgets = mKeyWidgets.at(keyRef);
const std::string grip = card ? card->keyInfo(keyRef).grip : widgets.keyGrip;
widgets.keyGrip = grip;
if (grip.empty()) {
widgets.keyFingerprint->setText(i18n("Slot empty"));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(false);
}
} else {
if (card) {
// update information if called with card
const std::string fpr = card->keyFingerprint(keyRef);
widgets.keyFingerprint->setText(QString::fromStdString(fpr));
if (fpr.size() >= 16) {
const std::string keyid = fpr.substr(fpr.size() - 16);
const auto subkeys = KeyCache::instance()->findSubkeysByKeyID({keyid});
if (subkeys.empty() || subkeys[0].isNull()) {
widgets.keyFingerprint->setToolTip(i18n("Public key not found."));
} else {
QStringList toolTips;
toolTips.reserve(subkeys.size());
for (const auto &sub: subkeys) {
// Yep you can have one subkey associated with multiple primary keys.
toolTips << Formatting::toolTip(sub.parent(), Formatting::Validity |
Formatting::StorageLocation |
Formatting::ExpiryDates |
Formatting::UserIDs |
Formatting::Fingerprint);
}
widgets.keyFingerprint->setToolTip(toolTips.join(QLatin1String("<br/>")));
}
}
}
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(true);
}
}
}
OpenPGPKeyCardWidget::OpenPGPKeyCardWidget(QWidget *parent)
: QWidget{parent}
, d{std::make_unique<Private>(this)}
{
}
OpenPGPKeyCardWidget::~OpenPGPKeyCardWidget() = default;
void OpenPGPKeyCardWidget::update(const Card *card)
{
d->update(card);
}
/* view/openpgpkeycardwidget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QWidget>
#include <memory>
namespace Kleo
{
namespace SmartCard
{
class Card;
}
class OpenPGPKeyCardWidget: public QWidget
{
Q_OBJECT
public:
explicit OpenPGPKeyCardWidget(QWidget *parent = nullptr);
~OpenPGPKeyCardWidget() override;
public Q_SLOTS:
void update(const SmartCard::Card *card);
Q_SIGNALS:
void createCSRRequested(const std::string &keyRef);
private:
class Private;
std::unique_ptr<Private> d;
};
}
......@@ -11,6 +11,8 @@
#include "pgpcardwidget.h"
#include "openpgpkeycardwidget.h"
#include "kleopatra_debug.h"
#include "commands/createcsrforcardkeycommand.h"
......@@ -20,6 +22,7 @@
#include "smartcard/readerstatus.h"
#include "dialogs/gencardkeydialog.h"
#include <Libkleo/GnuPG>
#include <QProgressDialog>
......@@ -98,15 +101,6 @@ class GenKeyThread: public QThread
std::string mBkpFile;
};
static void layoutKeyWidgets(QGridLayout *grid, const QString &keyName, const PGPCardWidget::KeyWidgets &keyWidgets)
{
int row = grid->rowCount();
grid->addWidget(new QLabel(keyName), row, 0);
grid->addWidget(keyWidgets.keyFingerprint, row, 1);
if (keyWidgets.createCSRButton) {
grid->addWidget(keyWidgets.createCSRButton, row, 2);
}
}
} // Namespace
PGPCardWidget::PGPCardWidget(QWidget *parent):
......@@ -182,13 +176,9 @@ PGPCardWidget::PGPCardWidget(QWidget *parent):
// The keys
areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:"))));
auto keysGrid = new QGridLayout;
for (const auto &keyInfo : OpenPGPCard::supportedKeys()) {
KeyWidgets keyWidgets = createKeyWidgets(keyInfo);
layoutKeyWidgets(keysGrid, OpenPGPCard::keyDisplayName(keyInfo.keyRef), keyWidgets);
}
keysGrid->setColumnStretch(keysGrid->columnCount(), 1);
areaVLay->addLayout(keysGrid);
mKeysWidget = new OpenPGPKeyCardWidget{this};
areaVLay->addWidget(mKeysWidget);
connect(mKeysWidget, &OpenPGPKeyCardWidget::createCSRRequested, this, &PGPCardWidget::createCSR);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
......@@ -242,24 +232,6 @@ PGPCardWidget::PGPCardWidget(QWidget *parent):
areaVLay->addStretch(1);
}
PGPCardWidget::KeyWidgets PGPCardWidget::createKeyWidgets(const KeyPairInfo &keyInfo)
{
const std::string keyRef = keyInfo.keyRef;
KeyWidgets keyWidgets;
keyWidgets.keyFingerprint = new QLabel(this);
keyWidgets.keyFingerprint->setTextInteractionFlags(Qt::TextBrowserInteraction);
if (keyInfo.canCertify() || keyInfo.canSign() || keyInfo.canAuthenticate())
{
keyWidgets.createCSRButton = new QPushButton(i18nc("@action:button", "Create CSR"), this);
keyWidgets.createCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for this key"));
keyWidgets.createCSRButton->setEnabled(false);
connect(keyWidgets.createCSRButton, &QPushButton::clicked,
this, [this, keyRef] () { createCSR(keyRef); });
}
mKeyWidgets.insert(keyRef, keyWidgets);
return keyWidgets;
}
void PGPCardWidget::setCard(const OpenPGPCard *card)
{
const QString version = card->displayAppVersion();
......@@ -282,9 +254,8 @@ void PGPCardWidget::setCard(const OpenPGPCard *card)
QStringLiteral("<a href=\"%1\">%1</a>").arg(url.toHtmlEscaped()));
mUrlLabel->setOpenExternalLinks(true);
updateKeyWidgets(OpenPGPCard::pgpSigKeyRef(), card);
updateKeyWidgets(OpenPGPCard::pgpEncKeyRef(), card);
updateKeyWidgets(OpenPGPCard::pgpAuthKeyRef(), card);
mKeysWidget->update(card);
mCardIsEmpty = card->keyFingerprint(OpenPGPCard::pgpSigKeyRef()).empty()
&& card->keyFingerprint(OpenPGPCard::pgpEncKeyRef()).empty()
&& card->keyFingerprint(OpenPGPCard::pgpAuthKeyRef()).empty();
......@@ -535,46 +506,4 @@ void PGPCardWidget::createCSR(const std::string &keyref)
cmd->start();
}
void PGPCardWidget::updateKeyWidgets(const std::string &keyRef, const OpenPGPCard *card)
{
KeyWidgets widgets = mKeyWidgets.value(keyRef);
const std::string grip = card ? card->keyInfo(keyRef).grip : widgets.keyGrip;
widgets.keyGrip = grip;
if (grip.empty()) {
widgets.keyFingerprint->setText(i18n("Slot empty"));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(false);
}
} else {
if (card) {
// update information if called with card
std::string fpr = card->keyFingerprint(keyRef);
widgets.keyFingerprint->setText(QString::fromStdString(fpr));
std::string keyid = fpr;
keyid.erase(0, keyid.size() - 16);
const auto subkeys = KeyCache::instance()->findSubkeysByKeyID({keyid});
if (subkeys.empty() || subkeys[0].isNull()) {
widgets.keyFingerprint->setToolTip(i18n("Public key not found."));
} else {
QStringList toolTips;
toolTips.reserve(subkeys.size());
for (const auto &sub: subkeys) {
// Yep you can have one subkey associated with multiple
// primary keys.
toolTips << Formatting::toolTip(sub.parent(), Formatting::Validity |
Formatting::StorageLocation |
Formatting::ExpiryDates |
Formatting::UserIDs |
Formatting::Fingerprint);
}
widgets.keyFingerprint->setToolTip(toolTips.join(QLatin1String("<br/>")));
}
}
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(true);
}
}
}
#include "pgpcardwidget.moc"
......@@ -25,6 +25,7 @@ class QPushButton;
namespace Kleo
{
class GenCardKeyDialog;
class OpenPGPKeyCardWidget;
namespace SmartCard
{
......@@ -42,12 +43,6 @@ public:
void doGenKey(GenCardKeyDialog *dlg);
void genKeyDone(const GpgME::Error &err, const std::string &backup);
struct KeyWidgets {
std::string keyGrip;
QLabel *keyFingerprint = nullptr;
QPushButton *createCSRButton = nullptr;
};
public Q_SLOTS:
void genkeyRequested();
void changeNameRequested();
......@@ -58,8 +53,6 @@ public Q_SLOTS:
void createCSR(const std::string &keyref);
private:
KeyWidgets createKeyWidgets(const SmartCard::KeyPairInfo &keyInfo);
void updateKeyWidgets(const std::string &keyRef, const SmartCard::OpenPGPCard *card);
void doChangePin(const std::string &keyRef, Commands::ChangePinCommand::ChangePinMode mode = Commands::ChangePinCommand::NormalMode);
private:
......@@ -68,7 +61,7 @@ private:
*mVersionLabel = nullptr,
*mUrlLabel = nullptr;
QPushButton *mKeyForCardKeysButton = nullptr;
QMap<std::string, KeyWidgets> mKeyWidgets;
OpenPGPKeyCardWidget *mKeysWidget = nullptr;
QString mUrl;
bool mCardIsEmpty = false;
bool mIs21 = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment