keysmanager.cpp 87.5 KB
Newer Older
1 2
/*
 * Copyright (C) 2002 Jean-Baptiste Mardelle <bj@altern.org>
3
 * Copyright (C) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017
4
 *               Rolf Eike Beer <kde@opensource.sf-tec.de>
5
 * Copyright (C) 2011 Luis Ángel Fernández Fernández <laffdez@gmail.com>
6
 * Copyright (C) 2016 Andrius Štikonas <andrius@stikonas.eu>
7
 */
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
8 9 10 11 12 13 14 15 16 17

/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/

Urs Wolfer's avatar
Urs Wolfer committed
18 19
#include "keysmanager.h"

Rolf Eike Beer's avatar
Rolf Eike Beer committed
20 21 22 23
#include "caff.h"
#include "core/images.h"
#include "core/kgpgkey.h"
#include "detailedconsole.h"
24
#include "gpgproc.h"
Rolf Eike Beer's avatar
Rolf Eike Beer committed
25
#include "groupedit.h"
26
#include "keyadaptor.h"
Rolf Eike Beer's avatar
Rolf Eike Beer committed
27 28 29 30
#include "keyexport.h"
#include "keyinfodialog.h"
#include "keyservers.h"
#include "keytreeview.h"
Laurent Montel's avatar
Laurent Montel committed
31
#include "kgpg_general_debug.h"
Rolf Eike Beer's avatar
Rolf Eike Beer committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#include "kgpg.h"
#include "kgpgchangekey.h"
#include "kgpgkeygenerate.h"
#include "kgpgoptions.h"
#include "kgpgrevokewidget.h"
#include "kgpgsettings.h"
#include "newkey.h"
#include "selectpublickeydialog.h"
#include "selectsecretkey.h"
#include "sourceselect.h"
#include "editor/kgpgeditor.h"
#include "editor/kgpgtextedit.h"
#include "model/keylistproxymodel.h"
#include "transactions/kgpgaddphoto.h"
#include "transactions/kgpgadduid.h"
#include "transactions/kgpgdecrypt.h"
#include "transactions/kgpgdelkey.h"
#include "transactions/kgpgdelsign.h"
#include "transactions/kgpgdeluid.h"
#include "transactions/kgpgencrypt.h"
#include "transactions/kgpgexport.h"
#include "transactions/kgpggeneratekey.h"
#include "transactions/kgpggeneraterevoke.h"
#include "transactions/kgpgimport.h"
#include "transactions/kgpgkeyservergettransaction.h"
#include "transactions/kgpgprimaryuid.h"
#include "transactions/kgpgsignkey.h"
#include "transactions/kgpgsignuid.h"
#include "transactions/kgpgtransactionjob.h"
61

62 63 64 65 66
#include <algorithm>

#include <Akonadi/Contact/ContactEditor>
#include <Akonadi/Contact/ContactEditorDialog>
#include <Akonadi/Contact/ContactSearchJob>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
67
#include <KActionCollection>
68 69 70
#include <KContacts/AddresseeList>
// #include <KContacts/Key> TODO
#include <KIO/Global>
71
#include <KIO/ApplicationLauncherJob>
Ahmad Samir's avatar
Ahmad Samir committed
72 73
#include <KIO/OpenUrlJob>
#include <KIO/JobUiDelegate>
74
#include <KJobTrackerInterface>
Andrius Štikonas's avatar
Andrius Štikonas committed
75
#include <KLocalizedString>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
76 77 78 79
#include <KMessageBox>
#include <KProcess>
#include <KSelectAction>
#include <KService>
80
#include <KSharedConfig>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
81
#include <KStandardAction>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
82
#include <KStandardGuiItem>
Urs Wolfer's avatar
Urs Wolfer committed
83
#include <KStandardShortcut>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
84
#include <KStatusNotifierItem>
85
#include <KTipDialog>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
86
#include <KToggleAction>
Andrius Štikonas's avatar
Andrius Štikonas committed
87

Rolf Eike Beer's avatar
Rolf Eike Beer committed
88 89
#include <QApplication>
#include <QClipboard>
Andrius Štikonas's avatar
Andrius Štikonas committed
90
#include <QDBusConnection>
Laurent Montel's avatar
Laurent Montel committed
91

92
#include <QDesktopServices>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
93 94
#include <QDir>
#include <QEvent>
95
#include <QFileDialog>
Andrius Štikonas's avatar
Andrius Štikonas committed
96
#include <QIcon>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
97
#include <QInputDialog>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
98 99
#include <QKeySequence>
#include <QLabel>
Andrius Štikonas's avatar
Andrius Štikonas committed
100
#include <QLineEdit>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
101
#include <QList>
Andrius Štikonas's avatar
Andrius Štikonas committed
102
#include <QMenu>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
103
#include <QMetaObject>
104
#include <QNetworkConfigurationManager>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
105 106 107 108
#include <QPainter>
#include <QPrintDialog>
#include <QPrinter>
#include <QProcess>
109
#include <QRegularExpression>
Andrius Štikonas's avatar
Andrius Štikonas committed
110
#include <QStatusBar>
Andrius Štikonas's avatar
Andrius Štikonas committed
111
#include <QUrl>
Rolf Eike Beer's avatar
Rolf Eike Beer committed
112
#include <QWidget>
Andrius Štikonas's avatar
Andrius Štikonas committed
113
#include <QWidgetAction>
Urs Wolfer's avatar
Urs Wolfer committed
114

