summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Heinecke <aheinecke@intevation.de>2016-05-18 10:53:00 (GMT)
committerAndre Heinecke <aheinecke@intevation.de>2016-08-02 10:11:49 (GMT)
commit4ab1c5cd5363916374edebf7585797af4be788b0 (patch)
treed74179286ed8183038c29df14a5bc7ee3184c70d
parente001135eab16bdd2f5393a795d869a50e37d9933 (diff)
Rework certificateselectionwidget to lineedit
Behaves now more like Address entry field, shares model between line edits. Full certificateselection dialog available on request. After user feedback a single line edit with the certificatelineedit for free entry certificate selection and an improved combobox for preset certificates was decided to be better then a mushed one for all widget. So we now use a combination of certificatecombobox and certificatelineedit for certificate selection. When adding / removing recipients this should behave like the address entry in KMail. Brings up certificatedetails when a key is found, otherwise shows the old certificate selection dialog which allows you to add mutliple certificates in one go so that there is no functionality lost.
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/crypto/gui/certificatelineedit.cpp209
-rw-r--r--src/crypto/gui/certificatelineedit.h (renamed from src/crypto/gui/certificateselectionwidget.h)71
-rw-r--r--src/crypto/gui/certificateselectionwidget.cpp146
-rw-r--r--src/crypto/gui/signencryptwidget.cpp142
-rw-r--r--src/crypto/gui/signencryptwidget.h19
-rw-r--r--src/utils/formatting.cpp29
-rw-r--r--src/utils/formatting.h2
8 files changed, 408 insertions, 213 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 052f57b..36598d2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -145,8 +145,8 @@ set(_kleopatra_SRCS
crypto/gui/wizardpage.cpp
crypto/gui/certificateselectionline.cpp
- crypto/gui/certificateselectionwidget.cpp
crypto/gui/certificatecombobox.cpp
+ crypto/gui/certificatelineedit.cpp
crypto/gui/signingcertificateselectionwidget.cpp
crypto/gui/signingcertificateselectiondialog.cpp
@@ -170,7 +170,6 @@ set(_kleopatra_SRCS
crypto/gui/signemailwizard.cpp
crypto/gui/signencryptwidget.cpp
crypto/gui/signencryptwizard.cpp
- crypto/gui/certificateselectionwidget.cpp
crypto/gui/verifychecksumsdialog.cpp
diff --git a/src/crypto/gui/certificatelineedit.cpp b/src/crypto/gui/certificatelineedit.cpp
new file mode 100644
index 0000000..bd01783
--- /dev/null
+++ b/src/crypto/gui/certificatelineedit.cpp
@@ -0,0 +1,209 @@
+/* crypto/gui/certificatelineedit.cpp
+
+ This file is part of Kleopatra, the KDE keymanager
+ Copyright (c) 2016 Intevation GmbH
+
+ Kleopatra is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ Kleopatra is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include "certificatelineedit.h"
+
+#include <QHBoxLayout>
+#include <QComboBox>
+#include <QLineEdit>
+#include <QCompleter>
+#include <QFontMetrics>
+#include <QSortFilterProxyModel>
+#include <QLabel>
+#include <QPushButton>
+#include <QAction>
+#include <QSignalBlocker>
+
+#include "kleopatra_debug.h"
+
+#include "models/keylistmodel.h"
+#include "models/keylistsortfilterproxymodel.h"
+#include "dialogs/certificateselectiondialog.h"
+#include "utils/formatting.h"
+#include "commands/detailscommand.h"
+
+#include <Libkleo/KeyFilter>
+
+#include <KLocalizedString>
+#include <KIconLoader>
+
+#include <gpgme++/key.h>
+
+using namespace Kleo;
+using namespace Kleo::Dialogs;
+using namespace GpgME;
+
+Q_DECLARE_METATYPE(Key);
+
+#define MINIMUM_WIDTH_STR "Short Short<LongLong@MiddleDomain.co.uk> (12345678 - OpenPGP)"
+
+CertificateLineEdit::CertificateLineEdit(AbstractKeyListModel *model,
+ QWidget *parent,
+ KeyFilter *filter)
+ : QWidget(parent),
+ mEdit(new QLineEdit()),
+ mFilterModel(new KeyListSortFilterProxyModel(this)),
+ mFilter(boost::shared_ptr<KeyFilter>(filter)),
+ mEditStarted(false),
+ mEditFinished(false),
+ mLineAction(new QAction(Q_NULLPTR))
+{
+ auto *hLay = new QHBoxLayout;
+ mEdit->setPlaceholderText(i18n("Please enter a name or email address..."));
+ hLay->addWidget(mEdit, -1);
+ mEdit->addAction(mLineAction, QLineEdit::LeadingPosition);
+
+ QFontMetrics fm(font());
+ mEdit->setMinimumWidth(fm.width(QStringLiteral(MINIMUM_WIDTH_STR)));
+
+ auto *completer = new QCompleter(this);
+ auto *completeFilterModel = new KeyListSortFilterProxyModel(completer);
+ completeFilterModel->setKeyFilter(mFilter);
+ completeFilterModel->setSourceModel(model);
+ completer->setModel(completeFilterModel);
+ completer->setCompletionColumn(KeyListModelInterface::Summary);
+ completer->setFilterMode(Qt::MatchContains);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ mEdit->setCompleter(completer);
+ mFilterModel->setSourceModel(model);
+ mFilterModel->setFilterKeyColumn(KeyListModelInterface::Summary);
+ if (filter) {
+ mFilterModel->setKeyFilter(mFilter);
+ }
+
+ connect(model, &QAbstractItemModel::dataChanged,
+ this, &CertificateLineEdit::updateKey);
+ connect(mEdit, &QLineEdit::editingFinished,
+ this, &CertificateLineEdit::updateKey);
+ connect(mEdit, &QLineEdit::textChanged,
+ this, &CertificateLineEdit::editChanged);
+ connect(mLineAction, &QAction::triggered,
+ this, &CertificateLineEdit::dialogRequested);
+
+ setLayout(hLay);
+ updateKey();
+
+ /* Take ownership of the model to prevent double deletion when the
+ * filter models are deleted */
+ model->setParent(parent ? parent : this);
+}
+
+void CertificateLineEdit::editChanged()
+{
+ updateKey();
+ if (!mEditStarted) {
+ Q_EMIT editingStarted();
+ mEditStarted = true;
+ }
+ mEditFinished = false;
+}
+
+void CertificateLineEdit::updateKey()
+{
+ const auto mailText = mEdit->text();
+ auto newKey = Key();
+ if (mailText.isEmpty()) {
+ Q_EMIT wantsRemoval(this);
+ mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("question")));
+ mLineAction->setToolTip(i18n("Please select a certificate."));
+ } else {
+ mFilterModel->setFilterFixedString(mailText);
+ if (mFilterModel->rowCount() > 1) {
+ if (mEditFinished) {
+ mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("question")).pixmap(KIconLoader::SizeSmallMedium));
+ mLineAction->setToolTip(i18n("Multiple certificates"));
+ }
+ } else if (mFilterModel->rowCount() == 1) {
+ newKey = mFilterModel->data(mFilterModel->index(0, 0), KeyListModelInterface::KeyRole).value<Key>();
+ mLineAction->setToolTip(Formatting::validity(newKey.userID(0)) +
+ QStringLiteral("<br/>Click here for details."));
+ /* FIXME: This needs to be solved by a multiple UID supporting model */
+ mLineAction->setIcon(Formatting::iconForUid(newKey.userID(0)));
+ } else {
+ mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("emblem-error")));
+ mLineAction->setToolTip(i18n("No matching certificates found.<br/>Click here to import a certificate."));
+ }
+ }
+ mKey = newKey;
+
+ if (mKey.isNull()) {
+ mEdit->setToolTip(QString());
+ } else {
+ mEdit->setToolTip(Formatting::toolTip(newKey, Formatting::ToolTipOption::AllOptions));
+ }
+
+ Q_EMIT keyChanged();
+}
+
+Key CertificateLineEdit::key() const
+{
+ return mKey;
+}
+
+void CertificateLineEdit::dialogRequested()
+{
+ if (!mKey.isNull()) {
+ auto cmd = new Commands::DetailsCommand(mKey, Q_NULLPTR);
+ cmd->start();
+ return;
+ }
+
+ CertificateSelectionDialog *const dlg = new CertificateSelectionDialog(this);
+
+ dlg->setKeyFilter(mFilter);
+
+ if (dlg->exec()) {
+ const std::vector<Key> keys = dlg->selectedCertificates();
+ if (!keys.size()) {
+ return;
+ }
+ for (unsigned int i = 0; i < keys.size(); i++) {
+ if (!i) {
+ setKey(keys[i]);
+ } else {
+ Q_EMIT addRequested(keys[i]);
+ }
+ }
+ }
+ updateKey();
+}
+
+void CertificateLineEdit::setKey(const Key &k)
+{
+ QSignalBlocker blocky(this);
+ qCDebug(KLEOPATRA_LOG) << "Setting Key. " << Formatting::summaryLine(k);
+ mEdit->setText(Formatting::summaryLine(k));
+}
+
+bool CertificateLineEdit::isEmpty() const
+{
+ return mEdit->text().isEmpty();
+}
diff --git a/src/crypto/gui/certificateselectionwidget.h b/src/crypto/gui/certificatelineedit.h
index b538aaa..35f1757 100644
--- a/src/crypto/gui/certificateselectionwidget.h
+++ b/src/crypto/gui/certificatelineedit.h
@@ -1,4 +1,4 @@
-/* crypto/gui/certificateselectionwidget.h
+/* crypto/gui/certificatelineedit.h
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2016 Intevation GmbH
@@ -28,64 +28,89 @@
you do not wish to do so, delete this exception statement from
your version.
*/
-#ifndef CRYPTO_GUI_CERTIFICATESELECTIONWIDGET_H
-#define CRYPTO_GUI_CERTIFICATESELECTIONWIDGET_H
+#ifndef CRYPTO_GUI_CERTIFICATELINEEDIT_H
+#define CRYPTO_GUI_CERTIFICATELINEEDIT_H
class QLineEdit;
#include <QWidget>
#include <QString>
+#include <gpgme++/key.h>
+#include <boost/shared_ptr.hpp>
+
#include "dialogs/certificateselectiondialog.h"
+class QLabel;
+class QAction;
+
namespace Kleo
{
class AbstractKeyListModel;
+class KeyFilter;
class KeyListSortFilterProxyModel;
-class CertificateComboBox;
-/** Generic Certificate Selection Widget.
+/** Line edit and completion based Certificate Selection Widget.
*
- * This class does not care about protocols. By default it will
- * prefer OpenPGP. Uses the KeyCache directly to fill the choices for
- * the selected capabilities.
+ * Shows the status of the selection with a status label and icon.
*
* The widget will use a single line HBox Layout. For larger dialog
* see certificateslectiondialog.
*/
-class CertificateSelectionWidget: public QWidget
+class CertificateLineEdit: public QWidget
{
Q_OBJECT
public:
/** Create the certificate selection line.
*
+ * If parent is not NULL the model is not taken
+ * over but the parent arugment used as the parent of the model.
+ *
+ * @param model: The keylistmodel to use.
* @param parent: The usual widget parent.
* @param options: The options to use. See certificateselectiondialog.
- * @param mailbox: If a mailbox entry should be shown.
- * @param defaultFpr: The default fingerprint to fill this with.
*/
- CertificateSelectionWidget(QWidget *parent = Q_NULLPTR,
- int otions = Dialogs::CertificateSelectionDialog::AnyFormat,
- bool mailbox = true,
- const QString &defaultFpr = QString());
+ CertificateLineEdit(AbstractKeyListModel *model,
+ QWidget *parent = Q_NULLPTR,
+ KeyFilter *filter = Q_NULLPTR);
/** Get the selected key */
GpgME::Key key() const;
+ /** Check if the text is empty */
+ bool isEmpty() const;
+
+ /** Set the preselected Key for this widget. */
+ void setKey(const GpgME::Key &key);
+
Q_SIGNALS:
- /** Emited when the selected key changed. */
+ /** Emitted when the selected key changed. */
void keyChanged();
+ /** Emitted when the entry is empty and editing is finished. */
+ void wantsRemoval(CertificateLineEdit *w);
+
+ /** Emitted when the entry is no longer empty. */
+ void editingStarted();
+
+ /** Emitted when the certselectiondialog resulted in multiple certificates. */
+ void addRequested(const GpgME::Key &key);
+
private Q_SLOTS:
- void keysMayHaveChanged();
- void mailEntryChanged();
+ void updateKey();
+ void dialogRequested();
+ void editChanged();
private:
- CertificateComboBox *mCombo;
- QLineEdit *mMailEntry;
- int mOptions;
- AbstractKeyListModel *mModel;
+ QLineEdit *mEdit;
KeyListSortFilterProxyModel *mFilterModel;
+ QLabel *mStatusLabel,
+ *mStatusIcon;
+ GpgME::Key mKey;
+ boost::shared_ptr<KeyFilter> mFilter;
+ bool mEditStarted,
+ mEditFinished;
+ QAction *mLineAction;
};
}
-#endif // CRYPTO_GUI_CERTIFICATESELECTIONWIDGET_H
+#endif
diff --git a/src/crypto/gui/certificateselectionwidget.cpp b/src/crypto/gui/certificateselectionwidget.cpp
deleted file mode 100644
index d7c2fbf..0000000
--- a/src/crypto/gui/certificateselectionwidget.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/* crypto/gui/certificateselectionwidget.cpp
-
- This file is part of Kleopatra, the KDE keymanager
- Copyright (c) 2016 Intevation GmbH
-
- Kleopatra is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- Kleopatra is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include "certificateselectionwidget.h"
-
-#include <QHBoxLayout>
-#include <QComboBox>
-#include <QLineEdit>
-#include <QCompleter>
-#include <QFontMetrics>
-
-#include <boost/shared_ptr.hpp>
-
-#include "models/keylistmodel.h"
-#include "models/keylistsortfilterproxymodel.h"
-#include "models/keycache.h"
-#include "dialogs/certificateselectiondialog.h"
-#include "certificatecombobox.h"
-
-#include <KLocalizedString>
-
-#include <gpgme++/key.h>
-
-using namespace Kleo;
-using namespace Kleo::Dialogs;
-using namespace GpgME;
-
-Q_DECLARE_METATYPE(Key);
-
-#define MINIMUM_WIDTH_STR "Short LongLong <LongLong@MiddleDomain.co.uk> (12345678 - OpenPGP)"
-#define MINIMUM_MAIL_WIDTH_STR "Short.Short@MiddleDomain.co.uk"
-CertificateSelectionWidget::CertificateSelectionWidget(QWidget *parent,
- int options, bool mailbox,
- const QString &defaultFpr)
- : QWidget(parent),
- mCombo(new CertificateComboBox(i18n("Please select a certificate"))),
- mMailEntry(new QLineEdit()),
- mOptions(options),
- mModel(AbstractKeyListModel::createFlatKeyListModel(this)),
- mFilterModel(new KeyListSortFilterProxyModel(this))
-{
- QHBoxLayout *hLay = new QHBoxLayout;
- mMailEntry->setPlaceholderText(i18n("E-Mail"));
- mMailEntry->setVisible(mailbox);
- hLay->addWidget(mMailEntry, 1);
- hLay->addWidget(mCombo, 1);
- QFontMetrics fm(font());
- mCombo->setMinimumWidth(fm.width(QStringLiteral(MINIMUM_WIDTH_STR)));
- mCombo->setMaxVisibleItems(8); // According to VDG
- mMailEntry->setMinimumWidth(fm.width(QStringLiteral(MINIMUM_MAIL_WIDTH_STR)));
-
- QCompleter *completer = new QCompleter(this);
- completer->setModel(mModel);
- completer->setCompletionRole(Qt::EditRole);
- completer->setCompletionColumn(KeyListModelInterface::PrettyEMail);
- mMailEntry->setCompleter(completer);
-
- mFilterModel->setSourceModel(mModel);
- mCombo->setModel(mFilterModel);
- mCombo->setModelColumn(KeyListModelInterface::Summary);
-
- connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged,
- this, &CertificateSelectionWidget::keysMayHaveChanged);
- connect(mMailEntry, &QLineEdit::textChanged,
- this, &CertificateSelectionWidget::mailEntryChanged);
- connect(mCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &CertificateSelectionWidget::keyChanged);
-
- keysMayHaveChanged();
-
- if (mailbox) {
- // When there is no mail entry shown we just show our stuff.
- mCombo->setCurrentIndex(-1);
- }
-
- setLayout(hLay);
-}
-
-void CertificateSelectionWidget::keysMayHaveChanged()
-{
- std::vector<Key> keys = (mOptions & CertificateSelectionDialog::SecretKeys) ? KeyCache::instance()->secretKeys()
- : KeyCache::instance()->keys();
- CertificateSelectionDialog::filterAllowedKeys(keys, mOptions);
- bool wasUnselected = mCombo->currentIndex() == -1;
- mModel->setKeys(keys);
- mFilterModel->sort(KeyListModelInterface::Summary);
- if (wasUnselected && mMailEntry->isVisible() && mMailEntry->text().isEmpty()) {
- mCombo->setCurrentIndex(-1);
- }
-}
-
-void CertificateSelectionWidget::mailEntryChanged()
-{
- const QString mailText = mMailEntry->text();
- if (mailText.isEmpty()) {
- mCombo->setCurrentIndex(-1);
- return;
- }
- mFilterModel->setFilterFixedString(mailText);
- if (mFilterModel->rowCount()) {
- mCombo->setModel(mFilterModel);
- if (mCombo->currentIndex() == -1) {
- mCombo->setCurrentIndex(0);
- }
- } else {
- mCombo->setInitialText(i18n("(no matching certificates found)"));
- mCombo->setCurrentIndex(-1);
- }
-}
-
-Key CertificateSelectionWidget::key() const
-{
- int idx = mCombo->currentIndex();
- if (idx == -1) {
- return Key();
- }
- return mCombo->currentData(KeyListModelInterface::KeyRole).value<Key>();
-}
diff --git a/src/crypto/gui/signencryptwidget.cpp b/src/crypto/gui/signencryptwidget.cpp
index c3e8064..8296648 100644
--- a/src/crypto/gui/signencryptwidget.cpp
+++ b/src/crypto/gui/signencryptwidget.cpp
@@ -33,7 +33,8 @@
#include "kleopatra_debug.h"
-#include "certificateselectionwidget.h"
+#include "certificatecombobox.h"
+#include "certificatelineedit.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
@@ -41,45 +42,92 @@
#include <QCheckBox>
#include <QScrollArea>
-#include <Libkleo/KeyRequester>
+#include <Libkleo/DefaultKeyFilter>
#include <KLocalizedString>
#include <KSharedConfig>
+#include "models/keylistmodel.h"
+#include "models/keylistsortfilterproxymodel.h"
+
using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace GpgME;
+namespace {
+class SignCertificateFilter: public DefaultKeyFilter
+{
+public:
+ SignCertificateFilter() : DefaultKeyFilter()
+ {
+ setRevoked(DefaultKeyFilter::NotSet);
+ setExpired(DefaultKeyFilter::NotSet);
+ setHasSecret(DefaultKeyFilter::Set);
+ setCanSign(DefaultKeyFilter::Set);
+ }
+};
+class EncryptCertificateFilter: public DefaultKeyFilter
+{
+public:
+ EncryptCertificateFilter(): DefaultKeyFilter()
+ {
+ setRevoked(DefaultKeyFilter::NotSet);
+ setExpired(DefaultKeyFilter::NotSet);
+ setCanEncrypt(DefaultKeyFilter::Set);
+ }
+};
+class EncryptSelfCertificateFilter: public EncryptCertificateFilter
+{
+public:
+ EncryptSelfCertificateFilter(): EncryptCertificateFilter()
+ {
+ setRevoked(DefaultKeyFilter::NotSet);
+ setExpired(DefaultKeyFilter::NotSet);
+ setCanEncrypt(DefaultKeyFilter::Set);
+ setHasSecret(DefaultKeyFilter::Set);
+ }
+};
+}
+
SignEncryptWidget::SignEncryptWidget(QWidget *parent)
- : QWidget(parent)
+ : QWidget(parent),
+ mModel(AbstractKeyListModel::createFlatKeyListModel(this))
{
QVBoxLayout *lay = new QVBoxLayout;
+ setContentsMargins(-6,-6,-6,-6);
+
+ mModel->useKeyCache(true, false);
/* The signature selection */
QHBoxLayout *sigLay = new QHBoxLayout;
- QCheckBox *sigChk = new QCheckBox(i18nc("@action", "Sign"));
+ QGroupBox *sigGrp = new QGroupBox(i18nc("@label", "Prove authenticity (sign)"));
+ QCheckBox *sigChk = new QCheckBox(i18nc("@label", "Sign as:"));
sigChk->setChecked(true);
- mSigSelect = new CertificateSelectionWidget(this,
- CertificateSelectionDialog::SignOnly |
- CertificateSelectionDialog::SecretKeys |
- CertificateSelectionDialog::AnyFormat,
- false);
+
+ KeyListSortFilterProxyModel *sigModel = new KeyListSortFilterProxyModel(this);
+ sigModel->setKeyFilter(boost::shared_ptr<KeyFilter>(new SignCertificateFilter()));
+ sigModel->setSourceModel(mModel);
+ mModel->setParent(this);
+
+ mSigSelect = new CertificateComboBox(i18n("No valid secret keys found."));
+ mSigSelect->setModel(sigModel);
+ mSigSelect->setModelColumn(KeyListModelInterface::Summary);
+
sigLay->addWidget(sigChk);
+ sigLay->addStretch(1);
sigLay->addWidget(mSigSelect);
- lay->addLayout(sigLay);
+ sigGrp->setLayout(sigLay);
+ lay->addWidget(sigGrp);
connect(sigChk, &QCheckBox::toggled, mSigSelect, &QWidget::setEnabled);
connect(sigChk, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
- connect(mSigSelect, &CertificateSelectionWidget::keyChanged,
+ connect(mSigSelect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &SignEncryptWidget::updateOp);
/* Recipient selection */
- mRecpLayout = new QVBoxLayout;
+ mRecpLayout = new QGridLayout;
mRecpLayout->setAlignment(Qt::AlignTop);
- mRecpLayout->addStretch(1);
QGroupBox *encBox = new QGroupBox(i18nc("@action", "Encrypt"));
- encBox->setCheckable(true);
- encBox->setChecked(true);
encBox->setAlignment(Qt::AlignLeft);
QVBoxLayout *encBoxLay = new QVBoxLayout;
encBox->setLayout(encBoxLay);
@@ -97,11 +145,15 @@ SignEncryptWidget::SignEncryptWidget(QWidget *parent)
QHBoxLayout *encSelfLay = new QHBoxLayout;
QCheckBox *encSelfChk = new QCheckBox(i18nc("@label", "Own certificate:"));
encSelfChk->setChecked(true);
- mSelfSelect = new CertificateSelectionWidget(this,
- CertificateSelectionDialog::EncryptOnly |
- CertificateSelectionDialog::SecretKeys |
- CertificateSelectionDialog::AnyFormat,
- false);
+
+ KeyListSortFilterProxyModel *encModel = new KeyListSortFilterProxyModel(this);
+ encModel->setKeyFilter(boost::shared_ptr<KeyFilter>(new EncryptSelfCertificateFilter()));
+ encModel->setSourceModel(mModel);
+ mModel->setParent(this);
+
+ mSelfSelect = new CertificateComboBox(i18n("No valid secret keys found."));
+ mSelfSelect->setModel(encModel);
+ mSelfSelect->setModelColumn(KeyListModelInterface::Summary);
encSelfLay->addWidget(encSelfChk);
encSelfLay->addWidget(mSelfSelect);
@@ -109,7 +161,7 @@ SignEncryptWidget::SignEncryptWidget(QWidget *parent)
connect(encSelfChk, &QCheckBox::toggled, mSelfSelect, &QWidget::setEnabled);
connect(encSelfChk, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
- connect(mSelfSelect, &CertificateSelectionWidget::keyChanged,
+ connect(mSelfSelect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &SignEncryptWidget::updateOp);
lay->addWidget(encBox);
@@ -121,20 +173,34 @@ SignEncryptWidget::SignEncryptWidget(QWidget *parent)
void SignEncryptWidget::addRecipient()
{
- CertificateSelectionWidget *certSel = new CertificateSelectionWidget(this,
- CertificateSelectionDialog::EncryptOnly |
- CertificateSelectionDialog::AnyFormat,
- true);
+ addRecipient(Key());
+}
+
+void SignEncryptWidget::addRecipient(const Key &key)
+{
+ CertificateLineEdit *certSel = new CertificateLineEdit(mModel, this,
+ new EncryptCertificateFilter());
mRecpWidgets << certSel;
- mRecpLayout->insertWidget(mRecpLayout->count() - 1, certSel);
- connect(certSel, &CertificateSelectionWidget::keyChanged,
+
+ mRecpLayout->addWidget(certSel, mRecpLayout->rowCount(), 0);
+ connect(certSel, &CertificateLineEdit::keyChanged,
this, &SignEncryptWidget::recipientsChanged);
+ connect(certSel, &CertificateLineEdit::wantsRemoval,
+ this, &SignEncryptWidget::recpRemovalRequested);
+ connect(certSel, &CertificateLineEdit::editingStarted,
+ this, static_cast<void (SignEncryptWidget::*)()>(&SignEncryptWidget::addRecipient));
+ connect(certSel, &CertificateLineEdit::addRequested,
+ this, static_cast<void (SignEncryptWidget::*)(const Key&)>(&SignEncryptWidget::addRecipient));
+
+ if (!key.isNull()) {
+ certSel->setKey(key);
+ }
}
void SignEncryptWidget::recipientsChanged()
{
bool oneEmpty = false;
- Q_FOREACH (const CertificateSelectionWidget *w, mRecpWidgets) {
+ Q_FOREACH (const CertificateLineEdit *w, mRecpWidgets) {
if (w->key().isNull()) {
oneEmpty = true;
break;
@@ -165,7 +231,7 @@ Key SignEncryptWidget::selfKey() const
QVector <Key> SignEncryptWidget::recipients() const
{
QVector<Key> ret;
- Q_FOREACH (const CertificateSelectionWidget *w, mRecpWidgets) {
+ Q_FOREACH (const CertificateLineEdit *w, mRecpWidgets) {
if (!w->isEnabled()) {
// If one is disabled, all are disabled.
break;
@@ -208,3 +274,21 @@ QString SignEncryptWidget::currentOp() const
{
return mOp;
}
+
+void SignEncryptWidget::recpRemovalRequested(CertificateLineEdit *w)
+{
+ if (!w) {
+ return;
+ }
+ int emptyEdits = 0;
+ Q_FOREACH (const CertificateLineEdit *edit, mRecpWidgets) {
+ if (edit->isEmpty()) {
+ emptyEdits++;
+ }
+ if (emptyEdits > 1) {
+ mRecpLayout->removeWidget(w);
+ mRecpWidgets.removeAll(w);
+ return;
+ }
+ }
+}
diff --git a/src/crypto/gui/signencryptwidget.h b/src/crypto/gui/signencryptwidget.h
index 1578774..4706fbc 100644
--- a/src/crypto/gui/signencryptwidget.h
+++ b/src/crypto/gui/signencryptwidget.h
@@ -36,11 +36,13 @@
#include <QMap>
#include <gpgme++/key.h>
-class QVBoxLayout;
+class QGridLayout;
namespace Kleo
{
-class CertificateSelectionWidget;
+class CertificateLineEdit;
+class CertificateComboBox;
+class AbstractKeyListModel;
class SignEncryptWidget: public QWidget
{
@@ -67,9 +69,9 @@ public:
protected Q_SLOTS:
void updateOp();
void recipientsChanged();
-
-protected:
+ void recpRemovalRequested(CertificateLineEdit *w);
void addRecipient();
+ void addRecipient(const GpgME::Key &key);
Q_SIGNALS:
/* Emitted when the certificate selection changed the operation
@@ -81,11 +83,12 @@ Q_SIGNALS:
void keysChanged();
private:
- CertificateSelectionWidget *mSigSelect,
- *mSelfSelect;
- QVector<CertificateSelectionWidget *> mRecpWidgets;
- QVBoxLayout *mRecpLayout;
+ CertificateComboBox *mSigSelect,
+ *mSelfSelect;
+ QVector<CertificateLineEdit *> mRecpWidgets;
+ QGridLayout *mRecpLayout;
QString mOp;
+ AbstractKeyListModel *mModel;
};
} // namespace Kleo
#endif // CRYPTO_GUI_SIGNENCRYPTWIDGET_H
diff --git a/src/utils/formatting.cpp b/src/utils/formatting.cpp
index faa5142..6db4976 100644
--- a/src/utils/formatting.cpp
+++ b/src/utils/formatting.cpp
@@ -756,7 +756,10 @@ QString Formatting::usageString(const Subkey &sub)
QString Formatting::summaryLine(const Key &key)
{
- return keyToString(key) + QStringLiteral(" (%1 - %2)").arg(key.shortKeyID()).arg(displayName(key.protocol()));
+ return keyToString(key) + QStringLiteral(" ") +
+ i18nc("First arg is the Key Protocol OpenPGP or S/MIME, second arg is the creation date.",
+ "(%1 - created: %2)", displayName(key.protocol()) ,
+ Formatting::creationDateString(key));
}
// Icon for certificate selection indication
@@ -764,16 +767,32 @@ QIcon Formatting::iconForUid(const UserID &uid)
{
switch (uid.validity()) {
case UserID::Ultimate:
- return QIcon::fromTheme(QStringLiteral("emblem-favorite"));
case UserID::Full:
- return QIcon::fromTheme(QStringLiteral("emblem-success"));
case UserID::Marginal:
- return QIcon::fromTheme(QStringLiteral("emblem-information"));
+ return QIcon::fromTheme(QStringLiteral("emblem-success"));
case UserID::Never:
return QIcon::fromTheme(QStringLiteral("emblem-error"));
case UserID::Undefined:
case UserID::Unknown:
default:
- return QIcon::fromTheme(QStringLiteral("emblem-warning"));
+ return QIcon::fromTheme(QStringLiteral("emblem-information"));
+ }
+}
+
+QString Formatting::validity(const UserID &uid)
+{
+ switch (uid.validity()) {
+ case UserID::Ultimate:
+ return i18n("The certificate is marked as your own.");
+ case UserID::Full:
+ return i18n("The certificate belongs to this recipient.");
+ case UserID::Marginal:
+ return i18n("The trust model indicates marginally that the certificate belongs to this recipient.");
+ case UserID::Never:
+ return i18n("This certificate should not be used.");
+ case UserID::Undefined:
+ case UserID::Unknown:
+ default:
+ return i18n("There is no indication that this certificate belongs to this recipient.");
}
}
diff --git a/src/utils/formatting.h b/src/utils/formatting.h
index c345069..8c0282c 100644
--- a/src/utils/formatting.h
+++ b/src/utils/formatting.h
@@ -111,6 +111,8 @@ QString ownerTrustShort(GpgME::Key::OwnerTrust trust);
QString validityShort(const GpgME::Subkey &subkey);
QString validityShort(const GpgME::UserID &uid);
QString validityShort(const GpgME::UserID::Signature &sig);
+/* A sentence about the validity of the UserID */
+QString validity(const GpgME::UserID &uid);
QString formatForComboBox(const GpgME::Key &key);