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