You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
codeine/src/app/xineConfig.cpp

322 lines
9.6 KiB

// (C) 2005 Max Howell (max.howell@methylblue.com)
// See COPYING file for licensing information
#include "debug.h"
#include <kapplication.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 <qcheckbox.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qscrollview.h>
#include <qspinbox.h>
#include <qtabwidget.h>
#include <qtooltip.h>
#include <qvbox.h>
#include <xine.h>
#include "xineConfig.h"
QString i18n(const char *text);
KDialogBase *XineConfigDialog::s_instance = 0;
namespace Codeine
{
void
showXineConfigurationDialog( QWidget *parent, xine_t *xine )
{
XineConfigDialog d( xine, parent );
if( d.exec() == QDialog::Accepted )
d.saveSettings();
}
}
class TabWidget : public QTabWidget
{
public:
TabWidget( QWidget *parent ) : QTabWidget( parent ) {}
virtual QSize sizeHint() const
{
// Qt gives a stupid default sizeHint for this widget
return QSize(
reinterpret_cast<QWidget*>(tabBar())->sizeHint().width() + 5,
QTabWidget::sizeHint().height() );
}
};
///@class XineConfigDialog
XineConfigDialog::XineConfigDialog( xine_t *xine, QWidget *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;
QVBox *box = new QVBox( this );
box->setSpacing( METRIC );
setMainWidget( box );
{
QHBox *hbox = new QHBox( box );
hbox->setSpacing( METRIC_3B2 );
hbox->setMargin( METRIC_3B2 );
QPixmap info = kapp->iconLoader()->loadIcon( "messagebox_info", KIcon::NoGroup, KIcon::SizeMedium, KIcon::DefaultState, 0, true );
QLabel *label = new QLabel( hbox );
label->setPixmap( info );
label->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
label = new QLabel( i18n(
"xine's defaults are usually sensible and should not require modification. "
"However, full configurability is provided for your pleasure ;-)." ), hbox );
label->setAlignment( QLabel::WordBreak | QLabel::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; }
};
QGridLayout *grid = 0;
QString currentPage;
QScrollView *view = 0;
parent = 0;
for( XineConfigEntryIterator it( m_xine ); *it; ++it )
{
const QString pageName = QString::fromUtf8( (*it)->key ).section( '.', 0, 0 );
if( (QStringList() << "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
QString pageTitle = pageName;
pageTitle[0] = pageTitle[0].upper();
tabs->addTab( view = new QScrollView, pageTitle );
view->setResizePolicy( QScrollView::AutoOneFit );
view->setHScrollBarMode( QScrollView::AlwaysOff );
view->setFrameShape( QFrame::NoFrame );
view->addChild( parent = new QWidget( view->viewport() ) );
QBoxLayout *layout = new QVBoxLayout( parent, /*margin*/METRIC_3B2, /*spacing*/0 );
parent = new QFrame( parent );
static_cast<QFrame*>(parent)->setFrameStyle( QFrame::Panel | QFrame::Raised );
static_cast<QFrame*>(parent)->setLineWidth( 2 );
grid = new QGridLayout( 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( QPtrListIterator<XineConfigEntry> it( m_entrys ); *it != 0; ++it )
(*it)->reset();
slotHelp();
}
bool
XineConfigDialog::isUnsavedSettings() const
{
for( QPtrListIterator<XineConfigEntry> it( m_entrys ); *it != 0; ++it )
if( (*it)->isChanged() )
return true;
return false;
}
#include <qdir.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, QFile::encodeName( QDir::homeDirPath() + "/.xine/config" ) );
}
///@class XineConfigEntry
XineConfigEntry::XineConfigEntry( QWidget *parent, QGridLayout *grid, xine_cfg_entry_t *entry )
: m_widget( 0 )
, m_key( entry->key )
, m_string( entry->str_value )
, m_number( entry->num_value )
{
QWidget *&w = m_widget;
const char *signal = 0;
const int row = grid->numRows();
QString description_text = QString::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 QString& ));
break;
}
case XINE_CONFIG_TYPE_ENUM: {
w = new KComboBox( parent );
for( int i = 0; entry->enum_values[i]; ++i )
((KComboBox*)w)->insertItem( QString::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 QSpinBox(
QMIN( m_number, entry->range_min ), // xine bug, sometimes the min and max ranges
QMAX( m_number, entry->range_max ), // are both 0 even though this is bullshit
1, parent );
((QSpinBox*)w)->setValue( m_number );
signal = SIGNAL(valueChanged( int ));
break;
}
case XINE_CONFIG_TYPE_BOOL: {
w = new QCheckBox( description_text, parent );
((QCheckBox*)w)->setChecked( m_number );
connect( w, SIGNAL(toggled( bool )), XineConfigDialog::instance(), SLOT(slotHelp()) );
QToolTip::add( w, "<qt>" + QString::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()) );
QLabel *description = new QLabel( description_text + ':', parent );
description->setAlignment( QLabel::WordBreak | QLabel::AlignVCenter );
const QString tip = "<qt>" + QString::fromUtf8( entry->help );
QToolTip::add( w, tip );
QToolTip::add( description, tip );
// grid->addWidget( description, row, 0, Qt::AlignVCenter );
grid->addWidget( w, row, 1, Qt::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 _(QSpinBox)->value() != m_number;
case CheckBox: return _(QCheckBox)->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: _(QSpinBox)->setValue( m_number ); break;
case CheckBox: _(QCheckBox)->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 = _(QSpinBox)->value(); break;
case CheckBox: m_number = _(QCheckBox)->isChecked(); break;
}
ent.str_value = qstrdup( 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 _
}