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