preferences_widgets.cpp 47.5 KB
Newer Older
1 2 3
/*****************************************************************************
 * preferences_widgets.cpp : Widgets for preferences displays
 ****************************************************************************
4
 * Copyright (C) 2006-2011 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
Antoine Cellerier's avatar
Antoine Cellerier committed
8
 *          Antoine Cellerier <dionoea@videolan.org>
9
 *          Jean-Baptiste Kempf <jb@videolan.org>
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

Clément Stenac's avatar
Clément Stenac committed
26 27
/**
 * Todo:
28
 *  - Validator for modulelist
Clément Stenac's avatar
Clément Stenac committed
29
 */
30 31 32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
Clément Stenac's avatar
Clément Stenac committed
33

34
#include "components/preferences_widgets.hpp"
35
#include "util/customwidgets.hpp"
36
#include "util/searchlineedit.hpp"
37
#include "util/qt_dirs.hpp"
38
#include <vlc_actions.h>
39
#include <vlc_intf_strings.h>
40
#include <vlc_modules.h>
41
#include <vlc_plugin.h>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
42

43 44
#include <QString>
#include <QVariant>
45
#include <QGridLayout>
46
#include <QSlider>
47
#include <QFileDialog>
48
#include <QGroupBox>
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
49
#include <QTreeWidgetItem>
50
#include <QSignalMapper>
51
#include <QDialogButtonBox>
52
#include <QKeyEvent>
53
#include <QColorDialog>
54 55
#include <QAction>
#include <QKeySequence>
56

57 58 59
#define MINWIDTH_BOX 90
#define LAST_COLUMN 10

60 61
QString formatTooltip(const QString & tooltip)
{
62 63 64
    QString text = tooltip;
    text.replace("\n", "<br/>");

65
    QString formatted =
66 67
    "<html><head><meta name=\"qrichtext\" content=\"1\" />"
    "<style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head>"
68
    "<body style=\" font-family:'Sans Serif'; "
69 70 71
    "font-style:normal; text-decoration:none;\">"
    "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; "
    "margin-right:0px; -qt-block-indent:0; text-indent:0px;\">" +
72
    text + "</p></body></html>";
73 74 75
    return formatted;
}

76 77 78
ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
                                             module_config_t *p_item,
                                             QWidget *parent,
79
                                             QGridLayout *l, int line )
80 81 82 83 84 85
{
    ConfigControl *p_control = NULL;

    switch( p_item->i_type )
    {
    case CONFIG_ITEM_MODULE:
86
        p_control = new StringListConfigControl( p_this, p_item, parent );
87 88
        break;
    case CONFIG_ITEM_MODULE_CAT:
89
        p_control = new ModuleConfigControl( p_this, p_item, parent );
90
        break;
91
    case CONFIG_ITEM_MODULE_LIST:
92
        p_control = new ModuleListConfigControl( p_this, p_item, parent, false );
93 94
        break;
    case CONFIG_ITEM_MODULE_LIST_CAT:
95
        p_control = new ModuleListConfigControl( p_this, p_item, parent, true );
96
        break;
97
    case CONFIG_ITEM_STRING:
98
        if( p_item->list.psz_cb )
99
            p_control = new StringListConfigControl( p_this, p_item, parent );
100 101
        else
            p_control = new StringConfigControl( p_this, p_item, parent, false );
102
        break;
103
    case CONFIG_ITEM_PASSWORD:
104
        p_control = new StringConfigControl( p_this, p_item, parent, true );
105
        break;
106
    case CONFIG_ITEM_RGB:
107
        p_control = new ColorConfigControl( p_this, p_item, parent );
108
        break;
Clément Stenac's avatar
Clément Stenac committed
109
    case CONFIG_ITEM_INTEGER:
110
        if( p_item->list.i_cb )
111
            p_control = new IntegerListConfigControl( p_this, p_item, parent, false );
112
        else if( p_item->min.i || p_item->max.i )
113
            p_control = new IntegerRangeConfigControl( p_this, p_item, parent );
Clément Stenac's avatar
Clément Stenac committed
114
        else
115
            p_control = new IntegerConfigControl( p_this, p_item, parent );
Clément Stenac's avatar
Clément Stenac committed
116
        break;
117 118
    case CONFIG_ITEM_LOADFILE:
    case CONFIG_ITEM_SAVEFILE:
119
        p_control = new FileConfigControl( p_this, p_item, parent );
120 121
        break;
    case CONFIG_ITEM_DIRECTORY:
122
        p_control = new DirectoryConfigControl( p_this, p_item, parent );
123
        break;
124
    case CONFIG_ITEM_FONT:
125
        p_control = new FontConfigControl( p_this, p_item, parent );
126
        break;
127
    case CONFIG_ITEM_KEY:
128
        p_control = new KeySelectorControl( p_this, p_item, parent );
129
        break;
130
    case CONFIG_ITEM_BOOL:
131
        p_control = new BoolConfigControl( p_this, p_item, parent );
132 133
        break;
    case CONFIG_ITEM_FLOAT:
134
        if( p_item->min.f || p_item->max.f )
135
            p_control = new FloatRangeConfigControl( p_this, p_item, parent );
136
        else
137
            p_control = new FloatConfigControl( p_this, p_item, parent );
138
        break;
139 140 141
    default:
        break;
    }
142
    if ( p_control ) p_control->insertIntoExistingGrid( l, line );
143 144 145
    return p_control;
}

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
/* Inserts controls into layouts
   This is sub-optimal in the OO way, as controls's code still
   depends on Layout classes. We should use layout inserters [friend]
   classes, but it's unlikely we had to deal with a different layout.*/