115
using namespace KgpgCore;
116 117

KeysManager::KeysManager(QWidget *parent)
118
           : KXmlGuiWindow(parent),
Rolf Eike Beer's avatar
Rolf Eike Beer committed
119
	   imodel(new KGpgItemModel(this)),
Rolf Eike Beer's avatar
Rolf Eike Beer committed
120 121 122 123 124
	   m_adduid(nullptr),
	   m_genkey(nullptr),
	   m_delkey(nullptr),
	   terminalkey(nullptr),
	   m_trayicon(nullptr)
125
{
126
	new KeyAdaptor(this);
Laurent Montel's avatar
Laurent Montel committed
127
	QDBusConnection::sessionBus().registerObject(QLatin1String( "/KeyInterface" ), this);
128 129 130 131

	setAttribute(Qt::WA_DeleteOnClose, false);
	setWindowTitle(i18n("Key Management"));

132
	KStandardAction::quit(this, &KeysManager::quitApp, actionCollection());
Laurent Montel's avatar
Laurent Montel committed
133
	actionCollection()->addAction(KStandardAction::Preferences, QLatin1String( "options_configure" ), this, SLOT(showOptions()));
134

135
	openEditor = actionCollection()->addAction(QLatin1String("kgpg_editor"), this, &KeysManager::slotOpenEditor);
Andrius Štikonas's avatar
Andrius Štikonas committed
136
	openEditor->setIcon(QIcon::fromTheme( QLatin1String( "accessories-text-editor" )));
137 138
	openEditor->setText(i18n("&Open Editor"));

139
	kserver = actionCollection()->addAction( QLatin1String("key_server"), this, &KeysManager::showKeyServer);
140
	kserver->setText( i18n("&Key Server Dialog") );
Andrius Štikonas's avatar
Andrius Štikonas committed
141
	kserver->setIcon( QIcon::fromTheme( QLatin1String( "network-server" )) );
142

143
	goToDefaultKey = actionCollection()->addAction(QLatin1String("go_default_key"), this, &KeysManager::slotGotoDefaultKey);
Andrius Štikonas's avatar
Andrius Štikonas committed
144
	goToDefaultKey->setIcon(QIcon::fromTheme( QLatin1String( "go-home" )));
Rolf Eike Beer's avatar
Rolf Eike Beer committed
145
	goToDefaultKey->setText(i18n("&Go to Default Key"));
146
	actionCollection()->setDefaultShortcut(goToDefaultKey, QKeySequence(Qt::CTRL + Qt::Key_Home));
Rolf Eike Beer's avatar
Rolf Eike Beer committed
147

148
	s_kgpgEditor = new KgpgEditor(this, imodel, Qt::Dialog);
149
	s_kgpgEditor->setAttribute(Qt::WA_DeleteOnClose, false);
Rolf Eike Beer's avatar
Rolf Eike Beer committed
150

151 152 153 154 155 156 157
	// this must come after kserver, preferences, and openEditor are created
	// because they are used to set up the tray icon context menu
	readOptions();

	if (showTipOfDay)
		installEventFilter(this);

Andrius Štikonas's avatar
Andrius Štikonas committed
158
	QAction *action;
159

160
	action = actionCollection()->addAction(QLatin1String("help_tipofday"), this, &KeysManager::slotTip);
Andrius Štikonas's avatar
Andrius Štikonas committed
161
	action->setIcon( QIcon::fromTheme( QLatin1String( "help-hint" )) );
162 163
	action->setText( i18n("Tip of the &Day") );

164
	action = actionCollection()->addAction(QLatin1String("gpg_man"), this, &KeysManager::slotManpage);
165
	action->setText( i18n("View GnuPG Manual") );
Andrius Štikonas's avatar
Andrius Štikonas committed
166
	action->setIcon( QIcon::fromTheme( QLatin1String( "help-contents" )) );
167

168
	action = actionCollection()->addAction(QLatin1String("key_refresh"), this, &KeysManager::refreshkey);
Andrius Štikonas's avatar
Andrius Štikonas committed
169
	action->setIcon(QIcon::fromTheme( QLatin1String( "view-refresh" )));
170
	action->setText(i18n("&Refresh List"));
171
	actionCollection()->setDefaultShortcuts(action, KStandardShortcut::reload());
172

173
	longId = actionCollection()->add<KToggleAction>(QLatin1String("show_long_keyid"), this, &KeysManager::slotShowLongId);
174
	longId->setText(i18n("Show &Long Key Id"));
175 176
	longId->setChecked(KGpgSettings::showLongKeyId());

177
	QAction *infoKey = actionCollection()->addAction(QLatin1String("key_info"), this, &KeysManager::keyproperties);
Andrius Štikonas's avatar
Andrius Štikonas committed
178
	infoKey->setIcon(QIcon::fromTheme( QLatin1String( "document-properties-key" )));
179
	infoKey->setText(i18n("K&ey Properties"));
180

181
	QAction *openKeyUrl = actionCollection()->addAction(QLatin1String("key_url"), this, &KeysManager::slotOpenKeyUrl);
182
	openKeyUrl->setIcon(QIcon::fromTheme(QLatin1String("internet-services")));
183 184
	openKeyUrl->setText(i18n("&Open Key URL"));

185
	editKey = actionCollection()->addAction(QLatin1String("key_edit"), this, &KeysManager::slotedit);
Andrius Štikonas's avatar
Andrius Štikonas committed
186
	editKey->setIcon(QIcon::fromTheme( QLatin1String( "utilities-terminal" )));
187
	editKey->setText(i18n("Edit Key in &Terminal"));
188
	actionCollection()->setDefaultShortcut(editKey, QKeySequence(Qt::ALT + Qt::Key_Return));
189

190
	QAction *generateKey = actionCollection()->addAction(QLatin1String("key_gener"), this, &KeysManager::slotGenerateKey);
Andrius Štikonas's avatar
Andrius Štikonas committed
191
	generateKey->setIcon(QIcon::fromTheme( QLatin1String( "key-generate-pair" )));
192
	generateKey->setText(i18n("&Generate Key Pair..."));
193
	actionCollection()->setDefaultShortcuts(generateKey, KStandardShortcut::shortcut(KStandardShortcut::New));
194

195
	exportPublicKey = actionCollection()->addAction(QLatin1String("key_export"), this, &KeysManager::slotexport);
Andrius Štikonas's avatar
Andrius Štikonas committed
196
	exportPublicKey->setIcon(QIcon::fromTheme( QLatin1String( "document-export-key" )));
197
	actionCollection()->setDefaultShortcuts(exportPublicKey, KStandardShortcut::shortcut(KStandardShortcut::Copy));
198

199
	QAction *importKey = actionCollection()->addAction(QLatin1String("key_import"), this, &KeysManager::slotPreImportKey);
Andrius Štikonas's avatar
Andrius Štikonas committed
200
	importKey->setIcon(QIcon::fromTheme( QLatin1String( "document-import-key" )));
201
	importKey->setText(i18n("&Import Key..."));
202
	actionCollection()->setDefaultShortcuts(importKey, KStandardShortcut::shortcut(KStandardShortcut::Paste));
203

204
	m_sendEmail = actionCollection()->addAction(QLatin1String("send_mail"), this, &KeysManager::slotSendEmail);
Andrius Štikonas's avatar
Andrius Štikonas committed
205
	m_sendEmail->setIcon(QIcon::fromTheme(QLatin1String("mail-send")));
206
	m_sendEmail->setText(i18n("Send Ema&il"));
207

208
	QAction *newContact = actionCollection()->addAction(QLatin1String("add_kab"), this, &KeysManager::addToKAB);
Andrius Štikonas's avatar
Andrius Štikonas committed
209
	newContact->setIcon(QIcon::fromTheme( QLatin1String( "contact-new" )));
210 211
	newContact->setText(i18n("&Create New Contact in Address Book"));

212
	createGroup = actionCollection()->addAction(QLatin1String("create_group"), this, &KeysManager::createNewGroup);
213
	createGroup->setIcon(Images::group());
214

215
	editCurrentGroup = actionCollection()->addAction(QLatin1String("edit_group"), this, &KeysManager::editGroup);
216
	editCurrentGroup->setText(i18n("&Edit Group..."));
217

218
	delGroup = actionCollection()->addAction(QLatin1String("delete_group"), this, &KeysManager::deleteGroup);
219
	delGroup->setText(i18n("&Delete Group"));
Andrius Štikonas's avatar
Andrius Štikonas committed
220
	delGroup->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
221

222
	m_groupRename = actionCollection()->addAction(QLatin1String("rename_group"), this, &KeysManager::renameGroup);
223
	m_groupRename->setText(i18n("&Rename Group"));
Andrius Štikonas's avatar
Andrius Štikonas committed
224
	m_groupRename->setIcon(QIcon::fromTheme( QLatin1String( "edit-rename" )));
225
	actionCollection()->setDefaultShortcut(m_groupRename, QKeySequence(Qt::Key_F2));
226

227
	deleteKey = actionCollection()->addAction(QLatin1String("key_delete"), this, &KeysManager::confirmdeletekey);
Andrius Štikonas's avatar
Andrius Štikonas committed
228
	deleteKey->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
229
	actionCollection()->setDefaultShortcut(deleteKey, QKeySequence(Qt::Key_Delete));
230

231
	setDefaultKey = actionCollection()->addAction(QLatin1String("key_default"), this, &KeysManager::slotSetDefKey);
232
	setDefaultKey->setText(i18n("Set as De&fault Key"));
233

234
	QAction *addPhoto = actionCollection()->addAction(QLatin1String("add_photo"), this, &KeysManager::slotAddPhoto);
235
	addPhoto->setText(i18n("&Add Photo..."));
236

237
	QAction *addUid = actionCollection()->addAction(QLatin1String("add_uid"), this, &KeysManager::slotAddUid);
238
	addUid->setText(i18n("&Add User Id..."));
239

240
	QAction *exportSecretKey = actionCollection()->addAction(QLatin1String("key_sexport"), this, &KeysManager::slotexportsec);
241
	exportSecretKey->setText(i18n("Export Secret Key..."));
242

243
	QAction *deleteKeyPair = actionCollection()->addAction(QLatin1String("key_pdelete"), this, &KeysManager::deleteseckey);
244
	deleteKeyPair->setText(i18n("Delete Key Pair"));
Andrius Štikonas's avatar
Andrius Štikonas committed
245
	deleteKeyPair->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
246

247
	m_revokeKey = actionCollection()->addAction(QLatin1String("key_revoke"), this, &KeysManager::revokeWidget);
248
	m_revokeKey->setText(i18n("Revoke Key..."));
249

250
	QAction *regeneratePublic = actionCollection()->addAction(QLatin1String("key_regener"), this, &KeysManager::slotregenerate);
251
	regeneratePublic->setText(i18n("&Regenerate Public Key"));
252

253
	delUid = actionCollection()->addAction(QLatin1String("del_uid"), this, &KeysManager::slotDelUid);
Andrius Štikonas's avatar
Andrius Štikonas committed
254
	delUid->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
255

256
	setPrimUid = actionCollection()->addAction(QLatin1String("prim_uid"), this, &KeysManager::slotPrimUid);
257
	setPrimUid->setText(i18n("Set User Id as &Primary"));
258

259
	QAction *openPhoto = actionCollection()->addAction(QLatin1String("key_photo"), this, &KeysManager::slotShowPhoto);
Andrius Štikonas's avatar
Andrius Štikonas committed
260
	openPhoto->setIcon(QIcon::fromTheme( QLatin1String( "image-x-generic" )));
261
	openPhoto->setText(i18n("&Open Photo"));
262

263
	QAction *deletePhoto = actionCollection()->addAction(QLatin1String("delete_photo"), this, &KeysManager::slotDeletePhoto);
Andrius Štikonas's avatar
Andrius Štikonas committed
264
	deletePhoto->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
265
	deletePhoto->setText(i18n("&Delete Photo"));
266

267
	delSignKey = actionCollection()->addAction(QLatin1String("key_delsign"), this, &KeysManager::delsignkey);
Andrius Štikonas's avatar
Andrius Štikonas committed
268
	delSignKey->setIcon(QIcon::fromTheme( QLatin1String( "edit-delete" )));
269
	delSignKey->setEnabled(false);
270

271
	importAllSignKeys = actionCollection()->addAction(QLatin1String("key_importallsign"), this, &KeysManager::importallsignkey);
Andrius Štikonas's avatar
Andrius Štikonas committed
272
	importAllSignKeys->setIcon(QIcon::fromTheme( QLatin1String( "document-import" )));
273
	importAllSignKeys->setText(i18n("Import &Missing Signatures From Keyserver"));
274

275
	refreshKey = actionCollection()->addAction(QLatin1String("key_server_refresh"), this, &KeysManager::refreshKeyFromServer);
Andrius Štikonas's avatar
Andrius Štikonas committed
276
	refreshKey->setIcon(QIcon::fromTheme( QLatin1String( "view-refresh" )));
277

278
	signKey = actionCollection()->addAction(QLatin1String("key_sign"), this, &KeysManager::signkey);
Andrius Štikonas's avatar
Andrius Štikonas committed
279
	signKey->setIcon(QIcon::fromTheme( QLatin1String( "document-sign-key" )));
280

281
	signUid = actionCollection()->addAction(QLatin1String("key_sign_uid"), this, &KeysManager::signuid);
Andrius Štikonas's avatar
Andrius Štikonas committed
282
	signUid->setIcon(QIcon::fromTheme( QLatin1String( "document-sign-key" )));
283

284
	signMailUid = actionCollection()->addAction(QLatin1String("key_sign_mail_uid"), this, &KeysManager::caff);
Andrius Štikonas's avatar
Andrius Štikonas committed
285
	signMailUid->setIcon(QIcon::fromTheme( QLatin1String( "document-sign-key" )));
286

287
	importSignatureKey = actionCollection()->addAction(QLatin1String("key_importsign"), this, &KeysManager::preimportsignkey);
Andrius Štikonas's avatar
Andrius Štikonas committed
288
	importSignatureKey->setIcon(QIcon::fromTheme( QLatin1String( "document-import-key" )));
289

290
	sTrust = actionCollection()->add<KToggleAction>(QLatin1String("show_trust"), this, &KeysManager::slotShowTrust);
291
	sTrust->setText(i18n("Trust"));
292

293
	sSize = actionCollection()->add<KToggleAction>(QLatin1String("show_size"), this, &KeysManager::slotShowSize);
294
	sSize->setText(i18n("Size"));
295

296
	sCreat = actionCollection()->add<KToggleAction>(QLatin1String("show_creat"), this, &KeysManager::slotShowCreation);
297
	sCreat->setText(i18n("Creation"));
298

299
	sExpi = actionCollection()->add<KToggleAction>(QLatin1String("show_expi"), this, &KeysManager::slotShowExpiration);
300 301
	sExpi->setText(i18n("Expiration"));

Laurent Montel's avatar
Laurent Montel committed
302
	photoProps = actionCollection()->add<KSelectAction>(QLatin1String( "photo_settings" ));
Andrius Štikonas's avatar
Andrius Štikonas committed
303
	photoProps->setIcon(QIcon::fromTheme( QLatin1String( "image-x-generic" )));
304 305 306 307 308 309 310 311 312 313
	photoProps->setText(i18n("&Photo ID's"));

	// Keep the list in kgpg.kcfg in sync with this one!
	QStringList list;
	list.append(i18n("Disable"));
	list.append(i18nc("small picture", "Small"));
	list.append(i18nc("medium picture", "Medium"));
	list.append(i18nc("large picture", "Large"));
	photoProps->setItems(list);

Laurent Montel's avatar
Laurent Montel committed
314
	trustProps = actionCollection()->add<KSelectAction>(QLatin1String( "trust_filter_settings" ));
315
	trustProps->setText(i18n("Minimum &Trust"));
316 317 318 319 320 321 322 323 324 325 326 327

	QStringList tlist;
	tlist.append(i18nc("no filter: show all keys", "&None"));
	tlist.append(i18nc("show only active keys", "&Active"));
	tlist.append(i18nc("show only keys with at least marginal trust", "&Marginal"));
	tlist.append(i18nc("show only keys with at least full trust", "&Full"));
	tlist.append(i18nc("show only ultimately trusted keys", "&Ultimate"));

	trustProps->setItems(tlist);

	iproxy = new KeyListProxyModel(this);
	iproxy->setKeyModel(imodel);
328
	connect(this, &KeysManager::readAgainOptions, iproxy, &KeyListProxyModel::settingsChanged);
329 330

	iview = new KeyTreeView(this, iproxy);
331 332
	connect(iview, &KeyTreeView::doubleClicked, this, QOverload<const QModelIndex &>::of(&KeysManager::defaultAction));
	connect(iview, &KeyTreeView::importDrop, this, QOverload<const QList<QUrl> &>::of(&KeysManager::slotImport));
333 334 335 336 337
	iview->setSelectionMode(QAbstractItemView::ExtendedSelection);
	setCentralWidget(iview);
	iview->resizeColumnsToContents();
	iview->setAlternatingRowColors(true);
	iview->setSortingEnabled(true);
338
	connect(iview, &KeyTreeView::customContextMenuRequested, this, &KeysManager::slotMenu);
339
	iview->setContextMenuPolicy(Qt::CustomContextMenu);
340
	connect(iview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KeysManager::checkList);
341

342
	connect(iview, &KeyTreeView::returnPressed, this, &KeysManager::slotDefaultAction);
343

344
	hPublic = actionCollection()->add<KToggleAction>(QLatin1String("show_secret"), iproxy, &KeyListProxyModel::setOnlySecret);
Andrius Štikonas's avatar
Andrius Štikonas committed
345
	hPublic->setIcon(QIcon::fromTheme( QLatin1String( "view-key-secret" )));
346 347 348
	hPublic->setText(i18n("&Show Only Secret Keys"));
	hPublic->setChecked(KGpgSettings::showSecret());

349 350 351 352 353 354 355 356
	int psize = KGpgSettings::photoProperties();
	photoProps->setCurrentItem(psize);
	slotSetPhotoSize(psize);
	psize = KGpgSettings::trustLevel();
	trustProps->setCurrentItem(psize);
	slotSetTrustFilter(psize);
	slotShowLongId(KGpgSettings::showLongKeyId());

Andrius Štikonas's avatar
Andrius Štikonas committed
357
	m_popuppub = new QMenu(this);
358
	m_popuppub->addAction(exportPublicKey);
359
	m_popuppub->addAction(m_sendEmail);
360
	m_popuppub->addAction(signMailUid);
361 362
	m_popuppub->addAction(signKey);
	m_popuppub->addAction(signUid);
363
	m_popuppub->addAction(deleteKey);
364
	m_popuppub->addAction(infoKey);
365
	m_popuppub->addAction(openKeyUrl);
366 367 368 369 370 371
	m_popuppub->addAction(editKey);
	m_popuppub->addAction(refreshKey);
	m_popuppub->addAction(createGroup);
	m_popuppub->addSeparator();
	m_popuppub->addAction(importAllSignKeys);

Andrius Štikonas's avatar
Andrius Štikonas committed
372
	m_popupsec = new QMenu(this);
373
	m_popupsec->addAction(exportPublicKey);
374
	m_popupsec->addAction(m_sendEmail);
375 376
	m_popupsec->addAction(signKey);
	m_popupsec->addAction(signUid);
377
	m_popupsec->addAction(signMailUid);
378
	m_popupsec->addAction(infoKey);
379
	m_popupsec->addAction(openKeyUrl);
380 381 382 383 384 385 386 387 388 389 390
	m_popupsec->addAction(editKey);
	m_popupsec->addAction(refreshKey);
	m_popupsec->addAction(setDefaultKey);
	m_popupsec->addSeparator();
	m_popupsec->addAction(importAllSignKeys);
	m_popupsec->addSeparator();
	m_popupsec->addAction(addPhoto);
	m_popupsec->addAction(addUid);
	m_popupsec->addAction(exportSecretKey);
	m_popupsec->addAction(deleteKeyPair);

Andrius Štikonas's avatar
Andrius Štikonas committed
391
	m_popupgroup = new QMenu(this);
392
	m_popupgroup->addAction(editCurrentGroup);
393
	m_popupgroup->addAction(m_groupRename);
394 395 396
	m_popupgroup->addAction(delGroup);
	m_popupgroup->addAction(refreshKey);

Andrius Štikonas's avatar
Andrius Štikonas committed
397
	m_popupout = new QMenu(this);
398 399
	m_popupout->addAction(importKey);

Rolf Eike Beer's avatar
Rolf Eike Beer committed
400
	m_popupsig = new QMenu(this);
401 402 403
	m_popupsig->addAction(importSignatureKey);
	m_popupsig->addAction(delSignKey);

Andrius Štikonas's avatar
Andrius Štikonas committed
404
	m_popupphoto = new QMenu(this);
405 406
	m_popupphoto->addAction(openPhoto);
	m_popupphoto->addAction(signUid);
407
	m_popupphoto->addAction(signMailUid);
408 409
	m_popupphoto->addAction(deletePhoto);

Andrius Štikonas's avatar
Andrius Štikonas committed
410
	m_popupuid = new QMenu(this);
411
	m_popupuid->addAction(m_sendEmail);
412
	m_popupuid->addAction(signMailUid);
413
	m_popupuid->addAction(signUid);
414 415 416
	m_popupuid->addAction(delUid);
	m_popupuid->addAction(setPrimUid);

Andrius Štikonas's avatar
Andrius Štikonas committed
417
	m_popuporphan = new QMenu(this);
418 419 420 421 422
	m_popuporphan->addAction(regeneratePublic);
	m_popuporphan->addAction(deleteKeyPair);

	exportPublicKey->setEnabled(false);

423
	KConfigGroup cg = KConfigGroup(KSharedConfig::openConfig().data(), "KeyView");
424 425
	iview->restoreLayout(cg);

426 427
	connect(photoProps, QOverload<int>::of(&KSelectAction::triggered), this, &KeysManager::slotSetPhotoSize);
	connect(trustProps, QOverload<int>::of(&KSelectAction::triggered), this, &KeysManager::slotSetTrustFilter);
428 429

	QLabel *searchLabel = new QLabel(i18n("Search:"), this);
Andrius Štikonas's avatar
Andrius Štikonas committed
430 431
	m_listviewsearch = new QLineEdit(this);
	m_listviewsearch->setClearButtonEnabled(true);
432 433 434

	QWidget *searchWidget = new QWidget(this);
	QHBoxLayout *searchLayout = new QHBoxLayout(searchWidget);
435
	searchLayout->setContentsMargins(0, 0, 0, 0);
436 437 438 439
	searchLayout->addWidget(searchLabel);
	searchLayout->addWidget(m_listviewsearch);
	searchLayout->addStretch();

Andrius Štikonas's avatar
Andrius Štikonas committed
440 441
	QWidgetAction *searchLineAction = new QWidgetAction(/*i18nc("Name of the action that is a search line, shown for example in the toolbar configuration dialog",
			"Search Line"), */this);
Laurent Montel's avatar
Laurent Montel committed
442
	actionCollection()->addAction(QLatin1String( "search_line" ), searchLineAction);
Andrius Štikonas's avatar
Andrius Štikonas committed
443
	searchLineAction->setDefaultWidget(searchWidget);
444

445
	action = actionCollection()->addAction(QLatin1String("search_focus"), m_listviewsearch, QOverload<>::of(&QWidget::setFocus));
446
	action->setText(i18nc("Name of the action that gives the focus to the search line", "Focus Search Line"));
447
	actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_F6));
