kdeui Library API Documentation

klistview.cpp

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