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