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