kdeui Library API Documentation

klistview.cpp

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