summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--kaddressbook/views/cardview.cpp6
-rw-r--r--kaddressbook/views/kaddressbookcardview.cpp5
2 files changed, 8 insertions, 3 deletions
diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp
index 6351c11..da552c3 100644
--- a/kaddressbook/views/cardview.cpp
+++ b/kaddressbook/views/cardview.cpp
@@ -1,228 +1,229 @@
/*
This file is part of KAddressBook.
Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
As a special exception, permission is given to link this program
with any edition of Qt, and distribute the resulting executable,
without including the source code for Qt in the source distribution.
*/
//BEGIN Includes
#include "cardview.h"
#include <limits.h>
#include <qpainter.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qlabel.h>
#include <qstyle.h>
#include <qcursor.h>
#include <qtooltip.h>
+#include "kabprefs.h"
#include <kdebug.h>
#include <kglobalsettings.h>
//END includes
#define MIN_ITEM_WIDTH 80
//BEGIN Helpers
//////////////////////////////////////
// CardViewTip
class CardViewTip : public QLabel {
public:
CardViewTip(QWidget *parent=0, const char *name=0) : QLabel( parent, name )
{
setPalette( QToolTip::palette() );
setFrameStyle( Panel|Plain );
setMidLineWidth(0);
setIndent(1);
}
~CardViewTip() {};
protected:
void leaveEvent( QEvent * )
{
hide();
}
};
//////////////////////////////////////
// CardViewItemList
//
// Warning: make sure you use findRef() instead of find() to find an
// item! Only the pointer value is unique in the list.
//
class CardViewItemList : public QPtrList<CardViewItem>
{
protected:
virtual int compareItems(QPtrCollection::Item item1,
QPtrCollection::Item item2)
{
CardViewItem *cItem1 = (CardViewItem*)item1;
CardViewItem *cItem2 = (CardViewItem*)item2;
if ( cItem1 == cItem2 )
return 0;
if ((cItem1 == 0) || (cItem2 == 0))
return cItem1 ? -1 : 1;
if (cItem1->caption() < cItem2->caption())
return -1;
else if (cItem1->caption() > cItem2->caption())
return 1;
return 0;
}
private:
/*int find( const CardViewItem * )
{
qDebug("DON'T USE CardViewItemList::find( item )! Use findRef( item )!");
}*/
};
//////////////////////////////////////
// CardViewSeparator
class CardViewSeparator
{
friend class CardView;
public:
CardViewSeparator(CardView *view)
: mView(view)
{
mRect = QRect(0, 0, view->separatorWidth(), 0);
}
~CardViewSeparator() {}
void paintSeparator(QPainter *p, QColorGroup &cg)
{
p->fillRect(0, 0, mRect.width(), mRect.height(),
cg.brush(QColorGroup::Button));
}
void repaintSeparator()
{
mView->repaintContents(mRect);
}
private:
CardView *mView;
QRect mRect;
};
//END Helpers
//BEGIN Private Data
class CardViewPrivate
{
public:
CardViewPrivate()
: mSelectionMode( CardView::Multi ),
mDrawCardBorder( true ),
mDrawFieldLabels( true ),
mDrawSeparators( true),
mSepWidth( 2 ),
mShowEmptyFields( false ),
mLayoutDirty( true ),
mLastClickOnItem( false ),
mItemMargin( 0 ),
mItemSpacing( 10 ),
mItemWidth( 200 ),
mMaxFieldLines( INT_MAX ),
mCurrentItem( 0L ),
mLastClickPos( QPoint(0, 0) ),
mRubberBandAnchor( 0 ),
mCompText( QString::null ),
mResizeAnchor(0)
{};
CardViewItemList mItemList;
QPtrList<CardViewSeparator> mSeparatorList;
QFontMetrics *mFm;
QFontMetrics *mBFm; // bold font
QFont mHeaderFont; // custom header font
CardView::SelectionMode mSelectionMode;
bool mDrawCardBorder;
bool mDrawFieldLabels;
bool mDrawSeparators;
int mSepWidth;
bool mShowEmptyFields;
bool mLayoutDirty;
bool mLastClickOnItem;
uint mItemMargin; // internal margin in items
uint mItemSpacing; // spacing between items, column seperators and border
int mItemWidth; // width of all items
uint mMaxFieldLines; // Max lines to dispaly pr field
CardViewItem *mCurrentItem;
QPoint mLastClickPos;
QTimer *mTimer; // times out if mouse rests for more than 500 msecs
CardViewTip *mTip; // passed to the item under a resting cursor to display full text
bool mOnSeparator; // set/reset on mouse movement
// for resizing by dragging the separators
int mResizeAnchor; // uint, ulong? the mouse down separator left
int mRubberBandAnchor; // for erasing rubber bands
// data used for resizing.
// as they are beeded by each mouse move while resizing, we store them here,
// saving 8 calculations in each mouse move.
int colspace; // amount of space between items pr column
uint first; // the first col to anchor at for painting rubber bands
int firstX; // X position of first in pixel
int pressed; // the colummn that was pressed on at resizing start
int span; // pressed - first
// key completion
QString mCompText; // current completion string
QDateTime mCompUpdated; // ...was updated at this time
};
class CardViewItemPrivate
{
public:
CardViewItemPrivate() :
x( 0 ),
y( 0 ),
mSelected( false ){};
QString mCaption;
QPtrList< CardViewItem::Field > mFieldList;
bool mSelected;
int x; // horizontal position, set by the view
int y; // vertical position, set by the view
int maxLabelWidth; // the width of the widest label, according to the view font.
int hcache; // height cache
};
//END Private Data
//BEGIN CardViewItem
CardViewItem::CardViewItem(CardView *parent, QString caption)
: d(new CardViewItemPrivate()), mView(parent)
{
d->mCaption = caption;
initialize();
}
CardViewItem::~CardViewItem()
@@ -467,385 +468,384 @@ void CardViewItem::removeField(const QString &label)
void CardViewItem::clearFields()
{
d->mFieldList.clear();
d->hcache = 0;
if (mView)
mView->setLayoutDirty(true);
}
QString CardViewItem::trimString(const QString &text, int width,
QFontMetrics &fm)
{
if (fm.width(text) <= width)
return text;
QString dots = "...";
int dotWidth = fm.width(dots);
QString trimmed;
int charNum = 0;
while (fm.width(trimmed) + dotWidth < width)
{
trimmed += text[charNum];
charNum++;
}
// Now trim the last char, since it put the width over the top
trimmed = trimmed.left(trimmed.length()-1);
trimmed += dots;
return trimmed;
}
CardViewItem *CardViewItem::nextItem()
{
CardViewItem *item = 0;
if (mView)
item = mView->itemAfter(this);
return item;
}
void CardViewItem::repaintCard()
{
if (mView)
mView->repaintItem(this);
}
void CardViewItem::setCaption(const QString &caption)
{
d->mCaption = caption;
repaintCard();
}
QString CardViewItem::fieldValue(const QString &label)
{
QPtrListIterator< CardViewItem::Field > iter(d->mFieldList);
for (iter.toFirst(); iter.current(); ++iter)
if ((*iter)->first == label)
return (*iter)->second;
return QString();
}
void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip )
{
bool trimmed( false );
QString s;
int mrg = mView->itemMargin();
int y = mView->d->mBFm->height() + 6 + mrg;
int w = mView->itemWidth() - (2*mrg);
int lw;
bool drawLabels = mView->drawFieldLabels();
bool isLabel = drawLabels && itempos.x() < w/2 ? true : false;
if ( itempos.y() < y )
{
if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 )
return;
// this is the caption
s = caption();
trimmed = mView->d->mBFm->width( s ) > w - 4;
y = 2 + mrg;
lw = 0;
isLabel=true;
} else {
// find the field
Field *f = fieldAt( itempos );
if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) )
return;
// y position:
// header font height + 4px hader margin + 2px leading + item margin
// + actual field index * (fontheight + 2px leading)
int maxLines = mView->maxFieldLines();
bool se = mView->showEmptyFields();
int fh = mView->d->mFm->height();
// {
Field *_f;
for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next())
if ( se || ! _f->second.isEmpty() )
y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2;
// }
if ( isLabel && itempos.y() > y + fh )
return;
// label or data?
s = isLabel ? f->first : f->second;
// trimmed?
int colonWidth = mView->d->mFm->width(":");
lw = drawLabels ? // label width
QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) :
0;
int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string
if ( isLabel )
{
trimmed = mView->d->mFm->width( s ) > mw - colonWidth;
} else {
QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) );
trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines);
}
}
if ( trimmed )
{
tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header
tip->setText( s );
tip->adjustSize();
// find a proper position
int lx;
lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/;
QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) ));
pnt += QPoint(lx, y);
if ( pnt.x() < 0 )
pnt.setX( 0 );
if ( pnt.x() + tip->width() > mView->visibleWidth() )
pnt.setX( mView->visibleWidth() - tip->width() );
if ( pnt.y() + tip->height() > mView->visibleHeight() )
pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) );
// show
tip->move( pnt );
tip->show();
}
}
CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const
{
int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin;
int iy = itempos.y();
// skip below caption
if ( iy <= ypos )
return 0;
// try find a field
bool showEmpty = mView->showEmptyFields();
int fh = mView->d->mFm->height();
int maxLines = mView->maxFieldLines();
Field *f;
for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() )
{
if ( showEmpty || !f->second.isEmpty() )
ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2;
if ( iy <= ypos )
break;
}
return f ? f : 0;
}
//END CardViewItem
//BEGIN CardView
CardView::CardView(QWidget *parent, const char *name)
: QScrollView(parent, name),
d(new CardViewPrivate())
{
d->mItemList.setAutoDelete(true);
d->mSeparatorList.setAutoDelete(true);
QFont f = font();
d->mFm = new QFontMetrics(f);
f.setBold(true);
d->mHeaderFont = f;
d->mBFm = new QFontMetrics(f);
d->mTip = ( new CardViewTip( viewport() ) ),
d->mTip->hide();
d->mTimer = ( new QTimer(this, "mouseTimer") ),
viewport()->setMouseTracking( true );
viewport()->setFocusProxy(this);
viewport()->setFocusPolicy(WheelFocus);
viewport()->setBackgroundMode(PaletteBase);
connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) );
- connect( this, SIGNAL(executed(CardViewItem *)), this, SIGNAL( doubleClicked(CardViewItem *)) );
//US setBackgroundMode(PaletteBackground, PaletteBase);
setBackgroundMode(PaletteBackground);
// no reason for a vertical scrollbar
setVScrollBarMode(AlwaysOff);
}
CardView::~CardView()
{
delete d->mFm;
delete d->mBFm;
delete d;
d = 0;
}
void CardView::insertItem(CardViewItem *item)
{
d->mItemList.inSort(item);
setLayoutDirty(true);
}
void CardView::takeItem(CardViewItem *item)
{
if ( d->mCurrentItem == item )
d->mCurrentItem = item->nextItem();
d->mItemList.take(d->mItemList.findRef(item));
setLayoutDirty(true);
}
void CardView::clear()
{
d->mItemList.clear();
setLayoutDirty(true);
}
CardViewItem *CardView::currentItem()
{
if ( ! d->mCurrentItem && d->mItemList.count() )
d->mCurrentItem = d->mItemList.first();
return d->mCurrentItem;
}
void CardView::setCurrentItem( CardViewItem *item )
{
if ( !item )
return;
else if ( item->cardView() != this )
{
kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl;
return;
}
else if ( item == currentItem() )
{
return;
}
if ( d->mSelectionMode == Single )
{
setSelected( item, true );
}
else
{
CardViewItem *it = d->mCurrentItem;
d->mCurrentItem = item;
if ( it )
it->repaintCard();
item->repaintCard();
}
if ( ! d->mOnSeparator )
ensureItemVisible( item );
emit currentChanged( item );
}
CardViewItem *CardView::itemAt(const QPoint &viewPos)
{
CardViewItem *item = 0;
QPtrListIterator<CardViewItem> iter(d->mItemList);
bool found = false;
for (iter.toFirst(); iter.current() && !found; ++iter)
{
item = *iter;
//if (item->d->mRect.contains(viewPos))
if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos))
found = true;
}
if (found)
return item;
return 0;
}
QRect CardView::itemRect(const CardViewItem *item)
{
//return item->d->mRect;
return QRect(item->d->x, item->d->y, d->mItemWidth, item->height());
}
void CardView::ensureItemVisible(const CardViewItem *item)
{
ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0);
ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0);
}
void CardView::repaintItem(const CardViewItem *item)
{
//repaintContents(item->d->mRect);
repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) );
}
void CardView::setSelectionMode(CardView::SelectionMode mode)
{
selectAll(false);
d->mSelectionMode = mode;
}
CardView::SelectionMode CardView::selectionMode() const
{
return d->mSelectionMode;
}
void CardView::selectAll(bool state)
{
QPtrListIterator<CardViewItem> iter(d->mItemList);
if (!state)
{
for (iter.toFirst(); iter.current(); ++iter)
{
if ((*iter)->isSelected())
{
(*iter)->setSelected(false);
(*iter)->repaintCard();
}
}
//emit selectionChanged(); // WARNING FIXME
emit selectionChanged(0);
}
else if (d->mSelectionMode != CardView::Single)
{
for (iter.toFirst(); iter.current(); ++iter)
{
(*iter)->setSelected(true);
}
if (d->mItemList.count() > 0)
{
// emit, since there must have been at least one selected
emit selectionChanged();
//repaint();//???
viewport()->update();
}
}
}
void CardView::setSelected(CardViewItem *item, bool selected)
{
if ((item == 0) || (item->isSelected() == selected))
return;
if ( selected && d->mCurrentItem != item )
{
CardViewItem *it = d->mCurrentItem;
d->mCurrentItem = item;
if ( it )
it->repaintCard();
}
if (d->mSelectionMode == CardView::Single)
{
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
if (selected)
{
item->setSelected(selected);
item->repaintCard();
emit selectionChanged();
emit selectionChanged(item);
}
else
{
emit selectionChanged();
emit selectionChanged(0);
}
}
else if (d->mSelectionMode == CardView::Multi)
@@ -1058,402 +1058,402 @@ void CardView::calcLayout()
for (sepIter.toFirst(); sepIter.current(); ++sepIter)
{
(*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin);
}
d->mLayoutDirty = false;
}
CardViewItem *CardView::itemAfter(CardViewItem *item)
{
/*int pos = */d->mItemList.findRef(item);
return d->mItemList.next();//at(pos+1);
}
uint CardView::itemMargin()
{
return d->mItemMargin;
}
void CardView::setItemMargin( uint margin )
{
if ( margin == d->mItemMargin )
return;
d->mItemMargin = margin;
setLayoutDirty( true );
}
uint CardView::itemSpacing()
{
return d->mItemSpacing;
}
void CardView::setItemSpacing( uint spacing )
{
if ( spacing == d->mItemSpacing )
return;
d->mItemSpacing = spacing;
setLayoutDirty( true );
}
void CardView::contentsMousePressEvent(QMouseEvent *e)
{
QScrollView::contentsMousePressEvent(e);
QPoint pos = e->pos();
d->mLastClickPos = pos;
CardViewItem *item = itemAt(pos);
if (item == 0)
{
d->mLastClickOnItem = false;
if ( d->mOnSeparator)
{
d->mResizeAnchor = e->x()+contentsX();
d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/;
int ccw = d->mItemWidth + d->colspace + d->mSepWidth;
d->first = (contentsX()+d->mSepWidth)/ccw;
d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw;
d->span = d->pressed - d->first;
d->firstX = d->first * ccw;
if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0)
}
else
{
selectAll(false);
}
return;
}
d->mLastClickOnItem = true;
CardViewItem *other = d->mCurrentItem;
setCurrentItem( item );
// Always emit the selection
emit clicked(item);
// Check the selection type and update accordingly
if (d->mSelectionMode == CardView::Single)
{
// make sure it isn't already selected
if (item->isSelected())
return;
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
item->setSelected(true);
item->repaintCard();
emit selectionChanged(item);
}
else if (d->mSelectionMode == CardView::Multi)
{
// toggle the selection
item->setSelected(!item->isSelected());
item->repaintCard();
emit selectionChanged();
}
else if (d->mSelectionMode == CardView::Extended)
{
if ((e->button() & Qt::LeftButton) &&
(e->state() & Qt::ShiftButton))
{
if ( item == other ) return;
bool s = ! item->isSelected();
if ( s && ! (e->state() & ControlButton) )
{
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
}
int from, to, a, b;
a = d->mItemList.findRef( item );
b = d->mItemList.findRef( other );
from = a < b ? a : b;
to = a > b ? a : b;
//kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl;
CardViewItem *aItem;
for ( ; from <= to; from++ )
{
aItem = d->mItemList.at( from );
aItem->setSelected( s );
repaintItem( aItem );
}
emit selectionChanged();
}
else if ((e->button() & Qt::LeftButton) &&
(e->state() & Qt::ControlButton))
{
item->setSelected(!item->isSelected());
item->repaintCard();
emit selectionChanged();
}
else if (e->button() & Qt::LeftButton)
{
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
item->setSelected(true);
item->repaintCard();
emit selectionChanged();
}
}
}
void CardView::contentsMouseReleaseEvent(QMouseEvent *e)
{
QScrollView::contentsMouseReleaseEvent(e);
if ( d->mResizeAnchor )
{
// finish the resizing:
unsetCursor();
// hide rubber bands
int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span);
drawRubberBands( 0 );
// we should move to reflect the new position if we are scrolled.
if ( contentsX() )
{
int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() );
setContentsPos( newX, contentsY() );
}
// set new item width
setItemWidth( newiw );
// reset anchors
d->mResizeAnchor = 0;
d->mRubberBandAnchor = 0;
return;
}
// If there are accel keys, we will not emit signals
if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton))
return;
// Get the item at this position
CardViewItem *item = itemAt(e->pos());
- if (item && KGlobalSettings::singleClick())
+ if (item && KABPrefs::instance()->mHonorSingleClick)
{
emit executed(item);
}
}
void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e)
{
QScrollView::contentsMouseDoubleClickEvent(e);
CardViewItem *item = itemAt(e->pos());
if (item)
{
d->mCurrentItem = item;
}
- if (item && !KGlobalSettings::singleClick())
+ if (item && !KABPrefs::instance()->mHonorSingleClick)
{
emit executed(item);
} else
emit doubleClicked(item);
}
void CardView::contentsMouseMoveEvent( QMouseEvent *e )
{
// resizing
if ( d->mResizeAnchor )
{
int x = e->x();
if ( x != d->mRubberBandAnchor )
drawRubberBands( x );
return;
}
if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) &&
((e->pos() - d->mLastClickPos).manhattanLength() > 4)) {
startDrag();
return;
}
d->mTimer->start( 500 );
// see if we are over a separator
// only if we actually have them painted?
if ( d->mDrawSeparators )
{
int colcontentw = d->mItemWidth + (2*d->mItemSpacing);
int colw = colcontentw + d->mSepWidth;
int m = e->x()%colw;
if ( m >= colcontentw && m > 0 )
{
setCursor( SplitVCursor ); // Why does this fail sometimes?
d->mOnSeparator = true;
}
else
{
setCursor( ArrowCursor );
d->mOnSeparator = false;
}
}
}
void CardView::enterEvent( QEvent * )
{
d->mTimer->start( 500 );
}
void CardView::leaveEvent( QEvent * )
{
d->mTimer->stop();
if (d->mOnSeparator)
{
d->mOnSeparator = false;
setCursor( ArrowCursor );
}
}
void CardView::focusInEvent( QFocusEvent * )
{
if (!d->mCurrentItem && d->mItemList.count() )
{
setCurrentItem( d->mItemList.first() );
}
else if ( d->mCurrentItem )
{
d->mCurrentItem->repaintCard();
}
}
void CardView::focusOutEvent( QFocusEvent * )
{
if (d->mCurrentItem)
d->mCurrentItem->repaintCard();
}
void CardView::keyPressEvent( QKeyEvent *e )
{
if ( ! ( childCount() && d->mCurrentItem ) )
{
e->ignore();
return;
}
uint pos = d->mItemList.findRef( d->mCurrentItem );
CardViewItem *aItem = 0L; // item that gets the focus
CardViewItem *old = d->mCurrentItem;
switch ( e->key() )
{
case Key_Up:
if ( pos > 0 )
{
aItem = d->mItemList.at( pos - 1 );
setCurrentItem( aItem );
}
break;
case Key_Down:
if ( pos < d->mItemList.count() - 1 )
{
aItem = d->mItemList.at( pos + 1 );
setCurrentItem( aItem );
}
break;
case Key_Left:
{
// look for an item in the previous/next column, starting from
// the vertical middle of the current item.
// FIXME use nice calculatd measures!!!
QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y );
aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) );
aItem = itemAt( aPoint );
// maybe we hit some space below an item
while ( !aItem && aPoint.y() > 27 )
{
aPoint -= QPoint( 0, 16 );
aItem = itemAt( aPoint );
}
if ( aItem )
setCurrentItem( aItem );
}
break;
case Key_Right:
{
// FIXME use nice calculated measures!!!
QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y );
aPoint += QPoint( 30,(d->mCurrentItem->height()/2) );
aItem = itemAt( aPoint );
while ( !aItem && aPoint.y() > 27 )
{
aPoint -= QPoint( 0, 16 );
aItem = itemAt( aPoint );
}
if ( aItem )
setCurrentItem( aItem );
}
break;
case Key_Home:
aItem = d->mItemList.first();
setCurrentItem( aItem );
break;
case Key_End:
aItem = d->mItemList.last();
setCurrentItem( aItem );
break;
case Key_Prior: // PageUp
{
// QListView: "Make the item above the top visible and current"
// TODO if contentsY(), pick the top item of the leftmost visible column
if ( contentsX() <= 0 )
return;
int cw = columnWidth();
int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing;
aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) );
if ( aItem )
setCurrentItem( aItem );
}
break;
case Key_Next: // PageDown
{
// QListView: "Make the item below the bottom visible and current"
// find the first not fully visible column.
// TODO: consider if a partly visible (or even hidden) item at the
// bottom of the rightmost column exists
int cw = columnWidth();
int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1;
// if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden
if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) )
theCol += cw;
// make sure this is not too far right
while ( theCol > contentsWidth() )
theCol -= columnWidth();
aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) );
if ( aItem )
setCurrentItem( aItem );
}
break;
case Key_Space:
setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() );
emit selectionChanged();
break;
case Key_Return:
case Key_Enter:
{
emit returnPressed( d->mCurrentItem );
emit executed( d->mCurrentItem );
diff --git a/kaddressbook/views/kaddressbookcardview.cpp b/kaddressbook/views/kaddressbookcardview.cpp
index 7f33bb4..15f154e 100644
--- a/kaddressbook/views/kaddressbookcardview.cpp
+++ b/kaddressbook/views/kaddressbookcardview.cpp
@@ -53,394 +53,399 @@ extern "C" {
// AddresseeCardViewItem (internal class)
class AddresseeCardViewItem : public CardViewItem
{
public:
AddresseeCardViewItem(const KABC::Field::List &fields,
bool showEmptyFields,
KABC::AddressBook *doc, const KABC::Addressee &a,
CardView *parent)
: CardViewItem(parent, a.formattedName()),
mFields( fields ), mShowEmptyFields(showEmptyFields),
mDocument(doc), mAddressee(a)
{
if ( mFields.isEmpty() ) {
mFields = KABC::Field::defaultFields();
}
refresh();
}
const KABC::Addressee &addressee() const { return mAddressee; }
void refresh()
{
// Update our addressee, since it may have changed elsewhere
mAddressee = mDocument->findByUid(mAddressee.uid());
if (!mAddressee.isEmpty())
{
clearFields();
// Try all the selected fields until we find one with text.
// This will limit the number of unlabeled icons in the view
KABC::Field::List::Iterator iter;
for (iter = mFields.begin(); iter != mFields.end(); ++iter)
{
// insert empty fields or not? not doing so saves a bit of memory and CPU
// (during geometry calculations), but prevents having equally
// wide label columns in all cards, unless CardViewItem/CardView search
// globally for the widest label. (anders)
//if (mShowEmptyFields || !(*iter)->value( mAddressee ).isEmpty())
insertField((*iter)->label(), (*iter)->value( mAddressee ));
}
// We might want to make this the first field. hmm... -mpilone
setCaption( mAddressee.realName() );
}
}
private:
KABC::Field::List mFields;
bool mShowEmptyFields;
KABC::AddressBook *mDocument;
KABC::Addressee mAddressee;
};
///////////////////////////////
// AddresseeCardView
AddresseeCardView::AddresseeCardView(QWidget *parent, const char *name)
: CardView(parent, name)
{
setAcceptDrops(true);
}
AddresseeCardView::~AddresseeCardView()
{
}
void AddresseeCardView::dragEnterEvent(QDragEnterEvent *e)
{
#ifndef KAB_EMBEDDED
if (QTextDrag::canDecode(e))
e->accept();
#else //KAB_EMBEDDED
qDebug("AddresseeCardView::dragEnterEvent drag&drop is not implemented");
#endif //KAB_EMBEDDED
}
void AddresseeCardView::dropEvent(QDropEvent *e)
{
emit addresseeDropped(e);
}
void AddresseeCardView::startDrag()
{
emit startAddresseeDrag();
}
///////////////////////////////
// KAddressBookCardView
KAddressBookCardView::KAddressBookCardView( KABC::AddressBook *ab,
QWidget *parent, const char *name )
: KAddressBookView( ab, parent, name )
{
mShowEmptyFields = false;
// Init the GUI
QVBoxLayout *layout = new QVBoxLayout(viewWidget());
mCardView = new AddresseeCardView(viewWidget(), "mCardView");
mCardView->setSelectionMode(CardView::Extended);
layout->addWidget(mCardView);
// Connect up the signals
connect(mCardView, SIGNAL(executed(CardViewItem *)),
this, SLOT(addresseeExecuted(CardViewItem *)));
connect(mCardView, SIGNAL(selectionChanged()),
this, SLOT(addresseeSelected()));
connect(mCardView, SIGNAL(addresseeDropped(QDropEvent*)),
this, SIGNAL(dropped(QDropEvent*)));
connect(mCardView, SIGNAL(startAddresseeDrag()),
this, SIGNAL(startDrag()));
}
KAddressBookCardView::~KAddressBookCardView()
{
}
void KAddressBookCardView::setFocusAV()
{
if ( mCardView )
mCardView->setFocus();
}
void KAddressBookCardView::scrollUP()
{
QKeyEvent * ev = new QKeyEvent ( QEvent::KeyPress, Qt::Key_Up, 0,0 );
QApplication::postEvent( mCardView, ev );
}
void KAddressBookCardView::scrollDOWN()
{
QKeyEvent * ev = new QKeyEvent ( QEvent::KeyPress, Qt::Key_Down, 0,0 );
QApplication::postEvent( mCardView, ev );
}
void KAddressBookCardView::readConfig(KConfig *config)
{
KAddressBookView::readConfig(config);
// costum colors?
if ( config->readBoolEntry( "EnableCustomColors", false ) )
{
QPalette p( mCardView->palette() );
QColor c = p.color(QPalette::Normal, QColorGroup::Base );
p.setColor( QPalette::Normal, QColorGroup::Base, config->readColorEntry( "BackgroundColor", &c ) );
c = p.color(QPalette::Normal, QColorGroup::Text );
p.setColor( QPalette::Normal, QColorGroup::Text, config->readColorEntry( "TextColor", &c ) );
c = p.color(QPalette::Normal, QColorGroup::Button );
p.setColor( QPalette::Normal, QColorGroup::Button, config->readColorEntry( "HeaderColor", &c ) );
c = p.color(QPalette::Normal, QColorGroup::ButtonText );
p.setColor( QPalette::Normal, QColorGroup::ButtonText, config->readColorEntry( "HeaderTextColor", &c ) );
c = p.color(QPalette::Normal, QColorGroup::Highlight );
p.setColor( QPalette::Normal, QColorGroup::Highlight, config->readColorEntry( "HighlightColor", &c ) );
c = p.color(QPalette::Normal, QColorGroup::HighlightedText );
p.setColor( QPalette::Normal, QColorGroup::HighlightedText, config->readColorEntry( "HighlightedTextColor", &c ) );
mCardView->viewport()->setPalette( p );
}
else
{
// needed if turned off during a session.
mCardView->viewport()->setPalette( mCardView->palette() );
}
//custom fonts?
QFont f( font() );
if ( config->readBoolEntry( "EnableCustomFonts", false ) )
{
mCardView->setFont( config->readFontEntry( "TextFont", &f) );
f.setBold( true );
mCardView->setHeaderFont( config->readFontEntry( "HeaderFont", &f ) );
}
else
{
mCardView->setFont( f );
f.setBold( true );
mCardView->setHeaderFont( f );
}
mCardView->setDrawCardBorder(config->readBoolEntry("DrawBorder", true));
mCardView->setDrawColSeparators(config->readBoolEntry("DrawSeparators",
true));
mCardView->setDrawFieldLabels(config->readBoolEntry("DrawFieldLabels",false));
mShowEmptyFields = config->readBoolEntry("ShowEmptyFields", false);
mCardView->setShowEmptyFields( mShowEmptyFields );
mCardView->setItemWidth( config->readNumEntry( "ItemWidth", 200 ) );
mCardView->setItemMargin( config->readNumEntry( "ItemMargin", 0 ) );
mCardView->setItemSpacing( config->readNumEntry( "ItemSpacing", 10 ) );
mCardView->setSeparatorWidth( config->readNumEntry( "SeparatorWidth", 2 ) );
+#if 0
+ // LR KABPrefs::instance()->mHonorSingleClick is handled and fixed in cardviews contentsMouseDoubleClickEven
disconnect(mCardView, SIGNAL(executed(CardViewItem *)),
this, SLOT(addresseeExecuted(CardViewItem *)));
if (KABPrefs::instance()->mHonorSingleClick)
connect(mCardView, SIGNAL(executed(CardViewItem *)),
this, SLOT(addresseeExecuted(CardViewItem *)));
else
connect(mCardView, SIGNAL(doubleClicked(CardViewItem *)),
this, SLOT(addresseeExecuted(CardViewItem *)));
+#endif
+ connect(mCardView, SIGNAL(doubleClicked(CardViewItem *)),
+ this, SLOT(addresseeExecuted(CardViewItem *)));
}
void KAddressBookCardView::writeConfig( KConfig *config )
{
config->writeEntry( "ItemWidth", mCardView->itemWidth() );
KAddressBookView::writeConfig( config );
}
void KAddressBookCardView::doSearch( const QString& s,KABC::Field *field )
{
mCardView->clear();
if ( s.isEmpty() || s == "*" ) {
refresh();
return;
}
QString pattern = s.lower()+"*";
QRegExp re;
re.setWildcard(true); // most people understand these better.
re.setCaseSensitive(false);
re.setPattern( pattern );
if (!re.isValid())
return;
mCardView->viewport()->setUpdatesEnabled( false );
KABC::Addressee::List addresseeList = addressees();
KABC::Addressee::List::Iterator it;
if ( field ) {
for (it = addresseeList.begin(); it != addresseeList.end(); ++it ) {
#if QT_VERSION >= 300
if (re.search(field->value( *it ).lower()) != -1)
#else
if (re.match(field->value( *it ).lower()) != -1)
#endif
new AddresseeCardViewItem(fields(), mShowEmptyFields,
addressBook(), *it, mCardView);
}
} else {
KABC::Field::List fieldList = fields();
KABC::Field::List::ConstIterator fieldIt;
for (it = addresseeList.begin(); it != addresseeList.end(); ++it ) {
for ( fieldIt = fieldList.begin(); fieldIt != fieldList.end(); ++fieldIt ) {
#if QT_VERSION >= 300
if (re.search((*fieldIt)->value( *it ).lower()) != -1)
#else
if (re.match((*fieldIt)->value( *it ).lower()) != -1)
#endif
{
new AddresseeCardViewItem(fields(), mShowEmptyFields,
addressBook(), *it, mCardView);
continue;
}
}
}
}
mCardView->viewport()->setUpdatesEnabled( true );
mCardView->viewport()->update();
if ( mCardView->firstItem() ) {
mCardView->setCurrentItem ( mCardView->firstItem() );
mCardView->setSelected ( mCardView->firstItem() , true );
}
else
emit selected(QString::null);
}
QStringList KAddressBookCardView::selectedUids()
{
QStringList uidList;
CardViewItem *item;
AddresseeCardViewItem *aItem;
for (item = mCardView->firstItem(); item; item = item->nextItem())
{
if (item->isSelected())
{
#ifndef KAB_EMBEDDED
aItem = dynamic_cast<AddresseeCardViewItem*>(item);
#else //KAB_EMBEDDED
aItem = (AddresseeCardViewItem*)(item);
#endif //KAB_EMBEDDED
if (aItem)
uidList << aItem->addressee().uid();
}
}
return uidList;
}
void KAddressBookCardView::refresh(QString uid)
{
CardViewItem *item;
AddresseeCardViewItem *aItem;
if (uid.isNull())
{
// Rebuild the view
mCardView->viewport()->setUpdatesEnabled( false );
mCardView->clear();
KABC::Addressee::List addresseeList = addressees();
KABC::Addressee::List::Iterator iter;
for (iter = addresseeList.begin(); iter != addresseeList.end(); ++iter)
{
if ( (*iter).uid().left(2) == "la" && (*iter).uid().left(19) == QString("last-syncAddressee-") )
continue;
aItem = new AddresseeCardViewItem(fields(), mShowEmptyFields,
addressBook(), *iter, mCardView);
}
mCardView->viewport()->setUpdatesEnabled( true );
mCardView->viewport()->update();
// by default nothing is selected
emit selected(QString::null);
}
else
{
// Try to find the one to refresh
bool found = false;
for (item = mCardView->firstItem(); item && !found;
item = item->nextItem())
{
#ifndef KAB_EMBEDDED
aItem = dynamic_cast<AddresseeCardViewItem*>(item);
#else //KAB_EMBEDDED
aItem = (AddresseeCardViewItem*)(item);
#endif //KAB_EMBEDDED
if ((aItem) && (aItem->addressee().uid() == uid))
{
aItem->refresh();
found = true;
}
}
}
}
void KAddressBookCardView::setSelected(QString uid, bool selected)
{
CardViewItem *item;
AddresseeCardViewItem *aItem;
if (uid.isNull())
{
mCardView->selectAll(selected);
}
else
{
bool found = false;
for (item = mCardView->firstItem(); item && !found;
item = item->nextItem())
{
#ifndef KAB_EMBEDDED
aItem = dynamic_cast<AddresseeCardViewItem*>(item);
#else //KAB_EMBEDDED
aItem = (AddresseeCardViewItem*)(item);
#endif //KAB_EMBEDDED
if ((aItem) && (aItem->addressee().uid() == uid))
{
mCardView->setSelected(aItem, selected);
mCardView->ensureItemVisible(item);
found = true;
}
}
}
}
//US added an additional method without parameter
void KAddressBookCardView::setSelected()
{
setSelected(QString::null, true);
}
void KAddressBookCardView::addresseeExecuted(CardViewItem *item)
{
#ifndef KAB_EMBEDDED
AddresseeCardViewItem *aItem = dynamic_cast<AddresseeCardViewItem*>(item);
#else //KAB_EMBEDDED
AddresseeCardViewItem *aItem = (AddresseeCardViewItem*)(item);
#endif //KAB_EMBEDDED
if (aItem)
{
//kdDebug()<<"... even has a valid item:)"<<endl;
emit executed(aItem->addressee().uid());
}
}
void KAddressBookCardView::addresseeSelected()
{
CardViewItem *item;
AddresseeCardViewItem *aItem;
bool found = false;
for (item = mCardView->firstItem(); item && !found;
item = item->nextItem())