1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
15 Author: Stefan Hundhammer <sh@suse.de>
17 This is a pure Qt widget - it can be used independently of YaST2.
25 #include "QY2ListView.h"
28 QY2ListView::QY2ListView( QWidget * parent )
30 , _mousePressedItem(0)
31 , _mousePressedCol( -1 )
32 , _mousePressedButton( NoButton )
33 , _sortByInsertionSequence( false )
35 , _mouseButton1PressedInHeader( false )
36 , _finalSizeChangeExpected( false )
38 QListView::setShowToolTips( false );
39 _toolTip = new QY2ListViewToolTip( this );
42 header()->installEventFilter( this );
44 connect( header(), SIGNAL( sizeChange ( int, int, int ) ),
45 this, SLOT ( columnWidthChanged( int, int, int ) ) );
49 QY2ListView::~QY2ListView()
57 QY2ListView::selectSomething()
59 QListViewItemIterator it( this );
63 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
65 if ( item && item->isSelectable() )
67 setSelected( item, true ); // emits signal, too
80 restoreColumnWidths();
85 QY2ListView::updateItemStates()
87 QListViewItemIterator it( this );
91 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
102 QY2ListView::updateItemData()
104 QListViewItemIterator it( this );
108 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
119 QY2ListView::toolTip( QListViewItem * listViewItem, int column )
121 if ( ! listViewItem )
122 return QString::null;
127 text.sprintf( "Column %d:\n%s", column, (const char *) listViewItem->text( column ) );
130 // Try known item classes
132 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (listViewItem);
135 return item->toolTip( column );
137 QY2CheckListItem * checkListItem = dynamic_cast<QY2CheckListItem *> (listViewItem);
140 return checkListItem->toolTip( column );
142 return QString::null;
147 QY2ListView::saveColumnWidths()
149 _savedColumnWidth.clear();
150 _savedColumnWidth.reserve( columns() );
152 for ( int i = 0; i < columns(); i++ )
154 _savedColumnWidth.push_back( columnWidth(i) );
160 QY2ListView::restoreColumnWidths()
162 if ( _savedColumnWidth.size() != (unsigned) columns() ) // never manually resized
164 for ( int i = 0; i < columns(); i++ ) // use optimized column width
167 else // stored settings after manual resizing
169 for ( int i = 0; i < columns(); i++ )
171 setColumnWidth( i, _savedColumnWidth[ i ] ); // restore saved column width
178 QY2ListView::contentsMousePressEvent( QMouseEvent * ev )
180 QListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
182 if ( item && item->isEnabled() )
184 _mousePressedItem = item;
185 _mousePressedCol = header()->sectionAt( ev->pos().x() );
186 _mousePressedButton = ev->button();
188 else // invalidate last click data
190 _mousePressedItem = 0;
191 _mousePressedCol = -1;
192 _mousePressedButton = -1;
195 // Call base class method
196 QListView::contentsMousePressEvent( ev );
201 QY2ListView::contentsMouseReleaseEvent( QMouseEvent * ev )
203 QListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
205 if ( item && item->isEnabled() && item == _mousePressedItem )
207 int col = header()->sectionAt( ev->pos().x() );
209 if ( item == _mousePressedItem &&
210 col == _mousePressedCol &&
211 ev->button() == _mousePressedButton )
213 emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
218 // invalidate last click data
220 _mousePressedItem = 0;
221 _mousePressedCol = -1;
222 _mousePressedButton = NoButton;
224 // Call base class method
225 QListView::contentsMouseReleaseEvent( ev );
230 QY2ListView::contentsMouseDoubleClickEvent( QMouseEvent * ev )
232 QListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
234 if ( item && item->isEnabled() )
236 int col = header()->sectionAt( ev->pos().x() );
237 emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
240 // invalidate last click data
242 _mousePressedItem = 0;
243 _mousePressedCol = -1;
244 _mousePressedButton = NoButton;
246 // Call base class method
247 QListView::contentsMouseDoubleClickEvent( ev );
252 QY2ListView::columnWidthChanged( int, int, int )
254 // Workaround for Qt bug:
256 // QHeader sends a sizeChange() signal for every size change, not only (as
257 // documented) when the user resizes a header column manually. But we only
258 // want to record the column widths if the user explicitly did that, so
259 // ignore those signals if the mouse isn't pressed. There is also one final
260 // sizeChange() signal immediately after the user releases the mouse button.
262 if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
266 // Consume that one sizeChange() signal that is sent immediately after
267 // the mouse button is released, but make sure to reset that flag only
270 if ( ! _mouseButton1PressedInHeader )
271 _finalSizeChangeExpected = false;
277 QY2ListView::eventFilter( QObject * obj, QEvent * event )
279 if ( event && obj && obj == header() )
281 if ( event->type() == QEvent::MouseButtonPress )
283 QMouseEvent * mouseEvent = (QMouseEvent *) event;
285 if ( mouseEvent->button() == 1 )
287 _mouseButton1PressedInHeader = true;
288 _finalSizeChangeExpected = false;
291 else if ( event->type() == QEvent::MouseButtonRelease )
293 QMouseEvent * mouseEvent = (QMouseEvent *) event;
295 if ( mouseEvent->button() == 1 )
297 _finalSizeChangeExpected = true;
298 _mouseButton1PressedInHeader = false;
303 return QListView::eventFilter( obj, event );
308 QY2ListView::minimumSizeHint() const
310 return QSize( 0, 0 );
315 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
317 _sortByInsertionSequence = sortByInsertionSequence;
326 QY2ListViewItem::QY2ListViewItem( QY2ListView * parentListView,
327 const QString & text )
328 : QListViewItem( parentListView, text )
330 _serial = parentListView->nextSerial();
334 QY2ListViewItem::QY2ListViewItem( QListViewItem * parentItem,
335 const QString & text )
336 : QListViewItem( parentItem, text )
340 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
342 if ( parentListView )
343 _serial = parentListView->nextSerial();
347 QY2ListViewItem::~QY2ListViewItem()
354 * Comparison function used for sorting the list.
361 QY2ListViewItem::compare( QListViewItem * otherListViewItem,
363 bool ascending ) const
365 bool sortByInsertionSequence = false;
366 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (listView());
368 if ( parentListView )
369 sortByInsertionSequence = parentListView->sortByInsertionSequence();
371 if ( sortByInsertionSequence )
373 QY2ListViewItem * other = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
377 if ( this->serial() < other->serial() ) return -1;
378 if ( this->serial() > other->serial() ) return 1;
382 // Still here? Try the other version: QY2CheckListItem.
384 QY2CheckListItem * otherCheckListItem = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
386 if ( otherCheckListItem )
388 if ( this->serial() < otherCheckListItem->serial() ) return -1;
389 if ( this->serial() > otherCheckListItem->serial() ) return 1;
395 return QListViewItem::compare( otherListViewItem, col, ascending );
400 QY2ListViewItem::paintCell( QPainter * painter,
401 const QColorGroup & colorGroup,
406 QColorGroup cg = colorGroup;
408 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
409 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
411 QListViewItem::paintCell( painter, cg, column, width, alignment );
419 QY2CheckListItem::QY2CheckListItem( QY2ListView * parentListView,
420 const QString & text,
421 QCheckListItem::Type type )
422 : QCheckListItem( parentListView, text, type )
424 _serial = parentListView->nextSerial();
428 QY2CheckListItem::QY2CheckListItem( QListViewItem * parentItem,
429 const QString & text,
430 QCheckListItem::Type type )
431 : QCheckListItem( parentItem, text, type )
434 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
436 if ( parentListView )
437 _serial = parentListView->nextSerial();
441 QY2CheckListItem::QY2CheckListItem( QCheckListItem * parentItem,
442 const QString & text,
443 QCheckListItem::Type type )
444 : QCheckListItem( parentItem, text, type )
447 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
449 if ( parentListView )
450 _serial = parentListView->nextSerial();
454 QY2CheckListItem::~QY2CheckListItem()
461 * Comparison function used for sorting the list.
468 QY2CheckListItem::compare( QListViewItem * otherListViewItem,
470 bool ascending ) const
472 bool sortByInsertionSequence = false;
473 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (listView());
475 if ( parentListView )
476 sortByInsertionSequence = parentListView->sortByInsertionSequence();
478 if ( sortByInsertionSequence )
480 QY2CheckListItem * other = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
484 if ( this->serial() < other->serial() ) return -1;
485 if ( this->serial() > other->serial() ) return 1;
490 // Still here? Try the other version: QY2ListViewItem.
492 QY2ListViewItem * otherCheckListItem = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
494 if ( otherCheckListItem )
496 if ( this->serial() < otherCheckListItem->serial() ) return -1;
497 if ( this->serial() > otherCheckListItem->serial() ) return 1;
503 return QListViewItem::compare( otherListViewItem, col, ascending );
508 QY2CheckListItem::paintCell( QPainter * painter,
509 const QColorGroup & colorGroup,
514 QColorGroup cg = colorGroup;
516 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
517 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
519 QCheckListItem::paintCell( painter, cg, column, width, alignment );
524 QY2ListViewToolTip::maybeTip( const QPoint & pos )
526 QHeader * header = _listView->header();
527 QListViewItem * item = _listView->itemAt( pos );
532 int x = _listView->viewportToContents( pos ).x();
533 int column = header->sectionAt(x);
538 indent = item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
539 indent *= _listView->treeStepSize();
541 if ( pos.x() < indent )
545 QString text = _listView->toolTip( item, column );
547 if ( ! text.isEmpty() )
549 QRect rect( _listView->itemRect( item ) );
554 rect.setWidth( indent );
558 QPoint topLeft( header->sectionPos( column ), 0 );
559 topLeft = _listView->contentsToViewport( topLeft );
560 rect.setX( topLeft.x() );
561 rect.setWidth( header->sectionSize( column ) );
569 #include "QY2ListView.moc"