source: trunk/demos/shared/arthurstyle.cpp@ 551

Last change on this file since 551 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 17.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the demonstration applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "arthurstyle.h"
43#include "arthurwidgets.h"
44#include <QLayout>
45#include <QPainter>
46#include <QPainterPath>
47#include <QPixmapCache>
48#include <QRadioButton>
49#include <QString>
50#include <QStyleOption>
51#include <QtDebug>
52
53QPixmap cached(const QString &img)
54{
55 if (QPixmap *p = QPixmapCache::find(img))
56 return *p;
57
58 QPixmap pm;
59 pm = QPixmap::fromImage(QImage(img), Qt::OrderedDither | Qt::OrderedAlphaDither);
60 if (pm.isNull())
61 return QPixmap();
62
63 QPixmapCache::insert(img, pm);
64 return pm;
65}
66
67
68ArthurStyle::ArthurStyle()
69 : QWindowsStyle()
70{
71 Q_INIT_RESOURCE(shared);
72}
73
74
75void ArthurStyle::drawHoverRect(QPainter *painter, const QRect &r) const
76{
77 qreal h = r.height();
78 qreal h2 = r.height() / qreal(2);
79 QPainterPath path;
80 path.addRect(r.x() + h2, r.y() + 0, r.width() - h2 * 2, r.height());
81 path.addEllipse(r.x(), r.y(), h, h);
82 path.addEllipse(r.x() + r.width() - h, r.y(), h, h);
83 path.setFillRule(Qt::WindingFill);
84 painter->setPen(Qt::NoPen);
85 painter->setBrush(QColor(191, 215, 191));
86 painter->setRenderHint(QPainter::Antialiasing);
87 painter->drawPath(path);
88}
89
90
91void ArthurStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
92 QPainter *painter, const QWidget *widget) const
93{
94
95 Q_ASSERT(option);
96 switch (element) {
97 case PE_FrameFocusRect:
98 break;
99
100 case PE_IndicatorRadioButton:
101 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
102 bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver);
103 painter->save();
104 QPixmap radio;
105 if (hover)
106 drawHoverRect(painter, widget->rect());
107
108 if (button->state & State_Sunken)
109 radio = cached(":res/images/radiobutton-on.png");
110 else if (button->state & State_On)
111 radio = cached(":res/images/radiobutton_on.png");
112 else
113 radio = cached(":res/images/radiobutton_off.png");
114 painter->drawPixmap(button->rect.topLeft(), radio);
115
116 painter->restore();
117 }
118 break;
119
120 case PE_PanelButtonCommand:
121 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
122 bool hover = (button->state & State_Enabled) && (button->state & State_MouseOver);
123
124 painter->save();
125 const QPushButton *pushButton = qobject_cast<const QPushButton *>(widget);
126 Q_ASSERT(pushButton);
127 QWidget *parent = pushButton->parentWidget();
128 if (parent && qobject_cast<QGroupBox *>(parent)) {
129 QLinearGradient lg(0, 0, 0, parent->height());
130 lg.setColorAt(0, QColor(224,224,224));
131 lg.setColorAt(1, QColor(255,255,255));
132 painter->setPen(Qt::NoPen);
133 painter->setBrush(lg);
134 painter->setBrushOrigin(-widget->mapToParent(QPoint(0,0)));
135 painter->drawRect(button->rect);
136 painter->setBrushOrigin(0,0);
137 }
138
139 bool down = (button->state & State_Sunken) || (button->state & State_On);
140
141 QPixmap left, right, mid;
142 if (down) {
143 left = cached(":res/images/button_pressed_cap_left.png");
144 right = cached(":res/images/button_pressed_cap_right.png");
145 mid = cached(":res/images/button_pressed_stretch.png");
146 } else {
147 left = cached(":res/images/button_normal_cap_left.png");
148 right = cached(":res/images/button_normal_cap_right.png");
149 mid = cached(":res/images/button_normal_stretch.png");
150 }
151 painter->drawPixmap(button->rect.topLeft(), left);
152 painter->drawTiledPixmap(QRect(button->rect.x() + left.width(),
153 button->rect.y(),
154 button->rect.width() - left.width() - right.width(),
155 left.height()),
156 mid);
157 painter->drawPixmap(button->rect.x() + button->rect.width() - right.width(),
158 button->rect.y(),
159 right);
160 if (hover)
161 painter->fillRect(widget->rect().adjusted(3,5,-3,-5), QColor(31,127,31,63));
162 painter->restore();
163 }
164 break;
165
166 case PE_FrameGroupBox:
167 if (const QStyleOptionFrameV2 *group
168 = qstyleoption_cast<const QStyleOptionFrameV2 *>(option)) {
169 const QRect &r = group->rect;
170
171 painter->save();
172 int radius = 14;
173 int radius2 = radius*2;
174 QPainterPath clipPath;
175 clipPath.moveTo(radius, 0);
176 clipPath.arcTo(r.right() - radius2, 0, radius2, radius2, 90, -90);
177 clipPath.arcTo(r.right() - radius2, r.bottom() - radius2, radius2, radius2, 0, -90);
178 clipPath.arcTo(r.left(), r.bottom() - radius2, radius2, radius2, 270, -90);
179 clipPath.arcTo(r.left(), r.top(), radius2, radius2, 180, -90);
180 painter->setClipPath(clipPath);
181 QPixmap titleStretch = cached(":res/images/title_stretch.png");
182 QPixmap topLeft = cached(":res/images/groupframe_topleft.png");
183 QPixmap topRight = cached(":res/images/groupframe_topright.png");
184 QPixmap bottomLeft = cached(":res/images/groupframe_bottom_left.png");
185 QPixmap bottomRight = cached(":res/images/groupframe_bottom_right.png");
186 QPixmap leftStretch = cached(":res/images/groupframe_left_stretch.png");
187 QPixmap topStretch = cached(":res/images/groupframe_top_stretch.png");
188 QPixmap rightStretch = cached(":res/images/groupframe_right_stretch.png");
189 QPixmap bottomStretch = cached(":res/images/groupframe_bottom_stretch.png");
190 QLinearGradient lg(0, 0, 0, r.height());
191 lg.setColorAt(0, QColor(224,224,224));
192 lg.setColorAt(1, QColor(255,255,255));
193 painter->setPen(Qt::NoPen);
194 painter->setBrush(lg);
195 painter->drawRect(r.adjusted(0, titleStretch.height()/2, 0, 0));
196 painter->setClipping(false);
197
198 int topFrameOffset = titleStretch.height()/2 - 2;
199 painter->drawPixmap(r.topLeft() + QPoint(0, topFrameOffset), topLeft);
200 painter->drawPixmap(r.topRight() - QPoint(topRight.width()-1, 0)
201 + QPoint(0, topFrameOffset), topRight);
202 painter->drawPixmap(r.bottomLeft() - QPoint(0, bottomLeft.height()-1), bottomLeft);
203 painter->drawPixmap(r.bottomRight() - QPoint(bottomRight.width()-1,
204 bottomRight.height()-1), bottomRight);
205
206 QRect left = r;
207 left.setY(r.y() + topLeft.height() + topFrameOffset);
208 left.setWidth(leftStretch.width());
209 left.setHeight(r.height() - topLeft.height() - bottomLeft.height() - topFrameOffset);
210 painter->drawTiledPixmap(left, leftStretch);
211
212 QRect top = r;
213 top.setX(r.x() + topLeft.width());
214 top.setY(r.y() + topFrameOffset);
215 top.setWidth(r.width() - topLeft.width() - topRight.width());
216 top.setHeight(topLeft.height());
217 painter->drawTiledPixmap(top, topStretch);
218
219 QRect right = r;
220 right.setX(r.right() - rightStretch.width()+1);
221 right.setY(r.y() + topRight.height() + topFrameOffset);
222 right.setWidth(rightStretch.width());
223 right.setHeight(r.height() - topRight.height()
224 - bottomRight.height() - topFrameOffset);
225 painter->drawTiledPixmap(right, rightStretch);
226
227 QRect bottom = r;
228 bottom.setX(r.x() + bottomLeft.width());
229 bottom.setY(r.bottom() - bottomStretch.height()+1);
230 bottom.setWidth(r.width() - bottomLeft.width() - bottomRight.width());
231 bottom.setHeight(bottomLeft.height());
232 painter->drawTiledPixmap(bottom, bottomStretch);
233 painter->restore();
234 }
235 break;
236
237 default:
238 QWindowsStyle::drawPrimitive(element, option, painter, widget);
239 break;
240 }
241 return;
242}
243
244
245void ArthurStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
246 QPainter *painter, const QWidget *widget) const
247{
248 switch (control) {
249 case CC_Slider:
250 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
251 QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
252 QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
253
254 painter->save();
255
256 bool hover = (slider->state & State_Enabled) && (slider->state & State_MouseOver);
257 if (hover) {
258 QRect moderated = widget->rect().adjusted(0, 4, 0, -4);
259 drawHoverRect(painter, moderated);
260 }
261
262 if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
263 QPixmap grv = cached(":res/images/slider_bar.png");
264 painter->drawPixmap(QRect(groove.x() + 5, groove.y(),
265 groove.width() - 10, grv.height()),
266 grv);
267 }
268 if ((option->subControls & SC_SliderHandle) && handle.isValid()) {
269 QPixmap hndl = cached(":res/images/slider_thumb_on.png");
270 painter->drawPixmap(handle.topLeft(), hndl);
271 }
272
273 painter->restore();
274 }
275 break;
276 case CC_GroupBox:
277 if (const QStyleOptionGroupBox *groupBox
278 = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
279 QStyleOptionGroupBox groupBoxCopy(*groupBox);
280 groupBoxCopy.subControls &= ~SC_GroupBoxLabel;
281 QWindowsStyle::drawComplexControl(control, &groupBoxCopy, painter, widget);
282
283 if (groupBox->subControls & SC_GroupBoxLabel) {
284 const QRect &r = groupBox->rect;
285 QPixmap titleLeft = cached(":res/images/title_cap_left.png");
286 QPixmap titleRight = cached(":res/images/title_cap_right.png");
287 QPixmap titleStretch = cached(":res/images/title_stretch.png");
288 int txt_width = groupBox->fontMetrics.width(groupBox->text) + 20;
289 painter->drawPixmap(r.center().x() - txt_width/2, 0, titleLeft);
290 QRect tileRect = subControlRect(control, groupBox, SC_GroupBoxLabel, widget);
291 painter->drawTiledPixmap(tileRect, titleStretch);
292 painter->drawPixmap(tileRect.x() + tileRect.width(), 0, titleRight);
293 int opacity = 31;
294 painter->setPen(QColor(0, 0, 0, opacity));
295 painter->drawText(tileRect.translated(0, 1),
296 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
297 painter->drawText(tileRect.translated(2, 1),
298 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
299 painter->setPen(QColor(0, 0, 0, opacity * 2));
300 painter->drawText(tileRect.translated(1, 1),
301 Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
302 painter->setPen(Qt::white);
303 painter->drawText(tileRect, Qt::AlignVCenter | Qt::AlignHCenter, groupBox->text);
304 }
305 }
306 break;
307 default:
308 QWindowsStyle::drawComplexControl(control, option, painter, widget);
309 break;
310 }
311 return;
312}
313
314QRect ArthurStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
315 SubControl subControl, const QWidget *widget) const
316{
317 QRect rect;
318
319 switch (control) {
320 default:
321 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
322 break;
323 case CC_GroupBox:
324 if (const QStyleOptionGroupBox *group
325 = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
326 switch (subControl) {
327 default:
328 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
329 break;
330 case SC_GroupBoxContents:
331 rect = QWindowsStyle::subControlRect(control, option, subControl, widget);
332 rect.adjust(0, -8, 0, 0);
333 break;
334 case SC_GroupBoxFrame:
335 rect = group->rect;
336 break;
337 case SC_GroupBoxLabel:
338 QPixmap titleLeft = cached(":res/images/title_cap_left.png");
339 QPixmap titleRight = cached(":res/images/title_cap_right.png");
340 QPixmap titleStretch = cached(":res/images/title_stretch.png");
341 int txt_width = group->fontMetrics.width(group->text) + 20;
342 rect = QRect(group->rect.center().x() - txt_width/2 + titleLeft.width(), 0,
343 txt_width - titleLeft.width() - titleRight.width(),
344 titleStretch.height());
345 break;
346 }
347 }
348 break;
349 }
350
351 if (control == CC_Slider && subControl == SC_SliderHandle) {
352 rect.setWidth(13);
353 rect.setHeight(27);
354 } else if (control == CC_Slider && subControl == SC_SliderGroove) {
355 rect.setHeight(9);
356 rect.moveTop(27/2 - 9/2);
357 }
358 return rect;
359}
360
361QSize ArthurStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
362 const QSize &size, const QWidget *widget) const
363{
364 QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget);
365
366
367 switch (type) {
368 case CT_RadioButton:
369 newSize += QSize(20, 0);
370 break;
371
372 case CT_PushButton:
373 newSize.setHeight(26);
374 break;
375
376 case CT_Slider:
377 newSize.setHeight(27);
378 break;
379
380 default:
381 break;
382 }
383
384 return newSize;
385}
386
387int ArthurStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const
388{
389 if (pm == PM_SliderLength)
390 return 13;
391 return QWindowsStyle::pixelMetric(pm, opt, widget);
392}
393
394void ArthurStyle::polish(QWidget *widget)
395{
396 if (widget->layout() && qobject_cast<QGroupBox *>(widget)) {
397 if (qFindChildren<QGroupBox *>(widget).size() == 0) {
398 widget->layout()->setSpacing(0);
399 widget->layout()->setMargin(12);
400 } else {
401 widget->layout()->setMargin(13);
402 }
403 }
404
405 if (qobject_cast<QPushButton *>(widget)
406 || qobject_cast<QRadioButton *>(widget)
407 || qobject_cast<QSlider *>(widget)) {
408 widget->setAttribute(Qt::WA_Hover);
409 }
410
411 QPalette pal = widget->palette();
412 if (widget->isWindow()) {
413 pal.setColor(QPalette::Background, QColor(241, 241, 241));
414 widget->setPalette(pal);
415 }
416
417}
418
419void ArthurStyle::unpolish(QWidget *widget)
420{
421 if (qobject_cast<QPushButton *>(widget)
422 || qobject_cast<QRadioButton *>(widget)
423 || qobject_cast<QSlider *>(widget)) {
424 widget->setAttribute(Qt::WA_Hover, false);
425 }
426}
427
428void ArthurStyle::polish(QPalette &palette)
429{
430 palette.setColor(QPalette::Background, QColor(241, 241, 241));
431}
432
433QRect ArthurStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
434{
435 QRect r;
436 switch(element) {
437 case SE_RadioButtonClickRect:
438 r = widget->rect();
439 break;
440 case SE_RadioButtonContents:
441 r = widget->rect().adjusted(20, 0, 0, 0);
442 break;
443 default:
444 r = QWindowsStyle::subElementRect(element, option, widget);
445 break;
446 }
447
448 if (qobject_cast<const QRadioButton*>(widget))
449 r = r.adjusted(5, 0, -5, 0);
450
451 return r;
452}
Note: See TracBrowser for help on using the repository browser.