void ConfigControl::insertInto( QBoxLayout *layout )
{
    QGridLayout *sublayout = new QGridLayout();
    fillGrid( sublayout, 0 );
    layout->addLayout( sublayout );
}

void ConfigControl::insertIntoExistingGrid( QGridLayout *l, int line )
{
    fillGrid( l, line );
}

162 163 164
/*******************************************************
 * Simple widgets
 *******************************************************/
165
InterfacePreviewWidget::InterfacePreviewWidget ( QWidget *parent ) : QLabel( parent )
166 167 168 169 170
{
    setGeometry( 0, 0, 128, 100 );
    setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
}

171
void InterfacePreviewWidget::setNormalPreview( bool b_minimal )
172
{
173
    setPreview( ( b_minimal ) ? MINIMAL : COMPLETE );
174 175 176 177
}

void InterfacePreviewWidget::setPreview( enum_style e_style )
{
178
    QString pixmapLocationString;
179 180 181 182 183

    switch( e_style )
    {
    default:
    case COMPLETE:
184
        pixmapLocationString = ":/prefsmenu/sample_complete.png";
185 186
        break;
    case MINIMAL:
187
        pixmapLocationString = ":/prefsmenu/sample_minimal.png";
188 189
        break;
    case SKINS:
190
        pixmapLocationString = ":/prefsmenu/sample_skins.png";
191 192 193
        break;
    }

194 195
    setPixmap( QPixmap( pixmapLocationString ).
               scaledToWidth( width(), Qt::SmoothTransformation ) );
196
    update();
197 198 199
}


200 201 202 203
/**************************************************************************
 * String-based controls
 *************************************************************************/

204
void
205
VStringConfigControl::doApply()
206
{
207
    config_PutPsz( getName(), qtu( getValue() ) );
208 209
}

210 211
/*********** String **************/
StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
Clément Stenac's avatar
Clément Stenac committed
212
                                          module_config_t *_p_item,
213 214 215
                                          QWidget *_parent,
                                          bool pwd ) :
                           VStringConfigControl( _p_this, _p_item )
216
{
217 218
    label = new QLabel( p_item->psz_text ? qtr(p_item->psz_text) : "", _parent );
    text = new QLineEdit( p_item->value.psz ? qfu(p_item->value.psz) : "", _parent );
219
    if( pwd ) text->setEchoMode( QLineEdit::Password );
220
    finish();
221
}
222

223 224 225 226 227
void StringConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->setColumnMinimumWidth( 1, 10 );
    l->addWidget( text, line, LAST_COLUMN, Qt::AlignRight );
228 229
}

