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"
27 #define y2log_component "qt-pkg"
28 #include <ycp/y2log.h>
30 QY2ListView::QY2ListView( QWidget * parent )
31 : QTreeWidget( parent )
32 , _mousePressedItem(0)
33 , _mousePressedCol( -1 )
34 , _mousePressedButton( Qt::NoButton )
35 , _sortByInsertionSequence( false )
37 , _mouseButton1PressedInHeader( false )
38 , _finalSizeChangeExpected( false )
40 //FIXME QTreeWidget::setShowToolTips( false );
41 setRootIsDecorated(false);
44 _toolTip = new QY2ListViewToolTip( this );
48 header()->installEventFilter( this );
51 connect( this, SIGNAL( columnResized ( int, int, int ) ),
52 this, SLOT ( columnWidthChanged( int, int, int ) ) );
57 QY2ListView::~QY2ListView()
67 QY2ListView::selectSomething()
69 QTreeWidgetItemIterator it( this );
73 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
75 if ( item && (item->flags() & Qt::ItemIsSelectable) )
77 item->setSelected(true); // emits signal, too
90 restoreColumnWidths();
95 QY2ListView::updateItemStates()
97 QTreeWidgetItemIterator it( this );
101 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
104 item->updateStatus();
112 QY2ListView::updateItemData()
114 QTreeWidgetItemIterator it( this );
118 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
129 QY2ListView::toolTip( QTreeWidgetItem * listViewItem, int column )
131 if ( ! listViewItem )
132 return QString::null;
137 text.sprintf( "Column %d:\n%s", column, (const char *) listViewItem->text( column ) );
140 // Try known item classes
142 QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (listViewItem);
145 return item->toolTip( column );
147 QY2CheckListItem * checkListItem = dynamic_cast<QY2CheckListItem *> (listViewItem);
150 return checkListItem->toolTip( column );
152 return QString::null;
157 QY2ListView::saveColumnWidths()
159 _savedColumnWidth.clear();
160 _savedColumnWidth.reserve( columnCount() );
162 for ( int i = 0; i < columnCount(); i++ )
164 _savedColumnWidth.push_back( columnWidth(i) );
170 QY2ListView::restoreColumnWidths()
172 if ( _savedColumnWidth.size() != (unsigned) columnCount() ) // never manually resized
174 for ( int i = 0; i < columnCount(); i++ ) // use optimized column width
175 resizeColumnToContents(i);
177 else // stored settings after manual resizing
179 for ( int i = 0; i < columnCount(); i++ )
181 setColumnWidth( i, _savedColumnWidth[ i ] ); // restore saved column width
188 QY2ListView::mousePressEvent( QMouseEvent * ev )
190 //y2internal("POS is %d %d", ev->pos().x(), ev->pos().y() );
191 QTreeWidgetItem * item = itemAt( ev->pos() );
194 if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
196 _mousePressedItem = item;
197 _mousePressedCol = header()->logicalIndexAt( ev->pos().x() );
198 _mousePressedButton = ev->button();
200 else // invalidate last click data
202 _mousePressedItem = 0;
203 _mousePressedCol = -1;
204 _mousePressedButton = -1;
207 // Call base class method
208 QTreeWidget::mousePressEvent( ev );
213 QY2ListView::mouseReleaseEvent( QMouseEvent * ev )
215 //y2internal("REPOS is %d %d", ev->pos().x(), ev->pos().y() );
216 QTreeWidgetItem * item = itemAt( ev->pos() );
218 if ( item && ( item->flags() & Qt::ItemIsEnabled ) && item == _mousePressedItem )
220 int col = header()->logicalIndexAt( ev->pos().x() );
221 //y2internal("COL %d", col);
222 if ( item == _mousePressedItem &&
223 col == _mousePressedCol &&
224 ev->button() == _mousePressedButton )
226 emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
231 // invalidate last click data
233 _mousePressedItem = 0;
234 _mousePressedCol = -1;
235 _mousePressedButton = Qt::NoButton;
237 // Call base class method
238 QTreeWidget::mouseReleaseEvent( ev );
243 QY2ListView::mouseDoubleClickEvent( QMouseEvent * ev )
245 QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
247 if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
249 int col = header()->logicalIndexAt( ev->pos().x() );
250 emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
253 // invalidate last click data
255 _mousePressedItem = 0;
256 _mousePressedCol = -1;
257 _mousePressedButton = Qt::NoButton;
259 // Call base class method
260 QTreeWidget::mouseDoubleClickEvent( ev );
265 QY2ListView::columnWidthChanged( int, int, int )
267 // Workaround for Qt bug:
269 // QHeader sends a sizeChange() signal for every size change, not only (as
270 // documented) when the user resizes a header column manually. But we only
271 // want to record the column widths if the user explicitly did that, so
272 // ignore those signals if the mouse isn't pressed. There is also one final
273 // sizeChange() signal immediately after the user releases the mouse button.
275 if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
279 // Consume that one sizeChange() signal that is sent immediately after
280 // the mouse button is released, but make sure to reset that flag only
283 if ( ! _mouseButton1PressedInHeader )
284 _finalSizeChangeExpected = false;
290 QY2ListView::eventFilter( QObject * obj, QEvent * event )
292 if ( event && obj && obj == header() )
294 if ( event->type() == QEvent::MouseButtonPress )
296 QMouseEvent * mouseEvent = (QMouseEvent *) event;
298 if ( mouseEvent->button() == 1 )
300 _mouseButton1PressedInHeader = true;
301 _finalSizeChangeExpected = false;
304 else if ( event->type() == QEvent::MouseButtonRelease )
306 QMouseEvent * mouseEvent = (QMouseEvent *) event;
308 if ( mouseEvent->button() == 1 )
310 _finalSizeChangeExpected = true;
311 _mouseButton1PressedInHeader = false;
316 return QTreeWidget::eventFilter( obj, event );
321 QY2ListView::minimumSizeHint() const
323 return QSize( 0, 0 );
328 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
330 _sortByInsertionSequence = sortByInsertionSequence;
332 header()->setClickable( ! _sortByInsertionSequence );
341 QY2ListViewItem::QY2ListViewItem( QY2ListView * parentListView,
342 const QString & text )
343 : QTreeWidgetItem( parentListView, QStringList(text), 1)
345 _serial = parentListView->nextSerial();
349 QY2ListViewItem::QY2ListViewItem( QTreeWidgetItem * parentItem,
350 const QString & text )
351 : QTreeWidgetItem( parentItem, QStringList(text), 1 )
355 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
357 if ( parentListView )
358 _serial = parentListView->nextSerial();
362 QY2ListViewItem::~QY2ListViewItem()
368 QY2ListViewItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
370 bool sortByInsertionSequence = false;
371 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (treeWidget());
373 if ( parentListView )
374 sortByInsertionSequence = parentListView->sortByInsertionSequence();
376 if ( sortByInsertionSequence )
378 const QY2ListViewItem * other = dynamic_cast<const QY2ListViewItem *> (&otherListViewItem);
382 return ( this->serial() < other->serial() );
385 // Still here? Try the other version: QY2CheckListItem.
387 const QY2CheckListItem * otherCheckListItem = dynamic_cast<const QY2CheckListItem *> (&otherListViewItem);
389 if ( otherCheckListItem )
391 return ( this->serial() < otherCheckListItem->serial() );
396 return QTreeWidgetItem::operator<(otherListViewItem);
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 // QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
415 QY2CheckListItem::QY2CheckListItem( QY2ListView * parentListView,
416 const QString & text )
417 : QY2ListViewItem( parentListView, text)
419 setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
420 setCheckState(0, Qt::Unchecked);
421 _serial = parentListView->nextSerial();
425 QY2CheckListItem::QY2CheckListItem( QTreeWidgetItem * parentItem,
426 const QString & text )
427 : QY2ListViewItem( parentItem, text)
430 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
432 if ( parentListView )
433 _serial = parentListView->nextSerial();
436 QY2CheckListItem::~QY2CheckListItem()
444 QY2CheckListItem::paintCell( QPainter * painter,
445 const QColorGroup & colorGroup,
450 QColorGroup cg = colorGroup;
452 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
453 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
455 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
461 QY2ListViewToolTip::maybeTip( const QPoint & pos )
463 Q3Header * header = _listView->header();
464 QTreeWidgetItem * item = _listView->itemAt( pos );
469 int x = _listView->viewportToContents( pos ).x();
470 int column = header->sectionAt(x);
475 indent = item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
476 indent *= _listView->treeStepSize();
478 if ( pos.x() < indent )
482 QString text = _listView->toolTip( item, column );
484 if ( ! text.isEmpty() )
486 QRect rect( _listView->itemRect( item ) );
491 rect.setWidth( indent );
495 QPoint topLeft( header->sectionPos( column ), 0 );
496 topLeft = _listView->contentsToViewport( topLeft );
497 rect.setX( topLeft.x() );
498 rect.setWidth( header->sectionSize( column ) );
508 #include "QY2ListView.moc"