16#include <config-libkleo.h> 
   18#include "keyrequester.h" 
   20#include "keyselectiondialog.h" 
   22#include <libkleo/algorithm.h> 
   23#include <libkleo/compliance.h> 
   24#include <libkleo/formatting.h> 
   25#include <libkleo/keyhelpers.h> 
   27#include <KLocalizedString> 
   30#include <QGpgME/KeyListJob> 
   32#include <QApplication> 
   38#include <gpgme++/key.h> 
   39#include <gpgme++/keylistresult.h> 
   41using namespace QGpgME;
 
   44Kleo::KeyRequester::KeyRequester(
unsigned int allowedKeys, 
bool multipleKeys, 
QWidget *parent)
 
   46    , mOpenPGPBackend(nullptr)
 
   47    , mSMIMEBackend(nullptr)
 
   48    , mMulti(multipleKeys)
 
   49    , mKeyUsage(allowedKeys)
 
   56Kleo::KeyRequester::KeyRequester(
QWidget *parent)
 
   58    , mOpenPGPBackend(nullptr)
 
   59    , mSMIMEBackend(nullptr)
 
   68void Kleo::KeyRequester::init()
 
   70    auto hlay = 
new QHBoxLayout(
this);
 
   71    hlay->setContentsMargins(0, 0, 0, 0);
 
   73    if (DeVSCompliance::isCompliant()) {
 
   74        mComplianceIcon = 
new QLabel{
this};
 
   75        mComplianceIcon->setPixmap(Formatting::questionIcon().pixmap(22));
 
   79    mLabel = 
new QLabel(
this);
 
   83    mEraseButton = 
new QPushButton(
this);
 
   84    mEraseButton->setAutoDefault(
false);
 
   86    mEraseButton->setIcon(
 
   88    mEraseButton->setToolTip(
i18nc(
"@info:tooltip", 
"Clear"));
 
   91    mDialogButton = 
new QPushButton(
i18nc(
"@action:button", 
"Change..."), 
this);
 
   92    mDialogButton->setAutoDefault(
false);
 
   94    if (mComplianceIcon) {
 
   95        hlay->addWidget(mComplianceIcon);
 
   97    hlay->addWidget(mLabel, 1);
 
   98    hlay->addWidget(mEraseButton);
 
   99    hlay->addWidget(mDialogButton);
 
  106    setAllowedKeys(mKeyUsage);
 
  109Kleo::KeyRequester::~KeyRequester()
 
  113const std::vector<GpgME::Key> &Kleo::KeyRequester::keys()
 const 
  118const GpgME::Key &Kleo::KeyRequester::key()
 const 
  120    static const GpgME::Key null = GpgME::Key::null;
 
  124        return mKeys.front();
 
  131    for (
auto it = keys.begin(); it != keys.end(); ++it) {
 
  133            mKeys.push_back(*it);
 
 
  143        mKeys.push_back(key);
 
 
  148QString Kleo::KeyRequester::fingerprint()
 const 
  157QStringList Kleo::KeyRequester::fingerprints()
 const 
  160    for (
auto it = mKeys.begin(); it != mKeys.end(); ++it) {
 
  162            if (
const char *fpr = it->primaryFingerprint()) {
 
  163                result.
push_back(QLatin1StringView(fpr));
 
  177    startKeyListJob(fingerprints);
 
 
  180void Kleo::KeyRequester::updateKeys()
 
  183        if (mComplianceIcon) {
 
  184            mComplianceIcon->setPixmap(Formatting::unavailableIcon().pixmap(22));
 
  185            mComplianceIcon->setToolTip(
QString{});
 
  190    if (mKeys.size() > 1) {
 
  191        setMultipleKeysEnabled(
true);
 
  194    QStringList labelTexts;
 
  196    for (std::vector<GpgME::Key>::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) {
 
  200        const QString fpr = QLatin1StringView(it->primaryFingerprint());
 
  203        toolTipText += keyID + QLatin1StringView(
": ");
 
  204        if (
const char *uid = it->userID(0).id()) {
 
  205            if (it->protocol() == GpgME::OpenPGP) {
 
  208                toolTipText += Formatting::prettyDN(uid);
 
  211            toolTipText += 
xi18n(
"<placeholder>unknown</placeholder>");
 
  213        toolTipText += QLatin1Char(
'\n');
 
  215    if (mComplianceIcon) {
 
  216        if (Kleo::all_of(mKeys, &Kleo::DeVSCompliance::keyIsCompliant)) {
 
  217            mComplianceIcon->setPixmap(Formatting::successIcon().pixmap(22));
 
  218            mComplianceIcon->setToolTip(DeVSCompliance::name(
true));
 
  220            mComplianceIcon->setPixmap(Formatting::warningIcon().pixmap(22));
 
  221            mComplianceIcon->setToolTip(DeVSCompliance::name(
false));
 
  224    mLabel->setText(labelTexts.
join(QLatin1StringView(
", ")));
 
  225    mLabel->setToolTip(toolTipText);
 
  228#ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ 
  229#define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ 
  230static void showKeyListError(QWidget *parent, 
const GpgME::Error &err)
 
  233    const QString msg = 
i18n(
 
  234        "<qt><p>An error occurred while fetching " 
  235        "the keys from the backend:</p>" 
  236        "<p><b>%1</b></p></qt>",
 
  237        Formatting::errorAsString(err));
 
  243void Kleo::KeyRequester::startKeyListJob(
const QStringList &fingerprints)
 
  245    if (!mSMIMEBackend && !mOpenPGPBackend) {
 
  252    unsigned int count = 0;
 
  253    for (QStringList::const_iterator it = fingerprints.
begin(); it != fingerprints.
end(); ++it) {
 
  254        if (!(*it).trimmed().isEmpty()) {
 
  262        setKey(GpgME::Key::null);
 
  266    if (mOpenPGPBackend) {
 
  267        KeyListJob *job = mOpenPGPBackend->keyListJob(
false); 
 
  270                               i18n(
"The OpenPGP backend does not support listing keys. " 
  271                                    "Check your installation."),
 
  272                               i18nc(
"@title:window", 
"Key Listing Failed"));
 
  274            connect(job, &KeyListJob::result, 
this, &SigningKeyRequester::slotKeyListResult);
 
  275            connect(job, &KeyListJob::nextKey, 
this, &SigningKeyRequester::slotNextKey);
 
  277            const GpgME::Error err =
 
  278                job->start(fingerprints, mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && !(mKeyUsage & Kleo::KeySelectionDialog::PublicKeys));
 
  281                showKeyListError(
this, err);
 
  289        KeyListJob *job = mSMIMEBackend->keyListJob(
false); 
 
  292                               i18n(
"The S/MIME backend does not support listing keys. " 
  293                                    "Check your installation."),
 
  294                               i18nc(
"@title:window", 
"Key Listing Failed"));
 
  296            connect(job, &KeyListJob::result, 
this, &SigningKeyRequester::slotKeyListResult);
 
  297            connect(job, &KeyListJob::nextKey, 
this, &SigningKeyRequester::slotNextKey);
 
  299            const GpgME::Error err =
 
  300                job->start(fingerprints, mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && !(mKeyUsage & Kleo::KeySelectionDialog::PublicKeys));
 
  303                showKeyListError(
this, err);
 
  311        mEraseButton->setEnabled(
false);
 
  312        mDialogButton->setEnabled(
false);
 
  316void Kleo::KeyRequester::slotNextKey(
const GpgME::Key &key)
 
  319        mTmpKeys.push_back(key);
 
  323void Kleo::KeyRequester::slotKeyListResult(
const GpgME::KeyListResult &res)
 
  326        showKeyListError(
this, res.error());
 
  330        mEraseButton->setEnabled(
true);
 
  331        mDialogButton->setEnabled(
true);
 
  338void Kleo::KeyRequester::slotDialogButtonClicked()
 
  340    KeySelectionDialog *dlg = mKeys.empty() ? 
new KeySelectionDialog(mDialogCaption, mDialogMessage, mInitialQuery, mKeyUsage, mMulti, 
false, 
this)
 
  341                                            : new KeySelectionDialog(mDialogCaption, mDialogCaption, mKeys, mKeyUsage, mMulti, false, this);
 
  345            setKeys(dlg->selectedKeys());
 
  347            setKey(dlg->selectedKey());
 
  355void Kleo::KeyRequester::slotEraseButtonClicked()
 
  357    if (!mKeys.empty()) {
 
  364void Kleo::KeyRequester::setDialogCaption(
const QString &caption)
 
  366    mDialogCaption = caption;
 
  369void Kleo::KeyRequester::setDialogMessage(
const QString &msg)
 
  371    mDialogMessage = msg;
 
  374bool Kleo::KeyRequester::isMultipleKeysEnabled()
 const 
  379void Kleo::KeyRequester::setMultipleKeysEnabled(
bool multi)
 
  381    if (multi == mMulti) {
 
  385    if (!multi && !mKeys.empty()) {
 
  386        mKeys.erase(mKeys.begin() + 1, mKeys.end());
 
  393unsigned int Kleo::KeyRequester::allowedKeys()
 const 
  398void Kleo::KeyRequester::setAllowedKeys(
unsigned int keyUsage)
 
  400    mKeyUsage = keyUsage;
 
  401    mOpenPGPBackend = 
nullptr;
 
  402    mSMIMEBackend = 
nullptr;
 
  404    if (mKeyUsage & KeySelectionDialog::OpenPGPKeys) {
 
  405        mOpenPGPBackend = openpgp();
 
  407    if (mKeyUsage & KeySelectionDialog::SMIMEKeys) {
 
  408        mSMIMEBackend = smime();
 
  411    if (mOpenPGPBackend && !mSMIMEBackend) {
 
  412        mDialogCaption = 
i18n(
"OpenPGP Key Selection");
 
  413        mDialogMessage = 
i18n(
"Please select an OpenPGP key to use.");
 
  414    } 
else if (!mOpenPGPBackend && mSMIMEBackend) {
 
  415        mDialogCaption = 
i18n(
"S/MIME Key Selection");
 
  416        mDialogMessage = 
i18n(
"Please select an S/MIME key to use.");
 
  418        mDialogCaption = 
i18n(
"Key Selection");
 
  419        mDialogMessage = 
i18n(
"Please select an (OpenPGP or S/MIME) key to use.");
 
  423QPushButton *Kleo::KeyRequester::dialogButton()
 
  425    return mDialogButton;
 
  428QPushButton *Kleo::KeyRequester::eraseButton()
 
  433static inline unsigned int foo(
bool openpgp, 
bool smime, 
bool trusted, 
bool valid)
 
  435    unsigned int result = 0;
 
  437        result |= Kleo::KeySelectionDialog::OpenPGPKeys;
 
  440        result |= Kleo::KeySelectionDialog::SMIMEKeys;
 
  443        result |= Kleo::KeySelectionDialog::TrustedKeys;
 
  446        result |= Kleo::KeySelectionDialog::ValidKeys;
 
  451static inline unsigned int encryptionKeyUsage(
bool openpgp, 
bool smime, 
bool trusted, 
bool valid)
 
  453    return foo(openpgp, smime, trusted, valid) | Kleo::KeySelectionDialog::EncryptionKeys | Kleo::KeySelectionDialog::PublicKeys;
 
  456static inline unsigned int signingKeyUsage(
bool openpgp, 
bool smime, 
bool trusted, 
bool valid)
 
  458    return foo(openpgp, smime, trusted, valid) | Kleo::KeySelectionDialog::SigningKeys | Kleo::KeySelectionDialog::SecretKeys;
 
  461Kleo::EncryptionKeyRequester::EncryptionKeyRequester(
bool multi, 
unsigned int proto, QWidget *parent, 
bool onlyTrusted, 
bool onlyValid)
 
  462    : 
KeyRequester(encryptionKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid), multi, parent)
 
  467Kleo::EncryptionKeyRequester::EncryptionKeyRequester(QWidget *parent)
 
  473Kleo::EncryptionKeyRequester::~EncryptionKeyRequester()
 
  477void Kleo::EncryptionKeyRequester::setAllowedKeys(
unsigned int proto, 
bool onlyTrusted, 
bool onlyValid)
 
  479    KeyRequester::setAllowedKeys(encryptionKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid));
 
  482Kleo::SigningKeyRequester::SigningKeyRequester(
bool multi, 
unsigned int proto, QWidget *parent, 
bool onlyTrusted, 
bool onlyValid)
 
  483    : 
KeyRequester(signingKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid), multi, parent)
 
  488Kleo::SigningKeyRequester::SigningKeyRequester(QWidget *parent)
 
  494Kleo::SigningKeyRequester::~SigningKeyRequester()
 
  498void Kleo::SigningKeyRequester::setAllowedKeys(
unsigned int proto, 
bool onlyTrusted, 
bool onlyValid)
 
  500    KeyRequester::setAllowedKeys(signingKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid));
 
  503void Kleo::KeyRequester::virtual_hook(
int, 
void *)
 
  506void Kleo::EncryptionKeyRequester::virtual_hook(
int id, 
void *data)
 
  508    KeyRequester::virtual_hook(
id, data);
 
  510void Kleo::SigningKeyRequester::virtual_hook(
int id, 
void *data)
 
  512    KeyRequester::virtual_hook(
id, data);
 
  515#include "moc_keyrequester.cpp" 
Base class for SigningKeyRequester and EncryptionKeyRequester.
 
void setFingerprint(const QString &fingerprint)
Set the key by fingerprint.
 
void setFingerprints(const QStringList &fingerprints)
Set the keys by fingerprint.
 
void setKeys(const std::vector< GpgME::Key > &keys)
Preferred method to set a key for multi-KeyRequesters.
 
void setKey(const GpgME::Key &key)
Preferred method to set a key for non-multi-KeyRequesters.
 
QString i18nc(const char *context, const char *text, const TYPE &arg...)
 
QString xi18n(const char *text, const TYPE &arg...)
 
QString i18n(const char *text, const TYPE &arg...)
 
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
 
QIcon fromTheme(const QString &name)
 
void push_back(parameter_type value)
 
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
 
QString fromLatin1(QByteArrayView str)
 
QString fromUtf8(QByteArrayView str)
 
QString join(QChar separator) const const
 
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)