Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/gui/qt/dialogs/preferences/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 57 kB image not shown  

SSL preferences_widgets.cpp   Sprache: C

 

/*****************************************************************************
 * preferences_widgets.cpp : Widgets for preferences displays
 ****************************************************************************
 * Copyright (C) 2006-2011 the VideoLAN team
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Antoine Cellerier <dionoea@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * 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.
 *****************************************************************************/


/**
 * Todo:
 *  - Validator for modulelist
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "dialogs/preferences/preferences_widgets.hpp"
#include "widgets/native/searchlineedit.hpp"
#include "util/vlchotkeyconverter.hpp"
#include "util/qt_dirs.hpp"
#include <vlc_intf_strings.h>
#include <vlc_modules.h>
#include <vlc_plugin.h>

#include <QWidget>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QGridLayout>
#include <QSlider>
#include <QFileDialog>
#include <QGroupBox>
#include <QTreeWidget>
#include <QTreeWidgetItemIterator>
#include <QDialogButtonBox>
#include <QKeyEvent>
#include <QColorDialog>
#include <QAction>
#include <QKeySequence>
#include <QDoubleSpinBox>
#include <QCheckBox>
#include <QComboBox>
#include <QLineEdit>
#include <QSpinBox>
#include <QPushButton>
#include <QFontComboBox>
#include <QMenu>
#include <QGuiApplication>
#include <QClipboard>
#include <QFont>
#include <QToolButton>

#define MINWIDTH_BOX 90
#define LAST_COLUMN 10

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

    QString formatted =
    "<html><head><meta name=\"qrichtext\" content=\"1\" />"
    "<style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head>"
    "<body style=\" font-family:'Sans Serif'; "
    "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;\">" +
    text + "</p></body></html>";
    return formatted;
}

ConfigControl *ConfigControl::createControl( module_config_t *p_item,
                                             QWidget *parent )
{
    ConfigControl *p_control = NULL;

    switch( p_item->i_type )
    {
    case CONFIG_ITEM_MODULE:
        p_control = new StringListConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_MODULE_CAT:
        p_control = new ModuleConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_MODULE_LIST:
        p_control = new ModuleListConfigControl( p_item, parent, false );
        break;
    case CONFIG_ITEM_MODULE_LIST_CAT:
        p_control = new ModuleListConfigControl( p_item, parent, true );
        break;
    case CONFIG_ITEM_STRING:
        if( p_item->list_count )
            p_control = new StringListConfigControl( p_item, parent );
        else
            p_control = new StringConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_PASSWORD:
        p_control = new PasswordConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_RGB:
        p_control = new ColorConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_INTEGER:
        if( p_item->list_count )
            p_control = new IntegerListConfigControl( p_item, parent );
        else
            p_control = new IntegerRangeConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_LOADFILE:
    case CONFIG_ITEM_SAVEFILE:
        p_control = new FileConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_DIRECTORY:
        p_control = new DirectoryConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_FONT:
        p_control = new FontConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_KEY:
        p_control = new KeySelectorControl( parent );
        break;
    case CONFIG_ITEM_BOOL:
        p_control = new BoolConfigControl( p_item, parent );
        break;
    case CONFIG_ITEM_FLOAT:
        p_control = new FloatRangeConfigControl( p_item, parent );
        break;
    default:
        break;
    }
    return p_control;
}

ConfigControl *ConfigControl::createControl( module_config_t *item,
                                             QWidget *parent,
                                             QGridLayout *l, int line )
{
    ConfigControl *control = createControl( item, parent );
    if ( control )
        control->insertInto( l, line );
    return control;
}

ConfigControl *ConfigControl::createControl( module_config_t *item,
                                             QWidget *parent,
                                             QBoxLayout *l, int index )
{
    ConfigControl *control = createControl( item, parent );
    if ( control )
        control->insertInto( l, index );
    return control;
}

/*******************************************************
 * Simple widgets
 *******************************************************/

InterfacePreviewWidget::InterfacePreviewWidget ( QWidget *parent ) : QLabel( parent )
{
    setGeometry( 0, 0, 128, 100 );
    setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
}

void InterfacePreviewWidget::setNormalPreview( bool b_minimal )
{
    setPreview( ( b_minimal ) ? MINIMAL : COMPLETE );
}

void InterfacePreviewWidget::setPreview( enum_style e_style )
{
    QString pixmapLocationString;

    switch( e_style )
    {
    default:
    case COMPLETE:
        pixmapLocationString = ":/prefsmenu/sample_complete.png";
        break;
    case MINIMAL:
        pixmapLocationString = ":/prefsmenu/sample_minimal.png";
        break;
    case SKINS:
        pixmapLocationString = ":/prefsmenu/sample_skins.png";
        break;
    }

    setPixmap( QPixmap( pixmapLocationString ).
               scaledToWidth( width(), Qt::SmoothTransformation ) );
    update();
}


/**************************************************************************
 * String-based controls
 *************************************************************************/


void
VStringConfigControl::doApply()
{
    config_PutPsz( getName(), qtu( getValue() ) );
}

void VStringConfigControl::storeValue()
{
    /* Note, this modifies our local copy of the item only */
    free( p_item->value.psz );
    p_item->value.psz = strdup( qtu( getValue() ) );
}

/*********** String **************/
StringConfigControl::StringConfigControl( module_config_t *_p_item,
                                          QWidget *_parent ) :
    VStringConfigControl( _p_item )
{
    label = new QLabel( p_item->psz_text ? qfut(p_item->psz_text) : "", _parent );
    text = new QLineEdit( p_item->value.psz ? qfu(p_item->value.psz) : "", _parent );
    finish();
}

StringConfigControl::StringConfigControl( module_config_t *_p_item,
                                          QLabel *_label, QLineEdit *_text ) :
    VStringConfigControl( _p_item )
{
    text = _text;
    label = _label;
    finish( );
}

void StringConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->setColumnMinimumWidth( 1, 10 );
    l->addWidget( text, line, LAST_COLUMN, Qt::AlignRight );
}

void StringConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, text );
}

void StringConfigControl::finish()
{
    text->setText( qfu(p_item->value.psz) );
    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        text->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( text );
}

