certmanager/lib

keylistview.cpp
1 /*
2  keylistview.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2004 Klarälvdalens Datakonsult AB
6 
7  Libkleopatra is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11 
12  Libkleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the TQt library by Trolltech AS, Norway (or with modified versions
24  of TQt that use the same license as TQt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  TQt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include "keylistview.h"
38 
39 #include <kdebug.h>
40 
41 #include <tqfontmetrics.h>
42 #include <tqtooltip.h>
43 #include <tqrect.h>
44 #include <tqheader.h>
45 #include <tqpoint.h>
46 #include <tqptrlist.h>
47 #include <tqpainter.h>
48 #include <tqfont.h>
49 #include <tqcolor.h>
50 #include <tqtimer.h>
51 #include <tqcstring.h>
52 
53 #include <gpgmepp/key.h>
54 
55 #include <vector>
56 #include <map>
57 
58 #include <assert.h>
59 
60 static const int updateDelayMilliSecs = 500;
61 
62 namespace {
63 
64  class ItemToolTip : public TQToolTip {
65  public:
66  ItemToolTip( Kleo::KeyListView * parent );
67  protected:
68  void maybeTip( const TQPoint & p );
69  private:
70  Kleo::KeyListView * mKeyListView;
71  };
72 
73  ItemToolTip::ItemToolTip( Kleo::KeyListView * parent )
74  : TQToolTip( parent->viewport() ), mKeyListView( parent ) {}
75 
76  void ItemToolTip::maybeTip( const TQPoint & p ) {
77  if ( !mKeyListView )
78  return;
79 
80  const TQListViewItem * item = mKeyListView->itemAt( p );
81  if ( !item )
82  return;
83 
84  const TQRect itemRect = mKeyListView->itemRect( item );
85  if ( !itemRect.isValid() )
86  return;
87 
88  const int col = mKeyListView->header()->sectionAt( p.x() );
89  if ( col == -1 )
90  return;
91 
92  const TQRect headerRect = mKeyListView->header()->sectionRect( col );
93  if ( !headerRect.isValid() )
94  return;
95 
96  const TQRect cellRect( headerRect.left(), itemRect.top(),
97  headerRect.width(), itemRect.height() );
98 
99  TQString tipStr;
100  if ( const Kleo::KeyListViewItem * klvi = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) )
101  tipStr = klvi->toolTip( col );
102  else
103  tipStr = item->text( col ) ;
104 
105  if ( !tipStr.isEmpty() )
106  tip( cellRect, tipStr );
107  }
108 
109 } // anon namespace
110 
111 struct Kleo::KeyListView::Private {
112  Private() : updateTimer( 0 ), itemToolTip( 0 ) {}
113 
114  std::vector<GpgME::Key> keyBuffer;
115  TQTimer * updateTimer;
116  TQToolTip * itemToolTip;
117  std::map<TQCString,KeyListViewItem*> itemMap;
118 };
119 
120 // a list of signals where we want to replace TQListViewItem with
121 // Kleo:KeyListViewItem:
122 static const struct {
123  const char * source;
124  const char * target;
125 } signalReplacements[] = {
126  { TQ_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&,int)),
127  TQ_SLOT(slotEmitDoubleClicked(TQListViewItem*,const TQPoint&,int)) },
128  { TQ_SIGNAL(returnPressed(TQListViewItem*)),
129  TQ_SLOT(slotEmitReturnPressed(TQListViewItem*)) },
130  { TQ_SIGNAL(selectionChanged(TQListViewItem*)),
131  TQ_SLOT(slotEmitSelectionChanged(TQListViewItem*)) },
132  { TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*,const TQPoint&)),
133  TQ_SLOT(slotEmitContextMenu(TDEListView*, TQListViewItem*,const TQPoint&)) },
134 };
135 static const int numSignalReplacements = sizeof signalReplacements / sizeof *signalReplacements;
136 
137 
138 Kleo::KeyListView::KeyListView( const ColumnStrategy * columnStrategy, const DisplayStrategy * displayStrategy, TQWidget * parent, const char * name, WFlags f )
139  : TDEListView( parent, name ),
140  mColumnStrategy( columnStrategy ),
141  mDisplayStrategy ( displayStrategy ),
142  mHierarchical( false )
143 {
144  setWFlags( f );
145 
146  d = new Private();
147 
148  d->updateTimer = new TQTimer( this );
149  connect( d->updateTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotUpdateTimeout()) );
150 
151  if ( !columnStrategy ) {
152  kdWarning(5150) << "Kleo::KeyListView: need a column strategy to work with!" << endl;
153  return;
154  }
155 
156  const TQFontMetrics fm = fontMetrics();
157 
158  for ( int col = 0 ; !columnStrategy->title( col ).isEmpty() ; ++col ) {
159  addColumn( columnStrategy->title( col ), columnStrategy->width( col, fm ) );
160  setColumnWidthMode( col, columnStrategy->widthMode( col ) );
161  }
162 
163  setAllColumnsShowFocus( true );
164  setShowToolTips( false ); // we do it instead...
165 
166  for ( int i = 0 ; i < numSignalReplacements ; ++i )
167  connect( this, signalReplacements[i].source, signalReplacements[i].target );
168 
169  TQToolTip::remove( this );
170  TQToolTip::remove( viewport() ); // make double sure :)
171  d->itemToolTip = new ItemToolTip( this );
172 }
173 
174 Kleo::KeyListView::~KeyListView() {
175  d->updateTimer->stop();
176  // need to clear here, since in ~TQListView, our children won't have
177  // a valid listView() pointing to us anymore, and their dtors try to
178  // unregister from us.
179  clear();
180  assert( d->itemMap.size() == 0 );
181  // need to delete the tooltip ourselves, as ~TQToolTip isn't virtual :o
182  delete d->itemToolTip; d->itemToolTip = 0;
183  delete d; d = 0;
184  delete mColumnStrategy; mColumnStrategy = 0;
185  delete mDisplayStrategy; mDisplayStrategy = 0;
186 }
187 
188 void Kleo::KeyListView::insertItem( TQListViewItem * qlvi ) {
189  //kdDebug() << "Kleo::KeyListView::insertItem( " << qlvi << " )" << endl;
190  TDEListView::insertItem( qlvi );
191  if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
192  registerItem( item );
193 }
194 
195 void Kleo::KeyListView::takeItem( TQListViewItem * qlvi ) {
196  //kdDebug() << "Kleo::KeyListView::takeItem( " << qlvi << " )" << endl;
197  if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
198  deregisterItem( item );
199  TDEListView::takeItem( qlvi );
200 }
201 
202 
203 void Kleo::KeyListView::setHierarchical( bool hier ) {
204  if ( hier == mHierarchical )
205  return;
206  mHierarchical = hier;
207  if ( hier )
208  gatherScattered();
209  else
210  scatterGathered( firstChild() );
211 }
212 
213 void Kleo::KeyListView::slotAddKey( const GpgME::Key & key ) {
214  if ( key.isNull() )
215  return;
216 
217  d->keyBuffer.push_back( key );
218  if ( !d->updateTimer->isActive() )
219  d->updateTimer->start( updateDelayMilliSecs, true /* single-shot */ );
220 }
221 
222 void Kleo::KeyListView::slotUpdateTimeout() {
223  if ( d->keyBuffer.empty() )
224  return;
225 
226  const bool wasUpdatesEnabled = viewport()->isUpdatesEnabled();
227  if ( wasUpdatesEnabled )
228  viewport()->setUpdatesEnabled( false );
229  kdDebug( 5150 ) << "Kleo::KeyListView::slotUpdateTimeout(): processing "
230  << d->keyBuffer.size() << " items en block" << endl;
231  if ( hierarchical() ) {
232  for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it )
233  doHierarchicalInsert( *it );
234  gatherScattered();
235  } else {
236  for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it )
237  (void)new KeyListViewItem( this, *it );
238  }
239  if ( wasUpdatesEnabled )
240  viewport()->setUpdatesEnabled( true );
241  d->keyBuffer.clear();
242 }
243 
244 void Kleo::KeyListView::clear() {
245  d->updateTimer->stop();
246  d->keyBuffer.clear();
247  TDEListView::clear();
248 }
249 
250 void Kleo::KeyListView::registerItem( KeyListViewItem * item ) {
251  //kdDebug() << "registerItem( " << item << " )" << endl;
252  if ( !item )
253  return;
254  const TQCString fpr = item->key().primaryFingerprint();
255  if ( !fpr.isEmpty() )
256  d->itemMap.insert( std::make_pair( fpr, item ) );
257 }
258 
259 void Kleo::KeyListView::deregisterItem( const KeyListViewItem * item ) {
260  //kdDebug() << "deregisterItem( KeyLVI: " << item << " )" << endl;
261  if ( !item )
262  return;
263  std::map<TQCString,KeyListViewItem*>::iterator it
264  = d->itemMap.find( item->key().primaryFingerprint() );
265  if ( it == d->itemMap.end() )
266  return;
267  Q_ASSERT( it->second == item );
268  if ( it->second != item )
269  return;
270  d->itemMap.erase( it );
271 }
272 
273 void Kleo::KeyListView::doHierarchicalInsert( const GpgME::Key & key ) {
274  const TQCString fpr = key.primaryFingerprint();
275  if ( fpr.isEmpty() )
276  return;
277  KeyListViewItem * item = 0;
278  if ( !key.isRoot() )
279  if ( KeyListViewItem * parent = itemByFingerprint( key.chainID() ) ) {
280  item = new KeyListViewItem( parent, key );
281  parent->setOpen( true );
282  }
283  if ( !item )
284  item = new KeyListViewItem( this, key ); // top-level (for now)
285 
286  d->itemMap.insert( std::make_pair( fpr, item ) );
287 }
288 
289 void Kleo::KeyListView::gatherScattered() {
290  KeyListViewItem * item = firstChild();
291  while ( item ) {
292  KeyListViewItem * cur = item;
293  item = item->nextSibling();
294  if ( cur->key().isRoot() )
295  continue;
296  if ( KeyListViewItem * parent = itemByFingerprint( cur->key().chainID() ) ) {
297  // found a new parent...
298  // ### todo: optimize by suppressing removing/adding the item to the itemMap...
299  takeItem( cur );
300  parent->insertItem( cur );
301  parent->setOpen( true );
302  }
303  }
304 }
305 
306 void Kleo::KeyListView::scatterGathered( TQListViewItem * start ) {
307  TQListViewItem * item = start;
308  while ( item ) {
309  TQListViewItem * cur = item;
310  item = item->nextSibling();
311 
312  scatterGathered( cur->firstChild() );
313  assert( cur->childCount() == 0 );
314 
315  // ### todo: optimize by suppressing removing/adding the item to the itemMap...
316  if ( cur->parent() )
317  cur->parent()->takeItem( cur );
318  else
319  takeItem( cur );
320  insertItem( cur );
321  }
322 }
323 
324 Kleo::KeyListViewItem * Kleo::KeyListView::itemByFingerprint( const TQCString & s ) const {
325  if ( s.isEmpty() )
326  return 0;
327  const std::map<TQCString,KeyListViewItem*>::const_iterator it = d->itemMap.find( s );
328  if ( it == d->itemMap.end() )
329  return 0;
330  return it->second;
331 }
332 
333 
334 void Kleo::KeyListView::slotRefreshKey( const GpgME::Key & key ) {
335  const char * fpr = key.primaryFingerprint();
336  if ( !fpr ) {
337  return;
338  }
339  if ( KeyListViewItem * item = itemByFingerprint( fpr ) ) {
340  item->setKey ( key );
341  }
342  else {
343  // none found -> add it
344  slotAddKey( key );
345  }
346 }
347 
348 // slots for the emission of covariant signals:
349 
350 void Kleo::KeyListView::slotEmitDoubleClicked( TQListViewItem * item, const TQPoint & p, int col ) {
351  if ( !item || lvi_cast<KeyListViewItem>( item ) )
352  emit doubleClicked( static_cast<KeyListViewItem*>( item ), p, col );
353 }
354 
355 void Kleo::KeyListView::slotEmitReturnPressed( TQListViewItem * item ) {
356  if ( !item || lvi_cast<KeyListViewItem>( item ) )
357  emit returnPressed( static_cast<KeyListViewItem*>( item ) );
358 }
359 
360 void Kleo::KeyListView::slotEmitSelectionChanged( TQListViewItem * item ) {
361  if ( !item || lvi_cast<KeyListViewItem>( item ) )
362  emit selectionChanged( static_cast<KeyListViewItem*>( item ) );
363 }
364 
365 void Kleo::KeyListView::slotEmitContextMenu( TDEListView*, TQListViewItem * item, const TQPoint & p ) {
366  if ( !item || lvi_cast<KeyListViewItem>( item ) )
367  emit contextMenu( static_cast<KeyListViewItem*>( item ), p );
368 }
369 
370 //
371 //
372 // KeyListViewItem
373 //
374 //
375 
376 Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, const GpgME::Key & key )
377  : TQListViewItem( parent )
378 {
379  setKey( key );
380 }
381 
382 Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Key & key )
383  : TQListViewItem( parent, after )
384 {
385  setKey( key );
386 }
387 
388 Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, const GpgME::Key & key )
389  : TQListViewItem( parent )
390 {
391  setKey( key );
392 }
393 
394 Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Key & key )
395  : TQListViewItem( parent, after )
396 {
397  setKey( key );
398 }
399 
400 Kleo::KeyListViewItem::~KeyListViewItem() {
401  // delete the children first... When children are deleted in the
402  // TQLVI dtor, they don't have listView() anymore, thus they don't
403  // call deregister( this ), leading to stale entries in the
404  // itemMap...
405  while ( TQListViewItem * item = firstChild() )
406  delete item;
407  // better do this here, too, since deletion is top-down and thus
408  // we're deleted when our parent item is no longer a
409  // KeyListViewItem, but a mere TQListViewItem, so our takeItem()
410  // overload is gone by that time...
411  if ( KeyListView * lv = listView() )
412  lv->deregisterItem( this );
413 }
414 
415 void Kleo::KeyListViewItem::setKey( const GpgME::Key & key ) {
416  KeyListView * lv = listView();
417  if ( lv )
418  lv->deregisterItem( this );
419  mKey = key;
420  if ( lv )
421  lv->registerItem( this );
422 
423  // the ColumnStrategy operations might be very slow, so cache their
424  // result here, where we're non-const :)
425  const Kleo::KeyListView::ColumnStrategy * cs = lv ? lv->columnStrategy() : 0 ;
426  if ( !cs )
427  return;
428  const int numCols = lv ? lv->columns() : 0 ;
429  for ( int i = 0 ; i < numCols ; ++i ) {
430  setText( i, cs->text( key, i ) );
431  if ( const TQPixmap * pix = cs->pixmap( key, i ) )
432  setPixmap( i, *pix );
433  }
434  repaint();
435 }
436 
437 TQString Kleo::KeyListViewItem::toolTip( int col ) const {
438  return listView() && listView()->columnStrategy()
439  ? listView()->columnStrategy()->toolTip( key(), col )
440  : TQString() ;
441 }
442 
443 int Kleo::KeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
444  if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
445  return TQListViewItem::compare( item, col, ascending );
446  KeyListViewItem * that = static_cast<KeyListViewItem*>( item );
447  return listView()->columnStrategy()->compare( this->key(), that->key(), col );
448 }
449 
450 void Kleo::KeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
451  const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
452  if ( !ds ) {
453  TQListViewItem::paintCell( p, cg, column, width, alignment );
454  return;
455  }
456  const TQColor fg = ds->keyForeground( key(), cg.text() );
457  const TQColor bg = ds->keyBackground( key(), cg.base() );
458  const TQFont f = ds->keyFont( key(), p->font() );
459 
460  TQColorGroup _cg = cg;
461  p->setFont( f );
462  _cg.setColor( TQColorGroup::Text, fg );
463  _cg.setColor( TQColorGroup::Base, bg );
464 
465  TQListViewItem::paintCell( p, _cg, column, width, alignment );
466 }
467 
468 void Kleo::KeyListViewItem::insertItem( TQListViewItem * qlvi ) {
469  //kdDebug() << "Kleo::KeyListViewItem::insertItem( " << qlvi << " )" << endl;
470  TQListViewItem::insertItem( qlvi );
471  if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
472  listView()->registerItem( item );
473 }
474 
475 void Kleo::KeyListViewItem::takeItem( TQListViewItem * qlvi ) {
476  //kdDebug() << "Kleo::KeyListViewItem::takeItem( " << qlvi << " )" << endl;
477  if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) )
478  listView()->deregisterItem( item );
479  TQListViewItem::takeItem( qlvi );
480 }
481 
482 
483 //
484 //
485 // SubkeyKeyListViewItem
486 //
487 //
488 
489 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, const GpgME::Subkey & subkey )
490  : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey )
491 {
492 
493 }
494 
495 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Subkey & subkey )
496  : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey )
497 {
498 
499 }
500 
501 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, const GpgME::Subkey & subkey )
502  : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey )
503 {
504 
505 }
506 
507 Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Subkey & subkey )
508  : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey )
509 {
510 
511 }
512 
513 void Kleo::SubkeyKeyListViewItem::setSubkey( const GpgME::Subkey & subkey ) {
514  mSubkey = subkey;
515  setKey( subkey.parent() );
516 }
517 
518 TQString Kleo::SubkeyKeyListViewItem::text( int col ) const {
519  return listView() && listView()->columnStrategy()
520  ? listView()->columnStrategy()->subkeyText( subkey(), col )
521  : TQString() ;
522 }
523 
524 TQString Kleo::SubkeyKeyListViewItem::toolTip( int col ) const {
525  return listView() && listView()->columnStrategy()
526  ? listView()->columnStrategy()->subkeyToolTip( subkey(), col )
527  : TQString() ;
528 }
529 
530 const TQPixmap * Kleo::SubkeyKeyListViewItem::pixmap( int col ) const {
531  return listView() && listView()->columnStrategy()
532  ? listView()->columnStrategy()->subkeyPixmap( subkey(), col ) : 0 ;
533 }
534 
535 int Kleo::SubkeyKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
536  if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
537  return KeyListViewItem::compare( item, col, ascending );
538  SubkeyKeyListViewItem * that = static_cast<SubkeyKeyListViewItem*>( item );
539  return listView()->columnStrategy()->subkeyCompare( this->subkey(), that->subkey(), col );
540 }
541 
542 void Kleo::SubkeyKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
543  const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
544  if ( !ds ) {
545  TQListViewItem::paintCell( p, cg, column, width, alignment );
546  return;
547  }
548  const TQColor fg = ds->subkeyForeground( subkey(), cg.text() );
549  const TQColor bg = ds->subkeyBackground( subkey(), cg.base() );
550  const TQFont f = ds->subkeyFont( subkey(), p->font() );
551 
552  TQColorGroup _cg = cg;
553  p->setFont( f );
554  _cg.setColor( TQColorGroup::Text, fg );
555  _cg.setColor( TQColorGroup::Base, bg );
556 
557  TQListViewItem::paintCell( p, _cg, column, width, alignment );
558 }
559 
560 
561 //
562 //
563 // UserIDKeyListViewItem
564 //
565 //
566 
567 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, const GpgME::UserID & userID )
568  : KeyListViewItem( parent, userID.parent() ), mUserID( userID )
569 {
570 
571 }
572 
573 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID & userID )
574  : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID )
575 {
576 
577 }
578 
579 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID & userID )
580  : KeyListViewItem( parent, userID.parent() ), mUserID( userID )
581 {
582 
583 }
584 
585 Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID & userID )
586  : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID )
587 {
588 
589 }
590 
591 void Kleo::UserIDKeyListViewItem::setUserID( const GpgME::UserID & userID ) {
592  mUserID = userID;
593  setKey( userID.parent() );
594 }
595 
596 TQString Kleo::UserIDKeyListViewItem::text( int col ) const {
597  return listView() && listView()->columnStrategy()
598  ? listView()->columnStrategy()->userIDText( userID(), col )
599  : TQString() ;
600 }
601 
602 TQString Kleo::UserIDKeyListViewItem::toolTip( int col ) const {
603  return listView() && listView()->columnStrategy()
604  ? listView()->columnStrategy()->userIDToolTip( userID(), col )
605  : TQString() ;
606 }
607 
608 const TQPixmap * Kleo::UserIDKeyListViewItem::pixmap( int col ) const {
609  return listView() && listView()->columnStrategy()
610  ? listView()->columnStrategy()->userIDPixmap( userID(), col ) : 0 ;
611 }
612 
613 int Kleo::UserIDKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
614  if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
615  return KeyListViewItem::compare( item, col, ascending );
616  UserIDKeyListViewItem * that = static_cast<UserIDKeyListViewItem*>( item );
617  return listView()->columnStrategy()->userIDCompare( this->userID(), that->userID(), col );
618 }
619 
620 
621 void Kleo::UserIDKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
622  const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
623  if ( !ds ) {
624  TQListViewItem::paintCell( p, cg, column, width, alignment );
625  return;
626  }
627  const TQColor fg = ds->useridForeground( userID(), cg.text() );
628  const TQColor bg = ds->useridBackground( userID(), cg.base() );
629  const TQFont f = ds->useridFont( userID(), p->font() );
630 
631  TQColorGroup _cg = cg;
632  p->setFont( f );
633  _cg.setColor( TQColorGroup::Text, fg );
634  _cg.setColor( TQColorGroup::Base, bg );
635 
636  TQListViewItem::paintCell( p, _cg, column, width, alignment );
637 }
638 
639 
640 //
641 //
642 // SignatureKeyListViewItem
643 //
644 //
645 
646 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, const GpgME::UserID::Signature & signature )
647  : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature )
648 {
649 
650 }
651 
652 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature )
653  : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature )
654 {
655 
656 }
657 
658 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID::Signature & signature )
659  : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature )
660 {
661 
662 }
663 
664 Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature )
665  : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature )
666 {
667 
668 }
669 
670 void Kleo::SignatureKeyListViewItem::setSignature( const GpgME::UserID::Signature & signature ) {
671  mSignature = signature;
672  setKey( signature.parent().parent() );
673 }
674 
675 TQString Kleo::SignatureKeyListViewItem::text( int col ) const {
676  return listView() && listView()->columnStrategy()
677  ? listView()->columnStrategy()->signatureText( signature(), col )
678  : TQString() ;
679 }
680 
681 TQString Kleo::SignatureKeyListViewItem::toolTip( int col ) const {
682  return listView() && listView()->columnStrategy()
683  ? listView()->columnStrategy()->signatureToolTip( signature(), col )
684  : TQString() ;
685 }
686 
687 const TQPixmap * Kleo::SignatureKeyListViewItem::pixmap( int col ) const {
688  return listView() && listView()->columnStrategy()
689  ? listView()->columnStrategy()->signaturePixmap( signature(), col ) : 0 ;
690 }
691 
692 int Kleo::SignatureKeyListViewItem::compare( TQListViewItem * item, int col, bool ascending ) const {
693  if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() )
694  return KeyListViewItem::compare( item, col, ascending );
695  SignatureKeyListViewItem * that = static_cast<SignatureKeyListViewItem*>( item );
696  return listView()->columnStrategy()->signatureCompare( this->signature(), that->signature(), col );
697 }
698 
699 void Kleo::SignatureKeyListViewItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int alignment ) {
700  const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ;
701  if ( !ds ) {
702  TQListViewItem::paintCell( p, cg, column, width, alignment );
703  return;
704  }
705  const TQColor fg = ds->signatureForeground( signature(), cg.text() );
706  const TQColor bg = ds->signatureBackground( signature(), cg.base() );
707  const TQFont f = ds->signatureFont( signature(), p->font() );
708 
709  TQColorGroup _cg = cg;
710  p->setFont( f );
711  _cg.setColor( TQColorGroup::Text, fg );
712  _cg.setColor( TQColorGroup::Base, bg );
713 
714  TQListViewItem::paintCell( p, _cg, column, width, alignment );
715 }
716 
717 
718 //
719 //
720 // ColumnStrategy
721 //
722 //
723 
724 Kleo::KeyListView::ColumnStrategy::~ColumnStrategy() {}
725 
726 int Kleo::KeyListView::ColumnStrategy::compare( const GpgME::Key & key1, const GpgME::Key & key2, int col ) const {
727  return TQString::localeAwareCompare( text( key1, col ), text( key2, col ) );
728 }
729 
730 int Kleo::KeyListView::ColumnStrategy::width( int col, const TQFontMetrics & fm ) const {
731  return fm.width( title( col ) ) * 2;
732 }
733 
734 int Kleo::KeyListView::ColumnStrategy::subkeyCompare( const GpgME::Subkey & sub1, const GpgME::Subkey & sub2, int col ) const {
735  return TQString::localeAwareCompare( subkeyText( sub1, col ), subkeyText( sub2, col ) );
736 }
737 
738 int Kleo::KeyListView::ColumnStrategy::userIDCompare( const GpgME::UserID & uid1, const GpgME::UserID & uid2, int col ) const {
739  return TQString::localeAwareCompare( userIDText( uid1, col ), userIDText( uid2, col ) );
740 }
741 
742 int Kleo::KeyListView::ColumnStrategy::signatureCompare( const GpgME::UserID::Signature & sig1, const GpgME::UserID::Signature & sig2, int col ) const {
743  return TQString::localeAwareCompare( signatureText( sig1, col ), signatureText( sig2, col ) );
744 }
745 
746 TQString Kleo::KeyListView::ColumnStrategy::toolTip( const GpgME::Key & key, int col ) const {
747  return text( key, col );
748 }
749 
750 TQString Kleo::KeyListView::ColumnStrategy::subkeyToolTip( const GpgME::Subkey & sub, int col ) const {
751  return subkeyText( sub, col );
752 }
753 
754 TQString Kleo::KeyListView::ColumnStrategy::userIDToolTip( const GpgME::UserID & uid, int col ) const {
755  return userIDText( uid, col );
756 }
757 
758 TQString Kleo::KeyListView::ColumnStrategy::signatureToolTip( const GpgME::UserID::Signature & sig, int col ) const {
759  return signatureText( sig, col );
760 }
761 
762 //
763 //
764 // DisplayStrategy
765 //
766 //
767 
768 Kleo::KeyListView::DisplayStrategy::~DisplayStrategy() {}
769 
770 
771 //font
772 TQFont Kleo::KeyListView::DisplayStrategy::keyFont( const GpgME::Key &, const TQFont & font ) const {
773  return font;
774 }
775 
776 TQFont Kleo::KeyListView::DisplayStrategy::subkeyFont( const GpgME::Subkey &, const TQFont & font ) const {
777  return font;
778 }
779 
780 TQFont Kleo::KeyListView::DisplayStrategy::useridFont( const GpgME::UserID &, const TQFont & font ) const {
781  return font;
782 }
783 
784 TQFont Kleo::KeyListView::DisplayStrategy::signatureFont( const GpgME::UserID::Signature &, const TQFont & font ) const {
785  return font;
786 }
787 
788 //foreground
789 TQColor Kleo::KeyListView::DisplayStrategy::keyForeground( const GpgME::Key &, const TQColor & fg )const {
790  return fg;
791 }
792 
793 TQColor Kleo::KeyListView::DisplayStrategy::subkeyForeground( const GpgME::Subkey &, const TQColor & fg ) const {
794  return fg;
795 }
796 
797 TQColor Kleo::KeyListView::DisplayStrategy::useridForeground( const GpgME::UserID &, const TQColor & fg ) const {
798  return fg;
799 }
800 
801 TQColor Kleo::KeyListView::DisplayStrategy::signatureForeground( const GpgME::UserID::Signature &, const TQColor & fg ) const {
802  return fg;
803 }
804 
805 //background
806 TQColor Kleo::KeyListView::DisplayStrategy::keyBackground( const GpgME::Key &, const TQColor & bg )const {
807  return bg;
808 }
809 
810 TQColor Kleo::KeyListView::DisplayStrategy::subkeyBackground( const GpgME::Subkey &, const TQColor & bg ) const {
811  return bg;
812 }
813 
814 TQColor Kleo::KeyListView::DisplayStrategy::useridBackground( const GpgME::UserID &, const TQColor & bg ) const {
815  return bg;
816 }
817 
818 TQColor Kleo::KeyListView::DisplayStrategy::signatureBackground( const GpgME::UserID::Signature &, const TQColor & bg ) const {
819  return bg;
820 }
821 
822 
823 //
824 //
825 // Collection of covariant return reimplementations of TQListView(Item)
826 // members:
827 //
828 //
829 
830 Kleo::KeyListView * Kleo::KeyListViewItem::listView() const {
831  return static_cast<Kleo::KeyListView*>( TQListViewItem::listView() );
832 }
833 
834 Kleo::KeyListViewItem * Kleo::KeyListViewItem::nextSibling() const {
835  return static_cast<Kleo::KeyListViewItem*>( TQListViewItem::nextSibling() );
836 }
837 
838 Kleo::KeyListViewItem * Kleo::KeyListView::firstChild() const {
839  return static_cast<Kleo::KeyListViewItem*>( TDEListView::firstChild() );
840 }
841 
842 Kleo::KeyListViewItem * Kleo::KeyListView::selectedItem() const {
843  return static_cast<Kleo::KeyListViewItem*>( TDEListView::selectedItem() );
844 }
845 
846 static void selectedItems( TQPtrList<Kleo::KeyListViewItem> & result, TQListViewItem * start ) {
847  for ( TQListViewItem * item = start ; item ; item = item->nextSibling() ) {
848  if ( item->isSelected() )
849  if ( Kleo::KeyListViewItem * i = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) )
850  result.append( i );
851  selectedItems( result, item->firstChild() );
852  }
853 }
854 
855 TQPtrList<Kleo::KeyListViewItem> Kleo::KeyListView::selectedItems() const {
856  TQPtrList<KeyListViewItem> result;
857  ::selectedItems( result, firstChild() );
858  return result;
859 }
860 
861 static bool hasSelection( TQListViewItem * start ) {
862  for ( TQListViewItem * item = start ; item ; item = item->nextSibling() )
863  if ( item->isSelected() || hasSelection( item->firstChild() ) )
864  return true;
865  return false;
866 }
867 
868 bool Kleo::KeyListView::hasSelection() const {
869  return ::hasSelection( firstChild() );
870 }
871 
872 #include "keylistview.moc"