certmanager/lib

keylistview.cpp
00001 /*
00002     keylistview.cpp
00003 
00004     This file is part of libkleopatra, the KDE keymanagement library
00005     Copyright (c) 2004 Klarälvdalens Datakonsult AB
00006 
00007     Libkleopatra is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.
00011 
00012     Libkleopatra is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the TQt library by Trolltech AS, Norway (or with modified versions
00024     of TQt that use the same license as TQt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     TQt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "keylistview.h"
00038 
00039 #include <kdebug.h>
00040 
00041 #include <tqfontmetrics.h>
00042 #include <tqtooltip.h>
00043 #include <tqrect.h>
00044 #include <tqheader.h>
00045 #include <tqpoint.h>
00046 #include <tqptrlist.h>
00047 #include <tqpainter.h>
00048 #include <tqfont.h>
00049 #include <tqcolor.h>
00050 #include <tqtimer.h>
00051 #include <tqcstring.h>
00052 
00053 #include <gpgmepp/key.h>
00054 
00055 #include <vector>
00056 #include <map>
00057 
00058 #include <assert.h>
00059 
00060 static const int updateDelayMilliSecs = 500;
00061 
00062 namespace {
00063 
00064   class ItemToolTip : public TQToolTip {
00065   public:
00066     ItemToolTip( Kleo::KeyListView * parent );
00067   protected:
00068     void maybeTip( const TQPoint & p );
00069   private:
00070     Kleo::KeyListView * mKeyListView;
00071   };
00072 
00073   ItemToolTip::ItemToolTip( Kleo::KeyListView * parent )
00074     : TQToolTip( parent->viewport() ), mKeyListView( parent ) {}
00075 
00076   void ItemToolTip::maybeTip( const TQPoint & p ) {
00077     if ( !mKeyListView )
00078       return;
00079 
00080     const TQListViewItem * item = mKeyListView->itemAt( p );
00081     if ( !item )
00082       return;
00083 
00084     const TQRect itemRect = mKeyListView->itemRect( item );
00085     if ( !itemRect.isValid() )
00086       return;
00087 
00088     const int col = mKeyListView->header()->sectionAt( p.x() );
00089     if ( col == -1 )
00090       return;
00091 
00092     const TQRect headerRect = mKeyListView->header()->sectionRect( col );
00093     if ( !headerRect.isValid() )
00094       return;
00095 
00096     const TQRect cellRect( headerRect.left(), itemRect.top(),
00097               headerRect.width(), itemRect.height() );
00098 
00099     TQString tipStr;
00100     if ( const Kleo::KeyListViewItem * klvi = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) )
00101       tipStr = klvi->toolTip( col );
00102     else
00103       tipStr = item->text( col ) ;
00104 
00105     if ( !tipStr.isEmpty() )
00106       tip( cellRect, tipStr );
00107   }
00108 
00109 } // anon namespace
00110 
00111 struct Kleo::KeyListView::Private {
00112   Private() : updateTimer( 0 ), itemToolTip( 0 ) {}
00113 
00114   std::vector<GpgME::Key> keyBuffer;
00115   TQTimer * updateTimer;
00116   TQToolTip * itemToolTip;
00117   std::map<TQCString,KeyListViewItem*> itemMap;
00118 };
00119 
00120 // a list of signals where we want to replace TQListViewItem with
00121 // Kleo:KeyListViewItem:
00122 static const struct {
00123   const char * source;
00124   const char * target;
00125 } signalReplacements[] = {
00126   { TQT_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&,int)),
00127     TQT_SLOT(slotEmitDoubleClicked(TQListViewItem*,const TQPoint&,int)) },
00128   { TQT_SIGNAL(returnPressed(TQListViewItem*)),
00129     TQT_SLOT(slotEmitReturnPressed(TQListViewItem*)) },
00130   { TQT_SIGNAL(selectionChanged(TQListViewItem*)),
00131     TQT_SLOT(slotEmitSelectionChanged(TQListViewItem*)) },
00132   { TQT_SIGNAL(contextMenu(KListView*, TQListViewItem*,const TQPoint&)),
00133     TQT_SLOT(slotEmitContextMenu(KListView*, TQListViewItem*,const TQPoint&)) },
00134 };
00135 static const int numSignalReplacements = sizeof signalReplacements / sizeof *signalReplacements;
00136 
00137 
00138 Kleo::KeyListView::KeyListView( const ColumnStrategy * columnStrategy, const DisplayStrategy * displayStrategy, TQWidget * parent, const char * name, WFlags f )
00139   : KListView( parent, name ),
00140     mColumnStrategy( columnStrategy ),
00141     mDisplayStrategy ( displayStrategy  ),
00142     mHierarchical( false )
00143 {
00144   setWFlags( f );
00145 
00146   d = new Private();
00147 
00148   d->updateTimer = new TQTimer( this );
00149   connect( d->updateTimer, TQT_SIGNAL(timeout()), TQT_SLOT(slotUpdateTimeout()) );
00150 
00151   if ( !columnStrategy ) {
00152     kdWarning(5150) << "Kleo::KeyListView: need a column strategy to work with!" << endl;
00153     return;
00154   }
00155 
00156   const TQFontMetrics fm = fontMetrics();
00157 
00158   for ( int col = 0 ; !columnStrategy->title( col ).isEmpty() ; ++col ) {
00159     addColumn( columnStrategy->title( col ), columnStrategy->width( col, fm ) );
00160     setColumnWidthMode( col, columnStrategy->widthMode( col ) );
00161   }
00162 
00163   setAllColumnsShowFocus( true );
00164   setShowToolTips( false ); // we do it instead...
00165 
00166   for ( int i = 0 ; i < numSignalReplacements ; ++i )
00167     connect( this, signalReplacements[i].source, signalReplacements[i].target );
00168 
00169   TQToolTip::remove( this );
00170   TQToolTip::remove( viewport() ); // make double sure :)
00171   d->itemToolTip = new ItemToolTip( this );
00172 }
00173 
00174 Kleo::KeyListView::~KeyListView() {
00175   d->updateTimer->stop();
00176   // need to clear here, since in ~TQListView, our children won't have
00177   // a valid listView() pointing to us anymore, and their dtors try to
00178   // unregister from us.
00179   clear();
00180   assert( d->itemMap.size() == 0 );
00181   // need to delete the tooltip ourselves, as ~TQToolTip isn't virtual :o
00182   delete d->itemToolTip; d->itemToolTip = 0;
00183   delete d; d = 0;
00184   delete mColumnStrategy; mColumnStrategy = 0;
00185   delete mDisplayStrategy; mDisplayStrategy = 0;
00186 }
00187 
00188 void Kleo::KeyListView::insertItem( TQListViewItem * qlvi ) {
00189   //kdDebug() << "Kleo::KeyListView::insertItem( " << qlvi << " )" << endl;
00190   KListView::insertItem( qlvi );
00191   if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
00192     registerItem( item );
00193 }
00194 
00195 void Kleo::KeyListView::takeItem( TQListViewItem * qlvi ) {
00196   //kdDebug() << "Kleo::KeyListView::takeItem( " << qlvi << " )" << endl;
00197   if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
00198     deregisterItem( item );
00199   KListView::takeItem( qlvi );
00200 }
00201 
00202 
00203 void Kleo::KeyListView::setHierarchical( bool hier ) {
00204   if ( hier == mHierarchical )
00205     return;
00206   mHierarchical = hier;
00207   if ( hier )
00208     gatherScattered();
00209   else
00210     scatterGathered( firstChild() );
00211 }
00212 
00213 void Kleo::KeyListView::slotAddKey( const GpgME::Key & key ) {
00214   if ( key.isNull() )
00215     return;
00216 
00217   d->keyBuffer.push_back( key );
00218   if ( !d->updateTimer->isActive() )
00219     d->updateTimer->start( updateDelayMilliSecs, true /* single-shot */ );
00220 }
00221 
00222 void Kleo::KeyListView::slotUpdateTimeout() {
00223   if ( d->keyBuffer.empty() )
00224     return;
00225 
00226   const bool wasUpdatesEnabled = viewport()->isUpdatesEnabled();
00227   if ( wasUpdatesEnabled )
00228     viewport()->setUpdatesEnabled( false );
00229   kdDebug( 5150 ) << "Kleo::KeyListView::slotUpdateTimeout(): processing "
00230           << d->keyBuffer.size() << " items en block" << endl;
00231   if ( hierarchical() ) {
00232     for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it )
00233       doHierarchicalInsert( *it );
00234     gatherScattered();
00235   } else {
00236     for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it )
00237       (void)new KeyListViewItem( this, *it );
00238   }
00239   if ( wasUpdatesEnabled )
00240     viewport()->setUpdatesEnabled( true );
00241   d->keyBuffer.clear();
00242 }
00243 
00244 void Kleo::KeyListView::clear() {
00245   d->updateTimer->stop();
00246   d->keyBuffer.clear();
00247   KListView::clear();
00248 }
00249 
00250 void Kleo::KeyListView::registerItem( KeyListViewItem * item ) {
00251   //kdDebug() << "registerItem( " << item << " )" << endl;
00252   if ( !item )
00253     return;
00254   const TQCString fpr = item->key().primaryFingerprint();
00255   if ( !fpr.isEmpty() )
00256     d->itemMap.insert( std::make_pair( fpr, item ) );
00257 }
00258 
00259 void Kleo::KeyListView::deregisterItem( const KeyListViewItem * item ) {
00260   //kdDebug() << "deregisterItem( KeyLVI: " << item << " )" << endl;
00261   if ( !item )
00262     return;
00263   std::map<TQCString,KeyListViewItem*>::iterator it
00264     = d->itemMap.find( item->key().primaryFingerprint() );
00265   if ( it == d->itemMap.end() )
00266     return;
00267   Q_ASSERT( it->second == item );
00268   if ( it->second != item )
00269     return;
00270   d->itemMap.erase( it );
00271 }
00272 
00273 void Kleo::KeyListView::doHierarchicalInsert( const GpgME::Key & key ) {
00274   const TQCString fpr = key.primaryFingerprint();
00275   if ( fpr.isEmpty() )
00276     return;
00277   KeyListViewItem * item = 0;
00278   if ( !key.isRoot() )
00279     if ( KeyListViewItem * parent = itemByFingerprint( key.chainID() ) ) {
00280       item = new KeyListViewItem( parent, key );
00281       parent->setOpen( true );
00282     }
00283   if ( !item )
00284     item = new KeyListViewItem( this, key ); // top-level (for now)
00285 
00286   d->itemMap.insert( std::make_pair( fpr, item ) );
00287 }
00288 
00289 void Kleo::KeyListView::gatherScattered() {
00290   KeyListViewItem * item = firstChild();
00291   while ( item ) {
00292     KeyListViewItem * cur = item;
00293     item = item->nextSibling();
00294     if ( cur->key().isRoot() )
00295       continue;
00296     if ( KeyListViewItem * parent = itemByFingerprint( cur->key().chainID() ) ) {
00297       // found a new parent...
00298       // ### todo: optimize by suppressing removing/adding the item to the itemMap...
00299       takeItem( cur );
00300       parent->insertItem( cur );
00301       parent->setOpen( true );
00302     }
00303   }
00304 }
00305 
00306 void Kleo::KeyListView::scatterGathered( TQListViewItem * start ) {
00307   TQListViewItem * item = start;
00308   while ( item ) {
00309     TQListViewItem * cur = item;
00310     item = item->nextSibling();
00311 
00312     scatterGathered( cur->firstChild() );
00313     assert( cur->childCount() == 0 );
00314 
00315     // ### todo: optimize by suppressing removing/adding the item to the itemMap...
00316     if ( cur->parent() )
00317       cur->parent()->takeItem( cur );
00318     else
00319       takeItem( cur );
00320     insertItem( cur );
00321   }
00322 }
00323 
00324 Kleo::KeyListViewItem * Kleo::KeyListView::itemByFingerprint( const TQCString & s ) const {
00325   if ( s.isEmpty() )
00326     return 0;
00327   const std::map<TQCString,KeyListViewItem*>::const_iterator it = d->itemMap.find( s );
00328   if ( it == d->itemMap.end() )
00329     return 0;
00330   return it->second;
00331 }
00332   
00333 
00334 void Kleo::KeyListView::slotRefreshKey( const GpgME::Key & key ) {
00335   const char * fpr = key.primaryFingerprint();
00336   if ( !fpr ) {
00337     return;
00338   }
00339   if ( KeyListViewItem * item = itemByFingerprint( fpr ) ) {
00340     item->setKey ( key );
00341   }
00342   else {
00343     // none found -> add it
00344     slotAddKey( key );
00345   }
00346 }
00347 
00348 // slots for the emission of covariant signals:
00349 
00350 void Kleo::KeyListView::slotEmitDoubleClicked( TQListViewItem * item, const TQPoint & p, int col ) {
00351   if ( !item || lvi_cast<KeyListViewItem>( item ) )
00352     emit doubleClicked( static_cast<KeyListViewItem*>( item ), p, col );
00353 }
00354 
00355 void Kleo::KeyListView::slotEmitReturnPressed( TQListViewItem * item ) {
00356   if ( !item || lvi_cast<KeyListViewItem>( item ) )
00357     emit returnPressed( static_cast<KeyListViewItem*>( item ) );
00358 }
00359 
00360 void Kleo::KeyListView::slotEmitSelectionChanged( TQListViewItem * item ) {
00361   if ( !item || lvi_cast<KeyListViewItem>( item ) )
00362     emit selectionChanged( static_cast<KeyListViewItem*>( item ) );
00363 }
00364 
00365 void Kleo::KeyListView::slotEmitContextMenu( KListView*, TQListViewItem * item, const TQPoint & p ) {
00366   if ( !item || lvi_cast<KeyListViewItem>( item ) )
00367     emit contextMenu( static_cast<KeyListViewItem*>( item ), p );
00368 }
00369 
00370 //
00371 //
00372 // KeyListViewItem
00373 //
00374 //
00375 
00376 Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, const GpgME::Key & key )
00377   : TQListViewItem( parent )
00378 {
00379   setKey( key );
00380 }
00381 
00382 Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Key & key )
00383   : TQListViewItem( parent, after )
00384 {
00385   setKey( key );
00386 }
00387 
00388 Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, const GpgME::Key & key )
00389   : TQListViewItem( parent )
00390 {
00391   setKey( key );
00392 }
00393 
00394 Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Key & key )
00395   : TQListViewItem( parent, after )
00396 {
00397   setKey( key );
00398 }
00399 
00400 Kleo::KeyListViewItem::~KeyListViewItem() {
00401   // delete the children first... When children are deleted in the
00402   // TQLVI dtor, they don't have listView() anymore, thus they don't
00403   // call deregister( this ), leading to stale entries in the
00404   // itemMap...
00405   while ( TQListViewItem * item = firstChild() )
00406     delete item;
00407   // better do this here, too, since deletion is top-down and thus
00408   // we're deleted when our parent item is no longer a
00409   // KeyListViewItem, but a mere TQListViewItem, so our takeItem()
00410   // overload is gone by that time...
00411   if ( KeyListView * lv = listView() )
00412     lv->deregisterItem( this );
00413 }
00414 
00415 void Kleo::KeyListViewItem::setKey( const GpgME::Key & key ) {
00416   KeyListView * lv = listView();
00417   if ( lv )
00418     lv->deregisterItem( this );
00419   mKey = key;
00420   if ( lv )
00421     lv->registerItem( this );
00422 
00423   // the ColumnStrategy operations might be very slow, so cache their
00424   // result here, where we're non-const :)
00425   const Kleo::KeyListView::ColumnStrategy * cs = lv ? lv->columnStrategy() : 0 ;
00426   if ( !cs )
00427     return;
00428   const int numCols = lv ? lv->columns() : 0 ;
00429   for ( int i = 0 ; i < numCols ; ++i ) {
00430     setText( i, cs->text( key, i ) );
00431     if ( const TQPixmap * pix = cs->pixmap( key, i ) )
00432       setPixmap( i, *pix );
00433   }
00434   repaint();
00435 }
00436 
00437 TQString Kleo::KeyListViewItem::toolTip( int col ) const {
00438   return listView() && listView()->columnStrategy()
00439     ? listView()->columnStrategy()->toolTip( key(), col )
00440     : TQString() ;
00441 }
00442 
00443 int Kleo::KeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
00444   if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
00445     return TQListViewItem::compare( item, col, ascending );
00446   KeyListViewItem * that = static_cast<KeyListViewItem*>( item );
00447   return listView()->columnStrategy()->compare( this->key(), that->key(), col );
00448 }
00449 
00450 void Kleo::KeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
00451   const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
00452   if ( !ds ) {
00453     TQListViewItem::paintCell( p, cg, column, width, alignment );
00454     return;
00455   }
00456   const TQColor fg = ds->keyForeground( key(), cg.text() );
00457   const TQColor bg = ds->keyBackground( key(), cg.base() );
00458   const TQFont f = ds->keyFont( key(), p->font() );
00459 
00460   TQColorGroup _cg = cg;
00461   p->setFont( f );
00462   _cg.setColor( TQColorGroup::Text, fg );
00463   _cg.setColor( TQColorGroup::Base, bg );
00464 
00465   TQListViewItem::paintCell( p, _cg, column, width, alignment );
00466 }
00467 
00468 void Kleo::KeyListViewItem::insertItem( TQListViewItem * qlvi ) {
00469   //kdDebug() << "Kleo::KeyListViewItem::insertItem( " << qlvi << " )" << endl;
00470   TQListViewItem::insertItem( qlvi );
00471   if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
00472     listView()->registerItem( item );
00473 }
00474 
00475 void Kleo::KeyListViewItem::takeItem( TQListViewItem * qlvi ) {
00476   //kdDebug() << "Kleo::KeyListViewItem::takeItem( " << qlvi << " )" << endl;
00477   if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
00478     listView()->deregisterItem( item );
00479   TQListViewItem::takeItem( qlvi );
00480 }
00481 
00482 
00483 //
00484 //
00485 // SubkeyKeyListViewItem
00486 //
00487 //
00488 
00489 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, const GpgME::Subkey & subkey )
00490   : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey )
00491 {
00492 
00493 }
00494 
00495 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Subkey & subkey )
00496   : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey )
00497 {
00498 
00499 }
00500 
00501 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, const GpgME::Subkey & subkey )
00502   : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey )
00503 {
00504 
00505 }
00506 
00507 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Subkey & subkey )
00508   : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey )
00509 {
00510 
00511 }
00512 
00513 void Kleo::SubkeyKeyListViewItem::setSubkey( const GpgME::Subkey & subkey ) {
00514   mSubkey = subkey;
00515   setKey( subkey.parent() );
00516 }
00517 
00518 TQString Kleo::SubkeyKeyListViewItem::text( int col ) const {
00519   return listView() && listView()->columnStrategy()
00520     ? listView()->columnStrategy()->subkeyText( subkey(), col )
00521     : TQString() ;
00522 }
00523 
00524 TQString Kleo::SubkeyKeyListViewItem::toolTip( int col ) const {
00525   return listView() && listView()->columnStrategy()
00526     ? listView()->columnStrategy()->subkeyToolTip( subkey(), col )
00527     : TQString() ;
00528 }
00529 
00530 const TQPixmap * Kleo::SubkeyKeyListViewItem::pixmap( int col ) const {
00531   return listView() && listView()->columnStrategy()
00532     ? listView()->columnStrategy()->subkeyPixmap( subkey(), col ) : 0 ;
00533 }
00534 
00535 int Kleo::SubkeyKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
00536   if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
00537     return KeyListViewItem::compare( item, col, ascending );
00538   SubkeyKeyListViewItem * that = static_cast<SubkeyKeyListViewItem*>( item );
00539   return listView()->columnStrategy()->subkeyCompare( this->subkey(), that->subkey(), col );
00540 }
00541 
00542 void Kleo::SubkeyKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
00543   const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
00544   if ( !ds ) {
00545     TQListViewItem::paintCell( p, cg, column, width, alignment );
00546     return;
00547   }
00548   const TQColor fg = ds->subkeyForeground( subkey(), cg.text() );
00549   const TQColor bg = ds->subkeyBackground( subkey(), cg.base() );
00550   const TQFont f = ds->subkeyFont( subkey(), p->font() );
00551 
00552   TQColorGroup _cg = cg;
00553   p->setFont( f );
00554   _cg.setColor( TQColorGroup::Text, fg );
00555   _cg.setColor( TQColorGroup::Base, bg );
00556 
00557   TQListViewItem::paintCell( p, _cg, column, width, alignment );
00558 }
00559 
00560 
00561 //
00562 //
00563 // UserIDKeyListViewItem
00564 //
00565 //
00566 
00567 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, const GpgME::UserID & userID )
00568   : KeyListViewItem( parent, userID.parent() ), mUserID( userID )
00569 {
00570 
00571 }
00572 
00573 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID & userID )
00574   : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID )
00575 {
00576 
00577 }
00578 
00579 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID & userID )
00580   : KeyListViewItem( parent, userID.parent() ), mUserID( userID )
00581 {
00582 
00583 }
00584 
00585 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID & userID )
00586   : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID )
00587 {
00588 
00589 }
00590 
00591 void Kleo::UserIDKeyListViewItem::setUserID( const GpgME::UserID & userID ) {
00592   mUserID = userID;
00593   setKey( userID.parent() );
00594 }
00595 
00596 TQString Kleo::UserIDKeyListViewItem::text( int col ) const {
00597   return listView() && listView()->columnStrategy()
00598     ? listView()->columnStrategy()->userIDText( userID(), col )
00599     : TQString() ;
00600 }
00601 
00602 TQString Kleo::UserIDKeyListViewItem::toolTip( int col ) const {
00603   return listView() && listView()->columnStrategy()
00604     ? listView()->columnStrategy()->userIDToolTip( userID(), col )
00605     : TQString() ;
00606 }
00607 
00608 const TQPixmap * Kleo::UserIDKeyListViewItem::pixmap( int col ) const {
00609   return listView() && listView()->columnStrategy()
00610     ? listView()->columnStrategy()->userIDPixmap( userID(), col ) : 0 ;
00611 }
00612 
00613 int Kleo::UserIDKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
00614   if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
00615     return KeyListViewItem::compare( item, col, ascending );
00616   UserIDKeyListViewItem * that = static_cast<UserIDKeyListViewItem*>( item );
00617   return listView()->columnStrategy()->userIDCompare( this->userID(), that->userID(), col );
00618 }
00619 
00620 
00621 void Kleo::UserIDKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
00622   const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
00623   if ( !ds ) {
00624     TQListViewItem::paintCell( p, cg, column, width, alignment );
00625     return;
00626   }
00627   const TQColor fg = ds->useridForeground( userID(), cg.text() );
00628   const TQColor bg = ds->useridBackground( userID(), cg.base() );
00629   const TQFont f = ds->useridFont( userID(), p->font() );
00630 
00631   TQColorGroup _cg = cg;
00632   p->setFont( f );
00633   _cg.setColor( TQColorGroup::Text, fg );
00634   _cg.setColor( TQColorGroup::Base, bg );
00635 
00636   TQListViewItem::paintCell( p, _cg, column, width, alignment );
00637 }
00638 
00639 
00640 //
00641 //
00642 // SignatureKeyListViewItem
00643 //
00644 //
00645 
00646 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, const GpgME::UserID::Signature & signature )
00647   : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature )
00648 {
00649 
00650 }
00651 
00652 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature )
00653   : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature )
00654 {
00655 
00656 }
00657 
00658 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID::Signature & signature )
00659   : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature )
00660 {
00661 
00662 }
00663 
00664 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature )
00665   : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature )
00666 {
00667 
00668 }
00669 
00670 void Kleo::SignatureKeyListViewItem::setSignature( const GpgME::UserID::Signature & signature ) {
00671   mSignature = signature;
00672   setKey( signature.parent().parent() );
00673 }
00674 
00675 TQString Kleo::SignatureKeyListViewItem::text( int col ) const {
00676   return listView() && listView()->columnStrategy()
00677     ? listView()->columnStrategy()->signatureText( signature(), col )
00678     : TQString() ;
00679 }
00680 
00681 TQString Kleo::SignatureKeyListViewItem::toolTip( int col ) const {
00682   return listView() && listView()->columnStrategy()
00683     ? listView()->columnStrategy()->signatureToolTip( signature(), col )
00684     : TQString() ;
00685 }
00686 
00687 const TQPixmap * Kleo::SignatureKeyListViewItem::pixmap( int col ) const {
00688   return listView() && listView()->columnStrategy()
00689     ? listView()->columnStrategy()->signaturePixmap( signature(), col ) : 0 ;
00690 }
00691 
00692 int Kleo::SignatureKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
00693   if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
00694     return KeyListViewItem::compare( item, col, ascending );
00695   SignatureKeyListViewItem * that = static_cast<SignatureKeyListViewItem*>( item );
00696   return listView()->columnStrategy()->signatureCompare( this->signature(), that->signature(), col );
00697 }
00698 
00699 void Kleo::SignatureKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
00700   const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
00701   if ( !ds ) {
00702     TQListViewItem::paintCell( p, cg, column, width, alignment );
00703     return;
00704   }
00705   const TQColor fg = ds->signatureForeground( signature(), cg.text() );
00706   const TQColor bg = ds->signatureBackground( signature(), cg.base() );
00707   const TQFont f = ds->signatureFont( signature(), p->font() );
00708 
00709   TQColorGroup _cg = cg;
00710   p->setFont( f );
00711   _cg.setColor( TQColorGroup::Text, fg );
00712   _cg.setColor( TQColorGroup::Base, bg );
00713 
00714   TQListViewItem::paintCell( p, _cg, column, width, alignment );
00715 }
00716 
00717 
00718 //
00719 //
00720 // ColumnStrategy
00721 //
00722 //
00723 
00724 Kleo::KeyListView::ColumnStrategy::~ColumnStrategy() {}
00725 
00726 int Kleo::KeyListView::ColumnStrategy::compare( const GpgME::Key & key1, const GpgME::Key & key2, int col ) const {
00727   return TQString::localeAwareCompare( text( key1, col ), text( key2, col ) );
00728 }
00729 
00730 int Kleo::KeyListView::ColumnStrategy::width( int col, const TQFontMetrics & fm ) const {
00731   return fm.width( title( col ) ) * 2;
00732 }
00733 
00734 int Kleo::KeyListView::ColumnStrategy::subkeyCompare( const GpgME::Subkey & sub1, const GpgME::Subkey & sub2, int col ) const {
00735   return TQString::localeAwareCompare( subkeyText( sub1, col ), subkeyText( sub2, col ) );
00736 }
00737 
00738 int Kleo::KeyListView::ColumnStrategy::userIDCompare( const GpgME::UserID & uid1, const GpgME::UserID & uid2, int col ) const {
00739   return TQString::localeAwareCompare( userIDText( uid1, col ), userIDText( uid2, col ) );
00740 }
00741 
00742 int Kleo::KeyListView::ColumnStrategy::signatureCompare( const GpgME::UserID::Signature & sig1, const GpgME::UserID::Signature & sig2, int col ) const {
00743   return TQString::localeAwareCompare( signatureText( sig1, col ), signatureText( sig2, col ) );
00744 }
00745 
00746 TQString Kleo::KeyListView::ColumnStrategy::toolTip( const GpgME::Key & key, int col ) const {
00747   return text( key, col );
00748 }
00749 
00750 TQString Kleo::KeyListView::ColumnStrategy::subkeyToolTip( const GpgME::Subkey & sub, int col ) const {
00751   return subkeyText( sub, col );
00752 }
00753 
00754 TQString Kleo::KeyListView::ColumnStrategy::userIDToolTip( const GpgME::UserID & uid, int col ) const {
00755   return userIDText( uid, col );
00756 }
00757 
00758 TQString Kleo::KeyListView::ColumnStrategy::signatureToolTip( const GpgME::UserID::Signature & sig, int col ) const {
00759   return signatureText( sig, col );
00760 }
00761 
00762 //
00763 //
00764 // DisplayStrategy
00765 //
00766 //
00767 
00768 Kleo::KeyListView::DisplayStrategy::~DisplayStrategy() {}
00769 
00770 
00771 //font
00772 TQFont Kleo::KeyListView::DisplayStrategy::keyFont( const GpgME::Key &, const TQFont & font ) const {
00773   return font;
00774 }
00775 
00776 TQFont Kleo::KeyListView::DisplayStrategy::subkeyFont( const GpgME::Subkey &, const TQFont & font ) const {
00777   return font;
00778 }
00779 
00780 TQFont Kleo::KeyListView::DisplayStrategy::useridFont( const GpgME::UserID &, const TQFont & font ) const {
00781   return font;
00782 }
00783 
00784 TQFont Kleo::KeyListView::DisplayStrategy::signatureFont( const GpgME::UserID::Signature &, const TQFont & font ) const {
00785   return font;
00786 }
00787 
00788 //foreground
00789 TQColor Kleo::KeyListView::DisplayStrategy::keyForeground( const GpgME::Key &, const TQColor & fg )const {
00790   return fg;
00791 }
00792 
00793 TQColor Kleo::KeyListView::DisplayStrategy::subkeyForeground( const GpgME::Subkey &, const TQColor & fg ) const {
00794   return fg;
00795 }
00796 
00797 TQColor Kleo::KeyListView::DisplayStrategy::useridForeground( const GpgME::UserID &, const TQColor & fg ) const {
00798   return fg;
00799 }
00800 
00801 TQColor Kleo::KeyListView::DisplayStrategy::signatureForeground( const GpgME::UserID::Signature &, const TQColor & fg ) const {
00802   return fg;
00803 }
00804 
00805 //background
00806 TQColor Kleo::KeyListView::DisplayStrategy::keyBackground( const GpgME::Key &, const TQColor & bg )const {
00807   return bg;
00808 }
00809 
00810 TQColor Kleo::KeyListView::DisplayStrategy::subkeyBackground( const GpgME::Subkey &, const TQColor & bg ) const {
00811   return bg;
00812 }
00813 
00814 TQColor Kleo::KeyListView::DisplayStrategy::useridBackground( const GpgME::UserID &, const TQColor & bg ) const {
00815   return bg;
00816 }
00817 
00818 TQColor Kleo::KeyListView::DisplayStrategy::signatureBackground( const GpgME::UserID::Signature &, const TQColor & bg ) const {
00819   return bg;
00820 }
00821 
00822 
00823 //
00824 //
00825 // Collection of covariant return reimplementations of TQListView(Item)
00826 // members:
00827 //
00828 //
00829 
00830 Kleo::KeyListView * Kleo::KeyListViewItem::listView() const {
00831   return static_cast<Kleo::KeyListView*>( TQListViewItem::listView() );
00832 }
00833 
00834 Kleo::KeyListViewItem * Kleo::KeyListViewItem::nextSibling() const {
00835   return static_cast<Kleo::KeyListViewItem*>( TQListViewItem::nextSibling() );
00836 }
00837 
00838 Kleo::KeyListViewItem * Kleo::KeyListView::firstChild() const {
00839   return static_cast<Kleo::KeyListViewItem*>( KListView::firstChild() );
00840 }
00841 
00842 Kleo::KeyListViewItem * Kleo::KeyListView::selectedItem() const {
00843   return static_cast<Kleo::KeyListViewItem*>( KListView::selectedItem() );
00844 }
00845 
00846 static void selectedItems( TQPtrList<Kleo::KeyListViewItem> & result, TQListViewItem * start ) {
00847   for ( TQListViewItem * item = start ; item ; item = item->nextSibling() ) {
00848     if ( item->isSelected() )
00849       if ( Kleo::KeyListViewItem * i = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) )
00850     result.append( i );
00851     selectedItems( result, item->firstChild() );
00852   }
00853 }
00854 
00855 TQPtrList<Kleo::KeyListViewItem> Kleo::KeyListView::selectedItems() const {
00856   TQPtrList<KeyListViewItem> result;
00857   ::selectedItems( result, firstChild() );
00858   return result;
00859 }
00860 
00861 static bool hasSelection( TQListViewItem * start ) {
00862   for ( TQListViewItem * item = start ; item ; item = item->nextSibling() )
00863     if ( item->isSelected() || hasSelection( item->firstChild() ) )
00864       return true;
00865   return false;
00866 }
00867 
00868 bool Kleo::KeyListView::hasSelection() const {
00869   return ::hasSelection( firstChild() );
00870 }
00871 
00872 #include "keylistview.moc"