Page MenuHome GnuPG

No OneTemporary

diff --git a/src/view/p15cardwidget.cpp b/src/view/p15cardwidget.cpp
index c24a824ff..7fe9f7cac 100644
--- a/src/view/p15cardwidget.cpp
+++ b/src/view/p15cardwidget.cpp
@@ -1,104 +1,25 @@
/* view/p15cardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "p15cardwidget.h"
-#include "cardkeysview.h"
-
-#include "settings.h"
-
-#include "smartcard/openpgpcard.h"
-#include "smartcard/p15card.h"
-#include "smartcard/readerstatus.h"
-
-#include <QLabel>
-#include <QPushButton>
-#include <QStringList>
-#include <QVBoxLayout>
-
-#include <KLocalizedString>
-#include <KSeparator>
-
-#include <Libkleo/Compat>
-#include <Libkleo/Formatting>
-#include <Libkleo/GnuPG>
-#include <Libkleo/KeyCache>
-
-#include <QGpgME/CryptoConfig>
-#include <QGpgME/ImportFromKeyserverJob>
-#include <QGpgME/KeyListJob>
-#include <QGpgME/Protocol>
-
-#include <gpgme++/importresult.h>
-#include <gpgme++/keylistresult.h>
-
-#include "kleopatra_debug.h"
+#include <smartcard/card.h>
using namespace Kleo;
using namespace Kleo::SmartCard;
P15CardWidget::P15CardWidget(QWidget *parent)
: SmartCardWidget{AppType::P15App, parent}
{
}
P15CardWidget::~P15CardWidget() = default;
-void P15CardWidget::searchPGPFpr(const std::string &fpr)
-{
- /* Only do auto import from LDAP */
- if (!Settings().alwaysSearchCardOnKeyserver() && !Kleo::keyserver().startsWith(QLatin1StringView{"ldap"})) {
- return;
- }
- statusLabel()->setText(i18n("Searching in directory service..."));
- statusLabel()->setVisible(true);
- qCDebug(KLEOPATRA_LOG) << "Looking for:" << fpr.c_str() << "on ldap server";
- QGpgME::KeyListJob *job = QGpgME::openpgp()->keyListJob(true);
- connect(job, &QGpgME::KeyListJob::result, job, [this](GpgME::KeyListResult, std::vector<GpgME::Key> keys, QString, GpgME::Error) {
- if (keys.size() == 1) {
- auto importJob = QGpgME::openpgp()->importFromKeyserverJob();
- qCDebug(KLEOPATRA_LOG) << "Importing: " << keys[0].primaryFingerprint();
- connect(importJob, &QGpgME::ImportFromKeyserverJob::result, importJob, [this](GpgME::ImportResult, QString, GpgME::Error) {
- qCDebug(KLEOPATRA_LOG) << "import job done";
- statusLabel()->setText(i18n("Automatic import finished."));
- });
- importJob->start(keys);
- } else if (keys.size() > 1) {
- qCDebug(KLEOPATRA_LOG) << "Multiple keys found on server";
- statusLabel()->setText(i18n("Error multiple keys found on server."));
- } else {
- qCDebug(KLEOPATRA_LOG) << "No key found";
- statusLabel()->setText(i18n("Key not found in directory service."));
- }
- });
- job->start(QStringList() << QString::fromStdString(fpr));
-}
-
-void P15CardWidget::setCard(const P15Card *card)
-{
- SmartCardWidget::setCard(card);
-
- const auto sigInfo = card->keyInfo(card->signingKeyRef());
- if (!sigInfo.grip.empty()) {
- const auto key = KeyCache::instance()->findSubkeyByKeyGrip(sigInfo.grip, GpgME::OpenPGP).parent();
- if (key.isNull()) {
- qCDebug(KLEOPATRA_LOG) << "Failed to find key for grip:" << sigInfo.grip.c_str();
- const auto pgpSigFpr = card->keyFingerprint(OpenPGPCard::pgpSigKeyRef());
- if (!pgpSigFpr.empty()) {
- qCDebug(KLEOPATRA_LOG) << "Should be pgp key:" << pgpSigFpr.c_str();
- searchPGPFpr(pgpSigFpr);
- }
- } else {
- statusLabel()->setVisible(false);
- }
- }
-}
-
#include "moc_p15cardwidget.cpp"
diff --git a/src/view/p15cardwidget.h b/src/view/p15cardwidget.h
index 5f3d878d4..30e91dbe8 100644
--- a/src/view/p15cardwidget.h
+++ b/src/view/p15cardwidget.h
@@ -1,35 +1,30 @@
/* view/p15cardwiget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "smartcardwidget.h"
namespace Kleo
{
namespace SmartCard
{
class P15Card;
}
class P15CardWidget : public SmartCardWidget
{
Q_OBJECT
public:
explicit P15CardWidget(QWidget *parent = nullptr);
~P15CardWidget() override;
-
- void setCard(const SmartCard::P15Card *card);
-
-private:
- void searchPGPFpr(const std::string &fpr);
};
}
diff --git a/src/view/smartcardwidget.cpp b/src/view/smartcardwidget.cpp
index 4ddb52f24..90583f787 100644
--- a/src/view/smartcardwidget.cpp
+++ b/src/view/smartcardwidget.cpp
@@ -1,399 +1,472 @@
/* view/smartcardwidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2024 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "smartcardwidget.h"
#include "infofield.h"
#include "smartcardactions.h"
#include <smartcard/card.h>
#include <smartcard/netkeycard.h>
#include <smartcard/pivcard.h>
#include <utils/accessibility.h>
#include <view/cardkeysview.h>
+#include <kleopatra_debug.h>
+#include <settings.h>
+
#include <Libkleo/Compliance>
+#include <Libkleo/GnuPG>
+#include <Libkleo/KeyCache>
#include <KLocalizedString>
#include <KMessageWidget>
+#include <QGpgME/ImportFromKeyserverJob>
+#include <QGpgME/KeyListJob>
+#include <QGpgME/Protocol>
+
#include <QGridLayout>
#include <QLabel>
#include <QMenu>
#include <QScrollArea>
#include <QToolButton>
#include <QVBoxLayout>
+#include <gpgme++/importresult.h>
+#include <gpgme++/keylistresult.h>
+
using namespace Kleo;
using namespace Kleo::SmartCard;
using namespace Qt::Literals::StringLiterals;
static QString cardTypeForDisplay(const Card *card)
{
switch (card->appType()) {
case AppType::NetKeyApp:
return i18nc("1 is a Version number", "NetKey v%1 Card", card->appVersion());
case AppType::OpenPGPApp: {
const std::string manufacturer = card->manufacturer();
const bool manufacturerIsUnknown = manufacturer.empty() || manufacturer == "unknown";
return (manufacturerIsUnknown //
? i18nc("Placeholder is a version number", "Unknown OpenPGP v%1 card", card->displayAppVersion())
: i18nc("First placeholder is manufacturer, second placeholder is a version number",
"%1 OpenPGP v%2 card",
QString::fromStdString(manufacturer),
card->displayAppVersion()));
}
case AppType::P15App:
return i18nc("%1 is a smartcard manufacturer", "%1 PKCS#15 card", QString::fromStdString(card->manufacturer()));
case AppType::PIVApp:
return i18nc("%1 version number", "PIV v%1 card", card->displayAppVersion());
default:
return {};
};
}
static std::vector<QAction *> actionsForCard(SmartCard::AppType appType)
{
std::vector<QString> actions;
switch (appType) {
case AppType::NetKeyApp:
actions = {
u"card_all_create_openpgp_certificate"_s,
u"card_netkey_set_nks_pin"_s,
u"card_netkey_set_sigg_pin"_s,
};
break;
case AppType::OpenPGPApp:
actions = {
u"card_pgp_generate_keys_and_certificate"_s,
u"card_pgp_change_pin"_s,
u"card_pgp_unblock_card"_s,
u"card_pgp_change_admin_pin"_s,
u"card_pgp_change_puk"_s,
u"card_pgp_change_cardholder"_s,
u"card_pgp_change_publickeyurl"_s,
};
break;
case AppType::P15App:
// there are no card actions for generic PKCS#15 cards
break;
case AppType::PIVApp:
actions = {
u"card_all_create_openpgp_certificate"_s,
u"card_piv_change_pin"_s,
u"card_piv_change_puk"_s,
u"card_piv_change_admin_key"_s,
};
break;
case AppType::NoApp:
break;
};
return SmartCardActions::instance()->actions(actions);
}
static void updateCardAction(QAction *action, const Card *card)
{
switch (card->appType()) {
case AppType::NetKeyApp: {
if (card->pinStates().empty()) {
action->setEnabled(false);
return;
}
if (action->objectName() == "card_all_create_openpgp_certificate"_L1) {
action->setEnabled(!card->hasNKSNullPin() && card->hasSigningKey() && card->hasEncryptionKey()
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->signingKeyRef()).algorithm)
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->encryptionKeyRef()).algorithm));
} else if (action->objectName() == "card_netkey_set_nks_pin"_L1) {
if (!card->hasNKSNullPin()) {
action->setText(i18nc("@action NKS is an identifier for a type of keys on a NetKey card", "Change NKS PIN"));
}
} else if (action->objectName() == "card_netkey_set_sigg_pin"_L1) {
if (!card->hasSigGNullPin()) {
action->setText(i18nc("@action SigG is an identifier for a type of keys on a NetKey card", "Change SigG PIN"));
}
}
break;
}
case AppType::OpenPGPApp:
if (action->objectName() == "card_pgp_change_puk"_L1) {
const auto pinCounters = card->pinCounters();
const bool pukIsAvailable = (pinCounters.size() == 3) && (pinCounters[1] > 0);
action->setText(pukIsAvailable ? i18nc("@action", "Change PUK") : i18nc("@action", "Set PUK"));
}
break;
case AppType::P15App:
break;
case AppType::PIVApp: {
if (action->objectName() == "card_all_create_openpgp_certificate"_L1) {
action->setEnabled(card->hasSigningKey() && card->hasEncryptionKey()
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->signingKeyRef()).algorithm)
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->encryptionKeyRef()).algorithm));
}
break;
}
case AppType::NoApp:
break;
};
}
static void updateCardActions(QToolButton *actionsButton, const Card *card)
{
if (!actionsButton->menu()) {
const auto actions = actionsForCard(card->appType());
if (actions.empty()) {
// there are no card actions for this card app
return;
} else {
actionsButton->setVisible(true);
}
auto menu = new QMenu{actionsButton};
for (auto action : actions) {
menu->addAction(SmartCardActions::createProxyAction(action, menu));
}
actionsButton->setMenu(menu);
}
for (auto action : actionsButton->menu()->actions()) {
updateCardAction(action, card);
}
}
static void updateNullPinWidget(KMessageWidget *nullPinWidget, const Card *card)
{
Q_ASSERT(card);
if (card->appType() != AppType::NetKeyApp) {
return;
}
/* Only check for the standard NKS NullPIN.
* According to users of NetKey cards it is fairly uncommon to use SigG certificates at all.
* So it should be optional to set the SigG pins. */
if (card->hasNKSNullPin()) {
nullPinWidget->setMessageType(KMessageWidget::Information);
nullPinWidget->setIcon(QIcon::fromTheme(u"data-information"_s));
const auto nullTitle = i18nc(
"NullPIN is a word that is used all over in the netkey "
"documentation and should be understandable by Netkey cardholders",
"The NullPIN is still active on this card.");
const auto nullDescription = i18n("You need to set a PIN before you can use the certificates.");
nullPinWidget->setText(QStringLiteral("<b>%1</b><br/>%2").arg(nullTitle, nullDescription));
nullPinWidget->setCloseButtonVisible(false);
if (nullPinWidget->actions().isEmpty()) {
nullPinWidget->addAction(SmartCardActions::createProxyAction(SmartCardActions::instance()->action(u"card_netkey_set_nks_pin"_s), nullPinWidget));
}
nullPinWidget->setVisible(true);
} else {
nullPinWidget->setVisible(false);
}
}
SmartCardWidget::SmartCardWidget(Kleo::SmartCard::AppType appType, QWidget *parent)
: QWidget{parent}
, mAppType{appType}
{
auto mainLayout = new QVBoxLayout{this};
mainLayout->setContentsMargins({});
auto area = new QScrollArea{this};
area->setFocusPolicy(Qt::NoFocus);
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
mainLayout->addWidget(area);
auto areaWidget = new QWidget{this};
area->setWidget(areaWidget);
auto contentLayout = new QVBoxLayout{areaWidget};
auto upperLayout = new QHBoxLayout;
{
auto gridLayout = new QGridLayout;
gridLayout->setColumnStretch(1, 1);
int row = -1;
row++;
mCardTypeField = std::make_unique<InfoField>(i18nc("@label", "Card type:"), parent);
gridLayout->addWidget(mCardTypeField->label(), row, 0);
gridLayout->addLayout(mCardTypeField->layout(), row, 1);
row++;
mSerialNumberField = std::make_unique<InfoField>(i18nc("@label", "Serial number:"), parent);
gridLayout->addWidget(mSerialNumberField->label(), row, 0);
gridLayout->addLayout(mSerialNumberField->layout(), row, 1);
if (mAppType == AppType::OpenPGPApp) {
row++;
mCardholderField =
std::make_unique<InfoField>(i18nc("@label The owner of a smartcard. GnuPG refers to this as cardholder.", "Cardholder:"), parent);
const auto action = SmartCardActions::createProxyAction(SmartCardActions::instance()->action(u"card_pgp_change_cardholder"_s), parent);
action->setIcon(QIcon::fromTheme(u"document-edit"_s));
Kleo::setAccessibleName(action, action->text());
action->setText({});
mCardholderField->setAction(action);
gridLayout->addWidget(mCardholderField->label(), row, 0);
gridLayout->addLayout(mCardholderField->layout(), row, 1);
}
if (mAppType == AppType::OpenPGPApp) {
row++;
mPublicKeyUrlField = std::make_unique<InfoField>(i18nc("@label", "Public key URL:"), parent);
// make the public key URL clickable
mPublicKeyUrlField->valueLabel()->setTextInteractionFlags(Qt::TextBrowserInteraction);
mPublicKeyUrlField->valueLabel()->setOpenExternalLinks(true);
const auto action = SmartCardActions::createProxyAction(SmartCardActions::instance()->action(u"card_pgp_change_publickeyurl"_s), parent);
action->setIcon(QIcon::fromTheme(u"document-edit"_s));
Kleo::setAccessibleName(action, action->text());
action->setText({});
mPublicKeyUrlField->setAction(action);
gridLayout->addWidget(mPublicKeyUrlField->label(), row, 0);
gridLayout->addLayout(mPublicKeyUrlField->layout(), row, 1);
}
if (mAppType == AppType::OpenPGPApp) {
row++;
mPinCountersField = std::make_unique<InfoField>(i18nc("@label The number of remaining attempts to enter a PIN or PUK, as in "
"Remaining attempts: PIN: 2, PUK: 3, Admin PIN: 3",
"Remaining attempts:"),
parent);
mPinCountersField->setToolTip(xi18nc("@info:tooltip", "Shows the number of remaining attempts for entering the correct PIN or PUK."));
gridLayout->addWidget(mPinCountersField->label(), row, 0);
gridLayout->addLayout(mPinCountersField->layout(), row, 1);
}
upperLayout->addLayout(gridLayout, 1);
}
{
auto layout = new QVBoxLayout;
mCardActionsButton = new QToolButton{this};
mCardActionsButton->setPopupMode(QToolButton::InstantPopup);
mCardActionsButton->setText(i18nc("@action:button", "Card Actions"));
mCardActionsButton->setToolTip(i18nc("@info", "Show actions available for this smart card"));
mCardActionsButton->setVisible(false);
layout->addWidget(mCardActionsButton);
layout->addStretch(1);
upperLayout->addLayout(layout);
}
contentLayout->addLayout(upperLayout);
if (mAppType == AppType::NetKeyApp) {
mNullPinWidget = new KMessageWidget{this};
mNullPinWidget->setVisible(false);
contentLayout->addWidget(mNullPinWidget);
- } else if (mAppType == AppType::P15App) {
- mStatusLabel = new QLabel{this};
- mStatusLabel->setVisible(false);
- contentLayout->addWidget(mStatusLabel);
}
+ // used for OpenPGP and PKCS#15 cards when looking up missing OpenPGP certificates
+ mStatusLabel = new QLabel{this};
+ mStatusLabel->setVisible(false);
+ contentLayout->addWidget(mStatusLabel);
+
mErrorWidget = new KMessageWidget{this};
mErrorWidget->setVisible(false);
contentLayout->addWidget(mErrorWidget);
Q_ASSERT(!mCardKeysView);
switch (mAppType) {
case AppType::NetKeyApp:
// do not show Created column by default; creation time is not reported by scdaemon for NetKey cards
mCardKeysView = new CardKeysView{this, CardKeysView::NoOptions};
break;
case AppType::OpenPGPApp:
case AppType::P15App:
mCardKeysView = new CardKeysView{this, CardKeysView::ShowCreated};
break;
case AppType::PIVApp:
// do not show Created column by default; creation time is not reported by scdaemon for PIV cards
mCardKeysView = new CardKeysView{this, CardKeysView::NoOptions};
break;
case AppType::NoApp:
return;
};
contentLayout->addWidget(mCardKeysView, 1);
}
-SmartCardWidget::~SmartCardWidget() = default;
+SmartCardWidget::~SmartCardWidget()
+{
+ if (mJob) {
+ mJob->slotCancel();
+ }
+}
void SmartCardWidget::setCard(const Card *card)
{
Q_ASSERT(mAppType == card->appType());
+ const bool firstSetup = !mCard;
mCard.reset(card->clone());
mCardTypeField->setValue(cardTypeForDisplay(card));
mSerialNumberField->setValue(card->displaySerialNumber());
if (mAppType == AppType::OpenPGPApp) {
const auto holder = card->cardHolder();
mCardholderField->setValue(holder.isEmpty() ? ("<em>"_L1 + i18n("not set") + "</em>"_L1) : holder);
const auto url = card->publicKeyUrl();
mPublicKeyUrlField->setValue(url.isEmpty() //
? ("<em>"_L1 + i18n("not set") + "</em>"_L1)
: u"<a href=\"%1\">%1</a>"_s.arg(url.toHtmlEscaped()));
const auto pinLabels = card->pinLabels();
const auto pinCounters = card->pinCounters();
QStringList countersWithLabels;
countersWithLabels.reserve(pinCounters.size());
for (const auto &pinCounter : pinCounters) {
// sanity check
if (countersWithLabels.size() == pinLabels.size()) {
break;
}
countersWithLabels.push_back(i18nc("label: value", "%1: %2", pinLabels[countersWithLabels.size()], pinCounter));
}
mPinCountersField->setValue(countersWithLabels.join(", "_L1));
}
updateCardActions(mCardActionsButton, card);
updateNullPinWidget(mNullPinWidget, card);
const auto errMsg = card->errorMsg();
if (!errMsg.isEmpty()) {
mErrorWidget->setMessageType(KMessageWidget::Error);
mErrorWidget->setCloseButtonVisible(false);
mErrorWidget->setText(i18nc("@info", "Error: %1", errMsg));
mErrorWidget->setVisible(true);
} else {
mErrorWidget->setVisible(false);
}
+ if (firstSetup && (mAppType == AppType::OpenPGPApp || mAppType == AppType::P15App)) {
+ retrieveOpenPGPCertificate();
+ }
+
mCardKeysView->setCard(mCard);
}
const Kleo::SmartCard::Card *SmartCardWidget::card() const
{
return mCard.get();
}
Kleo::SmartCard::AppType SmartCardWidget::cardType() const
{
return mCard ? mCard->appType() : AppType::NoApp;
}
std::string SmartCardWidget::serialNumber() const
{
return mCard ? mCard->serialNumber() : std::string{};
}
std::string SmartCardWidget::currentCardSlot() const
{
if (mCardKeysView) {
return mCardKeysView->currentCardSlot();
}
return {};
}
GpgME::Key SmartCardWidget::currentCertificate() const
{
if (mCardKeysView) {
return mCardKeysView->currentCertificate();
}
return {};
}
-QLabel *SmartCardWidget::statusLabel() const
+void SmartCardWidget::retrieveOpenPGPCertificate()
{
- return mStatusLabel;
+ Q_ASSERT(mCard);
+ Q_ASSERT(mAppType == AppType::OpenPGPApp || mAppType == AppType::P15App);
+ Q_ASSERT(!mJob);
+
+ mStatusLabel->setVisible(false);
+
+ // Auto import the OpenPGP key for the card keys only from LDAP or if explicitly enabled
+ if (!(Kleo::keyserver().startsWith("ldap"_L1) || //
+ (Settings().alwaysSearchCardOnKeyserver() && Kleo::haveKeyserverConfigured()))) {
+ return;
+ }
+ const auto sigInfo = mCard->keyInfo(mCard->signingKeyRef());
+ if (sigInfo.grip.empty()) {
+ return;
+ }
+ const auto key = KeyCache::instance()->findSubkeyByKeyGrip(sigInfo.grip, GpgME::OpenPGP).parent();
+ if (!key.isNull()) {
+ return;
+ }
+ qCDebug(KLEOPATRA_LOG) << __func__ << "No key found for key grip" << sigInfo.grip;
+ const auto fpr = mCard->keyFingerprint(mCard->signingKeyRef());
+ if (fpr.empty()) {
+ return;
+ }
+ qCDebug(KLEOPATRA_LOG) << __func__ << "Should be OpenPGP key" << fpr;
+ mStatusLabel->setText(i18n("Searching matching certificate in directory service..."));
+ mStatusLabel->setVisible(true);
+ qCDebug(KLEOPATRA_LOG) << __func__ << "Looking for" << fpr << "on key server" << Kleo::keyserver();
+ auto keyListJob = QGpgME::openpgp()->keyListJob(/* remote = */ true);
+ mJob = keyListJob;
+ connect(keyListJob, &QGpgME::KeyListJob::result, this, [this](GpgME::KeyListResult, std::vector<GpgME::Key> keys, QString, GpgME::Error) {
+ mJob.clear();
+ if (keys.size() == 1) {
+ qCDebug(KLEOPATRA_LOG) << "retrieveOpenPGPCertificate - Importing" << keys[0].primaryFingerprint();
+ auto importJob = QGpgME::openpgp()->importFromKeyserverJob();
+ mJob = importJob;
+ connect(importJob, &QGpgME::ImportFromKeyserverJob::result, this, [this](GpgME::ImportResult, QString, GpgME::Error) {
+ mJob.clear();
+ qCDebug(KLEOPATRA_LOG) << "retrieveOpenPGPCertificate - import job done";
+ mStatusLabel->setText(i18n("The matching certificate was imported successfully."));
+ });
+ importJob->start(keys);
+ } else if (keys.size() > 1) {
+ qCDebug(KLEOPATRA_LOG) << "retrieveOpenPGPCertificate - Multiple keys found on server";
+ mStatusLabel->setText(i18n("Multiple matching certificates were found in directory service."));
+ } else {
+ qCDebug(KLEOPATRA_LOG) << "retrieveOpenPGPCertificate - No key found on server";
+ mStatusLabel->setText(i18n("No matching certificate was found in directory service."));
+ }
+ });
+ keyListJob->start({QString::fromStdString(fpr)});
}
diff --git a/src/view/smartcardwidget.h b/src/view/smartcardwidget.h
index 7dc331f4d..0490e0103 100644
--- a/src/view/smartcardwidget.h
+++ b/src/view/smartcardwidget.h
@@ -1,72 +1,78 @@
/* view/smartcardwidget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2024 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
+#include <QPointer>
#include <QWidget>
#include <memory>
#include <string>
class KMessageWidget;
class QGridLayout;
class QLabel;
class QToolButton;
class QVBoxLayout;
namespace GpgME
{
class Key;
}
+namespace QGpgME
+{
+class Job;
+}
namespace Kleo
{
class CardKeysView;
class InfoField;
}
namespace Kleo::SmartCard
{
enum class AppType;
class Card;
}
class SmartCardWidget : public QWidget
{
Q_OBJECT
protected:
SmartCardWidget(Kleo::SmartCard::AppType appType, QWidget *parent = nullptr);
public:
~SmartCardWidget() override;
void setCard(const Kleo::SmartCard::Card *card);
const Kleo::SmartCard::Card *card() const;
Kleo::SmartCard::AppType cardType() const;
std::string serialNumber() const;
std::string currentCardSlot() const;
GpgME::Key currentCertificate() const;
-protected:
- QLabel *statusLabel() const;
+private:
+ void retrieveOpenPGPCertificate();
private:
Kleo::SmartCard::AppType mAppType;
std::shared_ptr<const Kleo::SmartCard::Card> mCard;
+ QPointer<QGpgME::Job> mJob;
std::unique_ptr<Kleo::InfoField> mCardTypeField;
std::unique_ptr<Kleo::InfoField> mSerialNumberField;
std::unique_ptr<Kleo::InfoField> mCardholderField;
std::unique_ptr<Kleo::InfoField> mPublicKeyUrlField;
std::unique_ptr<Kleo::InfoField> mPinCountersField;
QToolButton *mCardActionsButton = nullptr;
KMessageWidget *mNullPinWidget = nullptr;
QLabel *mStatusLabel = nullptr;
KMessageWidget *mErrorWidget = nullptr;
Kleo::CardKeysView *mCardKeysView = nullptr;
};

File Metadata

Mime Type
text/x-diff
Expires
Fri, Dec 5, 9:29 AM (1 d, 14 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0f/6c/d4a40ec6c3ce488c1235313380f6

Event Timeline