SVN_SILENT made messages (.desktop file) - always resolve ours
[kdepim.git] / kleopatra / dialogs / certifycertificatedialog.cpp
blob6960b26fb34b123ac7594d9a0cc7da484f0c7d88
1 /* -*- mode: c++; c-basic-offset:4 -*-
2 dialogs/signcertificatedialog.cpp
4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2008 Klarälvdalens Datakonsult AB
7 Kleopatra is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Kleopatra is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 In addition, as a special exception, the copyright holders give
22 permission to link the code of this program with any edition of
23 the Qt library by Trolltech AS, Norway (or with modified versions
24 of Qt that use the same license as Qt), and distribute linked
25 combinations including the two. You must obey the GNU General
26 Public License in all respects for all of the code used other than
27 Qt. If you modify this file, you may extend this exception to
28 your version of the file, but you are not obligated to do so. If
29 you do not wish to do so, delete this exception statement from
30 your version.
33 #include <config-kleopatra.h>
35 #include "certifycertificatedialog.h"
37 #include "certifycertificatedialog_p.h"
39 #include <utils/formatting.h>
40 #include <utils/kleo_assert.h>
42 #include <Libkleo/Stl_Util>
44 #include <KLocalizedString>
46 #include <QGridLayout>
47 #include <QStandardItem>
48 #include <QListView>
49 #include <QVBoxLayout>
50 #include <QWizardPage>
51 #include <QCheckBox>
52 #include <QLabel>
54 #include <QTextDocument> // Qt::escape
56 #include <boost/bind.hpp>
58 #include <gpg-error.h>
60 #include <cassert>
62 using namespace boost;
63 using namespace GpgME;
64 using namespace Kleo;
65 using namespace Kleo::Dialogs;
66 using namespace Kleo::Dialogs::CertifyCertificateDialogPrivate;
68 void UserIDModel::setCertificateToCertify(const Key &key)
70 m_key = key;
71 clear();
72 const std::vector<UserID> ids = key.userIDs();
73 for (unsigned int i = 0; i < ids.size(); ++i) {
74 QStandardItem *const item = new QStandardItem;
75 item->setText(Formatting::prettyUserID(key.userID(i)));
76 item->setData(i, UserIDIndex);
77 item->setCheckable(true);
78 item->setEditable(false);
79 appendRow(item);
83 void UserIDModel::setCheckedUserIDs(const std::vector<unsigned int> &uids)
85 const std::vector<unsigned int> sorted = kdtools::sorted(uids);
86 for (unsigned int i = 0, end = rowCount(); i != end; ++i) {
87 item(i)->setCheckState(kdtools::binary_search(sorted, i) ? Qt::Checked : Qt::Unchecked);
91 std::vector<unsigned int> UserIDModel::checkedUserIDs() const
93 std::vector<unsigned int> ids;
94 for (int i = 0; i < rowCount(); ++i)
95 if (item(i)->checkState() == Qt::Checked) {
96 ids.push_back(item(i)->data(UserIDIndex).toUInt());
98 return ids;
101 void SecretKeysModel::setSecretKeys(const std::vector<Key> &keys)
103 clear();
104 m_secretKeys = keys;
105 for (unsigned int i = 0; i < m_secretKeys.size(); ++i) {
106 const Key key = m_secretKeys[i];
107 QStandardItem *const item = new QStandardItem;
108 item->setText(Formatting::formatForComboBox(key));
109 item->setData(i, IndexRole);
110 item->setEditable(false);
111 appendRow(item);
115 std::vector<GpgME::Key> SecretKeysModel::secretKeys() const
117 return m_secretKeys;
120 Key SecretKeysModel::keyFromItem(const QStandardItem *item) const
122 assert(item);
123 const unsigned int idx = item->data(IndexRole).toUInt();
124 assert(idx < m_secretKeys.size());
125 return m_secretKeys[idx];
128 Key SecretKeysModel::keyFromIndex(const QModelIndex &idx) const
130 return keyFromItem(itemFromIndex(idx));
133 SelectUserIDsPage::SelectUserIDsPage(QWidget *parent) : QWizardPage(parent), m_userIDModel()
135 QVBoxLayout *const layout = new QVBoxLayout(this);
136 QLabel *const label = new QLabel;
137 label->setText(i18n("<b>Step 1:</b> Please select the user IDs you wish to certify."));
138 layout->addWidget(label);
139 m_listView = new QListView;
140 m_listView->setModel(&m_userIDModel);
141 layout->addWidget(m_listView, 1);
142 m_label = new QLabel;
143 layout->addWidget(m_label);
144 m_checkbox = new QCheckBox;
145 m_checkbox->setChecked(false);
146 m_checkbox->setText(i18n("I have verified the fingerprint"));
147 layout->addWidget(m_checkbox);
148 connect(m_checkbox, &QCheckBox::toggled, this, &SelectUserIDsPage::completeChanged);
149 connect(&m_userIDModel, &QStandardItemModel::itemChanged, this, &QWizardPage::completeChanged);
152 bool SelectUserIDsPage::isComplete() const
154 return m_checkbox->isChecked() && !selectedUserIDs().empty();
157 void SelectUserIDsPage::setSelectedUserIDs(const std::vector<unsigned int> &uids)
159 m_userIDModel.setCheckedUserIDs(uids);
162 std::vector<unsigned int> SelectUserIDsPage::selectedUserIDs() const
164 return m_userIDModel.checkedUserIDs();
167 void SelectUserIDsPage::setCertificateToCertify(const Key &key)
169 m_label->setText(i18n("Certificate: %1\nFingerprint: %2",
170 Formatting::formatForComboBox(key),
171 QLatin1String(key.primaryFingerprint())));
172 m_userIDModel.setCertificateToCertify(key);
176 SelectCheckLevelPage::SelectCheckLevelPage(QWidget *parent) : QWizardPage(parent), m_ui()
178 m_ui.setupUi(this);
181 unsigned int SelectCheckLevelPage::checkLevel() const
183 if (m_ui.checkLevelNotCheckedRB->isChecked()) {
184 return 1;
186 if (m_ui.checkLevelCasualRB->isChecked()) {
187 return 2;
189 if (m_ui.checkLevelThoroughlyRB->isChecked()) {
190 return 3;
192 assert(!"No check level radiobutton checked");
193 return 0;
196 OptionsPage::OptionsPage(QWidget *parent) : QWizardPage(parent), m_ui()
198 m_ui.setupUi(this);
199 m_ui.keyListView->setModel(&m_model);
200 connect(m_ui.keyListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QWizardPage::completeChanged);
201 setCommitPage(true);
202 setButtonText(QWizard::CommitButton, i18n("Certify"));
205 bool OptionsPage::exportableCertificationSelected() const
207 return m_ui.exportableSignatureRB->isChecked();
210 void OptionsPage::setCertificatesWithSecretKeys(const std::vector<Key> &keys)
212 assert(!keys.empty());
213 m_model.setSecretKeys(keys);
214 if (keys.size() == 1) {
215 m_ui.stackedWidget->setCurrentWidget(m_ui.singleKeyPage);
216 m_ui.singleKeyLabel->setText(i18n("Certification will be performed using certificate %1.", Formatting::prettyNameAndEMail(keys[0])));
217 } else {
218 m_ui.stackedWidget->setCurrentWidget(m_ui.multipleKeysPage);
220 Q_EMIT completeChanged();
223 Key OptionsPage::selectedSecretKey() const
225 if (m_model.secretKeys().size() == 1) {
226 return m_model.secretKeys().at(0);
228 const QModelIndexList idxs = m_ui.keyListView->selectionModel()->selectedIndexes();
229 assert(idxs.size() <= 1);
230 return idxs.isEmpty() ? Key() : m_model.keyFromIndex(idxs[0]);
233 bool OptionsPage::sendToServer() const
235 return m_ui.sendToServerCB->isChecked();
238 bool OptionsPage::validatePage()
240 Q_EMIT nextClicked();
241 return true;
244 bool OptionsPage::isComplete() const
246 return !selectedSecretKey().isNull();
249 SummaryPage::SummaryPage(QWidget *parent) : QWizardPage(parent), m_complete(false)
251 QGridLayout *const layout = new QGridLayout(this);
252 QLabel *const uidLabelLabel = new QLabel(i18n("Signed user IDs:"));
253 uidLabelLabel->setAlignment(Qt::AlignTop);
254 int row = 0;
255 layout->addWidget(new QLabel(i18n("<b>Summary:</b>")), row, 0, 1, 2);
256 layout->addWidget(uidLabelLabel, ++row, 0);
257 layout->addWidget(m_userIDsLabel = new QLabel, row, 1);
258 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
259 layout->addWidget(new QLabel(i18n("Check level:")), ++row, 0);
260 layout->addWidget(m_checkLevelLabel = new QLabel, row, 1);
261 #else
262 m_checkLevelLabel = 0;
263 #endif
264 layout->addWidget(new QLabel(i18n("Selected secret key:")), ++row, 0);
265 layout->addWidget(m_secretKeyLabel = new QLabel, row, 1);
266 m_secretKeyLabel->setTextFormat(Qt::PlainText);
267 layout->addWidget(m_resultLabel = new QLabel, ++row, 0, 1, 2, Qt::AlignCenter);
268 m_resultLabel->setWordWrap(true);
269 layout->setRowStretch(row, 1);
270 m_resultLabel->setAlignment(Qt::AlignCenter);
273 bool SummaryPage::isComplete() const
275 return m_complete;
278 void SummaryPage::setSummary(const SummaryPage::Summary &sum)
280 const Key key = sum.certificateToCertify;
281 QStringList ids;
282 Q_FOREACH (const unsigned int i, sum.selectedUserIDs) {
283 ids += Formatting::prettyUserID(key.userID(i)).toHtmlEscaped();
285 m_userIDsLabel->setText(QLatin1String("<qt>") + ids.join(QStringLiteral("<br/>")) + QLatin1String("</qt>"));
286 m_secretKeyLabel->setText(sum.secretKey.isNull() ? i18n("Default certificate") : Formatting::prettyNameAndEMail(sum.secretKey));
287 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
288 switch (sum.checkLevel) {
289 case 0:
290 m_checkLevelLabel->setText(i18n("No statement made"));
291 break;
292 case 1:
293 m_checkLevelLabel->setText(i18n("Not checked"));
294 break;
295 case 2:
296 m_checkLevelLabel->setText(i18n("Casually checked"));
297 break;
298 case 3:
299 m_checkLevelLabel->setText(i18n("Thoroughly checked"));
300 break;
302 #endif
305 void SummaryPage::setComplete(bool complete)
307 if (complete == m_complete) {
308 return;
310 m_complete = complete;
311 Q_EMIT completeChanged();
313 void SummaryPage::setResult(const Error &err)
315 if (err && !err.isCanceled())
316 if (err.code() == GPG_ERR_USER_1) {
317 m_resultLabel->setText(i18n("The certificate was not certified because it was already certified by the same certificate."));
318 } else {
319 m_resultLabel->setText(i18n("The certificate could not be certified. <b>Error</b>: %1", QString::fromLocal8Bit(err.asString()).toHtmlEscaped()));
321 else if (err.isCanceled()) {
322 m_resultLabel->setText(i18n("Certification canceled."));
323 } else {
324 m_resultLabel->setText(i18n("Certification successful."));
328 class CertifyCertificateDialog::Private
330 friend class ::Kleo::Dialogs::CertifyCertificateDialog;
331 CertifyCertificateDialog *const q;
333 public:
334 explicit Private(CertifyCertificateDialog *qq)
335 : q(qq),
336 summaryPageId(0),
337 selectUserIDsPage(0),
338 selectCheckLevelPage(0),
339 optionsPage(0),
340 summaryPage(0)
342 selectUserIDsPage = new SelectUserIDsPage(q);
343 q->addPage(selectUserIDsPage);
344 //selectCheckLevelPage = new SelectCheckLevelPage( q );
345 //setting the cert level explicitly is not supported by the backend,
346 //thus we omit the page from the UI
347 //q->addPage( selectCheckLevelPage );
348 optionsPage = new OptionsPage(q);
349 q->addPage(optionsPage);
350 summaryPage = new SummaryPage(q);
351 summaryPageId = q->addPage(summaryPage);
352 connect(optionsPage, &OptionsPage::nextClicked, q, &CertifyCertificateDialog::certificationPrepared);
355 Key key() const
357 return selectUserIDsPage ? selectUserIDsPage->certificateToCertify() : Key();
360 void ensureSummaryPageVisible();
362 void certificationResult(const Error &error);
364 void setOperationCompleted()
366 summaryPage->setComplete(true);
369 SummaryPage::Summary createSummary() const
371 SummaryPage::Summary sum;
372 sum.selectedUserIDs = selectUserIDsPage->selectedUserIDs();
373 sum.secretKey = optionsPage->selectedSecretKey();
374 sum.certificateToCertify = selectUserIDsPage->certificateToCertify();
375 //PENDING
376 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
377 sum.checkLevel = selectCheckLevelPage->checkLevel();
378 #else
379 sum.checkLevel = 0;
380 #endif
382 sum.exportable = optionsPage->exportableCertificationSelected();
383 sum.sendToServer = optionsPage->sendToServer();
384 return sum;
387 int summaryPageId;
388 SelectUserIDsPage *selectUserIDsPage;
389 SelectCheckLevelPage *selectCheckLevelPage;
390 OptionsPage *optionsPage;
391 SummaryPage *summaryPage;
394 CertifyCertificateDialog::CertifyCertificateDialog(QWidget *p, Qt::WindowFlags f)
395 : QWizard(p, f), d(new Private(this))
399 CertifyCertificateDialog::~CertifyCertificateDialog() {}
401 void CertifyCertificateDialog::setCertificateToCertify(const Key &key)
403 setWindowTitle(i18nc("arg is name, email of certificate holder", "Certify Certificate: %1", Formatting::prettyName(key)));
404 d->selectUserIDsPage->setCertificateToCertify(key);
407 void CertifyCertificateDialog::setCertificatesWithSecretKeys(const std::vector<Key> &keys)
409 d->optionsPage->setCertificatesWithSecretKeys(keys);
412 bool CertifyCertificateDialog::exportableCertificationSelected() const
414 return d->optionsPage->exportableCertificationSelected();
417 bool CertifyCertificateDialog::trustCertificationSelected() const
419 return false;
422 bool CertifyCertificateDialog::nonRevocableCertificationSelected() const
424 return false;
427 Key CertifyCertificateDialog::selectedSecretKey() const
429 return d->optionsPage->selectedSecretKey();
432 bool CertifyCertificateDialog::sendToServer() const
434 return d->optionsPage->sendToServer();
437 unsigned int CertifyCertificateDialog::selectedCheckLevel() const
439 //PENDING
440 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
441 return d->selectCheckLevelPage->checkLevel();
442 #endif
443 return 0;
446 void CertifyCertificateDialog::connectJob(SignKeyJob *job)
448 connect(job, SIGNAL(result(GpgME::Error)), this, SLOT(certificationResult(GpgME::Error)));
449 d->summaryPage->setSummary(d->createSummary());
452 void CertifyCertificateDialog::setError(const Error &error)
454 d->setOperationCompleted();
455 d->summaryPage->setResult(error);
456 d->ensureSummaryPageVisible();
457 if (error.isCanceled()) {
458 close();
462 void CertifyCertificateDialog::Private::certificationResult(const Error &err)
464 setOperationCompleted();
465 summaryPage->setResult(err);
466 ensureSummaryPageVisible();
469 namespace
471 struct UidEqual : std::binary_function<UserID, UserID, bool> {
472 bool operator()(const UserID &lhs, const UserID &rhs) const
474 return qstrcmp(lhs.parent().primaryFingerprint(),
475 rhs.parent().primaryFingerprint()) == 0
476 && qstrcmp(lhs.id(), rhs.id()) == 0;
481 void CertifyCertificateDialog::setSelectedUserIDs(const std::vector<UserID> &uids)
483 const Key key = d->key();
484 const char *const fpr = key.primaryFingerprint();
486 const std::vector<UserID> all = key.userIDs();
488 std::vector<unsigned int> indexes;
489 indexes.reserve(uids.size());
491 Q_FOREACH (const UserID &uid, uids) {
492 kleo_assert(qstrcmp(uid.parent().primaryFingerprint(), fpr) == 0);
493 const unsigned int idx =
494 std::distance(all.begin(), kdtools::find_if(all, boost::bind(UidEqual(), _1, uid)));
495 if (idx < all.size()) {
496 indexes.push_back(idx);
500 d->selectUserIDsPage->setSelectedUserIDs(indexes);
503 std::vector<unsigned int> CertifyCertificateDialog::selectedUserIDs() const
505 return d->selectUserIDsPage->selectedUserIDs();
508 void CertifyCertificateDialog::Private::ensureSummaryPageVisible()
510 while (q->currentId() != summaryPageId) {
511 q->next();
515 #include "moc_certifycertificatedialog.cpp"
516 #include "moc_certifycertificatedialog_p.cpp"