2 * Copyright 2006-2007 Aaron Seigo <aseigo@kde.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <QApplication>
26 #include <KWindowSystem>
27 #include <KColorScheme>
28 #include <KConfigGroup>
30 #include <KSelectionWatcher>
31 #include <KSharedConfig>
32 #include <KStandardDirs>
33 #include <KGlobalSettings>
35 #include "plasma/packages_p.h"
45 compositingActive(KWindowSystem::compositingActive())
47 generalFont
= QApplication::font();
52 QString groupName
= "Theme";
53 if (!app
.isEmpty() && app
!= "plasma") {
54 groupName
.append("-").append(app
);
57 KSharedConfigPtr config
= KSharedConfig::openConfig("plasmarc");
58 return KConfigGroup(config
, groupName
);
61 QString
findInTheme(const QString
&image
, const QString
&theme
) const;
62 static const char *defaultTheme
;
64 static PackageStructure::Ptr packageStructure
;
67 KSharedConfigPtr colors
;
70 bool compositingActive
;
72 KSelectionWatcher
*compositeWatch
;
76 PackageStructure::Ptr
Theme::Private::packageStructure(0);
77 const char *Theme::Private::defaultTheme
= "default";
85 K_GLOBAL_STATIC( ThemeSingleton
, privateThemeSelf
)
89 return &privateThemeSelf
->self
;
92 Theme::Theme(QObject
* parent
)
99 Display
*dpy
= QX11Info::display();
100 int screen
= DefaultScreen(dpy
);
101 d
->locolor
= DefaultDepth(dpy
, screen
) < 16;
104 char net_wm_cm_name
[100];
105 sprintf(net_wm_cm_name
, "_NET_WM_CM_S%d", screen
);
106 d
->compositeWatch
= new KSelectionWatcher(net_wm_cm_name
, -1, this);
107 connect(d
->compositeWatch
, SIGNAL(newOwner(Window
)), this, SLOT(compositingChanged()));
108 connect(d
->compositeWatch
, SIGNAL(lostOwner()), this, SLOT(compositingChanged()));
115 d
->config().writeEntry("name", d
->themeName
);
119 PackageStructure::Ptr
Theme::packageStructure()
121 if (!Private::packageStructure
) {
122 Private::packageStructure
= new ThemePackage();
125 return Private::packageStructure
;
128 void Theme::setApplication(const QString
&appname
)
130 if (d
->app
!= appname
) {
136 void Theme::settingsChanged()
138 setThemeName(d
->config().readEntry("name", Private::defaultTheme
));
141 void Theme::compositingChanged()
144 bool compositingActive
= d
->compositeWatch
->owner() != None
;
146 if (d
->compositingActive
!= compositingActive
) {
147 d
->compositingActive
= compositingActive
;
153 void Theme::colorsChanged()
158 void Theme::setThemeName(const QString
&themeName
)
160 QString theme
= themeName
;
161 if (theme
.isEmpty() || theme
== d
->themeName
) {
162 // let's try and get the default theme at least
163 if (d
->themeName
.isEmpty()) {
164 theme
= Private::defaultTheme
;
170 //TODO: should we care about names with relative paths in them?
171 QString themePath
= KStandardDirs::locate("data", "desktoptheme/" + theme
+ "/");
172 if (themePath
.isEmpty() && d
->themeName
.isEmpty()) {
173 themePath
= KStandardDirs::locate("data", "desktoptheme/default/");
175 if (themePath
.isEmpty()) {
179 theme
= Private::defaultTheme
;
182 d
->themeName
= theme
;
184 // load the color scheme config
185 QString colorsFile
= KStandardDirs::locate("data", "desktoptheme/" + theme
+ "/colors");
186 //kDebug() << "we're going for..." << colorsFile << "*******************";
188 disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(colorsChanged()));
189 if (colorsFile
.isEmpty()) {
191 connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(colorsChanged()));
193 d
->colors
= KSharedConfig::openConfig(colorsFile
);
196 KConfigGroup cg
= d
->config();
197 if (cg
.readEntry("name", Private::defaultTheme
) != d
->themeName
) {
198 cg
.writeEntry("name", d
->themeName
);
205 QString
Theme::themeName() const
210 QString
Theme::Private::findInTheme(const QString
&image
, const QString
&theme
) const
212 //TODO: this should be using Package
216 search
= "desktoptheme/" + theme
+ "/locolor/" + image
+ ".svg";
217 search
= KStandardDirs::locate("data", search
);
218 } else if (!compositingActive
) {
219 search
= "desktoptheme/" + theme
+ "/opaque/" + image
+ ".svg";
220 search
= KStandardDirs::locate("data", search
);
223 //not found or compositing enabled
224 if (search
.isEmpty()) {
225 search
= "desktoptheme/" + theme
+ '/' + image
+ ".svg";
226 search
= KStandardDirs::locate("data", search
);
232 QString
Theme::image(const QString
& name
) const
234 QString path
= d
->findInTheme(name
, d
->themeName
);
236 if (path
.isEmpty() && d
->themeName
!= Private::defaultTheme
) {
237 path
= d
->findInTheme(name
, Private::defaultTheme
);
240 if (path
.isEmpty()) {
241 kDebug() << "Theme says: bad image path " << name
;
247 KSharedConfigPtr
Theme::colors() const
252 QColor
Theme::textColor() const
254 KColorScheme
colors(QPalette::Active
, KColorScheme::Window
, Theme::self()->colors());
255 return colors
.foreground(KColorScheme::NormalText
).color();
258 QColor
Theme::backgroundColor() const
260 KColorScheme
colors(QPalette::Active
, KColorScheme::Window
, Theme::self()->colors());
261 return colors
.background().color();
264 void Theme::setFont(const QFont
&font
)
266 d
->generalFont
= font
;
269 QFont
Theme::font() const
271 //TODO: allow this to be overridden with a plasma specific font?
272 return d
->generalFont
;
275 QFontMetrics
Theme::fontMetrics() const
277 //TODO: allow this to be overridden with a plasma specific font?
278 return QFontMetrics(d
->generalFont
);