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