File indexing completed on 2024-06-23 05:13:36

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     commands/adduseridcommand.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
0006     SPDX-FileCopyrightText: 2022 g10 Code GmbH
0007     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include <config-kleopatra.h>
0013 
0014 #include "adduseridcommand.h"
0015 
0016 #include "command_p.h"
0017 
0018 #include "dialogs/adduseriddialog.h"
0019 
0020 #include <Libkleo/Formatting>
0021 #include <QGpgME/Protocol>
0022 #include <QGpgME/QuickJob>
0023 
0024 #include <QObjectCleanupHandler>
0025 
0026 #include <gpgme++/key.h>
0027 
0028 #include "kleopatra_debug.h"
0029 #include <KLocalizedString>
0030 
0031 using namespace Kleo;
0032 using namespace Kleo::Commands;
0033 using namespace GpgME;
0034 
0035 class AddUserIDCommand::Private : public Command::Private
0036 {
0037     friend class ::Kleo::Commands::AddUserIDCommand;
0038     AddUserIDCommand *q_func() const
0039     {
0040         return static_cast<AddUserIDCommand *>(q);
0041     }
0042 
0043 public:
0044     explicit Private(AddUserIDCommand *qq, KeyListController *c);
0045     ~Private() override;
0046 
0047 private:
0048     void slotDialogAccepted();
0049     void slotDialogRejected();
0050     void slotResult(const Error &err);
0051 
0052 private:
0053     void ensureDialogCreated();
0054     void createJob();
0055     void showErrorDialog(const Error &error);
0056     void showSuccessDialog();
0057 
0058 private:
0059     GpgME::Key key;
0060     QObjectCleanupHandler cleaner;
0061     QPointer<AddUserIDDialog> dialog;
0062     QPointer<QGpgME::QuickJob> job;
0063 };
0064 
0065 AddUserIDCommand::Private *AddUserIDCommand::d_func()
0066 {
0067     return static_cast<Private *>(d.get());
0068 }
0069 const AddUserIDCommand::Private *AddUserIDCommand::d_func() const
0070 {
0071     return static_cast<const Private *>(d.get());
0072 }
0073 
0074 #define d d_func()
0075 #define q q_func()
0076 
0077 AddUserIDCommand::Private::Private(AddUserIDCommand *qq, KeyListController *c)
0078     : Command::Private{qq, c}
0079 {
0080 }
0081 
0082 AddUserIDCommand::Private::~Private() = default;
0083 
0084 AddUserIDCommand::AddUserIDCommand(QAbstractItemView *v, KeyListController *c)
0085     : Command{v, new Private{this, c}}
0086 {
0087 }
0088 
0089 AddUserIDCommand::AddUserIDCommand(const GpgME::Key &key)
0090     : Command{key, new Private{this, nullptr}}
0091 {
0092 }
0093 
0094 AddUserIDCommand::~AddUserIDCommand()
0095 {
0096     qCDebug(KLEOPATRA_LOG).nospace() << this << "::" << __func__;
0097 }
0098 
0099 void AddUserIDCommand::doStart()
0100 {
0101     const std::vector<Key> keys = d->keys();
0102     if (keys.size() != 1) {
0103         d->finished();
0104         return;
0105     }
0106 
0107     d->key = keys.front();
0108     if (d->key.protocol() != GpgME::OpenPGP //
0109         || !d->key.hasSecret()) {
0110         d->finished();
0111         return;
0112     }
0113 
0114     d->ensureDialogCreated();
0115 
0116     const UserID uid = d->key.userID(0);
0117 
0118     d->dialog->setName(QString::fromUtf8(uid.name()));
0119     d->dialog->setEmail(Formatting::prettyEMail(uid.email(), uid.id()));
0120 
0121     d->dialog->show();
0122 }
0123 
0124 void AddUserIDCommand::Private::slotDialogAccepted()
0125 {
0126     Q_ASSERT(dialog);
0127 
0128     createJob();
0129     if (!job) {
0130         finished();
0131         return;
0132     }
0133     job->startAddUid(key, dialog->userID());
0134 }
0135 
0136 void AddUserIDCommand::Private::slotDialogRejected()
0137 {
0138     Q_EMIT q->canceled();
0139     finished();
0140 }
0141 
0142 void AddUserIDCommand::Private::slotResult(const Error &err)
0143 {
0144     if (err.isCanceled()) {
0145     } else if (err) {
0146         showErrorDialog(err);
0147     } else {
0148         showSuccessDialog();
0149     }
0150     finished();
0151 }
0152 
0153 void AddUserIDCommand::doCancel()
0154 {
0155     qCDebug(KLEOPATRA_LOG).nospace() << this << "::" << __func__;
0156     if (d->job) {
0157         d->job->slotCancel();
0158     }
0159 }
0160 
0161 void AddUserIDCommand::Private::ensureDialogCreated()
0162 {
0163     if (dialog) {
0164         return;
0165     }
0166 
0167     dialog = new AddUserIDDialog;
0168     cleaner.add(dialog);
0169     applyWindowID(dialog);
0170 
0171     connect(dialog, &QDialog::accepted, q, [this]() {
0172         slotDialogAccepted();
0173     });
0174     connect(dialog, &QDialog::rejected, q, [this]() {
0175         slotDialogRejected();
0176     });
0177 }
0178 
0179 void AddUserIDCommand::Private::createJob()
0180 {
0181     Q_ASSERT(!job);
0182 
0183     const auto backend = QGpgME::openpgp();
0184     if (!backend) {
0185         return;
0186     }
0187 
0188     const auto j = backend->quickJob();
0189     if (!j) {
0190         return;
0191     }
0192 
0193     connect(j, &QGpgME::Job::jobProgress, q, &Command::progress);
0194     connect(j, &QGpgME::QuickJob::result, q, [this](const GpgME::Error &err) {
0195         slotResult(err);
0196     });
0197 
0198     job = j;
0199 }
0200 
0201 void AddUserIDCommand::Private::showErrorDialog(const Error &err)
0202 {
0203     error(xi18nc("@info",
0204                  "<para>An error occurred while trying to add the user ID: "
0205                  "<message>%1</message></para>",
0206                  Formatting::errorAsString(err)),
0207           i18nc("@title:window", "Add User ID Error"));
0208 }
0209 
0210 void AddUserIDCommand::Private::showSuccessDialog()
0211 {
0212     information(i18nc("@info", "User ID successfully added."), //
0213                 i18nc("@title:window", "Add User ID Succeeded"));
0214 }
0215 
0216 #undef d
0217 #undef q
0218 
0219 #include "moc_adduseridcommand.cpp"