Clément Stenac's avatar
Clément Stenac committed
230 231
StringConfigControl::StringConfigControl( vlc_object_t *_p_this,
                                   module_config_t *_p_item,
232
                                   QLabel *_label, QLineEdit *_text, bool pwd ):
Clément Stenac's avatar
Clément Stenac committed
233 234 235
                           VStringConfigControl( _p_this, _p_item )
{
    text = _text;
236
    if( pwd ) text->setEchoMode( QLineEdit::Password );
237 238
    label = _label;
    finish( );
Clément Stenac's avatar
Clément Stenac committed
239
}
240

241 242
int VStringConfigControl::getType() const { return CONFIG_ITEM_STRING; }

243
void StringConfigControl::finish()
Clément Stenac's avatar
Clément Stenac committed
244
{
245
    text->setText( qfu(p_item->value.psz) );
246
    if( p_item->psz_longtext )
247
    {
248 249 250 251
        QString tipText = qtr(p_item->psz_longtext);
        text->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
252
    }
253 254
    if( label )
        label->setBuddy( text );
Antoine Cellerier's avatar
Antoine Cellerier committed
255 256
}

257 258
/*********** File **************/
FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
259 260
                                      module_config_t *_p_item, QWidget *p ) :
                           VStringConfigControl( _p_this, _p_item )
261
{
262 263 264
    label = new QLabel( qtr(p_item->psz_text), p );
    text = new QLineEdit( qfu(p_item->value.psz), p );
    browse = new QPushButton( qtr( "Browse..." ), p );
265 266 267 268 269 270

    BUTTONACT( browse, updateField() );

    finish();
}

271 272 273 274 275 276 277 278 279 280
void FileConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->setColumnMinimumWidth( 1, 10 );
    QHBoxLayout *textAndButton = new QHBoxLayout();
    textAndButton->setMargin( 0 );
    textAndButton->addWidget( text, 2 );
    textAndButton->addWidget( browse, 0 );
    l->addLayout( textAndButton, line, LAST_COLUMN, 0 );
}
281 282 283

FileConfigControl::FileConfigControl( vlc_object_t *_p_this,
                                   module_config_t *_p_item,
284
                                   QLabel *_label, QLineEdit *_text,
285
                                   QPushButton *_button ):
286 287
                           VStringConfigControl( _p_this, _p_item )
{
288
    browse = _button;
289 290
    text = _text;
    label = _label;
291 292 293

    BUTTONACT( browse, updateField() );

294 295 296 297 298
    finish( );
}

void FileConfigControl::updateField()
{
299 300 301 302 303 304 305 306 307
    QString file;

    if (p_item->i_type == CONFIG_ITEM_SAVEFILE)
        file = QFileDialog::getSaveFileName( NULL, qtr( "Save File" ),
                                             QVLCUserDir( VLC_HOME_DIR ) );
    else
        file = QFileDialog::getOpenFileName( NULL, qtr( "Select File" ),
                                             QVLCUserDir( VLC_HOME_DIR ) );

308
    if( file.isNull() ) return;
309
    text->setText( toNativeSeparators( file ) );
310 311 312 313 314
}

void FileConfigControl::finish()
{
    text->setText( qfu(p_item->value.psz) );
315
    if( p_item->psz_longtext )
316
    {
317 318 319 320
        QString tipText = qtr(p_item->psz_longtext);
        text->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
321
    }
322 323
    if( label )
        label->setBuddy( text );
324 325
}

326 327
/********* String / Directory **********/
DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
328 329
                        module_config_t *_p_item, QWidget *p ) :
     FileConfigControl( _p_this, _p_item, p )
330 331 332 333
{}

DirectoryConfigControl::DirectoryConfigControl( vlc_object_t *_p_this,
                        module_config_t *_p_item, QLabel *_p_label,
334 335
                        QLineEdit *_p_line, QPushButton *_p_button ):
     FileConfigControl( _p_this, _p_item, _p_label, _p_line, _p_button)
336 337 338 339
{}

void DirectoryConfigControl::updateField()
{
340
    QString dir = QFileDialog::getExistingDirectory( NULL,
341
                      qtr( I_OP_SEL_DIR ),
342
                      text->text().isEmpty() ?
343
                        QVLCUserDir( VLC_HOME_DIR ) : text->text(),
344 345
                  QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks );

346
    if( dir.isNull() ) return;
347
    text->setText( toNativeSepNoSlash( dir ) );
348 349
}

