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