
#include "optionsdetailed.h"
#include "convertpluginloader.h"
#include "configuration.h"

#include <tqlayout.h>
#include <tqlabel.h>
#include <tqcheckbox.h>
#include <tqtooltip.h>
#include <tqwhatsthis.h>

#include <knuminput.h>
#include <tdelocale.h>
#include <kcombobox.h>
#include <kiconloader.h>
#include <tdetoolbarbutton.h>
#include <klineedit.h>
#include <kinputdialog.h>
//#include <kdebug.h>
#include <tdemessagebox.h>

#include <math.h>


// TODO hide save button, if shown in the edit options window?

// FIXME refill the formats box, when the configuration changed

OptionsDetailed::OptionsDetailed( Config* _config, TQWidget *parent, const char *name )
    : TQWidget( parent, name )
{
    config = _config;

    TQGridLayout *gridLayout = new TQGridLayout( this );

    // normal options
    normalOptions = new TQWidget( this, "normalOptions" );
    gridLayout->addWidget( normalOptions, 0, 0 );

    TQGridLayout *normalGrid = new TQGridLayout( normalOptions, 2, 1, 6, 3 );

    TQHBoxLayout *normalTopBox = new TQHBoxLayout();
    normalGrid->addLayout( normalTopBox, 0, 0 );

    TQLabel* lConvert = new TQLabel( i18n("Convert")+":", normalOptions, "lConvert" );
    normalTopBox->addWidget( lConvert, 0, TQt::AlignVCenter );
    cFormat = new KComboBox( normalOptions, "cFormat" );
    normalTopBox->addWidget( cFormat, 0, TQt::AlignVCenter );
    connect( cFormat, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(formatChanged())
             );
    connect( cFormat, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(somethingChanged())
             );
    cQualityMode = new KComboBox( normalOptions, "cQualityMode" );
    cQualityMode->setFixedSize( cQualityMode->sizeHint() );
    normalTopBox->addWidget( cQualityMode, 0, TQt::AlignVCenter );
    connect( cQualityMode, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(qualityModeChanged())
             );
    connect( cQualityMode, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(somethingChanged())
             );
    iQuality = new KIntSpinBox( normalOptions, "iQuality" );
    normalTopBox->addWidget( iQuality, 0, TQt::AlignVCenter );
    connect( iQuality, TQ_SIGNAL(valueChanged(int)),
               this, TQ_SLOT(qualityChanged())
             );
    connect( iQuality, TQ_SIGNAL(valueChanged(int)),
               this, TQ_SLOT(somethingChanged())
             );
    cBitrateMode = new KComboBox( normalOptions, "cBitrateMode" );
    TQToolTip::add( cBitrateMode, i18n("vbr - variable bitrate\nabr - average bitrate\ncbr - constant bitrate") );
    normalTopBox->addWidget( cBitrateMode, 0, TQt::AlignVCenter );
    connect( cBitrateMode, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(bitrateModeChanged())
             );
    connect( cBitrateMode, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(somethingChanged())
             );
    normalTopBox->addSpacing( 18 );

    cBitrateRangeSwitch = new TQCheckBox( i18n("Bitrate range")+":", normalOptions, "cBitrateRangeSwitch" );
    TQToolTip::add( cBitrateRangeSwitch, i18n("Use it only if, you know what you are doing, you could reduce the quality.") );
    normalTopBox->addWidget( cBitrateRangeSwitch, 0, TQt::AlignVCenter );
    connect( cBitrateRangeSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(bitrateRangeToggled())
             );
    connect( cBitrateRangeSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(somethingChanged())
             );
    iMinBitrate = new KIntSpinBox( normalOptions, "iMinBitrate" );
    iMinBitrate->setMinValue( 32 );
    iMinBitrate->setMaxValue( 320 );
    iMinBitrate->setLineStep( 8 );
    iMinBitrate->setValue( 64 );
    normalTopBox->addWidget( iMinBitrate, 0, TQt::AlignVCenter );
    connect( iMinBitrate, TQ_SIGNAL(valueChanged(int)),
               this, TQ_SLOT(somethingChanged())
             );
    lBitrateRangeTo = new TQLabel( "-", normalOptions, "lBitrateRangeTo" );
    normalTopBox->addWidget( lBitrateRangeTo, 0, TQt::AlignVCenter );
    iMaxBitrate = new KIntSpinBox( normalOptions, "iMaxBitrate" );
    iMaxBitrate->setMinValue( 32 );
    iMaxBitrate->setMaxValue( 320 );
    iMaxBitrate->setLineStep( 8 );
    iMaxBitrate->setValue( 192 );
    normalTopBox->addWidget( iMaxBitrate, 0, TQt::AlignVCenter );
    connect( iMaxBitrate, TQ_SIGNAL(valueChanged(int)),
               this, TQ_SLOT(somethingChanged())
             );
    lBitrateRangeUnit = new TQLabel( "kbps", normalOptions, "lBitrateRangeUnit" );
    normalTopBox->addWidget( lBitrateRangeUnit, 0, TQt::AlignVCenter );
    normalTopBox->addStretch();

    TQHBoxLayout *normalMiddleBox = new TQHBoxLayout();
    normalGrid->addLayout( normalMiddleBox, 1, 0 );

    cSamplingrateSwitch = new TQCheckBox( i18n("Resample")+":", normalOptions, "cSamplingrateSwitch" );
    normalMiddleBox->addWidget( cSamplingrateSwitch, 0, TQt::AlignVCenter );
    connect( cSamplingrateSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(samplingrateToggled())
             );
    connect( cSamplingrateSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(somethingChanged())
             );
    cSamplingrate = new KComboBox( normalOptions, "cSamplingrate" );
    cSamplingrate->setEditable(true);
    cSamplingrate->insertItem("48000");
    cSamplingrate->insertItem("44100");
    cSamplingrate->insertItem("32000");
    cSamplingrate->insertItem("24000");
    cSamplingrate->insertItem("22050");
    cSamplingrate->insertItem("16000");
    cSamplingrate->insertItem("12000");
    cSamplingrate->insertItem("11025");
    cSamplingrate->insertItem("8000");
    cSamplingrate->setCurrentText("44100");
    normalMiddleBox->addWidget( cSamplingrate, 0, TQt::AlignVCenter );
    connect( cSamplingrate, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(somethingChanged())
             );
    lSamplingrateUnit = new TQLabel( "Hz", normalOptions, "lSamplingrateUnit" );
    normalMiddleBox->addWidget( lSamplingrateUnit, 0, TQt::AlignVCenter );
    normalMiddleBox->addSpacing( 18 );

    cChannelsSwitch = new TQCheckBox( i18n("Channels")+":", normalOptions, "cChannelsSwitch" );
    normalMiddleBox->addWidget( cChannelsSwitch, 0, TQt::AlignVCenter );
    connect( cChannelsSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(channelsToggled())
             );
    connect( cChannelsSwitch, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(somethingChanged())
             );
    cChannels = new KComboBox( normalOptions, "cChannels" );
/*    sChannels.append( i18n("Mono") );
    sChannels.append( i18n("Stereo") );
    sChannels.append( i18n("Joint-Stereo") );
    sChannels.append( i18n("Forced Joint-Stereo") );
    sChannels.append( i18n("Dual Channels") );
    cChannels->insertStringList( sChannels );*/
    normalMiddleBox->addWidget( cChannels, 0, TQt::AlignVCenter );
    connect( cChannels, TQ_SIGNAL(activated(int)),
               this, TQ_SLOT(somethingChanged())
             );
    normalMiddleBox->addSpacing( 18 );

    cReplayGain = new TQCheckBox( i18n("Replay Gain"), normalOptions, "cReplayGain" );
    cReplayGain->setChecked(true);
    TQToolTip::add( cReplayGain, i18n("Add a Replay Gain tag to the converted file.") );
    TQWhatsThis::add( cReplayGain, i18n("Replay Gain is a volume correction technique. A volume difference is calculated and stored in a tag. This way audio players can automatically adjust the volume and the original music data is not modified (like at normalization).") );
    normalMiddleBox->addWidget( cReplayGain, 0, TQt::AlignVCenter );
    connect( cReplayGain, TQ_SIGNAL(toggled(bool)),
               this, TQ_SLOT(somethingChanged())
             );
    normalMiddleBox->addStretch();

    TQHBoxLayout *normalBottomBox = new TQHBoxLayout( );
    normalGrid->addLayout( normalBottomBox, 2, 0 );

    outputDirectory = new OutputDirectory( config, normalOptions, "outputDirectory" );
    normalBottomBox->addWidget( outputDirectory, 0, TQt::AlignVCenter );
    connect( outputDirectory, TQ_SIGNAL(modeChanged(OutputDirectory::Mode)),
               this, TQ_SLOT(somethingChanged())
             );
    connect( outputDirectory, TQ_SIGNAL(directoryChanged(const TQString&)),
               this, TQ_SLOT(somethingChanged())
             );
    normalBottomBox->addSpacing( 18 );

    pProfileSave = new TDEToolBarButton( "document-save", 1003, normalOptions, "pProfileSave" );
    TQToolTip::add( pProfileSave, i18n("Save current options as a profile") );
    normalBottomBox->addWidget( pProfileSave, 0, TQt::AlignVCenter );
    connect( pProfileSave, TQ_SIGNAL(clicked()),
               this, TQ_SLOT(saveProfile())
             );

    // advanced options
    advancedOptions = new TQWidget( this, "advancedOptions" );
    advancedOptions->hide();
    gridLayout->addWidget( advancedOptions, 0, 0 );

    TQGridLayout *advancedGrid = new TQGridLayout( advancedOptions, 2, 1, 6, 3 );

    TQHBoxLayout *advancedTopBox = new TQHBoxLayout();
    advancedGrid->addLayout( advancedTopBox, 0, 0 );

    TQLabel* lUserOptionsLabel = new TQLabel( i18n("Command")+":", advancedOptions, "lUserOptionsLabel" );
    advancedTopBox->addWidget( lUserOptionsLabel, 0, TQt::AlignVCenter );
    lUserOptions = new KLineEdit( advancedOptions, "lUserOptions" );
    advancedTopBox->addWidget( lUserOptions, 0, TQt::AlignVCenter );
    connect( lUserOptions, TQ_SIGNAL(textChanged(const TQString&)),
               this, TQ_SLOT(somethingChanged())
             );

    TQHBoxLayout *advancedMiddleBox = new TQHBoxLayout();
    advancedGrid->addLayout( advancedMiddleBox, 1, 0 );

    TQLabel* lInfoParams = new TQLabel( i18n("%p: The parameters generated by soundKonverter"), advancedOptions, "lInfoParams" );
    advancedMiddleBox->addWidget( lInfoParams, 0, TQt::AlignVCenter );

    TQHBoxLayout *advancedBottomBox = new TQHBoxLayout();
    advancedGrid->addLayout( advancedBottomBox, 2, 0 );

    TQLabel* lInfoFiles = new TQLabel( i18n("%i: The input file ; %o: The output file"), advancedOptions, "lInfoFiles" );
    advancedBottomBox->addWidget( lInfoFiles, 0, TQt::AlignVCenter );

    refill();
}

