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, &copy, painter, widget);
1176                 copy.rect.adjust(1, 1, -1, -1);
1177                 drawPrimitive(pe, &copy, 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, &copy, painter, widget);
1203                 copy.rect.adjust(1, 1, -1, -1);
1204                 drawPrimitive(pe, &copy, 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