]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/QY2ListView.cc
don't reset the changes file
[duncan/yast2-qt4.git] / src / QY2ListView.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       QY2ListView.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   This is a pure Qt widget - it can be used independently of YaST2.
18
19 /-*/
20
21
22 #include <QPixmap>
23 #include <QHeaderView>
24 #include <QMouseEvent>
25 #include "QY2ListView.h"
26
27
28 QY2ListView::QY2ListView( QWidget * parent )
29     : QTreeWidget( parent )
30     , _mousePressedItem(0)
31     , _mousePressedCol( -1 )
32     , _mousePressedButton( Qt::NoButton )
33     , _sortByInsertionSequence( false )
34     , _nextSerial(0)
35     , _mouseButton1PressedInHeader( false )
36     , _finalSizeChangeExpected( false )
37 {
38     //FIXME QTreeWidget::setShowToolTips( false );
39     setRootIsDecorated(false);
40
41 #if FIXME_TOOLTIP
42     _toolTip = new QY2ListViewToolTip( this );
43 #endif
44
45      if ( header() )
46        header()->installEventFilter( this );
47
48 #if FIXME
49     connect( this,      SIGNAL( columnResized        ( int, int, int ) ),
50              this,      SLOT  ( columnWidthChanged( int, int, int ) ) );
51 #endif
52 }
53
54
55 QY2ListView::~QY2ListView()
56 {
57 #if FIXME_TOOLTIP
58     if ( _toolTip )
59         delete _toolTip;
60 #endif
61 }
62
63
64 void
65 QY2ListView::selectSomething()
66 {
67     QTreeWidgetItemIterator it( this );
68
69     while ( *it )
70     {
71         QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
72
73         if ( item && (item->flags() & Qt::ItemIsSelectable) )
74         {
75             item->setSelected(true); // emits signal, too
76             return;
77         }
78
79         ++it;
80     }
81 }
82
83
84 void
85 QY2ListView::clear()
86 {
87     QTreeWidget::clear();
88     restoreColumnWidths();
89 }
90
91
92 void
93 QY2ListView::updateItemStates()
94 {
95     QTreeWidgetItemIterator it( this );
96
97     while ( *it )
98     {
99         QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
100
101         if ( item )
102             item->updateStatus();
103
104         ++it;
105     }
106 }
107
108
109 void
110 QY2ListView::updateItemData()
111 {
112     QTreeWidgetItemIterator it( this );
113
114     while ( *it )
115     {
116         QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
117
118         if ( item )
119             item->updateData();
120
121         ++it;
122     }
123 }
124
125
126 QString
127 QY2ListView::toolTip( QTreeWidgetItem * listViewItem, int column )
128 {
129     if ( ! listViewItem )
130         return QString::null;
131
132     QString text;
133
134 #if 0
135     text.sprintf( "Column %d:\n%s", column, (const char *) listViewItem->text( column ) );
136 #endif
137
138     // Try known item classes
139
140     QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (listViewItem);
141
142     if ( item )
143         return item->toolTip( column );
144
145     QY2CheckListItem * checkListItem = dynamic_cast<QY2CheckListItem *> (listViewItem);
146
147     if ( checkListItem )
148         return checkListItem->toolTip( column );
149
150     return QString::null;
151 }
152
153
154 void
155 QY2ListView::saveColumnWidths()
156 {
157     _savedColumnWidth.clear();
158     _savedColumnWidth.reserve( columnCount() );
159
160     for ( int i = 0; i < columnCount(); i++ )
161     {
162         _savedColumnWidth.push_back( columnWidth(i) );
163     }
164 }
165
166
167 void
168 QY2ListView::restoreColumnWidths()
169 {
170     if ( _savedColumnWidth.size() != (unsigned) columnCount() )         // never manually resized
171     {
172         for ( int i = 0; i < columnCount(); i++ )               // use optimized column width
173             resizeColumnToContents(i);
174     }
175     else                                                // stored settings after manual resizing
176     {
177         for ( int i = 0; i < columnCount(); i++ )
178         {
179             setColumnWidth( i, _savedColumnWidth[ i ] ); // restore saved column width
180         }
181     }
182 }
183
184
185 void
186 QY2ListView::contentsMousePressEvent( QMouseEvent * ev )
187 {
188     //FIXME may be convert to global
189     QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
190
191     if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
192     {
193         _mousePressedItem       = item;
194 //FIXME _mousePressedCol        = header()->sectionAt( ev->pos().x() );
195         _mousePressedButton     = ev->button();
196     }
197     else        // invalidate last click data
198     {
199         _mousePressedItem       = 0;
200         _mousePressedCol        = -1;
201         _mousePressedButton     = -1;
202     }
203
204     // Call base class method
205     //FIXME QTreeWidget::contentsMousePressEvent( ev );
206 }
207
208
209 void
210 QY2ListView::contentsMouseReleaseEvent( QMouseEvent * ev )
211 {
212     QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
213
214     if ( item && ( item->flags() & Qt::ItemIsEnabled ) && item == _mousePressedItem )
215     {
216         int col = header()->logicalIndexAt( ev->pos().x() );
217
218         if ( item == _mousePressedItem  &&
219              col  == _mousePressedCol   &&
220              ev->button() == _mousePressedButton )
221         {
222             emit( columnClicked( ev->button(), item, col, ev->globalPos() ) );
223         }
224
225     }
226
227     // invalidate last click data
228
229     _mousePressedItem   = 0;
230     _mousePressedCol    = -1;
231     _mousePressedButton = Qt::NoButton;
232
233     // Call base class method
234     //FIXME QTreeWidget::contentsMouseReleaseEvent( ev );
235 }
236
237
238 void
239 QY2ListView::contentsMouseDoubleClickEvent( QMouseEvent * ev )
240 {
241     QTreeWidgetItem * item = itemAt( mapToGlobal( ev->pos() ) );
242
243     if ( item && ( item->flags() & Qt::ItemIsEnabled ) )
244     {
245         int col = header()->logicalIndexAt( ev->pos().x() );
246         emit( columnDoubleClicked( ev->button(), (QY2ListViewItem *) item, col, ev->globalPos() ) );
247      }
248
249      // invalidate last click data
250
251      _mousePressedItem  = 0;
252      _mousePressedCol   = -1;
253      _mousePressedButton        = Qt::NoButton;
254
255 //     // Call base class method
256 //     QTreeWidget::contentsMouseDoubleClickEvent( ev );
257 }
258
259
260 void
261 QY2ListView::columnWidthChanged( int, int, int )
262 {
263     // Workaround for Qt bug:
264     //
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.
270
271     if ( _mouseButton1PressedInHeader || _finalSizeChangeExpected )
272     {
273         saveColumnWidths();
274
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
277         // when appropriate.
278
279         if ( ! _mouseButton1PressedInHeader )
280             _finalSizeChangeExpected = false;
281     }
282 }
283
284
285 bool
286 QY2ListView::eventFilter( QObject * obj, QEvent * event )
287 {
288     if ( event && obj && obj == header() )
289     {
290         if ( event->type() == QEvent::MouseButtonPress )
291         {
292             QMouseEvent * mouseEvent = (QMouseEvent *) event;
293
294             if ( mouseEvent->button() == 1 )
295             {
296                 _mouseButton1PressedInHeader = true;
297                 _finalSizeChangeExpected     = false;
298             }
299         }
300         else if ( event->type() == QEvent::MouseButtonRelease )
301         {
302             QMouseEvent * mouseEvent = (QMouseEvent *) event;
303
304             if ( mouseEvent->button() == 1 )
305             {
306                 _finalSizeChangeExpected     = true;
307                 _mouseButton1PressedInHeader = false;
308             }
309         }
310     }
311
312     return QTreeWidget::eventFilter( obj, event );
313 }
314
315
316 QSize
317 QY2ListView::minimumSizeHint() const
318 {
319     return QSize( 0, 0 );
320 }
321
322
323 void
324 QY2ListView::setSortByInsertionSequence( bool sortByInsertionSequence )
325 {
326     _sortByInsertionSequence = sortByInsertionSequence;
327     //FIXME sort();
328     header()->setClickable( ! _sortByInsertionSequence );
329
330 }
331
332
333
334
335
336
337 QY2ListViewItem::QY2ListViewItem( QY2ListView *         parentListView,
338                                   const QString &       text )
339     : QTreeWidgetItem( parentListView, QStringList(text), 1)
340 {
341     _serial = parentListView->nextSerial();
342 }
343
344
345 QY2ListViewItem::QY2ListViewItem( QTreeWidgetItem *     parentItem,
346                                   const QString &       text )
347     : QTreeWidgetItem( parentItem, QStringList(text), 1 )
348 {
349     _serial = 0;
350
351     QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
352
353     if ( parentListView )
354         _serial = parentListView->nextSerial();
355 }
356
357
358 QY2ListViewItem::~QY2ListViewItem()
359 {
360     // NOP
361 }
362
363 bool
364 QY2ListViewItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
365 {
366   bool sortByInsertionSequence = false;
367     QY2ListView * parentListView = dynamic_cast<QY2ListView *> (treeWidget());
368
369     if ( parentListView )
370         sortByInsertionSequence = parentListView->sortByInsertionSequence();
371
372     if ( sortByInsertionSequence )
373     {
374         const QY2ListViewItem * other = dynamic_cast<const QY2ListViewItem *> (&otherListViewItem);
375
376         if ( other )
377         {
378             return ( this->serial() < other->serial() );
379         }
380
381         // Still here? Try the other version: QY2CheckListItem.
382
383         const QY2CheckListItem * otherCheckListItem = dynamic_cast<const QY2CheckListItem *> (&otherListViewItem);
384
385         if ( otherCheckListItem )
386         {
387             return ( this->serial() < otherCheckListItem->serial() );
388         }
389
390     }
391
392     return QTreeWidgetItem::operator<(otherListViewItem);
393 }
394
395 // void
396 // QY2ListViewItem::paintCell( QPainter *               painter,
397 //                          const QColorGroup & colorGroup,
398 //                          int                 column,
399 //                          int                 width,
400 //                          int                 alignment )
401 // {
402 //     QColorGroup cg = colorGroup;
403 //
404 //     if ( _textColor.isValid() )              cg.setColor( QColorGroup::Text, _textColor );
405 //     if ( _backgroundColor.isValid() )        cg.setColor( QColorGroup::Base, _backgroundColor );
406 //
407 //     QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
408 // }
409
410
411 QY2CheckListItem::QY2CheckListItem( QY2ListView *               parentListView,
412                                     const QString &             text )
413     : QY2ListViewItem( parentListView, text)
414 {
415     setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
416     setCheckState(0, Qt::Unchecked);
417     _serial = parentListView->nextSerial();
418 }
419
420
421 QY2CheckListItem::QY2CheckListItem( QTreeWidgetItem *           parentItem,
422                                     const QString &             text )
423     : QY2ListViewItem( parentItem, text)
424 {
425     _serial = 0;
426     QY2ListView * parentListView = dynamic_cast<QY2ListView *> ( treeWidget() );
427
428     if ( parentListView )
429         _serial = parentListView->nextSerial();
430 }
431
432 QY2CheckListItem::~QY2CheckListItem()
433 {
434     // NOP
435 }
436
437
438 /*
439 void
440 QY2CheckListItem::paintCell( QPainter *                 painter,
441                              const QColorGroup &        colorGroup,
442                              int                        column,
443                              int                        width,
444                              int                        alignment )
445 {
446     QColorGroup cg = colorGroup;
447
448     if ( _textColor.isValid() )         cg.setColor( QColorGroup::Text, _textColor );
449     if ( _backgroundColor.isValid() )   cg.setColor( QColorGroup::Base, _backgroundColor );
450
451     QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
452 }
453 */
454
455 #if FIXME_TOOLTIP
456 void
457 QY2ListViewToolTip::maybeTip( const QPoint & pos )
458 {
459     Q3Header *       header        = _listView->header();
460     QTreeWidgetItem * item          = _listView->itemAt( pos );
461
462     if ( ! item )
463         return;
464
465     int x      = _listView->viewportToContents( pos ).x();
466     int column = header->sectionAt(x);
467     int indent = 0;
468
469     if ( column == 0 )
470     {
471         indent  =  item->depth() + ( _listView->rootIsDecorated() ? 1 : 0 );
472         indent *=  _listView->treeStepSize();
473
474         if ( pos.x() < indent )
475             column = -1;
476     }
477
478     QString text = _listView->toolTip( item, column );
479
480     if ( ! text.isEmpty() )
481     {
482         QRect rect( _listView->itemRect( item ) );
483
484         if ( column < 0 )
485         {
486             rect.setX(0);
487             rect.setWidth( indent );
488         }
489         else
490         {
491             QPoint topLeft( header->sectionPos( column ), 0 );
492             topLeft = _listView->contentsToViewport( topLeft );
493             rect.setX( topLeft.x() );
494             rect.setWidth( header->sectionSize( column ) );
495         }
496
497         tip( rect, text );
498     }
499 }
500
501 #endif
502
503
504 #include "QY2ListView.moc"