OptionsDetailed::~OptionsDetailed()
{}

ConversionOptions OptionsDetailed::getCurrentOptions()
{
    ConversionOptions options;

    options.encodingOptions.sFormat = cFormat->currentText();
    options.encodingOptions.sQualityMode = cQualityMode->currentText();
    if( iQuality->isEnabled() ) {
        options.encodingOptions.iQuality = iQuality->value();
    }
    else {
        options.encodingOptions.iQuality = 0;
    }
    if( cQualityMode->currentText() == i18n("Bitrate") || cQualityMode->currentText() == i18n("Quality") ) {
        options.encodingOptions.sBitrateMode = cBitrateMode->currentText();
    }
    else {
        options.encodingOptions.sBitrateMode = "";
    }

    if( cBitrateRangeSwitch->isEnabled() && cBitrateRangeSwitch->isChecked() ) {
        options.encodingOptions.bBitrateRange = true;
        options.encodingOptions.iMinBitrate = iMinBitrate->value();
        options.encodingOptions.iMaxBitrate = iMaxBitrate->value();
    }
    else {
        options.encodingOptions.bBitrateRange = false;
        options.encodingOptions.iMinBitrate = 0;
        options.encodingOptions.iMaxBitrate = 0;
    }

    if( cSamplingrateSwitch->isEnabled() && cSamplingrateSwitch->isChecked() ) {
        options.encodingOptions.samplingRate.bEnabled = true;
        options.encodingOptions.samplingRate.iSamplingRate = cSamplingrate->currentText().toInt();
    }
    else {
        options.encodingOptions.samplingRate.bEnabled = false;
        options.encodingOptions.samplingRate.iSamplingRate = 0;
    }

    if( cChannelsSwitch->isEnabled() && cChannelsSwitch->isChecked() ) {
        options.encodingOptions.channels.bEnabled = true;
        options.encodingOptions.channels.sChannels = cChannels->currentText();
    }
    else {
        options.encodingOptions.channels.bEnabled = false;
        options.encodingOptions.channels.sChannels = "";
    }

    if( cReplayGain->isEnabled() && cReplayGain->isChecked() ) {
        options.encodingOptions.replaygain.bEnabled = true;
    }
    else {
        options.encodingOptions.replaygain.bEnabled = false;
    }

    options.outputOptions.mode = outputDirectory->mode();
    options.outputOptions.directory = outputDirectory->directory();

    options.encodingOptions.sInOutFiles = lUserOptions->text();

    return options;
}

