33 #include <config-kleopatra.h>
74 #include <kleo/stl_util.h>
76 #include <gpgme++/key.h>
78 #include <KActionCollection>
79 #include <KLocalizedString>
81 #include <QAbstractItemView>
85 #include <QItemSelectionModel>
88 #include <boost/bind.hpp>
94 using namespace Kleo::Commands;
95 using namespace Kleo::SmartCard;
96 using namespace boost;
97 using namespace GpgME;
99 class KeyListController::Private {
100 friend class ::Kleo::KeyListController;
106 void connectView( QAbstractItemView * view );
107 void connectCommand(
Command * cmd );
109 void connectTabWidget();
110 void disconnectTabWidget();
112 void addCommand(
Command * cmd ) {
113 connectCommand( cmd );
114 commands.insert( std::lower_bound( commands.begin(), commands.end(), cmd ), cmd );
116 void addView( QAbstractItemView * view ) {
118 views.insert( std::lower_bound( views.begin(), views.end(), view ), view );
120 void removeView( QAbstractItemView * view ) {
121 view->disconnect(
q );
122 view->selectionModel()->disconnect(
q );
123 views.erase( std::remove( views.begin(), views.end(), view ), views.end() );
127 void slotDestroyed( QObject * o ) {
128 kDebug() << (
void* )o;
129 views.erase( std::remove( views.begin(), views.end(), o ), views.end() );
130 commands.erase( std::remove( commands.begin(), commands.end(), o ), commands.end() );
132 void slotDoubleClicked(
const QModelIndex & idx );
133 void slotActivated(
const QModelIndex & idx );
134 void slotSelectionChanged(
const QItemSelection & old,
const QItemSelection & new_ );
135 void slotContextMenu(
const QPoint & pos );
136 void slotCommandFinished();
137 void slotAddKey(
const Key & key );
138 void slotAboutToRemoveKey(
const Key & key );
139 void slotProgress(
const QString & what,
int current,
int total ) {
140 emit
q->progress( current, total );
141 if ( !what.isEmpty() )
142 emit
q->message( what );
144 void slotActionTriggered();
145 void slotCurrentViewChanged( QAbstractItemView * view ) {
146 if ( view && !kdtools::binary_search( views, view ) ) {
147 kDebug() <<
"you need to register view" << view <<
"before trying to set it as the current view!";
151 q->enableDisableActions( view ? view->selectionModel() : 0 );
155 int toolTipOptions()
const;
158 static Command::Restrictions calculateRestrictionsMask(
const QItemSelectionModel * sm );
162 QPointer<QAction> action;
163 Command::Restrictions restrictions;
166 std::vector<action_item> actions;
167 std::vector<QAbstractItemView*> views;
168 std::vector<Command*> commands;
169 QPointer<QWidget> parentWidget;
170 QPointer<TabWidget> tabWidget;
171 QPointer<QAbstractItemView> currentView;
172 QPointer<AbstractKeyListModel> flatModel, hierarchicalModel;
187 q, SLOT(slotAddKey(GpgME::Key)) );
189 q, SLOT(slotAboutToRemoveKey(GpgME::Key)) );
192 KeyListController::Private::~Private() {}
195 : QObject( p ), d( new Private( this ) )
204 void KeyListController::Private::slotAddKey(
const Key & key ) {
207 flatModel->addKey( key );
208 if ( hierarchicalModel )
209 hierarchicalModel->addKey( key );
213 void KeyListController::Private::slotAboutToRemoveKey(
const Key & key ) {
216 flatModel->removeKey( key );
217 if ( hierarchicalModel )
218 hierarchicalModel->removeKey( key );
222 if ( !view || kdtools::binary_search( d->views, view ) )
228 if ( !view || !kdtools::binary_search( d->views, view ) )
230 d->removeView( view );
234 d->slotCurrentViewChanged( view );
242 if ( model == d->flatModel )
245 d->flatModel = model;
255 if ( model == d->hierarchicalModel )
258 d->hierarchicalModel = model;
268 if ( tabWidget == d->tabWidget )
271 d->disconnectTabWidget();
275 d->connectTabWidget();
277 d->slotCurrentViewChanged( tabWidget ? tabWidget->
currentView() : 0 );
281 d->parentWidget = parent;
285 return d->parentWidget;
288 static const struct {
292 { SIGNAL(viewAdded(QAbstractItemView*)), SLOT(addView(QAbstractItemView*)) },
293 { SIGNAL(viewAboutToBeRemoved(QAbstractItemView*)), SLOT(removeView(QAbstractItemView*)) },
294 { SIGNAL(currentViewChanged(QAbstractItemView*)), SLOT(slotCurrentViewChanged(QAbstractItemView*)) },
298 void KeyListController::Private::connectTabWidget() {
301 kdtools::for_each( tabWidget->views(), boost::bind( &Private::addView,
this, _1 ) );
306 void KeyListController::Private::disconnectTabWidget() {
311 kdtools::for_each( tabWidget->views(), boost::bind( &Private::removeView,
this, _1 ) );
319 return d->hierarchicalModel;
323 return d->currentView;
334 {
"file_new_certificate", i18n(
"New Certificate..."), QString(),
335 "view-certificate-add", 0, 0, QLatin1String(
"Ctrl+N"),
false,
true },
336 {
"file_export_certificates", i18n(
"Export Certificates..."), QString(),
337 "view-certificate-export", 0, 0, QLatin1String(
"Ctrl+E"),
false,
true },
338 {
"file_export_certificates_to_server", i18n(
"Export Certificates to Server..."), QString(),
339 "view-certificate-export-server", 0, 0, QLatin1String(
"Ctrl+Shift+E"),
false,
true },
340 {
"file_export_secret_keys", i18n(
"Export Secret Keys..."), QString(),
341 "view-certificate-export-secret", 0, 0, QString(),
false,
true },
342 {
"file_lookup_certificates", i18n(
"Lookup Certificates on Server..."), QString(),
343 "edit-find", 0, 0, QLatin1String(
"Shift+Ctrl+I"),
false,
true },
344 {
"file_import_certificates", i18n(
"Import Certificates..."), QString(),
345 "view-certificate-import", 0, 0, QLatin1String(
"Ctrl+I"),
false,
true },
346 {
"file_decrypt_verify_files", i18n(
"Decrypt/Verify Files..."), QString(),
347 "document-edit-decrypt-verify", 0, 0, QString(),
false,
true },
348 {
"file_sign_encrypt_files", i18n(
"Sign/Encrypt Files..."), QString(),
349 "document-edit-sign-encrypt", 0, 0, QString(),
false,
true },
350 {
"file_checksum_create_files", i18n(
"Create Checksum Files..."), QString(),
351 0, 0, 0, QString(),
false,
true },
352 {
"file_checksum_verify_files", i18n(
"Verify Checksum Files..."), QString(),
353 0, 0, 0, QString(),
false,
true },
355 {
"view_redisplay", i18n(
"Redisplay"), QString(),
356 "view-refresh", 0, 0, QLatin1String(
"F5"),
false,
true },
357 {
"view_stop_operations", i18n(
"Stop Operation" ), QString(),
358 "process-stop",
this, SLOT(
cancelCommands()), QLatin1String(
"Escape"),
false,
false },
359 {
"view_certificate_details", i18n(
"Certificate Details" ), QString(),
360 "dialog-information", 0, 0, QString(),
false,
true },
362 {
"certificates_delete", i18n(
"Delete" ), QString(),
363 "edit-delete", 0, 0, QLatin1String(
"Delete"),
false,
true },
364 {
"certificates_certify_certificate", i18n(
"Certify Certificate..."), QString(),
365 "view-certificate-sign", 0, 0, QString(),
false,
true },
366 {
"certificates_change_expiry", i18n(
"Change Expiry Date..."), QString(),
367 0, 0, 0, QString(),
false,
true },
368 {
"certificates_change_owner_trust", i18n(
"Change Owner Trust..."), QString(),
369 0, 0, 0, QString(),
false,
true },
370 {
"certificates_trust_root", i18n(
"Trust Root Certificate"), QString(),
371 0, 0, 0, QString(),
false,
true },
372 {
"certificates_distrust_root", i18n(
"Distrust Root Certificate"), QString(),
373 0, 0, 0, QString(),
false,
true },
374 {
"certificates_change_passphrase", i18n(
"Change Passphrase..."), QString(),
375 0, 0, 0, QString(),
false,
true },
376 {
"certificates_add_userid", i18n(
"Add User-ID..."), QString(),
377 0, 0, 0, QString(),
false,
true },
378 {
"certificates_dump_certificate", i18n(
"Dump Certificate"), QString(),
379 0, 0, 0, QString(),
false,
true },
381 {
"tools_refresh_x509_certificates", i18n(
"Refresh X.509 Certificates"), QString(),
382 "view-refresh", 0, 0, QString(),
false,
true },
383 {
"tools_refresh_openpgp_certificates", i18n(
"Refresh OpenPGP Certificates"), QString(),
384 "view-refresh", 0, 0, QString(),
false,
true },
385 #ifndef KDEPIM_ONLY_KLEO
386 {
"crl_clear_crl_cache", i18n(
"Clear CRL Cache"), QString(),
387 0, 0, 0, QString(),
false,
true },
388 {
"crl_dump_crl_cache", i18n(
"Dump CRL Cache"), QString(),
389 0, 0, 0, QString(),
false,
true },
390 #endif // KDEPIM_ONLY_KLEO
391 {
"crl_import_crl", i18n(
"Import CRL From File..."), QString(),
392 0, 0, 0, QString(),
false,
true },
402 if ( QAction * action = coll->action( QLatin1String(
"view_stop_operations") ) )
403 connect(
this, SIGNAL(
commandsExecuting(
bool)), action, SLOT(setEnabled(
bool)) );
406 registerActionForCommand<NewCertificateCommand>( coll->action( QLatin1String(
"file_new_certificate") ) );
408 registerActionForCommand<LookupCertificatesCommand>( coll->action( QLatin1String(
"file_lookup_certificates") ) );
409 registerActionForCommand<ImportCertificateFromFileCommand>( coll->action( QLatin1String(
"file_import_certificates") ) );
411 registerActionForCommand<ExportCertificateCommand>( coll->action( QLatin1String(
"file_export_certificates") ) );
412 registerActionForCommand<ExportSecretKeyCommand>( coll->action( QLatin1String(
"file_export_secret_keys") ) );
413 registerActionForCommand<ExportOpenPGPCertsToServerCommand>( coll->action( QLatin1String(
"file_export_certificates_to_server") ) );
415 registerActionForCommand<DecryptVerifyFilesCommand>( coll->action(QLatin1String(
"file_decrypt_verify_files") ) );
416 registerActionForCommand<SignEncryptFilesCommand>( coll->action( QLatin1String(
"file_sign_encrypt_files") ) );
419 registerActionForCommand<ChecksumCreateFilesCommand>(coll->action( QLatin1String(
"file_checksum_create_files") ) );
420 registerActionForCommand<ChecksumVerifyFilesCommand>(coll->action( QLatin1String(
"file_checksum_verify_files") ) );
423 registerActionForCommand<ReloadKeysCommand>( coll->action( QLatin1String(
"view_redisplay") ) );
425 registerActionForCommand<DetailsCommand>( coll->action( QLatin1String(
"view_certificate_details") ) );
427 registerActionForCommand<ChangeOwnerTrustCommand>( coll->action( QLatin1String(
"certificates_change_owner_trust") ) );
428 registerActionForCommand<TrustRootCommand>( coll->action( QLatin1String(
"certificates_trust_root") ) );
429 registerActionForCommand<DistrustRootCommand>( coll->action( QLatin1String(
"certificates_distrust_root") ) );
431 registerActionForCommand<CertifyCertificateCommand>( coll->action( QLatin1String(
"certificates_certify_certificate") ) );
432 registerActionForCommand<ChangeExpiryCommand>( coll->action( QLatin1String(
"certificates_change_expiry") ) );
433 registerActionForCommand<ChangePassphraseCommand>( coll->action( QLatin1String(
"certificates_change_passphrase") ) );
434 registerActionForCommand<AddUserIDCommand>( coll->action( QLatin1String(
"certificates_add_userid") ) );
436 registerActionForCommand<DeleteCertificatesCommand>( coll->action( QLatin1String(
"certificates_delete") ) );
438 registerActionForCommand<DumpCertificateCommand>( coll->action( QLatin1String(
"certificates_dump_certificate") ) );
440 registerActionForCommand<RefreshX509CertsCommand>( coll->action( QLatin1String(
"tools_refresh_x509_certificates") ) );
441 registerActionForCommand<RefreshOpenPGPCertsCommand>(coll->action( QLatin1String(
"tools_refresh_openpgp_certificates") ) );
443 registerActionForCommand<ImportCrlCommand>( coll->action( QLatin1String(
"crl_import_crl") ) );
445 registerActionForCommand<ClearCrlCacheCommand>( coll->action( QLatin1String(
"crl_clear_crl_cache") ) );
446 registerActionForCommand<DumpCrlCacheCommand>( coll->action( QLatin1String(
"crl_dump_crl_cache") ) );
451 void KeyListController::registerAction( QAction * action, Command::Restrictions restrictions,
Command * (*create)( QAbstractItemView *,
KeyListController * ) ) {
454 assert( !action->isCheckable() );
456 const Private::action_item ai = {
457 action, restrictions, create
459 connect( action, SIGNAL(triggered()),
this, SLOT(slotActionTriggered()) );
460 d->actions.push_back( ai );
464 if ( !cmd || kdtools::binary_search( d->commands, cmd ) )
466 d->addCommand( cmd );
467 kDebug() << (
void* )cmd;
468 if ( d->commands.size() == 1 )
473 return !d->commands.empty();
485 void KeyListController::Private::connectView( QAbstractItemView * view ) {
487 connect( view, SIGNAL(destroyed(QObject*)),
488 q, SLOT(slotDestroyed(QObject*)) );
489 connect( view, SIGNAL(doubleClicked(QModelIndex)),
490 q, SLOT(slotDoubleClicked(QModelIndex)) );
491 connect( view, SIGNAL(activated(QModelIndex)),
492 q, SLOT(slotActivated(QModelIndex)) );
493 connect( view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
494 q, SLOT(slotSelectionChanged(QItemSelection,QItemSelection)) );
496 view->setContextMenuPolicy( Qt::CustomContextMenu );
497 connect( view, SIGNAL(customContextMenuRequested(QPoint)),
498 q, SLOT(slotContextMenu(QPoint)) );
501 void KeyListController::Private::connectCommand(
Command * cmd ) {
504 connect( cmd, SIGNAL(destroyed(QObject*)),
q, SLOT(slotDestroyed(QObject*)) );
505 connect( cmd, SIGNAL(finished()),
q, SLOT(slotCommandFinished()) );
507 connect( cmd, SIGNAL(info(QString,
int)),
q, SIGNAL(message(QString,
int)) );
508 connect( cmd, SIGNAL(progress(QString,
int,
int)),
q, SLOT(slotProgress(QString,
int,
int)) );
512 void KeyListController::Private::slotDoubleClicked(
const QModelIndex & idx ) {
513 QAbstractItemView *
const view = qobject_cast<QAbstractItemView*>(
q->sender() );
514 if ( !view || !kdtools::binary_search( views, view ) )
525 void KeyListController::Private::slotActivated(
const QModelIndex & idx )
528 QAbstractItemView *
const view = qobject_cast<QAbstractItemView*>(
q->sender() );
529 if ( !view || !kdtools::binary_search( views, view ) )
534 void KeyListController::Private::slotSelectionChanged(
const QItemSelection & old,
const QItemSelection & new_ )
539 const QItemSelectionModel *
const sm = qobject_cast<QItemSelectionModel*>(
q->sender() );
542 q->enableDisableActions( sm );
545 void KeyListController::Private::slotContextMenu(
const QPoint & p ) {
546 QAbstractItemView *
const view = qobject_cast<QAbstractItemView*>(
q->sender() );
547 if ( view && kdtools::binary_search( views, view ) )
548 emit
q->contextMenuRequested( view, view->viewport()->mapToGlobal( p ) );
550 kDebug() <<
"sender is not a QAbstractItemView*!";
553 void KeyListController::Private::slotCommandFinished() {
555 if ( !cmd || !kdtools::binary_search( commands, cmd ) )
557 kDebug() << (
void* )cmd;
558 if ( commands.size() == 1 )
559 emit
q->commandsExecuting(
false );
563 const Command::Restrictions restrictionsMask = d->calculateRestrictionsMask( sm );
564 Q_FOREACH(
const Private::action_item & ai, d->actions )
566 ai.action->setEnabled( ai.restrictions == ( ai.restrictions & restrictionsMask ) );
570 Q_FOREACH(
const Key & key, keys )
571 if ( key.hasSecret() && key.ownerTrust() == Key::Ultimate )
577 bool trusted =
false, untrusted =
false;
578 Q_FOREACH(
const Key & key, keys )
580 if ( key.userID(0).validity() == UserID::Ultimate )
598 Command::Restrictions KeyListController::Private::calculateRestrictionsMask(
const QItemSelectionModel * sm ) {
606 const std::vector<Key> keys = m->
keys( sm->selectedRows() );
612 if ( keys.size() == 1 )
615 if ( kdtools::all( keys.begin(), keys.end(), boost::bind( &Key::hasSecret, _1 ) ) )
617 else if ( !kdtools::any( keys.begin(), keys.end(), boost::bind( &Key::hasSecret, _1 ) ) )
620 if ( kdtools::all( keys.begin(), keys.end(), boost::bind( &Key::protocol, _1 ) ==
OpenPGP ) )
622 else if ( kdtools::all( keys.begin(), keys.end(), boost::bind( &Key::protocol, _1 ) ==
CMS ) )
631 if (
const ReaderStatus * rs = ReaderStatus::instance() ) {
632 if ( rs->anyCardHasNullPin() )
634 if ( rs->anyCardCanLearnKeys() )
642 void KeyListController::Private::slotActionTriggered() {
643 if (
const QObject *
const s =
q->sender() ) {
644 const std::vector<action_item>::const_iterator it
645 = kdtools::find_if( actions, boost::bind( &action_item::action, _1 ) ==
q->sender() );
646 if ( it != actions.end() )
647 if (
Command *
const c = it->createCommand( this->currentView,
q ) )
654 kDebug() <<
"createCommand() == NULL for action(?) \""
655 << qPrintable( s->objectName() ) <<
"\"";
657 kDebug() <<
"I don't know anything about action(?) \"%s\"", qPrintable( s->objectName() );
659 kDebug() <<
"not called through a signal/slot connection (sender() == NULL)";
663 int KeyListController::Private::toolTipOptions()
const
665 using namespace Kleo::Formatting;
673 flags |= prefs.showValidity() ? validityFlags : 0;
674 flags |= prefs.showOwnerInformation() ? ownerFlags : 0;
675 flags |= prefs.showCertificateDetails() ? detailsFlags : 0;
681 const int opts = d->toolTipOptions();
683 d->flatModel->setToolTipOptions( opts );
684 if ( d->hierarchicalModel )
685 d->hierarchicalModel->setToolTipOptions( opts );
688 #include "moc_keylistcontroller.cpp"
static const char * flags[]
void removeView(QAbstractItemView *view)
bool shutdownWarningRequired() const
TabWidget * tabWidget() const
void addView(QAbstractItemView *view)
void setCurrentView(QAbstractItemView *view)
void setFlatModel(AbstractKeyListModel *model)
void added(const GpgME::Key &key)
void setTabWidget(TabWidget *tabs)
void setHierarchicalModel(AbstractKeyListModel *model)
void setToolTipOptions(int opts)
KeyListController(QObject *parent=0)
static const unsigned int numTabs2Controller
bool warnWhenRunningAtShutdown() const
void registerCommand(Command *cmd)
static const struct @13 tabs2controller[]
void setIndex(const QModelIndex &idx)
QList< QModelIndex > addKeys(const std::vector< GpgME::Key > &keys)
QWidget * parentWidget() const
Command::Restrictions find_root_restrictions(const std::vector< Key > &keys)
AbstractKeyListModel * flatModel() const
void setParentWidget(QWidget *parent)
void commandsExecuting(bool)
void aboutToRemove(const GpgME::Key &key)
static boost::shared_ptr< const KeyCache > instance()
virtual std::vector< GpgME::Key > keys(const QList< QModelIndex > &idxs) const =0
void make_actions_from_data(const action_data *data, unsigned int numData, KActionCollection *collection)
void createActions(KActionCollection *collection)
void setParentWidget(QWidget *widget)
QAbstractItemView * currentView() const
void enableDisableActions(const QItemSelectionModel *sm) const
std::vector< QAbstractItemView * > views() const
bool hasRunningCommands() const
static boost::shared_ptr< KeyCache > mutableInstance()
AbstractKeyListModel * hierarchicalModel() const
static bool all_secret_are_not_owner_trust_ultimate(const std::vector< Key > &keys)