kaddressbook

cardview.cpp
1 /*
2  This file is part of KAddressBook.
3  Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19  As a special exception, permission is given to link this program
20  with any edition of TQt, and distribute the resulting executable,
21  without including the source code for TQt in the source distribution.
22 */
23 
24 
25 #include <limits.h>
26 
27 #include <tqcursor.h>
28 #include <tqdatetime.h>
29 #include <tqlabel.h>
30 #include <tqpainter.h>
31 #include <tqstyle.h>
32 #include <tqtimer.h>
33 #include <tqtooltip.h>
34 
35 #include <kdebug.h>
36 #include <tdeglobalsettings.h>
37 
38 #include "cardview.h"
39 
40 #define MIN_ITEM_WIDTH 80
41 
42 class CardViewTip : public TQLabel
43 {
44  public:
45  CardViewTip( TQWidget *parent = 0, const char *name = 0 )
46  : TQLabel( parent, name )
47  {
48  setPalette( TQToolTip::palette() );
49  setFrameStyle( Panel | Plain );
50  setMidLineWidth( 0 );
51  setIndent( 1 );
52  }
53 
54  ~CardViewTip() {};
55 
56  protected:
57  void leaveEvent( TQEvent* )
58  {
59  hide();
60  }
61 };
62 
63 //
64 // Warning: make sure you use findRef() instead of find() to find an
65 // item! Only the pointer value is unique in the list.
66 //
67 class CardViewItemList : public TQPtrList<CardViewItem>
68 {
69  protected:
70  virtual int compareItems( TQPtrCollection::Item item1,
71  TQPtrCollection::Item item2 )
72  {
73  CardViewItem *cItem1 = (CardViewItem*)item1;
74  CardViewItem *cItem2 = (CardViewItem*)item2;
75 
76  if ( cItem1 == cItem2 )
77  return 0;
78 
79  if ( (cItem1 == 0) || (cItem2 == 0) )
80  return cItem1 ? -1 : 1;
81 
82  if ( cItem1->caption() < cItem2->caption() )
83  return -1;
84  else if ( cItem1->caption() > cItem2->caption() )
85  return 1;
86 
87  return 0;
88  }
89 };
90 
91 class CardViewSeparator
92 {
93  friend class CardView;
94 
95  public:
96  CardViewSeparator( CardView *view )
97  : mView( view )
98  {
99  mRect = TQRect( 0, 0, view->separatorWidth(), 0 );
100  }
101 
102  ~CardViewSeparator() {}
103 
104  void paintSeparator( TQPainter *p, TQColorGroup &cg )
105  {
106  p->fillRect( 0, 0, mRect.width(), mRect.height(),
107  cg.brush(TQColorGroup::Button) );
108  }
109 
110  void repaintSeparator()
111  {
112  mView->repaintContents( mRect );
113  }
114 
115  private:
116  CardView *mView;
117  TQRect mRect;
118 };
119 
120 class CardViewPrivate
121 {
122  public:
123  CardViewPrivate()
124  : mSelectionMode( CardView::Multi ),
125  mDrawCardBorder( true ),
126  mDrawFieldLabels( true ),
127  mDrawSeparators( true),
128  mSepWidth( 2 ),
129  mShowEmptyFields( false ),
130  mLayoutDirty( true ),
131  mLastClickOnItem( false ),
132  mItemMargin( 0 ),
133  mItemSpacing( 10 ),
134  mItemWidth( 200 ),
135  mMaxFieldLines( INT_MAX ),
136  mCurrentItem( 0L ),
137  mLastClickPos( TQPoint(0, 0) ),
138  mRubberBandAnchor( 0 ),
139  mCompText( TQString() )
140  {};
141 
142  CardViewItemList mItemList;
143  TQPtrList<CardViewSeparator> mSeparatorList;
144  TQFontMetrics *mFm;
145  TQFontMetrics *mBFm;
146  TQFont mHeaderFont;
147  CardView::SelectionMode mSelectionMode;
148  bool mDrawCardBorder;
149  bool mDrawFieldLabels;
150  bool mDrawSeparators;
151  int mSepWidth;
152  bool mShowEmptyFields;
153  bool mLayoutDirty;
154  bool mLastClickOnItem;
155  uint mItemMargin; // internal margin in items
156  uint mItemSpacing; // spacing between items, column seperators and border
157  int mItemWidth; // width of all items
158  uint mMaxFieldLines; // Max lines to dispaly pr field
159  CardViewItem *mCurrentItem;
160  TQPoint mLastClickPos;
161  TQTimer *mTimer; // times out if mouse rests for more than 500 msecs
162  CardViewTip *mTip; // passed to the item under a resting cursor to display full text
163  bool mOnSeparator; // set/reset on mouse movement
164  // for resizing by dragging the separators
165  int mResizeAnchor; // uint, ulong? the mouse down separator left
166  int mRubberBandAnchor; // for erasing rubber bands
167  // data used for resizing.
168  // as they are beeded by each mouse move while resizing, we store them here,
169  // saving 8 calculations in each mouse move.
170  int mColspace; // amount of space between items pr column
171  uint mFirst; // the first col to anchor at for painting rubber bands
172  int mFirstX; // X position of first in pixel
173  int mPressed; // the colummn that was pressed on at resizing start
174  int mSpan; // pressed - first
175  // key completion
176  TQString mCompText; // current completion string
177  TQDateTime mCompUpdated; // ...was updated at this time
178 };
179 
180 class CardViewItemPrivate
181 {
182  public:
183  CardViewItemPrivate() {}
184 
185  TQString mCaption;
186  TQPtrList< CardViewItem::Field > mFieldList;
187  bool mSelected;
188  int x; // horizontal position, set by the view
189  int y; // vertical position, set by the view
190  int maxLabelWidth; // the width of the widest label, according to the view font.
191  int hcache; // height cache
192 };
193 
194 
195 CardViewItem::CardViewItem( CardView *parent, const TQString &caption )
196  : d( new CardViewItemPrivate() ), mView( parent )
197 {
198  d->mCaption = caption;
199 
200  initialize();
201 }
202 
203 CardViewItem::~CardViewItem()
204 {
205  // Remove ourself from the view
206  if ( mView != 0 )
207  mView->takeItem( this );
208 
209  delete d;
210  d = 0;
211 }
212 
213 void CardViewItem::initialize()
214 {
215  d->mSelected = false;
216  d->mFieldList.setAutoDelete( true );
217  d->maxLabelWidth = 0;
218  d->hcache = 0;
219 
220  // Add ourself to the view
221  if ( mView != 0 )
222  mView->insertItem( this );
223 }
224 
225 void CardViewItem::paintCard( TQPainter *p, TQColorGroup &cg )
226 {
227  if ( !mView )
228  return;
229 
230  TQPen pen;
231  TQBrush brush;
232  TQFontMetrics fm = *(mView->d->mFm);
233  TQFontMetrics bFm = *(mView->d->mBFm);
234  bool drawLabels = mView->d->mDrawFieldLabels;
235  bool drawBorder = mView->d->mDrawCardBorder;
236  int mg = mView->itemMargin();
237  int w = mView->itemWidth() - ( mg * 2 );
238  int h = height() - ( mg * 2 );
239  const int colonWidth( fm.width( ":" ) );
240  int labelXPos = 2 + mg;
241  int labelWidth = TQMIN( w / 2 - 4 - mg, d->maxLabelWidth + colonWidth + 4 );
242  int valueXPos = labelWidth + 4 + mg;
243  int valueWidth = w - labelWidth - 4 - mg;
244 
245  p->setFont( mView->font() );
246  labelWidth -= colonWidth; // extra space for the colon
247 
248  if ( !drawLabels ) {
249  valueXPos = labelXPos;
250  valueWidth = w - 4;
251  }
252 
253  // Draw a simple box
254  if ( isSelected() )
255  pen = TQPen( cg.highlight(), 1 );
256  else
257  pen = TQPen( cg.button(), 1 );
258  p->setPen( pen );
259 
260  // Draw the border - this is only draw if the user asks for it.
261  if ( drawBorder )
262  p->drawRect( mg, mg, w, h );
263 
264  // set the proper pen color for the caption box
265  if ( isSelected() )
266  brush = cg.brush( TQColorGroup::Highlight );
267  else
268  brush = cg.brush( TQColorGroup::Button );
269 
270  p->fillRect( mg, mg, w, 4 + bFm.height(), brush );
271 
272  // Now paint the caption
273  p->save();
274  TQFont bFont = mView->headerFont();
275  p->setFont( bFont );
276  if ( isSelected() )
277  p->setPen( cg.highlightedText() );
278  else
279  p->setPen( cg.buttonText() );
280 
281  p->drawText( 2 + mg, 2 + mg + bFm.ascent(), trimString( d->mCaption, w - 4, bFm ) );
282  p->restore();
283 
284  // Go through the fields and draw them
285  TQPtrListIterator<CardViewItem::Field> iter( d->mFieldList );
286  TQString label, value;
287  int yPos = mg + 4 + bFm.height() + fm.height();
288  p->setPen( cg.text() );
289 
290  int fh = fm.height();
291  int cln( 0 );
292  TQString tmp;
293  int maxLines = mView->maxFieldLines();
294  for ( iter.toFirst(); iter.current(); ++iter ) {
295  value = (*iter)->second;
296  if ( value.isEmpty() && ! mView->d->mShowEmptyFields )
297  continue;
298 
299  if ( drawLabels ) {
300  label = trimString( (*iter)->first, labelWidth, fm );
301  p->drawText( labelXPos, yPos, label + ":" );
302  }
303 
304  for ( cln = 0; cln <= maxLines; cln++ ) {
305  tmp = value.section( '\n', cln, cln );
306  if ( !tmp.isEmpty() )
307  p->drawText( valueXPos, yPos + cln * fh, trimString( tmp, valueWidth, fm ) );
308  else
309  break;
310  }
311 
312  if ( cln == 0 )
313  cln = 1;
314  yPos += cln * fh + 2;
315  }
316 
317  // if we are the current item and the view has focus, draw focus rect
318  if ( mView->currentItem() == this && mView->hasFocus() ) {
319  mView->style().drawPrimitive( TQStyle::PE_FocusRect, p,
320  TQRect( 0, 0, mView->itemWidth(), h + (2 * mg) ), cg,
321  TQStyle::Style_FocusAtBorder,
322  TQStyleOption( isSelected() ? cg.highlight() : cg.base() ) );
323  }
324 }
325 
326 const TQString &CardViewItem::caption() const
327 {
328  return d->mCaption;
329 }
330 
331 
332 int CardViewItem::height( bool allowCache ) const
333 {
334  // use cache
335  if ( allowCache && d->hcache )
336  return d->hcache;
337 
338  // Base height:
339  // 2 for line width
340  // 2 for top caption pad
341  // 2 for bottom caption pad
342  // 2 pad for the end
343  // + 2 times the advised margin
344  int baseHeight = 8 + ( 2 * mView->itemMargin() );
345 
346  // size of font for each field
347  // 2 pad for each field
348 
349  bool sef = mView->showEmptyFields();
350  int fh = mView->d->mFm->height();
351  int fieldHeight = 0;
352  int lines;
353  int maxLines( mView->maxFieldLines() );
354  TQPtrListIterator<CardViewItem::Field> iter( d->mFieldList );
355  for ( iter.toFirst(); iter.current(); ++iter ) {
356  if ( !sef && (*iter)->second.isEmpty() )
357  continue;
358  lines = TQMIN( (*iter)->second.contains( '\n' ) + 1, maxLines );
359  fieldHeight += ( lines * fh ) + 2;
360  }
361 
362  // height of caption font (bold)
363  fieldHeight += mView->d->mBFm->height();
364  d->hcache = baseHeight + fieldHeight;
365  return d->hcache;
366 }
367 
369 {
370  return d->mSelected;
371 }
372 
373 void CardViewItem::setSelected( bool selected )
374 {
375  d->mSelected = selected;
376 }
377 
378 void CardViewItem::insertField( const TQString &label, const TQString &value )
379 {
380  CardViewItem::Field *f = new CardViewItem::Field( label, value );
381  d->mFieldList.append( f );
382  d->hcache = 0;
383 
384  if ( mView ) {
385  mView->setLayoutDirty( true );
386  d->maxLabelWidth = TQMAX( mView->d->mFm->width( label ), d->maxLabelWidth );
387  }
388 }
389 
390 void CardViewItem::removeField( const TQString &label )
391 {
393 
394  TQPtrListIterator<CardViewItem::Field> iter( d->mFieldList );
395  for ( iter.toFirst(); iter.current(); ++iter ) {
396  f = *iter;
397  if ( f->first == label )
398  break;
399  }
400 
401  if (*iter)
402  d->mFieldList.remove( *iter );
403  d->hcache = 0;
404 
405  if ( mView )
406  mView->setLayoutDirty( true );
407 }
408 
410 {
411  d->mFieldList.clear();
412  d->hcache = 0;
413 
414  if ( mView )
415  mView->setLayoutDirty( true );
416 }
417 
418 TQString CardViewItem::trimString( const TQString &text, int width,
419  TQFontMetrics &fm ) const
420 {
421  if ( fm.width( text ) <= width )
422  return text;
423 
424  TQString dots = "...";
425  int dotWidth = fm.width( dots );
426  TQString trimmed;
427  int charNum = 0;
428 
429  while ( fm.width( trimmed ) + dotWidth < width ) {
430  trimmed += text[ charNum ];
431  charNum++;
432  }
433 
434  // Now trim the last char, since it put the width over the top
435  trimmed = trimmed.left( trimmed.length() - 1 );
436  trimmed += dots;
437 
438  return trimmed;
439 }
440 
442 {
443  CardViewItem *item = 0;
444 
445  if ( mView )
446  item = mView->itemAfter( this );
447 
448  return item;
449 }
450 
452 {
453  if ( mView )
454  mView->repaintItem( this );
455 }
456 
457 void CardViewItem::setCaption( const TQString &caption )
458 {
459  d->mCaption = caption;
460  repaintCard();
461 }
462 
463 TQString CardViewItem::fieldValue( const TQString &label ) const
464 {
465  TQPtrListIterator<CardViewItem::Field> iter( d->mFieldList );
466  for ( iter.toFirst(); iter.current(); ++iter )
467  if ( (*iter)->first == label )
468  return (*iter)->second;
469 
470  return TQString();
471 }
472 
473 
474 void CardViewItem::showFullString( const TQPoint &itempos, CardViewTip *tip )
475 {
476  bool trimmed( false );
477  TQString s;
478  int mrg = mView->itemMargin();
479  int y = mView->d->mBFm->height() + 6 + mrg;
480  int w = mView->itemWidth() - (2 * mrg);
481  int lw;
482  bool drawLabels = mView->drawFieldLabels();
483  bool isLabel = drawLabels && itempos.x() < w / 2 ? true : false;
484 
485  if ( itempos.y() < y ) {
486  if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 )
487  return;
488  // this is the caption
489  s = caption();
490  trimmed = mView->d->mBFm->width( s ) > w - 4;
491  y = 2 + mrg;
492  lw = 0;
493  isLabel = true;
494  } else {
495  // find the field
496  Field *f = fieldAt( itempos );
497  if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) )
498  return;
499 
500  // y position:
501  // header font height + 4px hader margin + 2px leading + item margin
502  // + actual field index * (fontheight + 2px leading)
503  int maxLines = mView->maxFieldLines();
504  bool se = mView->showEmptyFields();
505  int fh = mView->d->mFm->height();
506 
507  Field *_f;
508  for ( _f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next() )
509  if ( se || ! _f->second.isEmpty() )
510  y += ( TQMIN( _f->second.contains( '\n' ) + 1, maxLines ) * fh ) + 2;
511 
512  if ( isLabel && itempos.y() > y + fh )
513  return;
514 
515  s = isLabel ? f->first : f->second;
516 
517  int colonWidth = mView->d->mFm->width(":");
518  lw = drawLabels ? TQMIN( w / 2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) : 0;
519  int mw = isLabel ? lw - colonWidth : w - lw - ( mrg * 2 );
520  if ( isLabel ) {
521  trimmed = mView->d->mFm->width( s ) > mw - colonWidth;
522  } else {
523  TQRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, TQt::AlignTop|TQt::AlignLeft, s ) );
524  trimmed = r.width() > mw || r.height() / fh > TQMIN( s.contains( '\n' ) + 1, maxLines );
525  }
526  }
527 
528  if ( trimmed ) {
529  tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() );
530  tip->setText( s );
531  tip->adjustSize();
532  // find a proper position
533  int lx;
534  lx = isLabel || !drawLabels ? mrg : lw + mrg + 2;
535  TQPoint pnt( mView->contentsToViewport( TQPoint( d->x, d->y ) ) );
536  pnt += TQPoint( lx, y );
537  if ( pnt.x() < 0 )
538  pnt.setX( 0 );
539  if ( pnt.x() + tip->width() > mView->visibleWidth() )
540  pnt.setX( mView->visibleWidth() - tip->width() );
541  if ( pnt.y() + tip->height() > mView->visibleHeight() )
542  pnt.setY( TQMAX( 0, mView->visibleHeight() - tip->height() ) );
543  // show
544  tip->move( pnt );
545  tip->show();
546  }
547 }
548 
549 CardViewItem::Field *CardViewItem::fieldAt( const TQPoint & itempos ) const
550 {
551  int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin;
552  int iy = itempos.y();
553  // skip below caption
554  if ( iy <= ypos )
555  return 0;
556  // try find a field
557  bool showEmpty = mView->showEmptyFields();
558  int fh = mView->d->mFm->height();
559  int maxLines = mView->maxFieldLines();
560  Field *f;
561  for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() ) {
562  if ( showEmpty || !f->second.isEmpty() )
563  ypos += (TQMIN( f->second.contains( '\n' )+1, maxLines ) * fh) + 2;
564  if ( iy <= ypos )
565  break;
566  }
567 
568  return f ? f : 0;
569 }
570 
571 
572 CardView::CardView( TQWidget *parent, const char *name )
573  : TQScrollView( parent, name ),
574  d( new CardViewPrivate() )
575 {
576  d->mItemList.setAutoDelete( true );
577  d->mSeparatorList.setAutoDelete( true );
578 
579  TQFont f = font();
580  d->mFm = new TQFontMetrics( f );
581  f.setBold( true );
582  d->mHeaderFont = f;
583  d->mBFm = new TQFontMetrics( f );
584  d->mTip = new CardViewTip( viewport() );
585  d->mTip->hide();
586  d->mTimer = new TQTimer( this, "mouseTimer" );
587 
588  viewport()->setMouseTracking( true );
589  viewport()->setFocusProxy( this );
590  viewport()->setFocusPolicy(TQWidget::WheelFocus );
591  viewport()->setBackgroundMode( PaletteBase );
592 
593  connect( d->mTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( tryShowFullText() ) );
594 
595  setBackgroundMode( PaletteBackground, PaletteBase );
596 
597  // no reason for a vertical scrollbar
598  setVScrollBarMode( AlwaysOff );
599 }
600 
601 CardView::~CardView()
602 {
603  delete d->mFm;
604  delete d->mBFm;
605  delete d;
606  d = 0;
607 }
608 
610 {
611  d->mItemList.inSort( item );
612  setLayoutDirty( true );
613 }
614 
616 {
617  if ( d->mCurrentItem == item )
618  d->mCurrentItem = item->nextItem();
619  d->mItemList.take( d->mItemList.findRef( item ) );
620 
621  setLayoutDirty( true );
622 }
623 
625 {
626  d->mItemList.clear();
627 
628  setLayoutDirty( true );
629 }
630 
632 {
633  if ( !d->mCurrentItem && d->mItemList.count() )
634  d->mCurrentItem = d->mItemList.first();
635 
636  return d->mCurrentItem;
637 }
638 
640 {
641  if ( !item )
642  return;
643  else if ( item->cardView() != this ) {
644  kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl;
645  return;
646  } else if ( item == currentItem() ) {
647  return;
648  }
649 
650  if ( d->mSelectionMode == Single ) {
651  setSelected( item, true );
652  } else {
653  CardViewItem *it = d->mCurrentItem;
654  d->mCurrentItem = item;
655  if ( it )
656  it->repaintCard();
657 
658  item->repaintCard();
659  }
660 
661  if ( ! d->mOnSeparator )
662  ensureItemVisible( item );
663 
664  emit currentChanged( item );
665 }
666 
667 CardViewItem *CardView::itemAt( const TQPoint &viewPos ) const
668 {
669  CardViewItem *item = 0;
670  TQPtrListIterator<CardViewItem> iter( d->mItemList );
671  bool found = false;
672  for ( iter.toFirst(); iter.current() && !found; ++iter ) {
673  item = *iter;
674  if ( TQRect( item->d->x, item->d->y, d->mItemWidth, item->height() ).contains( viewPos ) )
675  found = true;
676  }
677 
678  if ( found )
679  return item;
680 
681  return 0;
682 }
683 
684 TQRect CardView::itemRect( const CardViewItem *item ) const
685 {
686  return TQRect( item->d->x, item->d->y, d->mItemWidth, item->height() );
687 }
688 
690 {
691  ensureVisible( item->d->x, item->d->y, d->mItemSpacing, 0 );
692  ensureVisible( item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0 );
693 }
694 
696 {
697  repaintContents( TQRect( item->d->x, item->d->y, d->mItemWidth, item->height() ) );
698 }
699 
700 void CardView::setSelectionMode( CardView::SelectionMode mode )
701 {
702  selectAll( false );
703 
704  d->mSelectionMode = mode;
705 }
706 
707 CardView::SelectionMode CardView::selectionMode() const
708 {
709  return d->mSelectionMode;
710 }
711 
712 void CardView::selectAll( bool state )
713 {
714  TQPtrListIterator<CardViewItem> iter( d->mItemList );
715  if ( !state ) {
716  for ( iter.toFirst(); iter.current(); ++iter ) {
717  if ( (*iter)->isSelected() ) {
718  (*iter)->setSelected( false );
719  (*iter)->repaintCard();
720  }
721  }
722 
723  emit selectionChanged( 0 );
724  } else if ( d->mSelectionMode != CardView::Single ) {
725  for ( iter.toFirst(); iter.current(); ++iter ) {
726  (*iter)->setSelected( true );
727  }
728 
729  if ( d->mItemList.count() > 0 ) {
730  // emit, since there must have been at least one selected
731  emit selectionChanged();
732  viewport()->update();
733  }
734  }
735 }
736 
737 void CardView::setSelected( CardViewItem *item, bool selected )
738 {
739  if ( (item == 0) || (item->isSelected() == selected) )
740  return;
741 
742  if ( selected && d->mCurrentItem != item ) {
743  CardViewItem *it = d->mCurrentItem;
744  d->mCurrentItem = item;
745  if ( it )
746  it->repaintCard();
747  }
748 
749  if ( d->mSelectionMode == CardView::Single ) {
750  bool b = signalsBlocked();
751  blockSignals( true );
752  selectAll( false );
753  blockSignals( b );
754 
755  if ( selected ) {
756  item->setSelected( selected );
757  item->repaintCard();
758  emit selectionChanged();
759  emit selectionChanged( item );
760  } else {
761  emit selectionChanged();
762  emit selectionChanged( 0 );
763  }
764  } else if ( d->mSelectionMode == CardView::Multi ) {
765  item->setSelected( selected );
766  item->repaintCard();
767  emit selectionChanged();
768  } else if ( d->mSelectionMode == CardView::Extended ) {
769  bool b = signalsBlocked();
770  blockSignals( true );
771  selectAll( false );
772  blockSignals( b );
773 
774  item->setSelected( selected );
775  item->repaintCard();
776  emit selectionChanged();
777  }
778 }
779 
781 {
782  return (item && item->isSelected());
783 }
784 
786 {
787  // find the first selected item
788  TQPtrListIterator<CardViewItem> iter( d->mItemList );
789  for ( iter.toFirst(); iter.current(); ++iter ) {
790  if ( (*iter)->isSelected() )
791  return *iter;
792  }
793 
794  return 0;
795 }
796 
798 {
799  return d->mItemList.first();
800 }
801 
803 {
804  return d->mItemList.count();
805 }
806 
807 CardViewItem *CardView::findItem( const TQString &text, const TQString &label,
808  TQt::StringComparisonMode compare ) const
809 {
810  // If the text is empty, we will return null, since empty text will
811  // match anything!
812  if ( text.isEmpty() )
813  return 0;
814 
815  TQPtrListIterator<CardViewItem> iter( d->mItemList );
816  if ( compare & TQt::BeginsWith ) {
817  TQString value;
818  for ( iter.toFirst(); iter.current(); ++iter ) {
819  value = (*iter)->fieldValue( label ).upper();
820  if ( value.startsWith( text.upper() ) )
821  return *iter;
822  }
823  } else {
824  kdDebug(5720) << "CardView::findItem: search method not implemented" << endl;
825  }
826 
827  return 0;
828 }
829 
831 {
832  return d->mDrawSeparators ?
833  d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth :
834  d->mItemWidth + d->mItemSpacing;
835 }
836 
837 void CardView::drawContents( TQPainter *p, int clipx, int clipy,
838  int clipw, int cliph )
839 {
840  TQScrollView::drawContents( p, clipx, clipy, clipw, cliph );
841 
842  if ( d->mLayoutDirty )
843  calcLayout();
844 
845  // allow setting costum colors in the viewport pale
846  TQColorGroup cg = viewport()->palette().active();
847 
848  TQRect clipRect( clipx, clipy, clipw, cliph );
849  TQRect cardRect;
850  TQRect sepRect;
851  CardViewItem *item;
852  CardViewSeparator *sep;
853 
854  // make sure the viewport is a pure background
855  viewport()->erase( clipRect );
856 
857  // Now tell the cards to draw, if they are in the clip region
858  TQPtrListIterator<CardViewItem> iter( d->mItemList );
859  for ( iter.toFirst(); iter.current(); ++iter) {
860  item = *iter;
861  cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() );
862 
863  if ( clipRect.intersects( cardRect ) || clipRect.contains( cardRect ) ) {
864  // Tell the card to paint
865  p->save();
866  p->translate( cardRect.x(), cardRect.y() );
867  item->paintCard( p, cg );
868  p->restore();
869  }
870  }
871 
872  // Followed by the separators if they are in the clip region
873  TQPtrListIterator<CardViewSeparator> sepIter( d->mSeparatorList );
874  for ( sepIter.toFirst(); sepIter.current(); ++sepIter ) {
875  sep = *sepIter;
876  sepRect = sep->mRect;
877 
878  if ( clipRect.intersects( sepRect ) || clipRect.contains( sepRect ) ) {
879  p->save();
880  p->translate( sepRect.x(), sepRect.y() );
881  sep->paintSeparator( p, cg );
882  p->restore();
883  }
884  }
885 }
886 
887 void CardView::resizeEvent( TQResizeEvent *event )
888 {
889  TQScrollView::resizeEvent( event );
890 
891  setLayoutDirty( true );
892 }
893 
895 {
896  // Start in the upper left corner and layout all the
897  // cars using their height and width
898  int maxWidth = 0;
899  int maxHeight = 0;
900  int xPos = 0;
901  int yPos = 0;
902  int cardSpacing = d->mItemSpacing;
903 
904  // delete the old separators
905  d->mSeparatorList.clear();
906 
907  TQPtrListIterator<CardViewItem> iter( d->mItemList );
908  CardViewItem *item = 0;
909  CardViewSeparator *sep = 0;
910  xPos += cardSpacing;
911 
912  for ( iter.toFirst(); iter.current(); ++iter ) {
913  item = *iter;
914 
915  yPos += cardSpacing;
916 
917  if ( yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height() ) {
918  maxHeight = TQMAX( maxHeight, yPos );
919 
920  // Drawing in this column would be greater than the height
921  // of the scroll view, so move to next column
922  yPos = cardSpacing;
923  xPos += cardSpacing + maxWidth;
924  if ( d->mDrawSeparators ) {
925  // Create a separator since the user asked
926  sep = new CardViewSeparator( this );
927  sep->mRect.moveTopLeft( TQPoint( xPos, yPos + d->mItemMargin ) );
928  xPos += d->mSepWidth + cardSpacing;
929  d->mSeparatorList.append( sep );
930  }
931 
932  maxWidth = 0;
933  }
934 
935  item->d->x = xPos;
936  item->d->y = yPos;
937 
938  yPos += item->height();
939  maxWidth = TQMAX( maxWidth, d->mItemWidth );
940  }
941 
942  xPos += maxWidth;
943  resizeContents( xPos + cardSpacing, maxHeight );
944 
945  // Update the height of all the separators now that we know the
946  // max height of a column
947  TQPtrListIterator<CardViewSeparator> sepIter( d->mSeparatorList );
948  for ( sepIter.toFirst(); sepIter.current(); ++sepIter )
949  (*sepIter)->mRect.setHeight( maxHeight - 2 * cardSpacing - 2 * d->mItemMargin );
950 
951  d->mLayoutDirty = false;
952 }
953 
955 {
956  d->mItemList.findRef( item );
957  return d->mItemList.next();
958 }
959 
961 {
962  return d->mItemMargin;
963 }
964 
965 void CardView::setItemMargin( uint margin )
966 {
967  if ( margin == d->mItemMargin )
968  return;
969 
970  d->mItemMargin = margin;
971  setLayoutDirty( true );
972 }
973 
975 {
976  return d->mItemSpacing;
977 }
978 
979 void CardView::setItemSpacing( uint spacing )
980 {
981  if ( spacing == d->mItemSpacing )
982  return;
983 
984  d->mItemSpacing = spacing;
985  setLayoutDirty( true );
986 }
987 
988 void CardView::contentsMousePressEvent( TQMouseEvent *e )
989 {
990  TQScrollView::contentsMousePressEvent( e );
991 
992  TQPoint pos = contentsToViewport( e->pos() );
993  d->mLastClickPos = e->pos();
994 
995  CardViewItem *item = itemAt( e->pos() );
996 
997  if ( item == 0 ) {
998  d->mLastClickOnItem = false;
999  if ( d->mOnSeparator) {
1000  d->mResizeAnchor = e->x() + contentsX();
1001  d->mColspace = (2 * d->mItemSpacing);
1002  int ccw = d->mItemWidth + d->mColspace + d->mSepWidth;
1003  d->mFirst = (contentsX() + d->mSepWidth) / ccw;
1004  d->mPressed = (d->mResizeAnchor + d->mSepWidth) / ccw;
1005  d->mSpan = d->mPressed - d->mFirst;
1006  d->mFirstX = d->mFirst * ccw;
1007  if ( d->mFirstX )
1008  d->mFirstX -= d->mSepWidth;
1009  } else {
1010  selectAll( false );
1011  }
1012 
1013  return;
1014  }
1015 
1016  d->mLastClickOnItem = true;
1017 
1018  CardViewItem *other = d->mCurrentItem;
1019  setCurrentItem( item );
1020 
1021  // Always emit the selection
1022  emit clicked( item );
1023 
1024  // The RMB click
1025  if ( e->button() & TQt::RightButton ) {
1026  // clear previous selection
1027  bool blocked = signalsBlocked();
1028  blockSignals( true );
1029  selectAll( false );
1030  blockSignals( blocked );
1031 
1032  // select current item
1033  item->setSelected( true );
1034 
1035  emit contextMenuRequested( item, mapToGlobal( pos ) );
1036  return;
1037  }
1038 
1039  // Check the selection type and update accordingly
1040  if ( d->mSelectionMode == CardView::Single ) {
1041  // make sure it isn't already selected
1042  if ( item->isSelected() )
1043  return;
1044 
1045  bool b = signalsBlocked();
1046  blockSignals( true );
1047  selectAll( false );
1048  blockSignals( b );
1049 
1050  item->setSelected( true );
1051  item->repaintCard();
1052  emit selectionChanged( item );
1053  } else if ( d->mSelectionMode == CardView::Multi ) {
1054  // toggle the selection
1055  item->setSelected( !item->isSelected() );
1056  item->repaintCard();
1057  emit selectionChanged();
1058  } else if ( d->mSelectionMode == CardView::Extended ) {
1059  if ( (e->button() & TQt::LeftButton) && (e->state() & TQt::ShiftButton) ) {
1060  if ( item == other )
1061  return;
1062 
1063  bool s = !item->isSelected();
1064 
1065  if ( s && !(e->state() & ControlButton) ) {
1066  bool b = signalsBlocked();
1067  blockSignals( true );
1068  selectAll( false );
1069  blockSignals( b );
1070  }
1071 
1072  int from, to, a, b;
1073  a = d->mItemList.findRef( item );
1074  b = d->mItemList.findRef( other );
1075  from = a < b ? a : b;
1076  to = a > b ? a : b;
1077 
1078  CardViewItem *aItem;
1079  for ( ; from <= to; from++ ) {
1080  aItem = d->mItemList.at( from );
1081  aItem->setSelected( s );
1082  repaintItem( aItem );
1083  }
1084 
1085  emit selectionChanged();
1086  } else if ( (e->button() & TQt::LeftButton) && (e->state() & TQt::ControlButton) ) {
1087  item->setSelected( !item->isSelected() );
1088  item->repaintCard();
1089  emit selectionChanged();
1090  } else if ( e->button() & TQt::LeftButton ) {
1091  bool b = signalsBlocked();
1092  blockSignals( true );
1093  selectAll( false );
1094  blockSignals( b );
1095 
1096  item->setSelected( true );
1097  item->repaintCard();
1098  emit selectionChanged();
1099  }
1100  }
1101 }
1102 
1103 void CardView::contentsMouseReleaseEvent( TQMouseEvent *e )
1104 {
1105  TQScrollView::contentsMouseReleaseEvent( e );
1106 
1107  if ( d->mResizeAnchor && d->mSpan ) {
1108  unsetCursor();
1109  // hide rubber bands
1110  int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor) / d->mSpan);
1111  drawRubberBands( 0 );
1112  // we should move to reflect the new position if we are scrolled.
1113  if ( contentsX() ) {
1114  int newX = TQMAX( 0, ( d->mPressed * ( newiw + d->mColspace + d->mSepWidth ) ) - e->x() );
1115  setContentsPos( newX, contentsY() );
1116  }
1117  // set new item width
1118  setItemWidth( newiw );
1119  // reset anchors
1120  d->mResizeAnchor = 0;
1121  d->mRubberBandAnchor = 0;
1122  return;
1123  }
1124 
1125  // If there are accel keys, we will not emit signals
1126  if ( (e->state() & TQt::ShiftButton) || (e->state() & TQt::ControlButton) )
1127  return;
1128 
1129  // Get the item at this position
1130  CardViewItem *item = itemAt( e->pos() );
1131 
1132  if ( item && TDEGlobalSettings::singleClick() )
1133  emit executed( item );
1134 }
1135 
1136 void CardView::contentsMouseDoubleClickEvent( TQMouseEvent *e )
1137 {
1138  TQScrollView::contentsMouseDoubleClickEvent( e );
1139 
1140  CardViewItem *item = itemAt( e->pos() );
1141 
1142  if ( item )
1143  d->mCurrentItem = item;
1144 
1145  if ( item && !TDEGlobalSettings::singleClick() )
1146  emit executed(item);
1147 
1148  emit doubleClicked( item );
1149 }
1150 
1151 void CardView::contentsMouseMoveEvent( TQMouseEvent *e )
1152 {
1153  // resizing
1154  if ( d->mResizeAnchor ) {
1155  int x = e->x();
1156  if ( x != d->mRubberBandAnchor )
1157  drawRubberBands( x );
1158  return;
1159  }
1160 
1161  if ( d->mLastClickOnItem && (e->state() & TQt::LeftButton) &&
1162  ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) {
1163 
1164  startDrag();
1165  return;
1166  }
1167 
1168  d->mTimer->start( 500 );
1169 
1170  // see if we are over a separator
1171  // only if we actually have them painted?
1172  if ( d->mDrawSeparators ) {
1173  int colcontentw = d->mItemWidth + (2 * d->mItemSpacing);
1174  int colw = colcontentw + d->mSepWidth;
1175  int m = e->x() % colw;
1176  if ( m >= colcontentw && m > 0 ) {
1177  setCursor( SplitHCursor );
1178  d->mOnSeparator = true;
1179  } else {
1180  setCursor( ArrowCursor );
1181  d->mOnSeparator = false;
1182  }
1183  }
1184 }
1185 
1186 void CardView::enterEvent( TQEvent* )
1187 {
1188  d->mTimer->start( 500 );
1189 }
1190 
1191 void CardView::leaveEvent( TQEvent* )
1192 {
1193  d->mTimer->stop();
1194  if ( d->mOnSeparator ) {
1195  d->mOnSeparator = false;
1196  setCursor( ArrowCursor );
1197  }
1198 }
1199 
1200 void CardView::focusInEvent( TQFocusEvent* )
1201 {
1202  if ( !d->mCurrentItem && d->mItemList.count() )
1203  setCurrentItem( d->mItemList.first() );
1204  else if ( d->mCurrentItem )
1205  d->mCurrentItem->repaintCard();
1206 }
1207 
1208 void CardView::focusOutEvent( TQFocusEvent* )
1209 {
1210  if ( d->mCurrentItem )
1211  d->mCurrentItem->repaintCard();
1212 }
1213 
1214 void CardView::keyPressEvent( TQKeyEvent *e )
1215 {
1216  if ( !(childCount() && d->mCurrentItem) ) {
1217  e->ignore();
1218  return;
1219  }
1220 
1221  uint pos = d->mItemList.findRef( d->mCurrentItem );
1222  CardViewItem *aItem = 0;
1223  CardViewItem *old = d->mCurrentItem;
1224 
1225  switch ( e->key() ) {
1226  case Key_Up:
1227  if ( pos > 0 ) {
1228  aItem = d->mItemList.at( pos - 1 );
1229  setCurrentItem( aItem );
1230  }
1231  break;
1232  case Key_Down:
1233  if ( pos < d->mItemList.count() - 1 ) {
1234  aItem = d->mItemList.at( pos + 1 );
1235  setCurrentItem( aItem );
1236  }
1237  break;
1238  case Key_Left:
1239  {
1240  // look for an item in the previous/next column, starting from
1241  // the vertical middle of the current item.
1242  // FIXME use nice calculatd measures!!!
1243  TQPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y );
1244  aPoint -= TQPoint( 30, -(d->mCurrentItem->height() / 2) );
1245  aItem = itemAt( aPoint );
1246  // maybe we hit some space below an item
1247  while ( !aItem && aPoint.y() > 27 ) {
1248  aPoint -= TQPoint( 0, 16 );
1249  aItem = itemAt( aPoint );
1250  }
1251  if ( aItem )
1252  setCurrentItem( aItem );
1253 
1254  break;
1255  }
1256  case Key_Right:
1257  {
1258  // FIXME use nice calculated measures!!!
1259  TQPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y );
1260  aPoint += TQPoint( 30, (d->mCurrentItem->height() / 2) );
1261  aItem = itemAt( aPoint );
1262  while ( !aItem && aPoint.y() > 27 ) {
1263  aPoint -= TQPoint( 0, 16 );
1264  aItem = itemAt( aPoint );
1265  }
1266  if ( aItem )
1267  setCurrentItem( aItem );
1268 
1269  break;
1270  }
1271  case Key_Home:
1272  aItem = d->mItemList.first();
1273  setCurrentItem( aItem );
1274  break;
1275  case Key_End:
1276  aItem = d->mItemList.last();
1277  setCurrentItem( aItem );
1278  break;
1279  case Key_Prior: // PageUp
1280  {
1281  // TQListView: "Make the item above the top visible and current"
1282  // TODO if contentsY(), pick the top item of the leftmost visible column
1283  if ( contentsX() <= 0 )
1284  return;
1285  int cw = columnWidth();
1286  int theCol = ( TQMAX( 0, ( contentsX() / cw) * cw ) ) + d->mItemSpacing;
1287  aItem = itemAt( TQPoint( theCol + 1, d->mItemSpacing + 1 ) );
1288  if ( aItem )
1289  setCurrentItem( aItem );
1290 
1291  break;
1292  }
1293  case Key_Next: // PageDown
1294  {
1295  // TQListView: "Make the item below the bottom visible and current"
1296  // find the first not fully visible column.
1297  // TODO: consider if a partly visible (or even hidden) item at the
1298  // bottom of the rightmost column exists
1299  int cw = columnWidth();
1300  int theCol = ( (( contentsX() + visibleWidth() ) / cw) * cw ) + d->mItemSpacing + 1;
1301  // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden
1302  if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() ) % cw) <= int( d->mItemSpacing + d->mSepWidth ) )
1303  theCol += cw;
1304 
1305  // make sure this is not too far right
1306  while ( theCol > contentsWidth() )
1307  theCol -= columnWidth();
1308 
1309  aItem = itemAt( TQPoint( theCol, d->mItemSpacing + 1 ) );
1310 
1311  if ( aItem )
1312  setCurrentItem( aItem );
1313 
1314  break;
1315  }
1316  case Key_Space:
1317  setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() );
1318  emit selectionChanged();
1319  break;
1320  case Key_Return:
1321  case Key_Enter:
1322  emit returnPressed( d->mCurrentItem );
1323  emit executed( d->mCurrentItem );
1324  break;
1325  case Key_Menu:
1326  emit contextMenuRequested( d->mCurrentItem, viewport()->mapToGlobal(
1327  itemRect(d->mCurrentItem).center() ) );
1328  break;
1329  default:
1330  if ( (e->state() & ControlButton) && e->key() == Key_A ) {
1331  // select all
1332  selectAll( true );
1333  break;
1334  } else if ( !e->text().isEmpty() && e->text()[ 0 ].isPrint() ) {
1335  // if we have a string, do autosearch
1336  }
1337  break;
1338  }
1339 
1340  // handle selection
1341  if ( aItem ) {
1342  if ( d->mSelectionMode == CardView::Extended ) {
1343  if ( e->state() & ShiftButton ) {
1344  // shift button: toggle range
1345  // if control button is pressed, leave all items
1346  // and toggle selection current->old current
1347  // otherwise, ??????
1348  bool s = ! aItem->isSelected();
1349  int from, to, a, b;
1350  a = d->mItemList.findRef( aItem );
1351  b = d->mItemList.findRef( old );
1352  from = a < b ? a : b;
1353  to = a > b ? a : b;
1354 
1355  if ( to - from > 1 ) {
1356  bool b = signalsBlocked();
1357  blockSignals( true );
1358  selectAll( false );
1359  blockSignals( b );
1360  }
1361 
1362  CardViewItem *item;
1363  for ( ; from <= to; from++ ) {
1364  item = d->mItemList.at( from );
1365  item->setSelected( s );
1366  repaintItem( item );
1367  }
1368 
1369  emit selectionChanged();
1370  } else if ( e->state() & ControlButton ) {
1371  // control button: do nothing
1372  } else {
1373  // no button: move selection to this item
1374  bool b = signalsBlocked();
1375  blockSignals( true );
1376  selectAll( false );
1377  blockSignals( b );
1378 
1379  setSelected( aItem, true );
1380  emit selectionChanged();
1381  }
1382  }
1383  }
1384 }
1385 
1386 void CardView::contentsWheelEvent( TQWheelEvent *e )
1387 {
1388  scrollBy( 2 * e->delta() / -3, 0 );
1389 }
1390 
1391 void CardView::setLayoutDirty( bool dirty )
1392 {
1393  if ( d->mLayoutDirty != dirty ) {
1394  d->mLayoutDirty = dirty;
1395  repaint();
1396  }
1397 }
1398 
1399 void CardView::setDrawCardBorder( bool enabled )
1400 {
1401  if ( enabled != d->mDrawCardBorder ) {
1402  d->mDrawCardBorder = enabled;
1403  repaint();
1404  }
1405 }
1406 
1408 {
1409  return d->mDrawCardBorder;
1410 }
1411 
1413 {
1414  if ( enabled != d->mDrawSeparators ) {
1415  d->mDrawSeparators = enabled;
1416  setLayoutDirty( true );
1417  }
1418 }
1419 
1421 {
1422  return d->mDrawSeparators;
1423 }
1424 
1425 void CardView::setDrawFieldLabels( bool enabled )
1426 {
1427  if ( enabled != d->mDrawFieldLabels ) {
1428  d->mDrawFieldLabels = enabled;
1429  repaint();
1430  }
1431 }
1432 
1434 {
1435  return d->mDrawFieldLabels;
1436 }
1437 
1439 {
1440  if ( show != d->mShowEmptyFields ) {
1441  d->mShowEmptyFields = show;
1442  setLayoutDirty( true );
1443  }
1444 }
1445 
1447 {
1448  return d->mShowEmptyFields;
1449 }
1450 
1452 {
1453  // The default implementation is a no-op. It must be
1454  // reimplemented in a subclass to be useful
1455 }
1456 
1457 void CardView::tryShowFullText()
1458 {
1459  d->mTimer->stop();
1460  // if we have an item
1461  TQPoint cpos = viewportToContents( viewport()->mapFromGlobal( TQCursor::pos() ) );
1462  CardViewItem *item = itemAt( cpos );
1463  if ( item ) {
1464  // query it for a value to display
1465  TQPoint ipos = cpos - itemRect( item ).topLeft();
1466  item->showFullString( ipos, d->mTip );
1467  }
1468 }
1469 
1470 void CardView::drawRubberBands( int pos )
1471 {
1472  if ( pos && d &&
1473  (!d->mSpan || ((pos - d->mFirstX) / d->mSpan) - d->mColspace - d->mSepWidth < MIN_ITEM_WIDTH) )
1474  return;
1475 
1476  int tmpcw = (d->mRubberBandAnchor - d->mFirstX) / d->mSpan;
1477  int x = d->mFirstX + tmpcw - d->mSepWidth - contentsX();
1478  int h = visibleHeight();
1479 
1480  TQPainter p( viewport() );
1481  p.setRasterOp( XorROP );
1482  p.setPen( gray );
1483  p.setBrush( gray );
1484  uint n = d->mFirst;
1485  // erase
1486  if ( d->mRubberBandAnchor )
1487  do {
1488  p.drawRect( x, 0, 2, h );
1489  x += tmpcw;
1490  n++;
1491  } while ( x < visibleWidth() && n < d->mSeparatorList.count() );
1492  // paint new
1493  if ( ! pos )
1494  return;
1495  tmpcw = (pos - d->mFirstX) / d->mSpan;
1496  n = d->mFirst;
1497  x = d->mFirstX + tmpcw - d->mSepWidth - contentsX();
1498  do {
1499  p.drawRect( x, 0, 2, h );
1500  x += tmpcw;
1501  n++;
1502  } while ( x < visibleWidth() && n < d->mSeparatorList.count() );
1503  d->mRubberBandAnchor = pos;
1504 }
1505 
1507 {
1508  return d->mItemWidth;
1509 }
1510 
1512 {
1513  if ( w == d->mItemWidth )
1514  return;
1515  if ( w < MIN_ITEM_WIDTH )
1516  w = MIN_ITEM_WIDTH;
1517  d->mItemWidth = w;
1518  setLayoutDirty( true );
1519  updateContents();
1520 }
1521 
1522 void CardView::setHeaderFont( const TQFont &fnt )
1523 {
1524  d->mHeaderFont = fnt;
1525  delete d->mBFm;
1526  d->mBFm = new TQFontMetrics( fnt );
1527 }
1528 
1529 TQFont CardView::headerFont() const
1530 {
1531  return d->mHeaderFont;
1532 }
1533 
1534 void CardView::setFont( const TQFont &fnt )
1535 {
1536  TQScrollView::setFont( fnt );
1537  delete d->mFm;
1538  d->mFm = new TQFontMetrics( fnt );
1539 }
1540 
1542 {
1543  return d->mSepWidth;
1544 }
1545 
1547 {
1548  d->mSepWidth = width;
1549  setLayoutDirty( true );
1550 }
1551 
1553 {
1554  return d->mMaxFieldLines;
1555 }
1556 
1557 void CardView::setMaxFieldLines( int howmany )
1558 {
1559  d->mMaxFieldLines = howmany ? howmany : INT_MAX;
1560  // FIXME update, forcing the items to recalc height!!
1561 }
1562 
1563 #include "cardview.moc"
Represents a single card (item) in the card view.
Definition: cardview.h:50
void removeField(const TQString &label)
Removes the field with label label from the card.
Definition: cardview.cpp:390
const TQString & caption() const
Definition: cardview.cpp:326
virtual void paintCard(TQPainter *p, TQColorGroup &cg)
Paints the card using the given painter and color group.
Definition: cardview.cpp:225
CardViewItem * nextItem() const
Definition: cardview.cpp:441
void clearFields()
Removes all the fields from this card.
Definition: cardview.cpp:409
void setSelected(bool selected)
Sets the card as selected.
Definition: cardview.cpp:373
void setCaption(const TQString &caption)
Sets the caption of the card.
Definition: cardview.cpp:457
void showFullString(const TQPoint &pos, CardViewTip *tip)
Called by the parent card view when the mouse has been resting for a certain amount of time.
Definition: cardview.cpp:474
virtual void repaintCard()
Repaints the card.
Definition: cardview.cpp:451
CardViewItem(CardView *parent, const TQString &caption=TQString())
Constructor.
Definition: cardview.cpp:195
TQPair< TQString, TQString > Field
A single field in the card view.
Definition: cardview.h:58
bool isSelected() const
Definition: cardview.cpp:368
int height(bool allowCache=true) const
Definition: cardview.cpp:332
TQString fieldValue(const TQString &label) const
Definition: cardview.cpp:463
void insertField(const TQString &label, const TQString &value)
Adds a field to the card.
Definition: cardview.cpp:378
Field * fieldAt(const TQPoint &itempos) const
Definition: cardview.cpp:549
The CardView is a method of displaying data in cards.
Definition: cardview.h:195
void returnPressed(CardViewItem *)
Emitted when the return key is pressed in an item.
void setDrawColSeparators(bool enabled)
Sets if the column separator should be drawn.
Definition: cardview.cpp:1412
CardViewItem * itemAt(const TQPoint &viewPos) const
Definition: cardview.cpp:667
void setDrawCardBorder(bool enabled)
Sets if the border around a card should be draw.
Definition: cardview.cpp:1399
int separatorWidth() const
Definition: cardview.cpp:1541
void setShowEmptyFields(bool show)
Sets if fields with no value should be drawn (of cause the label only, but it allows for embedded edi...
Definition: cardview.cpp:1438
CardViewItem * itemAfter(const CardViewItem *item) const
Definition: cardview.cpp:954
void setItemSpacing(uint spacing)
Sets the item spacing.
Definition: cardview.cpp:979
void currentChanged(CardViewItem *)
Emitted when the current item changes.
bool drawColSeparators() const
Definition: cardview.cpp:1420
void clear()
Clears the view and deletes all card view items.
Definition: cardview.cpp:624
void setMaxFieldLines(int howmany)
Sets the maximum number of lines to display pr field.
Definition: cardview.cpp:1557
void ensureItemVisible(const CardViewItem *item)
Ensures that the given item is in the viewable area of the widget.
Definition: cardview.cpp:689
void contextMenuRequested(CardViewItem *, const TQPoint &)
Emitted when the context menu is requested in some way.
void setSelectionMode(SelectionMode mode)
Sets the selection mode.
Definition: cardview.cpp:700
CardViewItem * firstItem() const
Definition: cardview.cpp:797
CardViewItem * currentItem() const
Definition: cardview.cpp:631
CardViewItem * findItem(const TQString &text, const TQString &label, TQt::StringComparisonMode compare=TQt::BeginsWith) const
Attempts to find the first item matching the params.
Definition: cardview.cpp:807
void setFont(const TQFont &fnt)
Reimplementation from TQWidget.
Definition: cardview.cpp:1534
TQFont headerFont() const
Definition: cardview.cpp:1529
CardViewItem * selectedItem() const
Definition: cardview.cpp:785
TQRect itemRect(const CardViewItem *item) const
Definition: cardview.cpp:684
void setCurrentItem(CardViewItem *item)
Sets the CardViewItem item to the current item in the view.
Definition: cardview.cpp:639
bool isSelected(CardViewItem *item) const
Definition: cardview.cpp:780
void doubleClicked(CardViewItem *)
Emitted whenever the user double clicks on an item.
void executed(CardViewItem *)
Emitted whenever the user 'executes' an item.
void drawContents(TQPainter *p, int clipx, int clipy, int clipw, int cliph)
Determines which cards intersect that region and tells them to paint themselves.
Definition: cardview.cpp:837
uint columnWidth() const
Returns the amounts of pixels required for one column.
Definition: cardview.cpp:830
void calcLayout()
Does the math based on the bounding rect of the cards to properly lay the cards out on the screen.
Definition: cardview.cpp:894
void contentsWheelEvent(TQWheelEvent *)
Changes the direction the canvas scolls.
Definition: cardview.cpp:1386
void setHeaderFont(const TQFont &fnt)
Sets the header font.
Definition: cardview.cpp:1522
void setSeparatorWidth(int width)
Sets the column separator width.
Definition: cardview.cpp:1546
int maxFieldLines() const
Definition: cardview.cpp:1552
void takeItem(CardViewItem *item)
Takes the item from the view.
Definition: cardview.cpp:615
void setItemMargin(uint margin)
Sets the internal item margin.
Definition: cardview.cpp:965
void setDrawFieldLabels(bool enabled)
Sets if the field labels should be drawn.
Definition: cardview.cpp:1425
void selectAll(bool state)
Selects or deselects all items.
Definition: cardview.cpp:712
uint itemMargin() const
Definition: cardview.cpp:960
bool drawCardBorder() const
Definition: cardview.cpp:1407
void setLayoutDirty(bool dirty)
Sets the layout to dirty and calls for a repaint.
Definition: cardview.cpp:1391
void insertItem(CardViewItem *item)
Inserts the item into the card view.
Definition: cardview.cpp:609
void selectionChanged()
Emitted whenever the selection changes.
void clicked(CardViewItem *)
This method is emitted whenever an item is clicked.
void repaintItem(const CardViewItem *item)
Repaints the given item.
Definition: cardview.cpp:695
void setItemWidth(int width)
Sets the width made available to card items.
Definition: cardview.cpp:1511
uint itemSpacing() const
Definition: cardview.cpp:974
void resizeEvent(TQResizeEvent *)
Sets the layout to dirty and repaints.
Definition: cardview.cpp:887
bool drawFieldLabels() const
Definition: cardview.cpp:1433
int childCount() const
Definition: cardview.cpp:802
SelectionMode selectionMode() const
Definition: cardview.cpp:707
int itemWidth() const
Definition: cardview.cpp:1506
bool showEmptyFields() const
Definition: cardview.cpp:1446
void setSelected(CardViewItem *item, bool selected)
Selects or deselects the given item.
Definition: cardview.cpp:737
CardView(TQWidget *parent, const char *name)
Constructor.
Definition: cardview.cpp:572
virtual void startDrag()
Overload this method to be told when a drag should be started.
Definition: cardview.cpp:1451