void OptionsDetailed::setCurrentOptions( const ConversionOptions& options )
{
    // NOTE the values are not verified because they HAVE to be correct

    cFormat->setCurrentItem( formatIndex(options.encodingOptions.sFormat) );
    formatChanged();
    cQualityMode->setCurrentItem( qualityModeIndex(options.encodingOptions.sQualityMode) );
    qualityModeChanged();
    if( options.encodingOptions.iQuality != 0 ) {
        iQuality->setValue( options.encodingOptions.iQuality );
    }
    if( options.encodingOptions.sBitrateMode != "" ) {
        cBitrateMode->setCurrentItem( bitrateModeIndex(options.encodingOptions.sBitrateMode) );
    }

    if( options.encodingOptions.bBitrateRange == true ) {
        cBitrateRangeSwitch->setChecked( true );
        iMinBitrate->setValue( options.encodingOptions.iMinBitrate );
        iMaxBitrate->setValue( options.encodingOptions.iMaxBitrate );
    }
    else {
        cBitrateRangeSwitch->setChecked( false );
    }

    if( options.encodingOptions.samplingRate.bEnabled == true  ) {
        cSamplingrateSwitch->setChecked( true );
        cSamplingrate->setCurrentText( TQString::number(options.encodingOptions.samplingRate.iSamplingRate) );
    }
    else {
        cSamplingrateSwitch->setChecked( false );
    }

    if( options.encodingOptions.channels.bEnabled == true ) {
        cChannelsSwitch->setChecked( true );
        cChannels->setCurrentItem( channelsIndex(options.encodingOptions.channels.sChannels) );
    }
    else {
        cChannelsSwitch->setChecked( false );
    }

    if( options.encodingOptions.replaygain.bEnabled == true ) {
        cReplayGain->setChecked( true );
    }
    else {
        cReplayGain->setChecked( false );
    }

    outputDirectory->setMode( options.outputOptions.mode );
    outputDirectory->setDirectory( options.outputOptions.directory );

    lUserOptions->setText( options.encodingOptions.sInOutFiles );
}

