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