448
	connect(m_listviewsearch, &QLineEdit::textChanged, iproxy, &KeyListProxyModel::setFilterFixedString);
449

450 451
	setActionDescriptions(1);

452
	// get all keys data
Laurent Montel's avatar
Laurent Montel committed
453
	setupGUI(KXmlGuiWindow::Create | Save | ToolBar | StatusBar | Keys, QLatin1String( "keysmanager.rc" ));
454 455 456 457 458 459 460 461 462 463 464

	sTrust->setChecked(KGpgSettings::showTrust());
	iview->setColumnHidden(2, !KGpgSettings::showTrust());
	sSize->setChecked(KGpgSettings::showSize());
	iview->setColumnHidden(3, !KGpgSettings::showSize());
	sCreat->setChecked(KGpgSettings::showCreat());
	iview->setColumnHidden(4, !KGpgSettings::showCreat());
	sExpi->setChecked(KGpgSettings::showExpi());
	iview->setColumnHidden(5, !KGpgSettings::showExpi());
	iproxy->setOnlySecret(KGpgSettings::showSecret());

465
	m_statusBarLabel.setAlignment(Qt::AlignCenter);
Andrius Štikonas's avatar
Andrius Štikonas committed
466
	statusBar()->addPermanentWidget(&m_statusBarLabel);
