kdeui Library API Documentation

klistview.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org> 00003 Copyright (C) 2000,2003 Charles Samuels <charles@kde.org> 00004 Copyright (C) 2000 Peter Putzer 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2 as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 #include "config.h" 00021 00022 #include <qdragobject.h> 00023 #include <qtimer.h> 00024 #include <qheader.h> 00025 #include <qcursor.h> 00026 #include <qtooltip.h> 00027 #include <qstyle.h> 00028 #include <qpainter.h> 00029 00030 #include <kglobalsettings.h> 00031 #include <kconfig.h> 00032 #include <kcursor.h> 00033 #include <kapplication.h> 00034 #include <kipc.h> 00035 #include <kdebug.h> 00036 00037 #include "klistview.h" 00038 #include "klistviewlineedit.h" 00039 00040 class KListView::Tooltip : public QToolTip 00041 { 00042 public: 00043 Tooltip (KListView* parent, QToolTipGroup* group = 0L); 00044 virtual ~Tooltip () {} 00045 00046 protected: 00050 virtual void maybeTip (const QPoint&); 00051 00052 private: 00053 KListView* mParent; 00054 }; 00055 00056 KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group) 00057 : QToolTip (parent, group), 00058 mParent (parent) 00059 { 00060 } 00061 00062 void KListView::Tooltip::maybeTip (const QPoint&) 00063 { 00064 // FIXME 00065 } 00066 00067 class KListView::KListViewPrivate 00068 { 00069 public: 00070 KListViewPrivate (KListView* listview) 00071 : pCurrentItem (0), 00072 autoSelectDelay(0), 00073 dragOverItem(0), 00074 dragDelay (KGlobalSettings::dndEventDelay()), 00075 editor (new KListViewLineEdit (listview)), 00076 cursorInExecuteArea(false), 00077 itemsMovable (true), 00078 selectedBySimpleMove(false), 00079 selectedUsingMouse(false), 00080 itemsRenameable (false), 00081 validDrag (false), 00082 dragEnabled (false), 00083 autoOpen (true), 00084 disableAutoSelection (false), 00085 dropVisualizer (true), 00086 dropHighlighter (false), 00087 createChildren (true), 00088 pressedOnSelected (false), 00089 wasShiftEvent (false), 00090 fullWidth (false), 00091 sortAscending(true), 00092 tabRename(true), 00093 sortColumn(0), 00094 selectionDirection(0), 00095 tooltipColumn (0), 00096 selectionMode (Single), 00097 contextMenuKey (KGlobalSettings::contextMenuKey()), 00098 showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()), 00099 mDropVisualizerWidth (4), 00100 paintAbove (0), 00101 paintCurrent (0), 00102 paintBelow (0), 00103 painting (false), 00104 shadeSortColumn(KGlobalSettings::shadeSortColumn()) 00105 { 00106 renameable.append(0); 00107 connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int))); 00108 } 00109 00110 ~KListViewPrivate () 00111 { 00112 delete editor; 00113 } 00114 00115 QListViewItem* pCurrentItem; 00116 00117 QTimer autoSelect; 00118 int autoSelectDelay; 00119 00120 QTimer dragExpand; 00121 QListViewItem* dragOverItem; 00122 QPoint dragOverPoint; 00123 00124 QPoint startDragPos; 00125 int dragDelay; 00126 00127 KListViewLineEdit *editor; 00128 QValueList<int> renameable; 00129 00130 bool cursorInExecuteArea:1; 00131 bool bUseSingle:1; 00132 bool bChangeCursorOverItem:1; 00133 bool itemsMovable:1; 00134 bool selectedBySimpleMove : 1; 00135 bool selectedUsingMouse:1; 00136 bool itemsRenameable:1; 00137 bool validDrag:1; 00138 bool dragEnabled:1; 00139 bool autoOpen:1; 00140 bool disableAutoSelection:1; 00141 bool dropVisualizer:1; 00142 bool dropHighlighter:1; 00143 bool createChildren:1; 00144 bool pressedOnSelected:1; 00145 bool wasShiftEvent:1; 00146 bool fullWidth:1; 00147 bool sortAscending:1; 00148 bool tabRename:1; 00149 00150 int sortColumn; 00151 00152 //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX 00153 int selectionDirection; 00154 int tooltipColumn; 00155 00156 SelectionModeExt selectionMode; 00157 int contextMenuKey; 00158 bool showContextMenusOnPress; 00159 00160 QRect mOldDropVisualizer; 00161 int mDropVisualizerWidth; 00162 QRect mOldDropHighlighter; 00163 QListViewItem *afterItemDrop; 00164 QListViewItem *parentItemDrop; 00165 00166 QListViewItem *paintAbove; 00167 QListViewItem *paintCurrent; 00168 QListViewItem *paintBelow; 00169 bool painting:1; 00170 bool shadeSortColumn:1; 00171 00172 QColor alternateBackground; 00173 }; 00174 00175 00176 KListViewLineEdit::KListViewLineEdit(KListView *parent) 00177 : KLineEdit(parent->viewport()), item(0), col(0), p(parent) 00178 { 00179 setFrame( false ); 00180 hide(); 00181 connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() )); 00182 } 00183 00184 KListViewLineEdit::~KListViewLineEdit() 00185 { 00186 } 00187 00188 QListViewItem *KListViewLineEdit::currentItem() const 00189 { 00190 return item; 00191 } 00192 00193 void KListViewLineEdit::load(QListViewItem *i, int c) 00194 { 00195 item=i; 00196 col=c; 00197 00198 QRect rect(p->itemRect(i)); 00199 setText(item->text(c)); 00200 home( true ); 00201 00202 int fieldX = rect.x() - 1; 00203 int fieldW = p->columnWidth(col) + 2; 00204 00205 QHeader* const pHeader = p->header(); 00206 00207 const int pos = pHeader->mapToIndex(col); 00208 for ( int index = 0; index < pos; ++index ) 00209 fieldX += p->columnWidth( pHeader->mapToSection( index )); 00210 00211 if ( col == 0 ) { 00212 int d = i->depth() + (p->rootIsDecorated() ? 1 : 0); 00213 d *= p->treeStepSize(); 00214 fieldX += d; 00215 fieldW -= d; 00216 } 00217 00218 if ( i->pixmap( col ) ) {// add width of pixmap 00219 int d = i->pixmap( col )->width(); 00220 fieldX += d; 00221 fieldW -= d; 00222 } 00223 00224 setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2); 00225 show(); 00226 setFocus(); 00227 } 00228 00229 /* Helper functions to for 00230 * tabOrderedRename functionality. 00231 */ 00232 00233 static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir) 00234 { 00235 if (pi) 00236 { 00237 // Find the next renameable column in the current row 00238 for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir) 00239 if (pl->isRenameable(start)) 00240 return start; 00241 } 00242 00243 return -1; 00244 } 00245 00246 static QListViewItem *prevItem (QListViewItem *pi) 00247 { 00248 QListViewItem *pa = pi->itemAbove(); 00249 00250 /* Does what the QListViewItem::previousSibling() 00251 * of my dreams would do. 00252 */ 00253 if (pa && pa->parent() == pi->parent()) 00254 return pa; 00255 00256 return 0; 00257 } 00258 00259 static QListViewItem *lastQChild (QListViewItem *pi) 00260 { 00261 if (pi) 00262 { 00263 /* Since there's no QListViewItem::lastChild(). 00264 * This finds the last sibling for the given 00265 * item. 00266 */ 00267 for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling()) 00268 pi = pt; 00269 } 00270 00271 return pi; 00272 } 00273 00274 void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward) 00275 { 00276 const int ncols = p->columns(); 00277 const int dir = forward ? +1 : -1; 00278 const int restart = forward ? 0 : (ncols - 1); 00279 QListViewItem *top = (pitem && pitem->parent()) 00280 ? pitem->parent()->firstChild() 00281 : p->firstChild(); 00282 QListViewItem *pi = pitem; 00283 00284 terminate(); // Save current changes 00285 00286 do 00287 { 00288 /* Check the rest of the current row for an editable column, 00289 * if that fails, check the entire next/previous row. The 00290 * last case goes back to the first item in the current branch 00291 * or the last item in the current branch depending on the 00292 * direction. 00293 */ 00294 if ((column = nextCol(p, pi, column + dir, dir)) != -1 || 00295 (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 || 00296 (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1) 00297 { 00298 if (pi) 00299 { 00300 p->setCurrentItem(pi); // Calls terminate 00301 p->rename(pi, column); 00302 00303 /* Some listviews may override rename() to 00304 * prevent certain items from being renamed, 00305 * if this is done, [m_]item will be NULL 00306 * after the rename() call... try again. 00307 */ 00308 if (!item) 00309 continue; 00310 00311 break; 00312 } 00313 } 00314 } 00315 while (pi && !item); 00316 } 00317 00318 #ifdef KeyPress 00319 #undef KeyPress 00320 #endif 00321 00322 bool KListViewLineEdit::event (QEvent *pe) 00323 { 00324 if (pe->type() == QEvent::KeyPress) 00325 { 00326 QKeyEvent *k = (QKeyEvent *) pe; 00327 00328 if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) && 00329 p->tabOrderedRenaming() && p->itemsRenameable() && 00330 !(k->state() & ControlButton || k->state() & AltButton)) 00331 { 00332 selectNextCell(item, col, 00333 (k->key() == Key_Tab && !(k->state() & ShiftButton))); 00334 return true; 00335 } 00336 } 00337 00338 return KLineEdit::event(pe); 00339 } 00340 00341 void KListViewLineEdit::keyPressEvent(QKeyEvent *e) 00342 { 00343 if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter ) 00344 terminate(true); 00345 else if(e->key() == Qt::Key_Escape) 00346 terminate(false); 00347 else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up) 00348 { 00349 terminate(true); 00350 KLineEdit::keyPressEvent(e); 00351 } 00352 else 00353 KLineEdit::keyPressEvent(e); 00354 } 00355 00356 void KListViewLineEdit::terminate() 00357 { 00358 terminate(true); 00359 } 00360 00361 void KListViewLineEdit::terminate(bool commit) 00362 { 00363 if ( item ) 00364 { 00365 //kdDebug() << "KListViewLineEdit::terminate " << commit << endl; 00366 if (commit) 00367 item->setText(col, text()); 00368 int c=col; 00369 QListViewItem *i=item; 00370 col=0; 00371 item=0; 00372 hide(); // will call focusOutEvent, that's why we set item=0 before 00373 if (commit) 00374 emit done(i,c); 00375 } 00376 } 00377 00378 void KListViewLineEdit::focusOutEvent(QFocusEvent *ev) 00379 { 00380 QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev); 00381 // Don't let a RMB close the editor 00382 if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow) 00383 terminate(true); 00384 else 00385 KLineEdit::focusOutEvent(ev); 00386 } 00387 00388 void KListViewLineEdit::paintEvent( QPaintEvent *e ) 00389 { 00390 KLineEdit::paintEvent( e ); 00391 00392 if ( !frame() ) { 00393 QPainter p( this ); 00394 p.setClipRegion( e->region() ); 00395 p.drawRect( rect() ); 00396 } 00397 } 00398 00399 // selection changed -> terminate. As our "item" can be already deleted, 00400 // we can't call terminate(false), because that would emit done() with 00401 // a dangling pointer to "item". 00402 void KListViewLineEdit::slotSelectionChanged() 00403 { 00404 item = 0; 00405 col = 0; 00406 hide(); 00407 } 00408 00409 00410 KListView::KListView( QWidget *parent, const char *name ) 00411 : QListView( parent, name ), 00412 d (new KListViewPrivate (this)) 00413 { 00414 setDragAutoScroll(true); 00415 00416 connect( this, SIGNAL( onViewport() ), 00417 this, SLOT( slotOnViewport() ) ); 00418 connect( this, SIGNAL( onItem( QListViewItem * ) ), 00419 this, SLOT( slotOnItem( QListViewItem * ) ) ); 00420 00421 connect (this, SIGNAL(contentsMoving(int,int)), 00422 this, SLOT(cleanDropVisualizer())); 00423 connect (this, SIGNAL(contentsMoving(int,int)), 00424 this, SLOT(cleanItemHighlighter())); 00425 00426 slotSettingsChanged(KApplication::SETTINGS_MOUSE); 00427 if (kapp) 00428 { 00429 connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) ); 00430 kapp->addKipcEventMask( KIPC::SettingsChanged ); 00431 } 00432 00433 connect(&d->autoSelect, SIGNAL( timeout() ), 00434 this, SLOT( slotAutoSelect() ) ); 00435 connect(&d->dragExpand, SIGNAL( timeout() ), 00436 this, SLOT( slotDragExpand() ) ); 00437 00438 // context menu handling 00439 if (d->showContextMenusOnPress) 00440 { 00441 connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), 00442 this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00443 } 00444 else 00445 { 00446 connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), 00447 this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00448 } 00449 00450 connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)), 00451 this, SLOT (emitContextMenu (KListView*, QListViewItem*))); 00452 d->alternateBackground = KGlobalSettings::alternateBackgroundColor(); 00453 } 00454 00455 KListView::~KListView() 00456 { 00457 delete d; 00458 } 00459 00460 bool KListView::isExecuteArea( const QPoint& point ) 00461 { 00462 QListViewItem* item = itemAt( point ); 00463 if ( item ) { 00464 return isExecuteArea( point.x(), item ); 00465 } 00466 00467 return false; 00468 } 00469 00470 bool KListView::isExecuteArea( int x ) 00471 { 00472 return isExecuteArea( x, 0 ); 00473 } 00474 00475 bool KListView::isExecuteArea( int x, QListViewItem* item ) 00476 { 00477 if( allColumnsShowFocus() ) 00478 return true; 00479 else { 00480 int offset = 0; 00481 00482 00483 int width = columnWidth( 0 ); 00484 00485 QHeader* const thisHeader = header(); 00486 const int pos = thisHeader->mapToIndex( 0 ); 00487 00488 for ( int index = 0; index < pos; ++index ) 00489 offset += columnWidth( thisHeader->mapToSection( index ) ); 00490 00491 x += contentsX(); // in case of a horizontal scrollbar 00492 00493 if ( item ) 00494 { 00495 width = treeStepSize()*( item->depth() + ( rootIsDecorated() ? 1 : 0 ) ); 00496 width += itemMargin(); 00497 int ca = AlignHorizontal_Mask & columnAlignment( 0 ); 00498 if ( ca == AlignLeft || ca == AlignAuto ) { 00499 width += item->width( fontMetrics(), this, 0 ); 00500 if ( width > columnWidth( 0 ) ) 00501 width = columnWidth( 0 ); 00502 } 00503 } 00504 00505 return ( x > offset && x < ( offset + width ) ); 00506 } 00507 } 00508 00509 void KListView::slotOnItem( QListViewItem *item ) 00510 { 00511 QPoint vp = viewport()->mapFromGlobal( QCursor::pos() ); 00512 if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) { 00513 d->autoSelect.start( d->autoSelectDelay, true ); 00514 d->pCurrentItem = item; 00515 } 00516 } 00517 00518 void KListView::slotOnViewport() 00519 { 00520 if ( d->bChangeCursorOverItem ) 00521 viewport()->unsetCursor(); 00522 00523 d->autoSelect.stop(); 00524 d->pCurrentItem = 0L; 00525 } 00526 00527 void KListView::slotSettingsChanged(int category) 00528 { 00529 switch (category) 00530 { 00531 case KApplication::SETTINGS_MOUSE: 00532 d->dragDelay = KGlobalSettings::dndEventDelay(); 00533 d->bUseSingle = KGlobalSettings::singleClick(); 00534 00535 disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), 00536 this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int))); 00537 00538 if( d->bUseSingle ) 00539 connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)), 00540 this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int))); 00541 00542 d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon(); 00543 if ( !d->disableAutoSelection ) 00544 d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); 00545 00546 if( !d->bUseSingle || !d->bChangeCursorOverItem ) 00547 viewport()->unsetCursor(); 00548 00549 break; 00550 00551 case KApplication::SETTINGS_POPUPMENU: 00552 d->contextMenuKey = KGlobalSettings::contextMenuKey (); 00553 d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress (); 00554 00555 if (d->showContextMenusOnPress) 00556 { 00557 disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00558 00559 connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)), 00560 this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00561 } 00562 else 00563 { 00564 disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00565 00566 connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)), 00567 this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int))); 00568 } 00569 break; 00570 00571 default: 00572 break; 00573 } 00574 } 00575 00576 void KListView::slotAutoSelect() 00577 { 00578 // check that the item still exists 00579 if( itemIndex( d->pCurrentItem ) == -1 ) 00580 return; 00581 00582 if (!isActiveWindow()) 00583 { 00584 d->autoSelect.stop(); 00585 return; 00586 } 00587 00588 //Give this widget the keyboard focus. 00589 if( !hasFocus() ) 00590 setFocus(); 00591 00592 ButtonState keybstate = KApplication::keyboardMouseState(); 00593 00594 QListViewItem* previousItem = currentItem(); 00595 setCurrentItem( d->pCurrentItem ); 00596 00597 if( d->pCurrentItem ) { 00598 //Shift pressed? 00599 if( (keybstate & Qt::ShiftButton) ) { 00600 bool block = signalsBlocked(); 00601 blockSignals( true ); 00602 00603 //No Ctrl? Then clear before! 00604 if( !(keybstate & Qt::ControlButton) ) 00605 clearSelection(); 00606 00607 bool select = !d->pCurrentItem->isSelected(); 00608 bool update = viewport()->isUpdatesEnabled(); 00609 viewport()->setUpdatesEnabled( false ); 00610 00611 bool down = previousItem->itemPos() < d->pCurrentItem->itemPos(); 00612 QListViewItemIterator lit( down ? previousItem : d->pCurrentItem ); 00613 for ( ; lit.current(); ++lit ) { 00614 if ( down && lit.current() == d->pCurrentItem ) { 00615 d->pCurrentItem->setSelected( select ); 00616 break; 00617 } 00618 if ( !down && lit.current() == previousItem ) { 00619 previousItem->setSelected( select ); 00620 break; 00621 } 00622 lit.current()->setSelected( select ); 00623 } 00624 00625 blockSignals( block ); 00626 viewport()->setUpdatesEnabled( update ); 00627 triggerUpdate(); 00628 00629 emit selectionChanged(); 00630 00631 if( selectionMode() == QListView::Single ) 00632 emit selectionChanged( d->pCurrentItem ); 00633 } 00634 else if( (keybstate & KApplication::ControlModifier) ) 00635 setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() ); 00636 else { 00637 bool block = signalsBlocked(); 00638 blockSignals( true ); 00639 00640 if( !d->pCurrentItem->isSelected() ) 00641 clearSelection(); 00642 00643 blockSignals( block ); 00644 00645 setSelected( d->pCurrentItem, true ); 00646 } 00647 } 00648 else 00649 kdDebug() << "KListView::slotAutoSelect: Thatīs not supposed to happen!!!!" << endl; 00650 } 00651 00652 void KListView::slotHeaderChanged() 00653 { 00654 00655 const int colCount = columns(); 00656 if (d->fullWidth && colCount) 00657 { 00658 int w = 0; 00659 const int lastColumn = colCount - 1; 00660 for (int i = 0; i < lastColumn; ++i) w += columnWidth(i); 00661 setColumnWidth( lastColumn, viewport()->width() - w - 1 ); 00662 } 00663 } 00664 00665 void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c ) 00666 { 00667 if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) { 00668 d->validDrag=false; 00669 00670 // Double click mode ? 00671 if ( !d->bUseSingle ) 00672 { 00673 viewport()->unsetCursor(); 00674 emit executed( item ); 00675 emit executed( item, pos, c ); 00676 } 00677 else 00678 { 00679 ButtonState keybstate = KApplication::keyboardMouseState(); 00680 00681 d->autoSelect.stop(); 00682 00683 //Donīt emit executed if in SC mode and Shift or Ctrl are pressed 00684 if( !( ((keybstate & Qt::ShiftButton) || (keybstate & Qt::ControlButton)) ) ) { 00685 viewport()->unsetCursor(); 00686 emit executed( item ); 00687 emit executed( item, pos, c ); 00688 } 00689 } 00690 } 00691 } 00692 00693 void KListView::focusInEvent( QFocusEvent *fe ) 00694 { 00695 // kdDebug()<<"KListView::focusInEvent()"<<endl; 00696 QListView::focusInEvent( fe ); 00697 if ((d->selectedBySimpleMove) 00698 && (d->selectionMode == FileManager) 00699 && (fe->reason()!=QFocusEvent::Popup) 00700 && (fe->reason()!=QFocusEvent::ActiveWindow) 00701 && (currentItem())) 00702 { 00703 currentItem()->setSelected(true); 00704 currentItem()->repaint(); 00705 emit selectionChanged(); 00706 }; 00707 } 00708 00709 void KListView::focusOutEvent( QFocusEvent *fe ) 00710 { 00711 cleanDropVisualizer(); 00712 cleanItemHighlighter(); 00713 00714 d->autoSelect.stop(); 00715 00716 if ((d->selectedBySimpleMove) 00717 && (d->selectionMode == FileManager) 00718 && (fe->reason()!=QFocusEvent::Popup) 00719 && (fe->reason()!=QFocusEvent::ActiveWindow) 00720 && (currentItem()) 00721 && (!d->editor->isVisible())) 00722 { 00723 currentItem()->setSelected(false); 00724 currentItem()->repaint(); 00725 emit selectionChanged(); 00726 }; 00727 00728 QListView::focusOutEvent( fe ); 00729 } 00730 00731 void KListView::leaveEvent( QEvent *e ) 00732 { 00733 d->autoSelect.stop(); 00734 00735 QListView::leaveEvent( e ); 00736 } 00737 00738 bool KListView::event( QEvent *e ) 00739 { 00740 if (e->type() == QEvent::ApplicationPaletteChange) 00741 d->alternateBackground=KGlobalSettings::alternateBackgroundColor(); 00742 00743 return QListView::event(e); 00744 } 00745 00746 void KListView::contentsMousePressEvent( QMouseEvent *e ) 00747 { 00748 if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) 00749 { 00750 bool block = signalsBlocked(); 00751 blockSignals( true ); 00752 00753 clearSelection(); 00754 00755 blockSignals( block ); 00756 } 00757 else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove)) 00758 { 00759 d->selectedBySimpleMove=false; 00760 d->selectedUsingMouse=true; 00761 if (currentItem()) 00762 { 00763 currentItem()->setSelected(false); 00764 currentItem()->repaint(); 00765 // emit selectionChanged(); 00766 } 00767 } 00768 00769 QPoint p( contentsToViewport( e->pos() ) ); 00770 QListViewItem *at = itemAt (p); 00771 00772 // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) 00773 bool rootDecoClicked = at 00774 && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + 00775 treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) 00776 && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); 00777 00778 if (e->button() == LeftButton && !rootDecoClicked) 00779 { 00780 //Start a drag 00781 d->startDragPos = e->pos(); 00782 00783 if (at) 00784 { 00785 d->validDrag = true; 00786 d->pressedOnSelected = at->isSelected(); 00787 } 00788 } 00789 00790 QListView::contentsMousePressEvent( e ); 00791 } 00792 00793 void KListView::contentsMouseMoveEvent( QMouseEvent *e ) 00794 { 00795 if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag) 00796 QListView::contentsMouseMoveEvent (e); 00797 00798 QPoint vp = contentsToViewport(e->pos()); 00799 QListViewItem *item = itemAt( vp ); 00800 00801 //do we process cursor changes at all? 00802 if ( item && d->bChangeCursorOverItem && d->bUseSingle ) 00803 { 00804 //Cursor moved on a new item or in/out the execute area 00805 if( (item != d->pCurrentItem) || 00806 (isExecuteArea(vp) != d->cursorInExecuteArea) ) 00807 { 00808 d->cursorInExecuteArea = isExecuteArea(vp); 00809 00810 if( d->cursorInExecuteArea ) //cursor moved in execute area 00811 viewport()->setCursor( KCursor::handCursor() ); 00812 else //cursor moved out of execute area 00813 viewport()->unsetCursor(); 00814 } 00815 } 00816 00817 bool dragOn = dragEnabled(); 00818 QPoint newPos = e->pos(); 00819 if (dragOn && d->validDrag && 00820 (newPos.x() > d->startDragPos.x()+d->dragDelay || 00821 newPos.x() < d->startDragPos.x()-d->dragDelay || 00822 newPos.y() > d->startDragPos.y()+d->dragDelay || 00823 newPos.y() < d->startDragPos.y()-d->dragDelay)) 00824 //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance()) 00825 { 00826 QListView::contentsMouseReleaseEvent( 0 ); 00827 startDrag(); 00828 d->startDragPos = QPoint(); 00829 d->validDrag = false; 00830 } 00831 } 00832 00833 void KListView::contentsMouseReleaseEvent( QMouseEvent *e ) 00834 { 00835 if (e->button() == LeftButton) 00836 { 00837 // If the row was already selected, maybe we want to start an in-place editing 00838 if ( d->pressedOnSelected && itemsRenameable() ) 00839 { 00840 QPoint p( contentsToViewport( e->pos() ) ); 00841 QListViewItem *at = itemAt (p); 00842 if ( at ) 00843 { 00844 // true if the root decoration of the item "at" was clicked (i.e. the +/- sign) 00845 bool rootDecoClicked = 00846 ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) + 00847 treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() ) 00848 && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) ); 00849 00850 if (!rootDecoClicked) 00851 { 00852 int col = header()->mapToLogical( header()->cellAt( p.x() ) ); 00853 if ( d->renameable.contains(col) ) 00854 rename(at, col); 00855 } 00856 } 00857 } 00858 00859 d->pressedOnSelected = false; 00860 d->validDrag = false; 00861 d->startDragPos = QPoint(); 00862 } 00863 QListView::contentsMouseReleaseEvent( e ); 00864 } 00865 00866 void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e ) 00867 { 00868 // We don't want to call the parent method because it does setOpen, 00869 // whereas we don't do it in single click mode... (David) 00870 //QListView::contentsMouseDoubleClickEvent( e ); 00871 00872 QPoint vp = contentsToViewport(e->pos()); 00873 QListViewItem *item = itemAt( vp ); 00874 emit QListView::doubleClicked( item ); // we do it now 00875 00876 int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1; 00877 00878 if( item ) { 00879 emit doubleClicked( item, e->globalPos(), col ); 00880 00881 if( (e->button() == LeftButton) && !d->bUseSingle ) 00882 emitExecute( item, e->globalPos(), col ); 00883 } 00884 } 00885 00886 void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ) 00887 { 00888 if( (btn == LeftButton) && item ) 00889 emitExecute(item, pos, c); 00890 } 00891 00892 void KListView::contentsDropEvent(QDropEvent* e) 00893 { 00894 cleanDropVisualizer(); 00895 cleanItemHighlighter(); 00896 d->dragExpand.stop(); 00897 00898 if (acceptDrag (e)) 00899 { 00900 e->acceptAction(); 00901 QListViewItem *afterme; 00902 QListViewItem *parent; 00903 00904 findDrop(e->pos(), parent, afterme); 00905 00906 if (e->source() == viewport() && itemsMovable()) 00907 movableDropEvent(parent, afterme); 00908 else 00909 { 00910 emit dropped(e, afterme); 00911 emit dropped(this, e, afterme); 00912 emit dropped(e, parent, afterme); 00913 emit dropped(this, e, parent, afterme); 00914 } 00915 } 00916 } 00917 00918 void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme) 00919 { 00920 QPtrList<QListViewItem> items, afterFirsts, afterNows; 00921 QListViewItem *current=currentItem(); 00922 bool hasMoved=false; 00923 for (QListViewItem *i = firstChild(), *iNext=0; i; i = iNext) 00924 { 00925 iNext=i->itemBelow(); 00926 if (!i->isSelected()) 00927 continue; 00928 00929 // don't drop an item after itself, or else 00930 // it moves to the top of the list 00931 if (i==afterme) 00932 continue; 00933 00934 i->setSelected(false); 00935 00936 QListViewItem *afterFirst = i->itemAbove(); 00937 00938 if (!hasMoved) 00939 { 00940 emit aboutToMove(); 00941 hasMoved=true; 00942 } 00943 00944 moveItem(i, parent, afterme); 00945 00946 // ###### This should include the new parent !!! -> KDE 3.0 00947 // If you need this right now, have a look at keditbookmarks. 00948 emit moved(i, afterFirst, afterme); 00949 00950 items.append (i); 00951 afterFirsts.append (afterFirst); 00952 afterNows.append (afterme); 00953 00954 afterme = i; 00955 } 00956 clearSelection(); 00957 for (QListViewItem *i=items.first(); i; i=items.next() ) 00958 i->setSelected(true); 00959 if (current) 00960 setCurrentItem(current); 00961 00962 emit moved(items,afterFirsts,afterNows); 00963 00964 if (firstChild()) 00965 emit moved(); 00966 } 00967 00968 void KListView::contentsDragMoveEvent(QDragMoveEvent *event) 00969 { 00970 if (acceptDrag(event)) 00971 { 00972 event->acceptAction(); 00973 //Clean up the view 00974 00975 findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop); 00976 QPoint vp = contentsToViewport( event->pos() ); 00977 QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L; 00978 00979 if ( item != d->dragOverItem ) 00980 { 00981 d->dragExpand.stop(); 00982 d->dragOverItem = item; 00983 d->dragOverPoint = vp; 00984 if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() ) 00985 d->dragExpand.start( QApplication::startDragTime(), true ); 00986 } 00987 if (dropVisualizer()) 00988 { 00989 QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop); 00990 if (tmpRect != d->mOldDropVisualizer) 00991 { 00992 cleanDropVisualizer(); 00993 d->mOldDropVisualizer=tmpRect; 00994 viewport()->repaint(tmpRect); 00995 } 00996 } 00997 if (dropHighlighter()) 00998 { 00999 QRect tmpRect = drawItemHighlighter(0, itemAt( vp )); 01000 if (tmpRect != d->mOldDropHighlighter) 01001 { 01002 cleanItemHighlighter(); 01003 d->mOldDropHighlighter=tmpRect; 01004 viewport()->repaint(tmpRect); 01005 } 01006 } 01007 } 01008 else 01009 event->ignore(); 01010 } 01011 01012 void KListView::slotDragExpand() 01013 { 01014 if ( itemAt( d->dragOverPoint ) == d->dragOverItem ) 01015 d->dragOverItem->setOpen( true ); 01016 } 01017 01018 void KListView::contentsDragLeaveEvent (QDragLeaveEvent*) 01019 { 01020 d->dragExpand.stop(); 01021 cleanDropVisualizer(); 01022 cleanItemHighlighter(); 01023 } 01024 01025 void KListView::cleanDropVisualizer() 01026 { 01027 if (d->mOldDropVisualizer.isValid()) 01028 { 01029 QRect rect=d->mOldDropVisualizer; 01030 d->mOldDropVisualizer = QRect(); 01031 viewport()->repaint(rect, true); 01032 } 01033 } 01034 01035 int KListView::depthToPixels( int depth ) 01036 { 01037 return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin(); 01038 } 01039 01040 void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after) 01041 { 01042 QPoint p (contentsToViewport(pos)); 01043 01044 // Get the position to put it in 01045 QListViewItem *atpos = itemAt(p); 01046 01047 QListViewItem *above; 01048 if (!atpos) // put it at the end 01049 above = lastItem(); 01050 else 01051 { 01052 // Get the closest item before us ('atpos' or the one above, if any) 01053 if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2)) 01054 above = atpos->itemAbove(); 01055 else 01056 above = atpos; 01057 } 01058 01059 if (above) 01060 { 01061 // if above has children, I might need to drop it as the first item there 01062 01063 if (above->firstChild() && above->isOpen()) 01064 { 01065 parent = above; 01066 after = 0; 01067 return; 01068 } 01069 01070 // Now, we know we want to go after "above". But as a child or as a sibling ? 01071 // We have to ask the "above" item if it accepts children. 01072 if (above->isExpandable()) 01073 { 01074 // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children 01075 if (p.x() >= depthToPixels( above->depth() + 1 ) || 01076 (above->isOpen() && above->childCount() > 0) ) 01077 { 01078 parent = above; 01079 after = 0L; 01080 return; 01081 } 01082 } 01083 01084 // Ok, there's one more level of complexity. We may want to become a new 01085 // sibling, but of an upper-level group, rather than the "above" item 01086 QListViewItem * betterAbove = above->parent(); 01087 QListViewItem * last = above; 01088 while ( betterAbove ) 01089 { 01090 // We are allowed to become a sibling of "betterAbove" only if we are 01091 // after its last child 01092 if ( !last->nextSibling() ) 01093 { 01094 if (p.x() < depthToPixels ( betterAbove->depth() + 1 )) 01095 above = betterAbove; // store this one, but don't stop yet, there may be a better one 01096 else 01097 break; // not enough on the left, so stop 01098 last = betterAbove; 01099 betterAbove = betterAbove->parent(); // up one level 01100 } else 01101 break; // we're among the child of betterAbove, not after the last one 01102 } 01103 } 01104 // set as sibling 01105 after = above; 01106 parent = after ? after->parent() : 0L ; 01107 } 01108 01109 QListViewItem* KListView::lastChild () const 01110 { 01111 QListViewItem* lastchild = firstChild(); 01112 01113 if (lastchild) 01114 for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling()); 01115 01116 return lastchild; 01117 } 01118 01119 QListViewItem *KListView::lastItem() const 01120 { 01121 QListViewItem* last = lastChild(); 01122 01123 for (QListViewItemIterator it (last); it.current(); ++it) 01124 last = it.current(); 01125 01126 return last; 01127 } 01128 01129 KLineEdit *KListView::renameLineEdit() const 01130 { 01131 return d->editor; 01132 } 01133 01134 void KListView::startDrag() 01135 { 01136 QDragObject *drag = dragObject(); 01137 01138 if (!drag) 01139 return; 01140 01141 if (drag->drag() && drag->target() != viewport()) 01142 emit moved(); 01143 } 01144 01145 QDragObject *KListView::dragObject() 01146 { 01147 if (!currentItem()) 01148 return 0; 01149 01150 01151 return new QStoredDrag("application/x-qlistviewitem", viewport()); 01152 } 01153 01154 void KListView::setItemsMovable(bool b) 01155 { 01156 d->itemsMovable=b; 01157 } 01158 01159 bool KListView::itemsMovable() const 01160 { 01161 return d->itemsMovable; 01162 } 01163 01164 void KListView::setItemsRenameable(bool b) 01165 { 01166 d->itemsRenameable=b; 01167 } 01168 01169 bool KListView::itemsRenameable() const 01170 { 01171 return d->itemsRenameable; 01172 } 01173 01174 01175 void KListView::setDragEnabled(bool b) 01176 { 01177 d->dragEnabled=b; 01178 } 01179 01180 bool KListView::dragEnabled() const 01181 { 01182 return d->dragEnabled; 01183 } 01184 01185 void KListView::setAutoOpen(bool b) 01186 { 01187 d->autoOpen=b; 01188 } 01189 01190 bool KListView::autoOpen() const 01191 { 01192 return d->autoOpen; 01193 } 01194 01195 bool KListView::dropVisualizer() const 01196 { 01197 return d->dropVisualizer; 01198 } 01199 01200 void KListView::setDropVisualizer(bool b) 01201 { 01202 d->dropVisualizer=b; 01203 } 01204 01205 QPtrList<QListViewItem> KListView::selectedItems() const 01206 { 01207 return selectedItems(true); 01208 } 01209 01210 QPtrList<QListViewItem> KListView::selectedItems(bool includeHiddenItems) const 01211 { 01212 QPtrList<QListViewItem> list; 01213 01214 // Using selectionMode() instead of selectionModeExt() since for the cases that 01215 // we're interested in selectionMode() should work for either variety of the 01216 // setSelectionMode(). 01217 01218 switch(selectionMode()) 01219 { 01220 case NoSelection: 01221 break; 01222 case Single: 01223 if(selectedItem() && (includeHiddenItems || selectedItem()->isVisible())) 01224 list.append(selectedItem()); 01225 break; 01226 default: 01227 { 01228 int flags = QListViewItemIterator::Selected; 01229 if (!includeHiddenItems) 01230 { 01231 flags |= QListViewItemIterator::Visible; 01232 } 01233 01234 QListViewItemIterator it(const_cast<KListView *>(this), flags); 01235 01236 for(; it.current(); ++it) 01237 list.append(it.current()); 01238 01239 break; 01240 } 01241 } 01242 01243 return list; 01244 } 01245 01246 01247 void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after) 01248 { 01249 // sanity check - don't move a item into its own child structure 01250 QListViewItem *i = parent; 01251 while(i) 01252 { 01253 if(i == item) 01254 return; 01255 i = i->parent(); 01256 } 01257 01258 if (after) 01259 { 01260 item->moveItem(after); 01261 return; 01262 } 01263 01264 // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor 01265 // in here, without ever deleting the item. 01266 if (item->parent()) 01267 item->parent()->takeItem(item); 01268 else 01269 takeItem(item); 01270 01271 if (parent) 01272 parent->insertItem(item); 01273 else 01274 insertItem(item); 01275 } 01276 01277 void KListView::contentsDragEnterEvent(QDragEnterEvent *event) 01278 { 01279 if (acceptDrag (event)) 01280 event->accept(); 01281 } 01282 01283 void KListView::setDropVisualizerWidth (int w) 01284 { 01285 d->mDropVisualizerWidth = w > 0 ? w : 1; 01286 } 01287 01288 QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent, 01289 QListViewItem *after) 01290 { 01291 QRect insertmarker; 01292 01293 if (!after && !parent) 01294 insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2); 01295 else 01296 { 01297 int level = 0; 01298 if (after) 01299 { 01300 QListViewItem* it = 0L; 01301 if (after->isOpen()) 01302 { 01303 // Look for the last child (recursively) 01304 it = after->firstChild(); 01305 if (it) 01306 while (it->nextSibling() || it->firstChild()) 01307 if ( it->nextSibling() ) 01308 it = it->nextSibling(); 01309 else 01310 it = it->firstChild(); 01311 } 01312 01313 insertmarker = itemRect (it ? it : after); 01314 level = after->depth(); 01315 } 01316 else if (parent) 01317 { 01318 insertmarker = itemRect (parent); 01319 level = parent->depth() + 1; 01320 } 01321 insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() ); 01322 insertmarker.setRight (viewport()->width()); 01323 insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1); 01324 insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2); 01325 } 01326 01327 // This is not used anymore, at least by KListView itself (see viewportPaintEvent) 01328 // Remove for KDE 4.0. 01329 if (p) 01330 p->fillRect(insertmarker, Dense4Pattern); 01331 01332 return insertmarker; 01333 } 01334 01335 QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item) 01336 { 01337 QRect r; 01338 01339 if (item) 01340 { 01341 r = itemRect(item); 01342 r.setLeft(r.left()+(item->depth()+(rootIsDecorated() ? 1 : 0))*treeStepSize()); 01343 if (painter) 01344 style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), 01345 QStyle::Style_FocusAtBorder, colorGroup().highlight()); 01346 } 01347 01348 return r; 01349 } 01350 01351 void KListView::cleanItemHighlighter () 01352 { 01353 if (d->mOldDropHighlighter.isValid()) 01354 { 01355 QRect rect=d->mOldDropHighlighter; 01356 d->mOldDropHighlighter = QRect(); 01357 viewport()->repaint(rect, true); 01358 } 01359 } 01360 01361 void KListView::rename(QListViewItem *item, int c) 01362 { 01363 if (d->renameable.contains(c)) 01364 { 01365 ensureItemVisible(item); 01366 d->editor->load(item,c); 01367 } 01368 } 01369 01370 bool KListView::isRenameable (int col) const 01371 { 01372 return d->renameable.contains(col); 01373 } 01374 01375 void KListView::setRenameable (int col, bool renameable) 01376 { 01377 if (col>=header()->count()) return; 01378 01379 d->renameable.remove(col); 01380 if (renameable) 01381 d->renameable+=col; 01382 } 01383 01384 void KListView::doneEditing(QListViewItem *item, int row) 01385 { 01386 emit itemRenamed(item, item->text(row), row); 01387 emit itemRenamed(item); 01388 } 01389 01390 bool KListView::acceptDrag(QDropEvent* e) const 01391 { 01392 return acceptDrops() && itemsMovable() && (e->source()==viewport()); 01393 } 01394 01395 void KListView::setCreateChildren(bool b) 01396 { 01397 d->createChildren=b; 01398 } 01399 01400 bool KListView::createChildren() const 01401 { 01402 return d->createChildren; 01403 } 01404 01405 01406 int KListView::tooltipColumn() const 01407 { 01408 return d->tooltipColumn; 01409 } 01410 01411 void KListView::setTooltipColumn(int column) 01412 { 01413 d->tooltipColumn=column; 01414 } 01415 01416 void KListView::setDropHighlighter(bool b) 01417 { 01418 d->dropHighlighter=b; 01419 } 01420 01421 bool KListView::dropHighlighter() const 01422 { 01423 return d->dropHighlighter; 01424 } 01425 01426 bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const 01427 { 01428 return ((column==tooltipColumn()) && !tooltip(item, column).isEmpty()); 01429 } 01430 01431 QString KListView::tooltip(QListViewItem *item, int column) const 01432 { 01433 return item->text(column); 01434 } 01435 01436 void KListView::setTabOrderedRenaming(bool b) 01437 { 01438 d->tabRename = b; 01439 } 01440 01441 bool KListView::tabOrderedRenaming() const 01442 { 01443 return d->tabRename; 01444 } 01445 01446 void KListView::keyPressEvent (QKeyEvent* e) 01447 { 01448 //don't we need a contextMenuModifier too ? (aleXXX) 01449 if (e->key() == d->contextMenuKey) 01450 { 01451 emit menuShortCutPressed (this, currentItem()); 01452 return; 01453 } 01454 01455 if (d->selectionMode != FileManager) 01456 QListView::keyPressEvent (e); 01457 else 01458 fileManagerKeyPressEvent (e); 01459 } 01460 01461 void KListView::activateAutomaticSelection() 01462 { 01463 d->selectedBySimpleMove=true; 01464 d->selectedUsingMouse=false; 01465 if (currentItem()) 01466 { 01467 currentItem()->setSelected(true); 01468 currentItem()->repaint(); 01469 emit selectionChanged(); 01470 }; 01471 } 01472 01473 void KListView::deactivateAutomaticSelection() 01474 { 01475 d->selectedBySimpleMove=false; 01476 } 01477 01478 bool KListView::automaticSelection() const 01479 { 01480 return d->selectedBySimpleMove; 01481 } 01482 01483 void KListView::fileManagerKeyPressEvent (QKeyEvent* e) 01484 { 01485 //don't care whether it's on the keypad or not 01486 int e_state=(e->state() & ~Keypad); 01487 01488 int oldSelectionDirection(d->selectionDirection); 01489 01490 if ((e->key()!=Key_Shift) && (e->key()!=Key_Control) 01491 && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)) 01492 { 01493 if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove)) 01494 selectAll(false); 01495 d->selectionDirection=0; 01496 d->wasShiftEvent = (e_state == ShiftButton); 01497 }; 01498 01499 //d->wasShiftEvent = (e_state == ShiftButton); 01500 01501 01502 QListViewItem* item = currentItem(); 01503 if (!item) return; 01504 01505 QListViewItem* repaintItem1 = item; 01506 QListViewItem* repaintItem2 = 0L; 01507 QListViewItem* visItem = 0L; 01508 01509 QListViewItem* nextItem = 0L; 01510 int items = 0; 01511 01512 bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton)); 01513 int selectedItems(0); 01514 for (QListViewItem *tmpItem=firstChild(); tmpItem; tmpItem=tmpItem->nextSibling()) 01515 if (tmpItem->isSelected()) selectedItems++; 01516 01517 if (((!selectedItems) || ((selectedItems==1) && (d->selectedUsingMouse))) 01518 && (e_state==NoButton) 01519 && ((e->key()==Key_Down) 01520 || (e->key()==Key_Up) 01521 || (e->key()==Key_Next) 01522 || (e->key()==Key_Prior) 01523 || (e->key()==Key_Home) 01524 || (e->key()==Key_End))) 01525 { 01526 d->selectedBySimpleMove=true; 01527 d->selectedUsingMouse=false; 01528 } 01529 else if (selectedItems>1) 01530 d->selectedBySimpleMove=false; 01531 01532 bool emitSelectionChanged(false); 01533 01534 switch (e->key()) 01535 { 01536 case Key_Escape: 01537 selectAll(false); 01538 emitSelectionChanged=true; 01539 break; 01540 01541 case Key_Space: 01542 //toggle selection of current item 01543 if (d->selectedBySimpleMove) 01544 d->selectedBySimpleMove=false; 01545 item->setSelected(!item->isSelected()); 01546 emitSelectionChanged=true; 01547 break; 01548 01549 case Key_Insert: 01550 //toggle selection of current item and move to the next item 01551 if (d->selectedBySimpleMove) 01552 { 01553 d->selectedBySimpleMove=false; 01554 if (!item->isSelected()) item->setSelected(true); 01555 } 01556 else 01557 { 01558 item->setSelected(!item->isSelected()); 01559 }; 01560 01561 nextItem=item->itemBelow(); 01562 01563 if (nextItem) 01564 { 01565 repaintItem2=nextItem; 01566 visItem=nextItem; 01567 setCurrentItem(nextItem); 01568 }; 01569 d->selectionDirection=1; 01570 emitSelectionChanged=true; 01571 break; 01572 01573 case Key_Down: 01574 nextItem=item->itemBelow(); 01575 //toggle selection of current item and move to the next item 01576 if (shiftOrCtrl) 01577 { 01578 d->selectionDirection=1; 01579 if (d->selectedBySimpleMove) 01580 d->selectedBySimpleMove=false; 01581 else 01582 { 01583 if (oldSelectionDirection!=-1) 01584 { 01585 item->setSelected(!item->isSelected()); 01586 emitSelectionChanged=true; 01587 }; 01588 }; 01589 } 01590 else if ((d->selectedBySimpleMove) && (nextItem)) 01591 { 01592 item->setSelected(false); 01593 emitSelectionChanged=true; 01594 }; 01595 01596 if (nextItem) 01597 { 01598 if (d->selectedBySimpleMove) 01599 nextItem->setSelected(true); 01600 repaintItem2=nextItem; 01601 visItem=nextItem; 01602 setCurrentItem(nextItem); 01603 }; 01604 break; 01605 01606 case Key_Up: 01607 nextItem=item->itemAbove(); 01608 d->selectionDirection=-1; 01609 //move to the prev. item and toggle selection of this one 01610 // => No, can't select the last item, with this. For symmetry, let's 01611 // toggle selection and THEN move up, just like we do in down (David) 01612 if (shiftOrCtrl) 01613 { 01614 if (d->selectedBySimpleMove) 01615 d->selectedBySimpleMove=false; 01616 else 01617 { 01618 if (oldSelectionDirection!=1) 01619 { 01620 item->setSelected(!item->isSelected()); 01621 emitSelectionChanged=true; 01622 }; 01623 } 01624 } 01625 else if ((d->selectedBySimpleMove) && (nextItem)) 01626 { 01627 item->setSelected(false); 01628 emitSelectionChanged=true; 01629 }; 01630 01631 if (nextItem) 01632 { 01633 if (d->selectedBySimpleMove) 01634 nextItem->setSelected(true); 01635 repaintItem2=nextItem; 01636 visItem=nextItem; 01637 setCurrentItem(nextItem); 01638 }; 01639 break; 01640 01641 case Key_End: 01642 //move to the last item and toggle selection of all items inbetween 01643 nextItem=item; 01644 if (d->selectedBySimpleMove) 01645 item->setSelected(false); 01646 if (shiftOrCtrl) 01647 d->selectedBySimpleMove=false; 01648 01649 while(nextItem) 01650 { 01651 if (shiftOrCtrl) 01652 nextItem->setSelected(!nextItem->isSelected()); 01653 if (!nextItem->itemBelow()) 01654 { 01655 if (d->selectedBySimpleMove) 01656 nextItem->setSelected(true); 01657 repaintItem2=nextItem; 01658 visItem=nextItem; 01659 setCurrentItem(nextItem); 01660 } 01661 nextItem=nextItem->itemBelow(); 01662 } 01663 emitSelectionChanged=true; 01664 break; 01665 01666 case Key_Home: 01667 // move to the first item and toggle selection of all items inbetween 01668 nextItem = firstChild(); 01669 visItem = nextItem; 01670 repaintItem2 = visItem; 01671 if (d->selectedBySimpleMove) 01672 item->setSelected(false); 01673 if (shiftOrCtrl) 01674 { 01675 d->selectedBySimpleMove=false; 01676 01677 while ( nextItem != item ) 01678 { 01679 nextItem->setSelected( !nextItem->isSelected() ); 01680 nextItem = nextItem->itemBelow(); 01681 } 01682 item->setSelected( !item->isSelected() ); 01683 } 01684 setCurrentItem( firstChild() ); 01685 emitSelectionChanged=true; 01686 break; 01687 01688 case Key_Next: 01689 items=visibleHeight()/item->height(); 01690 nextItem=item; 01691 if (d->selectedBySimpleMove) 01692 item->setSelected(false); 01693 if (shiftOrCtrl) 01694 { 01695 d->selectedBySimpleMove=false; 01696 d->selectionDirection=1; 01697 }; 01698 01699 for (int i=0; i<items; i++) 01700 { 01701 if (shiftOrCtrl) 01702 nextItem->setSelected(!nextItem->isSelected()); 01703 //the end 01704 if ((i==items-1) || (!nextItem->itemBelow())) 01705 01706 { 01707 if (shiftOrCtrl) 01708 nextItem->setSelected(!nextItem->isSelected()); 01709 if (d->selectedBySimpleMove) 01710 nextItem->setSelected(true); 01711 ensureItemVisible(nextItem); 01712 setCurrentItem(nextItem); 01713 update(); 01714 if ((shiftOrCtrl) || (d->selectedBySimpleMove)) 01715 { 01716 emit selectionChanged(); 01717 } 01718 return; 01719 } 01720 nextItem=nextItem->itemBelow(); 01721 } 01722 break; 01723 01724 case Key_Prior: 01725 items=visibleHeight()/item->height(); 01726 nextItem=item; 01727 if (d->selectedBySimpleMove) 01728 item->setSelected(false); 01729 if (shiftOrCtrl) 01730 { 01731 d->selectionDirection=-1; 01732 d->selectedBySimpleMove=false; 01733 }; 01734 01735 for (int i=0; i<items; i++) 01736 { 01737 if ((nextItem!=item) &&(shiftOrCtrl)) 01738 nextItem->setSelected(!nextItem->isSelected()); 01739 //the end 01740 if ((i==items-1) || (!nextItem->itemAbove())) 01741 01742 { 01743 if (d->selectedBySimpleMove) 01744 nextItem->setSelected(true); 01745 ensureItemVisible(nextItem); 01746 setCurrentItem(nextItem); 01747 update(); 01748 if ((shiftOrCtrl) || (d->selectedBySimpleMove)) 01749 { 01750 emit selectionChanged(); 01751 } 01752 return; 01753 } 01754 nextItem=nextItem->itemAbove(); 01755 } 01756 break; 01757 01758 case Key_Minus: 01759 if ( item->isOpen() ) 01760 setOpen( item, false ); 01761 break; 01762 case Key_Plus: 01763 if ( !item->isOpen() && (item->isExpandable() || item->childCount()) ) 01764 setOpen( item, true ); 01765 break; 01766 default: 01767 bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control) 01768 && (e->key()!=Key_Meta) && (e->key()!=Key_Alt)); 01769 01770 bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected()); 01771 if (realKey && selectCurrentItem) 01772 item->setSelected(false); 01773 //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX) 01774 QListView::SelectionMode oldSelectionMode = selectionMode(); 01775 setSelectionMode (QListView::Multi); 01776 QListView::keyPressEvent (e); 01777 setSelectionMode (oldSelectionMode); 01778 if (realKey && selectCurrentItem) 01779 { 01780 currentItem()->setSelected(true); 01781 emitSelectionChanged=true; 01782 } 01783 repaintItem2=currentItem(); 01784 if (realKey) 01785 visItem=currentItem(); 01786 break; 01787 } 01788 01789 if (visItem) 01790 ensureItemVisible(visItem); 01791 01792 QRect ir; 01793 if (repaintItem1) 01794 ir = ir.unite( itemRect(repaintItem1) ); 01795 if (repaintItem2) 01796 ir = ir.unite( itemRect(repaintItem2) ); 01797 01798 if ( !ir.isEmpty() ) 01799 { // rectangle to be repainted 01800 if ( ir.x() < 0 ) 01801 ir.moveBy( -ir.x(), 0 ); 01802 viewport()->repaint( ir, false ); 01803 } 01804 /*if (repaintItem1) 01805 repaintItem1->repaint(); 01806 if (repaintItem2) 01807 repaintItem2->repaint();*/ 01808 update(); 01809 if (emitSelectionChanged) 01810 emit selectionChanged(); 01811 } 01812 01813 void KListView::setSelectionModeExt (SelectionModeExt mode) 01814 { 01815 d->selectionMode = mode; 01816 01817 switch (mode) 01818 { 01819 case Single: 01820 case Multi: 01821 case Extended: 01822 case NoSelection: 01823 setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode))); 01824 break; 01825 01826 case FileManager: 01827 setSelectionMode (QListView::Extended); 01828 break; 01829 01830 default: 01831 kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl; 01832 break; 01833 } 01834 } 01835 01836 KListView::SelectionModeExt KListView::selectionModeExt () const 01837 { 01838 return d->selectionMode; 01839 } 01840 01841 int KListView::itemIndex( const QListViewItem *item ) const 01842 { 01843 if ( !item ) 01844 return -1; 01845 01846 if ( item == firstChild() ) 01847 return 0; 01848 else { 01849 QListViewItemIterator it(firstChild()); 01850 uint j = 0; 01851 for (; it.current() && it.current() != item; ++it, ++j ); 01852 01853 if( !it.current() ) 01854 return -1; 01855 01856 return j; 01857 } 01858 } 01859 01860 QListViewItem* KListView::itemAtIndex(int index) 01861 { 01862 if (index<0) 01863 return 0; 01864 01865 int j(0); 01866 for (QListViewItemIterator it=firstChild(); it.current(); ++it) 01867 { 01868 if (j==index) 01869 return it.current(); 01870 ++j; 01871 }; 01872 return 0; 01873 } 01874 01875 01876 void KListView::emitContextMenu (KListView*, QListViewItem* i) 01877 { 01878 QPoint p; 01879 01880 if (i) 01881 p = viewport()->mapToGlobal(itemRect(i).center()); 01882 else 01883 p = mapToGlobal(rect().center()); 01884 01885 emit contextMenu (this, i, p); 01886 } 01887 01888 void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int) 01889 { 01890 emit contextMenu (this, i, p); 01891 } 01892 01893 void KListView::setAcceptDrops (bool val) 01894 { 01895 QListView::setAcceptDrops (val); 01896 viewport()->setAcceptDrops (val); 01897 } 01898 01899 int KListView::dropVisualizerWidth () const 01900 { 01901 return d->mDropVisualizerWidth; 01902 } 01903 01904 01905 void KListView::viewportPaintEvent(QPaintEvent *e) 01906 { 01907 d->paintAbove = 0; 01908 d->paintCurrent = 0; 01909 d->paintBelow = 0; 01910 d->painting = true; 01911 01912 QListView::viewportPaintEvent(e); 01913 01914 if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer)) 01915 { 01916 QPainter painter(viewport()); 01917 01918 // This is where we actually draw the drop-visualizer 01919 painter.fillRect(d->mOldDropVisualizer, Dense4Pattern); 01920 } 01921 if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter)) 01922 { 01923 QPainter painter(viewport()); 01924 01925 // This is where we actually draw the drop-highlighter 01926 style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(), 01927 QStyle::Style_FocusAtBorder); 01928 } 01929 d->painting = false; 01930 } 01931 01932 void KListView::setFullWidth() 01933 { 01934 setFullWidth(true); 01935 } 01936 01937 void KListView::setFullWidth(bool fullWidth) 01938 { 01939 d->fullWidth = fullWidth; 01940 header()->setStretchEnabled(fullWidth, columns()-1); 01941 } 01942 01943 bool KListView::fullWidth() const 01944 { 01945 return d->fullWidth; 01946 } 01947 01948 int KListView::addColumn(const QString& label, int width) 01949 { 01950 int result = QListView::addColumn(label, width); 01951 if (d->fullWidth) { 01952 header()->setStretchEnabled(false, columns()-2); 01953 header()->setStretchEnabled(true, columns()-1); 01954 } 01955 return result; 01956 } 01957 01958 int KListView::addColumn(const QIconSet& iconset, const QString& label, int width) 01959 { 01960 int result = QListView::addColumn(iconset, label, width); 01961 if (d->fullWidth) { 01962 header()->setStretchEnabled(false, columns()-2); 01963 header()->setStretchEnabled(true, columns()-1); 01964 } 01965 return result; 01966 } 01967 01968 void KListView::removeColumn(int index) 01969 { 01970 QListView::removeColumn(index); 01971 if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1); 01972 } 01973 01974 void KListView::viewportResizeEvent(QResizeEvent* e) 01975 { 01976 QListView::viewportResizeEvent(e); 01977 } 01978 01979 const QColor &KListView::alternateBackground() const 01980 { 01981 return d->alternateBackground; 01982 } 01983 01984 void KListView::setAlternateBackground(const QColor &c) 01985 { 01986 d->alternateBackground = c; 01987 repaint(); 01988 } 01989 01990 void KListView::setShadeSortColumn(bool shadeSortColumn) 01991 { 01992 d->shadeSortColumn = shadeSortColumn; 01993 repaint(); 01994 } 01995 01996 bool KListView::shadeSortColumn() const 01997 { 01998 return d->shadeSortColumn; 01999 } 02000 02001 void KListView::saveLayout(KConfig *config, const QString &group) const 02002 { 02003 KConfigGroupSaver saver(config, group); 02004 QStringList widths, order; 02005 02006 const int colCount = columns(); 02007 QHeader* const thisHeader = header(); 02008 for (int i = 0; i < colCount; ++i) 02009 { 02010 widths << QString::number(columnWidth(i)); 02011 order << QString::number(thisHeader->mapToIndex(i)); 02012 } 02013 config->writeEntry("ColumnWidths", widths); 02014 config->writeEntry("ColumnOrder", order); 02015 config->writeEntry("SortColumn", d->sortColumn); 02016 config->writeEntry("SortAscending", d->sortAscending); 02017 } 02018 02019 void KListView::restoreLayout(KConfig *config, const QString &group) 02020 { 02021 KConfigGroupSaver saver(config, group); 02022 QStringList cols = config->readListEntry("ColumnWidths"); 02023 int i = 0; 02024 { // scope the iterators 02025 QStringList::ConstIterator it = cols.constBegin(); 02026 const QStringList::ConstIterator itEnd = cols.constEnd(); 02027 for (; it != itEnd; ++it) 02028 setColumnWidth(i++, (*it).toInt()); 02029 } 02030 02031 // move sections in the correct sequence: from lowest to highest index position 02032 // otherwise we move a section from an index, which modifies 02033 // all index numbers to the right of the moved one 02034 cols = config->readListEntry("ColumnOrder"); 02035 const int colCount = columns(); 02036 for (i = 0; i < colCount; ++i) // final index positions from lowest to highest 02037 { 02038 QStringList::ConstIterator it = cols.constBegin(); 02039 const QStringList::ConstIterator itEnd = cols.constEnd(); 02040 02041 int section = 0; 02042 for (; (it != itEnd) && ((*it).toInt() != i); ++it, ++section) ; 02043 02044 if ( it != itEnd ) { 02045 // found the section to move to position i 02046 header()->moveSection(section, i); 02047 } 02048 } 02049 02050 if (config->hasKey("SortColumn")) 02051 setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); 02052 } 02053 02054 void KListView::setSorting(int column, bool ascending) 02055 { 02056 QListViewItem *selected = 0; 02057 02058 if (selectionMode() == QListView::Single) { 02059 selected = selectedItem(); 02060 if (selected && !selected->isVisible()) 02061 selected = 0; 02062 } 02063 else if (selectionMode() != QListView::NoSelection) { 02064 QListViewItem *item = firstChild(); 02065 while (item && !selected) { 02066 if (item->isSelected() && item->isVisible()) 02067 selected = item; 02068 item = item->itemBelow(); 02069 } 02070 } 02071 02072 d->sortColumn = column; 02073 d->sortAscending = ascending; 02074 QListView::setSorting(column, ascending); 02075 02076 if (selected) 02077 ensureItemVisible(selected); 02078 02079 QListViewItem* item = firstChild(); 02080 while ( item ) { 02081 KListViewItem *kItem = dynamic_cast<KListViewItem*>(item); 02082 if (kItem) kItem->m_known = false; 02083 item = item->itemBelow(); 02084 } 02085 } 02086 02087 int KListView::columnSorted(void) const 02088 { 02089 return d->sortColumn; 02090 } 02091 02092 bool KListView::ascendingSort(void) const 02093 { 02094 return d->sortAscending; 02095 } 02096 02097 void KListView::takeItem(QListViewItem *item) 02098 { 02099 if(item && item == d->editor->currentItem()) 02100 d->editor->terminate(); 02101 02102 QListView::takeItem(item); 02103 } 02104 02105 void KListView::disableAutoSelection() 02106 { 02107 if ( d->disableAutoSelection ) 02108 return; 02109 02110 d->disableAutoSelection = true; 02111 d->autoSelect.stop(); 02112 d->autoSelectDelay = -1; 02113 } 02114 02115 void KListView::resetAutoSelection() 02116 { 02117 if ( !d->disableAutoSelection ) 02118 return; 02119 02120 d->disableAutoSelection = false; 02121 d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); 02122 } 02123 02124 void KListView::doubleClicked( QListViewItem *item, const QPoint &pos, int c ) 02125 { 02126 emit QListView::doubleClicked( item, pos, c ); 02127 } 02128 02129 KListViewItem::KListViewItem(QListView *parent) 02130 : QListViewItem(parent) 02131 { 02132 init(); 02133 } 02134 02135 KListViewItem::KListViewItem(QListViewItem *parent) 02136 : QListViewItem(parent) 02137 { 02138 init(); 02139 } 02140 02141 KListViewItem::KListViewItem(QListView *parent, QListViewItem *after) 02142 : QListViewItem(parent, after) 02143 { 02144 init(); 02145 } 02146 02147 KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after) 02148 : QListViewItem(parent, after) 02149 { 02150 init(); 02151 } 02152 02153 KListViewItem::KListViewItem(QListView *parent, 02154 QString label1, QString label2, QString label3, QString label4, 02155 QString label5, QString label6, QString label7, QString label8) 02156 : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) 02157 { 02158 init(); 02159 } 02160 02161 KListViewItem::KListViewItem(QListViewItem *parent, 02162 QString label1, QString label2, QString label3, QString label4, 02163 QString label5, QString label6, QString label7, QString label8) 02164 : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8) 02165 { 02166 init(); 02167 } 02168 02169 KListViewItem::KListViewItem(QListView *parent, QListViewItem *after, 02170 QString label1, QString label2, QString label3, QString label4, 02171 QString label5, QString label6, QString label7, QString label8) 02172 : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) 02173 { 02174 init(); 02175 } 02176 02177 KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after, 02178 QString label1, QString label2, QString label3, QString label4, 02179 QString label5, QString label6, QString label7, QString label8) 02180 : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8) 02181 { 02182 init(); 02183 } 02184 02185 KListViewItem::~KListViewItem() 02186 { 02187 if(listView()) 02188 emit static_cast<KListView *>(listView())->itemRemoved(this); 02189 } 02190 02191 void KListViewItem::init() 02192 { 02193 m_odd = m_known = false; 02194 KListView *lv = static_cast<KListView *>(listView()); 02195 setDragEnabled( dragEnabled() || lv->dragEnabled() ); 02196 emit lv->itemAdded(this); 02197 } 02198 02199 void KListViewItem::insertItem(QListViewItem *item) 02200 { 02201 QListViewItem::insertItem(item); 02202 if(listView()) 02203 emit static_cast<KListView *>(listView())->itemAdded(item); 02204 } 02205 02206 void KListViewItem::takeItem(QListViewItem *item) 02207 { 02208 QListViewItem::takeItem(item); 02209 if(listView()) 02210 emit static_cast<KListView *>(listView())->itemRemoved(item); 02211 } 02212 02213 const QColor &KListViewItem::backgroundColor() 02214 { 02215 if (isAlternate()) 02216 return static_cast< KListView* >(listView())->alternateBackground(); 02217 return listView()->viewport()->colorGroup().base(); 02218 } 02219 02220 QColor KListViewItem::backgroundColor(int column) 02221 { 02222 KListView* view = static_cast< KListView* >(listView()); 02223 QColor color = isAlternate() ? 02224 view->alternateBackground() : 02225 view->viewport()->colorGroup().base(); 02226 02227 // calculate a different color if the current column is sorted (only if more than 1 column) 02228 if ( (view->columns() > 1) && view->shadeSortColumn() && (column == view->columnSorted()) ) 02229 { 02230 if ( color == Qt::black ) 02231 color = QColor(55, 55, 55); // dark gray 02232 else 02233 { 02234 int h,s,v; 02235 color.hsv(&h, &s, &v); 02236 if ( v > 175 ) 02237 color = color.dark(104); 02238 else 02239 color = color.light(120); 02240 } 02241 } 02242 02243 return color; 02244 } 02245 02246 bool KListViewItem::isAlternate() 02247 { 02248 KListView* const lv = static_cast<KListView *>(listView()); 02249 if (lv && lv->alternateBackground().isValid()) 02250 { 02251 KListViewItem *above; 02252 02253 KListView::KListViewPrivate* const lvD = lv->d; 02254 02255 // Ok, there's some weirdness here that requires explanation as this is a 02256 // speed hack. itemAbove() is a O(n) operation (though this isn't 02257 // immediately clear) so we want to call it as infrequently as possible -- 02258 // especially in the case of painting a cell. 02259 // 02260 // So, in the case that we *are* painting a cell: (1) we're assuming that 02261 // said painting is happening top to bottem -- this assumption is present 02262 // elsewhere in the implementation of this class, (2) itemBelow() is fast -- 02263 // roughly constant time. 02264 // 02265 // Given these assumptions we can do a mixture of caching and telling the 02266 // next item that the when that item is the current item that the now 02267 // current item will be the item above it. 02268 // 02269 // Ideally this will make checking to see if the item above the current item 02270 // is the alternate color a constant time operation rather than 0(n). 02271 02272 if (lvD->painting) { 02273 if (lvD->paintCurrent != this) 02274 { 02275 lvD->paintAbove = lvD->paintBelow == this ? lvD->paintCurrent : itemAbove(); 02276 lvD->paintCurrent = this; 02277 lvD->paintBelow = itemBelow(); 02278 } 02279 02280 above = dynamic_cast<KListViewItem *>(lvD->paintAbove); 02281 } 02282 else 02283 { 02284 above = dynamic_cast<KListViewItem *>(itemAbove()); 02285 } 02286 02287 m_known = above ? above->m_known : true; 02288 if (m_known) 02289 { 02290 m_odd = above ? !above->m_odd : false; 02291 } 02292 else 02293 { 02294 KListViewItem *item; 02295 bool previous = true; 02296 if (parent()) 02297 { 02298 item = dynamic_cast<KListViewItem *>(parent()); 02299 if (item) 02300 previous = item->m_odd; 02301 item = dynamic_cast<KListViewItem *>(parent()->firstChild()); 02302 } 02303 else 02304 { 02305 item = dynamic_cast<KListViewItem *>(lv->firstChild()); 02306 } 02307 02308 while(item) 02309 { 02310 item->m_odd = previous = !previous; 02311 item->m_known = true; 02312 item = dynamic_cast<KListViewItem *>(item->nextSibling()); 02313 } 02314 } 02315 return m_odd; 02316 } 02317 return false; 02318 } 02319 02320 void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) 02321 { 02322 QColorGroup _cg = cg; 02323 const QPixmap *pm = listView()->viewport()->backgroundPixmap(); 02324 02325 if (pm && !pm->isNull()) 02326 { 02327 _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(column), *pm)); 02328 QPoint o = p->brushOrigin(); 02329 p->setBrushOrigin( o.x()-listView()->contentsX(), o.y()-listView()->contentsY() ); 02330 } 02331 else 02332 { 02333 _cg.setColor((listView()->viewport()->backgroundMode() == Qt::FixedColor) ? 02334 QColorGroup::Background : QColorGroup::Base, 02335 backgroundColor(column)); 02336 } 02337 QListViewItem::paintCell(p, _cg, column, width, alignment); 02338 } 02339 02340 void KListView::virtual_hook( int, void* ) 02341 { /*BASE::virtual_hook( id, data );*/ } 02342 02343 #include "klistview.moc" 02344 #include "klistviewlineedit.moc" 02345 02346 // vim: noet
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:10:13 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003