void OptionsDetailed::saveProfile()
{
    bool ok;
    TQString name = KInputDialog::getText( i18n("New profile"), i18n("Enter a name for the new profile:"), "", &ok );
    if( ok ) {
        TQStringList profiles;
        profiles += i18n("Very low");
        profiles += i18n("Low");
        profiles += i18n("Medium");
        profiles += i18n("High");
        profiles += i18n("Very high");
        profiles += i18n("Lossless");
        profiles += i18n("Hybrid");
        profiles += i18n("Last used");
        profiles += "Last used";
        profiles += i18n("User defined");
        if( profiles.findIndex(name) != -1 ) {
            KMessageBox::error( this,
                i18n("You cannot overwrite the built-in profiles."),
                i18n("Profile already exists") );
            return;
        }
        profiles = config->getAllProfiles();
        if( profiles.findIndex(name) == -1 ) {
            config->addProfile( name, getCurrentOptions() );
        }
        else {
            int ret = KMessageBox::questionYesNo( this,
                          i18n("A profile with this name already exists.\n\nDo you want to overwrite the existing one?"),
                          i18n("Profile already exists") );
            if( ret == KMessageBox::Yes ) {
                config->removeProfile( name );
                config->addProfile( name, getCurrentOptions() );
            }
        }
    }
}

int OptionsDetailed::formatIndex( const TQString &string )
{
    return sFormat.findIndex( string );
}

int OptionsDetailed::qualityModeIndex( const TQString &string )
{
    return sQualityMode.findIndex( string );
}

int OptionsDetailed::bitrateModeIndex( const TQString &string )
{
    return sBitrateMode.findIndex( string );
}

int OptionsDetailed::channelsIndex( const TQString &string )
{
    return sChannels.findIndex( string );
}