467

468
	cg = KConfigGroup(KSharedConfig::openConfig().data(), "MainWindow");
469 470 471
	setAutoSaveSettings(cg, true);
	applyMainWindowSettings(cg);

472
	connect(this, &KeysManager::fontChanged, s_kgpgEditor, &KgpgEditor::slotSetFont);
473

474 475
	QNetworkConfigurationManager *netmgr = new QNetworkConfigurationManager(this);
	connect(netmgr, &QNetworkConfigurationManager::onlineStateChanged, this, &KeysManager::toggleNetworkActions);
476

477
	toggleNetworkActions(netmgr->isOnline());
478
	importSignatureKey->setEnabled(false);
Rolf Eike Beer's avatar
Rolf Eike Beer committed
479

480
    stateChanged(QStringLiteral("empty_list"));
481

482
	QMetaObject::invokeMethod(this, "refreshkey", Qt::QueuedConnection);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
483 484
}

Rolf Eike Beer's avatar
Rolf Eike Beer committed
485 486 487 488
KeysManager::~KeysManager()
{
}

489
void KeysManager::slotGenerateKey()
490
{
491
	if (m_genkey) {
492 493 494
		KMessageBox::error(this,
				i18n("Another key generation operation is still in progress.\nPlease wait a moment until this operation is complete."),
				i18n("Generating new key pair"));
495 496 497
		return;
	}

498
	QPointer<KgpgKeyGenerate> kg = new KgpgKeyGenerate(this);
499 500
	if (kg->exec() == QDialog::Accepted) {
		if (!kg->isExpertMode()) {
501
			KGpgGenerateKey *genkey = new KGpgGenerateKey(this, kg->name(), kg->email(),
502 503
					kg->comment(), kg->algo(), kg->size(), kg->days(), kg->expiration(),
					kg->caps());
504

505
			m_genkey = new KGpgTransactionJob(genkey);
506
			connect(m_genkey, &KGpgTransactionJob::result, this, &KeysManager::slotGenerateKeyDone);
507

508
			KIO::getJobTracker()->registerJob(m_genkey);
509
			m_genkey->start();
510
			QApplication::setOverrideCursor(Qt::BusyCursor);
511
		} else {
512
			KConfigGroup config(KSharedConfig::openConfig(), "General");
513

Laurent Montel's avatar
Laurent Montel committed
514
			QString terminalApp(config.readPathEntry("TerminalApplication", QLatin1String( "konsole" )));
515 516 517 518 519 520 521 522

			const QString gpgbin = KGpgSettings::gpgBinaryPath();
			QString gpg_args = gpgbin + QLatin1String(" --expert");
			if (GPGProc::gpgVersion(GPGProc::gpgVersionString(gpgbin)) > 0x20100)
				gpg_args += QLatin1String(" --full-gen-key");
			else
				gpg_args += QLatin1String(" --gen-key");

523
			QStringList args;
Rolf Eike Beer's avatar
Rolf Eike Beer committed
524
			args << QLatin1String( "-e" )
525
			     << gpg_args;
526 527 528 529 530 531 532 533 534 535 536 537

			QProcess *genKeyProc = new QProcess(this);
			genKeyProc->start(terminalApp, args);
			if (!genKeyProc->waitForStarted(-1)) {
				KMessageBox::error(this, i18n("Generating new key pair"),
						i18n("Can not start \"konsole\" application for expert mode."));
			} else {
				genKeyProc->waitForFinished(-1);
				refreshkey();
			}
		}
	}
Jimmy Gilles's avatar
Jimmy Gilles committed
538

539
	delete kg;
540 541
}

