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