void StringConfigControl::changeVisibility( bool visible )
{
    text->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

QString StringConfigControl::getValue() const
{
    return text->text();
}

/********* String / Password **********/
PasswordConfigControl::PasswordConfigControl( module_config_t *_p_item,
                                              QWidget *_parent ) :
    StringConfigControl( _p_item, _parent )
{
    finish();
}

PasswordConfigControl::PasswordConfigControl( module_config_t *_p_item,
                                              QLabel *_label, QLineEdit *_text ) :
    StringConfigControl( _p_item, _label, _text )
{
    finish();
}

void PasswordConfigControl::finish()
{
    text->setEchoMode( QLineEdit::Password );
}

/*********** File **************/
FileConfigControl::FileConfigControl( module_config_t *_p_item, QWidget *p ) :
    VStringConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    text = new QLineEdit( qfu(p_item->value.psz), p );
    browse = new QPushButton( qtr( "Browse..." ), p );

    BUTTONACT( browse, &FileConfigControl::updateField );

    finish();
}

FileConfigControl::FileConfigControl( module_config_t *_p_item,
                                      QLabel *_label, QLineEdit *_text,
                                      QPushButton *_button ) :
    VStringConfigControl( _p_item )
{
    browse = _button;
    text = _text;
    label = _label;

    BUTTONACT( browse, &FileConfigControl::updateField );

    finish( );
}

void FileConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->setColumnMinimumWidth( 1, 10 );
    QHBoxLayout *textAndButton = new QHBoxLayout();
    textAndButton->setContentsMargins(0, 0, 0, 0);
    textAndButton->addWidget( text, 2 );
    textAndButton->addWidget( browse, 0 );
    l->addLayout( textAndButton, line, LAST_COLUMN );
}

void FileConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    QHBoxLayout *textAndButton = new QHBoxLayout();
    textAndButton->setContentsMargins(0, 0, 0, 0);
    textAndButton->addWidget( text, 2 );
    textAndButton->addWidget( browse, 0 );
    l->insertLayout( index + 1, textAndButton );
}

void FileConfigControl::updateField()
{
    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 ) );

    if( file.isNull() ) return;
    text->setText( toNativeSeparators( file ) );
}

void FileConfigControl::finish()
{
    text->setText( qfu(p_item->value.psz) );
    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        text->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( text );
}

void FileConfigControl::changeVisibility( bool visible )
{
    text->setVisible( visible );
    browse->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

QString FileConfigControl::getValue() const
{
    return text->text();
}

/********* String / Directory **********/
DirectoryConfigControl::DirectoryConfigControl( module_config_t *_p_item,
                                                QWidget *p ) :
    FileConfigControl( _p_item, p )
{}

DirectoryConfigControl::DirectoryConfigControl( module_config_t *_p_item,
                                                QLabel *_p_label,
                                                QLineEdit *_p_line,
                                                QPushButton *_p_button ) :
    FileConfigControl( _p_item, _p_label, _p_line, _p_button)
{}

void DirectoryConfigControl::updateField()
{
    QString dir = QFileDialog::getExistingDirectory( NULL,
                      qfut( I_OP_SEL_DIR ),
                      text->text().isEmpty() ?
                        QVLCUserDir( VLC_HOME_DIR ) : text->text(),
                  QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks );

    if( dir.isNull() ) return;
    text->setText( toNativeSepNoSlash( std::move(dir) ) );
}

/********* String / Font **********/
FontConfigControl::FontConfigControl( module_config_t *_p_item, QWidget *p ) :
    VStringConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    font = new QFontComboBox( p );
    font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );

    if( p_item->psz_longtext )
    {
        label->setToolTip( formatTooltip( qfut(p_item->psz_longtext) ) );
    }
}

FontConfigControl::FontConfigControl( module_config_t *_p_item,
                                      QLabel *_p_label,
                                      QFontComboBox *_p_font) :
    VStringConfigControl( _p_item)
{
    label = _p_label;
    font = _p_font;
    font->setCurrentFont( QFont( qfu( p_item->value.psz) ) );

    if( p_item->psz_longtext )
    {
        label->setToolTip( formatTooltip( qfut(p_item->psz_longtext) ) );
    }
}

void FontConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( font, line, 1, 1, -1 );
}

void FontConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, font );
}

void FontConfigControl::changeVisibility( bool visible )
{
    font->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

QString FontConfigControl::getValue() const
{
    return font->currentFont().family();
}

/********* String / choice list **********/
StringListConfigControl::StringListConfigControl( module_config_t *_p_item,
                                                  QWidget *p ) :
    VStringConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    combo = new QComboBox( p );
    combo->setMinimumWidth( MINWIDTH_BOX );
    combo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );

    /* needed to see update from getting choice list where callback used */
    module_config_t *p_module_config = config_FindConfig( p_item->psz_name );

    finish( p_module_config );
}

StringListConfigControl::StringListConfigControl( module_config_t *_p_item,
                                                  QLabel *_label,
                                                  QComboBox *_combo ) :
    VStringConfigControl( _p_item )
{
    combo = _combo;
    label = _label;

    /* needed to see update from getting choice list where callback used */
    module_config_t *p_module_config = config_FindConfig( getName() );

    finish( p_module_config );
}

void StringListConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
}

void StringListConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, combo );
}

void StringListConfigControl::comboIndexChanged( int i_index )
{
    Q_UNUSED( i_index );
    emit changed();
}

void StringListConfigControl::finish(module_config_t *p_module_config )
{
    combo->setEditable( false );
    connect( combo, QOverload<int>::of(&QComboBox::currentIndexChanged),
             this, &StringListConfigControl::comboIndexChanged );

    if(!p_module_config) return;

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

        combo->addItem( qfu(texts[i]), QVariant( qfu(values[i])) );
        if( !strcmp( p_item->value.psz ? p_item->value.psz : "", values[i] ) )
            combo->setCurrentIndex( combo->count() - 1 );
        free( texts[i] );
        free( values[i] );
    }
    free( texts );
    free( values );

    if( p_module_config->psz_longtext )
    {
        QString tipText = qfut(p_module_config->psz_longtext);
        combo->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( combo );
}

