/*
* KCMStyle
* Copyright (C) 2002 Karol Szwed Disable: do not use any combo box effects. Disable: do not use any tooltip effects. Animate: Do some animation. Disable: do not use any rubberband effects. Disable: do not use any menu effects. Animate: Do some animation. Fade: Fade in menus using alpha-blending. Software Tint: Alpha-blend using a flat color. Software Blend: Alpha-blend using an image.Style
"
"This module allows you to modify the visual appearance "
"of user interface elements, such as the widget style "
"and effects."));
m_bEffectsDirty = false;
m_bStyleDirty= false;
m_bToolbarsDirty = false;
KGlobal::dirs()->addResourceType("themes",
KStandardDirs::kde_default("data") + "kstyle/themes");
KAboutData *about =
new KAboutData( I18N_NOOP("kcmstyle"),
I18N_NOOP("KDE Style Module"),
0, 0, KAboutData::License_GPL,
I18N_NOOP("(c) 2002 Karol Szwed, Daniel Molkentin"));
about->addAuthor("Karol Szwed", 0, "gallium@kde.org");
about->addAuthor("Daniel Molkentin", 0, "molkentin@kde.org");
about->addAuthor("Ralf Nolden", 0, "nolden@kde.org");
setAboutData( about );
// Setup pages and mainLayout
mainLayout = new QVBoxLayout( this );
tabWidget = new QTabWidget( this );
mainLayout->addWidget( tabWidget );
page1 = new QWidget( tabWidget );
page1Layout = new QVBoxLayout( page1, KDialog::marginHint(), KDialog::spacingHint() );
page2 = new QWidget( tabWidget );
page2Layout = new QVBoxLayout( page2, KDialog::marginHint(), KDialog::spacingHint() );
page3 = new QWidget( tabWidget );
page3Layout = new QVBoxLayout( page3, KDialog::marginHint(), KDialog::spacingHint() );
// Add Page1 (Style)
// -----------------
gbWidgetStyle = new QGroupBox( i18n("Widget Style"), page1, "gbWidgetStyle" );
gbWidgetStyle->setColumnLayout( 0, Qt::Vertical );
gbWidgetStyle->layout()->setMargin( KDialog::marginHint() );
gbWidgetStyle->layout()->setSpacing( KDialog::spacingHint() );
gbWidgetStyleLayout = new QVBoxLayout( gbWidgetStyle->layout() );
gbWidgetStyleLayout->setAlignment( Qt::AlignTop );
hbLayout = new QHBoxLayout( KDialog::spacingHint(), "hbLayout" );
cbStyle = new KComboBox( gbWidgetStyle, "cbStyle" );
cbStyle->setEditable( FALSE );
hbLayout->addWidget( cbStyle );
pbConfigStyle = new QPushButton( i18n("Con&figure..."), gbWidgetStyle );
pbConfigStyle->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Minimum );
pbConfigStyle->setEnabled( FALSE );
hbLayout->addWidget( pbConfigStyle );
gbWidgetStyleLayout->addLayout( hbLayout );
lblStyleDesc = new QLabel( gbWidgetStyle );
lblStyleDesc->setTextFormat(Qt::RichText);
gbWidgetStyleLayout->addWidget( lblStyleDesc );
cbIconsOnButtons = new QCheckBox( i18n("Sho&w icons on buttons"), gbWidgetStyle );
gbWidgetStyleLayout->addWidget( cbIconsOnButtons );
cbEnableTooltips = new QCheckBox( i18n("E&nable tooltips"), gbWidgetStyle );
gbWidgetStyleLayout->addWidget( cbEnableTooltips );
cbTearOffHandles = new QCheckBox( i18n("Show tear-off handles in &popup menus"), gbWidgetStyle );
gbWidgetStyleLayout->addWidget( cbTearOffHandles );
cbTearOffHandles->hide(); // reenable when the corresponding Qt method is virtual and properly reimplemented
QGroupBox *gbPreview = new QGroupBox( i18n( "Preview" ), page1 );
gbPreview->setColumnLayout( 0, Vertical );
gbPreview->layout()->setMargin( 0 );
gbPreview->layout()->setSpacing( KDialog::spacingHint() );
gbPreview->setFlat( true );
stylePreview = new StylePreview( gbPreview );
gbPreview->layout()->add( stylePreview );
page1Layout->addWidget( gbWidgetStyle );
page1Layout->addWidget( gbPreview );
// Connect all required stuff
connect( cbStyle, SIGNAL(activated(int)), this, SLOT(styleChanged()) );
connect( cbStyle, SIGNAL(activated(int)), this, SLOT(updateConfigButton()));
connect( pbConfigStyle, SIGNAL(clicked()), this, SLOT(styleSpecificConfig()));
// Add Page2 (Effects)
// -------------------
cbEnableEffects = new QCheckBox( i18n("&Enable GUI effects"), page2 );
containerFrame = new QFrame( page2 );
containerFrame->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
containerFrame->setMargin(0);
containerLayout = new QGridLayout( containerFrame, 1, 1, // rows, columns
KDialog::marginHint(), KDialog::spacingHint() );
comboComboEffect = new QComboBox( FALSE, containerFrame );
comboComboEffect->insertItem( i18n("Disable") );
comboComboEffect->insertItem( i18n("Animate") );
lblComboEffect = new QLabel( i18n("Combobo&x effect:"), containerFrame );
lblComboEffect->setBuddy( comboComboEffect );
containerLayout->addWidget( lblComboEffect, 0, 0 );
containerLayout->addWidget( comboComboEffect, 0, 1 );
comboTooltipEffect = new QComboBox( FALSE, containerFrame );
comboTooltipEffect->insertItem( i18n("Disable") );
comboTooltipEffect->insertItem( i18n("Animate") );
comboTooltipEffect->insertItem( i18n("Fade") );
lblTooltipEffect = new QLabel( i18n("&Tool tip effect:"), containerFrame );
lblTooltipEffect->setBuddy( comboTooltipEffect );
containerLayout->addWidget( lblTooltipEffect, 1, 0 );
containerLayout->addWidget( comboTooltipEffect, 1, 1 );
comboRubberbandEffect = new QComboBox( FALSE, containerFrame );
comboRubberbandEffect->insertItem( i18n("Disable") );
comboRubberbandEffect->insertItem( i18n("Make translucent") );
lblRubberbandEffect = new QLabel( i18n("&Rubberband effect:"), containerFrame );
lblRubberbandEffect->setBuddy( comboRubberbandEffect );
containerLayout->addWidget( lblRubberbandEffect, 2, 0 );
containerLayout->addWidget( comboRubberbandEffect, 2, 1 );
comboMenuEffect = new QComboBox( FALSE, containerFrame );
comboMenuEffect->insertItem( i18n("Disable") );
comboMenuEffect->insertItem( i18n("Animate") );
comboMenuEffect->insertItem( i18n("Fade") );
comboMenuEffect->insertItem( i18n("Make Translucent") );
lblMenuEffect = new QLabel( i18n("&Menu effect:"), containerFrame );
lblMenuEffect->setBuddy( comboMenuEffect );
containerLayout->addWidget( lblMenuEffect, 3, 0 );
containerLayout->addWidget( comboMenuEffect, 3, 1 );
comboMenuHandle = new QComboBox( FALSE, containerFrame );
comboMenuHandle->insertItem( i18n("Disable") );
comboMenuHandle->insertItem( i18n("Application Level") );
// comboMenuHandle->insertItem( i18n("Enable") );
lblMenuHandle = new QLabel( i18n("Me&nu tear-off handles:"), containerFrame );
lblMenuHandle->setBuddy( comboMenuHandle );
containerLayout->addWidget( lblMenuHandle, 4, 0 );
containerLayout->addWidget( comboMenuHandle, 4, 1 );
cbMenuShadow = new QCheckBox( i18n("Menu &drop shadow"), containerFrame );
containerLayout->addWidget( cbMenuShadow, 5, 0 );
// Push the [label combo] to the left.
comboSpacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
containerLayout->addItem( comboSpacer, 1, 2 );
// Separator.
QFrame* hline = new QFrame ( page2 );
hline->setFrameStyle( QFrame::HLine | QFrame::Sunken );
// Now implement the Menu Transparency container.
menuContainer = new QFrame( page2 );
menuContainer->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
menuContainer->setMargin(0);
menuContainerLayout = new QGridLayout( menuContainer, 1, 1, // rows, columns
KDialog::marginHint(), KDialog::spacingHint() );
menuPreview = new MenuPreview( menuContainer, /* opacity */ 90, MenuPreview::Blend );
comboMenuEffectType = new QComboBox( FALSE, menuContainer );
comboMenuEffectType->insertItem( i18n("Software Tint") );
comboMenuEffectType->insertItem( i18n("Software Blend") );
#ifdef HAVE_XRENDER
comboMenuEffectType->insertItem( i18n("XRender Blend") );
#endif
// So much stuffing around for a simple slider..
sliderBox = new QVBox( menuContainer );
sliderBox->setSpacing( KDialog::spacingHint() );
sliderBox->setMargin( 0 );
slOpacity = new QSlider( 0, 100, 5, /*opacity*/ 90, Qt::Horizontal, sliderBox );
slOpacity->setTickmarks( QSlider::Below );
slOpacity->setTickInterval( 10 );
QHBox* box1 = new QHBox( sliderBox );
box1->setSpacing( KDialog::spacingHint() );
box1->setMargin( 0 );
QLabel* lbl = new QLabel( i18n("0%"), box1 );
lbl->setAlignment( AlignLeft );
lbl = new QLabel( i18n("50%"), box1 );
lbl->setAlignment( AlignHCenter );
lbl = new QLabel( i18n("100%"), box1 );
lbl->setAlignment( AlignRight );
lblMenuEffectType = new QLabel( comboMenuEffectType, i18n("Menu trans&lucency type:"), menuContainer );
lblMenuEffectType->setAlignment( AlignBottom | AlignLeft );
lblMenuOpacity = new QLabel( slOpacity, i18n("Menu &opacity:"), menuContainer );
lblMenuOpacity->setAlignment( AlignBottom | AlignLeft );
menuContainerLayout->addWidget( lblMenuEffectType, 0, 0 );
menuContainerLayout->addWidget( comboMenuEffectType, 1, 0 );
menuContainerLayout->addWidget( lblMenuOpacity, 2, 0 );
menuContainerLayout->addWidget( sliderBox, 3, 0 );
menuContainerLayout->addMultiCellWidget( menuPreview, 0, 3, 1, 1 );
// Layout page2.
page2Layout->addWidget( cbEnableEffects );
page2Layout->addWidget( containerFrame );
page2Layout->addWidget( hline );
page2Layout->addWidget( menuContainer );
QSpacerItem* sp1 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
page2Layout->addItem( sp1 );
// Data flow stuff.
connect( cbEnableEffects, SIGNAL(toggled(bool)), containerFrame, SLOT(setEnabled(bool)) );
connect( cbEnableEffects, SIGNAL(toggled(bool)), this, SLOT(menuEffectChanged(bool)) );
connect( slOpacity, SIGNAL(valueChanged(int)),menuPreview, SLOT(setOpacity(int)) );
connect( comboMenuEffect, SIGNAL(activated(int)), this, SLOT(menuEffectChanged()) );
connect( comboMenuEffect, SIGNAL(highlighted(int)), this, SLOT(menuEffectChanged()) );
connect( comboMenuEffectType, SIGNAL(activated(int)), this, SLOT(menuEffectTypeChanged()) );
connect( comboMenuEffectType, SIGNAL(highlighted(int)), this, SLOT(menuEffectTypeChanged()) );
// Add Page3 (Miscellaneous)
// -------------------------
cbHoverButtons = new QCheckBox( i18n("High&light buttons under mouse"), page3 );
cbTransparentToolbars = new QCheckBox( i18n("Transparent tool&bars when moving"), page3 );
QWidget * dummy = new QWidget( page3 );
QHBoxLayout* box2 = new QHBoxLayout( dummy, 0, KDialog::spacingHint() );
lbl = new QLabel( i18n("Text pos&ition:"), dummy );
comboToolbarIcons = new QComboBox( FALSE, dummy );
comboToolbarIcons->insertItem( i18n("Icons Only") );
comboToolbarIcons->insertItem( i18n("Text Only") );
comboToolbarIcons->insertItem( i18n("Text Alongside Icons") );
comboToolbarIcons->insertItem( i18n("Text Under Icons") );
lbl->setBuddy( comboToolbarIcons );
box2->addWidget( lbl );
box2->addWidget( comboToolbarIcons );
QSpacerItem* sp2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
box2->addItem( sp2 );
page3Layout->addWidget( cbHoverButtons );
page3Layout->addWidget( cbTransparentToolbars );
page3Layout->addWidget( dummy );
// Layout page3.
QSpacerItem* sp3 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
page3Layout->addItem( sp3 );
// Load settings
load();
// Do all the setDirty connections.
connect(cbStyle, SIGNAL(activated(int)), this, SLOT(setStyleDirty()));
// Page2
connect( cbEnableEffects, SIGNAL(toggled(bool)), this, SLOT(setEffectsDirty()));
connect( cbEnableEffects, SIGNAL(toggled(bool)), this, SLOT(setStyleDirty()));
connect( comboTooltipEffect, SIGNAL(activated(int)), this, SLOT(setEffectsDirty()));
connect( comboRubberbandEffect, SIGNAL(activated(int)), this, SLOT(setStyleDirty()));
connect( comboComboEffect, SIGNAL(activated(int)), this, SLOT(setEffectsDirty()));
connect( comboMenuEffect, SIGNAL(activated(int)), this, SLOT(setStyleDirty()));
connect( comboMenuHandle, SIGNAL(activated(int)), this, SLOT(setStyleDirty()));
connect( comboMenuEffectType, SIGNAL(activated(int)), this, SLOT(setStyleDirty()));
connect( slOpacity, SIGNAL(valueChanged(int)),this, SLOT(setStyleDirty()));
connect( cbMenuShadow, SIGNAL(toggled(bool)), this, SLOT(setStyleDirty()));
// Page3
connect( cbHoverButtons, SIGNAL(toggled(bool)), this, SLOT(setToolbarsDirty()));
connect( cbTransparentToolbars, SIGNAL(toggled(bool)), this, SLOT(setToolbarsDirty()));
connect( cbEnableTooltips, SIGNAL(toggled(bool)), this, SLOT(setEffectsDirty()));
connect( cbIconsOnButtons, SIGNAL(toggled(bool)), this, SLOT(setEffectsDirty()));
connect( cbTearOffHandles, SIGNAL(toggled(bool)), this, SLOT(setEffectsDirty()));
connect( comboToolbarIcons, SIGNAL(activated(int)), this, SLOT(setToolbarsDirty()));
addWhatsThis();
// Insert the pages into the tabWidget
tabWidget->insertTab( page1, i18n("&Style"));
tabWidget->insertTab( page2, i18n("&Effects"));
tabWidget->insertTab( page3, i18n("&Toolbar"));
//Enable/disable the button for the initial style
updateConfigButton();
}
KCMStyle::~KCMStyle()
{
delete appliedStyle;
}
void KCMStyle::updateConfigButton()
{
if (!styleEntries[currentStyle()] || styleEntries[currentStyle()]->configPage.isEmpty()) {
pbConfigStyle->setEnabled(false);
return;
}
// We don't check whether it's loadable here -
// lets us report an error and not waste time
// loading things if the user doesn't click the button
pbConfigStyle->setEnabled( true );
}
void KCMStyle::styleSpecificConfig()
{
QString libname = styleEntries[currentStyle()]->configPage;
// Use KLibLoader to get the library, handling
// any errors that arise
KLibLoader* loader = KLibLoader::self();
KLibrary* library = loader->library( QFile::encodeName(libname) );
if (!library)
{
KMessageBox::detailedError(this,
i18n("There was an error loading the configuration dialog for this style."),
loader->lastErrorMessage(),
i18n("Unable to Load Dialog"));
return;
}
void* allocPtr = library->symbol("allocate_kstyle_config");
if (!allocPtr)
{
KMessageBox::detailedError(this,
i18n("There was an error loading the configuration dialog for this style."),
loader->lastErrorMessage(),
i18n("Unable to Load Dialog"));
return;
}
//Create the container dialog
StyleConfigDialog* dial = new StyleConfigDialog(this, styleEntries[currentStyle()]->name);
dial->enableButtonSeparator(true);
typedef QWidget*(* factoryRoutine)( QWidget* parent );
//Get the factory, and make the widget.
factoryRoutine factory = (factoryRoutine)(allocPtr); //Grmbl. So here I am on my
//"never use C casts" moralizing streak, and I find that one can't go void* -> function ptr
//even with a reinterpret_cast.
QWidget* pluginConfig = factory( dial );
//Insert it in...
dial->setMainWidget( pluginConfig );
//..and connect it to the wrapper
connect(pluginConfig, SIGNAL(changed(bool)), dial, SLOT(setDirty(bool)));
connect(dial, SIGNAL(defaults()), pluginConfig, SLOT(defaults()));
connect(dial, SIGNAL(save()), pluginConfig, SLOT(save()));
if (dial->exec() == QDialog::Accepted && dial->isDirty() ) {
// Force re-rendering of the preview, to apply settings
switchStyle(currentStyle(), true);
//For now, ask all KDE apps to recreate their styles to apply the setitngs
KIPC::sendMessageAll(KIPC::StyleChanged);
// We call setStyleDirty here to make sure we force style re-creation
setStyleDirty();
}
delete dial;
}
void KCMStyle::load()
{
load( false );
}
void KCMStyle::load(bool useDefaults)
{
KConfig config( "kdeglobals", true, false );
config.setReadDefaults( useDefaults );
// Page1 - Build up the Style ListBox
loadStyle( config );
// Page2 - Effects
loadEffects( config );
// Page3 - Misc.
loadMisc( config );
m_bEffectsDirty = false;
m_bStyleDirty= false;
m_bToolbarsDirty = false;
emit changed( useDefaults );
}
void KCMStyle::save()
{
// Don't do anything if we don't need to.
if ( !(m_bToolbarsDirty | m_bEffectsDirty | m_bStyleDirty ) )
return;
bool allowMenuTransparency = false;
bool allowMenuDropShadow = false;
// Read the KStyle flags to see if the style writer
// has enabled menu translucency in the style.
if (appliedStyle && appliedStyle->inherits("KStyle"))
{
allowMenuDropShadow = true;
KStyle* style = dynamic_cast
"
"One or more effects that you have chosen could not be applied because the selected "
"style does not support them; they have therefore been disabled.
"
"
" ).arg( cbStyle->currentText()) );
bool show_warning = false;
// Warn the user if they're applying a style that doesn't support
// menu translucency and they enabled it.
if ( (!allowMenuTransparency) &&
(cbEnableEffects->isChecked()) &&
(comboMenuEffect->currentItem() == 3) ) // Make Translucent
{
warn_string += i18n("Menu translucency is not available.
");
comboMenuEffect->setCurrentItem(0); // Disable menu effect.
show_warning = true;
}
if (!allowMenuDropShadow && cbMenuShadow->isChecked())
{
warn_string += i18n("Menu drop-shadows are not available.");
cbMenuShadow->setChecked(false);
show_warning = true;
}
// Tell the user what features we could not apply on their behalf.
if (show_warning)
KMessageBox::information(this, warn_string);
// Save effects.
KConfig config( "kdeglobals" );
config.setGroup("KDE");
config.writeEntry( "EffectsEnabled", cbEnableEffects->isChecked());
int item = comboComboEffect->currentItem();
config.writeEntry( "EffectAnimateCombo", item == 1 );
item = comboTooltipEffect->currentItem();
config.writeEntry( "EffectAnimateTooltip", item == 1);
config.writeEntry( "EffectFadeTooltip", item == 2 );
item = comboRubberbandEffect->currentItem();
{
QSettings settings; // Only for KStyle stuff
settings.writeEntry("/KStyle/Settings/SemiTransparentRubberband", item == 1);
}
item = comboMenuHandle->currentItem();
config.writeEntry( "InsertTearOffHandle", item );
item = comboMenuEffect->currentItem();
config.writeEntry( "EffectAnimateMenu", item == 1 );
config.writeEntry( "EffectFadeMenu", item == 2 );
// Handle KStyle's menu effects
QString engine("Disabled");
if (item == 3 && cbEnableEffects->isChecked()) // Make Translucent
switch( comboMenuEffectType->currentItem())
{
case 1: engine = "SoftwareBlend"; break;
case 2: engine = "XRender"; break;
default:
case 0: engine = "SoftwareTint"; break;
}
{ // Braces force a QSettings::sync()
QSettings settings; // Only for KStyle stuff
settings.writeEntry("/KStyle/Settings/MenuTransparencyEngine", engine);
settings.writeEntry("/KStyle/Settings/MenuOpacity", slOpacity->value()/100.0);
settings.writeEntry("/KStyle/Settings/MenuDropShadow",
cbEnableEffects->isChecked() && cbMenuShadow->isChecked() );
}
// Misc page
config.writeEntry( "ShowIconsOnPushButtons", cbIconsOnButtons->isChecked(), true, true );
config.writeEntry( "EffectNoTooltip", !cbEnableTooltips->isChecked(), true, true );
config.setGroup("General");
config.writeEntry( "widgetStyle", currentStyle() );
config.setGroup("Toolbar style");
config.writeEntry( "Highlighting", cbHoverButtons->isChecked(), true, true );
config.writeEntry( "TransparentMoving", cbTransparentToolbars->isChecked(), true, true );
QString tbIcon;
switch( comboToolbarIcons->currentItem() )
{
case 1: tbIcon = "TextOnly"; break;
case 2: tbIcon = "IconTextRight"; break;
case 3: tbIcon = "IconTextBottom"; break;
case 0:
default: tbIcon = "IconOnly"; break;
}
config.writeEntry( "IconText", tbIcon, true, true );
config.sync();
// Export the changes we made to qtrc, and update all qt-only
// applications on the fly, ensuring that we still follow the user's
// export fonts/colors settings.
if (m_bStyleDirty | m_bEffectsDirty) // Export only if necessary
{
uint flags = KRdbExportQtSettings;
KConfig kconfig("kcmdisplayrc", true /*readonly*/, false /*no globals*/);
kconfig.setGroup("X11");
bool exportKDEColors = kconfig.readBoolEntry("exportKDEColors", true);
if (exportKDEColors)
flags |= KRdbExportColors;
runRdb( flags );
}
// Now allow KDE apps to reconfigure themselves.
if ( m_bStyleDirty )
KIPC::sendMessageAll(KIPC::StyleChanged);
if ( m_bToolbarsDirty )
// ##### FIXME - Doesn't apply all settings correctly due to bugs in
// KApplication/KToolbar
KIPC::sendMessageAll(KIPC::ToolbarStyleChanged);
if (m_bEffectsDirty) {
KIPC::sendMessageAll(KIPC::SettingsChanged);
kapp->dcopClient()->send("kwin*", "", "reconfigure()", "");
}
//update kicker to re-used tooltips kicker parameter otherwise, it overwritted
//by style tooltips parameters.
QByteArray data;
kapp->dcopClient()->send( "kicker", "kicker", "configure()", data );
// Clean up
m_bEffectsDirty = false;
m_bToolbarsDirty = false;
m_bStyleDirty = false;
emit changed( false );
}
bool KCMStyle::findStyle( const QString& str, int& combobox_item )
{
StyleEntry* se = styleEntries.find(str.lower());
QString name = se ? se->name : str;
combobox_item = 0;
//look up name
for( int i = 0; i < cbStyle->count(); i++ )
{
if ( cbStyle->text(i) == name )
{
combobox_item = i;
return TRUE;
}
}
return FALSE;
}
void KCMStyle::defaults()
{
load( true );
}
void KCMStyle::setEffectsDirty()
{
m_bEffectsDirty = true;
emit changed(true);
}
void KCMStyle::setToolbarsDirty()
{
m_bToolbarsDirty = true;
emit changed(true);
}
void KCMStyle::setStyleDirty()
{
m_bStyleDirty = true;
emit changed(true);
}
// ----------------------------------------------------------------
// All the Style Switching / Preview stuff
// ----------------------------------------------------------------
void KCMStyle::loadStyle( KConfig& config )
{
cbStyle->clear();
// Create a dictionary of WidgetStyle to Name and Desc. mappings,
// as well as the config page info
styleEntries.clear();
styleEntries.setAutoDelete(true);
QString strWidgetStyle;
QStringList list = KGlobal::dirs()->findAllResources("themes", "*.themerc", true, true);
for (QStringList::iterator it = list.begin(); it != list.end(); ++it)
{
KSimpleConfig config( *it, true );
if ( !(config.hasGroup("KDE") && config.hasGroup("Misc")) )
continue;
config.setGroup("KDE");
strWidgetStyle = config.readEntry("WidgetStyle");
if (strWidgetStyle.isNull())
continue;
// We have a widgetstyle, so lets read the i18n entries for it...
StyleEntry* entry = new StyleEntry;
config.setGroup("Misc");
entry->name = config.readEntry("Name");
entry->desc = config.readEntry("Comment", i18n("No description available."));
entry->configPage = config.readEntry("ConfigPage", QString::null);
// Check if this style should be shown
config.setGroup("Desktop Entry");
entry->hidden = config.readBoolEntry("Hidden", false);
// Insert the entry into our dictionary.
styleEntries.insert(strWidgetStyle.lower(), entry);
}
// Obtain all style names
QStringList allStyles = QStyleFactory::keys();
// Get translated names, remove all hidden style entries.
QStringList styles;
StyleEntry* entry;
for (QStringList::iterator it = allStyles.begin(); it != allStyles.end(); it++)
{
QString id = (*it).lower();
// Find the entry.
if ( (entry = styleEntries.find(id)) != 0 )
{
// Do not add hidden entries
if (entry->hidden)
continue;
styles += entry->name;
nameToStyleKey[entry->name] = id;
}
else
{
styles += (*it); //Fall back to the key (but in original case)
nameToStyleKey[*it] = id;
}
}
// Sort the style list, and add it to the combobox
styles.sort();
cbStyle->insertStringList( styles );
// Find out which style is currently being used
config.setGroup( "General" );
QString defaultStyle = KStyle::defaultStyle();
QString cfgStyle = config.readEntry( "widgetStyle", defaultStyle );
// Select the current style
// Do not use cbStyle->listBox() as this may be NULL for some styles when
// they use QPopupMenus for the drop-down list!
// ##### Since Trolltech likes to seemingly copy & paste code,
// QStringList::findItem() doesn't have a Qt::StringComparisonMode field.
// We roll our own (yuck)
cfgStyle = cfgStyle.lower();
int item = 0;
for( int i = 0; i < cbStyle->count(); i++ )
{
QString id = nameToStyleKey[cbStyle->text(i)];
item = i;
if ( id == cfgStyle ) // ExactMatch
break;
else if ( id.contains( cfgStyle ) )
break;
else if ( id.contains( QApplication::style().className() ) )
break;
item = 0;
}
cbStyle->setCurrentItem( item );
m_bStyleDirty = false;
switchStyle( currentStyle() ); // make resets visible
}
QString KCMStyle::currentStyle()
{
return nameToStyleKey[cbStyle->currentText()];
}
void KCMStyle::styleChanged()
{
switchStyle( currentStyle() );
}
void KCMStyle::switchStyle(const QString& styleName, bool force)
{
// Don't flicker the preview if the same style is chosen in the cb
if (!force && appliedStyle && appliedStyle->name() == styleName)
return;
// Create an instance of the new style...
QStyle* style = QStyleFactory::create(styleName);
if (!style)
return;
// Prevent Qt from wrongly caching radio button images
QPixmapCache::clear();
setStyleRecursive( stylePreview, style );
// this flickers, but reliably draws the widgets correctly.
stylePreview->resize( stylePreview->sizeHint() );
delete appliedStyle;
appliedStyle = style;
// Set the correct style description
StyleEntry* entry = styleEntries.find( styleName );
QString desc;
desc = i18n("Description: %1").arg( entry ? entry->desc : i18n("No description available.") );
lblStyleDesc->setText( desc );
}
void KCMStyle::setStyleRecursive(QWidget* w, QStyle* s)
{
// Don't let broken styles kill the palette
// for other styles being previewed. (e.g SGI style)
w->unsetPalette();
QPalette newPalette(KApplication::createApplicationPalette());
s->polish( newPalette );
w->setPalette(newPalette);
// Apply the new style.
w->setStyle(s);
// Recursively update all children.
const QObjectList *children = w->children();
if (!children)
return;
// Apply the style to each child widget.
QPtrListIterator
Icons only: Shows only icons on toolbar buttons. " "Best option for low resolutions.
" "Text only: Shows only text on toolbar buttons.
" "Text alongside icons: Shows icons and text on toolbar buttons. " "Text is aligned alongside the icon.
" "Text under icons: Shows icons and text on toolbar buttons. " "Text is aligned below the icon.") ); QWhatsThis::add( cbIconsOnButtons, i18n( "If you enable this option, KDE Applications will " "show small icons alongside some important buttons.") ); QWhatsThis::add( cbTearOffHandles, i18n( "If you enable this option some pop-up menus will " "show so called tear-off handles. If you click them, you get the menu " "inside a widget. This can be very helpful when performing " "the same action multiple times.") ); } #include "kcmstyle.moc" // vim: set noet ts=4: