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