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 #include <config-kleopatra.h>
00034
00035 #include "keylistmodel.h"
00036 #include "predicates.h"
00037
00038 #ifdef KLEO_MODEL_TEST
00039 # include "modeltest.h"
00040 #endif
00041
00042 #include <utils/formatting.h>
00043
00044 #include <kleo/keyfiltermanager.h>
00045 #include <kleo/keyfilter.h>
00046
00047 #include <KLocale>
00048 #include <KIcon>
00049
00050 #include <QDateTime>
00051 #include <QFont>
00052 #include <QColor>
00053 #include <QApplication>
00054
00055 #include <gpgme++/key.h>
00056
00057 #include <boost/bind.hpp>
00058
00059 #include <boost/graph/adjacency_list.hpp>
00060 #include <boost/graph/topological_sort.hpp>
00061
00062 #include <algorithm>
00063 #include <vector>
00064 #include <map>
00065 #include <set>
00066 #include <iterator>
00067 #include <cassert>
00068
00069 #ifdef __GNUC__
00070 #include <ext/algorithm>
00071 #endif
00072
00073 using namespace GpgME;
00074 using namespace Kleo;
00075 using namespace boost;
00076
00077 class AbstractKeyListModel::Private {
00078 public:
00079 Private() : m_toolTipOptions( Formatting::Validity ) {}
00080 int m_toolTipOptions;
00081 };
00082 AbstractKeyListModel::AbstractKeyListModel( QObject * p )
00083 : QAbstractItemModel( p ), KeyListModelInterface(), d( new Private )
00084 {
00085
00086 }
00087
00088 AbstractKeyListModel::~AbstractKeyListModel() {}
00089
00090 void AbstractKeyListModel::setToolTipOptions( int opts )
00091 {
00092 d->m_toolTipOptions = opts;
00093 }
00094
00095 int AbstractKeyListModel::toolTipOptions() const
00096 {
00097 return d->m_toolTipOptions;
00098 }
00099
00100 Key AbstractKeyListModel::key( const QModelIndex & idx ) const {
00101 if ( idx.isValid() )
00102 return doMapToKey( idx );
00103 else
00104 return Key::null;
00105 }
00106
00107 std::vector<Key> AbstractKeyListModel::keys( const QList<QModelIndex> & indexes ) const {
00108 std::vector<Key> result;
00109 result.reserve( indexes.size() );
00110 std::transform( indexes.begin(), indexes.end(),
00111 std::back_inserter( result ),
00112 bind( &AbstractKeyListModel::key, this, _1 ) );
00113 result.erase( std::unique( result.begin(), result.end(), _detail::ByFingerprint<std::equal_to>() ), result.end() );
00114 return result;
00115 }
00116
00117 QModelIndex AbstractKeyListModel::index( const Key & key, int col ) const {
00118 if ( key.isNull() || col < 0 || col >= NumColumns )
00119 return QModelIndex();
00120 else
00121 return doMapFromKey( key, col );
00122 }
00123
00124 QList<QModelIndex> AbstractKeyListModel::indexes( const std::vector<Key> & keys ) const {
00125 QList<QModelIndex> result;
00126 std::transform( keys.begin(), keys.end(),
00127 std::back_inserter( result ),
00128
00129
00130 bind( &AbstractKeyListModel::index, this, _1, 0 ) );
00131 return result;
00132 }
00133
00134 void AbstractKeyListModel::setKeys( const std::vector<Key> & keys ) {
00135 clear();
00136 addKeys( keys );
00137 }
00138
00139 QModelIndex AbstractKeyListModel::addKey( const Key & key ) {
00140 const std::vector<Key> vec( 1, key );
00141 const QList<QModelIndex> l = doAddKeys( vec );
00142 return l.empty() ? QModelIndex() : l.front() ;
00143 }
00144
00145 void AbstractKeyListModel::removeKey( const Key & key ) {
00146 if ( key.isNull() )
00147 return;
00148 doRemoveKey( key );
00149 }
00150
00151 QList<QModelIndex> AbstractKeyListModel::addKeys( const std::vector<Key> & keys ) {
00152 std::vector<Key> sorted;
00153 sorted.reserve( keys.size() );
00154 std::remove_copy_if( keys.begin(), keys.end(),
00155 std::back_inserter( sorted ),
00156 bind( &Key::isNull, _1 ) );
00157 std::sort( sorted.begin(), sorted.end(), _detail::ByFingerprint<std::less>() );
00158 return doAddKeys( sorted );
00159 }
00160
00161 void AbstractKeyListModel::clear() {
00162 doClear();
00163 reset();
00164 }
00165
00166 int AbstractKeyListModel::columnCount( const QModelIndex & ) const {
00167 return NumColumns;
00168 }
00169
00170 QVariant AbstractKeyListModel::headerData( int section, Qt::Orientation o, int role ) const {
00171 if ( o == Qt::Horizontal )
00172 if ( role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole )
00173 switch ( section ) {
00174 case PrettyName: return i18n( "Name" );
00175 case PrettyEMail: return i18n( "E-Mail" );
00176 case ValidFrom: return i18n( "Valid From" );
00177 case ValidUntil: return i18n( "Valid Until" );
00178 case TechnicalDetails: return i18n( "Details" );
00179 case Fingerprint: return i18n( "Fingerprint" );
00180 case NumColumns: ;
00181 }
00182 return QVariant();
00183 }
00184
00185 static QVariant returnIfValid( const QColor & t ) {
00186 if ( t.isValid() )
00187 return t;
00188 else
00189 return QVariant();
00190 }
00191
00192 static QVariant returnIfValidIcon( const QString & t ) {
00193 if ( !t.isEmpty() )
00194 return QIcon( KIcon( t ) );
00195 else
00196 return QVariant();
00197 }
00198
00199 QVariant AbstractKeyListModel::data( const QModelIndex & index, int role ) const {
00200 const Key key = this->key( index );
00201 if ( key.isNull() )
00202 return QVariant();
00203
00204 const int column = index.column();
00205
00206 if ( role == Qt::DisplayRole || role == Qt::EditRole )
00207 switch ( column ) {
00208 case PrettyName:
00209 return Formatting::prettyName( key );
00210 case PrettyEMail:
00211 return Formatting::prettyEMail( key );
00212 case ValidFrom:
00213 if ( role == Qt::EditRole )
00214 return Formatting::creationDate( key );
00215 else
00216 return Formatting::creationDateString( key );
00217 case ValidUntil:
00218 if ( role == Qt::EditRole )
00219 return Formatting::expirationDate( key );
00220 else
00221 return Formatting::expirationDateString( key );
00222 case TechnicalDetails:
00223 return Formatting::type( key );
00224 case Fingerprint:
00225 return QString::fromLatin1( key.primaryFingerprint() );
00226 case NumColumns:
00227 break;
00228 }
00229 else if ( role == Qt::ToolTipRole )
00230 return Formatting::toolTip( key, toolTipOptions() );
00231 else if ( role == Qt::FontRole ) {
00232 QFont font = qApp->font();
00233 if ( column == Fingerprint )
00234 font.setFamily( "courier" );
00235 if ( const shared_ptr<KeyFilter> & filter = KeyFilterManager::instance()->filterMatching( key, KeyFilter::Appearance ) )
00236 return filter->font( font );
00237 else
00238 return font;
00239 } else if ( role == Qt::DecorationRole || role == Qt::BackgroundRole || role == Qt::ForegroundRole ) {
00240 if ( const shared_ptr<KeyFilter> & filter = KeyFilterManager::instance()->filterMatching( key, KeyFilter::Appearance ) ) {
00241 switch ( role ) {
00242 case Qt::DecorationRole: return column == Icon ? returnIfValidIcon( filter->icon() ) : QVariant() ;
00243 case Qt::BackgroundRole: return returnIfValid( filter->bgColor() );
00244 case Qt::ForegroundRole: return returnIfValid( filter->fgColor() );
00245 default: ;
00246 }
00247 }
00248 } else if ( role == Qt::TextAlignmentRole ) {
00249 }
00250 return QVariant();
00251 }
00252
00253
00254 namespace {
00255 template <typename Base>
00256 class TableModelMixin : public Base {
00257 public:
00258 explicit TableModelMixin( QObject * p=0 ) : Base( p ) {}
00259 ~TableModelMixin() {}
00260
00261 using Base::index;
00262 QModelIndex index( int row, int column, const QModelIndex & pidx=QModelIndex() ) const {
00263 return this->hasIndex( row, column, pidx ) ? this->createIndex( row, column, 0 ) : QModelIndex() ;
00264 }
00265
00266 private:
00267 QModelIndex parent( const QModelIndex & ) const { return QModelIndex(); }
00268 bool hasChildren( const QModelIndex & pidx ) const {
00269 return ( pidx.model() == this || !pidx.isValid() ) && this->rowCount( pidx ) > 0 && this->columnCount( pidx ) > 0 ;
00270 }
00271 };
00272
00273 class FlatKeyListModel
00274 #ifndef Q_MOC_RUN
00275 : public TableModelMixin<AbstractKeyListModel>
00276 #else
00277 : public AbstractKeyListModel
00278 #endif
00279 {
00280 Q_OBJECT
00281 public:
00282 explicit FlatKeyListModel( QObject * parent=0 );
00283 ~FlatKeyListModel();
00284
00285 int rowCount( const QModelIndex & pidx ) const { return pidx.isValid() ? 0 : mKeysByFingerprint.size() ; }
00286
00287 private:
00288 Key doMapToKey( const QModelIndex & index ) const;
00289 QModelIndex doMapFromKey( const Key & key, int col ) const;
00290 QList<QModelIndex> doAddKeys( const std::vector<Key> & keys );
00291 void doRemoveKey( const Key & key );
00292 void doClear() {
00293 mKeysByFingerprint.clear();
00294 }
00295
00296 private:
00297 std::vector<Key> mKeysByFingerprint;
00298 };
00299
00300 class HierarchicalKeyListModel : public AbstractKeyListModel {
00301 Q_OBJECT
00302 public:
00303 explicit HierarchicalKeyListModel( QObject * parent=0 );
00304 ~HierarchicalKeyListModel();
00305
00306 int rowCount( const QModelIndex & pidx ) const;
00307 using AbstractKeyListModel::index;
00308 QModelIndex index( int row, int col, const QModelIndex & pidx ) const;
00309 QModelIndex parent( const QModelIndex & idx ) const;
00310
00311 bool hasChildren( const QModelIndex & pidx ) const { return rowCount( pidx ) > 0 ; }
00312
00313 private:
00314 Key doMapToKey( const QModelIndex & index ) const;
00315 QModelIndex doMapFromKey( const Key & key, int col ) const;
00316 QList<QModelIndex> doAddKeys( const std::vector<Key> & keys );
00317 void doRemoveKey( const Key & key );
00318 void doClear() {
00319 mTopLevels.clear();
00320 mKeysByFingerprint.clear();
00321 mKeysByExistingParent.clear();
00322 mKeysByNonExistingParent.clear();
00323 }
00324
00325 private:
00326 void addTopLevelKey( const Key & key );
00327 void addKeyWithParent( const char * issuer_fpr, const Key & key );
00328 void addKeyWithoutParent( const char * issuer_fpr, const Key & key );
00329
00330 private:
00331 typedef std::map< std::string, std::vector<Key> > Map;
00332 std::vector<Key> mKeysByFingerprint;
00333 Map mKeysByExistingParent, mKeysByNonExistingParent;
00334 std::vector<Key> mTopLevels;
00335 };
00336
00337 static const char * cleanChainID( const Key & key ) {
00338 if ( key.isRoot() )
00339 return "";
00340 if ( const char * chid = key.chainID() )
00341 return chid;
00342 return "";
00343 }
00344
00345 }
00346
00347
00348 FlatKeyListModel::FlatKeyListModel( QObject * p )
00349 : TableModelMixin<AbstractKeyListModel>( p ),
00350 mKeysByFingerprint()
00351 {
00352
00353 }
00354
00355 FlatKeyListModel::~FlatKeyListModel() {}
00356
00357 Key FlatKeyListModel::doMapToKey( const QModelIndex & idx ) const {
00358 assert( idx.isValid() );
00359 if ( static_cast<unsigned>( idx.row() ) < mKeysByFingerprint.size() && idx.column() < NumColumns )
00360 return mKeysByFingerprint[ idx.row() ];
00361 else
00362 return Key::null;
00363 }
00364
00365 QModelIndex FlatKeyListModel::doMapFromKey( const Key & key, int col ) const {
00366 assert( !key.isNull() );
00367 const std::vector<Key>::const_iterator it
00368 = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
00369 key, _detail::ByFingerprint<std::less>() );
00370 if ( it == mKeysByFingerprint.end() )
00371 return QModelIndex();
00372 else
00373 return createIndex( it - mKeysByFingerprint.begin(), col );
00374 }
00375
00376 QList<QModelIndex> FlatKeyListModel::doAddKeys( const std::vector<Key> & keys ) {
00377 #ifdef __GNUC__
00378 assert( __gnu_cxx::is_sorted( keys.begin(), keys.end(), _detail::ByFingerprint<std::less>() ) );
00379 #endif
00380 if ( keys.empty() )
00381 return QList<QModelIndex>();
00382
00383 for ( std::vector<Key>::const_iterator it = keys.begin(), end = keys.end() ; it != end ; ++it ) {
00384
00385
00386 const std::vector<Key>::iterator pos = std::upper_bound( mKeysByFingerprint.begin(), mKeysByFingerprint.end(), *it, _detail::ByFingerprint<std::less>() );
00387 const unsigned int idx = std::distance( mKeysByFingerprint.begin(), pos );
00388
00389 if ( idx > 0 && qstrcmp( mKeysByFingerprint[idx-1].primaryFingerprint(), it->primaryFingerprint() ) == 0 ) {
00390
00391 mKeysByFingerprint[idx-1] = *it;
00392 emit dataChanged( createIndex( idx-1, 0 ), createIndex( idx-1, NumColumns-1 ) );
00393 } else {
00394
00395 beginInsertRows( QModelIndex(), idx, idx );
00396 mKeysByFingerprint.insert( pos, *it );
00397 endInsertRows();
00398 }
00399 }
00400
00401 return indexes( keys );
00402 }
00403
00404
00405 void FlatKeyListModel::doRemoveKey( const Key & key ) {
00406 const std::vector<Key>::iterator it
00407 = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
00408 key, _detail::ByFingerprint<std::less>() );
00409 if ( it == mKeysByFingerprint.end() )
00410 return;
00411
00412 const unsigned int row = std::distance( mKeysByFingerprint.begin(), it );
00413 beginRemoveRows( QModelIndex(), row, row );
00414 mKeysByFingerprint.erase( it );
00415 endRemoveRows();
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425 HierarchicalKeyListModel::HierarchicalKeyListModel( QObject * p )
00426 : AbstractKeyListModel( p ),
00427 mKeysByFingerprint(),
00428 mKeysByExistingParent(),
00429 mKeysByNonExistingParent(),
00430 mTopLevels()
00431 {
00432
00433 }
00434
00435 HierarchicalKeyListModel::~HierarchicalKeyListModel() {}
00436
00437 int HierarchicalKeyListModel::rowCount( const QModelIndex & pidx ) const {
00438
00439
00440 if ( !pidx.isValid() )
00441 return mTopLevels.size();
00442
00443 if ( pidx.column() != 0 )
00444 return 0;
00445
00446
00447 const Key issuer = this->key( pidx );
00448 const char * const fpr = issuer.primaryFingerprint();
00449 if ( !fpr || !*fpr )
00450 return 0;
00451 const Map::const_iterator it = mKeysByExistingParent.find( fpr );
00452 if ( it == mKeysByExistingParent.end() )
00453 return 0;
00454 return it->second.size();
00455 }
00456
00457 QModelIndex HierarchicalKeyListModel::index( int row, int col, const QModelIndex & pidx ) const {
00458
00459 if ( row < 0 || col < 0 || col >= NumColumns )
00460 return QModelIndex();
00461
00462
00463 if ( !pidx.isValid() ) {
00464 if ( static_cast<unsigned>( row ) < mTopLevels.size() )
00465 return index( mTopLevels[row], col );
00466 else
00467 return QModelIndex();
00468 }
00469
00470
00471 const Key issuer = this->key( pidx );
00472 const char * const fpr = issuer.primaryFingerprint();
00473 if ( !fpr || !*fpr )
00474 return QModelIndex();
00475 const Map::const_iterator it = mKeysByExistingParent.find( fpr );
00476 if ( it == mKeysByExistingParent.end() || static_cast<unsigned>( row ) >= it->second.size() )
00477 return QModelIndex();
00478 return index( it->second[row], col );
00479 }
00480
00481 QModelIndex HierarchicalKeyListModel::parent( const QModelIndex & idx ) const {
00482 const Key key = this->key( idx );
00483 if ( key.isNull() || key.isRoot() )
00484 return QModelIndex();
00485 const std::vector<Key>::const_iterator it
00486 = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
00487 cleanChainID( key ), _detail::ByFingerprint<std::less>() );
00488 return it != mKeysByFingerprint.end() ? index( *it ) : QModelIndex();
00489 }
00490
00491 Key HierarchicalKeyListModel::doMapToKey( const QModelIndex & idx ) const {
00492
00493 if ( !idx.isValid() )
00494 return Key::null;
00495
00496 const char * const issuer_fpr = static_cast<const char*>( idx.internalPointer() );
00497 if ( !issuer_fpr || !*issuer_fpr ) {
00498
00499 if ( static_cast<unsigned>( idx.row() ) >= mTopLevels.size() )
00500 return Key::null;
00501 else
00502 return mTopLevels[idx.row()];
00503 }
00504
00505
00506 const Map::const_iterator it
00507 = mKeysByExistingParent.find( issuer_fpr );
00508 if ( it == mKeysByExistingParent.end() || static_cast<unsigned>( idx.row() ) >= it->second.size() )
00509 return Key::null;
00510 return it->second[idx.row()];
00511 }
00512
00513 QModelIndex HierarchicalKeyListModel::doMapFromKey( const Key & key, int col ) const {
00514
00515 if ( key.isNull() )
00516 return QModelIndex();
00517
00518 const char * issuer_fpr = cleanChainID( key );
00519
00520
00521 const std::vector<Key> * v = &mTopLevels;
00522 if ( issuer_fpr && *issuer_fpr ) {
00523 const std::map< std::string, std::vector<Key> >::const_iterator it
00524 = mKeysByExistingParent.find( issuer_fpr );
00525
00526 if ( it != mKeysByExistingParent.end() )
00527 v = &it->second;
00528 else
00529 issuer_fpr = 0;
00530 }
00531
00532 const std::vector<Key>::const_iterator it
00533 = qBinaryFind( v->begin(), v->end(), key, _detail::ByFingerprint<std::less>() );
00534 if ( it == v->end() )
00535 return QModelIndex();
00536
00537 const unsigned int row = std::distance( v->begin(), it );
00538 return createIndex( row, col, const_cast<char* /* thanks, Trolls :/ */ >( issuer_fpr ) );
00539 }
00540
00541 void HierarchicalKeyListModel::addKeyWithParent( const char * issuer_fpr, const Key & key ) {
00542
00543 assert( issuer_fpr ); assert( *issuer_fpr ); assert( !key.isNull() );
00544
00545 std::vector<Key> & subjects = mKeysByExistingParent[issuer_fpr];
00546
00547
00548 const std::vector<Key>::iterator it = std::lower_bound( subjects.begin(), subjects.end(), key, _detail::ByFingerprint<std::less>() );
00549 const int row = std::distance( subjects.begin(), it );
00550
00551 if ( it != subjects.end() && qstricmp( it->primaryFingerprint(), key.primaryFingerprint() ) == 0 ) {
00552
00553 *it = key;
00554 emit dataChanged( createIndex( row, 0, const_cast<char*>( issuer_fpr ) ), createIndex( row, NumColumns-1, const_cast<char*>( issuer_fpr ) ) );
00555 } else {
00556
00557 const std::vector<Key>::const_iterator pos = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(), issuer_fpr, _detail::ByFingerprint<std::less>() );
00558 assert( pos != mKeysByFingerprint.end() );
00559 beginInsertRows( index( *pos ), row, row );
00560 subjects.insert( it, key );
00561 endInsertRows();
00562 }
00563 }
00564
00565 void HierarchicalKeyListModel::addKeyWithoutParent( const char * issuer_fpr, const Key & key ) {
00566
00567 assert( issuer_fpr ); assert( *issuer_fpr ); assert( !key.isNull() );
00568
00569 std::vector<Key> & subjects = mKeysByNonExistingParent[issuer_fpr];
00570
00571
00572 const std::vector<Key>::iterator it = std::lower_bound( subjects.begin(), subjects.end(), key, _detail::ByFingerprint<std::less>() );
00573
00574 if ( it != subjects.end() && qstricmp( it->primaryFingerprint(), key.primaryFingerprint() ) == 0 )
00575
00576 *it = key;
00577 else
00578
00579 subjects.insert( it, key );
00580
00581 addTopLevelKey( key );
00582 }
00583
00584 void HierarchicalKeyListModel::addTopLevelKey( const Key & key ) {
00585
00586
00587 const std::vector<Key>::iterator it = std::lower_bound( mTopLevels.begin(), mTopLevels.end(), key, _detail::ByFingerprint<std::less>() );
00588 const int row = std::distance( mTopLevels.begin(), it );
00589
00590 if ( it != mTopLevels.end() && qstricmp( it->primaryFingerprint(), key.primaryFingerprint() ) == 0 ) {
00591
00592 *it = key;
00593 emit dataChanged( createIndex( row, 0 ), createIndex( row, NumColumns-1 ) );
00594 } else {
00595
00596 beginInsertRows( QModelIndex(), row, row );
00597 mTopLevels.insert( it, key );
00598 endInsertRows();
00599 }
00600
00601 }
00602
00603 namespace {
00604
00605
00606 std::vector<Key> topological_sort( const std::vector<Key> & keys ) {
00607
00608 adjacency_list<> graph( keys.size() );
00609
00610
00611 for ( unsigned int i = 0, end = keys.size() ; i != end ; ++i ) {
00612 const char * const issuer_fpr = cleanChainID( keys[i] );
00613 if ( !issuer_fpr || !*issuer_fpr )
00614 continue;
00615 const std::vector<Key>::const_iterator it
00616 = qBinaryFind( keys.begin(), keys.end(), issuer_fpr, _detail::ByFingerprint<std::less>() );
00617 if ( it == keys.end() )
00618 continue;
00619 add_edge( i, std::distance( keys.begin(), it ), graph );
00620 }
00621
00622 std::vector<int> order;
00623 order.reserve( keys.size() );
00624 topological_sort( graph, std::back_inserter( order ) );
00625
00626 assert( order.size() == keys.size() );
00627
00628 std::vector<Key> result;
00629 result.reserve( keys.size() );
00630 Q_FOREACH( int i, order )
00631 result.push_back( keys[i] );
00632 return result;
00633 }
00634
00635 }
00636
00637 QList<QModelIndex> HierarchicalKeyListModel::doAddKeys( const std::vector<Key> & keys ) {
00638 #ifdef __GNUC__
00639 assert( __gnu_cxx::is_sorted( keys.begin(), keys.end(), _detail::ByFingerprint<std::less>() ) );
00640 #endif
00641 if ( keys.empty() )
00642 return QList<QModelIndex>();
00643
00644
00645 const std::vector<Key> oldKeys = mKeysByFingerprint;
00646
00647 std::vector<Key> merged;
00648 merged.reserve( keys.size() + mKeysByFingerprint.size() );
00649 std::set_union( keys.begin(), keys.end(),
00650 mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
00651 std::back_inserter( merged ), _detail::ByFingerprint<std::less>() );
00652
00653 mKeysByFingerprint = merged;
00654
00655 std::set<Key, _detail::ByFingerprint<std::less> > changedParents;
00656
00657 Q_FOREACH( const Key & key, topological_sort( keys ) ) {
00658
00659
00660 const char * const fpr = key.primaryFingerprint();
00661 if ( !fpr || !*fpr )
00662 continue;
00663
00664 const bool keyAlreadyExisted = qBinaryFind( oldKeys.begin(), oldKeys.end(), key, _detail::ByFingerprint<std::less>() ) != oldKeys.end();
00665
00666 const Map::iterator it = mKeysByNonExistingParent.find( fpr );
00667 const std::vector<Key> children = it != mKeysByNonExistingParent.end() ? it->second : std::vector<Key>();
00668 if ( it != mKeysByNonExistingParent.end() )
00669 mKeysByNonExistingParent.erase( it );
00670
00671
00672
00673 if ( !keyAlreadyExisted ) {
00674 std::vector<Key>::iterator last = mTopLevels.begin();
00675 std::vector<Key>::iterator lastFP = mKeysByFingerprint.begin();
00676
00677 Q_FOREACH( const Key & k, children ) {
00678 last = qBinaryFind( last, mTopLevels.end(), k, _detail::ByFingerprint<std::less>() );
00679 assert( last != mTopLevels.end() );
00680 const int row = std::distance( mTopLevels.begin(), last );
00681
00682 lastFP = qBinaryFind( lastFP, mKeysByFingerprint.end(), k, _detail::ByFingerprint<std::less>() );
00683 assert( lastFP != mKeysByFingerprint.end() );
00684
00685 emit rowAboutToBeMoved( QModelIndex(), row );
00686 beginRemoveRows( QModelIndex(), row, row );
00687 last = mTopLevels.erase( last );
00688 lastFP = mKeysByFingerprint.erase( lastFP );
00689 endRemoveRows();
00690 }
00691 }
00692
00693
00694 const char * const issuer_fpr = cleanChainID( key );
00695 if ( !issuer_fpr || !*issuer_fpr )
00696
00697 addTopLevelKey( key );
00698 else if ( std::binary_search( mKeysByFingerprint.begin(), mKeysByFingerprint.end(), issuer_fpr, _detail::ByFingerprint<std::less>() ) )
00699
00700 addKeyWithParent( issuer_fpr, key );
00701 else
00702
00703 addKeyWithoutParent( issuer_fpr, key );
00704
00705 const QModelIndex key_idx = index( key );
00706 QModelIndex key_parent = key_idx.parent();
00707 while ( key_parent.isValid() ) {
00708 changedParents.insert( doMapToKey( key_parent ) );
00709 key_parent = key_parent.parent();
00710 }
00711
00712
00713
00714 if ( !keyAlreadyExisted && !children.empty() ) {
00715 addKeys( children );
00716 const QModelIndex new_parent = index( key );
00717
00718
00719 for ( int i = children.size() - 1 ; i >= 0 ; --i )
00720 emit rowMoved( new_parent, i );
00721 }
00722 }
00723
00724
00725 Q_FOREACH( const Key & i, changedParents ) {
00726 const QModelIndex idx = index( i );
00727 if ( idx.isValid() )
00728 emit dataChanged( idx.sibling( idx.row(), 0 ), idx.sibling( idx.row(), NumColumns - 1 ) );
00729 }
00730 return indexes( keys );
00731 }
00732
00733 void HierarchicalKeyListModel::doRemoveKey( const Key & key ) {
00734 const QModelIndex idx = index( key );
00735 if ( !idx.isValid() )
00736 return;
00737
00738 const char * const fpr = key.primaryFingerprint();
00739 if ( mKeysByExistingParent.find( fpr ) != mKeysByExistingParent.end() ) {
00740
00741 std::vector<Key> keys = mKeysByFingerprint;
00742 const std::vector<Key>::iterator it = qBinaryFind( keys.begin(), keys.end(),
00743 key, _detail::ByFingerprint<std::less>() );
00744 if ( it == keys.end() )
00745 return;
00746 keys.erase( it );
00747
00748
00749 clear();
00750 addKeys( keys );
00751 return;
00752 }
00753
00754
00755
00756 const std::vector<Key>::iterator it = qBinaryFind( mKeysByFingerprint.begin(), mKeysByFingerprint.end(),
00757 key, _detail::ByFingerprint<std::less>() );
00758
00759 assert( it != mKeysByFingerprint.end() );
00760 assert( mKeysByNonExistingParent.find( fpr ) == mKeysByNonExistingParent.end() );
00761 assert( mKeysByExistingParent.find( fpr ) == mKeysByExistingParent.end() );
00762
00763 beginRemoveRows( parent( idx ), idx.row(), idx.row() );
00764 mKeysByFingerprint.erase( it );
00765
00766 const char * const issuer_fpr = cleanChainID( key );
00767
00768 const std::vector<Key>::iterator tlIt = qBinaryFind( mTopLevels.begin(), mTopLevels.end(), key, _detail::ByFingerprint<std::less>() );
00769 if( tlIt != mTopLevels.end() )
00770 mTopLevels.erase( tlIt );
00771
00772 if ( issuer_fpr && *issuer_fpr ) {
00773 const Map::iterator nexIt = mKeysByNonExistingParent.find( issuer_fpr );
00774 if ( nexIt != mKeysByNonExistingParent.end() ) {
00775 const std::vector<Key>::iterator eit = qBinaryFind( nexIt->second.begin(), nexIt->second.end(), key, _detail::ByFingerprint<std::less>() );
00776 if ( eit != nexIt->second.end() )
00777 nexIt->second.erase( eit );
00778 if ( nexIt->second.empty() )
00779 mKeysByNonExistingParent.erase( nexIt );
00780 }
00781
00782 const Map::iterator exIt = mKeysByExistingParent.find( issuer_fpr );
00783 if ( exIt != mKeysByExistingParent.end() ) {
00784 const std::vector<Key>::iterator eit = qBinaryFind( exIt->second.begin(), exIt->second.end(), key, _detail::ByFingerprint<std::less>() );
00785 if ( eit != exIt->second.end() )
00786 exIt->second.erase( eit );
00787 if ( exIt->second.empty() )
00788 mKeysByExistingParent.erase( exIt );
00789 }
00790 }
00791 endRemoveRows();
00792 }
00793
00794
00795 AbstractKeyListModel * AbstractKeyListModel::createFlatKeyListModel( QObject * p ) {
00796 AbstractKeyListModel * const m = new FlatKeyListModel( p );
00797 #ifdef KLEO_MODEL_TEST
00798 new ModelTest( m, p );
00799 #endif
00800 return m;
00801 }
00802
00803
00804 AbstractKeyListModel * AbstractKeyListModel::createHierarchicalKeyListModel( QObject * p ) {
00805 AbstractKeyListModel * const m = new HierarchicalKeyListModel( p );
00806 #ifdef KLEO_MODEL_TEST
00807 new ModelTest( m, p );
00808 #endif
00809 return m;
00810 }
00811
00812 #include "moc_keylistmodel.cpp"
00813 #include "keylistmodel.moc"
00814