350 351
/********* String / Font **********/
FontConfigControl::FontConfigControl( vlc_object_t *_p_this,
352 353
                        module_config_t *_p_item, QWidget *p ) :
     VStringConfigControl( _p_this, _p_item )
354
{
355 356
    label = new QLabel( qtr(p_item->psz_text), p );
    font = new QFontComboBox( p );
357
    font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );
358 359 360 361 362

    if( p_item->psz_longtext )
    {
        label->setToolTip( formatTooltip( qtr(p_item->psz_longtext) ) );
    }
363
}
364

365 366 367 368 369 370
void FontConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( font, line, 1, 1, -1 );
}

371 372
FontConfigControl::FontConfigControl( vlc_object_t *_p_this,
                        module_config_t *_p_item, QLabel *_p_label,
373 374
                        QFontComboBox *_p_font):
     VStringConfigControl( _p_this, _p_item)
375
{
376 377
    label = _p_label;
    font = _p_font;
378
    font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );
379 380 381 382 383

    if( p_item->psz_longtext )
    {
        label->setToolTip( formatTooltip( qtr(p_item->psz_longtext) ) );
    }
384 385
}

Antoine Cellerier's avatar
Antoine Cellerier committed
386 387
/********* String / choice list **********/
StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
388 389
               module_config_t *_p_item, QWidget *p ) :
               VStringConfigControl( _p_this, _p_item )
Antoine Cellerier's avatar
Antoine Cellerier committed
390
{
391 392
    label = new QLabel( qtr(p_item->psz_text), p );
    combo = new QComboBox( p );
393
    combo->setMinimumWidth( MINWIDTH_BOX );
394
    combo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Preferred );
395

396
    module_config_t *p_module_config = config_FindConfig( p_item->psz_name );
397

398
    finish( p_module_config );
399 400
}

401 402 403 404 405 406
void StringListConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
    int i = 0;
    foreach( QPushButton *button, buttons )
407
        l->addWidget( button, line, LAST_COLUMN + i++,
408 409 410
                      Qt::AlignRight );
}

411 412 413 414 415 416
void StringListConfigControl::comboIndexChanged( int i_index )
{
    Q_UNUSED( i_index );
    emit changed();
}

Antoine Cellerier's avatar
Antoine Cellerier committed
417 418
StringListConfigControl::StringListConfigControl( vlc_object_t *_p_this,
                module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
419
                bool ) : VStringConfigControl( _p_this, _p_item )
Antoine Cellerier's avatar
Antoine Cellerier committed
420 421 422
{
    combo = _combo;
    label = _label;
423

424
    module_config_t *p_module_config = config_FindConfig( getName() );
425

426
    finish( p_module_config );
Antoine Cellerier's avatar
Antoine Cellerier committed
427 428
}

429
void StringListConfigControl::finish(module_config_t *p_module_config )
Antoine Cellerier's avatar
Antoine Cellerier committed
430 431
{
    combo->setEditable( false );
432
    CONNECT( combo, currentIndexChanged ( int ), this, comboIndexChanged( int ) );
Antoine Cellerier's avatar
Antoine Cellerier committed
433

434 435
    if(!p_module_config) return;

436
    char **values, **texts;
437
    ssize_t count = config_GetPszChoices( p_item->psz_name, &values, &texts );
438
    for( ssize_t i = 0; i < count && texts; i++ )
439
    {
440 441 442
        if( texts[i] == NULL || values[i] == NULL )
            continue;

443 444
        combo->addItem( qfu(texts[i]), QVariant( qfu(values[i])) );
        if( !strcmp( p_item->value.psz ? p_item->value.psz : "", values[i] ) )
Antoine Cellerier's avatar
Antoine Cellerier committed
445
            combo->setCurrentIndex( combo->count() - 1 );
446 447
        free( texts[i] );
        free( values[i] );
Antoine Cellerier's avatar
Antoine Cellerier committed
448
    }
449 450
    free( texts );
    free( values );
451 452

    if( p_module_config->psz_longtext  )
453
    {
454 455 456 457
        QString tipText = qtr(p_module_config->psz_longtext);
        combo->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
458
    }
459 460
    if( label )
        label->setBuddy( combo );
Antoine Cellerier's avatar
Antoine Cellerier committed
461 462
}