void OptionsDetailed::refill()
{
    TQString format = cFormat->currentText();

    sFormat = config->allEncodableFormats();
    sFormat.append( "wav" );
    cFormat->clear();
    cFormat->insertStringList( sFormat );

    cFormat->setCurrentItem( formatIndex(format) );

    formatChanged();
}

void OptionsDetailed::formatChanged()
{
    if( cFormat->currentText() == "wav" ) {
        cReplayGain->setEnabled( false );
        sQualityMode.clear();
        sQualityMode.append( i18n("Lossless") );
        cQualityMode->clear();
        cQualityMode->insertStringList( sQualityMode );
        qualityModeChanged();
        lUserOptions->setEnabled( false );
        return;
    }

    FormatItem* formatItem = config->getFormatItem( cFormat->currentText() );
    if( formatItem == 0 ) {
        // FIXME error handling
        //kdDebug() << "NULL POINTER: `" << "Convert::formatChanged() / formatItem" << "'" << endl;
        return;
    }
    ConvertPlugin* plugin = formatItem->encoder;
    if( plugin == 0 ) {
        // FIXME error handling
        //kdDebug() << "NULL POINTER: `" << "OptionsDetailed::formatChanged() / plugin" << "'" << endl;
        return;
    }

    lUserOptions->setEnabled( true );
    TQString lastString = lUserOptions->text();
    TQString bin = config->binaries[plugin->enc.bin];
    if( lastString.left(bin.length()) != bin ) {
        lUserOptions->setText( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files );
    }

    TQString lastQualityMode = cQualityMode->currentText();
    sQualityMode.clear();

    if( formatItem->replaygain || ( plugin->enc.replaygain.enabled && formatItem->internalReplayGain ) ) {
        cReplayGain->setEnabled( true );
    }
    else {
        cReplayGain->setEnabled( false );
    }

    if( plugin->enc.lossy.enabled ) {
        if( plugin->enc.lossy.quality.enabled ) {
            sQualityMode.append( i18n("Quality") );
        }
        if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) {
            sQualityMode.append( i18n("Bitrate") );
        }
        if( !plugin->enc.lossy.quality.enabled && !plugin->enc.lossy.bitrate.abr.enabled && !plugin->enc.lossy.bitrate.cbr.enabled ) {
            sQualityMode.append( i18n("Unchanged") );
        }
    }
    if( plugin->enc.lossless.enabled ) {
        sQualityMode.append( i18n("Lossless") );
    }
    if( plugin->enc.hybrid.enabled ) {
        sQualityMode.append( i18n("Hybrid") );
    }
    if( !plugin->enc.lossy.enabled && !plugin->enc.lossless.enabled && !plugin->enc.hybrid.enabled ) {
        sQualityMode.append( i18n("Undefined") );
    }

    cQualityMode->clear();
    cQualityMode->insertStringList( sQualityMode );

    cQualityMode->setCurrentItem( qualityModeIndex(lastQualityMode) );
    qualityModeChanged();
}

