]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQMultiSelectionBox.cc
compiles, YQMultiSelectionBoxItem looks like it should, same as YQTree
[duncan/yast2-qt4.git] / src / YQMultiSelectionBox.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQMultiSelectionBox.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19 //#define QT3_SUPPORT 1
20
21 #include <limits.h>
22 #include <QString>
23 #include <QLabel>
24 #include <QVBoxLayout>
25 #include <QHeaderView>
26 #define y2log_component "qt-ui"
27 #include <ycp/y2log.h>
28
29 using std::max;
30
31 #include "utf8.h"
32 #include "YQUI.h"
33 #include "YEvent.h"
34 #include "YQMultiSelectionBox.h"
35 #include "YQSignalBlocker.h"
36 #include "YQWidgetCaption.h"
37
38 #define DEFAULT_VISIBLE_LINES           5
39 #define SHRINKABLE_VISIBLE_LINES        2
40
41
42 YQMultiSelectionBox::YQMultiSelectionBox( YWidget *             parent,
43                                           const string &        label )
44     : QFrame( (QWidget *) parent->widgetRep() )
45     , YMultiSelectionBox( parent, label )
46 {
47     QVBoxLayout* layout = new QVBoxLayout( this );
48     setLayout( layout );
49
50     setWidgetRep( this );
51
52     layout->setSpacing( YQWidgetSpacing );
53     layout->setMargin( YQWidgetMargin );
54
55     _caption = new YQWidgetCaption( this, label );
56     YUI_CHECK_NEW( _caption );
57     layout->addWidget( _caption );
58
59     _qt_listView = new QTreeWidget( this );
60     YUI_CHECK_NEW( _qt_listView );
61     layout->addWidget( _qt_listView );
62
63     _qt_listView->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
64     _qt_listView->setHeaderLabel("");   // QListView doesn't have one single column by default!
65     _qt_listView->sortItems( 0, Qt::AscendingOrder );
66     //FIXME _qt_listView->header()->setStretchEnabled( true );
67     _qt_listView->header()->hide();
68     _qt_listView->setRootIsDecorated ( false );
69     _caption->setBuddy( _qt_listView );
70
71     // Very small default size if specified
72
73     connect( _qt_listView,      SIGNAL( selectionChanged()      ),
74              this,              SLOT  ( slotSelected()          ) );
75
76     connect( this,              SIGNAL( valueChanged()          ),
77              this,              SLOT  ( slotValueChanged()      ) );
78 }
79
80
81 YQMultiSelectionBox::~YQMultiSelectionBox()
82 {
83     // NOP
84 }
85
86
87 void
88 YQMultiSelectionBox::setLabel( const string & label )
89 {
90     _caption->setText( label );
91     YMultiSelectionBox::setLabel( label );
92 }
93
94
95 void
96 YQMultiSelectionBox::addItem( YItem * yItem )
97 {
98     YQSignalBlocker sigBlocker( _qt_listView );
99     YMultiSelectionBox::addItem( yItem ); // will also check for NULL
100
101     YQMultiSelectionBoxItem * msbItem = new YQMultiSelectionBoxItem( this, _qt_listView, yItem );
102
103     YUI_CHECK_NEW( msbItem );
104
105     // Take care of the item's check box
106
107     if ( yItem->selected() )
108       msbItem->setCheckState(0, Qt::Checked);
109
110
111     // Take care of the QListView's keyboard focus
112
113     if ( ! _qt_listView->currentItem() )
114       msbItem->setSelected(true);
115 }
116
117
118 void YQMultiSelectionBox::selectItem( YItem * yItem, bool selected )
119 {
120     YMultiSelectionBox::selectItem( yItem, selected );
121     YQMultiSelectionBoxItem * msbItem = findItem( yItem );
122
123     if ( msbItem )
124       msbItem->setCheckState( 1, selected ? Qt::Checked : Qt::Unchecked );
125 }
126
127
128 void
129 YQMultiSelectionBox::deselectAllItems()
130 {
131     YQSignalBlocker sigBlocker( _qt_listView );
132     YMultiSelectionBox::deselectAllItems();
133
134     QTreeWidgetItemIterator it( _qt_listView );
135
136     while ( *it )
137     {
138       YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (*it);
139
140       if ( item )
141         item->setCheckState(0, Qt::Checked);
142
143       ++it;
144     }
145 }
146
147
148 void
149 YQMultiSelectionBox::deleteAllItems()
150 {
151     YQSignalBlocker sigBlocker( _qt_listView );
152
153     YMultiSelectionBox::deleteAllItems();
154     _qt_listView->clear();
155 }
156
157
158 YItem *
159 YQMultiSelectionBox::currentItem()
160 {
161     // QListView::currentItem() is very similar, but not exactly the same as
162     // QListView::selectedItem(), and it is NOT to be confused with an item's
163     // "selected" state in a YQMultiSelectionBox (the item's check box):
164     //
165     // QListView::currentItem() is the item that currently has the keyboard
166     // focus. By default, it is displayed with a faint dotted outline.
167     //
168     // QListView::selectedItem() is the item that is selected in the QListView
169     // widget. It is displayed in a very visible way with inverted colors
170     // (typically blue backround). If there is a selected item, it is also the
171     // current item. if there is no selected item, there might still be a
172     // current item, though.
173     //
174     // The Y(Q)MultiSelectionBox item's "selected" state is completely
175     // independent of all this: It only depends on the item's check
176     // box. QListView::selectedItem() and QListView::currentItem() are just
177     // mechanisms for keyboard navigation to show the user which item's check
178     // box will be toggled when he hits the space bar.
179     //
180     // For the purpose of this function, QListView::currentItem() is the
181     // minimum requirement.
182
183     QTreeWidgetItem * currentQItem = _qt_listView->currentItem();
184
185     if ( currentQItem )
186     {
187         YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (currentQItem);
188
189         if ( item )
190             return item->yItem();
191     }
192
193     return 0;
194 }
195
196
197 void
198 YQMultiSelectionBox::setCurrentItem( YItem * yItem )
199 {
200     // See also explanations about QListView::currentItem() vs.
201     // QListView::selectedItem() above
202     //
203     // This function uses QListView::selectedItem() for better visibility.
204     // This implicitly also changes QListView::currentItem().
205
206     YQSignalBlocker sigBlocker( _qt_listView );
207
208     if ( ! yItem )
209     {
210         _qt_listView->clearSelection();
211     }
212     else
213     {
214         YQMultiSelectionBoxItem * msbItem = findItem( yItem );
215
216         if ( msbItem )
217             msbItem->setSelected(true);
218
219         // This does NOT change the item's check box!
220         // (see explanations in YQMultiSelectionBox::currentItem() avove)
221     }
222 }
223
224
225 void
226 YQMultiSelectionBox::setEnabled( bool enabled )
227 {
228     _caption->setEnabled( enabled );
229     _qt_listView->setEnabled( enabled );
230     //_qt_listView->triggerUpdate();
231     YWidget::setEnabled( enabled );
232 }
233
234
235 int YQMultiSelectionBox::preferredWidth()
236 {
237     int hintWidth = (!_caption->isHidden()) ?
238                      _caption->sizeHint().width() + frameWidth() : 0;
239
240     return max( 80, hintWidth );
241 }
242
243
244 int YQMultiSelectionBox::preferredHeight()
245 {
246     int hintHeight       = (!_caption->isHidden()) ? _caption->sizeHint().height() : 0;
247     int visibleLines     = shrinkable() ? SHRINKABLE_VISIBLE_LINES : DEFAULT_VISIBLE_LINES;
248     hintHeight          += visibleLines * _qt_listView->fontMetrics().lineSpacing();
249     hintHeight          += _qt_listView->frameWidth() * 2;
250
251     return max( 80, hintHeight );
252 }
253
254
255 void
256 YQMultiSelectionBox::setSize( int newWidth, int newHeight )
257 {
258     resize( newWidth, newHeight );
259 }
260
261
262 bool
263 YQMultiSelectionBox::setKeyboardFocus()
264 {
265     _qt_listView->setFocus();
266
267     return true;
268 }
269
270
271 void
272 YQMultiSelectionBox::slotSelected()
273 {
274     if ( notify() )
275     {
276         if ( ! YQUI::ui()->eventPendingFor( this ) )
277         {
278             // Avoid overwriting a (more important) ValueChanged event with a SelectionChanged event
279
280             YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
281         }
282     }
283 }
284
285
286 void
287 YQMultiSelectionBox::slotValueChanged()
288 {
289     if ( notify() )
290         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
291 }
292
293
294 void
295 YQMultiSelectionBox::sendValueChanged()
296 {
297     emit valueChanged();
298 }
299
300
301 YQMultiSelectionBoxItem *
302 YQMultiSelectionBox::findItem( YItem * wantedItem )
303 {
304     // FIXME: Don't search through all items, use the YItem::data() pointer instead
305     QTreeWidgetItemIterator it( _qt_listView );
306
307     while ( *it )
308     {
309         YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (*it);
310
311         if ( item && item->yItem() == wantedItem )
312             return item;
313
314         ++it;
315     }
316
317     return 0;
318 }
319
320
321
322
323
324 int YQMultiSelectionBoxItem::_item_count = 0;
325
326
327
328 YQMultiSelectionBoxItem::YQMultiSelectionBoxItem( YQMultiSelectionBox * parent,
329                                                   QTreeWidget *                 listView,
330                                                   YItem *               yItem )
331     : QTreeWidgetItem( listView)
332     , _yItem( yItem )
333     , _multiSelectionBox( parent )
334 {
335     YUI_CHECK_PTR( yItem );
336     setFlags( Qt::ItemIsUserCheckable );
337     setCheckState( 0, Qt::Unchecked );
338     setText(0, fromUTF8( yItem->label() ));
339     setFlags(Qt::ItemIsUserCheckable);
340     _serial = _item_count++;
341 }
342
343 void
344 YQMultiSelectionBoxItem::stateChange( bool newState )
345 {
346     _yItem->setSelected( newState );
347     _multiSelectionBox->sendValueChanged();
348     //QTreeWidgetItem::stateChange( newState );
349     // FIXME checked or selected state?
350     QTreeWidgetItem::setCheckState( 0, newState ? Qt::Checked : Qt::Unchecked );
351 }
352
353
354 QString
355 YQMultiSelectionBoxItem::key( int, bool ) const
356 {
357     /*
358      * Return a sort key that depends on creation (i.e. insertion) order.
359      */
360
361     static QString sortKey;
362     sortKey.sprintf( "%010d", INT_MAX - _serial );
363
364     return sortKey;
365 }
366
367
368 #include "YQMultiSelectionBox.moc"