463
QString StringListConfigControl::getValue() const
Antoine Cellerier's avatar
Antoine Cellerier committed
464 465
{
    return combo->itemData( combo->currentIndex() ).toString();
Clément Stenac's avatar
Clément Stenac committed
466
}
467

468
void setfillVLCConfigCombo( const char *configname, intf_thread_t *p_intf,
469
                            QComboBox *combo )
470
{
471
    module_config_t *p_config = config_FindConfig( configname );
472 473
    if( p_config == NULL )
        return;
474

475 476 477
    if( (p_config->i_type & 0xF0) == CONFIG_ITEM_STRING )
    {
        char **values, **texts;
478
        ssize_t count = config_GetPszChoices(configname, &values, &texts);
479
        for( ssize_t i = 0; i < count; i++ )
480
        {
481
            combo->addItem( qtr(texts[i]), QVariant(qfu(values[i])) );
482
            if( p_config->value.psz && !strcmp(p_config->value.psz, values[i]) )
483 484 485
                combo->setCurrentIndex( i );
            free( texts[i] );
            free( values[i] );
486
        }
487 488 489 490 491 492 493
        free( texts );
        free( values );
    }
    else
    {
        int64_t *values;
        char **texts;
494
        ssize_t count = config_GetIntChoices(configname, &values, &texts);
495
        for( ssize_t i = 0; i < count; i++ )
496
        {
497 498 499 500
            combo->addItem( qtr(texts[i]), QVariant(qlonglong(values[i])) );
            if( p_config->value.i == values[i] )
                combo->setCurrentIndex( i );
            free( texts[i] );
501
        }
502
        free( texts );
Hannes Domani's avatar
Hannes Domani committed
503
        free( values );
504
    }
505 506 507

    if( p_config->psz_longtext != NULL )
        combo->setToolTip( qfu( p_config->psz_longtext ) );
508 509
}

510 511
/********* Module **********/
ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
512
               module_config_t *_p_item, QWidget *p ) :
513
               VStringConfigControl( _p_this, _p_item )
Clément Stenac's avatar
Clément Stenac committed
514
{
515 516
    label = new QLabel( qtr(p_item->psz_text), p );
    combo = new QComboBox( p );
517
    combo->setMinimumWidth( MINWIDTH_BOX );
518
    finish( );
519 520 521 522 523 524
}

void ModuleConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN, 0 );
Clément Stenac's avatar
Clément Stenac committed
525
}
526

Clément Stenac's avatar
Clément Stenac committed
527
ModuleConfigControl::ModuleConfigControl( vlc_object_t *_p_this,
528 529
                module_config_t *_p_item, QLabel *_label, QComboBox *_combo )
                : VStringConfigControl( _p_this, _p_item )
Clément Stenac's avatar
Clément Stenac committed
530 531
{
    combo = _combo;
532
    label = _label;
533
    finish( );
Clément Stenac's avatar
Clément Stenac committed
534 535
}

536
void ModuleConfigControl::finish( )
537 538 539 540
{
    combo->setEditable( false );

    /* build a list of available modules */
541 542
    size_t count;
    module_t **p_list = module_list_get( &count );
543
    combo->addItem( qtr("Default") );
544
    for( size_t i = 0; i < count; i++ )
545
    {
546 547
        module_t *p_parser = p_list[i];

548
        if( !strcmp( module_get_object( p_parser ), "core" ) ) continue;
549 550 551 552 553 554

        unsigned confsize;
        module_config_t *p_config;

        p_config = module_config_get (p_parser, &confsize);
        for (size_t i = 0; i < confsize; i++)
555
        {
556 557 558 559 560 561
            /* Hack: required subcategory is stored in i_min */
            const module_config_t *p_cfg = p_config + i;
            if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
                p_cfg->value.i == p_item->min.i )
                combo->addItem( qtr( module_GetLongName( p_parser )),
                                QVariant( module_get_object( p_parser ) ) );
562
            if( p_item->value.psz && !strcmp( p_item->value.psz,
563
                                              module_get_object( p_parser ) ) )
564 565
                combo->setCurrentIndex( combo->count() - 1 );
        }
566
        module_config_free (p_config);
567
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
568
    module_list_free( p_list );
569 570

    if( p_item->psz_longtext )
571
    {
572 573 574 575
        QString tipText = qtr(p_item->psz_longtext);
        combo->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
576
    }
577 578
    if( label )
        label->setBuddy( combo );
579 580
}

