diff --git a/kdeui/kcolorcombo.h b/kdeui/kcolorcombo.h index a3dc10a225..e98fae4cd6 100644 --- a/kdeui/kcolorcombo.h +++ b/kdeui/kcolorcombo.h @@ -1,71 +1,72 @@ /* This file is part of the KDE libraries Copyright (C) 1997 Martin Jones (mjones@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //----------------------------------------------------------------------------- // KDE color selection combo box // layout managment added Oct 1997 by Mario Weilguni // #ifndef _KCOLORCOMBO_H__ #define _KCOLORCOMBO_H__ #include #include #include "kselect.h" /** * Combobox for colours. */ class KColorCombo : public QComboBox { Q_OBJECT + Q_PROPERTY( QColor color READ color WRITE setColor ) public: KColorCombo( QWidget *parent, const char *name = 0L ); void setColor( const QColor &col ); /** * Retrieve the currently selected color. **/ QColor color(); public slots: void slotActivated( int index ); void slotHighlighted( int index ); signals: void activated( const QColor &col ); void highlighted( const QColor &col ); protected: /** * @reimplemented */ virtual void resizeEvent( QResizeEvent *re ); private: void addColors(); QColor customColor; QColor internalcolor; class KColorComboPrivate; KColorComboPrivate *d; }; #endif // __KCOLORCOMBO_H__ diff --git a/kdeui/klistview.cpp b/kdeui/klistview.cpp index 81aa61c873..120c709135 100644 --- a/kdeui/klistview.cpp +++ b/kdeui/klistview.cpp @@ -1,1859 +1,1890 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Reginald Stadlbauer Copyright (C) 2000 Charles Samuels 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define private public #include #undef private #include "klistview.h" #include "klistviewlineedit.h" #ifdef Q_WS_X11 #include #endif 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 (0L), oldCursor (listview->viewport()->cursor()), dragDelay (KGlobalSettings::dndEventDelay()), editor (new KListViewLineEdit (listview)), itemsMovable (true), selectedBySimpleMove(false), itemsRenameable (false), validDrag (false), dragEnabled (false), autoOpen (true), dropVisualizer (true), dropHighlighter (false), createChildren (true), pressedOnSelected (false), wasShiftEvent (false), fullWidth (false), sortAscending(true), sortColumn(0), selectionDirection(0), tooltipColumn (0), selectionMode (Single), contextMenuKey (KGlobalSettings::contextMenuKey()), showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()), mDropVisualizerWidth (4) { renameable += 0; connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int))); } ~KListViewPrivate () { delete editor; } QListViewItem* pCurrentItem; QTimer autoSelect; int autoSelectDelay; QCursor oldCursor; QPoint startDragPos; int dragDelay; KListViewLineEdit *editor; QValueList renameable; bool cursorInExecuteArea:1; bool bUseSingle:1; bool bChangeCursorOverItem:1; bool itemsMovable:1; bool selectedBySimpleMove : 1; bool itemsRenameable:1; bool validDrag:1; bool dragEnabled:1; bool autoOpen:1; bool dropVisualizer:1; bool dropHighlighter:1; bool createChildren:1; bool pressedOnSelected:1; bool wasShiftEvent:1; bool fullWidth:1; bool sortAscending: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; QColor alternateBackground; }; KListViewLineEdit::KListViewLineEdit(KListView *parent) : KLineEdit(parent->viewport()), item(0), col(0), p(parent) { setFrame( false ); hide(); connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() )); } KListViewLineEdit::~KListViewLineEdit() { } void KListViewLineEdit::load(QListViewItem *i, int c) { item=i; col=c; QRect rect(p->itemRect(i)); setText(item->text(c)); int fieldX = rect.x() - 1; int fieldW = p->columnWidth(col) + 2; int pos = p->header()->mapToIndex(col); for ( int index = 0; index < pos; index++ ) fieldX += p->columnWidth( p->header()->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(); } 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 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; hide(); // will call focusOutEvent, that's why we set item=0 before emit done(i,c); } } void KListViewLineEdit::focusOutEvent(QFocusEvent *ev) { QFocusEvent * focusEv = static_cast(ev); // Don't let a RMB close the editor if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow) terminate(true); } 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(); } 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() ) ); // 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 ) { if ( itemAt( point ) ) return isExecuteArea( point.x() ); return false; } bool KListView::isExecuteArea( int x ) { if( allColumnsShowFocus() ) return true; else { int offset = 0; int width = columnWidth( 0 ); int pos = header()->mapToIndex( 0 ); for ( int index = 0; index < pos; index++ ) offset += columnWidth( header()->mapToSection( index ) ); return ( x > offset && x < ( offset + width ) ); } } void KListView::slotOnItem( QListViewItem *item ) { if ( item && isExecuteArea( QCursor::pos().x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) { d->autoSelect.start( d->autoSelectDelay, true ); d->pCurrentItem = item; } } void KListView::slotOnViewport() { if ( d->bChangeCursorOverItem ) viewport()->setCursor( d->oldCursor ); 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(); d->autoSelectDelay = KGlobalSettings::autoSelectDelay(); if( !d->bUseSingle || !d->bChangeCursorOverItem ) viewport()->setCursor( d->oldCursor ); 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(); #ifdef Q_WS_X11 // FIXME(E): Implement for Qt Embedded Window root; Window child; int root_x, root_y, win_x, win_y; uint keybstate; XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, &root_x, &root_y, &win_x, &win_y, &keybstate ); #endif QListViewItem* previousItem = currentItem(); setCurrentItem( d->pCurrentItem ); #ifndef Q_WS_QWS // FIXME(E): Implement for Qt Embedded if( d->pCurrentItem ) { //Shift pressed? if( (keybstate & ShiftMask) ) { bool block = signalsBlocked(); blockSignals( true ); //No Ctrl? Then clear before! if( !(keybstate & ControlMask) ) 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 & ControlMask) ) 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; #endif } +void KListView::slotHeaderChanged() +{ + if (d->fullWidth && columns()) + { + int w = 0; + for (int i = 0; i < columns() - 1; ++i) w += columnWidth(i); + setColumnWidth( columns() - 1, viewport()->width() - w - 1 ); + } +} + void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c ) { if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) { // Double click mode ? if ( !d->bUseSingle ) { emit executed( item ); emit executed( item, pos, c ); } else { #ifndef Q_WS_QWS // FIXME(E): Implement for Qt Embedded Window root; Window child; int root_x, root_y, win_x, win_y; uint keybstate; XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, &root_x, &root_y, &win_x, &win_y, &keybstate ); d->autoSelect.stop(); //Donīt emit executed if in SC mode and Shift or Ctrl are pressed if( !( ((keybstate & ShiftMask) || (keybstate & ControlMask)) ) ) { emit executed( item ); emit executed( item, pos, c ); } #endif } } } void KListView::focusInEvent( QFocusEvent *fe ) { // kdDebug()<<"KListView::focusInEvent()"<selectedBySimpleMove) && (d->selectionMode == Konqueror) && (fe->reason()!=QFocusEvent::Popup) && (fe->reason()!=QFocusEvent::ActiveWindow) && (currentItem()!=0)) { currentItem()->setSelected(true); currentItem()->repaint(); emit selectionChanged(); }; } void KListView::focusOutEvent( QFocusEvent *fe ) { cleanDropVisualizer(); cleanItemHighlighter(); d->autoSelect.stop(); if ((d->selectedBySimpleMove) && (d->selectionMode == Konqueror) && (fe->reason()!=QFocusEvent::Popup) && (fe->reason()!=QFocusEvent::ActiveWindow) && (currentItem()!=0)) { 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()==Konqueror) && (d->selectedBySimpleMove)) { d->selectedBySimpleMove=false; if (currentItem()!=0) { 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()->setCursor( d->oldCursor ); } } 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 ); 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(); 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 items, afterFirsts, afterNows; QListViewItem *current=currentItem(); bool hasMoved=false; for (QListViewItem *i = firstChild(), *iNext=0; i != 0; 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 != 0; 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); 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, d->afterItemDrop); if (tmpRect != d->mOldDropHighlighter) { cleanItemHighlighter(); d->mOldDropHighlighter=tmpRect; viewport()->repaint(tmpRect); } } } else event->ignore(); } void KListView::contentsDragLeaveEvent (QDragLeaveEvent*) { 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) { // 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() == 0 ) { 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; } void KListView::startDrag() { QDragObject *drag = dragObject(); if (!drag) return; if (drag->drag() && drag->target() != viewport()) emit moved(); } QDragObject *KListView::dragObject() const { 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 KListView::selectedItems() const { QPtrList list; for (QListViewItem *i=firstChild(); i!=0; i=i->itemBelow()) if (i->isSelected()) list.append(i); return list; } void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after) { // sanity check - don't move a item into it's own child structure QListViewItem *i = parent; while(i) { if(i == item) return; i = i->parent(); } // 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); if (after) item->moveToJustAfter(after); } 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 3.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()+1)*treeStepSize()); if (painter) #if QT_VERSION < 300 style().drawFocusRect(painter, r, colorGroup(), &colorGroup().highlight(), true); #else style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(), QStyle::Style_FocusAtBorder, colorGroup().highlight()); #endif } 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) { d->editor->load(item,c); } bool KListView::isRenameable (int col) const { return d->renameable.contains(col); } void KListView::setRenameable (int col, bool yesno) { if (col>=header()->count()) return; d->renameable.remove(col); if (yesno && d->renameable.find(col)==d->renameable.end()) d->renameable+=col; else if (!yesno && d->renameable.find(col)!=d->renameable.end()) d->renameable.remove(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 ((tooltip(item, column).length()>0) && (column==tooltipColumn())); } QString KListView::tooltip(QListViewItem *item, int column) const { return item->text(column); } 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 != Konqueror) QListView::keyPressEvent (e); else konquerorKeyPressEvent (e); } //this one is only called in konq_listviewwidget, aleXXX //### KDE 3: do something about it, aleXXX void KListView::selectCurrentItemAndEnableSelectedBySimpleMoveMode() { d->selectedBySimpleMove=true; if (currentItem()!=0) { currentItem()->setSelected(true); currentItem()->repaint(); emit selectionChanged(); }; } void KListView::konquerorKeyPressEvent (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==0) return; setUpdatesEnabled(false); 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!=0; tmpItem=tmpItem->nextSibling()) if (tmpItem->isSelected()) selectedItems++; if ((selectedItems==0) && (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; 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!=0) { 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!=0)) { item->setSelected(false); emitSelectionChanged=TRUE; }; if (nextItem!=0) { 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!=0)) { item->setSelected(false); emitSelectionChanged=TRUE; }; if (nextItem!=0) { 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!=0) { if (shiftOrCtrl) nextItem->setSelected(!nextItem->isSelected()); if (nextItem->itemBelow()==0) { if (d->selectedBySimpleMove) nextItem->setSelected(true); repaintItem2=nextItem; visItem=nextItem; setCurrentItem(nextItem); } nextItem=nextItem->itemBelow(); } emitSelectionChanged=TRUE; break; case Key_Home: //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!=0) { if (shiftOrCtrl) nextItem->setSelected(!nextItem->isSelected()); if (nextItem->itemAbove()==0) { if (d->selectedBySimpleMove) nextItem->setSelected(true); repaintItem2=nextItem; visItem=nextItem; setCurrentItem(nextItem); } nextItem=nextItem->itemAbove(); } 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; isetSelected(!nextItem->isSelected()); //the end if ((i==items-1) || (nextItem->itemBelow()==0)) { if (shiftOrCtrl) nextItem->setSelected(!nextItem->isSelected()); if (d->selectedBySimpleMove) nextItem->setSelected(true); setUpdatesEnabled(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; isetSelected(!nextItem->isSelected()); //the end if ((i==items-1) || (nextItem->itemAbove()==0)) { if (d->selectedBySimpleMove) nextItem->setSelected(true); setUpdatesEnabled(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) setSelectionMode (QListView::Multi); QListView::keyPressEvent (e); setSelectionMode (QListView::Extended); if (realKey && selectCurrentItem) { currentItem()->setSelected(true); emitSelectionChanged=TRUE; } repaintItem2=currentItem(); if (realKey) visItem=currentItem(); break; } setUpdatesEnabled(true); 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(static_cast(mode))); break; case Konqueror: 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) { 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 #if QT_VERSION < 300 style().drawFocusRect(&painter, d->mOldDropHighlighter, colorGroup(), 0, true); #else style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(), QStyle::Style_FocusAtBorder); #endif } } void KListView::setFullWidth() { - d->fullWidth = true; - header()->setResizeEnabled(false); - verticalScrollBar()->installEventFilter(this); + setFullWidth(true); +} + +void KListView::setFullWidth(bool fullWidth) +{ + if ((d->fullWidth = fullWidth)) + { + connect(header(), SIGNAL(sizeChange(int, int, int)), + SLOT(slotHeaderChanged())); + connect(header(), SIGNAL(indexChange(int, int, int)), + SLOT(slotHeaderChanged())); + } + else + { + disconnect(SIGNAL(sizeChange(int, int, int)), header(), + SLOT(slotHeaderChanged())); + disconnect(SIGNAL(indexChange(int, int, int)), header(), + SLOT(slotHeaderChanged())); + } + slotHeaderChanged(); +} + +bool KListView::fullWidth() const +{ + return d->fullWidth; } void KListView::viewportResizeEvent(QResizeEvent* e) { - if (d->fullWidth && columns()) - setColumnWidth( 0, e->size().width() - 1 ); + slotHeaderChanged(); QListView::viewportResizeEvent(e); } const QColor &KListView::alternateBackground() const { return d->alternateBackground; } void KListView::setAlternateBackground(const QColor &c) { d->alternateBackground = c; repaint(); } void KListView::saveLayout(KConfig *config, const QString &group) const { KConfigGroupSaver saver(config, group); QStringList widths, order; for (int i = 0; i < columns(); ++i) { widths << QString::number(columnWidth(i)); order << QString::number(header()->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; for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) setColumnWidth(i++, (*it).toInt()); cols = config->readListEntry("ColumnOrder"); i = 0; for (QStringList::ConstIterator it = cols.begin(); it != cols.end(); ++it) header()->moveSection(i++, (*it).toInt()); if (config->hasKey("SortColumn")) setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true)); } void KListView::setSorting(int column, bool ascending) { d->sortColumn = column; d->sortAscending = ascending; QListView::setSorting(column, ascending); } struct KListViewItem::KListViewItemPrivate { bool odd : 1; bool known : 1; }; 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() { delete d; } void KListViewItem::init() { d = new KListViewItemPrivate; d->known = false; } const QColor &KListViewItem::backgroundColor() { KListView *lv = dynamic_cast(listView()); if (lv && lv->alternateBackground().isValid()) { KListViewItem *above = 0; QPtrStack items; for (KListViewItem *item = this; item; item = above) { items.push(item); above = dynamic_cast(item->itemAbove()); if (!above || above->d->known) break; } while (items.top()) { items.top()->d->odd = above ? !above->d->odd : false; items.top()->d->known = true; above = items.pop(); } if (d->odd) return lv->alternateBackground(); } return listView()->viewport()->colorGroup().base(); } void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) { QColorGroup _cg = cg; const QPixmap *pm = listView()->viewport()->backgroundPixmap(); if (pm && !pm->isNull()) { _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(), *pm)); p->setBrushOrigin( -listView()->contentsX(), -listView()->contentsY() ); } else _cg.setColor(QColorGroup::Base, backgroundColor()); QListViewItem::paintCell(p, _cg, column, width, alignment); } #include "klistview.moc" #include "klistviewlineedit.moc" // vim: ts=2 sw=2 et diff --git a/kdeui/klistview.h b/kdeui/klistview.h index da685fbd62..96b1a51194 100644 --- a/kdeui/klistview.h +++ b/kdeui/klistview.h @@ -1,894 +1,908 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Reginald Stadlbauer Copyright (C) 2000 Charles Samuels 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KLISTVIEW_H #define KLISTVIEW_H #include #include class QDragObject; class KConfig; /** * This Widget extends the functionality of QListView to honor the system * wide settings for Single Click/Double Click mode, AutoSelection and * ChangeCursorOverLink (TM). * * There is a new signal executed(). It gets connected to either * @ref QListView::clicked() or @ref QListView::doubleClicked() depending on the KDE * wide Single Click/Double Click settings. It is strongly recommended that * you use this signal instead of the above mentioned. This way you donīt * need to care about the current settings. * If you want to get informed when the user selects something connect to the * QListView::selectionChanged() signal. * * Drag-and-Drop is supported with the signal @ref #dropped(), just @ref #setAcceptDrops(true) * and connect it to a suitable slot. * To see where you are dropping, @ref setDropVisualizer(true). * And also you'll need @ref acceptDrag(QDropEvent*) * * KListView is drag-enabled, too: to benefit from that you've got derive from it. * Reimplement @ref dragObject() and (possibly) @ref startDrag(), * and @ref setDragEnabled(true). * * @version $Id$ */ class KListView : public QListView { Q_OBJECT + Q_PROPERTY( bool fullWidth READ fullWidth WRITE setFullWidth ) public: /** * Possible selection modes. * * The first four correspond directly to @ref QListView::SelectionMode, while * the Konqueror selection mode is defined as follows: * @li home: move to the first * @li end: move to the last * @li PgUp/PgDn: move one page up/down * @li up/down: move one item up/down * @li insert: toggle selection of current and move to the next * @li space: toggle selection of the current * @li CTRL+up: move to the previous item and toggle selection of this one * @li CTRL+down: toggle selection of the current item and move to the next * @li CTRL+end: toggle selection from (including) the current * item to (including) the last item * @li CTRL+home: toggle selection from (including) the current * item to the (including) the first item * @li CTRL+PgDn: toggle selection from (including) the current * item to (excluding) the item one page down * @li CTRL+PgUp: toggle selection from (excluding) the current * item to (including) the item one page up * * The combinations work the same with SHIFT instead of CTRL, except * that if you start selecting something using SHIFT everything selected * before will be deselected first. * * This way e.g. SHIFT+up/PgUp then SHIFT+down/PgDn leaves no item selected */ enum SelectionModeExt { Single = QListView::Single, Multi = QListView::Multi, Extended = QListView::Extended, NoSelection = QListView::NoSelection, Konqueror }; /** * Constructor. * * The parameters @p parent and @p name are handled by * @ref QListView, as usual. */ KListView (QWidget *parent = 0, const char *name = 0); /** * Destructor. */ virtual ~KListView(); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void setAcceptDrops (bool); /** * This function determines whether the given coordinates are within the * execute area. The execute area is the part of a @ref QListViewItem where mouse * clicks or double clicks respectively generate a @ref #executed() signal. * Depending on @ref QListView::allColumnsShowFocus() this is either the * whole item or only the first column. * @return true if point is inside execute area of an item, false in all * other cases including the case that it is over the viewport. */ virtual bool isExecuteArea( const QPoint& point ); /** * Same thing, but from an x coordinate only. This only checks if x is in * the first column (if all columns don't show focus), without testing if * the y coordinate is over an item or not. */ bool isExecuteArea( int x ); /** * @return a list containing the currently selected items. */ QPtrList selectedItems() const; /** * Arbitrarily move @p item to @p parent, positioned immediately after item @p after. */ void moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after); /** * @return the last item (not child!) of this listview. * * @see lastChild() */ QListViewItem *lastItem() const; /** * @return the last child of this listview. */ QListViewItem* lastChild () const; /** * @returns if it is legal to move items in the list view */ bool itemsMovable() const; /** * @return whether inplace-renaming has been enabled. * * @see #setItemsRenameable() */ bool itemsRenameable() const; /** * @return whether dragging is enabled. */ bool dragEnabled() const; /** * @return true if AutoOpen is enabled (not implemented currently). * * @see #setAutoOpen() */ bool autoOpen() const; /** * @return true if @p column is renamable. */ bool isRenameable (int column) const; /** * @return true if drawing of the drop-visualizer has been enabled. */ bool dropVisualizer() const; /** * @return the column for which tooltips are displayed (or -1 if none set). */ int tooltipColumn() const; /** * For future expansions. * * Do not use. * @deprecated */ bool createChildren() const; /** * @return true if drawing of the drop-highlighter has been enabled. */ bool dropHighlighter() const; /** * The dropVisualizerWidth defaults to 4. * * @return the current width of the drop-visualizer. */ int dropVisualizerWidth () const; /** * @return the "extended" selection mode of this listview. * * @see SelectionModeExt * @see setSelectionModeExt */ SelectionModeExt selectionModeExt () const; /** * Returns the index of @p item within the item tree or -1 if * @p item doesn't exist in this list view. This function takes * all items into account not only the visible ones. */ int itemIndex( const QListViewItem *item ) const; /** * Returns the item of @p index within the item tree or 0 if * @p index doesn't exist in this list view. This function takes * all items into account not only the visible ones. */ QListViewItem* itemAtIndex(int index); /** - * Let the column fit exactly all the available width. - * Single column listviews only. + * @deprecated */ void setFullWidth(); + /** + * Let the last column fit exactly all the available width. + */ + void setFullWidth(bool fullWidth); + /** + * Returns whether the last column is set to fit the available width. + */ + bool fullWidth() const; /** * sets the alternate background background color. * This only has an effect if the items are KListViewItems * * @param c the color to use for every other item. Set to an invalid * colour to disable alternate colours. */ void setAlternateBackground(const QColor &c); /** * @return the alternate background color */ const QColor &alternateBackground() const; /** * Saves the list view's layout (column widtsh, column order, sort column) * to a KConfig group * * @param config the @ref KConfig object to write to * @param group the config group to use */ void saveLayout(KConfig *config, const QString &group) const; /** * Reads the list view's layout from a KConfig group as stored with * @ref saveLayout * * @param config the @ref KConfig object to read from * @param group the config group to use */ void restoreLayout(KConfig *config, const QString &group); /** * Reimplemented to remember the current sort column and order */ virtual void setSorting(int column, bool ascending = true); signals: /** * This signal is emitted whenever the user executes an listview item. * That means depending on the KDE wide Single Click/Double Click * setting the user clicked or double clicked on that item. * @param item is the pointer to the executed listview item. * * Note that you may not delete any @ref QListViewItem objects in slots * connected to this signal. */ void executed( QListViewItem *item ); /** * This signal is emitted whenever the user executes an listview item. * That means depending on the KDE wide Single Click/Double Click * setting the user clicked or double clicked on that item. * @param item is the pointer to the executed listview item. * @param pos is the position where the user has clicked * @param c is the column into which the user clicked. * * Note that you may not delete any @ref QListViewItem objects in slots * connected to this signal. */ void executed( QListViewItem *item, const QPoint &pos, int c ); /** * This signal gets emitted whenever the user double clicks into the * listview. * @param item is the pointer to the clicked listview item. * @param pos is the position where the user has clicked, and * @param c is the column into which the user clicked. * * Note that you may not delete any @ref QListViewItem objects in slots * connected to this signal. * * This signal is more or less here for the sake of completeness. * You should normally not need to use this. In most cases itīs better * to use @ref #executed() instead. */ void doubleClicked( QListViewItem *item, const QPoint &pos, int c ); /** * This signal gets emitted whenever something acceptable is * dropped onto the listview. * * @param e is the drop event itself (it has already been accepted) * @param after is the item after which the drop occured (or 0L, if * the drop was above all items) * * @see #acceptDrop() */ void dropped (QDropEvent * e, QListViewItem *after); /** * This signal gets emitted whenever something acceptable is * dropped onto the listview. * * This is an overloaded version of the above (provided to simplify * processing drops outside of the class). * * @param list is the listview * @param e is the drop event itself (it has already been accepted) * @param after is the item after which the drop occured (or 0L, if * the drop was above all items */ void dropped (KListView* list, QDropEvent* e, QListViewItem* after); /** * This signal gets emitted whenever something acceptable is * dropped onto the listview. * * This function also provides a parent, in the event that your listview * is a tree * @param list is the listview * @param e is the drop event itself (it has already been accepted) * @param parent the item that is to be the parent of the new item * @param after is the item after which the drop occured (or 0L, if * the drop was above all items */ void dropped (KListView* list, QDropEvent* e, QListViewItem* parent, QListViewItem* after); /** * This signal gets emitted whenever something acceptable is * dropped onto the listview. * * This function also provides a parent, in the event that your listview * is a tree * @param e is the drop event itself (it has already been accepted) * @param parent the item that is to be the parent of the new item * @param after is the item after which the drop occured (or 0L, if * the drop was above all items */ void dropped (QDropEvent* e, QListViewItem* parent, QListViewItem* after); /** * This signal is emitted when ever the user moves an item in the list via * DnD. * If more than one item is moved at the same time, this signal is only emitted * once. */ void moved(); /** * Connect to this signal if you want to do some preprocessing before * a move is made, for example, to disable sorting * * This is sent only once per each groups of moves. That is, for each * drop that is a move this will be emitted once, before KListView calls * @ref moveItem() **/ void aboutToMove(); /** * This signal is emitted when ever the user moves an item in the list via * DnD. * If more than one item is moved at the same time, @p afterFirst and * @p afterNow will reflect what was true before the move. * This differs from @ref moved(), so be careful. All the items will have been * moved before @ref moved() is emitted, which is not true in this method. // FIXME * @param item the item that was moved * @param afterFirst the item that parameter item was in before the move, in the list * @param afterNow the item it's currently after. * **/ void moved (QListViewItem *item, QListViewItem *afterFirst, QListViewItem *afterNow); /** * This signal is emitted after all the items have been moved. It reports info for * each and every item moved, in order. The first element in @p items associates * with the first of afterFirst and afterNow. **/ void moved(QPtrList &items, QPtrList &afterFirst, QPtrList &afterNow); /** * This signal gets emitted when an item is renamed via in-place renaming. * * @param item is the renamed item. * @param str is the new value of column @p col. * @param col is the renamed column. */ void itemRenamed(QListViewItem* item, const QString &str, int col); /** * Same as above, but without the extra information. */ void itemRenamed(QListViewItem* item); /** * This signal is emitted when the shortcut key for popup-menus is pressed. * * Normally you should not use this, just connect a slot to signal * @ref contextMenu (KListView*, QListViewItem*, const QPoint&) to correctly * handle showing context menus regardless of settings. * * @param list is this listview. * @param item is the @ref currentItem() at the time the key was pressed. May be 0L. */ void menuShortCutPressed (KListView* list, QListViewItem* item); /** * This signal is emitted whenever a context-menu should be shown for item @p i. * It automatically adjusts for all settings involved (Menu key, showMenuOnPress/Click). * * @param l is this listview. * @param i is the item for which the menu should be shown. May be 0L. * @param p is the point at which the menu should be shown. */ void contextMenu (KListView* l, QListViewItem* i, const QPoint& p); public slots: /** * Rename column @p c of @p item. */ virtual void rename(QListViewItem *item, int c); /** * By default, if you called setItemsRenameable(true), * only the first column is renameable. * Use this function to enable the feature on other columns. * * If you want more intelligent (dynamic) selection, * you'll have to derive from KListView, * and override @ref rename() and call only call it * if you want the item to be renamed. **/ void setRenameable (int column, bool yesno=true); /** * Set whether items in the list view can be moved. * It is enabled by default. * * @see itemsMovable() */ virtual void setItemsMovable(bool b); /** * Enables inplace-renaming of items. * It is disabled by default. * * @see itemsRenameable() * @see setRenameable() */ virtual void setItemsRenameable(bool b); /** * Enable/Disable the dragging of items. * It is disabled by default. */ virtual void setDragEnabled(bool b); /** * Enable/Disable AutoOpen (not implemented currently). */ virtual void setAutoOpen(bool b); /** * Enable/Disable the drawing of a drop-visualizer * (a bar that shows where a dropped item would be inserted). * It is enabled by default, if dragging is enabled */ virtual void setDropVisualizer(bool b); /** * Set the width of the (default) drop-visualizer. * If you don't call this method, the width is set to 4. */ void setDropVisualizerWidth (int w); /** * Set which column should be used for automatic tooltips. * * @param column is the column for which tooltips will be shown. * Set -1 to disable this feature. */ virtual void setTooltipColumn(int column); /** * Enable/Disable the drawing of a drop-highlighter * (a rectangle around the item under the mouse cursor). * It is disabled by default. */ virtual void setDropHighlighter(bool b); /** * For future expansions. * * Do not use. * @deprecated */ virtual void setCreateChildren(bool b); /** * Set the selection mode. * * A different name was chosen to avoid API-clashes with @ref QListView::setSelectionMode(). */ void setSelectionModeExt (SelectionModeExt mode); protected: /** * Determine whether a drop on position @p p would count as * being above or below the QRect @p rect. * * @param rect is the rectangle we examine. * @param p is the point located in the rectangle, p is assumed to be in * viewport coordinates. */ inline bool below (const QRect& rect, const QPoint& p) { return (p.y() > (rect.top() + (rect.bottom() - rect.top())/2)); } /** * An overloaded version of below(const QRect&, const QPoint&). * * It differs from the above only in what arguments it takes. * * @param i the item whose rect() is passed to the above function. * @param p is translated from contents coordinates to viewport coordinates * before being passed to the above function. */ inline bool below (QListViewItem* i, const QPoint& p) { return below (itemRect(i), contentsToViewport(p)); } /** * Reimplemented to reload the alternate background in palette changes. * @internal */ virtual bool event( QEvent * ); /** * Emit signal @ref executed. * @internal */ void emitExecute( QListViewItem *item, const QPoint &pos, int c ); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void focusInEvent(QFocusEvent* fe); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void focusOutEvent( QFocusEvent *fe ); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void leaveEvent( QEvent *e ); /** * @return the tooltip for @p column of @p item. */ virtual QString tooltip(QListViewItem* item, int column) const; /** * @return whether the tooltip for @p column of @p item shall be shown at point @p pos. */ virtual bool showTooltip(QListViewItem *item, const QPoint &pos, int column) const; /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsDragMoveEvent (QDragMoveEvent *event); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsMousePressEvent( QMouseEvent *e ); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsMouseMoveEvent( QMouseEvent *e ); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsDragLeaveEvent (QDragLeaveEvent *event); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsMouseReleaseEvent (QMouseEvent*); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsDropEvent (QDropEvent*); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void contentsDragEnterEvent (QDragEnterEvent *); /** * @return a dragobject encoding the current selection. * * A common mistake is to forget the "const" in your reimplementation * @see setDragEnabled() */ virtual QDragObject *dragObject() const; /** * @return true if the @p event provides some acceptable * format. * A common mistake is to forget the "const" in your reimplementation */ virtual bool acceptDrag (QDropEvent* event) const; /** * Paint the drag line. If painter is null, don't try to :) * * If after == 0 then the marker should be drawn at the top. * * @return the rectangle that you painted to. */ virtual QRect drawDropVisualizer (QPainter *p, QListViewItem *parent, QListViewItem *after); /** * Paint the drag rectangle. If painter is null, don't try to :) * * * @return the rectangle that you painted to. */ virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item); /** * This method calls @ref dragObject() and starts the drag. * * Reimplement it to do fancy stuff like setting a pixmap or * using a non-default DragMode */ virtual void startDrag(); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void keyPressEvent (QKeyEvent*); /** * Reimplemented for internal reasons. * Further reimplementations should call this function or else * some features may not work correctly. * * The API is unaffected. */ virtual void viewportPaintEvent(QPaintEvent*); /** * Only called by konq_listviewwidget to select the current item * after listing. For more information look in konquerorKeyPressEvent(). */ void selectCurrentItemAndEnableSelectedBySimpleMoveMode(); /** * Reimplemented for setFullWidth() */ virtual void viewportResizeEvent(QResizeEvent* e); protected slots: /** * Update internal settings whenever the global ones change. * @internal */ void slotSettingsChanged(int); void slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c ); void doneEditing(QListViewItem *item, int row); /** * Repaint the rect where I was drawing the drop line. */ void cleanDropVisualizer(); /** * Repaint the rect where I was drawing the drop rectangle. */ void cleanItemHighlighter(); /** * Emit the @ref contextMenu signal. This slot is for mouse actions. */ void emitContextMenu (QListViewItem*, const QPoint&, int); /** * Emit the @ref contextMenu signal. This slot is for key presses. */ void emitContextMenu (KListView*, QListViewItem*); /** * Accessory slot for AutoSelect * @internal */ void slotOnItem( QListViewItem *item ); /** * Accessory slot for AutoSelect/ChangeCursorOverItem * @internal */ void slotOnViewport(); /** * Process AutoSelection. * @internal */ void slotAutoSelect(); + /** + * Reacts to header changes in full width mode + * @internal + */ + void slotHeaderChanged(); + protected: /** * Handle dropEvent when itemsMovable() is set to true. */ virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme); /** * Where is the nearest QListViewItem that I'm going to drop? */ virtual void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after); /** * A special keyPressEvent (for Konqueror-style selection). */ void konquerorKeyPressEvent (QKeyEvent*); /** * Convert the depth of an item into its indentation in pixels */ int depthToPixels( int depth ); private: class KListViewPrivate; class Tooltip; KListViewPrivate *d; }; /** * A listview item with support for alternate background colours. It is * a drop-in replacement for @ref QListViewItem * * @short listview item with alternate background colour support */ class KListViewItem : public QListViewItem { public: /** * constructors. The semantics remain as in @ref QListViewItem. * Although they accept a @ref QListViewItem as parent, please * don't mix KListViewItem (or subclasses) with QListViewItem * (or subclasses). */ KListViewItem(QListView *parent); KListViewItem(QListViewItem *parent); KListViewItem(QListView *parent, QListViewItem *after); KListViewItem(QListViewItem *parent, QListViewItem *after); KListViewItem(QListView *parent, QString, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null); KListViewItem(QListViewItem *parent, QString, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null); KListViewItem(QListView *parent, QListViewItem *after, QString, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null); KListViewItem(QListViewItem *parent, QListViewItem *after, QString, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null, QString = QString::null); virtual ~KListViewItem(); /** * returns the background colour for this item */ const QColor &backgroundColor(); virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); private: void init(); private: struct KListViewItemPrivate; KListViewItemPrivate *d; }; #endif // vim: ts=2 sw=2 et