void OptionsDetailed::qualityModeChanged()
{
    TQWhatsThis::remove( iQuality );

    if( cFormat->currentText() == "wav" ) {
        iQuality->setEnabled( false );
        cBitrateMode->setEnabled( false );
        cBitrateRangeSwitch->setEnabled( false );
        iMinBitrate->setEnabled( false );
        lBitrateRangeTo->setEnabled( false );
        iMaxBitrate->setEnabled( false );
        lBitrateRangeUnit->setEnabled( false );
        cSamplingrateSwitch->setEnabled( false );
        cSamplingrate->setEnabled( false );
        lSamplingrateUnit->setEnabled( false );
        cChannelsSwitch->setEnabled( false );
        cChannels->setEnabled( false );
        return;
    }

    TQString qualityModeString = cQualityMode->currentText();
    TQString lastString;
    int lastValue;

    ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() );

    if( lastQualityMode != qualityModeString ) {
        lastValue = 0;
        lastQualityMode = qualityModeString;
    }
    else {
        lastValue = iQuality->value();
    }

    if( qualityModeString != i18n("Lossless") ) {
//         bitrateRangeToggled(); NOTE seems to be unnecessary
        if( plugin->enc.lossy.samplingrate.enabled ) cSamplingrateSwitch->setEnabled( true );
        else cSamplingrateSwitch->setEnabled( false );
        samplingrateToggled();
        if( plugin->enc.lossy.channels.mono_enabled || plugin->enc.lossy.channels.stereo_enabled || plugin->enc.lossy.channels.joint_stereo_enabled ||
            plugin->enc.lossy.channels.forced_joint_stereo_enabled || plugin->enc.lossy.channels.dual_channels_enabled ) {
            cChannelsSwitch->setEnabled( true );
            lastString = cChannels->currentText();
            sChannels.clear();
            if( plugin->enc.lossy.channels.mono_enabled ) {
                sChannels.append( i18n("Mono") );
            }
            if( plugin->enc.lossy.channels.stereo_enabled ) {
                sChannels.append( i18n("Stereo") );
            }
            if( plugin->enc.lossy.channels.joint_stereo_enabled ) {
                sChannels.append( i18n("Joint-Stereo") );
            }
            if( plugin->enc.lossy.channels.forced_joint_stereo_enabled ) {
                sChannels.append( i18n("Forced Joint-Stereo") );
            }
            if( plugin->enc.lossy.channels.dual_channels_enabled ) {
                sChannels.append( i18n("Dual Channels") );
            }
            cChannels->clear();
            cChannels->insertStringList( sChannels );
            cChannels->setCurrentItem( channelsIndex(lastString) );
        }
        else cChannelsSwitch->setEnabled( false );
        channelsToggled();
    }

    if( qualityModeString == i18n("Bitrate") ) {
        TQToolTip::add( iQuality, i18n("Kilobit per second") );
        iQuality->setEnabled( true );
        iQuality->setMinValue( 32 );
        iQuality->setMaxValue( 320 );
        iQuality->setLineStep( 8 );
        if( lastValue != 0 ) iQuality->setValue( lastValue );
        else iQuality->setValue( 192 );
        cBitrateMode->setEnabled( true );
        lastString = cBitrateMode->currentText();
        sBitrateMode.clear();
        if( plugin->enc.lossy.bitrate.abr.enabled ) {
            sBitrateMode.append( "abr" );
        }
        if( plugin->enc.lossy.bitrate.cbr.enabled ) {
            sBitrateMode.append( "cbr" );
        }
        cBitrateMode->clear();
        cBitrateMode->insertStringList( sBitrateMode );
        cBitrateMode->setCurrentItem( bitrateModeIndex(lastString) );
        bitrateModeChanged();
    }
    else if( qualityModeString == i18n("Quality") ) {
//         TQToolTip::add( iQuality, i18n("This is a relative quality between 0 and 100.\nThe higher this number the higher is the quality.\nsoundKonverter will convert it into the file format's quality format.\nSee the \"What's this?\" for more informations.") );
        iQuality->setEnabled( true );
        iQuality->setMinValue( 0 );
        iQuality->setMaxValue( 100 );
        iQuality->setLineStep( 5 );
        if( lastValue != 0 ) iQuality->setValue( lastValue );
        else iQuality->setValue( 40 );
        qualityChanged();
        cBitrateMode->setEnabled( true );
        sBitrateMode.clear();
        sBitrateMode.append( "vbr" );
        cBitrateMode->clear();
        cBitrateMode->insertStringList( sBitrateMode );
        bitrateModeChanged();

        if( !plugin->enc.lossy.quality.help.isEmpty() ) {
            TQString str = plugin->enc.lossy.quality.help;
            str.replace("\\n","<br>");
            TQWhatsThis::add( iQuality, "<p>"+str+"</p>" );
        }
    }
    else if( qualityModeString == i18n("Lossless") || qualityModeString == i18n("Undefined") ) {
        iQuality->setEnabled( false );
        cBitrateMode->setEnabled( false );
        cBitrateRangeSwitch->setEnabled( false );
        iMinBitrate->setEnabled( false );
        lBitrateRangeTo->setEnabled( false );
        iMaxBitrate->setEnabled( false );
        lBitrateRangeUnit->setEnabled( false );
        cSamplingrateSwitch->setEnabled( false );
        cSamplingrate->setEnabled( false );
        lSamplingrateUnit->setEnabled( false );
        cChannelsSwitch->setEnabled( false );
        cChannels->setEnabled( false );
    }
    else if( qualityModeString == i18n("Hybrid") ) {
        TQToolTip::add( iQuality, i18n("Kilobit per second") );
        iQuality->setEnabled( true );
        iQuality->setMinValue( 32 );
        iQuality->setMaxValue( 320 );
        iQuality->setLineStep( 8 );
        if( lastValue != 0 ) iQuality->setValue( lastValue );
        else iQuality->setValue( 192 );
        cBitrateMode->setEnabled( false );
    }
    else if( qualityModeString == i18n("Unchanged") ) {
        iQuality->setEnabled( false );
        cBitrateMode->setEnabled( false );
        cBitrateRangeSwitch->setEnabled( false );
        iMinBitrate->setEnabled( false );
        lBitrateRangeTo->setEnabled( false );
        iMaxBitrate->setEnabled( false );
        lBitrateRangeUnit->setEnabled( false );
    }
}