581
QString ModuleConfigControl::getValue() const
582 583 584
{
    return combo->itemData( combo->currentIndex() ).toString();
}
Clément Stenac's avatar
Clément Stenac committed
585

586 587
/********* Module list **********/
ModuleListConfigControl::ModuleListConfigControl( vlc_object_t *_p_this,
588 589
        module_config_t *_p_item, QWidget *p, bool bycat ) :
    VStringConfigControl( _p_this, _p_item )
590
{
591
    groupBox = NULL;
592

593
    /* Special Hack */
594 595
    if( !p_item->psz_text ) return;

596 597
    groupBox = new QGroupBox ( qtr(p_item->psz_text), p );
    text = new QLineEdit( p );
598 599
    QGridLayout *layoutGroupBox = new QGridLayout( groupBox );

600 601
    finish( bycat );

602
    int boxline = 0;
603
    foreach ( checkBoxListItem *it, modules )
604 605 606 607 608
    {
        layoutGroupBox->addWidget( it->checkBox, boxline / 2, boxline % 2 );
        boxline++;
    }

609
    layoutGroupBox->addWidget( text, boxline, 0, 1, 2 );
610

611 612
    if( p_item->psz_longtext )
        text->setToolTip( formatTooltip( qtr( p_item->psz_longtext) ) );
613 614
}

615 616 617 618 619
void ModuleListConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( groupBox, line, 0, 1, -1 );
}

620 621
ModuleListConfigControl::~ModuleListConfigControl()
{
Hannes Domani's avatar
Hannes Domani committed
622 623
    foreach ( checkBoxListItem *it, modules )
        free( it->psz_module );
624 625
    qDeleteAll( modules );
    modules.clear();
626
    delete groupBox;
627 628
}

629 630
void ModuleListConfigControl::checkbox_lists( module_t *p_parser )
{
631 632 633 634
    const char *help = module_get_help( p_parser );
    checkbox_lists( qtr( module_GetLongName( p_parser ) ),
                    help != NULL ? qtr( help ): "",
                    module_get_object( p_parser ) );
635
}
636

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
void ModuleListConfigControl::checkbox_lists( QString label, QString help, const char* psz_module )
{
    QCheckBox *cb = new QCheckBox( label );
    checkBoxListItem *cbl = new checkBoxListItem;

    CONNECT( cb, stateChanged( int ), this, onUpdate() );
    if( !help.isEmpty() )
        cb->setToolTip( formatTooltip( help ) );
    cbl->checkBox = cb;

    cbl->psz_module = strdup( psz_module );
    modules.append( cbl );

    if( p_item->value.psz && strstr( p_item->value.psz, cbl->psz_module ) )
        cbl->checkBox->setChecked( true );
}
653

654 655 656
void ModuleListConfigControl::finish( bool bycat )
{
    /* build a list of available modules */
657 658 659
    size_t count;
    module_t **p_list = module_list_get( &count );
    for( size_t i = 0; i < count; i++ )
660
    {
661 662
        module_t *p_parser = p_list[i];

663 664
        if( bycat )
        {
665
            if( !strcmp( module_get_object( p_parser ), "core" ) ) continue;
666

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
667
            unsigned confsize;
668
            module_config_t *p_config = module_config_get (p_parser, &confsize);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
669 670

            for (size_t i = 0; i < confsize; i++)
671
            {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
672
                module_config_t *p_cfg = p_config + i;
673
                /* Hack: required subcategory is stored in i_min */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
674 675
                if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
                        p_cfg->value.i == p_item->min.i )
676
                {
677
                    checkbox_lists( p_parser );
678
                }
679 680 681 682 683 684 685 686 687 688 689

                /* Parental Advisory HACK:
                 * Selecting HTTP, RC and Telnet interfaces is difficult now
                 * since they are just the lua interface module */
                if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
                    !strcmp( module_get_object( p_parser ), "lua" ) &&
                    !strcmp( p_item->psz_name, "extraintf" ) &&
                    p_cfg->value.i == p_item->min.i )
                {
                    checkbox_lists( "Web", "Lua HTTP", "http" );
                    checkbox_lists( "Telnet", "Lua Telnet", "telnet" );
690
#ifndef _WIN32
691
                    checkbox_lists( "Console", "Lua CLI", "cli" );
692
#endif
693
                }
694
            }
695
            module_config_free (p_config);
696
        }
