1 /*
2 SPDX-FileCopyrightText: 2002 Jean-Baptiste Mardelle <bj@altern.org>
3 SPDX-FileCopyrightText: 2007, 2008, 2009, 2010, 2011, 2012 Rolf Eike Beer <kde@opensource.sf-tec.de>
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "selectpublickeydialog.h"
8
9 #include "kgpgsettings.h"
10 #include "core/images.h"
11 #include "core/KGpgRootNode.h"
12 #include "model/kgpgitemmodel.h"
13 #include "model/selectkeyproxymodel.h"
14
15 #include <QAction>
16 #include <QCheckBox>
17 #include <QDialogButtonBox>
18 #include <QHBoxLayout>
19 #include <QLabel>
20 #include <QLineEdit>
21 #include <QPushButton>
22 #include <QTableView>
23
24 #include <KActionCollection>
25 #include <KConfigGroup>
26 #include <KLocalizedString>
27
28 using namespace KgpgCore;
29
KgpgSelectPublicKeyDlg(QWidget * parent,KGpgItemModel * model,const QKeySequence & goDefaultKey,const bool hideasciioption,const QList<QUrl> & files)30 KgpgSelectPublicKeyDlg::KgpgSelectPublicKeyDlg(QWidget *parent, KGpgItemModel *model, const QKeySequence &goDefaultKey, const bool hideasciioption, const QList<QUrl> &files)
31 : QDialog(parent),
32 m_customoptions(nullptr),
33 imodel(model),
34 m_files(files),
35 m_hideasciioption(hideasciioption)
36 {
37 QWidget *mainWidget = new QWidget(this);
38 QVBoxLayout *mainLayout = new QVBoxLayout(this);
39 setLayout(mainLayout);
40 mainLayout->setSizeConstraint(QLayout::SetMinimumSize);
41 mainLayout->addWidget(mainWidget);
42
43 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
44 m_okButton = buttonBox->button(QDialogButtonBox::Ok);
45 m_okButton->setDefault(true);
46 m_okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
47 m_detailsButton = new QPushButton(this);
48 m_detailsButton->setText(i18n("&Options") + QStringLiteral(" >>"));
49 m_detailsButton->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
50 connect(m_detailsButton, &QPushButton::clicked, this, &KgpgSelectPublicKeyDlg::toggleDetails);
51 buttonBox->addButton(m_detailsButton, QDialogButtonBox::ActionRole);
52 connect(buttonBox, &QDialogButtonBox::accepted, this, &KgpgSelectPublicKeyDlg::accept);
53 connect(buttonBox, &QDialogButtonBox::rejected, this, &KgpgSelectPublicKeyDlg::reject);
54 m_okButton->setDefault(true);
55
56 int fcount = files.count();
57 bool fmode = (fcount > 0);
58
59 switch (fcount) {
60 case 0:
61 setWindowTitle(i18n("Select Public Key"));
62 break;
63 case 1:
64 setWindowTitle(i18n("Select Public Key for %1", files.first().fileName()));
65 break;
66 default:
67 setWindowTitle(i18np("Select Public Key for %2 and one more file", "Select Public Key for %2 and %1 more files", files.count() - 1, files.first().fileName()));
68 }
69
70 QWidget *page = new QWidget(this);
71
72 m_searchbar = new QWidget(page);
73 QHBoxLayout *searchbarHBoxLayout = new QHBoxLayout(m_searchbar);
74 searchbarHBoxLayout->setContentsMargins(0, 0, 0, 0);
75 QLabel *searchlabel = new QLabel(i18n("&Search: "), m_searchbar);
76 searchbarHBoxLayout->addWidget(searchlabel);
77
78 m_searchlineedit = new QLineEdit(m_searchbar);
79 searchbarHBoxLayout->addWidget(m_searchlineedit);
80 m_searchlineedit->setClearButtonEnabled(true);
81 searchlabel->setBuddy(m_searchlineedit);
82
83 iproxy = new SelectKeyProxyModel(this);
84 iproxy->setKeyModel(imodel);
85
86 m_keyslist = new QTableView(page);
87 m_keyslist->setSortingEnabled(true);
88 m_keyslist->setSelectionMode(QAbstractItemView::ExtendedSelection);
89 m_keyslist->setSelectionBehavior(QAbstractItemView::SelectRows);
90 m_keyslist->setModel(iproxy);
91 m_keyslist->resizeColumnsToContents();
92 m_keyslist->setWhatsThis(i18n("<b>Public keys list</b>: select the key that will be used for encryption."));
93 connect(m_searchlineedit, &QLineEdit::textChanged, iproxy, &SelectKeyProxyModel::setFilterFixedString);
94
95 optionsbox = new QWidget();
96 QVBoxLayout *optionsboxVBoxLayout = new QVBoxLayout(optionsbox);
97 optionsboxVBoxLayout->setContentsMargins(0, 0, 0, 0);
98 optionsbox->hide();
99
100 if (m_hideasciioption)
101 m_cbarmor = nullptr;
102 else
103 {
104 m_cbarmor = new QCheckBox(i18n("ASCII armored encryption"), optionsbox);
105 optionsboxVBoxLayout->addWidget(m_cbarmor);
106 m_cbarmor->setChecked(KGpgSettings::asciiArmor());
107 m_cbarmor->setWhatsThis(i18n("<b>ASCII encryption</b>: makes it possible to open the encrypted file/message in a text editor"));
108 }
109
110 m_cbuntrusted = new QCheckBox(i18n("Allow encryption with untrusted keys"), optionsbox);
111 optionsboxVBoxLayout->addWidget(m_cbuntrusted);
112 // connect before setting the state so the model gets the right state from the start
113 connect(m_cbuntrusted, &QCheckBox::toggled, this, &KgpgSelectPublicKeyDlg::slotUntrusted);
114 m_cbuntrusted->setChecked(KGpgSettings::allowUntrustedKeys());
115 m_cbuntrusted->setWhatsThis(i18n("<b>Allow encryption with untrusted keys</b>: when you import a public key, it is usually "
116 "marked as untrusted and you cannot use it unless you sign it in order to make it 'trusted'. Checking this "
117 "box enables you to use any key, even if it has not be signed."));
118
119 m_cbhideid = new QCheckBox(i18n("Hide user id"), optionsbox);
120 optionsboxVBoxLayout->addWidget(m_cbhideid);
121 m_cbhideid->setChecked(KGpgSettings::hideUserID());
122 m_cbhideid->setWhatsThis(i18n("<b>Hide user ID</b>: Do not put the keyid into encrypted packets. This option hides the receiver "
123 "of the message and is a countermeasure against traffic analysis. It may slow down the decryption process because "
124 "all available secret keys are tried."));
125
126 m_cbsymmetric = new QCheckBox(i18n("Symmetrical encryption"), optionsbox);
127 optionsboxVBoxLayout->addWidget(m_cbsymmetric);
128 m_cbsymmetric->setWhatsThis(i18n("<b>Symmetrical encryption</b>: encryption does not use keys. You just need to give a password "
129 "to encrypt/decrypt the file"));
130
131 QVBoxLayout *dialoglayout = new QVBoxLayout(page);
132 dialoglayout->setContentsMargins(0, 0, 0, 0);
133 dialoglayout->addWidget(m_searchbar);
134 dialoglayout->addWidget(m_keyslist);
135 page->setLayout(dialoglayout);
136
137 if (KGpgSettings::allowCustomEncryptionOptions())
138 {
139 QWidget *expertbox = new QWidget(page);
140 QHBoxLayout *expertboxHBoxLayout = new QHBoxLayout(expertbox);
141 expertboxHBoxLayout->setContentsMargins(0, 0, 0, 0);
142 (void) new QLabel(i18n("Custom option:"), expertbox);
143
144 m_customoptions = new QLineEdit(expertbox);
145 expertboxHBoxLayout->addWidget(m_customoptions);
146 m_customoptions->setText(KGpgSettings::customEncryptionOptions());
147 m_customoptions->setWhatsThis(i18n("<b>Custom option</b>: for experienced users only, allows you to enter a gpg command line option, like: '--armor'"));
148
149 dialoglayout->addWidget(expertbox);
150 }
151
152 KActionCollection *actcol = new KActionCollection(this);
153 QAction *action = actcol->addAction(QLatin1String( "go_default_key" ));
154 action->setText(i18n("&Go to Default Key"));
155 actcol->setDefaultShortcut(action, goDefaultKey);
156
157 connect(action, &QAction::triggered, this, &KgpgSelectPublicKeyDlg::slotGotoDefaultKey);
158 connect(m_cbsymmetric, &QCheckBox::toggled, this, &KgpgSelectPublicKeyDlg::slotSymmetric);
159 connect(m_keyslist->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KgpgSelectPublicKeyDlg::slotSelectionChanged);
160 connect(m_keyslist, &QTableView::doubleClicked, this, &KgpgSelectPublicKeyDlg::slotOk);
161
162 setMinimumSize(550, 200);
163 updateGeometry();
164
165 mainLayout->addWidget(page);
166 mainLayout->addWidget(optionsbox);
167 mainLayout->addWidget(buttonBox);
168 slotSelectionChanged();
169
170 if (fmode)
171 slotGotoDefaultKey();
172 }
173
selectedKeys() const174 QStringList KgpgSelectPublicKeyDlg::selectedKeys() const
175 {
176 if (getSymmetric())
177 return QStringList();
178
179 QStringList selectedKeys;
180
181 const QModelIndexList indexes = m_keyslist->selectionModel()->selectedIndexes();
182 for (const QModelIndex &idx : indexes) {
183 if (idx.column() != 0)
184 continue;
185 KGpgNode *nd = iproxy->nodeForIndex(idx);
186 if (nd->getType() == ITYPE_GROUP)
187 selectedKeys << nd->getName();
188 else
189 selectedKeys << nd->getId();
190 }
191
192 return selectedKeys;
193 }
194
getSymmetric() const195 bool KgpgSelectPublicKeyDlg::getSymmetric() const
196 {
197 return m_cbsymmetric->isChecked();
198 }
199
getCustomOptions() const200 QString KgpgSelectPublicKeyDlg::getCustomOptions() const
201 {
202 if (m_customoptions == nullptr)
203 return QString();
204 return m_customoptions->text().simplified();
205 }
206
getUntrusted() const207 bool KgpgSelectPublicKeyDlg::getUntrusted() const
208 {
209 return m_cbuntrusted->isChecked();
210 }
211
getArmor() const212 bool KgpgSelectPublicKeyDlg::getArmor() const
213 {
214 return m_hideasciioption || m_cbarmor->isChecked();
215 }
216
getFiles() const217 const QList<QUrl> &KgpgSelectPublicKeyDlg::getFiles() const
218 {
219 return m_files;
220 }
221
getHideId() const222 bool KgpgSelectPublicKeyDlg::getHideId() const
223 {
224 return m_cbhideid->isChecked();
225 }
226
slotOk()227 void KgpgSelectPublicKeyDlg::slotOk()
228 {
229 if (getSymmetric() || m_keyslist->selectionModel()->hasSelection())
230 accept();
231 }
232
slotSelectionChanged()233 void KgpgSelectPublicKeyDlg::slotSelectionChanged()
234 {
235 m_okButton->setEnabled(getSymmetric() || m_keyslist->selectionModel()->hasSelection());
236 }
237
slotSymmetric(const bool state)238 void KgpgSelectPublicKeyDlg::slotSymmetric(const bool state)
239 {
240 m_keyslist->setDisabled(state);
241 m_cbuntrusted->setDisabled(state);
242 m_cbhideid->setDisabled(state);
243 m_searchbar->setDisabled(state);
244 slotSelectionChanged();
245 }
246
slotUntrusted(const bool state)247 void KgpgSelectPublicKeyDlg::slotUntrusted(const bool state)
248 {
249 iproxy->setShowUntrusted(state);
250 }
251
slotGotoDefaultKey()252 void KgpgSelectPublicKeyDlg::slotGotoDefaultKey()
253 {
254 KGpgNode *nd = imodel->getRootNode()->findKey(KGpgSettings::defaultKey());
255 if (nd == nullptr)
256 return;
257 QModelIndex sidx = imodel->nodeIndex(nd);
258 QModelIndex pidx = iproxy->mapFromSource(sidx);
259 m_keyslist->selectionModel()->setCurrentIndex(pidx, QItemSelectionModel::Clear | QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
260 }
261
toggleDetails()262 void KgpgSelectPublicKeyDlg::toggleDetails()
263 {
264 const bool isVisible = optionsbox->isVisible();
265 optionsbox->setVisible(!isVisible);
266 m_detailsButton->setText(i18n("&Options") + (isVisible ? QStringLiteral(" >>") : QStringLiteral(" <<")));
267 }
268