1 /* -*- mode: c++; c-basic-offset:4 -*-
2     crypto/task.cpp
3 
4     This file is part of Kleopatra, the KDE keymanager
5     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
6 
7     SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 
10 #include <config-kleopatra.h>
11 #include "task.h"
12 #include "task_p.h"
13 #include "kleopatra_debug.h"
14 
15 #include <Libkleo/KleoException>
16 
17 #include <Libkleo/GnuPG>
18 #include <utils/auditlog.h>
19 
20 #include <gpgme++/exception.h>
21 
22 #include <gpg-error.h>
23 
24 #include <KIconLoader>
25 #include <KLocalizedString>
26 
27 
28 using namespace Kleo;
29 using namespace Kleo::Crypto;
30 using namespace GpgME;
31 
32 namespace
33 {
34 
35 class ErrorResult : public Task::Result
36 {
37 public:
ErrorResult(int code,const QString & details)38     ErrorResult(int code, const QString &details)
39         : Task::Result(), m_code(code), m_details(details) {}
40 
overview() const41     QString overview() const override
42     {
43         return makeOverview(m_details);
44     }
details() const45     QString details() const override
46     {
47         return QString();
48     }
errorCode() const49     int errorCode() const override
50     {
51         return m_code;
52     }
errorString() const53     QString errorString() const override
54     {
55         return m_details;
56     }
code() const57     VisualCode code() const override
58     {
59         return NeutralError;
60     }
auditLog() const61     AuditLog auditLog() const override
62     {
63         return AuditLog();
64     }
65 private:
66     const int m_code;
67     const QString m_details;
68 };
69 }
70 
71 class Task::Private
72 {
73     friend class ::Kleo::Crypto::Task;
74     Task *const q;
75 public:
76     explicit Private(Task *qq);
77 
78 private:
79     QString m_progressLabel;
80     int m_progress;
81     int m_totalProgress;
82     bool m_asciiArmor;
83     int m_id;
84 };
85 
86 namespace
87 {
88 static int nextTaskId = 0;
89 }
90 
Private(Task * qq)91 Task::Private::Private(Task *qq)
92     : q(qq), m_progressLabel(), m_progress(0), m_totalProgress(0), m_asciiArmor(false), m_id(nextTaskId++)
93 {
94 
95 }
96 
Task(QObject * p)97 Task::Task(QObject *p)
98     : QObject(p), d(new Private(this))
99 {
100 
101 }
102 
~Task()103 Task::~Task() {}
104 
setAsciiArmor(bool armor)105 void Task::setAsciiArmor(bool armor)
106 {
107     d->m_asciiArmor = armor;
108 }
109 
asciiArmor() const110 bool Task::asciiArmor() const
111 {
112     return d->m_asciiArmor;
113 }
114 
makeErrorTask(int code,const QString & details,const QString & label)115 std::shared_ptr<Task> Task::makeErrorTask(int code, const QString &details, const QString &label)
116 {
117     const std::shared_ptr<SimpleTask> t(new SimpleTask(label));
118     t->setResult(t->makeErrorResult(code, details));
119     return t;
120 }
121 
id() const122 int Task::id() const
123 {
124     return d->m_id;
125 }
126 
currentProgress() const127 int Task::currentProgress() const
128 {
129     return d->m_progress;
130 }
131 
totalProgress() const132 int Task::totalProgress() const
133 {
134     return d->m_totalProgress;
135 }
136 
tag() const137 QString Task::tag() const
138 {
139     return QString();
140 }
141 
progressLabel() const142 QString Task::progressLabel() const
143 {
144     return d->m_progressLabel;
145 }
146 
setProgress(const QString & label,int processed,int total)147 void Task::setProgress(const QString &label, int processed, int total)
148 {
149     d->m_progress = processed;
150     d->m_totalProgress = total;
151     d->m_progressLabel = label;
152     Q_EMIT progress(label, processed, total, QPrivateSignal());
153 }
154 
start()155 void Task::start()
156 {
157     try {
158         doStart();
159     } catch (const Kleo::Exception &e) {
160         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(int, e.error().encodedError()), Q_ARG(QString, e.message()));
161     } catch (const GpgME::Exception &e) {
162         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(int, e.error().encodedError()), Q_ARG(QString, QString::fromLocal8Bit(e.what())));
163     } catch (const std::exception &e) {
164         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(int, makeGnuPGError(GPG_ERR_UNEXPECTED)), Q_ARG(QString, QString::fromLocal8Bit(e.what())));
165     } catch (...) {
166         QMetaObject::invokeMethod(this, "emitError", Qt::QueuedConnection, Q_ARG(int, makeGnuPGError(GPG_ERR_UNEXPECTED)), Q_ARG(QString, i18n("Unknown exception in Task::start()")));
167     }
168     Q_EMIT started(QPrivateSignal());
169 }
170 
emitError(int errCode,const QString & details)171 void Task::emitError(int errCode, const QString &details)
172 {
173     emitResult(makeErrorResult(errCode, details));
174 }
175 
emitResult(const std::shared_ptr<const Task::Result> & r)176 void Task::emitResult(const std::shared_ptr<const Task::Result> &r)
177 {
178     d->m_progress = d->m_totalProgress;
179     Q_EMIT progress(progressLabel(), currentProgress(), totalProgress(), QPrivateSignal());
180     Q_EMIT result(r, QPrivateSignal());
181 }
182 
makeErrorResult(int errCode,const QString & details)183 std::shared_ptr<Task::Result> Task::makeErrorResult(int errCode, const QString &details)
184 {
185     return std::shared_ptr<Task::Result>(new ErrorResult(errCode, details));
186 }
187 
188 class Task::Result::Private
189 {
190 public:
Private()191     Private() {}
192 };
193 
Result()194 Task::Result::Result() : d(new Private()) {}
~Result()195 Task::Result::~Result() {}
196 
hasError() const197 bool Task::Result::hasError() const
198 {
199     return errorCode() != 0;
200 }
201 
image(const char * img)202 static QString image(const char *img)
203 {
204     // ### escape?
205     return KIconLoader::global()->iconPath(QLatin1String(img), KIconLoader::Small);
206 }
207 
makeOverview(const QString & msg)208 QString Task::Result::makeOverview(const QString &msg)
209 {
210     return QLatin1String("<b>") + msg + QLatin1String("</b>");
211 }
212 
iconPath(VisualCode code)213 QString Task::Result::iconPath(VisualCode code)
214 {
215     switch (code) {
216     case Danger:
217         return image("dialog-error");
218     case AllGood:
219         return image("dialog-ok");
220     case Warning:
221         return image("dialog-warning");
222     case NeutralError:
223     case NeutralSuccess:
224     default:
225         return QString();
226 
227     }
228 }
229 
icon() const230 QString Task::Result::icon() const
231 {
232     return iconPath(code());
233 }
234 
235 #include "moc_task_p.cpp"
236