697
        else if( module_provides( p_parser, p_item->psz_type ) )
698
        {
699
            checkbox_lists(p_parser);
700
        }
701
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
702
    module_list_free( p_list );
703 704 705 706 707 708 709 710 711

    if( p_item->psz_longtext )
    {
        QString tipText = qtr(p_item->psz_longtext);

        text->setToolTip( formatTooltip(tipText) );
        assert( groupBox );
        groupBox->setToolTip( formatTooltip(tipText) );
   }
712 713
}

714
QString ModuleListConfigControl::getValue() const
715
{
716
    assert( text );
717 718 719
    return text->text();
}

720
void ModuleListConfigControl::changeVisibility( bool b )
721
{
722
    foreach ( checkBoxListItem *it, modules )
723 724
        it->checkBox->setVisible( b );
    groupBox->setVisible( b );
725 726
}

727
void ModuleListConfigControl::onUpdate()
728 729
{
    text->clear();
730 731
    bool first = true;

732
    foreach ( checkBoxListItem *it, modules )
733
    {
734
        if( it->checkBox->isChecked() )
735 736 737
        {
            if( first )
            {
738
                text->setText( text->text() + it->psz_module );
739 740 741 742
                first = false;
            }
            else
            {
743
                text->setText( text->text() + ":" + it->psz_module );
744 745
            }
        }
746 747 748
    }
}

Clément Stenac's avatar
Clément Stenac committed
749 750 751 752
/**************************************************************************
 * Integer-based controls
 *************************************************************************/

753
void
754
VIntConfigControl::doApply()
755
{
756
    config_PutInt( getName(), getValue() );
757 758
}

Clément Stenac's avatar
Clément Stenac committed
759 760
/*********** Integer **************/
IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
761 762
                                            module_config_t *_p_item, QWidget *p ) :
                           VIntConfigControl( _p_this, _p_item )
Clément Stenac's avatar
Clément Stenac committed
763
{
764 765
    label = new QLabel( qtr(p_item->psz_text), p );
    spin = new QSpinBox( p ); spin->setMinimumWidth( MINWIDTH_BOX );
766
    spin->setAlignment( Qt::AlignRight );
767
    spin->setMaximumWidth( MINWIDTH_BOX );
768
    finish();
Clément Stenac's avatar
Clément Stenac committed
769
}
770

Clément Stenac's avatar
Clément Stenac committed
771 772
IntegerConfigControl::IntegerConfigControl( vlc_object_t *_p_this,
                                            module_config_t *_p_item,
773
                                            QLabel *_label, QSpinBox *_spin ) :
Clément Stenac's avatar
Clément Stenac committed
774 775 776
                                      VIntConfigControl( _p_this, _p_item )
{
    spin = _spin;
777 778
    label = _label;
    finish();
Clément Stenac's avatar
Clément Stenac committed
779 780
}

781 782 783 784 785 786
void IntegerConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
}

787
void IntegerConfigControl::finish()
Clément Stenac's avatar
Clément Stenac committed
788
{
789
    spin->setMaximum( 2000000000 );
790
    spin->setMinimum( -2000000000 );
791
    spin->setValue( p_item->value.i );
792 793

    if( p_item->psz_longtext )
794
    {
795 796 797 798
        QString tipText = qtr(p_item->psz_longtext);
        spin->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
799
    }
800 801
    if( label )
        label->setBuddy( spin );
Clément Stenac's avatar
Clément Stenac committed
802 803
}

