summaryrefslogtreecommitdiff
authorsandman <sandman>2002-06-29 23:45:19 (UTC)
committer sandman <sandman>2002-06-29 23:45:19 (UTC)
commit769df90a59d6aa840b8d6568287001e66e263f01 (patch) (side-by-side diff)
tree415c7e4ff70a9b035c31b28971a568bc2827ae34
parent0f179c0cc471b659b30dec4762c9c36678063f31 (diff)
downloadopie-769df90a59d6aa840b8d6568287001e66e263f01.zip
opie-769df90a59d6aa840b8d6568287001e66e263f01.tar.gz
opie-769df90a59d6aa840b8d6568287001e66e263f01.tar.bz2
*** empty log message ***
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--apps/Settings/Theme.desktop7
-rw-r--r--noncore/styles/theme/ogfxeffect.cpp324
-rw-r--r--noncore/styles/theme/ogfxeffect.h78
-rw-r--r--noncore/styles/theme/opie-theme.control11
-rw-r--r--noncore/styles/theme/othemebase.cpp1212
-rw-r--r--noncore/styles/theme/othemebase.h739
-rw-r--r--noncore/styles/theme/othemestyle.cpp1532
-rw-r--r--noncore/styles/theme/othemestyle.h365
-rw-r--r--noncore/styles/theme/plugin.cpp19
-rw-r--r--noncore/styles/theme/settings/main.cpp34
-rw-r--r--noncore/styles/theme/settings/settings.pro24
-rw-r--r--noncore/styles/theme/settings/themeset.cpp124
-rw-r--r--noncore/styles/theme/settings/themeset.h20
-rw-r--r--noncore/styles/theme/theme.pro32
-rw-r--r--pics/theme/Theme.pngbin0 -> 2771 bytes
16 files changed, 4522 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 1e60978..66c3fe4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,113 +1,113 @@
indefault: dynamic
all: default docs
LIBS=library libopie
INPUTCOMPONENTS= inputmethods/keyboard inputmethods/pickboard \
inputmethods/handwriting inputmethods/unikeyboard \
inputmethods/jumpx inputmethods/kjumpx \
inputmethods/dvorak
APPLETS= core/applets/batteryapplet core/applets/batteryapplet-ipaq \
core/applets/irdaapplet core/applets/volumeapplet \
core/applets/clockapplet core/applets/netmonapplet \
core/applets/screenshotapplet core/applets/clipboardapplet \
core/applets/cardmon core/applets/obex \
core/applets/vmemo noncore/net/netsetup/dialup \
noncore/net/netsetup/lan
MAIL= noncore/mail/libmail noncore/mail/bend
PLAYER = core/multimedia/opieplayer/libmpeg3 \
core/multimedia/opieplayer/libmad \
core/multimedia/opieplayer/wavplugin
-COMPONENTS=$(LOCALCOMPONENTS) $(INPUTCOMPONENTS) $(APPLETS) $(MAIL) $(PLAYER)
+COMPONENTS=$(LOCALCOMPONENTS) $(INPUTCOMPONENTS) $(APPLETS) $(MAIL) # $(PLAYER)
PIMAPPS = core/pim/addressbook core/pim/datebook \
core/pim/today core/pim/todo
COREAPPS = core/apps/filebrowser core/apps/helpbrowser \
core/apps/textedit core/apps/embeddedkonsole \
core/launcher core/apps/sysinfo \
core/apps/oipkg core/apps/qcop
COREMULTIMEDIA = core/multimedia/opieplayer
CORESETTINGS = core/settings/light-and-power core/settings/security \
core/settings/systemtime core/settings/citytime \
core/settings/wlansetup
NONCORESETTINGS =noncore/settings/language noncore/settings/rotation \
noncore/settings/appearance noncore/settings/sound \
noncore/settings/mediummount \
noncore/settings/tabmanager noncore/settings/appskey \
noncore/settings/netsystemtime
NONCORETOOLS = noncore/tools/calculator noncore/tools/clock \
noncore/tools/remote noncore/tools/opie-sh noncore/apps/advancedfm
NONCORESTYLES = noncore/styles/liquid noncore/styles/liquid/settings
GAMES = noncore/games/minesweep noncore/games/solitaire \
noncore/games/tetrix noncore/games/wordgame \
noncore/games/parashoot noncore/games/snake \
noncore/games/mindbreaker \
noncore/games/go noncore/games/qasteroids \
noncore/games/fifteen noncore/games/tictac \
noncore/games/kcheckers noncore/games/kpacman \
noncore/games/kbill
NONAPPS = noncore/apps/spreadsheet noncore/apps/tableviewer \
NONNET = noncore/net/netsetup noncore/net/opieftp \
noncore/mail
NONMULT = noncore/multimedia/showimg noncore/graphics/drawpad \
noncore/graphics/qpdf
NONCOMM = noncore/comm/keypebble
APPS=$(LOCALAPPS) $(PIMAPPS) $(COREAPPS) \
$(COREMULTIMEDIA) $(CORESETTINGS) \
$(NONCORESETTINGS) $(NONCORETOOLS) $(NONCORESTYLES) \
$(NONAPPS) $(NONNET) $(NONMULT) \
$(NONCOMM) $(GAMES)
NONTMAKEAPPS := ipaq/opiealarm
DOCS = docs/src/opie-policy
single: mpegplayer/libmpeg3
dynamic: $(APPS) $(NONTMAKEAPPS)
docs: $(DOCS)
$(COMPONENTS): $(LIBS)
$(NONTMAKEAPPS) $(APPS): $(LIBS) $(COMPONENTS)
$(LIBS) $(COMPONENTS) $(NONTMAKEAPPS) $(APPS) $(DOCS) single:
$(MAKE) -C $@ -f Makefile
showcomponents:
@echo $(LIBS) $(APPS) $(COMPONENTS) single
clean:
$(MAKE) -C single -f Makefile $@
for dir in $(NONTMAKEAPPS) $(APPS) $(LIBS) $(COMPONENTS) $(DOCS); do $(MAKE) -C $$dir -f Makefile $@ || exit 1; done
lupdate:
for dir in $(APPS) $(LIBS) $(COMPONENTS); do $(MAKE) -C $$dir -f Makefile $@ || exit 1; done
lrelease:
for dir in $(APPS) $(LIBS) $(COMPONENTS); do $(MAKE) -C $$dir -f Makefile $@ || exit 1; done
.PHONY: default dynamic $(NONTMAKEAPPS) $(LIBS) $(APPS) $(COMPONENTS) $(DOCS) single showcomponents clean
diff --git a/apps/Settings/Theme.desktop b/apps/Settings/Theme.desktop
new file mode 100644
index 0000000..197184f
--- a/dev/null
+++ b/apps/Settings/Theme.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Application
+Exec=theme-settings
+Icon=theme/Theme
+Name=Theme-Settings
+Name[de]=Thema-Einstellungen
+
diff --git a/noncore/styles/theme/ogfxeffect.cpp b/noncore/styles/theme/ogfxeffect.cpp
new file mode 100644
index 0000000..a991728
--- a/dev/null
+++ b/noncore/styles/theme/ogfxeffect.cpp
@@ -0,0 +1,324 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+*/
+
+// $Id$
+
+#include <qimage.h>
+#include <qpainter.h>
+
+#include "ogfxeffect.h"
+
+
+//======================================================================
+//
+// Gradient effects
+//
+//======================================================================
+
+
+QPixmap& OGfxEffect::gradient(QPixmap &pixmap, const QColor &ca,
+ const QColor &cb, GradientType eff, int ncols)
+{
+ if(pixmap.depth() > 8 &&
+ (eff == VerticalGradient || eff == HorizontalGradient)) {
+
+ int rDiff, gDiff, bDiff;
+ int rca, gca, bca /*, rcb, gcb, bcb*/;
+
+ register int x, y;
+
+ rDiff = (/*rcb = */ cb.red()) - (rca = ca.red());
+ gDiff = (/*gcb = */ cb.green()) - (gca = ca.green());
+ bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue());
+
+ register int rl = rca << 16;
+ register int gl = gca << 16;
+ register int bl = bca << 16;
+
+ int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff;
+ int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff;
+ int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff;
+
+ QPainter p(&pixmap);
+
+ // these for-loops could be merged, but the if's in the inner loop
+ // would make it slow
+ switch(eff) {
+ case VerticalGradient:
+ for ( y = 0; y < pixmap.height(); y++ ) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(0, y, pixmap.width()-1, y);
+ }
+ break;
+ case HorizontalGradient:
+ for( x = 0; x < pixmap.width(); x++) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(x, 0, x, pixmap.height()-1);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ else {
+// QImage image = OGfxEffect::gradient(pixmap.size(), ca, cb,
+// (OGfxEffect::GradientType) eff, ncols);
+// pixmap.convertFromImage(image);
+ }
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Blend effects
+//
+//======================================================================
+
+
+QPixmap& OGfxEffect::blend(QPixmap &pixmap, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir, int ncols)
+{
+ QImage image = pixmap.convertToImage();
+ OGfxEffect::blend(image, initial_intensity, bgnd, eff, anti_dir);
+
+ unsigned int tmp;
+
+ if ( pixmap. depth ( ) <= 8 )
+ image. convertDepth ( pixmap. depth ( ));
+
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+QImage& OGfxEffect::blend(QImage &image, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir)
+{
+ if (image.width() == 0 || image.height() == 0) {
+ qDebug ( "Invalid image\n" );
+ return image;
+ }
+
+ int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
+ int r, g, b;
+ int ind;
+
+ unsigned int xi, xf, yi, yf;
+ unsigned int a;
+
+ // check the boundaries of the initial intesity param
+ float unaffected = 1;
+ if (initial_intensity > 1) initial_intensity = 1;
+ if (initial_intensity < -1) initial_intensity = -1;
+ if (initial_intensity < 0) {
+ unaffected = 1. + initial_intensity;
+ initial_intensity = 0;
+ }
+
+
+ float intensity = initial_intensity;
+ float var = 1. - initial_intensity;
+
+ if (anti_dir) {
+ initial_intensity = intensity = 1.;
+ var = -var;
+ }
+
+ register int x, y;
+
+ unsigned int *data = (unsigned int *)image.bits();
+
+ if( eff == VerticalGradient || eff == HorizontalGradient ) {
+
+ // set the image domain to apply the effect to
+ xi = 0, xf = image.width();
+ yi = 0, yf = image.height();
+ if (eff == VerticalGradient) {
+ if (anti_dir) yf = (int)(image.height() * unaffected);
+ else yi = (int)(image.height() * (1 - unaffected));
+ }
+ else {
+ if (anti_dir) xf = (int)(image.width() * unaffected);
+ else xi = (int)(image.height() * (1 - unaffected));
+ }
+
+ var /= (eff == VerticalGradient?yf-yi:xf-xi);
+
+ for (y = yi; y < (int)yf; y++) {
+ intensity = eff == VerticalGradient? intensity + var :
+ initial_intensity;
+ for (x = xi; x < (int)xf ; x++) {
+ if (eff == HorizontalGradient) intensity += var;
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+ else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
+ float xvar = var / 2 / image.width(); // / unaffected;
+ float yvar = var / 2 / image.height(); // / unaffected;
+ float tmp;
+
+ for (x = 0; x < image.width() ; x++) {
+ tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
+ for (y = 0; y < image.height() ; y++) {
+ intensity = initial_intensity + tmp + yvar * y;
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+
+ else if (eff == RectangleGradient || eff == EllipticGradient) {
+ float xvar;
+ float yvar;
+
+ for (x = 0; x < image.width() / 2 + image.width() % 2; x++) {
+ xvar = var / image.width() * (image.width() - x*2/unaffected-1);
+ for (y = 0; y < image.height() / 2 + image.height() % 2; y++) {
+ yvar = var / image.height() * (image.height() - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //NW
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //NE
+ ind = image.width() - x - 1 + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+
+ //CT loop is doubled because of stupid central row/column issue.
+ // other solution?
+ for (x = 0; x < image.width() / 2; x++) {
+ xvar = var / image.width() * (image.width() - x*2/unaffected-1);
+ for (y = 0; y < image.height() / 2; y++) {
+ yvar = var / image.height() * (image.height() - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //SW
+ ind = x + image.width() * (image.height() - y -1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //SE
+ ind = image.width()-x-1 + image.width() * (image.height() - y - 1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+
+ else
+ qDebug ( "not implemented\n" );
+
+ return image;
+}
+
+#if 0
+// Not very efficient as we create a third big image...
+//
+QImage& KQGfxEffect::blend(QImage &image1, QImage &image2,
+ GradientType gt, int xf, int yf)
+{
+ if (image1.width() == 0 || image1.height() == 0 ||
+ image2.width() == 0 || image2.height() == 0)
+ return image1;
+
+ QImage image3;
+
+ image3 = KQGfxEffect::unbalancedGradient(image1.size(),
+ QColor(0,0,0), QColor(255,255,255),
+ gt, xf, yf, 0);
+
+ return blend(image1,image2,image3, Red); // Channel to use is arbitrary
+}
+#endif
diff --git a/noncore/styles/theme/ogfxeffect.h b/noncore/styles/theme/ogfxeffect.h
new file mode 100644
index 0000000..45a8482
--- a/dev/null
+++ b/noncore/styles/theme/ogfxeffect.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+*/
+
+// $Id$
+
+#ifndef __OGFX_EFFECT_H
+#define __OGFX_EFFECT_H
+
+#include <qpixmap.h>
+#include <qimage.h>
+
+/**
+ * This class includes various pixmap-based graphical effects.
+ *
+ * Everything is
+ * static, so there is no need to create an instance of this class. You can
+ * just call the static methods. They are encapsulated here merely to provide
+ * a common namespace.
+ */
+class OGfxEffect
+{
+public:
+ enum GradientType { VerticalGradient, HorizontalGradient,
+ DiagonalGradient, CrossDiagonalGradient,
+ PyramidGradient, RectangleGradient,
+ PipeCrossGradient, EllipticGradient };
+ enum RGBComponent { Red, Green, Blue };
+
+ enum Lighting {NorthLite, NWLite, WestLite, SWLite,
+ SouthLite, SELite, EastLite, NELite};
+
+ /**
+ * Create a gradient from color a to color b of the specified type.
+ *
+ * @param pixmap The pixmap to process.
+ * @param ca Color a.
+ * @param cb Color b.
+ * @param type The type of gradient.
+ * @param ncols The number of colors to use when not running on a
+ * truecolor display. The gradient will be dithered to this number of
+ * colors. Pass 0 to prevent dithering.
+ * @return Returns the generated pixmap, for convenience.
+ */
+ static QPixmap& gradient(QPixmap& pixmap, const QColor &ca, const QColor &cb,
+ GradientType type, int ncols=3);
+
+
+ /**
+ * Blend the provided pixmap into a background of the indicated color
+ *
+ * @param pixmap The pixmap to process.
+ * @param initial_intensity this parameter takes values from -1 to 1:
+ * @li If positive, it tells how much to fade the image in its
+ * less affected spot.
+ * @li If negative, it tells roughly indicates how much of the image
+ * remains unaffected
+ * @param bgnd Indicates the color of the background to blend in.
+ * @param eff Lets you choose what kind of blending you like.
+ * @param anti_dir Blend in the opposite direction (makes no much sense
+ * with concentric blending effects).
+ * @return Returns the @ref pixmap(), provided for convenience.
+ */
+ static QPixmap& blend(QPixmap& pixmap, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir=false, int ncols=3);
+
+
+ static QImage& blend(QImage &image, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir);
+};
+
+
+#endif
diff --git a/noncore/styles/theme/opie-theme.control b/noncore/styles/theme/opie-theme.control
new file mode 100644
index 0000000..02739fb
--- a/dev/null
+++ b/noncore/styles/theme/opie-theme.control
@@ -0,0 +1,11 @@
+Files: plugins/styles/libtheme.so* bin/theme-settings apps/Settings/Theme.desktop pics/theme/Theme.png
+Priority: optional
+Section: opie/system
+Maintainer: Robert Griebl <sandman@handhelds.org>
+Architecture: arm
+Version: $QPE_VERSION-$SUB_VERSION.1
+Depends: opie-base ($QPE_VERSION)
+Description: Themed style.
+ This style accepts all themes written
+for KDE 2.2
+
diff --git a/noncore/styles/theme/othemebase.cpp b/noncore/styles/theme/othemebase.cpp
new file mode 100644
index 0000000..00cea03
--- a/dev/null
+++ b/noncore/styles/theme/othemebase.cpp
@@ -0,0 +1,1212 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "othemebase.h"
+#include "ogfxeffect.h"
+#include <qpe/qpeapplication.h>
+//#include <kdebug.h>
+//#include <klocale.h>
+#include <qpe/config.h>
+//#include <kglobal.h>
+//#include <kglobalsettings.h>
+//#include <kstddirs.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qdir.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+#include <stdlib.h>
+#include <qstringlist.h>
+
+#include <stdio.h>
+
+template class QIntCache<OThemePixmap>
+;
+
+static const char *widgetEntries[] =
+ { // unsunken widgets (see header)
+ "PushButton", "ComboBox", "HSBarSlider", "VSBarSlider", "Bevel", "ToolButton",
+ "ScrollButton", "HScrollDeco", "VScrollDeco", "ComboDeco", "MenuItem", "Tab",
+ "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight",
+ // sunken widgets
+ "PushButtonDown", "ComboBoxDown", "HSBarSliderDown", "VSBarSliderDown",
+ "BevelDown", "ToolButtonDown", "ScrollButtonDown", "HScrollDecoDown",
+ "VScrollDecoDown", "ComboDecoDown", "MenuItemDown", "TabDown", "SunkenArrowUp",
+ "SunkenArrowDown", "SunkenArrowLeft", "SunkenArrowRight",
+ // everything else
+ "HScrollGroove", "VScrollGroove", "Slider", "SliderGroove", "CheckBoxDown",
+ "CheckBox", "RadioDown", "Radio", "HBarHandle", "VBarHandle",
+ "ToolBar", "Splitter", "CheckMark", "MenuBar", "DisableArrowUp",
+ "DisableArrowDown", "DisableArrowLeft", "DisableArrowRight", "ProgressBar",
+ "ProgressBackground", "MenuBarItem", "Background"
+ };
+
+#define INHERIT_ITEMS 16
+
+
+// This is used to encode the keys. I used to use masks but I think this
+// bitfield is nicer :) I don't know why C++ coders don't use these more..
+// (mosfet)
+struct kthemeKeyData
+{
+unsigned int id :
+ 6;
+unsigned int width :
+ 12;
+unsigned int height :
+ 12;
+unsigned int border :
+ 1;
+unsigned int mask :
+ 1;
+};
+
+union kthemeKey{
+ kthemeKeyData data;
+ unsigned int cacheKey;
+};
+
+class MyConfig : public Config
+{
+public:
+ MyConfig ( const QString &f, Domain d ) : Config ( f, d )
+ { }
+
+ bool hasGroup ( const QString &gname ) const
+ {
+ QMap< QString, ConfigGroup>::ConstIterator it = groups. find ( gname );
+ return ( it != groups.end() );
+ }
+};
+
+void OThemeBase::generateBorderPix( int i )
+{
+ // separate pixmap into separate components
+ if ( pbPixmaps[ i ] ) {
+ // evidently I have to do masks manually...
+ const QBitmap * srcMask = pbPixmaps[ i ] ->mask();
+ QBitmap destMask( pbWidth[ i ], pbWidth[ i ] );
+ QPixmap tmp( pbWidth[ i ], pbWidth[ i ] );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, 0, pbWidth[ i ], pbWidth[ i ],
+ Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, 0, 0, pbWidth[ i ], pbWidth[ i ],
+ Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::TopLeft, tmp );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], 0,
+ pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ],
+ 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::TopRight, tmp );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbPixmaps[ i ] ->height() - pbWidth[ i ],
+ pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, 0, pbPixmaps[ i ] ->height() - pbWidth[ i ],
+ pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::BottomLeft, tmp );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ],
+ Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ],
+ Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::BottomRight, tmp );
+
+ tmp.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] );
+ destMask.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] );
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ], 0,
+ pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ], 0,
+ pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ],
+ Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::Top, tmp );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ],
+ pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ],
+ pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::Bottom, tmp );
+
+ tmp.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 );
+ destMask.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 );
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbWidth[ i ], pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, 0, pbWidth[ i ], pbWidth[ i ],
+ pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::Left, tmp );
+
+ bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ],
+ pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2,
+ Qt::CopyROP, false );
+ if ( srcMask ) {
+ bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ],
+ pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2,
+ Qt::CopyROP, false );
+ tmp.setMask( destMask );
+ }
+ pbPixmaps[ i ] ->setBorder( OThemePixmap::Right, tmp );
+ }
+ else
+ qDebug ( "OThemeBase: Tried making border from empty pixmap" );
+}
+
+
+void OThemeBase::copyWidgetConfig( int sourceID, int destID, QString *pixnames,
+ QString *brdnames )
+{
+ scaleHints[ destID ] = scaleHints[ sourceID ];
+ gradients[ destID ] = gradients[ sourceID ];
+ blends[ destID ] = blends[ sourceID ];
+ bContrasts[ destID ] = bContrasts[ sourceID ];
+ borders[ destID ] = borders[ sourceID ];
+ highlights[ destID ] = highlights[ sourceID ];
+
+ if ( grLowColors[ sourceID ] )
+ grLowColors[ destID ] = new QColor( *grLowColors[ sourceID ] );
+ else
+ grLowColors[ destID ] = NULL;
+
+ if ( grHighColors[ sourceID ] )
+ grHighColors[ destID ] = new QColor( *grHighColors[ sourceID ] );
+ else
+ grHighColors[ destID ] = NULL;
+
+ if ( colors[ sourceID ] )
+ colors[ destID ] = new QColorGroup( *colors[ sourceID ] );
+ else
+ colors[ destID ] = NULL;
+
+ // pixmap
+ pixnames[ destID ] = pixnames[ sourceID ];
+ duplicate[ destID ] = false;
+ pixmaps[ destID ] = NULL;
+ images[ destID ] = NULL;
+ if ( !pixnames[ destID ].isEmpty() ) {
+ if ( scaleHints[ sourceID ] == TileScale && blends[ sourceID ] == 0.0 ) {
+ pixmaps[ destID ] = pixmaps[ sourceID ];
+ duplicate[ destID ] = true;
+ }
+ if ( !duplicate[ destID ] ) {
+ pixmaps[ destID ] = loadPixmap( pixnames[ destID ] );
+ if ( scaleHints[ destID ] == TileScale && blends[ destID ] == 0.0 )
+ images[ destID ] = NULL;
+ else
+ images[ destID ] = loadImage( pixnames[ destID ] );
+ }
+ }
+
+ // border pixmap
+ pbDuplicate[ destID ] = false;
+ pbPixmaps[ destID ] = NULL;
+ pbWidth[ destID ] = pbWidth[ sourceID ];
+ brdnames[ destID ] = brdnames[ sourceID ];
+ if ( !brdnames[ destID ].isEmpty() ) {
+ pbPixmaps[ destID ] = pbPixmaps[ sourceID ];
+ pbDuplicate[ destID ] = true;
+ }
+
+ if ( sourceID == ActiveTab && destID == InactiveTab )
+ aTabLine = iTabLine;
+ else if ( sourceID == InactiveTab && destID == ActiveTab )
+ iTabLine = aTabLine;
+}
+
+void OThemeBase::readConfig( Qt::GUIStyle /*style*/ )
+{
+#define PREBLEND_ITEMS 12
+ static WidgetType preBlend[] = {Slider, IndicatorOn, IndicatorOff,
+ ExIndicatorOn, ExIndicatorOff, HScrollDeco, VScrollDeco, HScrollDecoDown,
+ VScrollDecoDown, ComboDeco, ComboDecoDown, CheckMark};
+
+ int i;
+ QString tmpStr;
+ QString copyfrom[ WIDGETS ];
+ QString pixnames[ WIDGETS ]; // used for duplicate check
+ QString brdnames[ WIDGETS ];
+ bool loaded[ WIDGETS ]; // used for preloading for CopyWidget
+
+ if ( configFileName.isEmpty() ) {
+ Config cfg ( "qpe" );
+ cfg. setGroup ( "Appearance" );
+
+ configFileName = cfg. readEntry ( "Theme", "default" );
+ }
+ MyConfig config( configFilePath + "/themes/" + configFileName + ".themerc" , Config::File );
+
+ printf ( "Opened config file: %s\n", ( configFilePath + "/themes/" + configFileName + ".themerc" ). ascii());
+
+ // Are we initalized?
+ for ( i = 0; i < INHERIT_ITEMS; ++i ) {
+ applyResourceGroup( &config, i, copyfrom, pixnames, brdnames );
+ printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() );
+ }
+ for ( ; i < INHERIT_ITEMS*2; ++i ) {
+ if ( config.hasGroup( QString( widgetEntries[ i ] ) ) ) {
+ applyResourceGroup( &config, i, copyfrom, pixnames, brdnames );
+ printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() );
+ }
+ else {
+ copyfrom [ i ] = widgetEntries[ i - INHERIT_ITEMS ];
+ printf ( "%d [%s]: copy=%s\n", i, widgetEntries [i], copyfrom [i].latin1());
+ }
+ }
+ for ( ; i < WIDGETS; ++i ) {
+ applyResourceGroup( &config, i, copyfrom, pixnames, brdnames );
+ printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() );
+ }
+ applyMiscResourceGroup( &config );
+
+ // initalize defaults that may not be read
+ for ( i = 0; i < WIDGETS; ++i )
+ loaded[ i ] = false;
+ btnXShift = btnYShift = focus3DOffset = 0;
+ aTabLine = iTabLine = true;
+ roundedButton = roundedCombo = roundedSlider = focus3D = false;
+ splitterWidth = 10;
+
+ for ( i = 0; i < WIDGETS; ++i ) {
+ readResourceGroup( i, copyfrom, pixnames, brdnames, loaded );
+ printf ( "%d [%s]: copy=%s, pix=%s, brd=%s, colors=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1(), (colors[i]?colors[i]->background().name().latin1():"<none)" ));
+ }
+
+ // misc items
+ readMiscResourceGroup();
+
+ // Handle preblend items
+ for ( i = 0; i < PREBLEND_ITEMS; ++i ) {
+ if ( pixmaps[ preBlend[ i ] ] != NULL && blends[ preBlend[ i ] ] != 0.0 )
+ blend( preBlend[ i ] );
+ }
+}
+
+OThemeBase::OThemeBase( const QString & configFile )
+ : QWindowsStyle()
+{
+ configFilePath = QPEApplication::qpeDir ( ) + "/plugins/styles/";
+ configFileName = configFile;
+
+ readConfig( Qt::WindowsStyle );
+ cache = new OThemeCache( cacheSize );
+}
+
+void OThemeBase::applyConfigFile( const QString &/*file*/ )
+{
+#if 0
+ // handle std color scheme
+ Config inConfig( file, Config::File );
+ Config globalConfig ( "qpe" );
+
+ globalConfig. setGroup ( "Apperance" );
+ inConfig. setGroup( "General" );
+
+ if ( inConfig.hasKey( "foreground" ) )
+ globalConfig.writeEntry( "Text", inConfig.readEntry( "foreground", " " ) );
+ if ( inConfig.hasKey( "background" ) )
+ globalConfig.writeEntry( "Background", inConfig.readEntry( "background", " " ) );
+ if ( inConfig.hasKey( "selectForeground" ) )
+ globalConfig.writeEntry( "HighlightedText", inConfig.readEntry( "selectForeground", " " ) );
+ if ( inConfig.hasKey( "selectBackground" ) )
+ globalConfig.writeEntry( "Highlight", inConfig.readEntry( "selectBackground", " " ) );
+ if ( inConfig.hasKey( "windowForeground" ) )
+ globalConfig.writeEntry( "Text", inConfig.readEntry( "windowForeground", " " ) );
+ if ( inConfig.hasKey( "windowBackground" ) )
+ globalConfig.writeEntry( "Base", inConfig.readEntry( "windowBackground", " " ) );
+
+ // Keep track of the current theme so that we can select the right one
+ // in the KControl module.
+ globalConfig.writeEntry ( "CurrentTheme", file );
+
+ globalConfig.write();
+#endif
+}
+
+OThemeBase::~OThemeBase()
+{
+ int i;
+ for ( i = 0; i < WIDGETS; ++i ) {
+ if ( !duplicate[ i ] ) {
+ if ( images[ i ] )
+ delete images[ i ];
+ if ( pixmaps[ i ] )
+ delete pixmaps[ i ];
+ }
+ if ( !pbDuplicate[ i ] && pbPixmaps[ i ] )
+ delete pbPixmaps[ i ];
+ if ( colors[ i ] )
+ delete( colors[ i ] );
+ if ( grLowColors[ i ] )
+ delete( grLowColors[ i ] );
+ if ( grHighColors[ i ] )
+ delete( grHighColors[ i ] );
+ }
+ delete cache;
+}
+
+QImage* OThemeBase::loadImage( QString &name )
+{
+ QImage * image = new QImage;
+ QString path = configFilePath + "/pixmaps/" + name;
+ image->load( path );
+ if ( !image->isNull() )
+ return ( image );
+ qDebug ( "OThemeBase: Unable to load image %s\n", name.ascii ( ) );
+ delete image;
+ return ( NULL );
+}
+
+OThemePixmap* OThemeBase::loadPixmap( QString &name )
+{
+ OThemePixmap * pixmap = new OThemePixmap( false );
+ QString path = configFilePath + "/pixmaps/" + name;
+ pixmap->load( path );
+ if ( !pixmap->isNull() )
+ return pixmap;
+ qDebug ( "OThemeBase: Unable to load pixmap %s\n", name.ascii() );
+ delete pixmap;
+ return ( NULL );
+}
+
+OThemePixmap* OThemeBase::scale( int w, int h, WidgetType widget )
+{
+ if ( scaleHints[ widget ] == FullScale ) {
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ||
+ pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->pixmap( w, h, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale,
+ widget );
+ else
+ qDebug( "We would have inserted a null pixmap!\n" );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget );
+ QImage tmpImg = images[ widget ] ->smoothScale( w, h );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->convertFromImage( tmpImg );
+ if ( blends[ widget ] != 0.0 )
+ blend( widget );
+ }
+ }
+ }
+ else if ( scaleHints[ widget ] == HorizontalScale ) {
+ if ( pixmaps[ widget ] ->width() != w ) {
+ OThemePixmap * cachePix = cache->horizontalPixmap( w, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::HorizontalScale, widget );
+ else
+ qDebug ( "We would have inserted a null pixmap!\n" );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ cache->insert( pixmaps[ widget ], OThemeCache::HorizontalScale, widget );
+ QImage tmpImg = images[ widget ] ->
+ smoothScale( w, images[ widget ] ->height() );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->convertFromImage( tmpImg );
+ if ( blends[ widget ] != 0.0 )
+ blend( widget );
+ }
+ }
+ }
+ else if ( scaleHints[ widget ] == VerticalScale ) {
+ if ( pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->verticalPixmap( w, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, widget );
+ else
+ qDebug ( "We would have inserted a null pixmap!\n" );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, widget );
+ QImage tmpImg =
+ images[ widget ] ->smoothScale( images[ widget ] ->width(), h );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->convertFromImage( tmpImg );
+ if ( blends[ widget ] != 0.0 )
+ blend( widget );
+ }
+ }
+ }
+ // If blended tile here so the blend is scaled properly
+ else if ( scaleHints[ widget ] == TileScale && blends[ widget ] != 0.0 ) {
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ||
+ pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->pixmap( w, h, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget );
+ QPixmap tile;
+ tile.convertFromImage( *images[ widget ] );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->resize( w, h );
+ QPainter p( pixmaps[ widget ] );
+ p.drawTiledPixmap( 0, 0, w, h, tile );
+ if ( blends[ widget ] != 0.0 )
+ blend( widget );
+ }
+ }
+ }
+ return ( pixmaps[ widget ] );
+}
+
+OThemePixmap* OThemeBase::scaleBorder( int w, int h, WidgetType widget )
+{
+ OThemePixmap * pixmap = NULL;
+ if ( !pbPixmaps[ widget ] && !pbWidth[ widget ] )
+ return ( NULL );
+ pixmap = cache->pixmap( w, h, widget, true );
+ if ( pixmap ) {
+ pixmap = new OThemePixmap( *pixmap );
+ }
+ else {
+ pixmap = new OThemePixmap();
+ pixmap->resize( w, h );
+ QBitmap mask;
+ mask.resize( w, h );
+ mask.fill( color0 );
+ QPainter mPainter;
+ mPainter.begin( &mask );
+
+ QPixmap *tmp = borderPixmap( widget ) ->border( OThemePixmap::TopLeft );
+ const QBitmap *srcMask = tmp->mask();
+ int bdWidth = tmp->width();
+
+ bitBlt( pixmap, 0, 0, tmp, 0, 0, bdWidth, bdWidth,
+ Qt::CopyROP, false );
+ if ( srcMask )
+ bitBlt( &mask, 0, 0, srcMask, 0, 0, bdWidth, bdWidth,
+ Qt::CopyROP, false );
+ else
+ mPainter.fillRect( 0, 0, bdWidth, bdWidth, color1 );
+
+
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::TopRight );
+ srcMask = tmp->mask();
+ bitBlt( pixmap, w - bdWidth, 0, tmp, 0, 0, bdWidth,
+ bdWidth, Qt::CopyROP, false );
+ if ( srcMask )
+ bitBlt( &mask, w - bdWidth, 0, srcMask, 0, 0, bdWidth,
+ bdWidth, Qt::CopyROP, false );
+ else
+ mPainter.fillRect( w - bdWidth, 0, bdWidth, bdWidth, color1 );
+
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::BottomLeft );
+ srcMask = tmp->mask();
+ bitBlt( pixmap, 0, h - bdWidth, tmp, 0, 0, bdWidth,
+ bdWidth, Qt::CopyROP, false );
+ if ( srcMask )
+ bitBlt( &mask, 0, h - bdWidth, srcMask, 0, 0, bdWidth,
+ bdWidth, Qt::CopyROP, false );
+ else
+ mPainter.fillRect( 0, h - bdWidth, bdWidth, bdWidth, color1 );
+
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::BottomRight );
+ srcMask = tmp->mask();
+ bitBlt( pixmap, w - bdWidth, h - bdWidth, tmp, 0, 0,
+ bdWidth, bdWidth, Qt::CopyROP, false );
+ if ( srcMask )
+ bitBlt( &mask, w - bdWidth, h - bdWidth, srcMask, 0, 0,
+ bdWidth, bdWidth, Qt::CopyROP, false );
+ else
+ mPainter.fillRect( w - bdWidth, h - bdWidth, bdWidth, bdWidth, color1 );
+
+ QPainter p;
+ p.begin( pixmap );
+ if ( w - bdWidth * 2 > 0 ) {
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::Top );
+ srcMask = tmp->mask();
+ p.drawTiledPixmap( bdWidth, 0, w - bdWidth * 2, bdWidth, *tmp );
+ if ( srcMask )
+ mPainter.drawTiledPixmap( bdWidth, 0, w - bdWidth * 2, bdWidth, *srcMask );
+ else
+ mPainter.fillRect( bdWidth, 0, w - bdWidth * 2, bdWidth, color1 );
+
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::Bottom );
+ srcMask = tmp->mask();
+ p.drawTiledPixmap( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth,
+ *tmp );
+ if ( srcMask )
+ mPainter.drawTiledPixmap( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, *srcMask );
+ else
+ mPainter.fillRect( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth,
+ color1 );
+ }
+ if ( h - bdWidth * 2 > 0 ) {
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::Left );
+ srcMask = tmp->mask();
+ p.drawTiledPixmap( 0, bdWidth, bdWidth, h - bdWidth * 2, *tmp );
+ if ( srcMask )
+ mPainter.drawTiledPixmap( 0, bdWidth, bdWidth, h - bdWidth * 2, *srcMask );
+ else
+ mPainter.fillRect( 0, bdWidth, bdWidth, h - bdWidth * 2, color1 );
+
+ tmp = borderPixmap( widget ) ->border( OThemePixmap::Right );
+ srcMask = tmp->mask();
+ p.drawTiledPixmap( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2,
+ *tmp );
+ if ( srcMask )
+ mPainter.drawTiledPixmap( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, *srcMask );
+ else
+ mPainter.fillRect( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, color1 );
+ }
+ p.end();
+ mPainter.end();
+ pixmap->setMask( mask );
+ cache->insert( pixmap, OThemeCache::FullScale, widget, true );
+ if ( !pixmap->mask() )
+ qDebug ( "No mask for border pixmap!\n" );
+ }
+ return ( pixmap );
+}
+
+
+OThemePixmap* OThemeBase::blend( WidgetType widget )
+{
+ OGfxEffect::GradientType g;
+ switch ( gradients[ widget ] ) {
+ case GrHorizontal:
+ g = OGfxEffect::HorizontalGradient;
+ break;
+ case GrVertical:
+ g = OGfxEffect::VerticalGradient;
+ break;
+ case GrPyramid:
+ g = OGfxEffect::PyramidGradient;
+ break;
+ case GrRectangle:
+ g = OGfxEffect::RectangleGradient;
+ break;
+ case GrElliptic:
+ g = OGfxEffect::EllipticGradient;
+ break;
+ default:
+ g = OGfxEffect::DiagonalGradient;
+ break;
+ }
+ OGfxEffect::blend( *pixmaps[ widget ], blends[ widget ], *grLowColors[ widget ],
+ g, false );
+ return ( pixmaps[ widget ] );
+}
+
+OThemePixmap* OThemeBase::gradient( int w, int h, WidgetType widget )
+{
+ if ( gradients[ widget ] == GrVertical ) {
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->verticalPixmap( h, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale,
+ widget );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale,
+ widget );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->resize( w, h );
+ OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ],
+ *grLowColors[ widget ],
+ OGfxEffect::VerticalGradient );
+ }
+ }
+ }
+ else if ( gradients[ widget ] == GrHorizontal ) {
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ) {
+ OThemePixmap * cachePix = cache->horizontalPixmap( w, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ],
+ OThemeCache::HorizontalScale, widget );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ],
+ OThemeCache::HorizontalScale, widget );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->resize( w, h );
+ OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ],
+ *grLowColors[ widget ],
+ OGfxEffect::HorizontalGradient );
+ }
+ }
+ }
+ else if ( gradients[ widget ] == GrReverseBevel ) {
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ||
+ pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->pixmap( w, h, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale,
+ widget );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale,
+ widget );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->resize( w, h );
+
+ QPixmap s;
+ int offset = decoWidth( widget );
+ s.resize( w - offset * 2, h - offset * 2 );
+ QColor lc( *grLowColors[ widget ] );
+ QColor hc( *grHighColors[ widget ] );
+ if ( bevelContrast( widget ) ) {
+ int bc = bevelContrast( widget );
+ // want single increments, not factors like light()/dark()
+ lc.setRgb( lc.red() - bc, lc.green() - bc, lc.blue() - bc );
+ hc.setRgb( hc.red() + bc, hc.green() + bc, hc.blue() + bc );
+ }
+ OGfxEffect::gradient( *pixmaps[ widget ],
+ lc, hc,
+ OGfxEffect::DiagonalGradient );
+ OGfxEffect::gradient( s, *grHighColors[ widget ],
+ *grLowColors[ widget ],
+ OGfxEffect::DiagonalGradient );
+ bitBlt( pixmaps[ widget ], offset, offset, &s, 0, 0, w - offset * 2,
+ h - offset * 2, Qt::CopyROP );
+ }
+ }
+ }
+ else {
+ OGfxEffect::GradientType g;
+ switch ( gradients[ widget ] ) {
+ case GrPyramid:
+ g = OGfxEffect::PyramidGradient;
+ break;
+ case GrRectangle:
+ g = OGfxEffect::RectangleGradient;
+ break;
+ case GrElliptic:
+ g = OGfxEffect::EllipticGradient;
+ break;
+ default:
+ g = OGfxEffect::DiagonalGradient;
+ break;
+ }
+ if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ||
+ pixmaps[ widget ] ->height() != h ) {
+ OThemePixmap * cachePix = cache->pixmap( w, h, widget );
+ if ( cachePix ) {
+ cachePix = new OThemePixmap( *cachePix );
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale,
+ widget );
+ pixmaps[ widget ] = cachePix;
+ }
+ else {
+ if ( pixmaps[ widget ] )
+ cache->insert( pixmaps[ widget ], OThemeCache::FullScale,
+ widget );
+ pixmaps[ widget ] = new OThemePixmap;
+ pixmaps[ widget ] ->resize( w, h );
+ OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ],
+ *grLowColors[ widget ], g );
+ }
+ }
+ }
+ return ( pixmaps[ widget ] );
+}
+
+OThemePixmap* OThemeBase::scalePixmap( int w, int h, WidgetType widget )
+{
+
+ if ( gradients[ widget ] && blends[ widget ] == 0.0 )
+ return ( gradient( w, h, widget ) );
+
+ return ( scale( w, h, widget ) );
+}
+
+QColorGroup* OThemeBase::makeColorGroup( QColor &fg, QColor &bg,
+ Qt::GUIStyle )
+{
+ if ( shading == Motif ) {
+ int highlightVal, lowlightVal;
+ highlightVal = 100 + ( 2* /*KGlobalSettings::contrast()*/ 3 + 4 ) * 16 / 10;
+ lowlightVal = 100 + ( ( 2* /*KGlobalSettings::contrast()*/ 3 + 4 ) * 10 );
+ return ( new QColorGroup( fg, bg, bg.light( highlightVal ),
+ bg.dark( lowlightVal ), bg.dark( 120 ),
+ fg, qApp->palette().normal().base() ) );
+ }
+ else
+ return ( new QColorGroup( fg, bg, bg.light( 150 ), bg.dark(),
+ bg.dark( 120 ), fg,
+ qApp->palette().normal().base() ) );
+}
+
+static QColor strToColor ( const QString &str )
+{
+ QString str2 = str. stripWhiteSpace ( );
+
+ if ( str2 [0] == '#' )
+ return QColor ( str2 );
+ else {
+ QStringList sl = QStringList::split ( ',', str2 );
+
+ if ( sl. count ( ) >= 3 )
+ return QColor ( sl [0]. toInt ( ), sl [1]. toInt ( ), sl [2]. toInt ( ));
+ }
+ return QColor ( 0, 0, 0 );
+}
+
+
+
+void OThemeBase::applyMiscResourceGroup( Config *config )
+{
+ config-> setGroup ( "Misc" );
+ QString tmpStr;
+
+ tmpStr = config->readEntry( "SButtonPosition" );
+ if ( tmpStr == "BottomLeft" )
+ sbPlacement = SBBottomLeft;
+ else if ( tmpStr == "BottomRight" )
+ sbPlacement = SBBottomRight;
+ else {
+ if ( tmpStr != "Opposite" && !tmpStr.isEmpty() )
+ qDebug ( "OThemeBase: Unrecognized sb button option %s, using Opposite.\n", tmpStr.ascii() );
+ sbPlacement = SBOpposite;
+ }
+ tmpStr = config->readEntry( "ArrowType" );
+ if ( tmpStr == "Small" )
+ arrowStyle = SmallArrow;
+ else if ( tmpStr == "3D" )
+ arrowStyle = MotifArrow;
+ else {
+ if ( tmpStr != "Normal" && !tmpStr.isEmpty() )
+ qDebug ( "OThemeBase: Unrecognized arrow option %s, using Normal.\n", tmpStr.ascii() );
+ arrowStyle = LargeArrow;
+ }
+ tmpStr = config->readEntry( "ShadeStyle" );
+ if ( tmpStr == "Motif" )
+ shading = Motif;
+ else if ( tmpStr == "Next" )
+ shading = Next;
+ else if ( tmpStr == "KDE" )
+ shading = KDE;
+ else
+ shading = Windows;
+
+ defaultFrame = config->readNumEntry( "FrameWidth", 2 );
+ cacheSize = config->readNumEntry( "Cache", 1024 );
+ sbExtent = config->readNumEntry( "ScrollBarExtent", 16 );
+
+ config-> setGroup ( "General" );
+
+ if ( config-> hasKey ( "foreground" )) fgcolor = strToColor ( config-> readEntry ( "foreground" ));
+ if ( config-> hasKey ( "background" )) bgcolor = strToColor ( config-> readEntry ( "background" ));
+ if ( config-> hasKey ( "selectForeground" )) selfgcolor = strToColor ( config-> readEntry ( "selectForeground" ));
+ if ( config-> hasKey ( "selectBackground" )) selbgcolor = strToColor ( config-> readEntry ( "selectBackground" ));
+ if ( config-> hasKey ( "windowForeground" )) winfgcolor = strToColor ( config-> readEntry ( "windowForeground" ));
+ if ( config-> hasKey ( "windowBackground" )) winbgcolor = strToColor ( config-> readEntry ( "windowBackground" ));
+}
+
+void OThemeBase::readMiscResourceGroup()
+{}
+
+void OThemeBase::applyResourceGroup( Config *config, int i, QString *copyfrom, QString *pixnames, QString *brdnames )
+{
+ QString tmpStr;
+
+ config-> setGroup ( widgetEntries [ i ] );
+
+ tmpStr = config->readEntry( "CopyWidget", "" );
+ copyfrom [ i ] = tmpStr;
+ if ( !tmpStr.isEmpty() )
+ return ;
+
+ // Scale hint
+ tmpStr = config->readEntry( "Scale" );
+ if ( tmpStr == "Full" )
+ scaleHints [ i ] = FullScale;
+ else if ( tmpStr == "Horizontal" )
+ scaleHints [ i ] = HorizontalScale;
+ else if ( tmpStr == "Vertical" )
+ scaleHints [ i ] = VerticalScale;
+ else {
+ if ( tmpStr != "Tile" && !tmpStr.isEmpty() )
+ qDebug ( "OThemeBase: Unrecognized scale option %s, using Tile.\n", tmpStr.ascii() );
+ scaleHints [ i ] = TileScale;
+ }
+
+
+ // Gradient type
+ tmpStr = config->readEntry( "Gradient" );
+ if ( tmpStr == "Diagonal" )
+ gradients [ i ] = GrDiagonal;
+ else if ( tmpStr == "Horizontal" )
+ gradients [ i ] = GrHorizontal;
+ else if ( tmpStr == "Vertical" )
+ gradients [ i ] = GrVertical;
+ else if ( tmpStr == "Pyramid" )
+ gradients [ i ] = GrPyramid;
+ else if ( tmpStr == "Rectangle" )
+ gradients [ i ] = GrRectangle;
+ else if ( tmpStr == "Elliptic" )
+ gradients [ i ] = GrElliptic;
+ else if ( tmpStr == "ReverseBevel" )
+ gradients [ i ] = GrReverseBevel;
+ else {
+ if ( tmpStr != "None" && !tmpStr.isEmpty() )
+ qDebug ( "OThemeBase: Unrecognized gradient option %s, using None.\n", tmpStr.ascii() );
+ gradients [ i ] = GrNone;
+ }
+
+ // Blend intensity
+ blends[ i ] = config->readEntry( "BlendIntensity", "0.0" ).toDouble();
+
+ // Bevel contrast
+ bContrasts[ i ] = config->readNumEntry( "BevelContrast", 0 );
+
+ // Border width
+ borders [ i ] = config->readNumEntry( "Border", 1 );
+
+ // Highlight width
+ highlights [ i ] = config->readNumEntry( "Highlight", 1 );
+
+ // Gradient low color or blend background
+ if ( config->hasKey( "GradientLow" ) && ( gradients[ i ] != GrNone || blends[ i ] != 0.0 ))
+ grLowColors[ i ] = new QColor( strToColor ( config->readEntry( "GradientLow", qApp->palette().normal().background().name() )));
+ else
+ grLowColors[ i ] = NULL;
+
+
+ // Gradient high color
+ if ( config->hasKey( "GradientHigh" ) && ( gradients[ i ] != GrNone ))
+ grHighColors[ i ] = new QColor( strToColor ( config->readEntry( "GradientHigh", qApp->palette().normal().background().name() )));
+ else
+ grHighColors[ i ] = NULL;
+
+ // Extended color attributes
+ if ( config->hasKey( "Foreground" ) || config->hasKey( "Background" ) ) {
+ QColor bg = strToColor( config->readEntry( "Background", qApp->palette().normal().background().name() ));
+ QColor fg = strToColor( config->readEntry( "Foreground", qApp->palette().normal().foreground().name() ));
+
+ colors[ i ] = makeColorGroup( fg, bg, Qt::WindowsStyle );
+ }
+ else
+ colors[ i ] = NULL;
+
+ // Pixmap
+ tmpStr = config->readEntry( "Pixmap", "" );
+ pixnames[ i ] = tmpStr;
+ duplicate[ i ] = false;
+ pixmaps[ i ] = NULL;
+ images[ i ] = NULL;
+
+
+ // Pixmap border
+ tmpStr = config->readEntry( "PixmapBorder", "" );
+ brdnames[ i ] = tmpStr;
+ pbDuplicate[ i ] = false;
+ pbPixmaps[ i ] = NULL;
+ pbWidth[ i ] = 0;
+ if ( !tmpStr.isEmpty() ) {
+ pbWidth[ i ] = config->readNumEntry( "PixmapBWidth", 0 );
+ if ( pbWidth[ i ] == 0 ) {
+ qDebug ( "OThemeBase: No border width specified for pixmapped border widget %s\n", widgetEntries[ i ] );
+ qDebug ( "OThemeBase: Using default of 2.\n" );
+ pbWidth[ i ] = 2;
+ }
+ }
+
+
+ // Various widget specific settings. This was more efficent when bunched
+ // together in the misc group, but this makes an easier to read config.
+ if ( i == SliderGroove )
+ roundedSlider = config->readBoolEntry( "SmallGroove", false );
+ else if ( i == ActiveTab || i == InactiveTab )
+ aTabLine = iTabLine = config->readBoolEntry( "BottomLine", true );
+ else if ( i == Splitter )
+ splitterWidth = config->readNumEntry( "Width", 10 );
+ else if ( i == ComboBox || i == ComboBoxDown ) {
+ roundedCombo = config->readBoolEntry( "Round", false );
+ }
+ else if ( i == PushButton || i == PushButtonDown ) {
+ btnXShift = config->readNumEntry( "XShift", 0 );
+ btnYShift = config->readNumEntry( "YShift", 0 );
+ focus3D = config->readBoolEntry( "3DFocusRect", false );
+ focus3DOffset = config->readBoolEntry( "3DFocusOffset", 0 );
+ roundedButton = config->readBoolEntry( "Round", false );
+ }
+}
+
+
+void OThemeBase::readResourceGroup( int i, QString *copyfrom, QString *pixnames, QString *brdnames,
+ bool *loadArray )
+{
+ if ( loadArray[ i ] == true ) {
+ return ; // already been preloaded.
+ }
+
+ int tmpVal;
+ QString tmpStr;
+
+ tmpStr = copyfrom [ i ];
+ if ( !tmpStr.isEmpty() ) { // Duplicate another widget's config
+ int sIndex;
+ loadArray[ i ] = true;
+ for ( sIndex = 0; sIndex < WIDGETS; ++sIndex ) {
+ if ( tmpStr == widgetEntries[ sIndex ] ) {
+ if ( !loadArray[ sIndex ] ) // hasn't been loaded yet
+ readResourceGroup( sIndex, copyfrom, pixnames, brdnames,
+ loadArray );
+ break;
+ }
+ }
+ if ( loadArray[ sIndex ] ) {
+ copyWidgetConfig( sIndex, i, pixnames, brdnames );
+ }
+ else
+ qDebug ( "OThemeBase: Unable to identify source widget for %s\n", widgetEntries[ i ] );
+ return ;
+ }
+ // special inheritance for disabled arrows (these are tri-state unlike
+ // the rest of what we handle).
+ for ( tmpVal = DisArrowUp; tmpVal <= DisArrowRight; ++tmpVal ) {
+ if ( tmpVal == i ) {
+ tmpStr = pixnames [ i ];
+ if ( tmpStr.isEmpty() ) {
+ copyWidgetConfig( ArrowUp + ( tmpVal - DisArrowUp ), i, pixnames,
+ brdnames );
+ return ;
+ }
+ }
+ }
+
+ // Pixmap
+ int existing;
+ // Scan for duplicate pixmaps(two identical pixmaps, tile scale, no blend,
+ // no pixmapped border)
+ if ( !pixnames [ i ].isEmpty() ) {
+ for ( existing = 0; existing < i; ++existing ) {
+ if ( pixnames[ i ] == pixnames[ existing ] && scaleHints[ i ] == TileScale &&
+ scaleHints[ existing ] == TileScale && blends[ existing ] == 0.0 &&
+ blends[ i ] == 0.0 ) {
+ pixmaps[ i ] = pixmaps[ existing ];
+ duplicate[ i ] = true;
+ break;
+ }
+ }
+ }
+ // load
+ if ( !duplicate[ i ] && !pixnames[ i ].isEmpty() ) {
+ pixmaps[ i ] = loadPixmap( pixnames[ i ] );
+ // load and save images for scaled/blended widgets for speed.
+ if ( scaleHints[ i ] == TileScale && blends[ i ] == 0.0 )
+ images[ i ] = NULL;
+ else
+ images[ i ] = loadImage( pixnames[ i ] );
+ }
+
+ // Pixmap border
+ if ( !brdnames [ i ]. isEmpty () ) {
+ // duplicate check
+ for ( existing = 0; existing < i; ++existing ) {
+ if ( brdnames [i] == brdnames[ existing ] ) {
+ pbPixmaps[ i ] = pbPixmaps[ existing ];
+ pbDuplicate[ i ] = true;
+ break;
+ }
+ }
+ }
+ // load
+ if ( !pbDuplicate[ i ] && !brdnames[ i ].isEmpty() )
+ pbPixmaps[ i ] = loadPixmap( brdnames[ i ] );
+
+ if ( pbPixmaps[ i ] && !pbDuplicate[ i ] )
+ generateBorderPix( i );
+
+ loadArray[ i ] = true;
+}
+
+
+OThemePixmap::OThemePixmap( bool timer )
+ : QPixmap()
+{
+ if(timer){
+ t = new QTime;
+ t->start();
+ }
+ else
+ t = NULL;
+ int i;
+ for ( i = 0; i < 8; ++i )
+ b[ i ] = NULL;
+}
+
+OThemePixmap::OThemePixmap( const OThemePixmap &p )
+ : QPixmap( p )
+{
+ if(p.t){
+ t = new QTime;
+ t->start();
+ }
+ else
+ t = NULL;
+ int i;
+ for ( i = 0; i < 8; ++i )
+ if ( p.b[ i ] )
+ b[ i ] = new QPixmap( *p.b[ i ] );
+ else
+ b[ i ] = NULL;
+}
+
+
+
+OThemePixmap::~OThemePixmap()
+{
+ if(t)
+ delete t;
+ int i;
+ for ( i = 0; i < 8; ++i )
+ if ( b[ i ] )
+ delete b[ i ];
+}
+
+OThemeCache::OThemeCache( int maxSize, QObject *parent, const char *name )
+ : QObject( parent, name )
+{
+ cache.setMaxCost( maxSize * 1024 );
+ cache.setAutoDelete( true );
+ flushTimer.start(300000); // 5 minutes
+ connect(&flushTimer, SIGNAL(timeout()), SLOT(flushTimeout()));
+}
+
+void OThemeCache::flushTimeout()
+{
+ QIntCacheIterator<OThemePixmap> it( cache );
+ while ( it.current() ) {
+ if ( it.current() ->isOld() )
+ cache.remove( it.currentKey() );
+ else
+ ++it;
+ }
+}
+
+OThemePixmap* OThemeCache::pixmap( int w, int h, int widgetID, bool border,
+ bool mask )
+{
+
+ kthemeKey key;
+ key.cacheKey = 0; // shut up, gcc
+ key.data.id = widgetID;
+ key.data.width = w;
+ key.data.height = h;
+ key.data.border = border;
+ key.data.mask = mask;
+
+ OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey );
+ if ( pix )
+ pix->updateAccessed();
+ return ( pix );
+}
+
+OThemePixmap* OThemeCache::horizontalPixmap( int w, int widgetID )
+{
+ kthemeKey key;
+ key.cacheKey = 0; // shut up, gcc
+ key.data.id = widgetID;
+ key.data.width = w;
+ key.data.height = 0;
+ key.data.border = false;
+ key.data.mask = false;
+ OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey );
+ if ( pix )
+ pix->updateAccessed();
+ return ( pix );
+}
+
+OThemePixmap* OThemeCache::verticalPixmap( int h, int widgetID )
+{
+ kthemeKey key;
+ key.cacheKey = 0; // shut up, gcc
+ key.data.id = widgetID;
+ key.data.width = 0;
+ key.data.height = h;
+ key.data.border = false;
+ key.data.mask = false;
+ OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey );
+ if ( pix )
+ pix->updateAccessed();
+ return ( pix );
+}
+
+bool OThemeCache::insert( OThemePixmap *pixmap, ScaleHint scale, int widgetID,
+ bool border, bool mask )
+{
+ kthemeKey key;
+ key.cacheKey = 0; // shut up, gcc
+ key.data.id = widgetID;
+ key.data.width = ( scale == FullScale || scale == HorizontalScale ) ?
+ pixmap->width() : 0;
+ key.data.height = ( scale == FullScale || scale == VerticalScale ) ?
+ pixmap->height() : 0;
+ key.data.border = border;
+ key.data.mask = mask;
+
+ if ( cache.find( ( unsigned long ) key.cacheKey, true ) != NULL ) {
+ return ( true ); // a pixmap of this scale is already in there
+ }
+ return ( cache.insert( ( unsigned long ) key.cacheKey, pixmap,
+ pixmap->width() * pixmap->height() * pixmap->depth() / 8 ) );
+}
+
+//#include "kthemebase.moc"
diff --git a/noncore/styles/theme/othemebase.h b/noncore/styles/theme/othemebase.h
new file mode 100644
index 0000000..e691692
--- a/dev/null
+++ b/noncore/styles/theme/othemebase.h
@@ -0,0 +1,739 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef __OTHEMEBASE_H
+#define __OTHEMEBASE_H
+
+#include <qdatetime.h>
+#include <qtimer.h>
+#include <qwindowsstyle.h>
+#include <qpixmap.h>
+#include <qpe/config.h>
+#include <qimage.h>
+#include <qintcache.h>
+#include <qstring.h>
+#include <qpalette.h>
+
+#define WIDGETS 54
+
+/**
+ * This class adds simple time management to QPixmap for use in flushing
+ * OThemeCache.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ */
+class OThemePixmap : public QPixmap
+{
+public:
+ enum BorderType{Top = 0, Bottom, Left, Right, TopLeft, TopRight, BottomLeft,
+ BottomRight};
+
+ OThemePixmap( bool timer = true );
+ OThemePixmap( const OThemePixmap &p );
+ ~OThemePixmap();
+ QPixmap* border( BorderType type );
+ void setBorder( BorderType type, const QPixmap &p );
+ void updateAccessed();
+ bool isOld();
+protected:
+ QTime *t;
+ QPixmap *b[ 8 ];
+
+private:
+ class OThemePixmapPrivate;
+ OThemePixmapPrivate *d;
+};
+
+inline QPixmap* OThemePixmap::border( BorderType type )
+{
+ return ( b[ type ] );
+}
+
+inline void OThemePixmap::setBorder( BorderType type, const QPixmap &p )
+{
+ if ( b[ type ] ) {
+ qWarning( "OThemePixmap: Overwriting existing border!" );
+ delete( b[ type ] );
+ }
+ b[ type ] = new QPixmap( p );
+}
+
+inline void OThemePixmap::updateAccessed()
+{
+ if (t)
+ t->start();
+}
+
+inline bool OThemePixmap::isOld()
+{
+ return ( t ? t->elapsed() >= 300000 : false );
+}
+
+/**
+ * A very simple pixmap cache for theme plugins. QPixmapCache is not used
+ * since it uses QString keys which are not needed. All the information we
+ * need can be encoded in a numeric key. Using QIntCache instead allows us to
+ * skip the string operations.
+ *
+ * This class is mostly just inline methods that do bit operations on a key
+ * composed of the widget ID, width and/or height, and then calls
+ * QIntCache::find().
+ *
+ * One other thing to note is that full, horizontal, and vertically scaled
+ * pixmaps are not used interchangeably. For example, if you insert a fully
+ * scaled pixmap that is 32x32 then request a horizontally scaled pixmap with
+ * a width of 32, they will not match. This is because a pixmap that has been
+ * inserted into the cache has already been scaled at some point and it is
+ * very likely the vertical height was not originally 32. Thus the pixmap
+ * will be wrong when drawn, even though the horizontal width matches.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ *
+ */
+class OThemeCache : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * The scale hints supported by the cache. Note that Tiled is not here
+ * since tiled pixmaps are kept only once in OThemeBase.
+ */
+ enum ScaleHint{FullScale, HorizontalScale, VerticalScale};
+ /**
+ * The constructor.
+ *
+ * @param maxSize The maximum size of the cache in kilobytes.
+ */
+ OThemeCache( int maxSize, QObject *parent = 0, const char *name = 0 );
+ /**
+ * Inserts a new pixmap into the cache.
+ *
+ * @param pixmap The pixmap to insert.
+ * @param scale The scaling type of the pixmap.
+ * @param widgetID The widget ID of the pixmap, usually from OThemeBase's
+ * WidgetType enum.
+ *
+ * @return True if the insert was successful, false otherwise.
+ */
+ bool insert( OThemePixmap *pixmap, ScaleHint scale, int widgetID,
+ bool border = false, bool mask = false );
+ /**
+ * Returns a fully scaled pixmap.
+ *
+ * @param w The pixmap width to search for.
+ * @param h The pixmap height to search for.
+ * @param widgetID The widget ID to search for.
+ *
+ * @return True if a pixmap matching the width, height, and widget ID of
+ * the pixmap exists, NULL otherwise.
+ */
+ OThemePixmap* pixmap( int w, int h, int widgetID, bool border = false,
+ bool mask = false );
+ /**
+ * Returns a horizontally scaled pixmap.
+ *
+ * @param w The pixmap width to search for.
+ * @param widgetID The widget ID to search for.
+ *
+ * @return True if a pixmap matching the width and widget ID of
+ * the pixmap exists, NULL otherwise.
+ */
+ OThemePixmap* horizontalPixmap( int w, int widgetID );
+ /**
+ * Returns a vertically scaled pixmap.
+ *
+ * @param h The pixmap height to search for.
+ * @param widgetID The widget ID to search for.
+ *
+ * @return True if a pixmap matching the height and widget ID of
+ * the pixmap exists, NULL otherwise.
+ */
+ OThemePixmap* verticalPixmap( int h, int widgetID );
+protected slots:
+ void flushTimeout();
+protected:
+ QIntCache<OThemePixmap> cache;
+ QTimer flushTimer;
+
+private:
+ class OThemeCachePrivate;
+ OThemeCachePrivate *d;
+};
+
+
+/**
+ * This is a base class for KDE themed styles. It implements a cache,
+ * configuration file parsing, pixmap scaling, gradients, and a lot
+ * of inline methods for accessing user specified parameters.
+ *
+ * Note that this class *does not* actually implement any themes. It just
+ * provides the groundwork for doing so. The only reason to use this class
+ * directly is if you plan to reimplement all of the widgets. Otherwise,
+ * refer to OThemeStyle for a fully themed style you can derive from.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ */
+class OThemeBase: public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs a new OThemeBase object.
+ */
+ OThemeBase( const QString &configFile );
+ ~OThemeBase();
+ /**
+ * Describes if a pixmap should be scaled fully, horizontally, vertically,
+ * or not at all and tiled.
+ */
+ enum ScaleHint{FullScale, HorizontalScale, VerticalScale, TileScale};
+ /**
+ * The default arrow types.
+ */
+ enum ArrowStyle{MotifArrow, LargeArrow, SmallArrow};
+ /**
+ * The default frame shading styles.
+ */
+ enum ShadeStyle{Motif, Windows, Next, KDE};
+ /**
+ * The default scrollbar button layout. BottomLeft is like what Next
+ * uses, BottomRight is like Platinum, and Opposite it like Windows and
+ * Motif.
+ */
+ enum SButton{SBBottomLeft, SBBottomRight, SBOpposite};
+ /**
+ * The gradient types. Horizontal is left to right, Vertical is top to
+ * bottom, and diagonal is upper-left to bottom-right.
+ */
+ enum Gradient{GrNone, GrHorizontal, GrVertical, GrDiagonal, GrPyramid,
+ GrRectangle, GrElliptic, GrReverseBevel};
+ /**
+ * This provides a list of widget types that OThemeBase recognizes.
+ */
+ /* Internal note: The order here is important. Some widgets inherit
+ * properties. This is usually for when you have two settings for the
+ * same widget, ie: on(sunken), and off. The on settings will inherit
+ * the properties of the off one when nothing is specified in the config.
+ *
+ * In order to be able to handle this while still having everything in
+ * one group that is easy to loop from we have the following order:
+ * unsunked(off) items, sunken(on)items, and then the ones that don't
+ * matter. INHERIT_ITEMS define the number of widgets that have inheritence
+ * so if 0 == PushButtonOff then INHERIT_ITEMS should == PushButtonOn
+ * and so on. WIDGETS define the total number of widgets.
+ */
+ enum WidgetType{
+ // Off (unsunken widgets)
+ PushButton = 0, ComboBox, HScrollBarSlider, VScrollBarSlider, Bevel,
+ ToolButton, ScrollButton, HScrollDeco, VScrollDeco,
+ ComboDeco, MenuItem, InactiveTab, ArrowUp, ArrowDown, ArrowLeft,
+ ArrowRight,
+ // On (sunken widgets)
+ PushButtonDown, ComboBoxDown, HScrollBarSliderDown,
+ VScrollBarSliderDown, BevelDown, ToolButtonDown, ScrollButtonDown,
+ HScrollDecoDown, VScrollDecoDown, ComboDecoDown, MenuItemDown,
+ ActiveTab, SunkenArrowUp, SunkenArrowDown, SunkenArrowLeft,
+ SunkenArrowRight,
+ // Everything else (indicators must have separate settings)
+ HScrollGroove, VScrollGroove, Slider, SliderGroove, IndicatorOn,
+ IndicatorOff, ExIndicatorOn, ExIndicatorOff, HBarHandle, VBarHandle,
+ ToolBar, Splitter, CheckMark, MenuBar, DisArrowUp, DisArrowDown,
+ DisArrowLeft, DisArrowRight, ProgressBar, ProgressBg, MenuBarItem,
+ Background};
+
+ /**
+ * The scaling type specified by the Config file.
+ *
+ * @param widget A Widgets enum value.
+ *
+ * @return A ScaleHint enum value.
+ */
+ ScaleHint scaleHint( WidgetType widget ) const;
+ /**
+ * The gradient type specified by the KConfig file.
+ *
+ * @param widget A Widgets enum value.
+ *
+ * @return A Gradient enum value.
+ */
+ Gradient gradientHint( WidgetType widget ) const;
+ /**
+ * The color group specified for a given widget.
+ * If a color group is set in the theme configuration
+ * that is used, otherwise defaultColor is returned.
+ *
+ * @param defaultColor The colorGroup to set if one is available.
+ *
+ * @param widget The widget whose color group to retrieve.
+ *
+ */
+ const QColorGroup* colorGroup( const QColorGroup &defaultGroup,
+ WidgetType widget ) const;
+
+ QBrush pixmapBrush( const QColorGroup &group, QColorGroup::ColorRole role,
+ int w, int h, WidgetType widget );
+ /**
+ * True if the widget has a pixmap or gradient specified.
+ */
+ bool isPixmap( WidgetType widget ) const;
+ /**
+ * True if the widget has a color group specified.
+ */
+ bool isColor( WidgetType widget ) const;
+ /**
+ * True if the user specified a 3D focus rectangle
+ */
+ bool is3DFocus() const;
+ /**
+ * If the user specified a 3D focus rectangle, they may also specify an
+ * offset from the default rectangle to use when drawing it. This returns
+ * the specified offset.
+ */
+ int focusOffset() const;
+ /**
+ * The border width of the specified widget.
+ */
+ int borderWidth( WidgetType widget ) const;
+ /**
+ * Pixmap border width of the specified widget.
+ */
+ int pixBorderWidth( WidgetType widget ) const;
+ /**
+ * Returns the border pixmap if enabled for the specified widget. This
+ * will contain the originial pixmap, plus the edges separated in
+ * OThemePixmap::border() if valid. If invalid it will return NULL.
+ */
+ OThemePixmap* borderPixmap( WidgetType widget );
+ /**
+ * The highlight width of the specified widget.
+ */
+ int highlightWidth( WidgetType widget ) const;
+ /**
+ * The border plus highlight width of the widget.
+ */
+ int decoWidth( WidgetType widget ) const;
+ /**
+ * The extent (width for vertical, height for horizontal) requested
+ * for the scrollbars.
+ */
+ int getSBExtent() const;
+ /**
+ * The scrollbar button layout.
+ */
+ SButton scrollBarLayout() const;
+ /**
+ * The arrow type.
+ */
+ ArrowStyle arrowType() const;
+ /**
+ * The shading type.
+ */
+ ShadeStyle shade() const;
+ /**
+ * The frame width.
+ */
+ int frameWidth() const;
+ /**
+ * The splitter width.
+ */
+ int splitWidth() const;
+ /**
+ * The contrast for some bevel effects such as reverse gradient.
+ */
+ int bevelContrast( WidgetType widget ) const;
+ /**
+ * The button text X shift.
+ */
+ int buttonXShift() const;
+ /**
+ * The button text Y shift.
+ */
+ int buttonYShift() const;
+ /**
+ * Returns either the slider length of the slider pixmap if available,
+ * otherwise the length specified in the config file.
+ */
+ int sliderButtonLength() const;
+ /**
+ * True if rounded buttons are requested.
+ */
+ bool roundButton() const;
+ /**
+ * True if rounded comboboxes are requested.
+ */
+ bool roundComboBox() const;
+ /**
+ * True if rounded slider grooves are requested.
+ */
+ bool roundSlider() const;
+ /**
+ * True if a line should be drawn on the bottom of active tabs.
+ */
+ bool activeTabLine() const;
+ /**
+ * True if a line should be drawn on the bottom of inactive tabs.
+ */
+ bool inactiveTabLine() const;
+ /**
+ * Returns the current uncached pixmap for the given widget. This will
+ * usually be either the last scaled or gradient pixmap if those have
+ * been specified in the config file, the original pixmap if not, or NULL
+ * if no pixmap has been specified.
+ */
+ OThemePixmap* uncached( WidgetType widget ) const;
+ /**
+ * Returns the pixmap for the given widget at the specified width and
+ * height. This will return NULL if no pixmap or gradient is specified.
+ * It may also return a different sized pixmap if the scaling
+ * is set to Tiled. When using this method, you should call it using
+ * the needed width and height then use QPainter::drawTiledPixmap to
+ * paint it. Doing this, if the pixmap is scaled it will be the proper
+ * size, otherwise it will be tiled.
+ *
+ * @param w Requested width.
+ * @param h Requested height.
+ * @param widget Widget type.
+ * @return The pixmap or NULL if one is not specified.
+ */
+ virtual OThemePixmap *scalePixmap( int w, int h, WidgetType widget );
+ /**
+ * This method reads a configuration file and applies it to the user's
+ * kstylerc file. It does not signal applications to reload via the
+ * KDEChangeGeneral atom, if you want to do this you must do so yourself.
+ * See kcmdisplay's general.cpp for an example.
+ *
+ * @param file The configuration file to apply.
+ */
+ static void applyConfigFile( const QString &file );
+protected:
+ /**
+ * Returns a QImage for the given widget if the widget is scaled, NULL
+ * otherwise. QImages of the original pixmap are stored for scaled
+ * widgets in order to facilitate fast and accurate smooth-scaling. This
+ * also saves us a conversion from a pixmap to an image then back again.
+ */
+ QImage* image( WidgetType widget ) const;
+ /**
+ * Returns the gradient high color if one is specified, NULL otherwise.
+ */
+ QColor* gradientHigh( WidgetType widget ) const;
+ /**
+ * Returns the gradient low color if one is specified, NULL otherwise.
+ */
+ QColor* gradientLow( WidgetType widget ) const;
+ /**
+ * Reads in all the configuration file entries supported.
+ *
+ * @param colorStyle The style for the color groups. In KDE, colors were
+ * calculated a little differently for Motif vs Windows styles. This
+ * is obsolete.
+ */
+ void readConfig( Qt::GUIStyle colorStyle = Qt::WindowsStyle );
+ void readWidgetConfig( int i, Config *config, QString *pixnames,
+ QString *brdnames, bool *loadArray );
+ void copyWidgetConfig( int sourceID, int destID, QString *pixnames,
+ QString *brdnames );
+ /**
+ * Makes a full color group based on the given foreground and background
+ * colors. This is the same code used by KDE (kapp.cpp) in previous
+ * versions.
+ */
+ QColorGroup* makeColorGroup( QColor &fg, QColor &bg,
+ Qt::GUIStyle style = Qt::WindowsStyle );
+ OThemePixmap* scale( int w, int h, WidgetType widget );
+ OThemePixmap* scaleBorder( int w, int h, WidgetType type );
+ OThemePixmap* gradient( int w, int h, WidgetType widget );
+ OThemePixmap* blend( WidgetType widget );
+ void generateBorderPix( int i );
+ void applyResourceGroup( Config *config, int i, QString *copyfrom, QString *pixnames, QString *brdnames );
+ void applyMiscResourceGroup( Config *config );
+ void readResourceGroup( int i, QString *copyfrom, QString *pixnames, QString *brdnames,
+ bool *loadArray );
+ void readMiscResourceGroup();
+ /**
+ * Attempts to load a pixmap from the default OThemeBase locations.
+ */
+ OThemePixmap* loadPixmap( QString &name );
+ /**
+ * Attempts to load a image from the default OThemeBase locations.
+ */
+ QImage* loadImage( QString &name );
+private:
+ SButton sbPlacement;
+ ArrowStyle arrowStyle;
+ ShadeStyle shading;
+ int defaultFrame;
+ int btnXShift, btnYShift;
+ int sliderLen;
+ int splitterWidth;
+ int focus3DOffset;
+ int sbExtent;
+ bool smallGroove;
+ bool roundedButton, roundedCombo, roundedSlider;
+ bool aTabLine, iTabLine;
+ bool focus3D;
+ OThemeCache *cache;
+ int cacheSize;
+ QString configFileName;
+ QString configFilePath;
+
+protected:
+ QColor fgcolor, bgcolor, selfgcolor, selbgcolor, winfgcolor, winbgcolor;
+
+private:
+ /**
+ * The theme pixmaps. Many of these may be NULL if no pixmap is specified.
+ * There may also be duplicate pixmap pointers if more than one widget
+ * uses the same tiled pixmap. If a pixmap is tiled, it is kept here and
+ * this acts as a cache. Otherwise this will hold whatever the last scaled
+ * pixmap was.
+ */
+ OThemePixmap *pixmaps[ WIDGETS ];
+ /**
+ * The theme images. These are for scaled images and are kept in order
+ * to maintain fast smoothscaling.
+ */
+ QImage *images[ WIDGETS ];
+ /**
+ * The border widths
+ */
+ unsigned char borders[ WIDGETS ];
+ /**
+ * The highlight widths
+ */
+ unsigned char highlights[ WIDGETS ];
+ /**
+ * The scale hints for pixmaps and gradients.
+ */
+ ScaleHint scaleHints[ WIDGETS ];
+ /**
+ * All the color groups.
+ */
+ QColorGroup *colors[ WIDGETS ];
+ /**
+ * Gradient low colors (or blend background).
+ */
+ QColor *grLowColors[ WIDGETS ];
+ /**
+ * Gradient high colors.
+ */
+ QColor *grHighColors[ WIDGETS ];
+ /**
+ * Gradient types.
+ */
+ Gradient gradients[ WIDGETS ];
+ /**
+ * Blend intensity factors
+ */
+ float blends[ WIDGETS ];
+ /**
+ * Bevel contrasts
+ */
+ unsigned char bContrasts[ WIDGETS ];
+ /**
+ * Duplicate pixmap entries (used during destruction).
+ */
+ bool duplicate[ WIDGETS ];
+ /**
+ * Pixmapped border widths
+ */
+ int pbWidth[ WIDGETS ];
+ /**
+ * Pixmapped borders
+ */
+ OThemePixmap *pbPixmaps[ WIDGETS ];
+ /**
+ * Duplicate border pixmapped border entries
+ */
+ bool pbDuplicate[ WIDGETS ];
+
+private:
+ class OThemeBasePrivate;
+ OThemeBasePrivate *d;
+
+};
+
+inline bool OThemeBase::isPixmap( WidgetType widget ) const
+{
+ return ( pixmaps[ widget ] != NULL || gradients[ widget ] != GrNone );
+}
+
+inline bool OThemeBase::isColor( WidgetType widget ) const
+{
+ return ( colors[ widget ] != NULL );
+}
+
+inline bool OThemeBase::is3DFocus() const
+{
+ return ( focus3D );
+}
+
+inline int OThemeBase::focusOffset() const
+{
+ return ( focus3DOffset );
+}
+
+inline int OThemeBase::bevelContrast( WidgetType widget ) const
+{
+ return ( bContrasts[ widget ] );
+}
+
+inline OThemeBase::ScaleHint OThemeBase::scaleHint( WidgetType widget ) const
+{
+ return ( ( widget < WIDGETS ) ? scaleHints[ widget ] : TileScale );
+}
+
+inline OThemeBase::Gradient OThemeBase::gradientHint( WidgetType widget ) const
+{
+ return ( ( widget < WIDGETS ) ? gradients[ widget ] : GrNone );
+}
+
+inline OThemePixmap* OThemeBase::uncached( WidgetType widget ) const
+{
+ return ( pixmaps[ widget ] );
+}
+
+inline QBrush OThemeBase::pixmapBrush( const QColorGroup &group,
+ QColorGroup::ColorRole role,
+ int w, int h, WidgetType widget )
+{
+ if ( pixmaps[ widget ] || images[ widget ] )
+ return ( QBrush( group.color( role ), *scalePixmap( w, h, widget ) ) );
+ else
+ return ( group.color( role ) );
+}
+
+inline const QColorGroup* OThemeBase::colorGroup( const QColorGroup &defaultGroup,
+ WidgetType widget ) const
+{
+ return ( ( colors[ widget ] ) ? colors[ widget ] : &defaultGroup );
+}
+
+inline int OThemeBase::borderWidth( WidgetType widget ) const
+{
+ return ( pbWidth[ widget ] ? pbWidth[ widget ] : borders[ widget ] );
+}
+
+inline int OThemeBase::pixBorderWidth( WidgetType widget ) const
+{
+ return ( pbWidth[ widget ] );
+}
+
+inline int OThemeBase::highlightWidth( WidgetType widget ) const
+{
+ return ( pbWidth[ widget ] ? 0 : highlights[ widget ] );
+}
+
+inline int OThemeBase::decoWidth( WidgetType widget ) const
+{
+ return ( pbWidth[ widget ] ? pbWidth[ widget ] : borders[ widget ] + highlights[ widget ] );
+}
+
+inline QColor* OThemeBase::gradientHigh( WidgetType widget ) const
+{
+ return ( grHighColors[ widget ] );
+}
+
+inline QColor* OThemeBase::gradientLow( WidgetType widget ) const
+{
+ return ( grLowColors[ widget ] );
+}
+
+inline QImage* OThemeBase::image( WidgetType widget ) const
+{
+ return ( images[ widget ] );
+}
+
+inline OThemeBase::SButton OThemeBase::scrollBarLayout() const
+{
+ return ( sbPlacement );
+}
+
+inline OThemeBase::ArrowStyle OThemeBase::arrowType() const
+{
+ return ( arrowStyle );
+}
+
+inline OThemeBase::ShadeStyle OThemeBase::shade() const
+{
+ return ( shading );
+}
+
+inline int OThemeBase::frameWidth() const
+{
+ return ( defaultFrame );
+}
+
+inline int OThemeBase::buttonXShift() const
+{
+ return ( btnXShift );
+}
+
+inline int OThemeBase::splitWidth() const
+{
+ return ( splitterWidth );
+}
+
+inline int OThemeBase::buttonYShift() const
+{
+ return ( btnYShift );
+}
+
+inline int OThemeBase::sliderButtonLength() const
+{
+ if ( isPixmap( Slider ) )
+ return ( uncached( Slider ) ->width() );
+ else
+ return ( sliderLen );
+}
+
+inline bool OThemeBase::roundButton() const
+{
+ return ( roundedButton );
+}
+
+inline bool OThemeBase::roundComboBox() const
+{
+ return ( roundedCombo );
+}
+
+inline bool OThemeBase::roundSlider() const
+{
+ return ( roundedSlider );
+}
+
+inline bool OThemeBase::activeTabLine() const
+{
+ return ( aTabLine );
+}
+
+inline bool OThemeBase::inactiveTabLine() const
+{
+ return ( iTabLine );
+}
+
+inline int OThemeBase::getSBExtent() const
+{
+ return ( sbExtent );
+}
+
+inline OThemePixmap* OThemeBase::borderPixmap( WidgetType widget )
+{
+ return ( pbPixmaps[ widget ] );
+}
+
+#endif
diff --git a/noncore/styles/theme/othemestyle.cpp b/noncore/styles/theme/othemestyle.cpp
new file mode 100644
index 0000000..61127b8
--- a/dev/null
+++ b/noncore/styles/theme/othemestyle.cpp
@@ -0,0 +1,1532 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "othemestyle.h"
+#include "othemebase.h"
+#include <qpe/qpeapplication.h>
+#include <qbitmap.h>
+#define INCLUDE_MENUITEM_DEF
+#include <qmenudata.h>
+#include <qpopupmenu.h>
+#include <qtabbar.h>
+#include <qglobal.h>
+
+#include <limits.h>
+#include <stdio.h>
+
+#define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2)
+
+OThemeStyle::OThemeStyle( const QString &configFile )
+ : OThemeBase( configFile )
+{
+ setScrollBarExtent( getSBExtent(), getSBExtent() );
+ setButtonDefaultIndicatorWidth( 0 ); // We REALLY should support one, see drawPushButton() below!
+}
+
+OThemeStyle::~OThemeStyle()
+{}
+
+void OThemeStyle::polish( QApplication * /*app*/ )
+{}
+
+void OThemeStyle::polish( QPalette &p )
+{
+ oldPalette = p;
+
+ QColor bg = oldPalette. color ( QPalette::Normal, QColorGroup::Background );
+
+ if ( bgcolor. isValid ( ))
+ bg = bgcolor;
+
+ if ( isColor ( Background ))
+ bg = colorGroup ( oldPalette. active ( ), Background )-> background ( );
+
+ p = QPalette ( bg, bg );
+
+ if ( isPixmap( Background ) )
+ p. setBrush ( QColorGroup::Background, QBrush ( bg, *uncached ( Background )));
+
+ if ( fgcolor. isValid ( )) {
+ p. setColor ( QColorGroup::Foreground, fgcolor );
+ p. setColor ( QColorGroup::ButtonText, fgcolor );
+ }
+ if ( selfgcolor. isValid ( ))
+ p. setColor ( QColorGroup::HighlightedText, selfgcolor );
+ if ( selbgcolor. isValid ( ))
+ p. setColor ( QColorGroup::Highlight, selbgcolor );
+ if ( winfgcolor. isValid ( ))
+ p. setColor ( QColorGroup::Text, winfgcolor );
+ if ( winbgcolor. isValid ( ))
+ p. setColor ( QColorGroup::Base, winbgcolor );
+
+}
+
+
+void OThemeStyle::unPolish( QApplication *app )
+{
+ app->setPalette( oldPalette, true );
+}
+
+void OThemeStyle::polish( QWidget *w )
+{
+ if ( !w->isTopLevel() ) {
+ if ( w->inherits( "QGroupBox" )
+ || w->inherits( "QTabWidget" ) ) {
+ w->setAutoMask( TRUE );
+ return ;
+ }
+ if ( w->inherits( "QLabel" )
+ || w->inherits( "QSlider" )
+ || w->inherits( "QButton" )
+ || w->inherits( "QProgressBar" )
+ ) {
+ w->setBackgroundOrigin( QWidget::ParentOrigin );
+ }
+ }
+ if ( w->inherits( "QPopupMenu" ) ) {
+ popupPalette = w->palette();
+ if ( isColor( MenuItem ) || isColor( MenuItemDown ) ) {
+ QPalette newPal( w->palette() );
+ w->setPalettePropagation( QWidget::SamePalette );
+ if ( isColor( MenuItem ) ) {
+ newPal.setNormal( *colorGroup( newPal.normal(), MenuItem ) );
+ newPal.setDisabled( *colorGroup( newPal.normal(), MenuItem ) );
+ }
+ if ( isColor( MenuItemDown ) )
+ newPal.setActive( *colorGroup( newPal.active(), MenuItemDown ) );
+ w->setPalette( newPal );
+ }
+ }
+ if ( w->inherits( "QCheckBox" ) ) {
+ if ( isColor( IndicatorOff ) || isColor( IndicatorOn ) ) {
+ QPalette newPal( w->palette() );
+ w->setPalettePropagation( QWidget::SamePalette );
+ if ( isColor( IndicatorOff ) ) {
+ newPal.setNormal( *colorGroup( newPal.normal(), IndicatorOff ) );
+ newPal.setDisabled( *colorGroup( newPal.normal(), IndicatorOff ) );
+ }
+ if ( isColor( IndicatorOn ) )
+ newPal.setActive( *colorGroup( newPal.active(), IndicatorOn ) );
+ w->setPalette( newPal );
+ }
+ }
+ if ( w->inherits( "QRadioButton" ) ) {
+ if ( isColor( ExIndicatorOff ) || isColor( ExIndicatorOn ) ) {
+ QPalette newPal( w->palette() );
+ w->setPalettePropagation( QWidget::SamePalette );
+ if ( isColor( ExIndicatorOff ) ) {
+ newPal.setNormal( *colorGroup( newPal.normal(), ExIndicatorOff ) );
+ newPal.setDisabled( *colorGroup( newPal.normal(),
+ ExIndicatorOff ) );
+ }
+ if ( isColor( ExIndicatorOn ) )
+ newPal.setActive( *colorGroup( newPal.active(), ExIndicatorOn ) );
+ w->setPalette( newPal );
+ }
+ }
+}
+
+void OThemeStyle::unPolish( QWidget* w )
+{
+ if ( !w->isTopLevel() ) {
+ if ( w->inherits( "QGroupBox" )
+ || w->inherits( "QTabWidget" ) ) {
+ w->setAutoMask( FALSE );
+ return ;
+ }
+ if ( w->inherits( "QLabel" )
+ || w->inherits( "QSlider" )
+ || w->inherits( "QButton" )
+ || w->inherits( "QProgressBar" )
+ ) {
+ w->setBackgroundOrigin( QWidget::WidgetOrigin );
+ }
+ }
+ if ( w->inherits( "QPopupMenu" ) )
+ w->unsetPalette();
+ if ( w->inherits( "QCheckBox" ) )
+ w->unsetPalette();
+ if ( w->inherits( "QRadioButton" ) )
+ w->unsetPalette();
+}
+
+void OThemeStyle::drawBaseButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken, bool
+ rounded, WidgetType type, const QBrush * )
+{
+ int offset = borderPixmap( type ) ? 0 : decoWidth( type );
+ QPen oldPen = p->pen();
+
+ // handle reverse bevel here since it uses decowidth differently
+ if ( gradientHint( type ) == GrReverseBevel ) {
+ int i;
+ bitBlt( p->device(), x, y, scalePixmap( w, h, type ), 0, 0, w, h,
+ Qt::CopyROP, true );
+ p->setPen( g.text() );
+ for ( i = 0; i < borderWidth( type ); ++i, ++x, ++y, w -= 2, h -= 2 )
+ p->drawRect( x, y, w, h );
+ }
+ // same with KDE style borders
+ else if ( !borderPixmap( type ) && shade() == KDE ) {
+ qDrawWinButton( p, x, y, w, h, g, sunken );
+ if ( isPixmap( type ) )
+ p->drawTiledPixmap( x + 4, y + 4, w - 6, h - 6,
+ *scalePixmap( w - 6, h - 6,
+ type ) );
+ else
+ p->fillRect( x + 4, y + 4, w - 6, h - offset * 6,
+ g.brush( QColorGroup::Button ) );
+
+ }
+ else {
+ if ( ( w - offset * 2 ) > 0 && ( h - offset * 2 ) > 0 ) {
+ if ( isPixmap( type ) )
+ if ( rounded )
+ p->drawTiledPixmap( x, y, w, h, *scalePixmap( w, h, type ) );
+ else
+ p->drawTiledPixmap( x + offset, y + offset, w - offset * 2,
+ h - offset * 2,
+ *scalePixmap( w - offset * 2, h - offset * 2,
+ type ) );
+ else
+ p->fillRect( x + offset, y + offset, w - offset * 2, h - offset * 2,
+ g.brush( QColorGroup::Button ) );
+ }
+ if ( borderPixmap( type ) )
+ bitBlt( p->device(), x, y, scaleBorder( w, h, type ), 0, 0, w, h,
+ Qt::CopyROP, false );
+ else
+ drawShade( p, x, y, w, h, g, sunken, rounded,
+ highlightWidth( type ), borderWidth( type ), shade() );
+ }
+ p->setPen( oldPen );
+}
+
+void OThemeStyle::drawButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken,
+ const QBrush *fill )
+{
+ drawBaseButton( p, x, y, w, h, g, sunken, roundButton(), sunken ?
+ PushButtonDown : PushButton, fill );
+}
+
+void OThemeStyle::drawPushButton( QPushButton* btn, QPainter *p )
+{
+ bool sunken = btn->isOn() || btn->isDown();
+ int diw = buttonDefaultIndicatorWidth();
+ drawBaseButton( p, diw, diw, btn->width() - 2 * diw, btn->height() - 2 * diw,
+ *colorGroup( btn->colorGroup(), sunken ? PushButtonDown :
+ PushButton ), sunken, roundButton(),
+ sunken ? PushButtonDown : PushButton, NULL );
+ // TODO if diw, draw fancy default button indicator
+}
+
+void OThemeStyle::drawBaseMask( QPainter *p, int x, int y, int w, int h,
+ bool round )
+{
+ // round edge fills
+ static const QCOORD btm_left_fill[] = {
+ 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
+ 1, 2, 2, 2, 3, 2, 4, 2, 2, 3, 3, 3, 4, 3, 3, 4, 4, 4
+ };
+
+ static const QCOORD btm_right_fill[] = {
+ 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 1, 1, 1, 2, 1, 3, 1, 4,
+ 1, 0, 2, 1, 2, 2, 2, 3, 2, 0, 3, 1, 3, 2, 3, 0, 4, 1, 4
+ };
+
+ static const QCOORD top_left_fill[] = {
+ 3, 0, 4, 0, 2, 1, 3, 1, 4, 1, 1, 2, 2, 2, 3, 2, 4, 2, 0, 3,
+ 1, 3, 2, 3, 3, 3, 4, 3, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4
+ };
+
+ static const QCOORD top_right_fill[] = {
+ 0, 0, 1, 0, 0, 1, 1, 1, 2, 1, 0, 2, 1, 2, 2, 2, 3, 2, 0,
+ 3, 1, 3, 2, 3, 3, 3, 4, 3, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4
+ };
+
+ QBrush fillBrush( color1, SolidPattern );
+ p->setPen( color1 );
+ if ( round && w > 19 && h > 19 ) {
+ int x2 = x + w - 1;
+ int y2 = y + h - 1;
+ QPointArray a( QCOORDARRLEN( top_left_fill ), top_left_fill );
+ a.translate( 1, 1 );
+ p->drawPoints( a );
+ a.setPoints( QCOORDARRLEN( btm_left_fill ), btm_left_fill );
+ a.translate( 1, h - 6 );
+ p->drawPoints( a );
+ a.setPoints( QCOORDARRLEN( top_right_fill ), top_right_fill );
+ a.translate( w - 6, 1 );
+ p->drawPoints( a );
+ a.setPoints( QCOORDARRLEN( btm_right_fill ), btm_right_fill );
+ a.translate( w - 6, h - 6 );
+ p->drawPoints( a );
+
+ p->fillRect( x + 6, y, w - 12, h, fillBrush );
+ p->fillRect( x, y + 6, x + 6, h - 12, fillBrush );
+ p->fillRect( x2 - 6, y + 6, x2, h - 12, fillBrush );
+ p->drawLine( x + 6, y, x2 - 6, y );
+ p->drawLine( x + 6, y2, x2 - 6, y2 );
+ p->drawLine( x, y + 6, x, y2 - 6 );
+ p->drawLine( x2, y + 6, x2, y2 - 6 );
+
+ }
+ else
+ p->fillRect( x, y, w, h, fillBrush );
+}
+
+void OThemeStyle::drawButtonMask( QPainter *p, int x, int y, int w, int h )
+{
+ drawBaseMask( p, x, y, w, h, roundButton() );
+}
+
+void OThemeStyle::drawComboButtonMask( QPainter *p, int x, int y, int w, int h )
+{
+ drawBaseMask( p, x, y, w, h, roundComboBox() );
+}
+
+void OThemeStyle::drawBevelButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken,
+ const QBrush * )
+{
+ WidgetType type = sunken ? BevelDown : Bevel;
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, type ), sunken, false, type );
+}
+
+#if 0
+void OThemeStyle::drawKToolBarButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken,
+ bool raised, bool enabled, bool popup,
+ KToolButtonType type, const QString &btext,
+ const QPixmap *pixmap, QFont *font,
+ QWidget * )
+{
+ QFont tmp_font( QString::fromLatin1( "Helvetica" ), 10 );
+ if ( font )
+ tmp_font = *font;
+ QFontMetrics fm( tmp_font );
+ WidgetType widget = sunken ? ToolButtonDown : ToolButton;
+
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, widget ), sunken, false,
+ widget );
+ int dx, dy;
+ if ( type == Icon ) { // icon only
+ if ( pixmap ) {
+ dx = ( w - pixmap->width() ) / 2;
+ dy = ( h - pixmap->height() ) / 2;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ p->drawPixmap( x + dx, y + dy, *pixmap );
+ }
+ }
+ else if ( type == IconTextRight ) { // icon and text (if any)
+ if ( pixmap ) {
+ dx = 4;
+ dy = ( h - pixmap->height() ) / 2;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ p->drawPixmap( x + dx, y + dy, *pixmap );
+ }
+ if ( !btext.isNull() ) {
+ int tf = AlignVCenter | AlignLeft;
+ if ( pixmap )
+ dx = 4 + pixmap->width() + 2;
+ else
+ dx = 4;
+ dy = 0;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ if ( font )
+ p->setFont( *font );
+ if ( raised )
+ p->setPen( KGlobalSettings::toolBarHighlightColor() );
+ p->drawText( x + dx, y + dy, w - dx, h, tf, btext );
+ }
+ }
+ else if ( type == Text ) { // only text, even if there is a icon
+ if ( !btext.isNull() ) {
+ int tf = AlignTop | AlignLeft;
+ if ( !enabled )
+ p->setPen( g.dark() );
+ dx = ( w - fm.width( btext ) ) / 2;
+ dy = ( h - fm.lineSpacing() ) / 2;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ if ( font )
+ p->setFont( *font );
+ if ( raised )
+ p->setPen( KGlobalSettings::toolBarHighlightColor() );
+ p->drawText( x + dx, y + dy, fm.width( btext ), fm.lineSpacing(), tf, btext );
+ }
+ }
+ else if ( type == IconTextBottom ) {
+ if ( pixmap ) {
+ dx = ( w - pixmap->width() ) / 2;
+ dy = ( h - fm.lineSpacing() - pixmap->height() ) / 2;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ p->drawPixmap( x + dx, y + dy, *pixmap );
+ }
+ if ( !btext.isNull() ) {
+ int tf = AlignBottom | AlignHCenter;
+ dx = ( w - fm.width( btext ) ) / 2;
+ dy = h - fm.lineSpacing() - 4;
+ if ( sunken ) {
+ ++dx;
+ ++dy;
+ }
+ if ( font )
+ p->setFont( *font );
+ if ( raised )
+ p->setPen( KGlobalSettings::toolBarHighlightColor() );
+ p->drawText( x + dx, y + dy, fm.width( btext ), fm.lineSpacing(), tf, btext );
+ }
+ }
+ if ( popup ) {
+ if ( enabled )
+ qDrawArrow ( p, DownArrow, WindowsStyle, false, w - 5, h - 5, 0, 0,
+ g, true );
+ else
+ qDrawArrow ( p, DownArrow, WindowsStyle, false, w - 5, h - 5,
+ 0, 0, g, false );
+ }
+}
+
+void OThemeStyle::drawKBarHandle( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, KToolBarPos, QBrush * )
+{
+ if ( w > h )
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, HBarHandle ), false, false,
+ HBarHandle );
+ else
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, VBarHandle ), false, false,
+ VBarHandle );
+}
+
+void OThemeStyle::drawKToolBar( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, KToolBarPos, QBrush * )
+{
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, ToolBar ), false, false,
+ ToolBar );
+}
+#endif
+
+QRect OThemeStyle::buttonRect( int x, int y, int w, int h )
+{
+ int spacing = decoWidth( PushButton ) > decoWidth( PushButtonDown ) ?
+ decoWidth( PushButton ) : decoWidth( PushButtonDown );
+ return ( QRect( x + spacing, y + spacing, w - ( spacing * 2 ), h - ( spacing * 2 ) ) );
+}
+
+void OThemeStyle::drawComboButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken, bool,
+ bool, const QBrush * )
+{
+ WidgetType widget = sunken ? ComboBoxDown : ComboBox;
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, widget ), sunken,
+ roundComboBox(), widget );
+ if ( !sunken && isPixmap( ComboDeco ) )
+ p->drawPixmap( w - uncached( ComboDeco ) ->width() -
+ decoWidth( ComboBox ) - 2,
+ y + ( h - uncached( ComboDeco ) ->
+ height() ) / 2, *uncached( ComboDeco ) );
+ else if ( sunken && isPixmap( ComboDecoDown ) )
+ p->drawPixmap( w - uncached( ComboDecoDown ) ->width() -
+ decoWidth( ComboBoxDown ) - 2,
+ y + ( h - uncached( ComboDecoDown ) ->
+ height() ) / 2, *uncached( ComboDecoDown ) );
+ else {
+ qDrawArrow( p, Qt::DownArrow, Qt::MotifStyle, false, w - 15, y + 6, 10,
+ h - 15, *colorGroup( g, widget ), true );
+ qDrawShadeRect( p, w - 14, y + 7 + ( h - 15 ), 10, 3, *colorGroup( g, widget ) );
+ }
+}
+
+void OThemeStyle::drawScrollBarControls( QPainter *p, const QScrollBar *sb,
+ int sliderStart, uint controls,
+ uint activeControl )
+{
+ int sliderMin, sliderMax, sliderLength, buttonDim;
+ QRect add
+ , sub, addPage, subPage, slider;
+ int addX, addY, subX, subY;
+ bool horizontal = sb->orientation() == QScrollBar::Horizontal;
+ int len = ( horizontal ) ? sb->width() : sb->height();
+ int extent = ( horizontal ) ? sb->height() : sb->width();
+ int offset = decoWidth( horizontal ? HScrollGroove : VScrollGroove );
+ QColorGroup g = sb->colorGroup();
+
+ scrollBarMetrics( sb, sliderMin, sliderMax, sliderLength, buttonDim );
+ if ( sliderStart > sliderMax )
+ sliderStart = sliderMax;
+
+ int sliderEnd = sliderStart + sliderLength;
+ int sliderWidth = extent - offset * 2;
+
+ // Scary button placement code >:-P Feel free to improve this if you
+ // want. I get a headache just looking at it... (mosfet)
+ if ( scrollBarLayout() == SBOpposite ) {
+ if ( horizontal ) {
+ subY = addY = ( extent - buttonDim ) / 2;
+ subX = offset;
+ addX = len - buttonDim - offset;
+ }
+ else {
+ subX = addX = ( extent - buttonDim ) / 2;
+ subY = offset;
+ addY = len - buttonDim - offset;
+ }
+ sub.setRect( subX, subY, buttonDim, buttonDim );
+ add.setRect( addX, addY, buttonDim, buttonDim );
+ if ( horizontal ) {
+ subPage.setRect( sub.right() + 1, offset,
+ sliderStart - sub.right() - 1 , sliderWidth );
+ addPage.setRect( sliderEnd, offset, addX - sliderEnd, sliderWidth );
+ slider.setRect( sliderStart, offset, sliderLength, sliderWidth );
+ }
+ else {
+ subPage.setRect( offset, sub.bottom() + 1, sliderWidth,
+ sliderStart - sub.bottom() - 1 );
+ addPage.setRect( offset, sliderEnd, sliderWidth, addY - sliderEnd );
+ slider.setRect( offset, sliderStart, sliderWidth, sliderLength );
+ }
+ }
+ else if ( horizontal ) {
+ subY = addY = ( extent - buttonDim ) / 2;
+ if ( scrollBarLayout() == SBBottomLeft ) {
+ subX = offset;
+ addX = buttonDim + offset;
+ subPage.setRect( buttonDim * 2, 0, sliderStart - 1, extent );
+ addPage.setRect( sliderEnd, 0, len - sliderEnd, extent );
+ slider.setRect( sliderStart, 0, sliderLength, extent );
+ }
+ else {
+ subX = len - buttonDim - buttonDim - offset;
+ addX = len - buttonDim - offset;
+ subPage.setRect( offset + 1, offset, sliderStart - 1 , sliderWidth );
+ addPage.setRect( sliderEnd, offset, subX - sliderEnd, sliderWidth );
+ slider.setRect( sliderStart, offset, sliderLength, sliderWidth );
+ }
+ sub.setRect( subX, subY, buttonDim, buttonDim );
+ add.setRect( addX, addY, buttonDim, buttonDim );
+ }
+ else { // BottomLeft and BottomRight vertical bars are the same.
+ subX = addX = ( extent - buttonDim ) / 2;
+ subY = len - buttonDim - buttonDim - offset;
+ addY = len - buttonDim - offset;
+ subPage.setRect( offset, offset + 1, sliderWidth,
+ sliderStart - offset - 1 );
+ addPage.setRect( offset, sliderEnd, sliderWidth, subY - sliderEnd );
+ slider.setRect( offset, sliderStart, sliderWidth, sliderLength );
+ sub.setRect( subX, subY, buttonDim, buttonDim );
+ add.setRect( addX, addY, buttonDim, buttonDim );
+ }
+ // End of the button placement code
+
+ bool active;
+ if ( ( controls & QStyle::SubPage ) ) {
+ drawScrollBarGroove( p, sb, horizontal, subPage, g );
+ }
+ if ( ( controls & QStyle::AddPage ) ) {
+ drawScrollBarGroove( p, sb, horizontal, addPage, g );
+ }
+ if ( controls & QStyle::AddLine ) {
+ active = activeControl == QStyle::AddLine;
+ drawBaseButton( p, add.x(), add.y(), add.width(), add.height(),
+ *colorGroup( g, active ? ScrollButtonDown : ScrollButton ),
+ active, false, active ? ScrollButtonDown : ScrollButton );
+ drawArrow( p, ( horizontal ) ? RightArrow : DownArrow, active, add.x() + 3,
+ add.y() + 3, add.width() - 6, add.height() - 6,
+ *colorGroup( g, active ? ScrollButtonDown : ScrollButton ) );
+ }
+ if ( controls & QStyle::SubLine ) {
+ active = activeControl == QStyle::SubLine;
+ p->setPen( g.dark() );
+ p->drawRect( sub );
+ drawBaseButton( p, sub.x(), sub.y(), sub.width(), sub.height(),
+ *colorGroup( g, active ? ScrollButtonDown : ScrollButton ),
+ active, false, active ? ScrollButtonDown : ScrollButton );
+ drawArrow( p, ( horizontal ) ? LeftArrow : UpArrow, active, sub.x() + 3,
+ sub.y() + 3, sub.width() - 6, sub.height() - 6,
+ *colorGroup( g, active ? ScrollButtonDown : ScrollButton ) );
+ }
+ if ( controls & QStyle::Slider ) {
+ active = activeControl == QStyle::Slider;
+ WidgetType widget = horizontal ?
+ active ? HScrollBarSliderDown : HScrollBarSlider :
+ active ? VScrollBarSliderDown : VScrollBarSlider;
+
+ drawBaseButton( p, slider.x(), slider.y(), slider.width(),
+ slider.height(), *colorGroup( g, widget ), active, false,
+ widget );
+ int spaceW = horizontal ? slider.width() - decoWidth( widget ) - 4 :
+ slider.width();
+ int spaceH = horizontal ? slider.height() :
+ slider.height() - decoWidth( widget ) - 4;
+widget = active ? horizontal ? HScrollDecoDown : VScrollDecoDown :
+ horizontal ? HScrollDeco : VScrollDeco;
+ if ( isPixmap( widget ) ) {
+ if ( spaceW >= uncached( widget ) ->width() &&
+ spaceH >= uncached( widget ) ->height() ) {
+ p->drawPixmap( slider.x() + ( slider.width() -
+ uncached( widget ) ->width() ) / 2,
+ slider.y() + ( slider.height() -
+ uncached( widget ) ->height() ) / 2,
+ *uncached( widget ) );
+ }
+ }
+ }
+}
+
+void OThemeStyle::drawScrollBarGroove( QPainter *p, const QScrollBar *sb,
+ bool horizontal, QRect r, QColorGroup g )
+
+{
+ WidgetType widget = ( horizontal ) ? HScrollGroove : VScrollGroove;
+ if ( !isPixmap( widget ) ) {
+ p->fillRect( r, colorGroup( g, widget ) ->brush( QColorGroup::Background ) );
+ }
+ else {
+ // If the groove is pixmapped we make a full-sized image (it gets
+ // cached) then bitBlt it to the appropriate rect.
+ QPixmap buffer( sb->size() );
+ QPainter bPainter( &buffer );
+ bPainter.drawTiledPixmap( 0, 0, buffer.width(), buffer.height(),
+ *scalePixmap( buffer.width(), buffer.height(),
+ widget ) );
+ bitBlt( p->device(), r.x(), r.y(), &buffer, r.x(), r.y(), r.width(),
+ r.height(), Qt::CopyROP );
+ }
+ // Do the borders and frame
+ drawShade( p, sb->rect().x(), sb->rect().y(), sb->rect().width(),
+ sb->rect().height(), *colorGroup( g, widget ), true, false,
+ highlightWidth( widget ), borderWidth( widget ), shade() );
+}
+
+void OThemeStyle::scrollBarMetrics( const QScrollBar *sb, int &sliderMin,
+ int &sliderMax, int &sliderLength,
+ int &buttonDim )
+{
+ bool horizontal = sb->orientation() == QScrollBar::Horizontal;
+ int offset = decoWidth( horizontal ? HScrollGroove : VScrollGroove );
+ int maxlen;
+ int len = horizontal ? sb->width() : sb->height();
+ int extent = horizontal ? sb->height() : sb->width();
+
+ if ( len > ( extent - offset * 2 - 1 ) * 2 + offset * 2 )
+ buttonDim = extent - offset * 2;
+ else
+ buttonDim = ( len - offset * 2 ) / 2 - 1;
+ maxlen = len - offset * 2 - buttonDim * 2 - 1;
+
+ switch ( scrollBarLayout() ) {
+ case SBBottomLeft:
+ sliderMin = ( horizontal ) ? buttonDim * 2 + offset + 1 : offset + 1;
+ break;
+ case SBBottomRight:
+ sliderMin = offset + 1;
+ break;
+ case SBOpposite:
+ default:
+ sliderMin = offset + buttonDim;
+ break;
+ }
+ if ( sb->maxValue() == sb->minValue() )
+ sliderLength = maxlen;
+ else
+ sliderLength = ( sb->pageStep() * maxlen ) / ( sb->maxValue() -
+ sb->minValue() + sb->pageStep() );
+ if ( sliderLength < 12 || ( sb->maxValue() - sb->minValue() ) > INT_MAX / 2 )
+ sliderLength = 12;
+ if ( sliderLength > maxlen )
+ sliderLength = maxlen;
+ sliderMax = sliderMin + maxlen - sliderLength;
+}
+
+QStyle::ScrollControl OThemeStyle::scrollBarPointOver( const QScrollBar *sb,
+ int sliderStart,
+ const QPoint &p )
+{
+ if ( !sb->rect().contains( p ) )
+ return ( QStyle::NoScroll );
+ int sliderMin, sliderMax, sliderLength, buttonDim;
+ int pos = ( sb->orientation() == QScrollBar::Horizontal ) ? p.x() : p.y();
+ scrollBarMetrics( sb, sliderMin, sliderMax, sliderLength, buttonDim );
+
+ if ( scrollBarLayout() == SBOpposite ) {
+ if ( pos < sliderMin )
+ return QStyle::SubLine;
+ if ( pos < sliderStart )
+ return SubPage;
+ if ( pos < sliderStart + sliderLength )
+ return QStyle::Slider;
+ if ( pos < sliderMax + sliderLength )
+ return QStyle::AddPage;
+ return QStyle::AddLine;
+ }
+ if ( scrollBarLayout() == SBBottomLeft && sb->orientation() ==
+ QScrollBar::Horizontal ) {
+ if ( pos <= buttonDim )
+ return ( QStyle::SubLine );
+ else if ( pos <= buttonDim * 2 )
+ return ( QStyle::AddLine );
+ else if ( pos < sliderStart )
+ return ( QStyle::SubPage );
+ else if ( pos < sliderStart + sliderLength )
+ return ( QStyle::Slider );
+ return ( AddPage );
+ }
+ else {
+ if ( pos < sliderStart )
+ return QStyle::SubPage;
+ if ( pos < sliderStart + sliderLength )
+ return QStyle::Slider;
+ if ( pos < sliderMax + sliderLength )
+ return QStyle::AddPage;
+ if ( pos < sliderMax + sliderLength + buttonDim )
+ return QStyle::SubLine;
+ return QStyle::AddLine;
+ }
+}
+
+QSize OThemeStyle::exclusiveIndicatorSize() const
+{
+ if ( isPixmap( ExIndicatorOn ) )
+ return ( uncached( ExIndicatorOn ) ->size() );
+ else
+ return ( QWindowsStyle::exclusiveIndicatorSize() );
+}
+
+QSize OThemeStyle::indicatorSize() const
+{
+ if ( isPixmap( IndicatorOn ) )
+ return ( uncached( IndicatorOn ) ->size() );
+ else
+ return ( QWindowsStyle::indicatorSize() );
+}
+
+void OThemeStyle::drawExclusiveIndicator( QPainter* p, int x, int y, int w,
+ int h, const QColorGroup &g, bool on,
+ bool down, bool enabled )
+{
+ if ( isPixmap( ( on || down ) ? ExIndicatorOn : ExIndicatorOff ) ) {
+ p->drawPixmap( x, y, *uncached( ( on || down ) ? ExIndicatorOn :
+ ExIndicatorOff ) );
+ }
+ else {
+ QWindowsStyle::drawExclusiveIndicator( p, x, y, w, h,
+ *colorGroup( g, ExIndicatorOn ),
+ on, down, enabled );
+ }
+
+}
+
+void OThemeStyle::drawIndicator( QPainter* p, int x, int y, int w, int h,
+ const QColorGroup &g, int state, bool down,
+ bool enabled )
+{
+ if ( isPixmap( ( down || state != QButton::Off ) ?
+ IndicatorOn : IndicatorOff ) ) {
+ p->drawPixmap( x, y, *uncached( ( down || state != QButton::Off ) ?
+ IndicatorOn : IndicatorOff ) );
+ }
+ else {
+ QWindowsStyle::drawIndicator( p, x, y, w, h,
+ *colorGroup( g, IndicatorOn ), state,
+ down, enabled );
+ }
+}
+
+void OThemeStyle::drawExclusiveIndicatorMask( QPainter *p, int x, int y, int w,
+ int h, bool on )
+{
+ if ( isPixmap( ( on ) ? ExIndicatorOn : ExIndicatorOff ) ) {
+ const QBitmap * mask = uncached( ( on ) ? ExIndicatorOn : ExIndicatorOff ) ->
+ mask();
+ if ( mask ) {
+ p->drawPixmap( x, y, *mask );
+ }
+ else
+ p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) );
+ }
+ else
+ QWindowsStyle::drawExclusiveIndicatorMask( p, x, y, w, h, on );
+}
+
+void OThemeStyle::drawIndicatorMask( QPainter *p, int x, int y, int w, int h,
+ int state )
+{
+ if ( isPixmap( ( state != QButton::Off ) ? IndicatorOn : IndicatorOff ) ) {
+ const QBitmap * mask = uncached( ( state != QButton::Off ) ? IndicatorOn :
+ IndicatorOff ) ->mask();
+ if ( mask )
+ p->drawPixmap( x, y, *mask );
+ else
+ p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) );
+ }
+ else
+ QWindowsStyle::drawIndicatorMask( p, x, y, w, h, state );
+}
+
+void OThemeStyle::drawSliderGroove( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup& g, QCOORD c,
+ Orientation orient )
+{
+ if ( roundSlider() )
+ QWindowsStyle::drawSliderGroove( p, x, y, w, h,
+ *colorGroup( g, SliderGroove ),
+ c, orient );
+ else
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, SliderGroove ), true,
+ false, SliderGroove );
+}
+
+void OThemeStyle::drawSlider( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, Orientation orient,
+ bool tickAbove, bool tickBelow )
+{
+ if ( isPixmap( Slider ) ) {
+ if ( orient == Qt::Horizontal )
+ p->drawPixmap( x, y + ( h - uncached( Slider ) ->height() ) / 2,
+ *uncached( Slider ) );
+ else
+ p->drawPixmap( x + ( w - uncached( Slider ) ->width() ) / 2,
+ y, *uncached( Slider ) );
+ }
+ else {
+ QWindowsStyle::drawSlider( p, x, y, w, h, *colorGroup( g, Slider ),
+ orient, tickAbove, tickBelow );
+ }
+}
+
+void OThemeStyle::drawSliderMask( QPainter *p, int x, int y, int w, int h,
+ Orientation orient, bool tickAbove,
+ bool tickBelow )
+{
+ // This is odd. If we fill in the entire region it still masks the slider
+ // properly. I have no idea, this used to be different in Qt betas...
+ if ( isPixmap( Slider ) )
+ p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) );
+ else
+ QWindowsStyle::drawSliderMask( p, x, y, w, h, orient, tickAbove,
+ tickBelow );
+}
+
+int OThemeStyle::defaultFrameWidth() const
+{
+ return ( frameWidth() );
+}
+
+void OThemeStyle::getButtonShift( int &x, int &y )
+{
+ x = buttonXShift();
+ y = buttonYShift();
+}
+
+int OThemeStyle::sliderLength() const
+{
+ return ( sliderButtonLength() );
+}
+
+void OThemeStyle::drawArrow( QPainter *p, Qt::ArrowType type, bool down, int x,
+ int y, int w, int h, const QColorGroup &g,
+ bool enabled, const QBrush * )
+{
+ // Handles pixmapped arrows. A little inefficent because you can specify
+ // some as pixmaps and some as default types.
+ WidgetType widget;
+ switch ( type ) {
+ case UpArrow:
+widget = enabled ? down ? SunkenArrowUp : ArrowUp : DisArrowUp;
+ break;
+ case DownArrow:
+widget = enabled ? down ? SunkenArrowDown : ArrowDown : DisArrowDown;
+ break;
+ case LeftArrow:
+widget = enabled ? down ? SunkenArrowLeft : ArrowLeft : DisArrowLeft;
+ break;
+ case RightArrow:
+ default:
+widget = enabled ? down ? SunkenArrowRight : ArrowRight : DisArrowRight;
+ break;
+ }
+ if ( isPixmap( widget ) ) {
+ p->drawPixmap( x + ( w - uncached( widget ) ->width() ) / 2,
+ y + ( h - uncached( widget ) ->height() ) / 2,
+ *uncached( widget ) );
+ return ;
+ }
+ const QColorGroup *cg = colorGroup( g, widget );
+ // Standard arrow types
+ if ( arrowType() == MotifArrow )
+ qDrawArrow( p, type, Qt::MotifStyle, down, x, y, w, h, *cg, enabled );
+ else if ( arrowType() == SmallArrow ) {
+ QColorGroup tmp( *cg );
+ tmp.setBrush( QColorGroup::Button, QBrush( NoBrush ) );
+ QWindowsStyle::drawArrow( p, type, false, x, y, w, h,
+ tmp, true );
+ }
+ else {
+ QPointArray a;
+ int x2 = x + w - 1, y2 = y + h - 1;
+ switch ( type ) {
+ case Qt::UpArrow:
+ a.setPoints( 4, x, y2, x2, y2, x + w / 2, y, x, y2 );
+ break;
+ case Qt::DownArrow:
+ a.setPoints( 4, x, y, x2, y, x + w / 2, y2, x, y );
+ break;
+ case Qt::LeftArrow:
+ a.setPoints( 4, x2, y, x2, y2, x, y + h / 2, x2, y );
+ break;
+ default:
+ a.setPoints( 4, x, y, x, y2, x2, y + h / 2, x, y );
+ break;
+ }
+ QBrush oldBrush = p->brush();
+ QPen oldPen = p->pen();
+ p->setBrush( cg->brush( QColorGroup::Shadow ) );
+ p->setPen( cg->shadow() );
+ p->drawPolygon( a );
+ p->setBrush( oldBrush );
+ p->setPen( oldPen );
+ }
+}
+
+/* This is where we draw the borders and highlights. The new round button
+ * code is a pain in the arse. We don't want to be calculating arcs so
+ * use a whole lotta QPointArray's ;-) The code is made a lot more complex
+ * because you can have variable width border and highlights...
+ * I may want to cache this if round buttons are used, but am concerned
+ * about excessive cache misses. This is a memory/speed tradeoff that I
+ * have to test.
+ */
+void OThemeStyle::drawShade( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken, bool rounded,
+ int hWidth, int bWidth, ShadeStyle style )
+{
+ int i, sc, bc, x2, y2;
+ QPen highPen, lowPen;
+
+ if ( style == Motif ) {
+ highPen.setColor( sunken ? g.dark() : g.light() );
+ lowPen.setColor( sunken ? g.light() : g.dark() );
+ }
+ else {
+ highPen.setColor( sunken ? g.shadow() : g.light() );
+ lowPen.setColor( sunken ? g.light() : g.shadow() );
+ }
+
+ // Advanced round buttons
+ if ( rounded && w > 19 && h > 19 ) {
+ x2 = x + w - 1, y2 = y + h - 1;
+ QPointArray bPntArray, hPntArray, lPntArray;
+ QPointArray bLineArray, hLineArray, lLineArray;
+ // borders
+ for ( i = 0, bc = 0; i < bWidth; ++i ) {
+ bPntArray.putPoints( bc, 24, x + 4, y + 1, x + 5, y + 1, x + 3, y + 2, x + 2, y + 3,
+ x + 1, y + 4, x + 1, y + 5, x + 1, y2 - 5, x + 1, y2 - 4, x + 2, y2 - 3,
+ x2 - 5, y + 1, x2 - 4, y + 1, x2 - 3, y + 2, x2 - 5, y2 - 1,
+ x2 - 4, y2 - 1, x2 - 3, y2 - 2, x2 - 2, y2 - 3, x2 - 1, y2 - 5,
+ x2 - 1, y2 - 4, x + 3, y2 - 2, x + 4, y2 - 1, x + 5, y2 - 1,
+ x2 - 2, y + 3, x2 - 1, y + 4, x2 - 1, y + 5 );
+ bc += 24;
+ // ellispe edges don't match exactly, so fill in blanks
+ if ( i < bWidth - 1 || hWidth != 0 ) {
+ bPntArray.putPoints( bc, 20, x + 6, y + 1, x + 4, y + 2, x + 3, y + 3,
+ x + 2, y + 4, x + 1, y + 6, x2 - 6, y + 1, x2 - 4, y + 2,
+ x2 - 3, y + 3, x + 2, y2 - 4, x + 1, y2 - 6, x2 - 6, y2 - 1,
+ x2 - 4, y2 - 2, x2 - 3, y2 - 3, x2 - 2, y2 - 4, x2 - 1, y2 - 6,
+ x + 6, y2 - 1, x + 4, y2 - 2, x + 3, y2 - 3, x2 - 1, y + 6,
+ x2 - 2, y + 4 );
+ bc += 20;
+ }
+ bLineArray.putPoints( i * 8, 8, x + 6, y, x2 - 6, y, x, y + 6, x, y2 - 6,
+ x + 6, y2, x2 - 6, y2, x2, y + 6, x2, y2 - 6 );
+ ++x, ++y;
+ --x2, --y2;
+ }
+ // highlights
+ for ( i = 0, sc = 0; i < hWidth; ++i ) {
+ hPntArray.putPoints( sc, 12, x + 4, y + 1, x + 5, y + 1, // top left
+ x + 3, y + 2, x + 2, y + 3, x + 1, y + 4, x + 1, y + 5,
+ x + 1, y2 - 5, x + 1, y2 - 4, x + 2, y2 - 3, // half corners
+ x2 - 5, y + 1, x2 - 4, y + 1, x2 - 3, y + 2 );
+ lPntArray.putPoints( sc, 12, x2 - 5, y2 - 1, x2 - 4, y2 - 1, // btm right
+ x2 - 3, y2 - 2, x2 - 2, y2 - 3, x2 - 1, y2 - 5, x2 - 1, y2 - 4,
+ x + 3, y2 - 2, x + 4, y2 - 1, x + 5, y2 - 1, //half corners
+ x2 - 2, y + 3, x2 - 1, y + 4, x2 - 1, y + 5 );
+ sc += 12;
+ if ( i < hWidth - 1 ) {
+ hPntArray.putPoints( sc, 10, x + 6, y + 1, x + 4, y + 2, // top left
+ x + 3, y + 3, x + 2, y + 4, x + 1, y + 6,
+ x2 - 6, y + 1, x2 - 4, y + 2, // half corners
+ x2 - 3, y + 3, x + 2, y2 - 4, x + 1, y2 - 6 );
+ lPntArray.putPoints( sc, 10, x2 - 6, y2 - 1, x2 - 4, y2 - 2, // btm right
+ x2 - 3, y2 - 3, x2 - 2, y2 - 4, x2 - 1, y2 - 6,
+ x + 6, y2 - 1, x + 4, y2 - 2, // half corners
+ x + 3, y2 - 3, x2 - 1, y + 6, x2 - 2, y + 4 );
+ sc += 10;
+ }
+ hLineArray.putPoints( i * 4, 4, x + 6, y, x2 - 6, y, x, y + 6, x, y2 - 6 );
+ lLineArray.putPoints( i * 4, 4, x + 6, y2, x2 - 6, y2, x2, y + 6, x2, y2 - 6 );
+ ++x, ++y;
+ --x2, --y2;
+ }
+ p->setPen( Qt::black );
+ p->drawPoints( bPntArray );
+ p->drawLineSegments( bLineArray );
+ p->setPen( highPen );
+ p->drawPoints( hPntArray );
+ p->drawLineSegments( hLineArray );
+ p->setPen( lowPen );
+ p->drawPoints( lPntArray );
+ p->drawLineSegments( lLineArray );
+ }
+ // Rectangular buttons
+ else {
+ QPointArray highShade( hWidth * 4 );
+ QPointArray lowShade( hWidth * 4 );
+
+ p->setPen( g.shadow() );
+ for ( i = 0; i < bWidth && w > 2 && h > 2; ++i, ++x, ++y, w -= 2, h -= 2 )
+ p->drawRect( x, y , w, h );
+
+ if ( !hWidth )
+ return ;
+
+ x2 = x + w - 1, y2 = y + h - 1;
+ for ( i = 0; i < hWidth; ++i, ++x, ++y, --x2, --y2 ) {
+ highShade.putPoints( i * 4, 4, x, y, x2, y, x, y, x, y2 );
+ lowShade.putPoints( i * 4, 4, x, y2, x2, y2, x2, y, x2, y2 );
+ }
+ if ( style == Windows && hWidth > 1 ) {
+ p->setPen( highPen );
+ p->drawLineSegments( highShade, 0, 2 );
+ p->setPen( lowPen );
+ p->drawLineSegments( lowShade, 0, 2 );
+
+ p->setPen( ( sunken ) ? g.dark() : g.mid() );
+ p->drawLineSegments( highShade, 4 );
+ p->setPen( ( sunken ) ? g.mid() : g.dark() );
+ p->drawLineSegments( lowShade, 4 );
+ }
+ else {
+ p->setPen( ( sunken ) ? g.dark() : g.light() );
+ p->drawLineSegments( highShade );
+ p->setPen( ( sunken ) ? g.light() : g.dark() );
+ p->drawLineSegments( lowShade );
+ }
+ }
+}
+
+void OThemeStyle::drawPushButtonLabel( QPushButton *btn, QPainter *p )
+{
+ WidgetType widget = btn->isDown() || btn->isOn() ? PushButtonDown :
+ PushButton;
+ const QColorGroup *cg = colorGroup( btn->colorGroup(), widget );
+ int x, y, w, h;
+
+ QRect r = btn->rect();
+ r.rect( &x, &y, &w, &h );
+ x += decoWidth( widget );
+ y += decoWidth( widget );
+ w -= decoWidth( widget ) * 2;
+ h -= decoWidth( widget ) * 2;
+ bool act = btn->isOn() || btn->isDown();
+
+ // If this is a button with an associated popup menu, draw an arrow first
+ if ( btn->popup() ) {
+ int dx = menuButtonIndicatorWidth( btn->height() );
+
+ QColorGroup g( btn->colorGroup() );
+ int xx = x + w - dx - 4;
+ int yy = y - 3;
+ int hh = h + 6;
+
+ if ( !act ) {
+ p->setPen( g.light() );
+ p->drawLine( xx, yy + 3, xx, yy + hh - 4 );
+ }
+ else {
+ p->setPen( g.button() );
+ p->drawLine( xx, yy + 4, xx, yy + hh - 4 );
+ }
+ drawArrow( p, DownArrow, FALSE,
+ x + w - dx - 2, y + 2, dx, h - 4,
+ btn->colorGroup(),
+ btn->isEnabled() );
+ w -= dx;
+ }
+
+ // Next, draw iconset, if any
+ if ( btn->iconSet() && !btn->iconSet() ->isNull() ) {
+ QIconSet::Mode mode = btn->isEnabled()
+ ? QIconSet::Normal : QIconSet::Disabled;
+ if ( mode == QIconSet::Normal && btn->hasFocus() )
+ mode = QIconSet::Active;
+ QPixmap pixmap = btn->iconSet() ->pixmap( QIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+
+ p->drawPixmap( x + 6, y + h / 2 - pixh / 2, pixmap );
+ x += pixw + 8;
+ w -= pixw + 8;
+ }
+
+ if ( widget == PushButtonDown ) {
+ drawItem( p, x + buttonXShift(), y + buttonYShift(),
+ w, h, AlignCenter | ShowPrefix, *cg, btn->isEnabled(),
+ btn->pixmap(), btn->text(), -1, &cg->buttonText() );
+ }
+ else {
+ drawItem( p, x, y, w, h, AlignCenter | ShowPrefix, *cg,
+ btn->isEnabled(), btn->pixmap(), btn->text(), -1,
+ &cg->buttonText() );
+ }
+}
+
+int OThemeStyle::splitterWidth() const
+{
+ return ( splitWidth() );
+}
+
+void OThemeStyle::drawSplitter( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, Orientation )
+{
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, Splitter ), false, false,
+ Splitter );
+}
+
+void OThemeStyle::drawCheckMark( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool act, bool dis )
+{
+ if ( isPixmap( CheckMark ) ) {
+ if ( !dis )
+ p->drawPixmap( x + ( w - uncached( CheckMark ) ->width() ) / 2,
+ y + ( h - uncached( CheckMark ) ->height() ) / 2,
+ *uncached( CheckMark ) );
+ }
+ else
+ QWindowsStyle::drawCheckMark( p, x, y, w, h, *colorGroup( g, CheckMark ),
+ act, dis );
+}
+
+int OThemeStyle::popupMenuItemHeight( bool /*checkable*/, QMenuItem *mi,
+ const QFontMetrics &fm )
+{
+ int h2, h = 0;
+ int offset = QMAX( decoWidth( MenuItemDown ), decoWidth( MenuItem ) ) + 4;
+
+ if ( mi->isSeparator() )
+ return ( 2 );
+ if ( mi->isChecked() )
+ h = isPixmap( CheckMark ) ? uncached( CheckMark ) ->height() + offset :
+ offset + 16;
+ if ( mi->pixmap() ) {
+ h2 = mi->pixmap() ->height() + offset;
+ h = h2 > h ? h2 : h;
+ }
+ if ( mi->iconSet() ) {
+ h2 = mi->iconSet() ->
+ pixmap( QIconSet::Small, QIconSet::Normal ).height() + offset;
+ h = h2 > h ? h2 : h;
+ }
+ h2 = fm.height() + offset;
+ h = h2 > h ? h2 : h;
+ return ( h );
+}
+
+void OThemeStyle::drawPopupMenuItem( QPainter* p, bool checkable, int maxpmw,
+ int tab, QMenuItem* mi,
+ const QPalette& pal, bool act,
+ bool enabled, int x, int y, int w, int h )
+{
+ // I changed the following method to be based from Qt's instead of my own
+ // wacky code. Works much better now :P (mosfet)
+ static const int motifItemFrame = 2; // menu item frame width
+ static const int motifItemHMargin = 5; // menu item hor text margin
+ static const int motifItemVMargin = 4; // menu item ver text margin
+
+ static const int motifArrowHMargin = 6; // arrow horizontal margin
+ static const int windowsRightBorder = 12; // right border on windowsstatic const int windowsCheckMarkWidth = 12; // checkmarks width on windows
+ bool dis = !enabled;
+ const QColorGroup &g = dis ? *colorGroup( pal.normal(), MenuItem ) :
+ *colorGroup( pal.normal(), MenuItemDown );
+
+ QColorGroup itemg = dis ? *colorGroup( pal.disabled(), MenuItem )
+ : act ? *colorGroup( pal.active(), MenuItemDown )
+ : *colorGroup( pal.normal(), MenuItem );
+
+ maxpmw = QMAX( maxpmw, 20 );
+ int checkcol = maxpmw;
+
+ if ( mi && mi->isSeparator() ) {
+ p->setPen( g.dark() );
+ p->drawLine( x, y, x + w, y );
+ p->setPen( g.light() );
+ p->drawLine( x, y + 1, x + w, y + 1 );
+ return ;
+ }
+ if ( act ) {
+ drawBaseButton( p, x, y, w, h, g, true, false, MenuItemDown );
+ }
+ else {
+ drawShade( p, x, y, w, h, *colorGroup( g, MenuItem ), false, false,
+ highlightWidth( MenuItem ), borderWidth( MenuItem ),
+ shade() );
+ int dw = decoWidth( MenuItem );
+ if ( !isPixmap( MenuItem ) )
+ p->fillRect( x + dw, y + dw, w - dw * 2, h - dw * 2,
+ colorGroup( g, MenuItem ) ->
+ brush( QColorGroup::Background ) );
+ else {
+ // process inactive item pixmaps as one large item
+ p->drawTiledPixmap( x + dw, y + dw, w - dw * 2, h - dw * 2, *scalePixmap
+ // (w, p->window().height(), MenuItem),
+ ( w, p->clipRegion().boundingRect().height(), MenuItem ),
+ x, y );
+ }
+
+ if ( checkable && mi && mi->isChecked() ) {
+ // draw 'pressed' border around checkable items
+ // This is extremely important for items that have an iconset
+ // because the checkmark isn't drawn in that case
+ // An alternative would be superimposing the checkmark over
+ // the iconset instead or not drawing the iconset at all.
+ int mw = checkcol + motifItemFrame;
+ drawShade( p, x, y, mw, h, g, true, false,
+ highlightWidth( MenuItemDown ),
+ borderWidth( MenuItemDown ), shade() );
+ }
+ }
+ if ( !mi )
+ return ;
+ if ( mi->iconSet() ) {
+ QIconSet::Mode mode = dis ? QIconSet::Disabled : QIconSet::Normal;
+ if ( act && !dis )
+ mode = QIconSet::Active;
+ QPixmap pixmap = mi->iconSet() ->pixmap( QIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+ QRect cr( x, y, checkcol, h );
+ QRect pmr( 0, 0, pixw, pixh );
+ pmr.moveCenter( cr.center() );
+ p->setPen( itemg.text() );
+ p->drawPixmap( pmr.topLeft(), pixmap );
+
+ }
+ else if ( checkable ) {
+ int mw = checkcol + motifItemFrame;
+ int mh = h - 2 * motifItemFrame;
+ if ( mi->isChecked() ) {
+ drawCheckMark( p, x + motifItemFrame,
+ y + motifItemFrame, mw, mh, itemg, act, dis );
+ }
+ }
+
+ p->setPen( colorGroup( g, act ? MenuItemDown : MenuItem ) ->text() );
+
+ QColor discol;
+ if ( dis ) {
+ discol = itemg.text();
+ p->setPen( discol );
+ }
+
+ int xm = motifItemFrame + checkcol + motifItemHMargin;
+
+ QString s = mi->text();
+ if ( !s.isNull() ) {
+ int t = s.find( '\t' );
+ int m = motifItemVMargin;
+ const int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine;
+ if ( t >= 0 ) {
+ if ( dis && !act ) {
+ p->setPen( g.light() );
+ p->drawText( x + w - tab - windowsRightBorder - motifItemHMargin - motifItemFrame + 1,
+ y + m + 1, tab, h - 2 * m, text_flags, s.mid( t + 1 ) );
+ p->setPen( discol );
+ }
+ p->drawText( x + w - tab - windowsRightBorder - motifItemHMargin - motifItemFrame,
+ y + m, tab, h - 2 * m, text_flags, s.mid( t + 1 ) );
+ }
+ if ( dis && !act ) {
+ p->setPen( g.light() );
+ p->drawText( x + xm + 1, y + m + 1, w - xm + 1, h - 2 * m, text_flags, s, t );
+ p->setPen( discol );
+ }
+ p->drawText( x + xm, y + m, w - xm - tab + 1, h - 2 * m, text_flags, s, t );
+ }
+ else if ( mi->pixmap() ) {
+ QPixmap * pixmap = mi->pixmap();
+ if ( pixmap->depth() == 1 )
+ p->setBackgroundMode( OpaqueMode );
+ p->drawPixmap( x + xm, y + motifItemFrame, *pixmap );
+ if ( pixmap->depth() == 1 )
+ p->setBackgroundMode( TransparentMode );
+ }
+ if ( mi->popup() ) {
+ int dim = ( h - 2 * motifItemFrame ) / 2;
+ if ( act ) {
+ if ( !dis )
+ discol = colorGroup( g, MenuItemDown ) ->text();
+ //discol = white;
+ QColorGroup g2( discol, g.highlight(),
+ white, white,
+ dis ? discol : white,
+ discol, white );
+ drawArrow( p, RightArrow, true,
+ x + w - motifArrowHMargin - motifItemFrame - dim, y + h / 2 - dim / 2,
+ dim, dim, g2, TRUE );
+ }
+ else {
+ drawArrow( p, RightArrow,
+ false,
+ x + w - motifArrowHMargin - motifItemFrame - dim, y + h / 2 - dim / 2,
+ dim, dim, g, mi->isEnabled() );
+ }
+ }
+}
+
+void OThemeStyle::drawFocusRect( QPainter *p, const QRect &r,
+ const QColorGroup &g, const QColor *c,
+ bool atBorder )
+{
+ p->setPen( g.dark() );
+ if ( !is3DFocus() )
+ QWindowsStyle::drawFocusRect( p, r, g, c, atBorder );
+ else {
+ int i = focusOffset();
+ p->drawLine( r.x() + i, r.y() + 1 + i, r.x() + i, r.bottom() - 1 - i );
+ p->drawLine( r.x() + 1 + i, r.y() + i, r.right() - 1 - i, r.y() + i );
+ p->setPen( g.light() );
+ p->drawLine( r.right() - i, r.y() + 1 + i, r.right() - i, r.bottom() - 1 - i );
+ p->drawLine( r.x() + 1 + i, r.bottom() - i, r.right() - 1 - i, r.bottom() - i );
+ }
+}
+
+#if 0
+void OThemeStyle::drawKMenuBar( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool, QBrush * )
+{
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, MenuBar ), false, false,
+ MenuBar );
+}
+
+void OThemeStyle::drawKMenuItem( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool active,
+ QMenuItem *mi, QBrush * )
+{
+ const QColorGroup * cg = colorGroup( g, active ? MenuBarItem : MenuBar );
+ QColor btext = cg->buttonText();
+ if ( active )
+ drawBaseButton( p, x, y, w, h, *cg, false, false, MenuBarItem );
+ //qDrawShadePanel(p, x, y, w, h, *cg, false, 1);
+
+ drawItem( p, x, y, w, h, AlignCenter | ShowPrefix | DontClip | SingleLine,
+ *cg, mi->isEnabled(), mi->pixmap(), mi->text(),
+ -1, &btext );
+ ;
+}
+
+void OThemeStyle::drawKProgressBlock( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, QBrush * )
+{
+ drawBaseButton( p, x, y, w, h, *colorGroup( g, ProgressBar ), false, false,
+ ProgressBar );
+}
+
+void OThemeStyle::getKProgressBackground( const QColorGroup &g, QBrush &bg )
+{
+ const QColorGroup * cg = colorGroup( g, ProgressBg );
+ bg.setColor( cg->color( QColorGroup::Background ) );
+ if ( isPixmap( ProgressBg ) )
+ bg.setPixmap( *uncached( ProgressBg ) );
+}
+#endif
+
+void OThemeStyle::tabbarMetrics( const QTabBar* t, int& hframe, int& vframe, int& overlap )
+{
+ QCommonStyle::tabbarMetrics( t, hframe, vframe, overlap );
+}
+
+void OThemeStyle::drawTab( QPainter* p, const QTabBar* tb, QTab* t ,
+ bool selected )
+{
+ WidgetType widget = selected ? ActiveTab : InactiveTab;
+ const QColorGroup *cg = colorGroup( tb->colorGroup(), widget );
+ int i;
+ int x = t->r.x(), y = t->r.y();
+ int x2 = t->r.right(), y2 = t->r.bottom();
+ int bWidth = borderWidth( widget );
+ int hWidth = highlightWidth( widget );
+ if ( tb->shape() == QTabBar::RoundedAbove ) {
+ if ( !selected ) {
+ p->fillRect( x, y, x2 - x + 1, 2,
+ tb->palette().normal().brush( QColorGroup::Background ) );
+ y += 2;
+ }
+ p->setPen( cg->text() );
+ i = 0;
+ if ( i < bWidth ) {
+ p->drawLine( x, y + 1, x, y2 );
+ p->drawLine( x2, y + 1, x2, y2 );
+ p->drawLine( x + 1, y, x2 - 1, y );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y2, x2, y2 );
+ --y2;
+ }
+ ++i, ++x, ++y, --x2;
+ }
+ for ( ; i < bWidth; ++i, ++x, ++y, --x2 ) {
+ p->drawLine( x, y, x, y2 );
+ p->drawLine( x2, y, x2, y2 );
+ p->drawLine( x, y, x2, y );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y2, x2, y2 );
+ --y2;
+ }
+ }
+ i = 0;
+ if ( i < hWidth && bWidth == 0 ) {
+ p->setPen( cg->light() );
+ p->drawLine( x, y + 1, x, y2 );
+ p->drawLine( x + 1, y, x2 - 1, y );
+ p->setPen( cg->dark() );
+ p->drawLine( x2, y + 1, x2, y2 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y2, x2, y2 );
+ --y2;
+ }
+ ++i, ++x, ++y, --x2;
+ }
+ for ( ; i < hWidth; ++i, ++x, ++y, --x2 ) {
+ p->setPen( cg->light() );
+ p->drawLine( x, y, x, y2 );
+ p->drawLine( x, y, x2, y );
+ p->setPen( cg->dark() );
+ p->drawLine( x2, y + 1, x2, y2 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y2, x2, y2 );
+ --y2;
+ }
+ }
+ if ( isPixmap( widget ) )
+ p->drawTiledPixmap( x, y, x2 - x + 1, y2 - y + 1,
+ *scalePixmap( x2 - x + 1, y2 - y + 1, widget ) );
+ else
+ p->fillRect( x, y, x2 - x + 1, y2 - y + 1, cg->background() );
+ }
+ else if ( tb->shape() == QTabBar::RoundedBelow ) {
+ if ( !selected ) {
+ p->fillRect( x, y2 - 2, x2 - x + 1, 2,
+ tb->palette().normal().brush( QColorGroup::Background ) );
+ y2 -= 2;
+ }
+ p->setPen( cg->text() );
+ i = 0;
+ if ( i < bWidth ) {
+ p->drawLine( x, y, x, y2 - 1 );
+ p->drawLine( x2, y, x2, y2 - 1 );
+ p->drawLine( x + 1, y2, x2 - 1, y2 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y, x2, y );
+ ++y;
+ }
+ }
+ for ( ; i < bWidth; ++i, ++x, --x2, --y2 ) {
+ p->drawLine( x, y, x, y2 );
+ p->drawLine( x2, y, x2, y2 );
+ p->drawLine( x, y2, x2, y2 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y, x2, y );
+ ++y;
+ }
+ }
+ i = 0;
+ if ( i < hWidth && bWidth == 0 ) {
+ p->setPen( cg->dark() );
+ p->drawLine( x + 1, y2, x2 - 1, y2 );
+ p->drawLine( x2, y, x2, y2 - 1 );
+ p->setPen( cg->light() );
+ p->drawLine( x, y, x, y2 - 1 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y, x2, y );
+ ++y;
+ }
+ ++i, ++x, --x2, --y2;
+ }
+ for ( ; i < hWidth; ++i, ++x, --x2, --y2 ) {
+ p->setPen( cg->dark() );
+ p->drawLine( x, y2, x2, y2 );
+ p->drawLine( x2, y, x2, y2 );
+ p->setPen( cg->light() );
+ p->drawLine( x, y, x, y2 );
+ if ( selected ? activeTabLine() : inactiveTabLine() ) {
+ p->drawLine( x, y, x2, y );
+ ++y;
+ }
+ }
+ if ( isPixmap( widget ) )
+ p->drawTiledPixmap( x, y, x2 - x + 1, y2 - y + 1,
+ *scalePixmap( x2 - x + 1, y2 - y + 1, widget ) );
+ else
+ p->fillRect( x, y, x2 - x + 1, y2 - y + 1, cg->background() );
+ }
+ else
+ QCommonStyle::drawTab( p, tb, t, selected );
+}
+
+void OThemeStyle::drawTabMask( QPainter* p, const QTabBar* tb, QTab* t,
+ bool selected )
+{
+ QRect r( t->r );
+
+ if ( tb->shape() == QTabBar::RoundedAbove ) {
+ if ( !selected )
+ r.setTop( r.top() + 2 );
+ p->drawLine( r.left() + 1, r.top(), r.right() - 1, r.top() );
+ QBrush b( color1, SolidPattern );
+ p->fillRect( r.left(), r.top() + 1, r.width(), r.height() - 1, b );
+ }
+ else if ( tb->shape() == QTabBar::RoundedBelow ) {
+ if ( !selected )
+ r.setBottom( r.bottom() - 2 );
+ p->drawLine( r.left() + 1, r.bottom(), r.right() - 1, r.bottom() );
+ QBrush b( color1, SolidPattern );
+ p->fillRect( r.left(), r.top(), r.width(), r.height() - 1, b );
+ }
+ else
+ QCommonStyle::drawTabMask( p, tb, t, selected );
+
+}
+
+
+//#include "kthemestyle.moc"
+
diff --git a/noncore/styles/theme/othemestyle.h b/noncore/styles/theme/othemestyle.h
new file mode 100644
index 0000000..02bec78
--- a/dev/null
+++ b/noncore/styles/theme/othemestyle.h
@@ -0,0 +1,365 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef __KTHEMESTYLE_H
+#define __KTHEMESTYLE_H
+
+#include "othemebase.h"
+#include <qwindowdefs.h>
+#include <qobject.h>
+#include <qbutton.h>
+#include <qpushbutton.h>
+#include <qscrollbar.h>
+#include <qstring.h>
+
+
+/**
+ * KDE themed styles.
+ *
+ * It provides methods for
+ * drawing most widgets with user-specified borders, highlights, pixmaps,
+ * etc. It also handles various other settings such as scrollbar types,
+ * rounded buttons, and shading types. For a full list of parameters this
+ * class handles refer to the KDE theme configuration documentation.
+ *
+ */
+
+class OThemeStyle: public OThemeBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Construct a new @ref OThemeStyle object.
+ *
+ * @param configFile A KConfig file to use as the theme configuration.
+ * Defaults to ~/.kderc.
+ */
+ OThemeStyle( const QString &configFile = QString::null );
+ ~OThemeStyle();
+ virtual void polish( QWidget* );
+ virtual void unPolish( QWidget* );
+ /**
+ * By default this just sets the background brushes to the pixmapped
+ * background.
+ */
+ virtual void polish( QApplication *app );
+ virtual void unPolish( QApplication* );
+
+ /// @internal
+ // to make it possible for derived classes to overload this function
+ virtual void polish( QPalette& pal );
+
+ /**
+ * This is a convenience method for drawing widgets with
+ * borders, highlights, pixmaps, colors, etc...
+ * You specify the widget type and it will draw it according to the
+ * config file settings.
+ *
+ * @param p The QPainter to draw on.
+ * @param g The color group to use.
+ * @param rounded @p true if the widget is rounded, @p false if rectangular.
+ * @param type The widget type to paint.
+ * @param fill An optional fill brush. Currently ignored (the config file
+ * is used instead).
+ */
+ virtual void drawBaseButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken = FALSE,
+ bool rounded = FALSE, WidgetType type = Bevel,
+ const QBrush *fill = 0 );
+ /**
+ * Draw a mask with for widgets that may be rounded.
+ *
+ *Currently used
+ * by pushbuttons and comboboxes.
+ *
+ * @param p The QPainter to draw on.
+ * @param rounded @p true if the widget is rounded, @p false if rectangular.
+ */
+ virtual void drawBaseMask( QPainter *p, int x, int y, int w, int h,
+ bool rounded );
+ /**
+ * Draw a pushbutton.
+ *
+ * This calls @ref drawBaseButton() with @p PushButton as the
+ * widget type.
+ */
+ virtual void drawButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken = FALSE,
+ const QBrush *fill = 0 );
+ /**
+ * Draw a bevel button.
+ *
+ * This calls @ref drawBaseButton() with Bevel as the
+ * widget type.
+ */
+ virtual void drawBevelButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken = FALSE,
+ const QBrush *fill = 0 );
+#if 0
+ /**
+ * Draw a toolbar button.
+ */
+ virtual void drawKToolBarButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken = false,
+ bool raised = true, bool enabled = true,
+ bool popup = false, KToolButtonType type = Icon,
+ const QString &btext = QString::null,
+ const QPixmap *icon = NULL,
+ QFont *font = NULL, QWidget *btn = NULL );
+ /**
+ * Draw the handle used in toolbars.
+ */
+ void drawKBarHandle( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g,
+ KToolBarPos type, QBrush *fill = NULL );
+
+ /**
+ * Draw a toolbar.
+ */
+ void drawKToolBar( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, KToolBarPos type,
+ QBrush *fill = NULL );
+#endif
+ /**
+ * Return the space available in a pushbutton, taking configurable
+ * borders and highlights into account.
+ */
+ virtual QRect buttonRect( int x, int y, int w, int h );
+ /**
+ * Draw an arrow in the style specified by the config file.
+ */
+ virtual void drawArrow( QPainter *p, Qt::ArrowType type, bool down,
+ int x, int y, int w, int h, const QColorGroup &g,
+ bool enabled = true, const QBrush *fill = 0 );
+ /**
+ * Return the size of the exclusive indicator pixmap if one is specified
+ * in the config file, otherwise it uses the base style's size.
+ */
+ virtual QSize exclusiveIndicatorSize() const;
+ /**
+ * Draw an exclusive indicator widget.
+ *
+ * If a pixmap is specified in the
+ * config file that is used, otherwise the base style's widget is drawn.
+ */
+ virtual void drawExclusiveIndicator( QPainter* p, int x, int y, int w,
+ int h, const QColorGroup &g, bool on,
+ bool down = FALSE,
+ bool enabled = TRUE );
+ /**
+ * Set the mask of an exclusive indicator widget.
+ *
+ * If a pixmap is specified
+ * it is masked according to it's transparent pixels, otherwise the
+ * base style's mask is used.
+ */
+ virtual void drawExclusiveIndicatorMask( QPainter *p, int x, int y, int w,
+ int h, bool on );
+ /**
+ * Set the mask of an indicator widget.
+ *
+ * If a pixmap is specified
+ * it is masked according to it's transparent pixels, otherwise the
+ * base style's mask is used.
+ */
+ virtual void drawIndicatorMask( QPainter *p, int x, int y, int w, int h,
+ int state );
+ /**
+ * Set the mask for pushbuttons.
+ */
+ virtual void drawButtonMask( QPainter *p, int x, int y, int w, int h );
+ /**
+ * Set the mask for combo boxes.
+ */
+ virtual void drawComboButtonMask( QPainter *p, int x, int y, int w, int h );
+ /**
+ * Return the size of the indicator pixmap if one is specified
+ * in the config file, otherwise it uses the base style's size.
+ */
+ virtual QSize indicatorSize() const;
+ /**
+ * Draw an indicator widget.
+ *
+ * If a pixmap is specified in the
+ * config file that is used, otherwise the base style's widget is drawn.
+ */
+ virtual void drawIndicator( QPainter* p, int x, int y, int w, int h,
+ const QColorGroup &g, int state,
+ bool down = FALSE, bool enabled = TRUE );
+ /**
+ * Draw a combobox.
+ */
+ virtual void drawComboButton( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken = FALSE,
+ bool editable = FALSE, bool enabled = TRUE,
+ const QBrush *fill = 0 );
+ /**
+ * Draw a pushbutton.
+ */
+ virtual void drawPushButton( QPushButton* btn, QPainter *p );
+ /**
+ * Return the amount of button content displacement specified by the
+ * config file.
+ */
+ virtual void getButtonShift( int &x, int &y );
+ /**
+ * Return the frame width.
+ */
+ virtual int defaultFrameWidth() const;
+ /**
+ * Calculate the metrics of the scrollbar controls according to the
+ * layout specified by the config file.
+ */
+ virtual void scrollBarMetrics( const QScrollBar*, int&, int&, int&, int& );
+ /**
+ * Draw a themed scrollbar.
+ */
+ virtual void drawScrollBarControls( QPainter*, const QScrollBar*,
+ int sliderStart, uint controls,
+ uint activeControl );
+ /**
+ * Return the control that the given point is over according to the
+ * layout in the config file.
+ */
+ virtual ScrollControl scrollBarPointOver( const QScrollBar*,
+ int sliderStart, const QPoint& );
+ /**
+ * Return the configurable default slider length.
+ */
+ virtual int sliderLength() const;
+ /**
+ * Draw a slider control.
+ */
+ virtual void drawSlider( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, Orientation, bool tickAbove,
+ bool tickBelow );
+ /**
+ * Draw a slider groove.
+ */
+ void drawSliderGroove( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup& g, QCOORD c,
+ Orientation );
+ /**
+ * Draw the mask for a slider (both the control and groove.
+ */
+ virtual void drawSliderMask( QPainter *p, int x, int y, int w, int h,
+ Orientation, bool tickAbove, bool tickBelow );
+ // void drawSliderGrooveMask(QPainter *p,int x, int y, int w, int h,
+ // QCOORD c, Orientation );
+ /**
+ * Convience method for drawing themed scrollbar grooves.
+ *
+ * Since the
+ * grooves may be a scaled pixmap you cannot just bitblt the pixmap at
+ * any offset. This generates a cached pixmap at full size if needed and
+ * then copies the requested area.
+ *
+ * @param p The painter to draw on.
+ * @param sb The scrollbar (usually given by drawScrollBarControls).
+ * @param horizontal Is the scrollBar horizontal?
+ * @param r The rectangle to fill.
+ * @param g The color group to use.
+ */
+ virtual void drawScrollBarGroove( QPainter *p, const QScrollBar *sb,
+ bool horizontal, QRect r, QColorGroup g );
+ /**
+ * Draw a shaded rectangle using the given style.
+ *
+ * @param p The painter to draw on.
+ * @param g The color group to use.
+ * @param rounded Draws a rounded shape if true. Requires bWidth to be
+ * at least 1.
+ * @param hWidth The highlight width.
+ * @param bWidth The border width.
+ * @param style The shading style to use.
+ */
+ virtual void drawShade( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool sunken, bool rounded,
+ int hWidth, int bWidth, ShadeStyle style );
+ /**
+ * Draw the text for a pushbutton.
+ */
+ virtual void drawPushButtonLabel( QPushButton *btn, QPainter *p );
+ /**
+ * Draw a menubar.
+ */
+#if 0
+
+ void drawKMenuBar( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool macMode,
+ QBrush *fill = NULL );
+#endif
+ /**
+ * Draw a menubar item.
+ */
+#if 0
+
+ virtual void drawKMenuItem( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool active,
+ QMenuItem *item, QBrush *fill = NULL );
+#endif
+ /**
+ * Return the width of the splitter as specified in the config file.
+ */
+ virtual int splitterWidth() const;
+ /**
+ * Draw a splitter widget.
+ */
+ virtual void drawSplitter( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, Orientation );
+ /**
+ * Draw a checkmark.
+ */
+ virtual void drawCheckMark( QPainter *p, int x, int y, int w, int h,
+ const QColorGroup &g, bool act, bool dis );
+ /**
+ * Draw a menu item.
+ *
+ * Note: This method manually handles applying
+ * inactive menu backgrounds to the entire widget.
+ */
+ virtual void drawPopupMenuItem( QPainter *p, bool checkable, int maxpmw,
+ int tab, QMenuItem *mi, const QPalette &pal,
+ bool act, bool enabled, int x, int y, int w,
+ int h );
+ int popupMenuItemHeight( bool checkable, QMenuItem *mi,
+ const QFontMetrics &fm );
+ /**
+ * Draw the focus rectangle.
+ */
+ void drawFocusRect( QPainter *p, const QRect &r, const QColorGroup &g,
+ const QColor *c = 0, bool atBorder = false );
+ /**
+ * Draw a @ref KProgess bar.
+ */
+ // virtual void drawKProgressBlock(QPainter *p, int x, int y, int w, int h,
+ // const QColorGroup &g, QBrush *fill);
+ /**
+ * Return the background for @ref KProgress.
+ */
+ // virtual void getKProgressBackground(const QColorGroup &g, QBrush &bg);
+ virtual void tabbarMetrics( const QTabBar*, int&, int&, int& );
+ virtual void drawTab( QPainter*, const QTabBar*, QTab*, bool selected );
+ virtual void drawTabMask( QPainter*, const QTabBar*, QTab*, bool selected );
+protected:
+ QPalette oldPalette, popupPalette, indiPalette, exIndiPalette;
+
+ class OThemeStylePrivate;
+ OThemeStylePrivate *d;
+};
+
+#endif
diff --git a/noncore/styles/theme/plugin.cpp b/noncore/styles/theme/plugin.cpp
new file mode 100644
index 0000000..b334357
--- a/dev/null
+++ b/noncore/styles/theme/plugin.cpp
@@ -0,0 +1,19 @@
+//#include <klocale.h>
+#include "othemestyle.h"
+
+extern "C"
+{
+ QStyle * allocate() {
+ return new OThemeStyle ( "" );
+ }
+ int minor_version() {
+ return 0;
+ }
+ int major_version() {
+ return 1;
+ }
+ const char * description() {
+ return ( "Theme Style" );
+ }
+}
+
diff --git a/noncore/styles/theme/settings/main.cpp b/noncore/styles/theme/settings/main.cpp
new file mode 100644
index 0000000..94d40f3
--- a/dev/null
+++ b/noncore/styles/theme/settings/main.cpp
@@ -0,0 +1,34 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "themeset.h"
+
+#include <qpe/qpeapplication.h>
+
+
+int main ( int argc, char** argv )
+{
+ QPEApplication a ( argc, argv );
+
+ ThemeSet dlg;
+ a. showMainWidget ( &dlg );
+
+ return a. exec ( );
+}
diff --git a/noncore/styles/theme/settings/settings.pro b/noncore/styles/theme/settings/settings.pro
new file mode 100644
index 0000000..85d1f7a
--- a/dev/null
+++ b/noncore/styles/theme/settings/settings.pro
@@ -0,0 +1,24 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+DESTDIR = $(OPIEDIR)/bin
+HEADERS = themeset.h
+SOURCES = themeset.cpp main.cpp
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += ../$(OPIEDIR)/include
+LIBS += -lqpe
+TARGET = theme-settings
+
+TRANSLATIONS = ../../../../i18n/de/theme-settings.ts \
+ ../../../../i18n/en/theme-settings.ts \
+ ../../../../i18n/es/theme-settings.ts \
+ ../../../../i18n/fr/theme-settings.ts \
+ ../../../../i18n/hu/theme-settings.ts \
+ ../../../../i18n/ja/theme-settings.ts \
+ ../../../../i18n/ko/theme-settings.ts \
+ ../../../../i18n/no/theme-settings.ts \
+ ../../../../i18n/pl/theme-settings.ts \
+ ../../../../i18n/pt/theme-settings.ts \
+ ../../../../i18n/pt_BR/theme-settings.ts \
+ ../../../../i18n/sl/theme-settings.ts \
+ ../../../../i18n/zh_CN/theme-settings.ts \
+ ../../../../i18n/zh_TW/theme-settings.ts
diff --git a/noncore/styles/theme/settings/themeset.cpp b/noncore/styles/theme/settings/themeset.cpp
new file mode 100644
index 0000000..046618e
--- a/dev/null
+++ b/noncore/styles/theme/settings/themeset.cpp
@@ -0,0 +1,124 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+
+
+#include "themeset.h"
+
+#include <qpe/qpeapplication.h>
+#include <qpe/global.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistview.h>
+#include <qdir.h>
+
+#include <qpe/config.h>
+
+
+class MyConfig : public Config
+{
+public:
+ MyConfig ( const QString &f, Domain d ) : Config ( f, d )
+ { }
+
+ bool hasGroup ( const QString &gname ) const
+ {
+ QMap< QString, ConfigGroup>::ConstIterator it = groups. find ( gname );
+ return ( it != groups.end() );
+ }
+};
+
+class MyItem : public QListViewItem
+{
+public:
+ MyItem ( QListView *lv, const QString &name, const QString &comm, const QString &theme ) : QListViewItem ( lv, name, comm )
+ {
+ m_theme = theme;
+ }
+
+
+ QString m_theme;
+};
+
+
+ThemeSet::ThemeSet ( QWidget* parent, const char *name, WFlags fl )
+ : QDialog ( parent, name, fl )
+{
+ setCaption ( tr( "Theme Style" ) );
+
+ Config config ( "qpe" );
+ config. setGroup ( "Appearance" );
+
+ QString active = config. readEntry ( "Theme", "default" );
+
+ QVBoxLayout *vbox = new QVBoxLayout ( this );
+ vbox-> setSpacing ( 3 );
+ vbox-> setMargin ( 6 );
+
+ vbox-> addWidget ( new QLabel ( tr( "Select the theme to be used" ), this ));
+
+ m_list = new QListView ( this );
+ m_list-> addColumn ( tr( "Name" ));
+ m_list-> addColumn ( tr( "Description" ));
+ m_list-> setSelectionMode ( QListView::Single );
+ m_list-> setAllColumnsShowFocus ( true );
+ vbox-> addWidget ( m_list, 10 );
+
+ QListViewItem *item = new MyItem ( m_list, tr( "[No theme]" ), "", "" );
+ m_list-> setSelected ( item, true );
+
+ QString path = QPEApplication::qpeDir() + "/plugins/styles/themes";
+ QStringList list = QDir ( path, "*.themerc" ). entryList ( );
+
+ for ( QStringList::Iterator it = list. begin(); it != list. end ( ); ++it ) {
+ MyConfig cfg ( path + "/" + *it, Config::File );
+
+ if ( cfg. hasGroup ( "Misc" )) {
+ cfg. setGroup ( "Misc" );
+
+ QString name = cfg. readEntry ( "Name" );
+ QString comm = cfg. readEntry ( "Comment" );
+
+ if ( !name. isEmpty ( )) {
+ QString fname = (*it). left ((*it). length ( ) - 8 );
+
+ item = new MyItem ( m_list, name, comm, fname );
+ if ( active == fname ) {
+ m_list-> setSelected ( item, true );
+ }
+ }
+ }
+ }
+}
+
+void ThemeSet::accept ( )
+{
+ Config config ( "qpe" );
+ config. setGroup ( "Appearance" );
+
+ MyItem *it = (MyItem *) m_list-> selectedItem ( );
+ config. writeEntry ( "Theme", it ? it-> m_theme : QString ( "" ));
+
+ Global::applyStyle ( );
+
+ QDialog::accept ( );
+}
+
diff --git a/noncore/styles/theme/settings/themeset.h b/noncore/styles/theme/settings/themeset.h
new file mode 100644
index 0000000..24804ce
--- a/dev/null
+++ b/noncore/styles/theme/settings/themeset.h
@@ -0,0 +1,20 @@
+#ifndef __OPIE_THEME_SET_H__
+#define __OPIE_THEME_SET_H__
+
+#include <qdialog.h>
+
+class QListView;
+
+class ThemeSet : public QDialog {
+ Q_OBJECT
+
+public:
+ ThemeSet ( QWidget *parent = 0, const char *name = 0, WFlags fl = 0 );
+
+protected:
+ virtual void accept ( );
+
+private:
+ QListView *m_list;
+};
+#endif
diff --git a/noncore/styles/theme/theme.pro b/noncore/styles/theme/theme.pro
new file mode 100644
index 0000000..fdcd20e
--- a/dev/null
+++ b/noncore/styles/theme/theme.pro
@@ -0,0 +1,32 @@
+TEMPLATE = lib
+CONFIG = qt embedded debug warn_on
+SOURCES = ogfxeffect.cpp \
+ othemestyle.cpp \
+ othemebase.cpp \
+ plugin.cpp
+
+HEADERS = ogfxeffect.h \
+ othemebase.h \
+ othemestyle.h
+
+
+LIBS += -lqpe
+INCLUDEPATH += $(OPIEDIR)/include
+DESTDIR = $(OPIEDIR)/plugins/styles
+TARGET = theme
+VERSION = 1.0.0
+
+TRANSLATIONS = ../../../i18n/de/libtheme.ts \
+ ../../../i18n/en/libtheme.ts \
+ ../../../i18n/es/libtheme.ts \
+ ../../../i18n/fr/libtheme.ts \
+ ../../../i18n/hu/libtheme.ts \
+ ../../../i18n/ja/libtheme.ts \
+ ../../../i18n/ko/libtheme.ts \
+ ../../../i18n/no/libtheme.ts \
+ ../../../i18n/pl/libtheme.ts \
+ ../../../i18n/pt/libtheme.ts \
+ ../../../i18n/pt_BR/libtheme.ts \
+ ../../../i18n/sl/libtheme.ts \
+ ../../../i18n/zh_CN/libtheme.ts \
+ ../../../i18n/zh_TW/libtheme.ts
diff --git a/pics/theme/Theme.png b/pics/theme/Theme.png
new file mode 100644
index 0000000..67647d0
--- a/dev/null
+++ b/pics/theme/Theme.png
Binary files differ