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 )
216 int col = header()->logicalIndexAt( ev->pos().x() );
218 if ( item == _mousePressedItem &&
219 col == _mousePressedCol &&
220 ev->button() == _mousePressedButton )
222 emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
227 // invalidate last click data
229 _mousePressedItem = 0;
230 _mousePressedCol = -1;
231 _mousePressedButton = Qt::NoButton;
233 // Call base class method
234 //FIXME QTreeWidget::contentsMouseReleaseEvent( ev );
239 QY2ListView::contentsMouseDoubleClickEvent( QMouseEvent * ev )
241 QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
243 if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
245 int col = header()->logicalIndexAt( ev->pos().x() );
246 emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
249 // invalidate last click data
251 _mousePressedItem = 0;
252 _mousePressedCol = -1;
253 _mousePressedButton = Qt::NoButton;
255 // // Call base class method
256 // QTreeWidget::contentsMouseDoubleClickEvent( ev );
261 QY2ListView::columnWidthChanged( int, int, int )
263 // Workaround for Qt bug:
265 // QHeader sends a sizeChange() signal for every size change, not only (as
266 // documented) when the user resizes a header column manually. But we only
267 // want to record the column widths if the user explicitly did that, so
268 // ignore those signals if the mouse isn't pressed. There is also one final
269 // sizeChange() signal immediately after the user releases the mouse button.
271 if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
275 // Consume that one sizeChange() signal that is sent immediately after
276 // the mouse button is released, but make sure to reset that flag only
279 if ( ! _mouseButton1PressedInHeader )
280 _finalSizeChangeExpected = false;
286 QY2ListView::eventFilter( QObject * obj, QEvent * event )
288 if ( event && obj && obj == header() )
290 if ( event->type() == QEvent::MouseButtonPress )
292 QMouseEvent * mouseEvent = (QMouseEvent *) event;
294 if ( mouseEvent->button() == 1 )
296 _mouseButton1PressedInHeader = true;
297 _finalSizeChangeExpected = false;
300 else if ( event->type() == QEvent::MouseButtonRelease )
302 QMouseEvent * mouseEvent = (QMouseEvent *) event;
304 if ( mouseEvent->button() == 1 )
306 _finalSizeChangeExpected = true;
307 _mouseButton1PressedInHeader = false;
312 return QTreeWidget::eventFilter( obj, event );
317 QY2ListView::minimumSizeHint() const
319 return QSize( 0, 0 );
324 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
326 _sortByInsertionSequence = sortByInsertionSequence;
328 header()->setClickable( ! _sortByInsertionSequence );
337 QY2ListViewItem::QY2ListViewItem( QY2ListView * parentListView,
338 const QString & text )
339 : QTreeWidgetItem( parentListView, QStringList(text), 1)
341 _serial = parentListView->nextSerial();
345 QY2ListViewItem::QY2ListViewItem( QTreeWidgetItem * parentItem,
346 const QString & text )
347 : QTreeWidgetItem( parentItem, QStringList(text), 1 )
351 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
353 if ( parentListView )
354 _serial = parentListView->nextSerial();
358 QY2ListViewItem::~QY2ListViewItem()
364 QY2ListViewItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
366 bool sortByInsertionSequence = false;
367 QY2ListView * parentListView = dynamic_cast<QY2ListView *> (treeWidget());
369 if ( parentListView )
370 sortByInsertionSequence = parentListView->sortByInsertionSequence();
372 if ( sortByInsertionSequence )
374 const QY2ListViewItem * other = dynamic_cast<const QY2ListViewItem *> (&otherListViewItem);
378 return ( this->serial() < other->serial() );
381 // Still here? Try the other version: QY2CheckListItem.
383 const QY2CheckListItem * otherCheckListItem = dynamic_cast<const QY2CheckListItem *> (&otherListViewItem);
385 if ( otherCheckListItem )
387 return ( this->serial() < otherCheckListItem->serial() );
392 return QTreeWidgetItem::operator<(otherListViewItem);
396 // QY2ListViewItem::paintCell( QPainter * painter,
397 // const QColorGroup & colorGroup,
402 // QColorGroup cg = colorGroup;
404 // if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
405 // if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
407 // QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
411 QY2CheckListItem::QY2CheckListItem( QY2ListView * parentListView,
412 const QString & text )
413 : QY2ListViewItem( parentListView, text)
415 setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
416 setCheckState(0, Qt::Unchecked);
417 _serial = parentListView->nextSerial();
421 QY2CheckListItem::QY2CheckListItem( QTreeWidgetItem * parentItem,
422 const QString & text )
423 : QY2ListViewItem( parentItem, text)
426 QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
428 if ( parentListView )
429 _serial = parentListView->nextSerial();
432 QY2CheckListItem::~QY2CheckListItem()
440 QY2CheckListItem::paintCell( QPainter * painter,
441 const QColorGroup & colorGroup,
446 QColorGroup cg = colorGroup;
448 if ( _textColor.isValid() ) cg.setColor( QColorGroup::Text, _textColor );
449 if ( _backgroundColor.isValid() ) cg.setColor( QColorGroup::Base, _backgroundColor );
451 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
457 QY2ListViewToolTip::maybeTip( const QPoint & pos )
459 Q3Header * header = _listView->header();
460 QTreeWidgetItem * item = _listView->itemAt( pos );
465 int x = _listView->viewportToContents( pos ).x();
466 int column = header->sectionAt(x);
471 indent = item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
472 indent *= _listView->treeStepSize();
474 if ( pos.x() < indent )
478 QString text = _listView->toolTip( item, column );
480 if ( ! text.isEmpty() )
482 QRect rect( _listView->itemRect( item ) );
487 rect.setWidth( indent );
491 QPoint topLeft( header->sectionPos( column ), 0 );
492 topLeft = _listView->contentsToViewport( topLeft );
493 rect.setX( topLeft.x() );
494 rect.setWidth( header->sectionSize( column ) );
504 #include "QY2ListView.moc"