void OptionsDetailed::qualityChanged()
{
    if( cQualityMode->currentText() == i18n("Quality") ) {
        TQToolTip::remove( iQuality );

        FormatItem* formatItem = config->getFormatItem( cFormat->currentText() );
        if( formatItem == 0 ) {
            // FIXME error handling
            //kdDebug() << "NULL POINTER: `" << "Convert::formatChanged() / formatItem" << "'" << endl;
            return;
        }
        ConvertPlugin* plugin = formatItem->encoder;
        if( plugin == 0 ) {
            // FIXME error handling
            //kdDebug() << "NULL POINTER: `" << "OptionsDetailed::formatChanged() / plugin" << "'" << endl;
            return;
        }

        TQString quality;
        if( plugin->enc.lossy.quality.enabled ) {
            quality = plugin->enc.lossy.quality.param;
            int qualityLevel = iQuality->value();
            if( plugin->enc.lossy.quality.profiles.empty() ) {
                if( plugin->enc.lossy.quality.step < 1 ) {
                    if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min)
//                         t_float = ( (float)item->fileListItem->options.encodingOptions.iQuality * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min;
                        quality.replace( "%q", TQString::number( ( (float)qualityLevel * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min ) );
                    else
//                         t_float = ( (100.0f - (float)item->fileListItem->options.encodingOptions.iQuality) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max;
                        quality.replace( "%q", TQString::number( ( (100.0f - qualityLevel) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max ) );
                }
                else {
                    if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min)
//                         t_int = ( item->fileListItem->options.encodingOptions.iQuality * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min;
                        quality.replace( "%q", TQString::number( (qualityLevel * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min ) );
                    else
//                         t_int = ( (100 - item->fileListItem->options.encodingOptions.iQuality) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max;
                        quality.replace( "%q", TQString::number( ( (100 - qualityLevel) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max ) );
                }
                if( plugin->enc.bin == "oggenc" ) quality.replace(TQChar('.'),TDEGlobal::locale()->decimalSymbol()); // HACK make oggenc usable with all langauges
                else if( plugin->enc.lossy.quality.separator != '.' ) {
                    quality.replace( TQChar('.'), plugin->enc.lossy.quality.separator );
                }
            }
            else {
                TQStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( rint(qualityLevel*plugin->enc.lossy.quality.range_max/100) );
                quality.replace( "%q", *it );
            }
        }

        TQToolTip::add( iQuality, i18n("This is a relative quality between 0 and 100.\nThe higher this number the higher is the quality.\nsoundKonverter will convert it into the file format's quality format.\nSee the \"What's this?\" for more informations.\n\nCurrent parameter: \"%1\"").arg(quality) );
//         TQToolTip toolTip( iQuality );
//         toolTip.tip( i18n("Current parameter: \"%1\"").arg(quality) );
    }
}

void OptionsDetailed::bitrateModeChanged()
{
    ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() );

    if( cBitrateMode->currentText() == "abr" && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) {
        cBitrateRangeSwitch->setEnabled( true );
        bitrateRangeToggled();
    }
    else {
        cBitrateRangeSwitch->setEnabled( false );
        iMinBitrate->setEnabled( false );
        lBitrateRangeTo->setEnabled( false );
        iMaxBitrate->setEnabled( false );
        lBitrateRangeUnit->setEnabled( false );
    }
}

void OptionsDetailed::bitrateRangeToggled()
{
    if( cBitrateRangeSwitch->isChecked() && cBitrateRangeSwitch->isEnabled() ) {
        iMinBitrate->setEnabled( true );
        lBitrateRangeTo->setEnabled( true );
        iMaxBitrate->setEnabled( true );
        lBitrateRangeUnit->setEnabled( true );
    }
    else {
        iMinBitrate->setEnabled( false );
        lBitrateRangeTo->setEnabled( false );
        iMaxBitrate->setEnabled( false );
        lBitrateRangeUnit->setEnabled( false );
    }
}

void OptionsDetailed::samplingrateToggled() {
    if( cSamplingrateSwitch->isChecked() && cSamplingrateSwitch->isEnabled() ) {
        cSamplingrate->setEnabled( true );
        lSamplingrateUnit->setEnabled( true );
    }
    else {
        cSamplingrate->setEnabled( false );
        lSamplingrateUnit->setEnabled( false );
    }
}

void OptionsDetailed::channelsToggled() {
    if( cChannelsSwitch->isChecked() && cChannelsSwitch->isEnabled() ) {
        cChannels->setEnabled( true );
    }
    else {
        cChannels->setEnabled( false);
    }
}

void OptionsDetailed::somethingChanged()
{
    emit optionsChanged();
}

////////////////////////////////////////////////////////////
// access the options data - BEGIN
////////////////////////////////////////////////////////////

TQString OptionsDetailed::getFormat()
{
    return cFormat->currentText();
}

// TQString OptionsDetailed::getQualityMode()
// {
//     return cQualityMode->currentText();
// }

OutputDirectory::Mode OptionsDetailed::getOutputDirectoryMode()
{
    return outputDirectory->mode();
}

TQString OptionsDetailed::getOutputDirectoryPath()
{
    return outputDirectory->directory();
}


void OptionsDetailed::setFormat( const TQString &format )
{
    cFormat->setCurrentItem( formatIndex(format) );

    formatChanged();
}

void OptionsDetailed::setQualityMode( const TQString &qualityMode )
{
    cQualityMode->setCurrentItem( qualityModeIndex(qualityMode) );
    qualityModeChanged();
}

void OptionsDetailed::setQuality( int quality )
{
    iQuality->setValue( quality );
}

void OptionsDetailed::setBitrateMode( const TQString &bitrateMode )
{
    cBitrateMode->setCurrentItem( bitrateModeIndex(bitrateMode) );
    bitrateModeChanged();
}

void OptionsDetailed::setBitrateRangeEnabled( bool enabled )
{
    cBitrateRangeSwitch->setChecked( enabled );
}

void OptionsDetailed::setMinBitrate( int bitrate )
{
    iMinBitrate->setValue( bitrate );
}

void OptionsDetailed::setMaxBitrate( int bitrate )
{
    iMaxBitrate->setValue( bitrate );
}

void OptionsDetailed::setSamplingrateEnabled( bool enabled )
{
    cSamplingrateSwitch->setChecked( enabled );
}

void OptionsDetailed::setSamplingrate( int samplingrate )
{
    char text[8];

    sprintf( text, "%i", samplingrate );

    setSamplingrate( text );
}

void OptionsDetailed::setSamplingrate( const TQString &samplingrate )
{
    cSamplingrate->setCurrentText( samplingrate );
}

void OptionsDetailed::setChannelsEnabled( bool enabled )
{
    cChannelsSwitch->setChecked( enabled );
}

void OptionsDetailed::setChannels( const TQString &channels )
{
    cChannels->setCurrentItem( channelsIndex(channels) );
}

void OptionsDetailed::setReplayGainEnabled( bool enabled )
{
    cReplayGain->setChecked( enabled );
}

void OptionsDetailed::setOutputDirectoryMode( OutputDirectory::Mode mode )
{
    outputDirectory->setMode( mode );
}

void OptionsDetailed::setOutputDirectoryPath( const TQString &path )
{
    outputDirectory->setDirectory( path );
}

void OptionsDetailed::setUserOptions( const TQString &options )
{
    lUserOptions->setText( options );
}

int OptionsDetailed::getQuality()
{
    return iQuality->value();
}

bool OptionsDetailed::getBitrateRangeEnabled()
{
    return cBitrateRangeSwitch->isChecked();
}

bool OptionsDetailed::getSamplingrateEnabled()
{
    return cSamplingrateSwitch->isChecked();
}

int OptionsDetailed::getSamplingrate()
{
    return cSamplingrate->currentText().toInt();
}

bool OptionsDetailed::getChannelsEnabled()
{
    return cChannelsSwitch->isChecked();
}

TQString OptionsDetailed::getChannels()
{
    return cChannels->currentText();
}

////////////////////////////////////////////////////////////
// access the options data - END
////////////////////////////////////////////////////////////

void OptionsDetailed::toggleAdvancedOptions()
{
    if( normalOptions->isVisible() ) {
        normalOptions->hide();
        advancedOptions->show();
    }
    else {
        advancedOptions->hide();
        normalOptions->show();
    }
}

#include "optionsdetailed.moc"