542
void KeysManager::showKeyManager()
Jimmy Gilles's avatar
Jimmy Gilles committed
543
{
544
	show();
Jimmy Gilles's avatar
Jimmy Gilles committed
545 546
}

547
void KeysManager::slotOpenEditor()
Jimmy Gilles's avatar
Jimmy Gilles committed
548
{
549
	KgpgEditor *kgpgtxtedit = new KgpgEditor(this, imodel, Qt::Window);
Jimmy Gilles's avatar
Jimmy Gilles committed
550

551
	connect(this, &KeysManager::fontChanged, kgpgtxtedit, &KgpgEditor::slotSetFont);
Jimmy Gilles's avatar
Jimmy Gilles committed
552

553
	kgpgtxtedit->show();
Jimmy Gilles's avatar
Jimmy Gilles committed
554 555
}

Rolf Eike Beer's avatar
Rolf Eike Beer committed
556
void KeysManager::changeMessage(const QString &msg, const bool keep)
Jimmy Gilles's avatar
Jimmy Gilles committed
557
{
Rolf Eike Beer's avatar
Rolf Eike Beer committed
558 559 560
	int timeout = keep ? 0 : 10000;

	statusBar()->showMessage(msg, timeout);
Jimmy Gilles's avatar
Jimmy Gilles committed
561 562
}

