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