804
int IntegerConfigControl::getValue() const
Clément Stenac's avatar
Clément Stenac committed
805 806 807
{
    return spin->value();
}
Antoine Cellerier's avatar
Antoine Cellerier committed
808

809 810
int VIntConfigControl::getType() const { return CONFIG_ITEM_INTEGER; }

811 812
/********* Integer range **********/
IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
813 814
                                            module_config_t *_p_item, QWidget *p ) :
            IntegerConfigControl( _p_this, _p_item, p )
815 816 817 818 819 820 821 822 823 824 825 826 827 828
{
    finish();
}

IntegerRangeConfigControl::IntegerRangeConfigControl( vlc_object_t *_p_this,
                                            module_config_t *_p_item,
                                            QLabel *_label, QSpinBox *_spin ) :
            IntegerConfigControl( _p_this, _p_item, _label, _spin )
{
    finish();
}

void IntegerRangeConfigControl::finish()
{
829 830
    spin->setMaximum( p_item->max.i > INT_MAX ? INT_MAX : p_item->max.i );
    spin->setMinimum( p_item->min.i < INT_MIN ? INT_MIN : p_item->min.i );
831 832
}

833 834 835
IntegerRangeSliderConfigControl::IntegerRangeSliderConfigControl(
                                            vlc_object_t *_p_this,
                                            module_config_t *_p_item,
836
                                            QLabel *_label, QSlider *_slider ):
837 838 839 840
                    VIntConfigControl( _p_this, _p_item )
{
    slider = _slider;
    label = _label;
841 842
    slider->setMaximum( p_item->max.i > INT_MAX ? INT_MAX : p_item->max.i );
    slider->setMinimum( p_item->min.i < INT_MIN ? INT_MIN : p_item->min.i );
843
    slider->setValue( p_item->value.i );
844
    if( p_item->psz_longtext )
845
    {
846 847 848 849
        QString tipText = qtr(p_item->psz_longtext);
        slider->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
850
    }
851 852
    if( label )
        label->setBuddy( slider );
853 854
}

855
int IntegerRangeSliderConfigControl::getValue() const
856 857 858 859 860
{
        return slider->value();
}


Antoine Cellerier's avatar
Antoine Cellerier committed
861 862
/********* Integer / choice list **********/
IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
863 864
               module_config_t *_p_item, QWidget *p, bool ) :
               VIntConfigControl( _p_this, _p_item )
Antoine Cellerier's avatar
Antoine Cellerier committed
865
{
866 867
    label = new QLabel( qtr(p_item->psz_text), p );
    combo = new QComboBox( p );
868
    combo->setMinimumWidth( MINWIDTH_BOX );
869

870
    module_config_t *p_module_config = config_FindConfig( p_item->psz_name );
871

872
    finish( p_module_config );
Antoine Cellerier's avatar
Antoine Cellerier committed
873
}
874 875 876 877 878 879 880

void IntegerListConfigControl::fillGrid( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
    int i = 0;
    foreach( QPushButton *button, buttons )
881
        l->addWidget( button, line, LAST_COLUMN + i++,
882 883 884
                      Qt::AlignRight );
}

Antoine Cellerier's avatar
Antoine Cellerier committed
885 886
IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *_p_this,
                module_config_t *_p_item, QLabel *_label, QComboBox *_combo,
887
                bool ) : VIntConfigControl( _p_this, _p_item )
Antoine Cellerier's avatar
Antoine Cellerier committed
888 889 890
{
    combo = _combo;
    label = _label;
891

892
    module_config_t *p_module_config = config_FindConfig( getName() );
893

894
    finish( p_module_config );
Antoine Cellerier's avatar
Antoine Cellerier committed
895 896
}

897
void IntegerListConfigControl::finish(module_config_t *p_module_config )
Antoine Cellerier's avatar
Antoine Cellerier committed
898 899 900
{
    combo->setEditable( false );

901 902
    if(!p_module_config) return;

903 904
    int64_t *values;
    char **texts;
905
    ssize_t count = config_GetIntChoices( p_module_config->psz_name,
906 907
                                          &values, &texts );
    for( ssize_t i = 0; i < count; i++ )
Antoine Cellerier's avatar
Antoine Cellerier committed
908
    {