• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

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

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal