00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
#ifdef HAVE_CONFIG_H
00038
#include <config.h>
00039
#endif
00040
00041
#include "keyselectiondialog.h"
00042
00043
#include "keylistview.h"
00044
#include "progressdialog.h"
00045
00046
#include <kleo/dn.h>
00047
#include <kleo/keylistjob.h>
00048
#include <kleo/cryptobackendfactory.h>
00049
00050
00051
#include <gpgmepp/key.h>
00052
#include <gpgmepp/keylistresult.h>
00053
00054
00055
#include <klocale.h>
00056
#include <kapplication.h>
00057
#include <kglobal.h>
00058
#include <kiconloader.h>
00059
#include <kdebug.h>
00060
#include <kwin.h>
00061
#include <kconfig.h>
00062
#include <kmessagebox.h>
00063
00064
00065
#include <qcheckbox.h>
00066
#include <qlabel.h>
00067
#include <qpixmap.h>
00068
#include <qtimer.h>
00069
#include <qlayout.h>
00070
#include <qlineedit.h>
00071
#include <qwhatsthis.h>
00072
#include <qpopupmenu.h>
00073
#include <qregexp.h>
00074
#include <qpushbutton.h>
00075
00076
#include <algorithm>
00077
#include <iterator>
00078
00079
#include <string.h>
00080
#include <assert.h>
00081
00082
static bool checkKeyUsage(
const GpgME::Key & key,
unsigned int keyUsage ) {
00083
00084
if ( keyUsage & Kleo::KeySelectionDialog::ValidKeys )
00085
if ( key.isInvalid() )
00086 qDebug(
"key is invalid - ignoring" );
00087
if ( key.isExpired() ) {
00088 qDebug(
"key is expired" );
00089
return false;
00090 }
else if ( key.isRevoked() ) {
00091 qDebug(
"key is revoked" );
00092
return false;
00093 }
else if ( key.isDisabled() ) {
00094 qDebug(
"key is disabled" );
00095
return false;
00096 }
00097
00098
if ( keyUsage & Kleo::KeySelectionDialog::EncryptionKeys &&
00099 !key.canEncrypt() ) {
00100 qDebug(
"key can't encrypt" );
00101
return false;
00102 }
00103
if ( keyUsage & Kleo::KeySelectionDialog::SigningKeys &&
00104 !key.canSign() ) {
00105 qDebug(
"key can't sign" );
00106
return false;
00107 }
00108
if ( keyUsage & Kleo::KeySelectionDialog::CertificationKeys &&
00109 !key.canCertify() ) {
00110 qDebug(
"key can't certify" );
00111
return false;
00112 }
00113
if ( keyUsage & Kleo::KeySelectionDialog::AuthenticationKeys &&
00114 !key.canAuthenticate() ) {
00115 qDebug(
"key can't authenticate" );
00116
return false;
00117 }
00118
00119
if ( keyUsage & Kleo::KeySelectionDialog::SecretKeys &&
00120 !( keyUsage & Kleo::KeySelectionDialog::PublicKeys ) &&
00121 !key.isSecret() ) {
00122 qDebug(
"key isn't secret" );
00123
return false;
00124 }
00125
00126
if ( keyUsage & Kleo::KeySelectionDialog::TrustedKeys &&
00127 key.protocol() == GpgME::Context::OpenPGP &&
00128
00129
00130 !key.isSecret() ) {
00131 std::vector<GpgME::UserID> uids = key.userIDs();
00132
for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it )
00133
if ( !it->isRevoked() && it->validity() >= GpgME::UserID::Marginal )
00134
return true;
00135 qDebug(
"key has no UIDs with validity >= Marginal" );
00136
return false;
00137 }
00138
00139
00140
00141
return true;
00142 }
00143
00144
static bool checkKeyUsage(
const std::vector<GpgME::Key> & keys,
unsigned int keyUsage ) {
00145
for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it )
00146
if ( !checkKeyUsage( *it, keyUsage ) )
00147
return false;
00148
return true;
00149 }
00150
00151
static inline QString time_t2string( time_t t ) {
00152
QDateTime dt;
00153 dt.setTime_t( t );
00154
return dt.toString();
00155 }
00156
00157
namespace {
00158
00159
class ColumnStrategy :
public Kleo::KeyListView::ColumnStrategy {
00160
public:
00161 ColumnStrategy(
unsigned int keyUsage );
00162
00163
QString title(
int col )
const;
00164
int width(
int col,
const QFontMetrics & fm )
const;
00165
00166
QString text(
const GpgME::Key & key,
int col )
const;
00167
QString toolTip(
const GpgME::Key & key,
int col )
const;
00168
const QPixmap * pixmap(
const GpgME::Key & key,
int col )
const;
00169
00170
private:
00171
const QPixmap mKeyGoodPix, mKeyBadPix, mKeyUnknownPix, mKeyValidPix;
00172
const unsigned int mKeyUsage;
00173 };
00174
00175 ColumnStrategy::ColumnStrategy(
unsigned int keyUsage )
00176 : Kleo::KeyListView::ColumnStrategy(),
00177 mKeyGoodPix( UserIcon(
"key_ok" ) ),
00178 mKeyBadPix( UserIcon(
"key_bad" ) ),
00179 mKeyUnknownPix( UserIcon(
"key_unknown" ) ),
00180 mKeyValidPix( UserIcon(
"key" ) ),
00181 mKeyUsage( keyUsage )
00182 {
00183 kdWarning( keyUsage == 0, 5150 )
00184 <<
"KeySelectionDialog: keyUsage == 0. You want to use AllKeys instead." << endl;
00185 }
00186
00187
QString ColumnStrategy::title(
int col )
const {
00188
switch ( col ) {
00189
case 0:
return i18n(
"Key ID");
00190
case 1:
return i18n(
"User ID");
00191
default:
return QString::null;
00192 }
00193 }
00194
00195
int ColumnStrategy::width(
int col,
const QFontMetrics & fm )
const {
00196
if ( col == 0 ) {
00197
static const char hexchars[] =
"0123456789ABCDEF";
00198
int maxWidth = 0;
00199
for (
unsigned int i = 0 ; i < 16 ; ++i )
00200 maxWidth = kMax( fm.width(
QChar( hexchars[i] ) ), maxWidth );
00201
return 8 * maxWidth + 2 * mKeyGoodPix.width();
00202 }
00203
return Kleo::KeyListView::ColumnStrategy::width( col, fm );
00204 }
00205
00206
QString ColumnStrategy::text(
const GpgME::Key & key,
int col )
const {
00207
switch ( col ) {
00208
case 0:
00209 {
00210
if ( key.shortKeyID() )
00211
return QString::fromUtf8( key.shortKeyID() );
00212
else
00213
return i18n(
"<unknown>");
00214 }
00215
break;
00216
case 1:
00217 {
00218
const char * uid = key.userID(0).id();
00219
if ( key.protocol() == GpgME::Context::OpenPGP )
00220
return uid && *uid ? QString::fromUtf8( uid ) :
QString::null ;
00221
else
00222
return Kleo::DN( uid ).prettyDN();
00223 }
00224
break;
00225
default:
return QString::null;
00226 }
00227 }
00228
00229
QString ColumnStrategy::toolTip(
const GpgME::Key & key,
int )
const {
00230
const char * uid = key.userID(0).id();
00231
const char * fpr = key.subkey(0).fingerprint();
00232
const char * issuer = key.issuerName();
00233
const GpgME::Subkey subkey = key.subkey(0);
00234
const QString expiry = subkey.neverExpires() ? i18n(
"never") : time_t2string( subkey.expirationTime() ) ;
00235
const QString creation = time_t2string( subkey.creationTime() );
00236
if ( key.protocol() == GpgME::Context::OpenPGP )
00237
return i18n(
"OpenPGP key for %1\n"
00238
"Created: %2\n"
00239
"Expiry: %3\n"
00240
"Fingerprint: %4" )
00241 .arg( uid ? QString::fromUtf8( uid ) : i18n(
"unknown"),
00242 creation, expiry,
00243 fpr ? QString::fromLatin1( fpr ) : i18n(
"unknown") );
00244
else
00245
return i18n(
"S/MIME key for %1\n"
00246
"Created: %2\n"
00247
"Expiry: %3\n"
00248
"Fingerprint: %4\n"
00249
"Issuer: %5" )
00250 .arg( uid ?
Kleo::DN( uid ).prettyDN() : i18n(
"unknown"),
00251 creation, expiry,
00252 fpr ? QString::fromLatin1( fpr ) : i18n(
"unknown") )
00253 .arg( issuer ?
Kleo::DN( issuer ).prettyDN() : i18n(
"unknown") );
00254 }
00255
00256
const QPixmap * ColumnStrategy::pixmap(
const GpgME::Key & key,
int col )
const {
00257
if ( col != 0 )
00258
return 0;
00259
00260
if ( !( key.keyListMode() & GpgME::Context::Validate ) )
00261
return &mKeyUnknownPix;
00262
00263
if ( !checkKeyUsage( key, mKeyUsage ) )
00264
return &mKeyBadPix;
00265
00266
if ( key.protocol() == GpgME::Context::CMS )
00267
return &mKeyGoodPix;
00268
00269
switch ( key.userID(0).validity() ) {
00270
default:
00271
case GpgME::UserID::Unknown:
00272
case GpgME::UserID::Undefined:
00273
return &mKeyUnknownPix;
00274
case GpgME::UserID::Never:
00275
return &mKeyValidPix;
00276
case GpgME::UserID::Marginal:
00277
case GpgME::UserID::Full:
00278
case GpgME::UserID::Ultimate:
00279
return &mKeyGoodPix;
00280 }
00281 }
00282
00283 }
00284
00285
00286
static const int sCheckSelectionDelay = 250;
00287
00288 Kleo::KeySelectionDialog::KeySelectionDialog(
const QString & title,
00289
const QString & text,
00290
const std::vector<GpgME::Key> & selectedKeys,
00291
unsigned int keyUsage,
00292
bool extendedSelection,
00293
bool rememberChoice,
00294
QWidget * parent,
const char * name,
00295
bool modal )
00296 : KDialogBase( parent, name, modal, title, Default|Ok|Cancel, Ok ),
00297 mOpenPGPBackend( 0 ),
00298 mSMIMEBackend( 0 ),
00299 mRememberCB( 0 ),
00300 mSelectedKeys( selectedKeys ),
00301 mKeyUsage( keyUsage ),
00302 mCurrentContextMenuItem( 0 )
00303 {
00304 init( rememberChoice, extendedSelection, text, QString::null );
00305 }
00306
00307 Kleo::KeySelectionDialog::KeySelectionDialog(
const QString & title,
00308
const QString & text,
00309
const QString & initialQuery,
00310
unsigned int keyUsage,
00311
bool extendedSelection,
00312
bool rememberChoice,
00313
QWidget * parent,
const char * name,
00314
bool modal )
00315 : KDialogBase( parent, name, modal, title, Default|Ok|Cancel, Ok ),
00316 mOpenPGPBackend( 0 ),
00317 mSMIMEBackend( 0 ),
00318 mRememberCB( 0 ),
00319 mKeyUsage( keyUsage ),
00320 mSearchText( initialQuery ),
00321 mCurrentContextMenuItem( 0 )
00322 {
00323 init( rememberChoice, extendedSelection, text, initialQuery );
00324 }
00325
00326
void Kleo::KeySelectionDialog::init(
bool rememberChoice,
bool extendedSelection,
00327
const QString & text,
const QString & initialQuery ) {
00328
if ( mKeyUsage & OpenPGPKeys )
00329 mOpenPGPBackend = Kleo::CryptoBackendFactory::instance()->openpgp();
00330
if ( mKeyUsage & SMIMEKeys )
00331 mSMIMEBackend = Kleo::CryptoBackendFactory::instance()->smime();
00332
00333
QSize dialogSize( 580, 400 );
00334
if ( kapp ) {
00335 KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() );
00336
00337 KConfigGroup dialogConfig( KGlobal::config(),
"Key Selection Dialog" );
00338 dialogSize = dialogConfig.readSizeEntry(
"Dialog size", &dialogSize );
00339 }
00340 resize( dialogSize );
00341
00342 mCheckSelectionTimer =
new QTimer(
this );
00343 mStartSearchTimer =
new QTimer(
this );
00344
00345
QFrame *page = makeMainWidget();
00346
QVBoxLayout *topLayout =
new QVBoxLayout( page, 0, spacingHint() );
00347
00348
if ( !text.isEmpty() )
00349 topLayout->addWidget(
new QLabel( text, page ) );
00350
00351
QHBoxLayout * hlay =
new QHBoxLayout( topLayout );
00352
QLineEdit * le =
new QLineEdit( page );
00353 le->setText( initialQuery );
00354 hlay->addWidget(
new QLabel( le, i18n(
"&Search for:"), page ) );
00355 hlay->addWidget( le, 1 );
00356 le->setFocus();
00357
00358 connect( le, SIGNAL(textChanged(
const QString&)),
00359
this, SLOT(slotSearch(
const QString&)) );
00360 connect( mStartSearchTimer, SIGNAL(timeout()), SLOT(slotFilter()) );
00361
00362 mKeyListView =
new KeyListView(
new ColumnStrategy( mKeyUsage ), 0, page,
"mKeyListView" );
00363 mKeyListView->setResizeMode( QListView::LastColumn );
00364 mKeyListView->setRootIsDecorated(
true );
00365 mKeyListView->setShowSortIndicator(
true );
00366 mKeyListView->setSorting( 1,
true );
00367 mKeyListView->setShowToolTips(
true );
00368
if ( extendedSelection )
00369 mKeyListView->setSelectionMode( QListView::Extended );
00370 topLayout->addWidget( mKeyListView, 10 );
00371
00372
if ( rememberChoice ) {
00373 mRememberCB =
new QCheckBox( i18n(
"&Remember choice"), page );
00374 topLayout->addWidget( mRememberCB );
00375 QWhatsThis::add( mRememberCB,
00376 i18n(
"<qt><p>If you check this box your choice will "
00377
"be stored and you will not be asked again."
00378
"</p></qt>") );
00379 }
00380
00381 connect( mCheckSelectionTimer, SIGNAL(timeout()),
00382 SLOT(slotCheckSelection()) );
00383 connectSignals();
00384
00385 connect( mKeyListView,
00386 SIGNAL(doubleClicked(Kleo::KeyListViewItem*,
const QPoint&,
int)),
00387 SLOT(slotTryOk()) );
00388 connect( mKeyListView,
00389 SIGNAL(contextMenu(Kleo::KeyListViewItem*,
const QPoint&)),
00390 SLOT(slotRMB(Kleo::KeyListViewItem*,
const QPoint&)) );
00391
00392 setButtonText( KDialogBase::Default, i18n(
"&Reread Keys") );
00393 connect(
this, SIGNAL(defaultClicked()),
00394
this, SLOT(slotRereadKeys()) );
00395
00396 slotRereadKeys();
00397 }
00398
00399 Kleo::KeySelectionDialog::~KeySelectionDialog() {
00400 KConfigGroup dialogConfig( KGlobal::config(),
"Key Selection Dialog" );
00401 dialogConfig.writeEntry(
"Dialog size", size() );
00402 dialogConfig.sync();
00403 }
00404
00405
00406
void Kleo::KeySelectionDialog::connectSignals() {
00407
if ( mKeyListView->isMultiSelection() )
00408 connect( mKeyListView, SIGNAL(selectionChanged()),
00409 SLOT(slotSelectionChanged()) );
00410
else
00411 connect( mKeyListView, SIGNAL(selectionChanged(Kleo::KeyListViewItem*)),
00412 SLOT(slotCheckSelection(Kleo::KeyListViewItem*)) );
00413 }
00414
00415
void Kleo::KeySelectionDialog::disconnectSignals() {
00416
if ( mKeyListView->isMultiSelection() )
00417 disconnect( mKeyListView, SIGNAL(selectionChanged()),
00418
this, SLOT(slotSelectionChanged()) );
00419
else
00420 disconnect( mKeyListView, SIGNAL(selectionChanged(Kleo::KeyListViewItem*)),
00421
this, SLOT(slotCheckSelection(Kleo::KeyListViewItem*)) );
00422 }
00423
00424
const GpgME::Key & Kleo::KeySelectionDialog::selectedKey()
const {
00425
if ( mKeyListView->isMultiSelection() || !mKeyListView->selectedItem() )
00426
return GpgME::Key::null;
00427
return mKeyListView->selectedItem()->key();
00428 }
00429
00430
QString Kleo::KeySelectionDialog::fingerprint()
const {
00431
return selectedKey().subkey(0).fingerprint();
00432 }
00433
00434
QStringList Kleo::KeySelectionDialog::fingerprints()
const {
00435
QStringList result;
00436
for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it )
00437
if (
const char * fpr = it->subkey(0).fingerprint() )
00438 result.push_back( fpr );
00439
return result;
00440 }
00441
00442
QStringList Kleo::KeySelectionDialog::pgpKeyFingerprints()
const {
00443
QStringList result;
00444
for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it )
00445
if ( it->protocol() == GpgME::Context::OpenPGP )
00446
if (
const char * fpr = it->subkey(0).fingerprint() )
00447 result.push_back( fpr );
00448
return result;
00449 }
00450
00451
QStringList Kleo::KeySelectionDialog::smimeFingerprints()
const {
00452
QStringList result;
00453
for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it )
00454
if ( it->protocol() == GpgME::Context::CMS )
00455
if (
const char * fpr = it->subkey(0).fingerprint() )
00456 result.push_back( fpr );
00457
return result;
00458 }
00459
00460
void Kleo::KeySelectionDialog::slotRereadKeys() {
00461 mKeyListView->clear();
00462 mListJobCount = 0;
00463 mTruncated = 0;
00464 mSavedOffsetY = mKeyListView->contentsY();
00465
00466 disconnectSignals();
00467 this->setEnabled(
false );
00468
00469
00470
if ( mOpenPGPBackend )
00471 startKeyListJobForBackend( mOpenPGPBackend, std::vector<GpgME::Key>(),
false );
00472
if ( mSMIMEBackend )
00473 startKeyListJobForBackend( mSMIMEBackend, std::vector<GpgME::Key>(),
false );
00474
00475
if ( mListJobCount == 0 ) {
00476 this->setEnabled(
true );
00477 KMessageBox::information(
this,
00478 i18n(
"No backends found for listing keys. "
00479
"Check your installation."),
00480 i18n(
"Key Listing Failed") );
00481 connectSignals();
00482 }
00483 }
00484
00485
static void showKeyListError(
QWidget * parent,
const GpgME::Error & err ) {
00486 assert( err );
00487
const QString msg = i18n(
"<qt><p>An error occurred while fetching "
00488
"the keys from the backend:</p>"
00489
"<p><b>%1</b></p></qt>" )
00490 .arg( QString::fromLocal8Bit( err.asString() ) );
00491
00492 KMessageBox::error( parent, msg, i18n(
"Key Listing Failed" ) );
00493 }
00494
00495
namespace {
00496
struct ExtractFingerprint {
00497
QString operator()(
const GpgME::Key & key ) {
00498
return key.subkey(0).fingerprint();
00499 }
00500 };
00501 }
00502
00503
void Kleo::KeySelectionDialog::startKeyListJobForBackend(
const CryptoBackend::Protocol * backend,
const std::vector<GpgME::Key> & keys,
bool validate ) {
00504 assert( backend );
00505 KeyListJob * job = backend->keyListJob(
false,
false, validate );
00506
if ( !job )
00507
return;
00508
00509 connect( job, SIGNAL(result(
const GpgME::KeyListResult&)),
00510 SLOT(slotKeyListResult(
const GpgME::KeyListResult&)) );
00511 connect( job, SIGNAL(nextKey(
const GpgME::Key&)),
00512 mKeyListView, validate ?
00513 SLOT(slotRefreshKey(
const GpgME::Key&)) :
00514 SLOT(slotAddKey(
const GpgME::Key&)) );
00515
00516
QStringList fprs;
00517 std::transform( keys.begin(), keys.end(), std::back_inserter( fprs ), ExtractFingerprint() );
00518
const GpgME::Error err = job->start( fprs, mKeyUsage & SecretKeys && !( mKeyUsage & PublicKeys ) );
00519
00520
if ( err )
00521
return showKeyListError(
this, err );
00522
00523
00524 (
void)
new ProgressDialog( job, validate ? i18n(
"Checking selected keys..." ) : i18n(
"Fetching keys..." ),
this );
00525 ++mListJobCount;
00526 }
00527
00528
static void selectKeys( Kleo::KeyListView * klv,
const std::vector<GpgME::Key> & selectedKeys ) {
00529
if ( selectedKeys.empty() )
00530
return;
00531
int selectedKeysCount = selectedKeys.size();
00532
for ( Kleo::KeyListViewItem * item = klv->firstChild() ; item ; item = item->nextSibling() ) {
00533
const char * fpr = item->key().subkey(0).fingerprint();
00534
if ( !fpr || !*fpr )
00535
continue;
00536
for ( std::vector<GpgME::Key>::const_iterator it = selectedKeys.begin() ; it != selectedKeys.end() ; ++it )
00537
if ( qstrcmp( fpr, it->subkey(0).fingerprint() ) == 0 ) {
00538 item->setSelected(
true );
00539
if ( --selectedKeysCount <= 0 )
00540
return;
00541
else
00542
break;
00543 }
00544 }
00545 }
00546
00547
void Kleo::KeySelectionDialog::slotKeyListResult(
const GpgME::KeyListResult & res ) {
00548
if ( res.error() )
00549 showKeyListError(
this, res.error() );
00550
else if ( res.isTruncated() )
00551 ++mTruncated;
00552
00553
if ( --mListJobCount > 0 )
00554
return;
00555
00556
if ( mTruncated > 0 )
00557 KMessageBox::information(
this,
00558 i18n(
"One backend returned truncated output.\n"
00559
"Not all available keys are shown",
00560
"%n backends returned truncated output.\n"
00561
"Not all available keys are shown",
00562 mTruncated),
00563 i18n(
"Key List Result") );
00564
00565 mKeyListView->flushKeys();
00566
00567 this->setEnabled(
true );
00568 mListJobCount = mTruncated = 0;
00569 mKeysToCheck.clear();
00570
00571 selectKeys( mKeyListView, mSelectedKeys );
00572
00573 slotFilter();
00574
00575 connectSignals();
00576
00577 slotSelectionChanged();
00578
00579
00580 mKeyListView->setContentsPos( 0, mSavedOffsetY ); mSavedOffsetY = 0;
00581 }
00582
00583
void Kleo::KeySelectionDialog::slotSelectionChanged() {
00584 kdDebug(5150) <<
"KeySelectionDialog::slotSelectionChanged()" << endl;
00585
00586
00587
00588
00589 mCheckSelectionTimer->start( sCheckSelectionDelay );
00590 }
00591
00592
namespace {
00593
struct AlreadyChecked {
00594
bool operator()(
const GpgME::Key & key )
const {
00595
return key.keyListMode() & GpgME::Context::Validate ;
00596 }
00597 };
00598 }
00599
00600
void Kleo::KeySelectionDialog::slotCheckSelection( KeyListViewItem * item ) {
00601 kdDebug(5150) <<
"KeySelectionDialog::slotCheckSelection()\n";
00602
00603 mCheckSelectionTimer->stop();
00604
00605 mSelectedKeys.clear();
00606
00607
if ( !mKeyListView->isMultiSelection() ) {
00608
if ( item )
00609 mSelectedKeys.push_back( item->key() );
00610 }
00611
00612
for ( KeyListViewItem * it = mKeyListView->firstChild() ; it ; it = it->nextSibling() )
00613
if ( it->isSelected() )
00614 mSelectedKeys.push_back( it->key() );
00615
00616 mKeysToCheck.clear();
00617 std::remove_copy_if( mSelectedKeys.begin(), mSelectedKeys.end(),
00618 std::back_inserter( mKeysToCheck ),
00619 AlreadyChecked() );
00620
if ( mKeysToCheck.empty() ) {
00621 enableButtonOK( !mSelectedKeys.empty() &&
00622 checkKeyUsage( mSelectedKeys, mKeyUsage ) );
00623
return;
00624 }
00625
00626
00627 startValidatingKeyListing();
00628 }
00629
00630
void Kleo::KeySelectionDialog::startValidatingKeyListing() {
00631
if ( mKeysToCheck.empty() )
00632
return;
00633
00634 mListJobCount = 0;
00635 mTruncated = 0;
00636 mSavedOffsetY = mKeyListView->contentsY();
00637
00638 disconnectSignals();
00639 this->setEnabled(
false );
00640
00641 std::vector<GpgME::Key> smime, openpgp;
00642
for ( std::vector<GpgME::Key>::const_iterator it = mKeysToCheck.begin() ; it != mKeysToCheck.end() ; ++it )
00643
if ( it->protocol() == GpgME::Context::OpenPGP )
00644 openpgp.push_back( *it );
00645
else
00646 smime.push_back( *it );
00647
00648
if ( !openpgp.empty() ) {
00649 assert( mOpenPGPBackend );
00650 startKeyListJobForBackend( mOpenPGPBackend, openpgp,
true );
00651 }
00652
if ( !smime.empty() ) {
00653 assert( mSMIMEBackend );
00654 startKeyListJobForBackend( mSMIMEBackend, smime,
true );
00655 }
00656
00657 assert( mListJobCount > 0 );
00658 }
00659
00660
bool Kleo::KeySelectionDialog::rememberSelection()
const {
00661
return mRememberCB && mRememberCB->isChecked() ;
00662 }
00663
00664
void Kleo::KeySelectionDialog::slotRMB( Kleo::KeyListViewItem * item,
const QPoint & p ) {
00665
if ( !item )
return;
00666
00667 mCurrentContextMenuItem = item;
00668
00669
QPopupMenu menu;
00670 menu.insertItem( i18n(
"Recheck Key" ),
this, SLOT(slotRecheckKey()) );
00671 menu.exec( p );
00672 }
00673
00674
void Kleo::KeySelectionDialog::slotRecheckKey() {
00675
if ( !mCurrentContextMenuItem || mCurrentContextMenuItem->key().isNull() )
00676
return;
00677
00678 mKeysToCheck.clear();
00679 mKeysToCheck.push_back( mCurrentContextMenuItem->key() );
00680 }
00681
00682
void Kleo::KeySelectionDialog::slotTryOk() {
00683
if ( actionButton( Ok )->isEnabled() )
00684 slotOk();
00685 }
00686
00687
void Kleo::KeySelectionDialog::slotOk() {
00688
if ( mCheckSelectionTimer->isActive() )
00689 slotCheckSelection();
00690 mStartSearchTimer->stop();
00691 accept();
00692 }
00693
00694
00695
void Kleo::KeySelectionDialog::slotCancel() {
00696 mCheckSelectionTimer->stop();
00697 mStartSearchTimer->stop();
00698 reject();
00699 }
00700
00701
void Kleo::KeySelectionDialog::slotSearch(
const QString & text ) {
00702 mSearchText = text.stripWhiteSpace().upper();
00703 slotSearch();
00704 }
00705
00706
void Kleo::KeySelectionDialog::slotSearch() {
00707 mStartSearchTimer->start( sCheckSelectionDelay,
true );
00708 }
00709
00710
void Kleo::KeySelectionDialog::slotFilter() {
00711
if ( mSearchText.isEmpty() ) {
00712 showAllItems();
00713
return;
00714 }
00715
00716
00717
QRegExp keyIdRegExp(
"(?:0x)?[A-F0-9]{1,8}",
false );
00718
if ( keyIdRegExp.exactMatch( mSearchText ) ) {
00719
if ( mSearchText.startsWith(
"0X" ) )
00720
00721 filterByKeyID( mSearchText.mid( 2 ) );
00722
else
00723
00724 filterByKeyIDOrUID( mSearchText );
00725 }
else {
00726
00727 filterByUID( mSearchText );
00728 }
00729 }
00730
00731
void Kleo::KeySelectionDialog::filterByKeyID(
const QString & keyID ) {
00732 assert( keyID.length() <= 8 );
00733 assert( !keyID.isEmpty() );
00734
if ( keyID.isEmpty() )
00735 showAllItems();
00736
else
00737
for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() )
00738 item->setVisible( item->text( 0 ).upper().startsWith( keyID ) );
00739 }
00740
00741
static bool anyUIDMatches(
const Kleo::KeyListViewItem * item,
QRegExp & rx ) {
00742
if ( !item )
00743
return false;
00744
00745
const std::vector<GpgME::UserID> uids = item->key().userIDs();
00746
for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it )
00747
if ( it->id() && rx.search( QString::fromUtf8( it->id() ) ) >= 0 )
00748
return true;
00749
return false;
00750 }
00751
00752
void Kleo::KeySelectionDialog::filterByKeyIDOrUID(
const QString & str ) {
00753 assert( !str.isEmpty() );
00754
00755
00756
QRegExp rx(
"\\b" + QRegExp::escape( str ),
false );
00757
00758
for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() )
00759 item->setVisible( item->text( 0 ).upper().startsWith( str ) || anyUIDMatches( item, rx ) );
00760
00761 }
00762
00763
void Kleo::KeySelectionDialog::filterByUID(
const QString & str ) {
00764 assert( !str.isEmpty() );
00765
00766
00767
QRegExp rx(
"\\b" + QRegExp::escape( str ),
false );
00768
00769
for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() )
00770 item->setVisible( anyUIDMatches( item, rx ) );
00771 }
00772
00773
00774
void Kleo::KeySelectionDialog::showAllItems() {
00775
for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() )
00776 item->setVisible(
true );
00777 }
00778
00779
#include "keyselectiondialog.moc"