void StringListConfigControl::changeVisibility( bool visible )
{
    combo->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

QString StringListConfigControl::getValue() const
{
    return combo->itemData( combo->currentIndex() ).toString();
}

void setfillVLCConfigCombo( const char *configname, QComboBox *combo )
{
    module_config_t *p_config = config_FindConfig( configname );
    if( p_config == NULL )
        return;

    if( (p_config->i_type & 0xF0) == CONFIG_ITEM_STRING )
    {
        char **values, **texts;
        ssize_t count = config_GetPszChoices(configname, &values, &texts);
        for( ssize_t i = 0; i < count; i++ )
        {
            combo->addItem( qfut(texts[i]), QVariant(qfu(values[i])) );
            if( p_config->value.psz && !strcmp(p_config->value.psz, values[i]) )
                combo->setCurrentIndex( i );
            free( texts[i] );
            free( values[i] );
        }
        free( texts );
        free( values );
    }
    else
    {
        int64_t *values;
        char **texts;
        ssize_t count = config_GetIntChoices(configname, &values, &texts);
        for( ssize_t i = 0; i < count; i++ )
        {
            combo->addItem( qfut(texts[i]), QVariant(qlonglong(values[i])) );
            if( p_config->value.i == values[i] )
                combo->setCurrentIndex( i );
            free( texts[i] );
        }
        free( texts );
        free( values );
    }

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

/********* Module **********/
ModuleConfigControl::ModuleConfigControl( module_config_t *_p_item,
                                          QWidget *p ) :
    VStringConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    combo = new QComboBox( p );
    combo->setMinimumWidth( MINWIDTH_BOX );
    finish( );
}

ModuleConfigControl::ModuleConfigControl( module_config_t *_p_item,
                                          QLabel *_label, QComboBox *_combo ) :
    VStringConfigControl( _p_item )
{
    combo = _combo;
    label = _label;
    finish( );
}

void ModuleConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN );
}

void ModuleConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, combo );
}

void ModuleConfigControl::finish( )
{
    combo->setEditable( false );

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

        if( !strcmp( module_get_object( p_parser ), "core" ) ) continue;

        unsigned confsize;
        module_config_t *p_config;

        p_config = module_config_get (p_parser, &confsize);
        for (size_t i = 0; i < confsize; i++)
        {
            /* 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( qfut( module_GetLongName( p_parser )),
                                QVariant( module_get_object( p_parser ) ) );
                if( p_item->value.psz && !strcmp( p_item->value.psz,
                                                  module_get_object( p_parser ) ) )
                    combo->setCurrentIndex( combo->count() - 1 );
                break;
            }
        }
        module_config_free (p_config);
    }
    module_list_free( p_list );

    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        combo->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( combo );
}

void ModuleConfigControl::changeVisibility( bool visible )
{
    combo->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

QString ModuleConfigControl::getValue() const
{
    return combo->itemData( combo->currentIndex() ).toString();
}

/********* Module list **********/
ModuleListConfigControl::ModuleListConfigControl( module_config_t *_p_item,
                                                  QWidget *p, bool bycat ) :
    VStringConfigControl( _p_item )
{
    groupBox = NULL;

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

    groupBox = new QGroupBox( qfut(p_item->psz_text), p );
    text = new QLineEdit( p );
    QGridLayout *layoutGroupBox = new QGridLayout( groupBox );

    finish( bycat );

    int boxline = 0;
    foreach ( checkBoxListItem *it, modules )
    {
        layoutGroupBox->addWidget( it->checkBox, boxline / 2, boxline % 2 );
        boxline++;
    }

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

    if( p_item->psz_longtext )
        text->setToolTip( formatTooltip( qfut( p_item->psz_longtext) ) );
}

void ModuleListConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( groupBox, line, 0, 1, -1 );
}

void ModuleListConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, groupBox );
}

ModuleListConfigControl::~ModuleListConfigControl()
{
    qDeleteAll( modules );
    modules.clear();
}

void ModuleListConfigControl::checkbox_lists( module_t *p_parser )
{
    const char *help = module_get_help( p_parser );
    checkbox_lists( qfut( module_GetLongName( p_parser ) ),
                    help != NULL ? qfut( help ): "",
                    module_get_object( p_parser ) );
}

void ModuleListConfigControl::checkbox_lists( QString label, QString help, const char* psz_module )
{
    QCheckBox *cb = new QCheckBox( label );
    checkBoxListItem *cbl = new checkBoxListItem;

    connect( cb, &QtCheckboxChanged, this, &ModuleListConfigControl::onUpdate );
    if( !help.isEmpty() )
        cb->setToolTip( formatTooltip( help ) );
    cbl->checkBox = cb;

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

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

void ModuleListConfigControl::finish( bool bycat )
{
    /* build a list of available modules */
    size_t count;
    module_t **p_list = module_list_get( &count );
    for( size_t i = 0; i < count; i++ )
    {
        module_t *p_parser = p_list[i];

        if( bycat )
        {
            if( !strcmp( module_get_object( p_parser ), "core" ) ) continue;

            unsigned confsize;
            module_config_t *p_config = module_config_get (p_parser, &confsize);

            for (size_t i = 0; i < confsize; i++)
            {
                module_config_t *p_cfg = p_config + i;
                /* Hack: required subcategory is stored in i_min */
                if( p_cfg->i_type == CONFIG_SUBCATEGORY &&
                        p_cfg->value.i == p_item->min.i )
                {
                    checkbox_lists( p_parser );
                }

                /* 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" );
#ifndef _WIN32
                    checkbox_lists( "Console", "Lua CLI", "cli" );
#endif
                }
            }
            module_config_free (p_config);
        }
        else if( module_provides( p_parser, p_item->psz_type ) )
        {
            checkbox_lists(p_parser);
        }
    }
    module_list_free( p_list );
}

QString ModuleListConfigControl::getValue() const
{
    assert( text );
    return text->text();
}

void ModuleListConfigControl::changeVisibility( bool visible )
{
    foreach ( checkBoxListItem *it, modules )
        it->checkBox->setVisible( visible );
    groupBox->setVisible( visible );
}

void ModuleListConfigControl::onUpdate()
{
    text->clear();
    bool first = true;

    foreach ( checkBoxListItem *it, modules )
    {
        if( it->checkBox->isChecked() )
        {
            if( first )
            {
                text->setText( text->text() + it->psz_module );
                first = false;
            }
            else
            {
                text->setText( text->text() + ":" + it->psz_module );
            }
        }
    }
}

/**************************************************************************
 * Integer-based controls
 *************************************************************************/


void
VIntConfigControl::doApply()
{
    config_PutInt( getName(), getValue() );
}

void VIntConfigControl::storeValue()
{
    /* Note, this modifies our local copy of the item only */
    p_item->value.i = getValue();
}

/*********** Integer **************/
IntegerConfigControl::IntegerConfigControl( module_config_t *_p_item,
                                            QWidget *p ) :
    VIntConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    spin = new QSpinBox( p );
    spin->setMinimumWidth( MINWIDTH_BOX );
    spin->setAlignment( Qt::AlignRight );
    spin->setMaximumWidth( MINWIDTH_BOX );
    finish();
}

IntegerConfigControl::IntegerConfigControl( module_config_t *_p_item,
                                            QLabel *_label, QSpinBox *_spin ) :
    VIntConfigControl( _p_item )
{
    spin = _spin;
    label = _label;
    finish();
}

void IntegerConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
}

void IntegerConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, spin );
}

void IntegerConfigControl::finish()
{
    spin->setMaximum( 2000000000 );
    spin->setMinimum( -2000000000 );
    spin->setValue( p_item->value.i );

    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        spin->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( spin );
}

void IntegerConfigControl::changeVisibility( bool visible )
{
    spin->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

int IntegerConfigControl::getValue() const
{
    return spin->value();
}

/********* Integer range **********/
IntegerRangeConfigControl::IntegerRangeConfigControl( module_config_t *_p_item,
                                                      QWidget *p ) :
    IntegerConfigControl( _p_item, p )
{
    finish();
}

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

void IntegerRangeConfigControl::finish()
{
    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 );
}

IntegerRangeSliderConfigControl::IntegerRangeSliderConfigControl(
                                            module_config_t *_p_item,
                                            QLabel *_label, QSlider *_slider ) :
    VIntConfigControl( _p_item )
{
    slider = _slider;
    label = _label;
    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 );
    slider->setValue( p_item->value.i );
    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        slider->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( slider );
}

