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
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>
49 #include <QVBoxLayout>
50 #include <QWizardPage>
54 #include <QTextDocument> // Qt::escape
56 #include <boost/bind.hpp>
58 #include <gpg-error.h>
62 using namespace boost
;
63 using namespace GpgME
;
65 using namespace Kleo::Dialogs
;
66 using namespace Kleo::Dialogs::CertifyCertificateDialogPrivate
;
68 void UserIDModel::setCertificateToCertify(const Key
&key
)
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);
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());
101 void SecretKeysModel::setSecretKeys(const std::vector
<Key
> &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);
115 std::vector
<GpgME::Key
> SecretKeysModel::secretKeys() const
120 Key
SecretKeysModel::keyFromItem(const QStandardItem
*item
) const
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()
181 unsigned int SelectCheckLevelPage::checkLevel() const
183 if (m_ui
.checkLevelNotCheckedRB
->isChecked()) {
186 if (m_ui
.checkLevelCasualRB
->isChecked()) {
189 if (m_ui
.checkLevelThoroughlyRB
->isChecked()) {
192 assert(!"No check level radiobutton checked");
196 OptionsPage::OptionsPage(QWidget
*parent
) : QWizardPage(parent
), m_ui()
199 m_ui
.keyListView
->setModel(&m_model
);
200 connect(m_ui
.keyListView
->selectionModel(), &QItemSelectionModel::selectionChanged
, this, &QWizardPage::completeChanged
);
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])));
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();
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
);
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);
262 m_checkLevelLabel
= 0;
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
278 void SummaryPage::setSummary(const SummaryPage::Summary
&sum
)
280 const Key key
= sum
.certificateToCertify
;
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
) {
290 m_checkLevelLabel
->setText(i18n("No statement made"));
293 m_checkLevelLabel
->setText(i18n("Not checked"));
296 m_checkLevelLabel
->setText(i18n("Casually checked"));
299 m_checkLevelLabel
->setText(i18n("Thoroughly checked"));
305 void SummaryPage::setComplete(bool complete
)
307 if (complete
== m_complete
) {
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."));
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."));
324 m_resultLabel
->setText(i18n("Certification successful."));
328 class CertifyCertificateDialog::Private
330 friend class ::Kleo::Dialogs::CertifyCertificateDialog
;
331 CertifyCertificateDialog
*const q
;
334 explicit Private(CertifyCertificateDialog
*qq
)
337 selectUserIDsPage(0),
338 selectCheckLevelPage(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
);
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();
376 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
377 sum
.checkLevel
= selectCheckLevelPage
->checkLevel();
382 sum
.exportable
= optionsPage
->exportableCertificationSelected();
383 sum
.sendToServer
= optionsPage
->sendToServer();
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
422 bool CertifyCertificateDialog::nonRevocableCertificationSelected() const
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
440 #ifdef KLEO_SIGN_KEY_CERTLEVEL_SUPPORT
441 return d
->selectCheckLevelPage
->checkLevel();
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()) {
462 void CertifyCertificateDialog::Private::certificationResult(const Error
&err
)
464 setOperationCompleted();
465 summaryPage
->setResult(err
);
466 ensureSummaryPageVisible();
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
) {
515 #include "moc_certifycertificatedialog.cpp"
516 #include "moc_certifycertificatedialog_p.cpp"