]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQMultiSelectionBox.cc
compile some more
[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 Q3ListView( 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->addColumn( "" );      // QListView doesn't have one single column by default!
65     _qt_listView->setSorting( 0, false );
66     _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 =
101         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->setOn( true );
109
110
111     // Take care of the QListView's keyboard focus
112
113     if ( ! _qt_listView->selectedItem() )
114         _qt_listView->setSelected( msbItem, 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->setOn( selected );
125 }
126
127
128 void
129 YQMultiSelectionBox::deselectAllItems()
130 {
131     YQSignalBlocker sigBlocker( _qt_listView );
132     YMultiSelectionBox::deselectAllItems();
133
134     Q3ListViewItemIterator it( _qt_listView );
135
136     while ( *it )
137     {
138         YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (*it);
139
140         if ( item )
141             item->setOn( false );
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     Q3ListViewItem * 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             _qt_listView->setSelected( msbItem, 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->isShown() ?
238         _caption->sizeHint().width() + frameWidth() : 0;
239
240     return max( 80, hintWidth );
241 }
242
243
244 int YQMultiSelectionBox::preferredHeight()
245 {
246     int hintHeight       = _caption->isShown() ? _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     Q3ListViewItemIterator 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                                                   Q3ListView *          listView,
330                                                   YItem *               yItem )
331     : Q3CheckListItem( listView, fromUTF8( yItem->label() ), Q3CheckListItem::CheckBox )
332     , _yItem( yItem )
333     , _multiSelectionBox( parent )
334 {
335     YUI_CHECK_PTR( yItem );
336
337     _serial = _item_count++;
338 }
339
340
341 void
342 YQMultiSelectionBoxItem::stateChange( bool newState )
343 {
344     _yItem->setSelected( newState );
345     _multiSelectionBox->sendValueChanged();
346     Q3CheckListItem::stateChange( newState );
347 }
348
349
350 QString
351 YQMultiSelectionBoxItem::key( int, bool ) const
352 {
353     /*
354      * Return a sort key that depends on creation (i.e. insertion) order.
355      */
356
357     static QString sortKey;
358     sortKey.sprintf( "%010d", INT_MAX - _serial );
359
360     return sortKey;
361 }
362
363
364 #include "YQMultiSelectionBox.moc"