summaryrefslogtreecommitdiffabout
path: root/kaddressbook/views
Unidiff
Diffstat (limited to 'kaddressbook/views') (more/less context) (ignore whitespace changes)
-rw-r--r--kaddressbook/views/cardview.cpp1719
-rw-r--r--kaddressbook/views/cardview.desktop18
-rw-r--r--kaddressbook/views/cardview.h473
-rw-r--r--kaddressbook/views/colorlistbox.cpp230
-rw-r--r--kaddressbook/views/colorlistbox.h76
-rw-r--r--kaddressbook/views/configurecardviewdialog.cpp364
-rw-r--r--kaddressbook/views/configurecardviewdialog.h117
-rw-r--r--kaddressbook/views/configuretableviewdialog.cpp155
-rw-r--r--kaddressbook/views/configuretableviewdialog.h88
-rw-r--r--kaddressbook/views/contactlistview.cpp340
-rw-r--r--kaddressbook/views/contactlistview.h128
-rw-r--r--kaddressbook/views/kaddressbookcardview.cpp394
-rw-r--r--kaddressbook/views/kaddressbookcardview.h117
-rw-r--r--kaddressbook/views/kaddressbookiconview.cpp378
-rw-r--r--kaddressbook/views/kaddressbookiconview.h130
-rw-r--r--kaddressbook/views/kaddressbooktableview.cpp337
-rw-r--r--kaddressbook/views/kaddressbooktableview.h114
17 files changed, 5178 insertions, 0 deletions
diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp
new file mode 100644
index 0000000..65f793c
--- a/dev/null
+++ b/kaddressbook/views/cardview.cpp
@@ -0,0 +1,1719 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24//BEGIN Includes
25#include "cardview.h"
26
27#include <limits.h>
28
29#include <qpainter.h>
30#include <qtimer.h>
31#include <qdatetime.h>
32#include <qlabel.h>
33#include <qstyle.h>
34#include <qcursor.h>
35#include <qtooltip.h>
36
37#include <kdebug.h>
38#include <kglobalsettings.h>
39//END includes
40
41#define MIN_ITEM_WIDTH 80
42
43//BEGIN Helpers
44//////////////////////////////////////
45// CardViewTip
46class CardViewTip : public QLabel {
47 public:
48 CardViewTip(QWidget *parent=0, const char *name=0) : QLabel( parent, name )
49 {
50 setPalette( QToolTip::palette() );
51 setFrameStyle( Panel|Plain );
52 setMidLineWidth(0);
53 setIndent(1);
54 }
55
56 ~CardViewTip() {};
57 protected:
58 void leaveEvent( QEvent * )
59 {
60 hide();
61 }
62};
63
64//////////////////////////////////////
65// CardViewItemList
66
67
68//
69// Warning: make sure you use findRef() instead of find() to find an
70// item! Only the pointer value is unique in the list.
71//
72class CardViewItemList : public QPtrList<CardViewItem>
73{
74 protected:
75 virtual int compareItems(QPtrCollection::Item item1,
76 QPtrCollection::Item item2)
77 {
78 CardViewItem *cItem1 = (CardViewItem*)item1;
79 CardViewItem *cItem2 = (CardViewItem*)item2;
80
81 if ( cItem1 == cItem2 )
82 return 0;
83
84 if ((cItem1 == 0) || (cItem2 == 0))
85 return cItem1 ? -1 : 1;
86
87 if (cItem1->caption() < cItem2->caption())
88 return -1;
89
90 else if (cItem1->caption() > cItem2->caption())
91 return 1;
92
93 return 0;
94 }
95
96 private:
97 /*int find( const CardViewItem * )
98 {
99 qDebug("DON'T USE CardViewItemList::find( item )! Use findRef( item )!");
100 }*/
101};
102
103//////////////////////////////////////
104// CardViewSeparator
105class CardViewSeparator
106{
107 friend class CardView;
108
109 public:
110 CardViewSeparator(CardView *view)
111 : mView(view)
112 {
113 mRect = QRect(0, 0, view->separatorWidth(), 0);
114 }
115
116 ~CardViewSeparator() {}
117
118 void paintSeparator(QPainter *p, QColorGroup &cg)
119 {
120 p->fillRect(0, 0, mRect.width(), mRect.height(),
121 cg.brush(QColorGroup::Button));
122 }
123
124 void repaintSeparator()
125 {
126 mView->repaintContents(mRect);
127 }
128
129 private:
130 CardView *mView;
131 QRect mRect;
132};
133
134//END Helpers
135
136//BEGIN Private Data
137
138class CardViewPrivate
139{
140 public:
141 CardViewPrivate()
142 : mSelectionMode( CardView::Multi ),
143 mDrawCardBorder( true ),
144 mDrawFieldLabels( true ),
145 mDrawSeparators( true),
146 mSepWidth( 2 ),
147 mShowEmptyFields( false ),
148 mLayoutDirty( true ),
149 mLastClickOnItem( false ),
150 mItemMargin( 0 ),
151 mItemSpacing( 10 ),
152 mItemWidth( 200 ),
153 mMaxFieldLines( INT_MAX ),
154 mCurrentItem( 0L ),
155 mLastClickPos( QPoint(0, 0) ),
156 mRubberBandAnchor( 0 ),
157 mCompText( QString::null ),
158 mResizeAnchor(0)
159 {};
160
161 CardViewItemList mItemList;
162 QPtrList<CardViewSeparator> mSeparatorList;
163 QFontMetrics *mFm;
164 QFontMetrics *mBFm; // bold font
165 QFont mHeaderFont; // custom header font
166 CardView::SelectionMode mSelectionMode;
167 bool mDrawCardBorder;
168 bool mDrawFieldLabels;
169 bool mDrawSeparators;
170 int mSepWidth;
171 bool mShowEmptyFields;
172 bool mLayoutDirty;
173 bool mLastClickOnItem;
174 uint mItemMargin; // internal margin in items
175 uint mItemSpacing; // spacing between items, column seperators and border
176 int mItemWidth; // width of all items
177 uint mMaxFieldLines; // Max lines to dispaly pr field
178 CardViewItem *mCurrentItem;
179 QPoint mLastClickPos;
180 QTimer *mTimer; // times out if mouse rests for more than 500 msecs
181 CardViewTip *mTip; // passed to the item under a resting cursor to display full text
182 bool mOnSeparator; // set/reset on mouse movement
183 // for resizing by dragging the separators
184 int mResizeAnchor; // uint, ulong? the mouse down separator left
185 int mRubberBandAnchor; // for erasing rubber bands
186 // data used for resizing.
187 // as they are beeded by each mouse move while resizing, we store them here,
188 // saving 8 calculations in each mouse move.
189 int colspace; // amount of space between items pr column
190 uint first; // the first col to anchor at for painting rubber bands
191 int firstX; // X position of first in pixel
192 int pressed; // the colummn that was pressed on at resizing start
193 int span; // pressed - first
194 // key completion
195 QString mCompText; // current completion string
196 QDateTime mCompUpdated; // ...was updated at this time
197};
198
199class CardViewItemPrivate
200{
201 public:
202 CardViewItemPrivate() :
203 x( 0 ),
204 y( 0 ),
205 mSelected( false ){};
206
207
208 QString mCaption;
209 QPtrList< CardViewItem::Field > mFieldList;
210 bool mSelected;
211 int x; // horizontal position, set by the view
212 int y; // vertical position, set by the view
213 int maxLabelWidth; // the width of the widest label, according to the view font.
214 int hcache; // height cache
215};
216//END Private Data
217
218//BEGIN CardViewItem
219
220CardViewItem::CardViewItem(CardView *parent, QString caption)
221 : d(new CardViewItemPrivate()), mView(parent)
222{
223 d->mCaption = caption;
224
225 initialize();
226}
227
228CardViewItem::~CardViewItem()
229{
230 // Remove ourself from the view
231 if (mView != 0)
232 mView->takeItem(this);
233
234 delete d;
235 d = 0;
236}
237
238void CardViewItem::initialize()
239{
240 d->mSelected = false;
241 d->mFieldList.setAutoDelete(true);
242 d->maxLabelWidth = 0;
243 d->hcache=0;
244
245 //calcRect();
246
247 // Add ourself to the view
248 if (mView != 0)
249 mView->insertItem(this);
250}
251
252void CardViewItem::paintCard(QPainter *p, QColorGroup &cg)
253{
254
255 if (!mView)
256 return;
257
258 QPen pen;
259 QBrush brush;
260 QFontMetrics fm = *(mView->d->mFm);
261 QFontMetrics bFm = *(mView->d->mBFm);
262 bool drawLabels = mView->d->mDrawFieldLabels;
263 bool drawBorder = mView->d->mDrawCardBorder;
264 int mg = mView->itemMargin();
265 int w = mView->itemWidth() - (mg*2);
266 int h = height() - (mg*2);
267 const int colonWidth( fm.width(":") );
268 int labelXPos = 2 + mg;
269 int labelWidth = QMIN( w/2 - 4 - mg, d->maxLabelWidth + colonWidth + 4 );
270 int valueXPos = labelWidth + 4 + mg;
271 int valueWidth = w - labelWidth - 4 - mg;
272
273 p->setFont( mView->font() );
274 labelWidth -= colonWidth; // extra space for the colon
275
276 if (!drawLabels)
277 {
278 valueXPos = labelXPos;
279 valueWidth = w - 4;
280 }
281
282 // Draw a simple box
283 if (isSelected())
284 pen = QPen(cg.highlight(), 1);
285 else
286 pen = QPen(cg.button(), 1);
287 p->setPen(pen);
288
289 // Draw the border - this is only draw if the user asks for it.
290 if (drawBorder)
291 p->drawRect( mg, mg, w, h );
292
293 // set the proper pen color for the caption box
294 if (isSelected())
295 brush = cg.brush(QColorGroup::Highlight);
296 else
297 brush = cg.brush(QColorGroup::Button);
298
299 p->fillRect(mg, mg, w, 4 + bFm.height(), brush);
300
301 // Now paint the caption
302 p->save();
303 QFont bFont = mView->headerFont();
304 //bFont.setBold(true);
305 p->setFont(bFont);
306 if (isSelected())
307 p->setPen(cg.highlightedText());
308 else
309 p->setPen(cg.buttonText());
310 p->drawText(2+mg, 2+mg + bFm.ascent()/*bFm.height()*//*-bFm.descent()*//*-bFm.leading()*/, trimString(d->mCaption, w-4, bFm));
311 p->restore();
312
313 // Go through the fields and draw them
314 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
315 QString label, value;
316 int yPos = mg + 4 + bFm.height()/* + 1*/ + fm.height(); // why the + 1 ??? (anders)
317 p->setPen(cg.text());
318
319 int fh = fm.height();
320 int cln( 0 );
321 QString tmp;
322 int maxLines = mView->maxFieldLines();
323 for (iter.toFirst(); iter.current(); ++iter)
324 {
325 value = (*iter)->second;
326 if ( value.isEmpty() && ! mView->d->mShowEmptyFields )
327 continue;
328
329 if (drawLabels)
330 {
331 label = trimString((*iter)->first, labelWidth, fm);
332 p->drawText(labelXPos, yPos, label + ":");
333 }
334/* US original
335 for (cln=0; cln <= maxLines; cln++)
336 {
337 tmp = value.section('\n',cln,cln);
338 if ( !tmp.isEmpty() ) p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) );
339 else break;
340 }
341*/
342
343//US new implementation
344 QStringList strlst = QStringList::split('\n', value, true);
345
346 for (cln=0; cln <= maxLines && cln <= (int)strlst.count(); cln++)
347 {
348 tmp = strlst[cln];
349
350 if ( !tmp.isEmpty() )
351 p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) );
352 else
353 break;
354
355 }
356
357 if ( cln == 0 ) cln = 1;
358 yPos += cln * fh + 2;
359 }
360
361 // if we are the current item and the view has focus, draw focus rect
362 if ( mView->currentItem() == this && mView->hasFocus() )
363 {
364/*US
365 mView->style().drawPrimitive( QStyle::PE_FocusRect, p,
366 QRect(0, 0, mView->itemWidth(), h+(2*mg)), cg,
367 QStyle::Style_FocusAtBorder,
368 QStyleOption( isSelected() ? cg.highlight() : cg.base() ) );
369*/
370
371 const QColor pHighl = isSelected() ? cg.highlight() : cg.base();
372 const QRect r(0, 0, mView->itemWidth(), h+(2*mg));
373#ifndef DESKTOP_VERSION
374 mView->style().drawFocusRect(p, r, cg, &pHighl, true);
375#endif
376 }
377}
378
379const QString &CardViewItem::caption() const
380{
381 return d->mCaption;
382}
383
384
385int CardViewItem::height( bool allowCache ) const
386{
387 // use cache
388 if ( allowCache && d->hcache )
389 return d->hcache;
390
391 // Base height:
392 // 2 for line width
393 // 2 for top caption pad
394 // 2 for bottom caption pad
395 // 2 pad for the end
396 // + 2 times the advised margin
397 int baseHeight = 8 + ( 2 * mView->itemMargin() );
398
399 // size of font for each field
400 // 2 pad for each field
401
402 // anders: if the view does not show empty fields, check for value
403 bool sef = mView->showEmptyFields();
404 int fh = mView->d->mFm->height();//lineSpacing(); // font height
405 //int sp = QMAX( 0, 2- mView->d->mFm->leading() ); // field spacing NOTE make a property
406 int fieldHeight = 0;
407 int lines;
408 int maxLines( mView->maxFieldLines() );
409 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
410 for (iter.toFirst(); iter.current(); ++iter)
411 {
412 if ( !sef && (*iter)->second.isEmpty() )
413 continue;
414 lines = QMIN( (*iter)->second.contains('\n') + 1, maxLines );
415 fieldHeight += ( lines * fh ) + 2;//sp;
416 }
417
418 // height of caption font (bold)
419 fieldHeight += mView->d->mBFm->height();
420 d->hcache = baseHeight + fieldHeight;
421 return d->hcache;
422}
423
424bool CardViewItem::isSelected() const
425{
426 return d->mSelected;
427}
428
429void CardViewItem::setSelected(bool selected)
430{
431 d->mSelected = selected;
432}
433
434void CardViewItem::insertField(const QString &label, const QString &value)
435{
436 CardViewItem::Field *f = new CardViewItem::Field(label, value);
437 d->mFieldList.append(f);
438 d->hcache=0;
439
440 if (mView)
441 {
442 mView->setLayoutDirty(true);
443 d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth );
444 }
445}
446
447void CardViewItem::removeField(const QString &label)
448{
449 CardViewItem::Field *f;
450
451 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
452 for (iter.toFirst(); iter.current(); ++iter)
453 {
454 f = *iter;
455 if (f->first == label)
456 break;
457 }
458
459 if (*iter)
460 d->mFieldList.remove(*iter);
461 d->hcache = 0;
462
463 if (mView)
464 mView->setLayoutDirty(true);
465}
466
467void CardViewItem::clearFields()
468{
469 d->mFieldList.clear();
470 d->hcache = 0;
471
472 if (mView)
473 mView->setLayoutDirty(true);
474}
475
476QString CardViewItem::trimString(const QString &text, int width,
477 QFontMetrics &fm)
478{
479 if (fm.width(text) <= width)
480 return text;
481
482 QString dots = "...";
483 int dotWidth = fm.width(dots);
484 QString trimmed;
485 int charNum = 0;
486
487 while (fm.width(trimmed) + dotWidth < width)
488 {
489 trimmed += text[charNum];
490 charNum++;
491 }
492
493 // Now trim the last char, since it put the width over the top
494 trimmed = trimmed.left(trimmed.length()-1);
495 trimmed += dots;
496
497 return trimmed;
498}
499
500CardViewItem *CardViewItem::nextItem()
501{
502 CardViewItem *item = 0;
503
504 if (mView)
505 item = mView->itemAfter(this);
506
507 return item;
508}
509
510void CardViewItem::repaintCard()
511{
512 if (mView)
513 mView->repaintItem(this);
514}
515
516void CardViewItem::setCaption(const QString &caption)
517{
518 d->mCaption = caption;
519 repaintCard();
520}
521
522QString CardViewItem::fieldValue(const QString &label)
523{
524 QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
525 for (iter.toFirst(); iter.current(); ++iter)
526 if ((*iter)->first == label)
527 return (*iter)->second;
528
529 return QString();
530}
531
532
533void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip )
534{
535 bool trimmed( false );
536 QString s;
537 int mrg = mView->itemMargin();
538 int y = mView->d->mBFm->height() + 6 + mrg;
539 int w = mView->itemWidth() - (2*mrg);
540 int lw;
541 bool drawLabels = mView->drawFieldLabels();
542 bool isLabel = drawLabels && itempos.x() < w/2 ? true : false;
543
544 if ( itempos.y() < y )
545 {
546 if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 )
547 return;
548 // this is the caption
549 s = caption();
550 trimmed = mView->d->mBFm->width( s ) > w - 4;
551 y = 2 + mrg;
552 lw = 0;
553 isLabel=true;
554 } else {
555 // find the field
556 Field *f = fieldAt( itempos );
557 if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) )
558 return;
559
560 // y position:
561 // header font height + 4px hader margin + 2px leading + item margin
562 // + actual field index * (fontheight + 2px leading)
563 int maxLines = mView->maxFieldLines();
564 bool se = mView->showEmptyFields();
565 int fh = mView->d->mFm->height();
566// {
567 Field *_f;
568 for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next())
569 if ( se || ! _f->second.isEmpty() )
570 y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2;
571// }
572 if ( isLabel && itempos.y() > y + fh )
573 return;
574 // label or data?
575 s = isLabel ? f->first : f->second;
576 // trimmed?
577 int colonWidth = mView->d->mFm->width(":");
578 lw = drawLabels ? // label width
579 QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) :
580 0;
581 int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string
582 if ( isLabel )
583 {
584 trimmed = mView->d->mFm->width( s ) > mw - colonWidth;
585 } else {
586 QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) );
587 trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines);
588 }
589 }
590 if ( trimmed )
591 {
592 tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header
593 tip->setText( s );
594 tip->adjustSize();
595 // find a proper position
596 int lx;
597 lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/;
598 QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) ));
599 pnt += QPoint(lx, y);
600 if ( pnt.x() < 0 )
601 pnt.setX( 0 );
602 if ( pnt.x() + tip->width() > mView->visibleWidth() )
603 pnt.setX( mView->visibleWidth() - tip->width() );
604 if ( pnt.y() + tip->height() > mView->visibleHeight() )
605 pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) );
606 // show
607 tip->move( pnt );
608 tip->show();
609 }
610}
611
612CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const
613{
614 int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin;
615 int iy = itempos.y();
616 // skip below caption
617 if ( iy <= ypos )
618 return 0;
619 // try find a field
620 bool showEmpty = mView->showEmptyFields();
621 int fh = mView->d->mFm->height();
622 int maxLines = mView->maxFieldLines();
623 Field *f;
624 for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() )
625 {
626 if ( showEmpty || !f->second.isEmpty() )
627 ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2;
628 if ( iy <= ypos )
629 break;
630 }
631 return f ? f : 0;
632}
633//END CardViewItem
634
635//BEGIN CardView
636
637CardView::CardView(QWidget *parent, const char *name)
638 : QScrollView(parent, name),
639 d(new CardViewPrivate())
640{
641 d->mItemList.setAutoDelete(true);
642 d->mSeparatorList.setAutoDelete(true);
643
644 QFont f = font();
645 d->mFm = new QFontMetrics(f);
646 f.setBold(true);
647 d->mHeaderFont = f;
648 d->mBFm = new QFontMetrics(f);
649 d->mTip = ( new CardViewTip( viewport() ) ),
650 d->mTip->hide();
651 d->mTimer = ( new QTimer(this, "mouseTimer") ),
652
653 viewport()->setMouseTracking( true );
654 viewport()->setFocusProxy(this);
655 viewport()->setFocusPolicy(WheelFocus);
656 viewport()->setBackgroundMode(PaletteBase);
657
658 connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) );
659
660//US setBackgroundMode(PaletteBackground, PaletteBase);
661 setBackgroundMode(PaletteBackground);
662
663 // no reason for a vertical scrollbar
664 setVScrollBarMode(AlwaysOff);
665}
666
667CardView::~CardView()
668{
669 delete d->mFm;
670 delete d->mBFm;
671 delete d;
672 d = 0;
673}
674
675void CardView::insertItem(CardViewItem *item)
676{
677 d->mItemList.inSort(item);
678 setLayoutDirty(true);
679}
680
681void CardView::takeItem(CardViewItem *item)
682{
683 if ( d->mCurrentItem == item )
684 d->mCurrentItem = item->nextItem();
685 d->mItemList.take(d->mItemList.findRef(item));
686
687 setLayoutDirty(true);
688}
689
690void CardView::clear()
691{
692 d->mItemList.clear();
693
694 setLayoutDirty(true);
695}
696
697CardViewItem *CardView::currentItem()
698{
699 if ( ! d->mCurrentItem && d->mItemList.count() )
700 d->mCurrentItem = d->mItemList.first();
701 return d->mCurrentItem;
702}
703
704void CardView::setCurrentItem( CardViewItem *item )
705{
706 if ( !item )
707 return;
708 else if ( item->cardView() != this )
709 {
710 kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl;
711 return;
712 }
713 else if ( item == currentItem() )
714 {
715 return;
716 }
717
718 if ( d->mSelectionMode == Single )
719 {
720 setSelected( item, true );
721 }
722 else
723 {
724 CardViewItem *it = d->mCurrentItem;
725 d->mCurrentItem = item;
726 if ( it )
727 it->repaintCard();
728 item->repaintCard();
729 }
730 if ( ! d->mOnSeparator )
731 ensureItemVisible( item );
732 emit currentChanged( item );
733}
734
735CardViewItem *CardView::itemAt(const QPoint &viewPos)
736{
737 CardViewItem *item = 0;
738 QPtrListIterator<CardViewItem> iter(d->mItemList);
739 bool found = false;
740 for (iter.toFirst(); iter.current() && !found; ++iter)
741 {
742 item = *iter;
743 //if (item->d->mRect.contains(viewPos))
744 if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos))
745 found = true;
746 }
747
748 if (found)
749 return item;
750
751 return 0;
752}
753
754QRect CardView::itemRect(const CardViewItem *item)
755{
756 //return item->d->mRect;
757 return QRect(item->d->x, item->d->y, d->mItemWidth, item->height());
758}
759
760void CardView::ensureItemVisible(const CardViewItem *item)
761{
762 ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0);
763 ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0);
764}
765
766void CardView::repaintItem(const CardViewItem *item)
767{
768 //repaintContents(item->d->mRect);
769 repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) );
770}
771
772void CardView::setSelectionMode(CardView::SelectionMode mode)
773{
774 selectAll(false);
775
776 d->mSelectionMode = mode;
777}
778
779CardView::SelectionMode CardView::selectionMode() const
780{
781 return d->mSelectionMode;
782}
783
784void CardView::selectAll(bool state)
785{
786 QPtrListIterator<CardViewItem> iter(d->mItemList);
787 if (!state)
788 {
789 for (iter.toFirst(); iter.current(); ++iter)
790 {
791 if ((*iter)->isSelected())
792 {
793 (*iter)->setSelected(false);
794 (*iter)->repaintCard();
795 }
796 }
797 //emit selectionChanged(); // WARNING FIXME
798 emit selectionChanged(0);
799 }
800 else if (d->mSelectionMode != CardView::Single)
801 {
802 for (iter.toFirst(); iter.current(); ++iter)
803 {
804 (*iter)->setSelected(true);
805 }
806
807 if (d->mItemList.count() > 0)
808 {
809 // emit, since there must have been at least one selected
810 emit selectionChanged();
811 //repaint();//???
812 viewport()->update();
813 }
814 }
815}
816
817void CardView::setSelected(CardViewItem *item, bool selected)
818{
819 if ((item == 0) || (item->isSelected() == selected))
820 return;
821
822 if ( selected && d->mCurrentItem != item )
823 {
824 CardViewItem *it = d->mCurrentItem;
825 d->mCurrentItem = item;
826 if ( it )
827 it->repaintCard();
828 }
829
830 if (d->mSelectionMode == CardView::Single)
831 {
832 bool b = signalsBlocked();
833 blockSignals(true);
834 selectAll(false);
835 blockSignals(b);
836
837 if (selected)
838 {
839 item->setSelected(selected);
840 item->repaintCard();
841 emit selectionChanged();
842 emit selectionChanged(item);
843 }
844 else
845 {
846 emit selectionChanged();
847 emit selectionChanged(0);
848 }
849 }
850 else if (d->mSelectionMode == CardView::Multi)
851 {
852 item->setSelected(selected);
853 item->repaintCard();
854 emit selectionChanged();
855 }
856 else if (d->mSelectionMode == CardView::Extended)
857 {
858 bool b = signalsBlocked();
859 blockSignals(true);
860 selectAll(false);
861 blockSignals(b);
862
863 item->setSelected(selected);
864 item->repaintCard();
865 emit selectionChanged();
866 }
867}
868
869bool CardView::isSelected(CardViewItem *item) const
870{
871 return (item && item->isSelected());
872}
873
874CardViewItem *CardView::selectedItem() const
875{
876 // find the first selected item
877 QPtrListIterator<CardViewItem> iter(d->mItemList);
878 for (iter.toFirst(); iter.current(); ++iter)
879 {
880 if ((*iter)->isSelected())
881 return *iter;
882 }
883
884 return 0;
885}
886
887CardViewItem *CardView::firstItem() const
888{
889 return d->mItemList.first();
890}
891
892int CardView::childCount() const
893{
894 return d->mItemList.count();
895}
896/*US
897CardViewItem *CardView::findItem(const QString &text, const QString &label,
898 Qt::StringComparisonMode compare)
899{
900 // IF the text is empty, we will return null, since empty text will
901 // match anything!
902 if (text.isEmpty())
903 return 0;
904
905 QPtrListIterator<CardViewItem> iter(d->mItemList);
906 if (compare & Qt::BeginsWith)
907 {
908 QString value;
909 for (iter.toFirst(); iter.current(); ++iter)
910 {
911 value = (*iter)->fieldValue(label).upper();
912 if (value.startsWith(text.upper()))
913 return *iter;
914 }
915 }
916 else
917 {
918 kdDebug(5720) << "CardView::findItem: search method not implemented" << endl;
919 }
920
921 return 0;
922}
923*/
924
925uint CardView::columnWidth()
926{
927 return d->mDrawSeparators ?
928 d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth :
929 d->mItemWidth + d->mItemSpacing;
930}
931
932void CardView::drawContents(QPainter *p, int clipx, int clipy,
933 int clipw, int cliph)
934{
935 QScrollView::drawContents(p, clipx, clipy, clipw, cliph);
936
937 if (d->mLayoutDirty)
938 calcLayout();
939
940 //kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy
941 // << ", " << clipw << ", " << cliph << endl;
942
943 QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale
944
945 QRect clipRect(clipx, clipy, clipw, cliph);
946 QRect cardRect;
947 QRect sepRect;
948 CardViewItem *item;
949 CardViewSeparator *sep;
950
951 // make sure the viewport is a pure background
952 viewport()->erase(clipRect);
953
954 // Now tell the cards to draw, if they are in the clip region
955 QPtrListIterator<CardViewItem> iter(d->mItemList);
956 for (iter.toFirst(); iter.current(); ++iter)
957 {
958 item = *iter;
959 cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() );
960
961 if (clipRect.intersects(cardRect) || clipRect.contains(cardRect))
962 {
963 //kdDebug() << "\trepainting card at: " << cardRect.x() << ", "
964 // << cardRect.y() << endl;
965
966 // Tell the card to paint
967 p->save();
968 p->translate(cardRect.x(), cardRect.y());
969 item->paintCard(p, cg);
970 p->restore();
971 }
972 }
973
974 // Followed by the separators if they are in the clip region
975 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
976 for (sepIter.toFirst(); sepIter.current(); ++sepIter)
977 {
978 sep = *sepIter;
979 sepRect = sep->mRect;
980
981 if (clipRect.intersects(sepRect) || clipRect.contains(sepRect))
982 {
983 p->save();
984 p->translate(sepRect.x(), sepRect.y());
985 sep->paintSeparator(p, cg);
986 p->restore();
987 }
988 }
989}
990
991void CardView::resizeEvent(QResizeEvent *e)
992{
993 QScrollView::resizeEvent(e);
994
995 setLayoutDirty(true);
996}
997
998void CardView::calcLayout()
999{
1000 //kdDebug() << "CardView::calcLayout:" << endl;
1001
1002 // Start in the upper left corner and layout all the
1003 // cars using their height and width
1004 int maxWidth = 0;
1005 int maxHeight = 0;
1006 int xPos = 0;
1007 int yPos = 0;
1008 int cardSpacing = d->mItemSpacing;
1009
1010 // delete the old separators
1011 d->mSeparatorList.clear();
1012
1013 QPtrListIterator<CardViewItem> iter(d->mItemList);
1014 CardViewItem *item = 0;
1015 CardViewSeparator *sep = 0;
1016 xPos += cardSpacing;
1017
1018 for (iter.toFirst(); iter.current(); ++iter)
1019 {
1020 item = *iter;
1021
1022 yPos += cardSpacing;
1023
1024 if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height())
1025 {
1026 maxHeight = QMAX(maxHeight, yPos);
1027
1028 // Drawing in this column would be greater than the height
1029 // of the scroll view, so move to next column
1030 yPos = cardSpacing;
1031 xPos += cardSpacing + maxWidth;
1032 if (d->mDrawSeparators)
1033 {
1034 // Create a separator since the user asked
1035 sep = new CardViewSeparator(this);
1036 sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin));
1037 xPos += d->mSepWidth + cardSpacing;
1038 d->mSeparatorList.append(sep);
1039 }
1040
1041 maxWidth = 0;
1042 }
1043
1044 item->d->x = xPos;
1045 item->d->y = yPos;
1046
1047 yPos += item->height();
1048 maxWidth = QMAX(maxWidth, d->mItemWidth);
1049 }
1050
1051 xPos += maxWidth;
1052 resizeContents( xPos + cardSpacing, maxHeight );
1053
1054 // Update the height of all the separators now that we know the
1055 // max height of a column
1056 QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
1057 for (sepIter.toFirst(); sepIter.current(); ++sepIter)
1058 {
1059 (*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin);
1060 }
1061
1062 d->mLayoutDirty = false;
1063}
1064
1065CardViewItem *CardView::itemAfter(CardViewItem *item)
1066{
1067 /*int pos = */d->mItemList.findRef(item);
1068 return d->mItemList.next();//at(pos+1);
1069}
1070
1071uint CardView::itemMargin()
1072{
1073 return d->mItemMargin;
1074}
1075
1076void CardView::setItemMargin( uint margin )
1077{
1078 if ( margin == d->mItemMargin )
1079 return;
1080
1081 d->mItemMargin = margin;
1082 setLayoutDirty( true );
1083}
1084
1085uint CardView::itemSpacing()
1086{
1087 return d->mItemSpacing;
1088}
1089
1090void CardView::setItemSpacing( uint spacing )
1091{
1092 if ( spacing == d->mItemSpacing )
1093 return;
1094
1095 d->mItemSpacing = spacing;
1096 setLayoutDirty( true );
1097}
1098
1099void CardView::contentsMousePressEvent(QMouseEvent *e)
1100{
1101 QScrollView::contentsMousePressEvent(e);
1102
1103 QPoint pos = e->pos();
1104 d->mLastClickPos = pos;
1105
1106 CardViewItem *item = itemAt(pos);
1107
1108 if (item == 0)
1109 {
1110 d->mLastClickOnItem = false;
1111 if ( d->mOnSeparator)
1112 {
1113 d->mResizeAnchor = e->x()+contentsX();
1114 d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/;
1115 int ccw = d->mItemWidth + d->colspace + d->mSepWidth;
1116 d->first = (contentsX()+d->mSepWidth)/ccw;
1117 d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw;
1118 d->span = d->pressed - d->first;
1119 d->firstX = d->first * ccw;
1120 if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0)
1121 }
1122 else
1123 {
1124 selectAll(false);
1125 }
1126 return;
1127 }
1128
1129 d->mLastClickOnItem = true;
1130
1131 CardViewItem *other = d->mCurrentItem;
1132 setCurrentItem( item );
1133
1134 // Always emit the selection
1135 emit clicked(item);
1136
1137 // Check the selection type and update accordingly
1138 if (d->mSelectionMode == CardView::Single)
1139 {
1140 // make sure it isn't already selected
1141 if (item->isSelected())
1142 return;
1143
1144 bool b = signalsBlocked();
1145 blockSignals(true);
1146 selectAll(false);
1147 blockSignals(b);
1148
1149 item->setSelected(true);
1150 item->repaintCard();
1151 emit selectionChanged(item);
1152 }
1153
1154 else if (d->mSelectionMode == CardView::Multi)
1155 {
1156 // toggle the selection
1157 item->setSelected(!item->isSelected());
1158 item->repaintCard();
1159 emit selectionChanged();
1160 }
1161
1162 else if (d->mSelectionMode == CardView::Extended)
1163 {
1164 if ((e->button() & Qt::LeftButton) &&
1165 (e->state() & Qt::ShiftButton))
1166 {
1167 if ( item == other ) return;
1168
1169 bool s = ! item->isSelected();
1170
1171 if ( s && ! (e->state() & ControlButton) )
1172 {
1173 bool b = signalsBlocked();
1174 blockSignals(true);
1175 selectAll(false);
1176 blockSignals(b);
1177 }
1178
1179 int from, to, a, b;
1180 a = d->mItemList.findRef( item );
1181 b = d->mItemList.findRef( other );
1182 from = a < b ? a : b;
1183 to = a > b ? a : b;
1184 //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl;
1185 CardViewItem *aItem;
1186 for ( ; from <= to; from++ )
1187 {
1188 aItem = d->mItemList.at( from );
1189 aItem->setSelected( s );
1190 repaintItem( aItem );
1191 }
1192 emit selectionChanged();
1193 }
1194 else if ((e->button() & Qt::LeftButton) &&
1195 (e->state() & Qt::ControlButton))
1196 {
1197 item->setSelected(!item->isSelected());
1198 item->repaintCard();
1199 emit selectionChanged();
1200 }
1201
1202 else if (e->button() & Qt::LeftButton)
1203 {
1204 bool b = signalsBlocked();
1205 blockSignals(true);
1206 selectAll(false);
1207 blockSignals(b);
1208
1209 item->setSelected(true);
1210 item->repaintCard();
1211 emit selectionChanged();
1212 }
1213 }
1214
1215}
1216
1217void CardView::contentsMouseReleaseEvent(QMouseEvent *e)
1218{
1219 QScrollView::contentsMouseReleaseEvent(e);
1220
1221 if ( d->mResizeAnchor )
1222 {
1223 // finish the resizing:
1224 unsetCursor();
1225 // hide rubber bands
1226 int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span);
1227 drawRubberBands( 0 );
1228 // we should move to reflect the new position if we are scrolled.
1229 if ( contentsX() )
1230 {
1231 int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() );
1232 setContentsPos( newX, contentsY() );
1233 }
1234 // set new item width
1235 setItemWidth( newiw );
1236 // reset anchors
1237 d->mResizeAnchor = 0;
1238 d->mRubberBandAnchor = 0;
1239 return;
1240 }
1241
1242 // If there are accel keys, we will not emit signals
1243 if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton))
1244 return;
1245
1246 // Get the item at this position
1247 CardViewItem *item = itemAt(e->pos());
1248
1249 if (item && KGlobalSettings::singleClick())
1250 {
1251 emit executed(item);
1252 }
1253}
1254
1255void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e)
1256{
1257 QScrollView::contentsMouseDoubleClickEvent(e);
1258
1259 CardViewItem *item = itemAt(e->pos());
1260
1261 if (item)
1262 {
1263 d->mCurrentItem = item;
1264 }
1265
1266 if (item && !KGlobalSettings::singleClick())
1267 {
1268 emit executed(item);
1269 }
1270 emit doubleClicked(item);
1271}
1272
1273void CardView::contentsMouseMoveEvent( QMouseEvent *e )
1274{
1275 // resizing
1276 if ( d->mResizeAnchor )
1277 {
1278 int x = e->x();
1279 if ( x != d->mRubberBandAnchor )
1280 drawRubberBands( x );
1281 return;
1282 }
1283
1284 if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) &&
1285 ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) {
1286
1287 startDrag();
1288 return;
1289 }
1290
1291 d->mTimer->start( 500 );
1292
1293 // see if we are over a separator
1294 // only if we actually have them painted?
1295 if ( d->mDrawSeparators )
1296 {
1297 int colcontentw = d->mItemWidth + (2*d->mItemSpacing);
1298 int colw = colcontentw + d->mSepWidth;
1299 int m = e->x()%colw;
1300 if ( m >= colcontentw && m > 0 )
1301 {
1302 setCursor( SplitVCursor ); // Why does this fail sometimes?
1303 d->mOnSeparator = true;
1304 }
1305 else
1306 {
1307 setCursor( ArrowCursor );
1308 d->mOnSeparator = false;
1309 }
1310 }
1311}
1312
1313void CardView::enterEvent( QEvent * )
1314{
1315 d->mTimer->start( 500 );
1316}
1317
1318void CardView::leaveEvent( QEvent * )
1319{
1320 d->mTimer->stop();
1321 if (d->mOnSeparator)
1322 {
1323 d->mOnSeparator = false;
1324 setCursor( ArrowCursor );
1325 }
1326}
1327
1328void CardView::focusInEvent( QFocusEvent * )
1329{
1330 if (!d->mCurrentItem && d->mItemList.count() )
1331 {
1332 setCurrentItem( d->mItemList.first() );
1333 }
1334 else if ( d->mCurrentItem )
1335 {
1336 d->mCurrentItem->repaintCard();
1337 }
1338}
1339
1340void CardView::focusOutEvent( QFocusEvent * )
1341{
1342 if (d->mCurrentItem)
1343 d->mCurrentItem->repaintCard();
1344}
1345
1346void CardView::keyPressEvent( QKeyEvent *e )
1347{
1348 if ( ! ( childCount() && d->mCurrentItem ) )
1349 {
1350 e->ignore();
1351 return;
1352 }
1353
1354 uint pos = d->mItemList.findRef( d->mCurrentItem );
1355 CardViewItem *aItem = 0L; // item that gets the focus
1356 CardViewItem *old = d->mCurrentItem;
1357
1358 switch ( e->key() )
1359 {
1360 case Key_Up:
1361 if ( pos > 0 )
1362 {
1363 aItem = d->mItemList.at( pos - 1 );
1364 setCurrentItem( aItem );
1365 }
1366 break;
1367 case Key_Down:
1368 if ( pos < d->mItemList.count() - 1 )
1369 {
1370 aItem = d->mItemList.at( pos + 1 );
1371 setCurrentItem( aItem );
1372 }
1373 break;
1374 case Key_Left:
1375 {
1376 // look for an item in the previous/next column, starting from
1377 // the vertical middle of the current item.
1378 // FIXME use nice calculatd measures!!!
1379 QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y );
1380 aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) );
1381 aItem = itemAt( aPoint );
1382 // maybe we hit some space below an item
1383 while ( !aItem && aPoint.y() > 27 )
1384 {
1385 aPoint -= QPoint( 0, 16 );
1386 aItem = itemAt( aPoint );
1387 }
1388 if ( aItem )
1389 setCurrentItem( aItem );
1390 }
1391 break;
1392 case Key_Right:
1393 {
1394 // FIXME use nice calculated measures!!!
1395 QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y );
1396 aPoint += QPoint( 30,(d->mCurrentItem->height()/2) );
1397 aItem = itemAt( aPoint );
1398 while ( !aItem && aPoint.y() > 27 )
1399 {
1400 aPoint -= QPoint( 0, 16 );
1401 aItem = itemAt( aPoint );
1402 }
1403 if ( aItem )
1404 setCurrentItem( aItem );
1405 }
1406 break;
1407 case Key_Home:
1408 aItem = d->mItemList.first();
1409 setCurrentItem( aItem );
1410 break;
1411 case Key_End:
1412 aItem = d->mItemList.last();
1413 setCurrentItem( aItem );
1414 break;
1415 case Key_Prior: // PageUp
1416 {
1417 // QListView: "Make the item above the top visible and current"
1418 // TODO if contentsY(), pick the top item of the leftmost visible column
1419 if ( contentsX() <= 0 )
1420 return;
1421 int cw = columnWidth();
1422 int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing;
1423 aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) );
1424 if ( aItem )
1425 setCurrentItem( aItem );
1426 }
1427 break;
1428 case Key_Next: // PageDown
1429 {
1430 // QListView: "Make the item below the bottom visible and current"
1431 // find the first not fully visible column.
1432 // TODO: consider if a partly visible (or even hidden) item at the
1433 // bottom of the rightmost column exists
1434 int cw = columnWidth();
1435 int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1;
1436 // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden
1437 if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) )
1438 theCol += cw;
1439
1440 // make sure this is not too far right
1441 while ( theCol > contentsWidth() )
1442 theCol -= columnWidth();
1443
1444 aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) );
1445
1446 if ( aItem )
1447 setCurrentItem( aItem );
1448 }
1449 break;
1450 case Key_Space:
1451 setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() );
1452 emit selectionChanged();
1453 break;
1454 case Key_Return:
1455 case Key_Enter:
1456 emit returnPressed( d->mCurrentItem );
1457 emit executed( d->mCurrentItem );
1458 break;
1459 default:
1460 if ( (e->state() & ControlButton) && e->key() == Key_A )
1461 {
1462 // select all
1463 selectAll( true );
1464 break;
1465 }
1466 // if we have a string, do autosearch
1467 else if ( ! e->text().isEmpty() && e->text()[0].isPrint() )
1468 {
1469
1470 }
1471 break;
1472 }
1473 // handle selection
1474 if ( aItem )
1475 {
1476 if ( d->mSelectionMode == CardView::Extended )
1477 {
1478 if ( (e->state() & ShiftButton) )
1479 {
1480 // shift button: toggle range
1481 // if control button is pressed, leave all items
1482 // and toggle selection current->old current
1483 // otherwise, ??????
1484 bool s = ! aItem->isSelected();
1485 int from, to, a, b;
1486 a = d->mItemList.findRef( aItem );
1487 b = d->mItemList.findRef( old );
1488 from = a < b ? a : b;
1489 to = a > b ? a : b;
1490
1491 if ( to - from > 1 )
1492 {
1493 bool b = signalsBlocked();
1494 blockSignals(true);
1495 selectAll(false);
1496 blockSignals(b);
1497 }
1498
1499 //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl;
1500 CardViewItem *item;
1501 for ( ; from <= to; from++ )
1502 {
1503 item = d->mItemList.at( from );
1504 item->setSelected( s );
1505 repaintItem( item );
1506 }
1507 emit selectionChanged();
1508 }
1509 else if ( (e->state() & ControlButton) )
1510 {
1511 // control button: do nothing
1512 }
1513 else
1514 {
1515 // no button: move selection to this item
1516 bool b = signalsBlocked();
1517 blockSignals(true);
1518 selectAll(false);
1519 blockSignals(b);
1520
1521 setSelected( aItem, true );
1522 emit selectionChanged();
1523 }
1524 }
1525 }
1526}
1527
1528void CardView::contentsWheelEvent( QWheelEvent * e )
1529{
1530 scrollBy(2*e->delta()/-3, 0);
1531}
1532
1533void CardView::setLayoutDirty(bool dirty)
1534{
1535 if (d->mLayoutDirty != dirty)
1536 {
1537 d->mLayoutDirty = dirty;
1538 repaint();
1539 }
1540}
1541
1542void CardView::setDrawCardBorder(bool enabled)
1543{
1544 if (enabled != d->mDrawCardBorder)
1545 {
1546 d->mDrawCardBorder = enabled;
1547 repaint();
1548 }
1549}
1550
1551bool CardView::drawCardBorder() const
1552{
1553 return d->mDrawCardBorder;
1554}
1555
1556void CardView::setDrawColSeparators(bool enabled)
1557{
1558 if (enabled != d->mDrawSeparators)
1559 {
1560 d->mDrawSeparators = enabled;
1561 setLayoutDirty(true);
1562 }
1563}
1564
1565bool CardView::drawColSeparators() const
1566{
1567 return d->mDrawSeparators;
1568}
1569
1570void CardView::setDrawFieldLabels(bool enabled)
1571{
1572 if (enabled != d->mDrawFieldLabels)
1573 {
1574 d->mDrawFieldLabels = enabled;
1575 repaint();
1576 }
1577}
1578
1579bool CardView::drawFieldLabels() const
1580{
1581 return d->mDrawFieldLabels;
1582}
1583
1584void CardView::setShowEmptyFields(bool show)
1585{
1586 if (show != d->mShowEmptyFields)
1587 {
1588 d->mShowEmptyFields = show;
1589 setLayoutDirty(true);
1590 }
1591}
1592
1593bool CardView::showEmptyFields() const
1594{
1595 return d->mShowEmptyFields;
1596}
1597
1598void CardView::startDrag()
1599{
1600 // The default implementation is a no-op. It must be
1601 // reimplemented in a subclass to be useful
1602}
1603void CardView::tryShowFullText()
1604{
1605 d->mTimer->stop();
1606 // if we have an item
1607 QPoint cpos = viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) );
1608 CardViewItem *item = itemAt( cpos );
1609 if ( item )
1610 {
1611 // query it for a value to display
1612 //QString s = item ? item->caption() : "(no item)";
1613 //kdDebug()<<"MOUSE REST: "<<s<<endl;
1614 QPoint ipos = cpos - itemRect( item ).topLeft();
1615 item->showFullString( ipos, d->mTip );
1616 }
1617}
1618
1619void CardView::drawRubberBands( int pos )
1620{
1621 if ( pos && ((pos-d->firstX)/d->span) - d->colspace - d->mSepWidth < MIN_ITEM_WIDTH ) return;
1622
1623 int tmpcw = (d->mRubberBandAnchor-d->firstX)/d->span;
1624 int x = d->firstX + tmpcw - d->mSepWidth - contentsX();
1625 int h = visibleHeight();
1626
1627 QPainter p( viewport() );
1628 p.setRasterOp( XorROP );
1629 p.setPen( gray );
1630 p.setBrush( gray );
1631 uint n = d->first;
1632 // erase
1633 if ( d->mRubberBandAnchor )
1634 do {
1635 p.drawRect( x, 0, 2, h );
1636 x += tmpcw;
1637 n++;
1638 } while ( x < visibleWidth() && n < d->mSeparatorList.count() );
1639 // paint new
1640 if ( ! pos ) return;
1641 tmpcw = (pos - d->firstX)/d->span;
1642 n = d->first;
1643 x = d->firstX + tmpcw - d->mSepWidth - contentsX();
1644 do {
1645 p.drawRect( x, 0, 2, h );
1646 x += tmpcw;
1647 n++;
1648 } while ( x < visibleWidth() && n < d->mSeparatorList.count() );
1649 d->mRubberBandAnchor = pos;
1650}
1651
1652
1653int CardView::itemWidth() const
1654{
1655 return d->mItemWidth;
1656}
1657
1658void CardView::setItemWidth( int w )
1659{
1660 if ( w == d->mItemWidth )
1661 return;
1662 if ( w < MIN_ITEM_WIDTH )
1663 w = MIN_ITEM_WIDTH;
1664 d->mItemWidth = w;
1665 setLayoutDirty( true );
1666#ifndef KAB_EMBEDDED
1667 updateContents();
1668#else //KAB_EMBEDDED
1669//US updateContents( d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight() );
1670qDebug("CardView::setItemWidth has to be verified");
1671 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
1672#endif //KAB_EMBEDDED
1673}
1674
1675void CardView::setHeaderFont( const QFont &fnt )
1676{
1677 d->mHeaderFont = fnt;
1678 delete d->mBFm;
1679 d->mBFm = new QFontMetrics( fnt );
1680}
1681
1682QFont CardView::headerFont() const
1683{
1684 return d->mHeaderFont;
1685}
1686
1687void CardView::setFont( const QFont &fnt )
1688{
1689 QScrollView::setFont( fnt );
1690 delete d->mFm;
1691 d->mFm = new QFontMetrics( fnt );
1692}
1693
1694int CardView::separatorWidth()
1695{
1696 return d->mSepWidth;
1697}
1698
1699void CardView::setSeparatorWidth( int width )
1700{
1701 d->mSepWidth = width;
1702 setLayoutDirty( true ); // hmm, actually I could just adjust the x'es...
1703}
1704
1705int CardView::maxFieldLines() const
1706{
1707 return d->mMaxFieldLines;
1708}
1709
1710void CardView::setMaxFieldLines( int howmany )
1711{
1712 d->mMaxFieldLines = howmany ? howmany : INT_MAX;
1713 // FIXME update, forcing the items to recalc height!!
1714}
1715//END Cardview
1716
1717#ifndef KAB_EMBEDDED
1718#include "cardview.moc"
1719#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/cardview.desktop b/kaddressbook/views/cardview.desktop
new file mode 100644
index 0000000..8507360
--- a/dev/null
+++ b/kaddressbook/views/cardview.desktop
@@ -0,0 +1,18 @@
1[Desktop Entry]
2Encoding=UTF-8
3X-KDE-Library=libkaddrbk_cardview
4Name=Card View
5Name[be]=У выглядзе картак
6Name[ca]=Vista de targeta
7Name[da]=Kort-visning
8Name[el]=Προβολή καρτών
9Name[es]=Vista de tarjeta
10Name[hu]=Kártyanézet
11Name[pt_BR]=Visualização de Cartão
12Name[ru]=Карточка
13Name[sk]=Prezeranie karty
14Name[sv]=Kortvy
15Name[tr]=Kart Görünümü
16Name[zh_CN]=卡片视图
17Type=Service
18ServiceTypes=KAddressBook/View
diff --git a/kaddressbook/views/cardview.h b/kaddressbook/views/cardview.h
new file mode 100644
index 0000000..37dddb6
--- a/dev/null
+++ b/kaddressbook/views/cardview.h
@@ -0,0 +1,473 @@
1#ifndef CARDVIEW_H
2#define CARDVIEW_H
3
4#include <qscrollview.h>
5#include <qptrlist.h>
6#include <qstring.h>
7#include <qrect.h>
8#include <qpair.h>
9#include <qpoint.h>
10
11class QLabel;
12class QPainter;
13class QResizeEvent;
14class QMouseEvent;
15class CardView;
16class CardViewPrivate;
17class CardViewItemPrivate;
18class CardViewTip;
19
20/** Represents a single card (item) in the card view. A card has a caption
21* and a list of fields. A Field is a label<->value pair. The labels in a
22* card should be unique, since they will be used to index the values.
23*/
24class CardViewItem
25{
26 friend class CardView;
27
28 public:
29 /** A single field in the card view. The first item is the label
30 * and the second item is the value.
31 */
32 typedef QPair<QString, QString> Field;
33
34 /** Constructor.
35 *
36 * @param parent The CardView that this card should be displayed on.
37 * @param caption The caption of the card. This is the text that will
38 * appear at the top of the card. This is also the string that will
39 * be used to sort the cards in the view.
40 */
41 CardViewItem(CardView *parent, QString caption = QString::null);
42 virtual ~CardViewItem();
43
44 /** @return The caption of the card, or QString::null if none was ever
45 * set.
46 */
47 const QString &caption() const;
48
49 /** Sets the caption of the card. This is the text that will
50 * appear at the top of the card. This is also the string that will
51 * be used to sort the cards in the view.
52 */
53 void setCaption(const QString &caption);
54
55 /** Paints the card using the given painter and color group. The
56 * card will handle painting itself selected if it is selected.
57 */
58 virtual void paintCard(QPainter *p, QColorGroup &cg);
59
60 /** Repaints the card. This is done by sending a repaint event to the
61 * view with the clip rect defined as this card.
62 */
63 virtual void repaintCard();
64
65 /** Adds a field to the card.
66 *
67 * @param label The label of the field. The field labels must be unique
68 * within a card.
69 * @param The value of the field.
70 */
71 void insertField(const QString &label, const QString &value);
72
73 /** Removes the field with label <i>label</i> from the card.
74 */
75 void removeField(const QString &label);
76
77 /** @return The value of the field with label <i>label</i>.
78 */
79 QString fieldValue(const QString &label);
80
81 /** Removes all the fields from this card.
82 */
83 void clearFields();
84
85 /** @return The next card item. The order of the items will be the same
86 * as the display order in the view. 0 will be returned if this is the
87 * last card.
88 */
89 CardViewItem *nextItem();
90
91 /** @return True if this card is currently selected, false otherwise.
92 */
93 bool isSelected() const;
94
95 /** Called by the parent card view when the mouse has been resting for
96 * a certain amount of time. If the label or value at pos is obscured
97 * (trimmed) make the label display the full text.
98 */
99 void showFullString( const QPoint &pos, CardViewTip *tip );
100
101 /** @return a pointer to the Field at the position itempos
102 * in this item. 0 is returned if itempos is in the caption.
103 * @param itempos the position in item coordinates
104 */
105 Field *fieldAt( const QPoint &itempos ) const;
106
107 CardView *cardView() { return mView; };
108
109 /** @return The height of this item as rendered, in pixels.
110
111 if @p allowCache is true, the item may use an internally
112 cached value rather than recalculating from scratch. The
113 argument is mainly to allow the cardView to change global settings (like
114 maxFieldLines) that might influence the items heights
115 */
116 int height( bool allowCache=true ) const;
117
118 protected:
119 /** Sets the card as selected. This is usually only called from the
120 * card view.
121 */
122 void setSelected(bool selected);
123
124 private:
125 /** Sets the default values.
126 */
127 void initialize();
128
129 /** Trims a string to the width <i>width</i> using the font metrics
130 * to determine the width of each char. If the string is longer than
131 * <i>width</i>, then the string will be trimmed and a '...' will
132 * be appended.
133 */
134 QString trimString(const QString &text, int width, QFontMetrics &fm);
135
136 CardViewItemPrivate *d;
137 CardView *mView;
138};
139
140/** The CardView is a method of displaying data in cards. This idea is
141* similar to the idea of a rolodex or business cards. Each card has a
142* caption and a list of fields, which are label<->value pairs. The CardView
143* displays multiple cards in a grid. The Cards are sorted based on their
144* caption.
145*
146* The CardView class is designed to mirror the API of the QListView or
147* QIconView. The CardView is also completely independant of KAddressBook and
148* can be used elsewhere. With the exception of a few simple config checks,
149* the CardView is also 100% independant of KDE.
150*/
151class CardView : public QScrollView
152{
153 friend class CardViewItem;
154
155 Q_OBJECT
156
157 public:
158 /** Constructor.
159 */
160 CardView(QWidget *parent, const char *name);
161 virtual ~CardView();
162
163 /** Inserts the item into the card view. This method does not have
164 * to be called if you created the item with a proper parent. Once
165 * inserted, the CardView takes ownership of the item.
166 */
167 void insertItem(CardViewItem *item);
168
169 /** Takes the item from the view. The item will not be deleted and
170 * ownership of the item is returned to the caller.
171 */
172 void takeItem(CardViewItem *item);
173
174 /** Clears the view and deletes all card view items
175 */
176 void clear();
177
178 /** @return The current item, the item that has the focus.
179 * Whenever the view has focus, this item has a focus rectangle painted
180 * at it's border.
181 * @sa setCurrentItem()
182 */
183 CardViewItem *currentItem();
184
185 /** Sets the CardViewItem @p item to the current item in the view.
186 */
187 void setCurrentItem( CardViewItem *item );
188
189 /** @return The item found at the given point, or 0 if there is no item
190 * at that point.
191 */
192 CardViewItem *itemAt(const QPoint &viewPos);
193
194 /** @return The bounding rect of the given item.
195 */
196 QRect itemRect(const CardViewItem *item);
197
198 /** Ensures that the given item is in the viewable area of the widget
199 */
200 void ensureItemVisible(const CardViewItem *item);
201
202 /** Repaints the given item.
203 */
204 void repaintItem(const CardViewItem *item);
205
206 enum SelectionMode { Single, Multi, Extended, NoSelection };
207
208 /** Sets the selection mode.
209 *
210 * @see QListView
211 */
212 void setSelectionMode(SelectionMode mode);
213
214 /** @return The current selection mode.
215 */
216 SelectionMode selectionMode() const;
217
218 /** Selects or deselects the given item. This method honors the current
219 * selection mode, so if other items are selected, they may be unselected.
220 */
221 void setSelected(CardViewItem *item, bool selected);
222
223 /** Selects or deselects all items.
224 */
225 void selectAll(bool state);
226
227 /** @return True if the given item is selected, false otherwise.
228 */
229 bool isSelected(CardViewItem *item) const;
230
231 /** @return The first selected item. In single select mode, this will be
232 * the only selected item, in other modes this will be the first selected
233 * item, but others may exist. 0 if no item is selected.
234 */
235 CardViewItem *selectedItem() const;
236
237 /** @return The first item in the view. This may be 0 if no items have
238 * been inserted. This method combined with CardViewItem::nextItem()
239 * can be used to iterator through the list of items.
240 */
241 CardViewItem *firstItem() const;
242
243 /** @return The item after the given item or 0 if the item is the last
244 * item.
245 */
246 CardViewItem *itemAfter(CardViewItem *item);
247
248 /** @return The number of items in the view.
249 */
250 int childCount() const;
251
252 /** Attempts to find the first item matching the params.
253 *
254 * @param text The text to match.
255 * @param label The label of the field to match against.
256 * @param compare The compare method to use in doing the search.
257 *
258 * @return The first matching item, or 0 if no items match.
259 */
260/*US
261 CardViewItem *findItem(const QString &text, const QString &label,
262 Qt::StringComparisonMode compare = Qt::BeginsWith);
263*/
264
265 /** Returns the amounts of pixels required for one column.
266 * This depends on wheather drawSeparators is enabled:
267 * If so, it is itemWidth + 2*itemSpacing + separatorWidth
268 * If not, it is itemWidth + itemSpacing
269 * @see itemWidth(), setItemWidth(), itemSpacing() and setItemSpacing()
270 */
271 uint columnWidth();
272
273 /** Sets if the border around a card should be draw. The border is a thing
274 * (1 or 2 pixel) line that bounds the card. When drawn, it shows when
275 * a card is highlighted and when it isn't.
276 */
277 void setDrawCardBorder(bool enabled);
278
279 /** @return True if borders are drawn, false otherwise.
280 */
281 bool drawCardBorder() const;
282
283 /** Sets if the column separator should be drawn. The column separator
284 * is a thin verticle line (1 or 2 pixels) that is used to separate the
285 * columns in the list view. The separator is just for esthetics and it
286 * does not serve a functional purpose.
287 */
288 void setDrawColSeparators(bool enabled);
289
290 /** @return True if column separators are drawn, false otherwise.
291 */
292 bool drawColSeparators() const;
293
294 /** Sets if the field labels should be drawn. The field labels are the
295 * unique strings used to identify the fields. Sometimes drawing these
296 * labels makes sense as a source of clarity for the user, othertimes they
297 * waste too much space and do not assist the user.
298 */
299 void setDrawFieldLabels(bool enabled);
300
301 /** @return True if the field labels are drawn, false otherwise.
302 */
303 bool drawFieldLabels() const;
304
305 /** Sets if fields with no value should be drawn (of cause the label only,
306 * but it allows for embedded editing sometimes...)
307 */
308 void setShowEmptyFields(bool show);
309
310 /** @return Wheather empty fields should be shown
311 */
312 bool showEmptyFields() const;
313
314 /** @return the advisory internal margin in items. Setting a value above 1 means
315 * a space between the item contents and the focus recttangle drawn around
316 * the current item. The default value is 0.
317 * The value should be used by CardViewItem and derived classes.
318 * Note that this should not be greater than half of the minimal item width,
319 * which is 80. It is currently not checked, so setting a value greater than 40
320 * will probably mean a crash in the items painting routine.
321 * @private Note: I looked for a value in QStyle::PixelMetric to use, but I could
322 * not see a usefull one. One may turn up in a future version of Qt.
323 */
324 uint itemMargin();
325
326 /** Sets the internal item margin. @see itemMargin().
327 */
328 void setItemMargin( uint margin );
329
330 /** @return the item spacing.
331 * The item spacing is the space (in pixels) between each item in a
332 * column, between the items and column separators if drawn, and between
333 * the items and the borders of the widget. The default value is set to
334 * 10.
335 * @private Note: There is no usefull QStyle::PixelMetric to use for this atm.
336 * An option would be using KDialog::spacingHint().
337 */
338 uint itemSpacing();
339
340 /** Sets the item spacing.
341 * @see itemSpacing()
342 */
343 void setItemSpacing( uint spacing );
344
345 /** @return the width made available to the card items. */
346 int itemWidth() const;
347
348 /** Sets the width made available to card items. */
349 void setItemWidth( int width );
350
351 /** Sets the header font */
352 void setHeaderFont( const QFont &fnt );
353
354 /** @return the header font */
355 QFont headerFont() const;
356
357 /** @reimp */
358 void setFont( const QFont &fnt );
359
360 /** Sets the column separator width */
361 void setSeparatorWidth( int width );
362
363 /** @return the column separator width */
364 int separatorWidth();
365
366 /** Sets the maximum number of lines to display pr field.
367 If set to 0 (the default) all lines will be displayed.
368 */
369 void setMaxFieldLines( int howmany );
370
371 /** @return the maximum number of lines pr field */
372 int maxFieldLines() const;
373
374 signals:
375 /** Emitted whenever the selection changes. This means a user highlighted
376 * a new item or unhighlighted a currently selected item.
377 */
378 void selectionChanged();
379
380 /** Same as above method, only it carries the item that was selected. This
381 * method will only be emitted in single select mode, since it defineds
382 * which item was selected.
383 */
384 void selectionChanged(CardViewItem *);
385
386 /** This method is emitted whenever an item is clicked.
387 */
388 void clicked(CardViewItem *);
389
390 /** Emitted whenever the user 'executes' an item. This is dependant on
391 * the KDE global config. This could be a single click or a doubleclick.
392 * Also emitted when the return key is pressed on an item.
393 */
394 void executed(CardViewItem *);
395
396 /** Emitted whenever the user double clicks on an item.
397 */
398 void doubleClicked(CardViewItem *);
399
400 /** Emitted when the current item changes
401 */
402 void currentChanged( CardViewItem * );
403
404 /** Emitted when the return key is pressed in an item.
405 */
406 void returnPressed( CardViewItem * );
407
408 protected:
409 /** Determines which cards intersect that region and tells them to paint
410 * themselves.
411 */
412 void drawContents(QPainter *p, int clipx, int clipy, int clipw, int cliph);
413
414 /** Sets the layout to dirty and repaints.
415 */
416 void resizeEvent(QResizeEvent *e);
417
418 /** Changes the direction the canvas scolls.
419 */
420 void contentsWheelEvent(QWheelEvent *e);
421
422 /** Sets the layout to dirty and calls for a repaint.
423 */
424 void setLayoutDirty(bool dirty);
425
426 /** Does the math based on the bounding rect of the cards to properly
427 * lay the cards out on the screen. This is only done if the layout is
428 * marked as dirty.
429 */
430 void calcLayout();
431
432// virtual void mousePressEvent(QMouseEvent *e);
433// virtual void mouseReleaseEvent(QMouseEvent *e);
434// virtual void mouseMoveEvent(QMouseEvent *e);
435
436 virtual void contentsMousePressEvent(QMouseEvent *e);
437 virtual void contentsMouseMoveEvent(QMouseEvent *e);
438 virtual void contentsMouseReleaseEvent(QMouseEvent *e);
439 virtual void contentsMouseDoubleClickEvent(QMouseEvent *e);
440
441 virtual void enterEvent( QEvent * );
442 virtual void leaveEvent( QEvent * );
443
444 virtual void focusInEvent( QFocusEvent * );
445 virtual void focusOutEvent( QFocusEvent * );
446
447 virtual void keyPressEvent( QKeyEvent * );
448
449 /** Overload this method to be told when a drag should be started.
450 * In most cases you will want to start a drag event with the currently
451 * selected item.
452 */
453 virtual void startDrag();
454
455 private slots:
456 /** Called by a timer to display a label with truncated text.
457 * Pop up a label, if there is a field with obscured text or
458 * label at the cursor position.
459 */
460 void tryShowFullText();
461
462 private:
463 /** draws and erases the rubber bands while columns are resized.
464 * @p pos is the horizontal position inside the viewport to use as
465 * the anchor.
466 * If pos is 0, only erase is done.
467 */
468 void drawRubberBands( int pos );
469
470 CardViewPrivate *d;
471};
472
473#endif
diff --git a/kaddressbook/views/colorlistbox.cpp b/kaddressbook/views/colorlistbox.cpp
new file mode 100644
index 0000000..c243fa0
--- a/dev/null
+++ b/kaddressbook/views/colorlistbox.cpp
@@ -0,0 +1,230 @@
1/*
2 * kmail: KDE mail client
3 * This file: Copyright (C) 2000 Espen Sand, espen@kde.org
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include <qpainter.h>
22
23#include <kcolordialog.h>
24
25#ifndef KAB_EMBEDDED
26#include <kcolordrag.h>
27#endif //KAB_EMBEDDED
28
29#include "colorlistbox.h"
30
31ColorListBox::ColorListBox( QWidget *parent, const char *name, WFlags f )
32 :KListBox( parent, name, f ), mCurrentOnDragEnter(-1)
33{
34 connect( this, SIGNAL(selected(int)), this, SLOT(newColor(int)) );
35 setAcceptDrops( true);
36}
37
38
39void ColorListBox::setEnabled( bool state )
40{
41 if( state == isEnabled() )
42 {
43 return;
44 }
45
46 QListBox::setEnabled( state );
47 for( uint i=0; i<count(); i++ )
48 {
49 updateItem( i );
50 }
51}
52
53
54void ColorListBox::setColor( uint index, const QColor &color )
55{
56 if( index < count() )
57 {
58 ColorListItem *colorItem = (ColorListItem*)item(index);
59 colorItem->setColor(color);
60 updateItem( colorItem );
61 }
62}
63
64
65QColor ColorListBox::color( uint index ) const
66{
67 if( index < count() )
68 {
69 ColorListItem *colorItem = (ColorListItem*)item(index);
70 return( colorItem->color() );
71 }
72 else
73 {
74 return( black );
75 }
76}
77
78
79void ColorListBox::newColor( int index )
80{
81 if( isEnabled() == false )
82 {
83 return;
84 }
85
86 if( (uint)index < count() )
87 {
88 QColor c = color( index );
89#ifndef KAB_EMBEDDED
90 if( KColorDialog::getColor( c, this ) != QDialog::Rejected )
91 {
92 setColor( index, c );
93 }
94#else //KAB_EMBEDDED
95 KColorDialog* k = new KColorDialog( this );
96 k->setColor( c );
97 int res = k->exec();
98 if ( res ) {
99 setColor( index, k->getColor() );
100 }
101 delete k;
102#endif //KAB_EMBEDDED
103
104 }
105}
106
107
108void ColorListBox::dragEnterEvent( QDragEnterEvent *e )
109{
110#ifndef KAB_EMBEDDED
111 if( KColorDrag::canDecode(e) && isEnabled() )
112 {
113 mCurrentOnDragEnter = currentItem();
114 e->accept( true );
115 }
116 else
117 {
118 mCurrentOnDragEnter = -1;
119 e->accept( false );
120 }
121#else //KAB_EMBEDDED
122qDebug("ColorListBox::dragEnterEvent drag&drop currently not supported");
123#endif //KAB_EMBEDDED
124
125}
126
127
128void ColorListBox::dragLeaveEvent( QDragLeaveEvent * )
129{
130#ifndef KAB_EMBEDDED
131
132 if( mCurrentOnDragEnter != -1 )
133 {
134 setCurrentItem( mCurrentOnDragEnter );
135 mCurrentOnDragEnter = -1;
136 }
137#else //KAB_EMBEDDED
138qDebug("ColorListBox::dragLeaveEvent drag&drop currently not supported");
139#endif //KAB_EMBEDDED
140}
141
142
143void ColorListBox::dragMoveEvent( QDragMoveEvent *e )
144{
145#ifndef KAB_EMBEDDED
146 if( KColorDrag::canDecode(e) && isEnabled() )
147 {
148 ColorListItem *item = (ColorListItem*)itemAt( e->pos() );
149 if( item != 0 )
150 {
151 setCurrentItem ( item );
152 }
153 }
154#else //KAB_EMBEDDED
155qDebug("ColorListBox::dragMoveEvent drag&drop currently not supported");
156#endif //KAB_EMBEDDED
157
158}
159
160
161void ColorListBox::dropEvent( QDropEvent *e )
162{
163#ifndef KAB_EMBEDDED
164 QColor color;
165 if( KColorDrag::decode( e, color ) )
166 {
167 int index = currentItem();
168 if( index != -1 )
169 {
170 ColorListItem *colorItem = (ColorListItem*)item(index);
171 colorItem->setColor(color);
172 triggerUpdate( false ); // Redraw item
173 }
174 mCurrentOnDragEnter = -1;
175 }
176
177#else //KAB_EMBEDDED
178qDebug("ColorListBox::dropEvent drag&drop currently not supported");
179#endif //KAB_EMBEDDED
180
181}
182
183
184
185ColorListItem::ColorListItem( const QString &text, const QColor &color )
186 : QListBoxItem(), mColor( color ), mBoxWidth( 30 )
187{
188 setText( text );
189}
190
191
192const QColor &ColorListItem::color( void )
193{
194 return( mColor );
195}
196
197
198void ColorListItem::setColor( const QColor &color )
199{
200 mColor = color;
201}
202
203
204void ColorListItem::paint( QPainter *p )
205{
206 QFontMetrics fm = p->fontMetrics();
207 int h = fm.height();
208
209 p->drawText( mBoxWidth+3*2, fm.ascent() + fm.leading()/2, text() );
210
211 p->setPen( Qt::black );
212 p->drawRect( 3, 1, mBoxWidth, h-1 );
213 p->fillRect( 4, 2, mBoxWidth-2, h-3, mColor );
214}
215
216
217int ColorListItem::height(const QListBox *lb ) const
218{
219 return( lb->fontMetrics().lineSpacing()+1 );
220}
221
222
223int ColorListItem::width(const QListBox *lb ) const
224{
225 return( mBoxWidth + lb->fontMetrics().width( text() ) + 6 );
226}
227
228#ifndef KAB_EMBEDDED
229#include "colorlistbox.moc"
230#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/colorlistbox.h b/kaddressbook/views/colorlistbox.h
new file mode 100644
index 0000000..4a0e705
--- a/dev/null
+++ b/kaddressbook/views/colorlistbox.h
@@ -0,0 +1,76 @@
1/*
2 * kmail: KDE mail client
3 * This file: Copyright (C) 2000 Espen Sand, espen@kde.org
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#ifndef _COLOR_LISTBOX_H_
22#define _COLOR_LISTBOX_H_
23
24#include <klistbox.h>
25
26class QDragEnterEvent;
27class QDragLeaveEvent;
28class QDragMoveEvent;
29class QDropEvent;
30
31class ColorListBox : public KListBox
32{
33 Q_OBJECT
34
35 public:
36 ColorListBox( QWidget *parent=0, const char * name=0, WFlags f=0 );
37 void setColor( uint index, const QColor &color );
38 QColor color( uint index ) const;
39
40 public slots:
41 virtual void setEnabled( bool state );
42
43 protected:
44 void dragEnterEvent( QDragEnterEvent *e );
45 void dragLeaveEvent( QDragLeaveEvent *e );
46 void dragMoveEvent( QDragMoveEvent *e );
47 void dropEvent( QDropEvent *e );
48
49 private slots:
50 void newColor( int index );
51
52 private:
53 int mCurrentOnDragEnter;
54
55};
56
57
58class ColorListItem : public QListBoxItem
59{
60 public:
61 ColorListItem( const QString &text, const QColor &color=Qt::black );
62 const QColor &color( void );
63 void setColor( const QColor &color );
64
65 protected:
66 virtual void paint( QPainter * );
67 virtual int height( const QListBox * ) const;
68 virtual int width( const QListBox * ) const;
69
70 private:
71 QColor mColor;
72 int mBoxWidth;
73};
74
75#endif
76
diff --git a/kaddressbook/views/configurecardviewdialog.cpp b/kaddressbook/views/configurecardviewdialog.cpp
new file mode 100644
index 0000000..d518cf7
--- a/dev/null
+++ b/kaddressbook/views/configurecardviewdialog.cpp
@@ -0,0 +1,364 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qstring.h>
25#include <qlayout.h>
26#include <qlabel.h>
27#include <qcheckbox.h>
28#include <qvbox.h>
29#include <qgroupbox.h>
30#include <qspinbox.h>
31#include <qtabwidget.h>
32#include <qwhatsthis.h>
33
34#include <kdebug.h>
35#include <kglobal.h>
36#include <kglobalsettings.h>
37#include <klocale.h>
38#include <kiconloader.h>
39#include <kconfig.h>
40#include <kfontdialog.h>
41
42#ifndef KAB_EMBEDDED
43#include <kpushbutton.h>
44#else //KAB_EMBEDDED
45#include <qpushbutton.h>
46#endif //KAB_EMBEDDED
47
48#include "colorlistbox.h"
49
50#include "configurecardviewdialog.h"
51
52/////////////////////////////////
53// ConfigureCardViewDialog
54
55ConfigureCardViewWidget::ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent,
56 const char *name )
57 : ViewConfigureWidget( ab, parent, name )
58{
59#ifndef KAB_EMBEDDED
60 QWidget *page = addPage( i18n( "Look & Feel" ), QString::null,
61 DesktopIcon( "looknfeel" ) );
62#else //KAB_EMBEDDED
63 QWidget *page = addPage( i18n( "Look & Feel" ), QString::null,
64 KGlobal::iconLoader()->loadIcon( "looknfeel",
65 KIcon::Panel ) );
66#endif //KAB_EMBEDDED
67
68 mAdvancedPage = new CardViewLookNFeelPage( page );
69}
70
71ConfigureCardViewWidget::~ConfigureCardViewWidget()
72{
73}
74
75void ConfigureCardViewWidget::restoreSettings( KConfig *config )
76{
77 ViewConfigureWidget::restoreSettings( config );
78
79 mAdvancedPage->restoreSettings( config );
80}
81
82void ConfigureCardViewWidget::saveSettings( KConfig *config )
83{
84 ViewConfigureWidget::saveSettings( config );
85
86 mAdvancedPage->saveSettings( config );
87}
88
89////////////////////////
90// CardViewLookNFeelPage
91CardViewLookNFeelPage::CardViewLookNFeelPage( QWidget *parent, const char *name )
92 : QVBox( parent, name )
93{
94 initGUI();
95}
96
97CardViewLookNFeelPage::~CardViewLookNFeelPage()
98{
99}
100
101void CardViewLookNFeelPage::restoreSettings( KConfig *config )
102{
103 // colors
104 cbEnableCustomColors->setChecked( config->readBoolEntry( "EnableCustomColors", false ) );
105 QColor c;
106qDebug("CardViewLookNFeelPage::restoreSettings make base color configurable");
107
108#ifndef KAB_EMBEDDED
109 c = KGlobalSettings::baseColor();
110#else //KAB_EMBEDDED
111 c = QColor(0,0,0);
112#endif //KAB_EMBEDDED
113
114 lbColors->insertItem( new ColorListItem( i18n("Background Color"),
115 config->readColorEntry( "BackgroundColor", &c ) ) );
116 c = colorGroup().foreground();
117 lbColors->insertItem( new ColorListItem( i18n("Text Color"),
118 config->readColorEntry( "TextColor", &c ) ) );
119 c = colorGroup().button();
120 lbColors->insertItem( new ColorListItem( i18n("Header, Border and Separator Color"),
121 config->readColorEntry( "HeaderColor", &c ) ) );
122 c = colorGroup().buttonText();
123 lbColors->insertItem( new ColorListItem( i18n("Header Text Color"),
124 config->readColorEntry( "HeaderTextColor", &c ) ) );
125 c = colorGroup().highlight();
126 lbColors->insertItem( new ColorListItem( i18n("Highlight Color"),
127 config->readColorEntry( "HighlightColor", &c ) ) );
128 c = colorGroup().highlightedText();
129 lbColors->insertItem( new ColorListItem( i18n("Highlighted Text Color"),
130 config->readColorEntry( "HighlightedTextColor", &c ) ) );
131
132 enableColors();
133
134 // fonts
135 QFont fnt = font();
136 updateFontLabel( config->readFontEntry( "TextFont", &fnt ), (QLabel*)lTextFont );
137 fnt.setBold( true );
138 updateFontLabel( config->readFontEntry( "HeaderFont", &fnt ), (QLabel*)lHeaderFont );
139 cbEnableCustomFonts->setChecked( config->readBoolEntry( "EnableCustomFonts", false ) );
140 enableFonts();
141
142 // layout
143 sbMargin->setValue( config->readNumEntry( "ItemMargin", 0 ) );
144 sbSpacing->setValue( config->readNumEntry( "ItemSpacing", 10 ) );
145 sbSepWidth->setValue( config->readNumEntry( "SeparatorWidth", 2 ) );
146 cbDrawSeps->setChecked( config->readBoolEntry( "DrawSeparators", true ) );
147 cbDrawBorders->setChecked( config->readBoolEntry( "DrawBorder", true ) );
148
149 // behaviour
150 cbShowFieldLabels->setChecked( config->readBoolEntry( "DrawFieldLabels", false ) );
151 cbShowEmptyFields->setChecked( config->readBoolEntry( "ShowEmptyFields", false ) );
152}
153
154void CardViewLookNFeelPage::saveSettings( KConfig *config )
155{
156 // colors
157 config->writeEntry( "EnableCustomColors", cbEnableCustomColors->isChecked() );
158 if ( cbEnableCustomColors->isChecked() ) // ?? - Hmmm.
159 {
160 config->writeEntry( "BackgroundColor", lbColors->color( 0 ) );
161 config->writeEntry( "TextColor", lbColors->color( 1 ) );
162 config->writeEntry( "HeaderColor", lbColors->color( 2 ) );
163 config->writeEntry( "HeaderTextColor", lbColors->color( 3 ) );
164 config->writeEntry( "HighlightColor", lbColors->color( 4 ) );
165 config->writeEntry( "HighlightedTextColor", lbColors->color( 5 ) );
166 }
167 // fonts
168 config->writeEntry( "EnableCustomFonts", cbEnableCustomFonts->isChecked() );
169 if ( cbEnableCustomFonts->isChecked() )
170 {
171 config->writeEntry( "TextFont", lTextFont->font() );
172 config->writeEntry( "HeaderFont", lHeaderFont->font() );
173 }
174 // layout
175 config->writeEntry( "ItemMargin", sbMargin->value() );
176 config->writeEntry( "ItemSpacing", sbSpacing->value() );
177 config->writeEntry( "SeparatorWidth", sbSepWidth->value() );
178 config->writeEntry("DrawBorder", cbDrawBorders->isChecked());
179 config->writeEntry("DrawSeparators", cbDrawSeps->isChecked());
180
181 // behaviour
182 config->writeEntry("DrawFieldLabels", cbShowFieldLabels->isChecked());
183 config->writeEntry("ShowEmptyFields", cbShowEmptyFields->isChecked());
184}
185
186void CardViewLookNFeelPage::setTextFont()
187{
188 QFont f( lTextFont->font() );
189#ifndef KAB_EMBEDDED
190 if ( KFontDialog::getFont( f, false, this ) == QDialog::Accepted )
191 updateFontLabel( f, lTextFont );
192#else //KAB_EMBEDDED
193 bool ok;
194 QFont fout = KFontDialog::getFont( f, ok);
195 if ( ok )
196 updateFontLabel( fout, lTextFont );
197#endif //KAB_EMBEDDED
198}
199
200void CardViewLookNFeelPage::setHeaderFont()
201{
202 QFont f( lHeaderFont->font() );
203#ifndef KAB_EMBEDDED
204 if ( KFontDialog::getFont( f,false, this ) == QDialog::Accepted )
205 updateFontLabel( f, lHeaderFont );
206#else //KAB_EMBEDDED
207 bool ok;
208 QFont fout = KFontDialog::getFont( f, ok);
209 if ( ok )
210 updateFontLabel( fout, lHeaderFont );
211#endif //KAB_EMBEDDED
212}
213
214void CardViewLookNFeelPage::enableFonts()
215{
216 vbFonts->setEnabled( cbEnableCustomFonts->isChecked() );
217}
218
219void CardViewLookNFeelPage::enableColors()
220{
221 lbColors->setEnabled( cbEnableCustomColors->isChecked() );
222}
223
224void CardViewLookNFeelPage::initGUI()
225{
226 int spacing = KDialog::spacingHint();
227 int margin = KDialog::marginHint();
228
229 QTabWidget *tabs = new QTabWidget( this );
230
231 // Layout
232 QVBox *loTab = new QVBox( this, "layouttab" );
233
234 loTab->setSpacing( spacing );
235 loTab->setMargin( margin );
236
237 QGroupBox *gbGeneral = new QGroupBox( 1, Qt::Horizontal, i18n("General"), loTab );
238
239 cbDrawSeps = new QCheckBox( i18n("Draw &separators"), gbGeneral );
240
241 QHBox *hbSW = new QHBox( gbGeneral );
242 QLabel *lSW = new QLabel( i18n("Separator &width:"), hbSW );
243 sbSepWidth = new QSpinBox( 1, 50, 1, hbSW );
244 lSW->setBuddy( sbSepWidth);
245
246 QHBox *hbPadding = new QHBox( gbGeneral );
247 QLabel *lSpacing = new QLabel( i18n("&Padding:"), hbPadding );
248 sbSpacing = new QSpinBox( 0, 100, 1, hbPadding );
249 lSpacing->setBuddy( sbSpacing );
250
251 QGroupBox *gbCards = new QGroupBox( 1, Qt::Horizontal, i18n("Cards"), loTab );
252
253 QHBox *hbMargin = new QHBox( gbCards );
254 QLabel *lMargin = new QLabel( i18n("&Margin:"), hbMargin );
255 sbMargin = new QSpinBox( 0, 100, 1, hbMargin );
256 lMargin->setBuddy( sbMargin );
257
258 cbDrawBorders = new QCheckBox( i18n("Draw &borders"), gbCards );
259
260 loTab->setStretchFactor( new QWidget( loTab ), 1 );
261
262 QWhatsThis::add( sbMargin, i18n(
263 "The item margin is the distance (in pixels) between the item edge and the item data. Most noticeably, "
264 "incrementing the item margin will add space between the focus rectangle and the item data."
265 ) );
266 QWhatsThis::add( lMargin, QWhatsThis::textFor( sbMargin ) );
267 QWhatsThis::add( sbSpacing, i18n(
268 "The Item Spacing decides the distance (in pixels) between the items and anything else: the view "
269 "borders, other items or column separators."
270 ) );
271 QWhatsThis::add( lSpacing, QWhatsThis::textFor( sbSpacing ) );
272 QWhatsThis::add( sbSepWidth, i18n("Sets the width of column separators") );
273 QWhatsThis::add( lSW, QWhatsThis::textFor( sbSepWidth ) );
274
275 tabs->addTab( loTab, i18n("&Layout") );
276
277 // Colors
278 QVBox *colorTab = new QVBox( this, "colortab" );
279 colorTab->setSpacing( spacing );
280 colorTab->setMargin( spacing );
281 cbEnableCustomColors = new QCheckBox( i18n("&Enable custom Colors"), colorTab );
282 connect( cbEnableCustomColors, SIGNAL(clicked()), this, SLOT(enableColors()) );
283 lbColors = new ColorListBox( colorTab );
284 tabs->addTab( colorTab, i18n("&Colors") );
285
286 QWhatsThis::add( cbEnableCustomColors, i18n(
287 "If custom colors are enabled, you may choose the colors for the view below. "
288 "Otherwise colors from your current KDE color scheme are used."
289 ) );
290 QWhatsThis::add( lbColors, i18n(
291 "Double click or press RETURN on a item to select a color for the related strings in the view."
292 ) );
293
294 // Fonts
295 QVBox *fntTab = new QVBox( this, "fonttab" );
296
297 fntTab->setSpacing( spacing );
298 fntTab->setMargin( spacing );
299
300 cbEnableCustomFonts = new QCheckBox( i18n("&Enable custom fonts"), fntTab );
301 connect( cbEnableCustomFonts, SIGNAL(clicked()), this, SLOT(enableFonts()) );
302
303 vbFonts = new QWidget( fntTab );
304 QGridLayout *gFnts = new QGridLayout( vbFonts, 2, 3 );
305 gFnts->setSpacing( spacing );
306 gFnts->setAutoAdd( true );
307 gFnts->setColStretch( 1, 1 );
308 QLabel *lTFnt = new QLabel( i18n("&Text font:"), vbFonts );
309 lTextFont = new QLabel( vbFonts );
310 lTextFont->setFrameStyle( QFrame::Panel|QFrame::Sunken );
311#ifndef KAB_EMBEDDED
312 btnFont = new KPushButton( i18n("Choose..."), vbFonts );
313#else //KAB_EMBEDDED
314 btnFont = new QPushButton( i18n("Choose..."), vbFonts );
315#endif //KAB_EMBEDDED
316
317 lTFnt->setBuddy( btnFont );
318
319 connect( btnFont, SIGNAL(clicked()), this, SLOT(setTextFont()) );
320
321 QLabel *lHFnt = new QLabel( i18n("&Header font:"), vbFonts );
322 lHeaderFont = new QLabel( vbFonts );
323 lHeaderFont->setFrameStyle( QFrame::Panel|QFrame::Sunken );
324#ifndef KAB_EMBEDDED
325 btnHeaderFont = new KPushButton( i18n("Choose..."), vbFonts );
326#else //KAB_EMBEDDED
327 btnHeaderFont = new QPushButton( i18n("Choose..."), vbFonts );
328#endif //KAB_EMBEDDED
329 lHFnt->setBuddy( btnHeaderFont );
330 connect( btnHeaderFont, SIGNAL(clicked()), this, SLOT(setHeaderFont()) );
331
332 fntTab->setStretchFactor( new QWidget( fntTab ), 1 );
333
334 QWhatsThis::add( cbEnableCustomFonts, i18n(
335 "If custom fonts are enabled, you may choose which fonts to use for this view below. "
336 "Otherwise the default KDE font will be used, in bold style for the header and "
337 "normal style for the data."
338 ) );
339
340 tabs->addTab( fntTab, i18n("&Fonts") );
341
342 // Behaviour
343 QVBox *behaviourTab = new QVBox( this );
344 behaviourTab->setMargin( margin );
345 behaviourTab->setSpacing( spacing );
346
347 cbShowEmptyFields = new QCheckBox( i18n("Show &empty fields"), behaviourTab );
348 cbShowFieldLabels = new QCheckBox( i18n("Show field &labels"), behaviourTab );
349
350 behaviourTab->setStretchFactor( new QWidget( behaviourTab ), 1 );
351
352 tabs->addTab( behaviourTab, i18n("Be&havior") );
353
354}
355
356void CardViewLookNFeelPage::updateFontLabel( QFont fnt, QLabel *l )
357{
358 l->setFont( fnt );
359 l->setText( QString( fnt.family() + " %1" ).arg( fnt.pointSize() ) );
360}
361
362#ifndef KAB_EMBEDDED
363#include "configurecardviewdialog.moc"
364#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/configurecardviewdialog.h b/kaddressbook/views/configurecardviewdialog.h
new file mode 100644
index 0000000..7a62226
--- a/dev/null
+++ b/kaddressbook/views/configurecardviewdialog.h
@@ -0,0 +1,117 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#ifndef CONFIGURECARDVIEWDIALOG_H
25#define CONFIGURECARDVIEWDIALOG_H
26
27#include "viewconfigurewidget.h"
28
29#include <qvbox.h>
30#include <qwidget.h>
31#include <qfont.h>
32
33class QString;
34class QWidget;
35class QCheckBox;
36class QLabel;
37class KConfig;
38
39namespace KABC { class AddressBook; }
40
41class CardViewLookAndFeelPage;
42
43/**
44 Configure dialog for the card view. This dialog inherits from the
45 standard view dialog in order to add a custom page for the card
46 view.
47 */
48class ConfigureCardViewWidget : public ViewConfigureWidget
49{
50 public:
51 ConfigureCardViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name );
52 virtual ~ConfigureCardViewWidget();
53
54 virtual void restoreSettings( KConfig* );
55 virtual void saveSettings( KConfig* );
56
57 private:
58 class CardViewLookNFeelPage *mAdvancedPage;
59};
60
61/**
62 Card View Advanced LookNFeel settings widget:
63 this is a tabbed widget with 3 tabs:
64 Fonts
65 * text font
66 * header font
67
68 Colors
69 * background color
70 * text color
71 * highlight color
72 * title/sep text color
73 * title/sep bg color
74
75 Layout
76 * item margin
77 * item spacing
78*/
79
80class CardViewLookNFeelPage : public QVBox {
81
82 Q_OBJECT
83
84 public:
85 CardViewLookNFeelPage( QWidget *parent=0, const char *name=0 );
86 ~CardViewLookNFeelPage();
87
88 void restoreSettings( KConfig* );
89 void saveSettings( KConfig* );
90
91 private slots:
92 void setTextFont();
93 void setHeaderFont();
94 void enableFonts();
95 void enableColors();
96
97 private:
98 void initGUI();
99 void updateFontLabel( QFont, QLabel * );
100
101 QCheckBox *cbEnableCustomFonts,
102 *cbEnableCustomColors,
103 *cbDrawSeps, *cbDrawBorders,
104 *cbShowFieldLabels, *cbShowEmptyFields;
105 class ColorListBox *lbColors;
106 QLabel *lTextFont, *lHeaderFont;
107#ifndef KAB_EMBEDDED
108 class KPushButton *btnFont, *btnHeaderFont;
109#else //KAB_EMBEDDED
110 class QPushButton *btnFont, *btnHeaderFont;
111#endif //KAB_EMBEDDED
112 class QSpinBox *sbMargin, *sbSpacing, *sbSepWidth;
113
114 class QWidget *vbFonts;
115};
116
117#endif
diff --git a/kaddressbook/views/configuretableviewdialog.cpp b/kaddressbook/views/configuretableviewdialog.cpp
new file mode 100644
index 0000000..e1cc63e
--- a/dev/null
+++ b/kaddressbook/views/configuretableviewdialog.cpp
@@ -0,0 +1,155 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qstring.h>
25#include <qwidget.h>
26#include <qlayout.h>
27#include <qradiobutton.h>
28#include <qcheckbox.h>
29#include <qvbox.h>
30#include <qbuttongroup.h>
31
32#include <kglobal.h>
33#include <klocale.h>
34#include <klineedit.h>
35#include <kurlrequester.h>
36#include <kiconloader.h>
37
38#ifndef KAB_EMBEDDED
39#include <kimageio.h>
40#else //KAB_EMBEDDED
41#endif //KAB_EMBEDDED
42
43#include <kconfig.h>
44
45#include "configuretableviewdialog.h"
46
47ConfigureTableViewWidget::ConfigureTableViewWidget( KABC::AddressBook *ab,
48 QWidget *parent,
49 const char *name )
50 : ViewConfigureWidget( ab, parent, name )
51{
52 QWidget *page = addPage( i18n( "Look & Feel" ), QString::null,
53 KGlobal::iconLoader()->loadIcon( "looknfeel",
54 KIcon::Panel ) );
55
56 mPage = new LookAndFeelPage( page );
57}
58
59ConfigureTableViewWidget::~ConfigureTableViewWidget()
60{
61}
62
63void ConfigureTableViewWidget::restoreSettings( KConfig *config )
64{
65 ViewConfigureWidget::restoreSettings( config );
66
67 mPage->restoreSettings( config );
68}
69
70void ConfigureTableViewWidget::saveSettings( KConfig *config )
71{
72 ViewConfigureWidget::saveSettings( config );
73
74 mPage->saveSettings( config );
75}
76
77
78
79LookAndFeelPage::LookAndFeelPage(QWidget *parent, const char *name)
80 : QWidget(parent, name)
81{
82 initGUI();
83
84 // Set initial state
85 enableBackgroundToggled(mBackgroundBox->isChecked());
86}
87
88void LookAndFeelPage::restoreSettings( KConfig *config )
89{
90 mAlternateButton->setChecked(config->readBoolEntry("ABackground", true));
91 mLineButton->setChecked(config->readBoolEntry("SingleLine", false));
92 mToolTipBox->setChecked(config->readBoolEntry("ToolTips", true));
93
94 if (!mAlternateButton->isChecked() & !mLineButton->isChecked())
95 mNoneButton->setChecked(true);
96
97 mBackgroundBox->setChecked(config->readBoolEntry("Background", false));
98 mBackgroundName->lineEdit()->setText(config->readEntry("BackgroundName"));
99}
100
101void LookAndFeelPage::saveSettings( KConfig *config )
102{
103 config->writeEntry("ABackground", mAlternateButton->isChecked());
104 config->writeEntry("SingleLine", mLineButton->isChecked());
105 config->writeEntry("ToolTips", mToolTipBox->isChecked());
106 config->writeEntry("Background", mBackgroundBox->isChecked());
107 config->writeEntry("BackgroundName", mBackgroundName->lineEdit()->text());
108}
109
110void LookAndFeelPage::initGUI()
111{
112 QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialogBase::spacingHint());
113
114 QButtonGroup *group = new QButtonGroup(1, Qt::Horizontal,
115 i18n("Row Separator"), this);
116 layout->addWidget(group);
117
118 mAlternateButton = new QRadioButton(i18n("Alternating backgrounds"),
119 group, "mAlternateButton");
120 mLineButton = new QRadioButton(i18n("Single line"), group, "mLineButton");
121 mNoneButton = new QRadioButton(i18n("None"), group, "mNoneButton");
122
123 // Background Checkbox/Selector
124 QHBoxLayout *backgroundLayout = new QHBoxLayout();
125 layout->addLayout(backgroundLayout);
126
127 mBackgroundBox = new QCheckBox(i18n("Enable background image:"), this,
128 "mBackgroundBox");
129 connect(mBackgroundBox, SIGNAL(toggled(bool)),
130 SLOT(enableBackgroundToggled(bool)));
131 backgroundLayout->addWidget(mBackgroundBox);
132
133 mBackgroundName = new KURLRequester(this, "mBackgroundName");
134#ifndef KAB_EMBEDDED
135 mBackgroundName->setMode(KFile::File | KFile::ExistingOnly |
136 KFile::LocalOnly);
137 mBackgroundName->setFilter(KImageIO::pattern(KImageIO::Reading));
138#endif //KAB_EMBEDDED
139
140 backgroundLayout->addWidget(mBackgroundName);
141
142 // ToolTip Checkbox
143 mToolTipBox = new QCheckBox(i18n("Enable contact tooltips"), this,
144 "mToolTipBox");
145 layout->addWidget(mToolTipBox);
146}
147
148void LookAndFeelPage::enableBackgroundToggled(bool enabled)
149{
150 mBackgroundName->setEnabled(enabled);
151}
152
153#ifndef KAB_EMBEDDED
154#include "configuretableviewdialog.moc"
155#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/configuretableviewdialog.h b/kaddressbook/views/configuretableviewdialog.h
new file mode 100644
index 0000000..8392710
--- a/dev/null
+++ b/kaddressbook/views/configuretableviewdialog.h
@@ -0,0 +1,88 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#ifndef CONFIGURETABLEVIEWDIALOG_H
25#define CONFIGURETABLEVIEWDIALOG_H
26
27#include "viewconfigurewidget.h"
28
29class QString;
30class QWidget;
31class QRadioButton;
32class QCheckBox;
33class KURLRequester;
34class KConfig;
35
36namespace KABC { class AddressBook; }
37
38class LookAndFeelPage;
39
40/**
41 Configure dialog for the table view. This dialog inherits from the
42 standard view dialog in order to add a custom page for the table
43 view.
44 */
45class ConfigureTableViewWidget : public ViewConfigureWidget
46{
47 public:
48 ConfigureTableViewWidget( KABC::AddressBook *ab, QWidget *parent, const char *name );
49 virtual ~ConfigureTableViewWidget();
50
51 virtual void restoreSettings( KConfig* );
52 virtual void saveSettings( KConfig* );
53
54 private:
55 void initGUI();
56
57 LookAndFeelPage *mPage;
58};
59
60/**
61 Internal class. It is only defined here for moc
62*/
63class LookAndFeelPage : public QWidget
64{
65 Q_OBJECT
66
67 public:
68 LookAndFeelPage( QWidget *parent, const char *name = 0 );
69 ~LookAndFeelPage() {}
70
71 void restoreSettings( KConfig* );
72 void saveSettings( KConfig* );
73
74 protected slots:
75 void enableBackgroundToggled( bool );
76
77 private:
78 void initGUI();
79
80 QRadioButton *mAlternateButton;
81 QRadioButton *mLineButton;
82 QRadioButton *mNoneButton;
83 QCheckBox *mToolTipBox;
84 KURLRequester *mBackgroundName;
85 QCheckBox *mBackgroundBox;
86};
87
88#endif
diff --git a/kaddressbook/views/contactlistview.cpp b/kaddressbook/views/contactlistview.cpp
new file mode 100644
index 0000000..98b2fb2
--- a/dev/null
+++ b/kaddressbook/views/contactlistview.cpp
@@ -0,0 +1,340 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qheader.h>
25#include <qiconset.h>
26#include <qimage.h>
27#include <qdragobject.h>
28#include <qcombobox.h>
29#include <qpainter.h>
30#include <qbrush.h>
31#include <qevent.h>
32
33#include <klocale.h>
34#include <kglobalsettings.h>
35#include <kiconloader.h>
36#include <kdebug.h>
37#include <kconfig.h>
38#include <kapplication.h>
39#include <kurl.h>
40
41#include "kaddressbooktableview.h"
42
43#include "contactlistview.h"
44
45/////////////////////////////////
46// DynamicTip Methods
47
48DynamicTip::DynamicTip( ContactListView *parent)
49 : QToolTip( parent )
50{
51}
52
53void DynamicTip::maybeTip( const QPoint &pos )
54{
55 static bool ishidden = true;
56 if (!parentWidget()->inherits( "ContactListView" ))
57 return;
58
59 ContactListView *plv = (ContactListView*)parentWidget();
60 if (!plv->tooltips())
61 return;
62
63 QPoint posVp = plv->viewport()->pos();
64
65 QListViewItem *lvi = plv->itemAt( pos - posVp );
66 if (!lvi)
67 return;
68
69#ifndef KAB_EMBEDDED
70 ContactListViewItem *plvi = dynamic_cast< ContactListViewItem* >(lvi);
71#else //KAB_EMBEDDED
72 ContactListViewItem *plvi = (ContactListViewItem*)(lvi);
73#endif //KAB_EMBEDDED
74
75 if (!plvi)
76 return;
77
78 if (ishidden) {
79 QString s;
80 QRect r = plv->itemRect( lvi );
81 r.moveBy( posVp.x(), posVp.y() );
82
83 //kdDebug() << "Tip rec: " << r.x() << "," << r.y() << "," << r.width()
84 // << "," << r.height() << endl;
85
86 KABC::Addressee a = plvi->addressee();
87 if (a.isEmpty())
88 return;
89
90 s += i18n("label: value", "%1: %2").arg(a.formattedNameLabel())
91 .arg(a.formattedName());
92
93 s += '\n';
94 s += i18n("label: value", "%1: %2").arg(a.organizationLabel())
95 .arg(a.organization());
96
97 QString notes = a.note().stripWhiteSpace();
98 if ( !notes.isEmpty() ) {
99 notes += '\n';
100 s += '\n' + i18n("label: value", "%1: \n").arg(a.noteLabel());
101 QFontMetrics fm( font() );
102
103 // Begin word wrap code based on QMultiLineEdit code
104 int i = 0;
105 bool doBreak = false;
106 int linew = 0;
107 int lastSpace = -1;
108 int a = 0;
109 int lastw = 0;
110
111 while ( i < int(notes.length()) ) {
112 doBreak = FALSE;
113 if ( notes[i] != '\n' )
114 linew += fm.width( notes[i] );
115
116 if ( lastSpace >= a && notes[i] != '\n' )
117 if (linew >= parentWidget()->width()) {
118 doBreak = TRUE;
119 if ( lastSpace > a ) {
120 i = lastSpace;
121 linew = lastw;
122 }
123 else
124 i = QMAX( a, i-1 );
125 }
126
127 if ( notes[i] == '\n' || doBreak ) {
128 s += notes.mid( a, i - a + (doBreak?1:0) ) +"\n";
129
130 a = i + 1;
131 lastSpace = a;
132 linew = 0;
133 }
134
135 if ( notes[i].isSpace() ) {
136 lastSpace = i;
137 lastw = linew;
138 }
139
140 if ( lastSpace <= a ) {
141 lastw = linew;
142 }
143
144 ++i;
145 }
146 }
147
148 tip( r, s );
149 }
150 else
151 hide();
152 ishidden = !ishidden;
153
154}
155
156///////////////////////////
157// ContactListViewItem Methods
158
159ContactListViewItem::ContactListViewItem(const KABC::Addressee &a,
160 ContactListView *parent,
161 KABC::AddressBook *doc,
162 const KABC::Field::List &fields )
163 : KListViewItem(parent), mAddressee(a), mFields( fields ),
164 parentListView( parent ), mDocument(doc)
165{
166 refresh();
167}
168
169QString ContactListViewItem::key(int column, bool ascending) const
170{
171 return QListViewItem::key(column, ascending).lower();
172}
173
174void ContactListViewItem::paintCell(QPainter * p,
175 const QColorGroup & cg,
176 int column,
177 int width,
178 int align)
179{
180 KListViewItem::paintCell(p, cg, column, width, align);
181
182 if ( !p )
183 return;
184
185 if (parentListView->singleLine()) {
186 p->setPen( parentListView->alternateColor() );
187 p->drawLine( 0, height() - 1, width, height() - 1 );
188 }
189}
190
191
192ContactListView *ContactListViewItem::parent()
193{
194 return parentListView;
195}
196
197
198void ContactListViewItem::refresh()
199{
200 // Update our addressee, since it may have changed else were
201 mAddressee = mDocument->findByUid(mAddressee.uid());
202 if (mAddressee.isEmpty())
203 return;
204
205 int i = 0;
206 KABC::Field::List::ConstIterator it;
207 for( it = mFields.begin(); it != mFields.end(); ++it ) {
208 setText( i++, (*it)->value( mAddressee ) );
209 }
210}
211
212///////////////////////////////
213// ContactListView
214
215ContactListView::ContactListView(KAddressBookTableView *view,
216 KABC::AddressBook* /* doc */,
217 QWidget *parent,
218 const char *name )
219 : KListView( parent, name ),
220 pabWidget( view ),
221 oldColumn( 0 )
222{
223 mABackground = true;
224 mSingleLine = false;
225 mToolTips = true;
226#ifndef KAB_EMBEDDED
227 mAlternateColor = KGlobalSettings::alternateBackgroundColor();
228#else //KAB_EMBEDDED
229 mAlternateColor = QColor(240, 240, 240);
230#endif //KAB_EMBEDDED
231
232 setAlternateBackgroundEnabled(mABackground);
233 setAcceptDrops( true );
234 viewport()->setAcceptDrops( true );
235 setAllColumnsShowFocus( true );
236 setShowSortIndicator(true);
237
238 setSelectionModeExt( KListView::Extended );
239 setDropVisualizer(false);
240 // setFrameStyle(QFrame::NoFrame);
241 setLineWidth ( 0 );
242 setMidLineWidth ( 0 );
243 setMargin ( 0 );
244#ifndef KAB_EMBEDDED
245 connect(this, SIGNAL(dropped(QDropEvent*)),
246 this, SLOT(itemDropped(QDropEvent*)));
247#endif //KAB_EMBEDDED
248
249
250 new DynamicTip( this );
251}
252
253void ContactListView::paintEmptyArea( QPainter * p, const QRect & rect )
254{
255 QBrush b = palette().brush(QPalette::Active, QColorGroup::Base);
256
257 // Get the brush, which will have the background pixmap if there is one.
258 if (b.pixmap())
259 {
260 p->drawTiledPixmap( rect.left(), rect.top(), rect.width(), rect.height(),
261 *(b.pixmap()),
262 rect.left() + contentsX(),
263 rect.top() + contentsY() );
264 }
265
266 else
267 {
268 // Do a normal paint
269 KListView::paintEmptyArea(p, rect);
270 }
271}
272
273void ContactListView::contentsMousePressEvent(QMouseEvent* e)
274{
275 presspos = e->pos();
276 KListView::contentsMousePressEvent(e);
277}
278
279
280// To initiate a drag operation
281void ContactListView::contentsMouseMoveEvent( QMouseEvent *e )
282{
283 if ((e->state() & LeftButton) && (e->pos() - presspos).manhattanLength() > 4 ) {
284 emit startAddresseeDrag();
285 }
286 else
287 KListView::contentsMouseMoveEvent( e );
288}
289
290bool ContactListView::acceptDrag(QDropEvent *e) const
291{
292#ifndef KAB_EMBEDDED
293 return QTextDrag::canDecode(e);
294#else //KAB_EMBEDDED
295qDebug("ContactListView::acceptDrag has to be fixed");
296 return false;
297#endif //KAB_EMBEDDED
298}
299
300void ContactListView::itemDropped(QDropEvent *e)
301{
302 contentsDropEvent(e);
303}
304
305void ContactListView::contentsDropEvent( QDropEvent *e )
306{
307 emit addresseeDropped(e);
308}
309
310void ContactListView::setAlternateBackgroundEnabled(bool enabled)
311{
312 mABackground = enabled;
313
314 if (mABackground)
315 {
316 setAlternateBackground(mAlternateColor);
317 }
318 else
319 {
320 setAlternateBackground(QColor());
321 }
322}
323
324void ContactListView::setBackgroundPixmap(const QString &filename)
325{
326 if (filename.isEmpty())
327 {
328 unsetPalette();
329 }
330 else
331 {
332 qDebug("ContactListView::setBackgroundPixmap has to be verified");
333//US setPaletteBackgroundPixmap(QPixmap(filename));
334 KListView::setBackgroundPixmap((const QPixmap&)QPixmap(filename));
335 }
336
337}
338#ifndef KAB_EMBEDDED
339#include "contactlistview.moc"
340#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/contactlistview.h b/kaddressbook/views/contactlistview.h
new file mode 100644
index 0000000..ae9c994
--- a/dev/null
+++ b/kaddressbook/views/contactlistview.h
@@ -0,0 +1,128 @@
1#ifndef CONTACTLISTVIEW_H
2#define CONTACTLISTVIEW_H
3
4#include <qcolor.h>
5#include <qpixmap.h>
6#include <qtooltip.h>
7#include <qstring.h>
8
9#include <klistview.h>
10
11#include <kabc/field.h>
12#include <kabc/addressee.h>
13#include <kabc/addressbook.h>
14
15
16class QDropEvent;
17class KAddressBookTableView;
18class ContactListView;
19
20/** The whole tooltip design needs a lot of work. Currently it is
21* hacked together to function.
22*/
23class DynamicTip : public QToolTip
24{
25 public:
26 DynamicTip( ContactListView * parent );
27
28 protected:
29 void maybeTip( const QPoint & );
30
31 private:
32};
33
34class ContactListViewItem : public KListViewItem
35{
36
37public:
38 ContactListViewItem(const KABC::Addressee &a, ContactListView* parent,
39 KABC::AddressBook *doc, const KABC::Field::List &fields );
40 const KABC::Addressee &addressee() const { return mAddressee; }
41 virtual void refresh();
42 virtual ContactListView* parent();
43 virtual QString key ( int, bool ) const;
44
45 /** Adds the border around the cell if the user wants it.
46 * This is how the single line config option is implemented.
47 */
48 virtual void paintCell(QPainter * p, const QColorGroup & cg,
49 int column, int width, int align );
50
51private:
52 KABC::Addressee mAddressee;
53 KABC::Field::List mFields;
54 ContactListView *parentListView;
55 KABC::AddressBook *mDocument;
56};
57
58
59/////////////////////////////////////////////
60// ContactListView
61
62class ContactListView : public KListView
63{
64 Q_OBJECT
65
66public:
67 ContactListView(KAddressBookTableView *view,
68 KABC::AddressBook *doc,
69 QWidget *parent,
70 const char *name = 0L );
71 virtual ~ContactListView() {}
72 //void resort();
73
74 /** Returns true if tooltips should be displayed, false otherwise
75 */
76 bool tooltips() const { return mToolTips; }
77 void setToolTipsEnabled(bool enabled) { mToolTips = enabled; }
78
79 bool alternateBackground() const { return mABackground; }
80 void setAlternateBackgroundEnabled(bool enabled);
81
82 bool singleLine() const { return mSingleLine; }
83 void setSingleLineEnabled(bool enabled) { mSingleLine = enabled; }
84
85 const QColor &alternateColor() const { return mAlternateColor; }
86
87 /** Sets the background pixmap to <i>filename</i>. If the
88 * QString is empty (QString::isEmpty()), then the background
89 * pixmap will be disabled.
90 */
91 void setBackgroundPixmap(const QString &filename);
92
93protected:
94 /** Paints the background pixmap in the empty area. This method is needed
95 * since Qt::FixedPixmap will not scroll with the list view.
96 */
97 virtual void paintEmptyArea( QPainter * p, const QRect & rect );
98 virtual void contentsMousePressEvent(QMouseEvent*);
99 void contentsMouseMoveEvent( QMouseEvent *e );
100 void contentsDropEvent( QDropEvent *e );
101 virtual bool acceptDrag(QDropEvent *e) const;
102
103protected slots:
104 void itemDropped(QDropEvent *e);
105
106public slots:
107
108signals:
109 void startAddresseeDrag();
110 void addresseeDropped(QDropEvent *);
111
112private:
113 KAddressBookTableView *pabWidget;
114 int oldColumn;
115 int column;
116 bool ascending;
117
118 bool mABackground;
119 bool mSingleLine;
120 bool mToolTips;
121
122 QColor mAlternateColor;
123
124 QPoint presspos;
125};
126
127
128#endif
diff --git a/kaddressbook/views/kaddressbookcardview.cpp b/kaddressbook/views/kaddressbookcardview.cpp
new file mode 100644
index 0000000..239429f
--- a/dev/null
+++ b/kaddressbook/views/kaddressbookcardview.cpp
@@ -0,0 +1,394 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#include <qdragobject.h>
25#include <qevent.h>
26#include <qiconview.h>
27#include <qlayout.h>
28#include <qstringlist.h>
29
30#include <kabc/addressbook.h>
31#include <kabc/addressee.h>
32#include <kconfig.h>
33#include <kdebug.h>
34#include <klocale.h>
35
36#include "kabprefs.h"
37#include "viewmanager.h"
38
39#include "kaddressbookcardview.h"
40
41#ifndef KAB_EMBEDDED
42extern "C" {
43 void *init_libkaddrbk_cardview()
44 {
45 return ( new CardViewFactory );
46 }
47}
48#endif //KAB_EMBEDDED
49
50////////////////////////////////
51// AddresseeCardViewItem (internal class)
52class AddresseeCardViewItem : public CardViewItem
53{
54 public:
55 AddresseeCardViewItem(const KABC::Field::List &fields,
56 bool showEmptyFields,
57 KABC::AddressBook *doc, const KABC::Addressee &a,
58 CardView *parent)
59 : CardViewItem(parent, a.formattedName()),
60 mFields( fields ), mShowEmptyFields(showEmptyFields),
61 mDocument(doc), mAddressee(a)
62 {
63 if ( mFields.isEmpty() ) {
64 mFields = KABC::Field::defaultFields();
65 }
66 refresh();
67 }
68
69 const KABC::Addressee &addressee() const { return mAddressee; }
70
71 void refresh()
72 {
73 // Update our addressee, since it may have changed elsewhere
74 mAddressee = mDocument->findByUid(mAddressee.uid());
75
76 if (!mAddressee.isEmpty())
77 {
78 clearFields();
79
80 // Try all the selected fields until we find one with text.
81 // This will limit the number of unlabeled icons in the view
82 KABC::Field::List::Iterator iter;
83 for (iter = mFields.begin(); iter != mFields.end(); ++iter)
84 {
85 // insert empty fields or not? not doing so saves a bit of memory and CPU
86 // (during geometry calculations), but prevents having equally
87 // wide label columns in all cards, unless CardViewItem/CardView search
88 // globally for the widest label. (anders)
89 //if (mShowEmptyFields || !(*iter)->value( mAddressee ).isEmpty())
90 insertField((*iter)->label(), (*iter)->value( mAddressee ));
91 }
92
93 // We might want to make this the first field. hmm... -mpilone
94 setCaption( mAddressee.realName() );
95 }
96 }
97
98 private:
99 KABC::Field::List mFields;
100 bool mShowEmptyFields;
101 KABC::AddressBook *mDocument;
102 KABC::Addressee mAddressee;
103};
104
105///////////////////////////////
106// AddresseeCardView
107
108AddresseeCardView::AddresseeCardView(QWidget *parent, const char *name)
109 : CardView(parent, name)
110{
111 setAcceptDrops(true);
112}
113
114AddresseeCardView::~AddresseeCardView()
115{
116}
117
118void AddresseeCardView::dragEnterEvent(QDragEnterEvent *e)
119{
120#ifndef KAB_EMBEDDED
121 if (QTextDrag::canDecode(e))
122 e->accept();
123#else //KAB_EMBEDDED
124qDebug("AddresseeCardView::dragEnterEvent drag&drop is not implemented");
125#endif //KAB_EMBEDDED
126}
127
128void AddresseeCardView::dropEvent(QDropEvent *e)
129{
130 emit addresseeDropped(e);
131}
132
133void AddresseeCardView::startDrag()
134{
135 emit startAddresseeDrag();
136}
137
138
139///////////////////////////////
140// KAddressBookCardView
141
142KAddressBookCardView::KAddressBookCardView( KABC::AddressBook *ab,
143 QWidget *parent, const char *name )
144 : KAddressBookView( ab, parent, name )
145{
146 mShowEmptyFields = false;
147
148 // Init the GUI
149 QVBoxLayout *layout = new QVBoxLayout(viewWidget());
150
151 mCardView = new AddresseeCardView(viewWidget(), "mCardView");
152 mCardView->setSelectionMode(CardView::Extended);
153 layout->addWidget(mCardView);
154
155 // Connect up the signals
156 connect(mCardView, SIGNAL(executed(CardViewItem *)),
157 this, SLOT(addresseeExecuted(CardViewItem *)));
158 connect(mCardView, SIGNAL(selectionChanged()),
159 this, SLOT(addresseeSelected()));
160 connect(mCardView, SIGNAL(addresseeDropped(QDropEvent*)),
161 this, SIGNAL(dropped(QDropEvent*)));
162 connect(mCardView, SIGNAL(startAddresseeDrag()),
163 this, SIGNAL(startDrag()));
164}
165
166KAddressBookCardView::~KAddressBookCardView()
167{
168}
169
170void KAddressBookCardView::readConfig(KConfig *config)
171{
172 KAddressBookView::readConfig(config);
173
174 // costum colors?
175 if ( config->readBoolEntry( "EnableCustomColors", false ) )
176 {
177 QPalette p( mCardView->palette() );
178 QColor c = p.color(QPalette::Normal, QColorGroup::Base );
179 p.setColor( QPalette::Normal, QColorGroup::Base, config->readColorEntry( "BackgroundColor", &c ) );
180 c = p.color(QPalette::Normal, QColorGroup::Text );
181 p.setColor( QPalette::Normal, QColorGroup::Text, config->readColorEntry( "TextColor", &c ) );
182 c = p.color(QPalette::Normal, QColorGroup::Button );
183 p.setColor( QPalette::Normal, QColorGroup::Button, config->readColorEntry( "HeaderColor", &c ) );
184 c = p.color(QPalette::Normal, QColorGroup::ButtonText );
185 p.setColor( QPalette::Normal, QColorGroup::ButtonText, config->readColorEntry( "HeaderTextColor", &c ) );
186 c = p.color(QPalette::Normal, QColorGroup::Highlight );
187 p.setColor( QPalette::Normal, QColorGroup::Highlight, config->readColorEntry( "HighlightColor", &c ) );
188 c = p.color(QPalette::Normal, QColorGroup::HighlightedText );
189 p.setColor( QPalette::Normal, QColorGroup::HighlightedText, config->readColorEntry( "HighlightedTextColor", &c ) );
190 mCardView->viewport()->setPalette( p );
191 }
192 else
193 {
194 // needed if turned off during a session.
195 mCardView->viewport()->setPalette( mCardView->palette() );
196 }
197
198 //custom fonts?
199 QFont f( font() );
200 if ( config->readBoolEntry( "EnableCustomFonts", false ) )
201 {
202 mCardView->setFont( config->readFontEntry( "TextFont", &f) );
203 f.setBold( true );
204 mCardView->setHeaderFont( config->readFontEntry( "HeaderFont", &f ) );
205 }
206 else
207 {
208 mCardView->setFont( f );
209 f.setBold( true );
210 mCardView->setHeaderFont( f );
211 }
212
213 mCardView->setDrawCardBorder(config->readBoolEntry("DrawBorder", true));
214 mCardView->setDrawColSeparators(config->readBoolEntry("DrawSeparators",
215 true));
216 mCardView->setDrawFieldLabels(config->readBoolEntry("DrawFieldLabels",false));
217 mShowEmptyFields = config->readBoolEntry("ShowEmptyFields", false);
218
219 mCardView->setShowEmptyFields( mShowEmptyFields );
220
221 mCardView->setItemWidth( config->readNumEntry( "ItemWidth", 200 ) );
222 mCardView->setItemMargin( config->readNumEntry( "ItemMargin", 0 ) );
223 mCardView->setItemSpacing( config->readNumEntry( "ItemSpacing", 10 ) );
224 mCardView->setSeparatorWidth( config->readNumEntry( "SeparatorWidth", 2 ) );
225
226 disconnect(mCardView, SIGNAL(executed(CardViewItem *)),
227 this, SLOT(addresseeExecuted(CardViewItem *)));
228
229 if (KABPrefs::instance()->mHonorSingleClick)
230 connect(mCardView, SIGNAL(executed(CardViewItem *)),
231 this, SLOT(addresseeExecuted(CardViewItem *)));
232 else
233 connect(mCardView, SIGNAL(doubleClicked(CardViewItem *)),
234 this, SLOT(addresseeExecuted(CardViewItem *)));
235
236}
237
238void KAddressBookCardView::writeConfig( KConfig *config )
239{
240 config->writeEntry( "ItemWidth", mCardView->itemWidth() );
241 KAddressBookView::writeConfig( config );
242}
243
244QStringList KAddressBookCardView::selectedUids()
245{
246 QStringList uidList;
247 CardViewItem *item;
248 AddresseeCardViewItem *aItem;
249
250 for (item = mCardView->firstItem(); item; item = item->nextItem())
251 {
252 if (item->isSelected())
253 {
254#ifndef KAB_EMBEDDED
255 aItem = dynamic_cast<AddresseeCardViewItem*>(item);
256#else //KAB_EMBEDDED
257 aItem = (AddresseeCardViewItem*)(item);
258#endif //KAB_EMBEDDED
259 if (aItem)
260 uidList << aItem->addressee().uid();
261 }
262 }
263
264 return uidList;
265}
266
267void KAddressBookCardView::refresh(QString uid)
268{
269 CardViewItem *item;
270 AddresseeCardViewItem *aItem;
271
272 if (uid.isNull())
273 {
274 // Rebuild the view
275 mCardView->viewport()->setUpdatesEnabled( false );
276 mCardView->clear();
277
278 KABC::Addressee::List addresseeList = addressees();
279 KABC::Addressee::List::Iterator iter;
280 for (iter = addresseeList.begin(); iter != addresseeList.end(); ++iter)
281 {
282 aItem = new AddresseeCardViewItem(fields(), mShowEmptyFields,
283 addressBook(), *iter, mCardView);
284 }
285 mCardView->viewport()->setUpdatesEnabled( true );
286 mCardView->viewport()->update();
287
288 // by default nothing is selected
289 emit selected(QString::null);
290 }
291 else
292 {
293 // Try to find the one to refresh
294 bool found = false;
295 for (item = mCardView->firstItem(); item && !found;
296 item = item->nextItem())
297 {
298#ifndef KAB_EMBEDDED
299 aItem = dynamic_cast<AddresseeCardViewItem*>(item);
300#else //KAB_EMBEDDED
301 aItem = (AddresseeCardViewItem*)(item);
302#endif //KAB_EMBEDDED
303
304 if ((aItem) && (aItem->addressee().uid() == uid))
305 {
306 aItem->refresh();
307 found = true;
308 }
309 }
310 }
311}
312
313void KAddressBookCardView::setSelected(QString uid, bool selected)
314{
315 CardViewItem *item;
316 AddresseeCardViewItem *aItem;
317
318 if (uid.isNull())
319 {
320 mCardView->selectAll(selected);
321 }
322 else
323 {
324 bool found = false;
325 for (item = mCardView->firstItem(); item && !found;
326 item = item->nextItem())
327 {
328#ifndef KAB_EMBEDDED
329 aItem = dynamic_cast<AddresseeCardViewItem*>(item);
330#else //KAB_EMBEDDED
331 aItem = (AddresseeCardViewItem*)(item);
332#endif //KAB_EMBEDDED
333
334 if ((aItem) && (aItem->addressee().uid() == uid))
335 {
336 mCardView->setSelected(aItem, selected);
337 mCardView->ensureItemVisible(item);
338 found = true;
339 }
340 }
341 }
342}
343
344//US added an additional method without parameter
345void KAddressBookCardView::setSelected()
346{
347 setSelected(QString::null, true);
348}
349
350void KAddressBookCardView::addresseeExecuted(CardViewItem *item)
351{
352#ifndef KAB_EMBEDDED
353 AddresseeCardViewItem *aItem = dynamic_cast<AddresseeCardViewItem*>(item);
354#else //KAB_EMBEDDED
355 AddresseeCardViewItem *aItem = (AddresseeCardViewItem*)(item);
356#endif //KAB_EMBEDDED
357 if (aItem)
358 {
359 //kdDebug()<<"... even has a valid item:)"<<endl;
360 emit executed(aItem->addressee().uid());
361 }
362}
363
364void KAddressBookCardView::addresseeSelected()
365{
366 CardViewItem *item;
367 AddresseeCardViewItem *aItem;
368
369 bool found = false;
370 for (item = mCardView->firstItem(); item && !found;
371 item = item->nextItem())
372 {
373 if (item->isSelected())
374 {
375#ifndef KAB_EMBEDDED
376 aItem = dynamic_cast<AddresseeCardViewItem*>(item);
377#else //KAB_EMBEDDED
378 aItem = (AddresseeCardViewItem*)(item);
379#endif //KAB_EMBEDDED
380 if ( aItem )
381 {
382 emit selected(aItem->addressee().uid());
383 found = true;
384 }
385 }
386 }
387
388 if (!found)
389 emit selected(QString::null);
390
391}
392#ifndef KAB_EMBEDDED
393#include "kaddressbookcardview.moc"
394#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/kaddressbookcardview.h b/kaddressbook/views/kaddressbookcardview.h
new file mode 100644
index 0000000..cd70371
--- a/dev/null
+++ b/kaddressbook/views/kaddressbookcardview.h
@@ -0,0 +1,117 @@
1#ifndef KADDRESSBOOKCARDVIEW_H
2#define KADDRESSBOOKCARDVIEW_H
3
4/*
5 This file is part of KAddressBook.
6 Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 As a special exception, permission is given to link this program
23 with any edition of Qt, and distribute the resulting executable,
24 without including the source code for Qt in the source distribution.
25*/
26
27#include <qstring.h>
28#ifndef KAB_EMBEDDED
29#include <kiconview.h>
30#else //KAB_EMBEDDED
31#include <klocale.h>
32#endif //KAB_EMBEDDED
33
34#include "cardview.h"
35#include "kaddressbookview.h"
36#include "configurecardviewdialog.h"
37
38class QDragEnterEvent;
39class QDragEntryEvent;
40class QDropEvent;
41class KConfig;
42class AddresseeCardView;
43
44/**
45 This view uses the CardView class to create a card view. At some
46 point in the future I think this will be the default view of
47 KAddressBook.
48 */
49class KAddressBookCardView : public KAddressBookView
50{
51 Q_OBJECT
52
53 public:
54 KAddressBookCardView( KABC::AddressBook *ab, QWidget *parent,
55 const char *name = 0 );
56 virtual ~KAddressBookCardView();
57
58 virtual QStringList selectedUids();
59 virtual QString type() const { return "Card"; }
60
61 virtual void readConfig(KConfig *config);
62 virtual void writeConfig(KConfig *);
63
64 public slots:
65 void refresh(QString uid = QString::null);
66 void setSelected(QString uid/*US = QString::null*/, bool selected/*US = true*/);
67//US added an additional method without parameter
68 void setSelected();
69
70 protected slots:
71 void addresseeExecuted(CardViewItem *item);
72 void addresseeSelected();
73
74 private:
75 AddresseeCardView *mCardView;
76 bool mShowEmptyFields;
77};
78
79class AddresseeCardView : public CardView
80{
81 Q_OBJECT
82 public:
83 AddresseeCardView(QWidget *parent, const char *name = 0);
84 ~AddresseeCardView();
85
86 signals:
87 void startAddresseeDrag();
88 void addresseeDropped(QDropEvent *);
89
90 protected:
91 virtual void dragEnterEvent(QDragEnterEvent *);
92 virtual void dropEvent(QDropEvent *);
93 virtual void startDrag();
94};
95
96
97class CardViewFactory : public ViewFactory
98{
99 public:
100 KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name )
101 {
102 return new KAddressBookCardView( ab, parent, name );
103 }
104
105 QString type() const { return "Card"; }
106
107 QString description() const { return i18n( "Rolodex style cards represent contacts." ); }
108
109 ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent,
110 const char *name = 0 )
111 {
112 return new ConfigureCardViewWidget( ab, parent, name );
113 }
114};
115
116
117#endif
diff --git a/kaddressbook/views/kaddressbookiconview.cpp b/kaddressbook/views/kaddressbookiconview.cpp
new file mode 100644
index 0000000..50ff285
--- a/dev/null
+++ b/kaddressbook/views/kaddressbookiconview.cpp
@@ -0,0 +1,378 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#ifndef KAB_EMBEDDED
25#include <qiconview.h>
26#include <qstringlist.h>
27
28#include <kabc/addressee.h>
29#include <kconfig.h>
30#include <kdebug.h>
31#include <kglobal.h>
32#include <kiconloader.h>
33#include <klocale.h>
34
35#else //KAB_EMBEDDED
36#endif //KAB_EMBEDDED
37
38#include <kabc/addressbook.h>
39#include "kabprefs.h"
40#include "viewmanager.h"
41#include "kaddressbookiconview.h"
42#include <qlayout.h>
43#include <kglobal.h>
44/*US transfered to the headerfile
45class IconViewFactory : public ViewFactory
46{
47 public:
48 KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name )
49 {
50 return new KAddressBookIconView( ab, parent, name );
51 }
52
53 QString type() const { return "Icon"; }
54
55 QString description() const { return i18n( "Icons represent contacts. Very simple view." ); }
56};
57
58*/
59
60extern "C" {
61 void *init_libkaddrbk_iconview()
62 {
63 return ( new IconViewFactory );
64 }
65}
66
67////////////////////////////////
68// AddresseeIconView (internal class)
69#ifndef KAB_EMBEDDED
70AddresseeIconView::AddresseeIconView(QWidget *parent, const char *name)
71 : KIconView(parent, name)
72#else //KAB_EMBEDDED
73AddresseeIconView::AddresseeIconView(QWidget *parent, const char *name)
74 : QIconView(parent, name)
75#endif //KAB_EMBEDDED
76
77{
78 setSelectionMode( QIconView::Extended );
79 setResizeMode( QIconView::Adjust );
80 setWordWrapIconText( true );
81 setGridX( 100 );
82 setItemsMovable(false);
83 setSorting(true, true);
84
85
86//US ??? setMode( KIconView::Select );
87
88#ifndef KAB_EMBEDDED
89
90 connect(this, SIGNAL(dropped(QDropEvent*, const QValueList<QIconDragItem>&)),
91 this, SLOT(itemDropped(QDropEvent*, const QValueList<QIconDragItem>&)));
92#endif //KAB_EMBEDDED
93}
94
95AddresseeIconView::~AddresseeIconView()
96{
97}
98
99void AddresseeIconView::itemDropped(QDropEvent *e,
100 const QValueList<QIconDragItem> &)
101{
102 emit addresseeDropped(e);
103}
104
105QDragObject *AddresseeIconView::dragObject()
106{
107 emit startAddresseeDrag();
108
109 // We never want IconView to start the drag
110 return 0;
111}
112////////////////////////////////
113// AddresseeIconViewItem (internal class)
114#ifndef KAB_EMBEDDED
115class AddresseeIconViewItem : public KIconViewItem
116#else //KAB_EMBEDDED
117class AddresseeIconViewItem : public QIconViewItem
118#endif //KAB_EMBEDDED
119{
120 public:
121#ifndef KAB_EMBEDDED
122 AddresseeIconViewItem(const KABC::Field::List &fields,
123 KABC::AddressBook *doc, const KABC::Addressee &a,
124 QIconView *parent)
125 : KIconViewItem(parent), mFields( fields ), mDocument(doc), mAddressee(a)
126#else //KAB_EMBEDDED
127 AddresseeIconViewItem(const KABC::Field::List &fields,
128 KABC::AddressBook *doc, const KABC::Addressee &a,
129 QIconView *parent)
130 : QIconViewItem(parent), mFields( fields ), mDocument(doc), mAddressee(a)
131#endif //KAB_EMBEDDED
132 {
133 if ( mFields.isEmpty() ) {
134 mFields = KABC::Field::defaultFields();
135 }
136 refresh();
137 }
138
139 const KABC::Addressee &addressee() const { return mAddressee; }
140
141 void refresh()
142 {
143 // Update our addressee, since it may have changed elsewhere
144 mAddressee = mDocument->findByUid(mAddressee.uid());
145
146 if (!mAddressee.isEmpty())
147 setText( mAddressee.givenName() + " " + mAddressee.familyName() );
148
149 QPixmap icon;
150 QPixmap defaultIcon( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop, 128 ) );
151 KABC::Picture pic = mAddressee.photo();
152 if ( pic.data().isNull() )
153 pic = mAddressee.logo();
154
155 if ( pic.isIntern() && !pic.data().isNull() ) {
156 QImage img = pic.data();
157#ifndef KAB_EMBEDDED
158 if ( img.width() > img.height() )
159 icon = img.scaleWidth( 32 );
160 else
161 icon = img.scaleHeight( 32 );
162#else //KAB_EMBEDDED
163 qDebug("AddresseeIconViewItem::refresh - scale here dependend of the displaysize and the right factor");
164 icon.convertFromImage(img.smoothScale(32, 32));
165#endif //KAB_EMBEDDED
166
167 } else
168 icon = defaultIcon;
169
170 setPixmap( icon );
171 }
172
173 private:
174 KABC::Field::List mFields;
175 KABC::AddressBook *mDocument;
176 KABC::Addressee mAddressee;
177};
178
179///////////////////////////////
180// KAddressBookView
181
182KAddressBookIconView::KAddressBookIconView( KABC::AddressBook *ab,
183 QWidget *parent, const char *name)
184 : KAddressBookView( ab, parent, name )
185{
186 // Init the GUI
187 QVBoxLayout *layout = new QVBoxLayout(viewWidget());
188
189 mIconView = new AddresseeIconView(viewWidget(), "mIconView");
190 layout->addWidget(mIconView);
191
192 // Connect up the signals
193
194//US method executed is part of KIconView
195//US connect(mIconView, SIGNAL(executed(QIconViewItem *)),
196//US this, SLOT(addresseeExecuted(QIconViewItem *)));
197 connect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)),
198 this, SLOT(addresseeExecuted(QIconViewItem *)));
199
200 connect(mIconView, SIGNAL(selectionChanged()),
201 this, SLOT(addresseeSelected()));
202 connect(mIconView, SIGNAL(addresseeDropped(QDropEvent*)),
203 this, SIGNAL(dropped(QDropEvent*)));
204 connect(mIconView, SIGNAL(startAddresseeDrag()),
205 this, SIGNAL(startDrag()));
206}
207
208KAddressBookIconView::~KAddressBookIconView()
209{
210}
211
212void KAddressBookIconView::readConfig(KConfig *config)
213{
214 KAddressBookView::readConfig(config);
215
216//US method executed is part of KIconView
217//US disconnect(mIconView, SIGNAL(executed(QIconViewItem *)),
218//US this, SLOT(addresseeExecuted(QIconViewItem *)));
219 disconnect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)),
220 this, SLOT(addresseeExecuted(QIconViewItem *)));
221
222//US method executed is part of KIconView. Use selectionChanged instead
223/*US
224 if (KABPrefs::instance()->mHonorSingleClick)
225 connect(mIconView, SIGNAL(executed(QIconViewItem *)),
226 this, SLOT(addresseeExecuted(QIconViewItem *)));
227 else
228 connect(mIconView, SIGNAL(doubleClicked(QIconViewItem *)),
229 this, SLOT(addresseeExecuted(QIconViewItem *)));
230*/
231 connect(mIconView, SIGNAL(selectionChanged(QIconViewItem *)),
232 this, SLOT(addresseeExecuted(QIconViewItem *)));
233
234}
235
236QStringList KAddressBookIconView::selectedUids()
237{
238 QStringList uidList;
239 QIconViewItem *item;
240 AddresseeIconViewItem *aItem;
241
242 for (item = mIconView->firstItem(); item; item = item->nextItem())
243 {
244 if (item->isSelected())
245 {
246#ifndef KAB_EMBEDDED
247 aItem = dynamic_cast<AddresseeIconViewItem*>(item);
248#else //KAB_EMBEDDED
249 aItem = (AddresseeIconViewItem*)(item);
250#endif //KAB_EMBEDDED
251 if (aItem)
252 uidList << aItem->addressee().uid();
253 }
254 }
255
256 return uidList;
257}
258
259void KAddressBookIconView::refresh(QString uid)
260{
261 QIconViewItem *item;
262 AddresseeIconViewItem *aItem;
263
264 if ( uid.isNull() ) {
265 // Rebuild the view
266 mIconView->clear();
267 mIconList.clear();
268
269 KABC::Addressee::List addresseeList = addressees();
270 KABC::Addressee::List::Iterator iter;
271 for ( iter = addresseeList.begin(); iter != addresseeList.end(); ++iter )
272 aItem = new AddresseeIconViewItem( fields(), addressBook(), *iter, mIconView );
273
274 mIconView->arrangeItemsInGrid( true );
275
276 for ( item = mIconView->firstItem(); item; item = item->nextItem() )
277 {
278#ifndef KAB_EMBEDDED
279 AddresseeIconViewItem* aivi = dynamic_cast<AddresseeIconViewItem*>( item );
280#else //KAB_EMBEDDED
281 AddresseeIconViewItem* aivi = (AddresseeIconViewItem*)( item );
282#endif //KAB_EMBEDDED
283 mIconList.append( aivi );
284 }
285
286 } else {
287 // Try to find the one to refresh
288 for ( item = mIconView->firstItem(); item; item = item->nextItem() ) {
289#ifndef KAB_EMBEDDED
290 aItem = dynamic_cast<AddresseeIconViewItem*>(item);
291#else //KAB_EMBEDDED
292 aItem = (AddresseeIconViewItem*)(item);
293#endif //KAB_EMBEDDED
294 if ((aItem) && (aItem->addressee().uid() == uid)) {
295 aItem->refresh();
296 mIconView->arrangeItemsInGrid( true );
297 return;
298 }
299 }
300 refresh( QString::null );
301 }
302}
303
304void KAddressBookIconView::setSelected(QString uid, bool selected)
305{
306 QIconViewItem *item;
307 AddresseeIconViewItem *aItem;
308
309 if (uid.isNull())
310 {
311 mIconView->selectAll(selected);
312 }
313 else
314 {
315 bool found = false;
316 for (item = mIconView->firstItem(); item && !found;
317 item = item->nextItem())
318 {
319#ifndef KAB_EMBEDDED
320 aItem = dynamic_cast<AddresseeIconViewItem*>(item);
321#else //KAB_EMBEDDED
322 aItem = (AddresseeIconViewItem*)(item);
323#endif //KAB_EMBEDDED
324
325 if ((aItem) && (aItem->addressee().uid() == uid))
326 {
327 mIconView->setSelected(aItem, selected);
328 mIconView->ensureItemVisible( aItem );
329 found = true;
330 }
331 }
332 }
333}
334
335void KAddressBookIconView::addresseeExecuted(QIconViewItem *item)
336{
337#ifndef KAB_EMBEDDED
338 AddresseeIconViewItem *aItem = dynamic_cast<AddresseeIconViewItem*>(item);
339#else //KAB_EMBEDDED
340 AddresseeIconViewItem *aItem = (AddresseeIconViewItem*)(item);
341#endif //KAB_EMBEDDED
342
343 if (aItem) {
344 emit executed(aItem->addressee().uid());
345 }
346}
347
348void KAddressBookIconView::addresseeSelected()
349{
350 QIconViewItem *item;
351 AddresseeIconViewItem *aItem;
352
353 bool found = false;
354 for (item = mIconView->firstItem(); item && !found;
355 item = item->nextItem())
356 {
357 if (item->isSelected())
358 {
359#ifndef KAB_EMBEDDED
360 aItem = dynamic_cast<AddresseeIconViewItem*>(item);
361#else //KAB_EMBEDDED
362 aItem = (AddresseeIconViewItem*)(item);
363#endif //KAB_EMBEDDED
364 if (aItem)
365 {
366 emit selected(aItem->addressee().uid());
367 found = true;
368 }
369 }
370 }
371
372 if (!found)
373 emit selected(QString::null);
374}
375
376#ifndef KAB_EMBEDDED
377#include "kaddressbookiconview.moc"
378#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/kaddressbookiconview.h b/kaddressbook/views/kaddressbookiconview.h
new file mode 100644
index 0000000..3afada3
--- a/dev/null
+++ b/kaddressbook/views/kaddressbookiconview.h
@@ -0,0 +1,130 @@
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, permission is given to link this program
20 with any edition of Qt, and distribute the resulting executable,
21 without including the source code for Qt in the source distribution.
22*/
23
24#ifndef KADDRESSBOOKICONVIEW_H
25#define KADDRESSBOOKICONVIEW_H
26
27#include <qstring.h>
28#ifndef KAB_EMBEDDED
29#include <kiconview.h>
30#else //KAB_EMBEDDED
31#include <qiconview.h>
32#include <qptrlist.h>
33#include <klocale.h>
34#endif //KAB_EMBEDDED
35#include "kaddressbookview.h"
36
37class QIconViewItem;
38class KConfig;
39class AddresseeIconView;
40class AddresseeIconViewItem;
41class QIconDragItem;
42class KAddressBookIconView;
43
44namespace KABC { class AddressBook; }
45
46/** This is an example kaddressbook view that is implemented using
47* KIconView. This view is not the most useful view, but it displays
48* how simple implementing a new view can be.
49*/
50class KAddressBookIconView : public KAddressBookView
51{
52 Q_OBJECT
53
54 public:
55 KAddressBookIconView( KABC::AddressBook *ab, QWidget *parent,
56 const char *name = 0 );
57 virtual ~KAddressBookIconView();
58
59 virtual QStringList selectedUids();
60 virtual QString type() const { return "Icon"; }
61
62 virtual void readConfig(KConfig *config);
63
64 public slots:
65 void refresh(QString uid = QString::null);
66#ifndef KAB_EMBEDDED
67//MOC_SKIP_BEGIN
68 void setSelected(QString uid = QString::null, bool selected = true);
69//MOC_SKIP_END
70#else //KAB_EMBEDDED
71//US my MOC do not like default parameters ???
72 void setSelected(QString uid, bool selected);
73#endif //KAB_EMBEDDED
74
75 protected slots:
76 void addresseeExecuted(QIconViewItem *item);
77 void addresseeSelected();
78
79 private:
80 AddresseeIconView *mIconView;
81 QPtrList<AddresseeIconViewItem> mIconList;
82};
83
84
85#ifndef KAB_EMBEDDED
86//MOC_SKIP_BEGIN
87class AddresseeIconView : public KIconView
88//MOC_SKIP_END
89#else //KAB_EMBEDDED
90class AddresseeIconView : public QIconView
91#endif //KAB_EMBEDDED
92{
93 Q_OBJECT
94
95 public:
96 AddresseeIconView(QWidget *parent, const char *name);
97 ~AddresseeIconView();
98
99 signals:
100 void addresseeDropped(QDropEvent *);
101 void startAddresseeDrag();
102
103 protected:
104 virtual QDragObject *dragObject();
105
106 protected slots:
107 void itemDropped(QDropEvent *, const QValueList<QIconDragItem> &);
108};
109
110class IconViewFactory : public ViewFactory
111{
112 public:
113 KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name )
114 {
115 return new KAddressBookIconView( ab, parent, name );
116 }
117
118 QString type() const { return "Icon"; }
119
120 QString description() const { return i18n( "Icons represent contacts. Very simple view." ); }
121};
122/*
123extern "C" {
124 void *init_libkaddrbk_iconview()
125 {
126 return ( new IconViewFactory );
127 }
128}
129*/
130#endif
diff --git a/kaddressbook/views/kaddressbooktableview.cpp b/kaddressbook/views/kaddressbooktableview.cpp
new file mode 100644
index 0000000..ee2fcf8
--- a/dev/null
+++ b/kaddressbook/views/kaddressbooktableview.cpp
@@ -0,0 +1,337 @@
1// $Id$
2
3#include <qvbox.h>
4#include <qlistbox.h>
5#include <qwidget.h>
6#include <qfile.h>
7#include <qimage.h>
8#include <qcombobox.h>
9#include <qapplication.h>
10#include <qdragobject.h>
11#include <qevent.h>
12#include <qurl.h>
13#include <qpixmap.h>
14
15#include <kabc/addressbook.h>
16#include <kapplication.h>
17#include <kconfig.h>
18#include <kcolorbutton.h>
19#include <kdebug.h>
20#include <kglobal.h>
21#include <kiconloader.h>
22#include <klineedit.h>
23#include <klocale.h>
24#include <kmessagebox.h>
25#include <kurl.h>
26#include <kurlrequester.h>
27
28//US#include "configuretableviewdialog.h"
29#include "contactlistview.h"
30#include "kabprefs.h"
31#include "undocmds.h"
32#include "viewmanager.h"
33
34#include <qlayout.h>
35
36
37#include "kaddressbooktableview.h"
38
39
40KAddressBookTableView::KAddressBookTableView( KABC::AddressBook *ab,
41 QWidget *parent, const char *name )
42 : KAddressBookView( ab, parent, name )
43{
44 mainLayout = new QVBoxLayout( viewWidget(), 2 );
45
46 // The list view will be created when the config is read.
47 mListView = 0;
48}
49
50KAddressBookTableView::~KAddressBookTableView()
51{
52}
53
54void KAddressBookTableView::reconstructListView()
55{
56 if (mListView)
57 {
58 disconnect(mListView, SIGNAL(selectionChanged()),
59 this, SLOT(addresseeSelected()));
60 disconnect(mListView, SIGNAL(executed(QListViewItem*)),
61 this, SLOT(addresseeExecuted(QListViewItem*)));
62 disconnect(mListView, SIGNAL(doubleClicked(QListViewItem*)),
63 this, SLOT(addresseeExecuted(QListViewItem*)));
64 disconnect(mListView, SIGNAL(startAddresseeDrag()), this,
65 SIGNAL(startDrag()));
66 disconnect(mListView, SIGNAL(returnPressed(QListViewItem*)),
67 this, SLOT(addresseeExecuted(QListViewItem*)));
68
69 disconnect(mListView, SIGNAL(addresseeDropped(QDropEvent*)), this,
70 SIGNAL(dropped(QDropEvent*)));
71 delete mListView;
72 }
73
74 mListView = new ContactListView( this, addressBook(), viewWidget() );
75
76 // Add the columns
77 KABC::Field::List fieldList = fields();
78 KABC::Field::List::ConstIterator it;
79
80 int c = 0;
81 for( it = fieldList.begin(); it != fieldList.end(); ++it ) {
82 mListView->addColumn( (*it)->label() );
83 mListView->setColumnWidthMode(c++, QListView::Manual);
84//US
85 // qDebug("KAddressBookTableView::reconstructListView: field %s", (*it)->label().latin1());
86 }
87
88 connect(mListView, SIGNAL(selectionChanged()),
89 this, SLOT(addresseeSelected()));
90 connect(mListView, SIGNAL(startAddresseeDrag()), this,
91 SIGNAL(startDrag()));
92 connect(mListView, SIGNAL(addresseeDropped(QDropEvent*)), this,
93 SIGNAL(dropped(QDropEvent*)));
94
95 if (KABPrefs::instance()->mHonorSingleClick)
96 connect(mListView, SIGNAL(executed(QListViewItem*)),
97 this, SLOT(addresseeExecuted(QListViewItem*)));
98 else
99 connect(mListView, SIGNAL(doubleClicked(QListViewItem*)),
100 this, SLOT(addresseeExecuted(QListViewItem*)));
101 connect(mListView, SIGNAL(returnPressed(QListViewItem*)),
102 this, SLOT(addresseeExecuted(QListViewItem*)));
103 connect(mListView, SIGNAL(signalDelete()),
104 this, SLOT(addresseeDeleted()));
105
106 refresh();
107
108 mListView->setSorting( 0, true );
109 mainLayout->addWidget( mListView );
110 mainLayout->activate();
111 mListView->show();
112}
113
114void KAddressBookTableView::writeConfig(KConfig *config)
115{
116 KAddressBookView::writeConfig(config);
117
118 mListView->saveLayout(config, config->group());
119}
120
121void KAddressBookTableView::readConfig(KConfig *config)
122{
123 KAddressBookView::readConfig( config );
124
125 // The config could have changed the fields, so we need to reconstruct
126 // the listview.
127 reconstructListView();
128
129 // Set the list view options
130 mListView->setAlternateBackgroundEnabled(config->readBoolEntry("ABackground",
131 true));
132 mListView->setSingleLineEnabled(config->readBoolEntry("SingleLine", false));
133 mListView->setToolTipsEnabled(config->readBoolEntry("ToolTips", true));
134
135 if (config->readBoolEntry("Background", false))
136 mListView->setBackgroundPixmap(config->readEntry("BackgroundName"));
137
138 // Restore the layout of the listview
139 mListView->restoreLayout(config, config->group());
140}
141
142void KAddressBookTableView::refresh(QString uid)
143{
144 // For now just repopulate. In reality this method should
145 // check the value of uid, and if valid iterate through
146 // the listview to find the entry, then tell it to refresh.
147
148 if (uid.isNull()) {
149 // Clear the list view
150 QString currentUID, nextUID;
151#ifndef KAB_EMBEDDED
152 ContactListViewItem *currentItem = dynamic_cast<ContactListViewItem*>( mListView->currentItem() );
153#else //KAB_EMBEDDED
154 ContactListViewItem *currentItem = (ContactListViewItem*)( mListView->currentItem() );
155#endif //KAB_EMBEDDED
156
157 if ( currentItem ) {
158#ifndef KAB_EMBEDDED
159 ContactListViewItem *nextItem = dynamic_cast<ContactListViewItem*>( currentItem->itemBelow() );
160#else //KAB_EMBEDDED
161 ContactListViewItem *nextItem = (ContactListViewItem*)( currentItem->itemBelow() );
162#endif //KAB_EMBEDDED
163 if ( nextItem )
164 nextUID = nextItem->addressee().uid();
165 currentUID = currentItem->addressee().uid();
166 }
167
168 mListView->clear();
169
170 currentItem = 0;
171 KABC::Addressee::List addresseeList = addressees();
172 KABC::Addressee::List::Iterator it;
173 for (it = addresseeList.begin(); it != addresseeList.end(); ++it ) {
174 ContactListViewItem *item = new ContactListViewItem(*it, mListView, addressBook(), fields());
175 if ( (*it).uid() == currentUID )
176 currentItem = item;
177 else if ( (*it).uid() == nextUID && !currentItem )
178 currentItem = item;
179 }
180
181 // Sometimes the background pixmap gets messed up when we add lots
182 // of items.
183 mListView->repaint();
184
185 if ( currentItem ) {
186 mListView->setCurrentItem( currentItem );
187 mListView->ensureItemVisible( currentItem );
188 }
189 } else {
190 // Only need to update on entry. Iterate through and try to find it
191 ContactListViewItem *ceItem;
192 QListViewItemIterator it( mListView );
193 while ( it.current() ) {
194#ifndef KAB_EMBEDDED
195 ceItem = dynamic_cast<ContactListViewItem*>( it.current() );
196#else //KAB_EMBEDDED
197 ceItem = (ContactListViewItem*)( it.current() );
198#endif //KAB_EMBEDDED
199
200 if ( ceItem && ceItem->addressee().uid() == uid ) {
201 ceItem->refresh();
202 return;
203 }
204 ++it;
205 }
206
207 refresh( QString::null );
208 }
209}
210
211QStringList KAddressBookTableView::selectedUids()
212{
213 QStringList uidList;
214 QListViewItem *item;
215 ContactListViewItem *ceItem;
216
217 for(item = mListView->firstChild(); item; item = item->itemBelow())
218 {
219 if (mListView->isSelected( item ))
220 {
221#ifndef KAB_EMBEDDED
222 ceItem = dynamic_cast<ContactListViewItem*>(item);
223#else //KAB_EMBEDDED
224 ceItem = (ContactListViewItem*)(item);
225#endif //KAB_EMBEDDED
226
227 if (ceItem != 0L)
228 uidList << ceItem->addressee().uid();
229 }
230 }
231 if ( uidList.count() == 0 )
232 if ( mListView->currentItem() ) {
233 ceItem = (ContactListViewItem*)(mListView->currentItem()) ;
234 uidList << ceItem->addressee().uid();
235 }
236
237 return uidList;
238}
239
240void KAddressBookTableView::setSelected(QString uid, bool selected)
241{
242 QListViewItem *item;
243 ContactListViewItem *ceItem;
244
245 if (uid.isNull())
246 {
247 mListView->selectAll(selected);
248 }
249 else
250 {
251 for(item = mListView->firstChild(); item; item = item->itemBelow())
252 {
253#ifndef KAB_EMBEDDED
254 ceItem = dynamic_cast<ContactListViewItem*>(item);
255#else //KAB_EMBEDDED
256 ceItem = (ContactListViewItem*)(item);
257#endif //KAB_EMBEDDED
258
259
260 if ((ceItem != 0L) && (ceItem->addressee().uid() == uid))
261 {
262 mListView->setSelected(item, selected);
263
264 if (selected)
265 mListView->ensureItemVisible(item);
266 }
267 }
268 }
269}
270
271void KAddressBookTableView::addresseeSelected()
272{
273 // We need to try to find the first selected item. This might not be the
274 // last selected item, but when QListView is in multiselection mode,
275 // there is no way to figure out which one was
276 // selected last.
277 QListViewItem *item;
278 bool found =false;
279 for (item = mListView->firstChild(); item && !found;
280 item = item->nextSibling())
281 {
282 if (item->isSelected())
283 {
284 found = true;
285#ifndef KAB_EMBEDDED
286 ContactListViewItem *ceItem
287 = dynamic_cast<ContactListViewItem*>(item);
288#else //KAB_EMBEDDED
289 ContactListViewItem *ceItem
290 = (ContactListViewItem*)(item);
291#endif //KAB_EMBEDDED
292
293 if ( ceItem ) emit selected(ceItem->addressee().uid());
294 }
295 }
296
297 if (!found)
298 emit selected(QString::null);
299}
300
301void KAddressBookTableView::addresseeExecuted(QListViewItem *item)
302{
303 if (item)
304 {
305#ifndef KAB_EMBEDDED
306 ContactListViewItem *ceItem
307 = dynamic_cast<ContactListViewItem*>(item);
308#else //KAB_EMBEDDED
309 ContactListViewItem *ceItem
310 = (ContactListViewItem*)(item);
311#endif //KAB_EMBEDDED
312
313 if (ceItem)
314 {
315 emit executed(ceItem->addressee().uid());
316 }
317 }
318 else
319 {
320 emit executed(QString::null);
321 }
322}
323
324void KAddressBookTableView::addresseeDeleted()
325{
326
327 emit deleteRequest();
328
329}
330
331
332
333
334
335#ifndef KAB_EMBEDDED
336#include "kaddressbooktableview.moc"
337#endif //KAB_EMBEDDED
diff --git a/kaddressbook/views/kaddressbooktableview.h b/kaddressbook/views/kaddressbooktableview.h
new file mode 100644
index 0000000..bb991bc
--- a/dev/null
+++ b/kaddressbook/views/kaddressbooktableview.h
@@ -0,0 +1,114 @@
1#ifndef KADDRESSBOOKTABLEVIEW_H
2#define KADDRESSBOOKTABLEVIEW_H
3
4
5#ifndef KAB_EMBEDDED
6
7
8#ifdef HAVE_CONFIG_H
9#include <config.h>
10#endif
11
12#include <qwidget.h>
13#include <qlistview.h>
14#include <qstring.h>
15#include <qdialog.h>
16#include <qtabdialog.h>
17#include <qstringlist.h>
18#include <qvaluelist.h>
19
20#include "undo.h"
21
22#else //KAB_EMBEDDED
23#include "views/configuretableviewdialog.h"
24#endif //KAB_EMBEDDED
25
26#include "klocale.h"
27#include "kaddressbookview.h"
28
29class QListViewItem;
30class QListBox;
31class QVBoxLayout;
32class KConfig;
33
34class ContactListViewItem;
35class ContactListView;
36
37
38namespace KABC { class AddressBook; }
39
40/**
41 * This class is the table view for kaddressbook. This view is a KListView
42 * with multiple columns for the selected fields.
43 *
44 * @short Table View
45 * @author Don Sanders <dsanders@kde.org>
46 * @version 0.1
47 */
48class KAddressBookTableView : public KAddressBookView
49{
50friend class ContactListView;
51
52 Q_OBJECT
53
54 public:
55 KAddressBookTableView( KABC::AddressBook *ab, QWidget *parent,
56 const char *name = 0 );
57 virtual ~KAddressBookTableView();
58
59 virtual void refresh(QString uid = QString::null);
60 virtual QStringList selectedUids();
61 virtual void setSelected(QString uid = QString::null, bool selected = false);
62 virtual void readConfig(KConfig *config);
63 virtual void writeConfig(KConfig *config);
64 virtual QString type() const { return "Table"; }
65
66 public slots:
67 virtual void reconstructListView();
68
69 protected slots:
70 /** Called whenever the user selects an addressee in the list view.
71 */
72 void addresseeSelected();
73 void addresseeDeleted();
74
75 /** Called whenever the user executes an addressee. In terms of the
76 * list view, this is probably a double click
77 */
78 void addresseeExecuted(QListViewItem*);
79
80 private:
81 QVBoxLayout *mainLayout;
82 ContactListView *mListView;
83};
84
85
86class TableViewFactory : public ViewFactory
87{
88 public:
89 KAddressBookView *view( KABC::AddressBook *ab, QWidget *parent, const char *name )
90 {
91 return new KAddressBookTableView( ab, parent, name );
92 }
93
94 QString type() const { return "Table"; }
95
96 QString description() const { return i18n( "A listing of contacts in a table. Each cell of "
97 "the table holds a field of the contact." ); }
98
99 ViewConfigureWidget *configureWidget( KABC::AddressBook *ab, QWidget *parent,
100 const char *name = 0 )
101 {
102 return new ConfigureTableViewWidget( ab, parent, name );
103 }
104};
105/*US
106extern "C" {
107 void *init_libkaddrbk_tableview()
108 {
109 return ( new TableViewFactory );
110 }
111}
112*/
113
114#endif