void IntegerRangeSliderConfigControl::changeVisibility( bool visible )
{
    slider->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

int IntegerRangeSliderConfigControl::getValue() const
{
    return slider->value();
}

/********* Integer / choice list **********/
IntegerListConfigControl::IntegerListConfigControl( module_config_t *_p_item,
                                                    QWidget *p ) :
    VIntConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    combo = new QComboBox( p );
    combo->setMinimumWidth( MINWIDTH_BOX );

    /* needed to see update from getting choice list where callback used */
    module_config_t *p_module_config = config_FindConfig( p_item->psz_name );

    finish( p_module_config );
}

IntegerListConfigControl::IntegerListConfigControl( module_config_t *_p_item,
                                                    QLabel *_label,
                                                    QComboBox *_combo ) :
    VIntConfigControl( _p_item )
{
    combo = _combo;
    label = _label;

    /* needed to see update from getting choice list where callback used */
    module_config_t *p_module_config = config_FindConfig( getName() );

    finish( p_module_config );
}

void IntegerListConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( combo, line, LAST_COLUMN, Qt::AlignRight );
}

void IntegerListConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, combo );
}

void IntegerListConfigControl::finish( module_config_t *p_module_config )
{
    combo->setEditable( false );

    if(!p_module_config) return;

    int64_t *values;
    char **texts;
    ssize_t count = config_GetIntChoices( p_module_config->psz_name,
                                          &values, &texts );
    for( ssize_t i = 0; i < count; i++ )
    {
        combo->addItem( qfut(texts[i]), qlonglong(values[i]) );
        if( p_module_config->value.i == values[i] )
            combo->setCurrentIndex( combo->count() - 1 );
        free( texts[i] );
    }
    free( texts );
    free( values );
    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext );
        combo->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( combo );
}

void IntegerListConfigControl::changeVisibility( bool visible )
{
    combo->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

int IntegerListConfigControl::getValue() const
{
    return combo->itemData( combo->currentIndex() ).toInt();
}

/*********** Boolean **************/
BoolConfigControl::BoolConfigControl( module_config_t *_p_item, QWidget *p ) :
    VIntConfigControl( _p_item )
{
    checkbox = new QCheckBox( qfut(p_item->psz_text), p );
    finish();
}

BoolConfigControl::BoolConfigControl( module_config_t *_p_item,
                                      QLabel *_label,
                                      QAbstractButton *_checkbox ) :
    VIntConfigControl( _p_item )
{
    checkbox = _checkbox;
    VLC_UNUSED( _label );
    finish();
}

void BoolConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( checkbox, line, 0, 1, -1 );
}

void BoolConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, checkbox );
}

void BoolConfigControl::finish()
{
    checkbox->setChecked( p_item->value.i );
    if( p_item->psz_longtext )
        checkbox->setToolTip( formatTooltip(qfut(p_item->psz_longtext)) );
}

void BoolConfigControl::changeVisibility( bool visible )
{
    checkbox->setVisible( visible );
}

int BoolConfigControl::getValue() const
{
    return checkbox->isChecked();
}

/************* Color *************/
ColorConfigControl::ColorConfigControl( module_config_t *_p_item,
                                        QWidget *p ) :
    VIntConfigControl( _p_item )
{
    label = new QLabel( p );
    color_but = new QToolButton( p );
    finish();
}

ColorConfigControl::ColorConfigControl( module_config_t *_p_item,
                                        QLabel *_label,
                                        QAbstractButton *_color ) :
    VIntConfigControl( _p_item )
{
    label = _label;
    color_but = _color;
    finish();
}

void ColorConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( color_but, line, LAST_COLUMN, Qt::AlignRight );
}

void ColorConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, color_but );
}

void ColorConfigControl::finish()
{
    i_color = p_item->value.i;

    color_px = new QPixmap( 34, 20 );
    color_px->fill( QColor( i_color ) );
    color_but->setIcon( QIcon( *color_px ) );
    color_but->setMinimumWidth( 40 );

    label->setText( qfut(p_item->psz_text) );
    if( p_item->psz_longtext )
    {
        label->setToolTip( formatTooltip(qfut(p_item->psz_longtext)) );
        color_but->setToolTip( formatTooltip(qfut(p_item->psz_longtext)) );
    }

    BUTTONACT( color_but, &ColorConfigControl::selectColor );
}

