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.
24 #include <QMouseEvent>
25 #include "QY2ListView.h"
28 QY2ListView::QY2ListView( QWidget * parent )
29 : Q3ListView( parent )
30 , _mousePressedItem(0)
31 , _mousePressedCol( -1 )
32 , _mousePressedButton( Qt::NoButton )
33 , _sortByInsertionSequence( false )
35 , _mouseButton1PressedInHeader( false )
36 , _finalSizeChangeExpected( false )
38 Q3ListView::setShowToolTips( false );
41 _toolTip = new QY2ListViewToolTip( this );
45 header()->installEventFilter( this );
47 connect( header(), SIGNAL( sizeChange ( int, int, int ) ),
48 this, SLOT ( columnWidthChanged( int, int, int ) ) );
52 QY2ListView::~QY2ListView()
62 QY2ListView::selectSomething()
64 Q3ListViewItemIterator it( this );
68 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
70 if ( item && item->isSelectable() )
72 setSelected( item, true ); // emits signal, too
85 restoreColumnWidths();
90 QY2ListView::updateItemStates()
92 Q3ListViewItemIterator it( this );
96 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
107 QY2ListView::updateItemData()
109 Q3ListViewItemIterator it( this );
113 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
124 QY2ListView::toolTip( Q3ListViewItem * listViewItem, int column )
126 if ( ! listViewItem )
127 return QString::null;
132 text.sprintf( "Column %d:\n%s", column, (const char *) listViewItem->text( column ) );
135 // Try known item classes
137 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (listViewItem);
140 return item->toolTip( column );
142 QY2CheckListItem * checkListItem = dynamic_cast<QY2CheckListItem *> (listViewItem);
145 return checkListItem->toolTip( column );
147 return QString::null;
152 QY2ListView::saveColumnWidths()
154 _savedColumnWidth.clear();
155 _savedColumnWidth.reserve( columns() );
157 for ( int i = 0; i < columns(); i++ )
159 _savedColumnWidth.push_back( columnWidth(i) );
165 QY2ListView::restoreColumnWidths()
167 if ( _savedColumnWidth.size() != (unsigned) columns() ) // never manually resized
169 for ( int i = 0; i < columns(); i++ ) // use optimized column width
172 else // stored settings after manual resizing
174 for ( int i = 0; i < columns(); i++ )
176 setColumnWidth( i, _savedColumnWidth[ i ] ); // restore saved column width
183 QY2ListView::contentsMousePressEvent( QMouseEvent * ev )
185 Q3ListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
187 if ( item && item->isEnabled() )
189 _mousePressedItem = item;
190 _mousePressedCol = header()->sectionAt( ev->pos().x() );
191 _mousePressedButton = ev->button();
193 else // invalidate last click data
195 _mousePressedItem = 0;
196 _mousePressedCol = -1;
197 _mousePressedButton = -1;
200 // Call base class method
201 Q3ListView::contentsMousePressEvent( ev );
206 QY2ListView::contentsMouseReleaseEvent( QMouseEvent * ev )
208 Q3ListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
210 if ( item && item->isEnabled() && item == _mousePressedItem )
212 int col = header()->sectionAt( ev->pos().x() );
214 if ( item == _mousePressedItem &&
215 col == _mousePressedCol &&
216 ev->button() == _mousePressedButton )
218 emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
223 // invalidate last click data
225 _mousePressedItem = 0;
226 _mousePressedCol = -1;
227 _mousePressedButton = Qt::NoButton;
229 // Call base class method
230 Q3ListView::contentsMouseReleaseEvent( ev );
235 QY2ListView::contentsMouseDoubleClickEvent( QMouseEvent * ev )
237 Q3ListViewItem * item = itemAt( contentsToViewport( ev->pos() ) );
239 if ( item && item->isEnabled() )
241 int col = header()->sectionAt( ev->pos().x() );
242 emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
245 // invalidate last click data
247 _mousePressedItem = 0;
248 _mousePressedCol = -1;
249 _mousePressedButton = Qt::NoButton;
251 // Call base class method
252 Q3ListView::contentsMouseDoubleClickEvent( ev );
257 QY2ListView::columnWidthChanged( int, int, int )
259 // Workaround for Qt bug:
261 // QHeader sends a sizeChange() signal for every size change, not only (as
262 // documented) when the user resizes a header column manually. But we only
263 // want to record the column widths if the user explicitly did that, so
264 // ignore those signals if the mouse isn't pressed. There is also one final
265 // sizeChange() signal immediately after the user releases the mouse button.
267 if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
271 // Consume that one sizeChange() signal that is sent immediately after
272 // the mouse button is released, but make sure to reset that flag only
275 if ( ! _mouseButton1PressedInHeader )
276 _finalSizeChangeExpected = false;
282 QY2ListView::eventFilter( QObject * obj, QEvent * event )
284 if ( event && obj && obj == header() )
286 if ( event->type() == QEvent::MouseButtonPress )
288 QMouseEvent * mouseEvent = (QMouseEvent *) event;
290 if ( mouseEvent->button() == 1 )
292 _mouseButton1PressedInHeader = true;
293 _finalSizeChangeExpected = false;
296 else if ( event->type() == QEvent::MouseButtonRelease )
298 QMouseEvent * mouseEvent = (QMouseEvent *) event;
300 if ( mouseEvent->button() == 1 )
302 _finalSizeChangeExpected = true;
303 _mouseButton1PressedInHeader = false;
308 return Q3ListView::eventFilter( obj, event );
313 QY2ListView::minimumSizeHint() const
315 return QSize( 0, 0 );
320 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
322 _sortByInsertionSequence = sortByInsertionSequence;
331 QY2ListViewItem::QY2ListViewItem( QY2ListView * parentListView,
332 const QString & text )
333 : Q3ListViewItem( parentListView, text )
335 _serial = parentListView->nextSerial();
339 QY2ListViewItem::QY2ListViewItem( Q3ListViewItem * parentItem,
340 const QString & text )
341 : Q3ListViewItem( parentItem, text )
345 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
347 if ( parentListView )
348 _serial = parentListView->nextSerial();
352 QY2ListViewItem::~QY2ListViewItem()
359 * Comparison function used for sorting the list.
366 QY2ListViewItem::compare( Q3ListViewItem * otherListViewItem,
368 bool ascending ) const
370 bool sortByInsertionSequence = false;
371 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (listView());
373 if ( parentListView )
374 sortByInsertionSequence = parentListView->sortByInsertionSequence();
376 if ( sortByInsertionSequence )
378 QY2ListViewItem * other = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
382 if ( this->serial() < other->serial() ) return -1;
383 if ( this->serial() > other->serial() ) return 1;
387 // Still here? Try the other version: QY2CheckListItem.
389 QY2CheckListItem * otherCheckListItem = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
391 if ( otherCheckListItem )
393 if ( this->serial() < otherCheckListItem->serial() ) return -1;
394 if ( this->serial() > otherCheckListItem->serial() ) return 1;
400 return Q3ListViewItem::compare( otherListViewItem, col, ascending );
405 QY2ListViewItem::paintCell( QPainter * painter,
406 const QColorGroup & colorGroup,
411 QColorGroup cg = colorGroup;
413 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
414 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
416 Q3ListViewItem::paintCell( painter, cg, column, width, alignment );
424 QY2CheckListItem::QY2CheckListItem( QY2ListView * parentListView,
425 const QString & text,
426 Q3CheckListItem::Type type )
427 : Q3CheckListItem( parentListView, text, type )
429 _serial = parentListView->nextSerial();
433 QY2CheckListItem::QY2CheckListItem( Q3ListViewItem * parentItem,
434 const QString & text,
435 Q3CheckListItem::Type type )
436 : Q3CheckListItem( parentItem, text, type )
439 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
441 if ( parentListView )
442 _serial = parentListView->nextSerial();
446 QY2CheckListItem::QY2CheckListItem( Q3CheckListItem * parentItem,
447 const QString & text,
448 Q3CheckListItem::Type type )
449 : Q3CheckListItem( parentItem, text, type )
452 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( listView() );
454 if ( parentListView )
455 _serial = parentListView->nextSerial();
459 QY2CheckListItem::~QY2CheckListItem()
466 * Comparison function used for sorting the list.
473 QY2CheckListItem::compare( Q3ListViewItem * otherListViewItem,
475 bool ascending ) const
477 bool sortByInsertionSequence = false;
478 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (listView());
480 if ( parentListView )
481 sortByInsertionSequence = parentListView->sortByInsertionSequence();
483 if ( sortByInsertionSequence )
485 QY2CheckListItem * other = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
489 if ( this->serial() < other->serial() ) return -1;
490 if ( this->serial() > other->serial() ) return 1;
495 // Still here? Try the other version: QY2ListViewItem.
497 QY2ListViewItem * otherCheckListItem = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
499 if ( otherCheckListItem )
501 if ( this->serial() < otherCheckListItem->serial() ) return -1;
502 if ( this->serial() > otherCheckListItem->serial() ) return 1;
508 return Q3ListViewItem::compare( otherListViewItem, col, ascending );
513 QY2CheckListItem::paintCell( QPainter * painter,
514 const QColorGroup & colorGroup,
519 QColorGroup cg = colorGroup;
521 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
522 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
524 Q3CheckListItem::paintCell( painter, cg, column, width, alignment );
530 QY2ListViewToolTip::maybeTip( const QPoint & pos )
532 Q3Header * header = _listView->header();
533 Q3ListViewItem * item = _listView->itemAt( pos );
538 int x = _listView->viewportToContents( pos ).x();
539 int column = header->sectionAt(x);
544 indent = item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
545 indent *= _listView->treeStepSize();
547 if ( pos.x() < indent )
551 QString text = _listView->toolTip( item, column );
553 if ( ! text.isEmpty() )
555 QRect rect( _listView->itemRect( item ) );
560 rect.setWidth( indent );
564 QPoint topLeft( header->sectionPos( column ), 0 );
565 topLeft = _listView->contentsToViewport( topLeft );
566 rect.setX( topLeft.x() );
567 rect.setWidth( header->sectionSize( column ) );
577 #include "QY2ListView.moc"