1 /*****************************************************************************
2 * preferences_widgets.cpp : Widgets for preferences displays
3 ****************************************************************************
4 * Copyright (C) 2006-2011 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 * - i_action handler for IntegerLists, but I don't see any module using it...
29 * - Validator for modulelist
35 #include "components/preferences_widgets.hpp"
36 #include "util/customwidgets.hpp"
37 #include "util/searchlineedit.hpp"
38 #include "util/qt_dirs.hpp"
40 #include <vlc_intf_strings.h>
41 #include <vlc_modules.h>
45 #include <QGridLayout>
47 #include <QFileDialog>
49 #include <QTreeWidgetItem>
50 #include <QSignalMapper>
51 #include <QDialogButtonBox>
53 #include <QColorDialog>
55 #define MINWIDTH_BOX 90
56 #define LAST_COLUMN 10
58 QString formatTooltip(const QString & tooltip)
60 QString text = tooltip;
61 text.replace("\n", "<br/>");
64 "<html><head><meta name=\"qrichtext\" content=\"1\" />"
65 "<style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head>"
66 "<body style=\" font-family:'Sans Serif'; "
67 "font-style:normal; text-decoration:none;\">"
68 "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; "
69 "margin-right:0px; -qt-block-indent:0; text-indent:0px;\">" +
70 text + "</p></body></html>";
74 ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
75 module_config_t *p_item,
77 QGridLayout *l, int line )
79 ConfigControl *p_control = NULL;
81 switch( p_item->i_type )
83 case CONFIG_ITEM_MODULE:
84 p_control = new ModuleConfigControl( p_this, p_item, parent, false,
87 case CONFIG_ITEM_MODULE_CAT:
88 p_control = new ModuleConfigControl( p_this, p_item, parent, true,
91 case CONFIG_ITEM_MODULE_LIST:
92 p_control = new ModuleListConfigControl( p_this, p_item, parent, false,
95 case CONFIG_ITEM_MODULE_LIST_CAT:
96 p_control = new ModuleListConfigControl( p_this, p_item, parent, true,
99 case CONFIG_ITEM_STRING:
100 if( !p_item->i_list )
101 p_control = new StringConfigControl( p_this, p_item, parent,
104 p_control = new StringListConfigControl( p_this, p_item,
107 case CONFIG_ITEM_PASSWORD:
108 if( !p_item->i_list )
109 p_control = new StringConfigControl( p_this, p_item, parent,
112 p_control = new StringListConfigControl( p_this, p_item,
115 case CONFIG_ITEM_RGB:
116 p_control = new ColorConfigControl( p_this, p_item, parent, l, line );
118 case CONFIG_ITEM_INTEGER:
120 p_control = new IntegerListConfigControl( p_this, p_item,
121 parent, false, l, line );
122 else if( p_item->min.i || p_item->max.i )
123 p_control = new IntegerRangeConfigControl( p_this, p_item, parent,
126 p_control = new IntegerConfigControl( p_this, p_item, parent,
129 case CONFIG_ITEM_LOADFILE:
130 case CONFIG_ITEM_SAVEFILE:
131 p_control = new FileConfigControl( p_this, p_item, parent, l, line);
133 case CONFIG_ITEM_DIRECTORY:
134 p_control = new DirectoryConfigControl( p_this, p_item, parent, l,
137 case CONFIG_ITEM_FONT:
138 p_control = new FontConfigControl( p_this, p_item, parent, l,
141 case CONFIG_ITEM_KEY:
142 p_control = new KeySelectorControl( p_this, p_item, parent, l, line );
144 case CONFIG_ITEM_BOOL:
145 p_control = new BoolConfigControl( p_this, p_item, parent, l, line );
147 case CONFIG_ITEM_FLOAT:
148 if( p_item->min.f || p_item->max.f )
149 p_control = new FloatRangeConfigControl( p_this, p_item, parent,
152 p_control = new FloatConfigControl( p_this, p_item, parent,
161 /*******************************************************
163 *******************************************************/
164 InterfacePreviewWidget::InterfacePreviewWidget ( QWidget *parent ) : QLabel( parent )
166 setGeometry( 0, 0, 128, 100 );
167 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
170 void InterfacePreviewWidget::setNormalPreview( bool b_minimal )
172 setPreview( ( b_minimal ) ? MINIMAL : COMPLETE );
175 void InterfacePreviewWidget::setPreview( enum_style e_style )
177 QString pixmapLocationString(":/prefsmenu/");
183 pixmapLocationString += "sample_complete";
186 pixmapLocationString += "sample_minimal";
189 pixmapLocationString += "sample_skins";
193 setPixmap( QPixmap( pixmapLocationString ) );
198 /**************************************************************************
199 * String-based controls
200 *************************************************************************/
203 VStringConfigControl::doApply()
205 config_PutPsz( p_this, getName(), qtu( getValue() ) );
208 /*********** String **************/
209 StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
210 module_config_t *_p_item,
211 QWidget *_parent, QGridLayout *l,
212 int line, bool pwd ) :
213 VStringConfigControl( _p_this, _p_item, _parent )
215 label = new QLabel( qtr(p_item->psz_text) );
216 text = new QLineEdit( qfu(p_item->value.psz) );
217 if( pwd ) text->setEchoMode( QLineEdit::Password );
222 QHBoxLayout *layout = new QHBoxLayout();
223 layout->addWidget( label, 0 ); layout->insertSpacing( 1, 10 );
224 layout->addWidget( text, LAST_COLUMN );
225 widget->setLayout( layout );
229 l->addWidget( label, line, 0 );
230 l->setColumnMinimumWidth( 1, 10 );
231 l->addWidget( text, line, LAST_COLUMN );
235 StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
236 module_config_t *_p_item,
237 QLabel *_label, QLineEdit *_text, bool pwd ):
238 VStringConfigControl( _p_this, _p_item )
241 if( pwd ) text->setEchoMode( QLineEdit::Password );
246 void StringConfigControl::finish()
248 text->setText( qfu(p_item->value.psz) );
249 if( p_item->psz_longtext )
251 QString tipText = qtr(p_item->psz_longtext);
252 text->setToolTip( formatTooltip(tipText) );
254 label->setToolTip( formatTooltip(tipText) );
257 label->setBuddy( text );
260 /*********** File **************/
261 FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
262 module_config_t *_p_item,
263 QWidget *_parent, QGridLayout *l,
265 VStringConfigControl( _p_this, _p_item, _parent )
267 label = new QLabel( qtr(p_item->psz_text) );
268 text = new QLineEdit( qfu(p_item->value.psz) );
269 browse = new QPushButton( qtr( "Browse..." ) );
270 QHBoxLayout *textAndButton = new QHBoxLayout();
271 textAndButton->setMargin( 0 );
272 textAndButton->addWidget( text, 2 );
273 textAndButton->addWidget( browse, 0 );
275 BUTTONACT( browse, updateField() );
281 QHBoxLayout *layout = new QHBoxLayout();
282 layout->addWidget( label, 0 );
283 layout->insertSpacing( 1, 10 );
284 layout->addLayout( textAndButton, LAST_COLUMN );
285 widget->setLayout( layout );
289 l->addWidget( label, line, 0 );
290 l->setColumnMinimumWidth( 1, 10 );
291 l->addLayout( textAndButton, line, LAST_COLUMN );
296 FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
297 module_config_t *_p_item,
298 QLabel *_label, QLineEdit *_text,
299 QPushButton *_button ):
300 VStringConfigControl( _p_this, _p_item )
306 BUTTONACT( browse, updateField() );
311 void FileConfigControl::updateField()
315 if (p_item->i_type == CONFIG_ITEM_SAVEFILE)
316 file = QFileDialog::getSaveFileName( NULL, qtr( "Save File" ),
317 QVLCUserDir( VLC_HOME_DIR ) );
319 file = QFileDialog::getOpenFileName( NULL, qtr( "Select File" ),
320 QVLCUserDir( VLC_HOME_DIR ) );
322 if( file.isNull() ) return;
323 text->setText( toNativeSeparators( file ) );
326 void FileConfigControl::finish()
328 text->setText( qfu(p_item->value.psz) );
329 if( p_item->psz_longtext )
331 QString tipText = qtr(p_item->psz_longtext);
332 text->setToolTip( formatTooltip(tipText) );
334 label->setToolTip( formatTooltip(tipText) );
337 label->setBuddy( text );
340 /********* String / Directory **********/
341 DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
342 module_config_t *_p_item, QWidget *_p_widget,
343 QGridLayout *_p_layout, int _int ) :
344 FileConfigControl( _p_this, _p_item, _p_widget, _p_layout, _int )
347 DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
348 module_config_t *_p_item, QLabel *_p_label,
349 QLineEdit *_p_line, QPushButton *_p_button ):
350 FileConfigControl( _p_this, _p_item, _p_label, _p_line, _p_button)
353 void DirectoryConfigControl::updateField()
355 QString dir = QFileDialog::getExistingDirectory( NULL,
357 text->text().isEmpty() ?
358 QVLCUserDir( VLC_HOME_DIR ) : text->text(),
359 QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks );
361 if( dir.isNull() ) return;
362 text->setText( toNativeSepNoSlash( dir ) );
365 /********* String / Font **********/
366 FontConfigControl::FontConfigControl( vlc_object_t *_p_this,
367 module_config_t *_p_item, QWidget *_parent,
368 QGridLayout *_p_layout, int line) :
369 VStringConfigControl( _p_this, _p_item, _parent )
371 label = new QLabel( qtr(p_item->psz_text) );
372 font = new QFontComboBox( _parent );
373 font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );
376 QHBoxLayout *layout = new QHBoxLayout();
377 layout->addWidget( label, 0 );
378 layout->addWidget( font, 1 );
379 widget->setLayout( layout );
383 _p_layout->addWidget( label, line, 0 );
384 _p_layout->addWidget( font, line, 1, 1, -1 );
387 if( p_item->psz_longtext )
389 label->setToolTip( formatTooltip( qtr(p_item->psz_longtext) ) );
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)
400 font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );
402 if( p_item->psz_longtext )
404 label->setToolTip( formatTooltip( qtr(p_item->psz_longtext) ) );
408 /********* String / choice list **********/
409 StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
410 module_config_t *_p_item, QWidget *_parent,
411 QGridLayout *l, int line) :
412 VStringConfigControl( _p_this, _p_item, _parent )
414 label = new QLabel( qtr(p_item->psz_text) );
415 combo = new QComboBox();
416 combo->setMinimumWidth( MINWIDTH_BOX );
417 combo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
419 module_config_t *p_module_config = config_FindConfig( p_this, p_item->psz_name );
421 finish( p_module_config );
424 l = new QGridLayout();
425 l->addWidget( label, 0, 0 ); l->addWidget( combo, 0, LAST_COLUMN );
426 widget->setLayout( l );
430 l->addWidget( label, line, 0 );
431 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
434 if( p_item->i_action )
436 QSignalMapper *signalMapper = new QSignalMapper(this);
438 /* Some stringLists like Capture listings have action associated */
439 for( int i = 0; i < p_item->i_action; i++ )
441 QPushButton *button =
442 new QPushButton( qtr( p_item->ppsz_action_text[i] ));
443 CONNECT( button, clicked(), signalMapper, map() );
444 signalMapper->setMapping( button, i );
445 l->addWidget( button, line, LAST_COLUMN - p_item->i_action + i,
448 CONNECT( signalMapper, mapped( int ),
449 this, actionRequested( int ) );
453 void StringListConfigControl::actionRequested( int i_action )
455 /* Supplementary check for boundaries */
456 if( i_action < 0 || i_action >= p_item->i_action ) return;
458 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
459 if(!p_module_config) return;
462 val.psz_string = const_cast<char *>
463 qtu( (combo->itemData( combo->currentIndex() ).toString() ) );
465 p_module_config->ppf_action[i_action]( p_this, getName(), val, val, 0 );
467 if( p_module_config->b_dirty )
470 finish( p_module_config );
471 p_module_config->b_dirty = false;
474 StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
475 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
476 bool ) : VStringConfigControl( _p_this, _p_item )
481 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
483 finish( p_module_config );
486 void StringListConfigControl::finish(module_config_t *p_module_config )
488 combo->setEditable( false );
490 if(!p_module_config) return;
492 if( p_module_config->pf_update_list )
495 val.psz_string = strdup(p_module_config->value.psz);
497 p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
499 // assume in any case that dirty was set to true
500 // because lazy programmes will use the same callback for
501 // this, like the one behind the refresh push button?
502 p_module_config->b_dirty = false;
504 free( val.psz_string );
507 for( int i_index = 0; i_index < p_module_config->i_list; i_index++ )
509 if( !p_module_config->ppsz_list[i_index] )
511 combo->addItem( "", QVariant(""));
512 if( !p_item->value.psz )
513 combo->setCurrentIndex( combo->count() - 1 );
516 combo->addItem( qfu((p_module_config->ppsz_list_text &&
517 p_module_config->ppsz_list_text[i_index])?
518 _(p_module_config->ppsz_list_text[i_index]) :
519 p_module_config->ppsz_list[i_index] ),
520 QVariant( qfu(p_module_config->ppsz_list[i_index] )) );
521 if( p_item->value.psz && !strcmp( p_module_config->value.psz,
522 p_module_config->ppsz_list[i_index] ) )
523 combo->setCurrentIndex( combo->count() - 1 );
526 if( p_module_config->psz_longtext )
528 QString tipText = qtr(p_module_config->psz_longtext);
529 combo->setToolTip( formatTooltip(tipText) );
531 label->setToolTip( formatTooltip(tipText) );
534 label->setBuddy( combo );
537 QString StringListConfigControl::getValue() const
539 return combo->itemData( combo->currentIndex() ).toString();
542 void setfillVLCConfigCombo( const char *configname, intf_thread_t *p_intf,
545 module_config_t *p_config =
546 config_FindConfig( VLC_OBJECT(p_intf), configname );
550 bool string = (p_config->i_type & 0xF0) == CONFIG_ITEM_STRING;
553 def = QVariant( qfu(p_config->value.psz) );
555 def = QVariant( qlonglong( p_config->value.i ) );
557 if(p_config->pf_update_list)
560 val.i_int = p_config->value.i;
561 p_config->pf_update_list(VLC_OBJECT(p_intf), configname, val, val, NULL);
562 // assume in any case that dirty was set to true
563 // because lazy programmes will use the same callback for
564 // this, like the one behind the refresh push button?
565 p_config->b_dirty = false;
568 for ( int i_index = 0; i_index < p_config->i_list; i_index++ )
573 value = QVariant( qfu(p_config->ppsz_list[i_index]) );
575 value =QVariant( p_config->pi_list[i_index] );
576 combo->addItem( qtr(p_config->ppsz_list_text[i_index]), value );
578 combo->setCurrentIndex( i_index );
581 if( p_config->psz_longtext )
582 combo->setToolTip( qfu( p_config->psz_longtext ) );
586 /********* Module **********/
587 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
588 module_config_t *_p_item, QWidget *_parent, bool bycat,
589 QGridLayout *l, int line) :
590 VStringConfigControl( _p_this, _p_item, _parent )
592 label = new QLabel( qtr(p_item->psz_text) );
593 combo = new QComboBox();
594 combo->setMinimumWidth( MINWIDTH_BOX );
598 QHBoxLayout *layout = new QHBoxLayout();
599 layout->addWidget( label ); layout->addWidget( combo, LAST_COLUMN );
600 widget->setLayout( layout );
604 l->addWidget( label, line, 0 );
605 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
609 ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
610 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
611 bool bycat ) : VStringConfigControl( _p_this, _p_item )
618 void ModuleConfigControl::finish( bool bycat )
622 combo->setEditable( false );
624 /* build a list of available modules */
625 module_t **p_list = module_list_get( NULL );
626 combo->addItem( qtr("Default") );
627 for( size_t i = 0; (p_parser = p_list[i]) != NULL; i++ )
631 if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
634 module_config_t *p_config;
636 p_config = module_config_get (p_parser, &confsize);
637 for (size_t i = 0; i < confsize; i++)
639 /* Hack: required subcategory is stored in i_min */
640 const module_config_t *p_cfg = p_config + i;
641 if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
642 p_cfg->value.i == p_item->min.i )
643 combo->addItem( qtr( module_GetLongName( p_parser )),
644 QVariant( module_get_object( p_parser ) ) );
645 if( p_item->value.psz && !strcmp( p_item->value.psz,
646 module_get_object( p_parser ) ) )
647 combo->setCurrentIndex( combo->count() - 1 );
649 module_config_free (p_config);
651 else if( module_provides( p_parser, p_item->psz_type ) )
653 combo->addItem( qtr(module_GetLongName( p_parser ) ),
654 QVariant( module_get_object( p_parser ) ) );
655 if( p_item->value.psz && !strcmp( p_item->value.psz,
656 module_get_object( p_parser ) ) )
657 combo->setCurrentIndex( combo->count() - 1 );
660 module_list_free( p_list );
662 if( p_item->psz_longtext )
664 QString tipText = qtr(p_item->psz_longtext);
665 combo->setToolTip( formatTooltip(tipText) );
667 label->setToolTip( formatTooltip(tipText) );
670 label->setBuddy( combo );
673 QString ModuleConfigControl::getValue() const
675 return combo->itemData( combo->currentIndex() ).toString();
678 /********* Module list **********/
679 ModuleListConfigControl::ModuleListConfigControl( vlc_object_t *_p_this,
680 module_config_t *_p_item, QWidget *_parent, bool bycat,
681 QGridLayout *l, int line) :
682 VStringConfigControl( _p_this, _p_item, _parent )
687 if( !p_item->psz_text ) return;
689 groupBox = new QGroupBox ( qtr(p_item->psz_text), _parent );
690 text = new QLineEdit;
691 QGridLayout *layoutGroupBox = new QGridLayout( groupBox );
696 foreach ( checkBoxListItem *it, modules )
698 layoutGroupBox->addWidget( it->checkBox, boxline / 2, boxline % 2 );
702 layoutGroupBox->addWidget( text, boxline, 0, 1, 2 );
706 QVBoxLayout *layout = new QVBoxLayout();
707 layout->addWidget( groupBox, line, 0 );
708 widget->setLayout( layout );
712 l->addWidget( groupBox, line, 0, 1, -1 );
715 if( p_item->psz_longtext )
716 text->setToolTip( formatTooltip( qtr( p_item->psz_longtext) ) );
719 ModuleListConfigControl::~ModuleListConfigControl()
721 qDeleteAll( modules );
726 void ModuleListConfigControl::checkbox_lists( module_t *p_parser )
728 const char *help = module_get_help( p_parser );
729 checkbox_lists( qtr( module_GetLongName( p_parser ) ),
730 help != NULL ? qtr( help ): "",
731 module_get_object( p_parser ) );
734 void ModuleListConfigControl::checkbox_lists( QString label, QString help, const char* psz_module )
736 QCheckBox *cb = new QCheckBox( label );
737 checkBoxListItem *cbl = new checkBoxListItem;
739 CONNECT( cb, stateChanged( int ), this, onUpdate() );
740 if( !help.isEmpty() )
741 cb->setToolTip( formatTooltip( help ) );
744 cbl->psz_module = strdup( psz_module );
745 modules.append( cbl );
747 if( p_item->value.psz && strstr( p_item->value.psz, cbl->psz_module ) )
748 cbl->checkBox->setChecked( true );
751 void ModuleListConfigControl::finish( bool bycat )
755 /* build a list of available modules */
756 module_t **p_list = module_list_get( NULL );
757 for( size_t i = 0; (p_parser = p_list[i]) != NULL; i++ )
761 if( !strcmp( module_get_object( p_parser ), "main" ) ) continue;
764 module_config_t *p_config = module_config_get (p_parser, &confsize);
766 for (size_t i = 0; i < confsize; i++)
768 module_config_t *p_cfg = p_config + i;
769 /* Hack: required subcategory is stored in i_min */
770 if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
771 p_cfg->value.i == p_item->min.i )
773 checkbox_lists( p_parser );
776 /* Parental Advisory HACK:
777 * Selecting HTTP, RC and Telnet interfaces is difficult now
778 * since they are just the lua interface module */
779 if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
780 !strcmp( module_get_object( p_parser ), "lua" ) &&
781 !strcmp( p_item->psz_name, "extraintf" ) &&
782 p_cfg->value.i == p_item->min.i )
784 checkbox_lists( "Web", "Lua HTTP", "http" );
785 checkbox_lists( "Telnet", "Lua Telnet", "telnet" );
787 checkbox_lists( "Console", "Lua CLI", "cli" );
791 module_config_free (p_config);
793 else if( module_provides( p_parser, p_item->psz_type ) )
795 checkbox_lists(p_parser);
798 module_list_free( p_list );
800 if( p_item->psz_longtext )
802 QString tipText = qtr(p_item->psz_longtext);
804 text->setToolTip( formatTooltip(tipText) );
806 groupBox->setToolTip( formatTooltip(tipText) );
810 QString ModuleListConfigControl::getValue() const
816 void ModuleListConfigControl::hide()
818 foreach ( checkBoxListItem *it, modules )
819 it->checkBox->hide();
823 void ModuleListConfigControl::show()
825 foreach ( checkBoxListItem *it, modules )
826 it->checkBox->show();
831 void ModuleListConfigControl::onUpdate()
836 foreach ( checkBoxListItem *it, modules )
838 if( it->checkBox->isChecked() )
842 text->setText( text->text() + it->psz_module );
847 text->setText( text->text() + ":" + it->psz_module );
853 /**************************************************************************
854 * Integer-based controls
855 *************************************************************************/
858 VIntConfigControl::doApply()
860 config_PutInt( p_this, getName(), getValue() );
863 /*********** Integer **************/
864 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
865 module_config_t *_p_item,
866 QWidget *_parent, QGridLayout *l,
868 VIntConfigControl( _p_this, _p_item, _parent )
870 label = new QLabel( qtr(p_item->psz_text) );
871 spin = new QSpinBox; spin->setMinimumWidth( MINWIDTH_BOX );
872 spin->setAlignment( Qt::AlignRight );
873 spin->setMaximumWidth( MINWIDTH_BOX );
878 QHBoxLayout *layout = new QHBoxLayout();
879 layout->addWidget( label, 0 ); layout->addWidget( spin, LAST_COLUMN );
880 widget->setLayout( layout );
884 l->addWidget( label, line, 0 );
885 l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
888 IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
889 module_config_t *_p_item,
890 QLabel *_label, QSpinBox *_spin ) :
891 VIntConfigControl( _p_this, _p_item )
898 void IntegerConfigControl::finish()
900 spin->setMaximum( 2000000000 );
901 spin->setMinimum( -2000000000 );
902 spin->setValue( p_item->value.i );
904 if( p_item->psz_longtext )
906 QString tipText = qtr(p_item->psz_longtext);
907 spin->setToolTip( formatTooltip(tipText) );
909 label->setToolTip( formatTooltip(tipText) );
912 label->setBuddy( spin );
915 int IntegerConfigControl::getValue() const
917 return spin->value();
920 /********* Integer range **********/
921 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
922 module_config_t *_p_item,
923 QWidget *_parent, QGridLayout *l,
925 IntegerConfigControl( _p_this, _p_item, _parent, l, line )
930 IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
931 module_config_t *_p_item,
932 QLabel *_label, QSpinBox *_spin ) :
933 IntegerConfigControl( _p_this, _p_item, _label, _spin )
938 void IntegerRangeConfigControl::finish()
940 spin->setMaximum( p_item->max.i );
941 spin->setMinimum( p_item->min.i );
944 IntegerRangeSliderConfigControl::IntegerRangeSliderConfigControl(
945 vlc_object_t *_p_this,
946 module_config_t *_p_item,
947 QLabel *_label, QSlider *_slider ):
948 VIntConfigControl( _p_this, _p_item )
952 slider->setMaximum( p_item->max.i );
953 slider->setMinimum( p_item->min.i );
954 slider->setValue( p_item->value.i );
955 if( p_item->psz_longtext )
957 QString tipText = qtr(p_item->psz_longtext);
958 slider->setToolTip( formatTooltip(tipText) );
960 label->setToolTip( formatTooltip(tipText) );
963 label->setBuddy( slider );
966 int IntegerRangeSliderConfigControl::getValue() const
968 return slider->value();
972 /********* Integer / choice list **********/
973 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
974 module_config_t *_p_item, QWidget *_parent, bool,
975 QGridLayout *l, int line) :
976 VIntConfigControl( _p_this, _p_item, _parent )
978 label = new QLabel( qtr(p_item->psz_text) );
979 combo = new QComboBox();
980 combo->setMinimumWidth( MINWIDTH_BOX );
982 module_config_t *p_module_config = config_FindConfig( p_this, p_item->psz_name );
984 finish( p_module_config );
987 QHBoxLayout *layout = new QHBoxLayout();
988 layout->addWidget( label ); layout->addWidget( combo, LAST_COLUMN );
989 widget->setLayout( layout );
993 l->addWidget( label, line, 0 );
994 l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
997 if( p_item->i_action )
999 QSignalMapper *signalMapper = new QSignalMapper(this);
1001 /* Some stringLists like Capture listings have action associated */
1002 for( int i = 0; i < p_item->i_action; i++ )
1004 QPushButton *button =
1005 new QPushButton( qfu( p_item->ppsz_action_text[i] ));
1006 CONNECT( button, clicked(), signalMapper, map() );
1007 signalMapper->setMapping( button, i );
1008 l->addWidget( button, line, LAST_COLUMN - p_item->i_action + i,
1011 CONNECT( signalMapper, mapped( int ),
1012 this, actionRequested( int ) );
1016 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
1017 module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
1018 bool ) : VIntConfigControl( _p_this, _p_item )
1023 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
1025 finish( p_module_config );
1028 void IntegerListConfigControl::finish(module_config_t *p_module_config )
1030 combo->setEditable( false );
1032 if(!p_module_config) return;
1034 if( p_module_config->pf_update_list )
1037 val.i_int = p_module_config->value.i;
1039 p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
1041 // assume in any case that dirty was set to true
1042 // because lazy programmes will use the same callback for
1043 // this, like the one behind the refresh push button?
1044 p_module_config->b_dirty = false;
1047 for( int i_index = 0; i_index < p_module_config->i_list; i_index++ )
1049 combo->addItem( qtr(p_module_config->ppsz_list_text[i_index] ),
1050 QVariant( p_module_config->pi_list[i_index] ) );
1051 if( p_module_config->value.i == p_module_config->pi_list[i_index] )
1052 combo->setCurrentIndex( combo->count() - 1 );
1054 if( p_item->psz_longtext )
1056 QString tipText = qtr(p_item->psz_longtext );
1057 combo->setToolTip( formatTooltip(tipText) );
1059 label->setToolTip( formatTooltip(tipText) );
1062 label->setBuddy( combo );
1065 void IntegerListConfigControl::actionRequested( int i_action )
1067 /* Supplementary check for boundaries */
1068 if( i_action < 0 || i_action >= p_item->i_action ) return;
1070 module_config_t *p_module_config = config_FindConfig( p_this, getName() );
1071 if(!p_module_config) return;
1075 val.i_int = combo->itemData( combo->currentIndex() ).toInt();
1077 p_module_config->ppf_action[i_action]( p_this, getName(), val, val, 0 );
1079 if( p_module_config->b_dirty )
1082 finish( p_module_config );
1083 p_module_config->b_dirty = false;
1087 int IntegerListConfigControl::getValue() const
1089 return combo->itemData( combo->currentIndex() ).toInt();
1092 /*********** Boolean **************/
1093 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
1094 module_config_t *_p_item,
1095 QWidget *_parent, QGridLayout *l,
1097 VIntConfigControl( _p_this, _p_item, _parent )
1099 checkbox = new QCheckBox( qtr(p_item->psz_text) );
1104 QHBoxLayout *layout = new QHBoxLayout();
1105 layout->addWidget( checkbox, 0 );
1106 widget->setLayout( layout );
1110 l->addWidget( checkbox, line, 0 );
1114 BoolConfigControl::BoolConfigControl( vlc_object_t *_p_this,
1115 module_config_t *_p_item,
1117 QAbstractButton *_checkbox ) :
1118 VIntConfigControl( _p_this, _p_item )
1120 checkbox = _checkbox;
1121 VLC_UNUSED( _label );
1125 void BoolConfigControl::finish()
1127 checkbox->setChecked( p_item->value.i );
1128 if( p_item->psz_longtext )
1129 checkbox->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
1132 int BoolConfigControl::getValue() const
1134 return checkbox->isChecked();
1137 /************* Color *************/
1138 ColorConfigControl::ColorConfigControl( vlc_object_t *_p_this,
1139 module_config_t *_p_item,
1140 QWidget *_parent, QGridLayout *l,
1142 VIntConfigControl( _p_this, _p_item, _parent )
1145 color_but = new QToolButton;
1150 QHBoxLayout *layout = new QHBoxLayout();
1151 layout->addWidget( label, 0 ); layout->addWidget( color_but, LAST_COLUMN );
1152 widget->setLayout( layout );
1156 l->addWidget( label, line, 0 );
1157 l->addWidget( color_but, line, LAST_COLUMN, Qt::AlignRight );
1161 ColorConfigControl::ColorConfigControl( vlc_object_t *_p_this,
1162 module_config_t *_p_item,
1163 QLabel *_label, QAbstractButton *_color ):
1164 VIntConfigControl( _p_this, _p_item )
1171 void ColorConfigControl::finish()
1173 i_color = p_item->value.i;
1175 color_px = new QPixmap( 34, 20 );
1176 color_px->fill( QColor( i_color ) );
1177 color_but->setIcon( QIcon( *color_px ) );
1178 color_but->setMinimumWidth( 40 );
1180 label->setText( qtr(p_item->psz_text) );
1181 if( p_item->psz_longtext )
1183 label->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
1184 color_but->setToolTip( formatTooltip(qtr(p_item->psz_longtext)) );
1187 BUTTONACT( color_but, selectColor() );
1190 int ColorConfigControl::getValue() const
1195 void ColorConfigControl::selectColor()
1197 QColor color = QColorDialog::getColor( QColor( i_color ) );
1198 if( color.isValid() )
1200 i_color = (color.red() << 16) + (color.green() << 8) + color.blue();
1202 color_px->fill( QColor( i_color ) );
1203 color_but->setIcon( QIcon( *color_px ) );
1208 /**************************************************************************
1209 * Float-based controls
1210 *************************************************************************/
1213 VFloatConfigControl::doApply()
1215 config_PutFloat( p_this, getName(), getValue() );
1218 /*********** Float **************/
1219 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
1220 module_config_t *_p_item,
1221 QWidget *_parent, QGridLayout *l,
1223 VFloatConfigControl( _p_this, _p_item, _parent )
1225 label = new QLabel( qtr(p_item->psz_text) );
1226 spin = new QDoubleSpinBox;
1227 spin->setMinimumWidth( MINWIDTH_BOX );
1228 spin->setMaximumWidth( MINWIDTH_BOX );
1229 spin->setAlignment( Qt::AlignRight );
1234 QHBoxLayout *layout = new QHBoxLayout();
1235 layout->addWidget( label, 0 ); layout->addWidget( spin, LAST_COLUMN );
1236 widget->setLayout( layout );
1240 l->addWidget( label, line, 0 );
1241 l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
1245 FloatConfigControl::FloatConfigControl( vlc_object_t *_p_this,
1246 module_config_t *_p_item,
1248 QDoubleSpinBox *_spin ) :
1249 VFloatConfigControl( _p_this, _p_item )
1256 void FloatConfigControl::finish()
1258 spin->setMaximum( 2000000000. );
1259 spin->setMinimum( -2000000000. );
1260 spin->setSingleStep( 0.1 );
1261 spin->setValue( (double)p_item->value.f );
1262 if( p_item->psz_longtext )
1264 QString tipText = qtr(p_item->psz_longtext);
1265 spin->setToolTip( formatTooltip(tipText) );
1267 label->setToolTip( formatTooltip(tipText) );
1270 label->setBuddy( spin );
1273 float FloatConfigControl::getValue() const
1275 return (float)spin->value();
1278 /*********** Float with range **************/
1279 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
1280 module_config_t *_p_item,
1281 QWidget *_parent, QGridLayout *l,
1283 FloatConfigControl( _p_this, _p_item, _parent, l, line )
1288 FloatRangeConfigControl::FloatRangeConfigControl( vlc_object_t *_p_this,
1289 module_config_t *_p_item,
1291 QDoubleSpinBox *_spin ) :
1292 FloatConfigControl( _p_this, _p_item, _label, _spin )
1297 void FloatRangeConfigControl::finish()
1299 spin->setMaximum( (double)p_item->max.f );
1300 spin->setMinimum( (double)p_item->min.f );
1304 /**********************************************************************
1305 * Key selector widget
1306 **********************************************************************/
1307 KeySelectorControl::KeySelectorControl( vlc_object_t *_p_this,
1308 module_config_t *_p_item,
1309 QWidget *_parent, QGridLayout *l,
1311 ConfigControl( _p_this, _p_item, _parent )
1314 QWidget *keyContainer = new QWidget;
1315 QGridLayout *gLayout = new QGridLayout( keyContainer );
1318 qtr( "Select or double click an action to change the associated hotkey") );
1320 QLabel *searchLabel = new QLabel( qtr( "Search" ) );
1321 SearchLineEdit *actionSearch = new SearchLineEdit( keyContainer );
1323 table = new QTreeWidget;
1324 table->setColumnCount(3);
1325 table->headerItem()->setText( 0, qtr( "Action" ) );
1326 table->headerItem()->setText( 1, qtr( "Hotkey" ) );
1327 table->headerItem()->setToolTip( 1, qtr( "Application level hotkey" ) );
1328 table->headerItem()->setText( 2, qtr( "Global" ) );
1329 table->headerItem()->setToolTip( 2, qtr( "Desktop level hotkey" ) );
1330 table->setAlternatingRowColors( true );
1331 table->setSelectionBehavior( QAbstractItemView::SelectItems );
1333 table->installEventFilter( this );
1337 gLayout->addWidget( label, 0, 0, 1, 4 );
1338 gLayout->addWidget( searchLabel, 1, 0, 1, 2 );
1339 gLayout->addWidget( actionSearch, 1, 2, 1, 2 );
1340 gLayout->addWidget( table, 2, 0, 1, 4 );
1342 l->addWidget( keyContainer, line, 0, 1, -1 );
1344 CONNECT( actionSearch, textChanged( const QString& ),
1345 this, filter( const QString& ) );
1348 void KeySelectorControl::finish()
1350 if( label && p_item->psz_longtext )
1351 label->setToolTip( formatTooltip( qtr( p_item->psz_longtext ) ) );
1353 /* Fill the table */
1355 /* Get the main Module */
1356 module_t *p_main = module_get_main();
1359 /* Access to the module_config_t */
1361 module_config_t *p_config;
1363 p_config = module_config_get (p_main, &confsize);
1365 QMap<QString, QString> global_keys;
1366 for (size_t i = 0; i < confsize; i++)
1368 module_config_t *p_config_item = p_config + i;
1370 /* If we are a (non-global) key option not empty */
1371 if( CONFIG_ITEM(p_config_item->i_type) && p_config_item->psz_name != NULL
1372 && !strncmp( p_config_item->psz_name , "key-", 4 )
1373 && !EMPTY_STR( p_config_item->psz_text ) )
1377 - QString text in column 0
1378 - QString name in data of column 0
1379 - KeyValue in String in column 1
1381 QTreeWidgetItem *treeItem = new QTreeWidgetItem();
1382 treeItem->setText( 0, qtr( p_config_item->psz_text ) );
1383 treeItem->setData( 0, Qt::UserRole,
1384 QVariant( qfu( p_config_item->psz_name ) ) );
1386 QString keys = qfu( p_config_item->value.psz );
1387 treeItem->setText( 1, keys );
1388 treeItem->setToolTip( 1, qtr("Double click to change") );
1389 treeItem->setToolTip( 2, qtr("Double click to change") );
1390 treeItem->setData( 1, Qt::UserRole, QVariant( keys ) );
1391 table->addTopLevelItem( treeItem );
1395 if( CONFIG_ITEM(p_config_item->i_type) && p_config_item->psz_name != NULL
1396 && !strncmp( p_config_item->psz_name , "global-key", 10 )
1397 && !EMPTY_STR( p_config_item->psz_text )
1398 && !EMPTY_STR( p_config_item->value.psz ) )
1400 global_keys.insertMulti( qtr( p_config_item->psz_text ), qfu( p_config_item->value.psz ) );
1404 QMap<QString, QString>::const_iterator i = global_keys.constBegin();
1405 while (i != global_keys.constEnd())
1407 QList<QTreeWidgetItem *> list = table->findItems( i.key(), Qt::MatchExactly|Qt::MatchWrap, 0 );
1408 if( list.count() >= 1 )
1410 QString keys = i.value();
1411 list[0]->setText( 2, keys );
1412 list[0]->setData( 2, Qt::UserRole, keys );
1414 if( list.count() >= 2 )
1415 msg_Dbg( p_this, "This is probably wrong, %s", qtu(i.key()) );
1420 module_config_free (p_config);
1422 table->resizeColumnToContents( 0 );
1424 CONNECT( table, itemActivated( QTreeWidgetItem *, int ),
1425 this, selectKey( QTreeWidgetItem *, int ) );
1428 void KeySelectorControl::filter( const QString &qs_search )
1430 QList<QTreeWidgetItem *> resultList =
1431 table->findItems( qs_search, Qt::MatchContains, 0 );
1432 for( int i = 0; i < table->topLevelItemCount(); i++ )
1434 table->topLevelItem( i )->setHidden(
1435 !resultList.contains( table->topLevelItem( i ) ) );
1439 void KeySelectorControl::selectKey( QTreeWidgetItem *keyItem, int column )
1441 /* This happens when triggered by ClickEater */
1442 if( keyItem == NULL ) keyItem = table->currentItem();
1444 /* This can happen when nothing is selected on the treeView
1445 and the shortcutValue is clicked */
1446 if( !keyItem ) return;
1448 /* If clicked on the first column, assuming user wants the normal hotkey */
1449 if( column == 0 ) column = 1;
1451 bool b_global = ( column == 2 );
1453 /* Launch a small dialog to ask for a new key */
1454 KeyInputDialog *d = new KeyInputDialog( table, keyItem->text( 0 ), widget, b_global );
1457 if( d->result() == QDialog::Accepted )
1459 QString newKey = VLCKeyToString( d->keyValue );
1461 /* In case of conflict, reset other keys*/
1464 QTreeWidgetItem *it;
1465 for( int i = 0; i < table->topLevelItemCount() ; i++ )
1467 it = table->topLevelItem(i);
1468 if( ( keyItem != it ) &&
1469 ( it->data( 1 + b_global, Qt::UserRole ).toString() == newKey ) )
1471 it->setData( 1 + b_global, Qt::UserRole,
1472 QVariant( qfu( "Unset" ) ) );
1473 it->setText( 1 + b_global, qtr( "Unset" ) );
1478 keyItem->setText( column, newKey );
1479 keyItem->setData( column, Qt::UserRole, newKey );
1484 void KeySelectorControl::doApply()
1486 QTreeWidgetItem *it;
1487 for( int i = 0; i < table->topLevelItemCount() ; i++ )
1489 it = table->topLevelItem(i);
1490 if( it->data( 1, Qt::UserRole ).toInt() >= 0 )
1491 config_PutPsz( p_this,
1492 qtu( it->data( 0, Qt::UserRole ).toString() ),
1493 qtu( it->data( 1, Qt::UserRole ).toString() ) );
1494 if( !it->data( 2, Qt::UserRole ).toString().isEmpty() )
1496 config_PutPsz( p_this,
1497 qtu( "global-" + it->data( 0, Qt::UserRole ).toString() ),
1498 qtu( it->data( 2, Qt::UserRole ).toString() ) );
1504 bool KeySelectorControl::eventFilter( QObject *obj, QEvent *e )
1506 if( obj != table || e->type() != QEvent::KeyPress )
1507 return ConfigControl::eventFilter(obj, e);
1509 QKeyEvent *keyEv = static_cast<QKeyEvent*>(e);
1510 QTreeWidget *aTable = static_cast<QTreeWidget *>(obj);
1511 if( keyEv->key() == Qt::Key_Escape )
1513 aTable->clearFocus();
1516 else if( keyEv->key() == Qt::Key_Return ||
1517 keyEv->key() == Qt::Key_Enter )
1519 selectKey( aTable->currentItem(), aTable->currentColumn() );
1522 else if( keyEv->key() == Qt::Key_Delete )
1524 aTable->currentItem()->setText( aTable->currentColumn(), NULL );
1525 aTable->currentItem()->setData( aTable->currentColumn(), Qt::UserRole, QVariant() );
1534 * Class KeyInputDialog
1536 KeyInputDialog::KeyInputDialog( QTreeWidget *_table,
1537 const QString& keyToChange,
1540 QDialog( _parent ), keyValue(0), b_global( _b_global )
1546 setWindowTitle( ( b_global ? qtr( "Global" ) + QString(" ") : "" )
1547 + qtr( "Hotkey change" ) );
1548 setWindowRole( "vlc-key-input" );
1550 QVBoxLayout *vLayout = new QVBoxLayout( this );
1551 selected = new QLabel( qtr( "Press the new key or combination for " )
1552 + QString("<b>%1</b>").arg( keyToChange ) );
1553 vLayout->addWidget( selected , Qt::AlignCenter );
1555 warning = new QLabel;
1557 vLayout->insertWidget( 1, warning );
1559 buttonBox = new QDialogButtonBox;
1560 QPushButton *ok = new QPushButton( qtr("Assign") );
1561 QPushButton *cancel = new QPushButton( qtr("Cancel") );
1562 buttonBox->addButton( ok, QDialogButtonBox::AcceptRole );
1563 buttonBox->addButton( cancel, QDialogButtonBox::RejectRole );
1564 ok->setDefault( true );
1566 vLayout->addWidget( buttonBox );
1569 CONNECT( buttonBox, accepted(), this, accept() );
1570 CONNECT( buttonBox, rejected(), this, reject() );
1573 void KeyInputDialog::checkForConflicts( int i_vlckey )
1575 QList<QTreeWidgetItem *> conflictList =
1576 table->findItems( VLCKeyToString( i_vlckey ), Qt::MatchExactly,
1579 if( conflictList.count() &&
1580 !conflictList[0]->data( b_global ? 2 : 1, Qt::UserRole ).toString().isEmpty() &&
1581 conflictList[0]->data( b_global ? 2 : 1, Qt::UserRole ).toString() != "Unset" )
1583 warning->setText( qtr("Warning: this key or combination is already assigned to ") +
1584 QString( "\"<b>%1</b>\"" ).arg( conflictList[0]->text( 0 ) ) );
1593 void KeyInputDialog::keyPressEvent( QKeyEvent *e )
1595 if( e->key() == Qt::Key_Tab ||
1596 e->key() == Qt::Key_Shift ||
1597 e->key() == Qt::Key_Control ||
1598 e->key() == Qt::Key_Meta ||
1599 e->key() == Qt::Key_Alt ||
1600 e->key() == Qt::Key_AltGr )
1602 int i_vlck = qtEventToVLCKey( e );
1603 selected->setText( qtr( "Key or combination: " )
1604 + QString("<b>%1</b>").arg( VLCKeyToString( i_vlck ) ) );
1605 checkForConflicts( i_vlck );
1609 void KeyInputDialog::wheelEvent( QWheelEvent *e )
1611 int i_vlck = qtWheelEventToVLCKey( e );
1612 selected->setText( qtr( "Key: " ) + VLCKeyToString( i_vlck ) );
1613 checkForConflicts( i_vlck );