Better wording
[kdepim.git] / libkpgp / kpgpui.cpp
blob310f60afea6295d183d26a5b27d08039d101e92d
1 /*
2 kpgpui.cpp
4 Copyright (C) 2001,2002 the KPGP authors
5 See file AUTHORS.kpgp for details
7 This file is part of KPGP, the KDE PGP/GnuPG support library.
9 KPGP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "kpgpui.h"
20 #include "kpgp.h"
21 #include "kpgpkey.h"
23 #include <QLabel>
24 #include <QApplication>
25 #include <QTextCodec>
26 #include <QDateTime>
27 #include <QPixmap>
28 #include <QLayout>
29 #include <QTimer>
30 #include <QMenu>
31 #include <QRegExp>
32 #include <QFrame>
33 #include <QByteArray>
34 #include <QVBoxLayout>
35 #include <QHBoxLayout>
36 #include <QProgressBar>
37 #include <QButtonGroup>
38 #include <QTextEdit>
39 #include <QGroupBox>
40 #include <QTreeWidget>
41 #include <QHeaderView>
42 #include <QScrollArea>
43 #include <QScrollBar>
44 #include <QAbstractTextDocumentLayout>
46 #include <kvbox.h>
47 #include <kconfiggroup.h>
48 #include <klocale.h>
49 #include <kpassworddialog.h>
50 #include <kcharsets.h>
51 #include <kseparator.h>
52 #include <kiconloader.h>
53 #include <kconfigbase.h>
54 #include <kconfig.h>
55 #include <kprogressdialog.h>
56 #include <kwindowsystem.h>
57 #include <kpushbutton.h>
58 #include <kglobalsettings.h>
59 #include <klineedit.h>
61 #include <assert.h>
62 #include <string.h> // for memcpy(3)
64 #ifndef QT_NO_TREEWIDGET
65 const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250;
66 #endif
68 namespace Kpgp {
70 PassphraseDialog::PassphraseDialog( QWidget *parent,
71 const QString &caption,
72 const QString &keyID )
73 :KPasswordDialog( parent )
75 setCaption( caption );
76 setButtons( Ok|Cancel );
78 setPixmap( BarIcon("dialog-password") );
80 if (keyID.isNull())
81 setPrompt(i18n("Please enter your OpenPGP passphrase:"));
82 else
83 setPrompt(i18n("Please enter the OpenPGP passphrase for\n\"%1\":", keyID) );
87 PassphraseDialog::~PassphraseDialog()
91 QString PassphraseDialog::passphrase()
93 return password();
97 // ------------------------------------------------------------------------
98 // Forbidden accels for KMail: AC GH OP
99 // for KNode: ACE H O
100 Config::Config( QWidget *parent, bool encrypt )
101 : QWidget( parent ), pgp( Module::getKpgp() )
103 QGroupBox * group;
104 QLabel * label;
105 QString msg;
108 QVBoxLayout *topLayout = new QVBoxLayout( this );
109 topLayout->setSpacing( KDialog::spacingHint() );
110 topLayout->setMargin( 0 );
112 group = new QGroupBox( i18n("Warning"), this );
113 QVBoxLayout *lay = new QVBoxLayout(group);
114 lay->setSpacing( KDialog::spacingHint() );
115 // (mmutz) work around Qt label bug in 3.0.0 (and possibly later):
116 // 1. Don't use rich text: No <qt><b>...</b></qt>
117 label = new QLabel( i18n("Please check if encryption really "
118 "works before you start using it seriously. Also note that attachments "
119 "are not encrypted by the PGP/GPG module."), group );
120 label->setWordWrap( true );
121 lay->addWidget( label );
122 // 2. instead, set the font to bold:
123 QFont labelFont = label->font();
124 labelFont.setBold( true );
125 label->setFont( labelFont );
126 // 3. and activate wordwarp:
127 // end; to remove the workaround, add <qt><b>..</b></qt> around the
128 // text and remove lines QFont... -> label->setAlignment(...).
129 topLayout->addWidget( group );
130 group = new QGroupBox( i18n("Encryption Tool"), this );
131 lay = new QVBoxLayout(group);
132 lay->setSpacing( KDialog::spacingHint() );
134 KHBox * hbox = new KHBox( group );
135 lay->addWidget( hbox );
136 label = new QLabel( i18n("Select encryption tool to &use:"), hbox );
137 toolCombo = new QComboBox( hbox );
138 toolCombo->setEditable( false );
139 toolCombo->addItems( QStringList()
140 << i18n("Autodetect")
141 << i18n("GnuPG - Gnu Privacy Guard")
142 << i18n("PGP Version 2.x")
143 << i18n("PGP Version 5.x")
144 << i18n("PGP Version 6.x")
145 << i18n("Do not use any encryption tool") );
146 label->setBuddy( toolCombo );
147 hbox->setStretchFactor( toolCombo, 1 );
148 connect( toolCombo, SIGNAL(activated(int)),
149 this, SIGNAL(changed()) );
150 // This is the place to add a KUrlRequester to be used for asking
151 // the user for the path to the executable...
152 topLayout->addWidget( group );
154 mpOptionsGroupBox = new QGroupBox( i18n("Options"), this );
155 lay = new QVBoxLayout( mpOptionsGroupBox );
156 lay->setSpacing( KDialog::spacingHint() );
157 storePass = new QCheckBox( i18n("&Keep passphrase in memory"),
158 mpOptionsGroupBox );
159 lay->addWidget( storePass );
160 connect( storePass, SIGNAL(toggled(bool)),
161 this, SIGNAL(changed()) );
162 msg = i18n( "<qt><p>When this option is enabled, the passphrase of your "
163 "private key will be remembered by the application as long "
164 "as the application is running. Thus you will only have to "
165 "enter the passphrase once.</p><p>Be aware that this could be a "
166 "security risk. If you leave your computer, others "
167 "can use it to send signed messages and/or read your encrypted "
168 "messages. If a core dump occurs, the contents of your RAM will "
169 "be saved onto disk, including your passphrase.</p>"
170 "<p>Note that when using KMail, this setting only applies "
171 "if you are not using gpg-agent. It is also ignored "
172 "if you are using crypto plugins.</p></qt>" );
173 storePass->setWhatsThis( msg );
174 if( encrypt ) {
175 encToSelf = new QCheckBox( i18n("Always encr&ypt to self"),
176 mpOptionsGroupBox );
177 connect( encToSelf, SIGNAL(toggled(bool)),
178 this, SIGNAL(changed()) );
180 msg = i18n( "<qt><p>When this option is enabled, the message/file "
181 "will not only be encrypted with the receiver's public key, "
182 "but also with your key. This will enable you to decrypt the "
183 "message/file at a later time. This is generally a good idea."
184 "</p></qt>" );
185 encToSelf->setWhatsThis( msg );
187 else
188 encToSelf = 0;
189 showCipherText = new QCheckBox( i18n("&Show signed/encrypted text after "
190 "composing"));
191 lay->addWidget( showCipherText );
192 connect( showCipherText, SIGNAL(toggled(bool)),
193 this, SIGNAL(changed()) );
195 msg = i18n( "<qt><p>When this option is enabled, the signed/encrypted text "
196 "will be shown in a separate window, enabling you to know how "
197 "it will look before it is sent. This is a good idea when "
198 "you are verifying that your encryption system works.</p></qt>" );
199 showCipherText->setWhatsThis( msg );
200 if( encrypt ) {
201 showKeyApprovalDlg = new QCheckBox( i18n("Always show the encryption "
202 "keys &for approval"));
203 lay->addWidget( showKeyApprovalDlg );
204 connect( showKeyApprovalDlg, SIGNAL(toggled(bool)),
205 this, SIGNAL(changed()) );
206 msg = i18n( "<qt><p>When this option is enabled, the application will "
207 "always show you a list of public keys from which you can "
208 "choose the one it will use for encryption. If it is off, "
209 "the application will only show the dialog if it cannot find "
210 "the right key or if there are several which could be used. "
211 "</p></qt>" );
212 showKeyApprovalDlg->setWhatsThis( msg );
214 else
215 showKeyApprovalDlg = 0;
217 topLayout->addWidget( mpOptionsGroupBox );
219 topLayout->addStretch(1);
221 setValues(); // is this needed by KNode, b/c for KMail, it's not.
225 Config::~Config()
229 void
230 Config::setValues()
232 // set default values
233 storePass->setChecked( pgp->storePassPhrase() );
234 if( 0 != encToSelf )
235 encToSelf->setChecked( pgp->encryptToSelf() );
236 showCipherText->setChecked( pgp->showCipherText() );
237 if( 0 != showKeyApprovalDlg )
238 showKeyApprovalDlg->setChecked( pgp->showKeyApprovalDlg() );
240 int type = 0;
241 switch (pgp->pgpType) {
242 // translate Kpgp::Module enum to combobox' entries:
243 default:
244 case Module::tAuto: type = 0; break;
245 case Module::tGPG: type = 1; break;
246 case Module::tPGP2: type = 2; break;
247 case Module::tPGP5: type = 3; break;
248 case Module::tPGP6: type = 4; break;
249 case Module::tOff: type = 5; break;
251 toolCombo->setCurrentIndex( type );
254 void
255 Config::applySettings()
257 pgp->setStorePassPhrase(storePass->isChecked());
258 if( 0 != encToSelf )
259 pgp->setEncryptToSelf(encToSelf->isChecked());
260 pgp->setShowCipherText(showCipherText->isChecked());
261 if( 0 != showKeyApprovalDlg )
262 pgp->setShowKeyApprovalDlg( showKeyApprovalDlg->isChecked() );
264 Module::PGPType type;
265 switch ( toolCombo->currentIndex() ) {
266 // convert combobox entry indices to Kpgp::Module constants:
267 default:
268 case 0: type = Module::tAuto; break;
269 case 1: type = Module::tGPG; break;
270 case 2: type = Module::tPGP2; break;
271 case 3: type = Module::tPGP5; break;
272 case 4: type = Module::tPGP6; break;
273 case 5: type = Module::tOff; break;
275 pgp->pgpType = type;
277 pgp->writeConfig(true);
280 #ifndef QT_NO_TREEWIDGET
283 // ------------------------------------------------------------------------
284 KeySelectionDialog::KeySelectionDialog( const KeyList& keyList,
285 const QString& title,
286 const QString& text,
287 const KeyIDList& keyIds,
288 const bool rememberChoice,
289 const unsigned int allowedKeys,
290 const bool extendedSelection,
291 QWidget *parent )
292 : KDialog( parent ),
293 mRememberCB( 0 ),
294 mAllowedKeys( allowedKeys ),
295 mCurrentContextMenuItem( 0 )
297 setCaption( title );
298 setButtons( Default|Ok|Cancel );
299 if ( qApp ) {
300 KWindowSystem::setIcons( winId(),
301 qApp->windowIcon().pixmap( IconSize( KIconLoader::Desktop ),
302 IconSize( KIconLoader::Desktop ) ),
303 qApp->windowIcon().pixmap( IconSize( KIconLoader::Small ),
304 IconSize( KIconLoader::Small ) ) );
306 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
307 KConfig *config = pgp->getConfig();
308 KConfigGroup dialogConfig( config, "Key Selection Dialog" );
310 QSize defaultSize( 580, 400 );
311 QSize dialogSize = dialogConfig.readEntry( "Dialog size", defaultSize );
313 resize( dialogSize );
315 mCheckSelectionTimer = new QTimer( this );
316 mStartSearchTimer = new QTimer( this );
317 mStartSearchTimer->setSingleShot( true );
319 // load the key status icons
320 mKeyGoodPix = new QPixmap( UserIcon("key_ok") );
321 mKeyBadPix = new QPixmap( UserIcon("key_bad") );
322 mKeyUnknownPix = new QPixmap( UserIcon("key_unknown") );
323 mKeyValidPix = new QPixmap( UserIcon("key") );
325 QFrame *page = new QFrame( this );
326 setMainWidget( page );
327 QVBoxLayout *topLayout = new QVBoxLayout( page );
328 topLayout->setSpacing( spacingHint() );
329 topLayout->setMargin( 0 );
331 if( !text.isEmpty() ) {
332 QLabel *label = new QLabel( page );
333 label->setText( text );
334 topLayout->addWidget( label );
337 QHBoxLayout * hlay = new QHBoxLayout(); // inherits spacing
338 topLayout->addLayout( hlay );
339 QLineEdit * le = new QLineEdit( page );
340 QLabel *label = new QLabel( i18n("&Search for:"), page );
341 label->setBuddy( le );
342 hlay->addWidget( label );
343 hlay->addWidget( le, 1 );
344 le->setFocus();
346 connect( le, SIGNAL(textChanged(QString)),
347 this, SLOT(slotSearch(QString)) );
348 connect( mStartSearchTimer, SIGNAL(timeout()), SLOT(slotFilter()) );
350 mListView = new QTreeWidget( page );
351 mListView->setHeaderLabels( QStringList()
352 << i18n("Key ID")
353 << i18n("User ID") );
354 mListView->setAllColumnsShowFocus( true );
355 mListView->header()->setStretchLastSection( true );
356 mListView->setRootIsDecorated( true );
357 mListView->setSortingEnabled( true );
358 mListView->header()->setSortIndicatorShown( true );
359 mListView->sortItems( 1, Qt::AscendingOrder ); // sort by User ID
360 // mListView->setShowToolTips( true );
361 if( extendedSelection ) {
362 mListView->setSelectionMode( QTreeWidget::ExtendedSelection );
363 //mListView->setSelectionMode( QListView::Multi );
365 topLayout->addWidget( mListView, 10 );
367 if (rememberChoice) {
368 mRememberCB = new QCheckBox( i18n("Remember choice"), page );
369 topLayout->addWidget( mRememberCB );
370 mRememberCB->setWhatsThis(
371 i18n("<qt><p>If you check this box your choice will "
372 "be stored and you will not be asked again."
373 "</p></qt>"));
376 initKeylist( keyList, keyIds );
378 QTreeWidgetItem *lvi = 0;
379 if( extendedSelection ) {
380 lvi = mListView->currentItem();
381 slotCheckSelection();
383 else {
384 if ( mListView->selectedItems().size() > 0 )
385 lvi = mListView->selectedItems().first();
386 slotCheckSelection( lvi );
388 if( lvi != 0 )
389 mListView->scrollToItem( lvi );
391 if( extendedSelection ) {
392 connect( mCheckSelectionTimer, SIGNAL(timeout()),
393 this, SLOT(slotCheckSelection()) );
394 connect( mListView, SIGNAL(itemSelectionChanged()),
395 this, SLOT(slotSelectionChanged()) );
397 else {
398 connect( mListView, SIGNAL(itemSelectionChanged()),
399 this, SLOT(slotSelectionChanged()) );
401 connect( mListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(accept()) );
403 mListView->setContextMenuPolicy( Qt::CustomContextMenu );
404 connect( mListView, SIGNAL(customContextMenuRequested(QPoint)),
405 this, SLOT(slotRMB(QPoint)) );
407 setButtonGuiItem( KDialog::Default, KGuiItem(i18n("&Reread Keys")) );
408 connect( this, SIGNAL(defaultClicked()),
409 this, SLOT(slotRereadKeys()) );
410 connect(this, SIGNAL(okClicked()),SLOT(slotOk()));
411 connect(this,SIGNAL(cancelClicked()),SLOT(slotCancel()));
415 KeySelectionDialog::~KeySelectionDialog()
417 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
418 KConfig *config = pgp->getConfig();
419 KConfigGroup dialogConfig( config, "Key Selection Dialog" );
420 dialogConfig.writeEntry( "Dialog size", size() );
421 config->sync();
422 delete mKeyGoodPix;
423 delete mKeyBadPix;
424 delete mKeyUnknownPix;
425 delete mKeyValidPix;
429 KeyID KeySelectionDialog::key() const
431 if( mListView->selectionMode() == QTreeWidget::ExtendedSelection || mKeyIds.isEmpty() )
432 return KeyID();
433 else
434 return mKeyIds.first();
438 void KeySelectionDialog::initKeylist( const KeyList& keyList,
439 const KeyIDList& keyIds )
441 QTreeWidgetItem* firstSelectedItem = 0;
442 mKeyIds.clear();
443 mListView->clear();
445 // build a list of all public keys
446 foreach ( Key* key, keyList ) {
447 KeyID curKeyId = key->primaryKeyID();
449 QTreeWidgetItem* primaryUserID = new QTreeWidgetItem( mListView );
450 primaryUserID->setText( 0, curKeyId );
451 primaryUserID->setText( 1, key->primaryUserID() );
453 // select and open the given key
454 if( keyIds.indexOf( curKeyId ) != -1 ) {
455 if( 0 == firstSelectedItem ) {
456 firstSelectedItem = primaryUserID;
458 primaryUserID->setSelected( true );
459 mKeyIds.append( curKeyId );
461 primaryUserID->setExpanded( false );
463 // set icon for this key
464 switch( keyValidity( key ) ) {
465 case 0: // the key's validity can't be determined
466 primaryUserID->setData( 0, Qt::DecorationRole, *mKeyUnknownPix );
467 break;
468 case 1: // key is valid but not trusted
469 primaryUserID->setData( 0, Qt::DecorationRole, *mKeyValidPix );
470 break;
471 case 2: // key is valid and trusted
472 primaryUserID->setData( 0, Qt::DecorationRole, *mKeyGoodPix );
473 break;
474 case -1: // key is invalid
475 primaryUserID->setData( 0, Qt::DecorationRole, *mKeyBadPix );
476 break;
479 QTreeWidgetItem* childItem;
481 childItem = new QTreeWidgetItem( primaryUserID );
482 childItem->setText( 1, i18n( "Fingerprint: %1" , beautifyFingerprint( key->primaryFingerprint() ) ) );
483 if( primaryUserID->isSelected() && mListView->selectionMode() == QTreeWidget::ExtendedSelection ) {
484 childItem->setSelected( true );
487 childItem = new QTreeWidgetItem( primaryUserID );
488 childItem->setText( 1, keyInfo( key ) );
489 if( primaryUserID->isSelected() && mListView->selectionMode() == QTreeWidget::ExtendedSelection ) {
490 childItem->setSelected( true );
493 UserIDList userIDs = key->userIDs();
494 UserIDList::Iterator uidit( userIDs.begin() );
495 if( uidit != userIDs.end() ) {
496 ++uidit; // skip the primary user ID
497 for( ; uidit != userIDs.end(); ++uidit ) {
498 childItem = new QTreeWidgetItem( primaryUserID );
499 childItem->setText( 1, (*uidit)->text() );
500 if( primaryUserID->isSelected() && mListView->selectionMode() == QTreeWidget::ExtendedSelection ) {
501 childItem->setSelected( true );
507 if( 0 != firstSelectedItem ) {
508 mListView->setCurrentItem( firstSelectedItem );
513 QString KeySelectionDialog::keyInfo( const Kpgp::Key *key ) const
515 QString status, remark;
516 if( key->revoked() ) {
517 status = i18n("Revoked");
519 else if( key->expired() ) {
520 status = i18n("Expired");
522 else if( key->disabled() ) {
523 status = i18n("Disabled");
525 else if( key->invalid() ) {
526 status = i18n("Invalid");
528 else {
529 Validity keyTrust = key->keyTrust();
530 switch( keyTrust ) {
531 case KPGP_VALIDITY_UNDEFINED:
532 status = i18n("Undefined trust");
533 break;
534 case KPGP_VALIDITY_NEVER:
535 status = i18n("Untrusted");
536 break;
537 case KPGP_VALIDITY_MARGINAL:
538 status = i18n("Marginally trusted");
539 break;
540 case KPGP_VALIDITY_FULL:
541 status = i18n("Fully trusted");
542 break;
543 case KPGP_VALIDITY_ULTIMATE:
544 status = i18n("Ultimately trusted");
545 break;
546 case KPGP_VALIDITY_UNKNOWN:
547 default:
548 status = i18n("Unknown");
550 if( key->secret() ) {
551 remark = i18n("Secret key available");
553 else if( !key->canEncrypt() ) {
554 remark = i18n("Sign only key");
556 else if( !key->canSign() ) {
557 remark = i18n("Encryption only key");
561 QDateTime dt;
562 dt.setTime_t( key->creationDate() );
563 if( remark.isEmpty() ) {
564 return ' ' + i18nc("creation date and status of an OpenPGP key",
565 "Creation date: %1, Status: %2",
566 KGlobal::locale()->formatDate( dt.date(), KLocale::ShortDate ) ,
567 status );
569 else {
570 return ' ' + i18nc("creation date, status and remark of an OpenPGP key",
571 "Creation date: %1, Status: %2 (%3)",
572 KGlobal::locale()->formatDate( dt.date(), KLocale::ShortDate ) ,
573 status ,
574 remark );
578 QString KeySelectionDialog::beautifyFingerprint( const QByteArray& fpr ) const
580 QByteArray result;
582 if( 40 == fpr.length() ) {
583 // convert to this format:
584 // 0000 1111 2222 3333 4444 5555 6666 7777 8888 9999
585 result.fill( ' ', 50 );
586 memcpy( result.data() , fpr.data() , 4 );
587 memcpy( result.data() + 5, fpr.data() + 4, 4 );
588 memcpy( result.data() + 10, fpr.data() + 8, 4 );
589 memcpy( result.data() + 15, fpr.data() + 12, 4 );
590 memcpy( result.data() + 20, fpr.data() + 16, 4 );
591 memcpy( result.data() + 26, fpr.data() + 20, 4 );
592 memcpy( result.data() + 31, fpr.data() + 24, 4 );
593 memcpy( result.data() + 36, fpr.data() + 28, 4 );
594 memcpy( result.data() + 41, fpr.data() + 32, 4 );
595 memcpy( result.data() + 46, fpr.data() + 36, 4 );
597 else if( 32 == fpr.length() ) {
598 // convert to this format:
599 // 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
600 result.fill( ' ', 48 );
601 memcpy( result.data() , fpr.data() , 2 );
602 memcpy( result.data() + 3, fpr.data() + 2, 2 );
603 memcpy( result.data() + 6, fpr.data() + 4, 2 );
604 memcpy( result.data() + 9, fpr.data() + 6, 2 );
605 memcpy( result.data() + 12, fpr.data() + 8, 2 );
606 memcpy( result.data() + 15, fpr.data() + 10, 2 );
607 memcpy( result.data() + 18, fpr.data() + 12, 2 );
608 memcpy( result.data() + 21, fpr.data() + 14, 2 );
609 memcpy( result.data() + 25, fpr.data() + 16, 2 );
610 memcpy( result.data() + 28, fpr.data() + 18, 2 );
611 memcpy( result.data() + 31, fpr.data() + 20, 2 );
612 memcpy( result.data() + 34, fpr.data() + 22, 2 );
613 memcpy( result.data() + 37, fpr.data() + 24, 2 );
614 memcpy( result.data() + 40, fpr.data() + 26, 2 );
615 memcpy( result.data() + 43, fpr.data() + 28, 2 );
616 memcpy( result.data() + 46, fpr.data() + 30, 2 );
618 else { // unknown length of fingerprint
619 result = fpr;
622 return result;
625 int KeySelectionDialog::keyValidity( const Kpgp::Key *key ) const
627 if( 0 == key ) {
628 return -1;
631 if( ( mAllowedKeys & EncrSignKeys ) == EncryptionKeys ) {
632 // only encryption keys are allowed
633 if( ( mAllowedKeys & ValidKeys ) && !key->isValidEncryptionKey() ) {
634 // only valid encryption keys are allowed
635 return -1;
637 else if( !key->canEncrypt() ) {
638 return -1;
641 else if( ( mAllowedKeys & EncrSignKeys ) == SigningKeys ) {
642 // only signing keys are allowed
643 if( ( mAllowedKeys & ValidKeys ) && !key->isValidSigningKey() ) {
644 // only valid signing keys are allowed
645 return -1;
647 else if( !key->canSign() ) {
648 return -1;
651 else if( ( mAllowedKeys & ValidKeys ) && !key->isValid() ) {
652 // only valid keys are allowed
653 return -1;
656 // check the key's trust
657 int val = 0;
658 Validity keyTrust = key->keyTrust();
659 switch( keyTrust ) {
660 case KPGP_VALIDITY_NEVER:
661 val = -1;
662 break;
663 case KPGP_VALIDITY_MARGINAL:
664 case KPGP_VALIDITY_FULL:
665 case KPGP_VALIDITY_ULTIMATE:
666 val = 2;
667 break;
668 case KPGP_VALIDITY_UNDEFINED:
669 if( mAllowedKeys & TrustedKeys ) {
670 // only trusted keys are allowed
671 val = -1;
673 else {
674 val = 1;
676 break;
677 case KPGP_VALIDITY_UNKNOWN:
678 default:
679 val = 0;
682 return val;
686 void KeySelectionDialog::updateKeyInfo( const Kpgp::Key* key,
687 QTreeWidgetItem* lvi ) const
689 if( 0 == lvi ) {
690 return;
693 if( lvi->parent() != 0 ) {
694 lvi = lvi->parent();
697 if( 0 == key ) {
698 // the key doesn't exist anymore -> delete it from the list view
699 while( lvi->childCount() ) {
700 kDebug( 5326 ) <<"Deleting '" << lvi->child( 0 )->text( 1 ) <<"'";
701 delete lvi->takeChild( 0 );
703 kDebug( 5326 ) <<"Deleting key 0x" << lvi->text( 0 ) <<" ("
704 << lvi->text( 1 ) << ")\n";
705 delete lvi;
706 lvi = 0;
707 return;
710 // update the icon for this key
711 switch( keyValidity( key ) ) {
712 case 0: // the key's validity can't be determined
713 lvi->setData( 0, Qt::DecorationRole, *mKeyUnknownPix );
714 break;
715 case 1: // key is valid but not trusted
716 lvi->setData( 0, Qt::DecorationRole, *mKeyValidPix );
717 break;
718 case 2: // key is valid and trusted
719 lvi->setData( 0, Qt::DecorationRole, *mKeyGoodPix );
720 break;
721 case -1: // key is invalid
722 lvi->setData( 0, Qt::DecorationRole, *mKeyBadPix );
723 break;
726 // update the key info for this key
727 // the key info is identified by a leading space; this shouldn't be
728 // a problem because User Ids shouldn't start with a space
729 QTreeWidgetItemIterator it( lvi );
730 while ( *it ) {
731 if( lvi->text( 1 ).at(0) == ' ' ) {
732 lvi->setText( 1, keyInfo( key ) );
733 break;
735 ++it;
741 KeySelectionDialog::keyAdmissibility( QTreeWidgetItem* lvi,
742 TrustCheckMode trustCheckMode ) const
744 // Return:
745 // -1 = key must not be chosen,
746 // 0 = not enough information to decide whether the give key is allowed
747 // or not,
748 // 1 = key can be chosen
750 if( mAllowedKeys == AllKeys ) {
751 return 1;
754 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
756 if( 0 == pgp ) {
757 return 0;
760 KeyID keyId = getKeyId( lvi );
761 Kpgp::Key* key = pgp->publicKey( keyId );
763 if( 0 == key ) {
764 return 0;
767 int val = 0;
768 if( trustCheckMode == ForceTrustCheck ) {
769 key = pgp->rereadKey( keyId, true );
770 updateKeyInfo( key, lvi );
771 val = keyValidity( key );
773 else {
774 val = keyValidity( key );
775 if( ( trustCheckMode == AllowExpensiveTrustCheck ) && ( 0 == val ) ) {
776 key = pgp->rereadKey( keyId, true );
777 updateKeyInfo( key, lvi );
778 val = keyValidity( key );
782 switch( val ) {
783 case -1: // key is not usable
784 return -1;
785 break;
786 case 0: // key status unknown
787 return 0;
788 break;
789 case 1: // key is valid, but untrusted
790 if( mAllowedKeys & TrustedKeys ) {
791 // only trusted keys are allowed
792 return -1;
794 return 1;
795 break;
796 case 2: // key is trusted
797 return 1;
798 break;
799 default:
800 kDebug( 5326 ) <<"Error: Invalid key status value.";
803 return 0;
807 KeyID
808 KeySelectionDialog::getKeyId( const QTreeWidgetItem* lvi ) const
810 KeyID keyId;
812 if( 0 != lvi ) {
813 if( 0 != lvi->parent() ) {
814 keyId = lvi->parent()->text(0).toLocal8Bit();
816 else {
817 keyId = lvi->text(0).toLocal8Bit();
821 return keyId;
825 void KeySelectionDialog::slotRereadKeys()
827 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
829 if( 0 == pgp ) {
830 return;
833 KeyList keys;
835 if( PublicKeys & mAllowedKeys ) {
836 pgp->readPublicKeys( true );
837 keys = pgp->publicKeys();
839 else {
840 pgp->readSecretKeys( true );
841 keys = pgp->secretKeys();
844 // save the current position of the contents
845 int offsetY = mListView->verticalScrollBar()->value();
847 disconnect( mListView, SIGNAL(itemSelectionChanged()),
848 this, SLOT(slotSelectionChanged()) );
850 initKeylist( keys, KeyIDList( mKeyIds ) );
851 slotFilter();
853 connect( mListView, SIGNAL(itemSelectionChanged()),
854 this, SLOT(slotSelectionChanged()) );
855 slotSelectionChanged();
857 // restore the saved position of the contents
858 mListView->verticalScrollBar()->setValue( offsetY );
862 void KeySelectionDialog::slotSelectionChanged()
864 kDebug( 5326 ) <<"KeySelectionDialog::slotSelectionChanged()";
866 if ( mListView->selectionMode() == QTreeWidget::ExtendedSelection ) {
867 // (re)start the check selection timer. Checking the selection is delayed
868 // because else drag-selection doesn't work very good (checking key trust
869 // is slow).
870 mCheckSelectionTimer->start( sCheckSelectionDelay );
871 } else {
872 if ( mListView->selectedItems().size() > 0 )
873 slotCheckSelection( mListView->selectedItems().first() );
878 void KeySelectionDialog::slotCheckSelection( QTreeWidgetItem* plvi /* = 0 */ )
880 kDebug( 5326 ) <<"KeySelectionDialog::slotCheckSelection()";
882 if( mListView->selectionMode() != QTreeWidget::ExtendedSelection ) {
883 mKeyIds.clear();
884 KeyID keyId = getKeyId( plvi );
885 if( !keyId.isEmpty() ) {
886 mKeyIds.append( keyId );
887 enableButton( Ok, 1 == keyAdmissibility( plvi, AllowExpensiveTrustCheck ) );
889 else {
890 enableButton( Ok, false );
893 else {
894 mCheckSelectionTimer->stop();
896 // As we might change the selection, we have to disconnect the slot
897 // to prevent recursion
898 disconnect( mListView, SIGNAL(itemSelectionChanged()),
899 this, SLOT(slotSelectionChanged()) );
901 KeyIDList newKeyIdList;
902 QList<QTreeWidgetItem*> keysToBeChecked;
904 bool keysAllowed = true;
905 enum { UNKNOWN, SELECTED, DESELECTED } userAction = UNKNOWN;
906 // Iterate over the tree to find selected keys.
907 for( int lviIndex = 0; lviIndex < mListView->topLevelItemCount(); ++lviIndex ) {
908 QTreeWidgetItem *lvi = mListView->topLevelItem( lviIndex );
909 // We make sure that either all items belonging to a key are selected
910 // or unselected. As it's possible to select/deselect multiple keys at
911 // once in extended selection mode we have to figure out whether the user
912 // selected or deselected keys.
914 // First count the selected items of this key
915 int itemCount = 1 + lvi->childCount();
916 int selectedCount = lvi->isSelected() ? 1 : 0;
917 for( int clviIndex = 0; clviIndex < lvi->childCount(); ++clviIndex ) {
918 QTreeWidgetItem *clvi = lvi->child( clviIndex );
919 if( clvi->isSelected() ) {
920 ++selectedCount;
924 if( userAction == UNKNOWN ) {
925 // Figure out whether the user selected or deselected this key
926 // Remark: A selected count of 0 doesn't mean anything since in
927 // extended selection mode a normal left click deselects
928 // the not clicked items.
929 if( 0 < selectedCount ) {
930 if( -1 == mKeyIds.indexOf( lvi->text(0).toLocal8Bit() ) ) {
931 // some items of this key are selected and the key wasn't selected
932 // before => the user selected something
933 kDebug( 5326 ) <<"selectedCount:"<<selectedCount<<"/"<<itemCount
934 <<"--- User selected key"<<lvi->text(0);
935 userAction = SELECTED;
937 else if( ( itemCount > selectedCount ) &&
938 ( -1 != mKeyIds.indexOf( lvi->text(0).toLocal8Bit() ) ) ) {
939 // some items of this key are unselected and the key was selected
940 // before => the user deselected something
941 kDebug( 5326 ) <<"selectedCount:"<<selectedCount<<"/"<<itemCount
942 <<"--- User deselected key"<<lvi->text(0);
943 userAction = DESELECTED;
947 if( itemCount == selectedCount ) {
948 // add key to the list of selected keys
949 KeyID keyId = lvi->text(0).toLocal8Bit();
950 newKeyIdList.append( keyId );
951 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
952 if( -1 == admissibility ) {
953 keysAllowed = false;
955 else if ( 0 == admissibility ) {
956 keysToBeChecked.append( lvi );
959 else if( 0 < selectedCount ) {
960 // not all items of this key are selected or unselected. change this
961 // according to the user's action
962 if( userAction == SELECTED ) {
963 // select all items of this key
964 lvi->setSelected( true );
965 for( int clviIndex = 0; clviIndex < lvi->childCount(); ++clviIndex ) {
966 QTreeWidgetItem *clvi = lvi->child( clviIndex );
967 clvi->setSelected( true );
969 // add key to the list of selected keys
970 KeyID keyId = lvi->text(0).toLocal8Bit();
971 newKeyIdList.append( keyId );
972 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
973 if( -1 == admissibility ) {
974 keysAllowed = false;
976 else if ( 0 == admissibility ) {
977 keysToBeChecked.append( lvi );
980 else { // userAction == DESELECTED
981 // deselect all items of this key
982 lvi->setSelected( false );
983 for ( int clviIndex = 0; clviIndex < lvi->childCount(); ++clviIndex ) {
984 QTreeWidgetItem *clvi = lvi->child( clviIndex );
985 clvi->setSelected( false );
990 kDebug( 5326 ) <<"Selected keys:" << newKeyIdList.toStringList().join(",");
991 mKeyIds = newKeyIdList;
992 if( !keysToBeChecked.isEmpty() ) {
993 keysAllowed = keysAllowed && checkKeys( keysToBeChecked );
995 enableButton( Ok, keysAllowed );
997 connect( mListView, SIGNAL(selectionChanged()),
998 this, SLOT(slotSelectionChanged()) );
1003 bool KeySelectionDialog::checkKeys( const QList<QTreeWidgetItem*>& keys ) const
1005 KProgressDialog* pProgressDlg = 0;
1006 bool keysAllowed = true;
1007 kDebug( 5326 ) <<"Checking keys...";
1009 pProgressDlg = new KProgressDialog( 0, i18n("Checking Keys"),
1010 i18n("Checking key 0xMMMMMMMM..."));
1011 pProgressDlg->setModal(true );
1012 pProgressDlg->setAllowCancel( false );
1013 pProgressDlg->progressBar()->setMaximum( keys.count() );
1014 pProgressDlg->setMinimumDuration( 1000 );
1015 pProgressDlg->show();
1017 for( QList<QTreeWidgetItem*>::ConstIterator it = keys.begin();
1018 it != keys.end();
1019 ++it ) {
1020 kDebug( 5326 ) <<"Checking key 0x" << getKeyId( *it ) <<"...";
1021 pProgressDlg->setLabelText( i18n("Checking key 0x%1...",
1022 QString::fromAscii( getKeyId( *it ) ) ) );
1023 qApp->processEvents();
1024 keysAllowed = keysAllowed && ( -1 != keyAdmissibility( *it, AllowExpensiveTrustCheck ) );
1025 pProgressDlg->progressBar()->setValue( pProgressDlg->progressBar()->value() + 1 );
1026 qApp->processEvents();
1029 delete pProgressDlg;
1030 pProgressDlg = 0;
1032 return keysAllowed;
1036 void KeySelectionDialog::slotRMB( const QPoint& pos )
1038 QTreeWidgetItem *lvi = mListView->itemAt( pos );
1039 if( !lvi ) {
1040 return;
1043 mCurrentContextMenuItem = lvi;
1045 QMenu menu(this);
1046 menu.addAction( i18n( "Recheck Key" ), this, SLOT(slotRecheckKey()) );
1047 menu.exec( mListView->viewport()->mapToGlobal( pos ) );
1051 void KeySelectionDialog::slotRecheckKey()
1053 if( 0 != mCurrentContextMenuItem ) {
1054 // force rereading the key
1055 keyAdmissibility( mCurrentContextMenuItem, ForceTrustCheck );
1056 // recheck the selection
1057 slotCheckSelection( mCurrentContextMenuItem );
1061 void KeySelectionDialog::slotOk()
1063 if( mCheckSelectionTimer->isActive() ) {
1064 slotCheckSelection();
1066 mStartSearchTimer->stop();
1067 accept();
1071 void KeySelectionDialog::slotCancel()
1073 mCheckSelectionTimer->stop();
1074 mStartSearchTimer->stop();
1075 mKeyIds.clear();
1076 reject();
1079 void KeySelectionDialog::slotSearch( const QString & text )
1081 mSearchText = text.trimmed().toUpper();
1082 mStartSearchTimer->start( sCheckSelectionDelay );
1085 void KeySelectionDialog::slotFilter()
1087 if ( mSearchText.isEmpty() ) {
1088 showAllItems();
1089 return;
1092 // OK, so we need to filter:
1093 QRegExp keyIdRegExp( "(?:0x)?[A-F0-9]{1,8}", Qt::CaseInsensitive );
1094 if ( keyIdRegExp.exactMatch( mSearchText ) ) {
1095 if ( mSearchText.startsWith( "0X" ) )
1096 // search for keyID only:
1097 filterByKeyID( mSearchText.mid( 2 ) );
1098 else
1099 // search for UID and keyID:
1100 filterByKeyIDOrUID( mSearchText );
1101 } else {
1102 // search in UID:
1103 filterByUID( mSearchText );
1107 void KeySelectionDialog::filterByKeyID( const QString & keyID )
1109 assert( keyID.length() <= 8 );
1110 assert( !keyID.isEmpty() ); // regexp in slotFilter should prevent these
1111 if ( keyID.isEmpty() )
1112 showAllItems();
1113 else {
1114 for ( int i = 0; i < mListView->topLevelItemCount(); ++i ) {
1115 QTreeWidgetItem * item = mListView->topLevelItem( i );
1116 item->setHidden( !item->text( 0 ).toUpper().startsWith( keyID ) );
1121 void KeySelectionDialog::filterByKeyIDOrUID( const QString & str )
1123 assert( !str.isEmpty() );
1125 // match beginnings of words:
1126 QRegExp rx( "\\b" + QRegExp::escape( str ), Qt::CaseInsensitive );
1128 for ( int i = 0; i < mListView->topLevelItemCount(); ++i ) {
1129 QTreeWidgetItem * item = mListView->topLevelItem( i );
1130 item->setHidden( !item->text( 0 ).toUpper().startsWith( str )
1131 && rx.indexIn( item->text( 1 ) ) < 0
1132 && !anyChildMatches( item, rx ) );
1136 void KeySelectionDialog::filterByUID( const QString & str )
1138 assert( !str.isEmpty() );
1140 // match beginnings of words:
1141 QRegExp rx( "\\b" + QRegExp::escape( str ), Qt::CaseInsensitive );
1143 for ( int i = 0; i < mListView->topLevelItemCount(); ++i ) {
1144 QTreeWidgetItem * item = mListView->topLevelItem( i );
1145 item->setHidden( rx.indexIn( item->text( 1 ) ) < 0
1146 && !anyChildMatches( item, rx ) );
1151 bool KeySelectionDialog::anyChildMatches( const QTreeWidgetItem * item, QRegExp & rx ) const
1153 if ( !item )
1154 return false;
1156 for ( int i = 0; i < item->childCount(); ++i ) {
1157 QTreeWidgetItem* it = item->child( i );
1158 if ( rx.indexIn( it->text( 1 ) ) >= 0 ) {
1159 //item->setOpen( true ); // do we want that?
1160 return true;
1164 return false;
1167 void KeySelectionDialog::showAllItems()
1169 for ( QTreeWidgetItemIterator it( mListView ); *it; ++it )
1170 (*it)->setHidden( false );
1173 #endif // QT_NO_TREEWIDGET
1175 // ------------------------------------------------------------------------
1176 KeyRequester::KeyRequester( QWidget * parent, bool multipleKeys,
1177 unsigned int allowedKeys, const char * name )
1178 : QWidget( parent ),
1179 mDialogCaption( i18n("OpenPGP Key Selection") ),
1180 mDialogMessage( i18n("Please select an OpenPGP key to use.") ),
1181 mMulti( multipleKeys ),
1182 mAllowedKeys( allowedKeys ),
1183 d( 0 )
1185 setObjectName( name );
1186 QHBoxLayout * hlay = new QHBoxLayout( this );
1187 hlay->setSpacing( KDialog::spacingHint() );
1188 hlay->setMargin( 0 );
1190 // the label where the key id is to be displayed:
1191 mLabel = new QLabel( this );
1192 mLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
1194 // the button to unset any key:
1195 mEraseButton = new QPushButton( this );
1196 mEraseButton->setAutoDefault( false );
1197 mEraseButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum,
1198 QSizePolicy::Minimum ) );
1199 mEraseButton->setIcon( KIcon( "edit-clear-locationbar-rtl" ) );
1200 mEraseButton->setToolTip( i18n("Clear") );
1202 // the button to call the KeySelectionDialog:
1203 mDialogButton = new QPushButton( i18n("Change..."), this );
1204 mDialogButton->setAutoDefault( false );
1206 hlay->addWidget( mLabel, 1 );
1207 hlay->addWidget( mEraseButton );
1208 hlay->addWidget( mDialogButton );
1210 connect( mEraseButton, SIGNAL(clicked()), SLOT(slotEraseButtonClicked()) );
1211 connect( mDialogButton, SIGNAL(clicked()), SLOT(slotDialogButtonClicked()) );
1213 setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
1214 QSizePolicy::Fixed ) );
1217 KeyRequester::~KeyRequester() {
1221 KeyIDList KeyRequester::keyIDs() const {
1222 return mKeys;
1225 void KeyRequester::setKeyIDs( const KeyIDList & keyIDs ) {
1226 mKeys = keyIDs;
1227 if ( mKeys.empty() ) {
1228 mLabel->clear();
1229 return;
1231 if ( mKeys.size() > 1 )
1232 setMultipleKeysEnabled( true );
1234 QString s = mKeys.toStringList().join(", ");
1236 mLabel->setText( s );
1237 mLabel->setToolTip( s );
1240 void KeyRequester::slotDialogButtonClicked() {
1241 Module * pgp = Module::getKpgp();
1243 if ( !pgp ) {
1244 kWarning(5326) <<"Kpgp::KeyRequester::slotDialogButtonClicked(): No pgp module found!";
1245 return;
1248 setKeyIDs( keyRequestHook( pgp ) );
1249 emit changed();
1252 void KeyRequester::slotEraseButtonClicked() {
1253 mKeys.clear();
1254 mLabel->clear();
1255 emit changed();
1258 void KeyRequester::setDialogCaption( const QString & caption ) {
1259 mDialogCaption = caption;
1262 void KeyRequester::setDialogMessage( const QString & msg ) {
1263 mDialogMessage = msg;
1266 bool KeyRequester::isMultipleKeysEnabled() const {
1267 return mMulti;
1270 void KeyRequester::setMultipleKeysEnabled( bool multi ) {
1271 if ( multi == mMulti ) return;
1273 if ( !multi && mKeys.size() > 1 )
1274 mKeys.erase( ++mKeys.begin(), mKeys.end() );
1276 mMulti = multi;
1279 int KeyRequester::allowedKeys() const {
1280 return mAllowedKeys;
1283 void KeyRequester::setAllowedKeys( int allowedKeys ) {
1284 mAllowedKeys = allowedKeys;
1288 PublicKeyRequester::PublicKeyRequester( QWidget * parent, bool multi,
1289 unsigned int allowed, const char * name )
1290 : KeyRequester( parent, multi, allowed & ~SecretKeys, name )
1295 PublicKeyRequester::~PublicKeyRequester() {
1299 KeyIDList PublicKeyRequester::keyRequestHook( Module * pgp ) const {
1300 assert( pgp );
1301 return pgp->selectPublicKeys( mDialogCaption, mDialogMessage, mKeys, QString(), mAllowedKeys );
1304 SecretKeyRequester::SecretKeyRequester( QWidget * parent, bool multi,
1305 unsigned int allowed, const char * name )
1306 : KeyRequester( parent, multi, allowed & ~PublicKeys, name )
1311 SecretKeyRequester::~SecretKeyRequester() {
1315 KeyIDList SecretKeyRequester::keyRequestHook( Module * pgp ) const {
1316 assert( pgp );
1318 if(mKeys.isEmpty())
1319 return KeyIDList();
1321 KeyID keyID = mKeys.first();
1322 keyID = pgp->selectSecretKey( mDialogCaption, mDialogMessage, keyID );
1324 return KeyIDList() << keyID;
1329 // ------------------------------------------------------------------------
1330 KeyApprovalDialog::KeyApprovalDialog( const QStringList& addresses,
1331 const QVector<KeyIDList>& keyIDs,
1332 const int allowedKeys,
1333 QWidget *parent )
1334 : KDialog( parent ),
1335 mKeys( keyIDs ),
1336 mAllowedKeys( allowedKeys ),
1337 mPrefsChanged( false )
1339 setCaption( i18n("Encryption Key Approval") );
1340 setButtons( Ok|Cancel );
1342 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1344 if( pgp == 0 )
1345 return;
1347 // ##### error handling
1348 // if( addresses.isEmpty() || keyList.isEmpty() ||
1349 // addresses.count()+1 != keyList.count() )
1350 // do something;
1352 QFrame *page = new QFrame( this );
1353 setMainWidget( page );
1354 QVBoxLayout *topLayout = new QVBoxLayout( page );
1355 topLayout->setSpacing( KDialog::spacingHint() );
1356 topLayout->setMargin( 0 );
1358 QLabel *label = new QLabel( i18n("The following keys will be used for "
1359 "encryption:"),
1360 page );
1361 topLayout->addWidget( label );
1363 QScrollArea* sv = new QScrollArea( page );
1364 sv->setWidgetResizable( true );
1365 topLayout->addWidget( sv );
1366 KVBox* bigvbox = new KVBox;
1367 sv->setWidget( bigvbox );
1368 //bigvbox->setMargin( KDialog::marginHint() );
1369 bigvbox->setSpacing( KDialog::spacingHint() );
1371 QButtonGroup *mChangeButtonGroup = new QButtonGroup;
1372 mAddressLabels.resize( addresses.count() );
1373 mKeyIdsLabels.resize( keyIDs.size() );
1374 //mKeyIdListBoxes.resize( keyIDs.size() );
1375 mEncrPrefCombos.resize( addresses.count() );
1377 // the sender's key
1378 if( pgp->encryptToSelf() ) {
1379 mEncryptToSelf = 1;
1380 KHBox* hbox = new KHBox( bigvbox );
1381 new QLabel( i18n("Your keys:"), hbox );
1382 QLabel* keyidsL = new QLabel( hbox );
1383 if( keyIDs[0].isEmpty() ) {
1384 keyidsL->setText( i18nc( "@info", "<placeholder>none</placeholder> means 'no key'" ) );
1386 else {
1387 keyidsL->setText( "0x" + keyIDs[0].toStringList().join( "\n0x" ) );
1389 keyidsL->setFrameStyle( QFrame::Panel | QFrame::Sunken );
1391 QListBox* keyidLB = new QListBox( hbox );
1392 if( keyIDs[0].isEmpty() ) {
1393 keyidLB->insertItem( i18n("<none>") );
1395 else {
1396 keyidLB->insertStringList( keyIDs[0].toStringList() );
1398 keyidLB->setSelectionMode( QListBox::NoSelection );
1399 keyidLB->setFrameStyle( QFrame::Panel | QFrame::Sunken );
1401 QPushButton *button = new QPushButton( i18n("Change..."), hbox );
1402 mChangeButtonGroup->addButton( button );
1403 button->setAutoDefault( false );
1404 hbox->setStretchFactor( keyidsL, 10 );
1405 mKeyIdsLabels.insert( 0, keyidsL );
1406 //hbox->setStretchFactor( keyidLB, 10 );
1407 //mKeyIdListBoxes.insert( 0, keyidLB );
1409 new KSeparator( Qt::Horizontal, bigvbox );
1411 else {
1412 mEncryptToSelf = 0;
1413 // insert dummy KeyIdListBox
1414 mKeyIdsLabels.insert( 0, 0 );
1415 //mKeyIdListBoxes.insert( 0, 0 );
1418 QStringList::ConstIterator ait;
1419 QVector<KeyIDList>::const_iterator kit;
1420 int i;
1421 for( ait = addresses.begin(), kit = keyIDs.begin(), i = 0;
1422 ( ait != addresses.end() ) && ( kit != keyIDs.end() );
1423 ++ait, ++kit, ++i ) {
1424 if( i == 0 ) {
1425 ++kit; // skip the sender's key id
1427 else {
1428 new KSeparator( Qt::Horizontal, bigvbox );
1431 KHBox *hbox = new KHBox( bigvbox );
1432 new QLabel( i18n("Recipient:"), hbox );
1433 QLabel *addressL = new QLabel( *ait, hbox );
1434 hbox->setStretchFactor( addressL, 10 );
1435 mAddressLabels.insert( i, addressL );
1437 hbox = new KHBox( bigvbox );
1438 new QLabel( i18n("Encryption keys:"), hbox );
1439 QLabel* keyidsL = new QLabel( hbox );
1440 if( (*kit).isEmpty() ) {
1441 keyidsL->setText( i18nc( "@info", "<placeholder>none</placeholder> means 'no key'" ) );
1443 else {
1444 keyidsL->setText( "0x" + (*kit).toStringList().join( "\n0x" ) );
1446 keyidsL->setFrameStyle( QFrame::Panel | QFrame::Sunken );
1448 QListBox* keyidLB = new QListBox( hbox );
1449 if( (*kit).isEmpty() ) {
1450 keyidLB->insertItem( i18n("<none>") );
1452 else {
1453 keyidLB->insertStringList( (*kit).toStringList() );
1455 keyidLB->setSelectionMode( QListBox::NoSelection );
1456 keyidLB->setFrameStyle( QFrame::Panel | QFrame::Sunken );
1458 QPushButton *button = new QPushButton( i18n("Change..."), hbox );
1459 mChangeButtonGroup->addButton( button );
1460 button->setAutoDefault( false );
1461 hbox->setStretchFactor( keyidsL, 10 );
1462 mKeyIdsLabels.insert( i + 1, keyidsL );
1463 //hbox->setStretchFactor( keyidLB, 10 );
1464 //mKeyIdListBoxes.insert( i + 1, keyidLB );
1466 hbox = new KHBox( bigvbox );
1467 new QLabel( i18n("Encryption preference:"), hbox );
1468 QComboBox *encrPrefCombo = new QComboBox( hbox );
1469 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "<placeholder>none</placeholder>") );
1470 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "Never Encrypt with This Key") );
1471 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "Always Encrypt with This Key") );
1472 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "Encrypt Whenever Encryption is Possible") );
1473 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "Always Ask") );
1474 encrPrefCombo->addItem( i18nc( "@item:inlistbox", "Ask Whenever Encryption is Possible") );
1476 EncryptPref encrPref = pgp->encryptionPreference( *ait );
1477 switch( encrPref ) {
1478 case NeverEncrypt:
1479 encrPrefCombo->setCurrentIndex( 1 );
1480 break;
1481 case AlwaysEncrypt:
1482 encrPrefCombo->setCurrentIndex( 2 );
1483 break;
1484 case AlwaysEncryptIfPossible:
1485 encrPrefCombo->setCurrentIndex( 3 );
1486 break;
1487 case AlwaysAskForEncryption:
1488 encrPrefCombo->setCurrentIndex( 4 );
1489 break;
1490 case AskWheneverPossible:
1491 encrPrefCombo->setCurrentIndex( 5 );
1492 break;
1493 default:
1494 encrPrefCombo->setCurrentIndex( 0 );
1496 connect( encrPrefCombo, SIGNAL(activated(int)),
1497 this, SLOT(slotPrefsChanged(int)) );
1498 mEncrPrefCombos.insert( i, encrPrefCombo );
1500 connect( mChangeButtonGroup, SIGNAL(buttonClicked(int)),
1501 this, SLOT(slotChangeEncryptionKey(int)) );
1503 QSize size = sizeHint();
1505 // don't make the dialog too large
1506 QRect desk = KGlobalSettings::desktopGeometry(this);
1507 int screenWidth = desk.width();
1508 if( size.width() > 3*screenWidth/4 )
1509 size.setWidth( 3*screenWidth/4 );
1510 int screenHeight = desk.height();
1511 if( size.height() > 7*screenHeight/8 )
1512 size.setHeight( 7*screenHeight/8 );
1513 connect(this,SIGNAL(okClicked()),SLOT(slotOk()));
1514 connect(this,SIGNAL(cancelClicked()),SLOT(slotCancel()));
1515 setInitialSize( size );
1518 void
1519 KeyApprovalDialog::slotChangeEncryptionKey( int nr )
1521 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1523 kDebug( 5326 )<<"Key approval dialog size is"
1524 <<width()<<"x"<<height();
1526 if( pgp == 0 )
1527 return;
1529 if( !mEncryptToSelf )
1530 nr++;
1531 KeyIDList keyIds = mKeys[nr];
1532 if( nr == 0 ) {
1533 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"),
1534 i18nc("if in your language something like "
1535 "'key(s)' isn't possible please "
1536 "use the plural in the translation",
1537 "Select the key(s) which should "
1538 "be used to encrypt the message "
1539 "to yourself."),
1540 keyIds,
1542 mAllowedKeys );
1544 else {
1545 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"),
1546 i18nc("if in your language something like "
1547 "'key(s)' isn't possible please "
1548 "use the plural in the translation",
1549 "Select the key(s) which should "
1550 "be used to encrypt the message "
1551 "for\n%1",
1552 mAddressLabels[nr-1]->text() ),
1553 keyIds,
1554 mAddressLabels[nr-1]->text(),
1555 mAllowedKeys );
1557 if( !keyIds.isEmpty() ) {
1558 mKeys[nr] = keyIds;
1559 QLabel* keyidsL = mKeyIdsLabels[nr];
1560 keyidsL->setText( "0x" + keyIds.toStringList().join( "\n0x" ) );
1562 QListBox* qlb = mKeyIdListBoxes[nr];
1563 qlb->clear();
1564 qlb->insertStringList( keyIds.toStringList() );
1570 void
1571 KeyApprovalDialog::slotOk()
1573 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1575 if( pgp == 0 ) {
1576 accept();
1577 return;
1580 if( mPrefsChanged ) {
1581 // store the changed preferences
1582 for( int i = 0; i < mAddressLabels.size(); i++ ) {
1583 // traverse all Address and Encryption Preference widgets
1584 EncryptPref encrPref;
1585 switch( mEncrPrefCombos[i]->currentIndex() ) {
1586 case 1:
1587 encrPref = NeverEncrypt;
1588 break;
1589 case 2:
1590 encrPref = AlwaysEncrypt;
1591 break;
1592 case 3:
1593 encrPref = AlwaysEncryptIfPossible;
1594 break;
1595 case 4:
1596 encrPref = AlwaysAskForEncryption;
1597 break;
1598 case 5:
1599 encrPref = AskWheneverPossible;
1600 break;
1601 default:
1602 case 0:
1603 encrPref = UnknownEncryptPref;
1605 pgp->setEncryptionPreference( mAddressLabels[i]->text(), encrPref );
1609 accept();
1613 void
1614 KeyApprovalDialog::slotCancel()
1616 reject();
1621 // ------------------------------------------------------------------------
1622 CipherTextDialog::CipherTextDialog( const QByteArray & text,
1623 const QByteArray & charset, QWidget *parent )
1624 :KDialog( parent )
1626 setCaption( i18n("OpenPGP Information") );
1627 setButtons( Ok|Cancel );
1629 // FIXME (post KDE2.2): show some more info, e.g. the output of GnuPG/PGP
1630 QFrame *page = new QFrame( this );
1631 setMainWidget( page );
1632 QVBoxLayout *topLayout = new QVBoxLayout( page );
1633 topLayout->setSpacing( spacingHint() );
1634 topLayout->setMargin( 0 );
1636 QLabel *label = new QLabel( page );
1637 label->setText(i18n("Result of the last encryption/sign operation:"));
1638 topLayout->addWidget( label );
1640 mEditBox = new QTextEdit( page );
1641 mEditBox->setReadOnly(true);
1642 topLayout->addWidget( mEditBox, 10 );
1644 QString unicodeText;
1645 if (charset.isEmpty())
1646 unicodeText = QString::fromLocal8Bit(text.data());
1647 else {
1648 bool ok=true;
1649 QTextCodec *codec = KGlobal::charsets()->codecForName(charset, ok);
1650 if(!ok)
1651 unicodeText = QString::fromLocal8Bit(text.data());
1652 else
1653 unicodeText = codec->toUnicode(text.data(), text.length());
1656 mEditBox->setText(unicodeText);
1658 setMinimumSize();
1661 void CipherTextDialog::setMinimumSize()
1663 // this seems to force a layout of the entire document, so we get a
1664 // a proper contentsWidth(). Is there a better way?
1665 (void) mEditBox->document()->documentLayout()->documentSize();
1667 mEditBox->setMinimumHeight( mEditBox->fontMetrics().lineSpacing() * 25 );
1669 int textWidth = mEditBox->viewport()->width() + 30;
1672 int maxWidth = KGlobalSettings::desktopGeometry(parentWidget()).width()-100;
1674 mEditBox->setMinimumWidth( qMin( textWidth, maxWidth ) );
1677 void KeyRequester::virtual_hook( int, void* ) {}
1679 void PublicKeyRequester::virtual_hook( int id, void* data ) {
1680 base::virtual_hook( id, data );
1683 void SecretKeyRequester::virtual_hook( int id, void* data ) {
1684 base::virtual_hook( id, data );
1687 } // namespace Kpgp
1691 #include "kpgpui.moc"