author | zautrix <zautrix> | 2004-10-29 10:42:31 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-10-29 10:42:31 (UTC) |
commit | d96b4fd7188145c49120dd159b0ac00c987f4972 (patch) (side-by-side diff) | |
tree | ba8f3910a72938aa44aa82a477bbd84f5414a214 | |
parent | e152dd9c19c69e6efff6c593b2bf081bc426c7d5 (diff) | |
download | kdepimpi-d96b4fd7188145c49120dd159b0ac00c987f4972.zip kdepimpi-d96b4fd7188145c49120dd159b0ac00c987f4972.tar.gz kdepimpi-d96b4fd7188145c49120dd159b0ac00c987f4972.tar.bz2 |
made cardview handling singleclick and return pressed
-rw-r--r-- | kaddressbook/views/cardview.cpp | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp index 65f793c..6351c11 100644 --- a/kaddressbook/views/cardview.cpp +++ b/kaddressbook/views/cardview.cpp @@ -467,384 +467,385 @@ 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) @@ -1077,573 +1078,575 @@ 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()) { 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()) { emit executed(item); - } - emit doubleClicked(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 ); + case Key_Enter: + { + emit returnPressed( d->mCurrentItem ); + emit executed( d->mCurrentItem ); + } break; default: if ( (e->state() & ControlButton) && e->key() == Key_A ) { // select all selectAll( true ); break; } // if we have a string, do autosearch else if ( ! e->text().isEmpty() && e->text()[0].isPrint() ) { } break; } // handle selection if ( aItem ) { if ( d->mSelectionMode == CardView::Extended ) { if ( (e->state() & ShiftButton) ) { // shift button: toggle range // if control button is pressed, leave all items // and toggle selection current->old current // otherwise, ?????? bool s = ! aItem->isSelected(); int from, to, a, b; a = d->mItemList.findRef( aItem ); b = d->mItemList.findRef( old ); from = a < b ? a : b; to = a > b ? a : b; if ( to - from > 1 ) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); } //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; CardViewItem *item; for ( ; from <= to; from++ ) { item = d->mItemList.at( from ); item->setSelected( s ); repaintItem( item ); } emit selectionChanged(); } else if ( (e->state() & ControlButton) ) { // control button: do nothing } else { // no button: move selection to this item bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); setSelected( aItem, true ); emit selectionChanged(); } } } } void CardView::contentsWheelEvent( QWheelEvent * e ) { scrollBy(2*e->delta()/-3, 0); } void CardView::setLayoutDirty(bool dirty) { if (d->mLayoutDirty != dirty) { d->mLayoutDirty = dirty; repaint(); } } void CardView::setDrawCardBorder(bool enabled) { if (enabled != d->mDrawCardBorder) { d->mDrawCardBorder = enabled; repaint(); } } bool CardView::drawCardBorder() const { return d->mDrawCardBorder; } void CardView::setDrawColSeparators(bool enabled) { if (enabled != d->mDrawSeparators) { d->mDrawSeparators = enabled; setLayoutDirty(true); } } bool CardView::drawColSeparators() const { return d->mDrawSeparators; } void CardView::setDrawFieldLabels(bool enabled) { if (enabled != d->mDrawFieldLabels) { d->mDrawFieldLabels = enabled; repaint(); } } bool CardView::drawFieldLabels() const { return d->mDrawFieldLabels; } void CardView::setShowEmptyFields(bool show) { if (show != d->mShowEmptyFields) { d->mShowEmptyFields = show; setLayoutDirty(true); } } bool CardView::showEmptyFields() const { return d->mShowEmptyFields; } void CardView::startDrag() { // The default implementation is a no-op. It must be // reimplemented in a subclass to be useful } void CardView::tryShowFullText() { d->mTimer->stop(); // if we have an item QPoint cpos = viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ); CardViewItem *item = itemAt( cpos ); if ( item ) { // query it for a value to display //QString s = item ? item->caption() : "(no item)"; //kdDebug()<<"MOUSE REST: "<<s<<endl; QPoint ipos = cpos - itemRect( item ).topLeft(); item->showFullString( ipos, d->mTip ); } } void CardView::drawRubberBands( int pos ) { if ( pos && ((pos-d->firstX)/d->span) - d->colspace - d->mSepWidth < MIN_ITEM_WIDTH ) return; int tmpcw = (d->mRubberBandAnchor-d->firstX)/d->span; int x = d->firstX + tmpcw - d->mSepWidth - contentsX(); int h = visibleHeight(); QPainter p( viewport() ); p.setRasterOp( XorROP ); p.setPen( gray ); p.setBrush( gray ); uint n = d->first; // erase if ( d->mRubberBandAnchor ) do { p.drawRect( x, 0, 2, h ); x += tmpcw; n++; } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); // paint new if ( ! pos ) return; tmpcw = (pos - d->firstX)/d->span; n = d->first; x = d->firstX + tmpcw - d->mSepWidth - contentsX(); do { p.drawRect( x, 0, 2, h ); x += tmpcw; n++; } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); d->mRubberBandAnchor = pos; |