# kdeui Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:18 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003