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