22 #include <QApplication>
25 #include <QMutableListIterator>
27 #include <QStringBuilder>
31 #include "private/effectwatcher_p.h"
34 #include <kcolorscheme.h>
35 #include <kcomponentdata.h>
36 #include <kconfiggroup.h>
38 #include <kdirwatch.h>
40 #include <kglobalsettings.h>
41 #include <kmanagerselection.h>
42 #include <kimagecache.h>
43 #include <ksharedconfig.h>
44 #include <kstandarddirs.h>
45 #include <kwindowsystem.h>
48 #include "animations/animationscriptengine_p.h"
49 #include "libplasma-theme-global.h"
50 #include "private/packages_p.h"
57 #define DEFAULT_WALLPAPER_THEME "default"
58 #define DEFAULT_WALLPAPER_SUFFIX ".png"
73 Q_DECLARE_OPERATORS_FOR_FLAGS(CacheTypes)
78 ThemePrivate(Theme *theme)
80 colorScheme(QPalette::Active, KColorScheme::Window, KSharedConfigPtr(0)),
81 buttonColorScheme(QPalette::Active, KColorScheme::Button, KSharedConfigPtr(0)),
82 viewColorScheme(QPalette::Active, KColorScheme::View, KSharedConfigPtr(0)),
90 compositingActive(KWindowSystem::self()->compositingActive()),
95 useNativeWidgetStyle(
false)
97 generalFont = QApplication::font();
99 cacheTheme = config.cacheTheme();
101 saveTimer =
new QTimer(q);
102 saveTimer->setSingleShot(
true);
103 saveTimer->setInterval(600);
104 QObject::connect(saveTimer, SIGNAL(timeout()), q, SLOT(scheduledCacheUpdate()));
106 updateNotificationTimer =
new QTimer(q);
107 updateNotificationTimer->setSingleShot(
true);
108 updateNotificationTimer->setInterval(500);
109 QObject::connect(updateNotificationTimer, SIGNAL(timeout()), q, SLOT(notifyOfChanged()));
111 if (QPixmap::defaultDepth() > 8) {
112 QObject::connect(KWindowSystem::self(), SIGNAL(compositingChanged(
bool)), q, SLOT(compositingChanged(
bool)));
115 if (!s_blurEffectWatcher) {
116 s_blurEffectWatcher =
new EffectWatcher(
"_KDE_NET_WM_BLUR_BEHIND_REGION");
119 QObject::connect(s_blurEffectWatcher, SIGNAL(effectChanged(
bool)), q, SLOT(blurBehindChanged(
bool)));
129 KConfigGroup &config()
131 if (!cfg.isValid()) {
132 QString groupName =
"Theme";
135 QString app = KGlobal::mainComponent().componentName();
137 if (!app.isEmpty()) {
138 kDebug() <<
"using theme for app" << app;
139 groupName.append(
"-").append(app);
143 cfg = KConfigGroup(KSharedConfig::openConfig(themeRcFile), groupName);
149 QString findInTheme(
const QString &image,
const QString &theme,
bool cache =
true);
150 void compositingChanged(
bool active);
151 void discardCache(CacheTypes caches);
152 void scheduledCacheUpdate();
153 void scheduleThemeChangeNotification(CacheTypes caches);
154 void notifyOfChanged();
155 void colorsChanged();
156 void blurBehindChanged(
bool blur);
158 void settingsFileChanged(
const QString &);
159 void setThemeName(
const QString &themeName,
bool writeSettings);
160 void onAppExitCleanup();
161 void processWallpaperSettings(KConfigBase *metadata);
162 void processAnimationSettings(
const QString &theme, KConfigBase *metadata);
164 const QString processStyleSheet(
const QString &css);
166 static const char *defaultTheme;
167 static const char *systemColorsTheme;
168 static const char *themeRcFile;
171 static EffectWatcher *s_blurEffectWatcher;
176 QList<QString> fallbackThemes;
177 KSharedConfigPtr colors;
178 KColorScheme colorScheme;
179 KColorScheme buttonColorScheme;
180 KColorScheme viewColorScheme;
183 QString defaultWallpaperTheme;
184 QString defaultWallpaperSuffix;
185 int defaultWallpaperWidth;
186 int defaultWallpaperHeight;
187 KImageCache *pixmapCache;
188 KSharedConfigPtr svgElementsCache;
189 QHash<QString, QSet<QString> > invalidElements;
190 QHash<QString, QPixmap> pixmapsToCache;
191 QHash<QString, QString> keysToCache;
192 QHash<QString, QString> idsToCache;
193 QHash<QString, QString> animationMapping;
194 QHash<styles, QString> cachedStyleSheets;
195 QHash<QString, QString> discoveries;
197 QTimer *updateNotificationTimer;
199 CacheTypes cachesToDiscard;
202 bool compositingActive : 1;
206 bool hasWallpapers : 1;
208 bool useNativeWidgetStyle :1;
212 const char *ThemePrivate::defaultTheme =
"default";
213 const char *ThemePrivate::themeRcFile =
"plasmarc";
216 const char *ThemePrivate::systemColorsTheme =
"internal-system-colors";
218 EffectWatcher *ThemePrivate::s_blurEffectWatcher = 0;
221 bool ThemePrivate::useCache()
223 if (cacheTheme && !pixmapCache) {
225 pixmapCache =
new KImageCache(
"plasma_theme_" + themeName, config.themeCacheKb() * 1024);
226 if (themeName != systemColorsTheme) {
231 QFile f(KStandardDirs::locate(
"data",
"desktoptheme/" + themeName +
"/metadata.desktop"));
233 if (info.lastModified().toTime_t() > uint(pixmapCache->lastModifiedTime())) {
234 pixmapCache->clear();
242 void ThemePrivate::onAppExitCleanup()
244 pixmapsToCache.clear();
250 QString ThemePrivate::findInTheme(
const QString &image,
const QString &theme,
bool cache)
252 if (cache && discoveries.contains(image)) {
253 return discoveries[image];
259 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/locolor/") % image;
260 search = KStandardDirs::locate(
"data", search);
261 }
else if (!compositingActive) {
262 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/opaque/") % image;
263 search = KStandardDirs::locate(
"data", search);
265 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/translucent/") % image;
266 search = KStandardDirs::locate(
"data", search);
270 if (search.isEmpty()) {
271 search = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Char(
'/') % image;
272 search = KStandardDirs::locate(
"data", search);
275 if (cache && !search.isEmpty()) {
276 discoveries.insert(image, search);
282 void ThemePrivate::compositingChanged(
bool active)
285 if (compositingActive != active) {
286 compositingActive = active;
293 void ThemePrivate::discardCache(CacheTypes caches)
296 pixmapsToCache.clear();
299 pixmapCache->clear();
307 cachedStyleSheets.clear();
311 invalidElements.clear();
313 if (svgElementsCache) {
314 QFile f(svgElementsCache->name());
315 svgElementsCache = 0;
319 const QString svgElementsFile = KStandardDirs::locateLocal(
"cache",
"plasma-svgelements-" + themeName);
320 svgElementsCache = KSharedConfig::openConfig(svgElementsFile);
324 void ThemePrivate::scheduledCacheUpdate()
327 QHashIterator<QString, QPixmap> it(pixmapsToCache);
328 while (it.hasNext()) {
330 pixmapCache->insertPixmap(idsToCache[it.key()], it.value());
334 pixmapsToCache.clear();
339 void ThemePrivate::colorsChanged()
341 colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
342 buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
343 viewColorScheme = KColorScheme(QPalette::Active, KColorScheme::View, colors);
344 scheduleThemeChangeNotification(PixmapCache);
347 void ThemePrivate::blurBehindChanged(
bool blur)
349 if (blurActive != blur) {
351 scheduleThemeChangeNotification(PixmapCache | SvgElementsCache);
355 void ThemePrivate::scheduleThemeChangeNotification(CacheTypes caches)
357 cachesToDiscard |= caches;
358 updateNotificationTimer->start();
361 void ThemePrivate::notifyOfChanged()
364 discardCache(cachesToDiscard);
366 emit q->themeChanged();
369 const QString ThemePrivate::processStyleSheet(
const QString &css)
374 if (stylesheet.isEmpty()) {
375 stylesheet = QString(
"\n\
377 color: %textcolor;\n\
378 font-size: %fontsize;\n\
379 font-family: %fontfamily;\n\
381 a:active { color: %activatedlink; }\n\
382 a:link { color: %link; }\n\
383 a:visited { color: %visitedlink; }\n\
384 a:hover { color: %hoveredlink; text-decoration: none; }\n\
386 stylesheet = processStyleSheet(stylesheet);
391 }
else if (css ==
"SVG") {
392 stylesheet = cachedStyleSheets.value(
SVGSTYLE);
393 if (stylesheet.isEmpty()) {
394 QString skel =
".ColorScheme-%1{color:%2;}";
396 stylesheet += skel.arg(
"Text",
"%textcolor");
397 stylesheet += skel.arg(
"Background",
"%backgroundcolor");
399 stylesheet += skel.arg(
"ButtonText",
"%buttontextcolor");
400 stylesheet += skel.arg(
"ButtonBackground",
"%buttonbackgroundcolor");
401 stylesheet += skel.arg(
"ButtonHover",
"%buttonhovercolor");
402 stylesheet += skel.arg(
"ButtonFocus",
"%buttonfocuscolor");
404 stylesheet += skel.arg(
"ViewText",
"%viewtextcolor");
405 stylesheet += skel.arg(
"ViewBackground",
"%viewbackgroundcolor");
406 stylesheet += skel.arg(
"ViewHover",
"%viewhovercolor");
407 stylesheet += skel.arg(
"ViewFocus",
"%viewfocuscolor");
409 stylesheet = processStyleSheet(stylesheet);
410 cachedStyleSheets.insert(
SVGSTYLE, stylesheet);
418 QHash<QString, QString> elements;
437 elements[
"%fontsize"] = QString(
"%1pt").arg(font.pointSize());
438 elements[
"%fontfamily"] = font.family().split(
'[').first();
439 elements[
"%smallfontsize"] = QString(
"%1pt").arg(KGlobalSettings::smallestReadableFont().pointSize());
441 QHash<QString, QString>::const_iterator it = elements.constBegin();
442 QHash<QString, QString>::const_iterator itEnd = elements.constEnd();
443 for ( ; it != itEnd; ++it) {
444 stylesheet.replace(it.key(), it.value());
454 self.d->isDefault =
true;
457 KDirWatch::self()->addFile(KStandardDirs::locateLocal(
"config", ThemePrivate::themeRcFile));
458 QObject::connect(KDirWatch::self(), SIGNAL(created(QString)), &
self, SLOT(settingsFileChanged(QString)));
459 QObject::connect(KDirWatch::self(), SIGNAL(dirty(QString)), &
self, SLOT(settingsFileChanged(QString)));
465 K_GLOBAL_STATIC(ThemeSingleton, privateThemeSelf)
469 return &privateThemeSelf->self;
474 d(new ThemePrivate(this))
477 if (QCoreApplication::instance()) {
478 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
479 this, SLOT(onAppExitCleanup()));
485 d(new ThemePrivate(this))
488 bool useCache = d->cacheTheme;
489 d->cacheTheme =
false;
491 d->cacheTheme = useCache;
492 if (QCoreApplication::instance()) {
493 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()),
494 this, SLOT(onAppExitCleanup()));
500 if (d->svgElementsCache) {
501 QHashIterator<QString, QSet<QString> > it(d->invalidElements);
502 while (it.hasNext()) {
504 KConfigGroup imageGroup(d->svgElementsCache, it.key());
505 imageGroup.writeEntry(
"invalidElements", it.value().toList());
509 d->onAppExitCleanup();
524 const QStringList themes = KGlobal::dirs()->findAllResources(
"data",
"desktoptheme/*/metadata.desktop",
525 KStandardDirs::NoDuplicates);
526 return KPluginInfo::fromFiles(themes);
529 void ThemePrivate::settingsFileChanged(
const QString &file)
531 if (file.endsWith(themeRcFile)) {
532 config().config()->reparseConfiguration();
533 q->settingsChanged();
539 KConfigGroup cg = d->config();
540 d->setThemeName(cg.readEntry(
"name", ThemePrivate::defaultTheme),
false);
541 cg = KConfigGroup(cg.config(),
"PlasmaToolTips");
542 d->toolTipDelay = cg.readEntry(
"Delay", 700);
547 d->setThemeName(themeName,
true);
550 void ThemePrivate::processWallpaperSettings(KConfigBase *metadata)
557 if (metadata->hasGroup(
"Wallpaper")) {
560 cg = KConfigGroup(metadata,
"Wallpaper");
573 void ThemePrivate::processAnimationSettings(
const QString &theme, KConfigBase *metadata)
575 KConfigGroup cg(metadata,
"Animations");
576 const QString animDir = QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/animations/");
577 foreach (
const QString &path, cg.keyList()) {
578 const QStringList anims = cg.readEntry(path, QStringList());
579 foreach (
const QString &anim, anims) {
580 if (!animationMapping.contains(anim)) {
581 kDebug() <<
"Registering animation. animDir: " << animDir
582 <<
"\tanim: " << anim
583 <<
"\tpath: " << path <<
"\t*******\n\n\n";
586 animationMapping.insert(anim, animDir % path);
588 kDebug() <<
"************Animation already registered!\n\n\n";
595 void ThemePrivate::setThemeName(
const QString &tempThemeName,
bool writeSettings)
598 QString theme = tempThemeName;
599 if (theme.isEmpty() || theme == themeName) {
601 if (themeName.isEmpty()) {
602 theme = ThemePrivate::defaultTheme;
610 bool realTheme = theme != systemColorsTheme;
612 QString themePath = KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Char(
'/'));
613 if (themePath.isEmpty() && themeName.isEmpty()) {
614 themePath = KStandardDirs::locate(
"data",
"desktoptheme/default/");
616 if (themePath.isEmpty()) {
620 theme = ThemePrivate::defaultTheme;
625 if (themeName == theme) {
632 const QString colorsFile = realTheme ? KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/colors"))
639 const QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
640 KConfig metadata(metadataPath);
642 processWallpaperSettings(&metadata);
645 animationMapping.clear();
646 processAnimationSettings(themeName, &metadata);
648 KConfigGroup cg(&metadata,
"Settings");
649 useNativeWidgetStyle = cg.readEntry(
"UseNativeWidgetStyle",
false);
650 QString fallback = cg.readEntry(
"FallbackTheme", QString());
652 fallbackThemes.clear();
653 while (!fallback.isEmpty() && !fallbackThemes.contains(fallback)) {
654 fallbackThemes.append(fallback);
656 QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
657 KConfig metadata(metadataPath);
658 KConfigGroup cg(&metadata,
"Settings");
659 fallback = cg.readEntry(
"FallbackTheme", QString());
662 if (!fallbackThemes.contains(
"oxygen")) {
663 fallbackThemes.append(
"oxygen");
666 if (!fallbackThemes.contains(ThemePrivate::defaultTheme)) {
667 fallbackThemes.append(ThemePrivate::defaultTheme);
670 foreach (
const QString &theme, fallbackThemes) {
671 QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/metadata.desktop")));
672 KConfig metadata(metadataPath);
673 processAnimationSettings(theme, &metadata);
674 processWallpaperSettings(&metadata);
678 if (colorsFile.isEmpty()) {
680 QObject::connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
681 q, SLOT(colorsChanged()), Qt::UniqueConnection);
683 QObject::disconnect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
684 q, SLOT(colorsChanged()));
685 colors = KSharedConfig::openConfig(colorsFile);
688 colorScheme = KColorScheme(QPalette::Active, KColorScheme::Window, colors);
689 buttonColorScheme = KColorScheme(QPalette::Active, KColorScheme::Button, colors);
690 viewColorScheme = KColorScheme(QPalette::Active, KColorScheme::View, colors);
691 hasWallpapers = KStandardDirs::exists(KStandardDirs::locateLocal(
"data", QLatin1Literal(
"desktoptheme/") % theme % QLatin1Literal(
"/wallpapers/")));
693 if (realTheme && isDefault && writeSettings) {
695 KConfigGroup &cg = config();
696 if (ThemePrivate::defaultTheme == themeName) {
697 cg.deleteEntry(
"name");
699 cg.writeEntry(
"name", themeName);
704 scheduleThemeChangeNotification(SvgElementsCache);
715 if (name.contains(
"../") || name.isEmpty()) {
721 const QString svgzName = name % QLatin1Literal(
".svgz");
722 QString path = d->findInTheme(svgzName, d->themeName);
724 if (path.isEmpty()) {
726 const QString svgName = name % QLatin1Literal(
".svg");
727 path = d->findInTheme(svgName, d->themeName);
730 for (
int i = 0; path.isEmpty() && i < d->fallbackThemes.count(); ++i) {
731 if (d->themeName == d->fallbackThemes[i]) {
736 path = d->findInTheme(svgzName, d->fallbackThemes[i]);
738 if (path.isEmpty()) {
740 path = d->findInTheme(svgName, d->fallbackThemes[i]);
756 return d->processStyleSheet(css);
761 const QString path = d->animationMapping.value(name);
762 if (path.isEmpty()) {
767 return KStandardDirs::locate(
"data", path);
773 QString image = d->defaultWallpaperTheme;
775 image.append(
"/contents/images/%1x%2").append(d->defaultWallpaperSuffix);
776 QString defaultImage = image.arg(d->defaultWallpaperWidth).arg(d->defaultWallpaperHeight);
778 if (size.isValid()) {
783 image = image.arg(size.width()).arg(size.height());
785 image = defaultImage;
791 if (d->hasWallpapers) {
793 fullPath = d->findInTheme(QLatin1Literal(
"wallpapers/") % image, d->themeName);
795 if (fullPath.isEmpty()) {
796 fullPath = d->findInTheme(QLatin1Literal(
"wallpapers/") % defaultImage, d->themeName);
800 if (fullPath.isEmpty()) {
803 fullPath = KStandardDirs::locate(
"wallpaper", image);
806 if (fullPath.isEmpty()) {
810 fullPath = KStandardDirs::locate(
"wallpaper", defaultImage);
812 if (fullPath.isEmpty()) {
813 kDebug() <<
"exhausted every effort to find a wallpaper.";
822 if (name.contains(
"../")) {
827 return !(d->findInTheme(name % QLatin1Literal(
".svgz"), d->themeName,
false).isEmpty()) ||
828 !(d->findInTheme(name % QLatin1Literal(
".svg"), d->themeName,
false).isEmpty());
840 return d->colorScheme.foreground(KColorScheme::NormalText).color();
843 return d->colorScheme.decoration(KColorScheme::HoverColor).color();
846 return d->colorScheme.background(KColorScheme::NormalBackground).color();
849 return d->buttonColorScheme.foreground(KColorScheme::NormalText).color();
852 return d->buttonColorScheme.background(KColorScheme::NormalBackground).color();
855 return d->buttonColorScheme.decoration(KColorScheme::HoverColor).color();
858 return d->buttonColorScheme.decoration(KColorScheme::FocusColor).color();
861 return d->viewColorScheme.foreground(KColorScheme::NormalText).color();
864 return d->viewColorScheme.background(KColorScheme::NormalBackground).color();
867 return d->viewColorScheme.decoration(KColorScheme::HoverColor).color();
870 return d->viewColorScheme.decoration(KColorScheme::FocusColor).color();
873 return d->viewColorScheme.foreground(KColorScheme::LinkText).color();
876 return d->viewColorScheme.foreground(KColorScheme::VisitedText).color();
885 d->generalFont =
font;
892 KConfigGroup cg(KGlobal::config(),
"General");
893 return cg.readEntry(
"desktopFont", d->generalFont);
899 return d->generalFont;
903 return KGlobalSettings::smallestReadableFont();
907 return d->generalFont;
913 return QFontMetrics(d->generalFont);
918 return d->compositingActive;
923 if (d->useGlobal == useGlobal) {
927 d->useGlobal = useGlobal;
928 d->cfg = KConfigGroup();
929 d->themeName.clear();
940 return d->useNativeWidgetStyle;
946 const QString
id = d->keysToCache.value(key);
947 if (d->pixmapsToCache.contains(
id)) {
948 pix = d->pixmapsToCache.value(
id);
949 return !pix.isNull();
953 if (d->pixmapCache->findPixmap(key, &temp) && !temp.isNull()) {
965 if (d->useCache() && lastModified > uint(d->pixmapCache->lastModifiedTime())) {
975 d->pixmapCache->insertPixmap(key, pix);
982 d->pixmapsToCache.insert(
id, pix);
984 if (d->idsToCache.contains(
id)) {
985 d->keysToCache.remove(d->idsToCache[
id]);
988 d->keysToCache.insert(key,
id);
989 d->idsToCache.insert(
id, key);
990 d->saveTimer->start();
996 if (!d->svgElementsCache) {
1000 KConfigGroup imageGroup(d->svgElementsCache, image);
1001 rect = imageGroup.readEntry(element % QLatin1Literal(
"Size"), QRectF());
1003 if (rect.isValid()) {
1009 if (element.indexOf(
'_') <= 0) {
1013 bool invalid =
false;
1015 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1016 if (it == d->invalidElements.end()) {
1017 QSet<QString> elements = imageGroup.readEntry(
"invalidElements", QStringList()).toSet();
1018 d->invalidElements.insert(image, elements);
1019 invalid = elements.contains(element);
1021 invalid = it.value().contains(element);
1029 if (!d->svgElementsCache) {
1030 return QStringList();
1033 KConfigGroup imageGroup(d->svgElementsCache, image);
1034 QStringList keys = imageGroup.keyList();
1036 QMutableListIterator<QString> i(keys);
1037 while (i.hasNext()) {
1038 QString key = i.next();
1039 if (key.endsWith(
"Size")) {
1041 key.resize(key.size() - 4);
1052 if (!d->svgElementsCache) {
1056 if (rect.isValid()) {
1057 KConfigGroup imageGroup(d->svgElementsCache, image);
1058 imageGroup.writeEntry(element % QLatin1Literal(
"Size"), rect);
1060 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1061 if (it == d->invalidElements.end()) {
1062 d->invalidElements[image].insert(element);
1063 }
else if (!it.value().contains(element)) {
1064 if (it.value().count() > 1000) {
1065 it.value().erase(it.value().begin());
1068 it.value().insert(element);
1075 if (d->svgElementsCache) {
1076 KConfigGroup imageGroup(d->svgElementsCache, image);
1077 imageGroup.deleteGroup();
1080 d->invalidElements.remove(image);
1085 QHash<QString, QSet<QString> >::iterator it = d->invalidElements.find(image);
1086 if (it != d->invalidElements.end()) {
1087 if (!d->svgElementsCache) {
1088 KConfigGroup imageGroup(d->svgElementsCache, it.key());
1089 imageGroup.writeEntry(
"invalidElements", it.value().toList());
1092 d->invalidElements.erase(it);
1099 if (d->useCache()) {
1108 const QString metadataPath(KStandardDirs::locate(
"data", QLatin1Literal(
"desktoptheme/") % d->themeName % QLatin1Literal(
"/metadata.desktop")));
1109 KConfig metadata(metadataPath);
1110 KConfigGroup brandConfig(&metadata,
"Branding");
1111 return brandConfig.readEntry(
"homepage", KUrl(
"http://www.kde.org"));
1116 return d->toolTipDelay;
1121 #include <theme.moc>