[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: User-provided stylesheet (patch; KdeUiProxyStyle problem)
From: David Faure <faure () kde ! org>
Date: 2008-01-28 14:48:24
Message-ID: 200801281548.24686.faure () kde ! org
[Download RAW message or body]
During the KDE4 release-party/conference in Toulouse, Aurélien Gateau was demo'ing
the use of CSS stylesheets in Qt, and someone asked whether it was possible for a
user to set a global stylesheet to be used by all KDE applications.
This seems like a very good idea indeed, for easy-to-write widget "themes",
and for accessibility purposes as well.
During the next talk and afterwards I hacked it up and it works sort of fine...
(good enough for a demo a few hours later, to make the audience go "wow" ;)
The patch adds the GUI (KUrlRequester) for a user-specified stylesheet in `kcmshell4 \
style`, the KGlobalSettings code for using it, including honouring the --stylesheet \
argument so that this one has priority over the kde-global stylesheet [you can ignore \
the kcmdlineargs.cpp patch for trunk, which already has that line]. The apply button \
propagates the setting to all running kde applications, much like when changing \
widget styles.
There are 3 problems with this feature though.
The main problem is that any code using a proxy style like KdeUiProxyStyle \
(KLineEdit) and KonqProxyStyle (konqueror) crashes due to infinite recursion, the \
proxy style calls the real style, which is in fact the stylesheet-style, which calls \
the "base" style which is the kdeuiproxystyle, etc. I don't have a solution for this; \
this mail is about getting the other patches out in the open in case someone's \
interested, and for when the proxy-style issue is fixed :)
Another problem is that stylesheets usually refer to images, which are found in the \
"current working directory", but that solution doesn't work for applications with \
random working directories. It seems to me that we need a setStyleSheetDirectory() in \
QApplication and QWidget? Or what do I miss?
This feature triggers another bug: konsole switches to a proportional font when \
pressing the apply button in kcmshell4 style; this is again because of Qt's wrong \
logic of "when you use a stylesheet, the widget font is completely ignored", which \
still makes no sense to me even though it's documented that way. This is the same \
problem as the one which made use switch to a proxy style for klineedit iirc, is \
supposed to be fixed by Qt-4.4?
--
David Faure, faure@kde.org, sponsored by Trolltech to work on KDE,
Konqueror (http://www.konqueror.org), and KOffice (http://www.koffice.org).
["kdebase_kcmstyle.diff" (text/x-diff)]
Index: kcmstyle.h
===================================================================
--- kcmstyle.h (revision 767259)
+++ kcmstyle.h (working copy)
@@ -37,6 +37,7 @@
#include "menupreview.h"
+class KUrlRequester;
class KComboBox;
class KConfig;
class QCheckBox;
@@ -88,6 +89,7 @@ protected Q_SLOTS:
void setStyleDirty();
void styleChanged();
+ void styleSheetChanged();
void menuEffectChanged( bool enabled );
void menuEffectChanged();
void menuEffectTypeChanged();
@@ -149,6 +151,7 @@ private:
QCheckBox* cbHoverButtons;
QCheckBox* cbTransparentToolbars;
QCheckBox* cbEnableTooltips;
+ KUrlRequester* styleSheetRequester;
QComboBox* comboToolbarIcons;
QCheckBox* cbIconsOnButtons;
Index: kcmstyle.cpp
===================================================================
--- kcmstyle.cpp (revision 767259)
+++ kcmstyle.cpp (working copy)
@@ -22,6 +22,8 @@
*/
#include "kcmstyle.h"
+#include <kdebug.h>
+#include <kurlrequester.h>
#include <config-X11.h>
@@ -216,6 +218,15 @@ KCMStyle::KCMStyle( QWidget* parent, con
gbWidgetStyleLayout->addWidget( cbTearOffHandles );
cbTearOffHandles->hide(); // reenable when the corresponding Qt method is virtual \
and properly reimplemented
+ QHBoxLayout* styleSheetHBox = new QHBoxLayout();
+ gbWidgetStyleLayout->addLayout(styleSheetHBox);
+ QLabel* styleSheetLabel = new QLabel(i18n("Stylesheet"), gbWidgetStyle);
+ styleSheetHBox->addWidget(styleSheetLabel);
+ styleSheetRequester = new KUrlRequester( gbWidgetStyle );
+ styleSheetRequester->setMode(KFile::File | KFile::ExistingOnly | \
KFile::LocalOnly); + styleSheetHBox->addWidget(styleSheetRequester);
+ connect( styleSheetRequester, SIGNAL(textChanged(QString)), this, \
SLOT(styleSheetChanged())); +
QGroupBox *gbPreview = new QGroupBox( i18n( "Preview" ), page1 );
QVBoxLayout *previewLayout = new QVBoxLayout(gbPreview);
previewLayout->setMargin( 0 );
@@ -400,6 +411,7 @@ KCMStyle::KCMStyle( QWidget* parent, con
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( \
styleSheetRequester, SIGNAL(textChanged(QString)), this, SLOT(setStyleDirty())); \
connect( cbIconsOnButtons, SIGNAL(toggled(bool)), this, \
SLOT(setEffectsDirty())); connect( cbTearOffHandles, SIGNAL(toggled(bool)), \
this, SLOT(setEffectsDirty())); connect( comboToolbarIcons, \
SIGNAL(activated(int)), this, SLOT(setToolbarsDirty())); @@ -618,6 +630,7 @@ void \
KCMStyle::save()
KConfigGroup generalGroup(&_config, "General");
generalGroup.writeEntry("widgetStyle", currentStyle());
+ generalGroup.writeEntry("styleSheet", styleSheetRequester->url().path());
KConfigGroup toolbarStyleGroup(&_config, "Toolbar style");
toolbarStyleGroup.writeEntry("Highlighting", cbHoverButtons->isChecked(), \
KConfig::Normal|KConfig::Global); @@ -732,6 +745,7 @@ void KCMStyle::defaults()
cbHoverButtons->setChecked(true);
cbTransparentToolbars->setChecked(true);
cbEnableTooltips->setChecked(true);
+ styleSheetRequester->clear();
comboToolbarIcons->setCurrentIndex(0);
cbIconsOnButtons->setChecked(true);
cbTearOffHandles->setChecked(false);
@@ -861,6 +875,8 @@ void KCMStyle::loadStyle( KConfig& confi
m_bStyleDirty = false;
switchStyle( currentStyle() ); // make resets visible
+
+ styleSheetRequester->setPath(configGroup.readEntry("styleSheet"));
}
QString KCMStyle::currentStyle()
@@ -874,6 +890,26 @@ void KCMStyle::styleChanged()
switchStyle( currentStyle() );
}
+void KCMStyle::styleSheetChanged()
+{
+ QString styleSheet = styleSheetRequester->url().path();
+ kDebug() << styleSheet;
+ QByteArray styleSheetData;
+ if (!styleSheet.isEmpty()) {
+ QFile file(styleSheet);
+ if (file.open(QIODevice::ReadOnly)) {
+ styleSheetData = file.readAll();
+ }
+ }
+ if (!styleSheetData.isEmpty()) {
+ // TODO There should be a setStyleSheetDirectory....
+ stylePreview->setStyleSheet(QString::fromUtf8(styleSheetData));
+ } else {
+ stylePreview->setStyleSheet(QString());
+ // Also reset application stylesheet otherwise (if there was one), we can \
see no changes + qApp->setStyleSheet(QString());
+ }
+}
void KCMStyle::switchStyle(const QString& styleName, bool force)
{
@@ -1004,11 +1040,11 @@ void KCMStyle::loadEffects( KConfig& con
}
m_bEffectsDirty = false;
-}
+ }
-void KCMStyle::menuEffectTypeChanged()
-{
+ void KCMStyle::menuEffectTypeChanged()
+ {
MenuPreview::PreviewMode mode;
if (comboMenuEffect->currentIndex() != 3)
@@ -1021,33 +1057,33 @@ void KCMStyle::menuEffectTypeChanged()
menuPreview->setPreviewMode(mode);
m_bEffectsDirty = true;
-}
+ }
-void KCMStyle::menuEffectChanged()
-{
+ void KCMStyle::menuEffectChanged()
+ {
menuEffectChanged( cbEnableEffects->isChecked() );
m_bEffectsDirty = true;
-}
+ }
-void KCMStyle::menuEffectChanged( bool enabled )
-{
+ void KCMStyle::menuEffectChanged( bool enabled )
+ {
if (enabled &&
comboMenuEffect->currentIndex() == 3) {
menuContainer->setEnabled(true);
} else
menuContainer->setEnabled(false);
m_bEffectsDirty = true;
-}
+ }
// ----------------------------------------------------------------
// All the Miscellaneous stuff
// ----------------------------------------------------------------
-void KCMStyle::loadMisc( KConfig& config )
-{
+ void KCMStyle::loadMisc( KConfig& config )
+ {
// KDE's Part via KConfig
KConfigGroup configGroup = config.group("Toolbar style");
cbHoverButtons->setChecked(configGroup.readEntry("Highlighting", true));
@@ -1069,10 +1105,10 @@ void KCMStyle::loadMisc( KConfig& config
cbTearOffHandles->setChecked(configGroup.readEntry("InsertTearOffHandle", false));
m_bToolbarsDirty = false;
-}
+ }
-void KCMStyle::addWhatsThis()
-{
+ void KCMStyle::addWhatsThis()
+ {
// Page1
cbStyle->setWhatsThis( i18n("Here you can choose from a list of"
" predefined widget styles (e.g. the way buttons are drawn) which"
@@ -1127,8 +1163,9 @@ void KCMStyle::addWhatsThis()
"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:
+
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt (revision 767259)
+++ CMakeLists.txt (working copy)
@@ -12,7 +12,7 @@ kde4_add_ui_files(kcm_style_PART_SRCS st
kde4_add_plugin(kcm_style ${kcm_style_PART_SRCS})
-target_link_libraries(kcm_style ${KDE4_KDEUI_LIBS} ${BLITZ_LIBRARIES})
+target_link_libraries(kcm_style ${KDE4_KIO_LIBS} ${BLITZ_LIBRARIES})
install(TARGETS kcm_style DESTINATION ${PLUGIN_INSTALL_DIR})
["kdelibs_global_stylesheet.diff" (text/x-diff)]
Index: kdecore/kernel/kcmdlineargs.cpp
===================================================================
--- kdecore/kernel/kcmdlineargs.cpp (revision 767562)
+++ kdecore/kernel/kcmdlineargs.cpp (working copy)
@@ -298,6 +298,7 @@ KCmdLineArgsStatic::KCmdLineArgsStatic (
qt_options.add("qws", ki18n("forces the application to run as QWS Server"));
#endif
qt_options.add("reverse", ki18n("mirrors the whole layout of widgets"));
+ qt_options.add("stylesheet <file>", ki18n("sets the application stylesheet"));
// KDE options
kde_options.add("caption <caption>", ki18n("Use 'caption' as name in the titlebar"));
Index: kdeui/kernel/kapplication.cpp
===================================================================
--- kdeui/kernel/kapplication.cpp (revision 767562)
+++ kdeui/kernel/kapplication.cpp (working copy)
@@ -832,6 +832,12 @@ void KApplicationPrivate::parseCommandLi
}
#endif
+ KCmdLineArgs *qtArgs = KCmdLineArgs::parsedArgs("qt");
+ if (qtArgs && qtArgs->isSet("stylesheet")) {
+ extern QString kde_overrideStyleSheet; // see KGlobalSettings. Should we have a static setter?
+ kde_overrideStyleSheet = qtArgs->getOption("stylesheet");
+ }
+
if ( q->type() != KApplication::Tty ) {
if (args && args->isSet("icon"))
{
Index: kdeui/kernel/kglobalsettings.cpp
===================================================================
--- kdeui/kernel/kglobalsettings.cpp (revision 767562)
+++ kdeui/kernel/kglobalsettings.cpp (working copy)
@@ -822,9 +822,9 @@ void KGlobalSettings::Private::_k_slotNo
}
}
-// Set by KApplication - which is now in kdeui so this needs to be exported
-// In the long run, KGlobalSettings probably belongs to kdeui as well...
+// Set by KApplication
QString kde_overrideStyle;
+QString kde_overrideStyleSheet;
void KGlobalSettings::Private::applyGUIStyle()
{
@@ -848,11 +848,24 @@ void KGlobalSettings::Private::applyGUIS
if ( !sp && styleStr != defaultStyle)
sp = QStyleFactory::create( defaultStyle );
if ( !sp )
- sp = QStyleFactory::create( *(QStyleFactory::keys().begin()) );
+ sp = QStyleFactory::create(QStyleFactory::keys().first());
qApp->setStyle(sp);
}
else
qApp->setStyle(kde_overrideStyle);
+
+ QString styleSheet = pConfig.readEntry("styleSheet", QString());
+ if (!styleSheet.isEmpty() && kde_overrideStyleSheet.isEmpty()) {
+ QFile file(styleSheet);
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray data = file.readAll();
+ if (!data.isEmpty()) {
+ // TODO There should be a setStyleSheetDirectory....
+ qApp->setStyleSheet(QString::fromUtf8(data));
+ }
+ }
+ }
+
// Reread palette from config file.
kdisplaySetPalette();
}
Index: kdeui/widgets/klineedit.cpp
===================================================================
--- kdeui/widgets/klineedit.cpp (revision 767562)
+++ kdeui/widgets/klineedit.cpp (working copy)
@@ -192,9 +192,10 @@ void KLineEdit::init()
if ( !d->previousHighlightColor.isValid() )
d->previousHighlightColor=p.color(QPalette::Normal,QPalette::Highlight);
- QStyle *lineEditStyle = new KLineEditStyle(this);
- lineEditStyle->setParent(this);
- setStyle(lineEditStyle);
+ // TODO fix recursion
+ //QStyle *lineEditStyle = new KLineEditStyle(this);
+ //lineEditStyle->setParent(this);
+ //setStyle(lineEditStyle);
}
QString KLineEdit::clickMessage() const
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic