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.
23 #include <QHeaderView>
24 #include <QMouseEvent>
25 #include "QY2ListView.h"
28 QY2ListView::QY2ListView( QWidget * parent )
29 : QTreeWidget( parent )
30 , _mousePressedItem(0)
31 , _mousePressedCol( -1 )
32 , _mousePressedButton( Qt::NoButton )
33 , _sortByInsertionSequence( false )
35 , _mouseButton1PressedInHeader( false )
36 , _finalSizeChangeExpected( false )
38 //FIXME QTreeWidget::setShowToolTips( false );
39 setRootIsDecorated(false);
42 _toolTip = new QY2ListViewToolTip( this );
46 header()->installEventFilter( this );
49 connect( this, SIGNAL( columnResized ( int, int, int ) ),
50 this, SLOT ( columnWidthChanged( int, int, int ) ) );
55 QY2ListView::~QY2ListView()
65 QY2ListView::selectSomething()
67 QTreeWidgetItemIterator it( this );
71 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
73 if ( item && (item->flags() & Qt::ItemIsSelectable) )
75 item->setSelected(true); // emits signal, too
88 restoreColumnWidths();
93 QY2ListView::updateItemStates()
95 QTreeWidgetItemIterator it( this );
99 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
102 item->updateStatus();
110 QY2ListView::updateItemData()
112 QTreeWidgetItemIterator it( this );
116 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
127 QY2ListView::toolTip( QTreeWidgetItem * listViewItem, int column )
129 if ( ! listViewItem )
130 return QString::null;
135 text.sprintf( "Column %d:\n%s", column, (const char *) listViewItem->text( column ) );
138 // Try known item classes
140 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (listViewItem);
143 return item->toolTip( column );
145 QY2CheckListItem * checkListItem = dynamic_cast<QY2CheckListItem *> (listViewItem);
148 return checkListItem->toolTip( column );
150 return QString::null;
155 QY2ListView::saveColumnWidths()
157 _savedColumnWidth.clear();
158 _savedColumnWidth.reserve( columnCount() );
160 for ( int i = 0; i < columnCount(); i++ )
162 _savedColumnWidth.push_back( columnWidth(i) );
168 QY2ListView::restoreColumnWidths()
170 if ( _savedColumnWidth.size() != (unsigned) columnCount() ) // never manually resized
172 for ( int i = 0; i < columnCount(); i++ ) // use optimized column width
173 resizeColumnToContents(i);
175 else // stored settings after manual resizing
177 for ( int i = 0; i < columnCount(); i++ )
179 setColumnWidth( i, _savedColumnWidth[ i ] ); // restore saved column width
186 QY2ListView::contentsMousePressEvent( QMouseEvent * ev )
188 //FIXME may be convert to global
189 QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
191 if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
193 _mousePressedItem = item;
194 //FIXME _mousePressedCol = header()->sectionAt( ev->pos().x() );
195 _mousePressedButton = ev->button();
197 else // invalidate last click data
199 _mousePressedItem = 0;
200 _mousePressedCol = -1;
201 _mousePressedButton = -1;
204 // Call base class method
205 //FIXME QTreeWidget::contentsMousePressEvent( ev );
210 QY2ListView::contentsMouseReleaseEvent( QMouseEvent * ev )
212 QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
214 if ( item && ( item->flags() & Qt::ItemIsEnabled ) && item == _mousePressedItem )
217 // int col = header()->sectionAt( ev->pos().x() );
219 // if ( item == _mousePressedItem &&
220 // col == _mousePressedCol &&
221 // ev->button() == _mousePressedButton )
223 // emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
228 // invalidate last click data
230 _mousePressedItem = 0;
231 _mousePressedCol = -1;
232 _mousePressedButton = Qt::NoButton;
234 // Call base class method
235 //FIXME QTreeWidget::contentsMouseReleaseEvent( ev );
240 QY2ListView::contentsMouseDoubleClickEvent( QMouseEvent * ev )
242 QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
244 if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
246 int col = header()->logicalIndexAt( ev->pos().x() );
247 emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
250 // invalidate last click data
252 _mousePressedItem = 0;
253 _mousePressedCol = -1;
254 _mousePressedButton = Qt::NoButton;
256 // // Call base class method
257 // QTreeWidget::contentsMouseDoubleClickEvent( ev );
262 QY2ListView::columnWidthChanged( int, int, int )
264 // Workaround for Qt bug:
266 // QHeader sends a sizeChange() signal for every size change, not only (as
267 // documented) when the user resizes a header column manually. But we only
268 // want to record the column widths if the user explicitly did that, so
269 // ignore those signals if the mouse isn't pressed. There is also one final
270 // sizeChange() signal immediately after the user releases the mouse button.
272 if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
276 // Consume that one sizeChange() signal that is sent immediately after
277 // the mouse button is released, but make sure to reset that flag only
280 if ( ! _mouseButton1PressedInHeader )
281 _finalSizeChangeExpected = false;
287 QY2ListView::eventFilter( QObject * obj, QEvent * event )
289 if ( event && obj && obj == header() )
291 if ( event->type() == QEvent::MouseButtonPress )
293 QMouseEvent * mouseEvent = (QMouseEvent *) event;
295 if ( mouseEvent->button() == 1 )
297 _mouseButton1PressedInHeader = true;
298 _finalSizeChangeExpected = false;
301 else if ( event->type() == QEvent::MouseButtonRelease )
303 QMouseEvent * mouseEvent = (QMouseEvent *) event;
305 if ( mouseEvent->button() == 1 )
307 _finalSizeChangeExpected = true;
308 _mouseButton1PressedInHeader = false;
313 return QTreeWidget::eventFilter( obj, event );
318 QY2ListView::minimumSizeHint() const
320 return QSize( 0, 0 );
325 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
327 _sortByInsertionSequence = sortByInsertionSequence;
336 QY2ListViewItem::QY2ListViewItem( QY2ListView * parentListView,
337 const QString & text )
338 : QTreeWidgetItem( parentListView, QStringList(text), 1)
340 _serial = parentListView->nextSerial();
344 QY2ListViewItem::QY2ListViewItem( QTreeWidgetItem * parentItem,
345 const QString & text )
346 : QTreeWidgetItem( parentItem, QStringList(text), 1 )
350 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
352 if ( parentListView )
353 _serial = parentListView->nextSerial();
357 QY2ListViewItem::~QY2ListViewItem()
364 * Comparison function used for sorting the list.
371 QY2ListViewItem::compare( QTreeWidgetItem * otherListViewItem,
373 bool ascending ) const
375 bool sortByInsertionSequence = false;
376 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (treeWidget());
378 if ( parentListView )
379 sortByInsertionSequence = parentListView->sortByInsertionSequence();
381 if ( sortByInsertionSequence )
383 QY2ListViewItem * other = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
387 if ( this->serial() < other->serial() ) return -1;
388 if ( this->serial() > other->serial() ) return 1;
392 // Still here? Try the other version: QY2CheckListItem.
394 QY2CheckListItem * otherCheckListItem = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
396 if ( otherCheckListItem )
398 if ( this->serial() < otherCheckListItem->serial() ) return -1;
399 if ( this->serial() > otherCheckListItem->serial() ) return 1;
405 //return QTreeWidgetItem::compare( otherListViewItem, col, ascending );
411 // QY2ListViewItem::paintCell( QPainter * painter,
412 // const QColorGroup & colorGroup,
417 // QColorGroup cg = colorGroup;
419 // if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
420 // if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
422 // QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
430 QY2CheckListItem::QY2CheckListItem( QY2ListView * parentListView,
431 const QString & text )
432 : QTreeWidgetItem( parentListView, QStringList(text))
434 setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
435 setCheckState(0, Qt::Unchecked);
436 _serial = parentListView->nextSerial();
440 QY2CheckListItem::QY2CheckListItem( QTreeWidgetItem * parentItem,
441 const QString & text )
442 : QTreeWidgetItem( parentItem, QStringList(text))
445 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
447 if ( parentListView )
448 _serial = parentListView->nextSerial();
451 QY2CheckListItem::~QY2CheckListItem()
458 * Comparison function used for sorting the list.
465 QY2CheckListItem::compare( QTreeWidgetItem * otherListViewItem,
467 bool ascending ) const
469 bool sortByInsertionSequence = false;
470 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (treeWidget());
472 if ( parentListView )
473 sortByInsertionSequence = parentListView->sortByInsertionSequence();
475 if ( sortByInsertionSequence )
477 QY2CheckListItem * other = dynamic_cast<QY2CheckListItem *> (otherListViewItem);
481 if ( this->serial() < other->serial() ) return -1;
482 if ( this->serial() > other->serial() ) return 1;
487 // Still here? Try the other version: QY2ListViewItem.
489 QY2ListViewItem * otherCheckListItem = dynamic_cast<QY2ListViewItem *> (otherListViewItem);
491 if ( otherCheckListItem )
493 if ( this->serial() < otherCheckListItem->serial() ) return -1;
494 if ( this->serial() > otherCheckListItem->serial() ) return 1;
500 //FIXME return QTreeWidgetItem::compare( otherListViewItem, col, ascending );
506 QY2CheckListItem::paintCell( QPainter * painter,
507 const QColorGroup & colorGroup,
512 QColorGroup cg = colorGroup;
514 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
515 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
517 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
523 QY2ListViewToolTip::maybeTip( const QPoint & pos )
525 Q3Header * header = _listView->header();
526 QTreeWidgetItem * item = _listView->itemAt( pos );
531 int x = _listView->viewportToContents( pos ).x();
532 int column = header->sectionAt(x);
537 indent = item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
538 indent *= _listView->treeStepSize();
540 if ( pos.x() < indent )
544 QString text = _listView->toolTip( item, column );
546 if ( ! text.isEmpty() )
548 QRect rect( _listView->itemRect( item ) );
553 rect.setWidth( indent );
557 QPoint topLeft( header->sectionPos( column ), 0 );
558 topLeft = _listView->contentsToViewport( topLeft );
559 rect.setX( topLeft.x() );
560 rect.setWidth( header->sectionSize( column ) );
570 #include "QY2ListView.moc"