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