1 /*****************************************************************************
2 * preferences_widgets.cpp : Widgets for preferences displays
3 ****************************************************************************
4 * Copyright (C) 2006-2007 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Antoine Cellerier <dionoea@videolan.org>
9 * Jean-Baptiste Kempf <jb@videolan.org>
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.
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.
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 *****************************************************************************/
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
37 #include "components/preferences_widgets.hpp"
38 #include "util/customwidgets.hpp"
39 #include "util/qt_dirs.hpp"
44 #include <QGridLayout>
46 #include <QFileDialog>
48 #include <QTreeWidgetItem>
49 #include <QSignalMapper>
50 #include <QDialogButtonBox>
52 #define MINWIDTH_BOX 90
53 #define LAST_COLUMN 10
55 QString formatTooltip(const QString & tooltip)
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;\">" +
69 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
70 module_config_t *p_item,
74 return createControl( p_this, p_item, parent, NULL, i );
77 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
78 module_config_t *p_item,
80 QGridLayout *l, int &line )
82 ConfigControl *p_control = NULL;
84 switch( p_item->i_type )
86 case CONFIG_ITEM_MODULE:
87 p_control = new ModuleConfigControl( p_this, p_item, parent, false,
90 case CONFIG_ITEM_MODULE_CAT:
91 p_control = new ModuleConfigControl( p_this, p_item, parent, true,
94 case CONFIG_ITEM_MODULE_LIST:
95 p_control = new ModuleListConfigControl( p_this, p_item, parent, false,
98 case CONFIG_ITEM_MODULE_LIST_CAT:
99 p_control = new ModuleListConfigControl( p_this, p_item, parent, true,
101 /* Special Hack for a bug in video-filter */
102 if( qobject_cast<ModuleListConfigControl *>( p_control )->groupBox == NULL )
105 case CONFIG_ITEM_STRING:
106 if( !p_item->i_list )
107 p_control = new StringConfigControl( p_this, p_item, parent,
110 p_control = new StringListConfigControl( p_this, p_item,
111 parent, false, l, line );
113 case CONFIG_ITEM_PASSWORD:
114 if( !p_item->i_list )
115 p_control = new StringConfigControl( p_this, p_item, parent,
118 p_control = new StringListConfigControl( p_this, p_item,
119 parent, true, l, line );
121 case CONFIG_ITEM_INTEGER:
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,
129 p_control = new IntegerConfigControl( p_this, p_item, parent,
132 case CONFIG_ITEM_FILE:
133 p_control = new FileConfigControl( p_this, p_item, parent, l, line);
135 case CONFIG_ITEM_DIRECTORY:
136 p_control = new DirectoryConfigControl( p_this, p_item, parent, l,
140 case CONFIG_ITEM_FONT:
141 p_control = new FontConfigControl( p_this, p_item, parent, l,
145 case CONFIG_ITEM_KEY:
146 p_control = new KeySelectorControl( p_this, p_item, parent, l, line );
148 case CONFIG_ITEM_BOOL:
149 p_control = new BoolConfigControl( p_this, p_item, parent, l, line );
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,
156 p_control = new FloatConfigControl( p_this, p_item, parent,
165 void ConfigControl::doApply( intf_thread_t *p_intf )
169 case CONFIG_ITEM_INTEGER:
170 case CONFIG_ITEM_BOOL:
172 VIntConfigControl *vicc = qobject_cast<VIntConfigControl *>(this);
174 config_PutInt( p_intf, vicc->getName(), vicc->getValue() );
177 case CONFIG_ITEM_FLOAT:
179 VFloatConfigControl *vfcc =
180 qobject_cast<VFloatConfigControl *>(this);
182 config_PutFloat( p_intf, vfcc->getName(), vfcc->getValue() );
185 case CONFIG_ITEM_STRING:
187 VStringConfigControl *vscc =
188 qobject_cast<VStringConfigControl *>(this);
190 config_PutPsz( p_intf, vscc->getName(), qtu( vscc->getValue() ) );
193 case CONFIG_ITEM_KEY:
195 KeySelectorControl *ksc = qobject_cast<KeySelectorControl *>(this);
202 /**************************************************************************
203 * String-based controls
204 *************************************************************************/
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 )
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 );
220 QHBoxLayout *layout = new QHBoxLayout();
221 layout->addWidget( label, 0 ); layout->insertSpacing( 1, 10 );
222 layout->addWidget( text, LAST_COLUMN );
223 widget->setLayout( layout );
227 l->addWidget( label, line, 0 );
228 l->setColumnMinimumWidth( 1, 10 );
229 l->addWidget( text, line, LAST_COLUMN );
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 )
239 if( pwd ) text->setEchoMode( QLineEdit::Password );
244 void StringConfigControl::finish()
246 text->setText( qfu(p_item->value.psz) );
247 text->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
250 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
251 label->setBuddy( text );
255 /*********** File **************/
256 FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
257 module_config_t *_p_item,
258 QWidget *_parent, QGridLayout *l,
260 VStringConfigControl( _p_this, _p_item, _parent )
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 );
270 BUTTONACT( browse, updateField() );
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 );
284 l->addWidget( label, line, 0 );
285 l->setColumnMinimumWidth( 1, 10 );
286 l->addLayout( textAndButton, line, LAST_COLUMN );
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 )
301 BUTTONACT( browse, updateField() );
306 void FileConfigControl::updateField()
308 QString file = QFileDialog::getOpenFileName( NULL,
309 qtr( "Select File" ), qfu( config_GetHomeDir() ) );
310 if( file.isNull() ) return;
311 text->setText( toNativeSeparators( file ) );
314 void FileConfigControl::finish()
316 text->setText( qfu(p_item->value.psz) );
317 text->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
320 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
321 label->setBuddy( text );
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 )
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)
338 void DirectoryConfigControl::updateField()
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 );
346 if( dir.isNull() ) return;
347 text->setText( toNativeSepNoSlash( dir ) );
351 #include <QFontDialog>
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)
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)
366 void FontConfigControl::updateField()
369 QFont font = QFontDialog::getFont( &ok, QFont( text->text() ), NULL );
371 text->setText( font.family() );
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 )
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 );
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)
390 val.psz_string = strdup(p_module_config->value.psz);
392 p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
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;
399 free( val.psz_string );
402 finish( p_module_config, bycat );
405 l = new QGridLayout();
406 l->addWidget( label, 0, 0 ); l->addWidget( combo, 0, LAST_COLUMN );
407 widget->setLayout( l );
411 l->addWidget( label, line, 0 );
412 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
415 if( p_item->i_action )
417 QSignalMapper *signalMapper = new QSignalMapper(this);
419 /* Some stringLists like Capture listings have action associated */
420 for( int i = 0; i < p_item->i_action; i++ )
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,
429 CONNECT( signalMapper, mapped( int ),
430 this, actionRequested( int ) );
434 void StringListConfigControl::actionRequested( int i_action )
436 /* Supplementary check for boundaries */
437 if( i_action < 0 || i_action >= p_item->i_action ) return;
439 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
440 if(!p_module_config) return;
443 val.psz_string = const_cast<char *>
444 qtu( (combo->itemData( combo->currentIndex() ).toString() ) );
446 p_module_config->ppf_action[i_action]( p_this, getName(), val, val, 0 );
448 if( p_module_config->b_dirty )
451 finish( p_module_config, true );
452 p_module_config->b_dirty = false;
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 )
462 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
464 finish( p_module_config, bycat );
467 void StringListConfigControl::finish(module_config_t *p_module_config, bool bycat )
469 combo->setEditable( false );
471 if(!p_module_config) return;
473 for( int i_index = 0; i_index < p_module_config->i_list; i_index++ )
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 );
484 combo->setToolTip( formatTooltip(qtr(p_module_config->psz_longtext)) );
487 label->setToolTip( formatTooltip(qtr(p_module_config->psz_longtext)) );
488 label->setBuddy( combo );
492 QString StringListConfigControl::getValue()
494 return combo->itemData( combo->currentIndex() ).toString();
497 void setfillVLCConfigCombo( const char *configname, intf_thread_t *p_intf,
500 module_config_t *p_config =
501 config_FindConfig( VLC_OBJECT(p_intf), configname );
504 if(p_config->pf_update_list)
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;
515 for ( int i_index = 0; i_index < p_config->i_list; i_index++ )
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] )
521 combo->setCurrentIndex( i_index );
524 combo->setToolTip( qfu( p_config->psz_longtext ) );
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 )
534 label = new QLabel( qtr(p_item->psz_text) );
535 combo = new QComboBox();
536 combo->setMinimumWidth( MINWIDTH_BOX );
540 QHBoxLayout *layout = new QHBoxLayout();
541 layout->addWidget( label ); layout->addWidget( combo, LAST_COLUMN );
542 widget->setLayout( layout );
546 l->addWidget( label, line, 0 );
547 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
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 )
560 void ModuleConfigControl::finish( bool bycat )
564 combo->setEditable( false );
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++ )
573 if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
576 module_config_t *p_config;
578 p_config = module_config_get (p_parser, &confsize);
579 for (size_t i = 0; i < confsize; i++)
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 );
591 module_config_free (p_config);
593 else if( module_provides( p_parser, p_item->psz_type ) )
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 );
602 module_list_free( p_list );
603 combo->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
606 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
607 label->setBuddy( combo );
611 QString ModuleConfigControl::getValue()
613 return combo->itemData( combo->currentIndex() ).toString();
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 )
624 if( !p_item->psz_text ) return;
626 groupBox = new QGroupBox ( qtr(p_item->psz_text), _parent );
627 text = new QLineEdit;
628 QGridLayout *layoutGroupBox = new QGridLayout( groupBox );
633 for( QVector<checkBoxListItem*>::iterator it = modules.begin();
634 it != modules.end(); it++ )
636 layoutGroupBox->addWidget( (*it)->checkBox, boxline++, 0 );
638 layoutGroupBox->addWidget( text, boxline, 0 );
642 QVBoxLayout *layout = new QVBoxLayout();
643 layout->addWidget( groupBox, line, 0 );
644 widget->setLayout( layout );
648 l->addWidget( groupBox, line, 0, 1, -1 );
651 text->setToolTip( formatTooltip( qtr( p_item->psz_longtext) ) );
654 ModuleListConfigControl::~ModuleListConfigControl()
656 for( QVector<checkBoxListItem*>::iterator it = modules.begin();
657 it != modules.end(); it++ )
664 #define CHECKBOX_LISTS \
666 QCheckBox *cb = new QCheckBox( qtr( module_GetLongName( p_parser ) ) );\
667 checkBoxListItem *cbl = new checkBoxListItem; \
669 CONNECT( cb, stateChanged( int ), this, onUpdate() );\
670 cb->setToolTip( formatTooltip( qtr( module_get_help( p_parser ))));\
671 cbl->checkBox = cb; \
673 cbl->psz_module = strdup( module_get_object( p_parser ) ); \
674 modules.push_back( cbl ); \
676 if( p_item->value.psz && strstr( p_item->value.psz, cbl->psz_module ) ) \
677 cbl->checkBox->setChecked( true ); \
681 void ModuleListConfigControl::finish( bool bycat )
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++ )
691 if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
694 module_config_t *p_config = module_config_get (p_parser, &confsize);
696 for (size_t i = 0; i < confsize; i++)
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 )
706 module_config_free (p_config);
708 else if( module_provides( p_parser, p_item->psz_type ) )
713 module_list_free( p_list );
714 text->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
716 groupBox->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
718 #undef CHECKBOX_LISTS
720 QString ModuleListConfigControl::getValue()
726 void ModuleListConfigControl::hide()
728 for( QVector<checkBoxListItem*>::iterator it = modules.begin();
729 it != modules.end(); it++ )
731 (*it)->checkBox->hide();
736 void ModuleListConfigControl::show()
738 for( QVector<checkBoxListItem*>::iterator it = modules.begin();
739 it != modules.end(); it++ )
741 (*it)->checkBox->show();
747 void ModuleListConfigControl::onUpdate()
752 for( QVector<checkBoxListItem*>::iterator it = modules.begin();
753 it != modules.end(); it++ )
755 if( (*it)->checkBox->isChecked() )
759 text->setText( text->text() + (*it)->psz_module );
764 text->setText( text->text() + ":" + (*it)->psz_module );
770 /**************************************************************************
771 * Integer-based controls
772 *************************************************************************/
774 /*********** Integer **************/
775 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
776 module_config_t *_p_item,
777 QWidget *_parent, QGridLayout *l,
779 VIntConfigControl( _p_this, _p_item, _parent )
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 );
789 QHBoxLayout *layout = new QHBoxLayout();
790 layout->addWidget( label, 0 ); layout->addWidget( spin, LAST_COLUMN );
791 widget->setLayout( layout );
795 l->addWidget( label, line, 0 );
796 l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
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 )
809 void IntegerConfigControl::finish()
811 spin->setMaximum( 2000000000 );
812 spin->setMinimum( -2000000000 );
813 spin->setValue( p_item->value.i );
814 spin->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
817 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
818 label->setBuddy( spin );
822 int IntegerConfigControl::getValue()
824 return spin->value();
827 /********* Integer range **********/
828 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
829 module_config_t *_p_item,
830 QWidget *_parent, QGridLayout *l,
832 IntegerConfigControl( _p_this, _p_item, _parent, l, line )
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 )
845 void IntegerRangeConfigControl::finish()
847 spin->setMaximum( p_item->max.i );
848 spin->setMinimum( p_item->min.i );
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 )
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)) );
865 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
866 label->setBuddy( slider );
870 int IntegerRangeSliderConfigControl::getValue()
872 return slider->value();
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 )
882 label = new QLabel( qtr(p_item->psz_text) );
883 combo = new QComboBox();
884 combo->setMinimumWidth( MINWIDTH_BOX );
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)
890 val.i_int = p_module_config->value.i;
892 p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
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;
901 finish( p_module_config, bycat );
904 QHBoxLayout *layout = new QHBoxLayout();
905 layout->addWidget( label ); layout->addWidget( combo, LAST_COLUMN );
906 widget->setLayout( layout );
910 l->addWidget( label, line, 0 );
911 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
914 if( p_item->i_action )
916 QSignalMapper *signalMapper = new QSignalMapper(this);
918 /* Some stringLists like Capture listings have action associated */
919 for( int i = 0; i < p_item->i_action; i++ )
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,
928 CONNECT( signalMapper, mapped( int ),
929 this, actionRequested( int ) );
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 )
940 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
942 finish( p_module_config, bycat );
945 void IntegerListConfigControl::finish(module_config_t *p_module_config, bool bycat )
947 combo->setEditable( false );
949 if(!p_module_config) return;
951 for( int i_index = 0; i_index < p_module_config->i_list; i_index++ )
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 );
958 combo->setToolTip( formatTooltip(qtr(p_module_config->psz_longtext)) );
961 label->setToolTip( formatTooltip(qtr(p_module_config->psz_longtext)) );
962 label->setBuddy( combo );
966 void IntegerListConfigControl::actionRequested( int i_action )
968 /* Supplementary check for boundaries */
969 if( i_action < 0 || i_action >= p_item->i_action ) return;
971 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
972 if(!p_module_config) return;
976 val.i_int = combo->itemData( combo->currentIndex() ).toInt();
978 p_module_config->ppf_action[i_action]( p_this, getName(), val, val, 0 );
980 if( p_module_config->b_dirty )
983 finish( p_module_config, true );
984 p_module_config->b_dirty = false;
988 int IntegerListConfigControl::getValue()
990 return combo->itemData( combo->currentIndex() ).toInt();
993 /*********** Boolean **************/
994 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
995 module_config_t *_p_item,
996 QWidget *_parent, QGridLayout *l,
998 VIntConfigControl( _p_this, _p_item, _parent )
1000 checkbox = new QCheckBox( qtr(p_item->psz_text) );
1005 QHBoxLayout *layout = new QHBoxLayout();
1006 layout->addWidget( checkbox, 0 );
1007 widget->setLayout( layout );
1011 l->addWidget( checkbox, line, 0 );
1014 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
1015 module_config_t *_p_item,
1017 QCheckBox *_checkbox,
1019 VIntConfigControl( _p_this, _p_item )
1021 checkbox = _checkbox;
1022 VLC_UNUSED( _label );
1026 void BoolConfigControl::finish()
1028 checkbox->setCheckState( p_item->value.i == true ? Qt::Checked
1030 checkbox->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
1033 int BoolConfigControl::getValue()
1035 return checkbox->checkState() == Qt::Checked ? true : false;
1038 /**************************************************************************
1039 * Float-based controls
1040 *************************************************************************/
1042 /*********** Float **************/
1043 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
1044 module_config_t *_p_item,
1045 QWidget *_parent, QGridLayout *l,
1047 VFloatConfigControl( _p_this, _p_item, _parent )
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 );
1058 QHBoxLayout *layout = new QHBoxLayout();
1059 layout->addWidget( label, 0 ); layout->addWidget( spin, LAST_COLUMN );
1060 widget->setLayout( layout );
1064 l->addWidget( label, line, 0 );
1065 l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
1069 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
1070 module_config_t *_p_item,
1072 QDoubleSpinBox *_spin ) :
1073 VFloatConfigControl( _p_this, _p_item )
1080 void FloatConfigControl::finish()
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)) );
1089 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
1090 label->setBuddy( spin );
1094 float FloatConfigControl::getValue()
1096 return (float)spin->value();
1099 /*********** Float with range **************/
1100 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
1101 module_config_t *_p_item,
1102 QWidget *_parent, QGridLayout *l,
1104 FloatConfigControl( _p_this, _p_item, _parent, l, line )
1109 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
1110 module_config_t *_p_item,
1112 QDoubleSpinBox *_spin ) :
1113 FloatConfigControl( _p_this, _p_item, _label, _spin )
1118 void FloatRangeConfigControl::finish()
1120 spin->setMaximum( (double)p_item->max.f );
1121 spin->setMinimum( (double)p_item->min.f );
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,
1132 ConfigControl( _p_this, _p_item, _parent )
1135 QWidget *keyContainer = new QWidget;
1136 QGridLayout *gLayout = new QGridLayout( keyContainer );
1139 qtr( "Select an action to change the associated hotkey") );
1141 QLabel *searchLabel = new QLabel( qtr( "Search" ) );
1142 actionSearch = new SearchLineEdit( keyContainer );
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 );
1151 shortcutValue = new KeyShortcutEdit;
1152 shortcutValue->setReadOnly(true);
1154 QPushButton *clearButton = new QPushButton( qtr( "Clear" ) );
1155 QPushButton *setButton = new QPushButton( qtr( "Set" ) );
1156 setButton->setDefault( true );
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 );
1167 l->addWidget( keyContainer, line, 0, 1, -1 );
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& ) );
1176 void KeySelectorControl::finish()
1179 label->setToolTip( formatTooltip( qtr( p_item->psz_longtext ) ) );
1181 /* Fill the table */
1183 /* Get the main Module */
1184 module_t *p_main = module_get_main();
1187 /* Access to the module_config_t */
1189 module_config_t *p_config;
1191 p_config = module_config_get (p_main, &confsize);
1193 for (size_t i = 0; i < confsize; i++)
1195 module_config_t *p_item = p_config + i;
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 ) )
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
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 );
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 ) )
1224 QList<QTreeWidgetItem *> list =
1225 table->findItems( qtr( p_item->psz_text ), Qt::MatchExactly );
1226 if( list.count() > 1 )
1228 list[0]->setText( 2, VLCKeyToString( p_item->value.i ) );
1229 list[0]->setData( 2, Qt::UserRole,
1230 QVariant( p_item->value.i ) );
1234 module_config_free (p_config);
1235 module_release (p_main);
1237 table->resizeColumnToContents( 0 );
1239 CONNECT( table, itemDoubleClicked( QTreeWidgetItem *, int ),
1240 this, selectKey( QTreeWidgetItem * ) );
1241 CONNECT( table, itemSelectionChanged (),
1242 this, select1Key() );
1244 CONNECT( shortcutValue, pressed(), this, selectKey() );
1247 void KeySelectorControl::filter( const QString &qs_search )
1249 QList<QTreeWidgetItem *> resultList =
1250 table->findItems( qs_search, Qt::MatchContains, 0 );
1251 for( int i = 0; i < table->topLevelItemCount(); i++ )
1253 table->topLevelItem( i )->setHidden(
1254 !resultList.contains( table->topLevelItem( i ) ) );
1258 /* Show the key selected from the table in the keySelector */
1259 void KeySelectorControl::select1Key()
1261 QTreeWidgetItem *keyItem = table->currentItem();
1262 shortcutValue->setText( keyItem->text( 1 ) );
1263 shortcutValue->setValue( keyItem->data( 1, Qt::UserRole ).toInt() );
1266 void KeySelectorControl::selectKey( QTreeWidgetItem *keyItem )
1268 /* This happens when triggered by ClickEater */
1269 if( keyItem == NULL ) keyItem = table->currentItem();
1271 /* This can happen when nothing is selected on the treeView
1272 and the shortcutValue is clicked */
1273 if( !keyItem ) return;
1275 /* Launch a small dialog to ask for a new key */
1276 KeyInputDialog *d = new KeyInputDialog( table, keyItem->text( 0 ), widget );
1279 if( d->result() == QDialog::Accepted )
1281 int newValue = d->keyValue;
1282 shortcutValue->setText( VLCKeyToString( newValue ) );
1283 shortcutValue->setValue( newValue );
1287 QTreeWidgetItem *it;
1288 for( int i = 0; i < table->topLevelItemCount() ; i++ )
1290 it = table->topLevelItem(i);
1291 if( ( keyItem != it )
1292 && ( it->data( 1, Qt::UserRole ).toInt() == newValue ) )
1294 it->setData( 1, Qt::UserRole, QVariant( -1 ) );
1295 it->setText( 1, qtr( "Unset" ) );
1298 /* We already made an OK once. */
1305 void KeySelectorControl::setTheKey()
1307 if( !table->currentItem() ) return;
1308 table->currentItem()->setText( 1, shortcutValue->text() );
1309 table->currentItem()->setData( 1, Qt::UserRole, shortcutValue->getValue() );
1312 void KeySelectorControl::doApply()
1314 QTreeWidgetItem *it;
1315 for( int i = 0; i < table->topLevelItemCount() ; i++ )
1317 it = table->topLevelItem(i);
1318 if( it->data( 1, Qt::UserRole ).toInt() >= 0 )
1319 config_PutInt( p_this,
1320 qtu( it->data( 0, Qt::UserRole ).toString() ),
1321 it->data( 1, Qt::UserRole ).toInt() );
1325 KeyInputDialog::KeyInputDialog( QTreeWidget *_table,
1326 const QString& keyToChange,
1327 QWidget *_parent ) :
1328 QDialog( _parent ), keyValue(0)
1334 setWindowTitle( qtr( "Hotkey for " ) + keyToChange );
1336 vLayout = new QVBoxLayout( this );
1337 selected = new QLabel( qtr( "Press the new keys for " ) + keyToChange );
1338 vLayout->addWidget( selected , Qt::AlignCenter );
1340 warning = new QLabel;
1342 vLayout->insertWidget( 1, warning );
1344 buttonBox = new QDialogButtonBox;
1345 QPushButton *ok = new QPushButton( qtr("OK") );
1346 QPushButton *cancel = new QPushButton( qtr("Cancel") );
1347 buttonBox->addButton( ok, QDialogButtonBox::AcceptRole );
1348 buttonBox->addButton( cancel, QDialogButtonBox::RejectRole );
1349 ok->setDefault( true );
1351 vLayout->addWidget( buttonBox );
1354 CONNECT( buttonBox, accepted(), this, accept() );
1355 CONNECT( buttonBox, rejected(), this, reject() );
1358 void KeyInputDialog::checkForConflicts( int i_vlckey )
1360 QList<QTreeWidgetItem *> conflictList =
1361 table->findItems( VLCKeyToString( i_vlckey ), Qt::MatchExactly, 1 );
1363 if( conflictList.size() &&
1364 conflictList[0]->data( 1, Qt::UserRole ).toInt() > 1 )
1365 /* Avoid 0 or -1 that are the "Unset" states */
1367 warning->setText( qtr("Warning: the key is already assigned to \"") +
1368 conflictList[0]->text( 0 ) + "\"" );
1377 void KeyInputDialog::keyPressEvent( QKeyEvent *e )
1379 if( e->key() == Qt::Key_Tab ||
1380 e->key() == Qt::Key_Shift ||
1381 e->key() == Qt::Key_Control ||
1382 e->key() == Qt::Key_Meta ||
1383 e->key() == Qt::Key_Alt ||
1384 e->key() == Qt::Key_AltGr )
1386 int i_vlck = qtEventToVLCKey( e );
1387 selected->setText( qtr( "Key: " ) + VLCKeyToString( i_vlck ) );
1388 checkForConflicts( i_vlck );
1392 void KeyInputDialog::wheelEvent( QWheelEvent *e )
1394 int i_vlck = qtWheelEventToVLCKey( e );
1395 selected->setText( qtr( "Key: " ) + VLCKeyToString( i_vlck ) );
1396 checkForConflicts( i_vlck );
1400 void KeyShortcutEdit::mousePressEvent( QMouseEvent *)