|
|
|
// (C) 2005 Max Howell (max.howell@methylblue.com)
|
|
|
|
// See COPYING file for licensing information
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
#include <tdeapplication.h> // XineConfigDialog::ctor -> to get the iconloader
|
|
|
|
#include <kcombobox.h>
|
|
|
|
#include <kiconloader.h> // XineConfigDialog::ctor
|
|
|
|
#include <klineedit.h>
|
|
|
|
#include <kseparator.h>
|
|
|
|
#include <kstdguiitem.h>
|
|
|
|
#include <ntqcheckbox.h>
|
|
|
|
#include <ntqlabel.h>
|
|
|
|
#include <ntqlayout.h>
|
|
|
|
#include <ntqscrollview.h>
|
|
|
|
#include <ntqspinbox.h>
|
|
|
|
#include <ntqtabwidget.h>
|
|
|
|
#include <ntqtooltip.h>
|
|
|
|
#include <ntqvbox.h>
|
|
|
|
#include <xine.h>
|
|
|
|
#include "xineConfig.h"
|
|
|
|
|
|
|
|
TQString i18n(const char *text);
|
|
|
|
|
|
|
|
|
|
|
|
KDialogBase *XineConfigDialog::s_instance = 0;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Codeine
|
|
|
|
{
|
|
|
|
void
|
|
|
|
showXineConfigurationDialog( TQWidget *parent, xine_t *xine )
|
|
|
|
{
|
|
|
|
XineConfigDialog d( xine, parent );
|
|
|
|
if( d.exec() == TQDialog::Accepted )
|
|
|
|
d.saveSettings();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class TabWidget : public TQTabWidget
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TabWidget( TQWidget *parent ) : TQTabWidget( parent ) {}
|
|
|
|
|
|
|
|
virtual TQSize sizeHint() const
|
|
|
|
{
|
|
|
|
// TQt gives a stupid default sizeHint for this widget
|
|
|
|
return TQSize(
|
|
|
|
reinterpret_cast<TQWidget*>(tabBar())->sizeHint().width() + 5,
|
|
|
|
TQTabWidget::sizeHint().height() );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
///@class XineConfigDialog
|
|
|
|
|
|
|
|
XineConfigDialog::XineConfigDialog( xine_t *xine, TQWidget *parent )
|
|
|
|
: KDialogBase( parent, "xine_config_dialog",
|
|
|
|
true, //modal
|
|
|
|
i18n("Configure xine"), User1 | Stretch | Ok | Cancel,
|
|
|
|
Ok, //default button
|
|
|
|
false, //draw separator
|
|
|
|
KStdGuiItem::reset() )
|
|
|
|
, m_xine( xine )
|
|
|
|
{
|
|
|
|
DEBUG_BLOCK
|
|
|
|
|
|
|
|
s_instance = this;
|
|
|
|
const int METRIC = fontMetrics().width( 'x' );
|
|
|
|
const int METRIC_3B2 = (3*METRIC)/2;
|
|
|
|
|
|
|
|
TQVBox *box = new TQVBox( this );
|
|
|
|
box->setSpacing( METRIC );
|
|
|
|
setMainWidget( box );
|
|
|
|
|
|
|
|
{
|
|
|
|
TQHBox *hbox = new TQHBox( box );
|
|
|
|
hbox->setSpacing( METRIC_3B2 );
|
|
|
|
hbox->setMargin( METRIC_3B2 );
|
|
|
|
TQPixmap info = kapp->iconLoader()->loadIcon( "messagebox_info", TDEIcon::NoGroup, TDEIcon::SizeMedium, TDEIcon::DefaultState, 0, true );
|
|
|
|
TQLabel *label = new TQLabel( hbox );
|
|
|
|
label->setPixmap( info );
|
|
|
|
label->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
|
|
|
|
label = new TQLabel( i18n(
|
|
|
|
"xine's defaults are usually sensible and should not require modification. "
|
|
|
|
"However, full configurability is provided for your pleasure ;-)." ), hbox );
|
|
|
|
label->setAlignment( TQLabel::WordBreak | TQLabel::AlignVCenter );
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME after many hours I have discovered that this
|
|
|
|
// widget somehow sets the minSize of this widget to 0,0
|
|
|
|
// whenever you resize the widget. WTF?
|
|
|
|
TabWidget *tabs = new TabWidget( box );
|
|
|
|
|
|
|
|
|
|
|
|
class XineConfigEntryIterator {
|
|
|
|
xine_t *m_xine;
|
|
|
|
xine_cfg_entry_t m_entry;
|
|
|
|
bool m_valid;
|
|
|
|
public:
|
|
|
|
XineConfigEntryIterator( xine_t *xine ) : m_xine( xine ) { m_valid = xine_config_get_first_entry( m_xine, &m_entry ); }
|
|
|
|
inline XineConfigEntryIterator &operator++() { m_valid = xine_config_get_next_entry( m_xine, &m_entry ); return *this; }
|
|
|
|
inline xine_cfg_entry_t *operator*() { return m_valid ? &m_entry : 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TQGridLayout *grid = 0;
|
|
|
|
TQString currentPage;
|
|
|
|
TQScrollView *view = 0;
|
|
|
|
parent = 0;
|
|
|
|
|
|
|
|
for( XineConfigEntryIterator it( m_xine ); *it; ++it )
|
|
|
|
{
|
|
|
|
const TQString pageName = TQString::fromUtf8( (*it)->key ).section( '.', 0, 0 );
|
|
|
|
|
|
|
|
if( (TQStringList() << "ui" << "effects" << "subtitles").contains( pageName ) )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( pageName != currentPage ) {
|
|
|
|
if( view )
|
|
|
|
//NOTE won't be executed for last tab
|
|
|
|
view->viewport()->setMinimumWidth( grid->sizeHint().width() ); // seems necessary
|
|
|
|
|
|
|
|
TQString pageTitle = pageName;
|
|
|
|
pageTitle[0] = pageTitle[0].upper();
|
|
|
|
|
|
|
|
tabs->addTab( view = new TQScrollView, pageTitle );
|
|
|
|
view->setResizePolicy( TQScrollView::AutoOneFit );
|
|
|
|
view->setHScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
view->setFrameShape( TQFrame::NoFrame );
|
|
|
|
view->addChild( parent = new TQWidget( view->viewport() ) );
|
|
|
|
|
|
|
|
TQBoxLayout *layout = new TQVBoxLayout( parent, /*margin*/METRIC_3B2, /*spacing*/0 );
|
|
|
|
|
|
|
|
parent = new TQFrame( parent );
|
|
|
|
static_cast<TQFrame*>(parent)->setFrameStyle( TQFrame::Panel | TQFrame::Raised );
|
|
|
|
static_cast<TQFrame*>(parent)->setLineWidth( 2 );
|
|
|
|
grid = new TQGridLayout( parent, /*rows*/0, /*cols*/2, /*margin*/20, /*spacing*/int(METRIC*2.5) );
|
|
|
|
grid->setColStretch( 0, 3 );
|
|
|
|
grid->setColStretch( 1, 2 );
|
|
|
|
|
|
|
|
layout->addWidget( parent, 0 );
|
|
|
|
layout->addStretch( 1 );
|
|
|
|
|
|
|
|
currentPage = pageName;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_entrys.append( new XineConfigEntry( parent, grid, *it ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
//finishing touches
|
|
|
|
m_entrys.setAutoDelete( true );
|
|
|
|
enableButton( Ok, false );
|
|
|
|
enableButton( User1, false );
|
|
|
|
|
|
|
|
Q_ASSERT( !isUnsavedSettings() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
XineConfigDialog::slotHelp()
|
|
|
|
{
|
|
|
|
/// HACK called when a widget's input value changes
|
|
|
|
|
|
|
|
const bool b = isUnsavedSettings();
|
|
|
|
enableButton( Ok, b );
|
|
|
|
enableButton( User1, b );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
XineConfigDialog::slotUser1()
|
|
|
|
{
|
|
|
|
for( TQPtrListIterator<XineConfigEntry> it( m_entrys ); *it != 0; ++it )
|
|
|
|
(*it)->reset();
|
|
|
|
|
|
|
|
slotHelp();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
XineConfigDialog::isUnsavedSettings() const
|
|
|
|
{
|
|
|
|
for( TQPtrListIterator<XineConfigEntry> it( m_entrys ); *it != 0; ++it )
|
|
|
|
if( (*it)->isChanged() )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <ntqdir.h>
|
|
|
|
void
|
|
|
|
XineConfigDialog::saveSettings()
|
|
|
|
{
|
|
|
|
for( XineConfigEntry *entry = m_entrys.first(); entry; entry = m_entrys.next() )
|
|
|
|
if( entry->isChanged() )
|
|
|
|
entry->save( m_xine );
|
|
|
|
|
|
|
|
xine_config_save( m_xine, TQFile::encodeName( TQDir::homeDirPath() + "/.xine/config" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///@class XineConfigEntry
|
|
|
|
|
|
|
|
XineConfigEntry::XineConfigEntry( TQWidget *parent, TQGridLayout *grid, xine_cfg_entry_t *entry )
|
|
|
|
: m_widget( 0 )
|
|
|
|
, m_key( entry->key )
|
|
|
|
, m_string( entry->str_value )
|
|
|
|
, m_number( entry->num_value )
|
|
|
|
{
|
|
|
|
TQWidget *&w = m_widget;
|
|
|
|
const char *signal = 0;
|
|
|
|
const int row = grid->numRows();
|
|
|
|
|
|
|
|
TQString description_text = TQString::fromUtf8( entry->description );
|
|
|
|
description_text[0] = description_text[0].upper();
|
|
|
|
|
|
|
|
switch( entry->type )
|
|
|
|
{
|
|
|
|
case XINE_CONFIG_TYPE_STRING: {
|
|
|
|
w = new KLineEdit( m_string, parent );
|
|
|
|
signal = SIGNAL(textChanged( const TQString& ));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XINE_CONFIG_TYPE_ENUM: {
|
|
|
|
w = new KComboBox( parent );
|
|
|
|
for( int i = 0; entry->enum_values[i]; ++i )
|
|
|
|
((KComboBox*)w)->insertItem( TQString::fromUtf8( entry->enum_values[i] ) );
|
|
|
|
((KComboBox*)w)->setCurrentItem( m_number );
|
|
|
|
signal = SIGNAL(activated( int ));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XINE_CONFIG_TYPE_RANGE:
|
|
|
|
case XINE_CONFIG_TYPE_NUM: {
|
|
|
|
w = new TQSpinBox(
|
|
|
|
TQMIN( m_number, entry->range_min ), // xine bug, sometimes the min and max ranges
|
|
|
|
TQMAX( m_number, entry->range_max ), // are both 0 even though this is bullshit
|
|
|
|
1, parent );
|
|
|
|
((TQSpinBox*)w)->setValue( m_number );
|
|
|
|
signal = SIGNAL(valueChanged( int ));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XINE_CONFIG_TYPE_BOOL: {
|
|
|
|
w = new TQCheckBox( description_text, parent );
|
|
|
|
((TQCheckBox*)w)->setChecked( m_number );
|
|
|
|
|
|
|
|
connect( w, SIGNAL(toggled( bool )), XineConfigDialog::instance(), SLOT(slotHelp()) );
|
|
|
|
TQToolTip::add( w, "<qt>" + TQString::fromUtf8( entry->help ) );
|
|
|
|
grid->addMultiCellWidget( w, row, row, 0, 1 );
|
|
|
|
return; //no need for a description label
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
connect( w, signal, XineConfigDialog::instance(), SLOT(slotHelp()) );
|
|
|
|
|
|
|
|
TQLabel *description = new TQLabel( description_text + ':', parent );
|
|
|
|
description->setAlignment( TQLabel::WordBreak | TQLabel::AlignVCenter );
|
|
|
|
|
|
|
|
const TQString tip = "<qt>" + TQString::fromUtf8( entry->help );
|
|
|
|
TQToolTip::add( w, tip );
|
|
|
|
TQToolTip::add( description, tip );
|
|
|
|
|
|
|
|
// grid->addWidget( description, row, 0, TQt::AlignVCenter );
|
|
|
|
grid->addWidget( w, row, 1, TQt::AlignTop );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
XineConfigEntry::isChanged() const
|
|
|
|
{
|
|
|
|
#define _( x ) static_cast<x*>(m_widget)
|
|
|
|
|
|
|
|
switch( classType( m_widget->className() ) ) {
|
|
|
|
case LineEdit: return _(KLineEdit)->text().utf8() != m_string;
|
|
|
|
case ComboBox: return _(KComboBox)->currentItem() != m_number;
|
|
|
|
case SpinBox: return _(TQSpinBox)->value() != m_number;
|
|
|
|
case CheckBox: return _(TQCheckBox)->isChecked() != m_number;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
XineConfigEntry::reset()
|
|
|
|
{
|
|
|
|
// this is because we only get called by the XineConfigDialog reset button
|
|
|
|
// and we don't want to cause a check for Ok/Reset button enabled state for
|
|
|
|
// every XineConfigEntry
|
|
|
|
m_widget->blockSignals( true );
|
|
|
|
|
|
|
|
switch( classType( m_widget->className() ) ) {
|
|
|
|
case LineEdit: _(KLineEdit)->setText( m_string ); break;
|
|
|
|
case ComboBox: _(KComboBox)->setCurrentItem( m_number ); break;
|
|
|
|
case SpinBox: _(TQSpinBox)->setValue( m_number ); break;
|
|
|
|
case CheckBox: _(TQCheckBox)->setChecked( (bool)m_number ); break;
|
|
|
|
}
|
|
|
|
m_widget->blockSignals( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
XineConfigEntry::save( xine_t *xine )
|
|
|
|
{
|
|
|
|
xine_cfg_entry_t ent;
|
|
|
|
|
|
|
|
if( xine_config_lookup_entry( xine, key(), &ent ) )
|
|
|
|
{
|
|
|
|
switch( classType( m_widget->className() ) ) {
|
|
|
|
case LineEdit: m_string = _(KLineEdit)->text().utf8(); break;
|
|
|
|
case ComboBox: m_number = _(KComboBox)->currentItem(); break;
|
|
|
|
case SpinBox: m_number = _(TQSpinBox)->value(); break;
|
|
|
|
case CheckBox: m_number = _(TQCheckBox)->isChecked(); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ent.str_value = tqstrdup( m_string );
|
|
|
|
ent.num_value = m_number;
|
|
|
|
|
|
|
|
debug() << "Saving setting: " << key() << endl;
|
|
|
|
xine_config_update_entry( xine, &ent );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Debug::warning() << "Couldn't save: " << key() << endl;
|
|
|
|
|
|
|
|
#undef _
|
|
|
|
}
|