-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | apps/Settings/Theme.desktop | 7 | ||||
-rw-r--r-- | noncore/styles/theme/ogfxeffect.cpp | 324 | ||||
-rw-r--r-- | noncore/styles/theme/ogfxeffect.h | 78 | ||||
-rw-r--r-- | noncore/styles/theme/opie-theme.control | 11 | ||||
-rw-r--r-- | noncore/styles/theme/othemebase.cpp | 1212 | ||||
-rw-r--r-- | noncore/styles/theme/othemebase.h | 739 | ||||
-rw-r--r-- | noncore/styles/theme/othemestyle.cpp | 1532 | ||||
-rw-r--r-- | noncore/styles/theme/othemestyle.h | 365 | ||||
-rw-r--r-- | noncore/styles/theme/plugin.cpp | 19 | ||||
-rw-r--r-- | noncore/styles/theme/settings/main.cpp | 34 | ||||
-rw-r--r-- | noncore/styles/theme/settings/settings.pro | 24 | ||||
-rw-r--r-- | noncore/styles/theme/settings/themeset.cpp | 124 | ||||
-rw-r--r-- | noncore/styles/theme/settings/themeset.h | 20 | ||||
-rw-r--r-- | noncore/styles/theme/theme.pro | 32 | ||||
-rw-r--r-- | pics/theme/Theme.png | bin | 0 -> 2771 bytes |
16 files changed, 4522 insertions, 1 deletions
@@ -24,7 +24,7 @@ PLAYER = core/multimedia/opieplayer/libmpeg3 \ | |||
24 | core/multimedia/opieplayer/libmad \ | 24 | core/multimedia/opieplayer/libmad \ |
25 | core/multimedia/opieplayer/wavplugin | 25 | core/multimedia/opieplayer/wavplugin |
26 | 26 | ||
27 | COMPONENTS=$(LOCALCOMPONENTS) $(INPUTCOMPONENTS) $(APPLETS) $(MAIL) $(PLAYER) | 27 | COMPONENTS=$(LOCALCOMPONENTS) $(INPUTCOMPONENTS) $(APPLETS) $(MAIL) # $(PLAYER) |
28 | 28 | ||
29 | 29 | ||
30 | PIMAPPS = core/pim/addressbook core/pim/datebook \ | 30 | PIMAPPS = core/pim/addressbook core/pim/datebook \ |
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 @@ | |||
1 | [Desktop Entry] | ||
2 | Type=Application | ||
3 | Exec=theme-settings | ||
4 | Icon=theme/Theme | ||
5 | Name=Theme-Settings | ||
6 | Name[de]=Thema-Einstellungen | ||
7 | |||
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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net> | ||
3 | (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org> | ||
4 | (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org> | ||
5 | |||
6 | */ | ||
7 | |||
8 | // $Id$ | ||
9 | |||
10 | #include <qimage.h> | ||
11 | #include <qpainter.h> | ||
12 | |||
13 | #include "ogfxeffect.h" | ||
14 | |||
15 | |||
16 | //====================================================================== | ||
17 | // | ||
18 | // Gradient effects | ||
19 | // | ||
20 | //====================================================================== | ||
21 | |||
22 | |||
23 | QPixmap& OGfxEffect::gradient(QPixmap &pixmap, const QColor &ca, | ||
24 | const QColor &cb, GradientType eff, int ncols) | ||
25 | { | ||
26 | if(pixmap.depth() > 8 && | ||
27 | (eff == VerticalGradient || eff == HorizontalGradient)) { | ||
28 | |||
29 | int rDiff, gDiff, bDiff; | ||
30 | int rca, gca, bca /*, rcb, gcb, bcb*/; | ||
31 | |||
32 | register int x, y; | ||
33 | |||
34 | rDiff = (/*rcb = */ cb.red()) - (rca = ca.red()); | ||
35 | gDiff = (/*gcb = */ cb.green()) - (gca = ca.green()); | ||
36 | bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue()); | ||
37 | |||
38 | register int rl = rca << 16; | ||
39 | register int gl = gca << 16; | ||
40 | register int bl = bca << 16; | ||
41 | |||
42 | int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff; | ||
43 | int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff; | ||
44 | int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff; | ||
45 | |||
46 | QPainter p(&pixmap); | ||
47 | |||
48 | // these for-loops could be merged, but the if's in the inner loop | ||
49 | // would make it slow | ||
50 | switch(eff) { | ||
51 | case VerticalGradient: | ||
52 | for ( y = 0; y < pixmap.height(); y++ ) { | ||
53 | rl += rcdelta; | ||
54 | gl += gcdelta; | ||
55 | bl += bcdelta; | ||
56 | |||
57 | p.setPen(QColor(rl>>16, gl>>16, bl>>16)); | ||
58 | p.drawLine(0, y, pixmap.width()-1, y); | ||
59 | } | ||
60 | break; | ||
61 | case HorizontalGradient: | ||
62 | for( x = 0; x < pixmap.width(); x++) { | ||
63 | rl += rcdelta; | ||
64 | gl += gcdelta; | ||
65 | bl += bcdelta; | ||
66 | |||
67 | p.setPen(QColor(rl>>16, gl>>16, bl>>16)); | ||
68 | p.drawLine(x, 0, x, pixmap.height()-1); | ||
69 | } | ||
70 | break; | ||
71 | default: | ||
72 | ; | ||
73 | } | ||
74 | } | ||
75 | else { | ||
76 | // QImage image = OGfxEffect::gradient(pixmap.size(), ca, cb, | ||
77 | // (OGfxEffect::GradientType) eff, ncols); | ||
78 | // pixmap.convertFromImage(image); | ||
79 | } | ||
80 | |||
81 | return pixmap; | ||
82 | } | ||
83 | |||
84 | |||
85 | //====================================================================== | ||
86 | // | ||
87 | // Blend effects | ||
88 | // | ||
89 | //====================================================================== | ||
90 | |||
91 | |||
92 | QPixmap& OGfxEffect::blend(QPixmap &pixmap, float initial_intensity, | ||
93 | const QColor &bgnd, GradientType eff, | ||
94 | bool anti_dir, int ncols) | ||
95 | { | ||
96 | QImage image = pixmap.convertToImage(); | ||
97 | OGfxEffect::blend(image, initial_intensity, bgnd, eff, anti_dir); | ||
98 | |||
99 | unsigned int tmp; | ||
100 | |||
101 | if ( pixmap. depth ( ) <= 8 ) | ||
102 | image. convertDepth ( pixmap. depth ( )); | ||
103 | |||
104 | pixmap.convertFromImage(image); | ||
105 | |||
106 | return pixmap; | ||
107 | } | ||
108 | |||
109 | |||
110 | QImage& OGfxEffect::blend(QImage &image, float initial_intensity, | ||
111 | const QColor &bgnd, GradientType eff, | ||
112 | bool anti_dir) | ||
113 | { | ||
114 | if (image.width() == 0 || image.height() == 0) { | ||
115 | qDebug ( "Invalid image\n" ); | ||
116 | return image; | ||
117 | } | ||
118 | |||
119 | int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue(); | ||
120 | int r, g, b; | ||
121 | int ind; | ||
122 | |||
123 | unsigned int xi, xf, yi, yf; | ||
124 | unsigned int a; | ||
125 | |||
126 | // check the boundaries of the initial intesity param | ||
127 | float unaffected = 1; | ||
128 | if (initial_intensity > 1) initial_intensity = 1; | ||
129 | if (initial_intensity < -1) initial_intensity = -1; | ||
130 | if (initial_intensity < 0) { | ||
131 | unaffected = 1. + initial_intensity; | ||
132 | initial_intensity = 0; | ||
133 | } | ||
134 | |||
135 | |||
136 | float intensity = initial_intensity; | ||
137 | float var = 1. - initial_intensity; | ||
138 | |||
139 | if (anti_dir) { | ||
140 | initial_intensity = intensity = 1.; | ||
141 | var = -var; | ||
142 | } | ||
143 | |||
144 | register int x, y; | ||
145 | |||
146 | unsigned int *data = (unsigned int *)image.bits(); | ||
147 | |||
148 | if( eff == VerticalGradient || eff == HorizontalGradient ) { | ||
149 | |||
150 | // set the image domain to apply the effect to | ||
151 | xi = 0, xf = image.width(); | ||
152 | yi = 0, yf = image.height(); | ||
153 | if (eff == VerticalGradient) { | ||
154 | if (anti_dir) yf = (int)(image.height() * unaffected); | ||
155 | else yi = (int)(image.height() * (1 - unaffected)); | ||
156 | } | ||
157 | else { | ||
158 | if (anti_dir) xf = (int)(image.width() * unaffected); | ||
159 | else xi = (int)(image.height() * (1 - unaffected)); | ||
160 | } | ||
161 | |||
162 | var /= (eff == VerticalGradient?yf-yi:xf-xi); | ||
163 | |||
164 | for (y = yi; y < (int)yf; y++) { | ||
165 | intensity = eff == VerticalGradient? intensity + var : | ||
166 | initial_intensity; | ||
167 | for (x = xi; x < (int)xf ; x++) { | ||
168 | if (eff == HorizontalGradient) intensity += var; | ||
169 | ind = x + image.width() * y ; | ||
170 | r = qRed (data[ind]) + (int)(intensity * | ||
171 | (r_bgnd - qRed (data[ind]))); | ||
172 | g = qGreen(data[ind]) + (int)(intensity * | ||
173 | (g_bgnd - qGreen(data[ind]))); | ||
174 | b = qBlue (data[ind]) + (int)(intensity * | ||
175 | (b_bgnd - qBlue (data[ind]))); | ||
176 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
177 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
178 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
179 | a = qAlpha(data[ind]); | ||
180 | data[ind] = qRgba(r, g, b, a); | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) { | ||
185 | float xvar = var / 2 / image.width(); // / unaffected; | ||
186 | float yvar = var / 2 / image.height(); // / unaffected; | ||
187 | float tmp; | ||
188 | |||
189 | for (x = 0; x < image.width() ; x++) { | ||
190 | tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1); | ||
191 | for (y = 0; y < image.height() ; y++) { | ||
192 | intensity = initial_intensity + tmp + yvar * y; | ||
193 | ind = x + image.width() * y ; | ||
194 | r = qRed (data[ind]) + (int)(intensity * | ||
195 | (r_bgnd - qRed (data[ind]))); | ||
196 | g = qGreen(data[ind]) + (int)(intensity * | ||
197 | (g_bgnd - qGreen(data[ind]))); | ||
198 | b = qBlue (data[ind]) + (int)(intensity * | ||
199 | (b_bgnd - qBlue (data[ind]))); | ||
200 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
201 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
202 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
203 | a = qAlpha(data[ind]); | ||
204 | data[ind] = qRgba(r, g, b, a); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | |||
209 | else if (eff == RectangleGradient || eff == EllipticGradient) { | ||
210 | float xvar; | ||
211 | float yvar; | ||
212 | |||
213 | for (x = 0; x < image.width() / 2 + image.width() % 2; x++) { | ||
214 | xvar = var / image.width() * (image.width() - x*2/unaffected-1); | ||
215 | for (y = 0; y < image.height() / 2 + image.height() % 2; y++) { | ||
216 | yvar = var / image.height() * (image.height() - y*2/unaffected -1); | ||
217 | |||
218 | if (eff == RectangleGradient) | ||
219 | intensity = initial_intensity + QMAX(xvar, yvar); | ||
220 | else | ||
221 | intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar); | ||
222 | if (intensity > 1) intensity = 1; | ||
223 | if (intensity < 0) intensity = 0; | ||
224 | |||
225 | //NW | ||
226 | ind = x + image.width() * y ; | ||
227 | r = qRed (data[ind]) + (int)(intensity * | ||
228 | (r_bgnd - qRed (data[ind]))); | ||
229 | g = qGreen(data[ind]) + (int)(intensity * | ||
230 | (g_bgnd - qGreen(data[ind]))); | ||
231 | b = qBlue (data[ind]) + (int)(intensity * | ||
232 | (b_bgnd - qBlue (data[ind]))); | ||
233 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
234 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
235 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
236 | a = qAlpha(data[ind]); | ||
237 | data[ind] = qRgba(r, g, b, a); | ||
238 | |||
239 | //NE | ||
240 | ind = image.width() - x - 1 + image.width() * y ; | ||
241 | r = qRed (data[ind]) + (int)(intensity * | ||
242 | (r_bgnd - qRed (data[ind]))); | ||
243 | g = qGreen(data[ind]) + (int)(intensity * | ||
244 | (g_bgnd - qGreen(data[ind]))); | ||
245 | b = qBlue (data[ind]) + (int)(intensity * | ||
246 | (b_bgnd - qBlue (data[ind]))); | ||
247 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
248 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
249 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
250 | a = qAlpha(data[ind]); | ||
251 | data[ind] = qRgba(r, g, b, a); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | //CT loop is doubled because of stupid central row/column issue. | ||
256 | // other solution? | ||
257 | for (x = 0; x < image.width() / 2; x++) { | ||
258 | xvar = var / image.width() * (image.width() - x*2/unaffected-1); | ||
259 | for (y = 0; y < image.height() / 2; y++) { | ||
260 | yvar = var / image.height() * (image.height() - y*2/unaffected -1); | ||
261 | |||
262 | if (eff == RectangleGradient) | ||
263 | intensity = initial_intensity + QMAX(xvar, yvar); | ||
264 | else | ||
265 | intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar); | ||
266 | if (intensity > 1) intensity = 1; | ||
267 | if (intensity < 0) intensity = 0; | ||
268 | |||
269 | //SW | ||
270 | ind = x + image.width() * (image.height() - y -1) ; | ||
271 | r = qRed (data[ind]) + (int)(intensity * | ||
272 | (r_bgnd - qRed (data[ind]))); | ||
273 | g = qGreen(data[ind]) + (int)(intensity * | ||
274 | (g_bgnd - qGreen(data[ind]))); | ||
275 | b = qBlue (data[ind]) + (int)(intensity * | ||
276 | (b_bgnd - qBlue (data[ind]))); | ||
277 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
278 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
279 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
280 | a = qAlpha(data[ind]); | ||
281 | data[ind] = qRgba(r, g, b, a); | ||
282 | |||
283 | //SE | ||
284 | ind = image.width()-x-1 + image.width() * (image.height() - y - 1) ; | ||
285 | r = qRed (data[ind]) + (int)(intensity * | ||
286 | (r_bgnd - qRed (data[ind]))); | ||
287 | g = qGreen(data[ind]) + (int)(intensity * | ||
288 | (g_bgnd - qGreen(data[ind]))); | ||
289 | b = qBlue (data[ind]) + (int)(intensity * | ||
290 | (b_bgnd - qBlue (data[ind]))); | ||
291 | if (r > 255) r = 255; if (r < 0 ) r = 0; | ||
292 | if (g > 255) g = 255; if (g < 0 ) g = 0; | ||
293 | if (b > 255) b = 255; if (b < 0 ) b = 0; | ||
294 | a = qAlpha(data[ind]); | ||
295 | data[ind] = qRgba(r, g, b, a); | ||
296 | } | ||
297 | } | ||
298 | } | ||
299 | |||
300 | else | ||
301 | qDebug ( "not implemented\n" ); | ||
302 | |||
303 | return image; | ||
304 | } | ||
305 | |||
306 | #if 0 | ||
307 | // Not very efficient as we create a third big image... | ||
308 | // | ||
309 | QImage& KQGfxEffect::blend(QImage &image1, QImage &image2, | ||
310 | GradientType gt, int xf, int yf) | ||
311 | { | ||
312 | if (image1.width() == 0 || image1.height() == 0 || | ||
313 | image2.width() == 0 || image2.height() == 0) | ||
314 | return image1; | ||
315 | |||
316 | QImage image3; | ||
317 | |||
318 | image3 = KQGfxEffect::unbalancedGradient(image1.size(), | ||
319 | QColor(0,0,0), QColor(255,255,255), | ||
320 | gt, xf, yf, 0); | ||
321 | |||
322 | return blend(image1,image2,image3, Red); // Channel to use is arbitrary | ||
323 | } | ||
324 | #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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net> | ||
3 | (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org> | ||
4 | (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org> | ||
5 | |||
6 | */ | ||
7 | |||
8 | // $Id$ | ||
9 | |||
10 | #ifndef __OGFX_EFFECT_H | ||
11 | #define __OGFX_EFFECT_H | ||
12 | |||
13 | #include <qpixmap.h> | ||
14 | #include <qimage.h> | ||
15 | |||
16 | /** | ||
17 | * This class includes various pixmap-based graphical effects. | ||
18 | * | ||
19 | * Everything is | ||
20 | * static, so there is no need to create an instance of this class. You can | ||
21 | * just call the static methods. They are encapsulated here merely to provide | ||
22 | * a common namespace. | ||
23 | */ | ||
24 | class OGfxEffect | ||
25 | { | ||
26 | public: | ||
27 | enum GradientType { VerticalGradient, HorizontalGradient, | ||
28 | DiagonalGradient, CrossDiagonalGradient, | ||
29 | PyramidGradient, RectangleGradient, | ||
30 | PipeCrossGradient, EllipticGradient }; | ||
31 | enum RGBComponent { Red, Green, Blue }; | ||
32 | |||
33 | enum Lighting {NorthLite, NWLite, WestLite, SWLite, | ||
34 | SouthLite, SELite, EastLite, NELite}; | ||
35 | |||
36 | /** | ||
37 | * Create a gradient from color a to color b of the specified type. | ||
38 | * | ||
39 | * @param pixmap The pixmap to process. | ||
40 | * @param ca Color a. | ||
41 | * @param cb Color b. | ||
42 | * @param type The type of gradient. | ||
43 | * @param ncols The number of colors to use when not running on a | ||
44 | * truecolor display. The gradient will be dithered to this number of | ||
45 | * colors. Pass 0 to prevent dithering. | ||
46 | * @return Returns the generated pixmap, for convenience. | ||
47 | */ | ||
48 | static QPixmap& gradient(QPixmap& pixmap, const QColor &ca, const QColor &cb, | ||
49 | GradientType type, int ncols=3); | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Blend the provided pixmap into a background of the indicated color | ||
54 | * | ||
55 | * @param pixmap The pixmap to process. | ||
56 | * @param initial_intensity this parameter takes values from -1 to 1: | ||
57 | * @li If positive, it tells how much to fade the image in its | ||
58 | * less affected spot. | ||
59 | * @li If negative, it tells roughly indicates how much of the image | ||
60 | * remains unaffected | ||
61 | * @param bgnd Indicates the color of the background to blend in. | ||
62 | * @param eff Lets you choose what kind of blending you like. | ||
63 | * @param anti_dir Blend in the opposite direction (makes no much sense | ||
64 | * with concentric blending effects). | ||
65 | * @return Returns the @ref pixmap(), provided for convenience. | ||
66 | */ | ||
67 | static QPixmap& blend(QPixmap& pixmap, float initial_intensity, | ||
68 | const QColor &bgnd, GradientType eff, | ||
69 | bool anti_dir=false, int ncols=3); | ||
70 | |||
71 | |||
72 | static QImage& blend(QImage &image, float initial_intensity, | ||
73 | const QColor &bgnd, GradientType eff, | ||
74 | bool anti_dir); | ||
75 | }; | ||
76 | |||
77 | |||
78 | #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 @@ | |||
1 | Files: plugins/styles/libtheme.so* bin/theme-settings apps/Settings/Theme.desktop pics/theme/Theme.png | ||
2 | Priority: optional | ||
3 | Section: opie/system | ||
4 | Maintainer: Robert Griebl <sandman@handhelds.org> | ||
5 | Architecture: arm | ||
6 | Version: $QPE_VERSION-$SUB_VERSION.1 | ||
7 | Depends: opie-base ($QPE_VERSION) | ||
8 | Description: Themed style. | ||
9 | This style accepts all themes written | ||
10 | for KDE 2.2 | ||
11 | |||
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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public | ||
6 | License version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This library is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | Library General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Library General Public License | ||
14 | along with this library; see the file COPYING.LIB. If not, write to | ||
15 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | #include "othemebase.h" | ||
19 | #include "ogfxeffect.h" | ||
20 | #include <qpe/qpeapplication.h> | ||
21 | //#include <kdebug.h> | ||
22 | //#include <klocale.h> | ||
23 | #include <qpe/config.h> | ||
24 | //#include <kglobal.h> | ||
25 | //#include <kglobalsettings.h> | ||
26 | //#include <kstddirs.h> | ||
27 | #include <qfile.h> | ||
28 | #include <qtextstream.h> | ||
29 | #include <qdir.h> | ||
30 | #include <qpainter.h> | ||
31 | #include <qbitmap.h> | ||
32 | #include <stdlib.h> | ||
33 | #include <qstringlist.h> | ||
34 | |||
35 | #include <stdio.h> | ||
36 | |||
37 | template class QIntCache<OThemePixmap> | ||
38 | ; | ||
39 | |||
40 | static const char *widgetEntries[] = | ||
41 | { // unsunken widgets (see header) | ||
42 | "PushButton", "ComboBox", "HSBarSlider", "VSBarSlider", "Bevel", "ToolButton", | ||
43 | "ScrollButton", "HScrollDeco", "VScrollDeco", "ComboDeco", "MenuItem", "Tab", | ||
44 | "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", | ||
45 | // sunken widgets | ||
46 | "PushButtonDown", "ComboBoxDown", "HSBarSliderDown", "VSBarSliderDown", | ||
47 | "BevelDown", "ToolButtonDown", "ScrollButtonDown", "HScrollDecoDown", | ||
48 | "VScrollDecoDown", "ComboDecoDown", "MenuItemDown", "TabDown", "SunkenArrowUp", | ||
49 | "SunkenArrowDown", "SunkenArrowLeft", "SunkenArrowRight", | ||
50 | // everything else | ||
51 | "HScrollGroove", "VScrollGroove", "Slider", "SliderGroove", "CheckBoxDown", | ||
52 | "CheckBox", "RadioDown", "Radio", "HBarHandle", "VBarHandle", | ||
53 | "ToolBar", "Splitter", "CheckMark", "MenuBar", "DisableArrowUp", | ||
54 | "DisableArrowDown", "DisableArrowLeft", "DisableArrowRight", "ProgressBar", | ||
55 | "ProgressBackground", "MenuBarItem", "Background" | ||
56 | }; | ||
57 | |||
58 | #define INHERIT_ITEMS 16 | ||
59 | |||
60 | |||
61 | // This is used to encode the keys. I used to use masks but I think this | ||
62 | // bitfield is nicer :) I don't know why C++ coders don't use these more.. | ||
63 | // (mosfet) | ||
64 | struct kthemeKeyData | ||
65 | { | ||
66 | unsigned int id : | ||
67 | 6; | ||
68 | unsigned int width : | ||
69 | 12; | ||
70 | unsigned int height : | ||
71 | 12; | ||
72 | unsigned int border : | ||
73 | 1; | ||
74 | unsigned int mask : | ||
75 | 1; | ||
76 | }; | ||
77 | |||
78 | union kthemeKey{ | ||
79 | kthemeKeyData data; | ||
80 | unsigned int cacheKey; | ||
81 | }; | ||
82 | |||
83 | class MyConfig : public Config | ||
84 | { | ||
85 | public: | ||
86 | MyConfig ( const QString &f, Domain d ) : Config ( f, d ) | ||
87 | { } | ||
88 | |||
89 | bool hasGroup ( const QString &gname ) const | ||
90 | { | ||
91 | QMap< QString, ConfigGroup>::ConstIterator it = groups. find ( gname ); | ||
92 | return ( it != groups.end() ); | ||
93 | } | ||
94 | }; | ||
95 | |||
96 | void OThemeBase::generateBorderPix( int i ) | ||
97 | { | ||
98 | // separate pixmap into separate components | ||
99 | if ( pbPixmaps[ i ] ) { | ||
100 | // evidently I have to do masks manually... | ||
101 | const QBitmap * srcMask = pbPixmaps[ i ] ->mask(); | ||
102 | QBitmap destMask( pbWidth[ i ], pbWidth[ i ] ); | ||
103 | QPixmap tmp( pbWidth[ i ], pbWidth[ i ] ); | ||
104 | |||
105 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, 0, pbWidth[ i ], pbWidth[ i ], | ||
106 | Qt::CopyROP, false ); | ||
107 | if ( srcMask ) { | ||
108 | bitBlt( &destMask, 0, 0, srcMask, 0, 0, pbWidth[ i ], pbWidth[ i ], | ||
109 | Qt::CopyROP, false ); | ||
110 | tmp.setMask( destMask ); | ||
111 | } | ||
112 | pbPixmaps[ i ] ->setBorder( OThemePixmap::TopLeft, tmp ); | ||
113 | |||
114 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], 0, | ||
115 | pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); | ||
116 | if ( srcMask ) { | ||
117 | bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], | ||
118 | 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); | ||
119 | tmp.setMask( destMask ); | ||
120 | } | ||
121 | pbPixmaps[ i ] ->setBorder( OThemePixmap::TopRight, tmp ); | ||
122 | |||
123 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbPixmaps[ i ] ->height() - pbWidth[ i ], | ||
124 | pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); | ||
125 | if ( srcMask ) { | ||
126 | bitBlt( &destMask, 0, 0, srcMask, 0, pbPixmaps[ i ] ->height() - pbWidth[ i ], | ||
127 | pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); | ||
128 | tmp.setMask( destMask ); | ||
129 | } | ||
130 | pbPixmaps[ i ] ->setBorder( OThemePixmap::BottomLeft, tmp ); | ||
131 | |||
132 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], | ||
133 | pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], | ||
134 | Qt::CopyROP, false ); | ||
135 | if ( srcMask ) { | ||
136 | bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], | ||
137 | pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], | ||
138 | Qt::CopyROP, false ); | ||
139 | tmp.setMask( destMask ); | ||
140 | } | ||
141 | pbPixmaps[ i ] ->setBorder( OThemePixmap::BottomRight, tmp ); | ||
142 | |||
143 | tmp.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] ); | ||
144 | destMask.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] ); | ||
145 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ], 0, | ||
146 | pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); | ||
147 | if ( srcMask ) { | ||
148 | bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ], 0, | ||
149 | pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], | ||
150 | Qt::CopyROP, false ); | ||
151 | tmp.setMask( destMask ); | ||
152 | } | ||
153 | pbPixmaps[ i ] ->setBorder( OThemePixmap::Top, tmp ); | ||
154 | |||
155 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ], | ||
156 | pbPixmaps[ i ] ->height() - pbWidth[ i ], | ||
157 | pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); | ||
158 | if ( srcMask ) { | ||
159 | bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ], | ||
160 | pbPixmaps[ i ] ->height() - pbWidth[ i ], | ||
161 | pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); | ||
162 | tmp.setMask( destMask ); | ||
163 | } | ||
164 | pbPixmaps[ i ] ->setBorder( OThemePixmap::Bottom, tmp ); | ||
165 | |||
166 | tmp.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 ); | ||
167 | destMask.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 ); | ||
168 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbWidth[ i ], pbWidth[ i ], | ||
169 | pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); | ||
170 | if ( srcMask ) { | ||
171 | bitBlt( &destMask, 0, 0, srcMask, 0, pbWidth[ i ], pbWidth[ i ], | ||
172 | pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); | ||
173 | tmp.setMask( destMask ); | ||
174 | } | ||
175 | |||
176 | pbPixmaps[ i ] ->setBorder( OThemePixmap::Left, tmp ); | ||
177 | |||
178 | bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], | ||
179 | pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, | ||
180 | Qt::CopyROP, false ); | ||
181 | if ( srcMask ) { | ||
182 | bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], | ||
183 | pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, | ||
184 | Qt::CopyROP, false ); | ||
185 | tmp.setMask( destMask ); | ||
186 | } | ||
187 | pbPixmaps[ i ] ->setBorder( OThemePixmap::Right, tmp ); | ||
188 | } | ||
189 | else | ||
190 | qDebug ( "OThemeBase: Tried making border from empty pixmap" ); | ||
191 | } | ||
192 | |||
193 | |||
194 | void OThemeBase::copyWidgetConfig( int sourceID, int destID, QString *pixnames, | ||
195 | QString *brdnames ) | ||
196 | { | ||
197 | scaleHints[ destID ] = scaleHints[ sourceID ]; | ||
198 | gradients[ destID ] = gradients[ sourceID ]; | ||
199 | blends[ destID ] = blends[ sourceID ]; | ||
200 | bContrasts[ destID ] = bContrasts[ sourceID ]; | ||
201 | borders[ destID ] = borders[ sourceID ]; | ||
202 | highlights[ destID ] = highlights[ sourceID ]; | ||
203 | |||
204 | if ( grLowColors[ sourceID ] ) | ||
205 | grLowColors[ destID ] = new QColor( *grLowColors[ sourceID ] ); | ||
206 | else | ||
207 | grLowColors[ destID ] = NULL; | ||
208 | |||
209 | if ( grHighColors[ sourceID ] ) | ||
210 | grHighColors[ destID ] = new QColor( *grHighColors[ sourceID ] ); | ||
211 | else | ||
212 | grHighColors[ destID ] = NULL; | ||
213 | |||
214 | if ( colors[ sourceID ] ) | ||
215 | colors[ destID ] = new QColorGroup( *colors[ sourceID ] ); | ||
216 | else | ||
217 | colors[ destID ] = NULL; | ||
218 | |||
219 | // pixmap | ||
220 | pixnames[ destID ] = pixnames[ sourceID ]; | ||
221 | duplicate[ destID ] = false; | ||
222 | pixmaps[ destID ] = NULL; | ||
223 | images[ destID ] = NULL; | ||
224 | if ( !pixnames[ destID ].isEmpty() ) { | ||
225 | if ( scaleHints[ sourceID ] == TileScale && blends[ sourceID ] == 0.0 ) { | ||
226 | pixmaps[ destID ] = pixmaps[ sourceID ]; | ||
227 | duplicate[ destID ] = true; | ||
228 | } | ||
229 | if ( !duplicate[ destID ] ) { | ||
230 | pixmaps[ destID ] = loadPixmap( pixnames[ destID ] ); | ||
231 | if ( scaleHints[ destID ] == TileScale && blends[ destID ] == 0.0 ) | ||
232 | images[ destID ] = NULL; | ||
233 | else | ||
234 | images[ destID ] = loadImage( pixnames[ destID ] ); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | // border pixmap | ||
239 | pbDuplicate[ destID ] = false; | ||
240 | pbPixmaps[ destID ] = NULL; | ||
241 | pbWidth[ destID ] = pbWidth[ sourceID ]; | ||
242 | brdnames[ destID ] = brdnames[ sourceID ]; | ||
243 | if ( !brdnames[ destID ].isEmpty() ) { | ||
244 | pbPixmaps[ destID ] = pbPixmaps[ sourceID ]; | ||
245 | pbDuplicate[ destID ] = true; | ||
246 | } | ||
247 | |||
248 | if ( sourceID == ActiveTab && destID == InactiveTab ) | ||
249 | aTabLine = iTabLine; | ||
250 | else if ( sourceID == InactiveTab && destID == ActiveTab ) | ||
251 | iTabLine = aTabLine; | ||
252 | } | ||
253 | |||
254 | void OThemeBase::readConfig( Qt::GUIStyle /*style*/ ) | ||
255 | { | ||
256 | #define PREBLEND_ITEMS 12 | ||
257 | static WidgetType preBlend[] = {Slider, IndicatorOn, IndicatorOff, | ||
258 | ExIndicatorOn, ExIndicatorOff, HScrollDeco, VScrollDeco, HScrollDecoDown, | ||
259 | VScrollDecoDown, ComboDeco, ComboDecoDown, CheckMark}; | ||
260 | |||
261 | int i; | ||
262 | QString tmpStr; | ||
263 | QString copyfrom[ WIDGETS ]; | ||
264 | QString pixnames[ WIDGETS ]; // used for duplicate check | ||
265 | QString brdnames[ WIDGETS ]; | ||
266 | bool loaded[ WIDGETS ]; // used for preloading for CopyWidget | ||
267 | |||
268 | if ( configFileName.isEmpty() ) { | ||
269 | Config cfg ( "qpe" ); | ||
270 | cfg. setGroup ( "Appearance" ); | ||
271 | |||
272 | configFileName = cfg. readEntry ( "Theme", "default" ); | ||
273 | } | ||
274 | MyConfig config( configFilePath + "/themes/" + configFileName + ".themerc" , Config::File ); | ||
275 | |||
276 | printf ( "Opened config file: %s\n", ( configFilePath + "/themes/" + configFileName + ".themerc" ). ascii()); | ||
277 | |||
278 | // Are we initalized? | ||
279 | for ( i = 0; i < INHERIT_ITEMS; ++i ) { | ||
280 | applyResourceGroup( &config, i, copyfrom, pixnames, brdnames ); | ||
281 | printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() ); | ||
282 | } | ||
283 | for ( ; i < INHERIT_ITEMS*2; ++i ) { | ||
284 | if ( config.hasGroup( QString( widgetEntries[ i ] ) ) ) { | ||
285 | applyResourceGroup( &config, i, copyfrom, pixnames, brdnames ); | ||
286 | printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() ); | ||
287 | } | ||
288 | else { | ||
289 | copyfrom [ i ] = widgetEntries[ i - INHERIT_ITEMS ]; | ||
290 | printf ( "%d [%s]: copy=%s\n", i, widgetEntries [i], copyfrom [i].latin1()); | ||
291 | } | ||
292 | } | ||
293 | for ( ; i < WIDGETS; ++i ) { | ||
294 | applyResourceGroup( &config, i, copyfrom, pixnames, brdnames ); | ||
295 | printf ( "%d [%s]: copy=%s, pix=%s, brd=%s\n", i, widgetEntries [i], copyfrom [i].latin1(), pixnames[i].latin1(),brdnames[i].latin1() ); | ||
296 | } | ||
297 | applyMiscResourceGroup( &config ); | ||
298 | |||
299 | // initalize defaults that may not be read | ||
300 | for ( i = 0; i < WIDGETS; ++i ) | ||
301 | loaded[ i ] = false; | ||
302 | btnXShift = btnYShift = focus3DOffset = 0; | ||
303 | aTabLine = iTabLine = true; | ||
304 | roundedButton = roundedCombo = roundedSlider = focus3D = false; | ||
305 | splitterWidth = 10; | ||
306 | |||
307 | for ( i = 0; i < WIDGETS; ++i ) { | ||
308 | readResourceGroup( i, copyfrom, pixnames, brdnames, loaded ); | ||
309 | 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)" )); | ||
310 | } | ||
311 | |||
312 | // misc items | ||
313 | readMiscResourceGroup(); | ||
314 | |||
315 | // Handle preblend items | ||
316 | for ( i = 0; i < PREBLEND_ITEMS; ++i ) { | ||
317 | if ( pixmaps[ preBlend[ i ] ] != NULL && blends[ preBlend[ i ] ] != 0.0 ) | ||
318 | blend( preBlend[ i ] ); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | OThemeBase::OThemeBase( const QString & configFile ) | ||
323 | : QWindowsStyle() | ||
324 | { | ||
325 | configFilePath = QPEApplication::qpeDir ( ) + "/plugins/styles/"; | ||
326 | configFileName = configFile; | ||
327 | |||
328 | readConfig( Qt::WindowsStyle ); | ||
329 | cache = new OThemeCache( cacheSize ); | ||
330 | } | ||
331 | |||
332 | void OThemeBase::applyConfigFile( const QString &/*file*/ ) | ||
333 | { | ||
334 | #if 0 | ||
335 | // handle std color scheme | ||
336 | Config inConfig( file, Config::File ); | ||
337 | Config globalConfig ( "qpe" ); | ||
338 | |||
339 | globalConfig. setGroup ( "Apperance" ); | ||
340 | inConfig. setGroup( "General" ); | ||
341 | |||
342 | if ( inConfig.hasKey( "foreground" ) ) | ||
343 | globalConfig.writeEntry( "Text", inConfig.readEntry( "foreground", " " ) ); | ||
344 | if ( inConfig.hasKey( "background" ) ) | ||
345 | globalConfig.writeEntry( "Background", inConfig.readEntry( "background", " " ) ); | ||
346 | if ( inConfig.hasKey( "selectForeground" ) ) | ||
347 | globalConfig.writeEntry( "HighlightedText", inConfig.readEntry( "selectForeground", " " ) ); | ||
348 | if ( inConfig.hasKey( "selectBackground" ) ) | ||
349 | globalConfig.writeEntry( "Highlight", inConfig.readEntry( "selectBackground", " " ) ); | ||
350 | if ( inConfig.hasKey( "windowForeground" ) ) | ||
351 | globalConfig.writeEntry( "Text", inConfig.readEntry( "windowForeground", " " ) ); | ||
352 | if ( inConfig.hasKey( "windowBackground" ) ) | ||
353 | globalConfig.writeEntry( "Base", inConfig.readEntry( "windowBackground", " " ) ); | ||
354 | |||
355 | // Keep track of the current theme so that we can select the right one | ||
356 | // in the KControl module. | ||
357 | globalConfig.writeEntry ( "CurrentTheme", file ); | ||
358 | |||
359 | globalConfig.write(); | ||
360 | #endif | ||
361 | } | ||
362 | |||
363 | OThemeBase::~OThemeBase() | ||
364 | { | ||
365 | int i; | ||
366 | for ( i = 0; i < WIDGETS; ++i ) { | ||
367 | if ( !duplicate[ i ] ) { | ||
368 | if ( images[ i ] ) | ||
369 | delete images[ i ]; | ||
370 | if ( pixmaps[ i ] ) | ||
371 | delete pixmaps[ i ]; | ||
372 | } | ||
373 | if ( !pbDuplicate[ i ] && pbPixmaps[ i ] ) | ||
374 | delete pbPixmaps[ i ]; | ||
375 | if ( colors[ i ] ) | ||
376 | delete( colors[ i ] ); | ||
377 | if ( grLowColors[ i ] ) | ||
378 | delete( grLowColors[ i ] ); | ||
379 | if ( grHighColors[ i ] ) | ||
380 | delete( grHighColors[ i ] ); | ||
381 | } | ||
382 | delete cache; | ||
383 | } | ||
384 | |||
385 | QImage* OThemeBase::loadImage( QString &name ) | ||
386 | { | ||
387 | QImage * image = new QImage; | ||
388 | QString path = configFilePath + "/pixmaps/" + name; | ||
389 | image->load( path ); | ||
390 | if ( !image->isNull() ) | ||
391 | return ( image ); | ||
392 | qDebug ( "OThemeBase: Unable to load image %s\n", name.ascii ( ) ); | ||
393 | delete image; | ||
394 | return ( NULL ); | ||
395 | } | ||
396 | |||
397 | OThemePixmap* OThemeBase::loadPixmap( QString &name ) | ||
398 | { | ||
399 | OThemePixmap * pixmap = new OThemePixmap( false ); | ||
400 | QString path = configFilePath + "/pixmaps/" + name; | ||
401 | pixmap->load( path ); | ||
402 | if ( !pixmap->isNull() ) | ||
403 | return pixmap; | ||
404 | qDebug ( "OThemeBase: Unable to load pixmap %s\n", name.ascii() ); | ||
405 | delete pixmap; | ||
406 | return ( NULL ); | ||
407 | } | ||
408 | |||
409 | OThemePixmap* OThemeBase::scale( int w, int h, WidgetType widget ) | ||
410 | { | ||
411 | if ( scaleHints[ widget ] == FullScale ) { | ||
412 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || | ||
413 | pixmaps[ widget ] ->height() != h ) { | ||
414 | OThemePixmap * cachePix = cache->pixmap( w, h, widget ); | ||
415 | if ( cachePix ) { | ||
416 | cachePix = new OThemePixmap( *cachePix ); | ||
417 | if ( pixmaps[ widget ] ) | ||
418 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, | ||
419 | widget ); | ||
420 | else | ||
421 | qDebug( "We would have inserted a null pixmap!\n" ); | ||
422 | pixmaps[ widget ] = cachePix; | ||
423 | } | ||
424 | else { | ||
425 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget ); | ||
426 | QImage tmpImg = images[ widget ] ->smoothScale( w, h ); | ||
427 | pixmaps[ widget ] = new OThemePixmap; | ||
428 | pixmaps[ widget ] ->convertFromImage( tmpImg ); | ||
429 | if ( blends[ widget ] != 0.0 ) | ||
430 | blend( widget ); | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | else if ( scaleHints[ widget ] == HorizontalScale ) { | ||
435 | if ( pixmaps[ widget ] ->width() != w ) { | ||
436 | OThemePixmap * cachePix = cache->horizontalPixmap( w, widget ); | ||
437 | if ( cachePix ) { | ||
438 | cachePix = new OThemePixmap( *cachePix ); | ||
439 | if ( pixmaps[ widget ] ) | ||
440 | cache->insert( pixmaps[ widget ], OThemeCache::HorizontalScale, widget ); | ||
441 | else | ||
442 | qDebug ( "We would have inserted a null pixmap!\n" ); | ||
443 | pixmaps[ widget ] = cachePix; | ||
444 | } | ||
445 | else { | ||
446 | cache->insert( pixmaps[ widget ], OThemeCache::HorizontalScale, widget ); | ||
447 | QImage tmpImg = images[ widget ] -> | ||
448 | smoothScale( w, images[ widget ] ->height() ); | ||
449 | pixmaps[ widget ] = new OThemePixmap; | ||
450 | pixmaps[ widget ] ->convertFromImage( tmpImg ); | ||
451 | if ( blends[ widget ] != 0.0 ) | ||
452 | blend( widget ); | ||
453 | } | ||
454 | } | ||
455 | } | ||
456 | else if ( scaleHints[ widget ] == VerticalScale ) { | ||
457 | if ( pixmaps[ widget ] ->height() != h ) { | ||
458 | OThemePixmap * cachePix = cache->verticalPixmap( w, widget ); | ||
459 | if ( cachePix ) { | ||
460 | cachePix = new OThemePixmap( *cachePix ); | ||
461 | if ( pixmaps[ widget ] ) | ||
462 | cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, widget ); | ||
463 | else | ||
464 | qDebug ( "We would have inserted a null pixmap!\n" ); | ||
465 | pixmaps[ widget ] = cachePix; | ||
466 | } | ||
467 | else { | ||
468 | cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, widget ); | ||
469 | QImage tmpImg = | ||
470 | images[ widget ] ->smoothScale( images[ widget ] ->width(), h ); | ||
471 | pixmaps[ widget ] = new OThemePixmap; | ||
472 | pixmaps[ widget ] ->convertFromImage( tmpImg ); | ||
473 | if ( blends[ widget ] != 0.0 ) | ||
474 | blend( widget ); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | // If blended tile here so the blend is scaled properly | ||
479 | else if ( scaleHints[ widget ] == TileScale && blends[ widget ] != 0.0 ) { | ||
480 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || | ||
481 | pixmaps[ widget ] ->height() != h ) { | ||
482 | OThemePixmap * cachePix = cache->pixmap( w, h, widget ); | ||
483 | if ( cachePix ) { | ||
484 | cachePix = new OThemePixmap( *cachePix ); | ||
485 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget ); | ||
486 | pixmaps[ widget ] = cachePix; | ||
487 | } | ||
488 | else { | ||
489 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, widget ); | ||
490 | QPixmap tile; | ||
491 | tile.convertFromImage( *images[ widget ] ); | ||
492 | pixmaps[ widget ] = new OThemePixmap; | ||
493 | pixmaps[ widget ] ->resize( w, h ); | ||
494 | QPainter p( pixmaps[ widget ] ); | ||
495 | p.drawTiledPixmap( 0, 0, w, h, tile ); | ||
496 | if ( blends[ widget ] != 0.0 ) | ||
497 | blend( widget ); | ||
498 | } | ||
499 | } | ||
500 | } | ||
501 | return ( pixmaps[ widget ] ); | ||
502 | } | ||
503 | |||
504 | OThemePixmap* OThemeBase::scaleBorder( int w, int h, WidgetType widget ) | ||
505 | { | ||
506 | OThemePixmap * pixmap = NULL; | ||
507 | if ( !pbPixmaps[ widget ] && !pbWidth[ widget ] ) | ||
508 | return ( NULL ); | ||
509 | pixmap = cache->pixmap( w, h, widget, true ); | ||
510 | if ( pixmap ) { | ||
511 | pixmap = new OThemePixmap( *pixmap ); | ||
512 | } | ||
513 | else { | ||
514 | pixmap = new OThemePixmap(); | ||
515 | pixmap->resize( w, h ); | ||
516 | QBitmap mask; | ||
517 | mask.resize( w, h ); | ||
518 | mask.fill( color0 ); | ||
519 | QPainter mPainter; | ||
520 | mPainter.begin( &mask ); | ||
521 | |||
522 | QPixmap *tmp = borderPixmap( widget ) ->border( OThemePixmap::TopLeft ); | ||
523 | const QBitmap *srcMask = tmp->mask(); | ||
524 | int bdWidth = tmp->width(); | ||
525 | |||
526 | bitBlt( pixmap, 0, 0, tmp, 0, 0, bdWidth, bdWidth, | ||
527 | Qt::CopyROP, false ); | ||
528 | if ( srcMask ) | ||
529 | bitBlt( &mask, 0, 0, srcMask, 0, 0, bdWidth, bdWidth, | ||
530 | Qt::CopyROP, false ); | ||
531 | else | ||
532 | mPainter.fillRect( 0, 0, bdWidth, bdWidth, color1 ); | ||
533 | |||
534 | |||
535 | tmp = borderPixmap( widget ) ->border( OThemePixmap::TopRight ); | ||
536 | srcMask = tmp->mask(); | ||
537 | bitBlt( pixmap, w - bdWidth, 0, tmp, 0, 0, bdWidth, | ||
538 | bdWidth, Qt::CopyROP, false ); | ||
539 | if ( srcMask ) | ||
540 | bitBlt( &mask, w - bdWidth, 0, srcMask, 0, 0, bdWidth, | ||
541 | bdWidth, Qt::CopyROP, false ); | ||
542 | else | ||
543 | mPainter.fillRect( w - bdWidth, 0, bdWidth, bdWidth, color1 ); | ||
544 | |||
545 | tmp = borderPixmap( widget ) ->border( OThemePixmap::BottomLeft ); | ||
546 | srcMask = tmp->mask(); | ||
547 | bitBlt( pixmap, 0, h - bdWidth, tmp, 0, 0, bdWidth, | ||
548 | bdWidth, Qt::CopyROP, false ); | ||
549 | if ( srcMask ) | ||
550 | bitBlt( &mask, 0, h - bdWidth, srcMask, 0, 0, bdWidth, | ||
551 | bdWidth, Qt::CopyROP, false ); | ||
552 | else | ||
553 | mPainter.fillRect( 0, h - bdWidth, bdWidth, bdWidth, color1 ); | ||
554 | |||
555 | tmp = borderPixmap( widget ) ->border( OThemePixmap::BottomRight ); | ||
556 | srcMask = tmp->mask(); | ||
557 | bitBlt( pixmap, w - bdWidth, h - bdWidth, tmp, 0, 0, | ||
558 | bdWidth, bdWidth, Qt::CopyROP, false ); | ||
559 | if ( srcMask ) | ||
560 | bitBlt( &mask, w - bdWidth, h - bdWidth, srcMask, 0, 0, | ||
561 | bdWidth, bdWidth, Qt::CopyROP, false ); | ||
562 | else | ||
563 | mPainter.fillRect( w - bdWidth, h - bdWidth, bdWidth, bdWidth, color1 ); | ||
564 | |||
565 | QPainter p; | ||
566 | p.begin( pixmap ); | ||
567 | if ( w - bdWidth * 2 > 0 ) { | ||
568 | tmp = borderPixmap( widget ) ->border( OThemePixmap::Top ); | ||
569 | srcMask = tmp->mask(); | ||
570 | p.drawTiledPixmap( bdWidth, 0, w - bdWidth * 2, bdWidth, *tmp ); | ||
571 | if ( srcMask ) | ||
572 | mPainter.drawTiledPixmap( bdWidth, 0, w - bdWidth * 2, bdWidth, *srcMask ); | ||
573 | else | ||
574 | mPainter.fillRect( bdWidth, 0, w - bdWidth * 2, bdWidth, color1 ); | ||
575 | |||
576 | tmp = borderPixmap( widget ) ->border( OThemePixmap::Bottom ); | ||
577 | srcMask = tmp->mask(); | ||
578 | p.drawTiledPixmap( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, | ||
579 | *tmp ); | ||
580 | if ( srcMask ) | ||
581 | mPainter.drawTiledPixmap( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, *srcMask ); | ||
582 | else | ||
583 | mPainter.fillRect( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, | ||
584 | color1 ); | ||
585 | } | ||
586 | if ( h - bdWidth * 2 > 0 ) { | ||
587 | tmp = borderPixmap( widget ) ->border( OThemePixmap::Left ); | ||
588 | srcMask = tmp->mask(); | ||
589 | p.drawTiledPixmap( 0, bdWidth, bdWidth, h - bdWidth * 2, *tmp ); | ||
590 | if ( srcMask ) | ||
591 | mPainter.drawTiledPixmap( 0, bdWidth, bdWidth, h - bdWidth * 2, *srcMask ); | ||
592 | else | ||
593 | mPainter.fillRect( 0, bdWidth, bdWidth, h - bdWidth * 2, color1 ); | ||
594 | |||
595 | tmp = borderPixmap( widget ) ->border( OThemePixmap::Right ); | ||
596 | srcMask = tmp->mask(); | ||
597 | p.drawTiledPixmap( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, | ||
598 | *tmp ); | ||
599 | if ( srcMask ) | ||
600 | mPainter.drawTiledPixmap( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, *srcMask ); | ||
601 | else | ||
602 | mPainter.fillRect( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, color1 ); | ||
603 | } | ||
604 | p.end(); | ||
605 | mPainter.end(); | ||
606 | pixmap->setMask( mask ); | ||
607 | cache->insert( pixmap, OThemeCache::FullScale, widget, true ); | ||
608 | if ( !pixmap->mask() ) | ||
609 | qDebug ( "No mask for border pixmap!\n" ); | ||
610 | } | ||
611 | return ( pixmap ); | ||
612 | } | ||
613 | |||
614 | |||
615 | OThemePixmap* OThemeBase::blend( WidgetType widget ) | ||
616 | { | ||
617 | OGfxEffect::GradientType g; | ||
618 | switch ( gradients[ widget ] ) { | ||
619 | case GrHorizontal: | ||
620 | g = OGfxEffect::HorizontalGradient; | ||
621 | break; | ||
622 | case GrVertical: | ||
623 | g = OGfxEffect::VerticalGradient; | ||
624 | break; | ||
625 | case GrPyramid: | ||
626 | g = OGfxEffect::PyramidGradient; | ||
627 | break; | ||
628 | case GrRectangle: | ||
629 | g = OGfxEffect::RectangleGradient; | ||
630 | break; | ||
631 | case GrElliptic: | ||
632 | g = OGfxEffect::EllipticGradient; | ||
633 | break; | ||
634 | default: | ||
635 | g = OGfxEffect::DiagonalGradient; | ||
636 | break; | ||
637 | } | ||
638 | OGfxEffect::blend( *pixmaps[ widget ], blends[ widget ], *grLowColors[ widget ], | ||
639 | g, false ); | ||
640 | return ( pixmaps[ widget ] ); | ||
641 | } | ||
642 | |||
643 | OThemePixmap* OThemeBase::gradient( int w, int h, WidgetType widget ) | ||
644 | { | ||
645 | if ( gradients[ widget ] == GrVertical ) { | ||
646 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->height() != h ) { | ||
647 | OThemePixmap * cachePix = cache->verticalPixmap( h, widget ); | ||
648 | if ( cachePix ) { | ||
649 | cachePix = new OThemePixmap( *cachePix ); | ||
650 | if ( pixmaps[ widget ] ) | ||
651 | cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, | ||
652 | widget ); | ||
653 | pixmaps[ widget ] = cachePix; | ||
654 | } | ||
655 | else { | ||
656 | if ( pixmaps[ widget ] ) | ||
657 | cache->insert( pixmaps[ widget ], OThemeCache::VerticalScale, | ||
658 | widget ); | ||
659 | pixmaps[ widget ] = new OThemePixmap; | ||
660 | pixmaps[ widget ] ->resize( w, h ); | ||
661 | OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], | ||
662 | *grLowColors[ widget ], | ||
663 | OGfxEffect::VerticalGradient ); | ||
664 | } | ||
665 | } | ||
666 | } | ||
667 | else if ( gradients[ widget ] == GrHorizontal ) { | ||
668 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ) { | ||
669 | OThemePixmap * cachePix = cache->horizontalPixmap( w, widget ); | ||
670 | if ( cachePix ) { | ||
671 | cachePix = new OThemePixmap( *cachePix ); | ||
672 | if ( pixmaps[ widget ] ) | ||
673 | cache->insert( pixmaps[ widget ], | ||
674 | OThemeCache::HorizontalScale, widget ); | ||
675 | pixmaps[ widget ] = cachePix; | ||
676 | } | ||
677 | else { | ||
678 | if ( pixmaps[ widget ] ) | ||
679 | cache->insert( pixmaps[ widget ], | ||
680 | OThemeCache::HorizontalScale, widget ); | ||
681 | pixmaps[ widget ] = new OThemePixmap; | ||
682 | pixmaps[ widget ] ->resize( w, h ); | ||
683 | OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], | ||
684 | *grLowColors[ widget ], | ||
685 | OGfxEffect::HorizontalGradient ); | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | else if ( gradients[ widget ] == GrReverseBevel ) { | ||
690 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || | ||
691 | pixmaps[ widget ] ->height() != h ) { | ||
692 | OThemePixmap * cachePix = cache->pixmap( w, h, widget ); | ||
693 | if ( cachePix ) { | ||
694 | cachePix = new OThemePixmap( *cachePix ); | ||
695 | if ( pixmaps[ widget ] ) | ||
696 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, | ||
697 | widget ); | ||
698 | pixmaps[ widget ] = cachePix; | ||
699 | } | ||
700 | else { | ||
701 | if ( pixmaps[ widget ] ) | ||
702 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, | ||
703 | widget ); | ||
704 | pixmaps[ widget ] = new OThemePixmap; | ||
705 | pixmaps[ widget ] ->resize( w, h ); | ||
706 | |||
707 | QPixmap s; | ||
708 | int offset = decoWidth( widget ); | ||
709 | s.resize( w - offset * 2, h - offset * 2 ); | ||
710 | QColor lc( *grLowColors[ widget ] ); | ||
711 | QColor hc( *grHighColors[ widget ] ); | ||
712 | if ( bevelContrast( widget ) ) { | ||
713 | int bc = bevelContrast( widget ); | ||
714 | // want single increments, not factors like light()/dark() | ||
715 | lc.setRgb( lc.red() - bc, lc.green() - bc, lc.blue() - bc ); | ||
716 | hc.setRgb( hc.red() + bc, hc.green() + bc, hc.blue() + bc ); | ||
717 | } | ||
718 | OGfxEffect::gradient( *pixmaps[ widget ], | ||
719 | lc, hc, | ||
720 | OGfxEffect::DiagonalGradient ); | ||
721 | OGfxEffect::gradient( s, *grHighColors[ widget ], | ||
722 | *grLowColors[ widget ], | ||
723 | OGfxEffect::DiagonalGradient ); | ||
724 | bitBlt( pixmaps[ widget ], offset, offset, &s, 0, 0, w - offset * 2, | ||
725 | h - offset * 2, Qt::CopyROP ); | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | else { | ||
730 | OGfxEffect::GradientType g; | ||
731 | switch ( gradients[ widget ] ) { | ||
732 | case GrPyramid: | ||
733 | g = OGfxEffect::PyramidGradient; | ||
734 | break; | ||
735 | case GrRectangle: | ||
736 | g = OGfxEffect::RectangleGradient; | ||
737 | break; | ||
738 | case GrElliptic: | ||
739 | g = OGfxEffect::EllipticGradient; | ||
740 | break; | ||
741 | default: | ||
742 | g = OGfxEffect::DiagonalGradient; | ||
743 | break; | ||
744 | } | ||
745 | if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || | ||
746 | pixmaps[ widget ] ->height() != h ) { | ||
747 | OThemePixmap * cachePix = cache->pixmap( w, h, widget ); | ||
748 | if ( cachePix ) { | ||
749 | cachePix = new OThemePixmap( *cachePix ); | ||
750 | if ( pixmaps[ widget ] ) | ||
751 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, | ||
752 | widget ); | ||
753 | pixmaps[ widget ] = cachePix; | ||
754 | } | ||
755 | else { | ||
756 | if ( pixmaps[ widget ] ) | ||
757 | cache->insert( pixmaps[ widget ], OThemeCache::FullScale, | ||
758 | widget ); | ||
759 | pixmaps[ widget ] = new OThemePixmap; | ||
760 | pixmaps[ widget ] ->resize( w, h ); | ||
761 | OGfxEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], | ||
762 | *grLowColors[ widget ], g ); | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | return ( pixmaps[ widget ] ); | ||
767 | } | ||
768 | |||
769 | OThemePixmap* OThemeBase::scalePixmap( int w, int h, WidgetType widget ) | ||
770 | { | ||
771 | |||
772 | if ( gradients[ widget ] && blends[ widget ] == 0.0 ) | ||
773 | return ( gradient( w, h, widget ) ); | ||
774 | |||
775 | return ( scale( w, h, widget ) ); | ||
776 | } | ||
777 | |||
778 | QColorGroup* OThemeBase::makeColorGroup( QColor &fg, QColor &bg, | ||
779 | Qt::GUIStyle ) | ||
780 | { | ||
781 | if ( shading == Motif ) { | ||
782 | int highlightVal, lowlightVal; | ||
783 | highlightVal = 100 + ( 2* /*KGlobalSettings::contrast()*/ 3 + 4 ) * 16 / 10; | ||
784 | lowlightVal = 100 + ( ( 2* /*KGlobalSettings::contrast()*/ 3 + 4 ) * 10 ); | ||
785 | return ( new QColorGroup( fg, bg, bg.light( highlightVal ), | ||
786 | bg.dark( lowlightVal ), bg.dark( 120 ), | ||
787 | fg, qApp->palette().normal().base() ) ); | ||
788 | } | ||
789 | else | ||
790 | return ( new QColorGroup( fg, bg, bg.light( 150 ), bg.dark(), | ||
791 | bg.dark( 120 ), fg, | ||
792 | qApp->palette().normal().base() ) ); | ||
793 | } | ||
794 | |||
795 | static QColor strToColor ( const QString &str ) | ||
796 | { | ||
797 | QString str2 = str. stripWhiteSpace ( ); | ||
798 | |||
799 | if ( str2 [0] == '#' ) | ||
800 | return QColor ( str2 ); | ||
801 | else { | ||
802 | QStringList sl = QStringList::split ( ',', str2 ); | ||
803 | |||
804 | if ( sl. count ( ) >= 3 ) | ||
805 | return QColor ( sl [0]. toInt ( ), sl [1]. toInt ( ), sl [2]. toInt ( )); | ||
806 | } | ||
807 | return QColor ( 0, 0, 0 ); | ||
808 | } | ||
809 | |||
810 | |||
811 | |||
812 | void OThemeBase::applyMiscResourceGroup( Config *config ) | ||
813 | { | ||
814 | config-> setGroup ( "Misc" ); | ||
815 | QString tmpStr; | ||
816 | |||
817 | tmpStr = config->readEntry( "SButtonPosition" ); | ||
818 | if ( tmpStr == "BottomLeft" ) | ||
819 | sbPlacement = SBBottomLeft; | ||
820 | else if ( tmpStr == "BottomRight" ) | ||
821 | sbPlacement = SBBottomRight; | ||
822 | else { | ||
823 | if ( tmpStr != "Opposite" && !tmpStr.isEmpty() ) | ||
824 | qDebug ( "OThemeBase: Unrecognized sb button option %s, using Opposite.\n", tmpStr.ascii() ); | ||
825 | sbPlacement = SBOpposite; | ||
826 | } | ||
827 | tmpStr = config->readEntry( "ArrowType" ); | ||
828 | if ( tmpStr == "Small" ) | ||
829 | arrowStyle = SmallArrow; | ||
830 | else if ( tmpStr == "3D" ) | ||
831 | arrowStyle = MotifArrow; | ||
832 | else { | ||
833 | if ( tmpStr != "Normal" && !tmpStr.isEmpty() ) | ||
834 | qDebug ( "OThemeBase: Unrecognized arrow option %s, using Normal.\n", tmpStr.ascii() ); | ||
835 | arrowStyle = LargeArrow; | ||
836 | } | ||
837 | tmpStr = config->readEntry( "ShadeStyle" ); | ||
838 | if ( tmpStr == "Motif" ) | ||
839 | shading = Motif; | ||
840 | else if ( tmpStr == "Next" ) | ||
841 | shading = Next; | ||
842 | else if ( tmpStr == "KDE" ) | ||
843 | shading = KDE; | ||
844 | else | ||
845 | shading = Windows; | ||
846 | |||
847 | defaultFrame = config->readNumEntry( "FrameWidth", 2 ); | ||
848 | cacheSize = config->readNumEntry( "Cache", 1024 ); | ||
849 | sbExtent = config->readNumEntry( "ScrollBarExtent", 16 ); | ||
850 | |||
851 | config-> setGroup ( "General" ); | ||
852 | |||
853 | if ( config-> hasKey ( "foreground" )) fgcolor = strToColor ( config-> readEntry ( "foreground" )); | ||
854 | if ( config-> hasKey ( "background" )) bgcolor = strToColor ( config-> readEntry ( "background" )); | ||
855 | if ( config-> hasKey ( "selectForeground" )) selfgcolor = strToColor ( config-> readEntry ( "selectForeground" )); | ||
856 | if ( config-> hasKey ( "selectBackground" )) selbgcolor = strToColor ( config-> readEntry ( "selectBackground" )); | ||
857 | if ( config-> hasKey ( "windowForeground" )) winfgcolor = strToColor ( config-> readEntry ( "windowForeground" )); | ||
858 | if ( config-> hasKey ( "windowBackground" )) winbgcolor = strToColor ( config-> readEntry ( "windowBackground" )); | ||
859 | } | ||
860 | |||
861 | void OThemeBase::readMiscResourceGroup() | ||
862 | {} | ||
863 | |||
864 | void OThemeBase::applyResourceGroup( Config *config, int i, QString *copyfrom, QString *pixnames, QString *brdnames ) | ||
865 | { | ||
866 | QString tmpStr; | ||
867 | |||
868 | config-> setGroup ( widgetEntries [ i ] ); | ||
869 | |||
870 | tmpStr = config->readEntry( "CopyWidget", "" ); | ||
871 | copyfrom [ i ] = tmpStr; | ||
872 | if ( !tmpStr.isEmpty() ) | ||
873 | return ; | ||
874 | |||
875 | // Scale hint | ||
876 | tmpStr = config->readEntry( "Scale" ); | ||
877 | if ( tmpStr == "Full" ) | ||
878 | scaleHints [ i ] = FullScale; | ||
879 | else if ( tmpStr == "Horizontal" ) | ||
880 | scaleHints [ i ] = HorizontalScale; | ||
881 | else if ( tmpStr == "Vertical" ) | ||
882 | scaleHints [ i ] = VerticalScale; | ||
883 | else { | ||
884 | if ( tmpStr != "Tile" && !tmpStr.isEmpty() ) | ||
885 | qDebug ( "OThemeBase: Unrecognized scale option %s, using Tile.\n", tmpStr.ascii() ); | ||
886 | scaleHints [ i ] = TileScale; | ||
887 | } | ||
888 | |||
889 | |||
890 | // Gradient type | ||
891 | tmpStr = config->readEntry( "Gradient" ); | ||
892 | if ( tmpStr == "Diagonal" ) | ||
893 | gradients [ i ] = GrDiagonal; | ||
894 | else if ( tmpStr == "Horizontal" ) | ||
895 | gradients [ i ] = GrHorizontal; | ||
896 | else if ( tmpStr == "Vertical" ) | ||
897 | gradients [ i ] = GrVertical; | ||
898 | else if ( tmpStr == "Pyramid" ) | ||
899 | gradients [ i ] = GrPyramid; | ||
900 | else if ( tmpStr == "Rectangle" ) | ||
901 | gradients [ i ] = GrRectangle; | ||
902 | else if ( tmpStr == "Elliptic" ) | ||
903 | gradients [ i ] = GrElliptic; | ||
904 | else if ( tmpStr == "ReverseBevel" ) | ||
905 | gradients [ i ] = GrReverseBevel; | ||
906 | else { | ||
907 | if ( tmpStr != "None" && !tmpStr.isEmpty() ) | ||
908 | qDebug ( "OThemeBase: Unrecognized gradient option %s, using None.\n", tmpStr.ascii() ); | ||
909 | gradients [ i ] = GrNone; | ||
910 | } | ||
911 | |||
912 | // Blend intensity | ||
913 | blends[ i ] = config->readEntry( "BlendIntensity", "0.0" ).toDouble(); | ||
914 | |||
915 | // Bevel contrast | ||
916 | bContrasts[ i ] = config->readNumEntry( "BevelContrast", 0 ); | ||
917 | |||
918 | // Border width | ||
919 | borders [ i ] = config->readNumEntry( "Border", 1 ); | ||
920 | |||
921 | // Highlight width | ||
922 | highlights [ i ] = config->readNumEntry( "Highlight", 1 ); | ||
923 | |||
924 | // Gradient low color or blend background | ||
925 | if ( config->hasKey( "GradientLow" ) && ( gradients[ i ] != GrNone || blends[ i ] != 0.0 )) | ||
926 | grLowColors[ i ] = new QColor( strToColor ( config->readEntry( "GradientLow", qApp->palette().normal().background().name() ))); | ||
927 | else | ||
928 | grLowColors[ i ] = NULL; | ||
929 | |||
930 | |||
931 | // Gradient high color | ||
932 | if ( config->hasKey( "GradientHigh" ) && ( gradients[ i ] != GrNone )) | ||
933 | grHighColors[ i ] = new QColor( strToColor ( config->readEntry( "GradientHigh", qApp->palette().normal().background().name() ))); | ||
934 | else | ||
935 | grHighColors[ i ] = NULL; | ||
936 | |||
937 | // Extended color attributes | ||
938 | if ( config->hasKey( "Foreground" ) || config->hasKey( "Background" ) ) { | ||
939 | QColor bg = strToColor( config->readEntry( "Background", qApp->palette().normal().background().name() )); | ||
940 | QColor fg = strToColor( config->readEntry( "Foreground", qApp->palette().normal().foreground().name() )); | ||
941 | |||
942 | colors[ i ] = makeColorGroup( fg, bg, Qt::WindowsStyle ); | ||
943 | } | ||
944 | else | ||
945 | colors[ i ] = NULL; | ||
946 | |||
947 | // Pixmap | ||
948 | tmpStr = config->readEntry( "Pixmap", "" ); | ||
949 | pixnames[ i ] = tmpStr; | ||
950 | duplicate[ i ] = false; | ||
951 | pixmaps[ i ] = NULL; | ||
952 | images[ i ] = NULL; | ||
953 | |||
954 | |||
955 | // Pixmap border | ||
956 | tmpStr = config->readEntry( "PixmapBorder", "" ); | ||
957 | brdnames[ i ] = tmpStr; | ||
958 | pbDuplicate[ i ] = false; | ||
959 | pbPixmaps[ i ] = NULL; | ||
960 | pbWidth[ i ] = 0; | ||
961 | if ( !tmpStr.isEmpty() ) { | ||
962 | pbWidth[ i ] = config->readNumEntry( "PixmapBWidth", 0 ); | ||
963 | if ( pbWidth[ i ] == 0 ) { | ||
964 | qDebug ( "OThemeBase: No border width specified for pixmapped border widget %s\n", widgetEntries[ i ] ); | ||
965 | qDebug ( "OThemeBase: Using default of 2.\n" ); | ||
966 | pbWidth[ i ] = 2; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | |||
971 | // Various widget specific settings. This was more efficent when bunched | ||
972 | // together in the misc group, but this makes an easier to read config. | ||
973 | if ( i == SliderGroove ) | ||
974 | roundedSlider = config->readBoolEntry( "SmallGroove", false ); | ||
975 | else if ( i == ActiveTab || i == InactiveTab ) | ||
976 | aTabLine = iTabLine = config->readBoolEntry( "BottomLine", true ); | ||
977 | else if ( i == Splitter ) | ||
978 | splitterWidth = config->readNumEntry( "Width", 10 ); | ||
979 | else if ( i == ComboBox || i == ComboBoxDown ) { | ||
980 | roundedCombo = config->readBoolEntry( "Round", false ); | ||
981 | } | ||
982 | else if ( i == PushButton || i == PushButtonDown ) { | ||
983 | btnXShift = config->readNumEntry( "XShift", 0 ); | ||
984 | btnYShift = config->readNumEntry( "YShift", 0 ); | ||
985 | focus3D = config->readBoolEntry( "3DFocusRect", false ); | ||
986 | focus3DOffset = config->readBoolEntry( "3DFocusOffset", 0 ); | ||
987 | roundedButton = config->readBoolEntry( "Round", false ); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | |||
992 | void OThemeBase::readResourceGroup( int i, QString *copyfrom, QString *pixnames, QString *brdnames, | ||
993 | bool *loadArray ) | ||
994 | { | ||
995 | if ( loadArray[ i ] == true ) { | ||
996 | return ; // already been preloaded. | ||
997 | } | ||
998 | |||
999 | int tmpVal; | ||
1000 | QString tmpStr; | ||
1001 | |||
1002 | tmpStr = copyfrom [ i ]; | ||
1003 | if ( !tmpStr.isEmpty() ) { // Duplicate another widget's config | ||
1004 | int sIndex; | ||
1005 | loadArray[ i ] = true; | ||
1006 | for ( sIndex = 0; sIndex < WIDGETS; ++sIndex ) { | ||
1007 | if ( tmpStr == widgetEntries[ sIndex ] ) { | ||
1008 | if ( !loadArray[ sIndex ] ) // hasn't been loaded yet | ||
1009 | readResourceGroup( sIndex, copyfrom, pixnames, brdnames, | ||
1010 | loadArray ); | ||
1011 | break; | ||
1012 | } | ||
1013 | } | ||
1014 | if ( loadArray[ sIndex ] ) { | ||
1015 | copyWidgetConfig( sIndex, i, pixnames, brdnames ); | ||
1016 | } | ||
1017 | else | ||
1018 | qDebug ( "OThemeBase: Unable to identify source widget for %s\n", widgetEntries[ i ] ); | ||
1019 | return ; | ||
1020 | } | ||
1021 | // special inheritance for disabled arrows (these are tri-state unlike | ||
1022 | // the rest of what we handle). | ||
1023 | for ( tmpVal = DisArrowUp; tmpVal <= DisArrowRight; ++tmpVal ) { | ||
1024 | if ( tmpVal == i ) { | ||
1025 | tmpStr = pixnames [ i ]; | ||
1026 | if ( tmpStr.isEmpty() ) { | ||
1027 | copyWidgetConfig( ArrowUp + ( tmpVal - DisArrowUp ), i, pixnames, | ||
1028 | brdnames ); | ||
1029 | return ; | ||
1030 | } | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | // Pixmap | ||
1035 | int existing; | ||
1036 | // Scan for duplicate pixmaps(two identical pixmaps, tile scale, no blend, | ||
1037 | // no pixmapped border) | ||
1038 | if ( !pixnames [ i ].isEmpty() ) { | ||
1039 | for ( existing = 0; existing < i; ++existing ) { | ||
1040 | if ( pixnames[ i ] == pixnames[ existing ] && scaleHints[ i ] == TileScale && | ||
1041 | scaleHints[ existing ] == TileScale && blends[ existing ] == 0.0 && | ||
1042 | blends[ i ] == 0.0 ) { | ||
1043 | pixmaps[ i ] = pixmaps[ existing ]; | ||
1044 | duplicate[ i ] = true; | ||
1045 | break; | ||
1046 | } | ||
1047 | } | ||
1048 | } | ||
1049 | // load | ||
1050 | if ( !duplicate[ i ] && !pixnames[ i ].isEmpty() ) { | ||
1051 | pixmaps[ i ] = loadPixmap( pixnames[ i ] ); | ||
1052 | // load and save images for scaled/blended widgets for speed. | ||
1053 | if ( scaleHints[ i ] == TileScale && blends[ i ] == 0.0 ) | ||
1054 | images[ i ] = NULL; | ||
1055 | else | ||
1056 | images[ i ] = loadImage( pixnames[ i ] ); | ||
1057 | } | ||
1058 | |||
1059 | // Pixmap border | ||
1060 | if ( !brdnames [ i ]. isEmpty () ) { | ||
1061 | // duplicate check | ||
1062 | for ( existing = 0; existing < i; ++existing ) { | ||
1063 | if ( brdnames [i] == brdnames[ existing ] ) { | ||
1064 | pbPixmaps[ i ] = pbPixmaps[ existing ]; | ||
1065 | pbDuplicate[ i ] = true; | ||
1066 | break; | ||
1067 | } | ||
1068 | } | ||
1069 | } | ||
1070 | // load | ||
1071 | if ( !pbDuplicate[ i ] && !brdnames[ i ].isEmpty() ) | ||
1072 | pbPixmaps[ i ] = loadPixmap( brdnames[ i ] ); | ||
1073 | |||
1074 | if ( pbPixmaps[ i ] && !pbDuplicate[ i ] ) | ||
1075 | generateBorderPix( i ); | ||
1076 | |||
1077 | loadArray[ i ] = true; | ||
1078 | } | ||
1079 | |||
1080 | |||
1081 | OThemePixmap::OThemePixmap( bool timer ) | ||
1082 | : QPixmap() | ||
1083 | { | ||
1084 | if(timer){ | ||
1085 | t = new QTime; | ||
1086 | t->start(); | ||
1087 | } | ||
1088 | else | ||
1089 | t = NULL; | ||
1090 | int i; | ||
1091 | for ( i = 0; i < 8; ++i ) | ||
1092 | b[ i ] = NULL; | ||
1093 | } | ||
1094 | |||
1095 | OThemePixmap::OThemePixmap( const OThemePixmap &p ) | ||
1096 | : QPixmap( p ) | ||
1097 | { | ||
1098 | if(p.t){ | ||
1099 | t = new QTime; | ||
1100 | t->start(); | ||
1101 | } | ||
1102 | else | ||
1103 | t = NULL; | ||
1104 | int i; | ||
1105 | for ( i = 0; i < 8; ++i ) | ||
1106 | if ( p.b[ i ] ) | ||
1107 | b[ i ] = new QPixmap( *p.b[ i ] ); | ||
1108 | else | ||
1109 | b[ i ] = NULL; | ||
1110 | } | ||
1111 | |||
1112 | |||
1113 | |||
1114 | OThemePixmap::~OThemePixmap() | ||
1115 | { | ||
1116 | if(t) | ||
1117 | delete t; | ||
1118 | int i; | ||
1119 | for ( i = 0; i < 8; ++i ) | ||
1120 | if ( b[ i ] ) | ||
1121 | delete b[ i ]; | ||
1122 | } | ||
1123 | |||
1124 | OThemeCache::OThemeCache( int maxSize, QObject *parent, const char *name ) | ||
1125 | : QObject( parent, name ) | ||
1126 | { | ||
1127 | cache.setMaxCost( maxSize * 1024 ); | ||
1128 | cache.setAutoDelete( true ); | ||
1129 | flushTimer.start(300000); // 5 minutes | ||
1130 | connect(&flushTimer, SIGNAL(timeout()), SLOT(flushTimeout())); | ||
1131 | } | ||
1132 | |||
1133 | void OThemeCache::flushTimeout() | ||
1134 | { | ||
1135 | QIntCacheIterator<OThemePixmap> it( cache ); | ||
1136 | while ( it.current() ) { | ||
1137 | if ( it.current() ->isOld() ) | ||
1138 | cache.remove( it.currentKey() ); | ||
1139 | else | ||
1140 | ++it; | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | OThemePixmap* OThemeCache::pixmap( int w, int h, int widgetID, bool border, | ||
1145 | bool mask ) | ||
1146 | { | ||
1147 | |||
1148 | kthemeKey key; | ||
1149 | key.cacheKey = 0; // shut up, gcc | ||
1150 | key.data.id = widgetID; | ||
1151 | key.data.width = w; | ||
1152 | key.data.height = h; | ||
1153 | key.data.border = border; | ||
1154 | key.data.mask = mask; | ||
1155 | |||
1156 | OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); | ||
1157 | if ( pix ) | ||
1158 | pix->updateAccessed(); | ||
1159 | return ( pix ); | ||
1160 | } | ||
1161 | |||
1162 | OThemePixmap* OThemeCache::horizontalPixmap( int w, int widgetID ) | ||
1163 | { | ||
1164 | kthemeKey key; | ||
1165 | key.cacheKey = 0; // shut up, gcc | ||
1166 | key.data.id = widgetID; | ||
1167 | key.data.width = w; | ||
1168 | key.data.height = 0; | ||
1169 | key.data.border = false; | ||
1170 | key.data.mask = false; | ||
1171 | OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); | ||
1172 | if ( pix ) | ||
1173 | pix->updateAccessed(); | ||
1174 | return ( pix ); | ||
1175 | } | ||
1176 | |||
1177 | OThemePixmap* OThemeCache::verticalPixmap( int h, int widgetID ) | ||
1178 | { | ||
1179 | kthemeKey key; | ||
1180 | key.cacheKey = 0; // shut up, gcc | ||
1181 | key.data.id = widgetID; | ||
1182 | key.data.width = 0; | ||
1183 | key.data.height = h; | ||
1184 | key.data.border = false; | ||
1185 | key.data.mask = false; | ||
1186 | OThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); | ||
1187 | if ( pix ) | ||
1188 | pix->updateAccessed(); | ||
1189 | return ( pix ); | ||
1190 | } | ||
1191 | |||
1192 | bool OThemeCache::insert( OThemePixmap *pixmap, ScaleHint scale, int widgetID, | ||
1193 | bool border, bool mask ) | ||
1194 | { | ||
1195 | kthemeKey key; | ||
1196 | key.cacheKey = 0; // shut up, gcc | ||
1197 | key.data.id = widgetID; | ||
1198 | key.data.width = ( scale == FullScale || scale == HorizontalScale ) ? | ||
1199 | pixmap->width() : 0; | ||
1200 | key.data.height = ( scale == FullScale || scale == VerticalScale ) ? | ||
1201 | pixmap->height() : 0; | ||
1202 | key.data.border = border; | ||
1203 | key.data.mask = mask; | ||
1204 | |||
1205 | if ( cache.find( ( unsigned long ) key.cacheKey, true ) != NULL ) { | ||
1206 | return ( true ); // a pixmap of this scale is already in there | ||
1207 | } | ||
1208 | return ( cache.insert( ( unsigned long ) key.cacheKey, pixmap, | ||
1209 | pixmap->width() * pixmap->height() * pixmap->depth() / 8 ) ); | ||
1210 | } | ||
1211 | |||
1212 | //#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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public | ||
6 | License version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This library is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | Library General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Library General Public License | ||
14 | along with this library; see the file COPYING.LIB. If not, write to | ||
15 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | #ifndef __OTHEMEBASE_H | ||
19 | #define __OTHEMEBASE_H | ||
20 | |||
21 | #include <qdatetime.h> | ||
22 | #include <qtimer.h> | ||
23 | #include <qwindowsstyle.h> | ||
24 | #include <qpixmap.h> | ||
25 | #include <qpe/config.h> | ||
26 | #include <qimage.h> | ||
27 | #include <qintcache.h> | ||
28 | #include <qstring.h> | ||
29 | #include <qpalette.h> | ||
30 | |||
31 | #define WIDGETS 54 | ||
32 | |||
33 | /** | ||
34 | * This class adds simple time management to QPixmap for use in flushing | ||
35 | * OThemeCache. | ||
36 | * | ||
37 | * @author Daniel M. Duley <mosfet@kde.org> | ||
38 | */ | ||
39 | class OThemePixmap : public QPixmap | ||
40 | { | ||
41 | public: | ||
42 | enum BorderType{Top = 0, Bottom, Left, Right, TopLeft, TopRight, BottomLeft, | ||
43 | BottomRight}; | ||
44 | |||
45 | OThemePixmap( bool timer = true ); | ||
46 | OThemePixmap( const OThemePixmap &p ); | ||
47 | ~OThemePixmap(); | ||
48 | QPixmap* border( BorderType type ); | ||
49 | void setBorder( BorderType type, const QPixmap &p ); | ||
50 | void updateAccessed(); | ||
51 | bool isOld(); | ||
52 | protected: | ||
53 | QTime *t; | ||
54 | QPixmap *b[ 8 ]; | ||
55 | |||
56 | private: | ||
57 | class OThemePixmapPrivate; | ||
58 | OThemePixmapPrivate *d; | ||
59 | }; | ||
60 | |||
61 | inline QPixmap* OThemePixmap::border( BorderType type ) | ||
62 | { | ||
63 | return ( b[ type ] ); | ||
64 | } | ||
65 | |||
66 | inline void OThemePixmap::setBorder( BorderType type, const QPixmap &p ) | ||
67 | { | ||
68 | if ( b[ type ] ) { | ||
69 | qWarning( "OThemePixmap: Overwriting existing border!" ); | ||
70 | delete( b[ type ] ); | ||
71 | } | ||
72 | b[ type ] = new QPixmap( p ); | ||
73 | } | ||
74 | |||
75 | inline void OThemePixmap::updateAccessed() | ||
76 | { | ||
77 | if (t) | ||
78 | t->start(); | ||
79 | } | ||
80 | |||
81 | inline bool OThemePixmap::isOld() | ||
82 | { | ||
83 | return ( t ? t->elapsed() >= 300000 : false ); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * A very simple pixmap cache for theme plugins. QPixmapCache is not used | ||
88 | * since it uses QString keys which are not needed. All the information we | ||
89 | * need can be encoded in a numeric key. Using QIntCache instead allows us to | ||
90 | * skip the string operations. | ||
91 | * | ||
92 | * This class is mostly just inline methods that do bit operations on a key | ||
93 | * composed of the widget ID, width and/or height, and then calls | ||
94 | * QIntCache::find(). | ||
95 | * | ||
96 | * One other thing to note is that full, horizontal, and vertically scaled | ||
97 | * pixmaps are not used interchangeably. For example, if you insert a fully | ||
98 | * scaled pixmap that is 32x32 then request a horizontally scaled pixmap with | ||
99 | * a width of 32, they will not match. This is because a pixmap that has been | ||
100 | * inserted into the cache has already been scaled at some point and it is | ||
101 | * very likely the vertical height was not originally 32. Thus the pixmap | ||
102 | * will be wrong when drawn, even though the horizontal width matches. | ||
103 | * | ||
104 | * @author Daniel M. Duley <mosfet@kde.org> | ||
105 | * | ||
106 | */ | ||
107 | class OThemeCache : public QObject | ||
108 | { | ||
109 | Q_OBJECT | ||
110 | public: | ||
111 | /** | ||
112 | * The scale hints supported by the cache. Note that Tiled is not here | ||
113 | * since tiled pixmaps are kept only once in OThemeBase. | ||
114 | */ | ||
115 | enum ScaleHint{FullScale, HorizontalScale, VerticalScale}; | ||
116 | /** | ||
117 | * The constructor. | ||
118 | * | ||
119 | * @param maxSize The maximum size of the cache in kilobytes. | ||
120 | */ | ||
121 | OThemeCache( int maxSize, QObject *parent = 0, const char *name = 0 ); | ||
122 | /** | ||
123 | * Inserts a new pixmap into the cache. | ||
124 | * | ||
125 | * @param pixmap The pixmap to insert. | ||
126 | * @param scale The scaling type of the pixmap. | ||
127 | * @param widgetID The widget ID of the pixmap, usually from OThemeBase's | ||
128 | * WidgetType enum. | ||
129 | * | ||
130 | * @return True if the insert was successful, false otherwise. | ||
131 | */ | ||
132 | bool insert( OThemePixmap *pixmap, ScaleHint scale, int widgetID, | ||
133 | bool border = false, bool mask = false ); | ||
134 | /** | ||
135 | * Returns a fully scaled pixmap. | ||
136 | * | ||
137 | * @param w The pixmap width to search for. | ||
138 | * @param h The pixmap height to search for. | ||
139 | * @param widgetID The widget ID to search for. | ||
140 | * | ||
141 | * @return True if a pixmap matching the width, height, and widget ID of | ||
142 | * the pixmap exists, NULL otherwise. | ||
143 | */ | ||
144 | OThemePixmap* pixmap( int w, int h, int widgetID, bool border = false, | ||
145 | bool mask = false ); | ||
146 | /** | ||
147 | * Returns a horizontally scaled pixmap. | ||
148 | * | ||
149 | * @param w The pixmap width to search for. | ||
150 | * @param widgetID The widget ID to search for. | ||
151 | * | ||
152 | * @return True if a pixmap matching the width and widget ID of | ||
153 | * the pixmap exists, NULL otherwise. | ||
154 | */ | ||
155 | OThemePixmap* horizontalPixmap( int w, int widgetID ); | ||
156 | /** | ||
157 | * Returns a vertically scaled pixmap. | ||
158 | * | ||
159 | * @param h The pixmap height to search for. | ||
160 | * @param widgetID The widget ID to search for. | ||
161 | * | ||
162 | * @return True if a pixmap matching the height and widget ID of | ||
163 | * the pixmap exists, NULL otherwise. | ||
164 | */ | ||
165 | OThemePixmap* verticalPixmap( int h, int widgetID ); | ||
166 | protected slots: | ||
167 | void flushTimeout(); | ||
168 | protected: | ||
169 | QIntCache<OThemePixmap> cache; | ||
170 | QTimer flushTimer; | ||
171 | |||
172 | private: | ||
173 | class OThemeCachePrivate; | ||
174 | OThemeCachePrivate *d; | ||
175 | }; | ||
176 | |||
177 | |||
178 | /** | ||
179 | * This is a base class for KDE themed styles. It implements a cache, | ||
180 | * configuration file parsing, pixmap scaling, gradients, and a lot | ||
181 | * of inline methods for accessing user specified parameters. | ||
182 | * | ||
183 | * Note that this class *does not* actually implement any themes. It just | ||
184 | * provides the groundwork for doing so. The only reason to use this class | ||
185 | * directly is if you plan to reimplement all of the widgets. Otherwise, | ||
186 | * refer to OThemeStyle for a fully themed style you can derive from. | ||
187 | * | ||
188 | * @author Daniel M. Duley <mosfet@kde.org> | ||
189 | */ | ||
190 | class OThemeBase: public QWindowsStyle | ||
191 | { | ||
192 | Q_OBJECT | ||
193 | public: | ||
194 | /** | ||
195 | * Constructs a new OThemeBase object. | ||
196 | */ | ||
197 | OThemeBase( const QString &configFile ); | ||
198 | ~OThemeBase(); | ||
199 | /** | ||
200 | * Describes if a pixmap should be scaled fully, horizontally, vertically, | ||
201 | * or not at all and tiled. | ||
202 | */ | ||
203 | enum ScaleHint{FullScale, HorizontalScale, VerticalScale, TileScale}; | ||
204 | /** | ||
205 | * The default arrow types. | ||
206 | */ | ||
207 | enum ArrowStyle{MotifArrow, LargeArrow, SmallArrow}; | ||
208 | /** | ||
209 | * The default frame shading styles. | ||
210 | */ | ||
211 | enum ShadeStyle{Motif, Windows, Next, KDE}; | ||
212 | /** | ||
213 | * The default scrollbar button layout. BottomLeft is like what Next | ||
214 | * uses, BottomRight is like Platinum, and Opposite it like Windows and | ||
215 | * Motif. | ||
216 | */ | ||
217 | enum SButton{SBBottomLeft, SBBottomRight, SBOpposite}; | ||
218 | /** | ||
219 | * The gradient types. Horizontal is left to right, Vertical is top to | ||
220 | * bottom, and diagonal is upper-left to bottom-right. | ||
221 | */ | ||
222 | enum Gradient{GrNone, GrHorizontal, GrVertical, GrDiagonal, GrPyramid, | ||
223 | GrRectangle, GrElliptic, GrReverseBevel}; | ||
224 | /** | ||
225 | * This provides a list of widget types that OThemeBase recognizes. | ||
226 | */ | ||
227 | /* Internal note: The order here is important. Some widgets inherit | ||
228 | * properties. This is usually for when you have two settings for the | ||
229 | * same widget, ie: on(sunken), and off. The on settings will inherit | ||
230 | * the properties of the off one when nothing is specified in the config. | ||
231 | * | ||
232 | * In order to be able to handle this while still having everything in | ||
233 | * one group that is easy to loop from we have the following order: | ||
234 | * unsunked(off) items, sunken(on)items, and then the ones that don't | ||
235 | * matter. INHERIT_ITEMS define the number of widgets that have inheritence | ||
236 | * so if 0 == PushButtonOff then INHERIT_ITEMS should == PushButtonOn | ||
237 | * and so on. WIDGETS define the total number of widgets. | ||
238 | */ | ||
239 | enum WidgetType{ | ||
240 | // Off (unsunken widgets) | ||
241 | PushButton = 0, ComboBox, HScrollBarSlider, VScrollBarSlider, Bevel, | ||
242 | ToolButton, ScrollButton, HScrollDeco, VScrollDeco, | ||
243 | ComboDeco, MenuItem, InactiveTab, ArrowUp, ArrowDown, ArrowLeft, | ||
244 | ArrowRight, | ||
245 | // On (sunken widgets) | ||
246 | PushButtonDown, ComboBoxDown, HScrollBarSliderDown, | ||
247 | VScrollBarSliderDown, BevelDown, ToolButtonDown, ScrollButtonDown, | ||
248 | HScrollDecoDown, VScrollDecoDown, ComboDecoDown, MenuItemDown, | ||
249 | ActiveTab, SunkenArrowUp, SunkenArrowDown, SunkenArrowLeft, | ||
250 | SunkenArrowRight, | ||
251 | // Everything else (indicators must have separate settings) | ||
252 | HScrollGroove, VScrollGroove, Slider, SliderGroove, IndicatorOn, | ||
253 | IndicatorOff, ExIndicatorOn, ExIndicatorOff, HBarHandle, VBarHandle, | ||
254 | ToolBar, Splitter, CheckMark, MenuBar, DisArrowUp, DisArrowDown, | ||
255 | DisArrowLeft, DisArrowRight, ProgressBar, ProgressBg, MenuBarItem, | ||
256 | Background}; | ||
257 | |||
258 | /** | ||
259 | * The scaling type specified by the Config file. | ||
260 | * | ||
261 | * @param widget A Widgets enum value. | ||
262 | * | ||
263 | * @return A ScaleHint enum value. | ||
264 | */ | ||
265 | ScaleHint scaleHint( WidgetType widget ) const; | ||
266 | /** | ||
267 | * The gradient type specified by the KConfig file. | ||
268 | * | ||
269 | * @param widget A Widgets enum value. | ||
270 | * | ||
271 | * @return A Gradient enum value. | ||
272 | */ | ||
273 | Gradient gradientHint( WidgetType widget ) const; | ||
274 | /** | ||
275 | * The color group specified for a given widget. | ||
276 | * If a color group is set in the theme configuration | ||
277 | * that is used, otherwise defaultColor is returned. | ||
278 | * | ||
279 | * @param defaultColor The colorGroup to set if one is available. | ||
280 | * | ||
281 | * @param widget The widget whose color group to retrieve. | ||
282 | * | ||
283 | */ | ||
284 | const QColorGroup* colorGroup( const QColorGroup &defaultGroup, | ||
285 | WidgetType widget ) const; | ||
286 | |||
287 | QBrush pixmapBrush( const QColorGroup &group, QColorGroup::ColorRole role, | ||
288 | int w, int h, WidgetType widget ); | ||
289 | /** | ||
290 | * True if the widget has a pixmap or gradient specified. | ||
291 | */ | ||
292 | bool isPixmap( WidgetType widget ) const; | ||
293 | /** | ||
294 | * True if the widget has a color group specified. | ||
295 | */ | ||
296 | bool isColor( WidgetType widget ) const; | ||
297 | /** | ||
298 | * True if the user specified a 3D focus rectangle | ||
299 | */ | ||
300 | bool is3DFocus() const; | ||
301 | /** | ||
302 | * If the user specified a 3D focus rectangle, they may also specify an | ||
303 | * offset from the default rectangle to use when drawing it. This returns | ||
304 | * the specified offset. | ||
305 | */ | ||
306 | int focusOffset() const; | ||
307 | /** | ||
308 | * The border width of the specified widget. | ||
309 | */ | ||
310 | int borderWidth( WidgetType widget ) const; | ||
311 | /** | ||
312 | * Pixmap border width of the specified widget. | ||
313 | */ | ||
314 | int pixBorderWidth( WidgetType widget ) const; | ||
315 | /** | ||
316 | * Returns the border pixmap if enabled for the specified widget. This | ||
317 | * will contain the originial pixmap, plus the edges separated in | ||
318 | * OThemePixmap::border() if valid. If invalid it will return NULL. | ||
319 | */ | ||
320 | OThemePixmap* borderPixmap( WidgetType widget ); | ||
321 | /** | ||
322 | * The highlight width of the specified widget. | ||
323 | */ | ||
324 | int highlightWidth( WidgetType widget ) const; | ||
325 | /** | ||
326 | * The border plus highlight width of the widget. | ||
327 | */ | ||
328 | int decoWidth( WidgetType widget ) const; | ||
329 | /** | ||
330 | * The extent (width for vertical, height for horizontal) requested | ||
331 | * for the scrollbars. | ||
332 | */ | ||
333 | int getSBExtent() const; | ||
334 | /** | ||
335 | * The scrollbar button layout. | ||
336 | */ | ||
337 | SButton scrollBarLayout() const; | ||
338 | /** | ||
339 | * The arrow type. | ||
340 | */ | ||
341 | ArrowStyle arrowType() const; | ||
342 | /** | ||
343 | * The shading type. | ||
344 | */ | ||
345 | ShadeStyle shade() const; | ||
346 | /** | ||
347 | * The frame width. | ||
348 | */ | ||
349 | int frameWidth() const; | ||
350 | /** | ||
351 | * The splitter width. | ||
352 | */ | ||
353 | int splitWidth() const; | ||
354 | /** | ||
355 | * The contrast for some bevel effects such as reverse gradient. | ||
356 | */ | ||
357 | int bevelContrast( WidgetType widget ) const; | ||
358 | /** | ||
359 | * The button text X shift. | ||
360 | */ | ||
361 | int buttonXShift() const; | ||
362 | /** | ||
363 | * The button text Y shift. | ||
364 | */ | ||
365 | int buttonYShift() const; | ||
366 | /** | ||
367 | * Returns either the slider length of the slider pixmap if available, | ||
368 | * otherwise the length specified in the config file. | ||
369 | */ | ||
370 | int sliderButtonLength() const; | ||
371 | /** | ||
372 | * True if rounded buttons are requested. | ||
373 | */ | ||
374 | bool roundButton() const; | ||
375 | /** | ||
376 | * True if rounded comboboxes are requested. | ||
377 | */ | ||
378 | bool roundComboBox() const; | ||
379 | /** | ||
380 | * True if rounded slider grooves are requested. | ||
381 | */ | ||
382 | bool roundSlider() const; | ||
383 | /** | ||
384 | * True if a line should be drawn on the bottom of active tabs. | ||
385 | */ | ||
386 | bool activeTabLine() const; | ||
387 | /** | ||
388 | * True if a line should be drawn on the bottom of inactive tabs. | ||
389 | */ | ||
390 | bool inactiveTabLine() const; | ||
391 | /** | ||
392 | * Returns the current uncached pixmap for the given widget. This will | ||
393 | * usually be either the last scaled or gradient pixmap if those have | ||
394 | * been specified in the config file, the original pixmap if not, or NULL | ||
395 | * if no pixmap has been specified. | ||
396 | */ | ||
397 | OThemePixmap* uncached( WidgetType widget ) const; | ||
398 | /** | ||
399 | * Returns the pixmap for the given widget at the specified width and | ||
400 | * height. This will return NULL if no pixmap or gradient is specified. | ||
401 | * It may also return a different sized pixmap if the scaling | ||
402 | * is set to Tiled. When using this method, you should call it using | ||
403 | * the needed width and height then use QPainter::drawTiledPixmap to | ||
404 | * paint it. Doing this, if the pixmap is scaled it will be the proper | ||
405 | * size, otherwise it will be tiled. | ||
406 | * | ||
407 | * @param w Requested width. | ||
408 | * @param h Requested height. | ||
409 | * @param widget Widget type. | ||
410 | * @return The pixmap or NULL if one is not specified. | ||
411 | */ | ||
412 | virtual OThemePixmap *scalePixmap( int w, int h, WidgetType widget ); | ||
413 | /** | ||
414 | * This method reads a configuration file and applies it to the user's | ||
415 | * kstylerc file. It does not signal applications to reload via the | ||
416 | * KDEChangeGeneral atom, if you want to do this you must do so yourself. | ||
417 | * See kcmdisplay's general.cpp for an example. | ||
418 | * | ||
419 | * @param file The configuration file to apply. | ||
420 | */ | ||
421 | static void applyConfigFile( const QString &file ); | ||
422 | protected: | ||
423 | /** | ||
424 | * Returns a QImage for the given widget if the widget is scaled, NULL | ||
425 | * otherwise. QImages of the original pixmap are stored for scaled | ||
426 | * widgets in order to facilitate fast and accurate smooth-scaling. This | ||
427 | * also saves us a conversion from a pixmap to an image then back again. | ||
428 | */ | ||
429 | QImage* image( WidgetType widget ) const; | ||
430 | /** | ||
431 | * Returns the gradient high color if one is specified, NULL otherwise. | ||
432 | */ | ||
433 | QColor* gradientHigh( WidgetType widget ) const; | ||
434 | /** | ||
435 | * Returns the gradient low color if one is specified, NULL otherwise. | ||
436 | */ | ||
437 | QColor* gradientLow( WidgetType widget ) const; | ||
438 | /** | ||
439 | * Reads in all the configuration file entries supported. | ||
440 | * | ||
441 | * @param colorStyle The style for the color groups. In KDE, colors were | ||
442 | * calculated a little differently for Motif vs Windows styles. This | ||
443 | * is obsolete. | ||
444 | */ | ||
445 | void readConfig( Qt::GUIStyle colorStyle = Qt::WindowsStyle ); | ||
446 | void readWidgetConfig( int i, Config *config, QString *pixnames, | ||
447 | QString *brdnames, bool *loadArray ); | ||
448 | void copyWidgetConfig( int sourceID, int destID, QString *pixnames, | ||
449 | QString *brdnames ); | ||
450 | /** | ||
451 | * Makes a full color group based on the given foreground and background | ||
452 | * colors. This is the same code used by KDE (kapp.cpp) in previous | ||
453 | * versions. | ||
454 | */ | ||
455 | QColorGroup* makeColorGroup( QColor &fg, QColor &bg, | ||
456 | Qt::GUIStyle style = Qt::WindowsStyle ); | ||
457 | OThemePixmap* scale( int w, int h, WidgetType widget ); | ||
458 | OThemePixmap* scaleBorder( int w, int h, WidgetType type ); | ||
459 | OThemePixmap* gradient( int w, int h, WidgetType widget ); | ||
460 | OThemePixmap* blend( WidgetType widget ); | ||
461 | void generateBorderPix( int i ); | ||
462 | void applyResourceGroup( Config *config, int i, QString *copyfrom, QString *pixnames, QString *brdnames ); | ||
463 | void applyMiscResourceGroup( Config *config ); | ||
464 | void readResourceGroup( int i, QString *copyfrom, QString *pixnames, QString *brdnames, | ||
465 | bool *loadArray ); | ||
466 | void readMiscResourceGroup(); | ||
467 | /** | ||
468 | * Attempts to load a pixmap from the default OThemeBase locations. | ||
469 | */ | ||
470 | OThemePixmap* loadPixmap( QString &name ); | ||
471 | /** | ||
472 | * Attempts to load a image from the default OThemeBase locations. | ||
473 | */ | ||
474 | QImage* loadImage( QString &name ); | ||
475 | private: | ||
476 | SButton sbPlacement; | ||
477 | ArrowStyle arrowStyle; | ||
478 | ShadeStyle shading; | ||
479 | int defaultFrame; | ||
480 | int btnXShift, btnYShift; | ||
481 | int sliderLen; | ||
482 | int splitterWidth; | ||
483 | int focus3DOffset; | ||
484 | int sbExtent; | ||
485 | bool smallGroove; | ||
486 | bool roundedButton, roundedCombo, roundedSlider; | ||
487 | bool aTabLine, iTabLine; | ||
488 | bool focus3D; | ||
489 | OThemeCache *cache; | ||
490 | int cacheSize; | ||
491 | QString configFileName; | ||
492 | QString configFilePath; | ||
493 | |||
494 | protected: | ||
495 | QColor fgcolor, bgcolor, selfgcolor, selbgcolor, winfgcolor, winbgcolor; | ||
496 | |||
497 | private: | ||
498 | /** | ||
499 | * The theme pixmaps. Many of these may be NULL if no pixmap is specified. | ||
500 | * There may also be duplicate pixmap pointers if more than one widget | ||
501 | * uses the same tiled pixmap. If a pixmap is tiled, it is kept here and | ||
502 | * this acts as a cache. Otherwise this will hold whatever the last scaled | ||
503 | * pixmap was. | ||
504 | */ | ||
505 | OThemePixmap *pixmaps[ WIDGETS ]; | ||
506 | /** | ||
507 | * The theme images. These are for scaled images and are kept in order | ||
508 | * to maintain fast smoothscaling. | ||
509 | */ | ||
510 | QImage *images[ WIDGETS ]; | ||
511 | /** | ||
512 | * The border widths | ||
513 | */ | ||
514 | unsigned char borders[ WIDGETS ]; | ||
515 | /** | ||
516 | * The highlight widths | ||
517 | */ | ||
518 | unsigned char highlights[ WIDGETS ]; | ||
519 | /** | ||
520 | * The scale hints for pixmaps and gradients. | ||
521 | */ | ||
522 | ScaleHint scaleHints[ WIDGETS ]; | ||
523 | /** | ||
524 | * All the color groups. | ||
525 | */ | ||
526 | QColorGroup *colors[ WIDGETS ]; | ||
527 | /** | ||
528 | * Gradient low colors (or blend background). | ||
529 | */ | ||
530 | QColor *grLowColors[ WIDGETS ]; | ||
531 | /** | ||
532 | * Gradient high colors. | ||
533 | */ | ||
534 | QColor *grHighColors[ WIDGETS ]; | ||
535 | /** | ||
536 | * Gradient types. | ||
537 | */ | ||
538 | Gradient gradients[ WIDGETS ]; | ||
539 | /** | ||
540 | * Blend intensity factors | ||
541 | */ | ||
542 | float blends[ WIDGETS ]; | ||
543 | /** | ||
544 | * Bevel contrasts | ||
545 | */ | ||
546 | unsigned char bContrasts[ WIDGETS ]; | ||
547 | /** | ||
548 | * Duplicate pixmap entries (used during destruction). | ||
549 | */ | ||
550 | bool duplicate[ WIDGETS ]; | ||
551 | /** | ||
552 | * Pixmapped border widths | ||
553 | */ | ||
554 | int pbWidth[ WIDGETS ]; | ||
555 | /** | ||
556 | * Pixmapped borders | ||
557 | */ | ||
558 | OThemePixmap *pbPixmaps[ WIDGETS ]; | ||
559 | /** | ||
560 | * Duplicate border pixmapped border entries | ||
561 | */ | ||
562 | bool pbDuplicate[ WIDGETS ]; | ||
563 | |||
564 | private: | ||
565 | class OThemeBasePrivate; | ||
566 | OThemeBasePrivate *d; | ||
567 | |||
568 | }; | ||
569 | |||
570 | inline bool OThemeBase::isPixmap( WidgetType widget ) const | ||
571 | { | ||
572 | return ( pixmaps[ widget ] != NULL || gradients[ widget ] != GrNone ); | ||
573 | } | ||
574 | |||
575 | inline bool OThemeBase::isColor( WidgetType widget ) const | ||
576 | { | ||
577 | return ( colors[ widget ] != NULL ); | ||
578 | } | ||
579 | |||
580 | inline bool OThemeBase::is3DFocus() const | ||
581 | { | ||
582 | return ( focus3D ); | ||
583 | } | ||
584 | |||
585 | inline int OThemeBase::focusOffset() const | ||
586 | { | ||
587 | return ( focus3DOffset ); | ||
588 | } | ||
589 | |||
590 | inline int OThemeBase::bevelContrast( WidgetType widget ) const | ||
591 | { | ||
592 | return ( bContrasts[ widget ] ); | ||
593 | } | ||
594 | |||
595 | inline OThemeBase::ScaleHint OThemeBase::scaleHint( WidgetType widget ) const | ||
596 | { | ||
597 | return ( ( widget < WIDGETS ) ? scaleHints[ widget ] : TileScale ); | ||
598 | } | ||
599 | |||
600 | inline OThemeBase::Gradient OThemeBase::gradientHint( WidgetType widget ) const | ||
601 | { | ||
602 | return ( ( widget < WIDGETS ) ? gradients[ widget ] : GrNone ); | ||
603 | } | ||
604 | |||
605 | inline OThemePixmap* OThemeBase::uncached( WidgetType widget ) const | ||
606 | { | ||
607 | return ( pixmaps[ widget ] ); | ||
608 | } | ||
609 | |||
610 | inline QBrush OThemeBase::pixmapBrush( const QColorGroup &group, | ||
611 | QColorGroup::ColorRole role, | ||
612 | int w, int h, WidgetType widget ) | ||
613 | { | ||
614 | if ( pixmaps[ widget ] || images[ widget ] ) | ||
615 | return ( QBrush( group.color( role ), *scalePixmap( w, h, widget ) ) ); | ||
616 | else | ||
617 | return ( group.color( role ) ); | ||
618 | } | ||
619 | |||
620 | inline const QColorGroup* OThemeBase::colorGroup( const QColorGroup &defaultGroup, | ||
621 | WidgetType widget ) const | ||
622 | { | ||
623 | return ( ( colors[ widget ] ) ? colors[ widget ] : &defaultGroup ); | ||
624 | } | ||
625 | |||
626 | inline int OThemeBase::borderWidth( WidgetType widget ) const | ||
627 | { | ||
628 | return ( pbWidth[ widget ] ? pbWidth[ widget ] : borders[ widget ] ); | ||
629 | } | ||
630 | |||
631 | inline int OThemeBase::pixBorderWidth( WidgetType widget ) const | ||
632 | { | ||
633 | return ( pbWidth[ widget ] ); | ||
634 | } | ||
635 | |||
636 | inline int OThemeBase::highlightWidth( WidgetType widget ) const | ||
637 | { | ||
638 | return ( pbWidth[ widget ] ? 0 : highlights[ widget ] ); | ||
639 | } | ||
640 | |||
641 | inline int OThemeBase::decoWidth( WidgetType widget ) const | ||
642 | { | ||
643 | return ( pbWidth[ widget ] ? pbWidth[ widget ] : borders[ widget ] + highlights[ widget ] ); | ||
644 | } | ||
645 | |||
646 | inline QColor* OThemeBase::gradientHigh( WidgetType widget ) const | ||
647 | { | ||
648 | return ( grHighColors[ widget ] ); | ||
649 | } | ||
650 | |||
651 | inline QColor* OThemeBase::gradientLow( WidgetType widget ) const | ||
652 | { | ||
653 | return ( grLowColors[ widget ] ); | ||
654 | } | ||
655 | |||
656 | inline QImage* OThemeBase::image( WidgetType widget ) const | ||
657 | { | ||
658 | return ( images[ widget ] ); | ||
659 | } | ||
660 | |||
661 | inline OThemeBase::SButton OThemeBase::scrollBarLayout() const | ||
662 | { | ||
663 | return ( sbPlacement ); | ||
664 | } | ||
665 | |||
666 | inline OThemeBase::ArrowStyle OThemeBase::arrowType() const | ||
667 | { | ||
668 | return ( arrowStyle ); | ||
669 | } | ||
670 | |||
671 | inline OThemeBase::ShadeStyle OThemeBase::shade() const | ||
672 | { | ||
673 | return ( shading ); | ||
674 | } | ||
675 | |||
676 | inline int OThemeBase::frameWidth() const | ||
677 | { | ||
678 | return ( defaultFrame ); | ||
679 | } | ||
680 | |||
681 | inline int OThemeBase::buttonXShift() const | ||
682 | { | ||
683 | return ( btnXShift ); | ||
684 | } | ||
685 | |||
686 | inline int OThemeBase::splitWidth() const | ||
687 | { | ||
688 | return ( splitterWidth ); | ||
689 | } | ||
690 | |||
691 | inline int OThemeBase::buttonYShift() const | ||
692 | { | ||
693 | return ( btnYShift ); | ||
694 | } | ||
695 | |||
696 | inline int OThemeBase::sliderButtonLength() const | ||
697 | { | ||
698 | if ( isPixmap( Slider ) ) | ||
699 | return ( uncached( Slider ) ->width() ); | ||
700 | else | ||
701 | return ( sliderLen ); | ||
702 | } | ||
703 | |||
704 | inline bool OThemeBase::roundButton() const | ||
705 | { | ||
706 | return ( roundedButton ); | ||
707 | } | ||
708 | |||
709 | inline bool OThemeBase::roundComboBox() const | ||
710 | { | ||
711 | return ( roundedCombo ); | ||
712 | } | ||
713 | |||
714 | inline bool OThemeBase::roundSlider() const | ||
715 | { | ||
716 | return ( roundedSlider ); | ||
717 | } | ||
718 | |||
719 | inline bool OThemeBase::activeTabLine() const | ||
720 | { | ||
721 | return ( aTabLine ); | ||
722 | } | ||
723 | |||
724 | inline bool OThemeBase::inactiveTabLine() const | ||
725 | { | ||
726 | return ( iTabLine ); | ||
727 | } | ||
728 | |||
729 | inline int OThemeBase::getSBExtent() const | ||
730 | { | ||
731 | return ( sbExtent ); | ||
732 | } | ||
733 | |||
734 | inline OThemePixmap* OThemeBase::borderPixmap( WidgetType widget ) | ||
735 | { | ||
736 | return ( pbPixmaps[ widget ] ); | ||
737 | } | ||
738 | |||
739 | #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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public | ||
6 | License version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This library is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | Library General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Library General Public License | ||
14 | along with this library; see the file COPYING.LIB. If not, write to | ||
15 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #include "othemestyle.h" | ||
20 | #include "othemebase.h" | ||
21 | #include <qpe/qpeapplication.h> | ||
22 | #include <qbitmap.h> | ||
23 | #define INCLUDE_MENUITEM_DEF | ||
24 | #include <qmenudata.h> | ||
25 | #include <qpopupmenu.h> | ||
26 | #include <qtabbar.h> | ||
27 | #include <qglobal.h> | ||
28 | |||
29 | #include <limits.h> | ||
30 | #include <stdio.h> | ||
31 | |||
32 | #define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2) | ||
33 | |||
34 | OThemeStyle::OThemeStyle( const QString &configFile ) | ||
35 | : OThemeBase( configFile ) | ||
36 | { | ||
37 | setScrollBarExtent( getSBExtent(), getSBExtent() ); | ||
38 | setButtonDefaultIndicatorWidth( 0 ); // We REALLY should support one, see drawPushButton() below! | ||
39 | } | ||
40 | |||
41 | OThemeStyle::~OThemeStyle() | ||
42 | {} | ||
43 | |||
44 | void OThemeStyle::polish( QApplication * /*app*/ ) | ||
45 | {} | ||
46 | |||
47 | void OThemeStyle::polish( QPalette &p ) | ||
48 | { | ||
49 | oldPalette = p; | ||
50 | |||
51 | QColor bg = oldPalette. color ( QPalette::Normal, QColorGroup::Background ); | ||
52 | |||
53 | if ( bgcolor. isValid ( )) | ||
54 | bg = bgcolor; | ||
55 | |||
56 | if ( isColor ( Background )) | ||
57 | bg = colorGroup ( oldPalette. active ( ), Background )-> background ( ); | ||
58 | |||
59 | p = QPalette ( bg, bg ); | ||
60 | |||
61 | if ( isPixmap( Background ) ) | ||
62 | p. setBrush ( QColorGroup::Background, QBrush ( bg, *uncached ( Background ))); | ||
63 | |||
64 | if ( fgcolor. isValid ( )) { | ||
65 | p. setColor ( QColorGroup::Foreground, fgcolor ); | ||
66 | p. setColor ( QColorGroup::ButtonText, fgcolor ); | ||
67 | } | ||
68 | if ( selfgcolor. isValid ( )) | ||
69 | p. setColor ( QColorGroup::HighlightedText, selfgcolor ); | ||
70 | if ( selbgcolor. isValid ( )) | ||
71 | p. setColor ( QColorGroup::Highlight, selbgcolor ); | ||
72 | if ( winfgcolor. isValid ( )) | ||
73 | p. setColor ( QColorGroup::Text, winfgcolor ); | ||
74 | if ( winbgcolor. isValid ( )) | ||
75 | p. setColor ( QColorGroup::Base, winbgcolor ); | ||
76 | |||
77 | } | ||
78 | |||
79 | |||
80 | void OThemeStyle::unPolish( QApplication *app ) | ||
81 | { | ||
82 | app->setPalette( oldPalette, true ); | ||
83 | } | ||
84 | |||
85 | void OThemeStyle::polish( QWidget *w ) | ||
86 | { | ||
87 | if ( !w->isTopLevel() ) { | ||
88 | if ( w->inherits( "QGroupBox" ) | ||
89 | || w->inherits( "QTabWidget" ) ) { | ||
90 | w->setAutoMask( TRUE ); | ||
91 | return ; | ||
92 | } | ||
93 | if ( w->inherits( "QLabel" ) | ||
94 | || w->inherits( "QSlider" ) | ||
95 | || w->inherits( "QButton" ) | ||
96 | || w->inherits( "QProgressBar" ) | ||
97 | ) { | ||
98 | w->setBackgroundOrigin( QWidget::ParentOrigin ); | ||
99 | } | ||
100 | } | ||
101 | if ( w->inherits( "QPopupMenu" ) ) { | ||
102 | popupPalette = w->palette(); | ||
103 | if ( isColor( MenuItem ) || isColor( MenuItemDown ) ) { | ||
104 | QPalette newPal( w->palette() ); | ||
105 | w->setPalettePropagation( QWidget::SamePalette ); | ||
106 | if ( isColor( MenuItem ) ) { | ||
107 | newPal.setNormal( *colorGroup( newPal.normal(), MenuItem ) ); | ||
108 | newPal.setDisabled( *colorGroup( newPal.normal(), MenuItem ) ); | ||
109 | } | ||
110 | if ( isColor( MenuItemDown ) ) | ||
111 | newPal.setActive( *colorGroup( newPal.active(), MenuItemDown ) ); | ||
112 | w->setPalette( newPal ); | ||
113 | } | ||
114 | } | ||
115 | if ( w->inherits( "QCheckBox" ) ) { | ||
116 | if ( isColor( IndicatorOff ) || isColor( IndicatorOn ) ) { | ||
117 | QPalette newPal( w->palette() ); | ||
118 | w->setPalettePropagation( QWidget::SamePalette ); | ||
119 | if ( isColor( IndicatorOff ) ) { | ||
120 | newPal.setNormal( *colorGroup( newPal.normal(), IndicatorOff ) ); | ||
121 | newPal.setDisabled( *colorGroup( newPal.normal(), IndicatorOff ) ); | ||
122 | } | ||
123 | if ( isColor( IndicatorOn ) ) | ||
124 | newPal.setActive( *colorGroup( newPal.active(), IndicatorOn ) ); | ||
125 | w->setPalette( newPal ); | ||
126 | } | ||
127 | } | ||
128 | if ( w->inherits( "QRadioButton" ) ) { | ||
129 | if ( isColor( ExIndicatorOff ) || isColor( ExIndicatorOn ) ) { | ||
130 | QPalette newPal( w->palette() ); | ||
131 | w->setPalettePropagation( QWidget::SamePalette ); | ||
132 | if ( isColor( ExIndicatorOff ) ) { | ||
133 | newPal.setNormal( *colorGroup( newPal.normal(), ExIndicatorOff ) ); | ||
134 | newPal.setDisabled( *colorGroup( newPal.normal(), | ||
135 | ExIndicatorOff ) ); | ||
136 | } | ||
137 | if ( isColor( ExIndicatorOn ) ) | ||
138 | newPal.setActive( *colorGroup( newPal.active(), ExIndicatorOn ) ); | ||
139 | w->setPalette( newPal ); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | void OThemeStyle::unPolish( QWidget* w ) | ||
145 | { | ||
146 | if ( !w->isTopLevel() ) { | ||
147 | if ( w->inherits( "QGroupBox" ) | ||
148 | || w->inherits( "QTabWidget" ) ) { | ||
149 | w->setAutoMask( FALSE ); | ||
150 | return ; | ||
151 | } | ||
152 | if ( w->inherits( "QLabel" ) | ||
153 | || w->inherits( "QSlider" ) | ||
154 | || w->inherits( "QButton" ) | ||
155 | || w->inherits( "QProgressBar" ) | ||
156 | ) { | ||
157 | w->setBackgroundOrigin( QWidget::WidgetOrigin ); | ||
158 | } | ||
159 | } | ||
160 | if ( w->inherits( "QPopupMenu" ) ) | ||
161 | w->unsetPalette(); | ||
162 | if ( w->inherits( "QCheckBox" ) ) | ||
163 | w->unsetPalette(); | ||
164 | if ( w->inherits( "QRadioButton" ) ) | ||
165 | w->unsetPalette(); | ||
166 | } | ||
167 | |||
168 | void OThemeStyle::drawBaseButton( QPainter *p, int x, int y, int w, int h, | ||
169 | const QColorGroup &g, bool sunken, bool | ||
170 | rounded, WidgetType type, const QBrush * ) | ||
171 | { | ||
172 | int offset = borderPixmap( type ) ? 0 : decoWidth( type ); | ||
173 | QPen oldPen = p->pen(); | ||
174 | |||
175 | // handle reverse bevel here since it uses decowidth differently | ||
176 | if ( gradientHint( type ) == GrReverseBevel ) { | ||
177 | int i; | ||
178 | bitBlt( p->device(), x, y, scalePixmap( w, h, type ), 0, 0, w, h, | ||
179 | Qt::CopyROP, true ); | ||
180 | p->setPen( g.text() ); | ||
181 | for ( i = 0; i < borderWidth( type ); ++i, ++x, ++y, w -= 2, h -= 2 ) | ||
182 | p->drawRect( x, y, w, h ); | ||
183 | } | ||
184 | // same with KDE style borders | ||
185 | else if ( !borderPixmap( type ) && shade() == KDE ) { | ||
186 | qDrawWinButton( p, x, y, w, h, g, sunken ); | ||
187 | if ( isPixmap( type ) ) | ||
188 | p->drawTiledPixmap( x + 4, y + 4, w - 6, h - 6, | ||
189 | *scalePixmap( w - 6, h - 6, | ||
190 | type ) ); | ||
191 | else | ||
192 | p->fillRect( x + 4, y + 4, w - 6, h - offset * 6, | ||
193 | g.brush( QColorGroup::Button ) ); | ||
194 | |||
195 | } | ||
196 | else { | ||
197 | if ( ( w - offset * 2 ) > 0 && ( h - offset * 2 ) > 0 ) { | ||
198 | if ( isPixmap( type ) ) | ||
199 | if ( rounded ) | ||
200 | p->drawTiledPixmap( x, y, w, h, *scalePixmap( w, h, type ) ); | ||
201 | else | ||
202 | p->drawTiledPixmap( x + offset, y + offset, w - offset * 2, | ||
203 | h - offset * 2, | ||
204 | *scalePixmap( w - offset * 2, h - offset * 2, | ||
205 | type ) ); | ||
206 | else | ||
207 | p->fillRect( x + offset, y + offset, w - offset * 2, h - offset * 2, | ||
208 | g.brush( QColorGroup::Button ) ); | ||
209 | } | ||
210 | if ( borderPixmap( type ) ) | ||
211 | bitBlt( p->device(), x, y, scaleBorder( w, h, type ), 0, 0, w, h, | ||
212 | Qt::CopyROP, false ); | ||
213 | else | ||
214 | drawShade( p, x, y, w, h, g, sunken, rounded, | ||
215 | highlightWidth( type ), borderWidth( type ), shade() ); | ||
216 | } | ||
217 | p->setPen( oldPen ); | ||
218 | } | ||
219 | |||
220 | void OThemeStyle::drawButton( QPainter *p, int x, int y, int w, int h, | ||
221 | const QColorGroup &g, bool sunken, | ||
222 | const QBrush *fill ) | ||
223 | { | ||
224 | drawBaseButton( p, x, y, w, h, g, sunken, roundButton(), sunken ? | ||
225 | PushButtonDown : PushButton, fill ); | ||
226 | } | ||
227 | |||
228 | void OThemeStyle::drawPushButton( QPushButton* btn, QPainter *p ) | ||
229 | { | ||
230 | bool sunken = btn->isOn() || btn->isDown(); | ||
231 | int diw = buttonDefaultIndicatorWidth(); | ||
232 | drawBaseButton( p, diw, diw, btn->width() - 2 * diw, btn->height() - 2 * diw, | ||
233 | *colorGroup( btn->colorGroup(), sunken ? PushButtonDown : | ||
234 | PushButton ), sunken, roundButton(), | ||
235 | sunken ? PushButtonDown : PushButton, NULL ); | ||
236 | // TODO if diw, draw fancy default button indicator | ||
237 | } | ||
238 | |||
239 | void OThemeStyle::drawBaseMask( QPainter *p, int x, int y, int w, int h, | ||
240 | bool round ) | ||
241 | { | ||
242 | // round edge fills | ||
243 | static const QCOORD btm_left_fill[] = { | ||
244 | 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, | ||
245 | 1, 2, 2, 2, 3, 2, 4, 2, 2, 3, 3, 3, 4, 3, 3, 4, 4, 4 | ||
246 | }; | ||
247 | |||
248 | static const QCOORD btm_right_fill[] = { | ||
249 | 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 1, 1, 1, 2, 1, 3, 1, 4, | ||
250 | 1, 0, 2, 1, 2, 2, 2, 3, 2, 0, 3, 1, 3, 2, 3, 0, 4, 1, 4 | ||
251 | }; | ||
252 | |||
253 | static const QCOORD top_left_fill[] = { | ||
254 | 3, 0, 4, 0, 2, 1, 3, 1, 4, 1, 1, 2, 2, 2, 3, 2, 4, 2, 0, 3, | ||
255 | 1, 3, 2, 3, 3, 3, 4, 3, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4 | ||
256 | }; | ||
257 | |||
258 | static const QCOORD top_right_fill[] = { | ||
259 | 0, 0, 1, 0, 0, 1, 1, 1, 2, 1, 0, 2, 1, 2, 2, 2, 3, 2, 0, | ||
260 | 3, 1, 3, 2, 3, 3, 3, 4, 3, 0, 4, 1, 4, 2, 4, 3, 4, 4, 4 | ||
261 | }; | ||
262 | |||
263 | QBrush fillBrush( color1, SolidPattern ); | ||
264 | p->setPen( color1 ); | ||
265 | if ( round && w > 19 && h > 19 ) { | ||
266 | int x2 = x + w - 1; | ||
267 | int y2 = y + h - 1; | ||
268 | QPointArray a( QCOORDARRLEN( top_left_fill ), top_left_fill ); | ||
269 | a.translate( 1, 1 ); | ||
270 | p->drawPoints( a ); | ||
271 | a.setPoints( QCOORDARRLEN( btm_left_fill ), btm_left_fill ); | ||
272 | a.translate( 1, h - 6 ); | ||
273 | p->drawPoints( a ); | ||
274 | a.setPoints( QCOORDARRLEN( top_right_fill ), top_right_fill ); | ||
275 | a.translate( w - 6, 1 ); | ||
276 | p->drawPoints( a ); | ||
277 | a.setPoints( QCOORDARRLEN( btm_right_fill ), btm_right_fill ); | ||
278 | a.translate( w - 6, h - 6 ); | ||
279 | p->drawPoints( a ); | ||
280 | |||
281 | p->fillRect( x + 6, y, w - 12, h, fillBrush ); | ||
282 | p->fillRect( x, y + 6, x + 6, h - 12, fillBrush ); | ||
283 | p->fillRect( x2 - 6, y + 6, x2, h - 12, fillBrush ); | ||
284 | p->drawLine( x + 6, y, x2 - 6, y ); | ||
285 | p->drawLine( x + 6, y2, x2 - 6, y2 ); | ||
286 | p->drawLine( x, y + 6, x, y2 - 6 ); | ||
287 | p->drawLine( x2, y + 6, x2, y2 - 6 ); | ||
288 | |||
289 | } | ||
290 | else | ||
291 | p->fillRect( x, y, w, h, fillBrush ); | ||
292 | } | ||
293 | |||
294 | void OThemeStyle::drawButtonMask( QPainter *p, int x, int y, int w, int h ) | ||
295 | { | ||
296 | drawBaseMask( p, x, y, w, h, roundButton() ); | ||
297 | } | ||
298 | |||
299 | void OThemeStyle::drawComboButtonMask( QPainter *p, int x, int y, int w, int h ) | ||
300 | { | ||
301 | drawBaseMask( p, x, y, w, h, roundComboBox() ); | ||
302 | } | ||
303 | |||
304 | void OThemeStyle::drawBevelButton( QPainter *p, int x, int y, int w, int h, | ||
305 | const QColorGroup &g, bool sunken, | ||
306 | const QBrush * ) | ||
307 | { | ||
308 | WidgetType type = sunken ? BevelDown : Bevel; | ||
309 | drawBaseButton( p, x, y, w, h, *colorGroup( g, type ), sunken, false, type ); | ||
310 | } | ||
311 | |||
312 | #if 0 | ||
313 | void OThemeStyle::drawKToolBarButton( QPainter *p, int x, int y, int w, int h, | ||
314 | const QColorGroup &g, bool sunken, | ||
315 | bool raised, bool enabled, bool popup, | ||
316 | KToolButtonType type, const QString &btext, | ||
317 | const QPixmap *pixmap, QFont *font, | ||
318 | QWidget * ) | ||
319 | { | ||
320 | QFont tmp_font( QString::fromLatin1( "Helvetica" ), 10 ); | ||
321 | if ( font ) | ||
322 | tmp_font = *font; | ||
323 | QFontMetrics fm( tmp_font ); | ||
324 | WidgetType widget = sunken ? ToolButtonDown : ToolButton; | ||
325 | |||
326 | drawBaseButton( p, x, y, w, h, *colorGroup( g, widget ), sunken, false, | ||
327 | widget ); | ||
328 | int dx, dy; | ||
329 | if ( type == Icon ) { // icon only | ||
330 | if ( pixmap ) { | ||
331 | dx = ( w - pixmap->width() ) / 2; | ||
332 | dy = ( h - pixmap->height() ) / 2; | ||
333 | if ( sunken ) { | ||
334 | ++dx; | ||
335 | ++dy; | ||
336 | } | ||
337 | p->drawPixmap( x + dx, y + dy, *pixmap ); | ||
338 | } | ||
339 | } | ||
340 | else if ( type == IconTextRight ) { // icon and text (if any) | ||
341 | if ( pixmap ) { | ||
342 | dx = 4; | ||
343 | dy = ( h - pixmap->height() ) / 2; | ||
344 | if ( sunken ) { | ||
345 | ++dx; | ||
346 | ++dy; | ||
347 | } | ||
348 | p->drawPixmap( x + dx, y + dy, *pixmap ); | ||
349 | } | ||
350 | if ( !btext.isNull() ) { | ||
351 | int tf = AlignVCenter | AlignLeft; | ||
352 | if ( pixmap ) | ||
353 | dx = 4 + pixmap->width() + 2; | ||
354 | else | ||
355 | dx = 4; | ||
356 | dy = 0; | ||
357 | if ( sunken ) { | ||
358 | ++dx; | ||
359 | ++dy; | ||
360 | } | ||
361 | if ( font ) | ||
362 | p->setFont( *font ); | ||
363 | if ( raised ) | ||
364 | p->setPen( KGlobalSettings::toolBarHighlightColor() ); | ||
365 | p->drawText( x + dx, y + dy, w - dx, h, tf, btext ); | ||
366 | } | ||
367 | } | ||
368 | else if ( type == Text ) { // only text, even if there is a icon | ||
369 | if ( !btext.isNull() ) { | ||
370 | int tf = AlignTop | AlignLeft; | ||
371 | if ( !enabled ) | ||
372 | p->setPen( g.dark() ); | ||
373 | dx = ( w - fm.width( btext ) ) / 2; | ||
374 | dy = ( h - fm.lineSpacing() ) / 2; | ||
375 | if ( sunken ) { | ||
376 | ++dx; | ||
377 | ++dy; | ||
378 | } | ||
379 | if ( font ) | ||
380 | p->setFont( *font ); | ||
381 | if ( raised ) | ||
382 | p->setPen( KGlobalSettings::toolBarHighlightColor() ); | ||
383 | p->drawText( x + dx, y + dy, fm.width( btext ), fm.lineSpacing(), tf, btext ); | ||
384 | } | ||
385 | } | ||
386 | else if ( type == IconTextBottom ) { | ||
387 | if ( pixmap ) { | ||
388 | dx = ( w - pixmap->width() ) / 2; | ||
389 | dy = ( h - fm.lineSpacing() - pixmap->height() ) / 2; | ||
390 | if ( sunken ) { | ||
391 | ++dx; | ||
392 | ++dy; | ||
393 | } | ||
394 | p->drawPixmap( x + dx, y + dy, *pixmap ); | ||
395 | } | ||
396 | if ( !btext.isNull() ) { | ||
397 | int tf = AlignBottom | AlignHCenter; | ||
398 | dx = ( w - fm.width( btext ) ) / 2; | ||
399 | dy = h - fm.lineSpacing() - 4; | ||
400 | if ( sunken ) { | ||
401 | ++dx; | ||
402 | ++dy; | ||
403 | } | ||
404 | if ( font ) | ||
405 | p->setFont( *font ); | ||
406 | if ( raised ) | ||
407 | p->setPen( KGlobalSettings::toolBarHighlightColor() ); | ||
408 | p->drawText( x + dx, y + dy, fm.width( btext ), fm.lineSpacing(), tf, btext ); | ||
409 | } | ||
410 | } | ||
411 | if ( popup ) { | ||
412 | if ( enabled ) | ||
413 | qDrawArrow ( p, DownArrow, WindowsStyle, false, w - 5, h - 5, 0, 0, | ||
414 | g, true ); | ||
415 | else | ||
416 | qDrawArrow ( p, DownArrow, WindowsStyle, false, w - 5, h - 5, | ||
417 | 0, 0, g, false ); | ||
418 | } | ||
419 | } | ||
420 | |||
421 | void OThemeStyle::drawKBarHandle( QPainter *p, int x, int y, int w, int h, | ||
422 | const QColorGroup &g, KToolBarPos, QBrush * ) | ||
423 | { | ||
424 | if ( w > h ) | ||
425 | drawBaseButton( p, x, y, w, h, *colorGroup( g, HBarHandle ), false, false, | ||
426 | HBarHandle ); | ||
427 | else | ||
428 | drawBaseButton( p, x, y, w, h, *colorGroup( g, VBarHandle ), false, false, | ||
429 | VBarHandle ); | ||
430 | } | ||
431 | |||
432 | void OThemeStyle::drawKToolBar( QPainter *p, int x, int y, int w, int h, | ||
433 | const QColorGroup &g, KToolBarPos, QBrush * ) | ||
434 | { | ||
435 | drawBaseButton( p, x, y, w, h, *colorGroup( g, ToolBar ), false, false, | ||
436 | ToolBar ); | ||
437 | } | ||
438 | #endif | ||
439 | |||
440 | QRect OThemeStyle::buttonRect( int x, int y, int w, int h ) | ||
441 | { | ||
442 | int spacing = decoWidth( PushButton ) > decoWidth( PushButtonDown ) ? | ||
443 | decoWidth( PushButton ) : decoWidth( PushButtonDown ); | ||
444 | return ( QRect( x + spacing, y + spacing, w - ( spacing * 2 ), h - ( spacing * 2 ) ) ); | ||
445 | } | ||
446 | |||
447 | void OThemeStyle::drawComboButton( QPainter *p, int x, int y, int w, int h, | ||
448 | const QColorGroup &g, bool sunken, bool, | ||
449 | bool, const QBrush * ) | ||
450 | { | ||
451 | WidgetType widget = sunken ? ComboBoxDown : ComboBox; | ||
452 | drawBaseButton( p, x, y, w, h, *colorGroup( g, widget ), sunken, | ||
453 | roundComboBox(), widget ); | ||
454 | if ( !sunken && isPixmap( ComboDeco ) ) | ||
455 | p->drawPixmap( w - uncached( ComboDeco ) ->width() - | ||
456 | decoWidth( ComboBox ) - 2, | ||
457 | y + ( h - uncached( ComboDeco ) -> | ||
458 | height() ) / 2, *uncached( ComboDeco ) ); | ||
459 | else if ( sunken && isPixmap( ComboDecoDown ) ) | ||
460 | p->drawPixmap( w - uncached( ComboDecoDown ) ->width() - | ||
461 | decoWidth( ComboBoxDown ) - 2, | ||
462 | y + ( h - uncached( ComboDecoDown ) -> | ||
463 | height() ) / 2, *uncached( ComboDecoDown ) ); | ||
464 | else { | ||
465 | qDrawArrow( p, Qt::DownArrow, Qt::MotifStyle, false, w - 15, y + 6, 10, | ||
466 | h - 15, *colorGroup( g, widget ), true ); | ||
467 | qDrawShadeRect( p, w - 14, y + 7 + ( h - 15 ), 10, 3, *colorGroup( g, widget ) ); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | void OThemeStyle::drawScrollBarControls( QPainter *p, const QScrollBar *sb, | ||
472 | int sliderStart, uint controls, | ||
473 | uint activeControl ) | ||
474 | { | ||
475 | int sliderMin, sliderMax, sliderLength, buttonDim; | ||
476 | QRect add | ||
477 | , sub, addPage, subPage, slider; | ||
478 | int addX, addY, subX, subY; | ||
479 | bool horizontal = sb->orientation() == QScrollBar::Horizontal; | ||
480 | int len = ( horizontal ) ? sb->width() : sb->height(); | ||
481 | int extent = ( horizontal ) ? sb->height() : sb->width(); | ||
482 | int offset = decoWidth( horizontal ? HScrollGroove : VScrollGroove ); | ||
483 | QColorGroup g = sb->colorGroup(); | ||
484 | |||
485 | scrollBarMetrics( sb, sliderMin, sliderMax, sliderLength, buttonDim ); | ||
486 | if ( sliderStart > sliderMax ) | ||
487 | sliderStart = sliderMax; | ||
488 | |||
489 | int sliderEnd = sliderStart + sliderLength; | ||
490 | int sliderWidth = extent - offset * 2; | ||
491 | |||
492 | // Scary button placement code >:-P Feel free to improve this if you | ||
493 | // want. I get a headache just looking at it... (mosfet) | ||
494 | if ( scrollBarLayout() == SBOpposite ) { | ||
495 | if ( horizontal ) { | ||
496 | subY = addY = ( extent - buttonDim ) / 2; | ||
497 | subX = offset; | ||
498 | addX = len - buttonDim - offset; | ||
499 | } | ||
500 | else { | ||
501 | subX = addX = ( extent - buttonDim ) / 2; | ||
502 | subY = offset; | ||
503 | addY = len - buttonDim - offset; | ||
504 | } | ||
505 | sub.setRect( subX, subY, buttonDim, buttonDim ); | ||
506 | add.setRect( addX, addY, buttonDim, buttonDim ); | ||
507 | if ( horizontal ) { | ||
508 | subPage.setRect( sub.right() + 1, offset, | ||
509 | sliderStart - sub.right() - 1 , sliderWidth ); | ||
510 | addPage.setRect( sliderEnd, offset, addX - sliderEnd, sliderWidth ); | ||
511 | slider.setRect( sliderStart, offset, sliderLength, sliderWidth ); | ||
512 | } | ||
513 | else { | ||
514 | subPage.setRect( offset, sub.bottom() + 1, sliderWidth, | ||
515 | sliderStart - sub.bottom() - 1 ); | ||
516 | addPage.setRect( offset, sliderEnd, sliderWidth, addY - sliderEnd ); | ||
517 | slider.setRect( offset, sliderStart, sliderWidth, sliderLength ); | ||
518 | } | ||
519 | } | ||
520 | else if ( horizontal ) { | ||
521 | subY = addY = ( extent - buttonDim ) / 2; | ||
522 | if ( scrollBarLayout() == SBBottomLeft ) { | ||
523 | subX = offset; | ||
524 | addX = buttonDim + offset; | ||
525 | subPage.setRect( buttonDim * 2, 0, sliderStart - 1, extent ); | ||
526 | addPage.setRect( sliderEnd, 0, len - sliderEnd, extent ); | ||
527 | slider.setRect( sliderStart, 0, sliderLength, extent ); | ||
528 | } | ||
529 | else { | ||
530 | subX = len - buttonDim - buttonDim - offset; | ||
531 | addX = len - buttonDim - offset; | ||
532 | subPage.setRect( offset + 1, offset, sliderStart - 1 , sliderWidth ); | ||
533 | addPage.setRect( sliderEnd, offset, subX - sliderEnd, sliderWidth ); | ||
534 | slider.setRect( sliderStart, offset, sliderLength, sliderWidth ); | ||
535 | } | ||
536 | sub.setRect( subX, subY, buttonDim, buttonDim ); | ||
537 | add.setRect( addX, addY, buttonDim, buttonDim ); | ||
538 | } | ||
539 | else { // BottomLeft and BottomRight vertical bars are the same. | ||
540 | subX = addX = ( extent - buttonDim ) / 2; | ||
541 | subY = len - buttonDim - buttonDim - offset; | ||
542 | addY = len - buttonDim - offset; | ||
543 | subPage.setRect( offset, offset + 1, sliderWidth, | ||
544 | sliderStart - offset - 1 ); | ||
545 | addPage.setRect( offset, sliderEnd, sliderWidth, subY - sliderEnd ); | ||
546 | slider.setRect( offset, sliderStart, sliderWidth, sliderLength ); | ||
547 | sub.setRect( subX, subY, buttonDim, buttonDim ); | ||
548 | add.setRect( addX, addY, buttonDim, buttonDim ); | ||
549 | } | ||
550 | // End of the button placement code | ||
551 | |||
552 | bool active; | ||
553 | if ( ( controls & QStyle::SubPage ) ) { | ||
554 | drawScrollBarGroove( p, sb, horizontal, subPage, g ); | ||
555 | } | ||
556 | if ( ( controls & QStyle::AddPage ) ) { | ||
557 | drawScrollBarGroove( p, sb, horizontal, addPage, g ); | ||
558 | } | ||
559 | if ( controls & QStyle::AddLine ) { | ||
560 | active = activeControl == QStyle::AddLine; | ||
561 | drawBaseButton( p, add.x(), add.y(), add.width(), add.height(), | ||
562 | *colorGroup( g, active ? ScrollButtonDown : ScrollButton ), | ||
563 | active, false, active ? ScrollButtonDown : ScrollButton ); | ||
564 | drawArrow( p, ( horizontal ) ? RightArrow : DownArrow, active, add.x() + 3, | ||
565 | add.y() + 3, add.width() - 6, add.height() - 6, | ||
566 | *colorGroup( g, active ? ScrollButtonDown : ScrollButton ) ); | ||
567 | } | ||
568 | if ( controls & QStyle::SubLine ) { | ||
569 | active = activeControl == QStyle::SubLine; | ||
570 | p->setPen( g.dark() ); | ||
571 | p->drawRect( sub ); | ||
572 | drawBaseButton( p, sub.x(), sub.y(), sub.width(), sub.height(), | ||
573 | *colorGroup( g, active ? ScrollButtonDown : ScrollButton ), | ||
574 | active, false, active ? ScrollButtonDown : ScrollButton ); | ||
575 | drawArrow( p, ( horizontal ) ? LeftArrow : UpArrow, active, sub.x() + 3, | ||
576 | sub.y() + 3, sub.width() - 6, sub.height() - 6, | ||
577 | *colorGroup( g, active ? ScrollButtonDown : ScrollButton ) ); | ||
578 | } | ||
579 | if ( controls & QStyle::Slider ) { | ||
580 | active = activeControl == QStyle::Slider; | ||
581 | WidgetType widget = horizontal ? | ||
582 | active ? HScrollBarSliderDown : HScrollBarSlider : | ||
583 | active ? VScrollBarSliderDown : VScrollBarSlider; | ||
584 | |||
585 | drawBaseButton( p, slider.x(), slider.y(), slider.width(), | ||
586 | slider.height(), *colorGroup( g, widget ), active, false, | ||
587 | widget ); | ||
588 | int spaceW = horizontal ? slider.width() - decoWidth( widget ) - 4 : | ||
589 | slider.width(); | ||
590 | int spaceH = horizontal ? slider.height() : | ||
591 | slider.height() - decoWidth( widget ) - 4; | ||
592 | widget = active ? horizontal ? HScrollDecoDown : VScrollDecoDown : | ||
593 | horizontal ? HScrollDeco : VScrollDeco; | ||
594 | if ( isPixmap( widget ) ) { | ||
595 | if ( spaceW >= uncached( widget ) ->width() && | ||
596 | spaceH >= uncached( widget ) ->height() ) { | ||
597 | p->drawPixmap( slider.x() + ( slider.width() - | ||
598 | uncached( widget ) ->width() ) / 2, | ||
599 | slider.y() + ( slider.height() - | ||
600 | uncached( widget ) ->height() ) / 2, | ||
601 | *uncached( widget ) ); | ||
602 | } | ||
603 | } | ||
604 | } | ||
605 | } | ||
606 | |||
607 | void OThemeStyle::drawScrollBarGroove( QPainter *p, const QScrollBar *sb, | ||
608 | bool horizontal, QRect r, QColorGroup g ) | ||
609 | |||
610 | { | ||
611 | WidgetType widget = ( horizontal ) ? HScrollGroove : VScrollGroove; | ||
612 | if ( !isPixmap( widget ) ) { | ||
613 | p->fillRect( r, colorGroup( g, widget ) ->brush( QColorGroup::Background ) ); | ||
614 | } | ||
615 | else { | ||
616 | // If the groove is pixmapped we make a full-sized image (it gets | ||
617 | // cached) then bitBlt it to the appropriate rect. | ||
618 | QPixmap buffer( sb->size() ); | ||
619 | QPainter bPainter( &buffer ); | ||
620 | bPainter.drawTiledPixmap( 0, 0, buffer.width(), buffer.height(), | ||
621 | *scalePixmap( buffer.width(), buffer.height(), | ||
622 | widget ) ); | ||
623 | bitBlt( p->device(), r.x(), r.y(), &buffer, r.x(), r.y(), r.width(), | ||
624 | r.height(), Qt::CopyROP ); | ||
625 | } | ||
626 | // Do the borders and frame | ||
627 | drawShade( p, sb->rect().x(), sb->rect().y(), sb->rect().width(), | ||
628 | sb->rect().height(), *colorGroup( g, widget ), true, false, | ||
629 | highlightWidth( widget ), borderWidth( widget ), shade() ); | ||
630 | } | ||
631 | |||
632 | void OThemeStyle::scrollBarMetrics( const QScrollBar *sb, int &sliderMin, | ||
633 | int &sliderMax, int &sliderLength, | ||
634 | int &buttonDim ) | ||
635 | { | ||
636 | bool horizontal = sb->orientation() == QScrollBar::Horizontal; | ||
637 | int offset = decoWidth( horizontal ? HScrollGroove : VScrollGroove ); | ||
638 | int maxlen; | ||
639 | int len = horizontal ? sb->width() : sb->height(); | ||
640 | int extent = horizontal ? sb->height() : sb->width(); | ||
641 | |||
642 | if ( len > ( extent - offset * 2 - 1 ) * 2 + offset * 2 ) | ||
643 | buttonDim = extent - offset * 2; | ||
644 | else | ||
645 | buttonDim = ( len - offset * 2 ) / 2 - 1; | ||
646 | maxlen = len - offset * 2 - buttonDim * 2 - 1; | ||
647 | |||
648 | switch ( scrollBarLayout() ) { | ||
649 | case SBBottomLeft: | ||
650 | sliderMin = ( horizontal ) ? buttonDim * 2 + offset + 1 : offset + 1; | ||
651 | break; | ||
652 | case SBBottomRight: | ||
653 | sliderMin = offset + 1; | ||
654 | break; | ||
655 | case SBOpposite: | ||
656 | default: | ||
657 | sliderMin = offset + buttonDim; | ||
658 | break; | ||
659 | } | ||
660 | if ( sb->maxValue() == sb->minValue() ) | ||
661 | sliderLength = maxlen; | ||
662 | else | ||
663 | sliderLength = ( sb->pageStep() * maxlen ) / ( sb->maxValue() - | ||
664 | sb->minValue() + sb->pageStep() ); | ||
665 | if ( sliderLength < 12 || ( sb->maxValue() - sb->minValue() ) > INT_MAX / 2 ) | ||
666 | sliderLength = 12; | ||
667 | if ( sliderLength > maxlen ) | ||
668 | sliderLength = maxlen; | ||
669 | sliderMax = sliderMin + maxlen - sliderLength; | ||
670 | } | ||
671 | |||
672 | QStyle::ScrollControl OThemeStyle::scrollBarPointOver( const QScrollBar *sb, | ||
673 | int sliderStart, | ||
674 | const QPoint &p ) | ||
675 | { | ||
676 | if ( !sb->rect().contains( p ) ) | ||
677 | return ( QStyle::NoScroll ); | ||
678 | int sliderMin, sliderMax, sliderLength, buttonDim; | ||
679 | int pos = ( sb->orientation() == QScrollBar::Horizontal ) ? p.x() : p.y(); | ||
680 | scrollBarMetrics( sb, sliderMin, sliderMax, sliderLength, buttonDim ); | ||
681 | |||
682 | if ( scrollBarLayout() == SBOpposite ) { | ||
683 | if ( pos < sliderMin ) | ||
684 | return QStyle::SubLine; | ||
685 | if ( pos < sliderStart ) | ||
686 | return SubPage; | ||
687 | if ( pos < sliderStart + sliderLength ) | ||
688 | return QStyle::Slider; | ||
689 | if ( pos < sliderMax + sliderLength ) | ||
690 | return QStyle::AddPage; | ||
691 | return QStyle::AddLine; | ||
692 | } | ||
693 | if ( scrollBarLayout() == SBBottomLeft && sb->orientation() == | ||
694 | QScrollBar::Horizontal ) { | ||
695 | if ( pos <= buttonDim ) | ||
696 | return ( QStyle::SubLine ); | ||
697 | else if ( pos <= buttonDim * 2 ) | ||
698 | return ( QStyle::AddLine ); | ||
699 | else if ( pos < sliderStart ) | ||
700 | return ( QStyle::SubPage ); | ||
701 | else if ( pos < sliderStart + sliderLength ) | ||
702 | return ( QStyle::Slider ); | ||
703 | return ( AddPage ); | ||
704 | } | ||
705 | else { | ||
706 | if ( pos < sliderStart ) | ||
707 | return QStyle::SubPage; | ||
708 | if ( pos < sliderStart + sliderLength ) | ||
709 | return QStyle::Slider; | ||
710 | if ( pos < sliderMax + sliderLength ) | ||
711 | return QStyle::AddPage; | ||
712 | if ( pos < sliderMax + sliderLength + buttonDim ) | ||
713 | return QStyle::SubLine; | ||
714 | return QStyle::AddLine; | ||
715 | } | ||
716 | } | ||
717 | |||
718 | QSize OThemeStyle::exclusiveIndicatorSize() const | ||
719 | { | ||
720 | if ( isPixmap( ExIndicatorOn ) ) | ||
721 | return ( uncached( ExIndicatorOn ) ->size() ); | ||
722 | else | ||
723 | return ( QWindowsStyle::exclusiveIndicatorSize() ); | ||
724 | } | ||
725 | |||
726 | QSize OThemeStyle::indicatorSize() const | ||
727 | { | ||
728 | if ( isPixmap( IndicatorOn ) ) | ||
729 | return ( uncached( IndicatorOn ) ->size() ); | ||
730 | else | ||
731 | return ( QWindowsStyle::indicatorSize() ); | ||
732 | } | ||
733 | |||
734 | void OThemeStyle::drawExclusiveIndicator( QPainter* p, int x, int y, int w, | ||
735 | int h, const QColorGroup &g, bool on, | ||
736 | bool down, bool enabled ) | ||
737 | { | ||
738 | if ( isPixmap( ( on || down ) ? ExIndicatorOn : ExIndicatorOff ) ) { | ||
739 | p->drawPixmap( x, y, *uncached( ( on || down ) ? ExIndicatorOn : | ||
740 | ExIndicatorOff ) ); | ||
741 | } | ||
742 | else { | ||
743 | QWindowsStyle::drawExclusiveIndicator( p, x, y, w, h, | ||
744 | *colorGroup( g, ExIndicatorOn ), | ||
745 | on, down, enabled ); | ||
746 | } | ||
747 | |||
748 | } | ||
749 | |||
750 | void OThemeStyle::drawIndicator( QPainter* p, int x, int y, int w, int h, | ||
751 | const QColorGroup &g, int state, bool down, | ||
752 | bool enabled ) | ||
753 | { | ||
754 | if ( isPixmap( ( down || state != QButton::Off ) ? | ||
755 | IndicatorOn : IndicatorOff ) ) { | ||
756 | p->drawPixmap( x, y, *uncached( ( down || state != QButton::Off ) ? | ||
757 | IndicatorOn : IndicatorOff ) ); | ||
758 | } | ||
759 | else { | ||
760 | QWindowsStyle::drawIndicator( p, x, y, w, h, | ||
761 | *colorGroup( g, IndicatorOn ), state, | ||
762 | down, enabled ); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | void OThemeStyle::drawExclusiveIndicatorMask( QPainter *p, int x, int y, int w, | ||
767 | int h, bool on ) | ||
768 | { | ||
769 | if ( isPixmap( ( on ) ? ExIndicatorOn : ExIndicatorOff ) ) { | ||
770 | const QBitmap * mask = uncached( ( on ) ? ExIndicatorOn : ExIndicatorOff ) -> | ||
771 | mask(); | ||
772 | if ( mask ) { | ||
773 | p->drawPixmap( x, y, *mask ); | ||
774 | } | ||
775 | else | ||
776 | p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) ); | ||
777 | } | ||
778 | else | ||
779 | QWindowsStyle::drawExclusiveIndicatorMask( p, x, y, w, h, on ); | ||
780 | } | ||
781 | |||
782 | void OThemeStyle::drawIndicatorMask( QPainter *p, int x, int y, int w, int h, | ||
783 | int state ) | ||
784 | { | ||
785 | if ( isPixmap( ( state != QButton::Off ) ? IndicatorOn : IndicatorOff ) ) { | ||
786 | const QBitmap * mask = uncached( ( state != QButton::Off ) ? IndicatorOn : | ||
787 | IndicatorOff ) ->mask(); | ||
788 | if ( mask ) | ||
789 | p->drawPixmap( x, y, *mask ); | ||
790 | else | ||
791 | p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) ); | ||
792 | } | ||
793 | else | ||
794 | QWindowsStyle::drawIndicatorMask( p, x, y, w, h, state ); | ||
795 | } | ||
796 | |||
797 | void OThemeStyle::drawSliderGroove( QPainter *p, int x, int y, int w, int h, | ||
798 | const QColorGroup& g, QCOORD c, | ||
799 | Orientation orient ) | ||
800 | { | ||
801 | if ( roundSlider() ) | ||
802 | QWindowsStyle::drawSliderGroove( p, x, y, w, h, | ||
803 | *colorGroup( g, SliderGroove ), | ||
804 | c, orient ); | ||
805 | else | ||
806 | drawBaseButton( p, x, y, w, h, *colorGroup( g, SliderGroove ), true, | ||
807 | false, SliderGroove ); | ||
808 | } | ||
809 | |||
810 | void OThemeStyle::drawSlider( QPainter *p, int x, int y, int w, int h, | ||
811 | const QColorGroup &g, Orientation orient, | ||
812 | bool tickAbove, bool tickBelow ) | ||
813 | { | ||
814 | if ( isPixmap( Slider ) ) { | ||
815 | if ( orient == Qt::Horizontal ) | ||
816 | p->drawPixmap( x, y + ( h - uncached( Slider ) ->height() ) / 2, | ||
817 | *uncached( Slider ) ); | ||
818 | else | ||
819 | p->drawPixmap( x + ( w - uncached( Slider ) ->width() ) / 2, | ||
820 | y, *uncached( Slider ) ); | ||
821 | } | ||
822 | else { | ||
823 | QWindowsStyle::drawSlider( p, x, y, w, h, *colorGroup( g, Slider ), | ||
824 | orient, tickAbove, tickBelow ); | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void OThemeStyle::drawSliderMask( QPainter *p, int x, int y, int w, int h, | ||
829 | Orientation orient, bool tickAbove, | ||
830 | bool tickBelow ) | ||
831 | { | ||
832 | // This is odd. If we fill in the entire region it still masks the slider | ||
833 | // properly. I have no idea, this used to be different in Qt betas... | ||
834 | if ( isPixmap( Slider ) ) | ||
835 | p->fillRect( x, y, w, h, QBrush( color1, SolidPattern ) ); | ||
836 | else | ||
837 | QWindowsStyle::drawSliderMask( p, x, y, w, h, orient, tickAbove, | ||
838 | tickBelow ); | ||
839 | } | ||
840 | |||
841 | int OThemeStyle::defaultFrameWidth() const | ||
842 | { | ||
843 | return ( frameWidth() ); | ||
844 | } | ||
845 | |||
846 | void OThemeStyle::getButtonShift( int &x, int &y ) | ||
847 | { | ||
848 | x = buttonXShift(); | ||
849 | y = buttonYShift(); | ||
850 | } | ||
851 | |||
852 | int OThemeStyle::sliderLength() const | ||
853 | { | ||
854 | return ( sliderButtonLength() ); | ||
855 | } | ||
856 | |||
857 | void OThemeStyle::drawArrow( QPainter *p, Qt::ArrowType type, bool down, int x, | ||
858 | int y, int w, int h, const QColorGroup &g, | ||
859 | bool enabled, const QBrush * ) | ||
860 | { | ||
861 | // Handles pixmapped arrows. A little inefficent because you can specify | ||
862 | // some as pixmaps and some as default types. | ||
863 | WidgetType widget; | ||
864 | switch ( type ) { | ||
865 | case UpArrow: | ||
866 | widget = enabled ? down ? SunkenArrowUp : ArrowUp : DisArrowUp; | ||
867 | break; | ||
868 | case DownArrow: | ||
869 | widget = enabled ? down ? SunkenArrowDown : ArrowDown : DisArrowDown; | ||
870 | break; | ||
871 | case LeftArrow: | ||
872 | widget = enabled ? down ? SunkenArrowLeft : ArrowLeft : DisArrowLeft; | ||
873 | break; | ||
874 | case RightArrow: | ||
875 | default: | ||
876 | widget = enabled ? down ? SunkenArrowRight : ArrowRight : DisArrowRight; | ||
877 | break; | ||
878 | } | ||
879 | if ( isPixmap( widget ) ) { | ||
880 | p->drawPixmap( x + ( w - uncached( widget ) ->width() ) / 2, | ||
881 | y + ( h - uncached( widget ) ->height() ) / 2, | ||
882 | *uncached( widget ) ); | ||
883 | return ; | ||
884 | } | ||
885 | const QColorGroup *cg = colorGroup( g, widget ); | ||
886 | // Standard arrow types | ||
887 | if ( arrowType() == MotifArrow ) | ||
888 | qDrawArrow( p, type, Qt::MotifStyle, down, x, y, w, h, *cg, enabled ); | ||
889 | else if ( arrowType() == SmallArrow ) { | ||
890 | QColorGroup tmp( *cg ); | ||
891 | tmp.setBrush( QColorGroup::Button, QBrush( NoBrush ) ); | ||
892 | QWindowsStyle::drawArrow( p, type, false, x, y, w, h, | ||
893 | tmp, true ); | ||
894 | } | ||
895 | else { | ||
896 | QPointArray a; | ||
897 | int x2 = x + w - 1, y2 = y + h - 1; | ||
898 | switch ( type ) { | ||
899 | case Qt::UpArrow: | ||
900 | a.setPoints( 4, x, y2, x2, y2, x + w / 2, y, x, y2 ); | ||
901 | break; | ||
902 | case Qt::DownArrow: | ||
903 | a.setPoints( 4, x, y, x2, y, x + w / 2, y2, x, y ); | ||
904 | break; | ||
905 | case Qt::LeftArrow: | ||
906 | a.setPoints( 4, x2, y, x2, y2, x, y + h / 2, x2, y ); | ||
907 | break; | ||
908 | default: | ||
909 | a.setPoints( 4, x, y, x, y2, x2, y + h / 2, x, y ); | ||
910 | break; | ||
911 | } | ||
912 | QBrush oldBrush = p->brush(); | ||
913 | QPen oldPen = p->pen(); | ||
914 | p->setBrush( cg->brush( QColorGroup::Shadow ) ); | ||
915 | p->setPen( cg->shadow() ); | ||
916 | p->drawPolygon( a ); | ||
917 | p->setBrush( oldBrush ); | ||
918 | p->setPen( oldPen ); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | /* This is where we draw the borders and highlights. The new round button | ||
923 | * code is a pain in the arse. We don't want to be calculating arcs so | ||
924 | * use a whole lotta QPointArray's ;-) The code is made a lot more complex | ||
925 | * because you can have variable width border and highlights... | ||
926 | * I may want to cache this if round buttons are used, but am concerned | ||
927 | * about excessive cache misses. This is a memory/speed tradeoff that I | ||
928 | * have to test. | ||
929 | */ | ||
930 | void OThemeStyle::drawShade( QPainter *p, int x, int y, int w, int h, | ||
931 | const QColorGroup &g, bool sunken, bool rounded, | ||
932 | int hWidth, int bWidth, ShadeStyle style ) | ||
933 | { | ||
934 | int i, sc, bc, x2, y2; | ||
935 | QPen highPen, lowPen; | ||
936 | |||
937 | if ( style == Motif ) { | ||
938 | highPen.setColor( sunken ? g.dark() : g.light() ); | ||
939 | lowPen.setColor( sunken ? g.light() : g.dark() ); | ||
940 | } | ||
941 | else { | ||
942 | highPen.setColor( sunken ? g.shadow() : g.light() ); | ||
943 | lowPen.setColor( sunken ? g.light() : g.shadow() ); | ||
944 | } | ||
945 | |||
946 | // Advanced round buttons | ||
947 | if ( rounded && w > 19 && h > 19 ) { | ||
948 | x2 = x + w - 1, y2 = y + h - 1; | ||
949 | QPointArray bPntArray, hPntArray, lPntArray; | ||
950 | QPointArray bLineArray, hLineArray, lLineArray; | ||
951 | // borders | ||
952 | for ( i = 0, bc = 0; i < bWidth; ++i ) { | ||
953 | bPntArray.putPoints( bc, 24, x + 4, y + 1, x + 5, y + 1, x + 3, y + 2, x + 2, y + 3, | ||
954 | x + 1, y + 4, x + 1, y + 5, x + 1, y2 - 5, x + 1, y2 - 4, x + 2, y2 - 3, | ||
955 | x2 - 5, y + 1, x2 - 4, y + 1, x2 - 3, y + 2, x2 - 5, y2 - 1, | ||
956 | x2 - 4, y2 - 1, x2 - 3, y2 - 2, x2 - 2, y2 - 3, x2 - 1, y2 - 5, | ||
957 | x2 - 1, y2 - 4, x + 3, y2 - 2, x + 4, y2 - 1, x + 5, y2 - 1, | ||
958 | x2 - 2, y + 3, x2 - 1, y + 4, x2 - 1, y + 5 ); | ||
959 | bc += 24; | ||
960 | // ellispe edges don't match exactly, so fill in blanks | ||
961 | if ( i < bWidth - 1 || hWidth != 0 ) { | ||
962 | bPntArray.putPoints( bc, 20, x + 6, y + 1, x + 4, y + 2, x + 3, y + 3, | ||
963 | x + 2, y + 4, x + 1, y + 6, x2 - 6, y + 1, x2 - 4, y + 2, | ||
964 | x2 - 3, y + 3, x + 2, y2 - 4, x + 1, y2 - 6, x2 - 6, y2 - 1, | ||
965 | x2 - 4, y2 - 2, x2 - 3, y2 - 3, x2 - 2, y2 - 4, x2 - 1, y2 - 6, | ||
966 | x + 6, y2 - 1, x + 4, y2 - 2, x + 3, y2 - 3, x2 - 1, y + 6, | ||
967 | x2 - 2, y + 4 ); | ||
968 | bc += 20; | ||
969 | } | ||
970 | bLineArray.putPoints( i * 8, 8, x + 6, y, x2 - 6, y, x, y + 6, x, y2 - 6, | ||
971 | x + 6, y2, x2 - 6, y2, x2, y + 6, x2, y2 - 6 ); | ||
972 | ++x, ++y; | ||
973 | --x2, --y2; | ||
974 | } | ||
975 | // highlights | ||
976 | for ( i = 0, sc = 0; i < hWidth; ++i ) { | ||
977 | hPntArray.putPoints( sc, 12, x + 4, y + 1, x + 5, y + 1, // top left | ||
978 | x + 3, y + 2, x + 2, y + 3, x + 1, y + 4, x + 1, y + 5, | ||
979 | x + 1, y2 - 5, x + 1, y2 - 4, x + 2, y2 - 3, // half corners | ||
980 | x2 - 5, y + 1, x2 - 4, y + 1, x2 - 3, y + 2 ); | ||
981 | lPntArray.putPoints( sc, 12, x2 - 5, y2 - 1, x2 - 4, y2 - 1, // btm right | ||
982 | x2 - 3, y2 - 2, x2 - 2, y2 - 3, x2 - 1, y2 - 5, x2 - 1, y2 - 4, | ||
983 | x + 3, y2 - 2, x + 4, y2 - 1, x + 5, y2 - 1, //half corners | ||
984 | x2 - 2, y + 3, x2 - 1, y + 4, x2 - 1, y + 5 ); | ||
985 | sc += 12; | ||
986 | if ( i < hWidth - 1 ) { | ||
987 | hPntArray.putPoints( sc, 10, x + 6, y + 1, x + 4, y + 2, // top left | ||
988 | x + 3, y + 3, x + 2, y + 4, x + 1, y + 6, | ||
989 | x2 - 6, y + 1, x2 - 4, y + 2, // half corners | ||
990 | x2 - 3, y + 3, x + 2, y2 - 4, x + 1, y2 - 6 ); | ||
991 | lPntArray.putPoints( sc, 10, x2 - 6, y2 - 1, x2 - 4, y2 - 2, // btm right | ||
992 | x2 - 3, y2 - 3, x2 - 2, y2 - 4, x2 - 1, y2 - 6, | ||
993 | x + 6, y2 - 1, x + 4, y2 - 2, // half corners | ||
994 | x + 3, y2 - 3, x2 - 1, y + 6, x2 - 2, y + 4 ); | ||
995 | sc += 10; | ||
996 | } | ||
997 | hLineArray.putPoints( i * 4, 4, x + 6, y, x2 - 6, y, x, y + 6, x, y2 - 6 ); | ||
998 | lLineArray.putPoints( i * 4, 4, x + 6, y2, x2 - 6, y2, x2, y + 6, x2, y2 - 6 ); | ||
999 | ++x, ++y; | ||
1000 | --x2, --y2; | ||
1001 | } | ||
1002 | p->setPen( Qt::black ); | ||
1003 | p->drawPoints( bPntArray ); | ||
1004 | p->drawLineSegments( bLineArray ); | ||
1005 | p->setPen( highPen ); | ||
1006 | p->drawPoints( hPntArray ); | ||
1007 | p->drawLineSegments( hLineArray ); | ||
1008 | p->setPen( lowPen ); | ||
1009 | p->drawPoints( lPntArray ); | ||
1010 | p->drawLineSegments( lLineArray ); | ||
1011 | } | ||
1012 | // Rectangular buttons | ||
1013 | else { | ||
1014 | QPointArray highShade( hWidth * 4 ); | ||
1015 | QPointArray lowShade( hWidth * 4 ); | ||
1016 | |||
1017 | p->setPen( g.shadow() ); | ||
1018 | for ( i = 0; i < bWidth && w > 2 && h > 2; ++i, ++x, ++y, w -= 2, h -= 2 ) | ||
1019 | p->drawRect( x, y , w, h ); | ||
1020 | |||
1021 | if ( !hWidth ) | ||
1022 | return ; | ||
1023 | |||
1024 | x2 = x + w - 1, y2 = y + h - 1; | ||
1025 | for ( i = 0; i < hWidth; ++i, ++x, ++y, --x2, --y2 ) { | ||
1026 | highShade.putPoints( i * 4, 4, x, y, x2, y, x, y, x, y2 ); | ||
1027 | lowShade.putPoints( i * 4, 4, x, y2, x2, y2, x2, y, x2, y2 ); | ||
1028 | } | ||
1029 | if ( style == Windows && hWidth > 1 ) { | ||
1030 | p->setPen( highPen ); | ||
1031 | p->drawLineSegments( highShade, 0, 2 ); | ||
1032 | p->setPen( lowPen ); | ||
1033 | p->drawLineSegments( lowShade, 0, 2 ); | ||
1034 | |||
1035 | p->setPen( ( sunken ) ? g.dark() : g.mid() ); | ||
1036 | p->drawLineSegments( highShade, 4 ); | ||
1037 | p->setPen( ( sunken ) ? g.mid() : g.dark() ); | ||
1038 | p->drawLineSegments( lowShade, 4 ); | ||
1039 | } | ||
1040 | else { | ||
1041 | p->setPen( ( sunken ) ? g.dark() : g.light() ); | ||
1042 | p->drawLineSegments( highShade ); | ||
1043 | p->setPen( ( sunken ) ? g.light() : g.dark() ); | ||
1044 | p->drawLineSegments( lowShade ); | ||
1045 | } | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | void OThemeStyle::drawPushButtonLabel( QPushButton *btn, QPainter *p ) | ||
1050 | { | ||
1051 | WidgetType widget = btn->isDown() || btn->isOn() ? PushButtonDown : | ||
1052 | PushButton; | ||
1053 | const QColorGroup *cg = colorGroup( btn->colorGroup(), widget ); | ||
1054 | int x, y, w, h; | ||
1055 | |||
1056 | QRect r = btn->rect(); | ||
1057 | r.rect( &x, &y, &w, &h ); | ||
1058 | x += decoWidth( widget ); | ||
1059 | y += decoWidth( widget ); | ||
1060 | w -= decoWidth( widget ) * 2; | ||
1061 | h -= decoWidth( widget ) * 2; | ||
1062 | bool act = btn->isOn() || btn->isDown(); | ||
1063 | |||
1064 | // If this is a button with an associated popup menu, draw an arrow first | ||
1065 | if ( btn->popup() ) { | ||
1066 | int dx = menuButtonIndicatorWidth( btn->height() ); | ||
1067 | |||
1068 | QColorGroup g( btn->colorGroup() ); | ||
1069 | int xx = x + w - dx - 4; | ||
1070 | int yy = y - 3; | ||
1071 | int hh = h + 6; | ||
1072 | |||
1073 | if ( !act ) { | ||
1074 | p->setPen( g.light() ); | ||
1075 | p->drawLine( xx, yy + 3, xx, yy + hh - 4 ); | ||
1076 | } | ||
1077 | else { | ||
1078 | p->setPen( g.button() ); | ||
1079 | p->drawLine( xx, yy + 4, xx, yy + hh - 4 ); | ||
1080 | } | ||
1081 | drawArrow( p, DownArrow, FALSE, | ||
1082 | x + w - dx - 2, y + 2, dx, h - 4, | ||
1083 | btn->colorGroup(), | ||
1084 | btn->isEnabled() ); | ||
1085 | w -= dx; | ||
1086 | } | ||
1087 | |||
1088 | // Next, draw iconset, if any | ||
1089 | if ( btn->iconSet() && !btn->iconSet() ->isNull() ) { | ||
1090 | QIconSet::Mode mode = btn->isEnabled() | ||
1091 | ? QIconSet::Normal : QIconSet::Disabled; | ||
1092 | if ( mode == QIconSet::Normal && btn->hasFocus() ) | ||
1093 | mode = QIconSet::Active; | ||
1094 | QPixmap pixmap = btn->iconSet() ->pixmap( QIconSet::Small, mode ); | ||
1095 | int pixw = pixmap.width(); | ||
1096 | int pixh = pixmap.height(); | ||
1097 | |||
1098 | p->drawPixmap( x + 6, y + h / 2 - pixh / 2, pixmap ); | ||
1099 | x += pixw + 8; | ||
1100 | w -= pixw + 8; | ||
1101 | } | ||
1102 | |||
1103 | if ( widget == PushButtonDown ) { | ||
1104 | drawItem( p, x + buttonXShift(), y + buttonYShift(), | ||
1105 | w, h, AlignCenter | ShowPrefix, *cg, btn->isEnabled(), | ||
1106 | btn->pixmap(), btn->text(), -1, &cg->buttonText() ); | ||
1107 | } | ||
1108 | else { | ||
1109 | drawItem( p, x, y, w, h, AlignCenter | ShowPrefix, *cg, | ||
1110 | btn->isEnabled(), btn->pixmap(), btn->text(), -1, | ||
1111 | &cg->buttonText() ); | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | int OThemeStyle::splitterWidth() const | ||
1116 | { | ||
1117 | return ( splitWidth() ); | ||
1118 | } | ||
1119 | |||
1120 | void OThemeStyle::drawSplitter( QPainter *p, int x, int y, int w, int h, | ||
1121 | const QColorGroup &g, Orientation ) | ||
1122 | { | ||
1123 | drawBaseButton( p, x, y, w, h, *colorGroup( g, Splitter ), false, false, | ||
1124 | Splitter ); | ||
1125 | } | ||
1126 | |||
1127 | void OThemeStyle::drawCheckMark( QPainter *p, int x, int y, int w, int h, | ||
1128 | const QColorGroup &g, bool act, bool dis ) | ||
1129 | { | ||
1130 | if ( isPixmap( CheckMark ) ) { | ||
1131 | if ( !dis ) | ||
1132 | p->drawPixmap( x + ( w - uncached( CheckMark ) ->width() ) / 2, | ||
1133 | y + ( h - uncached( CheckMark ) ->height() ) / 2, | ||
1134 | *uncached( CheckMark ) ); | ||
1135 | } | ||
1136 | else | ||
1137 | QWindowsStyle::drawCheckMark( p, x, y, w, h, *colorGroup( g, CheckMark ), | ||
1138 | act, dis ); | ||
1139 | } | ||
1140 | |||
1141 | int OThemeStyle::popupMenuItemHeight( bool /*checkable*/, QMenuItem *mi, | ||
1142 | const QFontMetrics &fm ) | ||
1143 | { | ||
1144 | int h2, h = 0; | ||
1145 | int offset = QMAX( decoWidth( MenuItemDown ), decoWidth( MenuItem ) ) + 4; | ||
1146 | |||
1147 | if ( mi->isSeparator() ) | ||
1148 | return ( 2 ); | ||
1149 | if ( mi->isChecked() ) | ||
1150 | h = isPixmap( CheckMark ) ? uncached( CheckMark ) ->height() + offset : | ||
1151 | offset + 16; | ||
1152 | if ( mi->pixmap() ) { | ||
1153 | h2 = mi->pixmap() ->height() + offset; | ||
1154 | h = h2 > h ? h2 : h; | ||
1155 | } | ||
1156 | if ( mi->iconSet() ) { | ||
1157 | h2 = mi->iconSet() -> | ||
1158 | pixmap( QIconSet::Small, QIconSet::Normal ).height() + offset; | ||
1159 | h = h2 > h ? h2 : h; | ||
1160 | } | ||
1161 | h2 = fm.height() + offset; | ||
1162 | h = h2 > h ? h2 : h; | ||
1163 | return ( h ); | ||
1164 | } | ||
1165 | |||
1166 | void OThemeStyle::drawPopupMenuItem( QPainter* p, bool checkable, int maxpmw, | ||
1167 | int tab, QMenuItem* mi, | ||
1168 | const QPalette& pal, bool act, | ||
1169 | bool enabled, int x, int y, int w, int h ) | ||
1170 | { | ||
1171 | // I changed the following method to be based from Qt's instead of my own | ||
1172 | // wacky code. Works much better now :P (mosfet) | ||
1173 | static const int motifItemFrame = 2; // menu item frame width | ||
1174 | static const int motifItemHMargin = 5; // menu item hor text margin | ||
1175 | static const int motifItemVMargin = 4; // menu item ver text margin | ||
1176 | |||
1177 | static const int motifArrowHMargin = 6; // arrow horizontal margin | ||
1178 | static const int windowsRightBorder = 12; // right border on windowsstatic const int windowsCheckMarkWidth = 12; // checkmarks width on windows | ||
1179 | bool dis = !enabled; | ||
1180 | const QColorGroup &g = dis ? *colorGroup( pal.normal(), MenuItem ) : | ||
1181 | *colorGroup( pal.normal(), MenuItemDown ); | ||
1182 | |||
1183 | QColorGroup itemg = dis ? *colorGroup( pal.disabled(), MenuItem ) | ||
1184 | : act ? *colorGroup( pal.active(), MenuItemDown ) | ||
1185 | : *colorGroup( pal.normal(), MenuItem ); | ||
1186 | |||
1187 | maxpmw = QMAX( maxpmw, 20 ); | ||
1188 | int checkcol = maxpmw; | ||
1189 | |||
1190 | if ( mi && mi->isSeparator() ) { | ||
1191 | p->setPen( g.dark() ); | ||
1192 | p->drawLine( x, y, x + w, y ); | ||
1193 | p->setPen( g.light() ); | ||
1194 | p->drawLine( x, y + 1, x + w, y + 1 ); | ||
1195 | return ; | ||
1196 | } | ||
1197 | if ( act ) { | ||
1198 | drawBaseButton( p, x, y, w, h, g, true, false, MenuItemDown ); | ||
1199 | } | ||
1200 | else { | ||
1201 | drawShade( p, x, y, w, h, *colorGroup( g, MenuItem ), false, false, | ||
1202 | highlightWidth( MenuItem ), borderWidth( MenuItem ), | ||
1203 | shade() ); | ||
1204 | int dw = decoWidth( MenuItem ); | ||
1205 | if ( !isPixmap( MenuItem ) ) | ||
1206 | p->fillRect( x + dw, y + dw, w - dw * 2, h - dw * 2, | ||
1207 | colorGroup( g, MenuItem ) -> | ||
1208 | brush( QColorGroup::Background ) ); | ||
1209 | else { | ||
1210 | // process inactive item pixmaps as one large item | ||
1211 | p->drawTiledPixmap( x + dw, y + dw, w - dw * 2, h - dw * 2, *scalePixmap | ||
1212 | // (w, p->window().height(), MenuItem), | ||
1213 | ( w, p->clipRegion().boundingRect().height(), MenuItem ), | ||
1214 | x, y ); | ||
1215 | } | ||
1216 | |||
1217 | if ( checkable && mi && mi->isChecked() ) { | ||
1218 | // draw 'pressed' border around checkable items | ||
1219 | // This is extremely important for items that have an iconset | ||
1220 | // because the checkmark isn't drawn in that case | ||
1221 | // An alternative would be superimposing the checkmark over | ||
1222 | // the iconset instead or not drawing the iconset at all. | ||
1223 | int mw = checkcol + motifItemFrame; | ||
1224 | drawShade( p, x, y, mw, h, g, true, false, | ||
1225 | highlightWidth( MenuItemDown ), | ||
1226 | borderWidth( MenuItemDown ), shade() ); | ||
1227 | } | ||
1228 | } | ||
1229 | if ( !mi ) | ||
1230 | return ; | ||
1231 | if ( mi->iconSet() ) { | ||
1232 | QIconSet::Mode mode = dis ? QIconSet::Disabled : QIconSet::Normal; | ||
1233 | if ( act && !dis ) | ||
1234 | mode = QIconSet::Active; | ||
1235 | QPixmap pixmap = mi->iconSet() ->pixmap( QIconSet::Small, mode ); | ||
1236 | int pixw = pixmap.width(); | ||
1237 | int pixh = pixmap.height(); | ||
1238 | QRect cr( x, y, checkcol, h ); | ||
1239 | QRect pmr( 0, 0, pixw, pixh ); | ||
1240 | pmr.moveCenter( cr.center() ); | ||
1241 | p->setPen( itemg.text() ); | ||
1242 | p->drawPixmap( pmr.topLeft(), pixmap ); | ||
1243 | |||
1244 | } | ||
1245 | else if ( checkable ) { | ||
1246 | int mw = checkcol + motifItemFrame; | ||
1247 | int mh = h - 2 * motifItemFrame; | ||
1248 | if ( mi->isChecked() ) { | ||
1249 | drawCheckMark( p, x + motifItemFrame, | ||
1250 | y + motifItemFrame, mw, mh, itemg, act, dis ); | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | p->setPen( colorGroup( g, act ? MenuItemDown : MenuItem ) ->text() ); | ||
1255 | |||
1256 | QColor discol; | ||
1257 | if ( dis ) { | ||
1258 | discol = itemg.text(); | ||
1259 | p->setPen( discol ); | ||
1260 | } | ||
1261 | |||
1262 | int xm = motifItemFrame + checkcol + motifItemHMargin; | ||
1263 | |||
1264 | QString s = mi->text(); | ||
1265 | if ( !s.isNull() ) { | ||
1266 | int t = s.find( '\t' ); | ||
1267 | int m = motifItemVMargin; | ||
1268 | const int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine; | ||
1269 | if ( t >= 0 ) { | ||
1270 | if ( dis && !act ) { | ||
1271 | p->setPen( g.light() ); | ||
1272 | p->drawText( x + w - tab - windowsRightBorder - motifItemHMargin - motifItemFrame + 1, | ||
1273 | y + m + 1, tab, h - 2 * m, text_flags, s.mid( t + 1 ) ); | ||
1274 | p->setPen( discol ); | ||
1275 | } | ||
1276 | p->drawText( x + w - tab - windowsRightBorder - motifItemHMargin - motifItemFrame, | ||
1277 | y + m, tab, h - 2 * m, text_flags, s.mid( t + 1 ) ); | ||
1278 | } | ||
1279 | if ( dis && !act ) { | ||
1280 | p->setPen( g.light() ); | ||
1281 | p->drawText( x + xm + 1, y + m + 1, w - xm + 1, h - 2 * m, text_flags, s, t ); | ||
1282 | p->setPen( discol ); | ||
1283 | } | ||
1284 | p->drawText( x + xm, y + m, w - xm - tab + 1, h - 2 * m, text_flags, s, t ); | ||
1285 | } | ||
1286 | else if ( mi->pixmap() ) { | ||
1287 | QPixmap * pixmap = mi->pixmap(); | ||
1288 | if ( pixmap->depth() == 1 ) | ||
1289 | p->setBackgroundMode( OpaqueMode ); | ||
1290 | p->drawPixmap( x + xm, y + motifItemFrame, *pixmap ); | ||
1291 | if ( pixmap->depth() == 1 ) | ||
1292 | p->setBackgroundMode( TransparentMode ); | ||
1293 | } | ||
1294 | if ( mi->popup() ) { | ||
1295 | int dim = ( h - 2 * motifItemFrame ) / 2; | ||
1296 | if ( act ) { | ||
1297 | if ( !dis ) | ||
1298 | discol = colorGroup( g, MenuItemDown ) ->text(); | ||
1299 | //discol = white; | ||
1300 | QColorGroup g2( discol, g.highlight(), | ||
1301 | white, white, | ||
1302 | dis ? discol : white, | ||
1303 | discol, white ); | ||
1304 | drawArrow( p, RightArrow, true, | ||
1305 | x + w - motifArrowHMargin - motifItemFrame - dim, y + h / 2 - dim / 2, | ||
1306 | dim, dim, g2, TRUE ); | ||
1307 | } | ||
1308 | else { | ||
1309 | drawArrow( p, RightArrow, | ||
1310 | false, | ||
1311 | x + w - motifArrowHMargin - motifItemFrame - dim, y + h / 2 - dim / 2, | ||
1312 | dim, dim, g, mi->isEnabled() ); | ||
1313 | } | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | void OThemeStyle::drawFocusRect( QPainter *p, const QRect &r, | ||
1318 | const QColorGroup &g, const QColor *c, | ||
1319 | bool atBorder ) | ||
1320 | { | ||
1321 | p->setPen( g.dark() ); | ||
1322 | if ( !is3DFocus() ) | ||
1323 | QWindowsStyle::drawFocusRect( p, r, g, c, atBorder ); | ||
1324 | else { | ||
1325 | int i = focusOffset(); | ||
1326 | p->drawLine( r.x() + i, r.y() + 1 + i, r.x() + i, r.bottom() - 1 - i ); | ||
1327 | p->drawLine( r.x() + 1 + i, r.y() + i, r.right() - 1 - i, r.y() + i ); | ||
1328 | p->setPen( g.light() ); | ||
1329 | p->drawLine( r.right() - i, r.y() + 1 + i, r.right() - i, r.bottom() - 1 - i ); | ||
1330 | p->drawLine( r.x() + 1 + i, r.bottom() - i, r.right() - 1 - i, r.bottom() - i ); | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | #if 0 | ||
1335 | void OThemeStyle::drawKMenuBar( QPainter *p, int x, int y, int w, int h, | ||
1336 | const QColorGroup &g, bool, QBrush * ) | ||
1337 | { | ||
1338 | drawBaseButton( p, x, y, w, h, *colorGroup( g, MenuBar ), false, false, | ||
1339 | MenuBar ); | ||
1340 | } | ||
1341 | |||
1342 | void OThemeStyle::drawKMenuItem( QPainter *p, int x, int y, int w, int h, | ||
1343 | const QColorGroup &g, bool active, | ||
1344 | QMenuItem *mi, QBrush * ) | ||
1345 | { | ||
1346 | const QColorGroup * cg = colorGroup( g, active ? MenuBarItem : MenuBar ); | ||
1347 | QColor btext = cg->buttonText(); | ||
1348 | if ( active ) | ||
1349 | drawBaseButton( p, x, y, w, h, *cg, false, false, MenuBarItem ); | ||
1350 | //qDrawShadePanel(p, x, y, w, h, *cg, false, 1); | ||
1351 | |||
1352 | drawItem( p, x, y, w, h, AlignCenter | ShowPrefix | DontClip | SingleLine, | ||
1353 | *cg, mi->isEnabled(), mi->pixmap(), mi->text(), | ||
1354 | -1, &btext ); | ||
1355 | ; | ||
1356 | } | ||
1357 | |||
1358 | void OThemeStyle::drawKProgressBlock( QPainter *p, int x, int y, int w, int h, | ||
1359 | const QColorGroup &g, QBrush * ) | ||
1360 | { | ||
1361 | drawBaseButton( p, x, y, w, h, *colorGroup( g, ProgressBar ), false, false, | ||
1362 | ProgressBar ); | ||
1363 | } | ||
1364 | |||
1365 | void OThemeStyle::getKProgressBackground( const QColorGroup &g, QBrush &bg ) | ||
1366 | { | ||
1367 | const QColorGroup * cg = colorGroup( g, ProgressBg ); | ||
1368 | bg.setColor( cg->color( QColorGroup::Background ) ); | ||
1369 | if ( isPixmap( ProgressBg ) ) | ||
1370 | bg.setPixmap( *uncached( ProgressBg ) ); | ||
1371 | } | ||
1372 | #endif | ||
1373 | |||
1374 | void OThemeStyle::tabbarMetrics( const QTabBar* t, int& hframe, int& vframe, int& overlap ) | ||
1375 | { | ||
1376 | QCommonStyle::tabbarMetrics( t, hframe, vframe, overlap ); | ||
1377 | } | ||
1378 | |||
1379 | void OThemeStyle::drawTab( QPainter* p, const QTabBar* tb, QTab* t , | ||
1380 | bool selected ) | ||
1381 | { | ||
1382 | WidgetType widget = selected ? ActiveTab : InactiveTab; | ||
1383 | const QColorGroup *cg = colorGroup( tb->colorGroup(), widget ); | ||
1384 | int i; | ||
1385 | int x = t->r.x(), y = t->r.y(); | ||
1386 | int x2 = t->r.right(), y2 = t->r.bottom(); | ||
1387 | int bWidth = borderWidth( widget ); | ||
1388 | int hWidth = highlightWidth( widget ); | ||
1389 | if ( tb->shape() == QTabBar::RoundedAbove ) { | ||
1390 | if ( !selected ) { | ||
1391 | p->fillRect( x, y, x2 - x + 1, 2, | ||
1392 | tb->palette().normal().brush( QColorGroup::Background ) ); | ||
1393 | y += 2; | ||
1394 | } | ||
1395 | p->setPen( cg->text() ); | ||
1396 | i = 0; | ||
1397 | if ( i < bWidth ) { | ||
1398 | p->drawLine( x, y + 1, x, y2 ); | ||
1399 | p->drawLine( x2, y + 1, x2, y2 ); | ||
1400 | p->drawLine( x + 1, y, x2 - 1, y ); | ||
1401 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1402 | p->drawLine( x, y2, x2, y2 ); | ||
1403 | --y2; | ||
1404 | } | ||
1405 | ++i, ++x, ++y, --x2; | ||
1406 | } | ||
1407 | for ( ; i < bWidth; ++i, ++x, ++y, --x2 ) { | ||
1408 | p->drawLine( x, y, x, y2 ); | ||
1409 | p->drawLine( x2, y, x2, y2 ); | ||
1410 | p->drawLine( x, y, x2, y ); | ||
1411 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1412 | p->drawLine( x, y2, x2, y2 ); | ||
1413 | --y2; | ||
1414 | } | ||
1415 | } | ||
1416 | i = 0; | ||
1417 | if ( i < hWidth && bWidth == 0 ) { | ||
1418 | p->setPen( cg->light() ); | ||
1419 | p->drawLine( x, y + 1, x, y2 ); | ||
1420 | p->drawLine( x + 1, y, x2 - 1, y ); | ||
1421 | p->setPen( cg->dark() ); | ||
1422 | p->drawLine( x2, y + 1, x2, y2 ); | ||
1423 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1424 | p->drawLine( x, y2, x2, y2 ); | ||
1425 | --y2; | ||
1426 | } | ||
1427 | ++i, ++x, ++y, --x2; | ||
1428 | } | ||
1429 | for ( ; i < hWidth; ++i, ++x, ++y, --x2 ) { | ||
1430 | p->setPen( cg->light() ); | ||
1431 | p->drawLine( x, y, x, y2 ); | ||
1432 | p->drawLine( x, y, x2, y ); | ||
1433 | p->setPen( cg->dark() ); | ||
1434 | p->drawLine( x2, y + 1, x2, y2 ); | ||
1435 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1436 | p->drawLine( x, y2, x2, y2 ); | ||
1437 | --y2; | ||
1438 | } | ||
1439 | } | ||
1440 | if ( isPixmap( widget ) ) | ||
1441 | p->drawTiledPixmap( x, y, x2 - x + 1, y2 - y + 1, | ||
1442 | *scalePixmap( x2 - x + 1, y2 - y + 1, widget ) ); | ||
1443 | else | ||
1444 | p->fillRect( x, y, x2 - x + 1, y2 - y + 1, cg->background() ); | ||
1445 | } | ||
1446 | else if ( tb->shape() == QTabBar::RoundedBelow ) { | ||
1447 | if ( !selected ) { | ||
1448 | p->fillRect( x, y2 - 2, x2 - x + 1, 2, | ||
1449 | tb->palette().normal().brush( QColorGroup::Background ) ); | ||
1450 | y2 -= 2; | ||
1451 | } | ||
1452 | p->setPen( cg->text() ); | ||
1453 | i = 0; | ||
1454 | if ( i < bWidth ) { | ||
1455 | p->drawLine( x, y, x, y2 - 1 ); | ||
1456 | p->drawLine( x2, y, x2, y2 - 1 ); | ||
1457 | p->drawLine( x + 1, y2, x2 - 1, y2 ); | ||
1458 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1459 | p->drawLine( x, y, x2, y ); | ||
1460 | ++y; | ||
1461 | } | ||
1462 | } | ||
1463 | for ( ; i < bWidth; ++i, ++x, --x2, --y2 ) { | ||
1464 | p->drawLine( x, y, x, y2 ); | ||
1465 | p->drawLine( x2, y, x2, y2 ); | ||
1466 | p->drawLine( x, y2, x2, y2 ); | ||
1467 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1468 | p->drawLine( x, y, x2, y ); | ||
1469 | ++y; | ||
1470 | } | ||
1471 | } | ||
1472 | i = 0; | ||
1473 | if ( i < hWidth && bWidth == 0 ) { | ||
1474 | p->setPen( cg->dark() ); | ||
1475 | p->drawLine( x + 1, y2, x2 - 1, y2 ); | ||
1476 | p->drawLine( x2, y, x2, y2 - 1 ); | ||
1477 | p->setPen( cg->light() ); | ||
1478 | p->drawLine( x, y, x, y2 - 1 ); | ||
1479 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1480 | p->drawLine( x, y, x2, y ); | ||
1481 | ++y; | ||
1482 | } | ||
1483 | ++i, ++x, --x2, --y2; | ||
1484 | } | ||
1485 | for ( ; i < hWidth; ++i, ++x, --x2, --y2 ) { | ||
1486 | p->setPen( cg->dark() ); | ||
1487 | p->drawLine( x, y2, x2, y2 ); | ||
1488 | p->drawLine( x2, y, x2, y2 ); | ||
1489 | p->setPen( cg->light() ); | ||
1490 | p->drawLine( x, y, x, y2 ); | ||
1491 | if ( selected ? activeTabLine() : inactiveTabLine() ) { | ||
1492 | p->drawLine( x, y, x2, y ); | ||
1493 | ++y; | ||
1494 | } | ||
1495 | } | ||
1496 | if ( isPixmap( widget ) ) | ||
1497 | p->drawTiledPixmap( x, y, x2 - x + 1, y2 - y + 1, | ||
1498 | *scalePixmap( x2 - x + 1, y2 - y + 1, widget ) ); | ||
1499 | else | ||
1500 | p->fillRect( x, y, x2 - x + 1, y2 - y + 1, cg->background() ); | ||
1501 | } | ||
1502 | else | ||
1503 | QCommonStyle::drawTab( p, tb, t, selected ); | ||
1504 | } | ||
1505 | |||
1506 | void OThemeStyle::drawTabMask( QPainter* p, const QTabBar* tb, QTab* t, | ||
1507 | bool selected ) | ||
1508 | { | ||
1509 | QRect r( t->r ); | ||
1510 | |||
1511 | if ( tb->shape() == QTabBar::RoundedAbove ) { | ||
1512 | if ( !selected ) | ||
1513 | r.setTop( r.top() + 2 ); | ||
1514 | p->drawLine( r.left() + 1, r.top(), r.right() - 1, r.top() ); | ||
1515 | QBrush b( color1, SolidPattern ); | ||
1516 | p->fillRect( r.left(), r.top() + 1, r.width(), r.height() - 1, b ); | ||
1517 | } | ||
1518 | else if ( tb->shape() == QTabBar::RoundedBelow ) { | ||
1519 | if ( !selected ) | ||
1520 | r.setBottom( r.bottom() - 2 ); | ||
1521 | p->drawLine( r.left() + 1, r.bottom(), r.right() - 1, r.bottom() ); | ||
1522 | QBrush b( color1, SolidPattern ); | ||
1523 | p->fillRect( r.left(), r.top(), r.width(), r.height() - 1, b ); | ||
1524 | } | ||
1525 | else | ||
1526 | QCommonStyle::drawTabMask( p, tb, t, selected ); | ||
1527 | |||
1528 | } | ||
1529 | |||
1530 | |||
1531 | //#include "kthemestyle.moc" | ||
1532 | |||
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 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org> | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Library General Public | ||
6 | License version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This library is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | Library General Public License for more details. | ||
12 | |||
13 | You should have received a copy of the GNU Library General Public License | ||
14 | along with this library; see the file COPYING.LIB. If not, write to | ||
15 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
16 | Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | #ifndef __KTHEMESTYLE_H | ||
19 | #define __KTHEMESTYLE_H | ||
20 | |||
21 | #include "othemebase.h" | ||
22 | #include <qwindowdefs.h> | ||
23 | #include <qobject.h> | ||
24 | #include <qbutton.h> | ||
25 | #include <qpushbutton.h> | ||
26 | #include <qscrollbar.h> | ||
27 | #include <qstring.h> | ||
28 | |||
29 | |||
30 | /** | ||
31 | * KDE themed styles. | ||
32 | * | ||
33 | * It provides methods for | ||
34 | * drawing most widgets with user-specified borders, highlights, pixmaps, | ||
35 | * etc. It also handles various other settings such as scrollbar types, | ||
36 | * rounded buttons, and shading types. For a full list of parameters this | ||
37 | * class handles refer to the KDE theme configuration documentation. | ||
38 | * | ||
39 | */ | ||
40 | |||
41 | class OThemeStyle: public OThemeBase | ||
42 | { | ||
43 | Q_OBJECT | ||
44 | public: | ||
45 | /** | ||
46 | * Construct a new @ref OThemeStyle object. | ||
47 | * | ||
48 | * @param configFile A KConfig file to use as the theme configuration. | ||
49 | * Defaults to ~/.kderc. | ||
50 | */ | ||
51 | OThemeStyle( const QString &configFile = QString::null ); | ||
52 | ~OThemeStyle(); | ||
53 | virtual void polish( QWidget* ); | ||
54 | virtual void unPolish( QWidget* ); | ||
55 | /** | ||
56 | * By default this just sets the background brushes to the pixmapped | ||
57 | * background. | ||
58 | */ | ||
59 | virtual void polish( QApplication *app ); | ||
60 | virtual void unPolish( QApplication* ); | ||
61 | |||
62 | /// @internal | ||
63 | // to make it possible for derived classes to overload this function | ||
64 | virtual void polish( QPalette& pal ); | ||
65 | |||
66 | /** | ||
67 | * This is a convenience method for drawing widgets with | ||
68 | * borders, highlights, pixmaps, colors, etc... | ||
69 | * You specify the widget type and it will draw it according to the | ||
70 | * config file settings. | ||
71 | * | ||
72 | * @param p The QPainter to draw on. | ||
73 | * @param g The color group to use. | ||
74 | * @param rounded @p true if the widget is rounded, @p false if rectangular. | ||
75 | * @param type The widget type to paint. | ||
76 | * @param fill An optional fill brush. Currently ignored (the config file | ||
77 | * is used instead). | ||
78 | */ | ||
79 | virtual void drawBaseButton( QPainter *p, int x, int y, int w, int h, | ||
80 | const QColorGroup &g, bool sunken = FALSE, | ||
81 | bool rounded = FALSE, WidgetType type = Bevel, | ||
82 | const QBrush *fill = 0 ); | ||
83 | /** | ||
84 | * Draw a mask with for widgets that may be rounded. | ||
85 | * | ||
86 | *Currently used | ||
87 | * by pushbuttons and comboboxes. | ||
88 | * | ||
89 | * @param p The QPainter to draw on. | ||
90 | * @param rounded @p true if the widget is rounded, @p false if rectangular. | ||
91 | */ | ||
92 | virtual void drawBaseMask( QPainter *p, int x, int y, int w, int h, | ||
93 | bool rounded ); | ||
94 | /** | ||
95 | * Draw a pushbutton. | ||
96 | * | ||
97 | * This calls @ref drawBaseButton() with @p PushButton as the | ||
98 | * widget type. | ||
99 | */ | ||
100 | virtual void drawButton( QPainter *p, int x, int y, int w, int h, | ||
101 | const QColorGroup &g, bool sunken = FALSE, | ||
102 | const QBrush *fill = 0 ); | ||
103 | /** | ||
104 | * Draw a bevel button. | ||
105 | * | ||
106 | * This calls @ref drawBaseButton() with Bevel as the | ||
107 | * widget type. | ||
108 | */ | ||
109 | virtual void drawBevelButton( QPainter *p, int x, int y, int w, int h, | ||
110 | const QColorGroup &g, bool sunken = FALSE, | ||
111 | const QBrush *fill = 0 ); | ||
112 | #if 0 | ||
113 | /** | ||
114 | * Draw a toolbar button. | ||
115 | */ | ||
116 | virtual void drawKToolBarButton( QPainter *p, int x, int y, int w, int h, | ||
117 | const QColorGroup &g, bool sunken = false, | ||
118 | bool raised = true, bool enabled = true, | ||
119 | bool popup = false, KToolButtonType type = Icon, | ||
120 | const QString &btext = QString::null, | ||
121 | const QPixmap *icon = NULL, | ||
122 | QFont *font = NULL, QWidget *btn = NULL ); | ||
123 | /** | ||
124 | * Draw the handle used in toolbars. | ||
125 | */ | ||
126 | void drawKBarHandle( QPainter *p, int x, int y, int w, int h, | ||
127 | const QColorGroup &g, | ||
128 | KToolBarPos type, QBrush *fill = NULL ); | ||
129 | |||
130 | /** | ||
131 | * Draw a toolbar. | ||
132 | */ | ||
133 | void drawKToolBar( QPainter *p, int x, int y, int w, int h, | ||
134 | const QColorGroup &g, KToolBarPos type, | ||
135 | QBrush *fill = NULL ); | ||
136 | #endif | ||
137 | /** | ||
138 | * Return the space available in a pushbutton, taking configurable | ||
139 | * borders and highlights into account. | ||
140 | */ | ||
141 | virtual QRect buttonRect( int x, int y, int w, int h ); | ||
142 | /** | ||
143 | * Draw an arrow in the style specified by the config file. | ||
144 | */ | ||
145 | virtual void drawArrow( QPainter *p, Qt::ArrowType type, bool down, | ||
146 | int x, int y, int w, int h, const QColorGroup &g, | ||
147 | bool enabled = true, const QBrush *fill = 0 ); | ||
148 | /** | ||
149 | * Return the size of the exclusive indicator pixmap if one is specified | ||
150 | * in the config file, otherwise it uses the base style's size. | ||
151 | */ | ||
152 | virtual QSize exclusiveIndicatorSize() const; | ||
153 | /** | ||
154 | * Draw an exclusive indicator widget. | ||
155 | * | ||
156 | * If a pixmap is specified in the | ||
157 | * config file that is used, otherwise the base style's widget is drawn. | ||
158 | */ | ||
159 | virtual void drawExclusiveIndicator( QPainter* p, int x, int y, int w, | ||
160 | int h, const QColorGroup &g, bool on, | ||
161 | bool down = FALSE, | ||
162 | bool enabled = TRUE ); | ||
163 | /** | ||
164 | * Set the mask of an exclusive indicator widget. | ||
165 | * | ||
166 | * If a pixmap is specified | ||
167 | * it is masked according to it's transparent pixels, otherwise the | ||
168 | * base style's mask is used. | ||
169 | */ | ||
170 | virtual void drawExclusiveIndicatorMask( QPainter *p, int x, int y, int w, | ||
171 | int h, bool on ); | ||
172 | /** | ||
173 | * Set the mask of an indicator widget. | ||
174 | * | ||
175 | * If a pixmap is specified | ||
176 | * it is masked according to it's transparent pixels, otherwise the | ||
177 | * base style's mask is used. | ||
178 | */ | ||
179 | virtual void drawIndicatorMask( QPainter *p, int x, int y, int w, int h, | ||
180 | int state ); | ||
181 | /** | ||
182 | * Set the mask for pushbuttons. | ||
183 | */ | ||
184 | virtual void drawButtonMask( QPainter *p, int x, int y, int w, int h ); | ||
185 | /** | ||
186 | * Set the mask for combo boxes. | ||
187 | */ | ||
188 | virtual void drawComboButtonMask( QPainter *p, int x, int y, int w, int h ); | ||
189 | /** | ||
190 | * Return the size of the indicator pixmap if one is specified | ||
191 | * in the config file, otherwise it uses the base style's size. | ||
192 | */ | ||
193 | virtual QSize indicatorSize() const; | ||
194 | /** | ||
195 | * Draw an indicator widget. | ||
196 | * | ||
197 | * If a pixmap is specified in the | ||
198 | * config file that is used, otherwise the base style's widget is drawn. | ||
199 | */ | ||
200 | virtual void drawIndicator( QPainter* p, int x, int y, int w, int h, | ||
201 | const QColorGroup &g, int state, | ||
202 | bool down = FALSE, bool enabled = TRUE ); | ||
203 | /** | ||
204 | * Draw a combobox. | ||
205 | */ | ||
206 | virtual void drawComboButton( QPainter *p, int x, int y, int w, int h, | ||
207 | const QColorGroup &g, bool sunken = FALSE, | ||
208 | bool editable = FALSE, bool enabled = TRUE, | ||
209 | const QBrush *fill = 0 ); | ||
210 | /** | ||
211 | * Draw a pushbutton. | ||
212 | */ | ||
213 | virtual void drawPushButton( QPushButton* btn, QPainter *p ); | ||
214 | /** | ||
215 | * Return the amount of button content displacement specified by the | ||
216 | * config file. | ||
217 | */ | ||
218 | virtual void getButtonShift( int &x, int &y ); | ||
219 | /** | ||
220 | * Return the frame width. | ||
221 | */ | ||
222 | virtual int defaultFrameWidth() const; | ||
223 | /** | ||
224 | * Calculate the metrics of the scrollbar controls according to the | ||
225 | * layout specified by the config file. | ||
226 | */ | ||
227 | virtual void scrollBarMetrics( const QScrollBar*, int&, int&, int&, int& ); | ||
228 | /** | ||
229 | * Draw a themed scrollbar. | ||
230 | */ | ||
231 | virtual void drawScrollBarControls( QPainter*, const QScrollBar*, | ||
232 | int sliderStart, uint controls, | ||
233 | uint activeControl ); | ||
234 | /** | ||
235 | * Return the control that the given point is over according to the | ||
236 | * layout in the config file. | ||
237 | */ | ||
238 | virtual ScrollControl scrollBarPointOver( const QScrollBar*, | ||
239 | int sliderStart, const QPoint& ); | ||
240 | /** | ||
241 | * Return the configurable default slider length. | ||
242 | */ | ||
243 | virtual int sliderLength() const; | ||
244 | /** | ||
245 | * Draw a slider control. | ||
246 | */ | ||
247 | virtual void drawSlider( QPainter *p, int x, int y, int w, int h, | ||
248 | const QColorGroup &g, Orientation, bool tickAbove, | ||
249 | bool tickBelow ); | ||
250 | /** | ||
251 | * Draw a slider groove. | ||
252 | */ | ||
253 | void drawSliderGroove( QPainter *p, int x, int y, int w, int h, | ||
254 | const QColorGroup& g, QCOORD c, | ||
255 | Orientation ); | ||
256 | /** | ||
257 | * Draw the mask for a slider (both the control and groove. | ||
258 | */ | ||
259 | virtual void drawSliderMask( QPainter *p, int x, int y, int w, int h, | ||
260 | Orientation, bool tickAbove, bool tickBelow ); | ||
261 | // void drawSliderGrooveMask(QPainter *p,int x, int y, int w, int h, | ||
262 | // QCOORD c, Orientation ); | ||
263 | /** | ||
264 | * Convience method for drawing themed scrollbar grooves. | ||
265 | * | ||
266 | * Since the | ||
267 | * grooves may be a scaled pixmap you cannot just bitblt the pixmap at | ||
268 | * any offset. This generates a cached pixmap at full size if needed and | ||
269 | * then copies the requested area. | ||
270 | * | ||
271 | * @param p The painter to draw on. | ||
272 | * @param sb The scrollbar (usually given by drawScrollBarControls). | ||
273 | * @param horizontal Is the scrollBar horizontal? | ||
274 | * @param r The rectangle to fill. | ||
275 | * @param g The color group to use. | ||
276 | */ | ||
277 | virtual void drawScrollBarGroove( QPainter *p, const QScrollBar *sb, | ||
278 | bool horizontal, QRect r, QColorGroup g ); | ||
279 | /** | ||
280 | * Draw a shaded rectangle using the given style. | ||
281 | * | ||
282 | * @param p The painter to draw on. | ||
283 | * @param g The color group to use. | ||
284 | * @param rounded Draws a rounded shape if true. Requires bWidth to be | ||
285 | * at least 1. | ||
286 | * @param hWidth The highlight width. | ||
287 | * @param bWidth The border width. | ||
288 | * @param style The shading style to use. | ||
289 | */ | ||
290 | virtual void drawShade( QPainter *p, int x, int y, int w, int h, | ||
291 | const QColorGroup &g, bool sunken, bool rounded, | ||
292 | int hWidth, int bWidth, ShadeStyle style ); | ||
293 | /** | ||
294 | * Draw the text for a pushbutton. | ||
295 | */ | ||
296 | virtual void drawPushButtonLabel( QPushButton *btn, QPainter *p ); | ||
297 | /** | ||
298 | * Draw a menubar. | ||
299 | */ | ||
300 | #if 0 | ||
301 | |||
302 | void drawKMenuBar( QPainter *p, int x, int y, int w, int h, | ||
303 | const QColorGroup &g, bool macMode, | ||
304 | QBrush *fill = NULL ); | ||
305 | #endif | ||
306 | /** | ||
307 | * Draw a menubar item. | ||
308 | */ | ||
309 | #if 0 | ||
310 | |||
311 | virtual void drawKMenuItem( QPainter *p, int x, int y, int w, int h, | ||
312 | const QColorGroup &g, bool active, | ||
313 | QMenuItem *item, QBrush *fill = NULL ); | ||
314 | #endif | ||
315 | /** | ||
316 | * Return the width of the splitter as specified in the config file. | ||
317 | */ | ||
318 | virtual int splitterWidth() const; | ||
319 | /** | ||
320 | * Draw a splitter widget. | ||
321 | */ | ||
322 | virtual void drawSplitter( QPainter *p, int x, int y, int w, int h, | ||
323 | const QColorGroup &g, Orientation ); | ||
324 | /** | ||
325 | * Draw a checkmark. | ||
326 | */ | ||
327 | virtual void drawCheckMark( QPainter *p, int x, int y, int w, int h, | ||
328 | const QColorGroup &g, bool act, bool dis ); | ||
329 | /** | ||
330 | * Draw a menu item. | ||
331 | * | ||
332 | * Note: This method manually handles applying | ||
333 | * inactive menu backgrounds to the entire widget. | ||
334 | */ | ||
335 | virtual void drawPopupMenuItem( QPainter *p, bool checkable, int maxpmw, | ||
336 | int tab, QMenuItem *mi, const QPalette &pal, | ||
337 | bool act, bool enabled, int x, int y, int w, | ||
338 | int h ); | ||
339 | int popupMenuItemHeight( bool checkable, QMenuItem *mi, | ||
340 | const QFontMetrics &fm ); | ||
341 | /** | ||
342 | * Draw the focus rectangle. | ||
343 | */ | ||
344 | void drawFocusRect( QPainter *p, const QRect &r, const QColorGroup &g, | ||
345 | const QColor *c = 0, bool atBorder = false ); | ||
346 | /** | ||
347 | * Draw a @ref KProgess bar. | ||
348 | */ | ||
349 | // virtual void drawKProgressBlock(QPainter *p, int x, int y, int w, int h, | ||
350 | // const QColorGroup &g, QBrush *fill); | ||
351 | /** | ||
352 | * Return the background for @ref KProgress. | ||
353 | */ | ||
354 | // virtual void getKProgressBackground(const QColorGroup &g, QBrush &bg); | ||
355 | virtual void tabbarMetrics( const QTabBar*, int&, int&, int& ); | ||
356 | virtual void drawTab( QPainter*, const QTabBar*, QTab*, bool selected ); | ||
357 | virtual void drawTabMask( QPainter*, const QTabBar*, QTab*, bool selected ); | ||
358 | protected: | ||
359 | QPalette oldPalette, popupPalette, indiPalette, exIndiPalette; | ||
360 | |||
361 | class OThemeStylePrivate; | ||
362 | OThemeStylePrivate *d; | ||
363 | }; | ||
364 | |||
365 | #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 @@ | |||
1 | //#include <klocale.h> | ||
2 | #include "othemestyle.h" | ||
3 | |||
4 | extern "C" | ||
5 | { | ||
6 | QStyle * allocate() { | ||
7 | return new OThemeStyle ( "" ); | ||
8 | } | ||
9 | int minor_version() { | ||
10 | return 0; | ||
11 | } | ||
12 | int major_version() { | ||
13 | return 1; | ||
14 | } | ||
15 | const char * description() { | ||
16 | return ( "Theme Style" ); | ||
17 | } | ||
18 | } | ||
19 | |||
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 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include "themeset.h" | ||
22 | |||
23 | #include <qpe/qpeapplication.h> | ||
24 | |||
25 | |||
26 | int main ( int argc, char** argv ) | ||
27 | { | ||
28 | QPEApplication a ( argc, argv ); | ||
29 | |||
30 | ThemeSet dlg; | ||
31 | a. showMainWidget ( &dlg ); | ||
32 | |||
33 | return a. exec ( ); | ||
34 | } | ||
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 @@ | |||
1 | TEMPLATE= app | ||
2 | CONFIG += qt warn_on release | ||
3 | DESTDIR = $(OPIEDIR)/bin | ||
4 | HEADERS = themeset.h | ||
5 | SOURCES = themeset.cpp main.cpp | ||
6 | INCLUDEPATH += $(OPIEDIR)/include | ||
7 | DEPENDPATH+= ../$(OPIEDIR)/include | ||
8 | LIBS += -lqpe | ||
9 | TARGET = theme-settings | ||
10 | |||
11 | TRANSLATIONS = ../../../../i18n/de/theme-settings.ts \ | ||
12 | ../../../../i18n/en/theme-settings.ts \ | ||
13 | ../../../../i18n/es/theme-settings.ts \ | ||
14 | ../../../../i18n/fr/theme-settings.ts \ | ||
15 | ../../../../i18n/hu/theme-settings.ts \ | ||
16 | ../../../../i18n/ja/theme-settings.ts \ | ||
17 | ../../../../i18n/ko/theme-settings.ts \ | ||
18 | ../../../../i18n/no/theme-settings.ts \ | ||
19 | ../../../../i18n/pl/theme-settings.ts \ | ||
20 | ../../../../i18n/pt/theme-settings.ts \ | ||
21 | ../../../../i18n/pt_BR/theme-settings.ts \ | ||
22 | ../../../../i18n/sl/theme-settings.ts \ | ||
23 | ../../../../i18n/zh_CN/theme-settings.ts \ | ||
24 | ../../../../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 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | |||
22 | |||
23 | #include "themeset.h" | ||
24 | |||
25 | #include <qpe/qpeapplication.h> | ||
26 | #include <qpe/global.h> | ||
27 | |||
28 | #include <qlabel.h> | ||
29 | #include <qlayout.h> | ||
30 | #include <qlistview.h> | ||
31 | #include <qdir.h> | ||
32 | |||
33 | #include <qpe/config.h> | ||
34 | |||
35 | |||
36 | class MyConfig : public Config | ||
37 | { | ||
38 | public: | ||
39 | MyConfig ( const QString &f, Domain d ) : Config ( f, d ) | ||
40 | { } | ||
41 | |||
42 | bool hasGroup ( const QString &gname ) const | ||
43 | { | ||
44 | QMap< QString, ConfigGroup>::ConstIterator it = groups. find ( gname ); | ||
45 | return ( it != groups.end() ); | ||
46 | } | ||
47 | }; | ||
48 | |||
49 | class MyItem : public QListViewItem | ||
50 | { | ||
51 | public: | ||
52 | MyItem ( QListView *lv, const QString &name, const QString &comm, const QString &theme ) : QListViewItem ( lv, name, comm ) | ||
53 | { | ||
54 | m_theme = theme; | ||
55 | } | ||
56 | |||
57 | |||
58 | QString m_theme; | ||
59 | }; | ||
60 | |||
61 | |||
62 | ThemeSet::ThemeSet ( QWidget* parent, const char *name, WFlags fl ) | ||
63 | : QDialog ( parent, name, fl ) | ||
64 | { | ||
65 | setCaption ( tr( "Theme Style" ) ); | ||
66 | |||
67 | Config config ( "qpe" ); | ||
68 | config. setGroup ( "Appearance" ); | ||
69 | |||
70 | QString active = config. readEntry ( "Theme", "default" ); | ||
71 | |||
72 | QVBoxLayout *vbox = new QVBoxLayout ( this ); | ||
73 | vbox-> setSpacing ( 3 ); | ||
74 | vbox-> setMargin ( 6 ); | ||
75 | |||
76 | vbox-> addWidget ( new QLabel ( tr( "Select the theme to be used" ), this )); | ||
77 | |||
78 | m_list = new QListView ( this ); | ||
79 | m_list-> addColumn ( tr( "Name" )); | ||
80 | m_list-> addColumn ( tr( "Description" )); | ||
81 | m_list-> setSelectionMode ( QListView::Single ); | ||
82 | m_list-> setAllColumnsShowFocus ( true ); | ||
83 | vbox-> addWidget ( m_list, 10 ); | ||
84 | |||
85 | QListViewItem *item = new MyItem ( m_list, tr( "[No theme]" ), "", "" ); | ||
86 | m_list-> setSelected ( item, true ); | ||
87 | |||
88 | QString path = QPEApplication::qpeDir() + "/plugins/styles/themes"; | ||
89 | QStringList list = QDir ( path, "*.themerc" ). entryList ( ); | ||
90 | |||
91 | for ( QStringList::Iterator it = list. begin(); it != list. end ( ); ++it ) { | ||
92 | MyConfig cfg ( path + "/" + *it, Config::File ); | ||
93 | |||
94 | if ( cfg. hasGroup ( "Misc" )) { | ||
95 | cfg. setGroup ( "Misc" ); | ||
96 | |||
97 | QString name = cfg. readEntry ( "Name" ); | ||
98 | QString comm = cfg. readEntry ( "Comment" ); | ||
99 | |||
100 | if ( !name. isEmpty ( )) { | ||
101 | QString fname = (*it). left ((*it). length ( ) - 8 ); | ||
102 | |||
103 | item = new MyItem ( m_list, name, comm, fname ); | ||
104 | if ( active == fname ) { | ||
105 | m_list-> setSelected ( item, true ); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | void ThemeSet::accept ( ) | ||
113 | { | ||
114 | Config config ( "qpe" ); | ||
115 | config. setGroup ( "Appearance" ); | ||
116 | |||
117 | MyItem *it = (MyItem *) m_list-> selectedItem ( ); | ||
118 | config. writeEntry ( "Theme", it ? it-> m_theme : QString ( "" )); | ||
119 | |||
120 | Global::applyStyle ( ); | ||
121 | |||
122 | QDialog::accept ( ); | ||
123 | } | ||
124 | |||
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 @@ | |||
1 | #ifndef __OPIE_THEME_SET_H__ | ||
2 | #define __OPIE_THEME_SET_H__ | ||
3 | |||
4 | #include <qdialog.h> | ||
5 | |||
6 | class QListView; | ||
7 | |||
8 | class ThemeSet : public QDialog { | ||
9 | Q_OBJECT | ||
10 | |||
11 | public: | ||
12 | ThemeSet ( QWidget *parent = 0, const char *name = 0, WFlags fl = 0 ); | ||
13 | |||
14 | protected: | ||
15 | virtual void accept ( ); | ||
16 | |||
17 | private: | ||
18 | QListView *m_list; | ||
19 | }; | ||
20 | #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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG = qt embedded debug warn_on | ||
3 | SOURCES = ogfxeffect.cpp \ | ||
4 | othemestyle.cpp \ | ||
5 | othemebase.cpp \ | ||
6 | plugin.cpp | ||
7 | |||
8 | HEADERS = ogfxeffect.h \ | ||
9 | othemebase.h \ | ||
10 | othemestyle.h | ||
11 | |||
12 | |||
13 | LIBS += -lqpe | ||
14 | INCLUDEPATH += $(OPIEDIR)/include | ||
15 | DESTDIR = $(OPIEDIR)/plugins/styles | ||
16 | TARGET = theme | ||
17 | VERSION = 1.0.0 | ||
18 | |||
19 | TRANSLATIONS = ../../../i18n/de/libtheme.ts \ | ||
20 | ../../../i18n/en/libtheme.ts \ | ||
21 | ../../../i18n/es/libtheme.ts \ | ||
22 | ../../../i18n/fr/libtheme.ts \ | ||
23 | ../../../i18n/hu/libtheme.ts \ | ||
24 | ../../../i18n/ja/libtheme.ts \ | ||
25 | ../../../i18n/ko/libtheme.ts \ | ||
26 | ../../../i18n/no/libtheme.ts \ | ||
27 | ../../../i18n/pl/libtheme.ts \ | ||
28 | ../../../i18n/pt/libtheme.ts \ | ||
29 | ../../../i18n/pt_BR/libtheme.ts \ | ||
30 | ../../../i18n/sl/libtheme.ts \ | ||
31 | ../../../i18n/zh_CN/libtheme.ts \ | ||
32 | ../../../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 | |||