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