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