]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/preferences_widgets.cpp
qt4 - Mousewheel (2)
[vlc] / modules / gui / qt4 / components / preferences_widgets.cpp
1 /*****************************************************************************
2  * preferences_widgets.cpp : Widgets for preferences displays
3  ****************************************************************************
4  * Copyright (C) 2006-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Antoine Cellerier <dionoea@videolan.org>
9  *          Jean-Baptiste Kempf <jb@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 /**
27  * Todo:
28  *  - Finish implementation (see WX)
29  *  - Improvements over WX
30  *      - Password field implementation (through "pwd" bool param
31  *      - Validator for modulelist
32  *  - Implement update stuff using a general Updated signal
33  */
34
35 #include "components/preferences_widgets.hpp"
36 #include "util/customwidgets.hpp"
37 #include "qt4.hpp"
38
39 #include <QLineEdit>
40 #include <QString>
41 #include <QSpinBox>
42 #include <QDoubleSpinBox>
43 #include <QVariant>
44 #include <QComboBox>
45 #include <QGridLayout>
46 #include <QPushButton>
47 #include <QSlider>
48 #include <QFileDialog>
49 #include <QFontDialog>
50
51 #include <vlc_keys.h>
52
53 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
54                                              module_config_t *p_item,
55                                              QWidget *parent )
56 {
57     int i=0;
58     return createControl( p_this, p_item, parent, NULL, i );
59 }
60
61 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
62                                              module_config_t *p_item,
63                                              QWidget *parent,
64                                              QGridLayout *l, int &line )
65 {
66     ConfigControl *p_control = NULL;
67     if( p_item->psz_current ) return NULL;
68
69     switch( p_item->i_type )
70     {
71     case CONFIG_ITEM_MODULE:
72         p_control = new ModuleConfigControl( p_this, p_item, parent, false,
73                                              l, line );
74         break;
75     case CONFIG_ITEM_MODULE_CAT:
76         p_control = new ModuleConfigControl( p_this, p_item, parent, true,
77                                              l, line );
78         break;
79     case CONFIG_ITEM_MODULE_LIST:
80         p_control = new ModuleListConfigControl( p_this, p_item, parent, false,
81                                              l, line );
82         break;
83     case CONFIG_ITEM_MODULE_LIST_CAT:
84         p_control = new ModuleListConfigControl( p_this, p_item, parent, true,
85                                              l, line );
86         break;
87     case CONFIG_ITEM_STRING:
88         if( !p_item->i_list )
89             p_control = new StringConfigControl( p_this, p_item, parent,
90                                                  l, line, false );
91         else
92             p_control = new StringListConfigControl( p_this, p_item,
93                                             parent, false, l, line );
94         break;
95     case CONFIG_ITEM_INTEGER:
96         if( p_item->i_list )
97             p_control = new IntegerListConfigControl( p_this, p_item,
98                                             parent, false, l, line );
99         else if( p_item->min.i || p_item->max.i )
100             p_control = new IntegerRangeConfigControl( p_this, p_item, parent,
101                                                        l, line );
102         else
103             p_control = new IntegerConfigControl( p_this, p_item, parent,
104                                                   l, line );
105         break;
106     case CONFIG_ITEM_FILE:
107         p_control = new FileConfigControl( p_this, p_item, parent, l,
108                                                 line, false );
109         break;
110     case CONFIG_ITEM_DIRECTORY:
111         p_control = new DirectoryConfigControl( p_this, p_item, parent, l,
112                                                 line, false );
113         break;
114     case CONFIG_ITEM_FONT:
115         p_control = new FontConfigControl( p_this, p_item, parent, l,
116                                            line, false );
117         break;
118     case CONFIG_ITEM_KEY:
119         p_control = new KeySelectorControl( p_this, p_item, parent, l, line );
120         break;
121     case CONFIG_ITEM_BOOL:
122         p_control = new BoolConfigControl( p_this, p_item, parent, l, line );
123         break;
124     case CONFIG_ITEM_FLOAT:
125         if( p_item->min.f || p_item->max.f )
126             p_control = new FloatRangeConfigControl( p_this, p_item, parent,
127                                                      l, line );
128         else
129             p_control = new FloatConfigControl( p_this, p_item, parent,
130                                                   l, line );
131         break;
132     default:
133         break;
134     }
135     return p_control;
136 }
137
138 void ConfigControl::doApply( intf_thread_t *p_intf )
139 {
140     switch( getType() )
141     {
142         case 1:
143         {
144             VIntConfigControl *vicc = qobject_cast<VIntConfigControl *>(this);
145             assert( vicc );
146             config_PutInt( p_intf, vicc->getName(), vicc->getValue() );
147             break;
148         }
149         case 2:
150         {
151             VFloatConfigControl *vfcc =
152                                     qobject_cast<VFloatConfigControl *>(this);
153             assert( vfcc );
154             config_PutFloat( p_intf, vfcc->getName(), vfcc->getValue() );
155             break;
156         }
157         case 3:
158         {
159             VStringConfigControl *vscc =
160                             qobject_cast<VStringConfigControl *>(this);
161             assert( vscc );
162             config_PutPsz( p_intf, vscc->getName(), qta( vscc->getValue() ) );
163             break;
164         }
165         case 4:
166         {
167             KeySelectorControl *ksc = qobject_cast<KeySelectorControl *>(this);
168             assert( ksc );
169             ksc->doApply();
170         }
171     }
172 }
173
174 /**************************************************************************
175  * String-based controls
176  *************************************************************************/
177
178 /*********** String **************/
179 StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
180                                           module_config_t *_p_item,
181                                           QWidget *_parent, QGridLayout *l,
182                                           int &line, bool pwd ) :
183                            VStringConfigControl( _p_this, _p_item, _parent )
184 {
185     label = new QLabel( qfu(p_item->psz_text) );
186     text = new QLineEdit( qfu(p_item->value.psz) );
187     finish();
188
189     if( !l )
190     {
191         QHBoxLayout *layout = new QHBoxLayout();
192         layout->addWidget( label, 0 ); layout->addWidget( text, 1 );
193         widget->setLayout( layout );
194     }
195     else
196     {
197         l->addWidget( label, line, 0 ); l->addWidget( text, line, 1 );
198     }
199 }
200
201 StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
202                                    module_config_t *_p_item,
203                                    QLabel *_label, QLineEdit *_text, bool pwd ):
204                            VStringConfigControl( _p_this, _p_item )
205 {
206     text = _text;
207     label = _label;
208     finish( );
209 }
210
211 void StringConfigControl::finish()
212 {
213     text->setText( qfu(p_item->value.psz) );
214     text->setToolTip( qfu(p_item->psz_longtext) );
215     if( label )
216         label->setToolTip( qfu(p_item->psz_longtext) );
217 }
218
219 /*********** File **************/
220 FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
221                                           module_config_t *_p_item,
222                                           QWidget *_parent, QGridLayout *l,
223                                           int &line, bool pwd ) :
224                            VStringConfigControl( _p_this, _p_item, _parent )
225 {
226     label = new QLabel( qfu(p_item->psz_text) );
227     text = new QLineEdit( qfu(p_item->value.psz) );
228     browse = new QPushButton( qtr( "Browse..." ) );
229
230     BUTTONACT( browse, updateField() );
231
232     finish();
233
234     if( !l )
235     {
236         QHBoxLayout *layout = new QHBoxLayout();
237         layout->addWidget( label, 0 ); layout->addWidget( text, 1 );
238         layout->addWidget( browse, 2 );
239         widget->setLayout( layout );
240     }
241     else
242     {
243         l->addWidget( label, line, 0 ); l->addWidget( text, line, 1 );
244         l->addWidget( browse, line, 2 );
245     }
246 }
247
248
249 FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
250                                    module_config_t *_p_item,
251                                    QLabel *_label, QLineEdit *_text,
252                                    QPushButton *_button, bool pwd ):
253                            VStringConfigControl( _p_this, _p_item )
254 {
255     browse = _button;
256     text = _text;
257     label = _label;
258
259     BUTTONACT( browse, updateField() );
260
261     finish( );
262 }
263
264 void FileConfigControl::updateField()
265 {
266     QString file = QFileDialog::getOpenFileName( NULL,
267                   qtr( "Select File" ), qfu( p_this->p_libvlc->psz_homedir ) );
268     if( file.isNull() ) return;
269     text->setText( file );
270 }
271
272 void FileConfigControl::finish()
273 {
274     text->setText( qfu(p_item->value.psz) );
275     text->setToolTip( qfu(p_item->psz_longtext) );
276     if( label )
277         label->setToolTip( qfu(p_item->psz_longtext) );
278 }
279
280 /********* String / Directory **********/
281 DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
282                         module_config_t *_p_item, QWidget *_p_widget,
283                         QGridLayout *_p_layout, int& _int, bool _pwd ) :
284      FileConfigControl( _p_this, _p_item, _p_widget, _p_layout, _int, _pwd)
285 {}
286
287 DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
288                         module_config_t *_p_item, QLabel *_p_label,
289                         QLineEdit *_p_line, QPushButton *_p_button, bool _pwd ):
290      FileConfigControl( _p_this, _p_item, _p_label, _p_line, _p_button, _pwd)
291 {}
292
293 void DirectoryConfigControl::updateField()
294 {
295     QString dir = QFileDialog::getExistingDirectory( NULL,
296                       qtr( "Select Directory" ),
297                       text->text().isEmpty() ?
298                         qfu( p_this->p_libvlc->psz_homedir ) : text->text(),
299                       QFileDialog::ShowDirsOnly |
300                         QFileDialog::DontResolveSymlinks );
301     if( dir.isNull() ) return;
302     text->setText( dir );
303 }
304
305 /********* String / Font **********/
306 FontConfigControl::FontConfigControl( vlc_object_t *_p_this,
307                         module_config_t *_p_item, QWidget *_p_widget,
308                         QGridLayout *_p_layout, int& _int, bool _pwd ) :
309      FileConfigControl( _p_this, _p_item, _p_widget, _p_layout, _int, _pwd)
310 {}
311
312 FontConfigControl::FontConfigControl( vlc_object_t *_p_this,
313                         module_config_t *_p_item, QLabel *_p_label,
314                         QLineEdit *_p_line, QPushButton *_p_button, bool _pwd ):
315      FileConfigControl( _p_this, _p_item, _p_label, _p_line, _p_button, _pwd)
316 {}
317
318 void FontConfigControl::updateField()
319 {
320     bool ok;
321     QFont font = QFontDialog::getFont( &ok, QFont( text->text() ), NULL );
322     if( !ok ) return;
323     text->setText( font.family() );
324 }
325
326 /********* String / choice list **********/
327 StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
328                module_config_t *_p_item, QWidget *_parent, bool bycat,
329                QGridLayout *l, int &line) :
330                VStringConfigControl( _p_this, _p_item, _parent )
331 {
332     label = new QLabel( qfu(p_item->psz_text) );
333     combo = new QComboBox();
334     finish( bycat );
335     if( !l )
336     {
337         QHBoxLayout *layout = new QHBoxLayout();
338         layout->addWidget( label ); layout->addWidget( combo );
339         widget->setLayout( layout );
340     }
341     else
342     {
343         l->addWidget( label, line, 0 );
344         l->addWidget( combo, line, 1, Qt::AlignRight );
345     }
346 }
347 StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
348                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
349                 bool bycat ) : VStringConfigControl( _p_this, _p_item )
350 {
351     combo = _combo;
352     label = _label;
353     finish( bycat );
354 }
355
356 void StringListConfigControl::finish( bool bycat )
357 {
358     combo->setEditable( false );
359
360     for( int i_index = 0; i_index < p_item->i_list; i_index++ )
361     {
362         combo->addItem( qfu(p_item->ppsz_list_text ?
363                             p_item->ppsz_list_text[i_index] :
364                             p_item->ppsz_list[i_index] ),
365                         QVariant( p_item->ppsz_list[i_index] ) );
366         if( p_item->value.psz && !strcmp( p_item->value.psz,
367                                           p_item->ppsz_list[i_index] ) )
368             combo->setCurrentIndex( combo->count() - 1 );
369     }
370     combo->setToolTip( qfu(p_item->psz_longtext) );
371     if( label )
372         label->setToolTip( qfu(p_item->psz_longtext) );
373 }
374
375 QString StringListConfigControl::getValue()
376 {
377     return combo->itemData( combo->currentIndex() ).toString();
378 }
379
380 /********* Module **********/
381 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
382                module_config_t *_p_item, QWidget *_parent, bool bycat,
383                QGridLayout *l, int &line) :
384                VStringConfigControl( _p_this, _p_item, _parent )
385 {
386     label = new QLabel( qfu(p_item->psz_text) );
387     combo = new QComboBox();
388     finish( bycat );
389     if( !l )
390     {
391         QHBoxLayout *layout = new QHBoxLayout();
392         layout->addWidget( label ); layout->addWidget( combo );
393         widget->setLayout( layout );
394     }
395     else
396     {
397         l->addWidget( label, line, 0 );
398         l->addWidget( combo, line, 1, Qt::AlignRight );
399     }
400 }
401 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
402                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
403                 bool bycat ) : VStringConfigControl( _p_this, _p_item )
404 {
405     combo = _combo;
406     label = _label;
407     finish( bycat );
408 }
409
410 void ModuleConfigControl::finish( bool bycat )
411 {
412     vlc_list_t *p_list;
413     module_t *p_parser;
414
415     combo->setEditable( false );
416
417     /* build a list of available modules */
418     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
419     combo->addItem( qtr("Default") );
420     for( int i_index = 0; i_index < p_list->i_count; i_index++ )
421     {
422         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
423
424         if( bycat )
425         {
426             if( !strcmp( p_parser->psz_object_name, "main" ) ) continue;
427
428             for (size_t i = 0; i < p_parser->confsize; i++)
429             {
430                 module_config_t *p_config = p_parser->p_config + i;
431                 /* Hack: required subcategory is stored in i_min */
432                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
433                     p_config->value.i == p_item->min.i )
434                     combo->addItem( qfu(p_parser->psz_longname),
435                                     QVariant( p_parser->psz_object_name ) );
436                 if( p_item->value.psz && !strcmp( p_item->value.psz,
437                                                   p_parser->psz_object_name) )
438                     combo->setCurrentIndex( combo->count() - 1 );
439             }
440         }
441         else if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )
442         {
443             combo->addItem( qfu(p_parser->psz_longname),
444                             QVariant( p_parser->psz_object_name ) );
445             if( p_item->value.psz && !strcmp( p_item->value.psz,
446                                               p_parser->psz_object_name) )
447                 combo->setCurrentIndex( combo->count() - 1 );
448         }
449     }
450     vlc_list_release( p_list );
451     combo->setToolTip( qfu(p_item->psz_longtext) );
452     if( label )
453         label->setToolTip( qfu(p_item->psz_longtext) );
454 }
455
456 QString ModuleConfigControl::getValue()
457 {
458     return combo->itemData( combo->currentIndex() ).toString();
459 }
460
461 /********* Module list **********/
462 ModuleListConfigControl::ModuleListConfigControl( vlc_object_t *_p_this,
463                module_config_t *_p_item, QWidget *_parent, bool bycat,
464                QGridLayout *l, int &line) :
465                VStringConfigControl( _p_this, _p_item, _parent )
466 {
467     label = new QLabel( qfu(p_item->psz_text) );
468     text = new QLineEdit();
469     finish( bycat );
470
471     bool pom = false;
472     if( !l )
473     {
474         l = new QGridLayout();
475         line = 0;
476         pom = true;
477     }
478     for( QVector<QCheckBox*>::iterator it = modules.begin();
479          it != modules.end(); it++ )
480     {
481         l->addWidget( *it, line++, 1 );
482     }
483     l->addWidget( label, line, 0 );
484     l->addWidget( text, line, 1 );
485     if( pom )
486         widget->setLayout( l );
487 }
488 #if 0
489 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
490                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
491                 bool bycat ) : VStringConfigControl( _p_this, _p_item )
492 {
493     combo = _combo;
494     label = _label;
495     finish( bycat );
496 }
497 #endif
498
499 ModuleListConfigControl::~ModuleListConfigControl()
500 {
501     for( QVector<QCheckBox*>::iterator it = modules.begin();
502          it != modules.end(); it++ )
503     {
504         delete *it;
505     }
506     delete label;
507     delete text;
508 }
509
510 void ModuleListConfigControl::finish( bool bycat )
511 {
512     vlc_list_t *p_list;
513     module_t *p_parser;
514
515     /* build a list of available modules */
516     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
517     for( int i_index = 0; i_index < p_list->i_count; i_index++ )
518     {
519         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
520
521         if( bycat )
522         {
523             if( !strcmp( p_parser->psz_object_name, "main" ) ) continue;
524
525             for (size_t i = 0; i < p_parser->confsize; i++)
526             {
527                 module_config_t *p_config = p_parser->p_config + i;
528                 /* Hack: required subcategory is stored in i_min */
529                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
530                     p_config->value.i == p_item->min.i )
531                 {
532                     QCheckBox *cb =
533                         new QCheckBox( qfu( p_parser->psz_object_name ) );
534                     cb->setToolTip( qfu(p_parser->psz_longname) );
535                     modules.push_back( cb );
536                 }
537             }
538         }
539         else if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )
540         {
541             QCheckBox *cb =
542                 new QCheckBox( qfu( p_parser->psz_object_name ) );
543             cb->setToolTip( qfu(p_parser->psz_longname) );
544             modules.push_back( cb );
545         }
546     }
547     vlc_list_release( p_list );
548     text->setToolTip( qfu(p_item->psz_longtext) );
549     if( label )
550         label->setToolTip( qfu(p_item->psz_longtext) );
551 }
552
553 QString ModuleListConfigControl::getValue()
554 {
555     return text->text();
556 }
557
558 void ModuleListConfigControl::hide()
559 {
560     for( QVector<QCheckBox*>::iterator it = modules.begin();
561          it != modules.end(); it++ )
562     {
563         (*it)->hide();
564     }
565     text->hide();
566     label->hide();
567 }
568
569 void ModuleListConfigControl::show()
570 {
571     for( QVector<QCheckBox*>::iterator it = modules.begin();
572          it != modules.end(); it++ )
573     {
574         (*it)->show();
575     }
576     text->show();
577     label->show();
578 }
579
580
581 void ModuleListConfigControl::wakeUp_TheUserJustClickedOnSomething( int value )
582 {
583     text->clear();
584     for( QVector<QCheckBox*>::iterator it = modules.begin();
585          it != modules.end(); it++ )
586     {
587     }
588 }
589
590 /**************************************************************************
591  * Integer-based controls
592  *************************************************************************/
593
594 /*********** Integer **************/
595 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
596                                             module_config_t *_p_item,
597                                             QWidget *_parent, QGridLayout *l,
598                                             int &line ) :
599                            VIntConfigControl( _p_this, _p_item, _parent )
600 {
601     label = new QLabel( qfu(p_item->psz_text) );
602     spin = new QSpinBox; spin->setMinimumWidth( 80 );
603     spin->setMaximumWidth( 90 );
604     finish();
605
606     if( !l )
607     {
608         QHBoxLayout *layout = new QHBoxLayout();
609         layout->addWidget( label, 0 ); layout->addWidget( spin, 1 );
610         widget->setLayout( layout );
611     }
612     else
613     {
614         l->addWidget( label, line, 0 );
615         l->addWidget( spin, line, 1, Qt::AlignRight );
616     }
617 }
618 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
619                                             module_config_t *_p_item,
620                                             QLabel *_label, QSpinBox *_spin ) :
621                                       VIntConfigControl( _p_this, _p_item )
622 {
623     spin = _spin;
624     label = _label;
625     finish();
626 }
627
628 void IntegerConfigControl::finish()
629 {
630     spin->setMaximum( 2000000000 );
631     spin->setMinimum( -2000000000 );
632     spin->setValue( p_item->value.i );
633     spin->setToolTip( qfu(p_item->psz_longtext) );
634     if( label )
635         label->setToolTip( qfu(p_item->psz_longtext) );
636 }
637
638 int IntegerConfigControl::getValue()
639 {
640     return spin->value();
641 }
642
643 /********* Integer range **********/
644 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
645                                             module_config_t *_p_item,
646                                             QWidget *_parent, QGridLayout *l,
647                                             int &line ) :
648             IntegerConfigControl( _p_this, _p_item, _parent, l, line )
649 {
650     finish();
651 }
652
653 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
654                                             module_config_t *_p_item,
655                                             QLabel *_label, QSpinBox *_spin ) :
656             IntegerConfigControl( _p_this, _p_item, _label, _spin )
657 {
658     finish();
659 }
660
661 void IntegerRangeConfigControl::finish()
662 {
663     spin->setMaximum( p_item->max.i );
664     spin->setMinimum( p_item->min.i );
665 }
666
667 IntegerRangeSliderConfigControl::IntegerRangeSliderConfigControl(
668                                             vlc_object_t *_p_this,
669                                             module_config_t *_p_item,
670                                             QLabel *_label, QSlider *_slider ):
671                     VIntConfigControl( _p_this, _p_item )
672 {
673     slider = _slider;
674     label = _label;
675     slider->setMaximum( p_item->max.i );
676     slider->setMinimum( p_item->min.i );
677     slider->setValue( p_item->value.i );
678     slider->setToolTip( qfu(p_item->psz_longtext) );
679     if( label )
680         label->setToolTip( qfu(p_item->psz_longtext) );
681 }
682
683 int IntegerRangeSliderConfigControl::getValue()
684 {
685         return slider->value();
686 }
687
688
689 /********* Integer / choice list **********/
690 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
691                module_config_t *_p_item, QWidget *_parent, bool bycat,
692                QGridLayout *l, int &line) :
693                VIntConfigControl( _p_this, _p_item, _parent )
694 {
695     label = new QLabel( qfu(p_item->psz_text) );
696     combo = new QComboBox();
697     finish( bycat );
698     if( !l )
699     {
700         QHBoxLayout *layout = new QHBoxLayout();
701         layout->addWidget( label ); layout->addWidget( combo );
702         widget->setLayout( layout );
703     }
704     else
705     {
706         l->addWidget( label, line, 0 );
707         l->addWidget( combo, line, 1, Qt::AlignRight );
708     }
709 }
710 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
711                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
712                 bool bycat ) : VIntConfigControl( _p_this, _p_item )
713 {
714     combo = _combo;
715     label = _label;
716     finish( bycat );
717 }
718
719 void IntegerListConfigControl::finish( bool bycat )
720 {
721     combo->setEditable( false );
722
723     for( int i_index = 0; i_index < p_item->i_list; i_index++ )
724     {
725         combo->addItem( qfu(p_item->ppsz_list_text[i_index] ),
726                         QVariant( p_item->pi_list[i_index] ) );
727         if( p_item->value.i == p_item->pi_list[i_index] )
728             combo->setCurrentIndex( combo->count() - 1 );
729     }
730     combo->setToolTip( qfu(p_item->psz_longtext) );
731     if( label )
732         label->setToolTip( qfu(p_item->psz_longtext) );
733 }
734
735 int IntegerListConfigControl::getValue()
736 {
737     return combo->itemData( combo->currentIndex() ).toInt();
738 }
739
740 /*********** Boolean **************/
741 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
742                                       module_config_t *_p_item,
743                                       QWidget *_parent, QGridLayout *l,
744                                       int &line ) :
745                     VIntConfigControl( _p_this, _p_item, _parent )
746 {
747     checkbox = new QCheckBox( qfu(p_item->psz_text) );
748     finish();
749
750     if( !l )
751     {
752         QHBoxLayout *layout = new QHBoxLayout();
753         layout->addWidget( checkbox, 0 );
754         widget->setLayout( layout );
755     }
756     else
757     {
758         l->addWidget( checkbox, line, 0 );
759     }
760 }
761 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
762                                       module_config_t *_p_item,
763                                       QLabel *_label,
764                                       QCheckBox *_checkbox,
765                                       bool bycat ) :
766                    VIntConfigControl( _p_this, _p_item )
767 {
768     checkbox = _checkbox;
769     finish();
770 }
771
772 void BoolConfigControl::finish()
773 {
774     checkbox->setCheckState( p_item->value.i == VLC_TRUE ? Qt::Checked
775                                                         : Qt::Unchecked );
776     checkbox->setToolTip( qfu(p_item->psz_longtext) );
777 }
778
779 int BoolConfigControl::getValue()
780 {
781     return checkbox->checkState() == Qt::Checked ? VLC_TRUE : VLC_FALSE;
782 }
783
784 /**************************************************************************
785  * Float-based controls
786  *************************************************************************/
787
788 /*********** Float **************/
789 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
790                                         module_config_t *_p_item,
791                                         QWidget *_parent, QGridLayout *l,
792                                         int &line ) :
793                     VFloatConfigControl( _p_this, _p_item, _parent )
794 {
795     label = new QLabel( qfu(p_item->psz_text) );
796     spin = new QDoubleSpinBox; spin->setMinimumWidth( 80 );
797     spin->setMaximumWidth( 90 );
798     finish();
799
800     if( !l )
801     {
802         QHBoxLayout *layout = new QHBoxLayout();
803         layout->addWidget( label, 0 ); layout->addWidget( spin, 1 );
804         widget->setLayout( layout );
805     }
806     else
807     {
808         l->addWidget( label, line, 0 );
809         l->addWidget( spin, line, 1, Qt::AlignRight );
810     }
811 }
812
813 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
814                                         module_config_t *_p_item,
815                                         QLabel *_label,
816                                         QDoubleSpinBox *_spin ) :
817                     VFloatConfigControl( _p_this, _p_item )
818 {
819     spin = _spin;
820     label = _label;
821     finish();
822 }
823
824 void FloatConfigControl::finish()
825 {
826     spin->setMaximum( 2000000000. );
827     spin->setMinimum( -2000000000. );
828     spin->setSingleStep( 0.1 );
829     spin->setValue( (double)p_item->value.f );
830     spin->setToolTip( qfu(p_item->psz_longtext) );
831     if( label )
832         label->setToolTip( qfu(p_item->psz_longtext) );
833 }
834
835 float FloatConfigControl::getValue()
836 {
837     return (float)spin->value();
838 }
839
840 /*********** Float with range **************/
841 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
842                                         module_config_t *_p_item,
843                                         QWidget *_parent, QGridLayout *l,
844                                         int &line ) :
845                 FloatConfigControl( _p_this, _p_item, _parent, l, line )
846 {
847     finish();
848 }
849
850 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
851                                         module_config_t *_p_item,
852                                         QLabel *_label,
853                                         QDoubleSpinBox *_spin ) :
854                 FloatConfigControl( _p_this, _p_item, _label, _spin )
855 {
856     finish();
857 }
858
859 void FloatRangeConfigControl::finish()
860 {
861     spin->setMaximum( (double)p_item->max.f );
862     spin->setMinimum( (double)p_item->min.f );
863 }
864
865
866 /**********************************************************************
867  * Key selector widget
868  **********************************************************************/
869 KeySelectorControl::KeySelectorControl( vlc_object_t *_p_this,
870                                       module_config_t *_p_item,
871                                       QWidget *_parent, QGridLayout *l,
872                                       int &line ) :
873                                 ConfigControl( _p_this, _p_item, _parent )
874
875 {
876     label = new QLabel( qtr("Select an action to change the associated hotkey") );
877     table = new QTreeWidget( 0 );
878     finish();
879
880     if( !l )
881     {
882         QVBoxLayout *layout = new QVBoxLayout();
883         layout->addWidget( label, 0 ); layout->addWidget( table, 1 );
884         widget->setLayout( layout );
885     }
886     else
887     {
888         l->addWidget( label, line, 0, 1, 2 );
889         l->addWidget( table, line+1, 0, 1,2 );
890     }
891 }
892
893 void KeySelectorControl::finish()
894 {
895     if( label )
896         label->setToolTip( qfu(p_item->psz_longtext) );
897
898     /* Fill the table */
899     table->setColumnCount( 2 );
900     table->setAlternatingRowColors( true );
901
902     module_t *p_main = config_FindModule( p_this, "main" );
903     assert( p_main );
904
905     for (size_t i = 0; i < p_main->confsize; i++)
906     {
907         module_config_t *p_item = p_main->p_config + i;
908
909         if( p_item->i_type & CONFIG_ITEM && p_item->psz_name &&
910             strstr( p_item->psz_name , "key-" ) )
911         {
912             QTreeWidgetItem *treeItem = new QTreeWidgetItem();
913             treeItem->setText( 0, qfu( p_item->psz_text ) );
914             treeItem->setText( 1, VLCKeyToString( p_item->value.i ) );
915             treeItem->setData( 0, Qt::UserRole,
916                                   QVariant::fromValue( (void*)p_item ) );
917             values += p_item;
918             table->addTopLevelItem( treeItem );
919         }
920     }
921     table->resizeColumnToContents( 0 );
922
923     CONNECT( table, itemDoubleClicked( QTreeWidgetItem *, int ),
924              this, selectKey( QTreeWidgetItem * ) );
925 }
926
927 void KeySelectorControl::selectKey( QTreeWidgetItem *keyItem )
928 {
929    module_config_t *p_keyItem = static_cast<module_config_t*>
930                           (keyItem->data( 0, Qt::UserRole ).value<void*>());
931
932     KeyInputDialog *d = new KeyInputDialog( values, p_keyItem->psz_text );
933     d->exec();
934     if( d->result() == QDialog::Accepted )
935     {
936         p_keyItem->value.i = d->keyValue;
937         if( d->conflicts )
938         {
939             for( int i = 0; i < table->topLevelItemCount() ; i++ )
940             {
941                 QTreeWidgetItem *it = table->topLevelItem(i);
942                 module_config_t *p_item = static_cast<module_config_t*>
943                               (it->data( 0, Qt::UserRole ).value<void*>());
944                 it->setText( 1, VLCKeyToString( p_item->value.i ) );
945             }
946         }
947         else
948             keyItem->setText( 1, VLCKeyToString( p_keyItem->value.i ) );
949     }
950     delete d;
951 }
952
953 void KeySelectorControl::doApply()
954 {
955     foreach( module_config_t *p_current, values )
956     {
957         config_PutInt( p_this, p_current->psz_name, p_current->value.i );
958     }
959 }
960
961 KeyInputDialog::KeyInputDialog( QList<module_config_t*>& _values,
962                                 const char * _keyToChange ) :
963                                                 QDialog(0), keyValue(0)
964 {
965     setModal( true );
966     values = _values;
967     conflicts = false;
968     keyToChange = _keyToChange;
969     setWindowTitle( qtr( "Hotkey for " ) + qfu( keyToChange)  );
970
971     QVBoxLayout *l = new QVBoxLayout( this );
972     selected = new QLabel( qtr("Press the new keys for ")  + qfu(keyToChange) );
973     warning = new QLabel();
974     l->addWidget( selected , Qt::AlignCenter );
975     l->addWidget( warning, Qt::AlignCenter );
976
977     QHBoxLayout *l2 = new QHBoxLayout();
978     QPushButton *ok = new QPushButton( qtr("OK") );
979     l2->addWidget( ok );
980     QPushButton *cancel = new QPushButton( qtr("Cancel") );
981     l2->addWidget( cancel );
982
983     BUTTONACT( ok, accept() );
984     BUTTONACT( cancel, reject() );
985
986     l->addLayout( l2 );
987 }
988
989 void KeyInputDialog::checkForConflicts( int i_vlckey )
990 {
991     conflicts = false;
992     module_config_t *p_current = NULL;
993     foreach( p_current, values )
994     {
995         if( p_current->value.i == i_vlckey && strcmp( p_current->psz_text,
996                                                     keyToChange ) )
997         {
998             p_current->value.i = 0;
999             conflicts = true;
1000             break;
1001         }
1002     }
1003     if( conflicts )
1004     {
1005         warning->setText(
1006           qtr("Warning: the  key is already assigned to \"") +
1007           QString( p_current->psz_text ) + "\"" );
1008     }
1009     else warning->setText( "" );
1010 }
1011
1012 void KeyInputDialog::keyPressEvent( QKeyEvent *e )
1013 {
1014     if( e->key() == Qt::Key_Tab ) return;
1015     int i_vlck = qtEventToVLCKey( e );
1016     selected->setText( VLCKeyToString( i_vlck ) );
1017     checkForConflicts( i_vlck );
1018     keyValue = i_vlck;
1019 }
1020
1021 void KeyInputDialog::wheelEvent( QWheelEvent *e )
1022 {
1023     int i_vlck = qtWheelEventToVLCKey( e );
1024     selected->setText( VLCKeyToString( i_vlck ) );
1025     checkForConflicts( i_vlck );
1026     keyValue = i_vlck;
1027 }