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