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