summaryrefslogtreecommitdiffabout
path: root/kaddressbook/views/cardview.cpp
Side-by-side diff
Diffstat (limited to 'kaddressbook/views/cardview.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--kaddressbook/views/cardview.cpp9
1 files changed, 4 insertions, 5 deletions
diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp
index 84d3116..b6e053f 100644
--- a/kaddressbook/views/cardview.cpp
+++ b/kaddressbook/views/cardview.cpp
@@ -555,786 +555,785 @@ void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip )
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())
{
mFlagKeyPressed = false;
mFlagBlockKeyPressed = false;
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()) );
//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)
{
item->setSelected(selected);
item->repaintCard();
emit selectionChanged();
}
else if (d->mSelectionMode == CardView::Extended)
{
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
item->setSelected(selected);
item->repaintCard();
emit selectionChanged();
}
}
bool CardView::isSelected(CardViewItem *item) const
{
return (item && item->isSelected());
}
CardViewItem *CardView::selectedItem() const
{
// find the first selected item
QPtrListIterator<CardViewItem> iter(d->mItemList);
for (iter.toFirst(); iter.current(); ++iter)
{
if ((*iter)->isSelected())
return *iter;
}
return 0;
}
CardViewItem *CardView::firstItem() const
{
return d->mItemList.first();
}
int CardView::childCount() const
{
return d->mItemList.count();
}
/*US
CardViewItem *CardView::findItem(const QString &text, const QString &label,
Qt::StringComparisonMode compare)
{
// IF the text is empty, we will return null, since empty text will
// match anything!
if (text.isEmpty())
return 0;
QPtrListIterator<CardViewItem> iter(d->mItemList);
if (compare & Qt::BeginsWith)
{
QString value;
for (iter.toFirst(); iter.current(); ++iter)
{
value = (*iter)->fieldValue(label).upper();
if (value.startsWith(text.upper()))
return *iter;
}
}
else
{
kdDebug(5720) << "CardView::findItem: search method not implemented" << endl;
}
return 0;
}
*/
uint CardView::columnWidth()
{
return d->mDrawSeparators ?
d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth :
d->mItemWidth + d->mItemSpacing;
}
void CardView::drawContents(QPainter *p, int clipx, int clipy,
int clipw, int cliph)
{
- QScrollView::drawContents(p, clipx, clipy, clipw, cliph);
-
+ //QScrollView::drawContents(p, clipx, clipy, clipw, cliph);
if (d->mLayoutDirty)
calcLayout();
//kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy
// << ", " << clipw << ", " << cliph << endl;
QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale
-
+ int cX, cY;
+ contentsToViewport ( clipx, clipy, cX, cY );
QRect clipRect(clipx, clipy, clipw, cliph);
QRect cardRect;
QRect sepRect;
CardViewItem *item;
CardViewSeparator *sep;
-
// make sure the viewport is a pure background
- viewport()->erase(clipRect);
+ viewport()->erase( QRect ( cX, cY , clipw, cliph ) );
// Now tell the cards to draw, if they are in the clip region
QPtrListIterator<CardViewItem> iter(d->mItemList);
for (iter.toFirst(); iter.current(); ++iter)
{
item = *iter;
cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() );
if (clipRect.intersects(cardRect) || clipRect.contains(cardRect))
{
//kdDebug() << "\trepainting card at: " << cardRect.x() << ", "
// << cardRect.y() << endl;
// Tell the card to paint
p->save();
p->translate(cardRect.x(), cardRect.y());
item->paintCard(p, cg);
p->restore();
}
}
// Followed by the separators if they are in the clip region
QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
for (sepIter.toFirst(); sepIter.current(); ++sepIter)
{
sep = *sepIter;
sepRect = sep->mRect;
if (clipRect.intersects(sepRect) || clipRect.contains(sepRect))
{
p->save();
p->translate(sepRect.x(), sepRect.y());
sep->paintSeparator(p, cg);
p->restore();
}
}
}
void CardView::resizeEvent(QResizeEvent *e)
{
QScrollView::resizeEvent(e);
setLayoutDirty(true);
}
void CardView::calcLayout()
{
//kdDebug() << "CardView::calcLayout:" << endl;
// Start in the upper left corner and layout all the
// cars using their height and width
int maxWidth = 0;
int maxHeight = 0;
int xPos = 0;
int yPos = 0;
int cardSpacing = d->mItemSpacing;
// delete the old separators
d->mSeparatorList.clear();
QPtrListIterator<CardViewItem> iter(d->mItemList);
CardViewItem *item = 0;
CardViewSeparator *sep = 0;
xPos += cardSpacing;
for (iter.toFirst(); iter.current(); ++iter)
{
item = *iter;
yPos += cardSpacing;
if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height())
{
maxHeight = QMAX(maxHeight, yPos);
// Drawing in this column would be greater than the height
// of the scroll view, so move to next column
yPos = cardSpacing;
xPos += cardSpacing + maxWidth;
if (d->mDrawSeparators)
{
// Create a separator since the user asked
sep = new CardViewSeparator(this);
sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin));
xPos += d->mSepWidth + cardSpacing;
d->mSeparatorList.append(sep);
}
maxWidth = 0;
}
item->d->x = xPos;
item->d->y = yPos;
yPos += item->height();
maxWidth = QMAX(maxWidth, d->mItemWidth);
}
xPos += maxWidth;
resizeContents( xPos + cardSpacing, maxHeight );
// Update the height of all the separators now that we know the
// max height of a column
QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList);
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 && 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 && !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();