source: trunk/src/gui/styles/qs60style.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 156.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qs60style_p.h"
43
44#include "qapplication.h"
45#include "qpainter.h"
46#include "qstyleoption.h"
47#include "qevent.h"
48#include "qpixmapcache.h"
49
50#include "qcalendarwidget.h"
51#include "qdial.h"
52#include "qdialog.h"
53#include "qmessagebox.h"
54#include "qgroupbox.h"
55#include "qheaderview.h"
56#include "qlist.h"
57#include "qlistwidget.h"
58#include "qlistview.h"
59#include "qmenu.h"
60#include "qmenubar.h"
61#include "qpushbutton.h"
62#include "qscrollarea.h"
63#include "qscrollbar.h"
64#include "qtabbar.h"
65#include "qtableview.h"
66#include "qtextedit.h"
67#include "qtoolbar.h"
68#include "qtoolbutton.h"
69#include "qfocusframe.h"
70#include "qformlayout.h"
71#include "qradiobutton.h"
72#include "qcheckbox.h"
73#include "qdesktopwidget.h"
74#include "qprogressbar.h"
75
76#include "private/qtoolbarextension_p.h"
77#include "private/qcombobox_p.h"
78#include "private/qwidget_p.h"
79#include "private/qapplication_p.h"
80
81#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
82
83QT_BEGIN_NAMESPACE
84
85// from text/qfont.cpp
86extern Q_GUI_EXPORT int qt_defaultDpiY();
87
88const QS60StylePrivate::SkinElementFlags QS60StylePrivate::KDefaultSkinElementFlags =
89 SkinElementFlags(SF_PointNorth | SF_StateEnabled);
90
91static const qreal goldenRatio = 1.618;
92
93const layoutHeader QS60StylePrivate::m_layoutHeaders[] = {
94// *** generated layout data ***
95{240,320,1,19,"QVGA Landscape"},
96{320,240,1,19,"QVGA Portrait"},
97{360,640,1,19,"NHD Landscape"},
98{640,360,1,19,"NHD Portrait"},
99{352,800,1,12,"E90 Landscape"}
100// *** End of generated data ***
101};
102const int QS60StylePrivate::m_numberOfLayouts =
103 (int)sizeof(QS60StylePrivate::m_layoutHeaders)/sizeof(QS60StylePrivate::m_layoutHeaders[0]);
104
105const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = {
106// *** generated pixel metrics ***
107{5,0,-909,0,0,2,0,0,-1,7,12,22,15,15,7,198,-909,-909,-909,20,13,2,0,0,21,7,18,30,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1,106},
108{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,28,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1,106},
109{7,0,-909,0,0,2,0,0,-1,25,69,46,37,37,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,44,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135},
110{7,0,-909,0,0,2,0,0,-1,25,68,46,37,37,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,52,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135},
111{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,30,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1,106}
112// *** End of generated data ***
113};
114
115const short *QS60StylePrivate::m_pmPointer = QS60StylePrivate::data[0];
116
117// theme background texture
118QPixmap *QS60StylePrivate::m_background = 0;
119
120// theme palette
121QPalette *QS60StylePrivate::m_themePalette = 0;
122
123qint64 QS60StylePrivate::m_webPaletteKey = 0;
124
125QPointer<QWidget> QS60StylePrivate::m_pressedWidget = 0;
126
127const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = {
128 {SE_ButtonNormal, QS60StyleEnums::SP_QsnFrButtonTbCenter},
129 {SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
130 {SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter},
131 {SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter},
132 {SE_PopupBackground, QS60StyleEnums::SP_QsnFrPopupCenter},
133 {SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter},
134 {SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter},
135 {SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
136 {SE_ToolTip, QS60StyleEnums::SP_QsnFrPopupPreviewCenter},
137 {SE_ToolBar, QS60StyleEnums::SP_QsnFrPopupSubCenter},
138 {SE_ToolBarButton, QS60StyleEnums::SP_QsnFrSctrlButtonCenter},
139 {SE_ToolBarButtonPressed, QS60StyleEnums::SP_QsnFrSctrlButtonCenterPressed},
140 {SE_PanelBackground, QS60StyleEnums::SP_QsnFrSetOptCenter},
141 {SE_ButtonInactive, QS60StyleEnums::SP_QsnFrButtonCenterInactive},
142 {SE_Editor, QS60StyleEnums::SP_QsnFrInputCenter},
143 {SE_TableItemPressed, QS60StyleEnums::SP_QsnFrGridCenterPressed},
144 {SE_ListItemPressed, QS60StyleEnums::SP_QsnFrListPressed},
145};
146
147static const int frameElementsCount =
148 int(sizeof(QS60StylePrivate::m_frameElementsData)/sizeof(QS60StylePrivate::m_frameElementsData[0]));
149
150const int KNotFound = -909;
151const double KTabFontMul = 0.72;
152
153QS60StylePrivate::~QS60StylePrivate()
154{
155 clearCaches(); //deletes also background image
156 deleteThemePalette();
157}
158
159void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
160 const QRect &rect, SkinElementFlags flags)
161{
162 switch (element) {
163 case SE_ButtonNormal:
164 drawFrame(SF_ButtonNormal, painter, rect, flags | SF_PointNorth);
165 break;
166 case SE_ButtonPressed:
167 drawFrame(SF_ButtonPressed, painter, rect, flags | SF_PointNorth);
168 break;
169 case SE_FrameLineEdit:
170 drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth);
171 break;
172 case SE_ProgressBarGrooveHorizontal:
173 drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
174 QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
175 break;
176 case SE_ProgressBarGrooveVertical:
177 drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
178 QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Vertical, painter, rect, flags | SF_PointEast);
179 break;
180 case SE_ProgressBarIndicatorHorizontal:
181 drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointNorth);
182 break;
183 case SE_ProgressBarIndicatorVertical:
184 drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointWest);
185 break;
186 case SE_ScrollBarGrooveHorizontal:
187 drawRow(QS60StyleEnums::SP_QsnCpScrollBgBottom, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
188 QS60StyleEnums::SP_QsnCpScrollBgTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
189 break;
190 case SE_ScrollBarGrooveVertical:
191 drawRow(QS60StyleEnums::SP_QsnCpScrollBgTop, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
192 QS60StyleEnums::SP_QsnCpScrollBgBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
193 break;
194 case SE_ScrollBarHandleHorizontal:
195 drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottom, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
196 QS60StyleEnums::SP_QsnCpScrollHandleTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
197 break;
198 case SE_ScrollBarHandleVertical:
199 drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTop, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
200 QS60StyleEnums::SP_QsnCpScrollHandleBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
201 break;
202 case SE_SliderHandleHorizontal:
203 drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarker, painter, rect, flags | SF_PointNorth);
204 break;
205 case SE_SliderHandleVertical:
206 drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarker, painter, rect, flags | SF_PointEast);
207 break;
208 case SE_SliderHandleSelectedHorizontal:
209 drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected, painter, rect, flags | SF_PointNorth);
210 break;
211 case SE_SliderHandleSelectedVertical:
212 drawPart(QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected, painter, rect, flags | SF_PointEast);
213 break;
214 case SE_SliderGrooveVertical:
215 drawRow(QS60StyleEnums::SP_QgnGrafNsliderEndLeft, QS60StyleEnums::SP_QgnGrafNsliderMiddle,
216 QS60StyleEnums::SP_QgnGrafNsliderEndRight, Qt::Vertical, painter, rect, flags | SF_PointEast);
217 break;
218 case SE_SliderGrooveHorizontal:
219 drawRow(QS60StyleEnums::SP_QgnGrafNsliderEndLeft, QS60StyleEnums::SP_QgnGrafNsliderMiddle,
220 QS60StyleEnums::SP_QgnGrafNsliderEndRight, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
221 break;
222 case SE_TabBarTabEastActive:
223 drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
224 QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
225 break;
226 case SE_TabBarTabEastInactive:
227 drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
228 QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
229 break;
230 case SE_TabBarTabNorthActive:
231 drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
232 QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
233 break;
234 case SE_TabBarTabNorthInactive:
235 drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
236 QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
237 break;
238 case SE_TabBarTabSouthActive:
239 drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
240 QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
241 break;
242 case SE_TabBarTabSouthInactive:
243 drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
244 QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
245 break;
246 case SE_TabBarTabWestActive:
247 drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
248 QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
249 break;
250 case SE_TabBarTabWestInactive:
251 drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
252 QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
253 break;
254 case SE_ListHighlight:
255 drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth);
256 break;
257 case SE_PopupBackground:
258 drawFrame(SF_PopupBackground, painter, rect, flags | SF_PointNorth);
259 break;
260 case SE_SettingsList:
261 drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth);
262 break;
263 case SE_TableItem:
264 drawFrame(SF_TableItem, painter, rect, flags | SF_PointNorth);
265 break;
266 case SE_TableHeaderItem:
267 drawFrame(SF_TableHeaderItem, painter, rect, flags | SF_PointNorth);
268 break;
269 case SE_ToolTip:
270 drawFrame(SF_ToolTip, painter, rect, flags | SF_PointNorth);
271 break;
272 case SE_ToolBar:
273 drawFrame(SF_ToolBar, painter, rect, flags | SF_PointNorth);
274 break;
275 case SE_ToolBarButton:
276 drawFrame(SF_ToolBarButton, painter, rect, flags | SF_PointNorth);
277 break;
278 case SE_ToolBarButtonPressed:
279 drawFrame(SF_ToolBarButtonPressed, painter, rect, flags | SF_PointNorth);
280 break;
281 case SE_PanelBackground:
282 drawFrame(SF_PanelBackground, painter, rect, flags | SF_PointNorth);
283 break;
284 case SE_ScrollBarHandlePressedHorizontal:
285 drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
286 QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, Qt::Horizontal, painter, rect, flags | SF_PointEast);
287 break;
288 case SE_ScrollBarHandlePressedVertical:
289 drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
290 QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, Qt::Vertical, painter, rect, flags | SF_PointNorth);
291 break;
292 case SE_ButtonInactive:
293 drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth);
294 break;
295 case SE_Editor:
296 drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth);
297 break;
298 case SE_DropArea:
299 drawPart(QS60StyleEnums::SP_QgnGrafOrgBgGrid, painter, rect, flags | SF_PointNorth);
300 break;
301 case SE_TableItemPressed:
302 drawFrame(SF_TableItemPressed, painter, rect, flags | SF_PointNorth);
303 break;
304 case SE_ListItemPressed:
305 drawFrame(SF_ListItemPressed, painter, rect, flags | SF_PointNorth);
306 break;
307 default:
308 break;
309 }
310}
311
312void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part,
313 QPainter *painter, const QRect &rect, SkinElementFlags flags)
314{
315 drawPart(part, painter, rect, flags);
316}
317
318short QS60StylePrivate::pixelMetric(int metric)
319{
320 //If it is a custom value, need to strip away the base to map to internal
321 //pixel metric value table
322 if (metric & QStyle::PM_CustomBase) {
323 metric -= QStyle::PM_CustomBase;
324 metric += MAX_NON_CUSTOM_PIXELMETRICS - 1;
325 }
326
327 Q_ASSERT(metric < MAX_PIXELMETRICS);
328 const short returnValue = m_pmPointer[metric];
329 return returnValue;
330}
331
332QColor QS60StylePrivate::stateColor(const QColor &color, const QStyleOption *option)
333{
334 QColor retColor (color);
335 if (option && !(option->state & QStyle::State_Enabled)) {
336 QColor hsvColor = retColor.toHsv();
337 int colorSat = hsvColor.saturation();
338 int colorVal = hsvColor.value();
339 colorSat = (colorSat != 0) ? (colorSat >> 1) : 128;
340 colorVal = (colorVal != 0) ? (colorVal >> 1) : 128;
341 hsvColor.setHsv(hsvColor.hue(), colorSat, colorVal);
342 retColor = hsvColor.toRgb();
343 }
344 return retColor;
345}
346
347QColor QS60StylePrivate::lighterColor(const QColor &baseColor)
348{
349 QColor result(baseColor);
350 bool modifyColor = false;
351 if (result.saturation() == 0) {
352 result.setHsv(result.hue(), 128, result.value());
353 modifyColor = true;
354 }
355 if (result.value() == 0) {
356 result.setHsv(result.hue(), result.saturation(), 128);
357 modifyColor = true;
358 }
359 if (modifyColor)
360 result = result.lighter(175);
361 else
362 result = result.lighter(225);
363 return result;
364}
365
366bool QS60StylePrivate::drawsOwnThemeBackground(const QWidget *widget)
367{
368 return (widget ? (widget->windowType() == Qt::Dialog) : false);
369}
370
371QFont QS60StylePrivate::s60Font(
372 QS60StyleEnums::FontCategories fontCategory,
373 int pointSize, bool resolveFontSize) const
374{
375 QFont result;
376 int actualPointSize = pointSize;
377 if (actualPointSize <= 0) {
378 const QFont appFont = QApplication::font();
379 actualPointSize = appFont.pointSize();
380 if (actualPointSize <= 0)
381 actualPointSize = appFont.pixelSize() * 72 / qt_defaultDpiY();
382 }
383 Q_ASSERT(actualPointSize > 0);
384 const QPair<QS60StyleEnums::FontCategories, int> key(fontCategory, actualPointSize);
385 if (!m_mappedFontsCache.contains(key)) {
386 result = s60Font_specific(fontCategory, actualPointSize, resolveFontSize);
387 m_mappedFontsCache.insert(key, result);
388 } else {
389 result = m_mappedFontsCache.value(key);
390 if (result.pointSize() != actualPointSize)
391 result.setPointSize(actualPointSize);
392 }
393 return result;
394}
395
396void QS60StylePrivate::clearCaches(CacheClearReason reason)
397{
398 switch(reason){
399 case CC_LayoutChange:
400 // when layout changes, the colors remain in cache, but graphics and fonts can change
401 m_mappedFontsCache.clear();
402 QPixmapCache::clear();
403 break;
404 case CC_ThemeChange:
405 m_colorCache.clear();
406 QPixmapCache::clear();
407 deleteBackground();
408 break;
409 case CC_UndefinedChange:
410 default:
411 m_colorCache.clear();
412 m_mappedFontsCache.clear();
413 QPixmapCache::clear();
414 deleteBackground();
415 break;
416 }
417}
418
419// Since S60Style has 'button' and 'tooltip' as a graphic, we don't have any native color which to use
420// for QPalette::Button and QPalette::ToolTipBase. Therefore S60Style needs to guesstimate
421// palette colors by calculating average rgb values for button pixels.
422// Returns Qt::black if there is an issue with the graphics (image is NULL, or no bits() found).
423QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const
424{
425 const bool cachedColorExists = m_colorCache.contains(frame);
426 if (!cachedColorExists) {
427 const int frameCornerWidth = pixelMetric(PM_FrameCornerWidth);
428 const int frameCornerHeight = pixelMetric(PM_FrameCornerHeight);
429 Q_ASSERT(2 * frameCornerWidth < 32);
430 Q_ASSERT(2 * frameCornerHeight < 32);
431
432 const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32, 32)).toImage();
433 Q_ASSERT(frameImage.bytesPerLine() > 0);
434 if (frameImage.isNull())
435 return Qt::black;
436
437 const QRgb *pixelRgb = (const QRgb*)frameImage.bits();
438 const int pixels = frameImage.byteCount()/sizeof(QRgb);
439
440 int estimatedRed = 0;
441 int estimatedGreen = 0;
442 int estimatedBlue = 0;
443
444 int skips = 0;
445 int estimations = 0;
446
447 const int topBorderLastPixel = frameCornerHeight*frameImage.width() - 1;
448 const int bottomBorderFirstPixel = frameImage.width() * frameImage.height() - frameCornerHeight*frameImage.width() - 1;
449 const int rightBorderFirstPixel = frameImage.width() - frameCornerWidth;
450 const int leftBorderLastPixel = frameCornerWidth;
451
452 while ((skips + estimations) < pixels) {
453 if ((skips + estimations) > topBorderLastPixel &&
454 (skips + estimations) < bottomBorderFirstPixel) {
455 for (int rowIndex = 0; rowIndex < frameImage.width(); rowIndex++) {
456 if (rowIndex > leftBorderLastPixel &&
457 rowIndex < rightBorderFirstPixel) {
458 estimatedRed += qRed(*pixelRgb);
459 estimatedGreen += qGreen(*pixelRgb);
460 estimatedBlue += qBlue(*pixelRgb);
461 }
462 pixelRgb++;
463 estimations++;
464 }
465 } else {
466 pixelRgb++;
467 skips++;
468 }
469 }
470 QColor frameColor(estimatedRed/estimations, estimatedGreen/estimations, estimatedBlue/estimations);
471 m_colorCache.insert(frame, frameColor);
472 return !estimations ? Qt::black : frameColor;
473 } else {
474 return m_colorCache.value(frame);
475 }
476
477}
478
479void QS60StylePrivate::setThemePalette(QApplication *app) const
480{
481 Q_UNUSED(app)
482 QPalette widgetPalette = QPalette(Qt::white);
483 setThemePalette(&widgetPalette);
484}
485
486QPalette* QS60StylePrivate::themePalette()
487{
488 return m_themePalette;
489}
490
491void QS60StylePrivate::setBackgroundTexture(QApplication *app) const
492{
493 Q_UNUSED(app)
494 QPalette applicationPalette = QApplication::palette();
495 applicationPalette.setBrush(QPalette::Window, backgroundTexture());
496 setThemePalette(&applicationPalette);
497}
498
499void QS60StylePrivate::deleteBackground()
500{
501 if (m_background) {
502 delete m_background;
503 m_background = 0;
504 }
505}
506
507void QS60StylePrivate::setCurrentLayout(int index)
508{
509 m_pmPointer = data[index];
510}
511
512void QS60StylePrivate::drawPart(QS60StyleEnums::SkinParts skinPart,
513 QPainter *painter, const QRect &rect, SkinElementFlags flags)
514{
515 static const bool doCache =
516#if defined(Q_WS_S60)
517 // Freezes on 3.1. Anyways, caching is only really needed on touch UI
518 !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
519#else
520 true;
521#endif
522
523 const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), painter, flags));
524 if (!skinPartPixMap.isNull())
525 painter->drawPixmap(rect.topLeft(), skinPartPixMap);
526}
527
528void QS60StylePrivate::drawFrame(SkinFrameElements frameElement, QPainter *painter, const QRect &rect, SkinElementFlags flags)
529{
530 static const bool doCache =
531#if defined(Q_WS_S60)
532 // Freezes on 3.1. Anyways, caching is only really needed on touch UI
533 !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
534#else
535 true;
536#endif
537 const QPixmap frameElementPixMap((doCache ? cachedFrame : frame)(frameElement, rect.size(), flags));
538 if (!frameElementPixMap.isNull())
539 painter->drawPixmap(rect.topLeft(), frameElementPixMap);
540}
541
542void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start,
543 QS60StyleEnums::SkinParts middle, QS60StyleEnums::SkinParts end,
544 Qt::Orientation orientation, QPainter *painter, const QRect &rect,
545 SkinElementFlags flags)
546{
547 QSize startEndSize(partSize(start, flags));
548 startEndSize.scale(rect.size(), Qt::KeepAspectRatio);
549
550 QRect startRect = QRect(rect.topLeft(), startEndSize);
551 QRect middleRect = rect;
552 QRect endRect;
553
554 if (orientation == Qt::Horizontal) {
555 startRect.setHeight(rect.height());
556 startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width()));
557 endRect = startRect.translated(rect.width() - startRect.width(), 0);
558 middleRect.adjust(startRect.width(), 0, -startRect.width(), 0);
559 if (startRect.bottomRight().x() > endRect.topLeft().x()) {
560 const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x()) >> 1;
561 startRect.setWidth(startRect.width() - overlap);
562 endRect.adjust(overlap, 0, 0, 0);
563 }
564 } else {
565 startRect.setWidth(rect.width());
566 startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height()));
567 endRect = startRect.translated(0, rect.height() - startRect.height());
568 middleRect.adjust(0, startRect.height(), 0, -startRect.height());
569 if (startRect.topRight().y() > endRect.bottomLeft().y()) {
570 const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y()) >> 1;
571 startRect.setHeight(startRect.height() - overlap);
572 endRect.adjust(0, overlap, 0, 0);
573 }
574 }
575
576#if 0
577 painter->save();
578 painter->setOpacity(.3);
579 painter->fillRect(startRect, Qt::red);
580 painter->fillRect(middleRect, Qt::green);
581 painter->fillRect(endRect, Qt::blue);
582 painter->restore();
583#else
584 drawPart(start, painter, startRect, flags);
585 if (middleRect.isValid())
586 drawPart(middle, painter, middleRect, flags);
587 drawPart(end, painter, endRect, flags);
588#endif
589}
590
591QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part,
592 const QSize &size, QPainter *painter, SkinElementFlags flags)
593{
594 QPixmap result;
595 const int animationFrame = (flags & SF_Animation) ? currentAnimationFrame(part) : 0;
596
597 const QString cacheKey =
598 QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4 AnimationFrame=%5")
599 .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags).arg(animationFrame);
600 if (!QPixmapCache::find(cacheKey, result)) {
601 result = QS60StylePrivate::part(part, size, painter, flags);
602 QPixmapCache::insert(cacheKey, result);
603 }
604 return result;
605}
606
607QPixmap QS60StylePrivate::cachedFrame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
608{
609 QPixmap result;
610 const QString cacheKey =
611 QString::fromLatin1("S60Style: SkinFrameElements=%1 QSize=%2|%3 SkinElementFlags=%4")
612 .arg((int)frame).arg(size.width()).arg(size.height()).arg((int)flags);
613 if (!QPixmapCache::find(cacheKey, result)) {
614 result = QS60StylePrivate::frame(frame, size, flags);
615 QPixmapCache::insert(cacheKey, result);
616 }
617 return result;
618}
619
620void QS60StylePrivate::refreshUI()
621{
622 QList<QWidget *> widgets = QApplication::allWidgets();
623
624 for (int i = 0; i < widgets.size(); ++i) {
625 QWidget *widget = widgets.at(i);
626 if (widget == 0)
627 continue;
628
629 if (widget->style()) {
630 widget->style()->polish(widget);
631 QEvent event(QEvent::StyleChange);
632 qApp->sendEvent(widget, &event);
633 }
634 widget->update();
635 widget->updateGeometry();
636 }
637}
638
639void QS60StylePrivate::setFont(QWidget *widget) const
640{
641 QS60StyleEnums::FontCategories fontCategory = QS60StyleEnums::FC_Undefined;
642 if (!widget)
643 return;
644 if (qobject_cast<QPushButton *>(widget)){
645 fontCategory = QS60StyleEnums::FC_Primary;
646 } else if (qobject_cast<QToolButton *>(widget)){
647 fontCategory = QS60StyleEnums::FC_Primary;
648 } else if (qobject_cast<QHeaderView *>(widget)){
649 fontCategory = QS60StyleEnums::FC_Secondary;
650 } else if (qobject_cast<QGroupBox *>(widget)){
651 fontCategory = QS60StyleEnums::FC_Title;
652 } else if (qobject_cast<QMessageBox *>(widget)){
653 fontCategory = QS60StyleEnums::FC_Primary;
654 } else if (qobject_cast<QMenu *>(widget)){
655 fontCategory = QS60StyleEnums::FC_Primary;
656 } else if (qobject_cast<QCalendarWidget *>(widget)){
657 fontCategory = QS60StyleEnums::FC_Secondary;
658 }
659 if (fontCategory != QS60StyleEnums::FC_Undefined) {
660 const bool resolveFontSize = widget->testAttribute(Qt::WA_SetFont)
661 && (widget->font().resolve() & QFont::SizeResolved);
662 const QFont suggestedFont =
663 s60Font(fontCategory, widget->font().pointSizeF(), resolveFontSize);
664 widget->setFont(suggestedFont);
665 }
666}
667
668void QS60StylePrivate::setThemePalette(QWidget *widget) const
669{
670 if(!widget)
671 return;
672
673 //header view and its viewport need to be set 100% transparent button color, since drawing code will
674 //draw transparent theme graphics to table column and row headers.
675 if (qobject_cast<QHeaderView *>(widget)){
676 QPalette widgetPalette = QApplication::palette(widget);
677 widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
678 s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
679 QHeaderView* header = qobject_cast<QHeaderView *>(widget);
680 widgetPalette.setColor(QPalette::Button, Qt::transparent );
681 if (header->viewport())
682 header->viewport()->setPalette(widgetPalette);
683 QApplication::setPalette(widgetPalette, "QHeaderView");
684 }
685}
686
687void QS60StylePrivate::setThemePalette(QPalette *palette) const
688{
689 if (!palette)
690 return;
691
692 // basic colors
693 palette->setColor(QPalette::WindowText,
694 s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
695 palette->setColor(QPalette::ButtonText,
696 s60Color(QS60StyleEnums::CL_QsnTextColors, 20, 0));
697 palette->setColor(QPalette::Text,
698 s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
699 palette->setColor(QPalette::ToolTipText,
700 s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0));
701 palette->setColor(QPalette::BrightText, palette->color(QPalette::WindowText).lighter());
702 palette->setColor(QPalette::HighlightedText,
703 s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
704 palette->setColor(QPalette::Link,
705 s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0));
706 palette->setColor(QPalette::LinkVisited, palette->color(QPalette::Link).darker());
707 palette->setColor(QPalette::Highlight,
708 s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0));
709 // set background image as a texture brush
710 palette->setBrush(QPalette::Window, backgroundTexture());
711 // set as transparent so that styled full screen theme background is visible
712 palette->setBrush(QPalette::Base, Qt::transparent);
713 // set button and tooltipbase based on pixel colors
714 const QColor buttonColor = colorFromFrameGraphics(SF_ButtonNormal);
715 palette->setColor(QPalette::Button, buttonColor);
716 const QColor toolTipColor = colorFromFrameGraphics(SF_ToolTip);
717 palette->setColor(QPalette::ToolTipBase, toolTipColor);
718 palette->setColor(QPalette::Light, palette->color(QPalette::Button).lighter());
719 palette->setColor(QPalette::Dark, palette->color(QPalette::Button).darker());
720 palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125));
721 palette->setColor(QPalette::Mid, palette->color(QPalette::Button).darker(150));
722 palette->setColor(QPalette::Shadow, Qt::black);
723 QColor alternateBase = palette->light().color();
724 alternateBase.setAlphaF(0.8);
725 palette->setColor(QPalette::AlternateBase, alternateBase);
726
727 QApplication::setPalette(*palette); //calling QApplication::setPalette clears palette hash
728 setThemePaletteHash(palette);
729 storeThemePalette(palette);
730}
731
732void QS60StylePrivate::deleteThemePalette()
733{
734 if (m_themePalette) {
735 delete m_themePalette;
736 m_themePalette = 0;
737 }
738}
739
740void QS60StylePrivate::storeThemePalette(QPalette *palette)
741{
742 deleteThemePalette();
743 //store specified palette for latter use.
744 m_themePalette = new QPalette(*palette);
745}
746
747// set widget specific palettes
748void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const
749{
750 if (!palette)
751 return;
752
753 //store the original palette
754 QPalette widgetPalette = *palette;
755 const QColor mainAreaTextColor =
756 s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0);
757
758 widgetPalette.setColor(QPalette::WindowText,
759 s60Color(QS60StyleEnums::CL_QsnLineColors, 8, 0));
760 QApplication::setPalette(widgetPalette, "QSlider");
761 // return to original palette after each widget
762 widgetPalette = *palette;
763
764 widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
765 widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
766 const QStyleOption opt;
767 widgetPalette.setColor(QPalette::Disabled, QPalette::ButtonText,
768 s60Color(QS60StyleEnums::CL_QsnTextColors, 6, &opt));
769 QApplication::setPalette(widgetPalette, "QPushButton");
770 widgetPalette = *palette;
771
772 widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
773 widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
774 QApplication::setPalette(widgetPalette, "QToolButton");
775 widgetPalette = *palette;
776
777 widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
778 s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
779 QApplication::setPalette(widgetPalette, "QHeaderView");
780 widgetPalette = *palette;
781
782 widgetPalette.setColor(QPalette::ButtonText,
783 s60Color(QS60StyleEnums::CL_QsnTextColors, 8, 0));
784 QApplication::setPalette(widgetPalette, "QMenuBar");
785 widgetPalette = *palette;
786
787 widgetPalette.setColor(QPalette::Text,
788 s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
789 widgetPalette.setColor(QPalette::HighlightedText,
790 s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
791 QApplication::setPalette(widgetPalette, "QMenu");
792 widgetPalette = *palette;
793
794 widgetPalette.setColor(QPalette::WindowText,
795 s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0));
796 widgetPalette.setColor(QPalette::HighlightedText,
797 s60Color(QS60StyleEnums::CL_QsnTextColors, 3, 0));
798 QApplication::setPalette(widgetPalette, "QTabBar");
799 widgetPalette = *palette;
800
801 widgetPalette.setColor(QPalette::HighlightedText,
802 s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
803 QApplication::setPalette(widgetPalette, "QListView");
804 widgetPalette = *palette;
805
806 widgetPalette.setColor(QPalette::Text,
807 s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
808 widgetPalette.setColor(QPalette::HighlightedText,
809 s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
810 QApplication::setPalette(widgetPalette, "QTableView");
811 widgetPalette = *palette;
812
813 widgetPalette.setColor(QPalette::Text,
814 s60Color(QS60StyleEnums::CL_QsnTextColors, 27, 0));
815 widgetPalette.setColor(QPalette::HighlightedText,
816 s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
817 QApplication::setPalette(widgetPalette, "QLineEdit");
818 QApplication::setPalette(widgetPalette, "QTextEdit");
819 widgetPalette = *palette;
820
821 widgetPalette.setColor(QPalette::HighlightedText,
822 s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
823 QApplication::setPalette(widgetPalette, "QComboBox");
824 widgetPalette = *palette;
825
826 widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 7, 0));
827 widgetPalette.setColor(QPalette::HighlightedText,
828 s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
829 QApplication::setPalette(widgetPalette, "QRadioButton");
830 QApplication::setPalette(widgetPalette, "QCheckBox");
831 widgetPalette = *palette;
832
833 widgetPalette.setColor(QPalette::WindowText, mainAreaTextColor);
834 widgetPalette.setColor(QPalette::Button, QApplication::palette().color(QPalette::Button));
835 widgetPalette.setColor(QPalette::Dark, mainAreaTextColor.darker());
836 widgetPalette.setColor(QPalette::Light, mainAreaTextColor.lighter());
837 QApplication::setPalette(widgetPalette, "QDial");
838 widgetPalette = *palette;
839
840 widgetPalette.setBrush(QPalette::Window, QBrush());
841 QApplication::setPalette(widgetPalette, "QScrollArea");
842 widgetPalette = *palette;
843
844 //Webpages should not use S60 theme colors as they are designed to work
845 //with themeBackground and do not generally mesh well with web page backgrounds.
846 QPalette webPalette = *palette;
847 webPalette.setColor(QPalette::WindowText, Qt::black);
848 webPalette.setColor(QPalette::Text, Qt::black);
849 webPalette.setBrush(QPalette::Base, Qt::white);
850
851 QApplication::setPalette(webPalette, "QWebView");
852 QApplication::setPalette(webPalette, "QGraphicsWebView");
853
854 m_webPaletteKey = webPalette.cacheKey();
855}
856
857QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags)
858{
859 QSize result(20, 20);
860 switch (part)
861 {
862 case QS60StyleEnums::SP_QgnGrafBarProgress:
863 result.setWidth(pixelMetric(QStyle::PM_ProgressBarChunkWidth));
864 break;
865 case QS60StyleEnums::SP_QgnGrafTabActiveM:
866 case QS60StyleEnums::SP_QgnGrafTabPassiveM:
867 case QS60StyleEnums::SP_QgnGrafTabActiveR:
868 case QS60StyleEnums::SP_QgnGrafTabPassiveR:
869 case QS60StyleEnums::SP_QgnGrafTabPassiveL:
870 case QS60StyleEnums::SP_QgnGrafTabActiveL:
871 //Returned QSize for tabs must not be square, but narrow rectangle with width:height
872 //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones).
873 result.setWidth(result.height() >> 1);
874 break;
875
876 case QS60StyleEnums::SP_QgnGrafNsliderEndLeft:
877 case QS60StyleEnums::SP_QgnGrafNsliderEndRight:
878 case QS60StyleEnums::SP_QgnGrafNsliderMiddle:
879 break;
880
881 case QS60StyleEnums::SP_QgnGrafNsliderMarker:
882 case QS60StyleEnums::SP_QgnGrafNsliderMarkerSelected:
883 result.scale(pixelMetric(QStyle::PM_SliderLength),
884 pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio);
885 break;
886
887 case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
888 case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
889 result.setWidth(pixelMetric(PM_FrameCornerWidth));
890 break;
891
892 case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
893 case QS60StyleEnums::SP_QsnCpScrollBgBottom:
894 case QS60StyleEnums::SP_QsnCpScrollBgTop:
895 case QS60StyleEnums::SP_QsnCpScrollHandleBottom:
896 case QS60StyleEnums::SP_QsnCpScrollHandleTop:
897 case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
898 result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent));
899 result.setWidth(pixelMetric(QStyle::PM_ScrollBarExtent));
900 break;
901 case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
902 case QS60StyleEnums::SP_QsnCpScrollBgMiddle:
903 case QS60StyleEnums::SP_QsnCpScrollHandleMiddle:
904 result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent));
905 result.setWidth(pixelMetric(QStyle::PM_ScrollBarSliderMin));
906 break;
907 default:
908 // Generic frame part size gathering.
909 for (int i = 0; i < frameElementsCount; ++i)
910 {
911 switch (m_frameElementsData[i].center - part) {
912 case 8: /* CornerTl */
913 case 7: /* CornerTr */
914 case 6: /* CornerBl */
915 case 5: /* CornerBr */
916 result.setWidth(pixelMetric(PM_FrameCornerWidth));
917 // Falltrough intended...
918 case 4: /* SideT */
919 case 3: /* SideB */
920 result.setHeight(pixelMetric(PM_FrameCornerHeight));
921 break;
922 case 2: /* SideL */
923 case 1: /* SideR */
924 result.setWidth(pixelMetric(PM_FrameCornerWidth));
925 break;
926 case 0: /* center */
927 default:
928 break;
929 }
930 }
931 break;
932 }
933 if (flags & (SF_PointEast | SF_PointWest)) {
934 const int temp = result.width();
935 result.setWidth(result.height());
936 result.setHeight(temp);
937 }
938 return result;
939}
940
941bool QS60StylePrivate::canDrawThemeBackground(const QBrush &backgroundBrush, const QWidget *widget)
942{
943 // Always return true for web pages.
944 if (widget && m_webPaletteKey == QApplication::palette(widget).cacheKey())
945 return true;
946 //If brush is not changed from style's default values, draw theme graphics.
947 return (backgroundBrush.color() == Qt::transparent ||
948 backgroundBrush.style() == Qt::NoBrush) ? true : false;
949}
950
951bool QS60StylePrivate::isWidgetPressed(const QWidget *widget)
952{
953 return (widget && widget == m_pressedWidget);
954}
955
956/*!
957 \class QS60Style
958 \brief The QS60Style class provides a look and feel suitable for applications on S60.
959 \since 4.6
960 \ingroup appearance
961
962 \sa QMacStyle, QWindowsStyle, QWindowsXPStyle, QWindowsVistaStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
963*/
964
965
966/*!
967 Destroys the style.
968*/
969QS60Style::~QS60Style()
970{
971}
972
973/*!
974 \reimp
975*/
976void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
977{
978 const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
979 SubControls sub = option->subControls;
980
981 switch (control) {
982#ifndef QT_NO_SCROLLBAR
983 case CC_ScrollBar:
984 if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
985 const bool horizontal = optionSlider->orientation == Qt::Horizontal;
986
987 const QRect scrollBarSlider = subControlRect(control, optionSlider, SC_ScrollBarSlider, widget);
988 const QRect grooveRect = subControlRect(control, optionSlider, SC_ScrollBarGroove, widget);
989
990 const QS60StylePrivate::SkinElements grooveElement =
991 horizontal ? QS60StylePrivate::SE_ScrollBarGrooveHorizontal : QS60StylePrivate::SE_ScrollBarGrooveVertical;
992 QS60StylePrivate::drawSkinElement(grooveElement, painter, grooveRect, flags);
993
994 const SubControls subControls = optionSlider->subControls;
995
996 // select correct slider (horizontal/vertical/pressed)
997 const bool sliderPressed = ((optionSlider->state & State_Sunken) && (subControls & SC_ScrollBarSlider));
998 const QS60StylePrivate::SkinElements handleElement =
999 horizontal ?
1000 ( sliderPressed ?
1001 QS60StylePrivate::SE_ScrollBarHandlePressedHorizontal :
1002 QS60StylePrivate::SE_ScrollBarHandleHorizontal ) :
1003 ( sliderPressed ?
1004 QS60StylePrivate::SE_ScrollBarHandlePressedVertical :
1005 QS60StylePrivate::SE_ScrollBarHandleVertical);
1006 QS60StylePrivate::drawSkinElement(handleElement, painter, scrollBarSlider, flags);
1007 }
1008 break;
1009#endif // QT_NO_SCROLLBAR
1010#ifndef QT_NO_SLIDER
1011 case CC_Slider:
1012 if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
1013
1014 const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget);
1015 const bool horizontal = optionSlider->orientation == Qt::Horizontal;
1016
1017 //Highlight
1018/* if (optionSlider->state & State_HasFocus)
1019 drawPrimitive(PE_FrameFocusRect, optionSlider, painter, widget);*/
1020
1021 //Groove graphics
1022 if (QS60StylePrivate::hasSliderGrooveGraphic()) {
1023 const QS60StylePrivate::SkinElements grooveElement = horizontal ?
1024 QS60StylePrivate::SE_SliderGrooveHorizontal :
1025 QS60StylePrivate::SE_SliderGrooveVertical;
1026 QS60StylePrivate::drawSkinElement(grooveElement, painter, sliderGroove, flags);
1027 } else {
1028 const QPoint sliderGrooveCenter = sliderGroove.center();
1029 const bool horizontal = optionSlider->orientation == Qt::Horizontal;
1030 painter->save();
1031 if (widget)
1032 painter->setPen(widget->palette().windowText().color());
1033 if (horizontal)
1034 painter->drawLine(0, sliderGrooveCenter.y(), sliderGroove.right(), sliderGrooveCenter.y());
1035 else
1036 painter->drawLine(sliderGrooveCenter.x(), 0, sliderGrooveCenter.x(), sliderGroove.bottom());
1037 painter->restore();
1038 }
1039
1040 //Handle graphics
1041 const QRect sliderHandle = subControlRect(control, optionSlider, SC_SliderHandle, widget);
1042 QS60StylePrivate::SkinElements handleElement;
1043 if (optionSlider->state & State_Sunken)
1044 handleElement =
1045 horizontal ? QS60StylePrivate::SE_SliderHandleSelectedHorizontal : QS60StylePrivate::SE_SliderHandleSelectedVertical;
1046 else
1047 handleElement =
1048 horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical;
1049 QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags);
1050 }
1051 break;
1052#endif // QT_NO_SLIDER
1053#ifndef QT_NO_COMBOBOX
1054 case CC_ComboBox:
1055 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1056 const QRect cmbxEditField = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
1057 const QRect cmbxFrame = subControlRect(CC_ComboBox, option, SC_ComboBoxFrame, widget);
1058 const bool direction = cmb->direction == Qt::LeftToRight;
1059
1060 // Button frame
1061 QStyleOptionFrame buttonOption;
1062 buttonOption.QStyleOption::operator=(*cmb);
1063 const int maxHeight = cmbxFrame.height();
1064 const int maxWidth = cmbxFrame.width() - cmbxEditField.width();
1065 const int topLeftPoint = direction ?
1066 (cmbxEditField.right() + 1) : (cmbxEditField.left() + 1 - maxWidth);
1067 const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight);
1068 buttonOption.rect = buttonRect;
1069 buttonOption.state = cmb->state;
1070 drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
1071
1072 // draw label background - label itself is drawn separately
1073 const QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_FrameLineEdit;
1074 QS60StylePrivate::drawSkinElement(skinElement, painter, cmbxEditField, flags);
1075
1076 // Draw the combobox arrow
1077 if (sub & SC_ComboBoxArrow) {
1078 // Make rect slightly smaller
1079 buttonOption.rect.adjust(1, 1, -1, -1);
1080 painter->save();
1081 painter->setPen(option->palette.buttonText().color());
1082 drawPrimitive(PE_IndicatorSpinDown, &buttonOption, painter, widget);
1083 painter->restore();
1084 }
1085 }
1086 break;
1087#endif // QT_NO_COMBOBOX
1088#ifndef QT_NO_TOOLBUTTON
1089 case CC_ToolButton:
1090 if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
1091 State bflags = toolBtn->state & ~State_Sunken;
1092
1093 if (bflags & State_AutoRaise) {
1094 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) {
1095 bflags &= ~State_Raised;
1096 }
1097 }
1098 State mflags = bflags;
1099 if (toolBtn->state & State_Sunken) {
1100 if (toolBtn->activeSubControls & SC_ToolButton)
1101 bflags |= State_Sunken;
1102 mflags |= State_Sunken;
1103 }
1104
1105 const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget));
1106 QRect menuRect = QRect();
1107 if (toolBtn->subControls & SC_ToolButtonMenu)
1108 menuRect = subControlRect(control, toolBtn, SC_ToolButtonMenu, widget);
1109
1110 if (toolBtn->subControls & SC_ToolButton) {
1111 QStyleOption tool(0);
1112 tool.palette = toolBtn->palette;
1113
1114 if (bflags & (State_Sunken | State_On | State_Raised | State_Enabled)) {
1115 tool.rect = button.unite(menuRect);
1116 tool.state = bflags;
1117 const QToolButton *toolButtonWidget = qobject_cast<const QToolButton *>(widget);
1118 const QS60StylePrivate::SkinElements element =
1119 ((toolButtonWidget && toolButtonWidget->isDown()) || (option->state & State_Sunken)) ?
1120 QS60StylePrivate::SE_ToolBarButtonPressed : QS60StylePrivate::SE_ToolBarButton;
1121 QS60StylePrivate::drawSkinElement(element, painter, tool.rect, flags);
1122 drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
1123 }
1124 if (toolBtn->subControls & SC_ToolButtonMenu) {
1125 tool.rect = menuRect;
1126 tool.state = mflags;
1127 drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
1128 }
1129 }
1130 QStyleOptionToolButton toolButton = *toolBtn;
1131 if (toolBtn->features & QStyleOptionToolButton::Arrow) {
1132 PrimitiveElement pe;
1133 switch (toolBtn->arrowType) {
1134 case Qt::LeftArrow:
1135 pe = PE_IndicatorArrowLeft;
1136 break;
1137 case Qt::RightArrow:
1138 pe = PE_IndicatorArrowRight;
1139 break;
1140 case Qt::UpArrow:
1141 pe = PE_IndicatorArrowUp;
1142 break;
1143 case Qt::DownArrow:
1144 pe = PE_IndicatorArrowDown;
1145 break;
1146 default:
1147 break; }
1148 toolButton.rect = button;
1149 drawPrimitive(pe, &toolButton, painter, widget);
1150 }
1151
1152 if (toolBtn->text.length() > 0 ||
1153 !toolBtn->icon.isNull()) {
1154 const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
1155 toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
1156 drawControl(CE_ToolButtonLabel, &toolButton, painter, widget);
1157 }
1158 }
1159 break;
1160#endif //QT_NO_TOOLBUTTON
1161#ifndef QT_NO_SPINBOX
1162 case CC_SpinBox:
1163 if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
1164 QStyleOptionSpinBox copy = *spinBox;
1165 PrimitiveElement pe;
1166
1167 if (spinBox->subControls & SC_SpinBoxUp) {
1168 copy.subControls = SC_SpinBoxUp;
1169 QPalette spinBoxPal = spinBox->palette;
1170 if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) {
1171 spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
1172 copy.state &= ~State_Enabled;
1173 copy.palette = spinBoxPal;
1174 }
1175
1176 if (spinBox->activeSubControls == SC_SpinBoxUp && (spinBox->state & State_Sunken)) {
1177 copy.state |= State_On;
1178 copy.state |= State_Sunken;
1179 } else {
1180 copy.state |= State_Raised;
1181 copy.state &= ~State_Sunken;
1182 }
1183 pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
1184 PE_IndicatorSpinPlus :
1185 PE_IndicatorSpinUp;
1186
1187 copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget);
1188 drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
1189 copy.rect.adjust(1, 1, -1, -1);
1190 drawPrimitive(pe, &copy, painter, widget);
1191 }
1192
1193 if (spinBox->subControls & SC_SpinBoxDown) {
1194 copy.subControls = SC_SpinBoxDown;
1195 copy.state = spinBox->state;
1196 QPalette spinBoxPal = spinBox->palette;
1197 if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) {
1198 spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
1199 copy.state &= ~State_Enabled;
1200 copy.palette = spinBoxPal;
1201 }
1202
1203 if (spinBox->activeSubControls == SC_SpinBoxDown && (spinBox->state & State_Sunken)) {
1204 copy.state |= State_On;
1205 copy.state |= State_Sunken;
1206 } else {
1207 copy.state |= State_Raised;
1208 copy.state &= ~State_Sunken;
1209 }
1210 pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
1211 PE_IndicatorSpinMinus :
1212 PE_IndicatorSpinDown;
1213
1214 copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget);
1215 drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
1216 copy.rect.adjust(1, 1, -1, -1);
1217 drawPrimitive(pe, &copy, painter, widget);
1218 }
1219 }
1220 break;
1221#endif //QT_NO_SPINBOX
1222#ifndef QT_NO_GROUPBOX
1223 case CC_GroupBox:
1224 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
1225 // Draw frame
1226 const QRect textRect = subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget);
1227 const QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget);
1228 if (groupBox->subControls & SC_GroupBoxFrame) {
1229 QStyleOptionFrameV2 frame;
1230 frame.QStyleOption::operator=(*groupBox);
1231 frame.features = groupBox->features;
1232 frame.lineWidth = groupBox->lineWidth;
1233 frame.midLineWidth = groupBox->midLineWidth;
1234 frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
1235 drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
1236 }
1237
1238 // Draw title
1239 if ((groupBox->subControls & SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
1240 const QColor textColor = groupBox->textColor;
1241 painter->save();
1242
1243 if (textColor.isValid())
1244 painter->setPen(textColor);
1245 int alignment = int(groupBox->textAlignment);
1246 if (!styleHint(SH_UnderlineShortcut, option, widget))
1247 alignment |= Qt::TextHideMnemonic;
1248
1249 drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | Qt::AlignVCenter | alignment,
1250 groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
1251 textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
1252 painter->restore();
1253 }
1254
1255 // Draw checkbox
1256 if (groupBox->subControls & SC_GroupBoxCheckBox) {
1257 QStyleOptionButton box;
1258 box.QStyleOption::operator=(*groupBox);
1259 box.rect = checkBoxRect;
1260 drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
1261 }
1262 }
1263 break;
1264#endif //QT_NO_GROUPBOX
1265 default:
1266 QCommonStyle::drawComplexControl(control, option, painter, widget);
1267 }
1268}
1269
1270/*!
1271 \reimp
1272*/
1273void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
1274{
1275 Q_D(const QS60Style);
1276 const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
1277 switch (element) {
1278 case CE_CheckBox:
1279 case CE_RadioButton:
1280 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1281 bool isRadio = (element == CE_RadioButton);
1282 QStyleOptionButton subopt = *btn;
1283
1284 // Highlight needs to be drawn first, as it goes "underneath" the text and indicator.
1285 if (btn->state & State_HasFocus) {
1286 QStyleOptionFocusRect fropt;
1287 fropt.QStyleOption::operator=(*btn);
1288 fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
1289 : SE_CheckBoxFocusRect, btn, widget);
1290 drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
1291
1292 subopt.palette.setColor(QPalette::Active, QPalette::WindowText,
1293 subopt.palette.highlightedText().color());
1294 }
1295
1296 subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
1297 : SE_CheckBoxIndicator, btn, widget);
1298 drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
1299 &subopt, painter, widget);
1300 subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
1301 : SE_CheckBoxContents, btn, widget);
1302
1303 drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
1304 }
1305 break;
1306
1307 case CE_PushButton:
1308 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1309
1310 drawControl(CE_PushButtonBevel, btn, painter, widget);
1311 QStyleOptionButton subopt = *btn;
1312 subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
1313
1314 drawControl(CE_PushButtonLabel, &subopt, painter, widget);
1315 }
1316 break;
1317 case CE_PushButtonBevel:
1318 if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1319 const bool isDisabled = !(option->state & State_Enabled);
1320 const bool isFlat = button->features & QStyleOptionButton::Flat;
1321 QS60StyleEnums::SkinParts skinPart;
1322 QS60StylePrivate::SkinElements skinElement;
1323 if (!isDisabled) {
1324 const bool isPressed = (option->state & State_Sunken) ||
1325 (option->state & State_On);
1326 if (isFlat) {
1327 skinPart =
1328 isPressed ? QS60StyleEnums::SP_QsnFrButtonTbCenterPressed : QS60StyleEnums::SP_QsnFrButtonTbCenter;
1329 } else {
1330 skinElement =
1331 isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
1332 }
1333 } else {
1334 if (isFlat)
1335 skinPart =QS60StyleEnums::SP_QsnFrButtonCenterInactive;
1336 else
1337 skinElement = QS60StylePrivate::SE_ButtonInactive;
1338 }
1339 if (isFlat)
1340 QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
1341 else
1342 QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
1343 }
1344 break;
1345#ifndef QT_NO_TOOLBUTTON
1346 case CE_ToolButtonLabel:
1347 if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
1348 QStyleOptionToolButton optionToolButton = *toolBtn;
1349
1350 if (!optionToolButton.icon.isNull() && (optionToolButton.state & State_Sunken)
1351 && (optionToolButton.state & State_Enabled)) {
1352
1353 const QIcon::State state = optionToolButton.state & State_On ? QIcon::On : QIcon::Off;
1354 const QPixmap pm(optionToolButton.icon.pixmap(optionToolButton.rect.size().boundedTo(optionToolButton.iconSize),
1355 QIcon::Normal, state));
1356 optionToolButton.icon = generatedIconPixmap(QIcon::Selected, pm, &optionToolButton);
1357 }
1358
1359 QCommonStyle::drawControl(element, &optionToolButton, painter, widget);
1360 }
1361 break;
1362#endif //QT_NO_TOOLBUTTON
1363#ifndef QT_NO_COMBOBOX
1364 case CE_ComboBoxLabel:
1365 if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
1366 QStyleOption optionComboBox = *comboBox;
1367 optionComboBox.palette.setColor(QPalette::Active, QPalette::WindowText,
1368 optionComboBox.palette.text().color() );
1369 optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText,
1370 optionComboBox.palette.text().color() );
1371 QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
1372 const int frameW = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
1373
1374 if (!comboBox->currentIcon.isNull()) {
1375 const QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1376 const QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
1377 QRect iconRect(editRect);
1378 iconRect.setWidth(comboBox->iconSize.width() + frameW);
1379 iconRect = alignedRect(comboBox->direction,
1380 Qt::AlignLeft | Qt::AlignVCenter,
1381 iconRect.size(), editRect);
1382 if (comboBox->editable)
1383 painter->fillRect(iconRect, optionComboBox.palette.brush(QPalette::Base));
1384 drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
1385
1386 if (comboBox->direction == Qt::RightToLeft)
1387 editRect.setRight(editRect.right() - frameW - comboBox->iconSize.width());
1388 else
1389 editRect.setLeft(comboBox->iconSize.width() + frameW);
1390 }
1391 if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
1392 const Qt::TextElideMode elideMode = (comboBox->direction == Qt::LeftToRight) ? Qt::ElideRight : Qt::ElideLeft;
1393 const QString text = comboBox->fontMetrics.elidedText(comboBox->currentText, elideMode, editRect.width());
1394
1395 QCommonStyle::drawItemText(painter,
1396 editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0),
1397 visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
1398 comboBox->palette, comboBox->state & State_Enabled, text);
1399 }
1400 }
1401 break;
1402#endif //QT_NO_COMBOBOX
1403#ifndef QT_NO_ITEMVIEWS
1404 case CE_ItemViewItem:
1405 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
1406 QStyleOptionViewItemV4 voptAdj = *vopt;
1407 painter->save();
1408
1409 painter->setClipRect(voptAdj.rect);
1410 const bool isSelected = (vopt->state & State_Selected);
1411 const bool hasFocus = (vopt->state & State_HasFocus);
1412
1413 bool isScrollBarVisible = false;
1414 int scrollBarWidth = 0;
1415 QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget);
1416 for (int i = 0; i < scrollBars.size(); ++i) {
1417 QScrollBar *scrollBar = scrollBars.at(i);
1418 if (scrollBar && scrollBar->orientation() == Qt::Vertical) {
1419 isScrollBarVisible = scrollBar->isVisible();
1420 scrollBarWidth = scrollBar->size().width();
1421 break;
1422 }
1423 }
1424
1425 int rightValue = widget ? widget->contentsRect().right() : voptAdj.rect.right();
1426
1427 if (isScrollBarVisible)
1428 rightValue -= scrollBarWidth;
1429
1430 if (voptAdj.rect.right() > rightValue)
1431 voptAdj.rect.setRight(rightValue);
1432
1433 const QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &voptAdj, widget);
1434 QRect textRect = subElementRect(SE_ItemViewItemText, &voptAdj, widget);
1435 const QAbstractItemView *itemView = qobject_cast<const QAbstractItemView *>(widget);
1436
1437 // draw themed background for table unless background brush has been defined.
1438 if (vopt->backgroundBrush == Qt::NoBrush) {
1439 if (itemView) {
1440 drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);
1441 }
1442 } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);}
1443
1444 // draw the icon
1445 const QIcon::Mode mode = (voptAdj.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled;
1446 const QIcon::State state = (voptAdj.state & State_Open) ? QIcon::On : QIcon::Off;
1447 voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state);
1448
1449 // Draw selection check mark. Show check mark only in multi selection modes.
1450 if (itemView) {
1451 const bool singleSelection =
1452 (itemView->selectionMode() == QAbstractItemView::SingleSelection ||
1453 itemView->selectionMode() == QAbstractItemView::NoSelection)||
1454 (itemView->selectionModel()->selectedIndexes().count() < 2 );
1455
1456 const bool selectItemsOnly = (itemView->selectionBehavior() == QAbstractItemView::SelectItems);
1457
1458 const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget);
1459
1460 QStyleOptionViewItemV4 checkMarkOption(voptAdj);
1461 if (selectionRect.isValid())
1462 checkMarkOption.rect = selectionRect;
1463 // Draw selection mark.
1464 if (isSelected && !singleSelection && selectItemsOnly) {
1465 proxy()->drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget);
1466 // @todo: this should happen in the rect retrievel i.e. subElementRect()
1467 if (textRect.right() > selectionRect.left())
1468 textRect.setRight(selectionRect.left());
1469 } else if (singleSelection &&
1470 voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) {
1471 checkMarkOption.state = checkMarkOption.state & ~State_HasFocus;
1472
1473 switch (vopt->checkState) {
1474 case Qt::Unchecked:
1475 checkMarkOption.state |= State_Off;
1476 break;
1477 case Qt::PartiallyChecked:
1478 checkMarkOption.state |= State_NoChange;
1479 break;
1480 case Qt::Checked:
1481 checkMarkOption.state |= State_On;
1482 break;
1483 }
1484 drawPrimitive(PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget);
1485 }
1486 }
1487
1488 // draw the text
1489 if (!voptAdj.text.isEmpty()) {
1490 if (isSelected || hasFocus )
1491 painter->setPen(voptAdj.palette.highlightedText().color());
1492 else
1493 painter->setPen(voptAdj.palette.text().color());
1494 d->viewItemDrawText(painter, &voptAdj, textRect);
1495 }
1496 painter->restore();
1497 }
1498 break;
1499#endif // QT_NO_ITEMVIEWS
1500#ifndef QT_NO_TABBAR
1501 case CE_TabBarTabShape:
1502 if (const QStyleOptionTabV3 *optionTab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
1503 QStyleOptionTabV3 optionTabAdj = *optionTab;
1504 const bool isSelected = optionTab->state & State_Selected;
1505 const bool directionMirrored = (optionTab->direction == Qt::RightToLeft);
1506 QS60StylePrivate::SkinElements skinElement;
1507 switch (optionTab->shape) {
1508 case QTabBar::TriangularEast:
1509 case QTabBar::RoundedEast:
1510 skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabEastActive:
1511 QS60StylePrivate::SE_TabBarTabEastInactive;
1512 break;
1513 case QTabBar::TriangularSouth:
1514 case QTabBar::RoundedSouth:
1515 skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabSouthActive:
1516 QS60StylePrivate::SE_TabBarTabSouthInactive;
1517 break;
1518 case QTabBar::TriangularWest:
1519 case QTabBar::RoundedWest:
1520 skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabWestActive:
1521 QS60StylePrivate::SE_TabBarTabWestInactive;
1522 break;
1523 case QTabBar::TriangularNorth:
1524 case QTabBar::RoundedNorth:
1525 default:
1526 skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabNorthActive:
1527 QS60StylePrivate::SE_TabBarTabNorthInactive;
1528 break;
1529 }
1530 if (skinElement == QS60StylePrivate::SE_TabBarTabEastInactive ||
1531 skinElement == QS60StylePrivate::SE_TabBarTabNorthInactive ||
1532 skinElement == QS60StylePrivate::SE_TabBarTabSouthInactive ||
1533 skinElement == QS60StylePrivate::SE_TabBarTabWestInactive ||
1534 skinElement == QS60StylePrivate::SE_TabBarTabEastActive ||
1535 skinElement == QS60StylePrivate::SE_TabBarTabNorthActive ||
1536 skinElement == QS60StylePrivate::SE_TabBarTabSouthActive ||
1537 skinElement==QS60StylePrivate::SE_TabBarTabWestActive) {
1538 const int borderThickness =
1539 QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
1540 const int tabOverlap =
1541 QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness;
1542 const bool usesScrollButtons =
1543 (widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false;
1544 const int roomForScrollButton =
1545 usesScrollButtons ? QS60StylePrivate::pixelMetric(PM_TabBarScrollButtonWidth) : 0;
1546
1547 // adjust for overlapping tabs and scrollbuttons, if necessary
1548 if (skinElement == QS60StylePrivate::SE_TabBarTabEastInactive ||
1549 skinElement == QS60StylePrivate::SE_TabBarTabEastActive ||
1550 skinElement == QS60StylePrivate::SE_TabBarTabWestInactive ||
1551 skinElement == QS60StylePrivate::SE_TabBarTabWestActive){
1552 if (optionTabAdj.position == QStyleOptionTabV3::Beginning)
1553 optionTabAdj.rect.adjust(0, roomForScrollButton, 0, tabOverlap);
1554 else if (optionTabAdj.position == QStyleOptionTabV3::End)
1555 optionTabAdj.rect.adjust(0, 0, 0, tabOverlap);
1556 else
1557 optionTabAdj.rect.adjust(0, 0, 0, tabOverlap);
1558 } else {
1559 if (directionMirrored) {
1560 if (optionTabAdj.position == QStyleOptionTabV3::Beginning)
1561 optionTabAdj.rect.adjust(-tabOverlap, 0, -roomForScrollButton, 0);
1562 else
1563 optionTabAdj.rect.adjust(-tabOverlap, 0, 0, 0);
1564 } else {
1565 if (optionTabAdj.position == QStyleOptionTabV3::Beginning)
1566 optionTabAdj.rect.adjust(roomForScrollButton, 0, tabOverlap, 0);
1567 else
1568 optionTabAdj.rect.adjust(0, 0, tabOverlap, 0);
1569 }
1570 }
1571 }
1572 QS60StylePrivate::drawSkinElement(skinElement, painter, optionTabAdj.rect, flags);
1573 }
1574 break;
1575 case CE_TabBarTabLabel:
1576 if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
1577 QStyleOptionTabV3 optionTab = *tab;
1578 QRect tr = optionTab.rect;
1579 const bool directionMirrored = (optionTab.direction == Qt::RightToLeft);
1580 const int borderThickness = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
1581 const int tabOverlap =
1582 QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap) - borderThickness;
1583 const bool usesScrollButtons =
1584 (widget) ? (qobject_cast<const QTabBar*>(widget))->usesScrollButtons() : false;
1585 const int roomForScrollButton =
1586 usesScrollButtons ? QS60StylePrivate::pixelMetric(PM_TabBarScrollButtonWidth) : 0;
1587
1588 switch (tab->shape) {
1589 case QTabBar::TriangularWest:
1590 case QTabBar::RoundedWest:
1591 case QTabBar::TriangularEast:
1592 case QTabBar::RoundedEast:
1593 tr.adjust(0, 0, 0, tabOverlap);
1594 break;
1595 case QTabBar::TriangularSouth:
1596 case QTabBar::RoundedSouth:
1597 case QTabBar::TriangularNorth:
1598 case QTabBar::RoundedNorth:
1599 default:
1600 if (directionMirrored)
1601 tr.adjust(-tabOverlap, 0, 0, 0);
1602 else
1603 tr.adjust(0, 0, tabOverlap, 0);
1604 break;
1605 }
1606 painter->save();
1607 QFont f = painter->font();
1608 f.setPointSizeF(f.pointSizeF() * KTabFontMul);
1609 painter->setFont(f);
1610
1611 const bool selected = optionTab.state & State_Selected;
1612 if (selected)
1613 optionTab.palette.setColor(QPalette::Active, QPalette::WindowText,
1614 optionTab.palette.highlightedText().color());
1615
1616 const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast
1617 || optionTab.shape == QTabBar::RoundedWest
1618 || optionTab.shape == QTabBar::TriangularEast
1619 || optionTab.shape == QTabBar::TriangularWest;
1620
1621 //make room for scrollbuttons
1622 if (!verticalTabs) {
1623 if ((tab->position == QStyleOptionTabV3::Beginning && !directionMirrored))
1624 tr.adjust(roomForScrollButton, 0, 0, 0);
1625 else if ((tab->position == QStyleOptionTabV3::Beginning && directionMirrored))
1626 tr.adjust(0, 0, -roomForScrollButton, 0);
1627 } else {
1628 if (tab->position == QStyleOptionTabV3::Beginning)
1629 tr.adjust(0, roomForScrollButton, 0, 0);
1630 }
1631
1632 if (verticalTabs) {
1633 painter->save();
1634 int newX, newY, newRotation;
1635 if (optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::TriangularEast) {
1636 newX = tr.width();
1637 newY = tr.y();
1638 newRotation = 90;
1639 } else {
1640 newX = 0;
1641 newY = tr.y() + tr.height();
1642 newRotation = -90;
1643 }
1644 tr.setRect(0, 0, tr.height(), tr.width());
1645 QTransform m;
1646 m.translate(newX, newY);
1647 m.rotate(newRotation);
1648 painter->setTransform(m, true);
1649 }
1650 tr.adjust(0, 0, pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget),
1651 pixelMetric(PM_TabBarTabShiftVertical, tab, widget));
1652
1653 if (selected) {
1654 tr.setBottom(tr.bottom() - pixelMetric(PM_TabBarTabShiftVertical, tab, widget));
1655 tr.setRight(tr.right() - pixelMetric(PM_TabBarTabShiftHorizontal, tab, widget));
1656 }
1657
1658 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
1659 if (!styleHint(SH_UnderlineShortcut, &optionTab, widget))
1660 alignment |= Qt::TextHideMnemonic;
1661 if (!optionTab.icon.isNull()) {
1662 QSize iconSize = optionTab.iconSize;
1663 if (!iconSize.isValid()) {
1664 const int iconExtent = pixelMetric(PM_TabBarIconSize);
1665 iconSize = QSize(iconExtent, iconExtent);
1666 }
1667 QPixmap tabIcon = optionTab.icon.pixmap(iconSize,
1668 (optionTab.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
1669 if (tab->text.isEmpty())
1670 painter->drawPixmap(tr.center().x() - (tabIcon.height() >> 1),
1671 tr.center().y() - (tabIcon.height() >> 1),
1672 tabIcon);
1673 else
1674 painter->drawPixmap(tr.left() + tabOverlap,
1675 tr.center().y() - (tabIcon.height() >> 1),
1676 tabIcon);
1677 tr.setLeft(tr.left() + iconSize.width() + 4); //todo: magic four
1678 }
1679
1680 QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
1681 if (verticalTabs)
1682 painter->restore();
1683
1684 painter->restore();
1685 }
1686 break;
1687#endif // QT_NO_TABBAR
1688#ifndef QT_NO_PROGRESSBAR
1689 case CE_ProgressBarContents:
1690 if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1691 QRect progressRect = optionProgressBar->rect;
1692
1693 if (optionProgressBar->minimum == optionProgressBar->maximum && optionProgressBar->minimum == 0) {
1694 // busy indicator
1695 const QS60StylePrivate::SkinElementFlag orientationFlag = optionProgressBar->orientation == Qt::Horizontal ?
1696 QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointWest;
1697
1698 QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWaitAnim,
1699 painter, progressRect, flags | orientationFlag | QS60StylePrivate::SF_Animation );
1700 } else {
1701 const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0
1702 : (qreal)optionProgressBar->progress / optionProgressBar->maximum;
1703 const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
1704 if (optionProgressBar->orientation == Qt::Horizontal) {
1705 progressRect.setWidth(int(progressRect.width() * progressFactor));
1706 if(optionProgressBar->direction == Qt::RightToLeft)
1707 progressRect.translate(optionProgressBar->rect.width() - progressRect.width(), 0);
1708 progressRect.adjust(frameWidth, 0, -frameWidth, 0);
1709 } else {
1710 progressRect.adjust(0, frameWidth, 0, -frameWidth);
1711 progressRect.setTop(progressRect.bottom() - int(progressRect.height() * progressFactor));
1712 }
1713
1714 const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
1715 QS60StylePrivate::SE_ProgressBarIndicatorHorizontal : QS60StylePrivate::SE_ProgressBarIndicatorVertical;
1716 QS60StylePrivate::drawSkinElement(skinElement, painter, progressRect, flags);
1717 }
1718 }
1719 break;
1720 case CE_ProgressBarGroove:
1721 if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1722 const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
1723 QS60StylePrivate::SE_ProgressBarGrooveHorizontal : QS60StylePrivate::SE_ProgressBarGrooveVertical;
1724 QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
1725 }
1726 break;
1727 case CE_ProgressBarLabel:
1728 if (const QStyleOptionProgressBarV2 *progressbar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
1729 QStyleOptionProgressBarV2 optionProgressBar = *progressbar;
1730 QCommonStyle::drawItemText(painter, progressbar->rect, flags | Qt::AlignCenter | Qt::TextSingleLine, optionProgressBar.palette,
1731 progressbar->state & State_Enabled, progressbar->text, QPalette::WindowText);
1732 }
1733 break;
1734#endif // QT_NO_PROGRESSBAR
1735#ifndef QT_NO_MENU
1736 case CE_MenuItem:
1737 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
1738 QStyleOptionMenuItem optionMenuItem = *menuItem;
1739
1740 bool drawSubMenuIndicator = false;
1741 switch(menuItem->menuItemType) {
1742 case QStyleOptionMenuItem::Scroller:
1743 case QStyleOptionMenuItem::Separator:
1744 return; // no separators or scrollers in S60 menus
1745 case QStyleOptionMenuItem::SubMenu:
1746 drawSubMenuIndicator = true;
1747 break;
1748 default:
1749 break;
1750 }
1751 const bool enabled = optionMenuItem.state & State_Enabled;
1752 const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable;
1753
1754 uint text_flags = Qt::AlignLeading | Qt::TextShowMnemonic | Qt::TextDontClip
1755 | Qt::TextSingleLine | Qt::AlignVCenter;
1756 if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
1757 text_flags |= Qt::TextHideMnemonic;
1758
1759 const bool selected = (option->state & State_Selected) && (option->state & State_Enabled);
1760 if (selected)
1761 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
1762
1763 QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
1764 QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
1765
1766 //todo: move the vertical spacing stuff into subElementRect
1767 const int vSpacing = QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing);
1768 if (checkable){
1769 const int hSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing);
1770 QStyleOptionMenuItem optionCheckBox;
1771 optionCheckBox.QStyleOptionMenuItem::operator=(*menuItem);
1772 optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
1773 optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
1774 optionCheckBox.rect.moveCenter(QPoint(
1775 optionCheckBox.rect.center().x(),
1776 menuItem->rect.center().y()));
1777 const int moveByX = optionCheckBox.rect.width() + vSpacing;
1778 if (optionMenuItem.direction == Qt::LeftToRight) {
1779 textRect.translate(moveByX, 0);
1780 iconRect.translate(moveByX, 0);
1781 iconRect.setWidth(iconRect.width() + vSpacing);
1782 textRect.setWidth(textRect.width() - moveByX - vSpacing);
1783 optionCheckBox.rect.translate(vSpacing >> 1, hSpacing >> 1);
1784 } else {
1785 textRect.setWidth(textRect.width() - moveByX);
1786 iconRect.setWidth(iconRect.width() + vSpacing);
1787 iconRect.translate(-optionCheckBox.rect.width() - vSpacing, 0);
1788 optionCheckBox.rect.translate(textRect.width() + iconRect.width(), 0);
1789 }
1790 drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget);
1791 }
1792 //draw icon and/or checkState
1793 QPixmap pix = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize),
1794 enabled ? QIcon::Normal : QIcon::Disabled);
1795 const bool itemWithIcon = !pix.isNull();
1796 if (itemWithIcon) {
1797 drawItemPixmap(painter, iconRect, text_flags, pix);
1798 if (optionMenuItem.direction == Qt::LeftToRight)
1799 textRect.translate(vSpacing, 0);
1800 else
1801 textRect.translate(-vSpacing, 0);
1802 textRect.setWidth(textRect.width()-vSpacing);
1803 }
1804
1805 //draw indicators
1806 if (drawSubMenuIndicator) {
1807 QStyleOptionMenuItem arrowOptions;
1808 arrowOptions.QStyleOption::operator=(*menuItem);
1809 const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget) >> 1) +
1810 pixelMetric(PM_LayoutVerticalSpacing, option, widget);
1811 if (optionMenuItem.direction == Qt::LeftToRight)
1812 arrowOptions.rect.setLeft(textRect.right());
1813 arrowOptions.rect.setWidth(indicatorWidth);
1814 //by default sub menu indicator in S60 points to east,so here icon
1815 // direction is set to north (and south when in RightToLeft)
1816 const QS60StylePrivate::SkinElementFlag arrowDirection = (arrowOptions.direction == Qt::LeftToRight) ?
1817 QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth;
1818 painter->save();
1819 painter->setPen(option->palette.windowText().color());
1820 QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect,
1821 (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection));
1822 painter->restore();
1823 }
1824
1825 //draw text
1826 if (!enabled){
1827 //In s60, if something becomes disabled, it is removed from menu, so no native look-alike available.
1828 optionMenuItem.palette.setColor(QPalette::Disabled, QPalette::Text, QS60StylePrivate::lighterColor(
1829 optionMenuItem.palette.color(QPalette::Disabled, QPalette::Text)));
1830 painter->save();
1831 painter->setOpacity(0.5);
1832 }
1833 if (selected)
1834 optionMenuItem.palette.setColor(
1835 QPalette::Active, QPalette::Text, optionMenuItem.palette.highlightedText().color());
1836
1837 QCommonStyle::drawItemText(painter, textRect, text_flags,
1838 optionMenuItem.palette, enabled,
1839 optionMenuItem.text, QPalette::Text);
1840 if (!enabled)
1841 painter->restore();
1842 }
1843 break;
1844 case CE_MenuEmptyArea:
1845 break;
1846#endif //QT_NO_MENU
1847
1848#ifndef QT_NO_MENUBAR
1849 case CE_MenuBarEmptyArea:
1850 break;
1851#endif //QT_NO_MENUBAR
1852
1853 case CE_HeaderSection:
1854 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1855 painter->save();
1856 QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header));
1857 const int penWidth = (header->orientation == Qt::Horizontal) ?
1858 linePen.width() + QS60StylePrivate::pixelMetric(PM_BoldLineWidth)
1859 : linePen.width() + QS60StylePrivate::pixelMetric(PM_ThinLineWidth);
1860 linePen.setWidth(penWidth);
1861 painter->setPen(linePen);
1862 if (header->orientation == Qt::Horizontal){
1863 painter->drawLine(header->rect.bottomLeft(), header->rect.bottomRight());
1864 } else {
1865 if ( header->direction == Qt::LeftToRight ) {
1866 painter->drawLine(header->rect.topRight(), header->rect.bottomRight());
1867 } else {
1868 painter->drawLine(header->rect.topLeft(), header->rect.bottomLeft());
1869 }
1870 }
1871 painter->restore();
1872
1873 //Draw corner button as normal pushButton.
1874 if (qobject_cast<const QAbstractButton *>(widget)) {
1875 //Make cornerButton slightly smaller so that it is not on top of table border graphic.
1876 QStyleOptionHeader subopt = *header;
1877 const int borderTweak =
1878 QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
1879 if (subopt.direction == Qt::LeftToRight)
1880 subopt.rect.adjust(borderTweak, borderTweak, 0, -borderTweak);
1881 else
1882 subopt.rect.adjust(0, borderTweak, -borderTweak, -borderTweak);
1883 drawPrimitive(PE_PanelButtonBevel, &subopt, painter, widget);
1884 } else if ((header->palette.brush(QPalette::Button) != Qt::transparent)) {
1885 //Draw non-themed background. Background for theme is drawn in CE_ShapedFrame
1886 //to get continuous theme graphic across all the header cells.
1887 qDrawShadePanel(painter, header->rect, header->palette,
1888 header->state & (State_Sunken | State_On), penWidth,
1889 &header->palette.brush(QPalette::Button));
1890 }
1891 }
1892 break;
1893 case CE_HeaderEmptyArea: // no need to draw this
1894 break;
1895 case CE_Header:
1896 if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
1897 drawControl(CE_HeaderSection, header, painter, widget);
1898 QStyleOptionHeader subopt = *header;
1899 subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
1900 if (subopt.rect.isValid())
1901 drawControl(CE_HeaderLabel, &subopt, painter, widget);
1902 if (header->sortIndicator != QStyleOptionHeader::None) {
1903 subopt.rect = subElementRect(SE_HeaderArrow, option, widget);
1904 drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
1905 }
1906 }
1907 break;
1908#ifndef QT_NO_TOOLBAR
1909 case CE_ToolBar:
1910 if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
1911 const QToolBar *tbWidget = qobject_cast<const QToolBar *>(widget);
1912
1913 //toolbar within a toolbar, skip
1914 if (!tbWidget || (widget && qobject_cast<QToolBar *>(widget->parentWidget())))
1915 break;
1916
1917 // Normally in S60 5.0+ there is no background for toolbar, but in some cases with versatile QToolBar,
1918 // it looks a bit strange. So, lets fillRect with Button.
1919 if (!QS60StylePrivate::isToolBarBackground()) {
1920 QList<QAction *> actions = tbWidget->actions();
1921 bool justToolButtonsInToolBar = true;
1922 for (int i = 0; i < actions.size(); ++i) {
1923 QWidget *childWidget = tbWidget->widgetForAction(actions.at(i));
1924 const QToolButton *button = qobject_cast<const QToolButton *>(childWidget);
1925 if (!button){
1926 justToolButtonsInToolBar = false;
1927 }
1928 }
1929
1930 // Draw frame background
1931 // for vertical toolbars with text only and
1932 // for toolbars with extension buttons and
1933 // for toolbars with widgets in them.
1934 if (!justToolButtonsInToolBar ||
1935 (tbWidget &&
1936 (tbWidget->orientation() == Qt::Vertical) &&
1937 (tbWidget->toolButtonStyle() == Qt::ToolButtonTextOnly))) {
1938 painter->save();
1939 if (widget)
1940 painter->setBrush(widget->palette().button());
1941 painter->setOpacity(0.3);
1942 painter->fillRect(toolBar->rect, painter->brush());
1943 painter->restore();
1944 }
1945 } else {
1946 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBar, painter, toolBar->rect, flags);
1947 }
1948 }
1949 break;
1950#endif //QT_NO_TOOLBAR
1951 case CE_ShapedFrame:
1952 if (const QTextEdit *textEdit = qobject_cast<const QTextEdit *>(widget)) {
1953 const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option);
1954 if (QS60StylePrivate::canDrawThemeBackground(frame->palette.base(), widget))
1955 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags);
1956 else
1957 QCommonStyle::drawControl(element, option, painter, widget);
1958 } else if (qobject_cast<const QTableView *>(widget)) {
1959 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags);
1960 } else if (const QHeaderView *header = qobject_cast<const QHeaderView *>(widget)) {
1961 //QS60style draws header background here instead of in each headersection, to get
1962 //continuous graphic from section to section.
1963 QS60StylePrivate::SkinElementFlags adjustableFlags = flags;
1964 QRect headerRect = option->rect;
1965 if (header->orientation() != Qt::Horizontal) {
1966 //todo: update to horizontal table graphic
1967 adjustableFlags = (adjustableFlags | QS60StylePrivate::SF_PointWest);
1968 } else {
1969 const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
1970 if (option->direction == Qt::LeftToRight)
1971 headerRect.adjust(-2 * frameWidth, 0, 0, 0);
1972 else
1973 headerRect.adjust(0, 0, 2 * frameWidth, 0);
1974 }
1975 if (option->palette.brush(QPalette::Button).color() == Qt::transparent)
1976 QS60StylePrivate::drawSkinElement(
1977 QS60StylePrivate::SE_TableHeaderItem, painter, headerRect, adjustableFlags);
1978
1979 } else if (qobject_cast<const QFrame *>(widget)) {
1980 QCommonStyle::drawControl(element, option, painter, widget);
1981 }
1982 break;
1983 case CE_MenuScroller:
1984 break;
1985 case CE_FocusFrame: {
1986#ifdef QT_KEYPAD_NAVIGATION
1987 bool editFocus = false;
1988 if (const QFocusFrame *focusFrame = qobject_cast<const QFocusFrame*>(widget)) {
1989 if (focusFrame->widget() && focusFrame->widget()->hasEditFocus())
1990 editFocus = true;
1991 }
1992 const qreal opacity = editFocus ? 1 : 0.75; // Trial and error factors. Feel free to improve.
1993#else
1994 const qreal opacity = 0.85;
1995#endif
1996 // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin
1997 // Otherwise, we would overlay adjacent widgets.
1998 const int frameHeightReduction =
1999 qMin(0, pixelMetric(PM_LayoutVerticalSpacing)
2000 - pixelMetric(PM_FocusFrameVMargin));
2001 const int frameWidthReduction =
2002 qMin(0, pixelMetric(PM_LayoutHorizontalSpacing)
2003 - pixelMetric(PM_FocusFrameHMargin));
2004 const int rounding =
2005 qMin(pixelMetric(PM_FocusFrameVMargin),
2006 pixelMetric(PM_LayoutVerticalSpacing));
2007 const QRect frameRect =
2008 option->rect.adjusted(-frameWidthReduction, -frameHeightReduction,
2009 frameWidthReduction, frameHeightReduction);
2010 QPainterPath framePath;
2011 framePath.addRoundedRect(frameRect, rounding, rounding);
2012
2013 painter->save();
2014 painter->setRenderHint(QPainter::Antialiasing);
2015 painter->setOpacity(opacity);
2016 painter->fillPath(framePath, option->palette.color(QPalette::Text));
2017 painter->restore();
2018 }
2019 break;
2020 case CE_Splitter:
2021 if (option->state & State_Sunken && option->state & State_Enabled) {
2022 painter->save();
2023 painter->setOpacity(0.5);
2024 painter->setBrush(QS60StylePrivate::themePalette()->light());
2025 painter->setRenderHint(QPainter::Antialiasing);
2026 const qreal roundRectRadius = 4 * goldenRatio;
2027 painter->drawRoundedRect(option->rect, roundRectRadius, roundRectRadius);
2028 painter->restore();
2029 }
2030 break;
2031 default:
2032 QCommonStyle::drawControl(element, option, painter, widget);
2033 }
2034}
2035
2036/*!
2037 \reimp
2038*/
2039void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
2040{
2041 const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
2042 bool commonStyleDraws = false;
2043
2044 switch (element) {
2045 case PE_FrameFocusRect: {
2046 //Draw themed highlight to radiobuttons and checkboxes.
2047 //For other widgets skip, unless palette has been modified. In that case, draw with commonstyle.
2048 if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) {
2049 if ((qstyleoption_cast<const QStyleOptionFocusRect *>(option) &&
2050 (qobject_cast<const QRadioButton *>(widget) || qobject_cast<const QCheckBox *>(widget))))
2051 QS60StylePrivate::drawSkinElement(
2052 QS60StylePrivate::isWidgetPressed(widget) ?
2053 QS60StylePrivate::SE_ListItemPressed :
2054 QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
2055 } else {
2056 commonStyleDraws = true;
2057 }
2058 }
2059 break;
2060#ifndef QT_NO_LINEEDIT
2061 case PE_PanelLineEdit:
2062 if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
2063#ifndef QT_NO_COMBOBOX
2064 if (widget && qobject_cast<const QComboBox *>(widget->parentWidget()))
2065 break;
2066#endif
2067 if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget))
2068 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit, painter, option->rect, flags);
2069 else
2070 commonStyleDraws = true;
2071 }
2072 break;
2073#endif // QT_NO_LINEEDIT
2074 case PE_IndicatorCheckBox: {
2075 // Draw checkbox indicator as color skinned graphics.
2076 const QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ?
2077 QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff;
2078 painter->save();
2079
2080 const QColor themeColor = QS60StylePrivate::themePalette()->windowText().color();
2081 const QColor windowTextColor = option->palette.windowText().color();
2082
2083 if (themeColor != windowTextColor)
2084 painter->setPen(windowTextColor);
2085
2086 QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags | QS60StylePrivate::SF_ColorSkinned );
2087 painter->restore();
2088 }
2089 break;
2090 case PE_IndicatorViewItemCheck:
2091#ifndef QT_NO_ITEMVIEWS
2092 if (const QAbstractItemView *itemView = (qobject_cast<const QAbstractItemView *>(widget))) {
2093 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2094 const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator;
2095 const bool singleSelection = itemView->selectionMode() ==
2096 QAbstractItemView::SingleSelection || itemView->selectionMode() == QAbstractItemView::NoSelection;
2097 // draw either checkbox at the beginning
2098 if (checkBoxVisible && singleSelection) {
2099 drawPrimitive(PE_IndicatorCheckBox, option, painter, widget);
2100 // ... or normal "tick" selection at the end.
2101 } else if (option->state & State_Selected) {
2102 QRect tickRect = option->rect;
2103 const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
2104 // adjust tickmark rect to exclude frame border
2105 tickRect.adjust(0, -frameBorderWidth, 0, -frameBorderWidth);
2106 QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd;
2107 QS60StylePrivate::drawSkinPart(skinPart, painter, tickRect,
2108 (flags | QS60StylePrivate::SF_ColorSkinned));
2109 }
2110 }
2111 }
2112#endif //QT_NO_ITEMVIEWS
2113 break;
2114 case PE_IndicatorRadioButton: {
2115 QRect buttonRect = option->rect;
2116 //there is empty (a. 33%) space in svg graphics for radiobutton
2117 const qreal reduceWidth = (qreal)buttonRect.width() / 3.0;
2118 const qreal rectWidth = (qreal)option->rect.width() != 0 ? option->rect.width() : 1.0;
2119 // Try to occupy the full area
2120 const qreal scaler = 1 + (reduceWidth/rectWidth);
2121 buttonRect.setWidth((int)((buttonRect.width()-reduceWidth) * scaler));
2122 buttonRect.setHeight((int)(buttonRect.height() * scaler));
2123 // move the rect up for half of the new height-gain
2124 const int newY = (buttonRect.bottomRight().y() - option->rect.bottomRight().y()) >> 1 ;
2125 buttonRect.adjust(0, -newY, -1, -newY);
2126
2127 painter->save();
2128 const QColor themeColor = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, option);
2129 const QColor buttonTextColor = option->palette.buttonText().color();
2130 if (themeColor != buttonTextColor)
2131 painter->setPen(buttonTextColor);
2132 else
2133 painter->setPen(themeColor);
2134
2135 // Draw radiobutton indicator as color skinned graphics.
2136 QS60StyleEnums::SkinParts skinPart = (option->state & State_On) ?
2137 QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff;
2138 QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect,
2139 (flags | QS60StylePrivate::SF_ColorSkinned));
2140 painter->restore();
2141 }
2142 break;
2143 case PE_PanelButtonCommand:
2144 case PE_PanelButtonTool:
2145 case PE_PanelButtonBevel:
2146 case PE_FrameButtonBevel:
2147 if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget)) {
2148 const bool isPressed = option->state & State_Sunken;
2149 const QS60StylePrivate::SkinElements skinElement =
2150 isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
2151 QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
2152 } else {
2153 commonStyleDraws = true;
2154 }
2155 break;
2156#ifndef QT_NO_TOOLBUTTON
2157 case PE_IndicatorArrowDown:
2158 case PE_IndicatorArrowLeft:
2159 case PE_IndicatorArrowRight:
2160 case PE_IndicatorArrowUp: {
2161 QS60StyleEnums::SkinParts skinPart;
2162 if (element==PE_IndicatorArrowDown)
2163 skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
2164 else if (element==PE_IndicatorArrowLeft)
2165 skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowLeft;
2166 else if (element==PE_IndicatorArrowRight)
2167 skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowRight;
2168 else if (element==PE_IndicatorArrowUp)
2169 skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowUp;
2170
2171 QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
2172 }
2173 break;
2174#endif //QT_NO_TOOLBUTTON
2175#ifndef QT_NO_SPINBOX
2176 case PE_IndicatorSpinDown:
2177 case PE_IndicatorSpinUp:
2178 if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
2179 if (QS60StylePrivate::canDrawThemeBackground(spinBox->palette.base(), widget)) {
2180 QStyleOptionSpinBox optionSpinBox = *spinBox;
2181 const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ?
2182 QS60StyleEnums::SP_QgnGrafScrollArrowUp :
2183 QS60StyleEnums::SP_QgnGrafScrollArrowDown;
2184 const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
2185 optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
2186 QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect, flags);
2187 } else {
2188 commonStyleDraws = true;
2189 }
2190 }
2191#endif //QT_NO_SPINBOX
2192#ifndef QT_NO_COMBOBOX
2193 if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
2194 if (QS60StylePrivate::canDrawThemeBackground( option->palette.base(), widget)) {
2195 // We want to draw down arrow here for comboboxes as well.
2196 QStyleOptionFrame optionsComboBox = *cmb;
2197 const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
2198 const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
2199 optionsComboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
2200 QS60StylePrivate::drawSkinPart(part, painter, optionsComboBox.rect, flags);
2201 } else {
2202 commonStyleDraws = true;
2203 }
2204 }
2205#endif //QT_NO_COMBOBOX
2206 break;
2207 case PE_IndicatorSpinMinus:
2208 case PE_IndicatorSpinPlus:
2209 if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
2210 QStyleOptionSpinBox optionSpinBox = *spinBox;
2211 QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget);
2212 }
2213#ifndef QT_NO_COMBOBOX
2214 else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
2215 // We want to draw down arrow here for comboboxes as well.
2216 QStyleOptionFrame comboBox = *cmb;
2217 const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
2218 comboBox.rect.adjust(0, frameWidth, 0, -frameWidth);
2219 QCommonStyle::drawPrimitive(element, &comboBox, painter, widget);
2220 }
2221#endif //QT_NO_COMBOBOX
2222 break;
2223 case PE_Widget:
2224 if (QS60StylePrivate::drawsOwnThemeBackground(widget)
2225#ifndef QT_NO_COMBOBOX
2226 || qobject_cast<const QComboBoxListView *>(widget)
2227#endif //QT_NO_COMBOBOX
2228#ifndef QT_NO_MENU
2229 || qobject_cast<const QMenu *> (widget)
2230#endif //QT_NO_MENU
2231 ) {
2232 //Need extra check since dialogs have their own theme background
2233 if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) &&
2234 option->palette.window().texture().cacheKey() ==
2235 QS60StylePrivate::m_themePalette->window().texture().cacheKey())
2236 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, option->rect, flags);
2237 else
2238 commonStyleDraws = true;
2239 }
2240 break;
2241 case PE_FrameWindow:
2242 case PE_FrameTabWidget:
2243 if (const QStyleOptionTabWidgetFrame *tabFrame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
2244 QStyleOptionTabWidgetFrame optionTabFrame = *tabFrame;
2245 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PanelBackground, painter, optionTabFrame.rect, flags);
2246 }
2247 break;
2248 case PE_IndicatorHeaderArrow:
2249 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2250 if (header->sortIndicator & QStyleOptionHeader::SortUp)
2251 drawPrimitive(PE_IndicatorArrowUp, header, painter, widget);
2252 else if (header->sortIndicator & QStyleOptionHeader::SortDown)
2253 drawPrimitive(PE_IndicatorArrowDown, header, painter, widget);
2254 } // QStyleOptionHeader::None is not drawn => not needed
2255 break;
2256#ifndef QT_NO_GROUPBOX
2257 case PE_FrameGroupBox:
2258 if (const QStyleOptionFrameV2 *frame = qstyleoption_cast<const QStyleOptionFrameV2 *>(option))
2259 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_SettingsList, painter, frame->rect, flags);
2260 break;
2261#endif //QT_NO_GROUPBOX
2262
2263 // Qt3 primitives are not supported
2264 case PE_Q3CheckListController:
2265 case PE_Q3CheckListExclusiveIndicator:
2266 case PE_Q3CheckListIndicator:
2267 case PE_Q3DockWindowSeparator:
2268 case PE_Q3Separator:
2269 Q_ASSERT(false);
2270 break;
2271 case PE_Frame:
2272 break;
2273#ifndef QT_NO_ITEMVIEWS
2274 case PE_PanelItemViewItem:
2275 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2276 const bool isSelected = (vopt->state & State_Selected);
2277 const bool hasFocus = (vopt->state & State_HasFocus);
2278 const bool isPressed = QS60StylePrivate::isWidgetPressed(widget);
2279
2280 if (option->palette.highlight().color() == QS60StylePrivate::themePalette()->highlight().color()) {
2281 QRect highlightRect = vopt->rect.adjusted(1,1,-1,-1);
2282 const QAbstractItemView *itemView = qobject_cast<const QAbstractItemView *>(widget);
2283 QAbstractItemView::SelectionBehavior selectionBehavior =
2284 itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems;
2285 // Set the draw area for highlights (focus, select rect or pressed rect)
2286 if (hasFocus || isSelected || isPressed) {
2287 if (selectionBehavior != QAbstractItemView::SelectItems) {
2288 // set highlight rect so that it is continuous from cell to cell, yet sligthly
2289 // smaller than cell rect
2290 int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0;
2291 if (selectionBehavior == QAbstractItemView::SelectRows) {
2292 yBeginning = 1; yEnd = -1;
2293 if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
2294 xBeginning = 1;
2295 else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
2296 xEnd = -1;
2297 } else if (selectionBehavior == QAbstractItemView::SelectColumns) {
2298 xBeginning = 1; xEnd = -1;
2299 if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning)
2300 yBeginning = 1;
2301 else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End)
2302 yEnd = -1;
2303 }
2304 highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd);
2305 }
2306 }
2307 bool tableView = false;
2308 if (itemView && qobject_cast<const QTableView *>(widget))
2309 tableView = true;
2310
2311 QS60StylePrivate::SkinElements element;
2312 QRect elementRect = option->rect;
2313
2314 //draw item is drawn as pressed, if it already has focus.
2315 if (isPressed && (hasFocus || isSelected)) {
2316 element = tableView ? QS60StylePrivate::SE_TableItemPressed : QS60StylePrivate::SE_ListItemPressed;
2317 } else if (hasFocus || (isSelected && selectionBehavior != QAbstractItemView::SelectItems)) {
2318 element = QS60StylePrivate::SE_ListHighlight;
2319 elementRect = highlightRect;
2320 }
2321 QS60StylePrivate::drawSkinElement(element, painter, elementRect, flags);
2322 } else {
2323 QCommonStyle::drawPrimitive(element, option, painter, widget);
2324 }
2325 }
2326 break;
2327#endif //QT_NO_ITEMVIEWS
2328
2329 case PE_IndicatorMenuCheckMark:
2330 if (const QStyleOptionMenuItem *checkBox = qstyleoption_cast<const QStyleOptionMenuItem *>(option)){
2331 QStyleOptionMenuItem optionCheckBox = *checkBox;
2332 if (optionCheckBox.checked)
2333 optionCheckBox.state = (optionCheckBox.state | State_On);
2334 drawPrimitive(PE_IndicatorCheckBox, &optionCheckBox, painter, widget);
2335 }
2336 break;
2337#ifndef QT_NO_TOOLBAR
2338 case PE_IndicatorToolBarHandle:
2339 // no toolbar handles in S60/AVKON UI
2340 case PE_IndicatorToolBarSeparator:
2341 // no separators in S60/AVKON UI
2342 break;
2343#endif //QT_NO_TOOLBAR
2344
2345 case PE_PanelMenuBar:
2346 case PE_FrameMenu:
2347 break; //disable frame in menu
2348
2349 case PE_IndicatorBranch:
2350#if defined(Q_WS_S60)
2351 // 3.1 AVKON UI does not have tree view component, use common style for drawing there
2352 if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1) {
2353#else
2354 if (true) {
2355#endif
2356 QCommonStyle::drawPrimitive(element, option, painter, widget);
2357 } else {
2358 if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(option)) {
2359 const bool rightLine = option->state & State_Item;
2360 const bool downLine = option->state & State_Sibling;
2361 const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling);
2362 QS60StylePrivate::SkinElementFlags adjustedFlags = flags;
2363
2364 QS60StyleEnums::SkinParts skinPart;
2365 bool drawSkinPart = false;
2366 if (rightLine && downLine && upLine) {
2367 skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch;
2368 drawSkinPart = true;
2369 } else if (rightLine && upLine) {
2370 skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd;
2371 drawSkinPart = true;
2372 } else if (upLine && downLine) {
2373 skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight;
2374 drawSkinPart = true;
2375 }
2376
2377 if (option->direction == Qt::RightToLeft)
2378 adjustedFlags |= QS60StylePrivate::SF_Mirrored_X_Axis;
2379
2380 if (drawSkinPart)
2381 QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, adjustedFlags);
2382
2383 if (option->state & State_Children) {
2384 QS60StyleEnums::SkinParts skinPart =
2385 (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper;
2386 const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
2387 const int minDimension = qMin(option->rect.width(), option->rect.height());
2388 const int magicTweak = (option->direction == Qt::RightToLeft) ? -3 : 3; //@todo: magic
2389 //The branch indicator icon in S60 is supposed to be superimposed on top of branch lines.
2390 QRect iconRect(QPoint(option->rect.left() + magicTweak, selectionRect.top() + 1), QSize(minDimension, minDimension));
2391 if (!QS60StylePrivate::isTouchSupported())
2392 iconRect.translate(0, -4); //@todo: magic
2393 QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, adjustedFlags);
2394 }
2395 }
2396 }
2397 break;
2398 case PE_PanelItemViewRow: // ### Qt 5: remove
2399#ifndef QT_NO_ITEMVIEWS
2400 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
2401 if (vopt->palette.base().texture().cacheKey() != QS60StylePrivate::m_themePalette->base().texture().cacheKey()) {
2402 //QPalette::Base has been changed, let commonstyle draw the item
2403 commonStyleDraws = true;
2404 } else {
2405 QPalette::ColorGroup cg = vopt->state & State_Enabled ? QPalette::Normal : QPalette::Disabled;
2406 if (cg == QPalette::Normal && !(vopt->state & State_Active))
2407 cg = QPalette::Inactive;
2408 if (vopt->features & QStyleOptionViewItemV2::Alternate)
2409 painter->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
2410 //apart from alternate base, no background for list item is drawn for S60Style
2411 }
2412 }
2413#endif
2414 break;
2415 case PE_PanelScrollAreaCorner:
2416 break;
2417 case PE_IndicatorItemViewItemDrop:
2418 if (QS60StylePrivate::isTouchSupported())
2419 QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_DropArea, painter, option->rect, flags);
2420 else
2421 commonStyleDraws = true;
2422 break;
2423 // todo: items are below with #ifdefs "just in case". in final version, remove all non-required cases
2424 case PE_FrameLineEdit:
2425 case PE_IndicatorDockWidgetResizeHandle:
2426 case PE_PanelTipLabel:
2427
2428#ifndef QT_NO_TABBAR
2429 case PE_IndicatorTabTear: // No tab tear in S60
2430#endif // QT_NO_TABBAR
2431 case PE_FrameDefaultButton:
2432#ifndef QT_NO_DOCKWIDGET
2433 case PE_FrameDockWidget:
2434#endif //QT_NO_DOCKWIDGET
2435#ifndef QT_NO_PROGRESSBAR
2436 case PE_IndicatorProgressChunk:
2437#endif //QT_NO_PROGRESSBAR
2438#ifndef QT_NO_TOOLBAR
2439 case PE_PanelToolBar:
2440#endif //QT_NO_TOOLBAR
2441#ifndef QT_NO_COLUMNVIEW
2442 case PE_IndicatorColumnViewArrow:
2443#endif //QT_NO_COLUMNVIEW
2444 case PE_FrameTabBarBase: // since tabs are in S60 always in navipane, let's use common style for tab base in Qt.
2445 default:
2446 commonStyleDraws = true;
2447 }
2448 if (commonStyleDraws) {
2449 QCommonStyle::drawPrimitive(element, option, painter, widget);
2450 }
2451}
2452
2453/*! \reimp */
2454int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2455{
2456 int metricValue = QS60StylePrivate::pixelMetric(metric);
2457 if (metricValue == KNotFound)
2458 metricValue = QCommonStyle::pixelMetric(metric, option, widget);
2459
2460 // Menu scrollers should be set to zero height for combobox popups
2461 if (metric == PM_MenuScrollerHeight && !qobject_cast<const QMenu *>(widget))
2462 metricValue = 0;
2463
2464 //if layout direction is mirrored, switch left and right border margins
2465 if (option && option->direction == Qt::RightToLeft) {
2466 if (metric == PM_LayoutLeftMargin)
2467 metricValue = QS60StylePrivate::pixelMetric(PM_LayoutRightMargin);
2468 else if (metric == PM_LayoutRightMargin)
2469 metricValue = QS60StylePrivate::pixelMetric(PM_LayoutLeftMargin);
2470 }
2471
2472 if (widget && (metric == PM_LayoutTopMargin))
2473 if (widget->windowType() == Qt::Dialog)
2474 //double the top layout margin for dialogs, it is very close to real value
2475 //without having to define custom pixel metric
2476 metricValue *= 2;
2477
2478 if (widget && (metric == PM_FocusFrameHMargin))
2479 if (qobject_cast<const QTableView *>(widget))
2480 //Halve the focus frame margin for table items
2481 metricValue /= 2;
2482
2483 return metricValue;
2484}
2485
2486/*! \reimp */
2487QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
2488 const QSize &csz, const QWidget *widget) const
2489{
2490 QSize sz(csz);
2491 switch (ct) {
2492 case CT_ToolButton:
2493 sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
2494 //FIXME properly - style should calculate the location of border frame-part
2495 sz += QSize(2 * pixelMetric(PM_ButtonMargin), 2 * pixelMetric(PM_ButtonMargin));
2496 if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(opt))
2497 if (toolBtn->subControls & SC_ToolButtonMenu)
2498 sz += QSize(pixelMetric(PM_MenuButtonIndicator), 0);
2499 break;
2500 case CT_PushButton:
2501 sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
2502 //FIXME properly - style should calculate the location of border frame-part
2503 if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget))) {
2504 if (buttonWidget->isCheckable())
2505 sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0);
2506 const int iconHeight = (!buttonWidget->icon().isNull()) ? buttonWidget->iconSize().height() : 0;
2507 const int textHeight = (buttonWidget->text().length() > 0) ?
2508 buttonWidget->fontMetrics().size(Qt::TextSingleLine, buttonWidget->text()).height() : opt->fontMetrics.height();
2509 const int decoratorHeight = (buttonWidget->isCheckable()) ? pixelMetric(PM_IndicatorHeight) : 0;
2510
2511 const int contentHeight =
2512 qMax(qMax(iconHeight, decoratorHeight) + pixelMetric(PM_ButtonMargin),
2513 textHeight + 2*pixelMetric(PM_ButtonMargin));
2514 sz.setHeight(qMax(sz.height(), contentHeight));
2515 sz += QSize(2 * pixelMetric(PM_ButtonMargin), 0);
2516 }
2517 break;
2518 case CT_LineEdit:
2519 if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt))
2520 sz += QSize(2 * f->lineWidth, 4 * f->lineWidth);
2521 break;
2522 case CT_TabBarTab: {
2523 const QSize naviPaneSize = QS60StylePrivate::naviPaneSize();
2524 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget);
2525 if (naviPaneSize.height() > sz.height())
2526 sz.setHeight(naviPaneSize.height());
2527 // Adjust beginning tabbar item size, if scrollbuttons are used. This is to ensure that the
2528 // tabbar item content fits, since scrollbuttons are making beginning tabbar item smaller.
2529 int scrollButtonSize = 0;
2530 if (const QTabBar *tabBar = qobject_cast<const QTabBar *>(widget))
2531 scrollButtonSize = tabBar->usesScrollButtons() ? pixelMetric(PM_TabBarScrollButtonWidth) : 0;
2532 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
2533 const bool verticalTabs = tab->shape == QTabBar::RoundedEast
2534 || tab->shape == QTabBar::RoundedWest
2535 || tab->shape == QTabBar::TriangularEast
2536 || tab->shape == QTabBar::TriangularWest;
2537 if (tab->position == QStyleOptionTab::Beginning)
2538 sz += QSize(verticalTabs ? 0 : scrollButtonSize, !verticalTabs ? 0 : scrollButtonSize);
2539 }
2540 }
2541 break;
2542 case CT_MenuItem:
2543 case CT_ItemViewItem:
2544 if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
2545 if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
2546 sz = QSize();
2547 break;
2548 }
2549 }
2550 sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
2551 if (QS60StylePrivate::isTouchSupported())
2552 //Make itemview easier to use in touch devices
2553 //QCommonStyle does not adjust height with horizontal margin, it only adjusts width
2554 sz.setHeight(sz.height() + 2 * pixelMetric(PM_FocusFrameVMargin));
2555 break;
2556#ifndef QT_NO_COMBOBOX
2557 case CT_ComboBox: {
2558 // Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints
2559 // Make sure, that the combobox stays within the screen.
2560 const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size()
2561 - QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0);
2562 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget).
2563 boundedTo(desktopContentSize);
2564 }
2565 break;
2566#endif
2567 default:
2568 sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
2569 break;
2570 }
2571 return sz;
2572}
2573
2574/*! \reimp */
2575int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,
2576 QStyleHintReturn *hret) const
2577{
2578 int retValue = 0;
2579 switch (sh) {
2580 case SH_RequestSoftwareInputPanel:
2581 if (QS60StylePrivate::isSingleClickUi())
2582 retValue = RSIP_OnMouseClick;
2583 else
2584 retValue = RSIP_OnMouseClickAndAlreadyFocused;
2585 break;
2586 case SH_ComboBox_Popup:
2587 retValue = true;
2588 break;
2589 case SH_Table_GridLineColor:
2590 retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 2, 0).rgba());
2591 break;
2592 case SH_GroupBox_TextLabelColor:
2593 retValue = int(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0).rgba());
2594 break;
2595 case SH_ScrollBar_ScrollWhenPointerLeavesControl:
2596 retValue = true;
2597 break;
2598 case SH_Slider_SnapToValue:
2599 retValue = true;
2600 break;
2601 case SH_Slider_StopMouseOverSlider:
2602 retValue = true;
2603 break;
2604 case SH_LineEdit_PasswordCharacter:
2605 retValue = '*';
2606 break;
2607 case SH_ComboBox_PopupFrameStyle:
2608 retValue = QFrame::NoFrame | QFrame::Plain;
2609 break;
2610 case SH_Dial_BackgroundRole:
2611 retValue = QPalette::Base;
2612 break;
2613 case SH_ItemView_ActivateItemOnSingleClick: {
2614 if (QS60StylePrivate::isSingleClickUi())
2615 retValue = true;
2616 else if (opt && opt->state & QStyle::State_Selected)
2617 retValue = true;
2618 break;
2619 }
2620 case SH_ProgressDialog_TextLabelAlignment:
2621 retValue = (QApplication::layoutDirection() == Qt::LeftToRight) ?
2622 Qt::AlignLeft :
2623 Qt::AlignRight;
2624 break;
2625 case SH_Menu_SubMenuPopupDelay:
2626 retValue = 300;
2627 break;
2628 case SH_Menu_Scrollable:
2629 retValue = true;
2630 break;
2631 case SH_Menu_SelectionWrap:
2632 retValue = true;
2633 break;
2634 case SH_Menu_MouseTracking:
2635 retValue = true;
2636 break;
2637 case SH_ItemView_ShowDecorationSelected:
2638 retValue = true;
2639 break;
2640 case SH_ToolBar_Movable:
2641 retValue = false;
2642 break;
2643 case SH_BlinkCursorWhenTextSelected:
2644 retValue = true;
2645 break;
2646 case SH_UnderlineShortcut:
2647 retValue = 0;
2648 break;
2649 case SH_FormLayoutWrapPolicy:
2650 retValue = QFormLayout::WrapLongRows;
2651 break;
2652 case SH_ScrollBar_ContextMenu:
2653 retValue = false;
2654 break;
2655 default:
2656 retValue = QCommonStyle::styleHint(sh, opt, widget, hret);
2657 break;
2658 }
2659 return retValue;
2660}
2661
2662/*! \reimp */
2663QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget) const
2664{
2665 QRect ret;
2666 switch (control) {
2667#ifndef QT_NO_SCROLLBAR
2668 // This implementation of subControlRect(CC_ScrollBar..) basically just removes the SC_ScrollBarSubLine and SC_ScrollBarAddLine
2669 case CC_ScrollBar:
2670 if (const QStyleOptionSlider *scrollbarOption = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
2671 const QRect scrollBarRect = scrollbarOption->rect;
2672 const bool isHorizontal = scrollbarOption->orientation == Qt::Horizontal;
2673 const int maxlen = isHorizontal ? scrollBarRect.width() : scrollBarRect.height();
2674 int sliderlen;
2675
2676 // calculate slider length
2677 if (scrollbarOption->maximum != scrollbarOption->minimum) {
2678 const uint range = scrollbarOption->maximum - scrollbarOption->minimum;
2679 sliderlen = (qint64(scrollbarOption->pageStep) * maxlen) / (range + scrollbarOption->pageStep);
2680
2681 const int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbarOption, widget);
2682 if (sliderlen < slidermin || range > (INT_MAX >> 1))
2683 sliderlen = slidermin;
2684 if (sliderlen > maxlen)
2685 sliderlen = maxlen;
2686 } else {
2687 sliderlen = maxlen;
2688 }
2689
2690 const int sliderstart = sliderPositionFromValue(scrollbarOption->minimum,
2691 scrollbarOption->maximum,
2692 scrollbarOption->sliderPosition,
2693 maxlen - sliderlen,
2694 scrollbarOption->upsideDown);
2695
2696 switch (scontrol) {
2697 case SC_ScrollBarSubPage: // between top/left button and slider
2698 if (isHorizontal)
2699 ret.setRect(0, 0, sliderstart, scrollBarRect.height());
2700 else
2701 ret.setRect(0, 0, scrollBarRect.width(), sliderstart);
2702 break;
2703 case SC_ScrollBarAddPage: { // between bottom/right button and slider
2704 const int addPageLength = sliderstart + sliderlen;
2705 if (isHorizontal)
2706 ret = scrollBarRect.adjusted(addPageLength, 0, 0, 0);
2707 else
2708 ret = scrollBarRect.adjusted(0, addPageLength, 0, 0);
2709 }
2710 break;
2711 case SC_ScrollBarGroove:
2712 ret = scrollBarRect;
2713 break;
2714 case SC_ScrollBarSlider:
2715 if (scrollbarOption->orientation == Qt::Horizontal)
2716 ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height());
2717 else
2718 ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen);
2719 break;
2720 case SC_ScrollBarSubLine: // top/left button
2721 case SC_ScrollBarAddLine: // bottom/right button
2722 default:
2723 break;
2724 }
2725 ret = visualRect(scrollbarOption->direction, scrollBarRect, ret);
2726 }
2727 break;
2728#endif // QT_NO_SCROLLBAR
2729 case CC_SpinBox:
2730 if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
2731 const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
2732 const int buttonMargin = spinbox->frame ? 2 : 0;
2733 const int buttonContentWidth = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin;
2734 // Spinbox buttons should be no larger than one fourth of total width.
2735 // Thus, side-by-side buttons would take half of the total width.
2736 const int maxSize = qMax(spinbox->rect.width() / 4, buttonContentWidth);
2737 QSize buttonSize;
2738 buttonSize.setHeight(qMin(maxSize, qMax(8, spinbox->rect.height() - frameThickness)));
2739 //width should at least be equal to height
2740 buttonSize.setWidth(qMax(buttonSize.height(), buttonContentWidth));
2741 buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
2742
2743 // Normally spinbuttons should be side-by-side, but if spinbox grows very big
2744 // and spinbuttons reach their maximum size, they can be deployed one top of the other.
2745 const bool sideBySide = (buttonSize.height() * 2 < spinbox->rect.height()) ? false : true;
2746 const int y = frameThickness + spinbox->rect.y() +
2747 (spinbox->rect.height() - (sideBySide ? 1 : 2) * buttonSize.height()) / 2;
2748 const int x = spinbox->rect.x() +
2749 spinbox->rect.width() - frameThickness - (sideBySide ? 2 : 1) * buttonSize.width();
2750
2751 switch (scontrol) {
2752 case SC_SpinBoxUp:
2753 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
2754 return QRect();
2755 ret = QRect(x, y, buttonSize.width(), buttonSize.height());
2756 break;
2757 case SC_SpinBoxDown:
2758 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
2759 return QRect();
2760 ret = QRect(x + (sideBySide ? buttonSize.width() : 0),
2761 y + (sideBySide ? 0 : buttonSize.height()),
2762 buttonSize.width(), buttonSize.height());
2763 break;
2764 case SC_SpinBoxEditField:
2765 if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
2766 ret = QRect(
2767 frameThickness,
2768 frameThickness,
2769 spinbox->rect.width() - 2 * frameThickness,
2770 spinbox->rect.height() - 2 * frameThickness);
2771 else
2772 ret = QRect(
2773 frameThickness,
2774 frameThickness,
2775 x - frameThickness,
2776 spinbox->rect.height() - 2 * frameThickness);
2777 break;
2778 case SC_SpinBoxFrame:
2779 ret = spinbox->rect;
2780 break;
2781 default:
2782 break;
2783 }
2784 ret = visualRect(spinbox->direction, spinbox->rect, ret);
2785 }
2786 break;
2787 case CC_ComboBox:
2788 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
2789 ret = cmb->rect;
2790 const int width = cmb->rect.width();
2791 const int height = cmb->rect.height();
2792 const int buttonIconSize = QS60StylePrivate::pixelMetric(PM_ButtonIconSize);
2793 const int buttonMargin = cmb->frame ? 2 : 0;
2794 // lets use spinbox frame here as well, as no combobox specific value available.
2795 const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0;
2796 const int buttonWidth = qMax(cmb->rect.height(), buttonIconSize);
2797
2798 QSize buttonSize;
2799 buttonSize.setWidth(buttonWidth + 2 * buttonMargin);
2800 buttonSize.setHeight(qMax(8, (cmb->rect.height() >> 1) - frameThickness)); //buttons should be squares
2801 buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
2802 switch (scontrol) {
2803 case SC_ComboBoxArrow: {
2804 const int xposMod = cmb->rect.x() + width - buttonMargin - buttonWidth;
2805 const int ypos = cmb->rect.y();
2806 ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2 * buttonMargin);
2807 }
2808 break;
2809 case SC_ComboBoxEditField: {
2810 const int withFrameX = cmb->rect.x() + width - frameThickness - buttonSize.width();
2811 ret = QRect(
2812 frameThickness,
2813 frameThickness,
2814 withFrameX - frameThickness,
2815 height - 2 * frameThickness);
2816 }
2817 break;
2818 case SC_ComboBoxListBoxPopup: {
2819 const QRect desktopContent = QApplication::desktop()->availableGeometry();
2820
2821 // take the size of this and position bottom above available area
2822 QRect popupRect;
2823 const int width = desktopContent.width() - pixelMetric(PM_LayoutRightMargin) - pixelMetric(PM_LayoutLeftMargin);
2824 popupRect.setWidth(width);
2825 popupRect.setHeight(desktopContent.height()); //combobox resets height anyway based on content
2826 popupRect.setBottom(desktopContent.bottom());
2827 popupRect.translate(pixelMetric(PM_LayoutLeftMargin), 0);
2828 ret = popupRect;
2829 }
2830 break;
2831 default:
2832 break;
2833 }
2834 ret = visualRect(cmb->direction, cmb->rect, ret);
2835 }
2836 break;
2837 case CC_GroupBox:
2838 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
2839 ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
2840 switch (scontrol) {
2841 case SC_GroupBoxCheckBox: //fallthrough
2842 case SC_GroupBoxLabel: {
2843 //slightly indent text and boxes, so that dialog border does not mess with them.
2844 const int horizontalSpacing =
2845 QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing);
2846 ret.adjust(2, horizontalSpacing - 3, 0, 0);
2847 }
2848 break;
2849 case SC_GroupBoxFrame: {
2850 const QRect textBox = subControlRect(control, option, SC_GroupBoxLabel, widget);
2851 const int tbHeight = textBox.height();
2852 ret.translate(0, -ret.y());
2853 // include title to within the groupBox frame
2854 ret.setHeight(ret.height() + tbHeight);
2855 if (widget && ret.bottom() > widget->rect().bottom())
2856 ret.setBottom(widget->rect().bottom());
2857 }
2858 break;
2859 default:
2860 break;
2861 }
2862 }
2863 break;
2864 case CC_ToolButton:
2865 if (const QStyleOptionToolButton *toolButton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
2866 const int indicatorRect = pixelMetric(PM_MenuButtonIndicator) + 2 * pixelMetric(PM_ButtonMargin);
2867 const int border = pixelMetric(PM_ButtonMargin) + pixelMetric(PM_DefaultFrameWidth);
2868 ret = toolButton->rect;
2869 const bool popup = (toolButton->features &
2870 (QStyleOptionToolButton::MenuButtonPopup | QStyleOptionToolButton::PopupDelay))
2871 == QStyleOptionToolButton::MenuButtonPopup;
2872 switch (scontrol) {
2873 case SC_ToolButton:
2874 if (popup)
2875 ret.adjust(0, 0, -indicatorRect, 0);
2876 break;
2877 case SC_ToolButtonMenu:
2878 if (popup)
2879 ret.adjust(ret.width() - indicatorRect, border, -pixelMetric(PM_ButtonMargin), -border);
2880 break;
2881 default:
2882 break;
2883 }
2884 ret = visualRect(toolButton->direction, toolButton->rect, ret);
2885 }
2886 break;
2887 default:
2888 ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
2889 }
2890 return ret;
2891}
2892
2893/*!
2894 \reimp
2895*/
2896QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget) const
2897{
2898 QRect ret;
2899 switch (element) {
2900 case SE_RadioButtonFocusRect:
2901 ret = opt->rect;
2902 break;
2903 case SE_LineEditContents: {
2904 // in S60 the input text box doesn't start from line Edit's TL, but
2905 // a bit indented (8 pixels).
2906 const int KLineEditDefaultIndention = 8;
2907 ret = visualRect(
2908 opt->direction, opt->rect, opt->rect.adjusted(KLineEditDefaultIndention, 0, 0, 0));
2909 }
2910 break;
2911 case SE_TabBarTearIndicator:
2912 ret = QRect(0, 0, 0, 0);
2913 break;
2914 case SE_TabWidgetTabBar:
2915 if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2916 ret = QCommonStyle::subElementRect(element, opt, widget);
2917
2918 if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
2919 const int tabOverlapNoBorder =
2920 QS60StylePrivate::pixelMetric(PM_TabBarTabOverlap);
2921 const int tabOverlap =
2922 tabOverlapNoBorder - QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
2923 const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget);
2924 int gain = (tab) ? tabOverlap * tab->count() : 0;
2925 switch (twf->shape) {
2926 case QTabBar::RoundedNorth:
2927 case QTabBar::TriangularNorth:
2928 case QTabBar::RoundedSouth:
2929 case QTabBar::TriangularSouth: {
2930 if (widget) {
2931 // make sure that gain does not set the rect outside of widget boundaries
2932 if (twf->direction == Qt::RightToLeft) {
2933 if ((ret.left() - gain) < widget->rect().left())
2934 gain = widget->rect().left() - ret.left();
2935 ret.adjust(-gain, 0, 0, 0);
2936 } else {
2937 if ((ret.right() + gain) > widget->rect().right())
2938 gain = widget->rect().right() - ret.right();
2939 ret.adjust(0, 0, gain, 0);
2940 }
2941 }
2942 break;
2943 }
2944 default: {
2945 if (widget) {
2946 if ((ret.bottom() + gain) > widget->rect().bottom())
2947 gain = widget->rect().bottom() - ret.bottom();
2948 ret.adjust(0, 0, 0, gain);
2949 }
2950 break;
2951 }
2952 }
2953 }
2954 }
2955 break;
2956 case SE_ItemViewItemText:
2957 case SE_ItemViewItemDecoration:
2958 if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
2959 const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
2960 const bool multiSelection = !listItem ? false :
2961 listItem->selectionMode() == QAbstractItemView::MultiSelection ||
2962 listItem->selectionMode() == QAbstractItemView::ExtendedSelection ||
2963 listItem->selectionMode() == QAbstractItemView::ContiguousSelection;
2964 ret = QCommonStyle::subElementRect(element, opt, widget);
2965 // If both multiselect & check-state, then remove checkbox and move
2966 // text and decoration towards the beginning
2967 if (listItem &&
2968 multiSelection &&
2969 (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)) {
2970 const int verticalSpacing =
2971 QS60StylePrivate::pixelMetric(PM_LayoutVerticalSpacing);
2972 //const int horizontalSpacing = QS60StylePrivate::pixelMetric(PM_LayoutHorizontalSpacing);
2973 const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width();
2974 ret.adjust(-checkBoxRectWidth - verticalSpacing, 0, -checkBoxRectWidth - verticalSpacing, 0);
2975 }
2976 } else if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
2977 const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
2978 const int indicatorWidth = checkable ?
2979 pixelMetric(PM_ListViewIconSize, opt, widget) :
2980 pixelMetric(PM_SmallIconSize, opt, widget);
2981 ret = menuItem->rect;
2982
2983 if (element == SE_ItemViewItemDecoration) {
2984 if (menuItem->icon.isNull()) {
2985 ret = QRect();
2986 } else {
2987 if (menuItem->direction == Qt::RightToLeft)
2988 ret.translate(ret.width() - indicatorWidth, 0);
2989 ret.setWidth(indicatorWidth);
2990 }
2991 } else {
2992 ret = menuItem->rect;
2993 if (!menuItem->icon.isNull())
2994 if (menuItem->direction == Qt::LeftToRight)
2995 ret.adjust(indicatorWidth, 0, 0, 0);
2996 else
2997 ret.adjust(0, 0, -indicatorWidth, 0);
2998
2999 // Make room for submenu indicator
3000 if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){
3001 // submenu indicator is very small, so lets halve the rect
3002 if (menuItem->direction == Qt::LeftToRight)
3003 ret.adjust(0, 0, -(indicatorWidth >> 1), 0);
3004 else
3005 ret.adjust((indicatorWidth >> 1), 0, 0, 0);
3006 }
3007 }
3008 }
3009 break;
3010 case SE_ItemViewItemCheckIndicator:
3011 if (const QStyleOptionViewItemV2 *vopt = qstyleoption_cast<const QStyleOptionViewItemV2 *>(opt)) {
3012 const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
3013
3014 const bool singleSelection = listItem &&
3015 (listItem->selectionMode() == QAbstractItemView::SingleSelection ||
3016 listItem->selectionMode() == QAbstractItemView::NoSelection);
3017 const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) &&
3018 listItem &&
3019 singleSelection;
3020
3021 // Selection check mark rect.
3022 const int indicatorWidth = QS60StylePrivate::pixelMetric(PM_IndicatorWidth);
3023 const int indicatorHeight = QS60StylePrivate::pixelMetric(PM_IndicatorHeight);
3024 const int spacing = QS60StylePrivate::pixelMetric(PM_CheckBoxLabelSpacing);
3025
3026 const int itemHeight = opt->rect.height();
3027 int heightOffset = 0;
3028 if (indicatorHeight < itemHeight)
3029 heightOffset = ((itemHeight - indicatorHeight) >> 1);
3030 if (checkBoxOnly) {
3031 // Move rect and make it slightly smaller, so that
3032 // a) highlight border does not cross the rect
3033 // b) in s60 list checkbox is smaller than normal checkbox
3034 //todo; magic three
3035 ret.setRect(opt->rect.left() + 3, opt->rect.top() + heightOffset,
3036 indicatorWidth - 3, indicatorHeight - 3);
3037 } else {
3038 ret.setRect(opt->rect.right() - indicatorWidth - spacing, opt->rect.top() + heightOffset,
3039 indicatorWidth, indicatorHeight);
3040 }
3041 } else {
3042 ret = QCommonStyle::subElementRect(element, opt, widget);
3043 }
3044 break;
3045 case SE_HeaderLabel:
3046 ret = QCommonStyle::subElementRect(element, opt, widget);
3047 if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
3048 // Subtract area needed for line
3049 if (opt->state & State_Horizontal)
3050 ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_BoldLineWidth));
3051 else
3052 ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_ThinLineWidth));
3053 }
3054 ret = visualRect(opt->direction, opt->rect, ret);
3055 break;
3056 case SE_RadioButtonIndicator: {
3057 const int height = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
3058 ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1),
3059 pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), height);
3060 ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it
3061 ret = visualRect(opt->direction, opt->rect, ret);
3062 }
3063 break;
3064 case SE_CheckBoxIndicator: {
3065 const int height = pixelMetric(PM_IndicatorHeight, opt, widget);
3066 ret.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - height) >> 1),
3067 pixelMetric(PM_IndicatorWidth, opt, widget), height);
3068 ret.translate(2, 0); //move indicator slightly to avoid highlight crossing over it
3069 ret = visualRect(opt->direction, opt->rect, ret);
3070 }
3071 break;
3072 case SE_CheckBoxFocusRect:
3073 ret = opt->rect;
3074 break;
3075 default:
3076 ret = QCommonStyle::subElementRect(element, opt, widget);
3077 }
3078 return ret;
3079}
3080
3081/*!
3082 \reimp
3083 */
3084void QS60Style::polish(QWidget *widget)
3085{
3086 Q_D(const QS60Style);
3087 QCommonStyle::polish(widget);
3088
3089 if (!widget)
3090 return;
3091
3092 //Currently we only support animations in QProgressBar.
3093#ifndef QT_NO_PROGRESSBAR
3094 if (qobject_cast<QProgressBar *>(widget))
3095 widget->installEventFilter(this);
3096#endif
3097
3098 if (false
3099#ifndef QT_NO_SCROLLBAR
3100 || qobject_cast<QScrollBar *>(widget)
3101#endif
3102 ) {
3103 widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
3104 }
3105
3106 if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
3107 widget->setAttribute(Qt::WA_StyledBackground);
3108 } else if (false
3109#ifndef QT_NO_MENU
3110 || qobject_cast<const QMenu *> (widget)
3111#endif // QT_NO_MENU
3112 ) {
3113 widget->setAttribute(Qt::WA_StyledBackground);
3114 } else if (false
3115#ifndef QT_NO_COMBOBOX
3116 || qobject_cast<const QComboBoxListView *>(widget)
3117#endif //QT_NO_COMBOBOX
3118 ) {
3119 widget->setAttribute(Qt::WA_StyledBackground);
3120 }
3121 d->setThemePalette(widget);
3122 d->setFont(widget);
3123}
3124
3125/*!
3126 \reimp
3127 */
3128void QS60Style::unpolish(QWidget *widget)
3129{
3130 Q_D(QS60Style);
3131
3132 if (false
3133 #ifndef QT_NO_SCROLLBAR
3134 || qobject_cast<QScrollBar *>(widget)
3135 #endif
3136 )
3137 widget->setAttribute(Qt::WA_OpaquePaintEvent);
3138
3139 if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
3140 widget->setAttribute(Qt::WA_StyledBackground, false);
3141 } else if (false
3142#ifndef QT_NO_MENU
3143 || qobject_cast<const QMenu *> (widget)
3144#endif // QT_NO_MENU
3145 ) {
3146 widget->setAttribute(Qt::WA_StyledBackground, false);
3147 } else if (false
3148#ifndef QT_NO_COMBOBOX
3149 || qobject_cast<const QComboBoxListView *>(widget)
3150#endif //QT_NO_COMBOBOX
3151 ) {
3152 widget->setAttribute(Qt::WA_StyledBackground, false);
3153 }
3154
3155 if (widget)
3156 widget->setPalette(QPalette());
3157
3158#if defined(Q_WS_S60) && !defined(QT_NO_PROGRESSBAR)
3159 if (QProgressBar *bar = qobject_cast<QProgressBar *>(widget)) {
3160 widget->removeEventFilter(this);
3161 d->m_bars.removeAll(bar);
3162 }
3163#else
3164 Q_UNUSED(d)
3165#endif
3166 QCommonStyle::unpolish(widget);
3167}
3168
3169/*!
3170 \reimp
3171 */
3172void QS60Style::polish(QApplication *application)
3173{
3174 Q_D(QS60Style);
3175 QCommonStyle::polish(qApp);
3176 d->m_originalPalette = application->palette();
3177 d->setThemePalette(application);
3178 if (QS60StylePrivate::isTouchSupported())
3179 qApp->installEventFilter(this);
3180}
3181
3182/*!
3183 \reimp
3184 */
3185void QS60Style::unpolish(QApplication *application)
3186{
3187 Q_UNUSED(application)
3188
3189 Q_D(QS60Style);
3190 QCommonStyle::unpolish(qApp);
3191 const QPalette newPalette = QApplication::style()->standardPalette();
3192 QApplication::setPalette(newPalette);
3193 QApplicationPrivate::setSystemPalette(d->m_originalPalette);
3194 if (QS60StylePrivate::isTouchSupported())
3195 qApp->removeEventFilter(this);
3196}
3197
3198/*!
3199 \reimp
3200 */
3201bool QS60Style::event(QEvent *e)
3202{
3203#ifdef QT_KEYPAD_NAVIGATION
3204 Q_D(QS60Style);
3205 const QEvent::Type eventType = e->type();
3206 if ((eventType == QEvent::FocusIn ||
3207 eventType == QEvent::FocusOut ||
3208 eventType == QEvent::EnterEditFocus ||
3209 eventType == QEvent::LeaveEditFocus) &&
3210 QS60StylePrivate::isTouchSupported())
3211 return false;
3212#endif
3213
3214 switch (e->type()) {
3215 case QEvent::Timer: {
3216 QTimerEvent *te = static_cast<QTimerEvent*>(e);
3217 timerEvent(te);
3218 }
3219 break;
3220#ifdef QT_KEYPAD_NAVIGATION
3221 case QEvent::FocusIn:
3222 if (QWidget *focusWidget = QApplication::focusWidget()) {
3223
3224 // Menus and combobox popups do not draw focus frame around them
3225 if (qobject_cast<QComboBoxListView *>(focusWidget) ||
3226 qobject_cast<QMenu *>(focusWidget))
3227 break;
3228
3229 if (!d->m_focusFrame)
3230 d->m_focusFrame = new QFocusFrame(focusWidget);
3231 d->m_focusFrame->setWidget(focusWidget);
3232 } else if (d->m_focusFrame) {
3233 d->m_focusFrame->setWidget(0);
3234 }
3235 break;
3236 case QEvent::FocusOut:
3237 if (d->m_focusFrame)
3238 d->m_focusFrame->setWidget(0);
3239 break;
3240 case QEvent::EnterEditFocus:
3241 case QEvent::LeaveEditFocus:
3242 if (d->m_focusFrame)
3243 d->m_focusFrame->update();
3244 break;
3245#endif
3246 default:
3247 break;
3248 }
3249 return false;
3250}
3251
3252/*!
3253 \internal
3254 */
3255QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon,
3256 const QStyleOption *option, const QWidget *widget) const
3257{
3258 const int iconDimension = QS60StylePrivate::pixelMetric(PM_ToolBarIconSize);
3259 const QRect iconSize = (!option) ? QRect(0, 0, iconDimension, iconDimension) : option->rect;
3260 QS60StyleEnums::SkinParts part;
3261 QS60StylePrivate::SkinElementFlags adjustedFlags;
3262 if (option)
3263 adjustedFlags = (option->state & State_Enabled || option->state == 0) ?
3264 QS60StylePrivate::SF_StateEnabled :
3265 QS60StylePrivate::SF_StateDisabled;
3266
3267 switch(standardIcon) {
3268 case SP_MessageBoxWarning:
3269 part = QS60StyleEnums::SP_QgnNoteWarning;
3270 break;
3271 case SP_MessageBoxInformation:
3272 part = QS60StyleEnums::SP_QgnNoteInfo;
3273 break;
3274 case SP_MessageBoxCritical:
3275 part = QS60StyleEnums::SP_QgnNoteError;
3276 break;
3277 case SP_MessageBoxQuestion:
3278 part = QS60StyleEnums::SP_QgnNoteQuery;
3279 break;
3280 case SP_ArrowRight:
3281 part = QS60StyleEnums::SP_QgnIndiNaviArrowRight;
3282 break;
3283 case SP_ArrowLeft:
3284 part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
3285 break;
3286 case SP_ArrowUp:
3287 part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
3288 adjustedFlags |= QS60StylePrivate::SF_PointEast;
3289 break;
3290 case SP_ArrowDown:
3291 part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
3292 adjustedFlags |= QS60StylePrivate::SF_PointWest;
3293 break;
3294 case SP_ArrowBack:
3295 if (QApplication::layoutDirection() == Qt::RightToLeft)
3296 return QS60Style::standardIcon(SP_ArrowRight, option, widget);
3297 return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
3298 case SP_ArrowForward:
3299 if (QApplication::layoutDirection() == Qt::RightToLeft)
3300 return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
3301 return QS60Style::standardIcon(SP_ArrowRight, option, widget);
3302 case SP_ComputerIcon:
3303 part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge;
3304 break;
3305 case SP_DirClosedIcon:
3306 part = QS60StyleEnums::SP_QgnPropFolderSmall;
3307 break;
3308 case SP_DirOpenIcon:
3309 part = QS60StyleEnums::SP_QgnPropFolderCurrent;
3310 break;
3311 case SP_DirIcon:
3312 part = QS60StyleEnums::SP_QgnPropFolderSmall;
3313 break;
3314 case SP_FileDialogNewFolder:
3315 part = QS60StyleEnums::SP_QgnPropFolderSmallNew;
3316 break;
3317 case SP_FileIcon:
3318 part = QS60StyleEnums::SP_QgnPropFileSmall;
3319 break;
3320 case SP_TrashIcon:
3321 part = QS60StyleEnums::SP_QgnNoteErased;
3322 break;
3323 case SP_ToolBarHorizontalExtensionButton:
3324 part = QS60StyleEnums::SP_QgnIndiSubMenu;
3325 if (QApplication::layoutDirection() == Qt::RightToLeft)
3326 adjustedFlags |= QS60StylePrivate::SF_PointSouth;
3327 break;
3328 case SP_ToolBarVerticalExtensionButton:
3329 adjustedFlags |= QS60StylePrivate::SF_PointEast;
3330 part = QS60StyleEnums::SP_QgnIndiSubMenu;
3331 break;
3332
3333 default:
3334 return QCommonStyle::standardIconImplementation(standardIcon, option, widget);
3335 }
3336 const QS60StylePrivate::SkinElementFlags flags = adjustedFlags;
3337 const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), 0, flags));
3338 return cachedPixMap.isNull() ?
3339 QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap);
3340}
3341
3342/*!
3343 \internal
3344 Animate indeterminate progress bars only when visible
3345*/
3346bool QS60Style::eventFilter(QObject *object, QEvent *event)
3347{
3348 Q_D(QS60Style);
3349 switch(event->type()) {
3350 case QEvent::MouseButtonPress: {
3351 QWidget *w = QApplication::widgetAt(QCursor::pos());
3352 if (w) {
3353 QWidget *focusW = w->focusProxy();
3354 if (qobject_cast<QAbstractItemView *>(focusW) ||
3355 qobject_cast<QRadioButton *>(focusW) ||
3356 qobject_cast<QCheckBox *>(focusW))
3357 d->m_pressedWidget = focusW;
3358 else if (qobject_cast<QAbstractItemView *>(w)||
3359 qobject_cast<QRadioButton *>(w) ||
3360 qobject_cast<QCheckBox *>(w))
3361 d->m_pressedWidget = w;
3362
3363 if ( d->m_pressedWidget)
3364 d->m_pressedWidget->update();
3365 }
3366 break;
3367 }
3368 case QEvent::MouseButtonRelease: {
3369 const QWidget *w = QApplication::widgetAt(QCursor::pos());
3370 if (w && d->m_pressedWidget) {
3371 d->m_pressedWidget->update();
3372 d->m_pressedWidget = 0;
3373 }
3374 break;
3375 }
3376 default:
3377 break;
3378 }
3379
3380#ifdef Q_WS_S60
3381#ifndef QT_NO_PROGRESSBAR
3382 switch(event->type()) {
3383 case QEvent::StyleChange:
3384 case QEvent::Show:
3385 if (QProgressBar *bar = qobject_cast<QProgressBar *>(object)) {
3386 if (!d->m_bars.contains(bar))
3387 d->m_bars << bar;
3388 if (d->m_bars.size() == 1) //only start with first animated progressbar
3389 d->startAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim);
3390 }
3391 break;
3392 case QEvent::Destroy:
3393 case QEvent::Hide:
3394 if (QProgressBar *bar = reinterpret_cast<QProgressBar *>(object)) {
3395 d->stopAnimation(QS60StyleEnums::SP_QgnGrafBarWaitAnim);
3396 d->m_bars.removeAll(bar);
3397 }
3398 break;
3399 default:
3400 break;
3401 }
3402#endif // QT_NO_PROGRESSBAR
3403#endif // Q_WS_S60
3404 return QCommonStyle::eventFilter(object, event);
3405}
3406
3407/*!
3408 \internal
3409 Handle the timer \a event.
3410*/
3411void QS60Style::timerEvent(QTimerEvent *event)
3412{
3413#ifdef Q_WS_S60
3414#ifndef QT_NO_PROGRESSBAR
3415 Q_D(QS60Style);
3416
3417 QS60StyleAnimation *progressBarAnimation =
3418 QS60StylePrivate::animationDefinition(QS60StyleEnums::SP_QgnGrafBarWaitAnim);
3419
3420 if (event->timerId() == progressBarAnimation->timerId()) {
3421
3422 Q_ASSERT(progressBarAnimation->interval() > 0);
3423
3424 if (progressBarAnimation->currentFrame() == progressBarAnimation->frameCount() )
3425 if (progressBarAnimation->playMode() == QS60StyleEnums::AM_Looping)
3426 progressBarAnimation->setCurrentFrame(0);
3427 else
3428 d->stopAnimation(progressBarAnimation->animationId());
3429
3430 foreach (QProgressBar *bar, d->m_bars) {
3431 if ((bar->minimum() == 0 && bar->maximum() == 0))
3432 bar->update();
3433 }
3434 progressBarAnimation->setCurrentFrame(progressBarAnimation->currentFrame() + 1);
3435 }
3436#endif // QT_NO_PROGRESSBAR
3437#endif // Q_WS_S60
3438 event->ignore();
3439}
3440
3441extern QPoint qt_s60_fill_background_offset(const QWidget *targetWidget);
3442
3443bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush)
3444{
3445 const QPixmap backgroundTexture(QS60StylePrivate::backgroundTexture());
3446 if (backgroundTexture.cacheKey() != brush.texture().cacheKey())
3447 return false;
3448
3449 const QPaintDevice *target = painter->device();
3450 if (target->devType() == QInternal::Widget) {
3451 const QWidget *widget = static_cast<const QWidget *>(target);
3452 if (!widget->testAttribute(Qt::WA_TranslucentBackground)) {
3453 const QVector<QRect> &rects = rgn.rects();
3454 for (int i = 0; i < rects.size(); ++i) {
3455 const QRect rect(rects.at(i));
3456 painter->drawPixmap(rect.topLeft(), backgroundTexture,
3457 rect.translated(qt_s60_fill_background_offset(widget)));
3458 }
3459 }
3460 }
3461 return true;
3462}
3463
3464QT_END_NAMESPACE
3465
3466#endif // QT_NO_STYLE_S60 || QT_PLUGIN
Note: See TracBrowser for help on using the repository browser.