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

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

trunk: Merged in qt 4.6.2 sources.

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