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