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