void ColorConfigControl::changeVisibility( bool visible )
{
    color_but->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

int ColorConfigControl::getValue() const
{
    return i_color;
}

void ColorConfigControl::selectColor()
{
    QColor color = QColorDialog::getColor( QColor( i_color ) );
    if( color.isValid() )
    {
        i_color = (color.red() << 16) + (color.green() << 8) + color.blue();

        color_px->fill( QColor( i_color ) );
        color_but->setIcon( QIcon( *color_px ) );
    }
}


/**************************************************************************
 * Float-based controls
 *************************************************************************/


void
VFloatConfigControl::doApply()
{
    config_PutFloat( getName(), getValue() );
}

void VFloatConfigControl::storeValue()
{
    /* Note, this modifies our local copy of the item only */
    p_item->value.f = getValue();
}

/*********** Float **************/
FloatConfigControl::FloatConfigControl( module_config_t *_p_item,
                                        QWidget *p ) :
    VFloatConfigControl( _p_item )
{
    label = new QLabel( qfut(p_item->psz_text), p );
    spin = new QDoubleSpinBox( p );
    spin->setMinimumWidth( MINWIDTH_BOX );
    spin->setMaximumWidth( MINWIDTH_BOX );
    spin->setAlignment( Qt::AlignRight );
    finish();
}

FloatConfigControl::FloatConfigControl( module_config_t *_p_item,
                                        QLabel *_label,
                                        QDoubleSpinBox *_spin ) :
    VFloatConfigControl( _p_item )
{
    spin = _spin;
    label = _label;
    finish();
}

void FloatConfigControl::insertInto( QGridLayout *l, int line )
{
    l->addWidget( label, line, 0 );
    l->addWidget( spin, line, LAST_COLUMN, Qt::AlignRight );
}

void FloatConfigControl::insertInto( QBoxLayout *l, int index )
{
    l->insertWidget( index, label );
    l->insertWidget( index + 1, spin );
}

void FloatConfigControl::finish()
{
    spin->setMaximum( 2000000000. );
    spin->setMinimum( -2000000000. );
    spin->setSingleStep( 0.1 );
    spin->setValue( (double)p_item->value.f );
    if( p_item->psz_longtext )
    {
        QString tipText = qfut(p_item->psz_longtext);
        spin->setToolTip( formatTooltip(tipText) );
        if( label )
            label->setToolTip( formatTooltip(tipText) );
    }
    if( label )
        label->setBuddy( spin );
}

void FloatConfigControl::changeVisibility( bool visible )
{
    spin->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

float FloatConfigControl::getValue() const
{
    return (float)spin->value();
}

/*********** Float with range **************/
FloatRangeConfigControl::FloatRangeConfigControl( module_config_t *_p_item,
                                                  QWidget *p ) :
    FloatConfigControl( _p_item, p )
{
    finish();
}

FloatRangeConfigControl::FloatRangeConfigControl( module_config_t *_p_item,
                                                  QLabel *_label,
                                                  QDoubleSpinBox *_spin ) :
    FloatConfigControl( _p_item, _label, _spin )
{
    finish();
}

void FloatRangeConfigControl::finish()
{
    spin->setMaximum( (double)p_item->max.f );
    spin->setMinimum( (double)p_item->min.f );
}


/**********************************************************************
 * Key selector widget
 **********************************************************************/

KeySelectorControl::KeySelectorControl( QWidget *p ) : ConfigControl( nullptr )
{
    label = new QLabel( qtr( "Action hotkey mappings." ), p );

    label->setWordWrap( true );
    searchLabel = new QLabel( qtr( "Search" ), p );
    actionSearch = new SearchLineEdit();

    searchOptionLabel = new QLabel( qtr("in") );
    searchOption = new QComboBox();
    searchOption->addItem( qtr("Any field"), ANY_COL );
    searchOption->addItem( qtr("Actions"), ACTION_COL );
    searchOption->addItem( qtr("Hotkeys"), HOTKEY_COL );
    searchOption->addItem( qtr("Global Hotkeys"), GLOBAL_HOTKEY_COL );

    table = new QTreeWidget( p );
    table->setColumnCount( ANY_COL );
    table->headerItem()->setText( ACTION_COL, qtr( "Action" ) );
    table->headerItem()->setText( HOTKEY_COL, qtr( "Hotkey" ) );
    table->headerItem()->setToolTip( HOTKEY_COL, qtr( "Application level hotkey" ) );
    table->headerItem()->setText( GLOBAL_HOTKEY_COL, qtr( "Global" ) );
    table->headerItem()->setToolTip( GLOBAL_HOTKEY_COL, qtr( "Desktop level hotkey" ) );
    table->setAlternatingRowColors( true );
    table->setSelectionBehavior( QAbstractItemView::SelectItems );
    table->setStyleSheet( "QTreeView::item { padding: 5px 0; }" );

    table->installEventFilter( this );

    /* Find the top most widget */
    QWidget *parent, *rootWidget = p;
    while( (parent = rootWidget->parentWidget()) != NULL )
        rootWidget = parent;
    buildAppHotkeysList( rootWidget );

    finish();

    connect( actionSearch, &SearchLineEdit::textChanged, this, &KeySelectorControl::filter );
    connect( searchOption, QOverload<int>::of(&QComboBox::activated),
             this, &KeySelectorControl::filter );
}

void KeySelectorControl::insertInto( QGridLayout *l, int line )
{
    QGridLayout *gLayout = new QGridLayout();
    gLayout->addWidget( label, 0, 0, 1, 4 );
    gLayout->addWidget( searchLabel, 1, 0, 1, 1 );
    gLayout->addWidget( actionSearch, 1, 1, 1, 1 );
    gLayout->addWidget( searchOptionLabel, 1, 2, 1, 1 );
    gLayout->addWidget( searchOption, 1, 3, 1, 1 );
    gLayout->addWidget( table, 2, 0, 1, 4 );
    l->addLayout( gLayout, line, 0, 1, -1 );
}

void KeySelectorControl::buildAppHotkeysList( QWidget *rootWidget )
{
    QList<QAction *> actionsList = rootWidget->findChildren<QAction *>();
    foreach( const QAction *action, actionsList )
    {
        const QList<QKeySequence> shortcuts = action->shortcuts();
        foreach( const QKeySequence &keySequence, shortcuts )
            existingkeys << keySequence.toString();
    }
}

void KeySelectorControl::finish()
{
    /* Get the main Module */
    module_t *p_main = module_get_main();
    assert( p_main );

    /* Access to the module_config_t */
    unsigned confsize;
    module_config_t *p_config;

    p_config = module_config_get (p_main, &confsize);

    QList<module_config_t *> global_keys;
    global_keys.reserve( 112 );
    for (size_t i = 0; i < confsize; i++)
    {
        module_config_t *p_config_item = p_config + i;

        if( p_config_item->i_type != CONFIG_ITEM_KEY )
            continue;

        /* Capture global key items to fill in afterwards */
        if( strncmp( p_config_item->psz_name, "global-", 7 ) == 0 )
        {
            global_keys.append( p_config_item );
            continue;
        }

        KeyTableItem *treeItem = new KeyTableItem();
        treeItem->normal.config_name = p_config_item->psz_name;
        treeItem->normal.default_keys = qfu( p_config_item->orig.psz );
        treeItem->global.config_name = nullptr;
        treeItem->global.default_keys = qfu( "" );

        treeItem->setText( ACTION_COL, qfut( p_config_item->psz_text ) );
        if (p_config_item->psz_longtext)
            treeItem->setToolTip( ACTION_COL, qfut(p_config_item->psz_longtext) );

        treeItem->set_keys( p_config_item->value.psz, HOTKEY_COL );
        treeItem->setToolTip( HOTKEY_COL, qtr("Double click to change.\nDelete key to remove.") );
        treeItem->setToolTip( GLOBAL_HOTKEY_COL, qtr("Double click to change.\nDelete key to remove.") );

        table->addTopLevelItem( treeItem );
    }

    for (int i = 0; i < global_keys.count(); i++)
    {
        for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
        {
            KeyTableItem *item = static_cast<KeyTableItem *>( *iter );

            if( strcmp( item->normal.config_name, global_keys[i]->psz_name + 7 ) == 0 )
            {
                item->global.config_name = global_keys[i]->psz_name;
                item->global.default_keys = qfu( global_keys[i]->orig.psz );
                item->set_keys( global_keys[i]->value.psz, GLOBAL_HOTKEY_COL );
                break;
            }
        }
    }

    module_config_free (p_config);

    table->resizeColumnToContents( ACTION_COL );
    table->resizeColumnToContents( HOTKEY_COL );

    table->setUniformRowHeights( true );

    connect( table, &QTreeWidget::itemActivated,
             this, QOverload<QTreeWidgetItem *, int>::of(&KeySelectorControl::selectKey) );
}

void KeySelectorControl::changeVisibility( bool visible )
{
    table->setVisible( visible );
    if ( label ) label->setVisible( visible );
}

void KeySelectorControl::filter()
{
    const QString &qs_search = actionSearch->text();
    int i_column = searchOption->itemData( searchOption->currentIndex() ).toInt();
    int i_column_count = 1;
    if( i_column == ANY_COL )
    {
        i_column = 0; // ACTION_COL
        i_column_count = ANY_COL;
    }
    for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
    {
        QTreeWidgetItem *item = *iter;
        bool found = false;
        for( int idx = i_column; idx < (i_column + i_column_count); idx++ )
        {
            if( item->text( idx ).contains( qs_search, Qt::CaseInsensitive ) )
            {
                found = true;
                break;
            }
        }
        item->setHidden( !found );
    }
}

void KeySelectorControl::selectKey( QTreeWidgetItem *item, int column )
{
    selectKey( static_cast<KeyTableItem *>( item ), (enum ColumnIndex) column );
}

void KeySelectorControl::selectKey( KeyTableItem *item, enum ColumnIndex column )
{
    /* This happens when triggered by ClickEater */
    if( item == NULL )
        item = static_cast<KeyTableItem *>( table->currentItem() );

    /* This can happen when nothing is selected on the treeView
       and the shortcutValue is clicked */

    if( !item ) return;

    /* If clicked on the first column, assuming user wants the normal hotkey */
    if( column == ACTION_COL ) column = HOTKEY_COL;

    /* Launch a small dialog to ask for a new key */
    KeyInputDialog *d = new KeyInputDialog( table, item, column );
    d->setExistingkeysSet( &existingkeys );
    d->exec();

    if( d->result() == QDialog::Accepted )
    {
        /* In case of conflict, reset other keys*/
        if( d->conflicts )
            reassign_key( item, d->vlckey, column );
        else
            item->set_keys( d->vlckey, column );
    }
    else if( d->result() == 2 )
        unset( item, column );

    delete d;
}

void KeySelectorControl::doApply()
{
    for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
    {
        KeyTableItem *item = static_cast<KeyTableItem *>( *iter );

        config_PutPsz( item->normal.config_name, qtu( item->normal.keys ) );
        config_PutPsz( item->global.config_name, qtu( item->global.keys ) );
    }
}

bool KeySelectorControl::eventFilter( QObject *obj, QEvent *e )
{
#ifndef QT_NO_CONTEXTMENU
    if( obj == table && e->type() == QEvent::ContextMenu )
    {
        tableContextMenuEvent( table, static_cast<QContextMenuEvent*>(e) );
        return true;
    }
#endif

    if( obj != table || e->type() != QEvent::KeyPress )
        return ConfigControl::eventFilter(obj, e);

    switch( static_cast<QKeyEvent*>(e)->key() )
    {
        case Qt::Key_Escape:
            table->clearFocus();
            return true;

        case Qt::Key_Return:
        case Qt::Key_Enter:
            selectKey( table->currentItem(), table->currentColumn() );
            return true;

        case Qt::Key_Delete:
            if( table->currentColumn() != ACTION_COL )
                unset( table->currentItem(), table->currentColumn() );
            return true;

        default:
            return false;
    }
}

#ifndef QT_NO_CONTEXTMENU
void KeySelectorControl::tableContextMenuEvent( QWidget *widget, QContextMenuEvent *event )
{
    KeyTableItem *item = static_cast<KeyTableItem *>( this->table->currentItem() );
    if( !item || item->isHidden() )
        return;
    /* Avoid menu from right-click on empty space after last item */
    if( event->reason() == QContextMenuEvent::Mouse &&
        !this->table->itemAt( this->table->viewport()->mapFromGlobal( event->globalPos() ) ) )
        return;

    enum ColumnIndex column = (enum ColumnIndex) this->table->currentColumn();

    bool empty;
    bool matches_default;
    switch ( column )
    {
        case ACTION_COL:
            empty = (item->normal.keys.isEmpty() && item->global.keys.isEmpty());
            matches_default = (item->normal.matches_default && item->global.matches_default);
            break;
        case HOTKEY_COL:
            empty = item->normal.keys.isEmpty();
            matches_default = item->normal.matches_default;
            break;
        case GLOBAL_HOTKEY_COL:
            empty = item->global.keys.isEmpty();
            matches_default = item->global.matches_default;
            break;
        default:
            unreachable();
    }

    assert(widget);
    QMenu *menu = new QMenu(widget);
    menu->setAttribute(Qt::WA_DeleteOnClose);

    QAction *modify = new QAction( qtr( "&Modify" ), this->table );
    connect( modify, &QAction::triggered, [=]() { this->selectKey( item, column ); } );
    menu->addAction( modify );

    if( column != ACTION_COL )
    {
        QAction *copy = new QAction( qtr( "&Copy value" ), this->table );
        if( empty )
            copy->setEnabled( false );
        else
            connect( copy, &QAction::triggered, [=]() {
                this->copy_value( item, column );
            } );
        menu->addAction( copy );
    }

    QAction *unset = new QAction( qtr( "&Unset" ), this->table );
    if( empty )
        unset->setEnabled( false );
    else
        connect( unset, &QAction::triggered, [=]() { this->unset( item, column ); } );
    menu->addAction( unset );

    QAction *reset = new QAction( qtr( "&Reset" ), this->table );
    if( matches_default )
        reset->setEnabled( false );
    else
        connect( reset, &QAction::triggered, [=]() {
            if( column != ACTION_COL )
                this->reset( item, column );
            else
            {
                this->reset( item, HOTKEY_COL );
                this->reset( item, GLOBAL_HOTKEY_COL );
            }
        } );
    menu->addAction( reset );

    QString reset_all_label = (column == ACTION_COL) ? qtr( "Reset &all" )
                                                     : qtr( "Reset &all (column)" );
    QAction *reset_all = new QAction( reset_all_label, this->table );
    connect( reset_all, &QAction::triggered, [=]() { this->reset_all( column ); } );
    menu->addAction( reset_all );

    menu->popup( event->globalPos() );
}
#endif // QT_NO_CONTEXTMENU

void KeySelectorControl::unset( QTreeWidgetItem *item, int column )
{
    unset( static_cast<KeyTableItem*>( item ), (enum ColumnIndex) column );
}

void KeySelectorControl::unset( KeyTableItem *item,
                                enum KeySelectorControl::ColumnIndex column )
{
    if( item == nullptr )
        return;
    if( column == ACTION_COL )
        column = HOTKEY_COL;
    item->set_keys( nullptr, column );
}

void KeySelectorControl::reset( KeyTableItem *item,
                                enum KeySelectorControl::ColumnIndex column )
{
    QString item_default = item->get_default_keys( column );
    KeyTableItem *conflict = find_conflict( table, item_default, item, column );
    if( conflict != nullptr )
    {
        KeyConflictDialog *dialog = new KeyConflictDialog( this->table, conflict, column );
        dialog->exec();
        if( dialog->result() == QDialog::Accepted )
            reassign_key( item, item_default, column );
        delete dialog;
    }
    else
        item->set_keys( item_default, column );
}

void KeySelectorControl::reset_all( enum KeySelectorControl::ColumnIndex column )
{
    for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
    {
        KeyTableItem *item = static_cast<KeyTableItem *>( *iter );
        if( column != GLOBAL_HOTKEY_COL )
            item->set_keys( item->get_default_keys( HOTKEY_COL ), HOTKEY_COL );
        if( column != HOTKEY_COL )
            item->set_keys( item->get_default_keys( GLOBAL_HOTKEY_COL ), GLOBAL_HOTKEY_COL );
    }
}

void KeySelectorControl::reassign_key( KeyTableItem *item, const QString &key,
                                       enum KeySelectorControl::ColumnIndex column )
{
    for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
    {
        KeyTableItem *iter_item = static_cast<KeyTableItem *>( *iter );
        if( iter_item != item )
            iter_item->remove_key( key, column );
    }
    item->set_keys( key, column );
}

void KeySelectorControl::copy_value( KeyTableItem *item,
                                     enum KeySelectorControl::ColumnIndex column )
{
    QClipboard *clipboard = QGuiApplication::clipboard();
    clipboard->setText( item->get_keys( column ) );
}

KeyTableItem * KeySelectorControl::find_conflict( QTreeWidget *table, QString key,
                                                  KeyTableItem *ignore_item,
                                                  enum KeySelectorControl::ColumnIndex column )
{
    if( key.isEmpty() )
        return nullptr;
    for (QTreeWidgetItemIterator iter(table); *iter; ++iter)
    {
        KeyTableItem *item = static_cast<KeyTableItem *>( *iter );

        if( item == ignore_item )
            continue;

        if( item->contains_key( key, column ) )
            return item;
    }
    return nullptr;
}

const QString &KeyTableItem::get_keys( enum KeySelectorControl::ColumnIndex column )
{
    if( column == KeySelectorControl::GLOBAL_HOTKEY_COL )
        return global.keys;
    return normal.keys;
}

QString KeyTableItem::get_default_keys( enum KeySelectorControl::ColumnIndex column )
{
    if( column == KeySelectorControl::GLOBAL_HOTKEY_COL )
        return global.default_keys;
    return normal.default_keys;
}

void KeyTableItem::set_keys( QString keys, enum KeySelectorControl::ColumnIndex column )
{
    bool matches_default;
    if( column == KeySelectorControl::GLOBAL_HOTKEY_COL )
    {
        global.keys = keys;
        matches_default = global.matches_default = ( keys == global.default_keys );
    }
    else
    {
        normal.keys = keys;
        matches_default = normal.matches_default = ( keys ==  normal.default_keys );
    }
    setText( column, keys.replace( "\t", ", " ) );
    QFont font = this->font( KeySelectorControl::ACTION_COL );
    font.setWeight( matches_default ? QFont::Weight::Normal : QFont::Weight::Bold );
    setFont( column,  font );
    matches_default = (normal.matches_default && global.matches_default);
    font.setWeight( matches_default ? QFont::Weight::Normal : QFont::Weight::Bold );
    setFont( KeySelectorControl::ACTION_COL,  font );
}

bool KeyTableItem::contains_key( const QString &key, enum KeySelectorControl::ColumnIndex column )
{
    return get_keys( column ).split( "\t" ).contains( key );
}

void KeyTableItem::remove_key( const QString &key, enum KeySelectorControl::ColumnIndex column )
{
    QStringList keys_list = get_keys( column ).split( "\t" );
    if( keys_list.removeAll( key ) )
        set_keys( keys_list.join( "\t" ), column );
}

/**
 * Class KeyInputDialog
 **/

KeyInputDialog::KeyInputDialog( QTreeWidget *table_,
                                KeyTableItem * keyItem_,
                                enum KeySelectorControl::ColumnIndex column_ ) :
                                QDialog( table_ ), table( table_ ),
                                keyItem( keyItem_ ), column( column_ )
{
    setModal( true );
    conflicts = false;
    existingkeys = NULL;

    wheelConverter = new WheelToVLCConverter(this);
    connect(wheelConverter, &WheelToVLCConverter::vlcWheelKey, this, [this](int i_vlck){
        vlckey = VLCKeyToString( i_vlck, false );
        vlckey_tr = VLCKeyToString( i_vlck, true );
        selected->setText( qtr( "Key: <b>%1</b>" ).arg( vlckey_tr ) );
        checkForConflicts( QString() );
    });

    bool global = ( column == KeySelectorControl::GLOBAL_HOTKEY_COL );

    setWindowTitle( global ? qtr( "Global Hotkey change" )
                           : qtr( "Hotkey change" ) );
    setWindowRole( "vlc-key-input" );

    QVBoxLayout *vLayout = new QVBoxLayout( this );
    selected = new QLabel( qtr( "Press the new key or combination for <b>%1</b>" )
                           .arg( keyItem->text( KeySelectorControl::ACTION_COL ) ) );
    vLayout->addWidget( selected , Qt::AlignCenter );

    warning = new QLabel;
    warning->hide();
    vLayout->insertWidget( 1, warning );

    QDialogButtonBox *buttonBox = new QDialogButtonBox;
    ok = new QPushButton( qtr("Assign") );
    QPushButton *cancel = new QPushButton( qtr("Cancel") );
    unset = new QPushButton( qtr("Unset") );
    buttonBox->addButton( ok, QDialogButtonBox::AcceptRole );
    buttonBox->addButton( unset, QDialogButtonBox::ActionRole );
    buttonBox->addButton( cancel, QDialogButtonBox::RejectRole );
    ok->setDefault( true );

    ok->setFocusPolicy(Qt::NoFocus);
    unset->setFocusPolicy(Qt::NoFocus);
    cancel->setFocusPolicy(Qt::NoFocus);

    vLayout->addWidget( buttonBox );
    ok->hide();

    connect( buttonBox, &QDialogButtonBox::accepted, this, &KeyInputDialog::accept );
    connect( buttonBox, &QDialogButtonBox::rejected, this, &KeyInputDialog::reject );
    BUTTONACT( unset, &KeyInputDialog::unsetAction );
}

void KeyInputDialog::setExistingkeysSet( const QSet<QString> *keyset )
{
    existingkeys = keyset;
}

void KeyInputDialog::checkForConflicts( const QString &sequence )
{
    conflicts = false;
    if ( vlckey == "" )
    {
        accept();
        return;
    }

    KeyTableItem *conflict = KeySelectorControl::find_conflict( table, vlckey, keyItem, column );
    if( conflict != nullptr )
    {
        warning->setText(
                qtr("Warning: this key or combination is already assigned to \"<b>%1</b>\"")
                .arg( conflict->text( KeySelectorControl::ACTION_COL ) ) );
        warning->show();
        ok->show();
        unset->hide();

        conflicts = true;
        return;
    }

    if( existingkeys && !sequence.isEmpty()
        && existingkeys->contains( sequence ) )
    {
        warning->setText(
            qtr( "Warning: <b>%1</b> is already an application menu shortcut" )
                    .arg( sequence )
        );
        warning->show();
        ok->show();
        unset->hide();

        conflicts = true;
    }
    else accept();
}

void KeyInputDialog::keyPressEvent( QKeyEvent *e )
{
    if( e->key() == Qt::Key_Tab ||
        e->key() == Qt::Key_Shift ||
        e->key() == Qt::Key_Control ||
        e->key() == Qt::Key_Meta ||
        e->key() == Qt::Key_Alt ||
        e->key() == Qt::Key_AltGr )
        return;
    int i_vlck = qtEventToVLCKey( e );
    QKeySequence sequence( e->key() | e->modifiers() );
    vlckey = VLCKeyToString( i_vlck, false );
    vlckey_tr = VLCKeyToString( i_vlck, true );
    selected->setText( qtr( "Key or combination: <b>%1</b>" ).arg( vlckey_tr ) );
    checkForConflicts( sequence.toString() );
}

void KeyInputDialog::wheelEvent( QWheelEvent *e )
{
    wheelConverter->wheelEvent(e);
}

void KeyInputDialog::unsetAction() { done( 2 ); }

KeyConflictDialog::KeyConflictDialog( QTreeWidget *table, KeyTableItem * item,
                                      enum KeySelectorControl::ColumnIndex column ) :
                                      QDialog( table )
{
    setModal( true );

    bool global = ( column == KeySelectorControl::GLOBAL_HOTKEY_COL );

    setWindowTitle( global ? qtr( "Global Hotkey assignment conflict" )
                           : qtr( "Hotkey assignment conflict" ) );
    setWindowRole( "vlc-key-conflict" );

    QVBoxLayout *vLayout = new QVBoxLayout( this );
    QLabel *warning = new QLabel;
    warning->setText(
            qtr("Warning: this key or combination is already assigned to \"<b>%1</b>\"")
            .arg( item->text( KeySelectorControl::ACTION_COL ) ) );
    vLayout->addWidget( warning , Qt::AlignCenter );

    QDialogButtonBox *buttonBox = new QDialogButtonBox;
    QPushButton *force = new QPushButton( qtr("Assign") );
    QPushButton *cancel = new QPushButton( qtr("Cancel") );
    buttonBox->addButton( force, QDialogButtonBox::AcceptRole );
    buttonBox->addButton( cancel, QDialogButtonBox::RejectRole );
    force->setDefault( true );

    vLayout->addWidget( buttonBox );

    connect( buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
    connect( buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
}

Messung
CHZG
839810093

¤ Dauer der Verarbeitung: 0.30 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.