]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQSelectionBox.cc
YQMultiSelectionBoxItem compiles
[duncan/yast2-qt4.git] / src / YQSelectionBox.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQSelectionBox.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19 #define QT3_SUPPORT
20
21 #include <qstring.h>
22 #include <qlabel.h>
23 #include <q3listbox.h>
24 #include <qnamespace.h>
25 //Added by qt3to4:
26 #include <qpixmap.h>
27 #include <qevent.h>
28 #include <qevent.h>
29 #include <qevent.h>
30 #include <QVBoxLayout>
31 #define y2log_component "qt-ui"
32 #include <ycp/y2log.h>
33
34 using std::max;
35
36 #include "utf8.h"
37 #include "YEvent.h"
38 #include "YQUI.h"
39 #include "YQSelectionBox.h"
40 #include "YQSignalBlocker.h"
41 #include "YQDialog.h"
42 #include "YUIException.h"
43 #include "YQWidgetCaption.h"
44
45 #define VERBOSE_SELECTION               1
46
47 #define DEFAULT_VISIBLE_LINES           5
48 #define SHRINKABLE_VISIBLE_LINES        2
49
50
51 YQSelectionBox::YQSelectionBox( YWidget * parent, const string & label )
52     : QFrame( (QWidget *) parent->widgetRep() )
53     , YSelectionBox( parent, label )
54 {
55     setWidgetRep( this );
56
57     QVBoxLayout* layout = new QVBoxLayout( this );
58     setLayout( layout );
59
60     layout->setSpacing( YQWidgetSpacing );
61     layout->setMargin ( YQWidgetMargin  );
62
63     _caption = new YQWidgetCaption( this, label );
64     YUI_CHECK_NEW( _caption );
65     layout->addWidget( _caption );
66
67     _qt_listBox = new Q3ListBox( this );
68     YUI_CHECK_NEW( _qt_listBox );
69     layout->addWidget( _qt_listBox );
70
71     _qt_listBox->installEventFilter( this );
72     _qt_listBox->setVariableHeight( false );
73     _qt_listBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
74                                              QSizePolicy::Expanding ) );
75     _qt_listBox->setTopItem(0);
76     _caption->setBuddy( _qt_listBox );
77
78     connect( _qt_listBox,       SIGNAL( highlighted ( int ) ),
79              this,              SLOT  ( slotSelected( int ) ) );
80
81     connect( _qt_listBox,       SIGNAL( doubleClicked( Q3ListBoxItem * ) ),
82              this,              SLOT  ( slotActivated( Q3ListBoxItem * ) ) );
83
84     connect( &_timer,           SIGNAL( timeout()           ),
85              this,              SLOT  ( returnImmediately() ) );
86 }
87
88
89 YQSelectionBox::~YQSelectionBox()
90 {
91     // NOP
92 }
93
94
95 void YQSelectionBox::setLabel( const string & label )
96 {
97     _caption->setText( label );
98     YSelectionBox::setLabel( label );
99 }
100
101
102 void YQSelectionBox::addItem( YItem * item )
103 {
104     YSelectionBox::addItem( item );
105     QPixmap icon;
106
107     if ( item->hasIconName() )
108     {
109         string iconName = iconFullPath( item );
110         icon = QPixmap( iconName.c_str() );
111
112         if ( icon.isNull() )
113             y2warning( "Can't load icon %s", iconName.c_str() );
114     }
115
116     if ( icon.isNull() )
117         _qt_listBox->insertItem( fromUTF8( item->label() ) );
118     else
119         _qt_listBox->insertItem( icon, fromUTF8( item->label() ) );
120
121     if ( item->selected() )
122     {
123         YQSignalBlocker sigBlocker( _qt_listBox );
124         _qt_listBox->setCurrentItem( item->index() );
125     }
126 }
127
128
129 void YQSelectionBox::selectItem( YItem * item, bool selected )
130 {
131     YQSignalBlocker sigBlocker( _qt_listBox );
132
133     YSelectionBox::selectItem( item, selected );
134     _qt_listBox->setCurrentItem( selected ? item->index() : -1 );
135 }
136
137
138 void YQSelectionBox::selectItem( int index )
139 {
140     YSelectionBox::deselectAllItems();
141     YItem * item = YSelectionBox::itemAt( index );
142
143     if ( item )
144     {
145 #ifdef VERBOSE_SELECTION
146         y2debug( "%s \"%s\": Selecting item \"%s\"",
147                  widgetClass(),
148                  debugLabel().c_str(),
149                  item->label().c_str() );
150 #endif
151
152         item->setSelected( true );
153     }
154     else
155         YUI_THROW( YUIException( "Can't find selected item" ) );
156 }
157
158
159 void YQSelectionBox::deselectAllItems()
160 {
161     YSelectionBox::deselectAllItems();
162     _qt_listBox->clearSelection();
163
164     if ( _qt_listBox->currentItem() > -1 )
165     {
166         // Some item is selected after all; the Qt documtation says this
167         // happens if the QListBox is in single selection mode (which it is)
168         // and has the keyboard focus.
169         //
170         // Synchronize internal "selected" flags with what the QListBox
171         // displays. This has a small performance penalty because it calls
172         // YSelectionBox::deselectAllItems() again which again iterates over
173         // all items.
174         selectItem( _qt_listBox->currentItem() );
175     }
176 }
177
178
179 void YQSelectionBox::deleteAllItems()
180 {
181     YQSignalBlocker sigBlocker( _qt_listBox );
182
183     _qt_listBox->clear();
184     YSelectionBox::deleteAllItems();
185 }
186
187
188
189 int YQSelectionBox::preferredWidth()
190 {
191     int hintWidth = !_caption->isHidden() ?
192         _caption->sizeHint().width() + frameWidth() : 0;
193
194     return max( 80, hintWidth );
195 }
196
197
198 int YQSelectionBox::preferredHeight()
199 {
200     int hintHeight       = !_caption->isHidden() ? _caption->sizeHint().height() : 0;
201     int visibleLines     = shrinkable() ? SHRINKABLE_VISIBLE_LINES : DEFAULT_VISIBLE_LINES;
202     hintHeight          += visibleLines * _qt_listBox->fontMetrics().lineSpacing();
203     hintHeight          += _qt_listBox->frameWidth() * 2;
204
205     return max( 80, hintHeight );
206 }
207
208
209 void YQSelectionBox::setSize( int newWidth, int newHeight )
210 {
211     resize( newWidth, newHeight );
212 }
213
214
215 void YQSelectionBox::setEnabled( bool enabled )
216 {
217     _caption->setEnabled( enabled );
218     _qt_listBox->setEnabled( enabled );
219     _qt_listBox->triggerUpdate( true );
220     YWidget::setEnabled( enabled );
221 }
222
223
224 bool YQSelectionBox::setKeyboardFocus()
225 {
226     _qt_listBox->setFocus();
227
228     return true;
229 }
230
231
232 bool YQSelectionBox::eventFilter( QObject * obj, QEvent * ev )
233 {
234     if ( ev->type() == QEvent::KeyPress )
235     {
236         QKeyEvent * event = ( QKeyEvent * ) ev;
237
238         if ( ( event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter ) &&
239              ( event->state() == 0 || event->state() == Qt::Keypad ) )
240         {
241             YQDialog * dia = (YQDialog *) findDialog();
242
243             if ( dia )
244             {
245                 ( void ) dia->activateDefaultButton();
246                 return true;
247             }
248         }
249     }
250     else if ( ev->type() == QEvent::MouseButtonRelease )
251     {
252         QMouseEvent * mouseEvent = dynamic_cast<QMouseEvent *> (ev);
253
254         if ( mouseEvent && mouseEvent->button() == Qt::RightButton )
255         {
256             y2milestone( "Right click in selecton box detected" );
257             YQUI::ui()->maybeLeftHandedUser();
258         }
259     }
260
261     return QWidget::eventFilter( obj, ev );
262 }
263
264
265 void YQSelectionBox::slotSelected( int index )
266 {
267     selectItem( index );
268
269     if ( notify() )
270     {
271         if ( immediateMode() )
272             returnImmediately();
273         else
274         {
275             if ( ! YQUI::ui()->eventsBlocked() )
276             {
277                 // Delayed event delivery - only if events are to be delivered
278                 // right now.
279                 //
280                 // An event block that is in effect right now may or may not
281                 // affect events after the timer delay is expired.
282                 //
283                 // This may create nasty side effects such as bug #32510: When
284                 // an item is initially selected, that initial selection event
285                 // gets through even though (!) events are blocked during
286                 // widget creation.
287
288                 returnDelayed();
289             }
290         }
291     }
292 }
293
294
295 void YQSelectionBox::slotActivated( Q3ListBoxItem * qItem )
296 {
297     selectItem( _qt_listBox->index( qItem ) );
298
299     if ( notify() )
300         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
301 }
302
303
304 void YQSelectionBox::returnImmediately()
305 {
306     if ( ! YQUI::ui()->eventPendingFor( this ) )
307     {
308         // Avoid overwriting a (more important) Activated event with a
309         // SelectionChanged event
310
311         y2debug( "sending selbox event" );
312         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
313     }
314 }
315
316
317 void YQSelectionBox::returnDelayed()
318 {
319     y2debug( "Starting selbox timer" );
320     _timer.setSingleShot( true );
321     _timer.start( 250 ); // millisec
322 }
323
324
325
326 #include "YQSelectionBox.moc"