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