allow SVGs to use systemcolors

svn path=/trunk/KDE/kdelibs/; revision=1181642
This commit is contained in:
Manuel Mommertz 2010-10-01 16:04:34 +00:00
parent 37c3cf4d1c
commit 1d82f58e41
3 changed files with 153 additions and 36 deletions

101
svg.cpp
View File

@ -22,6 +22,7 @@
#include <cmath>
#include <QDir>
#include <QDomDocument>
#include <QMatrix>
#include <QPainter>
#include <QSharedData>
@ -31,6 +32,7 @@
#include <kcolorscheme.h>
#include <kconfiggroup.h>
#include <kdebug.h>
#include <kfilterdev.h>
#include <kiconeffect.h>
#include <kglobalsettings.h>
#include <ksharedptr.h>
@ -51,30 +53,76 @@ class SharedSvgRenderer : public QSvgRenderer, public QSharedData
: QSvgRenderer(parent)
{}
SharedSvgRenderer(const QString &filename, QObject *parent = 0)
: QSvgRenderer(filename, parent)
{}
SharedSvgRenderer(const QString &filename, const QString &styleSheet, QObject *parent = 0);
SharedSvgRenderer(const QByteArray &contents, QObject *parent = 0)
: QSvgRenderer(contents, parent)
{}
SharedSvgRenderer(const QByteArray &contents, const QString &styleSheet, QObject *parent = 0);
~SharedSvgRenderer()
{
//kDebug() << "leaving this world for a better one.";
}
private:
bool load(const QByteArray &contents, const QString &styleSheet);
};
SharedSvgRenderer::SharedSvgRenderer(const QString &filename, const QString &styleSheet, QObject *parent)
: QSvgRenderer(parent)
{
QIODevice *file = KFilterDev::deviceForFile(filename, "application/x-gzip");
if (!file->open(QIODevice::ReadOnly)) {
delete file;
return;
}
load(file->readAll(), styleSheet);
delete file;
}
SharedSvgRenderer::SharedSvgRenderer(const QByteArray &contents, const QString &styleSheet, QObject *parent)
: QSvgRenderer(parent)
{
load(contents, styleSheet);
}
bool SharedSvgRenderer::load(const QByteArray &contents, const QString &styleSheet)
{
if (styleSheet.isEmpty() || ! contents.contains("current-color-scheme")) {
return QSvgRenderer::load(contents);
}
QDomDocument svg;
if (!svg.setContent(contents)) {
return false;
}
QDomNode defs = svg.elementsByTagName("defs").item(0);
for (QDomElement style = defs.firstChildElement("style"); !style.isNull();
style = style.nextSiblingElement("style")) {
if (style.attribute("id") != "current-color-scheme") {
continue;
}
QDomElement colorScheme = svg.createElement("style");
colorScheme.setAttribute("type", "text/css");
colorScheme.setAttribute("id", "current-color-scheme");
defs.replaceChild(colorScheme, style);
colorScheme.appendChild(svg.createCDATASection(styleSheet));
break;
}
return QSvgRenderer::load(svg.toByteArray(-1));
}
class SvgPrivate
{
public:
SvgPrivate(Svg *svg)
: q(svg),
renderer(0),
styleCrc(0),
lastModified(0),
multipleImages(false),
themed(false),
applyColors(false),
usesColors(false),
cacheRendering(true),
themeFailed(false)
{
@ -145,8 +193,8 @@ class SvgPrivate
QObject::disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
q, SLOT(colorsChanged()));
checkApplyColorHint();
if (applyColors && !actualTheme()->colorScheme()) {
checkColorHints();
if (usesColors && !actualTheme()->colorScheme()) {
QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
q, SLOT(colorsChanged()));
}
@ -291,7 +339,10 @@ class SvgPrivate
//kDebug() << "FAIL! **************************";
//kDebug() << path << "**";
QHash<QString, SharedSvgRenderer::Ptr>::const_iterator it = s_renderers.constFind(path);
QByteArray styleSheet = actualTheme()->styleSheet("SVG").toUtf8();
styleCrc = qChecksum(styleSheet, styleSheet.size());
QHash<QString, SharedSvgRenderer::Ptr>::const_iterator it = s_renderers.constFind(styleCrc + path);
if (it != s_renderers.constEnd()) {
//kDebug() << "gots us an existing one!";
@ -300,10 +351,10 @@ class SvgPrivate
if (path.isEmpty()) {
renderer = new SharedSvgRenderer();
} else {
renderer = new SharedSvgRenderer(path);
renderer = new SharedSvgRenderer(path, actualTheme()->styleSheet("SVG"));
}
s_renderers[path] = renderer;
s_renderers[styleCrc + path] = renderer;
}
if (size == QSizeF()) {
@ -315,7 +366,7 @@ class SvgPrivate
{
if (renderer && renderer.count() == 2) {
// this and the cache reference it
s_renderers.erase(s_renderers.find(path));
s_renderers.erase(s_renderers.find(styleCrc + path));
if (theme) {
theme.data()->releaseRectsCache(path);
@ -323,6 +374,7 @@ class SvgPrivate
}
renderer = 0;
styleCrc = 0;
localRectCache.clear();
}
@ -380,9 +432,18 @@ class SvgPrivate
return renderer->matrixForElement(elementId);
}
void checkApplyColorHint()
void checkColorHints()
{
applyColors = elementRect("hint-apply-color-scheme").isValid();
if (elementRect("hint-apply-color-scheme").isValid()) {
applyColors = true;
usesColors = true;
} else if (elementRect("current-color-scheme").isValid()) {
applyColors = false;
usesColors = true;
} else {
applyColors = false;
usesColors = false;
}
}
//Folowing two are utility functions to snap rendered elements to the pixel grid
@ -439,10 +500,10 @@ class SvgPrivate
void themeChanged()
{
// check if new theme svg wants colorscheme applied
bool wasApplyColors = applyColors;
checkApplyColorHint();
if (applyColors && actualTheme()->colorScheme()) {
if (!wasApplyColors) {
bool wasUsesColors = usesColors;
checkColorHints();
if (usesColors && actualTheme()->colorScheme()) {
if (!wasUsesColors) {
QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
q, SLOT(colorsChanged()));
}
@ -466,7 +527,7 @@ class SvgPrivate
void colorsChanged()
{
if (!applyColors) {
if (!usesColors) {
return;
}
@ -485,10 +546,12 @@ class SvgPrivate
QString path;
QSizeF size;
QSizeF naturalSize;
QChar styleCrc;
unsigned int lastModified;
bool multipleImages : 1;
bool themed : 1;
bool applyColors : 1;
bool usesColors : 1;
bool cacheRendering : 1;
bool themeFailed : 1;
};

View File

@ -56,6 +56,11 @@ namespace Plasma
static const int DEFAULT_WALLPAPER_WIDTH = 1920;
static const int DEFAULT_WALLPAPER_HEIGHT = 1200;
enum styles {
DEFAULTSTYLE,
SVGSTYLE
};
class ThemePrivate
{
public:
@ -162,6 +167,7 @@ public:
QHash<QString, QString> keysToCache;
QHash<QString, QString> idsToCache;
QHash<QString, QString> animationMapping;
QHash<styles, QString> cachedStyleSheets;
QTimer *saveTimer;
#ifdef Q_WS_X11
@ -247,6 +253,7 @@ void ThemePrivate::discardCache(const QString &oldThemeName, bool keepSvgElement
pixmapCache = 0;
KSharedDataCache::deleteCache("plasma_theme_" + oldThemeName);
}
cachedStyleSheets.clear();
invalidElements.clear();
pixmapsToCache.clear();
saveTimer->stop();
@ -291,17 +298,43 @@ const QString ThemePrivate::processStyleSheet(const QString &css)
{
QString stylesheet;
if (css.isEmpty()) {
stylesheet = QString("\n\
body {\n\
color: %textcolor;\n\
font-size: %fontsize;\n\
font-family: %fontfamily;\n\
}\n\
a:active { color: %activatedlink; }\n\
a:link { color: %link; }\n\
a:visited { color: %visitedlink; }\n\
a:hover { color: %hoveredlink; text-decoration: none; }\n\
");
stylesheet = cachedStyleSheets[DEFAULTSTYLE];
if(stylesheet.isEmpty()) {
stylesheet = QString("\n\
body {\n\
color: %textcolor;\n\
font-size: %fontsize;\n\
font-family: %fontfamily;\n\
}\n\
a:active { color: %activatedlink; }\n\
a:link { color: %link; }\n\
a:visited { color: %visitedlink; }\n\
a:hover { color: %hoveredlink; text-decoration: none; }\n\
");
stylesheet = processStyleSheet(stylesheet);
}
cachedStyleSheets[DEFAULTSTYLE] = stylesheet;
return stylesheet;
} else if(css == "SVG") {
stylesheet = cachedStyleSheets[SVGSTYLE];
if(stylesheet.isEmpty()) {
QString skel = ".ColorScheme-%1{color:%2;}";
stylesheet += skel.arg("Text","%textcolor");
stylesheet += skel.arg("Background","%backgroundcolor");
stylesheet += skel.arg("ButtonText","%buttontextcolor");
stylesheet += skel.arg("ButtonBackground","%buttonbackgroundcolor");
stylesheet += skel.arg("ButtonHover","%buttonhovercolor");
stylesheet += skel.arg("ButtonFocus","%buttonfocuscolor");
stylesheet += skel.arg("ViewText","%viewtextcolor");
stylesheet += skel.arg("ViewBackground","%viewbackgroundcolor");
stylesheet = processStyleSheet(stylesheet);
}
cachedStyleSheets[SVGSTYLE] = stylesheet;
return stylesheet;
} else {
stylesheet = css;
}
@ -319,8 +352,18 @@ const QString ThemePrivate::processStyleSheet(const QString &css)
elements["%hoveredlink"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::HighlightColor).name();
elements["%link"] = Plasma::Theme::defaultTheme()->color(Plasma::Theme::LinkColor).name();
elements["%buttontextcolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonTextColor).name();
elements["%buttonbackgroundcolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonBackgroundColor).name();
elements["%buttonhovercolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonHoverColor).name();
elements["%buttonfocuscolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ButtonFocusColor).name();
elements["%viewtextcolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewTextColor).name();
elements["%viewbackgroundcolor"] =
Plasma::Theme::defaultTheme()->color(Plasma::Theme::ViewBackgroundColor).name();
elements["%smallfontsize"] =
QString("%1pt").arg(KGlobalSettings::smallestReadableFont().pointSize());
@ -726,23 +769,30 @@ QColor Theme::color(ColorRole role) const
switch (role) {
case TextColor:
return d->colorScheme.foreground(KColorScheme::NormalText).color();
break;
case HighlightColor:
return d->colorScheme.decoration(KColorScheme::HoverColor).color();
break;
case BackgroundColor:
return d->colorScheme.background(KColorScheme::NormalBackground).color();
break;
case ButtonTextColor:
return d->buttonColorScheme.foreground(KColorScheme::NormalText).color();
break;
case ButtonBackgroundColor:
return d->buttonColorScheme.background(KColorScheme::NormalBackground).color();
break;
case ButtonHoverColor:
return d->buttonColorScheme.decoration(KColorScheme::HoverColor).color();
case ButtonFocusColor:
return d->buttonColorScheme.decoration(KColorScheme::FocusColor).color();
case ViewTextColor:
return d->viewColorScheme.foreground(KColorScheme::NormalText).color();
case ViewBackgroundColor:
return d->viewColorScheme.background(KColorScheme::NormalBackground).color();
case LinkColor:
return d->viewColorScheme.foreground(KColorScheme::LinkText).color();

View File

@ -67,7 +67,11 @@ class PLASMA_EXPORT Theme : public QObject
ButtonTextColor = 4, /** text color for buttons */
ButtonBackgroundColor = 8, /** background color for buttons*/
LinkColor = 16, /** color for clickable links */
VisitedLinkColor = 32 /** color visited clickable links */
VisitedLinkColor = 32, /** color visited clickable links */
ButtonHoverColor = 64, /** color for hover effect on buttons */
ButtonFocusColor = 128, /** color for focus effect on buttons */
ViewTextColor = 256, /** text color for views */
ViewBackgroundColor = 512 /** background color for views */
};
enum FontRole {