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

KDE3Support

k3listview.cpp

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

KDE3Support

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal