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