Rolf Eike Beer's avatar
Rolf Eike Beer committed
563
void KeysManager::updateStatusCounter()
Jimmy Gilles's avatar
Jimmy Gilles committed
564
{
Andrius Štikonas's avatar
Andrius Štikonas committed
565
	m_statusBarLabel.setText(imodel->statusCountMessage());
Jimmy Gilles's avatar
Jimmy Gilles committed
566 567
}

568
void KeysManager::slotGenerateKeyDone(KJob *job)
569
{
Rolf Eike Beer's avatar
Rolf Eike Beer committed
570
	changeMessage(i18nc("Application ready for user input", "Ready"));
571
	QApplication::restoreOverrideCursor();
572

573 574 575 576 577
	KGpgTransactionJob *tjob = qobject_cast<KGpgTransactionJob *>(job);

	const KGpgGenerateKey * const genkey = qobject_cast<const KGpgGenerateKey *>(tjob->getTransaction());
	int res = tjob->getResultCode();

578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
	const QString infomessage(i18n("Generating new key pair"));

	switch (res) {
	case KGpgTransaction::TS_BAD_PASSPHRASE:
		KMessageBox::error(this, i18n("Bad passphrase. Cannot generate a new key pair."), infomessage);
		break;
	case KGpgTransaction::TS_USER_ABORTED:
		KMessageBox::error(this, i18n("Aborted by the user. Cannot generate a new key pair."), infomessage);
		break;
	case KGpgTransaction::TS_INVALID_EMAIL:
		KMessageBox::error(this, i18n("The email address is not valid. Cannot generate a new key pair."), infomessage);
		break;
	case KGpgGenerateKey::TS_INVALID_NAME:
		KMessageBox::error(this, i18n("The name is not accepted by gpg. Cannot generate a new key pair."), infomessage);
		break;
	case KGpgTransaction::TS_OK: {
Rolf Eike Beer's avatar
Rolf Eike Beer committed
594
		updateStatusCounter();
595

596
		QPointer<QDialog> keyCreated = new QDialog(this);
597
		keyCreated->setWindowTitle(i18n("New Key Pair Created"));
598

599
		QVBoxLayout *mainLayout = new QVBoxLayout(keyCreated);
600
		keyCreated->setLayout(mainLayout);
601 602

		newKey *page = new newKey(keyCreated);
Laurent Montel's avatar
Laurent Montel committed
603
		page->TLname->setText(QLatin1String( "<b>" ) + genkey->getName() + QLatin1String( "</b>" ));
604

605
		const QString email(genkey->getEmail());
Laurent Montel's avatar
Laurent Montel committed
606
		page->TLemail->setText(QLatin1String( "<b>" ) + email + QLatin1String( "</b>" ));
607

608
		page->kURLRequester1->setUrl(KGpgRevokeDialog::revokeUrl(genkey->getName(), email));
609

610
		const QString fingerprint(genkey->getFingerprint());
611
		page->TLid->setText(QLatin1String( "<b>" ) % fingerprint.rightRef(8) % QLatin1String( "</b>" ));
612 613 614
		page->LEfinger->setText(fingerprint);
		page->CBdefault->setChecked(true);
		page->show();
615 616
		mainLayout->addWidget(page);
		page->buttonBox->button(QDialogButtonBox::Ok)->setShortcut(Qt::CTRL | Qt::Key_Return);
617
		connect(page->buttonBox, &QDialogButtonBox::accepted, keyCreated.data(), &QDialog::accept);
618 619

		keyCreated->exec();
620
		if (keyCreated.isNull())
621
			return;
622 623

		imodel->refreshKey(fingerprint);
624
		KGpgKeyNode *knode = imodel->getRootNode()->findKey(fingerprint);
625
		if (page->CBdefault->isChecked())
626
			imodel->setDefaultKey(knode);
627

628
		iview->selectNode(knode);
629

630
		if (page->CBsave->isChecked() || page->CBprint->isChecked()) {
631
			QUrl revurl;
632 633 634 635 636 637
			if (page->CBsave->isChecked())
				revurl = page->kURLRequester1->url();

			KGpgGenerateRevoke *genRev = new KGpgGenerateRevoke(this, fingerprint, revurl,
					0, i18n("backup copy"));

638
			connect(genRev, &KGpgGenerateRevoke::done, this, &KeysManager::slotRevokeGenerated);
639

640
			if (page->CBprint->isChecked())
641
				connect(genRev, &KGpgGenerateRevoke::revokeCertificate, this, &KeysManager::doPrint);
642 643

			genRev->start();
644
		}
645
		delete keyCreated;
646
		break;
647 648
	}
	default:
Rolf Eike Beer's avatar
Rolf Eike Beer committed
649 650 651
		KMessageBox::detailedError(this,
				i18n("gpg process did not finish. Cannot generate a new key pair."),
				genkey->gpgErrorMessage(), infomessage);
652
	}
653

Rolf Eike Beer's avatar
Rolf Eike Beer committed
654
	m_genkey = nullptr;
655 656
}

657
void KeysManager::slotShowTrust()
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
658
{
659 660 661 662
	bool b = !sTrust->isChecked();
	iview->setColumnHidden(KEYCOLUMN_TRUST, b);
	if (!b && (iview->columnWidth(KEYCOLUMN_TRUST) == 0))
		iview->resizeColumnToContents(KEYCOLUMN_TRUST);