File indexing completed on 2024-06-16 04:55:59

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/task.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "task.h"
0013 #include "task_p.h"
0014 
0015 #include <Libkleo/KleoException>
0016 
0017 #include <Libkleo/AuditLogEntry>
0018 #include <Libkleo/GnuPG>
0019 
0020 #include <gpgme++/exception.h>
0021 
0022 #include <gpg-error.h>
0023 
0024 #include <KIconLoader>
0025 #include <KLocalizedString>
0026 
0027 using namespace Kleo;
0028 using namespace Kleo::Crypto;
0029 using namespace GpgME;
0030 
0031 namespace
0032 {
0033 
0034 class ErrorResult : public Task::Result
0035 {
0036 public:
0037     ErrorResult(const GpgME::Error &error, const QString &details)
0038         : Task::Result()
0039         , m_error(error)
0040         , m_details(details)
0041     {
0042     }
0043 
0044     QString overview() const override
0045     {
0046         return makeOverview(m_details);
0047     }
0048     QString details() const override
0049     {
0050         return QString();
0051     }
0052     GpgME::Error error() const override
0053     {
0054         return m_error;
0055     }
0056     QString errorString() const override
0057     {
0058         return m_details;
0059     }
0060     VisualCode code() const override
0061     {
0062         return NeutralError;
0063     }
0064     AuditLogEntry auditLog() const override
0065     {
0066         return AuditLogEntry();
0067     }
0068 
0069 private:
0070     const GpgME::Error m_error;
0071     const QString m_details;
0072 };
0073 }
0074 
0075 class Task::Private
0076 {
0077     friend class ::Kleo::Crypto::Task;
0078     Task *const q;
0079 
0080 public:
0081     explicit Private(Task *qq);
0082 
0083 private:
0084     int m_progress;
0085     int m_totalProgress;
0086     bool m_asciiArmor;
0087     int m_id;
0088 };
0089 
0090 namespace
0091 {
0092 static int nextTaskId = 0;
0093 }
0094 
0095 Task::Private::Private(Task *qq)
0096     : q(qq)
0097     , m_progress(0)
0098     , m_totalProgress(0)
0099     , m_asciiArmor(false)
0100     , m_id(nextTaskId++)
0101 {
0102 }
0103 
0104 Task::Task(QObject *p)
0105     : QObject(p)
0106     , d(new Private(this))
0107 {
0108 }
0109 
0110 Task::~Task()
0111 {
0112 }
0113 
0114 void Task::setAsciiArmor(bool armor)
0115 {
0116     d->m_asciiArmor = armor;
0117 }
0118 
0119 bool Task::asciiArmor() const
0120 {
0121     return d->m_asciiArmor;
0122 }
0123 
0124 std::shared_ptr<Task> Task::makeErrorTask(const GpgME::Error &error, const QString &details, const QString &label)
0125 {
0126     const std::shared_ptr<SimpleTask> t(new SimpleTask(label));
0127     t->setResult(t->makeErrorResult(error, details));
0128     return t;
0129 }
0130 
0131 int Task::id() const
0132 {
0133     return d->m_id;
0134 }
0135 
0136 int Task::currentProgress() const
0137 {
0138     return d->m_progress;
0139 }
0140 
0141 int Task::totalProgress() const
0142 {
0143     return d->m_totalProgress;
0144 }
0145 
0146 QString Task::tag() const
0147 {
0148     return QString();
0149 }
0150 
0151 void Task::setProgress(int processed, int total)
0152 {
0153     d->m_progress = processed;
0154     d->m_totalProgress = total;
0155     Q_EMIT progress(processed, total, QPrivateSignal());
0156 }
0157 
0158 void Task::start()
0159 {
0160     try {
0161         doStart();
0162     } catch (const Kleo::Exception &e) {
0163         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(GpgME::Error, e.error()), Q_ARG(QString, e.message()));
0164     } catch (const GpgME::Exception &e) {
0165         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(GpgME::Error, e.error()), Q_ARG(QString, QString::fromLocal8Bit(e.what())));
0166     } catch (const std::exception &e) {
0167         QMetaObject::invokeMethod(this,
0168                                   "emitError",
0169                                   Qt::QueuedConnection,
0170                                   Q_ARG(GpgME::Error, Error::fromCode(GPG_ERR_UNEXPECTED)),
0171                                   Q_ARG(QString, QString::fromLocal8Bit(e.what())));
0172     } catch (...) {
0173         QMetaObject::invokeMethod(this,
0174                                   "emitError",
0175                                   Qt::QueuedConnection,
0176                                   Q_ARG(GpgME::Error, Error::fromCode(GPG_ERR_UNEXPECTED)),
0177                                   Q_ARG(QString, i18n("Unknown exception in Task::start()")));
0178     }
0179     Q_EMIT started(QPrivateSignal());
0180 }
0181 
0182 void Task::emitError(const GpgME::Error &error, const QString &details)
0183 {
0184     emitResult(makeErrorResult(error, details));
0185 }
0186 
0187 void Task::emitResult(const std::shared_ptr<const Task::Result> &r)
0188 {
0189     d->m_progress = d->m_totalProgress;
0190     Q_EMIT progress(currentProgress(), totalProgress(), QPrivateSignal());
0191     Q_EMIT result(r, QPrivateSignal());
0192 }
0193 
0194 std::shared_ptr<Task::Result> Task::makeErrorResult(const GpgME::Error &error, const QString &details)
0195 {
0196     return std::shared_ptr<Task::Result>(new ErrorResult(error, details));
0197 }
0198 
0199 class Task::Result::Private
0200 {
0201 public:
0202     Private()
0203     {
0204     }
0205 };
0206 
0207 Task::Result::Result()
0208     : d(new Private())
0209 {
0210 }
0211 Task::Result::~Result()
0212 {
0213 }
0214 
0215 bool Task::Result::hasError() const
0216 {
0217     return error().code() != 0;
0218 }
0219 
0220 Task::Result::ContentType Task::Result::viewableContentType() const
0221 {
0222     return Task::Result::ContentType::None;
0223 }
0224 
0225 static QString image(const char *img)
0226 {
0227     // ### escape?
0228     return KIconLoader::global()->iconPath(QLatin1StringView(img), KIconLoader::Small);
0229 }
0230 
0231 QString Task::Result::makeOverview(const QString &msg)
0232 {
0233     return QLatin1StringView("<b>") + msg + QLatin1String("</b>");
0234 }
0235 
0236 QString Task::Result::iconPath(VisualCode code)
0237 {
0238     switch (code) {
0239     case Danger:
0240         return image("dialog-error");
0241     case AllGood:
0242         return image("dialog-ok");
0243     case Warning:
0244         return image("dialog-warning");
0245     case NeutralError:
0246     case NeutralSuccess:
0247     default:
0248         return QString();
0249     }
0250 }
0251 
0252 QString Task::Result::icon() const
0253 {
0254     return iconPath(code());
0255 }
0256 
0257 #include "moc_task_p.cpp"
0258 
0259 #include "moc_task.cpp"