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