summaryrefslogtreecommitdiffstats
path: root/kdeui/klistview.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kdeui/klistview.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdeui/klistview.cpp')
-rw-r--r--kdeui/klistview.cpp2365
1 files changed, 2365 insertions, 0 deletions
diff --git a/kdeui/klistview.cpp b/kdeui/klistview.cpp
new file mode 100644
index 000000000..9aeedfb2c
--- /dev/null
+++ b/kdeui/klistview.cpp
@@ -0,0 +1,2365 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2000,2003 Charles Samuels <charles@kde.org>
+ Copyright (C) 2000 Peter Putzer
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "config.h"
+
+#include <qdragobject.h>
+#include <qtimer.h>
+#include <qheader.h>
+#include <qcursor.h>
+#include <qtooltip.h>
+#include <qstyle.h>
+#include <qpainter.h>
+
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kapplication.h>
+#include <kipc.h>
+#include <kdebug.h>
+
+#include "klistview.h"
+#include "klistviewlineedit.h"
+
+class KListView::Tooltip : public QToolTip
+{
+public:
+ Tooltip (KListView* parent, QToolTipGroup* group = 0L);
+ virtual ~Tooltip () {}
+
+protected:
+ /**
+ * Reimplemented from QToolTip for internal reasons.
+ */
+ virtual void maybeTip (const QPoint&);
+
+private:
+ KListView* mParent;
+};
+
+KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group)
+ : QToolTip (parent, group),
+ mParent (parent)
+{
+}
+
+void KListView::Tooltip::maybeTip (const QPoint&)
+{
+ // FIXME
+}
+
+class KListView::KListViewPrivate
+{
+public:
+ KListViewPrivate (KListView* listview)
+ : pCurrentItem (0),
+ autoSelectDelay(0),
+ dragOverItem(0),
+ dragDelay (KGlobalSettings::dndEventDelay()),
+ editor (new KListViewLineEdit (listview)),
+ cursorInExecuteArea(false),
+ itemsMovable (true),
+ selectedBySimpleMove(false),
+ selectedUsingMouse(false),
+ itemsRenameable (false),
+ validDrag (false),
+ dragEnabled (false),
+ autoOpen (true),
+ disableAutoSelection (false),
+ dropVisualizer (true),
+ dropHighlighter (false),
+ createChildren (true),
+ pressedOnSelected (false),
+ wasShiftEvent (false),
+ fullWidth (false),
+ sortAscending(true),
+ tabRename(true),
+ sortColumn(0),
+ selectionDirection(0),
+ tooltipColumn (0),
+ selectionMode (Single),
+ contextMenuKey (KGlobalSettings::contextMenuKey()),
+ showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()),
+ mDropVisualizerWidth (4),
+ paintAbove (0),
+ paintCurrent (0),
+ paintBelow (0),
+ painting (false),
+ shadeSortColumn(KGlobalSettings::shadeSortColumn())
+ {
+ renameable.append(0);
+ connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int)));
+ }
+
+ ~KListViewPrivate ()
+ {
+ delete editor;
+ }
+
+ QListViewItem* pCurrentItem;
+
+ QTimer autoSelect;
+ int autoSelectDelay;
+
+ QTimer dragExpand;
+ QListViewItem* dragOverItem;
+ QPoint dragOverPoint;
+
+ QPoint startDragPos;
+ int dragDelay;
+
+ KListViewLineEdit *editor;
+ QValueList<int> renameable;
+
+ bool cursorInExecuteArea:1;
+ bool bUseSingle:1;
+ bool bChangeCursorOverItem:1;
+ bool itemsMovable:1;
+ bool selectedBySimpleMove : 1;
+ bool selectedUsingMouse:1;
+ bool itemsRenameable:1;
+ bool validDrag:1;
+ bool dragEnabled:1;
+ bool autoOpen:1;
+ bool disableAutoSelection:1;
+ bool dropVisualizer:1;
+ bool dropHighlighter:1;
+ bool createChildren:1;
+ bool pressedOnSelected:1;
+ bool wasShiftEvent:1;
+ bool fullWidth:1;
+ bool sortAscending:1;
+ bool tabRename:1;
+
+ int sortColumn;
+
+ //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX
+ int selectionDirection;
+ int tooltipColumn;
+
+ SelectionModeExt selectionMode;
+ int contextMenuKey;
+ bool showContextMenusOnPress;
+
+ QRect mOldDropVisualizer;
+ int mDropVisualizerWidth;
+ QRect mOldDropHighlighter;
+ QListViewItem *afterItemDrop;
+ QListViewItem *parentItemDrop;
+
+ QListViewItem *paintAbove;
+ QListViewItem *paintCurrent;
+ QListViewItem *paintBelow;
+ bool painting:1;
+ bool shadeSortColumn:1;
+
+ QColor alternateBackground;
+};
+
+
+KListViewLineEdit::KListViewLineEdit(KListView *parent)
+ : KLineEdit(parent->viewport()), item(0), col(0), p(parent)
+{
+ setFrame( false );
+ hide();
+ connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() ));
+ connect( parent, SIGNAL( itemRemoved( QListViewItem * ) ),
+ SLOT( slotItemRemoved( QListViewItem * ) ));
+}
+
+KListViewLineEdit::~KListViewLineEdit()
+{
+}
+
+QListViewItem *KListViewLineEdit::currentItem() const
+{
+ return item;
+}
+
+void KListViewLineEdit::load(QListViewItem *i, int c)
+{
+ item=i;
+ col=c;
+
+ QRect rect(p->itemRect(i));
+ setText(item->text(c));
+ home( true );
+
+ int fieldX = rect.x() - 1;
+ int fieldW = p->columnWidth(col) + 2;
+
+ QHeader* const pHeader = p->header();
+
+ const int pos = pHeader->mapToIndex(col);
+ for ( int index = 0; index < pos; ++index )
+ fieldX += p->columnWidth( pHeader->mapToSection( index ));
+
+ if ( col == 0 ) {
+ int d = i->depth() + (p->rootIsDecorated() ? 1 : 0);
+ d *= p->treeStepSize();
+ fieldX += d;
+ fieldW -= d;
+ }
+
+ if ( i->pixmap( col ) ) {// add width of pixmap
+ int d = i->pixmap( col )->width();
+ fieldX += d;
+ fieldW -= d;
+ }
+
+ setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2);
+ show();
+ setFocus();
+}
+
+/* Helper functions to for
+ * tabOrderedRename functionality.
+ */
+
+static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir)
+{
+ if (pi)
+ {
+ // Find the next renameable column in the current row
+ for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir)
+ if (pl->isRenameable(start))
+ return start;
+ }
+
+ return -1;
+}
+
+static QListViewItem *prevItem (QListViewItem *pi)
+{
+ QListViewItem *pa = pi->itemAbove();
+
+ /* Does what the QListViewItem::previousSibling()
+ * of my dreams would do.
+ */
+ if (pa && pa->parent() == pi->parent())
+ return pa;
+
+ return 0;
+}
+
+static QListViewItem *lastQChild (QListViewItem *pi)
+{
+ if (pi)
+ {
+ /* Since there's no QListViewItem::lastChild().
+ * This finds the last sibling for the given
+ * item.
+ */
+ for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling())
+ pi = pt;
+ }
+
+ return pi;
+}
+
+void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward)
+{
+ const int ncols = p->columns();
+ const int dir = forward ? +1 : -1;
+ const int restart = forward ? 0 : (ncols - 1);
+ QListViewItem *top = (pitem && pitem->parent())
+ ? pitem->parent()->firstChild()
+ : p->firstChild();
+ QListViewItem *pi = pitem;
+
+ terminate(); // Save current changes
+
+ do
+ {
+ /* Check the rest of the current row for an editable column,
+ * if that fails, check the entire next/previous row. The
+ * last case goes back to the first item in the current branch
+ * or the last item in the current branch depending on the
+ * direction.
+ */
+ if ((column = nextCol(p, pi, column + dir, dir)) != -1 ||
+ (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 ||
+ (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1)
+ {
+ if (pi)
+ {
+ p->setCurrentItem(pi); // Calls terminate
+ p->rename(pi, column);
+
+ /* Some listviews may override rename() to
+ * prevent certain items from being renamed,
+ * if this is done, [m_]item will be NULL
+ * after the rename() call... try again.
+ */
+ if (!item)
+ continue;
+
+ break;
+ }
+ }
+ }
+ while (pi && !item);
+}
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+bool KListViewLineEdit::event (QEvent *pe)
+{
+ if (pe->type() == QEvent::KeyPress)
+ {
+ QKeyEvent *k = (QKeyEvent *) pe;
+
+ if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) &&
+ p->tabOrderedRenaming() && p->itemsRenameable() &&
+ !(k->state() & ControlButton || k->state() & AltButton))
+ {
+ selectNextCell(item, col,
+ (k->key() == Key_Tab && !(k->state() & ShiftButton)));
+ return true;
+ }
+ }
+
+ return KLineEdit::event(pe);
+}
+
+void KListViewLineEdit::keyPressEvent(QKeyEvent *e)
+{
+ if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
+ terminate(true);
+ else if(e->key() == Qt::Key_Escape)
+ terminate(false);
+ else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up)
+ {
+ terminate(true);
+ KLineEdit::keyPressEvent(e);
+ }
+ else
+ KLineEdit::keyPressEvent(e);
+}
+
+void KListViewLineEdit::terminate()
+{
+ terminate(true);
+}
+
+void KListViewLineEdit::terminate(bool commit)
+{
+ if ( item )
+ {
+ //kdDebug() << "KListViewLineEdit::terminate " << commit << endl;
+ if (commit)
+ item->setText(col, text());
+ int c=col;
+ QListViewItem *i=item;
+ col=0;
+ item=0;
+ p->setFocus();// will call focusOutEvent, that's why we set item=0 before
+ hide();
+ if (commit)
+ emit done(i,c);
+ }
+}
+
+void KListViewLineEdit::focusOutEvent(QFocusEvent *ev)
+{
+ QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev);
+ // Don't let a RMB close the editor
+ if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow)
+ terminate(true);
+ else
+ KLineEdit::focusOutEvent(ev);
+}
+
+void KListViewLineEdit::paintEvent( QPaintEvent *e )
+{
+ KLineEdit::paintEvent( e );
+
+ if ( !frame() ) {
+ QPainter p( this );
+ p.setClipRegion( e->region() );
+ p.drawRect( rect() );
+ }
+}
+
+// selection changed -> terminate. As our "item" can be already deleted,
+// we can't call terminate(false), because that would emit done() with
+// a dangling pointer to "item".
+void KListViewLineEdit::slotSelectionChanged()
+{
+ item = 0;
+ col = 0;
+ hide();
+}
+
+// if the current item was removed -> terminate. Can't call terminate(false)
+// due to same reason as slotSelectionChanged().
+void KListViewLineEdit::slotItemRemoved(QListViewItem *i)
+{
+ if (currentItem() != i)
+ return;
+
+ item = 0;
+ col = 0;
+ hide();
+}
+
+
+KListView::KListView( QWidget *parent, const char *name )
+ : QListView( parent, name ),
+ d (new KListViewPrivate (this))
+{
+ setDragAutoScroll(true);
+
+ connect( this, SIGNAL( onViewport() ),
+ this, SLOT( slotOnViewport() ) );
+ connect( this, SIGNAL( onItem( QListViewItem * ) ),
+ this, SLOT( slotOnItem( QListViewItem * ) ) );
+
+ connect (this, SIGNAL(contentsMoving(int,int)),
+ this, SLOT(cleanDropVisualizer()));
+ connect (this, SIGNAL(contentsMoving(int,int)),
+ this, SLOT(cleanItemHighlighter()));
+
+ slotSettingsChanged(KApplication::SETTINGS_MOUSE);
+ if (kapp)
+ {
+ connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) );
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ }
+
+ connect(&d->autoSelect, SIGNAL( timeout() ),
+ this, SLOT( slotAutoSelect() ) );
+ connect(&d->dragExpand, SIGNAL( timeout() ),
+ this, SLOT( slotDragExpand() ) );
+
+ // context menu handling
+ if (d->showContextMenusOnPress)
+ {
+ connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ else
+ {
+ connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+
+ connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)),
+ this, SLOT (emitContextMenu (KListView*, QListViewItem*)));
+ d->alternateBackground = KGlobalSettings::alternateBackgroundColor();
+}
+
+KListView::~KListView()
+{
+ delete d;
+}
+
+bool KListView::isExecuteArea( const QPoint& point )
+{
+ QListViewItem* item = itemAt( point );
+ if ( item ) {
+ return isExecuteArea( point.x(), item );
+ }
+
+ return false;
+}
+
+bool KListView::isExecuteArea( int x )
+{
+ return isExecuteArea( x, 0 );
+}
+
+bool KListView::isExecuteArea( int x, QListViewItem* item )
+{
+ if( allColumnsShowFocus() )
+ return true;
+ else {
+ int offset = 0;
+
+
+ int width = columnWidth( 0 );
+
+ QHeader* const thisHeader = header();
+ const int pos = thisHeader->mapToIndex( 0 );
+
+ for ( int index = 0; index < pos; ++index )
+ offset += columnWidth( thisHeader->mapToSection( index ) );
+
+ x += contentsX(); // in case of a horizontal scrollbar
+
+ if ( item )
+ {
+ width = treeStepSize()*( item->depth() + ( rootIsDecorated() ? 1 : 0 ) );
+ width += itemMargin();
+ int ca = AlignHorizontal_Mask & columnAlignment( 0 );
+ if ( ca == AlignLeft || ca == AlignAuto ) {
+ width += item->width( fontMetrics(), this, 0 );
+ if ( width > columnWidth( 0 ) )
+ width = columnWidth( 0 );
+ }
+ }
+
+ return ( x > offset && x < ( offset + width ) );
+ }
+}
+
+void KListView::slotOnItem( QListViewItem *item )
+{
+ QPoint vp = viewport()->mapFromGlobal( QCursor::pos() );
+ if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) {
+ d->autoSelect.start( d->autoSelectDelay, true );
+ d->pCurrentItem = item;
+ }
+}
+
+void KListView::slotOnViewport()
+{
+ if ( d->bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ d->autoSelect.stop();
+ d->pCurrentItem = 0L;
+}
+
+void KListView::slotSettingsChanged(int category)
+{
+ switch (category)
+ {
+ case KApplication::SETTINGS_MOUSE:
+ d->dragDelay = KGlobalSettings::dndEventDelay();
+ d->bUseSingle = KGlobalSettings::singleClick();
+
+ disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)),
+ this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int)));
+
+ if( d->bUseSingle )
+ connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)),
+ this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int)));
+
+ d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon();
+ if ( !d->disableAutoSelection )
+ d->autoSelectDelay = KGlobalSettings::autoSelectDelay();
+
+ if( !d->bUseSingle || !d->bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ break;
+
+ case KApplication::SETTINGS_POPUPMENU:
+ d->contextMenuKey = KGlobalSettings::contextMenuKey ();
+ d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress ();
+
+ if (d->showContextMenusOnPress)
+ {
+ disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+
+ connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ else
+ {
+ disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+
+ connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void KListView::slotAutoSelect()
+{
+ // check that the item still exists
+ if( itemIndex( d->pCurrentItem ) == -1 )
+ return;
+
+ if (!isActiveWindow())
+ {
+ d->autoSelect.stop();
+ return;
+ }
+
+ //Give this widget the keyboard focus.
+ if( !hasFocus() )
+ setFocus();
+
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ QListViewItem* previousItem = currentItem();
+ setCurrentItem( d->pCurrentItem );
+
+ if( d->pCurrentItem ) {
+ //Shift pressed?
+ if( (keybstate & Qt::ShiftButton) ) {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ //No Ctrl? Then clear before!
+ if( !(keybstate & Qt::ControlButton) )
+ clearSelection();
+
+ bool select = !d->pCurrentItem->isSelected();
+ bool update = viewport()->isUpdatesEnabled();
+ viewport()->setUpdatesEnabled( false );
+
+ bool down = previousItem->itemPos() < d->pCurrentItem->itemPos();
+ QListViewItemIterator lit( down ? previousItem : d->pCurrentItem );
+ for ( ; lit.current(); ++lit ) {
+ if ( down && lit.current() == d->pCurrentItem ) {
+ d->pCurrentItem->setSelected( select );
+ break;
+ }
+ if ( !down && lit.current() == previousItem ) {
+ previousItem->setSelected( select );
+ break;
+ }
+ lit.current()->setSelected( select );
+ }
+
+ blockSignals( block );
+ viewport()->setUpdatesEnabled( update );
+ triggerUpdate();
+
+ emit selectionChanged();
+
+ if( selectionMode() == QListView::Single )
+ emit selectionChanged( d->pCurrentItem );
+ }
+ else if( (keybstate & KApplication::ControlModifier) )
+ setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() );
+ else {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ if( !d->pCurrentItem->isSelected() )
+ clearSelection();
+
+ blockSignals( block );
+
+ setSelected( d->pCurrentItem, true );
+ }
+ }
+ else
+ kdDebug() << "KListView::slotAutoSelect: Thatīs not supposed to happen!!!!" << endl;
+}
+
+void KListView::slotHeaderChanged()
+{
+
+ const int colCount = columns();
+ if (d->fullWidth && colCount)
+ {
+ int w = 0;
+ const int lastColumn = colCount - 1;
+ for (int i = 0; i < lastColumn; ++i) w += columnWidth(i);
+ setColumnWidth( lastColumn, viewport()->width() - w - 1 );
+ }
+}
+
+void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c )
+{
+ if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) {
+ d->validDrag=false;
+
+ // Double click mode ?
+ if ( !d->bUseSingle )
+ {
+ viewport()->unsetCursor();
+ emit executed( item );
+ emit executed( item, pos, c );
+ }
+ else
+ {
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ d->autoSelect.stop();
+
+ //Donīt emit executed if in SC mode and Shift or Ctrl are pressed
+ if( !( ((keybstate & Qt::ShiftButton) || (keybstate & Qt::ControlButton)) ) ) {
+ viewport()->unsetCursor();
+ emit executed( item );
+ emit executed( item, pos, c );
+ }
+ }
+ }
+}
+
+void KListView::focusInEvent( QFocusEvent *fe )
+{
+ // kdDebug()<<"KListView::focusInEvent()"<<endl;
+ QListView::focusInEvent( fe );
+ if ((d->selectedBySimpleMove)
+ && (d->selectionMode == FileManager)
+ && (fe->reason()!=QFocusEvent::Popup)
+ && (fe->reason()!=QFocusEvent::ActiveWindow)
+ && (currentItem()))
+ {
+ currentItem()->setSelected(true);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+}
+
+void KListView::focusOutEvent( QFocusEvent *fe )
+{
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+
+ d->autoSelect.stop();
+
+ if ((d->selectedBySimpleMove)
+ && (d->selectionMode == FileManager)
+ && (fe->reason()!=QFocusEvent::Popup)
+ && (fe->reason()!=QFocusEvent::ActiveWindow)
+ && (currentItem())
+ && (!d->editor->isVisible()))
+ {
+ currentItem()->setSelected(false);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+
+ QListView::focusOutEvent( fe );
+}
+
+void KListView::leaveEvent( QEvent *e )
+{
+ d->autoSelect.stop();
+
+ QListView::leaveEvent( e );
+}
+
+bool KListView::event( QEvent *e )
+{
+ if (e->type() == QEvent::ApplicationPaletteChange)
+ d->alternateBackground=KGlobalSettings::alternateBackgroundColor();
+
+ return QListView::event(e);
+}
+
+void KListView::contentsMousePressEvent( QMouseEvent *e )
+{
+ if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) )
+ {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ clearSelection();
+
+ blockSignals( block );
+ }
+ else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove))
+ {
+ d->selectedBySimpleMove=false;
+ d->selectedUsingMouse=true;
+ if (currentItem())
+ {
+ currentItem()->setSelected(false);
+ currentItem()->repaint();
+// emit selectionChanged();
+ }
+ }
+
+ QPoint p( contentsToViewport( e->pos() ) );
+ QListViewItem *at = itemAt (p);
+
+ // true if the root decoration of the item "at" was clicked (i.e. the +/- sign)
+ bool rootDecoClicked = at
+ && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) +
+ treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() )
+ && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) );
+
+ if (e->button() == LeftButton && !rootDecoClicked)
+ {
+ //Start a drag
+ d->startDragPos = e->pos();
+
+ if (at)
+ {
+ d->validDrag = true;
+ d->pressedOnSelected = at->isSelected();
+ }
+ }
+
+ QListView::contentsMousePressEvent( e );
+}
+
+void KListView::contentsMouseMoveEvent( QMouseEvent *e )
+{
+ if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag)
+ QListView::contentsMouseMoveEvent (e);
+
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem *item = itemAt( vp );
+
+ //do we process cursor changes at all?
+ if ( item && d->bChangeCursorOverItem && d->bUseSingle )
+ {
+ //Cursor moved on a new item or in/out the execute area
+ if( (item != d->pCurrentItem) ||
+ (isExecuteArea(vp) != d->cursorInExecuteArea) )
+ {
+ d->cursorInExecuteArea = isExecuteArea(vp);
+
+ if( d->cursorInExecuteArea ) //cursor moved in execute area
+ viewport()->setCursor( KCursor::handCursor() );
+ else //cursor moved out of execute area
+ viewport()->unsetCursor();
+ }
+ }
+
+ bool dragOn = dragEnabled();
+ QPoint newPos = e->pos();
+ if (dragOn && d->validDrag &&
+ (newPos.x() > d->startDragPos.x()+d->dragDelay ||
+ newPos.x() < d->startDragPos.x()-d->dragDelay ||
+ newPos.y() > d->startDragPos.y()+d->dragDelay ||
+ newPos.y() < d->startDragPos.y()-d->dragDelay))
+ //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
+ {
+ QListView::contentsMouseReleaseEvent( 0 );
+ startDrag();
+ d->startDragPos = QPoint();
+ d->validDrag = false;
+ }
+}
+
+void KListView::contentsMouseReleaseEvent( QMouseEvent *e )
+{
+ if (e->button() == LeftButton)
+ {
+ // If the row was already selected, maybe we want to start an in-place editing
+ if ( d->pressedOnSelected && itemsRenameable() )
+ {
+ QPoint p( contentsToViewport( e->pos() ) );
+ QListViewItem *at = itemAt (p);
+ if ( at )
+ {
+ // true if the root decoration of the item "at" was clicked (i.e. the +/- sign)
+ bool rootDecoClicked =
+ ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) +
+ treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() )
+ && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) );
+
+ if (!rootDecoClicked)
+ {
+ int col = header()->mapToLogical( header()->cellAt( p.x() ) );
+ if ( d->renameable.contains(col) )
+ rename(at, col);
+ }
+ }
+ }
+
+ d->pressedOnSelected = false;
+ d->validDrag = false;
+ d->startDragPos = QPoint();
+ }
+ QListView::contentsMouseReleaseEvent( e );
+}
+
+void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e )
+{
+ // We don't want to call the parent method because it does setOpen,
+ // whereas we don't do it in single click mode... (David)
+ //QListView::contentsMouseDoubleClickEvent( e );
+ if ( !e || e->button() != LeftButton )
+ return;
+
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem *item = itemAt( vp );
+ emit QListView::doubleClicked( item ); // we do it now
+
+ int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1;
+
+ if( item ) {
+ emit doubleClicked( item, e->globalPos(), col );
+
+ if( (e->button() == LeftButton) && !d->bUseSingle )
+ emitExecute( item, e->globalPos(), col );
+ }
+}
+
+void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c )
+{
+ if( (btn == LeftButton) && item )
+ emitExecute(item, pos, c);
+}
+
+void KListView::contentsDropEvent(QDropEvent* e)
+{
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+ d->dragExpand.stop();
+
+ if (acceptDrag (e))
+ {
+ e->acceptAction();
+ QListViewItem *afterme;
+ QListViewItem *parent;
+
+ findDrop(e->pos(), parent, afterme);
+
+ if (e->source() == viewport() && itemsMovable())
+ movableDropEvent(parent, afterme);
+ else
+ {
+ emit dropped(e, afterme);
+ emit dropped(this, e, afterme);
+ emit dropped(e, parent, afterme);
+ emit dropped(this, e, parent, afterme);
+ }
+ }
+}
+
+void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme)
+{
+ QPtrList<QListViewItem> items, afterFirsts, afterNows;
+ QListViewItem *current=currentItem();
+ bool hasMoved=false;
+ for (QListViewItem *i = firstChild(), *iNext=0; i; i = iNext)
+ {
+ iNext=i->itemBelow();
+ if (!i->isSelected())
+ continue;
+
+ // don't drop an item after itself, or else
+ // it moves to the top of the list
+ if (i==afterme)
+ continue;
+
+ i->setSelected(false);
+
+ QListViewItem *afterFirst = i->itemAbove();
+
+ if (!hasMoved)
+ {
+ emit aboutToMove();
+ hasMoved=true;
+ }
+
+ moveItem(i, parent, afterme);
+
+ // ###### This should include the new parent !!! -> KDE 3.0
+ // If you need this right now, have a look at keditbookmarks.
+ emit moved(i, afterFirst, afterme);
+
+ items.append (i);
+ afterFirsts.append (afterFirst);
+ afterNows.append (afterme);
+
+ afterme = i;
+ }
+ clearSelection();
+ for (QListViewItem *i=items.first(); i; i=items.next() )
+ i->setSelected(true);
+ if (current)
+ setCurrentItem(current);
+
+ emit moved(items,afterFirsts,afterNows);
+
+ if (firstChild())
+ emit moved();
+}
+
+void KListView::contentsDragMoveEvent(QDragMoveEvent *event)
+{
+ if (acceptDrag(event))
+ {
+ event->acceptAction();
+ //Clean up the view
+
+ findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop);
+ QPoint vp = contentsToViewport( event->pos() );
+ QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L;
+
+ if ( item != d->dragOverItem )
+ {
+ d->dragExpand.stop();
+ d->dragOverItem = item;
+ d->dragOverPoint = vp;
+ if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() )
+ d->dragExpand.start( QApplication::startDragTime(), true );
+ }
+ if (dropVisualizer())
+ {
+ QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop);
+ if (tmpRect != d->mOldDropVisualizer)
+ {
+ cleanDropVisualizer();
+ d->mOldDropVisualizer=tmpRect;
+ viewport()->repaint(tmpRect);
+ }
+ }
+ if (dropHighlighter())
+ {
+ QRect tmpRect = drawItemHighlighter(0, itemAt( vp ));
+ if (tmpRect != d->mOldDropHighlighter)
+ {
+ cleanItemHighlighter();
+ d->mOldDropHighlighter=tmpRect;
+ viewport()->repaint(tmpRect);
+ }
+ }
+ }
+ else
+ event->ignore();
+}
+
+void KListView::slotDragExpand()
+{
+ if ( itemAt( d->dragOverPoint ) == d->dragOverItem )
+ d->dragOverItem->setOpen( true );
+}
+
+void KListView::contentsDragLeaveEvent (QDragLeaveEvent*)
+{
+ d->dragExpand.stop();
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+}
+
+void KListView::cleanDropVisualizer()
+{
+ if (d->mOldDropVisualizer.isValid())
+ {
+ QRect rect=d->mOldDropVisualizer;
+ d->mOldDropVisualizer = QRect();
+ viewport()->repaint(rect, true);
+ }
+}
+
+int KListView::depthToPixels( int depth )
+{
+ return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin();
+}
+
+void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after)
+{
+ QPoint p (contentsToViewport(pos));
+
+ // Get the position to put it in
+ QListViewItem *atpos = itemAt(p);
+
+ QListViewItem *above;
+ if (!atpos) // put it at the end
+ above = lastItem();
+ else
+ {
+ // Get the closest item before us ('atpos' or the one above, if any)
+ if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2))
+ above = atpos->itemAbove();
+ else
+ above = atpos;
+ }
+
+ if (above)
+ {
+ // if above has children, I might need to drop it as the first item there
+
+ if (above->firstChild() && above->isOpen())
+ {
+ parent = above;
+ after = 0;
+ return;
+ }
+
+ // Now, we know we want to go after "above". But as a child or as a sibling ?
+ // We have to ask the "above" item if it accepts children.
+ if (above->isExpandable())
+ {
+ // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children
+ if (p.x() >= depthToPixels( above->depth() + 1 ) ||
+ (above->isOpen() && above->childCount() > 0) )
+ {
+ parent = above;
+ after = 0L;
+ return;
+ }
+ }
+
+ // Ok, there's one more level of complexity. We may want to become a new
+ // sibling, but of an upper-level group, rather than the "above" item
+ QListViewItem * betterAbove = above->parent();
+ QListViewItem * last = above;
+ while ( betterAbove )
+ {
+ // We are allowed to become a sibling of "betterAbove" only if we are
+ // after its last child
+ if ( !last->nextSibling() )
+ {
+ if (p.x() < depthToPixels ( betterAbove->depth() + 1 ))
+ above = betterAbove; // store this one, but don't stop yet, there may be a better one
+ else
+ break; // not enough on the left, so stop
+ last = betterAbove;
+ betterAbove = betterAbove->parent(); // up one level
+ } else
+ break; // we're among the child of betterAbove, not after the last one
+ }
+ }
+ // set as sibling
+ after = above;
+ parent = after ? after->parent() : 0L ;
+}
+
+QListViewItem* KListView::lastChild () const
+{
+ QListViewItem* lastchild = firstChild();
+
+ if (lastchild)
+ for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling());
+
+ return lastchild;
+}
+
+QListViewItem *KListView::lastItem() const
+{
+ QListViewItem* last = lastChild();
+
+ for (QListViewItemIterator it (last); it.current(); ++it)
+ last = it.current();
+
+ return last;
+}
+
+KLineEdit *KListView::renameLineEdit() const
+{
+ return d->editor;
+}
+
+void KListView::startDrag()
+{
+ QDragObject *drag = dragObject();
+
+ if (!drag)
+ return;
+
+ if (drag->drag() && drag->target() != viewport())
+ emit moved();
+}
+
+QDragObject *KListView::dragObject()
+{
+ if (!currentItem())
+ return 0;
+
+
+ return new QStoredDrag("application/x-qlistviewitem", viewport());
+}
+
+void KListView::setItemsMovable(bool b)
+{
+ d->itemsMovable=b;
+}
+
+bool KListView::itemsMovable() const
+{
+ return d->itemsMovable;
+}
+
+void KListView::setItemsRenameable(bool b)
+{
+ d->itemsRenameable=b;
+}
+
+bool KListView::itemsRenameable() const
+{
+ return d->itemsRenameable;
+}
+
+
+void KListView::setDragEnabled(bool b)
+{
+ d->dragEnabled=b;
+}
+
+bool KListView::dragEnabled() const
+{
+ return d->dragEnabled;
+}
+
+void KListView::setAutoOpen(bool b)
+{
+ d->autoOpen=b;
+}
+
+bool KListView::autoOpen() const
+{
+ return d->autoOpen;
+}
+
+bool KListView::dropVisualizer() const
+{
+ return d->dropVisualizer;
+}
+
+void KListView::setDropVisualizer(bool b)
+{
+ d->dropVisualizer=b;
+}
+
+QPtrList<QListViewItem> KListView::selectedItems() const
+{
+ return selectedItems(true);
+}
+
+QPtrList<QListViewItem> KListView::selectedItems(bool includeHiddenItems) const
+{
+ QPtrList<QListViewItem> list;
+
+ // Using selectionMode() instead of selectionModeExt() since for the cases that
+ // we're interested in selectionMode() should work for either variety of the
+ // setSelectionMode().
+
+ switch(selectionMode())
+ {
+ case NoSelection:
+ break;
+ case Single:
+ if(selectedItem() && (includeHiddenItems || selectedItem()->isVisible()))
+ list.append(selectedItem());
+ break;
+ default:
+ {
+ int flags = QListViewItemIterator::Selected;
+ if (!includeHiddenItems)
+ {
+ flags |= QListViewItemIterator::Visible;
+ }
+
+ QListViewItemIterator it(const_cast<KListView *>(this), flags);
+
+ for(; it.current(); ++it)
+ list.append(it.current());
+
+ break;
+ }
+ }
+
+ return list;
+}
+
+
+void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after)
+{
+ // sanity check - don't move a item into its own child structure
+ QListViewItem *i = parent;
+ while(i)
+ {
+ if(i == item)
+ return;
+ i = i->parent();
+ }
+
+ if (after)
+ {
+ item->moveItem(after);
+ return;
+ }
+
+ // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor
+ // in here, without ever deleting the item.
+ if (item->parent())
+ item->parent()->takeItem(item);
+ else
+ takeItem(item);
+
+ if (parent)
+ parent->insertItem(item);
+ else
+ insertItem(item);
+}
+
+void KListView::contentsDragEnterEvent(QDragEnterEvent *event)
+{
+ if (acceptDrag (event))
+ event->accept();
+}
+
+void KListView::setDropVisualizerWidth (int w)
+{
+ d->mDropVisualizerWidth = w > 0 ? w : 1;
+}
+
+QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent,
+ QListViewItem *after)
+{
+ QRect insertmarker;
+
+ if (!after && !parent)
+ insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2);
+ else
+ {
+ int level = 0;
+ if (after)
+ {
+ QListViewItem* it = 0L;
+ if (after->isOpen())
+ {
+ // Look for the last child (recursively)
+ it = after->firstChild();
+ if (it)
+ while (it->nextSibling() || it->firstChild())
+ if ( it->nextSibling() )
+ it = it->nextSibling();
+ else
+ it = it->firstChild();
+ }
+
+ insertmarker = itemRect (it ? it : after);
+ level = after->depth();
+ }
+ else if (parent)
+ {
+ insertmarker = itemRect (parent);
+ level = parent->depth() + 1;
+ }
+ insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() );
+ insertmarker.setRight (viewport()->width());
+ insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1);
+ insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2);
+ }
+
+ // This is not used anymore, at least by KListView itself (see viewportPaintEvent)
+ // Remove for KDE 4.0.
+ if (p)
+ p->fillRect(insertmarker, Dense4Pattern);
+
+ return insertmarker;
+}
+
+QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item)
+{
+ QRect r;
+
+ if (item)
+ {
+ r = itemRect(item);
+ r.setLeft(r.left()+(item->depth()+(rootIsDecorated() ? 1 : 0))*treeStepSize());
+ if (painter)
+ style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(),
+ QStyle::Style_FocusAtBorder, colorGroup().highlight());
+ }
+
+ return r;
+}
+
+void KListView::cleanItemHighlighter ()
+{
+ if (d->mOldDropHighlighter.isValid())
+ {
+ QRect rect=d->mOldDropHighlighter;
+ d->mOldDropHighlighter = QRect();
+ viewport()->repaint(rect, true);
+ }
+}
+
+void KListView::rename(QListViewItem *item, int c)
+{
+ if (d->renameable.contains(c))
+ {
+ ensureItemVisible(item);
+ d->editor->load(item,c);
+ }
+}
+
+bool KListView::isRenameable (int col) const
+{
+ return d->renameable.contains(col);
+}
+
+void KListView::setRenameable (int col, bool renameable)
+{
+ if (col>=header()->count()) return;
+
+ d->renameable.remove(col);
+ if (renameable)
+ d->renameable+=col;
+}
+
+void KListView::doneEditing(QListViewItem *item, int row)
+{
+ emit itemRenamed(item, item->text(row), row);
+ emit itemRenamed(item);
+}
+
+bool KListView::acceptDrag(QDropEvent* e) const
+{
+ return acceptDrops() && itemsMovable() && (e->source()==viewport());
+}
+
+void KListView::setCreateChildren(bool b)
+{
+ d->createChildren=b;
+}
+
+bool KListView::createChildren() const
+{
+ return d->createChildren;
+}
+
+
+int KListView::tooltipColumn() const
+{
+ return d->tooltipColumn;
+}
+
+void KListView::setTooltipColumn(int column)
+{
+ d->tooltipColumn=column;
+}
+
+void KListView::setDropHighlighter(bool b)
+{
+ d->dropHighlighter=b;
+}
+
+bool KListView::dropHighlighter() const
+{
+ return d->dropHighlighter;
+}
+
+bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const
+{
+ return ((column==tooltipColumn()) && !tooltip(item, column).isEmpty());
+}
+
+QString KListView::tooltip(QListViewItem *item, int column) const
+{
+ return item->text(column);
+}
+
+void KListView::setTabOrderedRenaming(bool b)
+{
+ d->tabRename = b;
+}
+
+bool KListView::tabOrderedRenaming() const
+{
+ return d->tabRename;
+}
+
+void KListView::keyPressEvent (QKeyEvent* e)
+{
+ //don't we need a contextMenuModifier too ? (aleXXX)
+ if (e->key() == d->contextMenuKey)
+ {
+ emit menuShortCutPressed (this, currentItem());
+ return;
+ }
+
+ if (d->selectionMode != FileManager)
+ QListView::keyPressEvent (e);
+ else
+ fileManagerKeyPressEvent (e);
+}
+
+void KListView::activateAutomaticSelection()
+{
+ d->selectedBySimpleMove=true;
+ d->selectedUsingMouse=false;
+ if (currentItem())
+ {
+ currentItem()->setSelected(true);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+}
+
+void KListView::deactivateAutomaticSelection()
+{
+ d->selectedBySimpleMove=false;
+}
+
+bool KListView::automaticSelection() const
+{
+ return d->selectedBySimpleMove;
+}
+
+void KListView::fileManagerKeyPressEvent (QKeyEvent* e)
+{
+ //don't care whether it's on the keypad or not
+ int e_state=(e->state() & ~Keypad);
+
+ int oldSelectionDirection(d->selectionDirection);
+
+ if ((e->key()!=Key_Shift) && (e->key()!=Key_Control)
+ && (e->key()!=Key_Meta) && (e->key()!=Key_Alt))
+ {
+ if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove))
+ selectAll(false);
+ d->selectionDirection=0;
+ d->wasShiftEvent = (e_state == ShiftButton);
+ };
+
+ //d->wasShiftEvent = (e_state == ShiftButton);
+
+
+ QListViewItem* item = currentItem();
+ if (!item) return;
+
+ QListViewItem* repaintItem1 = item;
+ QListViewItem* repaintItem2 = 0L;
+ QListViewItem* visItem = 0L;
+
+ QListViewItem* nextItem = 0L;
+ int items = 0;
+
+ bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton));
+ int selectedItems(0);
+ for (QListViewItem *tmpItem=firstChild(); tmpItem; tmpItem=tmpItem->nextSibling())
+ if (tmpItem->isSelected()) selectedItems++;
+
+ if (((!selectedItems) || ((selectedItems==1) && (d->selectedUsingMouse)))
+ && (e_state==NoButton)
+ && ((e->key()==Key_Down)
+ || (e->key()==Key_Up)
+ || (e->key()==Key_Next)
+ || (e->key()==Key_Prior)
+ || (e->key()==Key_Home)
+ || (e->key()==Key_End)))
+ {
+ d->selectedBySimpleMove=true;
+ d->selectedUsingMouse=false;
+ }
+ else if (selectedItems>1)
+ d->selectedBySimpleMove=false;
+
+ bool emitSelectionChanged(false);
+
+ switch (e->key())
+ {
+ case Key_Escape:
+ selectAll(false);
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Space:
+ //toggle selection of current item
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Insert:
+ //toggle selection of current item and move to the next item
+ if (d->selectedBySimpleMove)
+ {
+ d->selectedBySimpleMove=false;
+ if (!item->isSelected()) item->setSelected(true);
+ }
+ else
+ {
+ item->setSelected(!item->isSelected());
+ };
+
+ nextItem=item->itemBelow();
+
+ if (nextItem)
+ {
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ d->selectionDirection=1;
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Down:
+ nextItem=item->itemBelow();
+ //toggle selection of current item and move to the next item
+ if (shiftOrCtrl)
+ {
+ d->selectionDirection=1;
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ else
+ {
+ if (oldSelectionDirection!=-1)
+ {
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ };
+ };
+ }
+ else if ((d->selectedBySimpleMove) && (nextItem))
+ {
+ item->setSelected(false);
+ emitSelectionChanged=true;
+ };
+
+ if (nextItem)
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ break;
+
+ case Key_Up:
+ nextItem=item->itemAbove();
+ d->selectionDirection=-1;
+ //move to the prev. item and toggle selection of this one
+ // => No, can't select the last item, with this. For symmetry, let's
+ // toggle selection and THEN move up, just like we do in down (David)
+ if (shiftOrCtrl)
+ {
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ else
+ {
+ if (oldSelectionDirection!=1)
+ {
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ };
+ }
+ }
+ else if ((d->selectedBySimpleMove) && (nextItem))
+ {
+ item->setSelected(false);
+ emitSelectionChanged=true;
+ };
+
+ if (nextItem)
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ break;
+
+ case Key_End:
+ //move to the last item and toggle selection of all items inbetween
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ d->selectedBySimpleMove=false;
+
+ while(nextItem)
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ if (!nextItem->itemBelow())
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ }
+ nextItem=nextItem->itemBelow();
+ }
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Home:
+ // move to the first item and toggle selection of all items inbetween
+ nextItem = firstChild();
+ visItem = nextItem;
+ repaintItem2 = visItem;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectedBySimpleMove=false;
+
+ while ( nextItem != item )
+ {
+ nextItem->setSelected( !nextItem->isSelected() );
+ nextItem = nextItem->itemBelow();
+ }
+ item->setSelected( !item->isSelected() );
+ }
+ setCurrentItem( firstChild() );
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Next:
+ items=visibleHeight()/item->height();
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectedBySimpleMove=false;
+ d->selectionDirection=1;
+ };
+
+ for (int i=0; i<items; i++)
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ //the end
+ if ((i==items-1) || (!nextItem->itemBelow()))
+
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ ensureItemVisible(nextItem);
+ setCurrentItem(nextItem);
+ update();
+ if ((shiftOrCtrl) || (d->selectedBySimpleMove))
+ {
+ emit selectionChanged();
+ }
+ return;
+ }
+ nextItem=nextItem->itemBelow();
+ }
+ break;
+
+ case Key_Prior:
+ items=visibleHeight()/item->height();
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectionDirection=-1;
+ d->selectedBySimpleMove=false;
+ };
+
+ for (int i=0; i<items; i++)
+ {
+ if ((nextItem!=item) &&(shiftOrCtrl))
+ nextItem->setSelected(!nextItem->isSelected());
+ //the end
+ if ((i==items-1) || (!nextItem->itemAbove()))
+
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ ensureItemVisible(nextItem);
+ setCurrentItem(nextItem);
+ update();
+ if ((shiftOrCtrl) || (d->selectedBySimpleMove))
+ {
+ emit selectionChanged();
+ }
+ return;
+ }
+ nextItem=nextItem->itemAbove();
+ }
+ break;
+
+ case Key_Minus:
+ if ( item->isOpen() )
+ setOpen( item, false );
+ break;
+ case Key_Plus:
+ if ( !item->isOpen() && (item->isExpandable() || item->childCount()) )
+ setOpen( item, true );
+ break;
+ default:
+ bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control)
+ && (e->key()!=Key_Meta) && (e->key()!=Key_Alt));
+
+ bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected());
+ if (realKey && selectCurrentItem)
+ item->setSelected(false);
+ //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX)
+ QListView::SelectionMode oldSelectionMode = selectionMode();
+ setSelectionMode (QListView::Multi);
+ QListView::keyPressEvent (e);
+ setSelectionMode (oldSelectionMode);
+ if (realKey && selectCurrentItem)
+ {
+ currentItem()->setSelected(true);
+ emitSelectionChanged=true;
+ }
+ repaintItem2=currentItem();
+ if (realKey)
+ visItem=currentItem();
+ break;
+ }
+
+ if (visItem)
+ ensureItemVisible(visItem);
+
+ QRect ir;
+ if (repaintItem1)
+ ir = ir.unite( itemRect(repaintItem1) );
+ if (repaintItem2)
+ ir = ir.unite( itemRect(repaintItem2) );
+
+ if ( !ir.isEmpty() )
+ { // rectangle to be repainted
+ if ( ir.x() < 0 )
+ ir.moveBy( -ir.x(), 0 );
+ viewport()->repaint( ir, false );
+ }
+ /*if (repaintItem1)
+ repaintItem1->repaint();
+ if (repaintItem2)
+ repaintItem2->repaint();*/
+ update();
+ if (emitSelectionChanged)
+ emit selectionChanged();
+}
+
+void KListView::setSelectionModeExt (SelectionModeExt mode)
+{
+ d->selectionMode = mode;
+
+ switch (mode)
+ {
+ case Single:
+ case Multi:
+ case Extended:
+ case NoSelection:
+ setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode)));
+ break;
+
+ case FileManager:
+ setSelectionMode (QListView::Extended);
+ break;
+
+ default:
+ kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl;
+ break;
+ }
+}
+
+KListView::SelectionModeExt KListView::selectionModeExt () const
+{
+ return d->selectionMode;
+}
+
+int KListView::itemIndex( const QListViewItem *item ) const
+{
+ if ( !item )
+ return -1;
+
+ if ( item == firstChild() )
+ return 0;
+ else {
+ QListViewItemIterator it(firstChild());
+ uint j = 0;
+ for (; it.current() && it.current() != item; ++it, ++j );
+
+ if( !it.current() )
+ return -1;
+
+ return j;
+ }
+}
+
+QListViewItem* KListView::itemAtIndex(int index)
+{
+ if (index<0)
+ return 0;
+
+ int j(0);
+ for (QListViewItemIterator it=firstChild(); it.current(); ++it)
+ {
+ if (j==index)
+ return it.current();
+ ++j;
+ };
+ return 0;
+}
+
+
+void KListView::emitContextMenu (KListView*, QListViewItem* i)
+{
+ QPoint p;
+
+ if (i)
+ p = viewport()->mapToGlobal(itemRect(i).center());
+ else
+ p = mapToGlobal(rect().center());
+
+ emit contextMenu (this, i, p);
+}
+
+void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int)
+{
+ emit contextMenu (this, i, p);
+}
+
+void KListView::setAcceptDrops (bool val)
+{
+ QListView::setAcceptDrops (val);
+ viewport()->setAcceptDrops (val);
+}
+
+int KListView::dropVisualizerWidth () const
+{
+ return d->mDropVisualizerWidth;
+}
+
+
+void KListView::viewportPaintEvent(QPaintEvent *e)
+{
+ d->paintAbove = 0;
+ d->paintCurrent = 0;
+ d->paintBelow = 0;
+ d->painting = true;
+
+ QListView::viewportPaintEvent(e);
+
+ if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer))
+ {
+ QPainter painter(viewport());
+
+ // This is where we actually draw the drop-visualizer
+ painter.fillRect(d->mOldDropVisualizer, Dense4Pattern);
+ }
+ if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter))
+ {
+ QPainter painter(viewport());
+
+ // This is where we actually draw the drop-highlighter
+ style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(),
+ QStyle::Style_FocusAtBorder);
+ }
+ d->painting = false;
+}
+
+void KListView::setFullWidth()
+{
+ setFullWidth(true);
+}
+
+void KListView::setFullWidth(bool fullWidth)
+{
+ d->fullWidth = fullWidth;
+ header()->setStretchEnabled(fullWidth, columns()-1);
+}
+
+bool KListView::fullWidth() const
+{
+ return d->fullWidth;
+}
+
+int KListView::addColumn(const QString& label, int width)
+{
+ int result = QListView::addColumn(label, width);
+ if (d->fullWidth) {
+ header()->setStretchEnabled(false, columns()-2);
+ header()->setStretchEnabled(true, columns()-1);
+ }
+ return result;
+}
+
+int KListView::addColumn(const QIconSet& iconset, const QString& label, int width)
+{
+ int result = QListView::addColumn(iconset, label, width);
+ if (d->fullWidth) {
+ header()->setStretchEnabled(false, columns()-2);
+ header()->setStretchEnabled(true, columns()-1);
+ }
+ return result;
+}
+
+void KListView::removeColumn(int index)
+{
+ QListView::removeColumn(index);
+ if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1);
+}
+
+void KListView::viewportResizeEvent(QResizeEvent* e)
+{
+ QListView::viewportResizeEvent(e);
+}
+
+const QColor &KListView::alternateBackground() const
+{
+ return d->alternateBackground;
+}
+
+void KListView::setAlternateBackground(const QColor &c)
+{
+ d->alternateBackground = c;
+ repaint();
+}
+
+void KListView::setShadeSortColumn(bool shadeSortColumn)
+{
+ d->shadeSortColumn = shadeSortColumn;
+ repaint();
+}
+
+bool KListView::shadeSortColumn() const
+{
+ return d->shadeSortColumn;
+}
+
+void KListView::saveLayout(KConfig *config, const QString &group) const
+{
+ KConfigGroupSaver saver(config, group);
+ QStringList widths, order;
+
+ const int colCount = columns();
+ QHeader* const thisHeader = header();
+ for (int i = 0; i < colCount; ++i)
+ {
+ widths << QString::number(columnWidth(i));
+ order << QString::number(thisHeader->mapToIndex(i));
+ }
+ config->writeEntry("ColumnWidths", widths);
+ config->writeEntry("ColumnOrder", order);
+ config->writeEntry("SortColumn", d->sortColumn);
+ config->writeEntry("SortAscending", d->sortAscending);
+}
+
+void KListView::restoreLayout(KConfig *config, const QString &group)
+{
+ KConfigGroupSaver saver(config, group);
+ QStringList cols = config->readListEntry("ColumnWidths");
+ int i = 0;
+ { // scope the iterators
+ QStringList::ConstIterator it = cols.constBegin();
+ const QStringList::ConstIterator itEnd = cols.constEnd();
+ for (; it != itEnd; ++it)
+ setColumnWidth(i++, (*it).toInt());
+ }
+
+ // move sections in the correct sequence: from lowest to highest index position
+ // otherwise we move a section from an index, which modifies
+ // all index numbers to the right of the moved one
+ cols = config->readListEntry("ColumnOrder");
+ const int colCount = columns();
+ for (i = 0; i < colCount; ++i) // final index positions from lowest to highest
+ {
+ QStringList::ConstIterator it = cols.constBegin();
+ const QStringList::ConstIterator itEnd = cols.constEnd();
+
+ int section = 0;
+ for (; (it != itEnd) && ((*it).toInt() != i); ++it, ++section) ;
+
+ if ( it != itEnd ) {
+ // found the section to move to position i
+ header()->moveSection(section, i);
+ }
+ }
+
+ if (config->hasKey("SortColumn"))
+ setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true));
+}
+
+void KListView::setSorting(int column, bool ascending)
+{
+ QListViewItem *selected = 0;
+
+ if (selectionMode() == QListView::Single) {
+ selected = selectedItem();
+ if (selected && !selected->isVisible())
+ selected = 0;
+ }
+ else if (selectionMode() != QListView::NoSelection) {
+ QListViewItem *item = firstChild();
+ while (item && !selected) {
+ if (item->isSelected() && item->isVisible())
+ selected = item;
+ item = item->itemBelow();
+ }
+ }
+
+ d->sortColumn = column;
+ d->sortAscending = ascending;
+ QListView::setSorting(column, ascending);
+
+ if (selected)
+ ensureItemVisible(selected);
+
+ QListViewItem* item = firstChild();
+ while ( item ) {
+ KListViewItem *kItem = dynamic_cast<KListViewItem*>(item);
+ if (kItem) kItem->m_known = false;
+ item = item->itemBelow();
+ }
+}
+
+int KListView::columnSorted(void) const
+{
+ return d->sortColumn;
+}
+
+bool KListView::ascendingSort(void) const
+{
+ return d->sortAscending;
+}
+
+void KListView::takeItem(QListViewItem *item)
+{
+ if(item && item == d->editor->currentItem())
+ d->editor->terminate();
+
+ QListView::takeItem(item);
+}
+
+void KListView::disableAutoSelection()
+{
+ if ( d->disableAutoSelection )
+ return;
+
+ d->disableAutoSelection = true;
+ d->autoSelect.stop();
+ d->autoSelectDelay = -1;
+}
+
+void KListView::resetAutoSelection()
+{
+ if ( !d->disableAutoSelection )
+ return;
+
+ d->disableAutoSelection = false;
+ d->autoSelectDelay = KGlobalSettings::autoSelectDelay();
+}
+
+void KListView::doubleClicked( QListViewItem *item, const QPoint &pos, int c )
+{
+ emit QListView::doubleClicked( item, pos, c );
+}
+
+KListViewItem::KListViewItem(QListView *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::~KListViewItem()
+{
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemRemoved(this);
+}
+
+void KListViewItem::init()
+{
+ m_odd = m_known = false;
+ KListView *lv = static_cast<KListView *>(listView());
+ setDragEnabled( dragEnabled() || lv->dragEnabled() );
+ emit lv->itemAdded(this);
+}
+
+void KListViewItem::insertItem(QListViewItem *item)
+{
+ QListViewItem::insertItem(item);
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemAdded(item);
+}
+
+void KListViewItem::takeItem(QListViewItem *item)
+{
+ QListViewItem::takeItem(item);
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemRemoved(item);
+}
+
+const QColor &KListViewItem::backgroundColor()
+{
+ if (isAlternate())
+ return static_cast< KListView* >(listView())->alternateBackground();
+ return listView()->viewport()->colorGroup().base();
+}
+
+QColor KListViewItem::backgroundColor(int column)
+{
+ KListView* view = static_cast< KListView* >(listView());
+ QColor color = isAlternate() ?
+ view->alternateBackground() :
+ view->viewport()->colorGroup().base();
+
+ // calculate a different color if the current column is sorted (only if more than 1 column)
+ if ( (view->columns() > 1) && view->shadeSortColumn() && (column == view->columnSorted()) )
+ {
+ if ( color == Qt::black )
+ color = QColor(55, 55, 55); // dark gray
+ else
+ {
+ int h,s,v;
+ color.hsv(&h, &s, &v);
+ if ( v > 175 )
+ color = color.dark(104);
+ else
+ color = color.light(120);
+ }
+ }
+
+ return color;
+}
+
+bool KListViewItem::isAlternate()
+{
+ KListView* const lv = static_cast<KListView *>(listView());
+ if (lv && lv->alternateBackground().isValid())
+ {
+ KListViewItem *above;
+
+ KListView::KListViewPrivate* const lvD = lv->d;
+
+ // Ok, there's some weirdness here that requires explanation as this is a
+ // speed hack. itemAbove() is a O(n) operation (though this isn't
+ // immediately clear) so we want to call it as infrequently as possible --
+ // especially in the case of painting a cell.
+ //
+ // So, in the case that we *are* painting a cell: (1) we're assuming that
+ // said painting is happening top to bottem -- this assumption is present
+ // elsewhere in the implementation of this class, (2) itemBelow() is fast --
+ // roughly constant time.
+ //
+ // Given these assumptions we can do a mixture of caching and telling the
+ // next item that the when that item is the current item that the now
+ // current item will be the item above it.
+ //
+ // Ideally this will make checking to see if the item above the current item
+ // is the alternate color a constant time operation rather than 0(n).
+
+ if (lvD->painting) {
+ if (lvD->paintCurrent != this)
+ {
+ lvD->paintAbove = lvD->paintBelow == this ? lvD->paintCurrent : itemAbove();
+ lvD->paintCurrent = this;
+ lvD->paintBelow = itemBelow();
+ }
+
+ above = dynamic_cast<KListViewItem *>(lvD->paintAbove);
+ }
+ else
+ {
+ above = dynamic_cast<KListViewItem *>(itemAbove());
+ }
+
+ m_known = above ? above->m_known : true;
+ if (m_known)
+ {
+ m_odd = above ? !above->m_odd : false;
+ }
+ else
+ {
+ KListViewItem *item;
+ bool previous = true;
+ if (parent())
+ {
+ item = dynamic_cast<KListViewItem *>(parent());
+ if (item)
+ previous = item->m_odd;
+ item = dynamic_cast<KListViewItem *>(parent()->firstChild());
+ }
+ else
+ {
+ item = dynamic_cast<KListViewItem *>(lv->firstChild());
+ }
+
+ while(item)
+ {
+ previous = !previous;
+ item->m_odd = previous;
+ item->m_known = true;
+ item = dynamic_cast<KListViewItem *>(item->nextSibling());
+ }
+ }
+ return m_odd;
+ }
+ return false;
+}
+
+void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ QColorGroup _cg = cg;
+ QListView* lv = listView();
+ const QPixmap *pm = lv->viewport()->backgroundPixmap();
+
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(column), *pm));
+ QPoint o = p->brushOrigin();
+ p->setBrushOrigin( o.x()-lv->contentsX(), o.y()-lv->contentsY() );
+ }
+ else
+ {
+ _cg.setColor((lv->viewport()->backgroundMode() == Qt::FixedColor) ?
+ QColorGroup::Background : QColorGroup::Base,
+ backgroundColor(column));
+ }
+ QListViewItem::paintCell(p, _cg, column, width, alignment);
+}
+
+void KListView::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "klistview.moc"
+#include "klistviewlineedit.moc"
+
+// vim: noet