summaryrefslogtreecommitdiffstats
path: root/kcontrol/style/kcmstyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/style/kcmstyle.cpp')
-rw-r--r--kcontrol/style/kcmstyle.cpp1070
1 files changed, 1070 insertions, 0 deletions
diff --git a/kcontrol/style/kcmstyle.cpp b/kcontrol/style/kcmstyle.cpp
new file mode 100644
index 000000000..9333c0f72
--- /dev/null
+++ b/kcontrol/style/kcmstyle.cpp
@@ -0,0 +1,1070 @@
+/*
+ * KCMStyle
+ * Copyright (C) 2002 Karol Szwed <gallium@kde.org>
+ * Copyright (C) 2002 Daniel Molkentin <molkentin@kde.org>
+ *
+ * Portions Copyright (C) 2000 TrollTech AS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <qcheckbox.h>
+#include <kcombobox.h>
+#include <qlistbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qslider.h>
+#include <qstylefactory.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qfile.h>
+#include <qsettings.h>
+#include <qobjectlist.h>
+#include <qpixmapcache.h>
+#include <qwhatsthis.h>
+#include <qpushbutton.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kipc.h>
+#include <kaboutdata.h>
+#include <kdialog.h>
+#include <klibloader.h>
+#include <klistview.h>
+#include <kmessagebox.h>
+#include <ksimpleconfig.h>
+#include <kstyle.h>
+#include <kstandarddirs.h>
+
+#include "../krdb/krdb.h"
+
+#include "kcmstyle.h"
+#include "styleconfdialog.h"
+
+#include <X11/Xlib.h>
+// X11 namespace cleanup
+#undef Below
+#undef KeyPress
+#undef KeyRelease
+
+
+/**** DLL Interface for kcontrol ****/
+
+// Plugin Interface
+// Danimo: Why do we use the old interface?!
+extern "C"
+{
+ KDE_EXPORT KCModule *create_style(QWidget *parent, const char*)
+ {
+ KGlobal::locale()->insertCatalogue("kcmstyle");
+ return new KCMStyle(parent, "kcmstyle");
+ }
+
+ KDE_EXPORT void init_style()
+ {
+ uint flags = KRdbExportQtSettings | KRdbExportQtColors | KRdbExportXftSettings;
+ KConfig config("kcmdisplayrc", true /*readonly*/, false /*don't read kdeglobals etc.*/);
+ config.setGroup("X11");
+
+ // This key is written by the "colors" module.
+ bool exportKDEColors = config.readBoolEntry("exportKDEColors", true);
+ if (exportKDEColors)
+ flags |= KRdbExportColors;
+ runRdb( flags );
+
+ // Write some Qt root property.
+#ifndef __osf__ // this crashes under Tru64 randomly -- will fix later
+ QByteArray properties;
+ QDataStream d(properties, IO_WriteOnly);
+ d.setVersion( 3 ); // Qt2 apps need this.
+ d << kapp->palette() << KGlobalSettings::generalFont();
+ Atom a = XInternAtom(qt_xdisplay(), "_QT_DESKTOP_PROPERTIES", false);
+
+ // do it for all root windows - multihead support
+ int screen_count = ScreenCount(qt_xdisplay());
+ for (int i = 0; i < screen_count; i++)
+ XChangeProperty(qt_xdisplay(), RootWindow(qt_xdisplay(), i),
+ a, a, 8, PropModeReplace,
+ (unsigned char*) properties.data(), properties.size());
+#endif
+ }
+}
+
+/*
+typedef KGenericFactory<KWidgetSettingsModule, QWidget> GeneralFactory;
+K_EXPORT_COMPONENT_FACTORY( kcm_kcmstyle, GeneralFactory )
+*/
+
+
+KCMStyle::KCMStyle( QWidget* parent, const char* name )
+ : KCModule( parent, name ), appliedStyle(NULL)
+{
+ setQuickHelp( i18n("<h1>Style</h1>"
+ "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 );
+
+ 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, 2, 0 );
+ containerLayout->addWidget( comboMenuEffect, 2, 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, 3, 0 );
+ containerLayout->addWidget( comboMenuHandle, 3, 1 );
+
+ cbMenuShadow = new QCheckBox( i18n("Menu &drop shadow"), containerFrame );
+ containerLayout->addWidget( cbMenuShadow, 4, 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( 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<KStyle*>(appliedStyle);
+ if (style) {
+ KStyle::KStyleFlags flags = style->styleFlags();
+ if (flags & KStyle::AllowMenuTransparency)
+ allowMenuTransparency = true;
+ }
+ }
+
+ QString warn_string( i18n("<qt>Selected style: <b>%1</b><br><br>"
+ "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.<br>"
+ "<br>" ).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.<br>");
+ 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 = 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<QObject> childit(*children);
+ QObject *child;
+ while ((child = childit.current()) != 0)
+ {
+ ++childit;
+ if (child->isWidgetType())
+ setStyleRecursive((QWidget *) child, s);
+ }
+}
+
+
+// ----------------------------------------------------------------
+// All the Effects stuff
+// ----------------------------------------------------------------
+
+void KCMStyle::loadEffects( KConfig& config )
+{
+ // Load effects.
+ config.setGroup("KDE");
+
+ cbEnableEffects->setChecked( config.readBoolEntry( "EffectsEnabled", false) );
+
+ if ( config.readBoolEntry( "EffectAnimateCombo", false) )
+ comboComboEffect->setCurrentItem( 1 );
+ else
+ comboComboEffect->setCurrentItem( 0 );
+
+ if ( config.readBoolEntry( "EffectAnimateTooltip", false) )
+ comboTooltipEffect->setCurrentItem( 1 );
+ else if ( config.readBoolEntry( "EffectFadeTooltip", false) )
+ comboTooltipEffect->setCurrentItem( 2 );
+ else
+ comboTooltipEffect->setCurrentItem( 0 );
+
+ if ( config.readBoolEntry( "EffectAnimateMenu", false) )
+ comboMenuEffect->setCurrentItem( 1 );
+ else if ( config.readBoolEntry( "EffectFadeMenu", false) )
+ comboMenuEffect->setCurrentItem( 2 );
+ else
+ comboMenuEffect->setCurrentItem( 0 );
+
+ comboMenuHandle->setCurrentItem(config.readNumEntry("InsertTearOffHandle", 0));
+
+ // KStyle Menu transparency and drop-shadow options...
+ QSettings settings;
+ QString effectEngine = settings.readEntry("/KStyle/Settings/MenuTransparencyEngine", "Disabled");
+
+#ifdef HAVE_XRENDER
+ if (effectEngine == "XRender") {
+ comboMenuEffectType->setCurrentItem(2);
+ comboMenuEffect->setCurrentItem(3);
+ } else if (effectEngine == "SoftwareBlend") {
+ comboMenuEffectType->setCurrentItem(1);
+ comboMenuEffect->setCurrentItem(3);
+#else
+ if (effectEngine == "XRender" || effectEngine == "SoftwareBlend") {
+ comboMenuEffectType->setCurrentItem(1); // Software Blend
+ comboMenuEffect->setCurrentItem(3);
+#endif
+ } else if (effectEngine == "SoftwareTint") {
+ comboMenuEffectType->setCurrentItem(0);
+ comboMenuEffect->setCurrentItem(3);
+ } else
+ comboMenuEffectType->setCurrentItem(0);
+
+ if (comboMenuEffect->currentItem() != 3) // If not translucency...
+ menuPreview->setPreviewMode( MenuPreview::Tint );
+ else if (comboMenuEffectType->currentItem() == 0)
+ menuPreview->setPreviewMode( MenuPreview::Tint );
+ else
+ menuPreview->setPreviewMode( MenuPreview::Blend );
+
+ slOpacity->setValue( (int)(100 * settings.readDoubleEntry("/KStyle/Settings/MenuOpacity", 0.90)) );
+
+ // Menu Drop-shadows...
+ cbMenuShadow->setChecked( settings.readBoolEntry("/KStyle/Settings/MenuDropShadow", false) );
+
+ if (cbEnableEffects->isChecked()) {
+ containerFrame->setEnabled( true );
+ menuContainer->setEnabled( comboMenuEffect->currentItem() == 3 );
+ } else {
+ menuContainer->setEnabled( false );
+ containerFrame->setEnabled( false );
+ }
+
+ m_bEffectsDirty = false;
+}
+
+
+void KCMStyle::menuEffectTypeChanged()
+{
+ MenuPreview::PreviewMode mode;
+
+ if (comboMenuEffect->currentItem() != 3)
+ mode = MenuPreview::Tint;
+ else if (comboMenuEffectType->currentItem() == 0)
+ mode = MenuPreview::Tint;
+ else
+ mode = MenuPreview::Blend;
+
+ menuPreview->setPreviewMode(mode);
+
+ m_bEffectsDirty = true;
+}
+
+
+void KCMStyle::menuEffectChanged()
+{
+ menuEffectChanged( cbEnableEffects->isChecked() );
+ m_bEffectsDirty = true;
+}
+
+
+void KCMStyle::menuEffectChanged( bool enabled )
+{
+ if (enabled &&
+ comboMenuEffect->currentItem() == 3) {
+ menuContainer->setEnabled(true);
+ } else
+ menuContainer->setEnabled(false);
+ m_bEffectsDirty = true;
+}
+
+
+// ----------------------------------------------------------------
+// All the Miscellaneous stuff
+// ----------------------------------------------------------------
+
+void KCMStyle::loadMisc( KConfig& config )
+{
+ // KDE's Part via KConfig
+ config.setGroup("Toolbar style");
+ cbHoverButtons->setChecked(config.readBoolEntry("Highlighting", true));
+ cbTransparentToolbars->setChecked(config.readBoolEntry("TransparentMoving", true));
+
+ QString tbIcon = config.readEntry("IconText", "IconOnly");
+ if (tbIcon == "TextOnly")
+ comboToolbarIcons->setCurrentItem(1);
+ else if (tbIcon == "IconTextRight")
+ comboToolbarIcons->setCurrentItem(2);
+ else if (tbIcon == "IconTextBottom")
+ comboToolbarIcons->setCurrentItem(3);
+ else
+ comboToolbarIcons->setCurrentItem(0);
+
+ config.setGroup("KDE");
+ cbIconsOnButtons->setChecked(config.readBoolEntry("ShowIconsOnPushButtons", false));
+ cbEnableTooltips->setChecked(!config.readBoolEntry("EffectNoTooltip", false));
+ cbTearOffHandles->setChecked(config.readBoolEntry("InsertTearOffHandle", false));
+
+ m_bToolbarsDirty = false;
+}
+
+void KCMStyle::addWhatsThis()
+{
+ // Page1
+ QWhatsThis::add( cbStyle, i18n("Here you can choose from a list of"
+ " predefined widget styles (e.g. the way buttons are drawn) which"
+ " may or may not be combined with a theme (additional information"
+ " like a marble texture or a gradient).") );
+ QWhatsThis::add( stylePreview, i18n("This area shows a preview of the currently selected style "
+ "without having to apply it to the whole desktop.") );
+
+ // Page2
+ QWhatsThis::add( page2, i18n("This page allows you to enable various widget style effects. "
+ "For best performance, it is advisable to disable all effects.") );
+ QWhatsThis::add( cbEnableEffects, i18n( "If you check this box, you can select several effects "
+ "for different widgets like combo boxes, menus or tooltips.") );
+ QWhatsThis::add( comboComboEffect, i18n( "<p><b>Disable: </b>do not use any combo box effects.</p>\n"
+ "<b>Animate: </b>Do some animation.") );
+ QWhatsThis::add( comboTooltipEffect, i18n( "<p><b>Disable: </b>do not use any tooltip effects.</p>\n"
+ "<p><b>Animate: </b>Do some animation.</p>\n"
+ "<b>Fade: </b>Fade in tooltips using alpha-blending.") );
+ QWhatsThis::add( comboMenuEffect, i18n( "<p><b>Disable: </b>do not use any menu effects.</p>\n"
+ "<p><b>Animate: </b>Do some animation.</p>\n"
+ "<p><b>Fade: </b>Fade in menus using alpha-blending.</p>\n"
+ "<b>Make Translucent: </b>Alpha-blend menus for a see-through effect. (KDE styles only)") );
+ QWhatsThis::add( cbMenuShadow, i18n( "When enabled, all popup menus will have a drop-shadow, otherwise "
+ "drop-shadows will not be displayed. At present, only KDE styles can have this "
+ "effect enabled.") );
+ QWhatsThis::add( comboMenuEffectType, i18n( "<p><b>Software Tint: </b>Alpha-blend using a flat color.</p>\n"
+ "<p><b>Software Blend: </b>Alpha-blend using an image.</p>\n"
+ "<b>XRender Blend: </b>Use the XFree RENDER extension for image blending (if available). "
+ "This method may be slower than the Software routines on non-accelerated displays, "
+ "but may however improve performance on remote displays.</p>\n") );
+ QWhatsThis::add( slOpacity, i18n("By adjusting this slider you can control the menu effect opacity.") );
+
+ // Page3
+ QWhatsThis::add( page3, i18n("<b>Note:</b> that all widgets in this combobox "
+ "do not apply to Qt-only applications.") );
+ QWhatsThis::add( cbHoverButtons, i18n("If this option is selected, toolbar buttons will change "
+ "their color when the mouse cursor is moved over them." ) );
+ QWhatsThis::add( cbTransparentToolbars, i18n("If you check this box, the toolbars will be "
+ "transparent when moving them around.") );
+ QWhatsThis::add( cbEnableTooltips, i18n( "If you check this option, the KDE application "
+ "will offer tooltips when the cursor remains over items in the toolbar." ) );
+ QWhatsThis::add( comboToolbarIcons, i18n( "<p><b>Icons only:</b> Shows only icons on toolbar buttons. "
+ "Best option for low resolutions.</p>"
+ "<p><b>Text only: </b>Shows only text on toolbar buttons.</p>"
+ "<p><b>Text alongside icons: </b> Shows icons and text on toolbar buttons. "
+ "Text is aligned alongside the icon.</p>"
+ "<b>Text under icons: </b> 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: