]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/preferences_widgets.cpp
Qt4 - Preferences: spaces and comments.
[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, 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
49 QString formatTooltip(const QString & tooltip)
50 {
51     QString formatted =
52     "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">"
53     " p, li { white-space: pre-wrap; } </style></head><body style=\" font-family:'Sans Serif';"
54     " font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;\">"
55     "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; "
56     "-qt-block-indent:0; text-indent:0px;\">" +
57     tooltip +
58     "</p></body></html>";
59     return formatted;
60 }
61
62 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
63                                              module_config_t *p_item,
64                                              QWidget *parent )
65 {
66     int i=0;
67     return createControl( p_this, p_item, parent, NULL, i );
68 }
69
70 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
71                                              module_config_t *p_item,
72                                              QWidget *parent,
73                                              QGridLayout *l, int &line )
74 {
75     ConfigControl *p_control = NULL;
76     if( p_item->psz_current || p_item->b_unsaveable ) return 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     finish( bycat );
357     if( !l )
358     {
359         QHBoxLayout *layout = new QHBoxLayout();
360         layout->addWidget( label ); layout->addWidget( combo );
361         widget->setLayout( layout );
362     }
363     else
364     {
365         l->addWidget( label, line, 0 );
366         l->addWidget( combo, line, 1, Qt::AlignRight );
367     }
368
369     if( p_item->i_action )
370     {
371         QSignalMapper *signalMapper = new QSignalMapper(this);
372
373         /* Some stringLists like Capture listings have action associated */
374         for( int i = 0; i < p_item->i_action; i++ )
375         {
376             QPushButton *button =
377                 new QPushButton( qfu( p_item->ppsz_action_text[i] ));
378             CONNECT( button, clicked(), signalMapper, map() );
379             signalMapper->setMapping( button, i );
380             l->addWidget( button, line, 2 + i, Qt::AlignRight );
381         }
382         CONNECT( signalMapper, mapped( int ),
383                 this, actionRequested( int ) );
384     }
385 }
386
387 void StringListConfigControl::actionRequested( int i_action )
388 {
389     /* Supplementary check for boundaries */
390     if( i_action < 0 || i_action >= p_item->i_action ) return;
391
392     vlc_value_t val;
393     val.psz_string = qtu( (combo->itemData( combo->currentIndex() ).toString() ) );
394
395     p_item->ppf_action[i_action]( p_this, getName(), val, val, 0 );
396
397     if( p_item->b_dirty )
398     {
399         combo->clear();
400         finish( true );
401         p_item->b_dirty = VLC_FALSE;
402     }
403 }
404 StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
405                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
406                 bool bycat ) : VStringConfigControl( _p_this, _p_item )
407 {
408     combo = _combo;
409     label = _label;
410     finish( bycat );
411 }
412
413 void StringListConfigControl::finish( bool bycat )
414 {
415     combo->setEditable( false );
416
417     for( int i_index = 0; i_index < p_item->i_list; i_index++ )
418     {
419         combo->addItem( qfu(p_item->ppsz_list_text ?
420                             p_item->ppsz_list_text[i_index] :
421                             p_item->ppsz_list[i_index] ),
422                         QVariant( p_item->ppsz_list[i_index] ) );
423         if( p_item->value.psz && !strcmp( p_item->value.psz,
424                                           p_item->ppsz_list[i_index] ) )
425             combo->setCurrentIndex( combo->count() - 1 );
426     }
427     combo->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
428     if( label )
429         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
430 }
431
432 QString StringListConfigControl::getValue()
433 {
434     return combo->itemData( combo->currentIndex() ).toString();
435 }
436
437 void setfillVLCConfigCombo( const char *configname, intf_thread_t *p_intf,
438                         QComboBox *combo, QWidget *parent )
439 {
440     module_config_t *p_config =
441                       config_FindConfig( VLC_OBJECT(p_intf), configname );
442     if( p_config )
443     {
444         for ( int i_index = 0; i_index < p_config->i_list; i_index++ )
445         {
446             combo->addItem( qfu( p_config->ppsz_list_text[i_index] ),
447                     QVariant( p_config->pi_list[i_index] ) );
448             if( p_config->value.i == p_config->pi_list[i_index] )
449             {
450                 combo->setCurrentIndex( i_index );
451             }
452         }
453         combo->setToolTip( qfu( p_config->psz_longtext ) );
454     }
455 }
456
457 /********* Module **********/
458 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
459                module_config_t *_p_item, QWidget *_parent, bool bycat,
460                QGridLayout *l, int &line) :
461                VStringConfigControl( _p_this, _p_item, _parent )
462 {
463     label = new QLabel( qtr(p_item->psz_text) );
464     combo = new QComboBox();
465     finish( bycat );
466     if( !l )
467     {
468         QHBoxLayout *layout = new QHBoxLayout();
469         layout->addWidget( label ); layout->addWidget( combo );
470         widget->setLayout( layout );
471     }
472     else
473     {
474         l->addWidget( label, line, 0 );
475         l->addWidget( combo, line, 1, Qt::AlignRight );
476     }
477 }
478
479 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
480                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
481                 bool bycat ) : VStringConfigControl( _p_this, _p_item )
482 {
483     combo = _combo;
484     label = _label;
485     finish( bycat );
486 }
487
488 void ModuleConfigControl::finish( bool bycat )
489 {
490     vlc_list_t *p_list;
491     module_t *p_parser;
492
493     combo->setEditable( false );
494
495     /* build a list of available modules */
496     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
497     combo->addItem( qtr("Default") );
498     for( int i_index = 0; i_index < p_list->i_count; i_index++ )
499     {
500         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
501
502         if( bycat )
503         {
504             if( !strcmp( module_GetObjName( p_parser ), "main" ) ) continue;
505
506             for (size_t i = 0; i < p_parser->confsize; i++)
507             {
508                 module_config_t *p_config = p_parser->p_config + i;
509                 /* Hack: required subcategory is stored in i_min */
510                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
511                     p_config->value.i == p_item->min.i )
512                     combo->addItem( qtr( module_GetLongName( p_parser )),
513                                     QVariant( module_GetObjName( p_parser ) ) );
514                 if( p_item->value.psz && !strcmp( p_item->value.psz,
515                                                   module_GetObjName( p_parser ) ) )
516                     combo->setCurrentIndex( combo->count() - 1 );
517             }
518         }
519         else if( module_IsCapable( p_parser, p_item->psz_type ) )
520         {
521             combo->addItem( qtr(module_GetLongName( p_parser ) ),
522                             QVariant( module_GetObjName( p_parser ) ) );
523             if( p_item->value.psz && !strcmp( p_item->value.psz,
524                                               module_GetObjName( p_parser ) ) )
525                 combo->setCurrentIndex( combo->count() - 1 );
526         }
527     }
528     vlc_list_release( p_list );
529     combo->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
530     if( label )
531         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
532 }
533
534 QString ModuleConfigControl::getValue()
535 {
536     return combo->itemData( combo->currentIndex() ).toString();
537 }
538
539 /********* Module list **********/
540 ModuleListConfigControl::ModuleListConfigControl( vlc_object_t *_p_this,
541         module_config_t *_p_item, QWidget *_parent, bool bycat,
542         QGridLayout *l, int &line) :
543     VStringConfigControl( _p_this, _p_item, _parent )
544 {
545     groupBox = new QGroupBox ( qtr(p_item->psz_text) );
546     text = new QLineEdit();
547     QGridLayout *layoutGroupBox = new QGridLayout( groupBox );
548
549     finish( bycat );
550
551     int boxline = 0;
552     for( QVector<checkBoxListItem*>::iterator it = modules.begin();
553             it != modules.end(); it++ )
554     {
555         layoutGroupBox->addWidget( (*it)->checkBox, boxline++, 0 );
556     }
557     layoutGroupBox->addWidget( text, boxline, 0 );
558
559     if( !l )
560     {
561         QVBoxLayout *layout = new QVBoxLayout();
562         layout->addWidget( groupBox, line, 0 );
563         widget->setLayout( layout );
564     }
565     else
566     {
567         l->addWidget( groupBox, line, 0, 1, -1 );
568     }
569
570     text->setToolTip( formatTooltip( qtr( p_item->psz_longtext) ) );
571 }
572
573 ModuleListConfigControl::~ModuleListConfigControl()
574 {
575     for( QVector<checkBoxListItem*>::iterator it = modules.begin();
576             it != modules.end(); it++ )
577     {
578         delete *it;
579     }
580     delete groupBox;
581     delete text;
582 }
583
584 #define CHECKBOX_LISTS \
585 { \
586        QCheckBox *cb = new QCheckBox( qtr( module_GetLongName( p_parser ) ) );\
587        checkBoxListItem *cbl = new checkBoxListItem; \
588 \
589        CONNECT( cb, stateChanged( int ), this, onUpdate( int ) );\
590        cb->setToolTip( formatTooltip( qtr( module_GetLongName( p_parser ))));\
591        cbl->checkBox = cb; \
592 \
593        int i = -1; \
594        while( p_parser->pp_shortcuts[++i] != NULL); \
595        i--; \
596 \
597        cbl->psz_module = strdup( i>=0?p_parser->pp_shortcuts[i] \
598                                  : module_GetObjName( p_parser ) ); \
599        modules.push_back( cbl ); \
600 }
601
602
603 void ModuleListConfigControl::finish( bool bycat )
604 {
605     vlc_list_t *p_list;
606     module_t *p_parser;
607
608     /* build a list of available modules */
609     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
610     for( int i_index = 0; i_index < p_list->i_count; i_index++ )
611     {
612         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
613
614         if( bycat )
615         {
616             if( !strcmp( module_GetObjName( p_parser ), "main" ) ) continue;
617
618             for (size_t i = 0; i < p_parser->confsize; i++)
619             {
620                 module_config_t *p_config = p_parser->p_config + i;
621                 /* Hack: required subcategory is stored in i_min */
622                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
623                         p_config->value.i == p_item->min.i )
624                 {
625                     CHECKBOX_LISTS;
626                 }
627             }
628         }
629         else if( module_IsCapable( p_parser, p_item->psz_type ) )
630         {
631             CHECKBOX_LISTS;
632         }
633     }
634     vlc_list_release( p_list );
635     text->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
636     if( groupBox )
637         groupBox->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
638 }
639 #undef CHECKBOX_LISTS
640
641 QString ModuleListConfigControl::getValue()
642 {
643     return text->text();
644 }
645
646 void ModuleListConfigControl::hide()
647 {
648     for( QVector<checkBoxListItem*>::iterator it = modules.begin();
649          it != modules.end(); it++ )
650     {
651         (*it)->checkBox->hide();
652     }
653     groupBox->hide();
654 }
655
656 void ModuleListConfigControl::show()
657 {
658     for( QVector<checkBoxListItem*>::iterator it = modules.begin();
659          it != modules.end(); it++ )
660     {
661         (*it)->checkBox->show();
662     }
663     groupBox->show();
664 }
665
666
667 void ModuleListConfigControl::onUpdate( int value )
668 {
669     text->clear();
670     bool first = true;
671
672     for( QVector<checkBoxListItem*>::iterator it = modules.begin();
673          it != modules.end(); it++ )
674     {
675         if( (*it)->checkBox->isChecked() )
676         {
677             if( first )
678             {
679                 text->setText( text->text() + (*it)->psz_module );
680                 first = false;
681             }
682             else
683             {
684                 text->setText( text->text() + ":" + (*it)->psz_module );
685             }
686         }
687     }
688 }
689
690 /**************************************************************************
691  * Integer-based controls
692  *************************************************************************/
693
694 /*********** Integer **************/
695 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
696                                             module_config_t *_p_item,
697                                             QWidget *_parent, QGridLayout *l,
698                                             int &line ) :
699                            VIntConfigControl( _p_this, _p_item, _parent )
700 {
701     label = new QLabel( qtr(p_item->psz_text) );
702     spin = new QSpinBox; spin->setMinimumWidth( 80 );
703     spin->setAlignment( Qt::AlignRight );
704     spin->setMaximumWidth( 90 );
705     finish();
706
707     if( !l )
708     {
709         QHBoxLayout *layout = new QHBoxLayout();
710         layout->addWidget( label, 0 ); layout->addWidget( spin, 1 );
711         widget->setLayout( layout );
712     }
713     else
714     {
715         l->addWidget( label, line, 0 );
716         l->addWidget( spin, line, 1, Qt::AlignRight );
717     }
718 }
719 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
720                                             module_config_t *_p_item,
721                                             QLabel *_label, QSpinBox *_spin ) :
722                                       VIntConfigControl( _p_this, _p_item )
723 {
724     spin = _spin;
725     label = _label;
726     finish();
727 }
728
729 void IntegerConfigControl::finish()
730 {
731     spin->setMaximum( 2000000000 );
732     spin->setMinimum( -2000000000 );
733     spin->setValue( p_item->value.i );
734     spin->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
735     if( label )
736         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
737 }
738
739 int IntegerConfigControl::getValue()
740 {
741     return spin->value();
742 }
743
744 /********* Integer range **********/
745 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
746                                             module_config_t *_p_item,
747                                             QWidget *_parent, QGridLayout *l,
748                                             int &line ) :
749             IntegerConfigControl( _p_this, _p_item, _parent, l, line )
750 {
751     finish();
752 }
753
754 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
755                                             module_config_t *_p_item,
756                                             QLabel *_label, QSpinBox *_spin ) :
757             IntegerConfigControl( _p_this, _p_item, _label, _spin )
758 {
759     finish();
760 }
761
762 void IntegerRangeConfigControl::finish()
763 {
764     spin->setMaximum( p_item->max.i );
765     spin->setMinimum( p_item->min.i );
766 }
767
768 IntegerRangeSliderConfigControl::IntegerRangeSliderConfigControl(
769                                             vlc_object_t *_p_this,
770                                             module_config_t *_p_item,
771                                             QLabel *_label, QSlider *_slider ):
772                     VIntConfigControl( _p_this, _p_item )
773 {
774     slider = _slider;
775     label = _label;
776     slider->setMaximum( p_item->max.i );
777     slider->setMinimum( p_item->min.i );
778     slider->setValue( p_item->value.i );
779     slider->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
780     if( label )
781         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
782 }
783
784 int IntegerRangeSliderConfigControl::getValue()
785 {
786         return slider->value();
787 }
788
789
790 /********* Integer / choice list **********/
791 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
792                module_config_t *_p_item, QWidget *_parent, bool bycat,
793                QGridLayout *l, int &line) :
794                VIntConfigControl( _p_this, _p_item, _parent )
795 {
796     label = new QLabel( qtr(p_item->psz_text) );
797     combo = new QComboBox();
798     finish( bycat );
799     if( !l )
800     {
801         QHBoxLayout *layout = new QHBoxLayout();
802         layout->addWidget( label ); layout->addWidget( combo );
803         widget->setLayout( layout );
804     }
805     else
806     {
807         l->addWidget( label, line, 0 );
808         l->addWidget( combo, line, 1, Qt::AlignRight );
809     }
810 }
811 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
812                 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
813                 bool bycat ) : VIntConfigControl( _p_this, _p_item )
814 {
815     combo = _combo;
816     label = _label;
817     finish( bycat );
818 }
819
820 void IntegerListConfigControl::finish( bool bycat )
821 {
822     combo->setEditable( false );
823
824     for( int i_index = 0; i_index < p_item->i_list; i_index++ )
825     {
826         combo->addItem( qtr(p_item->ppsz_list_text[i_index] ),
827                         QVariant( p_item->pi_list[i_index] ) );
828         if( p_item->value.i == p_item->pi_list[i_index] )
829             combo->setCurrentIndex( combo->count() - 1 );
830     }
831     combo->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
832     if( label )
833         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
834 }
835
836 int IntegerListConfigControl::getValue()
837 {
838     return combo->itemData( combo->currentIndex() ).toInt();
839 }
840
841 /*********** Boolean **************/
842 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
843                                       module_config_t *_p_item,
844                                       QWidget *_parent, QGridLayout *l,
845                                       int &line ) :
846                     VIntConfigControl( _p_this, _p_item, _parent )
847 {
848     checkbox = new QCheckBox( qtr(p_item->psz_text) );
849     finish();
850
851     if( !l )
852     {
853         QHBoxLayout *layout = new QHBoxLayout();
854         layout->addWidget( checkbox, 0 );
855         widget->setLayout( layout );
856     }
857     else
858     {
859         l->addWidget( checkbox, line, 0 );
860     }
861 }
862 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
863                                       module_config_t *_p_item,
864                                       QLabel *_label,
865                                       QCheckBox *_checkbox,
866                                       bool bycat ) :
867                    VIntConfigControl( _p_this, _p_item )
868 {
869     checkbox = _checkbox;
870     finish();
871 }
872
873 void BoolConfigControl::finish()
874 {
875     checkbox->setCheckState( p_item->value.i == VLC_TRUE ? Qt::Checked
876                                                         : Qt::Unchecked );
877     checkbox->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
878 }
879
880 int BoolConfigControl::getValue()
881 {
882     return checkbox->checkState() == Qt::Checked ? VLC_TRUE : VLC_FALSE;
883 }
884
885 /**************************************************************************
886  * Float-based controls
887  *************************************************************************/
888
889 /*********** Float **************/
890 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
891                                         module_config_t *_p_item,
892                                         QWidget *_parent, QGridLayout *l,
893                                         int &line ) :
894                     VFloatConfigControl( _p_this, _p_item, _parent )
895 {
896     label = new QLabel( qtr(p_item->psz_text) );
897     spin = new QDoubleSpinBox; spin->setMinimumWidth( 80 );
898     spin->setMaximumWidth( 90 );
899     spin->setAlignment( Qt::AlignRight );
900     finish();
901
902     if( !l )
903     {
904         QHBoxLayout *layout = new QHBoxLayout();
905         layout->addWidget( label, 0 ); layout->addWidget( spin, 1 );
906         widget->setLayout( layout );
907     }
908     else
909     {
910         l->addWidget( label, line, 0 );
911         l->addWidget( spin, line, 1, Qt::AlignRight );
912     }
913 }
914
915 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
916                                         module_config_t *_p_item,
917                                         QLabel *_label,
918                                         QDoubleSpinBox *_spin ) :
919                     VFloatConfigControl( _p_this, _p_item )
920 {
921     spin = _spin;
922     label = _label;
923     finish();
924 }
925
926 void FloatConfigControl::finish()
927 {
928     spin->setMaximum( 2000000000. );
929     spin->setMinimum( -2000000000. );
930     spin->setSingleStep( 0.1 );
931     spin->setValue( (double)p_item->value.f );
932     spin->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
933     if( label )
934         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
935 }
936
937 float FloatConfigControl::getValue()
938 {
939     return (float)spin->value();
940 }
941
942 /*********** Float with range **************/
943 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
944                                         module_config_t *_p_item,
945                                         QWidget *_parent, QGridLayout *l,
946                                         int &line ) :
947                 FloatConfigControl( _p_this, _p_item, _parent, l, line )
948 {
949     finish();
950 }
951
952 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
953                                         module_config_t *_p_item,
954                                         QLabel *_label,
955                                         QDoubleSpinBox *_spin ) :
956                 FloatConfigControl( _p_this, _p_item, _label, _spin )
957 {
958     finish();
959 }
960
961 void FloatRangeConfigControl::finish()
962 {
963     spin->setMaximum( (double)p_item->max.f );
964     spin->setMinimum( (double)p_item->min.f );
965 }
966
967
968 /**********************************************************************
969  * Key selector widget
970  **********************************************************************/
971 KeySelectorControl::KeySelectorControl( vlc_object_t *_p_this,
972                                       module_config_t *_p_item,
973                                       QWidget *_parent, QGridLayout *l,
974                                       int &line ) :
975                                 ConfigControl( _p_this, _p_item, _parent )
976
977 {
978     label = new QLabel( qtr("Select an action to change the associated hotkey") );
979     table = new QTreeWidget( 0 );
980     finish();
981
982     if( !l )
983     {
984         QVBoxLayout *layout = new QVBoxLayout();
985         layout->addWidget( label, 0 ); layout->addWidget( table, 1 );
986         widget->setLayout( layout );
987     }
988     else
989     {
990         l->addWidget( label, line, 0, 1, 2 );
991         l->addWidget( table, line+1, 0, 1,2 );
992     }
993 }
994
995 void KeySelectorControl::finish()
996 {
997     if( label )
998         label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
999
1000     /* Fill the table */
1001     table->setColumnCount( 2 );
1002     table->setAlternatingRowColors( true );
1003
1004     module_t *p_main = config_FindModule( p_this, "main" );
1005     assert( p_main );
1006
1007     for (size_t i = 0; i < p_main->confsize; i++)
1008     {
1009         module_config_t *p_item = p_main->p_config + i;
1010
1011         if( p_item->i_type & CONFIG_ITEM && p_item->psz_name &&
1012             strstr( p_item->psz_name , "key-" ) )
1013         {
1014             QTreeWidgetItem *treeItem = new QTreeWidgetItem();
1015             treeItem->setText( 0, qtr( p_item->psz_text ) );
1016             treeItem->setText( 1, VLCKeyToString( p_item->value.i ) );
1017             treeItem->setData( 0, Qt::UserRole,
1018                                   QVariant::fromValue( (void*)p_item ) );
1019             values += p_item;
1020             table->addTopLevelItem( treeItem );
1021         }
1022     }
1023     table->resizeColumnToContents( 0 );
1024
1025     CONNECT( table, itemDoubleClicked( QTreeWidgetItem *, int ),
1026              this, selectKey( QTreeWidgetItem * ) );
1027 }
1028
1029 void KeySelectorControl::selectKey( QTreeWidgetItem *keyItem )
1030 {
1031    module_config_t *p_keyItem = static_cast<module_config_t*>
1032                           (keyItem->data( 0, Qt::UserRole ).value<void*>());
1033
1034     KeyInputDialog *d = new KeyInputDialog( values, p_keyItem->psz_text );
1035     d->exec();
1036     if( d->result() == QDialog::Accepted )
1037     {
1038         p_keyItem->value.i = d->keyValue;
1039         if( d->conflicts )
1040         {
1041             for( int i = 0; i < table->topLevelItemCount() ; i++ )
1042             {
1043                 QTreeWidgetItem *it = table->topLevelItem(i);
1044                 module_config_t *p_item = static_cast<module_config_t*>
1045                               (it->data( 0, Qt::UserRole ).value<void*>());
1046                 if( p_keyItem != p_item && p_item->value.i == d->keyValue )
1047                     p_item->value.i = 0;
1048                 it->setText( 1, VLCKeyToString( p_item->value.i ) );
1049             }
1050         }
1051         else
1052             keyItem->setText( 1, VLCKeyToString( p_keyItem->value.i ) );
1053     }
1054     delete d;
1055 }
1056
1057 void KeySelectorControl::doApply()
1058 {
1059     foreach( module_config_t *p_current, values )
1060     {
1061         config_PutInt( p_this, p_current->psz_name, p_current->value.i );
1062     }
1063 }
1064
1065 KeyInputDialog::KeyInputDialog( QList<module_config_t*>& _values,
1066                                 const char * _keyToChange ) :
1067                                                 QDialog(0), keyValue(0)
1068 {
1069     setModal( true );
1070     values = _values;
1071     conflicts = false;
1072     keyToChange = _keyToChange;
1073     setWindowTitle( qtr( "Hotkey for " ) + qfu( keyToChange)  );
1074
1075     QVBoxLayout *l = new QVBoxLayout( this );
1076     selected = new QLabel( qtr("Press the new keys for ")  + qfu(keyToChange) );
1077     warning = new QLabel();
1078     l->addWidget( selected , Qt::AlignCenter );
1079     l->addWidget( warning, Qt::AlignCenter );
1080
1081     QHBoxLayout *l2 = new QHBoxLayout();
1082     QPushButton *ok = new QPushButton( qtr("OK") );
1083     l2->addWidget( ok );
1084     QPushButton *cancel = new QPushButton( qtr("Cancel") );
1085     l2->addWidget( cancel );
1086
1087     BUTTONACT( ok, accept() );
1088     BUTTONACT( cancel, reject() );
1089
1090     l->addLayout( l2 );
1091 }
1092
1093 void KeyInputDialog::checkForConflicts( int i_vlckey )
1094 {
1095     conflicts = false;
1096     module_config_t *p_current = NULL;
1097     foreach( p_current, values )
1098     {
1099         if( p_current->value.i == i_vlckey && strcmp( p_current->psz_text,
1100                                                     keyToChange ) )
1101         {
1102             conflicts = true;
1103             break;
1104         }
1105     }
1106     if( conflicts )
1107     {
1108         warning->setText(
1109           qtr("Warning: the  key is already assigned to \"") +
1110           QString( p_current->psz_text ) + "\"" );
1111     }
1112     else warning->setText( "" );
1113 }
1114
1115 void KeyInputDialog::keyPressEvent( QKeyEvent *e )
1116 {
1117     if( e->key() == Qt::Key_Tab ) return;
1118     int i_vlck = qtEventToVLCKey( e );
1119     selected->setText( VLCKeyToString( i_vlck ) );
1120     checkForConflicts( i_vlck );
1121     keyValue = i_vlck;
1122 }
1123
1124 void KeyInputDialog::wheelEvent( QWheelEvent *e )
1125 {
1126     int i_vlck = qtWheelEventToVLCKey( e );
1127     selected->setText( VLCKeyToString( i_vlck ) );
1128     checkForConflicts( i_vlck );
1129     keyValue = i_vlck;
1130 }