Ticket #62964: patch-mavericks-aesthetics.diff
File patch-mavericks-aesthetics.diff, 577.3 KB (added by Wowfunhappy (Jonathan), 3 years ago) |
---|
-
src/widgets/styles/qmacstyle_mac.mm
From 45dd03d13134a7aa03f1b43ff64eff9ba0d9e13c Mon Sep 17 00:00:00 2001 From: Wowfunhappy <Wowfunhappy@gmail.com> Date: Mon, 24 May 2021 16:46:41 -0400 Subject: [PATCH] Use QT 5.8 qmacstyle_mac.mm This commit is for aesthetics only; not strictly necessary for software to work. The high diff count is because it's based on the version from qt 5.8. --- src/widgets/styles/qmacstyle_mac.mm | 11200 +++++++++++++++++----------------- 1 file changed, 5564 insertions(+), 5636 deletions(-) diff --git src/widgets/styles/qmacstyle_mac.mm src/widgets/styles/qmacstyle_mac.mm index e6436f82a6..be7c58cf72 100644
1 1 /**************************************************************************** 2 **3 ** Copyright (C) 2016 The Qt Company Ltd.4 ** Contact: https://www.qt.io/licensing/5 **6 ** This file is part of the QtWidgets module of the Qt Toolkit.7 **8 ** $QT_BEGIN_LICENSE:LGPL$9 ** Commercial License Usage10 ** Licensees holding valid commercial Qt licenses may use this file in11 ** accordance with the commercial license agreement provided with the12 ** Software or, alternatively, in accordance with the terms contained in13 ** a written agreement between you and The Qt Company. For licensing terms14 ** and conditions see https://www.qt.io/terms-conditions. For further15 ** information use the contact form at https://www.qt.io/contact-us.16 **17 ** GNU Lesser General Public License Usage18 ** Alternatively, this file may be used under the terms of the GNU Lesser19 ** General Public License version 3 as published by the Free Software20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the21 ** packaging of this file. Please review the following information to22 ** ensure the GNU Lesser General Public License version 3 requirements23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.24 **25 ** GNU General Public License Usage26 ** Alternatively, this file may be used under the terms of the GNU27 ** General Public License version 2.0 or (at your option) the GNU General28 ** Public license version 3 or any later version approved by the KDE Free29 ** Qt Foundation. The licenses are as published by the Free Software30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL331 ** included in the packaging of this file. Please review the following32 ** information to ensure the GNU General Public License requirements will33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and34 ** https://www.gnu.org/licenses/gpl-3.0.html.35 **36 ** $QT_END_LICENSE$37 **38 ****************************************************************************/2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtWidgets module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 39 40 40 /* 41 42 43 */41 Note: The qdoc comments for QMacStyle are contained in 42 .../doc/src/qstyles.qdoc. 43 */ 44 44 45 45 #include <AppKit/AppKit.h> 46 46 … … 51 51 //#define DEBUG_SIZE_CONSTRAINT 52 52 53 53 #include <private/qcore_mac_p.h> 54 #if QT_CONFIG(tabbar) 55 #include <private/qtabbar_p.h> 56 #endif 54 #include <private/qcombobox_p.h> 57 55 #include <private/qpainter_p.h> 58 56 #include <qapplication.h> 59 57 #include <qbitmap.h> 60 #if QT_CONFIG(combobox) 61 #include <private/qcombobox_p.h> 58 #include <qcheckbox.h> 62 59 #include <qcombobox.h> 63 #endif64 #if QT_CONFIG(dialogbuttonbox)65 60 #include <qdialogbuttonbox.h> 66 #endif67 #if QT_CONFIG(dockwidget)68 61 #include <qdockwidget.h> 69 #endif70 62 #include <qevent.h> 71 63 #include <qfocusframe.h> 72 64 #include <qformlayout.h> 73 65 #include <qgroupbox.h> 74 66 #include <qhash.h> 75 67 #include <qheaderview.h> 76 #if QT_CONFIG(lineedit)77 68 #include <qlineedit.h> 78 #endif79 #if QT_CONFIG(mainwindow)80 69 #include <qmainwindow.h> 81 #endif82 #if QT_CONFIG(mdiarea)83 70 #include <qmdisubwindow.h> 84 #endif85 #if QT_CONFIG(menubar)86 71 #include <qmenubar.h> 87 #endif88 72 #include <qpaintdevice.h> 89 73 #include <qpainter.h> 90 74 #include <qpixmapcache.h> 91 75 #include <qpointer.h> 92 #if QT_CONFIG(progressbar)93 76 #include <qprogressbar.h> 94 #endif95 #if QT_CONFIG(pushbutton)96 77 #include <qpushbutton.h> 97 #endif98 78 #include <qradiobutton.h> 99 #if QT_CONFIG(rubberband)100 79 #include <qrubberband.h> 101 #endif102 #if QT_CONFIG(scrollbar)103 80 #include <qscrollbar.h> 104 #endif105 #if QT_CONFIG(sizegrip)106 81 #include <qsizegrip.h> 107 #endif108 82 #include <qstyleoption.h> 109 83 #include <qtoolbar.h> 110 #if QT_CONFIG(toolbutton)111 84 #include <qtoolbutton.h> 112 #endif113 #if QT_CONFIG(treeview)114 85 #include <qtreeview.h> 115 #endif116 #if QT_CONFIG(tableview)117 86 #include <qtableview.h> 118 #endif119 #include <qoperatingsystemversion.h>120 #if QT_CONFIG(wizard)121 87 #include <qwizard.h> 122 #endif123 88 #include <qdebug.h> 124 89 #include <qlibrary.h> 125 #if QT_CONFIG(datetimeedit)126 90 #include <qdatetimeedit.h> 127 #endif128 91 #include <qmath.h> 129 92 #include <QtWidgets/qgraphicsproxywidget.h> 130 #if QT_CONFIG(graphicsview)131 93 #include <QtWidgets/qgraphicsview.h> 132 #endif133 94 #include <QtCore/qvariant.h> 134 95 #include <private/qstylehelper_p.h> 135 96 #include <private/qstyleanimation_p.h> … … static QWindow *qt_getWindow(const QWidget *widget) 145 106 } 146 107 147 108 @interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject { 148 QMacStylePrivate *mPrivate;109 QMacStylePrivate *mPrivate; 149 110 } 150 111 - (id)initWithPrivate:(QMacStylePrivate *)priv; 151 112 - (void)scrollBarStyleDidChange:(NSNotification *)notification; … … QT_NAMESPACE_ALIAS_OBJC_CLASS(NotificationReceiver); 164 125 - (void)scrollBarStyleDidChange:(NSNotification *)notification 165 126 { 166 127 Q_UNUSED(notification); 167 128 168 129 // purge destroyed scroll bars: 169 130 QMacStylePrivate::scrollBars.removeAll(QPointer<QObject>()); 170 131 171 132 QEvent event(QEvent::StyleChange); 172 133 for (const auto &o : QMacStylePrivate::scrollBars) 173 134 QCoreApplication::sendEvent(o, &event); … … static const QColor mainWindowGradientEnd(200, 200, 200); 225 186 226 187 static const int DisclosureOffset = 4; 227 188 228 // Tab bar colors229 // active: window is active230 // selected: tab is selected231 // hovered: tab is hovered232 static const QColor tabBarTabBackgroundActive(190, 190, 190);233 static const QColor tabBarTabBackgroundActiveHovered(178, 178, 178);234 static const QColor tabBarTabBackgroundActiveSelected(211, 211, 211);235 static const QColor tabBarTabBackground(227, 227, 227);236 static const QColor tabBarTabBackgroundSelected(246, 246, 246);237 static const QColor tabBarTabLineActive(160, 160, 160);238 static const QColor tabBarTabLineActiveHovered(150, 150, 150);239 static const QColor tabBarTabLine(210, 210, 210);240 static const QColor tabBarTabLineSelected(189, 189, 189);241 static const QColor tabBarCloseButtonBackgroundHovered(162, 162, 162);242 static const QColor tabBarCloseButtonBackgroundPressed(153, 153, 153);243 static const QColor tabBarCloseButtonBackgroundSelectedHovered(192, 192, 192);244 static const QColor tabBarCloseButtonBackgroundSelectedPressed(181, 181, 181);245 static const QColor tabBarCloseButtonCross(100, 100, 100);246 static const QColor tabBarCloseButtonCrossSelected(115, 115, 115);247 248 static const int closeButtonSize = 14;249 static const qreal closeButtonCornerRadius = 2.0;250 251 189 // Resolve these at run-time, since the functions was moved in Leopard. 252 190 typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *); 253 191 static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0; 254 192 255 #if QT_CONFIG(tabbar) 193 static int closeButtonSize = 12; 194 #ifndef QT_NO_TABBAR 256 195 static bool isVerticalTabs(const QTabBar::Shape shape) { 257 196 return (shape == QTabBar::RoundedEast 258 259 260 197 || shape == QTabBar::TriangularEast 198 || shape == QTabBar::RoundedWest 199 || shape == QTabBar::TriangularWest); 261 200 } 262 201 #endif 263 202 … … static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) 265 204 { 266 205 QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); 267 206 QPlatformNativeInterface::NativeResourceForIntegrationFunction function = 268 207 nativeInterface->nativeResourceFunctionForIntegration("testContentBorderPosition"); 269 208 if (!function) 270 209 return false; // Not Cocoa platform plugin. 271 210 272 211 typedef bool (*TestContentBorderPositionFunction)(QWindow *, int); 273 212 return (reinterpret_cast<TestContentBorderPositionFunction>(function))(window, windowY); 274 213 } 275 214 276 215 277 static void drawTabCloseButton(QPainter *p, bool hover, bool selected, bool pressed, bool documentMode)216 void drawTabCloseButton(QPainter *p, bool hover, bool active, bool selected) 278 217 { 218 // draw background circle 279 219 p->setRenderHints(QPainter::Antialiasing); 280 220 QRect rect(0, 0, closeButtonSize, closeButtonSize); 281 const int width = rect.width(); 282 const int height = rect.height(); 283 221 QColor background; 284 222 if (hover) { 285 // draw background circle286 QColor background;287 if ( selected) {288 if ( documentMode)289 background = pressed ? tabBarCloseButtonBackgroundSelectedPressed : tabBarCloseButtonBackgroundSelectedHovered;223 background = QColor(124, 124, 124); 224 } else { 225 if (active) { 226 if (selected) 227 background = QColor(104, 104, 104); 290 228 else 291 background = QColor( 255, 255, 255, pressed ? 150 : 100); // Translucent white229 background = QColor(83, 83, 83); 292 230 } else { 293 background = pressed ? tabBarCloseButtonBackgroundPressed : tabBarCloseButtonBackgroundHovered; 294 if (!documentMode) 295 background = background.lighter(pressed ? 135 : 140); // Lighter tab background, lighter color 231 if (selected) 232 background = QColor(144, 144, 144); 233 else 234 background = QColor(114, 114, 114); 296 235 } 297 298 p->setPen(Qt::transparent);299 p->setBrush(background);300 p->drawRoundedRect(rect, closeButtonCornerRadius, closeButtonCornerRadius);301 236 } 302 237 p->setPen(Qt::transparent); 238 p->setBrush(background); 239 p->drawEllipse(rect); 240 303 241 // draw cross 304 const int margin = 3; 242 int min = 3; 243 int max = 9; 305 244 QPen crossPen; 306 crossPen.setColor( selected ? (documentMode ? tabBarCloseButtonCrossSelected : Qt::white) : tabBarCloseButtonCross);307 crossPen.setWidthF(1. 1);245 crossPen.setColor(QColor(194, 194, 194)); 246 crossPen.setWidthF(1.3); 308 247 crossPen.setCapStyle(Qt::FlatCap); 309 248 p->setPen(crossPen); 310 p->drawLine(m argin, margin, width - margin, height - margin);311 p->drawLine(m argin, height - margin, width - margin, margin);249 p->drawLine(min, min, max, max); 250 p->drawLine(min, max, max, min); 312 251 } 313 252 314 #if QT_CONFIG(tabbar)253 #ifndef QT_NO_TABBAR 315 254 QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) 316 255 { 317 256 if (isVerticalTabs(shape)) { … … QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) 335 274 return tabRect; 336 275 } 337 276 338 void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified , int tabOverlap)277 void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified) 339 278 { 340 QRect rect = tabOpt->rect; 341 342 switch (tabOpt->shape) { 343 case QTabBar::RoundedNorth: 344 case QTabBar::TriangularNorth: 345 case QTabBar::RoundedSouth: 346 case QTabBar::TriangularSouth: 347 rect.adjust(-tabOverlap, 0, 0, 0); 348 break; 349 case QTabBar::RoundedEast: 350 case QTabBar::TriangularEast: 351 case QTabBar::RoundedWest: 352 case QTabBar::TriangularWest: 353 rect.adjust(0, -tabOverlap, 0, 0); 354 break; 355 default: 356 break; 357 } 358 359 p->translate(rect.x(), rect.y()); 360 rect.moveLeft(0); 361 rect.moveTop(0); 362 const QRect tabRect = rotateTabPainter(p, tabOpt->shape, rect); 363 364 const int width = tabRect.width(); 365 const int height = tabRect.height(); 366 const bool active = (tabOpt->state & QStyle::State_Active); 367 const bool selected = (tabOpt->state & QStyle::State_Selected); 368 369 const QRect bodyRect(1, 1, width - 2, height - 2); 370 const QRect topLineRect(1, 0, width - 2, 1); 371 const QRect bottomLineRect(1, height - 1, width - 2, 1); 279 QRect r = tabOpt->rect; 280 p->translate(tabOpt->rect.x(), tabOpt->rect.y()); 281 r.moveLeft(0); 282 r.moveTop(0); 283 QRect tabRect = rotateTabPainter(p, tabOpt->shape, r); 284 285 int width = tabRect.width(); 286 int height = 20; 287 bool active = (tabOpt->state & QStyle::State_Active); 288 bool selected = (tabOpt->state & QStyle::State_Selected); 289 372 290 if (selected) { 291 QRect rect(1, 0, width - 2, height); 292 373 293 // fill body 374 294 if (tabOpt->documentMode && isUnified) { 375 295 p->save(); 376 296 p->setCompositionMode(QPainter::CompositionMode_Source); 377 p->fillRect( tabRect, QColor(Qt::transparent));297 p->fillRect(rect, QColor(Qt::transparent)); 378 298 p->restore(); 379 299 } else if (active) { 380 p->fillRect(bodyRect, tabBarTabBackgroundActiveSelected); 381 // top line 382 p->fillRect(topLineRect, tabBarTabLineSelected); 300 p->fillRect(rect, QColor(167, 167, 167)); 383 301 } else { 384 p->fillRect(bodyRect, tabBarTabBackgroundSelected); 385 } 302 QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); 303 gradient.setColorAt(0, QColor(216, 216, 216)); 304 gradient.setColorAt(0.5, QColor(215, 215, 215)); 305 gradient.setColorAt(1, QColor(210, 210, 210)); 306 p->fillRect(rect, gradient); 307 } 308 309 // draw border 310 QColor borderSides; 311 QColor borderBottom; 312 if (active) { 313 borderSides = QColor(88, 88, 88); 314 borderBottom = QColor(88, 88, 88); 315 } else { 316 borderSides = QColor(121, 121, 121); 317 borderBottom = QColor(116, 116, 116); 318 } 319 320 p->setPen(borderSides); 321 322 int bottom = height; 323 // left line 324 p->drawLine(0, 1, 0, bottom-2); 325 // right line 326 p->drawLine(width-1, 1, width-1, bottom-2); 327 328 // bottom line 329 if (active) { 330 p->setPen(QColor(168, 168, 168)); 331 p->drawLine(3, bottom-1, width-3, bottom-1); 332 } 333 p->setPen(borderBottom); 334 p->drawLine(2, bottom, width-2, bottom); 335 336 int w = 3; 337 QRectF rectangleLeft(1, height - w, w, w); 338 QRectF rectangleRight(width - 2, height - 1, w, w); 339 int startAngle = 180 * 16; 340 int spanAngle = 90 * 16; 341 p->setRenderHint(QPainter::Antialiasing); 342 p->drawArc(rectangleLeft, startAngle, spanAngle); 343 p->drawArc(rectangleRight, startAngle, -spanAngle); 386 344 } else { 387 345 // when the mouse is over non selected tabs they get a new color 388 constbool hover = (tabOpt->state & QStyle::State_MouseOver);346 bool hover = (tabOpt->state & QStyle::State_MouseOver); 389 347 if (hover) { 390 // fill body 391 p->fillRect(bodyRect, tabBarTabBackgroundActiveHovered); 392 // bottom line 393 p->fillRect(bottomLineRect, tabBarTabLineActiveHovered); 348 QRect rect(1, 2, width - 1, height - 1); 349 p->fillRect(rect, QColor(110, 110, 110)); 350 } 351 352 // seperator lines between tabs 353 bool west = (tabOpt->shape == QTabBar::RoundedWest || tabOpt->shape == QTabBar::TriangularWest); 354 bool drawOnRight = !west; 355 if ((!drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected) 356 || (drawOnRight && tabOpt->selectedPosition != QStyleOptionTab::NextIsSelected)) { 357 QColor borderColor; 358 QColor borderHighlightColor; 359 if (active) { 360 borderColor = QColor(64, 64, 64); 361 borderHighlightColor = QColor(140, 140, 140); 362 } else { 363 borderColor = QColor(135, 135, 135); 364 borderHighlightColor = QColor(178, 178, 178); 365 } 366 367 int x = drawOnRight ? width : 0; 368 369 // tab seperator line 370 p->setPen(borderColor); 371 p->drawLine(x, 2, x, height + 1); 372 373 // tab seperator highlight 374 p->setPen(borderHighlightColor); 375 p->drawLine(x-1, 2, x-1, height + 1); 376 p->drawLine(x+1, 2, x+1, height + 1); 394 377 } 395 378 } 396 397 // separator lines between tabs398 const QRect leftLineRect(0, 1, 1, height - 2);399 const QRect rightLineRect(width - 1, 1, 1, height - 2);400 const QColor separatorLineColor = active ? tabBarTabLineActive : tabBarTabLine;401 p->fillRect(leftLineRect, separatorLineColor);402 p->fillRect(rightLineRect, separatorLineColor);403 379 } 404 380 405 381 void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w) … … void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget * 410 386 } else { 411 387 r.setHeight(w->height()); 412 388 } 413 const QRect tabRect = rotateTabPainter(p, tbb->shape, r); 414 const int width = tabRect.width(); 415 const int height = tabRect.height(); 416 const bool active = (tbb->state & QStyle::State_Active); 417 418 // fill body 419 const QRect bodyRect(0, 1, width, height - 1); 420 const QColor bodyColor = active ? tabBarTabBackgroundActive : tabBarTabBackground; 421 p->fillRect(bodyRect, bodyColor); 422 423 // top line 424 const QRect topLineRect(0, 0, width, 1); 425 const QColor topLineColor = active ? tabBarTabLineActive : tabBarTabLine; 426 p->fillRect(topLineRect, topLineColor); 427 428 // bottom line 429 const QRect bottomLineRect(0, height - 1, width, 1); 430 const QColor bottomLineColor = active ? tabBarTabLineActive : tabBarTabLine; 431 p->fillRect(bottomLineRect, bottomLineColor); 389 QRect tabRect = rotateTabPainter(p, tbb->shape, r); 390 int width = tabRect.width(); 391 int height = tabRect.height(); 392 bool active = (tbb->state & QStyle::State_Active); 393 394 // top border lines 395 QColor borderHighlightTop; 396 QColor borderTop; 397 if (active) { 398 borderTop = QColor(64, 64, 64); 399 borderHighlightTop = QColor(174, 174, 174); 400 } else { 401 borderTop = QColor(135, 135, 135); 402 borderHighlightTop = QColor(207, 207, 207); 403 } 404 p->setPen(borderHighlightTop); 405 p->drawLine(tabRect.x(), 0, width, 0); 406 p->setPen(borderTop); 407 p->drawLine(tabRect.x(), 1, width, 1); 408 409 // center block 410 QRect centralRect(tabRect.x(), 2, width, height - 2); 411 if (active) { 412 QColor mainColor = QColor(120, 120, 120); 413 p->fillRect(centralRect, mainColor); 414 } else { 415 QLinearGradient gradient(centralRect.topLeft(), centralRect.bottomLeft()); 416 gradient.setColorAt(0, QColor(165, 165, 165)); 417 gradient.setColorAt(0.5, QColor(164, 164, 164)); 418 gradient.setColorAt(1, QColor(158, 158, 158)); 419 p->fillRect(centralRect, gradient); 420 } 421 422 // bottom border lines 423 QColor borderHighlightBottom; 424 QColor borderBottom; 425 if (active) { 426 borderHighlightBottom = QColor(153, 153, 153); 427 borderBottom = QColor(64, 64, 64); 428 } else { 429 borderHighlightBottom = QColor(177, 177, 177); 430 borderBottom = QColor(127, 127, 127); 431 } 432 p->setPen(borderHighlightBottom); 433 p->drawLine(tabRect.x(), height - 2, width, height - 2); 434 p->setPen(borderBottom); 435 p->drawLine(tabRect.x(), height - 1, width, height - 1); 432 436 } 433 437 #endif 434 438 435 439 static int getControlSize(const QStyleOption *option, const QWidget *widget) 436 440 { 437 441 switch (QMacStyle::widgetSizePolicy(widget, option)) { 438 case QMacStyle::SizeSmall:439 return QAquaSizeSmall;440 case QMacStyle::SizeMini:441 return QAquaSizeMini;442 default:443 break;442 case QMacStyle::SizeSmall: 443 return QAquaSizeSmall; 444 case QMacStyle::SizeMini: 445 return QAquaSizeMini; 446 default: 447 break; 444 448 } 445 449 return QAquaSizeLarge; 446 450 } 447 451 448 452 449 #if QT_CONFIG(treeview)453 #ifndef QT_NO_TREEVIEW 450 454 static inline bool isTreeView(const QWidget *widget) 451 455 { 452 456 return (widget && widget->parentWidget() && … … static inline bool isTreeView(const QWidget *widget) 455 459 } 456 460 #endif 457 461 458 #if QT_CONFIG(tabbar)462 #ifndef QT_NO_TABBAR 459 463 static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) 460 464 { 461 465 ThemeTabDirection ttd; 462 466 switch (shape) { 463 case QTabBar::RoundedSouth:464 case QTabBar::TriangularSouth:465 ttd = kThemeTabSouth;466 break;467 default: // Added to remove the warning, since all values are taken care of, really!468 case QTabBar::RoundedNorth:469 case QTabBar::TriangularNorth:470 ttd = kThemeTabNorth;471 break;472 case QTabBar::RoundedWest:473 case QTabBar::TriangularWest:474 ttd = kThemeTabWest;475 break;476 case QTabBar::RoundedEast:477 case QTabBar::TriangularEast:478 ttd = kThemeTabEast;479 break;467 case QTabBar::RoundedSouth: 468 case QTabBar::TriangularSouth: 469 ttd = kThemeTabSouth; 470 break; 471 default: // Added to remove the warning, since all values are taken care of, really! 472 case QTabBar::RoundedNorth: 473 case QTabBar::TriangularNorth: 474 ttd = kThemeTabNorth; 475 break; 476 case QTabBar::RoundedWest: 477 case QTabBar::TriangularWest: 478 ttd = kThemeTabWest; 479 break; 480 case QTabBar::RoundedEast: 481 case QTabBar::TriangularEast: 482 ttd = kThemeTabEast; 483 break; 480 484 } 481 485 return ttd; 482 486 } … … OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inR 522 526 QRegion *region = static_cast<QRegion *>(inRefcon); 523 527 if (!region) 524 528 return paramErr; 525 529 526 530 switch (inMessage) { 527 case kHIShapeEnumerateRect:528 *region += QRect(inRect->origin.x, inRect->origin.y,529 inRect->size.width, inRect->size.height);530 break;531 case kHIShapeEnumerateInit:532 // Assume the region is already setup correctly533 case kHIShapeEnumerateTerminate:534 default:535 break;531 case kHIShapeEnumerateRect: 532 *region += QRect(inRect->origin.x, inRect->origin.y, 533 inRect->size.width, inRect->size.height); 534 break; 535 case kHIShapeEnumerateInit: 536 // Assume the region is already setup correctly 537 case kHIShapeEnumerateTerminate: 538 default: 539 break; 536 540 } 537 541 return noErr; 538 542 } 539 543 540 544 /*! 541 542 543 544 */545 \internal 546 Create's a mutable shape, it's the caller's responsibility to release. 547 WARNING: this function clamps the coordinates to SHRT_MIN/MAX on 10.4 and below. 548 */ 545 549 HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) 546 550 { 547 551 HIMutableShapeRef shape = HIShapeCreateMutable(); … … static bool qt_macWindowMainWindow(const QWidget *window) 588 592 } 589 593 590 594 /***************************************************************************** 591 595 QMacCGStyle globals 592 596 *****************************************************************************/ 593 597 const int qt_mac_hitheme_version = 0; //the HITheme version we speak 594 598 const int macItemFrame = 2; // menu item frame width … … const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use fo 598 602 QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background. 599 603 600 604 /***************************************************************************** 601 605 QMacCGStyle utility functions 602 606 *****************************************************************************/ 603 607 static inline int qt_mac_hitheme_tab_version() 604 608 { … … static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg 655 659 if (widg->font().pointSize() > font.pointSize()) 656 660 return ret; 657 661 } 658 662 659 663 if (ct == QStyle::CT_CustomBase && widg) { 660 #if QT_CONFIG(pushbutton)661 664 if (qobject_cast<const QPushButton *>(widg)) 662 665 ct = QStyle::CT_PushButton; 663 #endif664 666 else if (qobject_cast<const QRadioButton *>(widg)) 665 667 ct = QStyle::CT_RadioButton; 666 #if QT_CONFIG(checkbox)667 668 else if (qobject_cast<const QCheckBox *>(widg)) 668 669 ct = QStyle::CT_CheckBox; 669 #endif 670 #if QT_CONFIG(combobox) 670 #ifndef QT_NO_COMBOBOX 671 671 else if (qobject_cast<const QComboBox *>(widg)) 672 672 ct = QStyle::CT_ComboBox; 673 673 #endif 674 #if QT_CONFIG(toolbutton)674 #ifndef QT_NO_TOOLBUTTON 675 675 else if (qobject_cast<const QToolButton *>(widg)) 676 676 ct = QStyle::CT_ToolButton; 677 677 #endif 678 678 else if (qobject_cast<const QSlider *>(widg)) 679 679 ct = QStyle::CT_Slider; 680 #if QT_CONFIG(progressbar)680 #ifndef QT_NO_PROGRESSBAR 681 681 else if (qobject_cast<const QProgressBar *>(widg)) 682 682 ct = QStyle::CT_ProgressBar; 683 683 #endif 684 #if QT_CONFIG(lineedit)684 #ifndef QT_NO_LINEEDIT 685 685 else if (qobject_cast<const QLineEdit *>(widg)) 686 686 ct = QStyle::CT_LineEdit; 687 687 #endif 688 688 else if (qobject_cast<const QHeaderView *>(widg)) 689 689 ct = QStyle::CT_HeaderSection; 690 #if QT_CONFIG(menubar)690 #ifndef QT_NO_MENUBAR 691 691 else if (qobject_cast<const QMenuBar *>(widg)) 692 692 ct = QStyle::CT_MenuBar; 693 693 #endif 694 #if QT_CONFIG(sizegrip)694 #ifndef QT_NO_SIZEGRIP 695 695 else if (qobject_cast<const QSizeGrip *>(widg)) 696 696 ct = QStyle::CT_SizeGrip; 697 697 #endif 698 698 else 699 699 return ret; 700 700 } 701 701 702 702 switch (ct) { 703 #if QT_CONFIG(pushbutton) 704 case QStyle::CT_PushButton: { 705 const QPushButton *psh = qobject_cast<const QPushButton *>(widg); 706 // If this comparison is false, then the widget was not a push button. 707 // This is bad and there's very little we can do since we were requested to find a 708 // sensible size for a widget that pretends to be a QPushButton but is not. 709 if(psh) { 710 QString buttonText = qt_mac_removeMnemonics(psh->text()); 711 if (buttonText.contains(QLatin1Char('\n'))) 712 ret = QSize(-1, -1); 713 else if (sz == QAquaSizeLarge) 714 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); 703 case QStyle::CT_PushButton: { 704 const QPushButton *psh = qobject_cast<const QPushButton *>(widg); 705 // If this comparison is false, then the widget was not a push button. 706 // This is bad and there's very little we can do since we were requested to find a 707 // sensible size for a widget that pretends to be a QPushButton but is not. 708 if(psh) { 709 QString buttonText = qt_mac_removeMnemonics(psh->text()); 710 if (buttonText.contains(QLatin1Char('\n'))) 711 ret = QSize(-1, -1); 712 else if (sz == QAquaSizeLarge) 713 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); 714 else if (sz == QAquaSizeSmall) 715 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); 716 else if (sz == QAquaSizeMini) 717 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); 718 719 if (!psh->icon().isNull()){ 720 // If the button got an icon, and the icon is larger than the 721 // button, we can't decide on a default size 722 ret.setWidth(-1); 723 if (ret.height() < psh->iconSize().height()) 724 ret.setHeight(-1); 725 } 726 else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){ 727 // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels. 728 // However, this doesn't work for German, therefore only do it for English, 729 // I suppose it would be better to do some sort of lookups for languages 730 // that like to have really long words. 731 ret.setWidth(77 - 8); 732 } 733 } else { 734 // The only sensible thing to do is to return whatever the style suggests... 735 if (sz == QAquaSizeLarge) 736 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); 737 else if (sz == QAquaSizeSmall) 738 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); 739 else if (sz == QAquaSizeMini) 740 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); 741 else 742 // Since there's no default size we return the large size... 743 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); 744 } 745 #if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam 746 } else if (ct == QStyle::CT_RadioButton) { 747 QRadioButton *rdo = static_cast<QRadioButton *>(widg); 748 // Exception for case where multiline radio button text requires no size constrainment 749 if (rdo->text().find('\n') != -1) 750 return ret; 751 if (sz == QAquaSizeLarge) 752 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight)); 715 753 else if (sz == QAquaSizeSmall) 716 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmall PushButtonHeight));754 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight)); 717 755 else if (sz == QAquaSizeMini) 718 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); 719 720 if (!psh->icon().isNull()){ 721 // If the button got an icon, and the icon is larger than the 722 // button, we can't decide on a default size 723 ret.setWidth(-1); 724 if (ret.height() < psh->iconSize().height()) 725 ret.setHeight(-1); 726 } 727 else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){ 728 // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels. 729 // However, this doesn't work for German, therefore only do it for English, 730 // I suppose it would be better to do some sort of lookups for languages 731 // that like to have really long words. 732 ret.setWidth(77 - 8); 733 } 734 } else { 735 // The only sensible thing to do is to return whatever the style suggests... 756 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight)); 757 } else if (ct == QStyle::CT_CheckBox) { 736 758 if (sz == QAquaSizeLarge) 737 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetric PushButtonHeight));759 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight)); 738 760 else if (sz == QAquaSizeSmall) 739 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmall PushButtonHeight));761 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight)); 740 762 else if (sz == QAquaSizeMini) 741 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); 742 else 743 // Since there's no default size we return the large size... 744 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); 745 } 763 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight)); 746 764 #endif 747 #if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam 748 } else if (ct == QStyle::CT_RadioButton) { 749 QRadioButton *rdo = static_cast<QRadioButton *>(widg); 750 // Exception for case where multiline radio button text requires no size constrainment 751 if (rdo->text().find('\n') != -1) 752 return ret; 753 if (sz == QAquaSizeLarge) 754 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight)); 755 else if (sz == QAquaSizeSmall) 756 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight)); 757 else if (sz == QAquaSizeMini) 758 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight)); 759 } else if (ct == QStyle::CT_CheckBox) { 760 if (sz == QAquaSizeLarge) 761 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight)); 762 else if (sz == QAquaSizeSmall) 763 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight)); 764 else if (sz == QAquaSizeMini) 765 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight)); 766 #endif 767 break; 768 } 769 case QStyle::CT_SizeGrip: 770 if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) { 771 HIRect r; 772 HIPoint p = { 0, 0 }; 773 HIThemeGrowBoxDrawInfo gbi; 774 gbi.version = 0; 775 gbi.state = kThemeStateActive; 776 gbi.kind = kHIThemeGrowBoxKindNormal; 777 gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown 778 : kThemeGrowRight | kThemeGrowDown; 779 gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; 780 if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { 781 int width = 0; 782 #if QT_CONFIG(mdiarea) 783 if (widg && qobject_cast<QMdiSubWindow *>(widg->parentWidget())) 784 width = r.size.width; 765 break; 766 } 767 case QStyle::CT_SizeGrip: 768 if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) { 769 HIRect r; 770 HIPoint p = { 0, 0 }; 771 HIThemeGrowBoxDrawInfo gbi; 772 gbi.version = 0; 773 gbi.state = kThemeStateActive; 774 gbi.kind = kHIThemeGrowBoxKindNormal; 775 gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown 776 : kThemeGrowRight | kThemeGrowDown; 777 gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; 778 if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { 779 int width = 0; 780 #ifndef QT_NO_MDIAREA 781 if (widg && qobject_cast<QMdiSubWindow *>(widg->parentWidget())) 782 width = r.size.width; 785 783 #endif 786 ret = QSize(width, r.size.height); 784 ret = QSize(width, r.size.height); 785 } 787 786 } 788 }789 break;790 case QStyle::CT_ComboBox:791 switch (sz) {792 case QAquaSizeLarge:793 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight));794 break;795 case QAquaSizeSmall:796 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight));797 break;798 case QAquaSizeMini:799 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight));800 787 break; 801 default: 788 case QStyle::CT_ComboBox: 789 switch (sz) { 790 case QAquaSizeLarge: 791 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight)); 792 break; 793 case QAquaSizeSmall: 794 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight)); 795 break; 796 case QAquaSizeMini: 797 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight)); 798 break; 799 default: 800 break; 801 } 802 802 break; 803 } 804 break; 805 case QStyle::CT_ToolButton: 806 if (sz == QAquaSizeSmall) { 807 int width = 0, height = 0; 808 if (szHint == QSize(-1, -1)) { //just 'guess'.. 809 #if QT_CONFIG(toolbutton) 810 const QToolButton *bt = qobject_cast<const QToolButton *>(widg); 811 // If this conversion fails then the widget was not what it claimed to be. 812 if(bt) { 813 if (!bt->icon().isNull()) { 814 QSize iconSize = bt->iconSize(); 815 QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal); 816 width = qMax(width, qMax(iconSize.width(), pmSize.width())); 817 height = qMax(height, qMax(iconSize.height(), pmSize.height())); 818 } 819 if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) { 820 int text_width = bt->fontMetrics().width(bt->text()), 821 text_height = bt->fontMetrics().height(); 822 if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) { 823 width = qMax(width, text_width); 824 height += text_height; 825 } else { 826 width += text_width; 827 width = qMax(height, text_height); 803 case QStyle::CT_ToolButton: 804 if (sz == QAquaSizeSmall) { 805 int width = 0, height = 0; 806 if (szHint == QSize(-1, -1)) { //just 'guess'.. 807 #ifndef QT_NO_TOOLBUTTON 808 const QToolButton *bt = qobject_cast<const QToolButton *>(widg); 809 // If this conversion fails then the widget was not what it claimed to be. 810 if(bt) { 811 if (!bt->icon().isNull()) { 812 QSize iconSize = bt->iconSize(); 813 QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal); 814 width = qMax(width, qMax(iconSize.width(), pmSize.width())); 815 height = qMax(height, qMax(iconSize.height(), pmSize.height())); 828 816 } 829 } 830 } else 817 if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) { 818 int text_width = bt->fontMetrics().width(bt->text()), 819 text_height = bt->fontMetrics().height(); 820 if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) { 821 width = qMax(width, text_width); 822 height += text_height; 823 } else { 824 width += text_width; 825 width = qMax(height, text_height); 826 } 827 } 828 } else 831 829 #endif 832 { 833 // Let's return the size hint... 830 { 831 // Let's return the size hint... 832 width = szHint.width(); 833 height = szHint.height(); 834 } 835 } else { 834 836 width = szHint.width(); 835 837 height = szHint.height(); 836 838 } 837 } else {838 width = szHint.width();839 height = szHint.height();839 width = qMax(20, width + 5); //border 840 height = qMax(20, height + 5); //border 841 ret = QSize(width, height); 840 842 } 841 width = qMax(20, width + 5); //border 842 height = qMax(20, height + 5); //border 843 ret = QSize(width, height); 844 } 845 break; 846 case QStyle::CT_Slider: { 847 int w = -1; 848 const QSlider *sld = qobject_cast<const QSlider *>(widg); 849 // If this conversion fails then the widget was not what it claimed to be. 850 if(sld) { 851 if (sz == QAquaSizeLarge) { 852 if (sld->orientation() == Qt::Horizontal) { 853 w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); 854 if (sld->tickPosition() != QSlider::NoTicks) 855 w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); 856 } else { 857 w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth); 858 if (sld->tickPosition() != QSlider::NoTicks) 859 w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth); 860 } 861 } else if (sz == QAquaSizeSmall) { 862 if (sld->orientation() == Qt::Horizontal) { 863 w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight); 864 if (sld->tickPosition() != QSlider::NoTicks) 865 w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight); 866 } else { 867 w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth); 868 if (sld->tickPosition() != QSlider::NoTicks) 869 w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth); 870 } 871 } else if (sz == QAquaSizeMini) { 872 if (sld->orientation() == Qt::Horizontal) { 873 w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight); 874 if (sld->tickPosition() != QSlider::NoTicks) 875 w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight); 876 } else { 877 w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth); 878 if (sld->tickPosition() != QSlider::NoTicks) 879 w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth); 843 break; 844 case QStyle::CT_Slider: { 845 int w = -1; 846 const QSlider *sld = qobject_cast<const QSlider *>(widg); 847 // If this conversion fails then the widget was not what it claimed to be. 848 if(sld) { 849 if (sz == QAquaSizeLarge) { 850 if (sld->orientation() == Qt::Horizontal) { 851 w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); 852 if (sld->tickPosition() != QSlider::NoTicks) 853 w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); 854 } else { 855 w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth); 856 if (sld->tickPosition() != QSlider::NoTicks) 857 w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth); 858 } 859 } else if (sz == QAquaSizeSmall) { 860 if (sld->orientation() == Qt::Horizontal) { 861 w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight); 862 if (sld->tickPosition() != QSlider::NoTicks) 863 w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight); 864 } else { 865 w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth); 866 if (sld->tickPosition() != QSlider::NoTicks) 867 w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth); 868 } 869 } else if (sz == QAquaSizeMini) { 870 if (sld->orientation() == Qt::Horizontal) { 871 w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight); 872 if (sld->tickPosition() != QSlider::NoTicks) 873 w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight); 874 } else { 875 w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth); 876 if (sld->tickPosition() != QSlider::NoTicks) 877 w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth); 878 } 880 879 } 880 } else { 881 // This is tricky, we were requested to find a size for a slider which is not 882 // a slider. We don't know if this is vertical or horizontal or if we need to 883 // have tick marks or not. 884 // For this case we will return an horizontal slider without tick marks. 885 w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); 886 w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); 881 887 } 882 } else { 883 // This is tricky, we were requested to find a size for a slider which is not 884 // a slider. We don't know if this is vertical or horizontal or if we need to 885 // have tick marks or not. 886 // For this case we will return an horizontal slider without tick marks. 887 w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); 888 w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); 888 if (sld->orientation() == Qt::Horizontal) 889 ret.setHeight(w); 890 else 891 ret.setWidth(w); 892 break; 889 893 } 890 if (sld->orientation() == Qt::Horizontal) 891 ret.setHeight(w); 892 else 893 ret.setWidth(w); 894 break; 895 } 896 #if QT_CONFIG(progressbar) 897 case QStyle::CT_ProgressBar: { 898 int finalValue = -1; 899 Qt::Orientation orient = Qt::Horizontal; 900 if (const QProgressBar *pb = qobject_cast<const QProgressBar *>(widg)) 901 orient = pb->orientation(); 902 903 if (sz == QAquaSizeLarge) 904 finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness) 905 + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset); 906 else 907 finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness) 908 + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset); 909 if (orient == Qt::Horizontal) 910 ret.setHeight(finalValue); 911 else 912 ret.setWidth(finalValue); 913 break; 914 } 915 #endif 916 #if QT_CONFIG(combobox) 917 case QStyle::CT_LineEdit: 918 if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) { 919 //should I take into account the font dimentions of the lineedit? -Sam 894 #ifndef QT_NO_PROGRESSBAR 895 case QStyle::CT_ProgressBar: { 896 int finalValue = -1; 897 Qt::Orientation orient = Qt::Horizontal; 898 if (const QProgressBar *pb = qobject_cast<const QProgressBar *>(widg)) 899 orient = pb->orientation(); 900 920 901 if (sz == QAquaSizeLarge) 921 ret = QSize(-1, 21); 902 finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness) 903 + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset); 922 904 else 923 ret = QSize(-1, 19); 905 finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness) 906 + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset); 907 if (orient == Qt::Horizontal) 908 ret.setHeight(finalValue); 909 else 910 ret.setWidth(finalValue); 911 break; 924 912 } 925 break;926 913 #endif 927 case QStyle::CT_HeaderSection: 928 #if QT_CONFIG(treeview) 929 if (isTreeView(widg)) 930 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight)); 914 #ifndef QT_NO_COMBOBOX 915 case QStyle::CT_LineEdit: 916 if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) { 917 //should I take into account the font dimentions of the lineedit? -Sam 918 if (sz == QAquaSizeLarge) 919 ret = QSize(-1, 21); 920 else 921 ret = QSize(-1, 19); 922 } 923 break; 931 924 #endif 932 break; 933 case QStyle::CT_MenuBar: 934 if (sz == QAquaSizeLarge) { 935 ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]); 936 // In the qt_mac_set_native_menubar(false) case, 937 // we come it here with a zero-height main menu, 938 // preventing the in-window menu from displaying. 939 // Use 22 pixels for the height, by observation. 940 if (ret.height() <= 0) 941 ret.setHeight(22); 942 } 943 break; 944 default: 945 break; 925 case QStyle::CT_HeaderSection: 926 #ifndef QT_NO_TREEVIEW 927 if (isTreeView(widg)) 928 ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight)); 929 #endif 930 break; 931 case QStyle::CT_MenuBar: 932 if (sz == QAquaSizeLarge) { 933 ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]); 934 // In the qt_mac_set_native_menubar(false) case, 935 // we come it here with a zero-height main menu, 936 // preventing the in-window menu from displaying. 937 // Use 22 pixels for the height, by observation. 938 if (ret.height() <= 0) 939 ret.setHeight(22); 940 } 941 break; 942 default: 943 break; 946 944 } 947 945 return ret; 948 946 } … … static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg 952 950 static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini) 953 951 { 954 952 Q_UNUSED(widg); 955 953 956 954 if (large == QSize(-1, -1)) { 957 955 if (small != QSize(-1, -1)) 958 956 return QAquaSizeSmall; … … static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz 966 964 } else if (mini == QSize(-1, -1)) { 967 965 return QAquaSizeLarge; 968 966 } 969 970 #if QT_CONFIG(mainwindow)967 968 #ifndef QT_NO_MAINWINDOW 971 969 if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) { 972 970 //if (small.width() != -1 || small.height() != -1) 973 971 return QAquaSizeSmall; … … static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz 975 973 return QAquaSizeMini; 976 974 } 977 975 #endif 978 976 979 977 #if 0 980 978 /* Figure out which size we're closer to, I just hacked this in, I haven't 981 982 979 tested it as it would probably look pretty strange to have some widgets 980 big and some widgets small in the same window?? -Sam */ 983 981 int large_delta=0; 984 982 if (large.width() != -1) { 985 983 int delta = large.width() - widg->width(); … … static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz 1018 1016 1019 1017 void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const 1020 1018 { 1021 constqreal pixelRatio = p->device()->devicePixelRatioF();1019 qreal pixelRatio = p->device()->devicePixelRatioF(); 1022 1020 static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4"); 1023 1021 const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio); 1024 1022 QPixmap focusRingPixmap; 1025 1023 const qreal size = radius * 2 + 5; 1026 1024 1027 1025 if (!QPixmapCache::find(key, focusRingPixmap)) { 1028 1026 focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio); 1029 1027 focusRingPixmap.fill(Qt::transparent); 1030 1028 focusRingPixmap.setDevicePixelRatio(pixelRatio); 1031 1029 { 1032 const CGFloat focusRingWidth = radius > 0 ? 3.5 : 6;1033 1030 QMacAutoReleasePool pool; 1034 QMacCGContext ctx(&focusRingPixmap);1035 CGContextBeginTransparencyLayer(ctx, NULL);1036 CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below1037 1038 [NSGraphicsContext saveGraphicsState];1039 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx1040 flipped:NO]];1041 CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size);1042 1031 NSBezierPath *focusRingPath; 1043 if (radius > 0) { 1044 const CGFloat roundedRectInset = -1.5; 1045 focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSRectFromCGRect(CGRectInset(focusRingRect, roundedRectInset, roundedRectInset)) 1032 if (radius > 0) 1033 focusRingPath = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(hMargin, vMargin, size, size) 1046 1034 xRadius:radius 1047 1035 yRadius:radius]; 1048 } else { 1049 const CGFloat outerClipInset = -focusRingWidth / 2; 1050 NSBezierPath *focusRingClipPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(CGRectInset(focusRingRect, outerClipInset, outerClipInset))]; 1051 const CGFloat innerClipInset = 1; 1052 NSBezierPath *focusRingInnerClipPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(CGRectInset(focusRingRect, innerClipInset, innerClipInset))]; 1053 [focusRingClipPath appendBezierPath:focusRingInnerClipPath.bezierPathByReversingPath]; 1054 [focusRingClipPath setClip]; 1055 focusRingPath = [NSBezierPath bezierPathWithRect:NSRectFromCGRect(focusRingRect)]; 1056 focusRingPath.lineJoinStyle = NSRoundLineJoinStyle; 1057 } 1058 1059 focusRingPath.lineWidth = focusRingWidth; 1060 [[NSColor keyboardFocusIndicatorColor] setStroke]; 1061 [focusRingPath stroke]; 1062 1063 CGContextEndTransparencyLayer(ctx); 1036 else 1037 focusRingPath = [NSBezierPath bezierPathWithRect:NSMakeRect(hMargin, vMargin, size, size)]; 1038 [NSGraphicsContext saveGraphicsState]; 1039 QMacCGContext gc(&focusRingPixmap); 1040 [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:(CGContextRef)gc 1041 flipped:NO]]; 1042 NSSetFocusRingStyle(NSFocusRingOnly); 1043 [focusRingPath fill]; 1064 1044 [NSGraphicsContext restoreGraphicsState]; 1065 1045 } 1066 1046 QPixmapCache::insert(key, focusRingPixmap); 1067 1047 } 1068 1048 1069 1049 // Add 2 for the actual ring tickness going inwards 1070 1050 const qreal hCornerSize = 2 + hMargin + radius; 1071 1051 const qreal vCornerSize = 2 + vMargin + radius; … … void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h 1097 1077 QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); 1098 1078 } 1099 1079 1100 #if QT_CONFIG(tabbar)1101 void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const1102 {1103 Q_ASSERT(textRect);1104 Q_ASSERT(iconRect);1105 QRect tr = opt->rect;1106 const bool verticalTabs = opt->shape == QTabBar::RoundedEast1107 || opt->shape == QTabBar::RoundedWest1108 || opt->shape == QTabBar::TriangularEast1109 || opt->shape == QTabBar::TriangularWest;1110 if (verticalTabs)1111 tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform1112 1113 int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget);1114 int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget);1115 const int hpadding = 4;1116 const int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;1117 if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)1118 verticalShift = -verticalShift;1119 tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding);1120 1121 // left widget1122 if (!opt->leftButtonSize.isEmpty()) {1123 const int buttonSize = verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width();1124 tr.setLeft(tr.left() + 4 + buttonSize);1125 // make text aligned to center1126 if (opt->rightButtonSize.isEmpty())1127 tr.setRight(tr.right() - 4 - buttonSize);1128 }1129 // right widget1130 if (!opt->rightButtonSize.isEmpty()) {1131 const int buttonSize = verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width();1132 tr.setRight(tr.right() - 4 - buttonSize);1133 // make text aligned to center1134 if (opt->leftButtonSize.isEmpty())1135 tr.setLeft(tr.left() + 4 + buttonSize);1136 }1137 1138 // icon1139 if (!opt->icon.isNull()) {1140 QSize iconSize = opt->iconSize;1141 if (!iconSize.isValid()) {1142 int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize);1143 iconSize = QSize(iconExtent, iconExtent);1144 }1145 QSize tabIconSize = opt->icon.actualSize(iconSize,1146 (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled,1147 (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off);1148 // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize1149 tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height()));1150 1151 *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2,1152 tabIconSize.width(), tabIconSize.height());1153 if (!verticalTabs)1154 *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect);1155 1156 int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;1157 stylePadding -= hpadding;1158 1159 tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4);1160 tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4);1161 }1162 1163 if (!verticalTabs)1164 tr = proxyStyle->visualRect(opt->direction, opt->rect, tr);1165 1166 *textRect = tr;1167 }1168 #endif // QT_CONFIG(tabbar)1169 1170 1080 QAquaWidgetSize QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, 1171 const QWidget *widg,1172 QStyle::ContentsType ct,1173 QSize szHint, QSize *insz) const1081 const QWidget *widg, 1082 QStyle::ContentsType ct, 1083 QSize szHint, QSize *insz) const 1174 1084 { 1175 1085 QAquaWidgetSize sz = aquaSizeConstrain(option, widg, ct, szHint, insz); 1176 1086 if (sz == QAquaSizeUnknown) … … QAquaWidgetSize QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption 1179 1089 } 1180 1090 1181 1091 QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, 1182 QStyle::ContentsType ct, QSize szHint, QSize *insz) const1092 QStyle::ContentsType ct, QSize szHint, QSize *insz) const 1183 1093 { 1184 1094 #if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) 1185 1095 if (option) { … … QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, 1188 1098 if (option->state & QStyle::State_Mini) 1189 1099 return QAquaSizeMini; 1190 1100 } 1191 1101 1192 1102 if (!widg) { 1193 1103 if (insz) 1194 1104 *insz = QSize(); … … QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, 1198 1108 return QAquaSizeMini; 1199 1109 return QAquaSizeUnknown; 1200 1110 } 1201 1111 1202 1112 Q_Q(const QMacStyle); 1203 1113 QSize large = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeLarge), 1204 1205 1114 small = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeSmall), 1115 mini = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeMini); 1206 1116 bool guess_size = false; 1207 1117 QAquaWidgetSize ret = QAquaSizeUnknown; 1208 1118 QMacStyle::WidgetSizePolicy wsp = q->widgetSizePolicy(widg); … … QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, 1216 1126 ret = QAquaSizeLarge; 1217 1127 if (guess_size) 1218 1128 ret = qt_aqua_guess_size(widg, large, small, mini); 1219 1129 1220 1130 QSize *sz = 0; 1221 1131 if (ret == QAquaSizeSmall) 1222 1132 sz = &small; … … QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, 1253 1163 } 1254 1164 1255 1165 /** 1256 1257 1258 */1166 Returns the free space awailable for contents inside the 1167 button (and not the size of the contents itself) 1168 */ 1259 1169 HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn, 1260 1170 const HIThemeButtonDrawInfo *bdi) const 1261 1171 { … … HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn, 1268 1178 } else if (bdi->kind == kThemePushButtonMini) { 1269 1179 outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; 1270 1180 } 1271 1181 1272 1182 HIRect contentBounds; 1273 1183 HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds); 1274 1184 return contentBounds; 1275 1185 } 1276 1186 1277 1187 /** 1278 1279 1280 */1188 Calculates the size of the button contents. 1189 This includes both the text and the icon. 1190 */ 1281 1191 QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const 1282 1192 { 1283 1193 Q_Q(const QMacStyle); 1284 1194 QSize csz(0, 0); 1285 1195 QSize iconSize = btn->icon.isNull() ? QSize(0, 0) 1286 1196 : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0)); 1287 1197 QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1) 1288 1198 : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text); 1289 1199 csz.setWidth(iconSize.width() + textRect.width() 1290 + ((btn->features & QStyleOptionButton::HasMenu)1291 1200 + ((btn->features & QStyleOptionButton::HasMenu) 1201 ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0)); 1292 1202 csz.setHeight(qMax(iconSize.height(), textRect.height())); 1293 1203 return csz; 1294 1204 } 1295 1205 1296 1206 /** 1297 1298 1299 1300 */1207 Checks if the actual contents of btn fits inside the free content bounds of 1208 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' 1209 for determining which button kind to use for drawing. 1210 */ 1301 1211 bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn, 1302 1212 HIThemeButtonDrawInfo *bdi, 1303 1213 ThemeButtonKind buttonKindToCheck) const … … bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn, 1308 1218 QRect freeContentRect = qt_qrectForHIRect(pushButtonContentBounds(btn, bdi)); 1309 1219 bdi->kind = tmp; 1310 1220 return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(), 1311 contentSize.width(), contentSize.height()));1221 contentSize.width(), contentSize.height())); 1312 1222 } 1313 1223 1314 1224 /** 1315 1316 1317 1318 1319 */1225 Creates a HIThemeButtonDrawInfo structure that specifies the correct button 1226 kind and other details to use for drawing the given push button. Which 1227 button kind depends on the size of the button, the size of the contents, 1228 explicit user style settings, etc. 1229 */ 1320 1230 void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, 1321 1231 const QWidget *widget, 1322 1232 const ThemeDrawState tds, … … void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, 1328 1238 bdi->version = qt_mac_hitheme_version; 1329 1239 bdi->state = tdsModified; 1330 1240 bdi->value = kThemeButtonOff; 1331 1241 1332 1242 if (tds == kThemeStateInactive) 1333 1243 bdi->state = kThemeStateActive; 1334 1244 if (btn->state & QStyle::State_HasFocus) 1335 1245 bdi->adornment = kThemeAdornmentFocus; 1336 1246 else 1337 1247 bdi->adornment = kThemeAdornmentNone; 1338 1339 1248 1249 1340 1250 if (btn->features & (QStyleOptionButton::Flat)) { 1341 1251 bdi->kind = kThemeBevelButton; 1342 1252 } else { 1343 1253 switch (aquaSizeConstrain(btn, widget)) { 1344 case QAquaSizeSmall: 1345 bdi->kind = kThemePushButtonSmall; 1346 break; 1347 case QAquaSizeMini: 1348 bdi->kind = kThemePushButtonMini; 1349 break; 1350 case QAquaSizeLarge: 1351 // ... We should honor if the user is explicit about using the 1352 // large button. But right now Qt will specify the large button 1353 // as default rather than QAquaSizeUnknown. 1354 // So we treat it like QAquaSizeUnknown 1355 // to get the dynamic choosing of button kind. 1356 case QAquaSizeUnknown: 1357 // Choose the button kind that closest match the button rect, but at the 1358 // same time displays the button contents without clipping. 1359 bdi->kind = kThemeBevelButton; 1360 if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){ 1361 if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { 1362 if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){ 1363 if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) 1364 bdi->kind = kThemePushButtonMini; 1365 } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){ 1366 if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) 1367 bdi->kind = kThemePushButtonSmall; 1368 } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { 1254 case QAquaSizeSmall: 1255 bdi->kind = kThemePushButtonSmall; 1256 break; 1257 case QAquaSizeMini: 1258 bdi->kind = kThemePushButtonMini; 1259 break; 1260 case QAquaSizeLarge: 1261 // ... We should honor if the user is explicit about using the 1262 // large button. But right now Qt will specify the large button 1263 // as default rather than QAquaSizeUnknown. 1264 // So we treat it like QAquaSizeUnknown 1265 // to get the dynamic choosing of button kind. 1266 case QAquaSizeUnknown: 1267 // Choose the button kind that closest match the button rect, but at the 1268 // same time displays the button contents without clipping. 1269 bdi->kind = kThemeBevelButton; 1270 if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){ 1271 if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { 1272 if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){ 1273 if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) 1274 bdi->kind = kThemePushButtonMini; 1275 } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){ 1276 if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) 1277 bdi->kind = kThemePushButtonSmall; 1278 } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { 1279 bdi->kind = kThemePushButton; 1280 } 1281 } else { 1369 1282 bdi->kind = kThemePushButton; 1370 1283 } 1371 } else {1372 bdi->kind = kThemePushButton;1373 1284 } 1374 }1375 1285 } 1376 1286 } 1377 1287 } 1378 1288 1379 #if QT_CONFIG(pushbutton)1380 1289 bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option) 1381 1290 { 1382 1291 QMacStyle *macStyle = qobject_cast<QMacStyle *>(pushButton->style()); … … bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOpti 1386 1295 macStyle->d_func()->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); 1387 1296 return bdi.kind == kThemeBevelButton; 1388 1297 } 1389 #endif1390 1298 1391 1299 /** 1392 1393 1394 1395 1396 */1300 Creates a HIThemeButtonDrawInfo structure that specifies the correct button 1301 kind and other details to use for drawing the given combobox. Which button 1302 kind depends on the size of the combo, wether or not it is editable, 1303 explicit user style settings, etc. 1304 */ 1397 1305 void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, 1398 const QWidget *widget, const ThemeDrawState &tds) const1306 const QWidget *widget, const ThemeDrawState &tds) const 1399 1307 { 1400 1308 bdi->version = qt_mac_hitheme_version; 1401 1309 bdi->adornment = kThemeAdornmentArrowLeftArrow; … … void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem 1404 1312 bdi->adornment = kThemeAdornmentFocus; 1405 1313 if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) 1406 1314 bdi->state = kThemeStatePressed; 1315 else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) 1316 bdi->state = kThemeStateActive; 1407 1317 else 1408 1318 bdi->state = tds; 1409 1319 1410 1320 QAquaWidgetSize aSize = aquaSizeConstrain(combo, widget); 1411 1321 switch (aSize) { 1412 case QAquaSizeMini:1413 bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini)1322 case QAquaSizeMini: 1323 bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) 1414 1324 : ThemeButtonKind(kThemePopupButtonMini); 1415 break;1416 case QAquaSizeSmall:1417 bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall)1325 break; 1326 case QAquaSizeSmall: 1327 bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall) 1418 1328 : ThemeButtonKind(kThemePopupButtonSmall); 1419 break;1420 case QAquaSizeUnknown:1421 case QAquaSizeLarge:1422 // Unless the user explicitly specified large buttons, determine the1423 // kind by looking at the combox size.1424 // ... specifying small and mini-buttons it not a current feature of1425 // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add1426 // an extra check here before using the mini and small buttons.1427 int h = combo->rect.size().height();1428 if (combo->editable){1429 #if QT_CONFIG(datetimeedit)1430 if (qobject_cast<const QDateTimeEdit *>(widget)) {1431 // Except when, you know, we get a QDateTimeEdit with calendarPopup1432 // enabled. And then things get weird, basically because it's a1433 // transvestite spinbox with editable combobox tendencies. Meaning1434 // that it wants to look a combobox, except that it isn't one, so it1435 // doesn't get all those extra free margins around. (Don't know whose1436 // idea those margins were, but now it looks like we're stuck with1437 // them forever). So anyway, the height threshold should be smaller1438 // in this case, or the style gets confused when it needs to render1439 // or return any subcontrol size of the poor thing.1440 if (h < 9)1441 bdi->kind = kThemeComboBoxMini;1442 else if (h < 22)1443 bdi->kind = kThemeComboBoxSmall;1444 else1445 bdi->kind = kThemeComboBox;1446 } else1329 break; 1330 case QAquaSizeUnknown: 1331 case QAquaSizeLarge: 1332 // Unless the user explicitly specified large buttons, determine the 1333 // kind by looking at the combox size. 1334 // ... specifying small and mini-buttons it not a current feature of 1335 // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add 1336 // an extra check here before using the mini and small buttons. 1337 int h = combo->rect.size().height(); 1338 if (combo->editable){ 1339 #ifndef QT_NO_DATETIMEEDIT 1340 if (qobject_cast<const QDateTimeEdit *>(widget)) { 1341 // Except when, you know, we get a QDateTimeEdit with calendarPopup 1342 // enabled. And then things get weird, basically because it's a 1343 // transvestite spinbox with editable combobox tendencies. Meaning 1344 // that it wants to look a combobox, except that it isn't one, so it 1345 // doesn't get all those extra free margins around. (Don't know whose 1346 // idea those margins were, but now it looks like we're stuck with 1347 // them forever). So anyway, the height threshold should be smaller 1348 // in this case, or the style gets confused when it needs to render 1349 // or return any subcontrol size of the poor thing. 1350 if (h < 9) 1351 bdi->kind = kThemeComboBoxMini; 1352 else if (h < 22) 1353 bdi->kind = kThemeComboBoxSmall; 1354 else 1355 bdi->kind = kThemeComboBox; 1356 } else 1447 1357 #endif 1448 { 1358 { 1359 if (h < 21) 1360 bdi->kind = kThemeComboBoxMini; 1361 else if (h < 26) 1362 bdi->kind = kThemeComboBoxSmall; 1363 else 1364 bdi->kind = kThemeComboBox; 1365 } 1366 } else { 1367 // Even if we specify that we want the kThemePopupButton, Carbon 1368 // will use the kThemePopupButtonSmall if the size matches. So we 1369 // do the same size check explicit to have the size of the inner 1370 // text field be correct. Therefore, do this even if the user specifies 1371 // the use of LargeButtons explicit. 1449 1372 if (h < 21) 1450 bdi->kind = kTheme ComboBoxMini;1373 bdi->kind = kThemePopupButtonMini; 1451 1374 else if (h < 26) 1452 bdi->kind = kTheme ComboBoxSmall;1375 bdi->kind = kThemePopupButtonSmall; 1453 1376 else 1454 bdi->kind = kTheme ComboBox;1377 bdi->kind = kThemePopupButton; 1455 1378 } 1456 } else { 1457 // Even if we specify that we want the kThemePopupButton, Carbon 1458 // will use the kThemePopupButtonSmall if the size matches. So we 1459 // do the same size check explicit to have the size of the inner 1460 // text field be correct. Therefore, do this even if the user specifies 1461 // the use of LargeButtons explicit. 1462 if (h < 21) 1463 bdi->kind = kThemePopupButtonMini; 1464 else if (h < 26) 1465 bdi->kind = kThemePopupButtonSmall; 1466 else 1467 bdi->kind = kThemePopupButton; 1468 } 1469 break; 1379 break; 1470 1380 } 1471 1381 } 1472 1382 1473 1383 /** 1474 1475 1476 */1384 Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain 1385 the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. 1386 */ 1477 1387 HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int buttonKind) 1478 1388 { 1479 1389 HIRect innerBounds = outerBounds; … … HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int butt 1481 1391 // So make the rect a bit smaller to compensate 1482 1392 // (I wish HIThemeGetButtonBackgroundBounds worked) 1483 1393 switch (buttonKind){ 1484 case kThemePopupButton:1485 innerBounds.origin.x += 2;1486 innerBounds.origin.y += 2;1487 innerBounds.size.width -= 5;1488 innerBounds.size.height -= 6;1489 break;1490 case kThemePopupButtonSmall:1491 innerBounds.origin.x += 3;1492 innerBounds.origin.y += 3;1493 innerBounds.size.width -= 6;1494 innerBounds.size.height -= 7;1495 break;1496 case kThemePopupButtonMini:1497 innerBounds.origin.x += 2;1498 innerBounds.origin.y += 2;1499 innerBounds.size.width -= 5;1500 innerBounds.size.height -= 6;1501 break;1502 case kThemeComboBox:1503 innerBounds.origin.x += 3;1504 innerBounds.origin.y += 2;1505 innerBounds.size.width -= 6;1506 innerBounds.size.height -= 8;1507 break;1508 case kThemeComboBoxSmall:1509 innerBounds.origin.x += 3;1510 innerBounds.origin.y += 3;1511 innerBounds.size.width -= 7;1512 innerBounds.size.height -= 8;1513 break;1514 case kThemeComboBoxMini:1515 innerBounds.origin.x += 3;1516 innerBounds.origin.y += 3;1517 innerBounds.size.width -= 4;1518 innerBounds.size.height -= 8;1519 break;1520 default:1521 break;1394 case kThemePopupButton: 1395 innerBounds.origin.x += 2; 1396 innerBounds.origin.y += 2; 1397 innerBounds.size.width -= 5; 1398 innerBounds.size.height -= 6; 1399 break; 1400 case kThemePopupButtonSmall: 1401 innerBounds.origin.x += 3; 1402 innerBounds.origin.y += 3; 1403 innerBounds.size.width -= 6; 1404 innerBounds.size.height -= 7; 1405 break; 1406 case kThemePopupButtonMini: 1407 innerBounds.origin.x += 2; 1408 innerBounds.origin.y += 2; 1409 innerBounds.size.width -= 5; 1410 innerBounds.size.height -= 6; 1411 break; 1412 case kThemeComboBox: 1413 innerBounds.origin.x += 3; 1414 innerBounds.origin.y += 2; 1415 innerBounds.size.width -= 6; 1416 innerBounds.size.height -= 8; 1417 break; 1418 case kThemeComboBoxSmall: 1419 innerBounds.origin.x += 3; 1420 innerBounds.origin.y += 3; 1421 innerBounds.size.width -= 7; 1422 innerBounds.size.height -= 8; 1423 break; 1424 case kThemeComboBoxMini: 1425 innerBounds.origin.x += 3; 1426 innerBounds.origin.y += 3; 1427 innerBounds.size.width -= 4; 1428 innerBounds.size.height -= 8; 1429 break; 1430 default: 1431 break; 1522 1432 } 1523 1433 return innerBounds; 1524 1434 } 1525 1435 1526 1436 /** 1527 1528 1529 */1437 Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind 1438 of combobox we choose to draw. This function calculates and returns this size. 1439 */ 1530 1440 QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi) 1531 1441 { 1532 1442 QRect ret = outerBounds; 1533 1443 switch (bdi.kind){ 1534 case kThemeComboBox:1535 ret.adjust(5, 5, -22, -5);1536 break;1537 case kThemeComboBoxSmall:1538 ret.adjust(4, 5, -18, 0);1539 ret.setHeight(16);1540 break;1541 case kThemeComboBoxMini:1542 ret.adjust(4, 5, -16, 0);1543 ret.setHeight(13);1544 break;1545 case kThemePopupButton:1546 ret.adjust(10, 2, -23, -4);1547 break;1548 case kThemePopupButtonSmall:1549 ret.adjust(9, 3, -20, -3);1550 break;1551 case kThemePopupButtonMini:1552 ret.adjust(8, 3, -19, 0);1553 ret.setHeight(13);1554 break;1444 case kThemeComboBox: 1445 ret.adjust(5, 5, -22, -5); 1446 break; 1447 case kThemeComboBoxSmall: 1448 ret.adjust(4, 5, -18, 0); 1449 ret.setHeight(16); 1450 break; 1451 case kThemeComboBoxMini: 1452 ret.adjust(4, 5, -16, 0); 1453 ret.setHeight(13); 1454 break; 1455 case kThemePopupButton: 1456 ret.adjust(10, 2, -23, -4); 1457 break; 1458 case kThemePopupButtonSmall: 1459 ret.adjust(9, 3, -20, -3); 1460 break; 1461 case kThemePopupButtonMini: 1462 ret.adjust(8, 3, -19, 0); 1463 ret.setHeight(13); 1464 break; 1555 1465 } 1556 1466 return ret; 1557 1467 } 1558 1468 1559 1469 /** 1560 1561 1562 1563 */1470 Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version, 1471 create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop 1472 it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. 1473 */ 1564 1474 void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) 1565 1475 { 1566 1476 if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ … … void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButt 1579 1489 buffPainter.end(); 1580 1490 QPixmapCache::insert(key, buffer); 1581 1491 } 1582 1492 1583 1493 const int bwidth = 20; 1584 1494 const int fwidth = 10; 1585 1495 const int fheight = 10; … … void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButt 1590 1500 int flower = h - fheight; 1591 1501 int sheight = flower - fheight; 1592 1502 int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2; 1593 1503 1594 1504 // Draw upper and lower gap 1595 1505 p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight); 1596 1506 p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight); … … void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButt 1609 1519 } 1610 1520 1611 1521 /** 1612 1613 1614 */1522 Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header 1523 onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. 1524 */ 1615 1525 void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds, 1616 bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p)1526 bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p) 1617 1527 { 1618 1528 static SInt32 headerHeight = 0; 1619 1529 static OSStatus err = GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight); 1620 1530 Q_UNUSED(err); 1621 1531 1622 1532 QPixmap buffer; 1623 1533 QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value)); 1624 1534 if (!QPixmapCache::find(key, buffer)) { … … void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds, 1637 1547 const int frameh_s = 3; 1638 1548 const int transh = buffer.height() - frameh_n - frameh_s; 1639 1549 int center = buttonh - frameh_s - int(transh / 2.0f) + 1; // Align bottom; 1640 1550 1641 1551 int skipTopBorder = 0; 1642 1552 if (!drawTopBorder) 1643 1553 skipTopBorder = 1; 1644 1554 1645 1555 p->translate(outerBounds.origin.x, outerBounds.origin.y); 1646 1556 1647 1557 p->drawPixmap(QRect(QRect(0, -skipTopBorder, buttonw - framew , frameh_n)), buffer, QRect(framew, 0, 1, frameh_n)); 1648 1558 p->drawPixmap(QRect(0, buttonh - frameh_s, buttonw - framew, frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, frameh_s)); 1649 1559 // Draw upper and lower center blocks … … void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds, 1669 1579 // Draw left center transition block border 1670 1580 p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(0, frameh_n + 1, framew, transh)); 1671 1581 } 1672 1582 1673 1583 p->translate(-outerBounds.origin.x, -outerBounds.origin.y); 1674 1584 } 1675 1585 1676 1586 /* 1677 1678 1679 1680 */1587 Returns cutoff sizes for scroll bars. 1588 thumbIndicatorCutoff is the smallest size where the thumb indicator is drawn. 1589 scrollButtonsCutoff is the smallest size where the up/down buttons is drawn. 1590 */ 1681 1591 enum ScrollBarCutoffType { thumbIndicatorCutoff = 0, scrollButtonsCutoff = 1 }; 1682 1592 static int scrollButtonsCutoffSize(ScrollBarCutoffType cutoffType, QMacStyle::WidgetSizePolicy widgetSize) 1683 1593 { 1684 1594 // Mini scroll bars do not exist as of version 10.4. 1685 1595 if (widgetSize == QMacStyle::SizeMini) 1686 1596 return 0; 1687 1597 1688 1598 const int sizeIndex = (widgetSize == QMacStyle::SizeSmall) ? 1 : 0; 1689 1599 static const int sizeTable[2][2] = { { 61, 56 }, { 49, 44 } }; 1690 1600 return sizeTable[sizeIndex][cutoffType]; 1691 1601 } 1692 1602 1693 1603 void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, 1694 HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const1604 HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const 1695 1605 { 1696 1606 memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another... 1697 1607 tdi->version = qt_mac_hitheme_version; … … void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti 1699 1609 tdi->filler1 = 0; 1700 1610 bool isScrollbar = (cc == QStyle::CC_ScrollBar); 1701 1611 switch (aquaSizeConstrain(slider, needToRemoveMe)) { 1702 case QAquaSizeUnknown:1703 case QAquaSizeLarge:1704 if (isScrollbar)1705 tdi->kind = kThemeMediumScrollBar;1706 else1707 tdi->kind = kThemeMediumSlider;1708 break;1709 case QAquaSizeMini:1710 if (isScrollbar)1711 tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented1712 else1713 tdi->kind = kThemeMiniSlider;1714 break;1715 case QAquaSizeSmall:1716 if (isScrollbar)1717 tdi->kind = kThemeSmallScrollBar;1718 else1719 tdi->kind = kThemeSmallSlider;1720 break;1612 case QAquaSizeUnknown: 1613 case QAquaSizeLarge: 1614 if (isScrollbar) 1615 tdi->kind = kThemeMediumScrollBar; 1616 else 1617 tdi->kind = kThemeMediumSlider; 1618 break; 1619 case QAquaSizeMini: 1620 if (isScrollbar) 1621 tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented 1622 else 1623 tdi->kind = kThemeMiniSlider; 1624 break; 1625 case QAquaSizeSmall: 1626 if (isScrollbar) 1627 tdi->kind = kThemeSmallScrollBar; 1628 else 1629 tdi->kind = kThemeSmallSlider; 1630 break; 1721 1631 } 1722 1632 1723 1633 bool usePlainKnob = slider->tickPosition == QSlider::NoTicks 1724 1725 1634 || slider->tickPosition == QSlider::TicksBothSides; 1635 1726 1636 tdi->bounds = qt_hirectForQRect(slider->rect); 1727 if (isScrollbar ) {1637 if (isScrollbar || QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) { 1728 1638 tdi->min = slider->minimum; 1729 1639 tdi->max = slider->maximum; 1730 1640 tdi->value = slider->sliderPosition; … … void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti 1737 1647 tdi->max = 10 * slider->rect.width(); 1738 1648 else 1739 1649 tdi->max = 10 * slider->rect.height(); 1740 1650 1741 1651 int range = slider->maximum - slider->minimum; 1742 1652 if (range == 0) { 1743 1653 tdi->value = 0; … … void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti 1760 1670 tdi->attributes &= ~kThemeTrackRightToLeft; 1761 1671 } 1762 1672 } 1763 1673 1764 1674 // Tiger broke reverse scroll bars so put them back and "fake it" 1765 1675 if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) { 1766 1676 tdi->attributes &= ~kThemeTrackRightToLeft; 1767 1677 tdi->value = tdi->max - tdi->value; 1768 1678 } 1769 1679 1770 1680 tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive 1771 1681 : kThemeTrackDisabled; 1772 1682 if (!isScrollbar) { 1773 1683 if (slider->state & QStyle::QStyle::State_HasFocus) 1774 1684 tdi->attributes |= kThemeTrackHasFocus; … … void QMacStylePrivate::setAutoDefaultButton(QObject *button) const 1797 1707 } 1798 1708 1799 1709 QMacStylePrivate::QMacStylePrivate() 1800 1710 : mouseDown(false), backingStoreNSView(nil) 1801 1711 { 1802 1712 defaultButtonStart = CFAbsoluteTimeGetCurrent(); 1803 1713 memset(&buttonState, 0, sizeof(ButtonState)); 1804 1714 1805 1715 if (ptrHIShapeGetBounds == 0) { 1806 1716 QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon")); 1807 1717 library.setLoadHints(QLibrary::ExportExternalSymbolsHint); 1808 1718 ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds")); 1809 1719 } 1810 1720 1811 1721 } 1812 1722 1813 1723 QMacStylePrivate::~QMacStylePrivate() 1814 1724 { 1815 1725 QMacAutoReleasePool pool; 1816 1726 Q_FOREACH (NSView *b, cocoaControls) 1817 1727 [b release]; 1818 1728 } 1819 1729 1820 1730 ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) … … ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) 1837 1747 static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind) 1838 1748 { 1839 1749 QCocoaWidget w; 1840 1750 1841 1751 switch (kind) { 1842 case kThemePopupButton:1843 case kThemePopupButtonSmall:1844 case kThemePopupButtonMini:1845 w.first = QCocoaPopupButton;1846 break;1847 case kThemeComboBox:1848 w.first = QCocoaComboBox;1849 break;1850 case kThemeArrowButton:1851 w.first = QCocoaArrowButton;1852 break;1853 case kThemeCheckBox:1854 case kThemeCheckBoxSmall:1855 case kThemeCheckBoxMini:1856 w.first = QCocoaCheckBox;1857 break;1858 case kThemeRadioButton:1859 case kThemeRadioButtonSmall:1860 case kThemeRadioButtonMini:1861 w.first = QCocoaRadioButton;1862 break;1863 case kThemePushButton:1864 case kThemePushButtonSmall:1865 case kThemePushButtonMini:1866 w.first = QCocoaPushButton;1867 break;1868 default:1869 break;1752 case kThemePopupButton: 1753 case kThemePopupButtonSmall: 1754 case kThemePopupButtonMini: 1755 w.first = QCocoaPopupButton; 1756 break; 1757 case kThemeComboBox: 1758 w.first = QCocoaComboBox; 1759 break; 1760 case kThemeArrowButton: 1761 w.first = QCocoaArrowButton; 1762 break; 1763 case kThemeCheckBox: 1764 case kThemeCheckBoxSmall: 1765 case kThemeCheckBoxMini: 1766 w.first = QCocoaCheckBox; 1767 break; 1768 case kThemeRadioButton: 1769 case kThemeRadioButtonSmall: 1770 case kThemeRadioButtonMini: 1771 w.first = QCocoaRadioButton; 1772 break; 1773 case kThemePushButton: 1774 case kThemePushButtonSmall: 1775 case kThemePushButtonMini: 1776 w.first = QCocoaPushButton; 1777 break; 1778 default: 1779 break; 1870 1780 } 1871 1781 1872 1782 switch (kind) { 1873 case kThemePushButtonSmall:1874 case kThemePopupButtonSmall:1875 case kThemeCheckBoxSmall:1876 case kThemeRadioButtonSmall:1877 w.second = QAquaSizeSmall;1878 break;1879 case kThemePushButtonMini:1880 case kThemePopupButtonMini:1881 case kThemeCheckBoxMini:1882 case kThemeRadioButtonMini:1883 w.second = QAquaSizeMini;1884 break;1885 default:1886 w.second = QAquaSizeLarge;1887 break;1783 case kThemePushButtonSmall: 1784 case kThemePopupButtonSmall: 1785 case kThemeCheckBoxSmall: 1786 case kThemeRadioButtonSmall: 1787 w.second = QAquaSizeSmall; 1788 break; 1789 case kThemePushButtonMini: 1790 case kThemePopupButtonMini: 1791 case kThemeCheckBoxMini: 1792 case kThemeRadioButtonMini: 1793 w.second = QAquaSizeMini; 1794 break; 1795 default: 1796 w.second = QAquaSizeLarge; 1797 break; 1888 1798 } 1889 1799 1890 1800 return w; 1891 1801 } 1892 1802 … … NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const 1894 1804 { 1895 1805 NSView *bv = cocoaControls[widget]; 1896 1806 if (!bv) { 1897 1807 1898 1808 if (widget.first == QCocoaPopupButton 1899 1809 || widget.first == QCocoaPullDownButton) 1900 1810 bv = [[NSPopUpButton alloc] init]; … … NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const 1908 1818 bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 10, 100)]; 1909 1819 else 1910 1820 bv = [[NSButton alloc] init]; 1911 1821 1912 1822 switch (widget.first) { 1913 case QCocoaArrowButton: {1914 NSButton *bc = (NSButton *)bv;1915 bc.buttonType = NSOnOffButton;1916 bc.bezelStyle = NSDisclosureBezelStyle;1917 break;1918 }1919 case QCocoaCheckBox: {1920 NSButton *bc = (NSButton *)bv;1921 bc.buttonType = NSSwitchButton;1922 break;1923 }1924 case QCocoaRadioButton: {1925 NSButton *bc = (NSButton *)bv;1926 bc.buttonType = NSRadioButton;1927 break;1928 }1929 case QCocoaPushButton: {1930 NSButton *bc = (NSButton *)bv;1931 bc.buttonType = NSMomentaryLightButton;1932 bc.bezelStyle = NSRoundedBezelStyle;1933 break;1934 }1935 case QCocoaPullDownButton: {1936 NSPopUpButton *bc = (NSPopUpButton *)bv;1937 bc.pullsDown = YES;1938 break;1939 }1940 default:1941 break;1823 case QCocoaArrowButton: { 1824 NSButton *bc = (NSButton *)bv; 1825 bc.buttonType = NSOnOffButton; 1826 bc.bezelStyle = NSDisclosureBezelStyle; 1827 break; 1828 } 1829 case QCocoaCheckBox: { 1830 NSButton *bc = (NSButton *)bv; 1831 bc.buttonType = NSSwitchButton; 1832 break; 1833 } 1834 case QCocoaRadioButton: { 1835 NSButton *bc = (NSButton *)bv; 1836 bc.buttonType = NSRadioButton; 1837 break; 1838 } 1839 case QCocoaPushButton: { 1840 NSButton *bc = (NSButton *)bv; 1841 bc.buttonType = NSMomentaryLightButton; 1842 bc.bezelStyle = NSRoundedBezelStyle; 1843 break; 1844 } 1845 case QCocoaPullDownButton: { 1846 NSPopUpButton *bc = (NSPopUpButton *)bv; 1847 bc.pullsDown = YES; 1848 break; 1849 } 1850 default: 1851 break; 1942 1852 } 1943 1853 1944 1854 if ([bv isKindOfClass:[NSButton class]]) { 1945 1855 NSButton *bc = (NSButton *)bv; 1946 1856 bc.title = @""; 1947 1857 } 1948 1858 1949 1859 if ([bv isKindOfClass:[NSControl class]]) { 1950 1860 NSCell *bcell = [(NSControl *)bv cell]; 1951 1861 switch (widget.second) { 1952 case QAquaSizeSmall:1953 bcell.controlSize = NSSmallControlSize;1954 break;1955 case QAquaSizeMini:1956 bcell.controlSize = NSMiniControlSize;1957 break;1958 default:1959 break;1862 case QAquaSizeSmall: 1863 bcell.controlSize = NSSmallControlSize; 1864 break; 1865 case QAquaSizeMini: 1866 bcell.controlSize = NSMiniControlSize; 1867 break; 1868 default: 1869 break; 1960 1870 } 1961 1871 } 1962 1872 1963 1873 const_cast<QMacStylePrivate *>(this)->cocoaControls.insert(widget, bv); 1964 1874 } 1965 1875 1966 1876 return bv; 1967 1877 } 1968 1878 … … void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const 1992 1902 offset = QPoint(5, 0); 1993 1903 else if (widget == QCocoaWidget(QCocoaComboBox, QAquaSizeLarge)) 1994 1904 offset = QPoint(3, 0); 1995 1905 1996 1906 QMacCGContext ctx(p); 1997 1907 CGContextSaveGState(ctx); 1998 1908 CGContextTranslateCTM(ctx, offset.x(), offset.y()); 1999 1909 2000 1910 [NSGraphicsContext saveGraphicsState]; 2001 1911 [NSGraphicsContext setCurrentContext:[NSGraphicsContext 2002 1912 graphicsContextWithGraphicsPort:ctx flipped:YES]]; 2003 1913 2004 1914 NSRect rect = NSMakeRect(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); 2005 1915 2006 1916 [backingStoreNSView addSubview:view]; 2007 1917 view.frame = rect; 2008 1918 if (drawRectBlock) … … void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const 2010 1920 else 2011 1921 [view drawRect:rect]; 2012 1922 [view removeFromSuperviewWithoutNeedingDisplay]; 2013 1923 2014 1924 [NSGraphicsContext restoreGraphicsState]; 2015 1925 CGContextRestoreGState(ctx); 2016 1926 } … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2024 1934 QPainter *p, const QStyleOption *opt) const 2025 1935 { 2026 1936 int xoff = 0, 2027 2028 2029 2030 2031 1937 yoff = 0, 1938 extraWidth = 0, 1939 extraHeight = 0, 1940 finalyoff = 0; 1941 2032 1942 const bool combo = opt->type == QStyleOption::SO_ComboBox; 2033 1943 const bool editableCombo = bdi->kind == kThemeComboBox 2034 2035 1944 || bdi->kind == kThemeComboBoxSmall 1945 || bdi->kind == kThemeComboBoxMini; 2036 1946 const bool button = opt->type == QStyleOption::SO_Button; 2037 1947 const bool viewItem = opt->type == QStyleOption::SO_ViewItem; 2038 1948 const bool pressed = bdi->state == kThemeStatePressed; 2039 1949 const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; 1950 2040 1951 if (button && pressed) { 2041 1952 if (bdi->kind == kThemePushButton) { 2042 1953 extraHeight = 2; … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2046 1957 extraHeight = 5; 2047 1958 } 2048 1959 } 2049 1960 2050 1961 int devicePixelRatio = p->device()->devicePixelRatioF(); 2051 1962 int width = devicePixelRatio * (int(macRect.size.width) + extraWidth); 2052 1963 int height = devicePixelRatio * (int(macRect.size.height) + extraHeight); 2053 1964 2054 1965 if (width <= 0 || height <= 0) 2055 1966 return; // nothing to draw 2056 1967 2057 1968 QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_') 2058 2059 2060 1969 + QString::number(bdi->value) + QLatin1Char('_') 1970 + (button ? QString::number(bdi->state) + QLatin1Char('_') : QString()) 1971 + QLatin1Char('_') + QString::number(width) + QLatin1Char('_') + QString::number(height); 2061 1972 QPixmap pm; 2062 1973 if (!QPixmapCache::find(key, pm)) { 2063 1974 QPixmap activePixmap(width, height); … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2074 1985 HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); 2075 1986 if (button && pressed) 2076 1987 bdi->state = kThemeStateActive; 2077 else if ( viewItem)1988 else if (usingYosemiteOrLater && viewItem) 2078 1989 bdi->state = kThemeStateInactive; 2079 1990 HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); 2080 1991 } 2081 1992 } 2082 1993 2083 1994 if (!combo && !button && bdi->value == kThemeButtonOff) { 2084 1995 pm = activePixmap; 2085 } else if ((combo && !editableCombo) || button) { 1996 } else if (!usingYosemiteOrLater && (combo || button)) { 1997 QImage image = activePixmap.toImage(); 1998 1999 for (int y = 0; y < height; ++y) { 2000 QRgb *scanLine = reinterpret_cast<QRgb *>(image.scanLine(y)); 2001 2002 for (int x = 0; x < width; ++x) { 2003 QRgb &pixel = scanLine[x]; 2004 2005 int darkest = qRed(pixel); 2006 int mid = qGreen(pixel); 2007 int lightest = qBlue(pixel); 2008 2009 if (darkest > mid) 2010 qSwap(darkest, mid); 2011 if (mid > lightest) 2012 qSwap(mid, lightest); 2013 if (darkest > mid) 2014 qSwap(darkest, mid); 2015 2016 int gray = (mid + 2 * lightest) / 3; 2017 if (pressed) 2018 gray *= 0.88; 2019 pixel = qRgba(gray, gray, gray, qAlpha(pixel)); 2020 } 2021 } 2022 pm = QPixmap::fromImage(image); 2023 } else if ((usingYosemiteOrLater && combo && !editableCombo) || button) { 2086 2024 QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi->kind); 2087 2025 NSButton *bc = (NSButton *)cocoaControl(cw); 2088 2026 [bc highlight:pressed]; 2089 2027 bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; 2090 2028 bc.allowsMixedState = YES; 2091 2029 bc.state = bdi->value == kThemeButtonOn ? NSOnState : 2092 2030 bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState; 2093 2031 // The view frame may differ from what we pass to HITheme 2094 2032 QRect rect = opt->rect; 2095 2033 if (bdi->kind == kThemePopupButtonMini) 2096 2034 rect.adjust(0, 0, -5, 0); 2097 2035 drawNSViewInRect(cw, bc, rect, p); 2098 2036 return; 2099 } else if ( editableCombo || viewItem) {2037 } else if (usingYosemiteOrLater && (editableCombo || viewItem)) { 2100 2038 QImage image = activePixmap.toImage(); 2101 2039 2102 2040 for (int y = 0; y < height; ++y) { 2103 2041 QRgb *scanLine = reinterpret_cast<QRgb *>(image.scanLine(y)); 2104 2042 2105 2043 for (int x = 0; x < width; ++x) { 2106 2044 QRgb &pixel = scanLine[x]; 2107 2045 int gray = qRed(pixel); // We know the image is grayscale 2108 2046 int alpha = qAlpha(pixel); 2109 2047 2110 2048 if (gray == 128 && alpha == 128) { 2111 2049 pixel = qRgba(255, 255, 255, 255); 2112 2050 } else if (alpha == 0) { … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2127 2065 QPixmap colorlessPixmap(width, height); 2128 2066 colorlessPixmap.setDevicePixelRatio(devicePixelRatio); 2129 2067 colorlessPixmap.fill(Qt::transparent); 2130 2068 2131 2069 QMacCGContext cg(&colorlessPixmap); 2132 2070 HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); 2133 2071 int oldValue = bdi->value; … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2136 2074 bdi->value = oldValue; 2137 2075 colorlessImage = colorlessPixmap.toImage(); 2138 2076 } 2139 2077 2140 2078 for (int y = 0; y < height; ++y) { 2141 2079 QRgb *colorlessScanLine = reinterpret_cast<QRgb *>(colorlessImage.scanLine(y)); 2142 2080 const QRgb *activeScanLine = reinterpret_cast<const QRgb *>(activeImage.scanLine(y)); 2143 2081 2144 2082 for (int x = 0; x < width; ++x) { 2145 2083 QRgb &colorlessPixel = colorlessScanLine[x]; 2146 2084 QRgb activePixel = activeScanLine[x]; 2147 2085 2148 2086 if (activePixel != colorlessPixel) { 2149 2087 int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)), 2150 2088 qBlue(activePixel)); 2151 2089 QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel)); 2152 2090 if (qGray(newPixel) < qGray(colorlessPixel) 2153 2091 || qAlpha(newPixel) > qAlpha(colorlessPixel)) 2154 2092 colorlessPixel = newPixel; 2155 2093 } 2156 2094 } … … void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD 2163 2101 } 2164 2102 2165 2103 QMacStyle::QMacStyle() 2166 2104 : QCommonStyle(*new QMacStylePrivate) 2167 2105 { 2168 2106 Q_D(QMacStyle); 2169 2107 QMacAutoReleasePool pool; 2170 2108 2171 2109 d->receiver = [[NotificationReceiver alloc] initWithPrivate:d]; 2172 2110 NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver); 2173 2111 2174 2112 [[NSNotificationCenter defaultCenter] addObserver:receiver 2175 selector:@selector(scrollBarStyleDidChange:) 2176 name:NSPreferredScrollerStyleDidChangeNotification 2177 object:nil]; 2178 2179 // Create scroller objects. Scroller internal direction setup happens 2180 // on initWithFrame and cannot be changed later on. Create two scrollers 2181 // initialized with fake geometry. Correct geometry is set at draw time. 2113 selector:@selector(scrollBarStyleDidChange:) 2114 name:NSPreferredScrollerStyleDidChangeNotification 2115 object:nil]; 2116 2117 //d->nsscroller = [[NSScroller alloc] init]; 2182 2118 d->horizontalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; 2183 2119 d->verticalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; 2184 2120 2185 2121 d->indicatorBranchButtonCell = nil; 2186 2122 } 2187 2123 … … QMacStyle::~QMacStyle() 2189 2125 { 2190 2126 Q_D(QMacStyle); 2191 2127 QMacAutoReleasePool pool; 2192 2128 2129 //[reinterpret_cast<NSScroller*>(d->nsscroller) release]; 2193 2130 [d->horizontalScroller release]; 2194 2131 [d->verticalScroller release]; 2195 2132 2196 2133 NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver); 2197 2134 [[NSNotificationCenter defaultCenter] removeObserver:receiver]; 2198 2135 [receiver release]; 2199 2136 2200 2137 delete qt_mac_backgroundPattern; 2201 2138 qt_mac_backgroundPattern = 0; 2202 2139 } 2203 2140 2204 2141 /*! \internal 2205 2206 */2142 Generates the standard widget background pattern. 2143 */ 2207 2144 QPixmap QMacStylePrivate::generateBackgroundPattern() const 2208 2145 { 2209 2146 QMacAutoReleasePool pool; … … QPixmap QMacStylePrivate::generateBackgroundPattern() const 2216 2153 } 2217 2154 2218 2155 /*! \internal 2219 2220 2221 */2156 Fills the given \a rect with the pattern stored in \a brush. As an optimization, 2157 HIThemeSetFill us used directly if we are filling with the standard background. 2158 */ 2222 2159 void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) 2223 2160 { 2224 2161 #if 0 … … void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush 2226 2163 const QPaintDevice *target = painter->device(); 2227 2164 const QPaintDevice *redirected = QPainter::redirected(target, &dummy); 2228 2165 //const bool usePainter = redirected && redirected != target; 2229 2166 2230 2167 if (!usePainter && qt_mac_backgroundPattern 2231 2168 && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { 2232 2169 2233 2170 painter->setClipRegion(rgn); 2234 2171 2235 2172 QMacCGContext cg(target); 2236 2173 CGContextSaveGState(cg); 2237 2174 HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); 2238 2175 2239 2176 for (const QRect &rect : rgn) { 2240 2177 // Anchor the pattern to the top so it stays put when the window is resized. 2241 2178 CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height())); 2242 2179 CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); 2243 2180 CGContextFillRect(cg, mac_rect); 2244 2181 } 2245 2182 2246 2183 CGContextRestoreGState(cg); 2247 2184 } else { 2248 2185 #endif 2249 2186 const QRect rect(rgn.boundingRect()); 2250 2187 painter->setClipRegion(rgn); 2251 2188 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); 2252 // } 2253 } 2254 2255 void QMacStyle::polish(QPalette &pal) 2256 { 2257 Q_D(QMacStyle); 2258 if (!qt_mac_backgroundPattern) { 2259 if (!qApp) 2260 return; 2261 qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); 2189 // } 2262 2190 } 2263 2264 2265 QCFString theme; 2266 const OSErr err = CopyThemeIdentifier(&theme); 2267 if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) { 2268 pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240)); 2269 } else { 2270 pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254)); 2191 2192 void QMacStyle::polish(QPalette &pal) 2193 { 2194 Q_D(QMacStyle); 2195 if (!qt_mac_backgroundPattern) { 2196 if (!qApp) 2197 return; 2198 qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); 2199 } 2200 2201 2202 QCFString theme; 2203 const OSErr err = CopyThemeIdentifier(&theme); 2204 if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) { 2205 pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240)); 2206 } else { 2207 pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254)); 2208 } 2271 2209 } 2272 } 2273 2274 void QMacStyle::polish(QApplication *) 2275 { 2276 } 2277 2278 void QMacStyle::unpolish(QApplication *) 2279 { 2280 } 2281 2282 void QMacStyle::polish(QWidget* w) 2283 { 2284 if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) { 2285 // Set a clear brush so that the metal shines through. 2286 QPalette pal = w->palette(); 2287 QBrush background(Qt::transparent); 2288 pal.setBrush(QPalette::All, QPalette::Window, background); 2289 pal.setBrush(QPalette::All, QPalette::Button, background); 2290 w->setPalette(pal); 2291 w->setAttribute(Qt::WA_SetPalette, false); 2210 2211 void QMacStyle::polish(QApplication *) 2212 { 2292 2213 } 2293 2294 #if QT_CONFIG(menu) 2295 if (qobject_cast<QMenu*>(w) 2296 #if QT_CONFIG(combobox) 2297 || qobject_cast<QComboBoxPrivateContainer *>(w) 2298 #endif 2299 ) { 2300 w->setWindowOpacity(0.985); 2301 if (!w->testAttribute(Qt::WA_SetPalette)) { 2302 QPixmap px(64, 64); 2303 px.fill(Qt::white); 2304 HIThemeMenuDrawInfo mtinfo; 2305 mtinfo.version = qt_mac_hitheme_version; 2306 mtinfo.menuType = kThemeMenuTypePopUp; 2307 // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); 2308 // ### 2309 //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), 2310 // kHIThemeOrientationNormal); 2214 2215 void QMacStyle::unpolish(QApplication *) 2216 { 2217 } 2218 2219 void QMacStyle::polish(QWidget* w) 2220 { 2221 if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) { 2222 // Set a clear brush so that the metal shines through. 2311 2223 QPalette pal = w->palette(); 2312 QBrush background( px);2224 QBrush background(Qt::transparent); 2313 2225 pal.setBrush(QPalette::All, QPalette::Window, background); 2314 2226 pal.setBrush(QPalette::All, QPalette::Button, background); 2315 2227 w->setPalette(pal); 2316 2228 w->setAttribute(Qt::WA_SetPalette, false); 2317 2229 } 2318 } 2230 2231 #ifndef QT_NO_MENU 2232 if (qobject_cast<QMenu*>(w) 2233 #ifndef QT_NO_COMBOBOX 2234 || qobject_cast<QComboBoxPrivateContainer *>(w) 2319 2235 #endif 2320 2321 #if QT_CONFIG(tabbar) 2322 if (QTabBar *tb = qobject_cast<QTabBar*>(w)) { 2323 if (tb->documentMode()) { 2324 w->setAttribute(Qt::WA_Hover); 2325 w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont())); 2326 QPalette p = w->palette(); 2327 p.setColor(QPalette::WindowText, QColor(17, 17, 17)); 2328 w->setPalette(p); 2329 w->setAttribute(Qt::WA_SetPalette, false); 2330 w->setAttribute(Qt::WA_SetFont, false); 2236 ) { 2237 w->setWindowOpacity(0.985); 2238 if (!w->testAttribute(Qt::WA_SetPalette)) { 2239 QPixmap px(64, 64); 2240 px.fill(Qt::white); 2241 HIThemeMenuDrawInfo mtinfo; 2242 mtinfo.version = qt_mac_hitheme_version; 2243 mtinfo.menuType = kThemeMenuTypePopUp; 2244 // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); 2245 // ### 2246 //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), 2247 // kHIThemeOrientationNormal); 2248 QPalette pal = w->palette(); 2249 QBrush background(px); 2250 pal.setBrush(QPalette::All, QPalette::Window, background); 2251 pal.setBrush(QPalette::All, QPalette::Button, background); 2252 w->setPalette(pal); 2253 w->setAttribute(Qt::WA_SetPalette, false); 2254 } 2331 2255 } 2332 }2333 2256 #endif 2334 2335 QCommonStyle::polish(w); 2336 2337 if (QRubberBand *rubber = qobject_cast<QRubberBand*>(w)) { 2338 rubber->setWindowOpacity(0.25); 2339 rubber->setAttribute(Qt::WA_PaintOnScreen, false); 2340 rubber->setAttribute(Qt::WA_NoSystemBackground, false); 2341 } 2342 2343 if (qobject_cast<QScrollBar*>(w)) { 2344 w->setAttribute(Qt::WA_OpaquePaintEvent, false); 2345 w->setAttribute(Qt::WA_Hover, true); 2346 w->setMouseTracking(true); 2347 } 2348 } 2349 2350 void QMacStyle::unpolish(QWidget* w) 2351 { 2352 if (( 2353 #if QT_CONFIG(menu) 2354 qobject_cast<QMenu*>(w) || 2257 2258 #ifndef QT_NO_TABBAR 2259 if (QTabBar *tb = qobject_cast<QTabBar*>(w)) { 2260 if (tb->documentMode()) { 2261 w->setAttribute(Qt::WA_Hover); 2262 w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont())); 2263 QPalette p = w->palette(); 2264 p.setColor(QPalette::WindowText, QColor(17, 17, 17)); 2265 w->setPalette(p); 2266 } 2267 } 2355 2268 #endif 2356 qt_mac_is_metal(w)2357 ) && !w->testAttribute(Qt::WA_SetPalette)) {2358 QPalette pal = qApp->palette(w);2359 w->setPalette(pal);2360 w->setAttribute(Qt::WA_SetPalette, false);2361 w->setWindowOpacity(1.0);2362 }2363 2364 #if QT_CONFIG(combobox) 2365 if (QComboBox *combo = qobject_cast<QComboBox*>(w)) {2366 if (!combo->isEditable()) {2367 if (QWidget *widget = combo->findChild<QComboBoxPrivateContainer *>())2368 widget->setWindowOpacity(1.0);2269 2270 QCommonStyle::polish(w); 2271 2272 if (QRubberBand *rubber = qobject_cast<QRubberBand*>(w)) { 2273 rubber->setWindowOpacity(0.25); 2274 rubber->setAttribute(Qt::WA_PaintOnScreen, false); 2275 rubber->setAttribute(Qt::WA_NoSystemBackground, false); 2276 } 2277 2278 if (qobject_cast<QScrollBar*>(w)) { 2279 w->setAttribute(Qt::WA_OpaquePaintEvent, false); 2280 w->setAttribute(Qt::WA_Hover, true); 2281 w->setMouseTracking(true); 2369 2282 } 2370 2283 } 2284 2285 void QMacStyle::unpolish(QWidget* w) 2286 { 2287 if (( 2288 #ifndef QT_NO_MENU 2289 qobject_cast<QMenu*>(w) || 2371 2290 #endif 2372 2373 #if QT_CONFIG(tabbar) 2374 if (qobject_cast<QTabBar*>(w)) { 2375 if (!w->testAttribute(Qt::WA_SetFont)) 2376 w->setFont(qApp->font(w)); 2377 if (!w->testAttribute(Qt::WA_SetPalette)) 2378 w->setPalette(qApp->palette(w)); 2379 } 2291 qt_mac_is_metal(w) 2292 ) && !w->testAttribute(Qt::WA_SetPalette)) { 2293 QPalette pal = qApp->palette(w); 2294 w->setPalette(pal); 2295 w->setAttribute(Qt::WA_SetPalette, false); 2296 w->setWindowOpacity(1.0); 2297 } 2298 2299 #ifndef QT_NO_COMBOBOX 2300 if (QComboBox *combo = qobject_cast<QComboBox *>(w)) { 2301 if (!combo->isEditable()) { 2302 if (QWidget *widget = combo->findChild<QComboBoxPrivateContainer *>()) 2303 widget->setWindowOpacity(1.0); 2304 } 2305 } 2380 2306 #endif 2381 2382 if (QRubberBand *rubber = qobject_cast<QRubberBand*>(w)) { 2383 rubber->setWindowOpacity(1.0); 2384 rubber->setAttribute(Qt::WA_PaintOnScreen, true); 2385 rubber->setAttribute(Qt::WA_NoSystemBackground, true); 2386 } 2387 2388 if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w)) 2389 frame->setAttribute(Qt::WA_NoSystemBackground, true); 2390 2391 QCommonStyle::unpolish(w); 2392 2393 if (qobject_cast<QScrollBar*>(w)) { 2394 w->setAttribute(Qt::WA_OpaquePaintEvent, true); 2395 w->setAttribute(Qt::WA_Hover, false); 2396 w->setMouseTracking(false); 2307 2308 if (QRubberBand *rubber = qobject_cast<QRubberBand*>(w)) { 2309 rubber->setWindowOpacity(1.0); 2310 rubber->setAttribute(Qt::WA_PaintOnScreen, true); 2311 rubber->setAttribute(Qt::WA_NoSystemBackground, true); 2312 } 2313 2314 if (QFocusFrame *frame = qobject_cast<QFocusFrame *>(w)) 2315 frame->setAttribute(Qt::WA_NoSystemBackground, true); 2316 2317 QCommonStyle::unpolish(w); 2318 2319 if (qobject_cast<QScrollBar*>(w)) { 2320 w->setAttribute(Qt::WA_OpaquePaintEvent, true); 2321 w->setAttribute(Qt::WA_Hover, false); 2322 w->setMouseTracking(false); 2323 } 2397 2324 } 2398 } 2399 2400 int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const 2401 { 2402 Q_D(const QMacStyle); 2403 int controlSize = getControlSize(opt, widget); 2404 SInt32 ret = 0; 2405 2406 switch (metric) { 2407 case PM_TabCloseIndicatorWidth: 2408 case PM_TabCloseIndicatorHeight: 2409 ret = closeButtonSize; 2410 break; 2411 case PM_ToolBarIconSize: 2412 ret = proxy()->pixelMetric(PM_LargeIconSize); 2413 break; 2414 case PM_FocusFrameVMargin: 2415 case PM_FocusFrameHMargin: 2416 GetThemeMetric(kThemeMetricFocusRectOutset, &ret); 2417 break; 2418 case PM_DialogButtonsSeparator: 2419 ret = -5; 2420 break; 2421 case PM_DialogButtonsButtonHeight: { 2422 QSize sz; 2423 ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); 2424 if (sz == QSize(-1, -1)) 2425 ret = 32; 2426 else 2427 ret = sz.height(); 2428 break; } 2429 case PM_DialogButtonsButtonWidth: { 2430 QSize sz; 2431 ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); 2432 if (sz == QSize(-1, -1)) 2433 ret = 70; 2434 else 2435 ret = sz.width(); 2436 break; } 2437 2438 case PM_MenuBarHMargin: 2439 ret = 8; 2440 break; 2441 2442 case PM_MenuBarVMargin: 2443 ret = 0; 2444 break; 2445 2446 case PM_MenuBarPanelWidth: 2447 ret = 0; 2448 break; 2449 2450 case QStyle::PM_MenuDesktopFrameWidth: 2451 ret = 5; 2452 break; 2453 2454 case PM_CheckBoxLabelSpacing: 2455 case PM_RadioButtonLabelSpacing: 2456 ret = 2; 2457 break; 2458 case PM_MenuScrollerHeight: 2325 2326 int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const 2327 { 2328 Q_D(const QMacStyle); 2329 int controlSize = getControlSize(opt, widget); 2330 SInt32 ret = 0; 2331 2332 switch (metric) { 2333 case PM_TabCloseIndicatorWidth: 2334 case PM_TabCloseIndicatorHeight: 2335 ret = closeButtonSize; 2336 break; 2337 case PM_ToolBarIconSize: 2338 ret = proxy()->pixelMetric(PM_LargeIconSize); 2339 break; 2340 case PM_FocusFrameVMargin: 2341 case PM_FocusFrameHMargin: 2342 GetThemeMetric(kThemeMetricFocusRectOutset, &ret); 2343 break; 2344 case PM_DialogButtonsSeparator: 2345 ret = -5; 2346 break; 2347 case PM_DialogButtonsButtonHeight: { 2348 QSize sz; 2349 ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); 2350 if (sz == QSize(-1, -1)) 2351 ret = 32; 2352 else 2353 ret = sz.height(); 2354 break; } 2355 case PM_DialogButtonsButtonWidth: { 2356 QSize sz; 2357 ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); 2358 if (sz == QSize(-1, -1)) 2359 ret = 70; 2360 else 2361 ret = sz.width(); 2362 break; } 2363 2364 case PM_MenuBarHMargin: 2365 ret = 8; 2366 break; 2367 2368 case PM_MenuBarVMargin: 2369 ret = 0; 2370 break; 2371 2372 case PM_MenuBarPanelWidth: 2373 ret = 0; 2374 break; 2375 2376 case QStyle::PM_MenuDesktopFrameWidth: 2377 ret = 5; 2378 break; 2379 2380 case PM_CheckBoxLabelSpacing: 2381 case PM_RadioButtonLabelSpacing: 2382 ret = 2; 2383 break; 2384 case PM_MenuScrollerHeight: 2459 2385 #if 0 2460 SInt16 ash, asw;2461 GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw);2462 ret = ash;2386 SInt16 ash, asw; 2387 GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw); 2388 ret = ash; 2463 2389 #else 2464 ret = 15; // I hate having magic numbers in here...2390 ret = 15; // I hate having magic numbers in here... 2465 2391 #endif 2466 break;2467 case PM_DefaultFrameWidth:2468 #if QT_CONFIG(mainwindow)2469 if (widget && (widget->isWindow() || !widget->parentWidget()2470 || (qobject_cast<const QMainWindow*>(widget->parentWidget())2471 && static_cast<QMainWindow *>(widget->parentWidget())->centralWidget() == widget))2472 && qobject_cast<const QAbstractScrollArea *>(widget))2473 ret = 0;2474 else2392 break; 2393 case PM_DefaultFrameWidth: 2394 #ifndef QT_NO_MAINWINDOW 2395 if (widget && (widget->isWindow() || !widget->parentWidget() 2396 || (qobject_cast<const QMainWindow*>(widget->parentWidget()) 2397 && static_cast<QMainWindow *>(widget->parentWidget())->centralWidget() == widget)) 2398 && qobject_cast<const QAbstractScrollArea *>(widget)) 2399 ret = 0; 2400 else 2475 2401 #endif 2476 // The combo box popup has no frame. 2477 if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0) 2478 ret = 0; 2479 else 2480 ret = 1; 2481 break; 2482 case PM_MaximumDragDistance: 2483 ret = -1; 2484 break; 2485 case PM_ScrollBarSliderMin: 2486 ret = 24; 2487 break; 2488 case PM_SpinBoxFrameWidth: 2489 GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret); 2490 switch (d->aquaSizeConstrain(opt, widget)) { 2491 default: 2492 ret += 2; 2493 break; 2494 case QAquaSizeMini: 2495 ret += 1; 2496 break; 2497 } 2498 break; 2499 case PM_ButtonShiftHorizontal: 2500 case PM_ButtonShiftVertical: 2501 ret = 0; 2502 break; 2503 case PM_SliderLength: 2504 ret = 17; 2505 break; 2506 // Returns the number of pixels to use for the business part of the 2507 // slider (i.e., the non-tickmark portion). The remaining space is shared 2508 // equally between the tickmark regions. 2509 case PM_SliderControlThickness: 2510 if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 2511 int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); 2512 int ticks = sl->tickPosition; 2513 int n = 0; 2514 if (ticks & QSlider::TicksAbove) 2515 ++n; 2516 if (ticks & QSlider::TicksBelow) 2517 ++n; 2518 if (!n) { 2519 ret = space; 2402 // The combo box popup has no frame. 2403 if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0) 2404 ret = 0; 2405 else 2406 ret = 1; 2520 2407 break; 2521 } 2522 2523 int thick = 6; // Magic constant to get 5 + 16 + 5 2524 if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) 2525 thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; 2526 2527 space -= thick; 2528 if (space > 0) 2529 thick += (space * 2) / (n + 2); 2530 ret = thick; 2531 } else { 2532 ret = 0; 2533 } 2534 break; 2535 case PM_SmallIconSize: 2536 ret = int(QStyleHelper::dpiScaled(16.)); 2537 break; 2538 2539 case PM_LargeIconSize: 2540 ret = int(QStyleHelper::dpiScaled(32.)); 2541 break; 2542 2543 case PM_IconViewIconSize: 2544 ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); 2545 break; 2546 2547 case PM_ButtonDefaultIndicator: 2548 ret = 0; 2549 break; 2550 case PM_TitleBarHeight: { 2551 NSUInteger style = NSTitledWindowMask; 2552 if (widget && ((widget->windowFlags() & Qt::Tool) == Qt::Tool)) 2553 style |= NSUtilityWindowMask; 2554 ret = int([NSWindow frameRectForContentRect:NSZeroRect 2555 styleMask:style].size.height); 2556 break; } 2557 case QStyle::PM_TabBarTabHSpace: 2558 switch (d->aquaSizeConstrain(opt, widget)) { 2559 case QAquaSizeLarge: 2560 ret = QCommonStyle::pixelMetric(metric, opt, widget); 2561 break; 2562 case QAquaSizeSmall: 2563 ret = 20; 2564 break; 2565 case QAquaSizeMini: 2566 ret = 16; 2567 break; 2568 case QAquaSizeUnknown: 2569 const QStyleOptionTab *tb = qstyleoption_cast<const QStyleOptionTab *>(opt); 2570 if (tb && tb->documentMode) 2571 ret = 30; 2572 else 2573 ret = QCommonStyle::pixelMetric(metric, opt, widget); 2574 break; 2575 } 2576 break; 2577 case PM_TabBarTabVSpace: 2578 ret = 4; 2579 break; 2580 case PM_TabBarTabShiftHorizontal: 2581 case PM_TabBarTabShiftVertical: 2582 ret = 0; 2583 break; 2584 case PM_TabBarBaseHeight: 2585 ret = 0; 2586 break; 2587 case PM_TabBarTabOverlap: 2588 ret = 1; 2589 break; 2590 case PM_TabBarBaseOverlap: 2591 switch (d->aquaSizeConstrain(opt, widget)) { 2592 case QAquaSizeUnknown: 2593 case QAquaSizeLarge: 2594 ret = 11; 2595 break; 2596 case QAquaSizeSmall: 2597 ret = 8; 2598 break; 2599 case QAquaSizeMini: 2600 ret = 7; 2601 break; 2602 } 2603 break; 2604 case PM_ScrollBarExtent: { 2605 const QAquaWidgetSize size = d->effectiveAquaSizeConstrain(opt, widget); 2606 ret = static_cast<SInt32>([NSScroller 2607 scrollerWidthForControlSize:static_cast<NSControlSize>(size) 2608 scrollerStyle:[NSScroller preferredScrollerStyle]]); 2609 break; } 2610 case PM_IndicatorHeight: { 2611 switch (d->aquaSizeConstrain(opt, widget)) { 2612 case QAquaSizeUnknown: 2613 case QAquaSizeLarge: 2614 GetThemeMetric(kThemeMetricCheckBoxHeight, &ret); 2615 break; 2616 case QAquaSizeMini: 2617 GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret); 2618 break; 2619 case QAquaSizeSmall: 2620 GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret); 2621 break; 2622 } 2623 break; } 2624 case PM_IndicatorWidth: { 2625 switch (d->aquaSizeConstrain(opt, widget)) { 2626 case QAquaSizeUnknown: 2627 case QAquaSizeLarge: 2628 GetThemeMetric(kThemeMetricCheckBoxWidth, &ret); 2629 break; 2630 case QAquaSizeMini: 2631 GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret); 2632 break; 2633 case QAquaSizeSmall: 2634 GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret); 2635 break; 2636 } 2637 ++ret; 2638 break; } 2639 case PM_ExclusiveIndicatorHeight: { 2640 switch (d->aquaSizeConstrain(opt, widget)) { 2641 case QAquaSizeUnknown: 2642 case QAquaSizeLarge: 2643 GetThemeMetric(kThemeMetricRadioButtonHeight, &ret); 2644 break; 2645 case QAquaSizeMini: 2646 GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret); 2647 break; 2648 case QAquaSizeSmall: 2649 GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret); 2650 break; 2651 } 2652 break; } 2653 case PM_ExclusiveIndicatorWidth: { 2654 switch (d->aquaSizeConstrain(opt, widget)) { 2655 case QAquaSizeUnknown: 2656 case QAquaSizeLarge: 2657 GetThemeMetric(kThemeMetricRadioButtonWidth, &ret); 2658 break; 2659 case QAquaSizeMini: 2660 GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret); 2661 break; 2662 case QAquaSizeSmall: 2663 GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret); 2664 break; 2665 } 2666 ++ret; 2667 break; } 2668 case PM_MenuVMargin: 2669 ret = 4; 2670 break; 2671 case PM_MenuPanelWidth: 2672 ret = 0; 2673 break; 2674 case PM_ToolTipLabelFrameWidth: 2675 ret = 0; 2676 break; 2677 case PM_SizeGripSize: { 2678 QAquaWidgetSize aSize; 2679 if (widget && widget->window()->windowType() == Qt::Tool) 2680 aSize = QAquaSizeSmall; 2681 else 2682 aSize = QAquaSizeLarge; 2683 const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize); 2684 ret = size.width(); 2685 break; } 2686 case PM_MdiSubWindowFrameWidth: 2687 ret = 1; 2688 break; 2689 case PM_DockWidgetFrameWidth: 2690 ret = 0; 2691 break; 2692 case PM_DockWidgetTitleMargin: 2693 ret = 0; 2694 break; 2695 case PM_DockWidgetSeparatorExtent: 2696 ret = 1; 2697 break; 2698 case PM_ToolBarHandleExtent: 2699 ret = 11; 2700 break; 2701 case PM_ToolBarItemMargin: 2702 ret = 0; 2703 break; 2704 case PM_ToolBarItemSpacing: 2705 ret = 4; 2706 break; 2707 case PM_SplitterWidth: 2708 ret = qMax(7, QApplication::globalStrut().width()); 2709 break; 2710 case PM_LayoutLeftMargin: 2711 case PM_LayoutTopMargin: 2712 case PM_LayoutRightMargin: 2713 case PM_LayoutBottomMargin: 2714 { 2715 bool isWindow = false; 2716 if (opt) { 2717 isWindow = (opt->state & State_Window); 2718 } else if (widget) { 2719 isWindow = widget->isWindow(); 2720 } 2721 2722 if (isWindow) { 2723 bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal); 2724 if (isMetal) { 2725 if (metric == PM_LayoutTopMargin) { 2726 return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */); 2727 } else if (metric == PM_LayoutBottomMargin) { 2728 return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */); 2729 } else { 2730 return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */); 2408 case PM_MaximumDragDistance: 2409 ret = -1; 2410 break; 2411 case PM_ScrollBarSliderMin: 2412 ret = 24; 2413 break; 2414 case PM_SpinBoxFrameWidth: 2415 GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret); 2416 switch (d->aquaSizeConstrain(opt, widget)) { 2417 default: 2418 ret += 2; 2419 break; 2420 case QAquaSizeMini: 2421 ret += 1; 2422 break; 2423 } 2424 break; 2425 case PM_ButtonShiftHorizontal: 2426 case PM_ButtonShiftVertical: 2427 ret = 0; 2428 break; 2429 case PM_SliderLength: 2430 ret = 17; 2431 break; 2432 // Returns the number of pixels to use for the business part of the 2433 // slider (i.e., the non-tickmark portion). The remaining space is shared 2434 // equally between the tickmark regions. 2435 case PM_SliderControlThickness: 2436 if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 2437 int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); 2438 int ticks = sl->tickPosition; 2439 int n = 0; 2440 if (ticks & QSlider::TicksAbove) 2441 ++n; 2442 if (ticks & QSlider::TicksBelow) 2443 ++n; 2444 if (!n) { 2445 ret = space; 2446 break; 2731 2447 } 2448 2449 int thick = 6; // Magic constant to get 5 + 16 + 5 2450 if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) 2451 thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; 2452 2453 space -= thick; 2454 if (space > 0) 2455 thick += (space * 2) / (n + 2); 2456 ret = thick; 2732 2457 } else { 2733 /* 2734 AHIG would have (20, 8, 10) here but that makes 2735 no sense. It would also have 14 for the top margin 2736 but this contradicts both Builder and most 2737 applications. 2738 */ 2739 return_SIZE(20, 10, 10); // AHIG 2458 ret = 0; 2740 2459 } 2741 } else { 2742 // hack to detect QTabWidget 2743 if (widget && widget->parentWidget() 2744 && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) { 2745 if (metric == PM_LayoutTopMargin) { 2746 /* 2747 Builder would have 14 (= 20 - 6) instead of 12, 2748 but that makes the tab look disproportionate. 2749 */ 2750 return_SIZE(12, 6, 6); // guess 2460 break; 2461 case PM_SmallIconSize: 2462 ret = int(QStyleHelper::dpiScaled(16.)); 2463 break; 2464 2465 case PM_LargeIconSize: 2466 ret = int(QStyleHelper::dpiScaled(32.)); 2467 break; 2468 2469 case PM_IconViewIconSize: 2470 ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); 2471 break; 2472 2473 case PM_ButtonDefaultIndicator: 2474 ret = 0; 2475 break; 2476 case PM_TitleBarHeight: 2477 // Always use NSTitledWindowMask since we never need any other type of window here 2478 ret = int([NSWindow frameRectForContentRect:NSZeroRect 2479 styleMask:NSTitledWindowMask].size.height); 2480 break; 2481 case PM_TabBarTabVSpace: 2482 ret = 4; 2483 break; 2484 case PM_TabBarTabShiftHorizontal: 2485 case PM_TabBarTabShiftVertical: 2486 ret = 0; 2487 break; 2488 case PM_TabBarBaseHeight: 2489 ret = 0; 2490 break; 2491 case PM_TabBarTabOverlap: 2492 ret = 0; 2493 break; 2494 case PM_TabBarBaseOverlap: 2495 switch (d->aquaSizeConstrain(opt, widget)) { 2496 case QAquaSizeUnknown: 2497 case QAquaSizeLarge: 2498 ret = 11; 2499 break; 2500 case QAquaSizeSmall: 2501 ret = 8; 2502 break; 2503 case QAquaSizeMini: 2504 ret = 7; 2505 break; 2506 } 2507 break; 2508 case PM_ScrollBarExtent: { 2509 const QAquaWidgetSize size = d->effectiveAquaSizeConstrain(opt, widget); 2510 ret = static_cast<SInt32>([NSScroller 2511 scrollerWidthForControlSize:static_cast<NSControlSize>(size) 2512 scrollerStyle:[NSScroller preferredScrollerStyle]]); 2513 break; } 2514 case PM_IndicatorHeight: { 2515 switch (d->aquaSizeConstrain(opt, widget)) { 2516 case QAquaSizeUnknown: 2517 case QAquaSizeLarge: 2518 GetThemeMetric(kThemeMetricCheckBoxHeight, &ret); 2519 break; 2520 case QAquaSizeMini: 2521 GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret); 2522 break; 2523 case QAquaSizeSmall: 2524 GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret); 2525 break; 2526 } 2527 break; } 2528 case PM_IndicatorWidth: { 2529 switch (d->aquaSizeConstrain(opt, widget)) { 2530 case QAquaSizeUnknown: 2531 case QAquaSizeLarge: 2532 GetThemeMetric(kThemeMetricCheckBoxWidth, &ret); 2533 break; 2534 case QAquaSizeMini: 2535 GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret); 2536 break; 2537 case QAquaSizeSmall: 2538 GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret); 2539 break; 2540 } 2541 ++ret; 2542 break; } 2543 case PM_ExclusiveIndicatorHeight: { 2544 switch (d->aquaSizeConstrain(opt, widget)) { 2545 case QAquaSizeUnknown: 2546 case QAquaSizeLarge: 2547 GetThemeMetric(kThemeMetricRadioButtonHeight, &ret); 2548 break; 2549 case QAquaSizeMini: 2550 GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret); 2551 break; 2552 case QAquaSizeSmall: 2553 GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret); 2554 break; 2555 } 2556 break; } 2557 case PM_ExclusiveIndicatorWidth: { 2558 switch (d->aquaSizeConstrain(opt, widget)) { 2559 case QAquaSizeUnknown: 2560 case QAquaSizeLarge: 2561 GetThemeMetric(kThemeMetricRadioButtonWidth, &ret); 2562 break; 2563 case QAquaSizeMini: 2564 GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret); 2565 break; 2566 case QAquaSizeSmall: 2567 GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret); 2568 break; 2569 } 2570 ++ret; 2571 break; } 2572 case PM_MenuVMargin: 2573 ret = 4; 2574 break; 2575 case PM_MenuPanelWidth: 2576 ret = 0; 2577 break; 2578 case PM_ToolTipLabelFrameWidth: 2579 ret = 0; 2580 break; 2581 case PM_SizeGripSize: { 2582 QAquaWidgetSize aSize; 2583 if (widget && widget->window()->windowType() == Qt::Tool) 2584 aSize = QAquaSizeSmall; 2585 else 2586 aSize = QAquaSizeLarge; 2587 const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize); 2588 ret = size.width(); 2589 break; } 2590 case PM_MdiSubWindowFrameWidth: 2591 ret = 1; 2592 break; 2593 case PM_DockWidgetFrameWidth: 2594 ret = 0; 2595 break; 2596 case PM_DockWidgetTitleMargin: 2597 ret = 0; 2598 break; 2599 case PM_DockWidgetSeparatorExtent: 2600 ret = 1; 2601 break; 2602 case PM_ToolBarHandleExtent: 2603 ret = 11; 2604 break; 2605 case PM_ToolBarItemMargin: 2606 ret = 0; 2607 break; 2608 case PM_ToolBarItemSpacing: 2609 ret = 4; 2610 break; 2611 case PM_SplitterWidth: 2612 ret = qMax(7, QApplication::globalStrut().width()); 2613 break; 2614 case PM_LayoutLeftMargin: 2615 case PM_LayoutTopMargin: 2616 case PM_LayoutRightMargin: 2617 case PM_LayoutBottomMargin: 2618 { 2619 bool isWindow = false; 2620 if (opt) { 2621 isWindow = (opt->state & State_Window); 2622 } else if (widget) { 2623 isWindow = widget->isWindow(); 2624 } 2625 2626 if (isWindow) { 2627 bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal); 2628 if (isMetal) { 2629 if (metric == PM_LayoutTopMargin) { 2630 return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */); 2631 } else if (metric == PM_LayoutBottomMargin) { 2632 return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */); 2633 } else { 2634 return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */); 2635 } 2751 2636 } else { 2752 return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */); 2637 /* 2638 AHIG would have (20, 8, 10) here but that makes 2639 no sense. It would also have 14 for the top margin 2640 but this contradicts both Builder and most 2641 applications. 2642 */ 2643 return_SIZE(20, 10, 10); // AHIG 2753 2644 } 2754 2645 } else { 2755 /* 2756 Child margins are highly inconsistent in AHIG and Builder. 2757 */ 2758 return_SIZE(12, 8, 6); // guess 2646 // hack to detect QTabWidget 2647 if (widget && widget->parentWidget() 2648 && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) { 2649 if (metric == PM_LayoutTopMargin) { 2650 /* 2651 Builder would have 14 (= 20 - 6) instead of 12, 2652 but that makes the tab look disproportionate. 2653 */ 2654 return_SIZE(12, 6, 6); // guess 2655 } else { 2656 return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */); 2657 } 2658 } else { 2659 /* 2660 Child margins are highly inconsistent in AHIG and Builder. 2661 */ 2662 return_SIZE(12, 8, 6); // guess 2663 } 2759 2664 } 2760 2665 } 2666 case PM_LayoutHorizontalSpacing: 2667 case PM_LayoutVerticalSpacing: 2668 return -1; 2669 case QStyle::PM_TabBarTabHSpace: 2670 switch (d->aquaSizeConstrain(opt, widget)) { 2671 case QAquaSizeLarge: 2672 case QAquaSizeUnknown: 2673 ret = QCommonStyle::pixelMetric(metric, opt, widget); 2674 break; 2675 case QAquaSizeSmall: 2676 ret = 20; 2677 break; 2678 case QAquaSizeMini: 2679 ret = 16; 2680 break; 2681 } 2682 break; 2683 case PM_MenuHMargin: 2684 ret = 0; 2685 break; 2686 case PM_ToolBarExtensionExtent: 2687 ret = 21; 2688 break; 2689 case PM_ToolBarFrameWidth: 2690 ret = 1; 2691 break; 2692 case PM_ScrollView_ScrollBarOverlap: 2693 ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ? 2694 pixelMetric(PM_ScrollBarExtent, opt, widget) : 0; 2695 break; 2696 default: 2697 ret = QCommonStyle::pixelMetric(metric, opt, widget); 2698 break; 2761 2699 } 2762 case PM_LayoutHorizontalSpacing: 2763 case PM_LayoutVerticalSpacing: 2764 return -1; 2765 case PM_MenuHMargin: 2766 ret = 0; 2767 break; 2768 case PM_ToolBarExtensionExtent: 2769 ret = 21; 2770 break; 2771 case PM_ToolBarFrameWidth: 2772 ret = 1; 2773 break; 2774 case PM_ScrollView_ScrollBarOverlap: 2775 ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ? 2776 pixelMetric(PM_ScrollBarExtent, opt, widget) : 0; 2777 break; 2778 default: 2779 ret = QCommonStyle::pixelMetric(metric, opt, widget); 2780 break; 2700 return ret; 2781 2701 } 2782 return ret; 2783 } 2784 2785 QPalette QMacStyle::standardPalette() const 2786 { 2787 QPalette pal = QCommonStyle::standardPalette(); 2788 pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); 2789 pal.setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); 2790 pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); 2791 return pal; 2792 } 2793 2794 int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, 2795 QStyleHintReturn *hret) const 2796 { 2797 QMacAutoReleasePool pool; 2798 2799 SInt32 ret = 0; 2800 switch (sh) { 2801 case SH_Slider_SnapToValue: 2802 case SH_PrintDialog_RightAlignButtons: 2803 case SH_FontDialog_SelectAssociatedText: 2804 case SH_MenuBar_MouseTracking: 2805 case SH_Menu_MouseTracking: 2806 case SH_ComboBox_ListMouseTracking: 2807 case SH_MainWindow_SpaceBelowMenuBar: 2808 case SH_ItemView_ChangeHighlightOnFocus: 2809 ret = 1; 2810 break; 2811 case SH_ToolBox_SelectedPageTitleBold: 2812 ret = 0; 2813 break; 2814 case SH_DialogButtonBox_ButtonsHaveIcons: 2815 ret = 0; 2816 break; 2817 case SH_Menu_SelectionWrap: 2818 ret = false; 2819 break; 2820 case SH_Menu_KeyboardSearch: 2821 ret = true; 2822 break; 2823 case SH_Menu_SpaceActivatesItem: 2824 ret = true; 2825 break; 2826 case SH_Slider_AbsoluteSetButtons: 2827 ret = Qt::LeftButton|Qt::MidButton; 2828 break; 2829 case SH_Slider_PageSetButtons: 2830 ret = 0; 2831 break; 2832 case SH_ScrollBar_ContextMenu: 2833 ret = false; 2834 break; 2835 case SH_TitleBar_AutoRaise: 2836 ret = true; 2837 break; 2838 case SH_Menu_AllowActiveAndDisabled: 2839 ret = false; 2840 break; 2841 case SH_Menu_SubMenuPopupDelay: 2842 ret = 100; 2843 break; 2844 case SH_Menu_SubMenuUniDirection: 2845 ret = true; 2846 break; 2847 case SH_Menu_SubMenuSloppySelectOtherActions: 2848 ret = false; 2849 break; 2850 case SH_Menu_SubMenuResetWhenReenteringParent: 2851 ret = true; 2852 break; 2853 case SH_Menu_SubMenuDontStartSloppyOnLeave: 2854 ret = true; 2855 break; 2856 2857 case SH_ScrollBar_LeftClickAbsolutePosition: { 2858 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 2859 bool result = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; 2860 if(QApplication::keyboardModifiers() & Qt::AltModifier) 2861 ret = !result; 2862 else 2863 ret = result; 2864 break; } 2865 case SH_TabBar_PreferNoArrows: 2866 ret = true; 2867 break; 2868 /* 2869 case SH_DialogButtons_DefaultButton: 2870 ret = QDialogButtons::Reject; 2871 break; 2872 */ 2873 case SH_GroupBox_TextLabelVerticalAlignment: 2874 ret = Qt::AlignTop; 2875 break; 2876 case SH_ScrollView_FrameOnlyAroundContents: 2877 ret = QCommonStyle::styleHint(sh, opt, w, hret); 2878 break; 2879 case SH_Menu_FillScreenWithScroll: 2880 ret = false; 2881 break; 2882 case SH_Menu_Scrollable: 2883 ret = true; 2884 break; 2885 case SH_RichText_FullWidthSelection: 2886 ret = true; 2887 break; 2888 case SH_BlinkCursorWhenTextSelected: 2889 ret = false; 2890 break; 2891 case SH_ScrollBar_StopMouseOverSlider: 2892 ret = true; 2893 break; 2894 case SH_ListViewExpand_SelectMouseType: 2895 ret = QEvent::MouseButtonRelease; 2896 break; 2897 case SH_TabBar_SelectMouseType: 2898 #if QT_CONFIG(tabbar) 2899 if (const QStyleOptionTabBarBase *opt2 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt)) { 2900 ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; 2901 } else 2902 #endif 2903 { 2904 ret = QEvent::MouseButtonRelease; 2905 } 2906 break; 2907 case SH_ComboBox_Popup: 2908 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) 2909 ret = !cmb->editable; 2910 else 2911 ret = 0; 2912 break; 2913 case SH_Workspace_FillSpaceOnMaximize: 2914 ret = true; 2915 break; 2916 case SH_Widget_ShareActivation: 2917 ret = true; 2918 break; 2919 case SH_Header_ArrowAlignment: 2920 ret = Qt::AlignRight; 2921 break; 2922 case SH_TabBar_Alignment: { 2923 #if QT_CONFIG(tabwidget) 2924 if (const QTabWidget *tab = qobject_cast<const QTabWidget*>(w)) { 2925 if (tab->documentMode()) { 2926 ret = Qt::AlignLeft; 2702 2703 QPalette QMacStyle::standardPalette() const 2704 { 2705 QPalette pal = QCommonStyle::standardPalette(); 2706 pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); 2707 pal.setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); 2708 pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); 2709 return pal; 2710 } 2711 2712 int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, 2713 QStyleHintReturn *hret) const 2714 { 2715 QMacAutoReleasePool pool; 2716 2717 SInt32 ret = 0; 2718 switch (sh) { 2719 case SH_Slider_SnapToValue: 2720 case SH_PrintDialog_RightAlignButtons: 2721 case SH_FontDialog_SelectAssociatedText: 2722 case SH_MenuBar_MouseTracking: 2723 case SH_Menu_MouseTracking: 2724 case SH_ComboBox_ListMouseTracking: 2725 case SH_MainWindow_SpaceBelowMenuBar: 2726 case SH_ItemView_ChangeHighlightOnFocus: 2727 ret = 1; 2927 2728 break; 2928 } 2929 } 2729 case SH_ToolBox_SelectedPageTitleBold: 2730 ret = 0; 2731 break; 2732 case SH_DialogButtonBox_ButtonsHaveIcons: 2733 ret = 0; 2734 break; 2735 case SH_Menu_SelectionWrap: 2736 ret = false; 2737 break; 2738 case SH_Menu_KeyboardSearch: 2739 ret = true; 2740 break; 2741 case SH_Menu_SpaceActivatesItem: 2742 ret = true; 2743 break; 2744 case SH_Slider_AbsoluteSetButtons: 2745 ret = Qt::LeftButton|Qt::MidButton; 2746 break; 2747 case SH_Slider_PageSetButtons: 2748 ret = 0; 2749 break; 2750 case SH_ScrollBar_ContextMenu: 2751 ret = false; 2752 break; 2753 case SH_TitleBar_AutoRaise: 2754 ret = true; 2755 break; 2756 case SH_Menu_AllowActiveAndDisabled: 2757 ret = false; 2758 break; 2759 case SH_Menu_SubMenuPopupDelay: 2760 ret = 100; 2761 break; 2762 case SH_Menu_SubMenuUniDirection: 2763 ret = true; 2764 break; 2765 case SH_Menu_SubMenuSloppySelectOtherActions: 2766 ret = false; 2767 break; 2768 case SH_Menu_SubMenuResetWhenReenteringParent: 2769 ret = true; 2770 break; 2771 case SH_Menu_SubMenuDontStartSloppyOnLeave: 2772 ret = true; 2773 break; 2774 2775 case SH_ScrollBar_LeftClickAbsolutePosition: { 2776 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 2777 bool result = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; 2778 if(QApplication::keyboardModifiers() & Qt::AltModifier) 2779 ret = !result; 2780 else 2781 ret = result; 2782 break; } 2783 case SH_TabBar_PreferNoArrows: 2784 ret = true; 2785 break; 2786 /* 2787 case SH_DialogButtons_DefaultButton: 2788 ret = QDialogButtons::Reject; 2789 break; 2790 */ 2791 case SH_GroupBox_TextLabelVerticalAlignment: 2792 ret = Qt::AlignTop; 2793 break; 2794 case SH_ScrollView_FrameOnlyAroundContents: 2795 ret = QCommonStyle::styleHint(sh, opt, w, hret); 2796 break; 2797 case SH_Menu_FillScreenWithScroll: 2798 ret = false; 2799 break; 2800 case SH_Menu_Scrollable: 2801 ret = true; 2802 break; 2803 case SH_RichText_FullWidthSelection: 2804 ret = true; 2805 break; 2806 case SH_BlinkCursorWhenTextSelected: 2807 ret = false; 2808 break; 2809 case SH_ScrollBar_StopMouseOverSlider: 2810 ret = true; 2811 break; 2812 case SH_ListViewExpand_SelectMouseType: 2813 ret = QEvent::MouseButtonRelease; 2814 break; 2815 case SH_TabBar_SelectMouseType: 2816 #ifndef QT_NO_TABBAR 2817 if (const QStyleOptionTabBarBase *opt2 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt)) { 2818 ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; 2819 } else 2930 2820 #endif 2931 #if QT_CONFIG(tabbar) 2932 if (const QTabBar *tab = qobject_cast<const QTabBar*>(w)) { 2933 if (tab->documentMode()) { 2934 ret = Qt::AlignLeft; 2821 { 2822 ret = QEvent::MouseButtonRelease; 2823 } 2935 2824 break; 2936 } 2937 } 2825 case SH_ComboBox_Popup: 2826 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) 2827 ret = !cmb->editable; 2828 else 2829 ret = 0; 2830 break; 2831 case SH_Workspace_FillSpaceOnMaximize: 2832 ret = true; 2833 break; 2834 case SH_Widget_ShareActivation: 2835 ret = true; 2836 break; 2837 case SH_Header_ArrowAlignment: 2838 ret = Qt::AlignRight; 2839 break; 2840 case SH_TabBar_Alignment: { 2841 #ifndef QT_NO_TABWIDGET 2842 if (const QTabWidget *tab = qobject_cast<const QTabWidget*>(w)) { 2843 if (tab->documentMode()) { 2844 ret = Qt::AlignLeft; 2845 break; 2846 } 2847 } 2938 2848 #endif 2939 ret = Qt::AlignCenter; 2940 } break; 2941 case SH_UnderlineShortcut: 2942 ret = false; 2943 break; 2944 case SH_ToolTipLabel_Opacity: 2945 ret = 242; // About 95% 2946 break; 2947 case SH_Button_FocusPolicy: 2948 ret = Qt::TabFocus; 2949 break; 2950 case SH_EtchDisabledText: 2951 ret = false; 2952 break; 2953 case SH_FocusFrame_Mask: { 2954 ret = true; 2955 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { 2956 const uchar fillR = 192, fillG = 191, fillB = 190; 2957 QImage img; 2958 2959 QSize pixmapSize = opt->rect.size(); 2960 if (!pixmapSize.isEmpty()) { 2961 QPixmap pix(pixmapSize); 2962 pix.fill(QColor(fillR, fillG, fillB)); 2963 QPainter pix_paint(&pix); 2964 proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w); 2965 pix_paint.end(); 2966 img = pix.toImage(); 2967 } 2968 2969 const QRgb *sptr = (QRgb*)img.bits(), *srow; 2970 const int sbpl = img.bytesPerLine(); 2971 const int w = sbpl/4, h = img.height(); 2972 2973 QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32); 2974 QRgb *dptr = (QRgb*)img_mask.bits(), *drow; 2975 const int dbpl = img_mask.bytesPerLine(); 2976 2977 for (int y = 0; y < h; ++y) { 2978 srow = sptr+((y*sbpl)/4); 2979 drow = dptr+((y*dbpl)/4); 2980 for (int x = 0; x < w; ++x) { 2981 const int redDiff = qRed(*srow) - fillR; 2982 const int greenDiff = qGreen(*srow) - fillG; 2983 const int blueDiff = qBlue(*srow) - fillB; 2984 const int diff = (redDiff * redDiff) + (greenDiff * greenDiff) + (blueDiff * blueDiff); 2985 (*drow++) = (diff < 10) ? 0xffffffff : 0xff000000; 2986 ++srow; 2849 #ifndef QT_NO_TABBAR 2850 if (const QTabBar *tab = qobject_cast<const QTabBar*>(w)) { 2851 if (tab->documentMode()) { 2852 ret = Qt::AlignLeft; 2853 break; 2854 } 2987 2855 } 2988 }2989 QBitmap qmask = QBitmap::fromImage(img_mask);2990 mask->region = QRegion(qmask);2991 }2992 break; }2993 case SH_TitleBar_NoBorder:2994 ret = 1;2995 break;2996 case SH_RubberBand_Mask:2997 ret = 0;2998 break;2999 case SH_ComboBox_LayoutDirection:3000 ret = Qt::LeftToRight;3001 break;3002 case SH_ItemView_EllipsisLocation:3003 ret = Qt::AlignHCenter;3004 break;3005 case SH_ItemView_ShowDecorationSelected:3006 ret = true;3007 break;3008 case SH_TitleBar_ModifyNotification:3009 ret = false;3010 break;3011 case SH_ScrollBar_RollBetweenButtons:3012 ret = true;3013 break;3014 case SH_WindowFrame_Mask:3015 ret = 1;3016 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(hret)) {3017 mask->region = opt->rect;3018 mask->region -= QRect(opt->rect.left(), opt->rect.top(), 5, 1);3019 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 1, 3, 1);3020 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 2, 2, 1);3021 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 3, 1, 2);3022 3023 mask->region -= QRect(opt->rect.right() - 4, opt->rect.top(), 5, 1);3024 mask->region -= QRect(opt->rect.right() - 2, opt->rect.top() + 1, 3, 1);3025 mask->region -= QRect(opt->rect.right() - 1, opt->rect.top() + 2, 2, 1);3026 mask->region -= QRect(opt->rect.right() , opt->rect.top() + 3, 1, 2);3027 }3028 break;3029 case SH_TabBar_ElideMode:3030 ret = Qt::ElideRight;3031 break;3032 #if QT_CONFIG(dialogbuttonbox)3033 case SH_DialogButtonLayout:3034 ret = QDialogButtonBox::MacLayout;3035 break;3036 2856 #endif 3037 case SH_FormLayoutWrapPolicy: 3038 ret = QFormLayout::DontWrapRows; 3039 break; 3040 case SH_FormLayoutFieldGrowthPolicy: 3041 ret = QFormLayout::FieldsStayAtSizeHint; 3042 break; 3043 case SH_FormLayoutFormAlignment: 3044 ret = Qt::AlignHCenter | Qt::AlignTop; 3045 break; 3046 case SH_FormLayoutLabelAlignment: 3047 ret = Qt::AlignRight; 3048 break; 3049 case SH_ComboBox_PopupFrameStyle: 3050 ret = QFrame::NoFrame | QFrame::Plain; 3051 break; 3052 case SH_MessageBox_TextInteractionFlags: 3053 ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; 3054 break; 3055 case SH_SpellCheckUnderlineStyle: 3056 ret = QTextCharFormat::DashUnderline; 3057 break; 3058 case SH_MessageBox_CenterButtons: 3059 ret = false; 3060 break; 3061 case SH_MenuBar_AltKeyNavigation: 3062 ret = false; 3063 break; 3064 case SH_ItemView_MovementWithoutUpdatingSelection: 3065 ret = false; 3066 break; 3067 case SH_FocusFrame_AboveWidget: 3068 ret = true; 3069 break; 3070 #if QT_CONFIG(wizard) 3071 case SH_WizardStyle: 3072 ret = QWizard::MacStyle; 3073 break; 2857 ret = Qt::AlignCenter; 2858 } break; 2859 case SH_UnderlineShortcut: 2860 ret = false; 2861 break; 2862 case SH_ToolTipLabel_Opacity: 2863 ret = 242; // About 95% 2864 break; 2865 case SH_Button_FocusPolicy: 2866 ret = Qt::TabFocus; 2867 break; 2868 case SH_EtchDisabledText: 2869 ret = false; 2870 break; 2871 case SH_FocusFrame_Mask: { 2872 ret = true; 2873 if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { 2874 const uchar fillR = 192, fillG = 191, fillB = 190; 2875 QImage img; 2876 2877 QSize pixmapSize = opt->rect.size(); 2878 if (!pixmapSize.isEmpty()) { 2879 QPixmap pix(pixmapSize); 2880 pix.fill(QColor(fillR, fillG, fillB)); 2881 QPainter pix_paint(&pix); 2882 proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w); 2883 pix_paint.end(); 2884 img = pix.toImage(); 2885 } 2886 2887 const QRgb *sptr = (QRgb*)img.bits(), *srow; 2888 const int sbpl = img.bytesPerLine(); 2889 const int w = sbpl/4, h = img.height(); 2890 2891 QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32); 2892 QRgb *dptr = (QRgb*)img_mask.bits(), *drow; 2893 const int dbpl = img_mask.bytesPerLine(); 2894 2895 for (int y = 0; y < h; ++y) { 2896 srow = sptr+((y*sbpl)/4); 2897 drow = dptr+((y*dbpl)/4); 2898 for (int x = 0; x < w; ++x) { 2899 const int redDiff = qRed(*srow) - fillR; 2900 const int greenDiff = qGreen(*srow) - fillG; 2901 const int blueDiff = qBlue(*srow) - fillB; 2902 const int diff = (redDiff * redDiff) + (greenDiff * greenDiff) + (blueDiff * blueDiff); 2903 (*drow++) = (diff < 10) ? 0xffffffff : 0xff000000; 2904 ++srow; 2905 } 2906 } 2907 QBitmap qmask = QBitmap::fromImage(img_mask); 2908 mask->region = QRegion(qmask); 2909 } 2910 break; } 2911 case SH_TitleBar_NoBorder: 2912 ret = 1; 2913 break; 2914 case SH_RubberBand_Mask: 2915 ret = 0; 2916 break; 2917 case SH_ComboBox_LayoutDirection: 2918 ret = Qt::LeftToRight; 2919 break; 2920 case SH_ItemView_EllipsisLocation: 2921 ret = Qt::AlignHCenter; 2922 break; 2923 case SH_ItemView_ShowDecorationSelected: 2924 ret = true; 2925 break; 2926 case SH_TitleBar_ModifyNotification: 2927 ret = false; 2928 break; 2929 case SH_ScrollBar_RollBetweenButtons: 2930 ret = true; 2931 break; 2932 case SH_WindowFrame_Mask: 2933 ret = 1; 2934 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(hret)) { 2935 mask->region = opt->rect; 2936 mask->region -= QRect(opt->rect.left(), opt->rect.top(), 5, 1); 2937 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 1, 3, 1); 2938 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 2, 2, 1); 2939 mask->region -= QRect(opt->rect.left(), opt->rect.top() + 3, 1, 2); 2940 2941 mask->region -= QRect(opt->rect.right() - 4, opt->rect.top(), 5, 1); 2942 mask->region -= QRect(opt->rect.right() - 2, opt->rect.top() + 1, 3, 1); 2943 mask->region -= QRect(opt->rect.right() - 1, opt->rect.top() + 2, 2, 1); 2944 mask->region -= QRect(opt->rect.right() , opt->rect.top() + 3, 1, 2); 2945 } 2946 break; 2947 case SH_TabBar_ElideMode: 2948 ret = Qt::ElideRight; 2949 break; 2950 case SH_DialogButtonLayout: 2951 ret = QDialogButtonBox::MacLayout; 2952 break; 2953 case SH_FormLayoutWrapPolicy: 2954 ret = QFormLayout::DontWrapRows; 2955 break; 2956 case SH_FormLayoutFieldGrowthPolicy: 2957 ret = QFormLayout::FieldsStayAtSizeHint; 2958 break; 2959 case SH_FormLayoutFormAlignment: 2960 ret = Qt::AlignHCenter | Qt::AlignTop; 2961 break; 2962 case SH_FormLayoutLabelAlignment: 2963 ret = Qt::AlignRight; 2964 break; 2965 case SH_ComboBox_PopupFrameStyle: 2966 ret = QFrame::NoFrame | QFrame::Plain; 2967 break; 2968 case SH_MessageBox_TextInteractionFlags: 2969 ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; 2970 break; 2971 case SH_SpellCheckUnderlineStyle: 2972 ret = QTextCharFormat::DashUnderline; 2973 break; 2974 case SH_MessageBox_CenterButtons: 2975 ret = false; 2976 break; 2977 case SH_MenuBar_AltKeyNavigation: 2978 ret = false; 2979 break; 2980 case SH_ItemView_MovementWithoutUpdatingSelection: 2981 ret = false; 2982 break; 2983 case SH_FocusFrame_AboveWidget: 2984 ret = true; 2985 break; 2986 #ifndef QT_NO_WIZARD 2987 case SH_WizardStyle: 2988 ret = QWizard::MacStyle; 2989 break; 3074 2990 #endif 3075 case SH_ItemView_ArrowKeysNavigateIntoChildren: 3076 ret = false; 3077 break; 3078 case SH_Menu_FlashTriggeredItem: 3079 ret = true; 3080 break; 3081 case SH_Menu_FadeOutOnHide: 3082 ret = true; 3083 break; 3084 case SH_Menu_Mask: 3085 if (opt) { 3086 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { 2991 case SH_ItemView_ArrowKeysNavigateIntoChildren: 2992 ret = false; 2993 break; 2994 case SH_Menu_FlashTriggeredItem: 3087 2995 ret = true; 3088 HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, 3089 opt->rect.width(), opt->rect.height() - 8); 3090 HIThemeMenuDrawInfo mdi; 3091 mdi.version = 0; 3092 #if QT_CONFIG(menu) 3093 if (w && qobject_cast<QMenu *>(w->parentWidget())) 3094 mdi.menuType = kThemeMenuTypeHierarchical; 3095 else 2996 break; 2997 case SH_Menu_FadeOutOnHide: 2998 ret = true; 2999 break; 3000 case SH_Menu_Mask: 3001 if (opt) { 3002 if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { 3003 ret = true; 3004 HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, 3005 opt->rect.width(), opt->rect.height() - 8); 3006 HIThemeMenuDrawInfo mdi; 3007 mdi.version = 0; 3008 #ifndef QT_NO_MENU 3009 if (w && qobject_cast<QMenu *>(w->parentWidget())) 3010 mdi.menuType = kThemeMenuTypeHierarchical; 3011 else 3096 3012 #endif 3097 mdi.menuType = kThemeMenuTypePopUp;3098 QCFType<HIShapeRef> shape;3099 HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape);3100 3101 mask->region = qt_mac_fromHIShapeRef(shape);3102 }3103 }3104 break;3105 case SH_ItemView_PaintAlternatingRowColorsForEmptyArea:3106 ret = true;3107 break;3108 #if QT_CONFIG(tabbar)3109 case SH_TabBar_CloseButtonPosition:3110 ret = QTabBar::LeftSide;3111 break;3013 mdi.menuType = kThemeMenuTypePopUp; 3014 QCFType<HIShapeRef> shape; 3015 HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape); 3016 3017 mask->region = qt_mac_fromHIShapeRef(shape); 3018 } 3019 } 3020 break; 3021 case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: 3022 ret = true; 3023 break; 3024 #ifndef QT_NO_TABBAR 3025 case SH_TabBar_CloseButtonPosition: 3026 ret = QTabBar::LeftSide; 3027 break; 3112 3028 #endif 3113 case SH_DockWidget_ButtonsHaveFrame:3114 ret = false;3115 break;3116 case SH_ScrollBar_Transient:3117 if ((qobject_cast<const QScrollBar *>(w) && w->parent() &&3118 qobject_cast<QAbstractScrollArea*>(w->parent()->parent()))3029 case SH_DockWidget_ButtonsHaveFrame: 3030 ret = false; 3031 break; 3032 case SH_ScrollBar_Transient: 3033 if ((qobject_cast<const QScrollBar *>(w) && w->parent() && 3034 qobject_cast<QAbstractScrollArea*>(w->parent()->parent())) 3119 3035 #ifndef QT_NO_ACCESSIBILITY 3120 || (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar))3036 || (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar)) 3121 3037 #endif 3122 ) { 3123 ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; 3038 ) { 3039 ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; 3040 } 3041 break; 3042 case SH_ItemView_ScrollMode: 3043 ret = QAbstractItemView::ScrollPerPixel; 3044 break; 3045 default: 3046 ret = QCommonStyle::styleHint(sh, opt, w, hret); 3047 break; 3124 3048 } 3125 break; 3126 case SH_ItemView_ScrollMode: 3127 ret = QAbstractItemView::ScrollPerPixel; 3128 break; 3129 default: 3130 ret = QCommonStyle::styleHint(sh, opt, w, hret); 3131 break; 3049 return ret; 3132 3050 } 3133 return ret; 3134 } 3135 3136 QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, 3137 const QStyleOption *opt) const 3138 { 3139 switch (iconMode) { 3140 case QIcon::Disabled: { 3141 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); 3142 int imgh = img.height(); 3143 int imgw = img.width(); 3144 QRgb pixel; 3145 for (int y = 0; y < imgh; ++y) { 3146 for (int x = 0; x < imgw; ++x) { 3147 pixel = img.pixel(x, y); 3148 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), 3149 qAlpha(pixel) / 2)); 3051 3052 QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, 3053 const QStyleOption *opt) const 3054 { 3055 switch (iconMode) { 3056 case QIcon::Disabled: { 3057 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); 3058 int imgh = img.height(); 3059 int imgw = img.width(); 3060 QRgb pixel; 3061 for (int y = 0; y < imgh; ++y) { 3062 for (int x = 0; x < imgw; ++x) { 3063 pixel = img.pixel(x, y); 3064 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), 3065 qAlpha(pixel) / 2)); 3066 } 3067 } 3068 return QPixmap::fromImage(img); 3150 3069 } 3070 default: 3071 ; 3151 3072 } 3152 return QPixmap::fromImage(img); 3153 } 3154 default: 3155 ; 3073 return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); 3156 3074 } 3157 return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);3158 } 3159 3160 3161 QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, 3162 const QWidget *widget) const3163 { 3164 // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap()3165 // I don't want infinite recursion so if we do get in that situation, just return the Window's3166 // standard pixmap instead (since there is no mac-specific icon then). This should be fine until3167 // someone changes how Windows standard3168 // pixmap works.3169 static bool recursionGuard = false;3170 3171 if (recursionGuard)3172 re turn QCommonStyle::standardPixmap(standardPixmap, opt, widget);3173 3174 recursionGuard = true;3175 QIcon icon = proxy()->standardIcon(standardPixmap, opt, widget);3176 recursionGuard = false;3177 int size;3178 switch (standardPixmap) {3179 default:3180 size = 32;3181 break;3182 case SP_MessageBoxCritical:3183 case SP_MessageBoxQuestion:3184 case SP_MessageBoxInformation:3185 case SP_MessageBoxWarning:3186 size = 64;3187 break;3075 3076 3077 QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, 3078 const QWidget *widget) const 3079 { 3080 // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap() 3081 // I don't want infinite recursion so if we do get in that situation, just return the Window's 3082 // standard pixmap instead (since there is no mac-specific icon then). This should be fine until 3083 // someone changes how Windows standard 3084 // pixmap works. 3085 static bool recursionGuard = false; 3086 3087 if (recursionGuard) 3088 return QCommonStyle::standardPixmap(standardPixmap, opt, widget); 3089 3090 recursionGuard = true; 3091 QIcon icon = proxy()->standardIcon(standardPixmap, opt, widget); 3092 recursionGuard = false; 3093 int size; 3094 switch (standardPixmap) { 3095 default: 3096 size = 32; 3097 break; 3098 case SP_MessageBoxCritical: 3099 case SP_MessageBoxQuestion: 3100 case SP_MessageBoxInformation: 3101 case SP_MessageBoxWarning: 3102 size = 64; 3103 break; 3104 } 3105 return icon.pixmap(qt_getWindow(widget), QSize(size, size)); 3188 3106 } 3189 return icon.pixmap(qt_getWindow(widget), QSize(size, size)); 3190 } 3191 3192 void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) 3193 { 3194 QWidget *wadget = const_cast<QWidget *>(widget); 3195 wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge); 3196 wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall); 3197 wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini); 3198 } 3199 3200 QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt) 3201 { 3202 while (widget) { 3203 if (widget->testAttribute(Qt::WA_MacMiniSize)) { 3107 3108 /*void QMacStyle::setFocusRectPolicy(QWidget *w, FocusRectPolicy policy) 3109 { 3110 switch (policy) { 3111 case FocusDefault: 3112 break; 3113 case FocusEnabled: 3114 case FocusDisabled: 3115 w->setAttribute(Qt::WA_MacShowFocusRect, policy == FocusEnabled); 3116 break; 3117 } 3118 } 3119 3120 QMacStyle::FocusRectPolicy QMacStyle::focusRectPolicy(const QWidget *w) 3121 { 3122 return w->testAttribute(Qt::WA_MacShowFocusRect) ? FocusEnabled : FocusDisabled; 3123 }*/ 3124 3125 void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) 3126 { 3127 QWidget *wadget = const_cast<QWidget *>(widget); 3128 wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge); 3129 wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall); 3130 wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini); 3131 } 3132 3133 QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt) 3134 { 3135 while (widget) { 3136 if (widget->testAttribute(Qt::WA_MacMiniSize)) { 3137 return SizeMini; 3138 } else if (widget->testAttribute(Qt::WA_MacSmallSize)) { 3139 return SizeSmall; 3140 } else if (widget->testAttribute(Qt::WA_MacNormalSize)) { 3141 return SizeLarge; 3142 } 3143 widget = widget->parentWidget(); 3144 } 3145 3146 if (opt && opt->state & State_Mini) 3204 3147 return SizeMini; 3205 } else if (widget->testAttribute(Qt::WA_MacSmallSize)) {3148 else if (opt && opt->state & State_Small) 3206 3149 return SizeSmall; 3207 } else if (widget->testAttribute(Qt::WA_MacNormalSize)) { 3208 return SizeLarge; 3209 } 3210 widget = widget->parentWidget(); 3150 3151 return SizeDefault; 3211 3152 } 3212 3213 if (opt && opt->state & State_Mini) 3214 return SizeMini; 3215 else if (opt && opt->state & State_Small) 3216 return SizeSmall; 3217 3218 return SizeDefault; 3219 } 3220 3221 void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, 3222 const QWidget *w) const 3223 { 3224 Q_D(const QMacStyle); 3225 ThemeDrawState tds = d->getDrawState(opt->state); 3226 QMacCGContext cg(p); 3227 QWindow *window = w && w->window() ? w->window()->windowHandle() : 3228 QStyleHelper::styleObjectWindow(opt->styleObject); 3229 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 3230 switch (pe) { 3231 case PE_IndicatorArrowUp: 3232 case PE_IndicatorArrowDown: 3233 case PE_IndicatorArrowRight: 3234 case PE_IndicatorArrowLeft: { 3235 p->save(); 3236 p->setRenderHint(QPainter::Antialiasing); 3237 int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1; 3238 QMatrix matrix; 3239 matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); 3240 QPainterPath path; 3241 switch(pe) { 3242 default: 3243 case PE_IndicatorArrowDown: 3244 break; 3245 case PE_IndicatorArrowUp: 3246 matrix.rotate(180); 3247 break; 3248 case PE_IndicatorArrowLeft: 3249 matrix.rotate(90); 3250 break; 3251 case PE_IndicatorArrowRight: 3252 matrix.rotate(-90); 3253 break; 3254 } 3255 path.moveTo(0, 5); 3256 path.lineTo(-4, -3); 3257 path.lineTo(4, -3); 3258 p->setMatrix(matrix); 3259 p->setPen(Qt::NoPen); 3260 p->setBrush(QColor(0, 0, 0, 135)); 3261 p->drawPath(path); 3262 p->restore(); 3263 break; } 3264 #if QT_CONFIG(tabbar) 3265 case PE_FrameTabBarBase: 3266 if (const QStyleOptionTabBarBase *tbb 3267 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt)) { 3268 if (tbb->documentMode) { 3153 3154 void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, 3155 const QWidget *w) const 3156 { 3157 Q_D(const QMacStyle); 3158 ThemeDrawState tds = d->getDrawState(opt->state); 3159 QMacCGContext cg(p); 3160 QWindow *window = w && w->window() ? w->window()->windowHandle() : 3161 QStyleHelper::styleObjectWindow(opt->styleObject); 3162 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 3163 switch (pe) { 3164 case PE_IndicatorArrowUp: 3165 case PE_IndicatorArrowDown: 3166 case PE_IndicatorArrowRight: 3167 case PE_IndicatorArrowLeft: { 3269 3168 p->save(); 3270 drawTabBase(p, tbb, w); 3169 p->setRenderHint(QPainter::Antialiasing); 3170 int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1; 3171 QMatrix matrix; 3172 matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); 3173 QPainterPath path; 3174 switch(pe) { 3175 default: 3176 case PE_IndicatorArrowDown: 3177 break; 3178 case PE_IndicatorArrowUp: 3179 matrix.rotate(180); 3180 break; 3181 case PE_IndicatorArrowLeft: 3182 matrix.rotate(90); 3183 break; 3184 case PE_IndicatorArrowRight: 3185 matrix.rotate(-90); 3186 break; 3187 } 3188 path.moveTo(0, 5); 3189 path.lineTo(-4, -3); 3190 path.lineTo(4, -3); 3191 p->setMatrix(matrix); 3192 p->setPen(Qt::NoPen); 3193 p->setBrush(QColor(0, 0, 0, 135)); 3194 p->drawPath(path); 3271 3195 p->restore(); 3272 return; 3196 break; } 3197 #ifndef QT_NO_TABBAR 3198 case PE_FrameTabBarBase: 3199 if (const QStyleOptionTabBarBase *tbb 3200 = qstyleoption_cast<const QStyleOptionTabBarBase *>(opt)) { 3201 if (tbb->documentMode) { 3202 p->save(); 3203 drawTabBase(p, tbb, w); 3204 p->restore(); 3205 return; 3206 } 3207 3208 QRegion region(tbb->rect); 3209 region -= tbb->tabBarRect; 3210 p->save(); 3211 p->setClipRegion(region); 3212 QStyleOptionTabWidgetFrame twf; 3213 twf.QStyleOption::operator=(*tbb); 3214 twf.shape = tbb->shape; 3215 switch (getTabDirection(twf.shape)) { 3216 case kThemeTabNorth: 3217 twf.rect = twf.rect.adjusted(0, 0, 0, 10); 3218 break; 3219 case kThemeTabSouth: 3220 twf.rect = twf.rect.adjusted(0, -10, 0, 0); 3221 break; 3222 case kThemeTabWest: 3223 twf.rect = twf.rect.adjusted(0, 0, 10, 0); 3224 break; 3225 case kThemeTabEast: 3226 twf.rect = twf.rect.adjusted(0, -10, 0, 0); 3227 break; 3228 } 3229 proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w); 3230 p->restore(); 3231 } 3232 break; 3233 #endif 3234 case PE_PanelTipLabel: 3235 p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase)); 3236 break; 3237 case PE_FrameGroupBox: 3238 if (const QStyleOptionFrame *groupBox = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { 3239 if (groupBox->features & QStyleOptionFrame::Flat) { 3240 QCommonStyle::drawPrimitive(pe, groupBox, p, w); 3241 } else { 3242 HIThemeGroupBoxDrawInfo gdi; 3243 gdi.version = qt_mac_hitheme_version; 3244 gdi.state = tds; 3245 #ifndef QT_NO_GROUPBOX 3246 if (w && qobject_cast<QGroupBox *>(w->parentWidget())) 3247 gdi.kind = kHIThemeGroupBoxKindSecondary; 3248 else 3249 #endif 3250 gdi.kind = kHIThemeGroupBoxKindPrimary; 3251 HIRect hirect = qt_hirectForQRect(opt->rect); 3252 HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); 3253 } 3254 } 3255 break; 3256 case PE_IndicatorToolBarSeparator: { 3257 QPainterPath path; 3258 if (opt->state & State_Horizontal) { 3259 int xpoint = opt->rect.center().x(); 3260 path.moveTo(xpoint + 0.5, opt->rect.top() + 1); 3261 path.lineTo(xpoint + 0.5, opt->rect.bottom()); 3262 } else { 3263 int ypoint = opt->rect.center().y(); 3264 path.moveTo(opt->rect.left() + 2 , ypoint + 0.5); 3265 path.lineTo(opt->rect.right() + 1, ypoint + 0.5); 3266 } 3267 QPainterPathStroker theStroker; 3268 theStroker.setCapStyle(Qt::FlatCap); 3269 theStroker.setDashPattern(QVector<qreal>() << 1 << 2); 3270 path = theStroker.createStroke(path); 3271 p->fillPath(path, QColor(0, 0, 0, 119)); 3273 3272 } 3274 3275 QRegion region(tbb->rect);3276 region -= tbb->tabBarRect;3277 p->save();3278 p->setClipRegion(region);3279 QStyleOptionTabWidgetFrame twf;3280 twf.QStyleOption::operator=(*tbb);3281 twf.shape = tbb->shape;3282 switch (getTabDirection(twf.shape)) {3283 case kThemeTabNorth:3284 twf.rect = twf.rect.adjusted(0, 0, 0, 10);3285 3273 break; 3286 case kThemeTabSouth: 3287 twf.rect = twf.rect.adjusted(0, -10, 0, 0); 3274 case PE_FrameWindow: 3275 break; 3276 case PE_IndicatorDockWidgetResizeHandle: { 3277 // The docwidget resize handle is drawn as a one-pixel wide line. 3278 p->save(); 3279 if (opt->state & State_Horizontal) { 3280 p->setPen(QColor(160, 160, 160)); 3281 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 3282 } else { 3283 p->setPen(QColor(145, 145, 145)); 3284 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); 3285 } 3286 p->restore(); 3287 } break; 3288 case PE_IndicatorToolBarHandle: { 3289 p->save(); 3290 QPainterPath path; 3291 int x = opt->rect.x() + 6; 3292 int y = opt->rect.y() + 7; 3293 static const int RectHeight = 2; 3294 if (opt->state & State_Horizontal) { 3295 while (y < opt->rect.height() - RectHeight - 5) { 3296 path.moveTo(x, y); 3297 path.addEllipse(x, y, RectHeight, RectHeight); 3298 y += 6; 3299 } 3300 } else { 3301 while (x < opt->rect.width() - RectHeight - 5) { 3302 path.moveTo(x, y); 3303 path.addEllipse(x, y, RectHeight, RectHeight); 3304 x += 6; 3305 } 3306 } 3307 p->setPen(Qt::NoPen); 3308 QColor dark = opt->palette.dark().color().darker(); 3309 dark.setAlphaF(0.50); 3310 p->fillPath(path, dark); 3311 p->restore(); 3312 3313 break; 3314 } 3315 case PE_IndicatorHeaderArrow: 3316 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3317 // In HITheme, up is down, down is up and hamburgers eat people. 3318 if (header->sortIndicator != QStyleOptionHeader::None) 3319 proxy()->drawPrimitive( 3320 (header->sortIndicator == QStyleOptionHeader::SortDown) ? 3321 PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w); 3322 } 3323 break; 3324 case PE_IndicatorMenuCheckMark: { 3325 const int checkw = 8; 3326 const int checkh = 8; 3327 const int xoff = qMax(0, (opt->rect.width() - checkw) / 2); 3328 const int yoff = qMax(0, (opt->rect.width() - checkh) / 2); 3329 const int x1 = xoff + opt->rect.x(); 3330 const int y1 = yoff + opt->rect.y() + checkw/2; 3331 const int x2 = xoff + opt->rect.x() + checkw/4; 3332 const int y2 = yoff + opt->rect.y() + checkh; 3333 const int x3 = xoff + opt->rect.x() + checkw; 3334 const int y3 = yoff + opt->rect.y(); 3335 3336 QVector<QLineF> a(2); 3337 a << QLineF(x1, y1, x2, y2); 3338 a << QLineF(x2, y2, x3, y3); 3339 if (opt->palette.currentColorGroup() == QPalette::Active) { 3340 if (opt->state & State_On) 3341 p->setPen(QPen(opt->palette.highlightedText().color(), 3)); 3342 else 3343 p->setPen(QPen(opt->palette.text().color(), 3)); 3344 } else { 3345 p->setPen(QPen(QColor(100, 100, 100), 3)); 3346 } 3347 p->save(); 3348 p->setRenderHint(QPainter::Antialiasing); 3349 p->drawLines(a); 3350 p->restore(); 3351 break; } 3352 case PE_IndicatorViewItemCheck: 3353 case PE_IndicatorRadioButton: 3354 case PE_IndicatorCheckBox: { 3355 bool drawColorless = tds == kThemeStateInactive; 3356 HIThemeButtonDrawInfo bdi; 3357 bdi.version = qt_mac_hitheme_version; 3358 bdi.state = tds; 3359 if (drawColorless) 3360 bdi.state = kThemeStateActive; 3361 bdi.adornment = kThemeDrawIndicatorOnly; 3362 if (opt->state & State_HasFocus) 3363 bdi.adornment |= kThemeAdornmentFocus; 3364 bool isRadioButton = (pe == PE_IndicatorRadioButton); 3365 switch (d->aquaSizeConstrain(opt, w)) { 3366 case QAquaSizeUnknown: 3367 case QAquaSizeLarge: 3368 if (isRadioButton) 3369 bdi.kind = kThemeRadioButton; 3370 else 3371 bdi.kind = kThemeCheckBox; 3372 break; 3373 case QAquaSizeMini: 3374 if (isRadioButton) 3375 bdi.kind = kThemeMiniRadioButton; 3376 else 3377 bdi.kind = kThemeMiniCheckBox; 3378 break; 3379 case QAquaSizeSmall: 3380 if (isRadioButton) 3381 bdi.kind = kThemeSmallRadioButton; 3382 else 3383 bdi.kind = kThemeSmallCheckBox; 3384 break; 3385 } 3386 if (opt->state & State_NoChange) 3387 bdi.value = kThemeButtonMixed; 3388 else if (opt->state & State_On) 3389 bdi.value = kThemeButtonOn; 3390 else 3391 bdi.value = kThemeButtonOff; 3392 HIRect macRect = qt_hirectForQRect(opt->rect); 3393 if (!drawColorless) 3394 HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); 3395 else 3396 d->drawColorlessButton(macRect, &bdi, p, opt); 3397 break; } 3398 case PE_FrameFocusRect: 3399 // Use the our own focus widget stuff. 3400 break; 3401 case PE_IndicatorBranch: { 3402 if (!(opt->state & State_Children)) 3403 break; 3404 if (!d->indicatorBranchButtonCell) 3405 const_cast<QMacStylePrivate *>(d)->indicatorBranchButtonCell = (void *)[[NSButtonCell alloc] init]; 3406 NSButtonCell *triangleCell = (NSButtonCell *)d->indicatorBranchButtonCell; 3407 [triangleCell setButtonType:NSOnOffButton]; 3408 [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; 3409 [triangleCell setBezelStyle:NSDisclosureBezelStyle]; 3410 bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); 3411 [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; 3412 3413 CGContextSaveGState(cg); 3414 [NSGraphicsContext saveGraphicsState]; 3415 3416 [NSGraphicsContext setCurrentContext:[NSGraphicsContext 3417 graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; 3418 3419 QRect qtRect = opt->rect.adjusted(DisclosureOffset, 0, -DisclosureOffset, 0); 3420 CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); 3421 CGContextTranslateCTM(cg, rect.origin.x, rect.origin.y + rect.size.height); 3422 CGContextScaleCTM(cg, 1, -1); 3423 CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y); 3424 3425 [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; 3426 3427 [NSGraphicsContext restoreGraphicsState]; 3428 CGContextRestoreGState(cg); 3429 break; } 3430 3431 case PE_Frame: { 3432 QPen oldPen = p->pen(); 3433 p->setPen(opt->palette.base().color().darker(140)); 3434 p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); 3435 p->setPen(opt->palette.base().color().darker(180)); 3436 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 3437 p->setPen(oldPen); 3438 break; } 3439 3440 case PE_FrameLineEdit: 3441 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { 3442 if (frame->state & State_Sunken) { 3443 QColor baseColor(frame->palette.background().color()); 3444 HIThemeFrameDrawInfo fdi; 3445 fdi.version = qt_mac_hitheme_version; 3446 fdi.state = tds; 3447 SInt32 frame_size; 3448 fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : 3449 kHIThemeFrameTextFieldSquare; 3450 GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); 3451 if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) 3452 fdi.state = kThemeStateInactive; 3453 else if (fdi.state == kThemeStatePressed) 3454 // This pressed state doesn't make sense for a line edit frame. 3455 // And Yosemite agrees with us. Otherwise it starts showing yellow pixels. 3456 fdi.state = kThemeStateActive; 3457 fdi.isFocused = (frame->state & State_HasFocus); 3458 int lw = frame->lineWidth; 3459 if (lw <= 0) 3460 lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w); 3461 { //clear to base color 3462 p->save(); 3463 p->setPen(QPen(baseColor, lw)); 3464 p->setBrush(Qt::NoBrush); 3465 p->drawRect(frame->rect); 3466 p->restore(); 3467 } 3468 HIRect hirect = qt_hirectForQRect(frame->rect, 3469 QRect(frame_size, frame_size, 3470 frame_size * 2, frame_size * 2)); 3471 3472 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); 3473 } else { 3474 QCommonStyle::drawPrimitive(pe, opt, p, w); 3475 } 3476 } 3288 3477 break; 3289 case kThemeTabWest: 3290 twf.rect = twf.rect.adjusted(0, 0, 10, 0); 3478 case PE_PanelLineEdit: 3479 QCommonStyle::drawPrimitive(pe, opt, p, w); 3480 // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). 3481 // Focus frame is drawn outside the rectangle passed in the option-rect. 3482 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { 3483 #ifndef QT_NO_LINEEDIT 3484 if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) { 3485 int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); 3486 int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); 3487 QStyleOptionFrame focusFrame = *panel; 3488 focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); 3489 drawControl(CE_FocusFrame, &focusFrame, p, w); 3490 } 3491 #endif 3492 } 3493 3291 3494 break; 3292 case kThemeTabEast: 3293 twf.rect = twf.rect.adjusted(0, -10, 0, 0); 3495 #ifndef QT_NO_TABWIDGET 3496 case PE_FrameTabWidget: 3497 if (const QStyleOptionTabWidgetFrame *twf 3498 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 3499 HIRect hirect = qt_hirectForQRect(twf->rect); 3500 HIThemeTabPaneDrawInfo tpdi; 3501 tpdi.version = qt_mac_hitheme_tab_version(); 3502 tpdi.state = tds; 3503 tpdi.direction = getTabDirection(twf->shape); 3504 tpdi.size = kHIThemeTabSizeNormal; 3505 tpdi.kind = kHIThemeTabKindNormal; 3506 tpdi.adornment = kHIThemeTabPaneAdornmentNormal; 3507 HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); 3508 } 3294 3509 break; 3295 }3296 proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w);3297 p->restore();3298 }3299 break;3300 #endif3301 case PE_PanelTipLabel:3302 p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase));3303 break;3304 case PE_FrameGroupBox:3305 if (const QStyleOptionFrame *groupBox = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {3306 if (groupBox->features & QStyleOptionFrame::Flat) {3307 QCommonStyle::drawPrimitive(pe, groupBox, p, w);3308 } else {3309 HIThemeGroupBoxDrawInfo gdi;3310 gdi.version = qt_mac_hitheme_version;3311 gdi.state = tds;3312 #if QT_CONFIG(groupbox)3313 if (w && qobject_cast<QGroupBox *>(w->parentWidget()))3314 gdi.kind = kHIThemeGroupBoxKindSecondary;3315 else3316 3510 #endif 3317 gdi.kind = kHIThemeGroupBoxKindPrimary; 3318 HIRect hirect = qt_hirectForQRect(opt->rect); 3319 HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); 3320 } 3321 } 3322 break; 3323 case PE_IndicatorToolBarSeparator: { 3324 QPainterPath path; 3325 if (opt->state & State_Horizontal) { 3326 int xpoint = opt->rect.center().x(); 3327 path.moveTo(xpoint + 0.5, opt->rect.top() + 1); 3328 path.lineTo(xpoint + 0.5, opt->rect.bottom()); 3329 } else { 3330 int ypoint = opt->rect.center().y(); 3331 path.moveTo(opt->rect.left() + 2 , ypoint + 0.5); 3332 path.lineTo(opt->rect.right() + 1, ypoint + 0.5); 3333 } 3334 QPainterPathStroker theStroker; 3335 theStroker.setCapStyle(Qt::FlatCap); 3336 theStroker.setDashPattern(QVector<qreal>() << 1 << 2); 3337 path = theStroker.createStroke(path); 3338 p->fillPath(path, QColor(0, 0, 0, 119)); 3339 } 3340 break; 3341 case PE_FrameWindow: 3342 break; 3343 case PE_IndicatorDockWidgetResizeHandle: { 3344 // The docwidget resize handle is drawn as a one-pixel wide line. 3345 p->save(); 3346 if (opt->state & State_Horizontal) { 3347 p->setPen(QColor(160, 160, 160)); 3511 case PE_PanelScrollAreaCorner: { 3512 const QBrush brush(opt->palette.brush(QPalette::Base)); 3513 p->fillRect(opt->rect, brush); 3514 p->setPen(QPen(QColor(217, 217, 217))); 3348 3515 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 3349 } else { 3350 p->setPen(QColor(145, 145, 145)); 3351 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); 3352 } 3353 p->restore(); 3354 } break; 3355 case PE_IndicatorToolBarHandle: { 3356 p->save(); 3357 QPainterPath path; 3358 int x = opt->rect.x() + 6; 3359 int y = opt->rect.y() + 7; 3360 static const int RectHeight = 2; 3361 if (opt->state & State_Horizontal) { 3362 while (y < opt->rect.height() - RectHeight - 5) { 3363 path.moveTo(x, y); 3364 path.addEllipse(x, y, RectHeight, RectHeight); 3365 y += 6; 3366 } 3367 } else { 3368 while (x < opt->rect.width() - RectHeight - 5) { 3369 path.moveTo(x, y); 3370 path.addEllipse(x, y, RectHeight, RectHeight); 3371 x += 6; 3516 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 3517 } break; 3518 case PE_FrameStatusBarItem: 3519 break; 3520 case PE_IndicatorTabClose: { 3521 bool hover = (opt->state & State_MouseOver); 3522 bool selected = (opt->state & State_Selected); 3523 bool active = (opt->state & State_Active); 3524 drawTabCloseButton(p, hover, active, selected); 3525 } break; 3526 case PE_PanelStatusBar: { 3527 // Fill the status bar with the titlebar gradient. 3528 QLinearGradient linearGrad; 3529 if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) { 3530 linearGrad = titlebarGradientActive(); 3531 } else { 3532 linearGrad = titlebarGradientInactive(); 3372 3533 } 3534 3535 linearGrad.setStart(0, opt->rect.top()); 3536 linearGrad.setFinalStop(0, opt->rect.bottom()); 3537 p->fillRect(opt->rect, linearGrad); 3538 3539 // Draw the black separator line at the top of the status bar. 3540 if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) 3541 p->setPen(titlebarSeparatorLineActive); 3542 else 3543 p->setPen(titlebarSeparatorLineInactive); 3544 p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top()); 3545 3546 break; 3373 3547 } 3374 p->setPen(Qt::NoPen); 3375 QColor dark = opt->palette.dark().color().darker(); 3376 dark.setAlphaF(0.50); 3377 p->fillPath(path, dark); 3378 p->restore(); 3379 3380 break; 3381 } 3382 case PE_IndicatorHeaderArrow: 3383 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3384 // In HITheme, up is down, down is up and hamburgers eat people. 3385 if (header->sortIndicator != QStyleOptionHeader::None) 3386 proxy()->drawPrimitive( 3387 (header->sortIndicator == QStyleOptionHeader::SortDown) ? 3388 PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w); 3389 } 3390 break; 3391 case PE_IndicatorMenuCheckMark: { 3392 QColor pc; 3393 if (opt->state & State_On) 3394 pc = opt->palette.highlightedText().color(); 3395 else 3396 pc = opt->palette.text().color(); 3397 3398 QCFType<CGColorRef> checkmarkColor = CGColorCreateGenericRGB(static_cast<CGFloat>(pc.redF()), 3399 static_cast<CGFloat>(pc.greenF()), 3400 static_cast<CGFloat>(pc.blueF()), 3401 static_cast<CGFloat>(pc.alphaF())); 3402 // kCTFontUIFontSystem and others give the same result 3403 // as kCTFontUIFontMenuItemMark. However, the latter is 3404 // more reminiscent to HITheme's kThemeMenuItemMarkFont. 3405 // See also the font for small- and mini-sized widgets, 3406 // where we end up using the generic system font type. 3407 const CTFontUIFontType fontType = (opt->state & State_Mini) ? kCTFontUIFontMiniSystem : 3408 (opt->state & State_Small) ? kCTFontUIFontSmallSystem : 3409 kCTFontUIFontMenuItemMark; 3410 // Similarly for the font size, where there is a small difference 3411 // between regular combobox and item view items, and and menu items. 3412 // However, we ignore any difference for small- and mini-sized widgets. 3413 const CGFloat fontSize = fontType == kCTFontUIFontMenuItemMark ? opt->fontMetrics.height() : 0.0; 3414 QCFType<CTFontRef> checkmarkFont = CTFontCreateUIFontForLanguage(fontType, fontSize, NULL); 3415 3416 CGContextSaveGState(cg); 3417 CGContextSetShouldSmoothFonts(cg, NO); // Same as HITheme and Cocoa menu checkmarks 3418 3419 // Baseline alignment tweaks for QComboBox and QMenu 3420 const CGFloat vOffset = (opt->state & State_Mini) ? 0.0 : 3421 (opt->state & State_Small) ? 1.0 : 3422 0.75; 3423 3424 CGContextTranslateCTM(cg, 0, opt->rect.bottom()); 3425 CGContextScaleCTM(cg, 1, -1); 3426 // Translate back to the original position and add rect origin and offset 3427 CGContextTranslateCTM(cg, opt->rect.x(), vOffset); 3428 3429 // CTFont has severe difficulties finding the checkmark character among its 3430 // glyphs. Fortunately, CTLine knows its ways inside the Cocoa labyrinth. 3431 static const CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; 3432 static const int numValues = sizeof(keys) / sizeof(keys[0]); 3433 const CFTypeRef values[] = { (CFTypeRef)checkmarkFont, (CFTypeRef)checkmarkColor }; 3434 Q_STATIC_ASSERT((sizeof(values) / sizeof(values[0])) == numValues); 3435 QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 3436 numValues, NULL, NULL); 3437 // U+2713: CHECK MARK 3438 QCFType<CFAttributedStringRef> checkmarkString = CFAttributedStringCreate(kCFAllocatorDefault, (CFStringRef)@"\u2713", attributes); 3439 QCFType<CTLineRef> line = CTLineCreateWithAttributedString(checkmarkString); 3440 3441 CTLineDraw((CTLineRef)line, cg); 3442 CGContextFlush(cg); // CTLineDraw's documentation says it doesn't flush 3443 3444 CGContextRestoreGState(cg); 3445 break; } 3446 case PE_IndicatorViewItemCheck: 3447 case PE_IndicatorRadioButton: 3448 case PE_IndicatorCheckBox: { 3449 bool drawColorless = tds == kThemeStateInactive; 3450 HIThemeButtonDrawInfo bdi; 3451 bdi.version = qt_mac_hitheme_version; 3452 bdi.state = tds; 3453 if (drawColorless) 3454 bdi.state = kThemeStateActive; 3455 bdi.adornment = kThemeDrawIndicatorOnly; 3456 if (opt->state & State_HasFocus) 3457 bdi.adornment |= kThemeAdornmentFocus; 3458 bool isRadioButton = (pe == PE_IndicatorRadioButton); 3459 switch (d->aquaSizeConstrain(opt, w)) { 3460 case QAquaSizeUnknown: 3461 case QAquaSizeLarge: 3462 if (isRadioButton) 3463 bdi.kind = kThemeRadioButton; 3464 else 3465 bdi.kind = kThemeCheckBox; 3466 break; 3467 case QAquaSizeMini: 3468 if (isRadioButton) 3469 bdi.kind = kThemeMiniRadioButton; 3470 else 3471 bdi.kind = kThemeMiniCheckBox; 3472 break; 3473 case QAquaSizeSmall: 3474 if (isRadioButton) 3475 bdi.kind = kThemeSmallRadioButton; 3476 else 3477 bdi.kind = kThemeSmallCheckBox; 3478 break; 3479 } 3480 if (opt->state & State_NoChange) 3481 bdi.value = kThemeButtonMixed; 3482 else if (opt->state & State_On) 3483 bdi.value = kThemeButtonOn; 3484 else 3485 bdi.value = kThemeButtonOff; 3486 HIRect macRect = qt_hirectForQRect(opt->rect); 3487 if (!drawColorless) 3488 HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); 3489 else 3490 d->drawColorlessButton(macRect, &bdi, p, opt); 3491 break; } 3492 case PE_FrameFocusRect: 3493 // Use the our own focus widget stuff. 3494 break; 3495 case PE_IndicatorBranch: { 3496 if (!(opt->state & State_Children)) 3497 break; 3498 if (!d->indicatorBranchButtonCell) 3499 const_cast<QMacStylePrivate *>(d)->indicatorBranchButtonCell = (void *)[[NSButtonCell alloc] init]; 3500 NSButtonCell *triangleCell = (NSButtonCell *)d->indicatorBranchButtonCell; 3501 [triangleCell setButtonType:NSOnOffButton]; 3502 [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; 3503 [triangleCell setBezelStyle:NSDisclosureBezelStyle]; 3504 bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); 3505 [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; 3506 3507 CGContextSaveGState(cg); 3508 [NSGraphicsContext saveGraphicsState]; 3509 3510 [NSGraphicsContext setCurrentContext:[NSGraphicsContext 3511 graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; 3512 3513 QRect qtRect = opt->rect.adjusted(DisclosureOffset, 0, -DisclosureOffset, 0); 3514 CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); 3515 CGContextTranslateCTM(cg, rect.origin.x, rect.origin.y + rect.size.height); 3516 CGContextScaleCTM(cg, 1, -1); 3517 CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y); 3518 3519 [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; 3520 3521 [NSGraphicsContext restoreGraphicsState]; 3522 CGContextRestoreGState(cg); 3523 break; } 3524 3525 case PE_Frame: { 3526 QPen oldPen = p->pen(); 3527 p->setPen(opt->palette.base().color().darker(140)); 3528 p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); 3529 p->setPen(opt->palette.base().color().darker(180)); 3530 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 3531 p->setPen(oldPen); 3532 break; } 3533 3534 case PE_FrameLineEdit: 3535 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { 3536 if (frame->state & State_Sunken) { 3537 QColor baseColor(frame->palette.background().color()); 3538 HIThemeFrameDrawInfo fdi; 3539 fdi.version = qt_mac_hitheme_version; 3540 fdi.state = tds; 3541 SInt32 frame_size; 3542 fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : 3543 kHIThemeFrameTextFieldSquare; 3544 GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); 3545 if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) 3546 fdi.state = kThemeStateInactive; 3547 else if (fdi.state == kThemeStatePressed) 3548 // This pressed state doesn't make sense for a line edit frame. 3549 // And Yosemite agrees with us. Otherwise it starts showing yellow pixels. 3550 fdi.state = kThemeStateActive; 3551 fdi.isFocused = (frame->state & State_HasFocus); 3552 int lw = frame->lineWidth; 3553 if (lw <= 0) 3554 lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w); 3555 { //clear to base color 3556 p->save(); 3557 p->setPen(QPen(baseColor, lw)); 3558 p->setBrush(Qt::NoBrush); 3559 p->drawRect(frame->rect); 3560 p->restore(); 3561 } 3562 HIRect hirect = qt_hirectForQRect(frame->rect, 3563 QRect(frame_size, frame_size, 3564 frame_size * 2, frame_size * 2)); 3565 3566 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); 3567 } else { 3548 3549 default: 3568 3550 QCommonStyle::drawPrimitive(pe, opt, p, w); 3569 } 3570 } 3571 break; 3572 case PE_PanelLineEdit: 3573 QCommonStyle::drawPrimitive(pe, opt, p, w); 3574 // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). 3575 // Focus frame is drawn outside the rectangle passed in the option-rect. 3576 if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { 3577 #if QT_CONFIG(lineedit) 3578 if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) { 3579 int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); 3580 int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); 3581 QStyleOptionFrame focusFrame = *panel; 3582 focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); 3583 drawControl(CE_FocusFrame, &focusFrame, p, w); 3584 } 3585 #endif 3586 } 3587 3588 break; 3589 #if QT_CONFIG(tabwidget) 3590 case PE_FrameTabWidget: 3591 if (const QStyleOptionTabWidgetFrame *twf 3592 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 3593 HIRect hirect = qt_hirectForQRect(twf->rect); 3594 HIThemeTabPaneDrawInfo tpdi; 3595 tpdi.version = qt_mac_hitheme_tab_version(); 3596 tpdi.state = tds; 3597 tpdi.direction = getTabDirection(twf->shape); 3598 tpdi.size = kHIThemeTabSizeNormal; 3599 tpdi.kind = kHIThemeTabKindNormal; 3600 tpdi.adornment = kHIThemeTabPaneAdornmentNormal; 3601 HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); 3602 } 3603 break; 3604 #endif 3605 case PE_PanelScrollAreaCorner: { 3606 const QBrush brush(opt->palette.brush(QPalette::Base)); 3607 p->fillRect(opt->rect, brush); 3608 p->setPen(QPen(QColor(217, 217, 217))); 3609 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 3610 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 3611 } break; 3612 case PE_FrameStatusBarItem: 3613 break; 3614 case PE_IndicatorTabClose: { 3615 // Make close button visible only on the hovered tab. 3616 if (QTabBar *tabBar = qobject_cast<QTabBar*>(w->parentWidget())) { 3617 const bool documentMode = tabBar->documentMode(); 3618 const QTabBarPrivate *tabBarPrivate = static_cast<QTabBarPrivate *>(QObjectPrivate::get(tabBar)); 3619 const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex(); 3620 if (!documentMode || 3621 (hoveredTabIndex != -1 && ((w == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || 3622 (w == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { 3623 const bool hover = (opt->state & State_MouseOver); 3624 const bool selected = (opt->state & State_Selected); 3625 const bool pressed = (opt->state & State_Sunken); 3626 drawTabCloseButton(p, hover, selected, pressed, documentMode); 3627 } 3628 } 3629 } break; 3630 case PE_PanelStatusBar: { 3631 // Fill the status bar with the titlebar gradient. 3632 QLinearGradient linearGrad; 3633 if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) { 3634 linearGrad = titlebarGradientActive(); 3635 } else { 3636 linearGrad = titlebarGradientInactive(); 3551 break; 3637 3552 } 3638 3639 linearGrad.setStart(0, opt->rect.top());3640 linearGrad.setFinalStop(0, opt->rect.bottom());3641 p->fillRect(opt->rect, linearGrad);3642 3643 // Draw the black separator line at the top of the status bar.3644 if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active))3645 p->setPen(titlebarSeparatorLineActive);3646 else3647 p->setPen(titlebarSeparatorLineInactive);3648 p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top());3649 3650 break;3651 }3652 3653 default:3654 QCommonStyle::drawPrimitive(pe, opt, p, w);3655 break;3656 3553 } 3657 } 3658 3659 static inline QPixmap darkenPixmap(const QPixmap &pixmap) 3660 { 3661 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);3662 int imgh = img.height();3663 int imgw = img.width();3664 int h, s, v, a;3665 QRgb pixel;3666 for (int y = 0; y < imgh; ++y) {3667 for (int x = 0; x < imgw; ++x) {3668 pixel = img.pixel(x, y);3669 a = qAlpha(pixel);3670 QColor hsvColor(pixel);3671 hsvColor.getHsv(&h, &s, &v);3672 s = qMin(100, s * 2);3673 v = v / 2;3674 hsvColor.setHsv(h, s, v);3675 pixel = hsvColor.rgb();3676 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a));3554 3555 static inline QPixmap darkenPixmap(const QPixmap &pixmap) 3556 { 3557 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); 3558 int imgh = img.height(); 3559 int imgw = img.width(); 3560 int h, s, v, a; 3561 QRgb pixel; 3562 for (int y = 0; y < imgh; ++y) { 3563 for (int x = 0; x < imgw; ++x) { 3564 pixel = img.pixel(x, y); 3565 a = qAlpha(pixel); 3566 QColor hsvColor(pixel); 3567 hsvColor.getHsv(&h, &s, &v); 3568 s = qMin(100, s * 2); 3569 v = v / 2; 3570 hsvColor.setHsv(h, s, v); 3571 pixel = hsvColor.rgb(); 3572 img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a)); 3573 } 3677 3574 } 3575 return QPixmap::fromImage(img); 3678 3576 } 3679 return QPixmap::fromImage(img); 3680 } 3681 3682 3683 3684 void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, 3685 const QWidget *w) const 3686 { 3687 Q_D(const QMacStyle); 3688 ThemeDrawState tds = d->getDrawState(opt->state); 3689 QMacCGContext cg(p); 3690 QWindow *window = w && w->window() ? w->window()->windowHandle() : 3691 QStyleHelper::styleObjectWindow(opt->styleObject); 3692 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 3693 switch (ce) { 3694 case CE_HeaderSection: 3695 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3696 HIThemeButtonDrawInfo bdi; 3697 bdi.version = qt_mac_hitheme_version; 3698 State flags = header->state; 3699 QRect ir = header->rect; 3700 bdi.kind = kThemeListHeaderButton; 3701 bdi.adornment = kThemeAdornmentNone; 3702 bdi.state = kThemeStateActive; 3703 3704 if (flags & State_On) 3705 bdi.value = kThemeButtonOn; 3706 else 3707 bdi.value = kThemeButtonOff; 3708 3709 if (header->orientation == Qt::Horizontal){ 3710 switch (header->position) { 3711 case QStyleOptionHeader::Beginning: 3712 ir.adjust(-1, -1, 0, 0); 3713 break; 3714 case QStyleOptionHeader::Middle: 3715 ir.adjust(-1, -1, 0, 0); 3716 break; 3717 case QStyleOptionHeader::OnlyOneSection: 3718 case QStyleOptionHeader::End: 3719 ir.adjust(-1, -1, 1, 0); 3720 break; 3721 default: 3722 break; 3577 3578 3579 3580 void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, 3581 const QWidget *w) const 3582 { 3583 Q_D(const QMacStyle); 3584 ThemeDrawState tds = d->getDrawState(opt->state); 3585 QMacCGContext cg(p); 3586 QWindow *window = w && w->window() ? w->window()->windowHandle() : 3587 QStyleHelper::styleObjectWindow(opt->styleObject); 3588 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 3589 const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; 3590 switch (ce) { 3591 case CE_HeaderSection: 3592 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3593 HIThemeButtonDrawInfo bdi; 3594 bdi.version = qt_mac_hitheme_version; 3595 State flags = header->state; 3596 QRect ir = header->rect; 3597 bdi.kind = kThemeListHeaderButton; 3598 bdi.adornment = kThemeAdornmentNone; 3599 bdi.state = kThemeStateActive; 3600 3601 if (flags & State_On) 3602 bdi.value = kThemeButtonOn; 3603 else 3604 bdi.value = kThemeButtonOff; 3605 3606 if (header->orientation == Qt::Horizontal){ 3607 switch (header->position) { 3608 case QStyleOptionHeader::Beginning: 3609 ir.adjust(-1, -1, 0, 0); 3610 break; 3611 case QStyleOptionHeader::Middle: 3612 ir.adjust(-1, -1, 0, 0); 3613 break; 3614 case QStyleOptionHeader::OnlyOneSection: 3615 case QStyleOptionHeader::End: 3616 ir.adjust(-1, -1, 1, 0); 3617 break; 3618 default: 3619 break; 3620 } 3621 3622 if (header->position != QStyleOptionHeader::Beginning 3623 && header->position != QStyleOptionHeader::OnlyOneSection) { 3624 bdi.adornment = header->direction == Qt::LeftToRight 3625 ? kThemeAdornmentHeaderButtonLeftNeighborSelected 3626 : kThemeAdornmentHeaderButtonRightNeighborSelected; 3627 } 3628 } 3629 3630 if (flags & State_Active) { 3631 if (!(flags & State_Enabled)) 3632 bdi.state = kThemeStateUnavailable; 3633 else if (flags & State_Sunken) 3634 bdi.state = kThemeStatePressed; 3635 } else { 3636 if (flags & State_Enabled) 3637 bdi.state = kThemeStateInactive; 3638 else 3639 bdi.state = kThemeStateUnavailableInactive; 3640 } 3641 3642 if (header->sortIndicator != QStyleOptionHeader::None) { 3643 bdi.value = kThemeButtonOn; 3644 if (header->sortIndicator == QStyleOptionHeader::SortDown) 3645 bdi.adornment = kThemeAdornmentHeaderButtonSortUp; 3646 } 3647 if (flags & State_HasFocus) 3648 bdi.adornment = kThemeAdornmentFocus; 3649 3650 ir = visualRect(header->direction, header->rect, ir); 3651 HIRect bounds = qt_hirectForQRect(ir); 3652 3653 bool noVerticalHeader = true; 3654 #ifndef QT_NO_TABLEVIEW 3655 if (w) 3656 if (const QTableView *table = qobject_cast<const QTableView *>(w->parentWidget())) 3657 noVerticalHeader = !table->verticalHeader()->isVisible(); 3658 #endif 3659 3660 bool drawTopBorder = header->orientation == Qt::Horizontal; 3661 bool drawLeftBorder = header->orientation == Qt::Vertical 3662 || header->position == QStyleOptionHeader::OnlyOneSection 3663 || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); 3664 d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p); 3723 3665 } 3724 3725 if (header->position != QStyleOptionHeader::Beginning 3726 && header->position != QStyleOptionHeader::OnlyOneSection) { 3727 bdi.adornment = header->direction == Qt::LeftToRight 3728 ? kThemeAdornmentHeaderButtonLeftNeighborSelected 3729 : kThemeAdornmentHeaderButtonRightNeighborSelected; 3666 break; 3667 case CE_HeaderLabel: 3668 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3669 p->save(); 3670 QRect textr = header->rect; 3671 if (!header->icon.isNull()) { 3672 QIcon::Mode mode = QIcon::Disabled; 3673 if (opt->state & State_Enabled) 3674 mode = QIcon::Normal; 3675 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 3676 QPixmap pixmap = header->icon.pixmap(window, QSize(iconExtent, iconExtent), mode); 3677 3678 QRect pixr = header->rect; 3679 pixr.setY(header->rect.center().y() - (pixmap.height() / pixmap.devicePixelRatio() - 1) / 2); 3680 proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); 3681 textr.translate(pixmap.width() / pixmap.devicePixelRatio() + 2, 0); 3682 } 3683 3684 proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette, 3685 header->state & State_Enabled, header->text, QPalette::ButtonText); 3686 p->restore(); 3730 3687 } 3731 } 3732 3733 if (flags & State_Active) { 3734 if (!(flags & State_Enabled)) 3735 bdi.state = kThemeStateUnavailable; 3736 else if (flags & State_Sunken) 3737 bdi.state = kThemeStatePressed; 3738 } else { 3739 if (flags & State_Enabled) 3740 bdi.state = kThemeStateInactive; 3741 else 3742 bdi.state = kThemeStateUnavailableInactive; 3743 } 3744 3745 if (header->sortIndicator != QStyleOptionHeader::None) { 3746 bdi.value = kThemeButtonOn; 3747 if (header->sortIndicator == QStyleOptionHeader::SortDown) 3748 bdi.adornment = kThemeAdornmentHeaderButtonSortUp; 3749 } 3750 if (flags & State_HasFocus) 3751 bdi.adornment = kThemeAdornmentFocus; 3752 3753 ir = visualRect(header->direction, header->rect, ir); 3754 HIRect bounds = qt_hirectForQRect(ir); 3755 3756 bool noVerticalHeader = true; 3757 #if QT_CONFIG(tableview) 3758 if (w) 3759 if (const QTableView *table = qobject_cast<const QTableView *>(w->parentWidget())) 3760 noVerticalHeader = !table->verticalHeader()->isVisible(); 3761 #endif 3762 3763 bool drawTopBorder = header->orientation == Qt::Horizontal; 3764 bool drawLeftBorder = header->orientation == Qt::Vertical 3765 || header->position == QStyleOptionHeader::OnlyOneSection 3766 || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); 3767 d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p); 3768 } 3769 break; 3770 case CE_HeaderLabel: 3771 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 3772 p->save(); 3773 QRect textr = header->rect; 3774 if (!header->icon.isNull()) { 3775 QIcon::Mode mode = QIcon::Disabled; 3776 if (opt->state & State_Enabled) 3777 mode = QIcon::Normal; 3778 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 3779 QPixmap pixmap = header->icon.pixmap(window, QSize(iconExtent, iconExtent), mode); 3780 3781 QRect pixr = header->rect; 3782 pixr.setY(header->rect.center().y() - (pixmap.height() / pixmap.devicePixelRatio() - 1) / 2); 3783 proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); 3784 textr.translate(pixmap.width() / pixmap.devicePixelRatio() + 2, 0); 3785 } 3786 3787 proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette, 3788 header->state & State_Enabled, header->text, QPalette::ButtonText); 3789 p->restore(); 3790 } 3791 break; 3792 case CE_ToolButtonLabel: 3793 if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { 3794 QStyleOptionToolButton myTb = *tb; 3795 myTb.state &= ~State_AutoRaise; 3688 break; 3689 case CE_ToolButtonLabel: 3690 if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { 3691 QStyleOptionToolButton myTb = *tb; 3692 myTb.state &= ~State_AutoRaise; 3796 3693 #ifndef QT_NO_ACCESSIBILITY 3797 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { 3798 QRect cr = tb->rect; 3799 int shiftX = 0; 3800 int shiftY = 0; 3801 bool needText = false; 3802 int alignment = 0; 3803 bool down = tb->state & (State_Sunken | State_On); 3804 if (down) { 3805 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w); 3806 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w); 3807 } 3808 // The down state is special for QToolButtons in a toolbar on the Mac 3809 // The text is a bit bolder and gets a drop shadow and the icons are also darkened. 3810 // This doesn't really fit into any particular case in QIcon, so we 3811 // do the majority of the work ourselves. 3812 if (!(tb->features & QStyleOptionToolButton::Arrow)) { 3813 Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; 3814 if (tb->icon.isNull() && !tb->text.isEmpty()) 3815 tbstyle = Qt::ToolButtonTextOnly; 3816 3817 switch (tbstyle) { 3818 case Qt::ToolButtonTextOnly: { 3819 needText = true; 3820 alignment = Qt::AlignCenter; 3821 break; } 3822 case Qt::ToolButtonIconOnly: 3823 case Qt::ToolButtonTextBesideIcon: 3824 case Qt::ToolButtonTextUnderIcon: { 3825 QRect pr = cr; 3826 QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal 3827 : QIcon::Disabled; 3828 QIcon::State iconState = (tb->state & State_On) ? QIcon::On 3829 : QIcon::Off; 3830 QPixmap pixmap = tb->icon.pixmap(window, 3831 tb->rect.size().boundedTo(tb->iconSize), 3832 iconMode, iconState); 3833 3834 // Draw the text if it's needed. 3835 if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { 3836 needText = true; 3837 if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { 3838 pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6); 3839 cr.adjust(0, pr.bottom(), 0, -3); 3840 alignment |= Qt::AlignCenter; 3841 } else { 3842 pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8); 3843 cr.adjust(pr.right(), 0, 0, 0); 3844 alignment |= Qt::AlignLeft | Qt::AlignVCenter; 3845 } 3694 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { 3695 QRect cr = tb->rect; 3696 int shiftX = 0; 3697 int shiftY = 0; 3698 bool needText = false; 3699 int alignment = 0; 3700 bool down = tb->state & (State_Sunken | State_On); 3701 if (down) { 3702 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w); 3703 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w); 3846 3704 } 3847 if (opt->state & State_Sunken) { 3848 pr.translate(shiftX, shiftY); 3849 pixmap = darkenPixmap(pixmap); 3850 } 3851 proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); 3852 break; } 3853 default: 3854 Q_ASSERT(false); 3855 break; 3856 } 3857 3858 if (needText) { 3859 QPalette pal = tb->palette; 3860 QPalette::ColorRole role = QPalette::NoRole; 3861 if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w)) 3862 alignment |= Qt::TextHideMnemonic; 3863 if (down) 3864 cr.translate(shiftX, shiftY); 3865 if (tbstyle == Qt::ToolButtonTextOnly 3866 || (tbstyle != Qt::ToolButtonTextOnly && !down)) { 3867 QPen pen = p->pen(); 3868 QColor light = down ? Qt::black : Qt::white; 3869 light.setAlphaF(0.375f); 3870 p->setPen(light); 3871 p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text); 3872 p->setPen(pen); 3873 if (down && tbstyle == Qt::ToolButtonTextOnly) { 3874 pal = QApplication::palette("QMenu"); 3875 pal.setCurrentColorGroup(tb->palette.currentColorGroup()); 3876 role = QPalette::HighlightedText; 3705 // The down state is special for QToolButtons in a toolbar on the Mac 3706 // The text is a bit bolder and gets a drop shadow and the icons are also darkened. 3707 // This doesn't really fit into any particular case in QIcon, so we 3708 // do the majority of the work ourselves. 3709 if (!(tb->features & QStyleOptionToolButton::Arrow)) { 3710 Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; 3711 if (tb->icon.isNull() && !tb->text.isEmpty()) 3712 tbstyle = Qt::ToolButtonTextOnly; 3713 3714 switch (tbstyle) { 3715 case Qt::ToolButtonTextOnly: { 3716 needText = true; 3717 alignment = Qt::AlignCenter; 3718 break; } 3719 case Qt::ToolButtonIconOnly: 3720 case Qt::ToolButtonTextBesideIcon: 3721 case Qt::ToolButtonTextUnderIcon: { 3722 QRect pr = cr; 3723 QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal 3724 : QIcon::Disabled; 3725 QIcon::State iconState = (tb->state & State_On) ? QIcon::On 3726 : QIcon::Off; 3727 QPixmap pixmap = tb->icon.pixmap(window, 3728 tb->rect.size().boundedTo(tb->iconSize), 3729 iconMode, iconState); 3730 3731 // Draw the text if it's needed. 3732 if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { 3733 needText = true; 3734 if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { 3735 pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6); 3736 cr.adjust(0, pr.bottom(), 0, -3); 3737 alignment |= Qt::AlignCenter; 3738 } else { 3739 pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8); 3740 cr.adjust(pr.right(), 0, 0, 0); 3741 alignment |= Qt::AlignLeft | Qt::AlignVCenter; 3742 } 3743 } 3744 if (opt->state & State_Sunken) { 3745 pr.translate(shiftX, shiftY); 3746 pixmap = darkenPixmap(pixmap); 3747 } 3748 proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); 3749 break; } 3750 default: 3751 Q_ASSERT(false); 3752 break; 3877 3753 } 3754 3755 if (needText) { 3756 QPalette pal = tb->palette; 3757 QPalette::ColorRole role = QPalette::NoRole; 3758 if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w)) 3759 alignment |= Qt::TextHideMnemonic; 3760 if (down) 3761 cr.translate(shiftX, shiftY); 3762 if (tbstyle == Qt::ToolButtonTextOnly 3763 || (tbstyle != Qt::ToolButtonTextOnly && !down)) { 3764 QPen pen = p->pen(); 3765 QColor light = down ? Qt::black : Qt::white; 3766 light.setAlphaF(0.375f); 3767 p->setPen(light); 3768 p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text); 3769 p->setPen(pen); 3770 if (down && tbstyle == Qt::ToolButtonTextOnly) { 3771 pal = QApplication::palette("QMenu"); 3772 pal.setCurrentColorGroup(tb->palette.currentColorGroup()); 3773 role = QPalette::HighlightedText; 3774 } 3775 } 3776 proxy()->drawItemText(p, cr, alignment, pal, 3777 tb->state & State_Enabled, tb->text, role); 3778 } 3779 } else { 3780 QCommonStyle::drawControl(ce, &myTb, p, w); 3878 3781 } 3879 proxy()->drawItemText(p, cr, alignment, pal,3880 tb->state & State_Enabled, tb->text, role);3782 } else { 3783 QCommonStyle::drawControl(ce, &myTb, p, w); 3881 3784 } 3882 } else {3883 QCommonStyle::drawControl(ce, &myTb, p, w);3884 }3885 } else {3886 QCommonStyle::drawControl(ce, &myTb, p, w);3887 }3888 3785 #else 3889 Q_UNUSED(tb)3786 Q_UNUSED(tb) 3890 3787 #endif 3891 } 3892 break; 3893 case CE_ToolBoxTabShape: 3894 QCommonStyle::drawControl(ce, opt, p, w); 3895 break; 3896 case CE_PushButtonBevel: 3897 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 3898 if (!(btn->state & (State_Raised | State_Sunken | State_On))) 3788 } 3899 3789 break; 3900 3901 if (btn->features & QStyleOptionButton::CommandLinkButton) { 3790 case CE_ToolBoxTabShape: 3902 3791 QCommonStyle::drawControl(ce, opt, p, w); 3903 3792 break; 3904 } 3905 3906 // No default button pulsating animation on Yosemite, 3907 // so we have to do few things differently. 3908 3909 // a focused auto-default button within an active window 3910 // takes precedence over a normal default button 3911 if (btn->features & QStyleOptionButton::AutoDefaultButton 3912 && opt->state & State_Active && opt->state & State_HasFocus) { 3913 d->autoDefaultButton = opt->styleObject; 3914 } else if (d->autoDefaultButton == opt->styleObject) { 3915 d->setAutoDefaultButton(0); 3916 } 3917 3918 if (!d->autoDefaultButton) { 3919 if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) { 3920 d->defaultButton = opt->styleObject; 3921 } else if (d->defaultButton == opt->styleObject) { 3922 if (QStyleAnimation *animation = d->animation(opt->styleObject)) { 3923 animation->updateTarget(); 3924 d->stopAnimation(opt->styleObject); 3793 case CE_PushButtonBevel: 3794 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 3795 if (!(btn->state & (State_Raised | State_Sunken | State_On))) 3796 break; 3797 3798 if (btn->features & QStyleOptionButton::CommandLinkButton) { 3799 QCommonStyle::drawControl(ce, opt, p, w); 3800 break; 3925 3801 } 3926 d->defaultButton = 0; 3927 } 3928 } 3929 3930 // TODO: find out the pressed button in a qwidget independent way 3931 extern QWidget *qt_button_down; // qwidgetwindow.cpp 3932 if (opt->styleObject == qt_button_down) 3933 d->pressedButton = opt->styleObject; 3934 else if (d->pressedButton == opt->styleObject) 3935 d->pressedButton = 0; 3936 3937 bool hasMenu = btn->features & QStyleOptionButton::HasMenu; 3938 HIThemeButtonDrawInfo bdi; 3939 d->initHIThemePushButton(btn, w, tds, &bdi); 3940 3941 if (!hasMenu) { 3942 // HITheme is not drawing a nice focus frame around buttons. 3943 // We'll do it ourselves further down. 3944 bdi.adornment &= ~kThemeAdornmentFocus; 3945 3946 // We can't rely on an animation existing to test for the default look. That means a bit 3947 // more logic (notice that the logic is slightly different for the bevel and the label). 3948 if (tds == kThemeStateActive 3949 && (btn->features & QStyleOptionButton::DefaultButton 3950 || (btn->features & QStyleOptionButton::AutoDefaultButton 3951 && d->autoDefaultButton == btn->styleObject))) 3952 bdi.adornment |= kThemeAdornmentDefault; 3953 } 3954 3955 // Unlike Carbon, we want the button to always be drawn inside its bounds. 3956 // Therefore, make the button a bit smaller, so that even if it got focus, 3957 // the focus 'shadow' will be inside. 3958 HIRect newRect = qt_hirectForQRect(btn->rect); 3959 if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) { 3960 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset; 3961 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; 3962 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset; 3963 newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset; 3964 } else if (bdi.kind == kThemePushButtonMini) { 3965 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2; 3966 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; 3967 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; 3968 } 3969 3970 if (hasMenu && bdi.kind != kThemeBevelButton) { 3971 QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); 3972 cw.first = QCocoaPullDownButton; 3973 NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); 3974 [pdb highlight:(bdi.state == kThemeStatePressed)]; 3975 pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; 3976 QRect rect = opt->rect; 3977 rect.adjust(0, 0, cw.second == QAquaSizeSmall ? -4 : cw.second == QAquaSizeMini ? -9 : -6, 0); 3978 d->drawNSViewInRect(cw, pdb, rect, p, w != 0); 3979 } else if (hasMenu && bdi.state == kThemeStatePressed) 3980 d->drawColorlessButton(newRect, &bdi, p, opt); 3981 else 3982 HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); 3983 3984 if (btn->state & State_HasFocus) { 3985 CGRect focusRect = newRect; 3986 if (bdi.kind == kThemePushButton) 3987 focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. 3988 else if (bdi.kind == kThemePushButtonMini) 3989 focusRect.size.height = 15; // Our QPushButton sizes are really weird 3990 3991 if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) { 3992 if (bdi.kind == kThemePushButtonSmall) { 3993 focusRect = CGRectInset(focusRect, -1, 0); 3994 } else if (bdi.kind == kThemePushButtonMini) { 3995 focusRect = CGRectInset(focusRect, 1, 0); 3802 3803 // No default button pulsating animation on Yosemite, 3804 // so we have to do few things differently. 3805 3806 // a focused auto-default button within an active window 3807 // takes precedence over a normal default button 3808 if (btn->features & QStyleOptionButton::AutoDefaultButton 3809 && opt->state & State_Active && opt->state & State_HasFocus) { 3810 if (usingYosemiteOrLater) 3811 d->autoDefaultButton = opt->styleObject; 3812 else 3813 d->setAutoDefaultButton(opt->styleObject); 3814 } else if (d->autoDefaultButton == opt->styleObject) { 3815 d->setAutoDefaultButton(0); 3996 3816 } 3997 } else { 3998 if (bdi.kind == kThemePushButton) { 3999 focusRect = CGRectInset(focusRect, 1, 1); 4000 } else if (bdi.kind == kThemePushButtonSmall) { 4001 focusRect = CGRectInset(focusRect, 0, 2); 3817 3818 if (!d->autoDefaultButton) { 3819 if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) { 3820 d->defaultButton = opt->styleObject; 3821 if (!usingYosemiteOrLater && !d->animation(opt->styleObject)) 3822 d->startAnimation(new QStyleAnimation(opt->styleObject)); 3823 } else if (d->defaultButton == opt->styleObject) { 3824 if (QStyleAnimation *animation = d->animation(opt->styleObject)) { 3825 animation->updateTarget(); 3826 d->stopAnimation(opt->styleObject); 3827 } 3828 d->defaultButton = 0; 3829 } 3830 } 3831 3832 // TODO: find out the pressed button in a qwidget independent way 3833 extern QWidget *qt_button_down; // qwidgetwindow.cpp 3834 if (opt->styleObject == qt_button_down) 3835 d->pressedButton = opt->styleObject; 3836 else if (d->pressedButton == opt->styleObject) 3837 d->pressedButton = 0; 3838 3839 bool hasMenu = btn->features & QStyleOptionButton::HasMenu; 3840 HIThemeButtonDrawInfo bdi; 3841 d->initHIThemePushButton(btn, w, tds, &bdi); 3842 3843 if (usingYosemiteOrLater) { 3844 if (!hasMenu) { 3845 // HITheme is not drawing a nice focus frame around buttons. 3846 // We'll do it ourselves further down. 3847 bdi.adornment &= ~kThemeAdornmentFocus; 3848 3849 // We can't rely on an animation existing to test for the default look. That means a bit 3850 // more logic (notice that the logic is slightly different for the bevel and the label). 3851 if (tds == kThemeStateActive 3852 && (btn->features & QStyleOptionButton::DefaultButton 3853 || (btn->features & QStyleOptionButton::AutoDefaultButton 3854 && d->autoDefaultButton == btn->styleObject))) 3855 bdi.adornment |= kThemeAdornmentDefault; 3856 } 3857 } else { 3858 // the default button animation is paused meanwhile any button 3859 // is pressed or an auto-default button is animated instead 3860 if (QStyleAnimation *defaultAnimation = d->animation(d->defaultButton)) { 3861 if (d->pressedButton || d->autoDefaultButton) { 3862 if (defaultAnimation->state() == QStyleAnimation::Running) { 3863 defaultAnimation->pause(); 3864 defaultAnimation->updateTarget(); 3865 } 3866 } else if (defaultAnimation->state() == QStyleAnimation::Paused) { 3867 defaultAnimation->resume(); 3868 } 3869 } 3870 3871 if (!d->pressedButton) { 3872 QStyleAnimation* animation = d->animation(opt->styleObject); 3873 if (animation && animation->state() == QStyleAnimation::Running) { 3874 bdi.adornment |= kThemeAdornmentDefault; 3875 bdi.animation.time.start = d->defaultButtonStart; 3876 bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); 3877 } 3878 } 3879 } 3880 3881 // Unlike Carbon, we want the button to always be drawn inside its bounds. 3882 // Therefore, make the button a bit smaller, so that even if it got focus, 3883 // the focus 'shadow' will be inside. 3884 HIRect newRect = qt_hirectForQRect(btn->rect); 3885 if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) { 3886 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset; 3887 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; 3888 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset; 3889 newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset; 4002 3890 } else if (bdi.kind == kThemePushButtonMini) { 4003 focusRect = CGRectInset(focusRect, 2, 1); 3891 newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2; 3892 newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; 3893 newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; 3894 } 3895 3896 if (hasMenu && usingYosemiteOrLater && bdi.kind != kThemeBevelButton) { 3897 QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); 3898 cw.first = QCocoaPullDownButton; 3899 NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); 3900 [pdb highlight:(bdi.state == kThemeStatePressed)]; 3901 pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; 3902 QRect rect = opt->rect; 3903 rect.adjust(0, 0, cw.second == QAquaSizeSmall ? -4 : cw.second == QAquaSizeMini ? -9 : -6, 0); 3904 d->drawNSViewInRect(cw, pdb, rect, p, w != 0); 3905 } else if (hasMenu && bdi.state == kThemeStatePressed) 3906 d->drawColorlessButton(newRect, &bdi, p, opt); 3907 else 3908 HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); 3909 3910 if (usingYosemiteOrLater && btn->state & State_HasFocus) { 3911 CGRect focusRect = newRect; 3912 if (bdi.kind == kThemePushButton) 3913 focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. 3914 else if (bdi.kind == kThemePushButtonMini) 3915 focusRect.size.height = 15; // Our QPushButton sizes are really weird 3916 3917 if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) { 3918 if (bdi.kind == kThemePushButtonSmall) { 3919 focusRect = CGRectInset(focusRect, -1, 0); 3920 } else if (bdi.kind == kThemePushButtonMini) { 3921 focusRect = CGRectInset(focusRect, 1, 0); 3922 } 3923 } else { 3924 if (bdi.kind == kThemePushButton) { 3925 focusRect = CGRectInset(focusRect, 1, 1); 3926 } else if (bdi.kind == kThemePushButtonSmall) { 3927 focusRect = CGRectInset(focusRect, 0, 2); 3928 } else if (bdi.kind == kThemePushButtonMini) { 3929 focusRect = CGRectInset(focusRect, 2, 1); 3930 } 3931 } 3932 3933 const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4; 3934 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); 3935 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); 3936 const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height); 3937 d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); 3938 } 3939 3940 if (hasMenu && (!usingYosemiteOrLater || bdi.kind == kThemeBevelButton)) { 3941 int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); 3942 QRect ir = btn->rect; 3943 int arrowXOffset = bdi.kind == kThemePushButton ? 6 : 3944 bdi.kind == kThemePushButtonSmall ? 7 : 8; 3945 int arrowYOffset = bdi.kind == kThemePushButton ? 3 : 3946 bdi.kind == kThemePushButtonSmall ? 1 : 2; 3947 if (!w) { 3948 // adjustment for Qt Quick Controls 3949 arrowYOffset -= ir.top(); 3950 if (bdi.kind == kThemePushButtonSmall) 3951 arrowYOffset += 1; 3952 } 3953 QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset, 3954 ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2); 3955 ar = visualRect(btn->direction, ir, ar); 3956 HIRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height()); 3957 3958 HIThemePopupArrowDrawInfo pdi; 3959 pdi.version = qt_mac_hitheme_version; 3960 pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; 3961 pdi.orientation = kThemeArrowDown; 3962 if (bdi.kind == kThemePushButtonMini) 3963 pdi.size = kThemeArrow5pt; 3964 else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) 3965 pdi.size = kThemeArrow7pt; 3966 HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); 4004 3967 } 4005 3968 } 4006 4007 const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4; 4008 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); 4009 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); 4010 const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height); 4011 d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); 4012 } 4013 4014 if (hasMenu && bdi.kind == kThemeBevelButton) { 4015 int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); 4016 QRect ir = btn->rect; 4017 int arrowXOffset = bdi.kind == kThemePushButton ? 6 : 4018 bdi.kind == kThemePushButtonSmall ? 7 : 8; 4019 int arrowYOffset = bdi.kind == kThemePushButton ? 3 : 4020 bdi.kind == kThemePushButtonSmall ? 1 : 2; 4021 if (!w) { 4022 // adjustment for Qt Quick Controls 4023 arrowYOffset -= ir.top(); 4024 if (bdi.kind == kThemePushButtonSmall) 4025 arrowYOffset += 1; 4026 } 4027 QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset, 4028 ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2); 4029 ar = visualRect(btn->direction, ir, ar); 4030 HIRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height()); 4031 4032 HIThemePopupArrowDrawInfo pdi; 4033 pdi.version = qt_mac_hitheme_version; 4034 pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; 4035 pdi.orientation = kThemeArrowDown; 4036 if (bdi.kind == kThemePushButtonMini) 4037 pdi.size = kThemeArrow5pt; 4038 else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) 4039 pdi.size = kThemeArrow7pt; 4040 HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); 4041 } 4042 } 4043 break; 4044 case CE_PushButtonLabel: 4045 if (const QStyleOptionButton *b = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 4046 QStyleOptionButton btn(*b); 4047 // We really don't want the label to be drawn the same as on 4048 // windows style if it has an icon and text, then it should be more like a 4049 // tab. So, cheat a little here. However, if it *is* only an icon 4050 // the windows style works great, so just use that implementation. 4051 bool hasMenu = btn.features & QStyleOptionButton::HasMenu; 4052 bool hasIcon = !btn.icon.isNull(); 4053 bool hasText = !btn.text.isEmpty(); 4054 4055 if (!hasMenu) { 4056 if (tds == kThemeStatePressed 4057 || (tds == kThemeStateActive 4058 && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) 4059 || d->autoDefaultButton == btn.styleObject))) 4060 btn.palette.setColor(QPalette::ButtonText, Qt::white); 4061 } 4062 4063 if (!hasIcon && !hasMenu) { 4064 // ### this is really overly difficult, simplify. 4065 // It basically tries to get the right font for "small" and "mini" icons. 4066 QFont oldFont = p->font(); 4067 QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont()); 4068 ThemeFontID themeId = kThemePushButtonFont; 4069 if (oldFont == newFont) { // Yes, use HITheme to draw the text for small sizes. 4070 switch (d->aquaSizeConstrain(opt, w)) { 4071 default: 4072 break; 4073 case QAquaSizeSmall: 4074 themeId = kThemeSmallSystemFont; 4075 break; 4076 case QAquaSizeMini: 4077 themeId = kThemeMiniSystemFont; 4078 break; 3969 break; 3970 case CE_PushButtonLabel: 3971 if (const QStyleOptionButton *b = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 3972 QStyleOptionButton btn(*b); 3973 // We really don't want the label to be drawn the same as on 3974 // windows style if it has an icon and text, then it should be more like a 3975 // tab. So, cheat a little here. However, if it *is* only an icon 3976 // the windows style works great, so just use that implementation. 3977 bool hasMenu = btn.features & QStyleOptionButton::HasMenu; 3978 bool hasIcon = !btn.icon.isNull(); 3979 bool hasText = !btn.text.isEmpty(); 3980 3981 if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { 3982 if (tds == kThemeStatePressed 3983 || (tds == kThemeStateActive 3984 && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) 3985 || d->autoDefaultButton == btn.styleObject))) 3986 btn.palette.setColor(QPalette::ButtonText, Qt::white); 3987 } 3988 3989 if (!hasIcon && !hasMenu) { 3990 // ### this is really overly difficult, simplify. 3991 // It basically tries to get the right font for "small" and "mini" icons. 3992 QFont oldFont = p->font(); 3993 QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont()); 3994 ThemeFontID themeId = kThemePushButtonFont; 3995 if (oldFont == newFont) { // Yes, use HITheme to draw the text for small sizes. 3996 switch (d->aquaSizeConstrain(opt, w)) { 3997 default: 3998 break; 3999 case QAquaSizeSmall: 4000 themeId = kThemeSmallSystemFont; 4001 break; 4002 case QAquaSizeMini: 4003 themeId = kThemeMiniSystemFont; 4004 break; 4005 } 4006 } 4007 4008 if (themeId == kThemePushButtonFont) { 4009 QCommonStyle::drawControl(ce, &btn, p, w); 4010 } else { 4011 p->save(); 4012 CGContextSetShouldAntialias(cg, true); 4013 CGContextSetShouldSmoothFonts(cg, true); 4014 HIThemeTextInfo tti; 4015 tti.version = qt_mac_hitheme_version; 4016 tti.state = tds; 4017 QColor textColor; 4018 textColor = btn.palette.buttonText().color(); 4019 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 4020 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 4021 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 4022 CGContextSetFillColor(cg, colorComp); 4023 tti.fontID = themeId; 4024 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 4025 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 4026 tti.options = kHIThemeTextBoxOptionNone; 4027 tti.truncationPosition = kHIThemeTextTruncationNone; 4028 tti.truncationMaxLines = 1 + btn.text.count(QLatin1Char('\n')); 4029 QCFString buttonText = qt_mac_removeMnemonics(btn.text); 4030 QRect r = btn.rect; 4031 HIRect bounds = qt_hirectForQRect(r); 4032 HIThemeDrawTextBox(buttonText, &bounds, &tti, 4033 cg, kHIThemeOrientationNormal); 4034 p->restore(); 4035 } 4036 } else { 4037 if (hasIcon && !hasText) { 4038 QCommonStyle::drawControl(ce, &btn, p, w); 4039 } else { 4040 QRect freeContentRect = btn.rect; 4041 QRect textRect = itemTextRect( 4042 btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); 4043 if (hasMenu) { 4044 textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls 4045 } 4046 // Draw the icon: 4047 if (hasIcon) { 4048 int contentW = textRect.width(); 4049 if (hasMenu) 4050 contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; 4051 QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled; 4052 if (mode == QIcon::Normal && btn.state & State_HasFocus) 4053 mode = QIcon::Active; 4054 // Decide if the icon is should be on or off: 4055 QIcon::State state = QIcon::Off; 4056 if (btn.state & State_On) 4057 state = QIcon::On; 4058 QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state); 4059 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); 4060 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); 4061 contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding; 4062 int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; 4063 int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2; 4064 QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight); 4065 QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect); 4066 proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); 4067 int newOffset = iconDestRect.x() + iconDestRect.width() 4068 + QMacStylePrivate::PushButtonContentPadding - textRect.x(); 4069 textRect.adjust(newOffset, 0, newOffset, 0); 4070 } 4071 // Draw the text: 4072 if (hasText) { 4073 textRect = visualRect(btn.direction, freeContentRect, textRect); 4074 proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, 4075 (btn.state & State_Enabled), btn.text, QPalette::ButtonText); 4076 } 4077 } 4079 4078 } 4080 4079 } 4081 4082 if (themeId == kThemePushButtonFont) { 4083 QCommonStyle::drawControl(ce, &btn, p, w); 4084 } else { 4085 p->save(); 4086 CGContextSetShouldAntialias(cg, true); 4087 CGContextSetShouldSmoothFonts(cg, true); 4088 HIThemeTextInfo tti; 4089 tti.version = qt_mac_hitheme_version; 4090 tti.state = tds; 4091 QColor textColor; 4092 textColor = btn.palette.buttonText().color(); 4093 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 4094 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 4095 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 4096 CGContextSetFillColor(cg, colorComp); 4097 tti.fontID = themeId; 4098 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 4099 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 4100 tti.options = kHIThemeTextBoxOptionNone; 4101 tti.truncationPosition = kHIThemeTextTruncationNone; 4102 tti.truncationMaxLines = 1 + btn.text.count(QLatin1Char('\n')); 4103 QCFString buttonText = qt_mac_removeMnemonics(btn.text); 4104 QRect r = btn.rect; 4105 HIRect bounds = qt_hirectForQRect(r); 4106 HIThemeDrawTextBox(buttonText, &bounds, &tti, 4107 cg, kHIThemeOrientationNormal); 4108 p->restore(); 4080 break; 4081 case CE_ComboBoxLabel: 4082 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 4083 QStyleOptionComboBox comboCopy = *cb; 4084 comboCopy.direction = Qt::LeftToRight; 4085 if (opt->state & QStyle::State_Small) 4086 comboCopy.rect.translate(0, w ? 0 : (QSysInfo::macVersion() >= QSysInfo::MV_10_10 ? 0 : -2)); // Supports Qt Quick Controls 4087 else if (QSysInfo::macVersion() == QSysInfo::MV_10_9) 4088 comboCopy.rect.translate(0, 1); 4089 QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); 4109 4090 } 4110 } else { 4111 if (hasIcon && !hasText) { 4112 QCommonStyle::drawControl(ce, &btn, p, w); 4113 } else { 4114 QRect freeContentRect = btn.rect; 4115 QRect textRect = itemTextRect( 4116 btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); 4117 if (hasMenu) { 4118 textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls 4119 } 4120 // Draw the icon: 4121 if (hasIcon) { 4122 int contentW = textRect.width(); 4123 if (hasMenu) 4124 contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; 4125 QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled; 4126 if (mode == QIcon::Normal && btn.state & State_HasFocus) 4127 mode = QIcon::Active; 4128 // Decide if the icon is should be on or off: 4129 QIcon::State state = QIcon::Off; 4130 if (btn.state & State_On) 4131 state = QIcon::On; 4132 QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state); 4133 int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); 4134 int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); 4135 contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding; 4136 int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; 4137 int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2; 4138 QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight); 4139 QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect); 4140 proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); 4141 int newOffset = iconDestRect.x() + iconDestRect.width() 4142 + QMacStylePrivate::PushButtonContentPadding - textRect.x(); 4143 textRect.adjust(newOffset, 0, newOffset, 0); 4091 break; 4092 #ifndef QT_NO_TABBAR 4093 case CE_TabBarTabShape: 4094 if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) { 4095 4096 if (tabOpt->documentMode) { 4097 p->save(); 4098 bool isUnified = false; 4099 if (w) { 4100 QRect tabRect = tabOpt->rect; 4101 QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft()); 4102 isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y()); 4103 } 4104 4105 drawTabShape(p, tabOpt, isUnified); 4106 p->restore(); 4107 return; 4144 4108 } 4145 // Draw the text: 4146 if (hasText) { 4147 textRect = visualRect(btn.direction, freeContentRect, textRect); 4148 proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, 4149 (btn.state & State_Enabled), btn.text, QPalette::ButtonText); 4109 4110 HIThemeTabDrawInfo tdi; 4111 tdi.version = 1; 4112 tdi.style = kThemeTabNonFront; 4113 tdi.direction = getTabDirection(tabOpt->shape); 4114 switch (d->aquaSizeConstrain(opt, w)) { 4115 default: 4116 case QAquaSizeUnknown: 4117 case QAquaSizeLarge: 4118 tdi.size = kHIThemeTabSizeNormal; 4119 break; 4120 case QAquaSizeSmall: 4121 tdi.size = kHIThemeTabSizeSmall; 4122 break; 4123 case QAquaSizeMini: 4124 tdi.size = kHIThemeTabSizeMini; 4125 break; 4150 4126 } 4151 } 4152 } 4153 } 4154 break; 4155 case CE_ComboBoxLabel: 4156 if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 4157 QStyleOptionComboBox comboCopy = *cb; 4158 comboCopy.direction = Qt::LeftToRight; 4159 QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); 4160 } 4161 break; 4162 #if QT_CONFIG(tabbar) 4163 case CE_TabBarTabShape: 4164 if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) { 4165 if (tabOpt->documentMode) { 4166 p->save(); 4167 bool isUnified = false; 4168 if (w) { 4127 bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast; 4169 4128 QRect tabRect = tabOpt->rect; 4170 QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft()); 4171 isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y()); 4129 4130 bool selected = tabOpt->state & State_Selected; 4131 if (selected) { 4132 if (!(tabOpt->state & State_Active)) 4133 tdi.style = kThemeTabFrontUnavailable; 4134 else if (!(tabOpt->state & State_Enabled)) 4135 tdi.style = kThemeTabFrontInactive; 4136 else 4137 tdi.style = kThemeTabFront; 4138 } else if (!(tabOpt->state & State_Active)) { 4139 tdi.style = kThemeTabNonFrontUnavailable; 4140 } else if (!(tabOpt->state & State_Enabled)) { 4141 tdi.style = kThemeTabNonFrontInactive; 4142 } else if (tabOpt->state & State_Sunken) { 4143 tdi.style = kThemeTabNonFrontPressed; 4144 } 4145 if (tabOpt->state & State_HasFocus) 4146 tdi.adornment = kHIThemeTabAdornmentFocus; 4147 else 4148 tdi.adornment = kHIThemeTabAdornmentNone; 4149 tdi.kind = kHIThemeTabKindNormal; 4150 4151 if (!usingYosemiteOrLater) { 4152 if (!verticalTabs) 4153 tabRect.setY(tabRect.y() - 1); 4154 else 4155 tabRect.setX(tabRect.x() - 1); 4156 } 4157 QStyleOptionTab::TabPosition tp = tabOpt->position; 4158 QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; 4159 if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { 4160 if (sp == QStyleOptionTab::NextIsSelected) 4161 sp = QStyleOptionTab::PreviousIsSelected; 4162 else if (sp == QStyleOptionTab::PreviousIsSelected) 4163 sp = QStyleOptionTab::NextIsSelected; 4164 switch (tp) { 4165 case QStyleOptionTab::Beginning: 4166 tp = QStyleOptionTab::End; 4167 break; 4168 case QStyleOptionTab::End: 4169 tp = QStyleOptionTab::Beginning; 4170 break; 4171 default: 4172 break; 4173 } 4174 } 4175 bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22); 4176 4177 switch (tp) { 4178 case QStyleOptionTab::Beginning: 4179 tdi.position = kHIThemeTabPositionFirst; 4180 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) 4181 tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; 4182 break; 4183 case QStyleOptionTab::Middle: 4184 tdi.position = kHIThemeTabPositionMiddle; 4185 if (selected) 4186 tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; 4187 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected. 4188 tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; 4189 break; 4190 case QStyleOptionTab::End: 4191 tdi.position = kHIThemeTabPositionLast; 4192 if (selected) 4193 tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; 4194 break; 4195 case QStyleOptionTab::OnlyOneTab: 4196 tdi.position = kHIThemeTabPositionOnly; 4197 break; 4198 } 4199 // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. 4200 if (stretchTabs) { 4201 HIRect hirect = CGRectMake(0, 0, 23, 23); 4202 QPixmap pm(23, 23); 4203 pm.fill(Qt::transparent); 4204 { 4205 QMacCGContext pmcg(&pm); 4206 HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0); 4207 } 4208 QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7); 4209 } else { 4210 HIRect hirect = qt_hirectForQRect(tabRect); 4211 HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0); 4212 } 4172 4213 } 4173 4174 const int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, opt, w);4175 drawTabShape(p, tabOpt, isUnified, tabOverlap);4176 4177 p->restore();4178 return;4179 }4180 4181 HIThemeTabDrawInfo tdi;4182 tdi.version = 1;4183 tdi.style = kThemeTabNonFront;4184 tdi.direction = getTabDirection(tabOpt->shape);4185 switch (d->aquaSizeConstrain(opt, w)) {4186 default:4187 case QAquaSizeUnknown:4188 case QAquaSizeLarge:4189 tdi.size = kHIThemeTabSizeNormal;4190 break;4191 case QAquaSizeSmall:4192 tdi.size = kHIThemeTabSizeSmall;4193 break;4194 case QAquaSizeMini:4195 tdi.size = kHIThemeTabSizeMini;4196 4214 break; 4197 } 4198 bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast; 4199 QRect tabRect = tabOpt->rect; 4200 4201 bool selected = tabOpt->state & State_Selected; 4202 if (selected) { 4203 if (!(tabOpt->state & State_Active)) 4204 tdi.style = kThemeTabFrontUnavailable; 4205 else if (!(tabOpt->state & State_Enabled)) 4206 tdi.style = kThemeTabFrontInactive; 4207 else 4208 tdi.style = kThemeTabFront; 4209 } else if (!(tabOpt->state & State_Active)) { 4210 tdi.style = kThemeTabNonFrontUnavailable; 4211 } else if (!(tabOpt->state & State_Enabled)) { 4212 tdi.style = kThemeTabNonFrontInactive; 4213 } else if (tabOpt->state & State_Sunken) { 4214 tdi.style = kThemeTabNonFrontPressed; 4215 } 4216 if (tabOpt->state & State_HasFocus) 4217 tdi.adornment = kHIThemeTabAdornmentFocus; 4218 else 4219 tdi.adornment = kHIThemeTabAdornmentNone; 4220 tdi.kind = kHIThemeTabKindNormal; 4221 4222 QStyleOptionTab::TabPosition tp = tabOpt->position; 4223 QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; 4224 if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { 4225 if (sp == QStyleOptionTab::NextIsSelected) 4226 sp = QStyleOptionTab::PreviousIsSelected; 4227 else if (sp == QStyleOptionTab::PreviousIsSelected) 4228 sp = QStyleOptionTab::NextIsSelected; 4229 switch (tp) { 4230 case QStyleOptionTab::Beginning: 4231 tp = QStyleOptionTab::End; 4232 break; 4233 case QStyleOptionTab::End: 4234 tp = QStyleOptionTab::Beginning; 4235 break; 4236 default: 4237 break; 4215 case CE_TabBarTabLabel: 4216 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { 4217 QStyleOptionTab myTab = *tab; 4218 ThemeTabDirection ttd = getTabDirection(myTab.shape); 4219 bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; 4220 bool selected = (myTab.state & QStyle::State_Selected); 4221 4222 // Check to see if we use have the same as the system font 4223 // (QComboMenuItem is internal and should never be seen by the 4224 // outside world, unless they read the source, in which case, it's 4225 // their own fault). 4226 bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); 4227 bool isSelectedAndNeedsShadow = selected && !usingYosemiteOrLater; 4228 if (isSelectedAndNeedsShadow || verticalTabs || nonDefaultFont || !tab->icon.isNull() 4229 || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) { 4230 int heightOffset = 0; 4231 if (verticalTabs) { 4232 heightOffset = -1; 4233 } else if (nonDefaultFont) { 4234 if (p->fontMetrics().height() == myTab.rect.height()) 4235 heightOffset = 2; 4236 } 4237 myTab.rect.setHeight(myTab.rect.height() + heightOffset); 4238 4239 if (myTab.documentMode || isSelectedAndNeedsShadow) { 4240 p->save(); 4241 rotateTabPainter(p, myTab.shape, myTab.rect); 4242 4243 QColor shadowColor = QColor(myTab.documentMode ? Qt::white : Qt::black); 4244 shadowColor.setAlpha(75); 4245 QPalette np = tab->palette; 4246 np.setColor(QPalette::WindowText, shadowColor); 4247 4248 QRect nr = proxy()->subElementRect(SE_TabBarTabText, opt, w); 4249 nr.moveTop(-1); 4250 int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic; 4251 proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled, 4252 tab->text, QPalette::WindowText); 4253 p->restore(); 4254 } 4255 4256 QCommonStyle::drawControl(ce, &myTab, p, w); 4257 } else { 4258 p->save(); 4259 CGContextSetShouldAntialias(cg, true); 4260 CGContextSetShouldSmoothFonts(cg, true); 4261 HIThemeTextInfo tti; 4262 tti.version = qt_mac_hitheme_version; 4263 tti.state = tds; 4264 QColor textColor = myTab.palette.windowText().color(); 4265 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 4266 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 4267 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 4268 CGContextSetFillColor(cg, colorComp); 4269 switch (d->aquaSizeConstrain(opt, w)) { 4270 default: 4271 case QAquaSizeUnknown: 4272 case QAquaSizeLarge: 4273 tti.fontID = kThemeSystemFont; 4274 break; 4275 case QAquaSizeSmall: 4276 tti.fontID = kThemeSmallSystemFont; 4277 break; 4278 case QAquaSizeMini: 4279 tti.fontID = kThemeMiniSystemFont; 4280 break; 4281 } 4282 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 4283 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 4284 tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone; 4285 tti.truncationPosition = kHIThemeTextTruncationNone; 4286 tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n')); 4287 QCFString tabText = qt_mac_removeMnemonics(myTab.text); 4288 QRect r = myTab.rect.adjusted(0, 0, 0, -1); 4289 HIRect bounds = qt_hirectForQRect(r); 4290 HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal); 4291 p->restore(); 4292 } 4238 4293 } 4239 }4240 bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22);4241 4242 switch (tp) {4243 case QStyleOptionTab::Beginning:4244 tdi.position = kHIThemeTabPositionFirst;4245 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs)4246 tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;4247 break;4248 case QStyleOptionTab::Middle:4249 tdi.position = kHIThemeTabPositionMiddle;4250 if (selected)4251 tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;4252 if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected.4253 tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator;4254 break;4255 case QStyleOptionTab::End:4256 tdi.position = kHIThemeTabPositionLast;4257 if (selected)4258 tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator;4259 break;4260 case QStyleOptionTab::OnlyOneTab:4261 tdi.position = kHIThemeTabPositionOnly;4262 4294 break; 4263 } 4264 // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. 4265 if (stretchTabs) {4266 HIRect hirect = CGRectMake(0, 0, 23, 23);4267 QPixmap pm(23, 23);4268 pm.fill(Qt::transparent);4269 {4270 QMacCGContext pmcg(&pm);4271 HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0);4272 }4273 QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7);4274 } else {4275 HIRect hirect = qt_hirectForQRect(tabRect);4276 HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0);4277 }4278 }4279 break;4280 case CE_TabBarTabLabel:4281 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {4282 QStyleOptionTab myTab = *tab;4283 ThemeTabDirection ttd = getTabDirection(myTab.shape);4284 bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;4285 4286 // Check to see if we use have the same as the system font4287 // (QComboMenuItem is internal and should never be seen by the4288 // outside world, unless they read the source, in which case, it's4289 // their own fault).4290 bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem");4291 4292 if (!myTab.documentMode && (myTab.state & State_Selected) && (myTab.state & State_Active))4293 if (const auto *tabBar = qobject_cast<const QTabBar *>(w))4294 if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid())4295 myTab.palette.setColor(QPalette::WindowText, Qt::white);4296 4297 if (verticalTabs || nonDefaultFont || !tab->icon.isNull()4298 || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) {4299 int heightOffset = 0;4300 if (verticalTabs) {4301 heightOffset = -1;4302 } else if (nonDefaultFont) {4303 if (p->fontMetrics().height() == myTab.rect.height())4304 heightOffset = 2;4295 #endif 4296 #ifndef QT_NO_DOCKWIDGET 4297 case CE_DockWidgetTitle: 4298 if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(w)) { 4299 bool floating = dockWidget->isFloating(); 4300 if (floating) { 4301 ThemeDrawState tds = d->getDrawState(opt->state); 4302 HIThemeWindowDrawInfo wdi; 4303 wdi.version = qt_mac_hitheme_version; 4304 wdi.state = tds; 4305 wdi.windowType = kThemeMovableDialogWindow; 4306 wdi.titleHeight = opt->rect.height(); 4307 wdi.titleWidth = opt->rect.width(); 4308 wdi.attributes = 0; 4309 4310 HIRect titleBarRect; 4311 HIRect tmpRect = qt_hirectForQRect(opt->rect); 4312 { 4313 QCFType<HIShapeRef> titleRegion; 4314 QRect newr = opt->rect.adjusted(0, 0, 2, 0); 4315 HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); 4316 ptrHIShapeGetBounds(titleRegion, &tmpRect); 4317 newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); 4318 titleBarRect = qt_hirectForQRect(newr); 4319 } 4320 QMacCGContext cg(p); 4321 HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); 4322 } else { 4323 // fill title bar background 4324 QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); 4325 linearGrad.setColorAt(0, mainWindowGradientBegin); 4326 linearGrad.setColorAt(1, mainWindowGradientEnd); 4327 p->fillRect(opt->rect, linearGrad); 4328 4329 // draw horizontal lines at top and bottom 4330 p->save(); 4331 p->setPen(mainWindowGradientBegin.lighter(114)); 4332 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4333 p->setPen(mainWindowGradientEnd.darker(114)); 4334 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); 4335 p->restore(); 4336 } 4305 4337 } 4306 myTab.rect.setHeight(myTab.rect.height() + heightOffset); 4307 4308 QCommonStyle::drawControl(ce, &myTab, p, w); 4309 } else { 4310 p->save(); 4311 CGContextSetShouldAntialias(cg, true); 4312 CGContextSetShouldSmoothFonts(cg, true); 4313 HIThemeTextInfo tti; 4314 tti.version = qt_mac_hitheme_version; 4315 tti.state = tds; 4316 QColor textColor = myTab.palette.windowText().color(); 4317 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 4318 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 4319 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 4320 CGContextSetFillColor(cg, colorComp); 4321 switch (d->aquaSizeConstrain(opt, w)) { 4322 default: 4323 case QAquaSizeUnknown: 4324 case QAquaSizeLarge: 4325 tti.fontID = kThemeSystemFont; 4326 break; 4327 case QAquaSizeSmall: 4328 tti.fontID = kThemeSmallSystemFont; 4329 break; 4330 case QAquaSizeMini: 4331 tti.fontID = kThemeMiniSystemFont; 4332 break; 4338 4339 // Draw the text... 4340 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt)) { 4341 if (!dwOpt->title.isEmpty()) { 4342 4343 const bool verticalTitleBar = dwOpt->verticalTitleBar; 4344 4345 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, w); 4346 if (verticalTitleBar) { 4347 QRect rect = dwOpt->rect; 4348 QRect r = rect.transposed(); 4349 4350 titleRect = QRect(r.left() + rect.bottom() 4351 - titleRect.bottom(), 4352 r.top() + titleRect.left() - rect.left(), 4353 titleRect.height(), titleRect.width()); 4354 4355 p->translate(r.left(), r.top() + r.width()); 4356 p->rotate(-90); 4357 p->translate(-r.left(), -r.top()); 4358 } 4359 4360 QFont oldFont = p->font(); 4361 p->setFont(qt_app_fonts_hash()->value("QToolButton", p->font())); 4362 QString text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, 4363 titleRect.width()); 4364 drawItemText(p, titleRect, 4365 Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette, 4366 dwOpt->state & State_Enabled, text, 4367 QPalette::WindowText); 4368 p->setFont(oldFont); 4369 } 4333 4370 } 4334 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 4335 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 4336 tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone; 4337 tti.truncationPosition = kHIThemeTextTruncationNone; 4338 tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n')); 4339 QCFString tabText = qt_mac_removeMnemonics(myTab.text); 4340 QRect r = myTab.rect.adjusted(0, 0, 0, -1); 4341 HIRect bounds = qt_hirectForQRect(r); 4342 HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal); 4343 p->restore(); 4344 } 4345 } 4346 break; 4371 break; 4347 4372 #endif 4348 #if QT_CONFIG(dockwidget) 4349 case CE_DockWidgetTitle: 4350 if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(w)) { 4351 bool floating = dockWidget->isFloating(); 4352 if (floating) { 4353 ThemeDrawState tds = d->getDrawState(opt->state); 4354 HIThemeWindowDrawInfo wdi; 4355 wdi.version = qt_mac_hitheme_version; 4356 wdi.state = tds; 4357 wdi.windowType = kThemeMovableDialogWindow; 4358 wdi.titleHeight = opt->rect.height(); 4359 wdi.titleWidth = opt->rect.width(); 4360 wdi.attributes = 0; 4361 4362 HIRect titleBarRect; 4363 HIRect tmpRect = qt_hirectForQRect(opt->rect); 4364 { 4365 QCFType<HIShapeRef> titleRegion; 4366 QRect newr = opt->rect.adjusted(0, 0, 2, 0); 4367 HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); 4368 ptrHIShapeGetBounds(titleRegion, &tmpRect); 4369 newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); 4370 titleBarRect = qt_hirectForQRect(newr); 4373 case CE_FocusFrame: { 4374 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w); 4375 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); 4376 d->drawFocusRing(p, opt->rect, hMargin, vMargin); 4377 break; } 4378 case CE_MenuItem: 4379 case CE_MenuEmptyArea: 4380 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 4381 p->fillRect(mi->rect, opt->palette.background()); 4382 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w); 4383 int tabwidth = mi->tabWidth; 4384 int maxpmw = mi->maxIconWidth; 4385 bool active = mi->state & State_Selected; 4386 bool enabled = mi->state & State_Enabled; 4387 HIRect menuRect = qt_hirectForQRect(mi->menuRect); 4388 HIRect itemRect = qt_hirectForQRect(mi->rect); 4389 HIThemeMenuItemDrawInfo mdi; 4390 mdi.version = qt_mac_hitheme_version; 4391 mdi.itemType = kThemeMenuItemPlain; 4392 if (!mi->icon.isNull()) 4393 mdi.itemType |= kThemeMenuItemHasIcon; 4394 if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) 4395 mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground; 4396 else 4397 mdi.itemType |= kThemeMenuItemPopUpBackground; 4398 if (enabled) 4399 mdi.state = kThemeMenuActive; 4400 else 4401 mdi.state = kThemeMenuDisabled; 4402 if (active) 4403 mdi.state |= kThemeMenuSelected; 4404 QRect contentRect; 4405 if (mi->menuItemType == QStyleOptionMenuItem::Separator) { 4406 // First arg should be &menurect, but wacky stuff happens then. 4407 HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi, 4408 cg, kHIThemeOrientationNormal); 4409 break; 4410 } else { 4411 HIRect cr; 4412 bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent; 4413 if (needAlpha) { 4414 CGContextSaveGState(cg); 4415 CGContextSetAlpha(cg, 0.0); 4416 } 4417 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, 4418 cg, kHIThemeOrientationNormal, &cr); 4419 if (needAlpha) 4420 CGContextRestoreGState(cg); 4421 if (ce == CE_MenuEmptyArea) 4422 break; 4423 contentRect = qt_qrectForHIRect(cr); 4424 } 4425 int xpos = contentRect.x() + 18; 4426 int checkcol = maxpmw; 4427 if (!enabled) 4428 p->setPen(mi->palette.text().color()); 4429 else if (active) 4430 p->setPen(mi->palette.highlightedText().color()); 4431 else 4432 p->setPen(mi->palette.buttonText().color()); 4433 4434 if (mi->checked) { 4435 // Use the HIThemeTextInfo foo to draw the check mark correctly, if we do it, 4436 // we somehow need to use a special encoding as it doesn't look right with our 4437 // drawText(). 4438 p->save(); 4439 CGContextSetShouldAntialias(cg, true); 4440 CGContextSetShouldSmoothFonts(cg, true); 4441 QColor textColor = p->pen().color(); 4442 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 4443 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 4444 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 4445 CGContextSetFillColor(cg, colorComp); 4446 HIThemeTextInfo tti; 4447 tti.version = qt_mac_hitheme_version; 4448 tti.state = tds; 4449 if (active && enabled) 4450 tti.state = kThemeStatePressed; 4451 switch (widgetSize) { 4452 case QAquaSizeUnknown: 4453 case QAquaSizeLarge: 4454 tti.fontID = kThemeMenuItemMarkFont; 4455 break; 4456 case QAquaSizeSmall: 4457 tti.fontID = kThemeSmallSystemFont; 4458 break; 4459 case QAquaSizeMini: 4460 tti.fontID = kThemeMiniSystemFont; 4461 break; 4462 } 4463 tti.horizontalFlushness = kHIThemeTextHorizontalFlushLeft; 4464 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 4465 tti.options = kHIThemeTextBoxOptionNone; 4466 tti.truncationPosition = kHIThemeTextTruncationNone; 4467 tti.truncationMaxLines = 1; 4468 QCFString checkmark; 4469 #if 0 4470 if (mi->checkType == QStyleOptionMenuItem::Exclusive) 4471 checkmark = QString(QChar(kDiamondUnicode)); 4472 else 4473 #endif 4474 checkmark = QString(QChar(kCheckUnicode)); 4475 int mw = checkcol + macItemFrame; 4476 int mh = contentRect.height() - 2 * macItemFrame; 4477 int xp = contentRect.x(); 4478 xp += macItemFrame; 4479 CGFloat outWidth, outHeight, outBaseline; 4480 HIThemeGetTextDimensions(checkmark, 0, &tti, &outWidth, &outHeight, 4481 &outBaseline); 4482 if (widgetSize == QAquaSizeMini) 4483 outBaseline += 1; 4484 QRect r(xp, contentRect.y(), mw, mh); 4485 r.translate(0, p->fontMetrics().ascent() - int(outBaseline) + 1); 4486 HIRect bounds = qt_hirectForQRect(r); 4487 HIThemeDrawTextBox(checkmark, &bounds, &tti, 4488 cg, kHIThemeOrientationNormal); 4489 p->restore(); 4490 } 4491 if (!mi->icon.isNull()) { 4492 QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal 4493 : QIcon::Disabled; 4494 // Always be normal or disabled to follow the Mac style. 4495 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize); 4496 QSize iconSize(smallIconSize, smallIconSize); 4497 #ifndef QT_NO_COMBOBOX 4498 if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(w)) { 4499 iconSize = comboBox->iconSize(); 4500 } 4501 #endif 4502 QPixmap pixmap = mi->icon.pixmap(window, iconSize, mode); 4503 int pixw = pixmap.width() / pixmap.devicePixelRatio(); 4504 int pixh = pixmap.height() / pixmap.devicePixelRatio(); 4505 QRect cr(xpos, contentRect.y(), checkcol, contentRect.height()); 4506 QRect pmr(0, 0, pixw, pixh); 4507 pmr.moveCenter(cr.center()); 4508 p->drawPixmap(pmr.topLeft(), pixmap); 4509 xpos += pixw + 6; 4510 } 4511 4512 QString s = mi->text; 4513 if (!s.isEmpty()) { 4514 int t = s.indexOf(QLatin1Char('\t')); 4515 int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic 4516 | Qt::TextSingleLine | Qt::AlignAbsolute; 4517 int yPos = contentRect.y(); 4518 if (widgetSize == QAquaSizeMini) 4519 yPos += 1; 4520 p->save(); 4521 if (t >= 0) { 4522 p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); 4523 int xp = contentRect.right() - tabwidth - macRightBorder 4524 - macItemHMargin - macItemFrame + 1; 4525 p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags, 4526 s.mid(t + 1)); 4527 s = s.left(t); 4528 } 4529 4530 const int xm = macItemFrame + maxpmw + macItemHMargin; 4531 QFont myFont = mi->font; 4532 // myFont may not have any "hard" flags set. We override 4533 // the point size so that when it is resolved against the device, this font will win. 4534 // This is mainly to handle cases where someone sets the font on the window 4535 // and then the combo inherits it and passes it onward. At that point the resolve mask 4536 // is very, very weak. This makes it stonger. 4537 myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF()); 4538 p->setFont(myFont); 4539 p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1, 4540 contentRect.height(), text_flags ^ Qt::AlignRight, s); 4541 p->restore(); 4542 } 4371 4543 } 4372 QMacCGContext cg(p); 4373 HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); 4374 } else { 4375 // fill title bar background 4376 QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); 4377 linearGrad.setColorAt(0, mainWindowGradientBegin); 4378 linearGrad.setColorAt(1, mainWindowGradientEnd); 4379 p->fillRect(opt->rect, linearGrad); 4380 4381 // draw horizontal lines at top and bottom 4382 p->save(); 4383 p->setPen(mainWindowGradientBegin.lighter(114)); 4384 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4385 p->setPen(mainWindowGradientEnd.darker(114)); 4386 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); 4387 p->restore(); 4388 } 4389 } 4390 4391 // Draw the text... 4392 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(opt)) { 4393 if (!dwOpt->title.isEmpty()) { 4394 4395 const bool verticalTitleBar = dwOpt->verticalTitleBar; 4396 4397 QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, w); 4398 if (verticalTitleBar) { 4399 QRect rect = dwOpt->rect; 4400 QRect r = rect.transposed(); 4401 4402 titleRect = QRect(r.left() + rect.bottom() 4403 - titleRect.bottom(), 4404 r.top() + titleRect.left() - rect.left(), 4405 titleRect.height(), titleRect.width()); 4406 4407 p->translate(r.left(), r.top() + r.width()); 4408 p->rotate(-90); 4409 p->translate(-r.left(), -r.top()); 4544 break; 4545 case CE_MenuHMargin: 4546 case CE_MenuVMargin: 4547 case CE_MenuTearoff: 4548 case CE_MenuScroller: 4549 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 4550 p->fillRect(mi->rect, opt->palette.background()); 4551 4552 HIRect menuRect = qt_hirectForQRect(mi->menuRect); 4553 HIRect itemRect = qt_hirectForQRect(mi->rect); 4554 HIThemeMenuItemDrawInfo mdi; 4555 mdi.version = qt_mac_hitheme_version; 4556 if (!(opt->state & State_Enabled)) 4557 mdi.state = kThemeMenuDisabled; 4558 else if (opt->state & State_Selected) 4559 mdi.state = kThemeMenuSelected; 4560 else 4561 mdi.state = kThemeMenuActive; 4562 if (ce == CE_MenuScroller) { 4563 if (opt->state & State_DownArrow) 4564 mdi.itemType = kThemeMenuItemScrollDownArrow; 4565 else 4566 mdi.itemType = kThemeMenuItemScrollUpArrow; 4567 } else { 4568 mdi.itemType = kThemeMenuItemPlain; 4569 } 4570 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, 4571 cg, 4572 kHIThemeOrientationNormal, 0); 4573 if (ce == CE_MenuTearoff) { 4574 p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine)); 4575 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1, 4576 mi->rect.x() + mi->rect.width() - 4, 4577 mi->rect.y() + mi->rect.height() / 2 - 1); 4578 p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine)); 4579 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2, 4580 mi->rect.x() + mi->rect.width() - 4, 4581 mi->rect.y() + mi->rect.height() / 2); 4582 } 4410 4583 } 4411 4412 QFont oldFont = p->font();4413 p->setFont(qt_app_fonts_hash()->value("QToolButton", p->font()));4414 QString text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight,4415 titleRect.width());4416 drawItemText(p, titleRect,4417 Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette,4418 dwOpt->state & State_Enabled, text,4419 QPalette::WindowText);4420 p->setFont(oldFont);4421 }4422 }4423 break;4424 #endif4425 case CE_FocusFrame: {4426 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);4427 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);4428 d->drawFocusRing(p, opt->rect, hMargin, vMargin);4429 break; }4430 case CE_MenuItem:4431 case CE_MenuEmptyArea:4432 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {4433 p->fillRect(mi->rect, opt->palette.background());4434 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w);4435 int tabwidth = mi->tabWidth;4436 int maxpmw = mi->maxIconWidth;4437 bool active = mi->state & State_Selected;4438 bool enabled = mi->state & State_Enabled;4439 HIRect menuRect = qt_hirectForQRect(mi->menuRect);4440 HIRect itemRect = qt_hirectForQRect(mi->rect);4441 HIThemeMenuItemDrawInfo mdi;4442 mdi.version = qt_mac_hitheme_version;4443 mdi.itemType = kThemeMenuItemPlain;4444 if (!mi->icon.isNull())4445 mdi.itemType |= kThemeMenuItemHasIcon;4446 if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)4447 mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground;4448 else4449 mdi.itemType |= kThemeMenuItemPopUpBackground;4450 if (enabled)4451 mdi.state = kThemeMenuActive;4452 else4453 mdi.state = kThemeMenuDisabled;4454 if (active)4455 mdi.state |= kThemeMenuSelected;4456 QRect contentRect;4457 if (mi->menuItemType == QStyleOptionMenuItem::Separator) {4458 // First arg should be &menurect, but wacky stuff happens then.4459 HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi,4460 cg, kHIThemeOrientationNormal);4461 4584 break; 4462 } else { 4463 HIRect cr; 4464 bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent; 4465 if (needAlpha) { 4466 CGContextSaveGState(cg); 4467 CGContextSetAlpha(cg, 0.0); 4585 case CE_MenuBarItem: 4586 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 4587 HIRect menuRect = qt_hirectForQRect(mi->menuRect); 4588 HIRect itemRect = qt_hirectForQRect(mi->rect); 4589 4590 const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken); 4591 if (selected) { 4592 // Draw a selected menu item background: 4593 HIThemeMenuItemDrawInfo mdi; 4594 mdi.version = qt_mac_hitheme_version; 4595 mdi.state = kThemeMenuSelected; 4596 mdi.itemType = kThemeMenuItemPlain; 4597 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0); 4598 } else { 4599 // Draw the toolbar background: 4600 HIThemeMenuBarDrawInfo bdi; 4601 bdi.version = qt_mac_hitheme_version; 4602 bdi.state = kThemeMenuBarNormal; 4603 bdi.attributes = 0; 4604 HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal); 4605 } 4606 4607 if (!mi->icon.isNull()) { 4608 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 4609 drawItemPixmap(p, mi->rect, 4610 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip 4611 | Qt::TextSingleLine, 4612 mi->icon.pixmap(window, QSize(iconExtent, iconExtent), 4613 (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled)); 4614 } else { 4615 drawItemText(p, mi->rect, 4616 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip 4617 | Qt::TextSingleLine, 4618 mi->palette, mi->state & State_Enabled, 4619 mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText); 4620 } 4468 4621 } 4469 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, 4470 cg, kHIThemeOrientationNormal, &cr); 4471 if (needAlpha) 4472 CGContextRestoreGState(cg); 4473 if (ce == CE_MenuEmptyArea) 4622 break; 4623 case CE_MenuBarEmptyArea: 4624 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 4625 HIThemeMenuBarDrawInfo bdi; 4626 bdi.version = qt_mac_hitheme_version; 4627 bdi.state = kThemeMenuBarNormal; 4628 bdi.attributes = 0; 4629 HIRect hirect = qt_hirectForQRect(mi->rect); 4630 HIThemeDrawMenuBarBackground(&hirect, &bdi, cg, 4631 kHIThemeOrientationNormal); 4474 4632 break; 4475 contentRect = qt_qrectForHIRect(cr);4476 }4477 int xpos = contentRect.x() + 18;4478 int checkcol = maxpmw;4479 if (!enabled)4480 p->setPen(mi->palette.text().color());4481 else if (active)4482 p->setPen(mi->palette.highlightedText().color());4483 else4484 p->setPen(mi->palette.buttonText().color());4485 4486 if (mi->checked) {4487 QStyleOption checkmarkOpt;4488 checkmarkOpt.initFrom(w);4489 4490 const int mw = checkcol + macItemFrame;4491 const int mh = contentRect.height() + macItemFrame;4492 const int xp = contentRect.x() + macItemFrame;4493 checkmarkOpt.rect = QRect(xp, contentRect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh);4494 4495 checkmarkOpt.state.setFlag(State_On, active);4496 checkmarkOpt.state.setFlag(State_Enabled, enabled);4497 if (widgetSize == QAquaSizeMini)4498 checkmarkOpt.state |= State_Mini;4499 else if (widgetSize == QAquaSizeSmall)4500 checkmarkOpt.state |= State_Small;4501 4502 // We let drawPrimitive(PE_IndicatorMenuCheckMark) pick the right color4503 checkmarkOpt.palette.setColor(QPalette::HighlightedText, p->pen().color());4504 checkmarkOpt.palette.setColor(QPalette::Text, p->pen().color());4505 4506 proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &checkmarkOpt, p, w);4507 }4508 if (!mi->icon.isNull()) {4509 QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal4510 : QIcon::Disabled;4511 // Always be normal or disabled to follow the Mac style.4512 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize);4513 QSize iconSize(smallIconSize, smallIconSize);4514 #if QT_CONFIG(combobox)4515 if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(w)) {4516 iconSize = comboBox->iconSize();4517 4633 } 4518 #endif 4519 QPixmap pixmap = mi->icon.pixmap(window, iconSize, mode); 4520 int pixw = pixmap.width() / pixmap.devicePixelRatio(); 4521 int pixh = pixmap.height() / pixmap.devicePixelRatio(); 4522 QRect cr(xpos, contentRect.y(), checkcol, contentRect.height()); 4523 QRect pmr(0, 0, pixw, pixh); 4524 pmr.moveCenter(cr.center()); 4525 p->drawPixmap(pmr.topLeft(), pixmap); 4526 xpos += pixw + 6; 4527 } 4528 4529 QString s = mi->text; 4530 if (!s.isEmpty()) { 4531 int t = s.indexOf(QLatin1Char('\t')); 4532 int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic 4533 | Qt::TextSingleLine | Qt::AlignAbsolute; 4534 int yPos = contentRect.y(); 4535 if (widgetSize == QAquaSizeMini) 4536 yPos += 1; 4537 p->save(); 4538 if (t >= 0) { 4539 p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); 4540 int xp = contentRect.right() - tabwidth - macRightBorder 4541 - macItemHMargin - macItemFrame + 1; 4542 p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags, 4543 s.mid(t + 1)); 4544 s = s.left(t); 4634 case CE_ProgressBarContents: 4635 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { 4636 HIThemeTrackDrawInfo tdi; 4637 tdi.version = qt_mac_hitheme_version; 4638 tdi.reserved = 0; 4639 bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0); 4640 const bool vertical = pb->orientation == Qt::Vertical; 4641 const bool inverted = pb->invertedAppearance; 4642 bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)); 4643 if (inverted) 4644 reverse = !reverse; 4645 switch (d->aquaSizeConstrain(opt, w)) { 4646 case QAquaSizeUnknown: 4647 case QAquaSizeLarge: 4648 tdi.kind = !isIndeterminate ? kThemeLargeProgressBar 4649 : kThemeLargeIndeterminateBar; 4650 break; 4651 case QAquaSizeMini: 4652 case QAquaSizeSmall: 4653 tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar; 4654 break; 4655 } 4656 tdi.bounds = qt_hirectForQRect(pb->rect); 4657 tdi.max = pb->maximum; 4658 tdi.min = pb->minimum; 4659 tdi.value = pb->progress; 4660 tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; 4661 4662 if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) { 4663 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) 4664 tdi.trackInfo.progress.phase = animation->animationStep(); 4665 else if (opt->styleObject) 4666 d->startAnimation(new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject)); 4667 } else { 4668 d->stopAnimation(opt->styleObject); 4669 } 4670 if (!(pb->state & State_Active)) 4671 tdi.enableState = kThemeTrackInactive; 4672 else if (!(pb->state & State_Enabled)) 4673 tdi.enableState = kThemeTrackDisabled; 4674 else 4675 tdi.enableState = kThemeTrackActive; 4676 HIThemeOrientation drawOrientation = kHIThemeOrientationNormal; 4677 if (reverse) { 4678 if (vertical) { 4679 drawOrientation = kHIThemeOrientationInverted; 4680 } else { 4681 CGContextSaveGState(cg); 4682 CGContextTranslateCTM(cg, pb->rect.width(), 0); 4683 CGContextScaleCTM(cg, -1, 1); 4684 } 4685 } 4686 HIThemeDrawTrack(&tdi, 0, cg, drawOrientation); 4687 if (reverse && !vertical) 4688 CGContextRestoreGState(cg); 4545 4689 } 4546 4547 const int xm = macItemFrame + maxpmw + macItemHMargin;4548 QFont myFont = mi->font;4549 // myFont may not have any "hard" flags set. We override4550 // the point size so that when it is resolved against the device, this font will win.4551 // This is mainly to handle cases where someone sets the font on the window4552 // and then the combo inherits it and passes it onward. At that point the resolve mask4553 // is very, very weak. This makes it stonger.4554 myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF());4555 p->setFont(myFont);4556 p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1,4557 contentRect.height(), text_flags ^ Qt::AlignRight, s);4558 p->restore();4559 }4560 }4561 break;4562 case CE_MenuHMargin:4563 case CE_MenuVMargin:4564 case CE_MenuTearoff:4565 case CE_MenuScroller:4566 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {4567 p->fillRect(mi->rect, opt->palette.background());4568 4569 HIRect menuRect = qt_hirectForQRect(mi->menuRect);4570 HIRect itemRect = qt_hirectForQRect(mi->rect);4571 HIThemeMenuItemDrawInfo mdi;4572 mdi.version = qt_mac_hitheme_version;4573 if (!(opt->state & State_Enabled))4574 mdi.state = kThemeMenuDisabled;4575 else if (opt->state & State_Selected)4576 mdi.state = kThemeMenuSelected;4577 else4578 mdi.state = kThemeMenuActive;4579 if (ce == CE_MenuScroller) {4580 if (opt->state & State_DownArrow)4581 mdi.itemType = kThemeMenuItemScrollDownArrow;4582 else4583 mdi.itemType = kThemeMenuItemScrollUpArrow;4584 } else {4585 mdi.itemType = kThemeMenuItemPlain;4586 }4587 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi,4588 cg,4589 kHIThemeOrientationNormal, 0);4590 if (ce == CE_MenuTearoff) {4591 p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine));4592 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1,4593 mi->rect.x() + mi->rect.width() - 4,4594 mi->rect.y() + mi->rect.height() / 2 - 1);4595 p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine));4596 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2,4597 mi->rect.x() + mi->rect.width() - 4,4598 mi->rect.y() + mi->rect.height() / 2);4599 }4600 }4601 break;4602 case CE_MenuBarItem:4603 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {4604 HIRect menuRect = qt_hirectForQRect(mi->menuRect);4605 HIRect itemRect = qt_hirectForQRect(mi->rect);4606 4607 const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken);4608 if (selected) {4609 // Draw a selected menu item background:4610 HIThemeMenuItemDrawInfo mdi;4611 mdi.version = qt_mac_hitheme_version;4612 mdi.state = kThemeMenuSelected;4613 mdi.itemType = kThemeMenuItemPlain;4614 HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0);4615 } else {4616 // Draw the toolbar background:4617 HIThemeMenuBarDrawInfo bdi;4618 bdi.version = qt_mac_hitheme_version;4619 bdi.state = kThemeMenuBarNormal;4620 bdi.attributes = 0;4621 HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal);4622 }4623 4624 if (!mi->icon.isNull()) {4625 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);4626 drawItemPixmap(p, mi->rect,4627 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip4628 | Qt::TextSingleLine,4629 mi->icon.pixmap(window, QSize(iconExtent, iconExtent),4630 (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled));4631 } else {4632 drawItemText(p, mi->rect,4633 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip4634 | Qt::TextSingleLine,4635 mi->palette, mi->state & State_Enabled,4636 mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText);4637 }4638 }4639 break;4640 case CE_MenuBarEmptyArea:4641 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {4642 HIThemeMenuBarDrawInfo bdi;4643 bdi.version = qt_mac_hitheme_version;4644 bdi.state = kThemeMenuBarNormal;4645 bdi.attributes = 0;4646 HIRect hirect = qt_hirectForQRect(mi->rect);4647 HIThemeDrawMenuBarBackground(&hirect, &bdi, cg,4648 kHIThemeOrientationNormal);4649 break;4650 }4651 case CE_ProgressBarContents:4652 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {4653 HIThemeTrackDrawInfo tdi;4654 tdi.version = qt_mac_hitheme_version;4655 tdi.reserved = 0;4656 bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0);4657 const bool vertical = pb->orientation == Qt::Vertical;4658 const bool inverted = pb->invertedAppearance;4659 bool reverse = (!vertical && (pb->direction == Qt::RightToLeft));4660 if (inverted)4661 reverse = !reverse;4662 switch (d->aquaSizeConstrain(opt, w)) {4663 case QAquaSizeUnknown:4664 case QAquaSizeLarge:4665 tdi.kind = !isIndeterminate ? kThemeLargeProgressBar4666 : kThemeLargeIndeterminateBar;4667 4690 break; 4668 case QAquaSizeMini: 4669 case QAquaSizeSmall: 4670 tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar; 4691 case CE_ProgressBarLabel: 4692 case CE_ProgressBarGroove: 4671 4693 break; 4672 } 4673 tdi.bounds = qt_hirectForQRect(pb->rect); 4674 tdi.max = pb->maximum; 4675 tdi.min = pb->minimum; 4676 tdi.value = pb->progress; 4677 tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; 4678 4679 if (isIndeterminate) { 4680 if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) 4681 tdi.trackInfo.progress.phase = animation->animationStep(); 4682 else if (opt->styleObject) 4683 d->startAnimation(new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject)); 4684 } else { 4685 d->stopAnimation(opt->styleObject); 4686 } 4687 if (!(pb->state & State_Active)) 4688 tdi.enableState = kThemeTrackInactive; 4689 else if (!(pb->state & State_Enabled)) 4690 tdi.enableState = kThemeTrackDisabled; 4691 else 4692 tdi.enableState = kThemeTrackActive; 4693 HIThemeOrientation drawOrientation = kHIThemeOrientationNormal; 4694 if (reverse) { 4695 if (vertical) { 4696 drawOrientation = kHIThemeOrientationInverted; 4697 } else { 4698 CGContextSaveGState(cg); 4699 CGContextTranslateCTM(cg, pb->rect.width(), 0); 4700 CGContextScaleCTM(cg, -1, 1); 4701 } 4702 } 4703 HIThemeDrawTrack(&tdi, 0, cg, drawOrientation); 4704 if (reverse && !vertical) 4705 CGContextRestoreGState(cg); 4706 } 4707 break; 4708 case CE_ProgressBarLabel: 4709 case CE_ProgressBarGroove: 4710 break; 4711 case CE_SizeGrip: { 4712 if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { 4713 HIThemeGrowBoxDrawInfo gdi; 4714 gdi.version = qt_mac_hitheme_version; 4715 gdi.state = tds; 4716 gdi.kind = kHIThemeGrowBoxKindNormal; 4717 gdi.direction = kThemeGrowRight | kThemeGrowDown; 4718 gdi.size = kHIThemeGrowBoxSizeNormal; 4719 HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y()); 4720 HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal); 4721 } else { 4722 // It isn't possible to draw a transparent size grip with the 4723 // native API, so we do it ourselves here. 4724 const bool metal = qt_mac_is_metal(w); 4725 QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192); 4726 QPen metalHighlight = QColor(5, 5, 5, 192); 4727 lineColor.setWidth(1); 4728 p->save(); 4729 p->setRenderHint(QPainter::Antialiasing); 4730 p->setPen(lineColor); 4731 const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); 4732 const int NumLines = metal ? 4 : 3; 4733 for (int l = 0; l < NumLines; ++l) { 4734 const int offset = (l * 4 + (metal ? 2 : 3)); 4735 QPoint start, end; 4736 if (layoutDirection == Qt::LeftToRight) { 4737 start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); 4738 end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); 4694 case CE_SizeGrip: { 4695 if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { 4696 HIThemeGrowBoxDrawInfo gdi; 4697 gdi.version = qt_mac_hitheme_version; 4698 gdi.state = tds; 4699 gdi.kind = kHIThemeGrowBoxKindNormal; 4700 gdi.direction = kThemeGrowRight | kThemeGrowDown; 4701 gdi.size = kHIThemeGrowBoxSizeNormal; 4702 HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y()); 4703 HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal); 4739 4704 } else { 4740 start = QPoint(offset, opt->rect.height() - 1); 4741 end = QPoint(1, opt->rect.height() - offset); 4742 } 4743 p->drawLine(start, end); 4744 if (metal) { 4745 p->setPen(metalHighlight); 4746 p->setRenderHint(QPainter::Antialiasing, false); 4747 p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1)); 4748 p->setRenderHint(QPainter::Antialiasing, true); 4705 // It isn't possible to draw a transparent size grip with the 4706 // native API, so we do it ourselves here. 4707 const bool metal = qt_mac_is_metal(w); 4708 QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192); 4709 QPen metalHighlight = QColor(5, 5, 5, 192); 4710 lineColor.setWidth(1); 4711 p->save(); 4712 p->setRenderHint(QPainter::Antialiasing); 4749 4713 p->setPen(lineColor); 4714 const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); 4715 const int NumLines = metal ? 4 : 3; 4716 for (int l = 0; l < NumLines; ++l) { 4717 const int offset = (l * 4 + (metal ? 2 : 3)); 4718 QPoint start, end; 4719 if (layoutDirection == Qt::LeftToRight) { 4720 start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); 4721 end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); 4722 } else { 4723 start = QPoint(offset, opt->rect.height() - 1); 4724 end = QPoint(1, opt->rect.height() - offset); 4725 } 4726 p->drawLine(start, end); 4727 if (metal) { 4728 p->setPen(metalHighlight); 4729 p->setRenderHint(QPainter::Antialiasing, false); 4730 p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1)); 4731 p->setRenderHint(QPainter::Antialiasing, true); 4732 p->setPen(lineColor); 4733 } 4734 } 4735 p->restore(); 4750 4736 } 4737 break; 4751 4738 } 4752 p->restore(); 4753 } 4754 break; 4755 } 4756 case CE_Splitter: 4757 if (opt->rect.width() > 1 && opt->rect.height() > 1){ 4758 HIThemeSplitterDrawInfo sdi; 4759 sdi.version = qt_mac_hitheme_version; 4760 sdi.state = tds; 4761 sdi.adornment = kHIThemeSplitterAdornmentMetal; 4762 HIRect hirect = qt_hirectForQRect(opt->rect); 4763 HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); 4764 } else { 4765 QPen oldPen = p->pen(); 4766 p->setPen(opt->palette.dark().color()); 4767 if (opt->state & QStyle::State_Horizontal) 4768 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 4769 else 4770 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4771 p->setPen(oldPen); 4772 } 4773 break; 4774 case CE_RubberBand: 4775 if (const QStyleOptionRubberBand *rubber = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) { 4776 QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight)); 4777 if (!rubber->opaque) { 4778 QColor strokeColor; 4779 // I retrieved these colors from the Carbon-Dev mailing list 4780 strokeColor.setHsvF(0, 0, 0.86, 1.0); 4781 fillColor.setHsvF(0, 0, 0.53, 0.25); 4782 if (opt->rect.width() * opt->rect.height() <= 3) { 4783 p->fillRect(opt->rect, strokeColor); 4739 case CE_Splitter: 4740 if (opt->rect.width() > 1 && opt->rect.height() > 1){ 4741 HIThemeSplitterDrawInfo sdi; 4742 sdi.version = qt_mac_hitheme_version; 4743 sdi.state = tds; 4744 sdi.adornment = qt_mac_is_metal(w) || usingYosemiteOrLater ? 4745 kHIThemeSplitterAdornmentMetal : kHIThemeSplitterAdornmentNone; 4746 HIRect hirect = qt_hirectForQRect(opt->rect); 4747 HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); 4784 4748 } else { 4785 4749 QPen oldPen = p->pen(); 4786 QBrush oldBrush = p->brush(); 4787 QPen pen(strokeColor); 4788 p->setPen(pen); 4789 p->setBrush(fillColor); 4790 QRect adjusted = opt->rect.adjusted(1, 1, -1, -1); 4791 if (adjusted.isValid()) 4792 p->drawRect(adjusted); 4750 p->setPen(opt->palette.dark().color()); 4751 if (opt->state & QStyle::State_Horizontal) 4752 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 4753 else 4754 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4793 4755 p->setPen(oldPen); 4794 p->setBrush(oldBrush);4795 4756 } 4796 } else { 4797 p->fillRect(opt->rect, fillColor); 4798 } 4799 } 4800 break; 4801 #ifndef QT_NO_TOOLBAR 4802 case CE_ToolBar: { 4803 const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt); 4804 4805 // Unified title and toolbar drawing. In this mode the cocoa platform plugin will 4806 // fill the top toolbar area part with a background gradient that "unifies" with 4807 // the title bar. The following code fills the toolBar area with transparent pixels 4808 // to make that gradient visible. 4809 if (w) { 4810 #if QT_CONFIG(mainwindow) 4811 if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) { 4812 if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) { 4813 4814 // fill with transparent pixels. 4815 p->save(); 4816 p->setCompositionMode(QPainter::CompositionMode_Source); 4817 p->fillRect(opt->rect, Qt::transparent); 4818 p->restore(); 4819 4820 // Drow a horizontal sepearator line at the toolBar bottom if the "unified" area ends here. 4821 // There might be additional toolbars or other widgets such as tab bars in document 4822 // mode below. Determine this by making a unified toolbar area test for the row below 4823 // this toolbar. 4824 QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); 4825 bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); 4826 if (isEndOfUnifiedArea) { 4827 SInt32 margin; 4828 GetThemeMetric(kThemeMetricSeparatorSize, &margin); 4829 CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); 4830 HIThemeSeparatorDrawInfo separatorDrawInfo; 4831 separatorDrawInfo.version = 0; 4832 separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive; 4833 QMacCGContext cg(p); 4834 HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal); 4757 break; 4758 case CE_RubberBand: 4759 if (const QStyleOptionRubberBand *rubber = qstyleoption_cast<const QStyleOptionRubberBand *>(opt)) { 4760 QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight)); 4761 if (!rubber->opaque) { 4762 QColor strokeColor; 4763 // I retrieved these colors from the Carbon-Dev mailing list 4764 strokeColor.setHsvF(0, 0, 0.86, 1.0); 4765 fillColor.setHsvF(0, 0, 0.53, 0.25); 4766 if (opt->rect.width() * opt->rect.height() <= 3) { 4767 p->fillRect(opt->rect, strokeColor); 4768 } else { 4769 QPen oldPen = p->pen(); 4770 QBrush oldBrush = p->brush(); 4771 QPen pen(strokeColor); 4772 p->setPen(pen); 4773 p->setBrush(fillColor); 4774 QRect adjusted = opt->rect.adjusted(1, 1, -1, -1); 4775 if (adjusted.isValid()) 4776 p->drawRect(adjusted); 4777 p->setPen(oldPen); 4778 p->setBrush(oldBrush); 4779 } 4780 } else { 4781 p->fillRect(opt->rect, fillColor); 4835 4782 } 4836 break;4837 4783 } 4838 } 4839 #endif 4840 } 4841 4842 // draw background gradient 4843 QLinearGradient linearGrad; 4844 if (opt->state & State_Horizontal) 4845 linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom()); 4846 else 4847 linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0); 4848 4849 linearGrad.setColorAt(0, mainWindowGradientBegin); 4850 linearGrad.setColorAt(1, mainWindowGradientEnd); 4851 p->fillRect(opt->rect, linearGrad); 4852 4853 p->save(); 4854 if (opt->state & State_Horizontal) { 4855 p->setPen(mainWindowGradientBegin.lighter(114)); 4856 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4857 p->setPen(mainWindowGradientEnd.darker(114)); 4858 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); 4859 4860 } else { 4861 p->setPen(mainWindowGradientBegin.lighter(114)); 4862 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 4863 p->setPen(mainWindowGradientEnd.darker(114)); 4864 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); 4865 } 4866 p->restore(); 4867 4868 4869 } break; 4784 break; 4785 #ifndef QT_NO_TOOLBAR 4786 case CE_ToolBar: { 4787 const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt); 4788 4789 // Unified title and toolbar drawing. In this mode the cocoa platform plugin will 4790 // fill the top toolbar area part with a background gradient that "unifies" with 4791 // the title bar. The following code fills the toolBar area with transparent pixels 4792 // to make that gradient visible. 4793 if (w) { 4794 #ifndef QT_NO_MAINWINDOW 4795 if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) { 4796 if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) { 4797 4798 // fill with transparent pixels. 4799 p->save(); 4800 p->setCompositionMode(QPainter::CompositionMode_Source); 4801 p->fillRect(opt->rect, Qt::transparent); 4802 p->restore(); 4803 4804 // Drow a horizontal sepearator line at the toolBar bottom if the "unified" area ends here. 4805 // There might be additional toolbars or other widgets such as tab bars in document 4806 // mode below. Determine this by making a unified toolbar area test for the row below 4807 // this toolbar. 4808 QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); 4809 bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); 4810 if (isEndOfUnifiedArea) { 4811 SInt32 margin; 4812 GetThemeMetric(kThemeMetricSeparatorSize, &margin); 4813 CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); 4814 HIThemeSeparatorDrawInfo separatorDrawInfo; 4815 separatorDrawInfo.version = 0; 4816 separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive; 4817 QMacCGContext cg(p); 4818 HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal); 4819 } 4820 break; 4821 } 4822 } 4870 4823 #endif 4871 default: 4872 QCommonStyle::drawControl(ce, opt, p, w); 4873 break; 4874 } 4875 } 4876 4877 static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir) 4878 { 4879 if (dir == Qt::RightToLeft) { 4880 rect->adjust(-right, top, -left, bottom); 4881 } else { 4882 rect->adjust(left, top, right, bottom); 4883 } 4884 } 4885 4886 QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, 4887 const QWidget *widget) const 4888 { 4889 Q_D(const QMacStyle); 4890 QRect rect; 4891 int controlSize = getControlSize(opt, widget); 4892 4893 switch (sr) { 4894 case SE_ItemViewItemText: 4895 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) { 4896 int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget); 4897 // We add the focusframeargin between icon and text in commonstyle 4898 rect = QCommonStyle::subElementRect(sr, opt, widget); 4899 if (vopt->features & QStyleOptionViewItem::HasDecoration) 4900 rect.adjust(-fw, 0, 0, 0); 4901 } 4902 break; 4903 case SE_ToolBoxTabContents: 4904 rect = QCommonStyle::subElementRect(sr, opt, widget); 4905 break; 4906 case SE_PushButtonContents: 4907 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 4908 // Unlike Carbon, we want the button to always be drawn inside its bounds. 4909 // Therefore, the button is a bit smaller, so that even if it got focus, 4910 // the focus 'shadow' will be inside. Adjust the content rect likewise. 4911 HIThemeButtonDrawInfo bdi; 4912 d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi); 4913 HIRect contentRect = d->pushButtonContentBounds(btn, &bdi); 4914 rect = qt_qrectForHIRect(contentRect); 4915 } 4916 break; 4917 case SE_HeaderLabel: { 4918 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); 4919 rect.setRect(opt->rect.x() + margin, opt->rect.y(), 4920 opt->rect.width() - margin * 2, opt->rect.height() - 2); 4921 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 4922 // Subtract width needed for arrow, if there is one 4923 if (header->sortIndicator != QStyleOptionHeader::None) { 4824 } 4825 4826 // draw background gradient 4827 QLinearGradient linearGrad; 4924 4828 if (opt->state & State_Horizontal) 4925 rect.setWidth(rect.width() - (opt->rect.height() / 2) - (margin * 2));4829 linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom()); 4926 4830 else 4927 rect.setHeight(rect.height() - (opt->rect.width() / 2) - (margin * 2)); 4928 } 4831 linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0); 4832 4833 linearGrad.setColorAt(0, mainWindowGradientBegin); 4834 linearGrad.setColorAt(1, mainWindowGradientEnd); 4835 p->fillRect(opt->rect, linearGrad); 4836 4837 p->save(); 4838 if (opt->state & State_Horizontal) { 4839 p->setPen(mainWindowGradientBegin.lighter(114)); 4840 p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); 4841 p->setPen(mainWindowGradientEnd.darker(114)); 4842 p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); 4843 4844 } else { 4845 p->setPen(mainWindowGradientBegin.lighter(114)); 4846 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); 4847 p->setPen(mainWindowGradientEnd.darker(114)); 4848 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); 4849 } 4850 p->restore(); 4851 4852 4853 } break; 4854 #endif 4855 default: 4856 QCommonStyle::drawControl(ce, opt, p, w); 4857 break; 4929 4858 } 4930 rect = visualRect(opt->direction, opt->rect, rect);4931 break;4932 4859 } 4933 case SE_ProgressBarGroove: 4934 // Wrong in the secondary dimension, but accurate enough in the main dimension. 4935 rect = opt->rect; 4936 break; 4937 case SE_ProgressBarLabel: 4938 break; 4939 case SE_ProgressBarContents: 4940 rect = opt->rect; 4941 break; 4942 case SE_TreeViewDisclosureItem: { 4943 HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(), 4944 opt->rect.width(), opt->rect.height()); 4945 HIThemeButtonDrawInfo bdi; 4946 bdi.version = qt_mac_hitheme_version; 4947 bdi.state = kThemeStateActive; 4948 bdi.kind = kThemeDisclosureButton; 4949 bdi.value = kThemeDisclosureRight; 4950 bdi.adornment = kThemeAdornmentNone; 4951 HIRect contentRect; 4952 HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect); 4953 QCFType<HIShapeRef> shape; 4954 HIRect outRect; 4955 HIThemeGetButtonShape(&inRect, &bdi, &shape); 4956 ptrHIShapeGetBounds(shape, &outRect); 4957 rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y), 4958 int(contentRect.origin.x - outRect.origin.x + DisclosureOffset), 4959 int(outRect.size.height)); 4960 break; 4860 4861 static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir) 4862 { 4863 if (dir == Qt::RightToLeft) { 4864 rect->adjust(-right, top, -left, bottom); 4865 } else { 4866 rect->adjust(left, top, right, bottom); 4867 } 4961 4868 } 4962 #if QT_CONFIG(tabwidget) 4963 case SE_TabWidgetLeftCorner: 4964 if (const QStyleOptionTabWidgetFrame *twf 4965 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 4966 switch (twf->shape) { 4967 case QTabBar::RoundedNorth: 4968 case QTabBar::TriangularNorth: 4969 rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize); 4970 break; 4971 case QTabBar::RoundedSouth: 4972 case QTabBar::TriangularSouth: 4973 rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()), 4974 twf->leftCornerWidgetSize); 4869 4870 QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, 4871 const QWidget *widget) const 4872 { 4873 Q_D(const QMacStyle); 4874 QRect rect; 4875 int controlSize = getControlSize(opt, widget); 4876 4877 switch (sr) { 4878 case SE_ItemViewItemText: 4879 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) { 4880 int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget); 4881 // We add the focusframeargin between icon and text in commonstyle 4882 rect = QCommonStyle::subElementRect(sr, opt, widget); 4883 if (vopt->features & QStyleOptionViewItem::HasDecoration) 4884 rect.adjust(-fw, 0, 0, 0); 4885 } 4975 4886 break; 4976 default: 4887 case SE_ToolBoxTabContents: 4888 rect = QCommonStyle::subElementRect(sr, opt, widget); 4889 break; 4890 case SE_PushButtonContents: 4891 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 4892 // Unlike Carbon, we want the button to always be drawn inside its bounds. 4893 // Therefore, the button is a bit smaller, so that even if it got focus, 4894 // the focus 'shadow' will be inside. Adjust the content rect likewise. 4895 HIThemeButtonDrawInfo bdi; 4896 d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi); 4897 HIRect contentRect = d->pushButtonContentBounds(btn, &bdi); 4898 rect = qt_qrectForHIRect(contentRect); 4899 } 4900 break; 4901 case SE_HeaderLabel: { 4902 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); 4903 rect.setRect(opt->rect.x() + margin, opt->rect.y(), 4904 opt->rect.width() - margin * 2, opt->rect.height() - 2); 4905 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { 4906 // Subtract width needed for arrow, if there is one 4907 if (header->sortIndicator != QStyleOptionHeader::None) { 4908 if (opt->state & State_Horizontal) 4909 rect.setWidth(rect.width() - (opt->rect.height() / 2) - (margin * 2)); 4910 else 4911 rect.setHeight(rect.height() - (opt->rect.width() / 2) - (margin * 2)); 4912 } 4913 } 4914 rect = visualRect(opt->direction, opt->rect, rect); 4977 4915 break; 4978 4916 } 4979 rect = visualRect(twf->direction, twf->rect, rect); 4980 } 4981 break; 4982 case SE_TabWidgetRightCorner: 4983 if (const QStyleOptionTabWidgetFrame *twf 4984 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 4985 switch (twf->shape) { 4986 case QTabBar::RoundedNorth: 4987 case QTabBar::TriangularNorth: 4988 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0), 4989 twf->rightCornerWidgetSize); 4990 break; 4991 case QTabBar::RoundedSouth: 4992 case QTabBar::TriangularSouth: 4993 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 4994 twf->rect.height() - twf->rightCornerWidgetSize.height()), 4995 twf->rightCornerWidgetSize); 4917 case SE_ProgressBarGroove: 4918 // Wrong in the secondary dimension, but accurate enough in the main dimension. 4919 rect = opt->rect; 4996 4920 break; 4997 default: 4921 case SE_ProgressBarLabel: 4922 break; 4923 case SE_ProgressBarContents: 4924 rect = opt->rect; 4925 break; 4926 case SE_TreeViewDisclosureItem: { 4927 HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(), 4928 opt->rect.width(), opt->rect.height()); 4929 HIThemeButtonDrawInfo bdi; 4930 bdi.version = qt_mac_hitheme_version; 4931 bdi.state = kThemeStateActive; 4932 bdi.kind = kThemeDisclosureButton; 4933 bdi.value = kThemeDisclosureRight; 4934 bdi.adornment = kThemeAdornmentNone; 4935 HIRect contentRect; 4936 HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect); 4937 QCFType<HIShapeRef> shape; 4938 HIRect outRect; 4939 HIThemeGetButtonShape(&inRect, &bdi, &shape); 4940 ptrHIShapeGetBounds(shape, &outRect); 4941 rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y), 4942 int(contentRect.origin.x - outRect.origin.x + DisclosureOffset), 4943 int(outRect.size.height)); 4998 4944 break; 4999 4945 } 5000 rect = visualRect(twf->direction, twf->rect, rect); 5001 } 5002 break; 5003 case SE_TabWidgetTabContents: 5004 rect = QCommonStyle::subElementRect(sr, opt, widget); 5005 if (const QStyleOptionTabWidgetFrame *twf 5006 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 5007 if (twf->lineWidth != 0) { 5008 switch (getTabDirection(twf->shape)) { 5009 case kThemeTabNorth: 5010 rect.adjust(+1, +14, -1, -1); 5011 break; 5012 case kThemeTabSouth: 5013 rect.adjust(+1, +1, -1, -14); 5014 break; 5015 case kThemeTabWest: 5016 rect.adjust(+14, +1, -1, -1); 5017 break; 5018 case kThemeTabEast: 5019 rect.adjust(+1, +1, -14, -1); 4946 #ifndef QT_NO_TABWIDGET 4947 case SE_TabWidgetLeftCorner: 4948 if (const QStyleOptionTabWidgetFrame *twf 4949 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 4950 switch (twf->shape) { 4951 case QTabBar::RoundedNorth: 4952 case QTabBar::TriangularNorth: 4953 rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize); 4954 break; 4955 case QTabBar::RoundedSouth: 4956 case QTabBar::TriangularSouth: 4957 rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()), 4958 twf->leftCornerWidgetSize); 4959 break; 4960 default: 4961 break; 4962 } 4963 rect = visualRect(twf->direction, twf->rect, rect); 5020 4964 } 5021 }5022 }5023 break;5024 case SE_TabBarTabText:5025 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {5026 QRect dummyIconRect;5027 d->tabLayout(tab, widget, &rect, &dummyIconRect);5028 }5029 break;5030 case SE_TabBarTabLeftButton:5031 case SE_TabBarTabRightButton:5032 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {5033 bool selected = tab->state & State_Selected;5034 int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);5035 int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);5036 int hpadding = 5;5037 5038 bool verticalTabs = tab->shape == QTabBar::RoundedEast5039 || tab->shape == QTabBar::RoundedWest5040 || tab->shape == QTabBar::TriangularEast5041 || tab->shape == QTabBar::TriangularWest;5042 5043 QRect tr = tab->rect;5044 if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth)5045 verticalShift = -verticalShift;5046 if (verticalTabs) {5047 qSwap(horizontalShift, verticalShift);5048 horizontalShift *= -1;5049 verticalShift *= -1;5050 }5051 if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest)5052 horizontalShift = -horizontalShift;5053 5054 tr.adjust(0, 0, horizontalShift, verticalShift);5055 if (selected)5056 {5057 tr.setBottom(tr.bottom() - verticalShift);5058 tr.setRight(tr.right() - horizontalShift);5059 }5060 5061 QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize;5062 int w = size.width();5063 int h = size.height();5064 int midHeight = static_cast<int>(qCeil(float(tr.height() - h) / 2));5065 int midWidth = ((tr.width() - w) / 2);5066 5067 bool atTheTop = true;5068 switch (tab->shape) {5069 case QTabBar::RoundedWest:5070 case QTabBar::TriangularWest:5071 atTheTop = (sr == SE_TabBarTabLeftButton);5072 4965 break; 5073 case QTabBar::RoundedEast: 5074 case QTabBar::TriangularEast: 5075 atTheTop = (sr == SE_TabBarTabRightButton); 4966 case SE_TabWidgetRightCorner: 4967 if (const QStyleOptionTabWidgetFrame *twf 4968 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 4969 switch (twf->shape) { 4970 case QTabBar::RoundedNorth: 4971 case QTabBar::TriangularNorth: 4972 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0), 4973 twf->rightCornerWidgetSize); 4974 break; 4975 case QTabBar::RoundedSouth: 4976 case QTabBar::TriangularSouth: 4977 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 4978 twf->rect.height() - twf->rightCornerWidgetSize.height()), 4979 twf->rightCornerWidgetSize); 4980 break; 4981 default: 4982 break; 4983 } 4984 rect = visualRect(twf->direction, twf->rect, rect); 4985 } 4986 break; 4987 case SE_TabWidgetTabContents: 4988 rect = QCommonStyle::subElementRect(sr, opt, widget); 4989 if (const QStyleOptionTabWidgetFrame *twf 4990 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 4991 if (twf->lineWidth != 0) { 4992 switch (getTabDirection(twf->shape)) { 4993 case kThemeTabNorth: 4994 rect.adjust(+1, +14, -1, -1); 4995 break; 4996 case kThemeTabSouth: 4997 rect.adjust(+1, +1, -1, -14); 4998 break; 4999 case kThemeTabWest: 5000 rect.adjust(+14, +1, -1, -1); 5001 break; 5002 case kThemeTabEast: 5003 rect.adjust(+1, +1, -14, -1); 5004 } 5005 } 5006 } 5076 5007 break; 5077 default:5078 if (sr == SE_TabBarTabLeftButton)5079 rect = QRect(tab->rect.x() + hpadding, midHeight, w, h);5080 else5081 rect = QRect(tab->rect.right() - w - hpadding, midHeight, w, h);5082 rect = visualRect(tab->direction, tab->rect, rect);5083 }5084 if (verticalTabs) {5085 if (atTheTop)5086 rect = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h);5087 else5088 rect = QRect(midWidth, tr.y() + hpadding, w, h);5089 }5090 }5091 break;5092 #endif5093 case SE_LineEditContents:5094 rect = QCommonStyle::subElementRect(sr, opt, widget);5095 #if QT_CONFIG(combobox)5096 if (widget && qobject_cast<const QComboBox*>(widget->parentWidget()))5097 rect.adjust(-1, -2, 0, 0);5098 else5099 5008 #endif 5100 rect.adjust(-1, -1, 0, +1); 5101 break; 5102 case SE_CheckBoxLayoutItem: 5103 rect = opt->rect; 5104 if (controlSize == QAquaSizeLarge) { 5105 setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction); 5106 } else if (controlSize == QAquaSizeSmall) { 5107 setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction); 5108 } else { 5109 setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction); 5110 } 5111 break; 5112 case SE_ComboBoxLayoutItem: 5113 #ifndef QT_NO_TOOLBAR 5114 if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) { 5115 // Do nothing, because QToolbar needs the entire widget rect. 5116 // Otherwise it will be clipped. Equivalent to 5117 // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without 5118 // all the hassle. 5119 } else 5009 case SE_LineEditContents: 5010 rect = QCommonStyle::subElementRect(sr, opt, widget); 5011 #ifndef QT_NO_COMBOBOX 5012 if (widget && qobject_cast<const QComboBox*>(widget->parentWidget())) 5013 rect.adjust(-1, -2, 0, 0); 5014 else 5120 5015 #endif 5121 { 5122 rect = opt->rect; 5123 if (controlSize == QAquaSizeLarge) { 5124 rect.adjust(+3, +2, -3, -4); 5125 } else if (controlSize == QAquaSizeSmall) { 5126 setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction); 5127 } else { 5128 setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction); 5129 } 5130 } 5131 break; 5132 case SE_LabelLayoutItem: 5133 rect = opt->rect; 5134 setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction); 5135 break; 5136 case SE_ProgressBarLayoutItem: { 5137 rect = opt->rect; 5138 int bottom = SIZE(3, 8, 8); 5139 if (opt->state & State_Horizontal) { 5140 rect.adjust(0, +1, 0, -bottom); 5141 } else { 5142 setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction); 5143 } 5144 break; 5145 } 5146 case SE_PushButtonLayoutItem: 5147 if (const QStyleOptionButton *buttonOpt 5148 = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 5149 if ((buttonOpt->features & QStyleOptionButton::Flat)) 5150 break; // leave rect alone 5151 } 5152 rect = opt->rect; 5153 if (controlSize == QAquaSizeLarge) { 5154 rect.adjust(+6, +4, -6, -8); 5155 } else if (controlSize == QAquaSizeSmall) { 5156 rect.adjust(+5, +4, -5, -6); 5157 } else { 5158 rect.adjust(+1, 0, -1, -2); 5159 } 5160 break; 5161 case SE_RadioButtonLayoutItem: 5162 rect = opt->rect; 5163 if (controlSize == QAquaSizeLarge) { 5164 setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */, 5165 0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction); 5166 } else if (controlSize == QAquaSizeSmall) { 5167 rect.adjust(0, +6, 0 /* fix */, -5); 5168 } else { 5169 rect.adjust(0, +6, 0 /* fix */, -7); 5170 } 5171 break; 5172 case SE_SliderLayoutItem: 5173 if (const QStyleOptionSlider *sliderOpt 5174 = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 5175 rect = opt->rect; 5176 if (sliderOpt->tickPosition == QSlider::NoTicks) { 5177 int above = SIZE(3, 0, 2); 5178 int below = SIZE(4, 3, 0); 5179 if (sliderOpt->orientation == Qt::Horizontal) { 5180 rect.adjust(0, +above, 0, -below); 5181 } else { 5182 rect.adjust(+above, 0, -below, 0); //### Seems that QSlider flip the position of the ticks in reverse mode. 5183 } 5184 } else if (sliderOpt->tickPosition == QSlider::TicksAbove) { 5185 int below = SIZE(3, 2, 0); 5186 if (sliderOpt->orientation == Qt::Horizontal) { 5187 rect.setHeight(rect.height() - below); 5016 rect.adjust(-1, -1, 0, +1); 5017 break; 5018 case SE_CheckBoxLayoutItem: 5019 rect = opt->rect; 5020 if (controlSize == QAquaSizeLarge) { 5021 setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction); 5022 } else if (controlSize == QAquaSizeSmall) { 5023 setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction); 5188 5024 } else { 5189 rect.setWidth(rect.width() - below);5025 setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction); 5190 5026 } 5191 } else if (sliderOpt->tickPosition == QSlider::TicksBelow) { 5192 int above = SIZE(3, 2, 0); 5193 if (sliderOpt->orientation == Qt::Horizontal) { 5194 rect.setTop(rect.top() + above); 5195 } else { 5196 rect.setLeft(rect.left() + above); 5027 break; 5028 case SE_ComboBoxLayoutItem: 5029 #ifndef QT_NO_TOOLBAR 5030 if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) { 5031 // Do nothing, because QToolbar needs the entire widget rect. 5032 // Otherwise it will be clipped. Equivalent to 5033 // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without 5034 // all the hassle. 5035 } else 5036 #endif 5037 { 5038 rect = opt->rect; 5039 if (controlSize == QAquaSizeLarge) { 5040 rect.adjust(+3, +2, -3, -4); 5041 } else if (controlSize == QAquaSizeSmall) { 5042 setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction); 5043 } else { 5044 setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction); 5045 } 5197 5046 } 5198 }5199 }5200 break;5201 case SE_FrameLayoutItem:5202 // hack because QStyleOptionFrame doesn't have a frameStyle member5203 if (const QFrame *frame = qobject_cast<const QFrame *>(widget)) {5204 rect = opt->rect;5205 switch (frame->frameStyle() & QFrame::Shape_Mask) {5206 case QFrame::HLine:5207 rect.adjust(0, +1, 0, -1);5208 break;5209 case QFrame::VLine:5210 rect.adjust(+1, 0, -1, 0);5211 5047 break; 5212 default: 5213 ; 5214 } 5215 } 5216 break; 5217 case SE_GroupBoxLayoutItem: 5218 rect = opt->rect; 5219 if (const QStyleOptionGroupBox *groupBoxOpt = 5220 qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { 5221 /* 5222 AHIG is very inconsistent when it comes to group boxes. 5223 Basically, we make sure that (non-checkable) group boxes 5224 and tab widgets look good when laid out side by side. 5225 */ 5226 if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox 5227 | QStyle::SC_GroupBoxLabel)) { 5228 int delta; 5229 if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) { 5230 delta = SIZE(8, 4, 4); // guess 5048 case SE_LabelLayoutItem: 5049 rect = opt->rect; 5050 setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction); 5051 break; 5052 case SE_ProgressBarLayoutItem: { 5053 rect = opt->rect; 5054 int bottom = SIZE(3, 8, 8); 5055 if (opt->state & State_Horizontal) { 5056 rect.adjust(0, +1, 0, -bottom); 5231 5057 } else { 5232 delta = SIZE(15, 12, 12); // guess5058 setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction); 5233 5059 } 5234 rect.setTop(rect.top() + delta);5060 break; 5235 5061 } 5236 } 5237 rect.setBottom(rect.bottom() - 1); 5238 break; 5239 #if QT_CONFIG(tabwidget) 5240 case SE_TabWidgetLayoutItem: 5241 if (const QStyleOptionTabWidgetFrame *tabWidgetOpt = 5242 qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 5243 /* 5244 AHIG specifies "12 or 14" as the distance from the window 5245 edge. We choose 14 and since the default top margin is 20, 5246 the overlap is 6. 5247 */ 5248 rect = tabWidgetOpt->rect; 5249 if (tabWidgetOpt->shape == QTabBar::RoundedNorth) 5250 rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */)); 5251 } 5252 break; 5253 #endif 5254 #if QT_CONFIG(dockwidget) 5255 case SE_DockWidgetCloseButton: 5256 case SE_DockWidgetFloatButton: 5257 case SE_DockWidgetTitleBarText: 5258 case SE_DockWidgetIcon: { 5259 int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); 5260 int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); 5261 QRect srect = opt->rect; 5262 5263 const QStyleOptionDockWidget *dwOpt 5264 = qstyleoption_cast<const QStyleOptionDockWidget*>(opt); 5265 bool canClose = dwOpt == 0 ? true : dwOpt->closable; 5266 bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; 5267 5268 const bool verticalTitleBar = dwOpt->verticalTitleBar; 5269 5270 // If this is a vertical titlebar, we transpose and work as if it was 5271 // horizontal, then transpose again. 5272 if (verticalTitleBar) 5273 srect = srect.transposed(); 5274 5275 do { 5276 int right = srect.right(); 5277 int left = srect.left(); 5278 5279 QRect closeRect; 5280 if (canClose) { 5281 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, 5282 opt, widget).actualSize(QSize(iconSize, iconSize)); 5283 sz += QSize(buttonMargin, buttonMargin); 5284 if (verticalTitleBar) 5285 sz = sz.transposed(); 5286 closeRect = QRect(left, 5287 srect.center().y() - sz.height()/2, 5288 sz.width(), sz.height()); 5289 left = closeRect.right() + 1; 5290 } 5291 if (sr == SE_DockWidgetCloseButton) { 5292 rect = closeRect; 5293 break; 5294 } 5295 5296 QRect floatRect; 5297 if (canFloat) { 5298 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, 5299 opt, widget).actualSize(QSize(iconSize, iconSize)); 5300 sz += QSize(buttonMargin, buttonMargin); 5301 if (verticalTitleBar) 5302 sz = sz.transposed(); 5303 floatRect = QRect(left, 5304 srect.center().y() - sz.height()/2, 5305 sz.width(), sz.height()); 5306 left = floatRect.right() + 1; 5307 } 5308 if (sr == SE_DockWidgetFloatButton) { 5309 rect = floatRect; 5310 break; 5062 case SE_PushButtonLayoutItem: 5063 if (const QStyleOptionButton *buttonOpt 5064 = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 5065 if ((buttonOpt->features & QStyleOptionButton::Flat)) 5066 break; // leave rect alone 5311 5067 } 5312 5313 QRect iconRect; 5314 if (const QDockWidget *dw = qobject_cast<const QDockWidget*>(widget)) { 5315 QIcon icon; 5316 if (dw->isFloating()) 5317 icon = dw->windowIcon(); 5318 if (!icon.isNull() 5319 && icon.cacheKey() != QApplication::windowIcon().cacheKey()) { 5320 QSize sz = icon.actualSize(QSize(rect.height(), rect.height())); 5321 if (verticalTitleBar) 5322 sz = sz.transposed(); 5323 iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2, 5324 sz.width(), sz.height()); 5325 right = iconRect.left() - 1; 5326 } 5327 } 5328 if (sr == SE_DockWidgetIcon) { 5329 rect = iconRect; 5330 break; 5331 } 5332 5333 QRect textRect = QRect(left, srect.top(), 5334 right - left, srect.height()); 5335 if (sr == SE_DockWidgetTitleBarText) { 5336 rect = textRect; 5337 break; 5068 rect = opt->rect; 5069 if (controlSize == QAquaSizeLarge) { 5070 rect.adjust(+6, +4, -6, -8); 5071 } else if (controlSize == QAquaSizeSmall) { 5072 rect.adjust(+5, +4, -5, -6); 5073 } else { 5074 rect.adjust(+1, 0, -1, -2); 5338 5075 } 5339 } while (false); 5340 5341 if (verticalTitleBar) { 5342 rect = QRect(srect.left() + rect.top() - srect.top(), 5343 srect.top() + srect.right() - rect.right(), 5344 rect.height(), rect.width()); 5345 } else { 5346 rect = visualRect(opt->direction, srect, rect); 5347 } 5348 break; 5349 } 5350 #endif 5351 default: 5352 rect = QCommonStyle::subElementRect(sr, opt, widget); 5353 break; 5354 } 5355 return rect; 5356 } 5357 5358 static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg) 5359 { 5360 QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5); 5361 HIThemePopupArrowDrawInfo padi; 5362 padi.version = qt_mac_hitheme_version; 5363 padi.state = tds; 5364 padi.orientation = kThemeArrowDown; 5365 padi.size = kThemeArrow7pt; 5366 HIRect hirect = qt_hirectForQRect(arrowRect); 5367 HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); 5368 } 5369 5370 void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, 5371 const QWidget *widget) const 5372 { 5373 Q_D(const QMacStyle); 5374 ThemeDrawState tds = d->getDrawState(opt->state); 5375 QMacCGContext cg(p); 5376 QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : 5377 QStyleHelper::styleObjectWindow(opt->styleObject); 5378 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 5379 switch (cc) { 5380 case CC_Slider: 5381 case CC_ScrollBar: 5382 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 5383 HIThemeTrackDrawInfo tdi; 5384 d->getSliderInfo(cc, slider, &tdi, widget); 5385 if (slider->state & State_Sunken) { 5386 if (cc == CC_Slider) { 5387 if (slider->activeSubControls == SC_SliderHandle) 5388 tdi.trackInfo.slider.pressState = kThemeThumbPressed; 5389 else if (slider->activeSubControls == SC_SliderGroove) 5390 tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed; 5076 break; 5077 case SE_RadioButtonLayoutItem: 5078 rect = opt->rect; 5079 if (controlSize == QAquaSizeLarge) { 5080 setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */, 5081 0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction); 5082 } else if (controlSize == QAquaSizeSmall) { 5083 rect.adjust(0, +6, 0 /* fix */, -5); 5391 5084 } else { 5392 if (slider->activeSubControls == SC_ScrollBarSubLine 5393 || slider->activeSubControls == SC_ScrollBarAddLine) { 5394 // This test looks complex but it basically boils down 5395 // to the following: The "RTL look" on the mac also 5396 // changed the directions of the controls, that's not 5397 // what people expect (an arrow is an arrow), so we 5398 // kind of fake and say the opposite button is hit. 5399 // This works great, up until 10.4 which broke the 5400 // scroll bars, so I also have actually do something 5401 // similar when I have an upside down scroll bar 5402 // because on Tiger I only "fake" the reverse stuff. 5403 bool reverseHorizontal = (slider->direction == Qt::RightToLeft 5404 && slider->orientation == Qt::Horizontal); 5405 5406 if ((reverseHorizontal 5407 && slider->activeSubControls == SC_ScrollBarAddLine) 5408 || (!reverseHorizontal 5409 && slider->activeSubControls == SC_ScrollBarSubLine)) { 5410 tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed 5411 | kThemeLeftOutsideArrowPressed; 5412 } else { 5413 tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed 5414 | kThemeRightOutsideArrowPressed; 5415 } 5416 } else if (slider->activeSubControls == SC_ScrollBarAddPage) { 5417 tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed; 5418 } else if (slider->activeSubControls == SC_ScrollBarSubPage) { 5419 tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed; 5420 } else if (slider->activeSubControls == SC_ScrollBarSlider) { 5421 tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed; 5422 } 5085 rect.adjust(0, +6, 0 /* fix */, -7); 5423 5086 } 5424 } 5425 HIRect macRect; 5426 bool tracking = slider->sliderPosition == slider->sliderValue; 5427 if (!tracking) { 5428 // Small optimization, the same as q->subControlRect 5429 QCFType<HIShapeRef> shape; 5430 HIThemeGetTrackThumbShape(&tdi, &shape); 5431 ptrHIShapeGetBounds(shape, &macRect); 5432 tdi.value = slider->sliderValue; 5433 } 5434 5435 // Remove controls from the scroll bar if it is to short to draw them correctly. 5436 // This is done in two stages: first the thumb indicator is removed when it is 5437 // no longer possible to move it, second the up/down buttons are removed when 5438 // there is not enough space for them. 5439 if (cc == CC_ScrollBar) { 5440 if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject)) 5441 QMacStylePrivate::scrollBars.append(QPointer<QObject>(opt->styleObject)); 5442 const int scrollBarLength = (slider->orientation == Qt::Horizontal) 5443 ? slider->rect.width() : slider->rect.height(); 5444 const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget, opt); 5445 if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy)) 5446 tdi.attributes &= ~kThemeTrackShowThumb; 5447 if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) 5448 tdi.enableState = kThemeTrackNothingToScroll; 5449 } else { 5450 if (!(slider->subControls & SC_SliderHandle)) 5451 tdi.attributes &= ~kThemeTrackShowThumb; 5452 if (!(slider->subControls & SC_SliderGroove)) 5453 tdi.attributes |= kThemeTrackHideTrack; 5454 } 5455 5456 const bool isHorizontal = slider->orientation == Qt::Horizontal; 5457 5458 if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { 5459 bool wasActive = false; 5460 CGFloat opacity = 0.0; 5461 CGFloat expandScale = 1.0; 5462 CGFloat expandOffset = -1.0; 5463 bool shouldExpand = false; 5464 const CGFloat maxExpandScale = tdi.kind == kThemeSmallScrollBar ? 11.0 / 7.0 : 13.0 / 9.0; 5465 5466 if (QObject *styleObject = opt->styleObject) { 5467 int oldPos = styleObject->property("_q_stylepos").toInt(); 5468 int oldMin = styleObject->property("_q_stylemin").toInt(); 5469 int oldMax = styleObject->property("_q_stylemax").toInt(); 5470 QRect oldRect = styleObject->property("_q_stylerect").toRect(); 5471 QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>()); 5472 uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); 5473 5474 // a scrollbar is transient when the scrollbar itself and 5475 // its sibling are both inactive (ie. not pressed/hovered/moved) 5476 bool transient = !opt->activeSubControls && !(slider->state & State_On); 5477 5478 if (!transient || 5479 oldPos != slider->sliderPosition || 5480 oldMin != slider->minimum || 5481 oldMax != slider->maximum || 5482 oldRect != slider->rect || 5483 oldState != slider->state || 5484 oldActiveControls != slider->activeSubControls) { 5485 5486 // if the scrollbar is transient or its attributes, geometry or 5487 // state has changed, the opacity is reset back to 100% opaque 5488 opacity = 1.0; 5489 5490 styleObject->setProperty("_q_stylepos", slider->sliderPosition); 5491 styleObject->setProperty("_q_stylemin", slider->minimum); 5492 styleObject->setProperty("_q_stylemax", slider->maximum); 5493 styleObject->setProperty("_q_stylerect", slider->rect); 5494 styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(slider->state)); 5495 styleObject->setProperty("_q_stylecontrols", static_cast<uint>(slider->activeSubControls)); 5496 5497 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject)); 5498 if (transient) { 5499 if (!anim) { 5500 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject); 5501 d->startAnimation(anim); 5502 } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5503 // the scrollbar was already fading out while the 5504 // state changed -> restart the fade out animation 5505 anim->setCurrentTime(0); 5506 } 5507 } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5508 d->stopAnimation(styleObject); 5087 break; 5088 case SE_SliderLayoutItem: 5089 if (const QStyleOptionSlider *sliderOpt 5090 = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 5091 rect = opt->rect; 5092 if (sliderOpt->tickPosition == QSlider::NoTicks) { 5093 int above = SIZE(3, 0, 2); 5094 int below = SIZE(4, 3, 0); 5095 if (sliderOpt->orientation == Qt::Horizontal) { 5096 rect.adjust(0, +above, 0, -below); 5097 } else { 5098 rect.adjust(+above, 0, -below, 0); //### Seems that QSlider flip the position of the ticks in reverse mode. 5509 5099 } 5510 } 5511 5512 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject)); 5513 if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5514 // once a scrollbar was active (hovered/pressed), it retains 5515 // the active look even if it's no longer active while fading out 5516 if (oldActiveControls) 5517 anim->setActive(true); 5518 5519 wasActive = anim->wasActive(); 5520 opacity = anim->currentValue(); 5521 } 5522 5523 shouldExpand = (opt->activeSubControls || wasActive); 5524 if (shouldExpand) { 5525 if (!anim && !oldActiveControls) { 5526 // Start expand animation only once and when entering 5527 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject); 5528 d->startAnimation(anim); 5100 } else if (sliderOpt->tickPosition == QSlider::TicksAbove) { 5101 int below = SIZE(3, 2, 0); 5102 if (sliderOpt->orientation == Qt::Horizontal) { 5103 rect.setHeight(rect.height() - below); 5104 } else { 5105 rect.setWidth(rect.width() - below); 5529 5106 } 5530 if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) { 5531 expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue(); 5532 expandOffset = 5.5 * anim->currentValue() - 1; 5107 } else if (sliderOpt->tickPosition == QSlider::TicksBelow) { 5108 int above = SIZE(3, 2, 0); 5109 if (sliderOpt->orientation == Qt::Horizontal) { 5110 rect.setTop(rect.top() + above); 5533 5111 } else { 5534 // Keep expanded state after the animation ends, and when fading out 5535 expandScale = maxExpandScale; 5536 expandOffset = 4.5; 5112 rect.setLeft(rect.left() + above); 5537 5113 } 5538 5114 } 5539 5115 } 5540 5541 CGContextSaveGState(cg); 5542 [NSGraphicsContext saveGraphicsState]; 5543 5544 [NSGraphicsContext setCurrentContext:[NSGraphicsContext 5545 graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; 5546 NSScroller *scroller = isHorizontal ? d->horizontalScroller : d-> verticalScroller; 5547 // mac os behaviour: as soon as one color channel is >= 128, 5548 // the bg is considered bright, scroller is dark 5549 const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); 5550 const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && 5551 bgColor.blue() < 128; 5552 if (isDarkBg) 5553 [scroller setKnobStyle:NSScrollerKnobStyleLight]; 5554 else 5555 [scroller setKnobStyle:NSScrollerKnobStyleDefault]; 5556 5557 [scroller setControlSize:(tdi.kind == kThemeSmallScrollBar ? NSMiniControlSize 5558 : NSRegularControlSize)]; 5559 [scroller setBounds:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; 5560 [scroller setScrollerStyle:NSScrollerStyleOverlay]; 5561 5562 CGContextBeginTransparencyLayer(cg, NULL); 5563 CGContextSetAlpha(cg, opacity); 5564 5565 // Draw the track when hovering 5566 if (opt->activeSubControls || wasActive) { 5567 NSRect rect = [scroller bounds]; 5568 if (shouldExpand) { 5569 if (isHorizontal) 5570 rect.origin.y += 4.5 - expandOffset; 5571 else 5572 rect.origin.x += 4.5 - expandOffset; 5573 } 5574 [scroller drawKnobSlotInRect:rect highlight:YES]; 5575 } 5576 5577 const qreal length = slider->maximum - slider->minimum + slider->pageStep; 5578 const qreal proportion = slider->pageStep / length; 5579 qreal value = (slider->sliderValue - slider->minimum) / length; 5580 if (isHorizontal && slider->direction == Qt::RightToLeft) 5581 value = 1.0 - value - proportion; 5582 5583 [scroller setKnobProportion:1.0]; 5584 5585 const int minKnobWidth = 26; 5586 5587 if (isHorizontal) { 5588 const qreal plannedWidth = proportion * slider->rect.width(); 5589 const qreal width = qMax<qreal>(minKnobWidth, plannedWidth); 5590 const qreal totalWidth = slider->rect.width() + plannedWidth - width; 5591 [scroller setFrame:NSMakeRect(0, 0, width, slider->rect.height())]; 5592 if (shouldExpand) { 5593 CGContextScaleCTM(cg, 1, expandScale); 5594 CGContextTranslateCTM(cg, value * totalWidth, -expandOffset); 5595 } else { 5596 CGContextTranslateCTM(cg, value * totalWidth, 1); 5597 } 5598 } else { 5599 const qreal plannedHeight = proportion * slider->rect.height(); 5600 const qreal height = qMax<qreal>(minKnobWidth, plannedHeight); 5601 const qreal totalHeight = slider->rect.height() + plannedHeight - height; 5602 [scroller setFrame:NSMakeRect(0, 0, slider->rect.width(), height)]; 5603 if (shouldExpand) { 5604 CGContextScaleCTM(cg, expandScale, 1); 5605 CGContextTranslateCTM(cg, -expandOffset, value * totalHeight); 5606 } else { 5607 CGContextTranslateCTM(cg, 1, value * totalHeight); 5608 } 5609 } 5610 if (length > 0.0) { 5611 [scroller layout]; 5612 [scroller drawKnob]; 5613 } 5614 5615 CGContextEndTransparencyLayer(cg); 5616 5617 [NSGraphicsContext restoreGraphicsState]; 5618 CGContextRestoreGState(cg); 5619 } else { 5620 d->stopAnimation(opt->styleObject); 5621 5622 if (cc == CC_Slider) { 5623 // Fix min and max positions. (See also getSliderInfo() 5624 // for the slider values adjustments.) 5625 // HITheme seems to have forgotten how to render 5626 // a slide at those positions, leaving a gap between 5627 // the knob and the ends of the track. 5628 // We fix this by rendering the track first, and then 5629 // the knob on top. However, in order to not clip the 5630 // knob, we reduce the the drawing rect for the track. 5631 HIRect bounds = tdi.bounds; 5632 if (isHorizontal) { 5633 tdi.bounds.size.width -= 2; 5634 tdi.bounds.origin.x += 1; 5635 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) 5636 tdi.bounds.origin.y -= 2; 5637 else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) 5638 tdi.bounds.origin.y += 3; 5639 } else { 5640 tdi.bounds.size.height -= 2; 5641 tdi.bounds.origin.y += 1; 5642 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right 5643 tdi.bounds.origin.x -= 4; 5644 else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left 5645 tdi.bounds.origin.x += 2; 5646 } 5647 5648 // Yosemite demands its blue progress track when no tickmarks are present 5649 if (!(slider->subControls & SC_SliderTickmarks)) { 5650 QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; 5651 QCocoaWidget cw = QCocoaWidget(sliderKind, QAquaSizeLarge); 5652 NSSlider *sl = (NSSlider *)d->cocoaControl(cw); 5653 sl.minValue = slider->minimum; 5654 sl.maxValue = slider->maximum; 5655 sl.intValue = slider->sliderValue; 5656 sl.enabled = slider->state & QStyle::State_Enabled; 5657 d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(NSRect rect, CGContextRef ctx) { 5658 const bool isSierraOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra; 5659 if (slider->upsideDown) { 5660 if (isHorizontal) { 5661 CGContextTranslateCTM(ctx, rect.size.width, 0); 5662 CGContextScaleCTM(ctx, -1, 1); 5663 } 5664 } else if (!isHorizontal && !isSierraOrLater) { 5665 CGContextTranslateCTM(ctx, 0, rect.size.height); 5666 CGContextScaleCTM(ctx, 1, -1); 5667 } 5668 const bool shouldFlip = isHorizontal || (slider->upsideDown && isSierraOrLater); 5669 [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:shouldFlip]; 5670 // No need to restore the CTM later, the context has been saved 5671 // and will be restored at the end of drawNSViewInRect() 5672 }); 5673 tdi.attributes |= kThemeTrackHideTrack; 5674 } else { 5675 tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus); 5676 HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, 5677 kHIThemeOrientationNormal); 5678 tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb; 5116 break; 5117 case SE_FrameLayoutItem: 5118 // hack because QStyleOptionFrame doesn't have a frameStyle member 5119 if (const QFrame *frame = qobject_cast<const QFrame *>(widget)) { 5120 rect = opt->rect; 5121 switch (frame->frameStyle() & QFrame::Shape_Mask) { 5122 case QFrame::HLine: 5123 rect.adjust(0, +1, 0, -1); 5124 break; 5125 case QFrame::VLine: 5126 rect.adjust(+1, 0, -1, 0); 5127 break; 5128 default: 5129 ; 5679 5130 } 5680 5681 tdi.bounds = bounds;5682 5131 } 5683 5684 if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { 5685 5686 HIRect bounds; 5687 // As part of fixing the min and max positions, 5688 // we need to adjust the tickmarks as well 5689 bounds = tdi.bounds; 5690 if (slider->orientation == Qt::Horizontal) { 5691 tdi.bounds.size.width += 2; 5692 tdi.bounds.origin.x -= 1; 5693 if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) 5694 tdi.bounds.origin.y -= 2; 5695 } else { 5696 tdi.bounds.size.height += 3; 5697 tdi.bounds.origin.y -= 3; 5698 tdi.bounds.origin.y += 1; 5699 if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left 5700 tdi.bounds.origin.x -= 2; 5701 } 5702 5703 if (qt_mac_is_metal(widget)) { 5704 if (tdi.enableState == kThemeTrackInactive) 5705 tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like 5706 } 5707 int interval = slider->tickInterval; 5708 if (interval == 0) { 5709 interval = slider->pageStep; 5710 if (interval == 0) 5711 interval = slider->singleStep; 5712 if (interval == 0) 5713 interval = 1; 5714 } 5715 int numMarks = 1 + ((slider->maximum - slider->minimum) / interval); 5716 5717 if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) { 5718 // They asked for both, so we'll give it to them. 5719 tdi.trackInfo.slider.thumbDir = kThemeThumbDownward; 5720 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5721 cg, 5722 kHIThemeOrientationNormal); 5723 tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; 5724 // 10.10 and above need a slight shift 5725 if (slider->orientation == Qt::Vertical) 5726 tdi.bounds.origin.x -= 2; 5727 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5728 cg, 5729 kHIThemeOrientationNormal); 5730 // Reset to plain thumb to be drawn further down 5731 tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; 5732 } else { 5733 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5734 cg, 5735 kHIThemeOrientationNormal); 5132 break; 5133 case SE_GroupBoxLayoutItem: 5134 rect = opt->rect; 5135 if (const QStyleOptionGroupBox *groupBoxOpt = 5136 qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { 5137 /* 5138 AHIG is very inconsistent when it comes to group boxes. 5139 Basically, we make sure that (non-checkable) group boxes 5140 and tab widgets look good when laid out side by side. 5141 */ 5142 if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox 5143 | QStyle::SC_GroupBoxLabel)) { 5144 int delta; 5145 if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) { 5146 delta = SIZE(8, 4, 4); // guess 5147 } else { 5148 delta = SIZE(15, 12, 12); // guess 5149 } 5150 rect.setTop(rect.top() + delta); 5736 5151 } 5737 5738 tdi.bounds = bounds;5739 5152 } 5740 5741 if (cc == CC_Slider) { 5742 // Still as part of fixing the min and max positions, 5743 // we also adjust the knob position. We can do this 5744 // because it's rendered separately from the track. 5745 if (slider->orientation == Qt::Vertical) { 5746 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right 5747 tdi.bounds.origin.x -= 2; 5748 } 5153 rect.setBottom(rect.bottom() - 1); 5154 break; 5155 #ifndef QT_NO_TABWIDGET 5156 case SE_TabWidgetLayoutItem: 5157 if (const QStyleOptionTabWidgetFrame *tabWidgetOpt = 5158 qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 5159 /* 5160 AHIG specifies "12 or 14" as the distance from the window 5161 edge. We choose 14 and since the default top margin is 20, 5162 the overlap is 6. 5163 */ 5164 rect = tabWidgetOpt->rect; 5165 if (tabWidgetOpt->shape == QTabBar::RoundedNorth) 5166 rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */)); 5749 5167 } 5750 5751 HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, 5752 kHIThemeOrientationNormal); 5753 } 5754 } 5755 break; 5756 #if QT_CONFIG(spinbox) 5757 case CC_SpinBox: 5758 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 5759 QStyleOptionSpinBox newSB = *sb; 5760 if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { 5761 SInt32 frame_size; 5762 GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); 5763 5764 QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); 5765 lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size); 5766 5767 HIThemeFrameDrawInfo fdi; 5768 fdi.version = qt_mac_hitheme_version; 5769 fdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; 5770 fdi.kind = kHIThemeFrameTextFieldSquare; 5771 fdi.isFocused = false; 5772 HIRect hirect = qt_hirectForQRect(lineeditRect); 5773 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); 5774 } 5775 if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { 5776 HIThemeButtonDrawInfo bdi; 5777 bdi.version = qt_mac_hitheme_version; 5778 QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget); 5779 switch (aquaSize) { 5780 case QAquaSizeUnknown: 5781 case QAquaSizeLarge: 5782 bdi.kind = kThemeIncDecButton; 5168 break; 5169 #endif 5170 #ifndef QT_NO_DOCKWIDGET 5171 case SE_DockWidgetCloseButton: 5172 case SE_DockWidgetFloatButton: 5173 case SE_DockWidgetTitleBarText: 5174 case SE_DockWidgetIcon: { 5175 int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); 5176 int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); 5177 QRect srect = opt->rect; 5178 5179 const QStyleOptionDockWidget *dwOpt 5180 = qstyleoption_cast<const QStyleOptionDockWidget*>(opt); 5181 bool canClose = dwOpt == 0 ? true : dwOpt->closable; 5182 bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; 5183 5184 const bool verticalTitleBar = dwOpt->verticalTitleBar; 5185 5186 // If this is a vertical titlebar, we transpose and work as if it was 5187 // horizontal, then transpose again. 5188 if (verticalTitleBar) 5189 srect = srect.transposed(); 5190 5191 do { 5192 int right = srect.right(); 5193 int left = srect.left(); 5194 5195 QRect closeRect; 5196 if (canClose) { 5197 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, 5198 opt, widget).actualSize(QSize(iconSize, iconSize)); 5199 sz += QSize(buttonMargin, buttonMargin); 5200 if (verticalTitleBar) 5201 sz = sz.transposed(); 5202 closeRect = QRect(left, 5203 srect.center().y() - sz.height()/2, 5204 sz.width(), sz.height()); 5205 left = closeRect.right() + 1; 5206 } 5207 if (sr == SE_DockWidgetCloseButton) { 5208 rect = closeRect; 5783 5209 break; 5784 case QAquaSizeMini: 5785 bdi.kind = kThemeIncDecButtonMini; 5210 } 5211 5212 QRect floatRect; 5213 if (canFloat) { 5214 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, 5215 opt, widget).actualSize(QSize(iconSize, iconSize)); 5216 sz += QSize(buttonMargin, buttonMargin); 5217 if (verticalTitleBar) 5218 sz = sz.transposed(); 5219 floatRect = QRect(left, 5220 srect.center().y() - sz.height()/2, 5221 sz.width(), sz.height()); 5222 left = floatRect.right() + 1; 5223 } 5224 if (sr == SE_DockWidgetFloatButton) { 5225 rect = floatRect; 5786 5226 break; 5787 case QAquaSizeSmall: 5788 bdi.kind = kThemeIncDecButtonSmall; 5227 } 5228 5229 QRect iconRect; 5230 if (const QDockWidget *dw = qobject_cast<const QDockWidget*>(widget)) { 5231 QIcon icon; 5232 if (dw->isFloating()) 5233 icon = dw->windowIcon(); 5234 if (!icon.isNull() 5235 && icon.cacheKey() != QApplication::windowIcon().cacheKey()) { 5236 QSize sz = icon.actualSize(QSize(rect.height(), rect.height())); 5237 if (verticalTitleBar) 5238 sz = sz.transposed(); 5239 iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2, 5240 sz.width(), sz.height()); 5241 right = iconRect.left() - 1; 5242 } 5243 } 5244 if (sr == SE_DockWidgetIcon) { 5245 rect = iconRect; 5246 break; 5247 } 5248 5249 QRect textRect = QRect(left, srect.top(), 5250 right - left, srect.height()); 5251 if (sr == SE_DockWidgetTitleBarText) { 5252 rect = textRect; 5789 5253 break; 5254 } 5255 } while (false); 5256 5257 if (verticalTitleBar) { 5258 rect = QRect(srect.left() + rect.top() - srect.top(), 5259 srect.top() + srect.right() - rect.right(), 5260 rect.height(), rect.width()); 5261 } else { 5262 rect = visualRect(opt->direction, srect, rect); 5790 5263 } 5791 if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled 5792 | QAbstractSpinBox::StepDownEnabled))) 5793 tds = kThemeStateUnavailable; 5794 if (sb->activeSubControls == SC_SpinBoxDown 5795 && (sb->state & State_Sunken)) 5796 tds = kThemeStatePressedDown; 5797 else if (sb->activeSubControls == SC_SpinBoxUp 5798 && (sb->state & State_Sunken)) 5799 tds = kThemeStatePressedUp; 5800 if (tds == kThemeStateInactive) 5801 bdi.state = kThemeStateActive; 5802 else 5803 bdi.state = tds; 5804 bdi.value = kThemeButtonOff; 5805 bdi.adornment = kThemeAdornmentNone; 5806 5807 QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); 5808 5809 updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); 5810 HIRect newRect = qt_hirectForQRect(updown); 5811 QRect off_rct; 5812 HIRect outRect; 5813 HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect); 5814 off_rct.setRect(int(newRect.origin.x - outRect.origin.x), 5815 int(newRect.origin.y - outRect.origin.y), 5816 int(outRect.size.width - newRect.size.width), 5817 int(outRect.size.height - newRect.size.height)); 5818 5819 newRect = qt_hirectForQRect(updown, off_rct); 5820 if (tds == kThemeStateInactive) 5821 d->drawColorlessButton(newRect, &bdi, p, sb); 5822 else 5823 HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); 5264 break; 5824 5265 } 5825 }5826 break;5827 5266 #endif 5828 case CC_ComboBox: 5829 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){ 5830 HIThemeButtonDrawInfo bdi; 5831 d->initComboboxBdi(combo, &bdi, widget, tds); 5832 HIRect rect = qt_hirectForQRect(combo->rect); 5833 if (combo->editable) 5834 rect.origin.y += tds == kThemeStateInactive ? 1 : 2; 5835 if (tds != kThemeStateInactive) 5836 QMacStylePrivate::drawCombobox(rect, bdi, p); 5837 else if (!widget && combo->editable) { 5838 QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); 5839 NSView *cb = d->cocoaControl(cw); 5840 QRect r = combo->rect.adjusted(3, 0, 0, 0); 5841 d->drawNSViewInRect(cw, cb, r, p, widget != 0); 5842 } else 5843 d->drawColorlessButton(rect, &bdi, p, opt); 5267 default: 5268 rect = QCommonStyle::subElementRect(sr, opt, widget); 5269 break; 5844 5270 } 5845 break; 5846 case CC_TitleBar: 5847 if (const QStyleOptionTitleBar *titlebar 5848 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { 5849 if (titlebar->state & State_Active) { 5850 if (titlebar->titleBarState & State_Active) 5851 tds = kThemeStateActive; 5852 else 5853 tds = kThemeStateInactive; 5854 } else { 5855 tds = kThemeStateInactive; 5856 } 5857 5858 HIThemeWindowDrawInfo wdi; 5859 wdi.version = qt_mac_hitheme_version; 5860 wdi.state = tds; 5861 wdi.windowType = QtWinType; 5862 wdi.titleHeight = titlebar->rect.height(); 5863 wdi.titleWidth = titlebar->rect.width(); 5864 wdi.attributes = kThemeWindowHasTitleText; 5865 // It seems HIThemeDrawTitleBarWidget is not able to draw a dirty 5866 // close button, so use HIThemeDrawWindowFrame instead. 5867 if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton) 5868 wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty; 5869 5870 HIRect titleBarRect; 5871 HIRect tmpRect = qt_hirectForQRect(titlebar->rect); 5872 { 5873 QCFType<HIShapeRef> titleRegion; 5874 QRect newr = titlebar->rect.adjusted(0, 0, 2, 0); 5875 HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); 5876 ptrHIShapeGetBounds(titleRegion, &tmpRect); 5877 newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); 5878 titleBarRect = qt_hirectForQRect(newr); 5879 } 5880 HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); 5881 if (titlebar->subControls & (SC_TitleBarCloseButton 5882 | SC_TitleBarMaxButton 5883 | SC_TitleBarMinButton 5884 | SC_TitleBarNormalButton)) { 5885 HIThemeWindowWidgetDrawInfo wwdi; 5886 wwdi.version = qt_mac_hitheme_version; 5887 wwdi.widgetState = tds; 5888 if (titlebar->state & State_MouseOver) 5889 wwdi.widgetState = kThemeStateRollover; 5890 wwdi.windowType = QtWinType; 5891 wwdi.attributes = wdi.attributes | kThemeWindowHasFullZoom | kThemeWindowHasCloseBox | kThemeWindowHasCollapseBox; 5892 wwdi.windowState = wdi.state; 5893 wwdi.titleHeight = wdi.titleHeight; 5894 wwdi.titleWidth = wdi.titleWidth; 5895 ThemeDrawState savedControlState = wwdi.widgetState; 5896 uint sc = SC_TitleBarMinButton; 5897 ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox; 5898 bool active = titlebar->state & State_Active; 5899 5900 while (sc <= SC_TitleBarCloseButton) { 5901 if (sc & titlebar->subControls) { 5902 uint tmp = sc; 5903 wwdi.widgetState = savedControlState; 5904 wwdi.widgetType = tbw; 5905 if (sc == SC_TitleBarMinButton) 5906 tmp |= SC_TitleBarNormalButton; 5907 if (active && (titlebar->activeSubControls & tmp) 5908 && (titlebar->state & State_Sunken)) 5909 wwdi.widgetState = kThemeStatePressed; 5910 // Draw all sub controllers except the dirty close button 5911 // (it is already handled by HIThemeDrawWindowFrame). 5912 if (!(widget && widget->isWindowModified() && tbw == kThemeWidgetCloseBox)) { 5913 HIThemeDrawTitleBarWidget(&titleBarRect, &wwdi, cg, kHIThemeOrientationNormal); 5914 p->paintEngine()->syncState(); 5271 return rect; 5272 } 5273 5274 static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg) 5275 { 5276 QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5); 5277 HIThemePopupArrowDrawInfo padi; 5278 padi.version = qt_mac_hitheme_version; 5279 padi.state = tds; 5280 padi.orientation = kThemeArrowDown; 5281 padi.size = kThemeArrow7pt; 5282 HIRect hirect = qt_hirectForQRect(arrowRect); 5283 HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); 5284 } 5285 5286 void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, 5287 const QWidget *widget) const 5288 { 5289 Q_D(const QMacStyle); 5290 ThemeDrawState tds = d->getDrawState(opt->state); 5291 QMacCGContext cg(p); 5292 QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : 5293 QStyleHelper::styleObjectWindow(opt->styleObject); 5294 const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); 5295 const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; 5296 switch (cc) { 5297 case CC_Slider: 5298 case CC_ScrollBar: 5299 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 5300 HIThemeTrackDrawInfo tdi; 5301 d->getSliderInfo(cc, slider, &tdi, widget); 5302 if (slider->state & State_Sunken) { 5303 if (cc == CC_Slider) { 5304 if (slider->activeSubControls == SC_SliderHandle) 5305 tdi.trackInfo.slider.pressState = kThemeThumbPressed; 5306 else if (slider->activeSubControls == SC_SliderGroove) 5307 tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed; 5308 } else { 5309 if (slider->activeSubControls == SC_ScrollBarSubLine 5310 || slider->activeSubControls == SC_ScrollBarAddLine) { 5311 // This test looks complex but it basically boils down 5312 // to the following: The "RTL look" on the mac also 5313 // changed the directions of the controls, that's not 5314 // what people expect (an arrow is an arrow), so we 5315 // kind of fake and say the opposite button is hit. 5316 // This works great, up until 10.4 which broke the 5317 // scroll bars, so I also have actually do something 5318 // similar when I have an upside down scroll bar 5319 // because on Tiger I only "fake" the reverse stuff. 5320 bool reverseHorizontal = (slider->direction == Qt::RightToLeft 5321 && slider->orientation == Qt::Horizontal); 5322 5323 if ((reverseHorizontal 5324 && slider->activeSubControls == SC_ScrollBarAddLine) 5325 || (!reverseHorizontal 5326 && slider->activeSubControls == SC_ScrollBarSubLine)) { 5327 tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed 5328 | kThemeLeftOutsideArrowPressed; 5329 } else { 5330 tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed 5331 | kThemeRightOutsideArrowPressed; 5332 } 5333 } else if (slider->activeSubControls == SC_ScrollBarAddPage) { 5334 tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed; 5335 } else if (slider->activeSubControls == SC_ScrollBarSubPage) { 5336 tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed; 5337 } else if (slider->activeSubControls == SC_ScrollBarSlider) { 5338 tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed; 5339 } 5915 5340 } 5916 5341 } 5917 sc = sc << 1; 5918 tbw = tbw >> 1; 5919 } 5920 } 5921 p->paintEngine()->syncState(); 5922 if (titlebar->subControls & SC_TitleBarLabel) { 5923 int iw = 0; 5924 if (!titlebar->icon.isNull()) { 5925 QCFType<HIShapeRef> titleRegion2; 5926 HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn, 5927 &titleRegion2); 5928 ptrHIShapeGetBounds(titleRegion2, &tmpRect); 5929 if (tmpRect.size.width != 1) { 5930 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 5931 iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width(); 5342 HIRect macRect; 5343 bool tracking = slider->sliderPosition == slider->sliderValue; 5344 if (!tracking) { 5345 // Small optimization, the same as q->subControlRect 5346 QCFType<HIShapeRef> shape; 5347 HIThemeGetTrackThumbShape(&tdi, &shape); 5348 ptrHIShapeGetBounds(shape, &macRect); 5349 tdi.value = slider->sliderValue; 5932 5350 } 5933 } 5934 if (!titlebar->text.isEmpty()) { 5935 p->save(); 5936 QCFType<HIShapeRef> titleRegion3; 5937 HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3); 5938 ptrHIShapeGetBounds(titleRegion3, &tmpRect); 5939 p->setClipRect(qt_qrectForHIRect(tmpRect)); 5940 QRect br = p->clipRegion().boundingRect(); 5941 int x = br.x(), 5942 y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2); 5943 if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2)) 5944 x += iw; 5945 else 5946 x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2; 5947 if (iw) { 5948 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 5949 p->drawPixmap(x - iw, y, 5950 titlebar->icon.pixmap(window, QSize(iconExtent, iconExtent), QIcon::Normal)); 5351 5352 // Remove controls from the scroll bar if it is to short to draw them correctly. 5353 // This is done in two stages: first the thumb indicator is removed when it is 5354 // no longer possible to move it, second the up/down buttons are removed when 5355 // there is not enough space for them. 5356 if (cc == CC_ScrollBar) { 5357 if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject)) 5358 QMacStylePrivate::scrollBars.append(QPointer<QObject>(opt->styleObject)); 5359 const int scrollBarLength = (slider->orientation == Qt::Horizontal) 5360 ? slider->rect.width() : slider->rect.height(); 5361 const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget, opt); 5362 if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy)) 5363 tdi.attributes &= ~kThemeTrackShowThumb; 5364 if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) 5365 tdi.enableState = kThemeTrackNothingToScroll; 5366 } else { 5367 if (!(slider->subControls & SC_SliderHandle)) 5368 tdi.attributes &= ~kThemeTrackShowThumb; 5369 if (!(slider->subControls & SC_SliderGroove)) 5370 tdi.attributes |= kThemeTrackHideTrack; 5371 } 5372 5373 const bool isHorizontal = slider->orientation == Qt::Horizontal; 5374 5375 if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { 5376 bool wasActive = false; 5377 CGFloat opacity = 0.0; 5378 CGFloat expandScale = 1.0; 5379 CGFloat expandOffset = -1.0; 5380 bool shouldExpand = false; 5381 const CGFloat maxExpandScale = tdi.kind == kThemeSmallScrollBar ? 11.0 / 7.0 : 13.0 / 9.0; 5382 5383 if (QObject *styleObject = opt->styleObject) { 5384 int oldPos = styleObject->property("_q_stylepos").toInt(); 5385 int oldMin = styleObject->property("_q_stylemin").toInt(); 5386 int oldMax = styleObject->property("_q_stylemax").toInt(); 5387 QRect oldRect = styleObject->property("_q_stylerect").toRect(); 5388 int oldState = styleObject->property("_q_stylestate").toInt(); 5389 uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); 5390 5391 // a scrollbar is transient when the scrollbar itself and 5392 // its sibling are both inactive (ie. not pressed/hovered/moved) 5393 bool transient = !opt->activeSubControls && !(slider->state & State_On); 5394 5395 if (!transient || 5396 oldPos != slider->sliderPosition || 5397 oldMin != slider->minimum || 5398 oldMax != slider->maximum || 5399 oldRect != slider->rect || 5400 oldState != slider->state || 5401 oldActiveControls != slider->activeSubControls) { 5402 5403 // if the scrollbar is transient or its attributes, geometry or 5404 // state has changed, the opacity is reset back to 100% opaque 5405 opacity = 1.0; 5406 5407 styleObject->setProperty("_q_stylepos", slider->sliderPosition); 5408 styleObject->setProperty("_q_stylemin", slider->minimum); 5409 styleObject->setProperty("_q_stylemax", slider->maximum); 5410 styleObject->setProperty("_q_stylerect", slider->rect); 5411 styleObject->setProperty("_q_stylestate", static_cast<int>(slider->state)); 5412 styleObject->setProperty("_q_stylecontrols", static_cast<uint>(slider->activeSubControls)); 5413 5414 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject)); 5415 if (transient) { 5416 if (!anim) { 5417 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject); 5418 d->startAnimation(anim); 5419 } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5420 // the scrollbar was already fading out while the 5421 // state changed -> restart the fade out animation 5422 anim->setCurrentTime(0); 5423 } 5424 } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5425 d->stopAnimation(styleObject); 5426 } 5427 } 5428 5429 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject)); 5430 if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { 5431 // once a scrollbar was active (hovered/pressed), it retains 5432 // the active look even if it's no longer active while fading out 5433 if (oldActiveControls) 5434 anim->setActive(true); 5435 5436 wasActive = anim->wasActive(); 5437 opacity = anim->currentValue(); 5438 } 5439 5440 shouldExpand = (opt->activeSubControls || wasActive); 5441 if (shouldExpand) { 5442 if (!anim && !oldActiveControls) { 5443 // Start expand animation only once and when entering 5444 anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject); 5445 d->startAnimation(anim); 5446 } 5447 if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) { 5448 expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue(); 5449 expandOffset = 5.5 * anim->currentValue() - 1; 5450 } else { 5451 // Keep expanded state after the animation ends, and when fading out 5452 expandScale = maxExpandScale; 5453 expandOffset = 4.5; 5454 } 5455 } 5456 } 5457 5458 CGContextSaveGState(cg); 5459 [NSGraphicsContext saveGraphicsState]; 5460 5461 [NSGraphicsContext setCurrentContext:[NSGraphicsContext 5462 graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; 5463 //NSScroller *scroller = reinterpret_cast<NSScroller*>(d->nsscroller); 5464 NSScroller *scroller = isHorizontal ? d->horizontalScroller : d-> verticalScroller; 5465 [scroller initWithFrame:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; 5466 // mac os behaviour: as soon as one color channel is >= 128, 5467 // the bg is considered bright, scroller is dark 5468 const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); 5469 const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && 5470 bgColor.blue() < 128; 5471 if (isDarkBg) 5472 [scroller setKnobStyle:NSScrollerKnobStyleLight]; 5473 else 5474 [scroller setKnobStyle:NSScrollerKnobStyleDefault]; 5475 5476 [scroller setControlSize:(tdi.kind == kThemeSmallScrollBar ? NSMiniControlSize 5477 : NSRegularControlSize)]; 5478 [scroller setBounds:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; 5479 [scroller setScrollerStyle:NSScrollerStyleOverlay]; 5480 5481 CGContextBeginTransparencyLayer(cg, NULL); 5482 CGContextSetAlpha(cg, opacity); 5483 5484 // Draw the track when hovering 5485 if (opt->activeSubControls || wasActive) { 5486 NSRect rect = [scroller bounds]; 5487 if (shouldExpand) { 5488 if (isHorizontal) 5489 rect.origin.y += 4.5 - expandOffset; 5490 else 5491 rect.origin.x += 4.5 - expandOffset; 5492 } 5493 [scroller drawKnobSlotInRect:rect highlight:YES]; 5494 } 5495 5496 const qreal length = slider->maximum - slider->minimum + slider->pageStep; 5497 const qreal proportion = slider->pageStep / length; 5498 qreal value = (slider->sliderValue - slider->minimum) / length; 5499 if (isHorizontal && slider->direction == Qt::RightToLeft) 5500 value = 1.0 - value - proportion; 5501 5502 [scroller setKnobProportion:1.0]; 5503 5504 const int minKnobWidth = 26; 5505 5506 if (isHorizontal) { 5507 const qreal plannedWidth = proportion * slider->rect.width(); 5508 const qreal width = qMax<qreal>(minKnobWidth, plannedWidth); 5509 const qreal totalWidth = slider->rect.width() + plannedWidth - width; 5510 [scroller setFrame:NSMakeRect(0, 0, width, slider->rect.height())]; 5511 if (shouldExpand) { 5512 CGContextScaleCTM(cg, 1, expandScale); 5513 CGContextTranslateCTM(cg, value * totalWidth, -expandOffset); 5514 } else { 5515 CGContextTranslateCTM(cg, value * totalWidth, 1); 5516 } 5517 } else { 5518 const qreal plannedHeight = proportion * slider->rect.height(); 5519 const qreal height = qMax<qreal>(minKnobWidth, plannedHeight); 5520 const qreal totalHeight = slider->rect.height() + plannedHeight - height; 5521 [scroller setFrame:NSMakeRect(0, 0, slider->rect.width(), height)]; 5522 if (shouldExpand) { 5523 CGContextScaleCTM(cg, expandScale, 1); 5524 CGContextTranslateCTM(cg, -expandOffset, value * totalHeight); 5525 } else { 5526 CGContextTranslateCTM(cg, 1, value * totalHeight); 5527 } 5528 } 5529 if (length > 0.0) { 5530 [scroller layout]; 5531 [scroller drawKnob]; 5532 } 5533 5534 CGContextEndTransparencyLayer(cg); 5535 5536 [NSGraphicsContext restoreGraphicsState]; 5537 CGContextRestoreGState(cg); 5538 } else { 5539 d->stopAnimation(opt->styleObject); 5540 5541 if (usingYosemiteOrLater && cc == CC_Slider) { 5542 // Fix min and max positions. (See also getSliderInfo() 5543 // for the slider values adjustments.) 5544 // HITheme seems to have forgotten how to render 5545 // a slide at those positions, leaving a gap between 5546 // the knob and the ends of the track. 5547 // We fix this by rendering the track first, and then 5548 // the knob on top. However, in order to not clip the 5549 // knob, we reduce the the drawing rect for the track. 5550 HIRect bounds = tdi.bounds; 5551 if (isHorizontal) { 5552 tdi.bounds.size.width -= 2; 5553 tdi.bounds.origin.x += 1; 5554 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) 5555 tdi.bounds.origin.y -= 2; 5556 else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) 5557 tdi.bounds.origin.y += 3; 5558 } else { 5559 tdi.bounds.size.height -= 2; 5560 tdi.bounds.origin.y += 1; 5561 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right 5562 tdi.bounds.origin.x -= 4; 5563 else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left 5564 tdi.bounds.origin.x += 2; 5565 } 5566 5567 // Yosemite demands its blue progress track when no tickmarks are present 5568 if (!(slider->subControls & SC_SliderTickmarks)) { 5569 QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; 5570 QCocoaWidget cw = QCocoaWidget(sliderKind, QAquaSizeLarge); 5571 NSSlider *sl = (NSSlider *)d->cocoaControl(cw); 5572 sl.minValue = slider->minimum; 5573 sl.maxValue = slider->maximum; 5574 sl.intValue = slider->sliderValue; 5575 sl.enabled = slider->state & QStyle::State_Enabled; 5576 d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(NSRect rect, CGContextRef ctx) { 5577 if (slider->upsideDown) { 5578 if (isHorizontal) { 5579 CGContextTranslateCTM(ctx, rect.size.width, 0); 5580 CGContextScaleCTM(ctx, -1, 1); 5581 } 5582 } else if (!isHorizontal) { 5583 CGContextTranslateCTM(ctx, 0, rect.size.height); 5584 CGContextScaleCTM(ctx, 1, -1); 5585 } 5586 [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:NO]; 5587 // No need to restore the CTM later, the context has been saved 5588 // and will be restored at the end of drawNSViewInRect() 5589 }); 5590 tdi.attributes |= kThemeTrackHideTrack; 5591 } else { 5592 tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus); 5593 HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, 5594 kHIThemeOrientationNormal); 5595 tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb; 5596 } 5597 5598 tdi.bounds = bounds; 5599 } 5600 5601 if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { 5602 5603 HIRect bounds; 5604 if (usingYosemiteOrLater) { 5605 // As part of fixing the min and max positions, 5606 // we need to adjust the tickmarks as well 5607 bounds = tdi.bounds; 5608 if (slider->orientation == Qt::Horizontal) { 5609 tdi.bounds.size.width += 2; 5610 tdi.bounds.origin.x -= 1; 5611 if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) 5612 tdi.bounds.origin.y -= 2; 5613 } else { 5614 tdi.bounds.size.height += 3; 5615 tdi.bounds.origin.y -= 3; 5616 tdi.bounds.origin.y += 1; 5617 if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left 5618 tdi.bounds.origin.x -= 2; 5619 } 5620 } 5621 5622 if (qt_mac_is_metal(widget)) { 5623 if (tdi.enableState == kThemeTrackInactive) 5624 tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like 5625 } 5626 int interval = slider->tickInterval; 5627 if (interval == 0) { 5628 interval = slider->pageStep; 5629 if (interval == 0) 5630 interval = slider->singleStep; 5631 if (interval == 0) 5632 interval = 1; 5633 } 5634 int numMarks = 1 + ((slider->maximum - slider->minimum) / interval); 5635 5636 if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) { 5637 // They asked for both, so we'll give it to them. 5638 tdi.trackInfo.slider.thumbDir = kThemeThumbDownward; 5639 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5640 cg, 5641 kHIThemeOrientationNormal); 5642 tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; 5643 if (usingYosemiteOrLater) { 5644 if (slider->orientation == Qt::Vertical) 5645 tdi.bounds.origin.x -= 2; 5646 } 5647 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5648 cg, 5649 kHIThemeOrientationNormal); 5650 // Reset to plain thumb to be drawn further down 5651 tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; 5652 } else { 5653 HIThemeDrawTrackTickMarks(&tdi, numMarks, 5654 cg, 5655 kHIThemeOrientationNormal); 5656 } 5657 5658 if (usingYosemiteOrLater) 5659 tdi.bounds = bounds; 5660 } 5661 5662 if (usingYosemiteOrLater && cc == CC_Slider) { 5663 // Still as part of fixing the min and max positions, 5664 // we also adjust the knob position. We can do this 5665 // because it's rendered separately from the track. 5666 if (slider->orientation == Qt::Vertical) { 5667 if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right 5668 tdi.bounds.origin.x -= 2; 5669 } 5670 } 5671 5672 HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, 5673 kHIThemeOrientationNormal); 5951 5674 } 5952 drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive,5953 titlebar->text, QPalette::Text);5954 p->restore();5955 }5956 }5957 }5958 break;5959 case CC_GroupBox:5960 if (const QStyleOptionGroupBox *gb5961 = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {5962 5963 QStyleOptionGroupBox groupBox(*gb);5964 const bool flat = groupBox.features & QStyleOptionFrame::Flat;5965 if (!flat)5966 groupBox.state |= QStyle::State_Mini; // Force mini-sized checkbox to go with small-sized label5967 else5968 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame; // We don't like frames and ugly lines5969 5970 bool didModifySubControls = false;5971 if ((!widget || !widget->testAttribute(Qt::WA_SetFont))5972 && QApplication::desktopSettingsAware()) {5973 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel;5974 didModifySubControls = true;5975 }5976 QCommonStyle::drawComplexControl(cc, &groupBox, p, widget);5977 if (didModifySubControls) {5978 p->save();5979 CGContextSetShouldAntialias(cg, true);5980 CGContextSetShouldSmoothFonts(cg, true);5981 HIThemeTextInfo tti;5982 tti.version = qt_mac_hitheme_version;5983 tti.state = tds;5984 QColor textColor = groupBox.palette.windowText().color();5985 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()),5986 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) };5987 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());5988 CGContextSetFillColor(cg, colorComp);5989 tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont;5990 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;5991 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;5992 tti.options = kHIThemeTextBoxOptionNone;5993 tti.truncationPosition = kHIThemeTextTruncationNone;5994 tti.truncationMaxLines = 1 + groupBox.text.count(QLatin1Char('\n'));5995 QCFString groupText = qt_mac_removeMnemonics(groupBox.text);5996 QRect r = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget);5997 HIRect bounds = qt_hirectForQRect(r);5998 HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal);5999 p->restore();6000 }6001 }6002 break;6003 case CC_ToolButton:6004 if (const QStyleOptionToolButton *tb6005 = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {6006 #ifndef QT_NO_ACCESSIBILITY6007 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {6008 if (tb->subControls & SC_ToolButtonMenu) {6009 QStyleOption arrowOpt = *tb;6010 arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);6011 arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);6012 arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);6013 proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);6014 } else if ((tb->features & QStyleOptionToolButton::HasMenu)6015 && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {6016 drawToolbarButtonArrow(tb->rect, tds, cg);6017 }6018 if (tb->state & State_On) {6019 QWindow *window = 0;6020 if (widget && widget->window())6021 window = widget->window()->windowHandle();6022 else if (opt->styleObject)6023 window = opt->styleObject->property("_q_styleObjectWindow").value<QWindow *>();6024 6025 NSView *view = window ? (NSView *)window->winId() : nil;6026 bool isKey = false;6027 if (view)6028 isKey = [view.window isKeyWindow];6029 6030 QBrush brush(isKey ? QColor(0, 0, 0, 28)6031 : QColor(0, 0, 0, 21));6032 QPainterPath path;6033 path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4);6034 p->setRenderHint(QPainter::Antialiasing);6035 p->fillPath(path, brush);6036 }6037 proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);6038 } else {6039 ThemeButtonKind bkind = kThemeBevelButton;6040 switch (d->aquaSizeConstrain(opt, widget)) {6041 case QAquaSizeUnknown:6042 case QAquaSizeLarge:6043 bkind = kThemeBevelButton;6044 break;6045 case QAquaSizeMini:6046 case QAquaSizeSmall:6047 bkind = kThemeSmallBevelButton;6048 break;6049 5675 } 6050 6051 QRect button, menuarea; 6052 button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); 6053 menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); 6054 State bflags = tb->state, 6055 mflags = tb->state; 6056 if (tb->subControls & SC_ToolButton) 6057 bflags |= State_Sunken; 6058 if (tb->subControls & SC_ToolButtonMenu) 6059 mflags |= State_Sunken; 6060 6061 if (tb->subControls & SC_ToolButton) { 6062 if (bflags & (State_Sunken | State_On | State_Raised)) { 5676 break; 5677 #ifndef QT_NO_SPINBOX 5678 case CC_SpinBox: 5679 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 5680 QStyleOptionSpinBox newSB = *sb; 5681 if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { 5682 SInt32 frame_size; 5683 GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); 5684 5685 QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); 5686 lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size); 5687 5688 HIThemeFrameDrawInfo fdi; 5689 fdi.version = qt_mac_hitheme_version; 5690 fdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; 5691 fdi.kind = kHIThemeFrameTextFieldSquare; 5692 fdi.isFocused = false; 5693 HIRect hirect = qt_hirectForQRect(lineeditRect); 5694 HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); 5695 } 5696 if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { 6063 5697 HIThemeButtonDrawInfo bdi; 6064 5698 bdi.version = qt_mac_hitheme_version; 6065 bdi.state = tds; 6066 bdi.adornment = kThemeAdornmentNone; 6067 bdi.kind = bkind; 5699 QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget); 5700 switch (aquaSize) { 5701 case QAquaSizeUnknown: 5702 case QAquaSizeLarge: 5703 bdi.kind = kThemeIncDecButton; 5704 break; 5705 case QAquaSizeMini: 5706 bdi.kind = kThemeIncDecButtonMini; 5707 break; 5708 case QAquaSizeSmall: 5709 bdi.kind = kThemeIncDecButtonSmall; 5710 break; 5711 } 5712 if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled 5713 | QAbstractSpinBox::StepDownEnabled))) 5714 tds = kThemeStateUnavailable; 5715 if (sb->activeSubControls == SC_SpinBoxDown 5716 && (sb->state & State_Sunken)) 5717 tds = kThemeStatePressedDown; 5718 else if (sb->activeSubControls == SC_SpinBoxUp 5719 && (sb->state & State_Sunken)) 5720 tds = kThemeStatePressedUp; 5721 if (tds == kThemeStateInactive) 5722 bdi.state = kThemeStateActive; 5723 else 5724 bdi.state = tds; 6068 5725 bdi.value = kThemeButtonOff; 6069 if (tb->state & State_HasFocus)6070 bdi.adornment = kThemeAdornmentFocus;6071 if (tb->state & State_Sunken)6072 bdi.state = kThemeStatePressed;6073 if (tb->state & State_On)6074 bdi.value = kThemeButtonOn;6075 6076 QRect off_rct(0, 0, 0, 0);6077 HI Rect myRect, macRect;6078 myRect = CGRectMake(tb->rect.x(), tb->rect.y(),6079 tb->rect.width(), tb->rect.height());6080 HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);6081 off_rct.setRect(int(myRect.origin.x - macRect.origin.x),6082 int(myRect.origin.y - macRect.origin.y),6083 int(macRect.size.width - myRect.size.width),6084 int(macRect.size.height - myRect.size.height));6085 6086 myRect = qt_hirectForQRect(button, off_rct);6087 HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0);5726 bdi.adornment = kThemeAdornmentNone; 5727 5728 QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); 5729 5730 updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); 5731 HIRect newRect = qt_hirectForQRect(updown); 5732 QRect off_rct; 5733 HIRect outRect; 5734 HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect); 5735 off_rct.setRect(int(newRect.origin.x - outRect.origin.x), 5736 int(newRect.origin.y - outRect.origin.y), 5737 int(outRect.size.width - newRect.size.width), 5738 int(outRect.size.height - newRect.size.height)); 5739 5740 newRect = qt_hirectForQRect(updown, off_rct); 5741 if (tds == kThemeStateInactive) 5742 d->drawColorlessButton(newRect, &bdi, p, sb); 5743 else 5744 HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); 6088 5745 } 6089 5746 } 6090 6091 if (tb->subControls & SC_ToolButtonMenu) { 6092 HIThemeButtonDrawInfo bdi; 6093 bdi.version = qt_mac_hitheme_version; 6094 bdi.state = tds; 6095 bdi.value = kThemeButtonOff; 6096 bdi.adornment = kThemeAdornmentNone; 6097 bdi.kind = bkind; 6098 if (tb->state & State_HasFocus) 6099 bdi.adornment = kThemeAdornmentFocus; 6100 if (tb->state & (State_On | State_Sunken) 6101 || (tb->activeSubControls & SC_ToolButtonMenu)) 6102 bdi.state = kThemeStatePressed; 6103 HIRect hirect = qt_hirectForQRect(menuarea); 6104 HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0); 6105 QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8); 6106 HIThemePopupArrowDrawInfo padi; 6107 padi.version = qt_mac_hitheme_version; 6108 padi.state = tds; 6109 padi.orientation = kThemeArrowDown; 6110 padi.size = kThemeArrow7pt; 6111 hirect = qt_hirectForQRect(r); 6112 HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); 6113 } else if (tb->features & QStyleOptionToolButton::HasMenu) { 6114 drawToolbarButtonArrow(tb->rect, tds, cg); 6115 } 6116 QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); 6117 int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); 6118 QStyleOptionToolButton label = *tb; 6119 label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); 6120 proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); 6121 } 6122 #endif 6123 } 6124 break; 6125 #if QT_CONFIG(dial) 6126 case CC_Dial: 6127 if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt)) 6128 QStyleHelper::drawDial(dial, p); 6129 break; 5747 break; 6130 5748 #endif 6131 default: 6132 QCommonStyle::drawComplexControl(cc, opt, p, widget); 6133 break; 6134 } 6135 } 6136 6137 QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, 6138 const QStyleOptionComplex *opt, 6139 const QPoint &pt, const QWidget *widget) const 6140 { 6141 Q_D(const QMacStyle); 6142 SubControl sc = QStyle::SC_None; 6143 switch (cc) { 6144 case CC_ComboBox: 6145 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 6146 sc = QCommonStyle::hitTestComplexControl(cc, cmb, pt, widget); 6147 if (!cmb->editable && sc != QStyle::SC_None) 6148 sc = SC_ComboBoxArrow; // A bit of a lie, but what we want 6149 } 6150 break; 6151 case CC_Slider: 6152 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6153 HIThemeTrackDrawInfo tdi; 6154 d->getSliderInfo(cc, slider, &tdi, widget); 6155 ControlPartCode part; 6156 HIPoint pos = CGPointMake(pt.x(), pt.y()); 6157 if (HIThemeHitTestTrack(&tdi, &pos, &part)) { 6158 if (part == kControlPageUpPart || part == kControlPageDownPart) 6159 sc = SC_SliderGroove; 6160 else 6161 sc = SC_SliderHandle; 6162 } 6163 } 6164 break; 6165 case CC_ScrollBar: 6166 if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6167 HIScrollBarTrackInfo sbi; 6168 sbi.version = qt_mac_hitheme_version; 6169 if (!(sb->state & State_Active)) 6170 sbi.enableState = kThemeTrackInactive; 6171 else if (sb->state & State_Enabled) 6172 sbi.enableState = kThemeTrackActive; 6173 else 6174 sbi.enableState = kThemeTrackDisabled; 6175 6176 // The arrow buttons are not drawn if the scroll bar is to short, 6177 // exclude them from the hit test. 6178 const int scrollBarLength = (sb->orientation == Qt::Horizontal) 6179 ? sb->rect.width() : sb->rect.height(); 6180 if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget, opt))) 6181 sbi.enableState = kThemeTrackNothingToScroll; 6182 6183 sbi.viewsize = sb->pageStep; 6184 HIPoint pos = CGPointMake(pt.x(), pt.y()); 6185 6186 HIRect macSBRect = qt_hirectForQRect(sb->rect); 6187 ControlPartCode part; 6188 bool reverseHorizontal = (sb->direction == Qt::RightToLeft 6189 && sb->orientation == Qt::Horizontal); 6190 if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal, 6191 &pos, 0, &part)) { 6192 if (part == kControlUpButtonPart) 6193 sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine; 6194 else if (part == kControlDownButtonPart) 6195 sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine; 6196 } else { 6197 HIThemeTrackDrawInfo tdi; 6198 d->getSliderInfo(cc, sb, &tdi, widget); 6199 if(tdi.enableState == kThemeTrackInactive) 6200 tdi.enableState = kThemeTrackActive; 6201 if (HIThemeHitTestTrack(&tdi, &pos, &part)) { 6202 if (part == kControlPageUpPart) 6203 sc = reverseHorizontal ? SC_ScrollBarAddPage 6204 : SC_ScrollBarSubPage; 6205 else if (part == kControlPageDownPart) 6206 sc = reverseHorizontal ? SC_ScrollBarSubPage 6207 : SC_ScrollBarAddPage; 6208 else 6209 sc = SC_ScrollBarSlider; 6210 } 6211 } 6212 } 6213 break; 6214 /* 6215 I don't know why, but we only get kWindowContentRgn here, which isn't what we want at all. 6216 It would be very nice if this would work. 6217 case QStyle::CC_TitleBar: 6218 if (const QStyleOptionTitleBar *tbar = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { 6219 HIThemeWindowDrawInfo wdi; 6220 memset(&wdi, 0, sizeof(wdi)); 6221 wdi.version = qt_mac_hitheme_version; 6222 wdi.state = kThemeStateActive; 6223 wdi.windowType = QtWinType; 6224 wdi.titleWidth = tbar->rect.width(); 6225 wdi.titleHeight = tbar->rect.height(); 6226 if (tbar->titleBarState) 6227 wdi.attributes |= kThemeWindowHasFullZoom | kThemeWindowHasCloseBox 6228 | kThemeWindowHasCollapseBox; 6229 else if (tbar->titleBarFlags & Qt::WindowSystemMenuHint) 6230 wdi.attributes |= kThemeWindowHasCloseBox; 6231 QRect tmpRect = tbar->rect; 6232 tmpRect.setHeight(tmpRect.height() + 100); 6233 HIRect hirect = qt_hirectForQRect(tmpRect); 6234 WindowRegionCode hit; 6235 HIPoint hipt = CGPointMake(pt.x(), pt.y()); 6236 if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) { 6237 switch (hit) { 6238 case kWindowCloseBoxRgn: 6239 sc = QStyle::SC_TitleBarCloseButton; 6240 break; 6241 case kWindowCollapseBoxRgn: 6242 sc = QStyle::SC_TitleBarMinButton; 6243 break; 6244 case kWindowZoomBoxRgn: 6245 sc = QStyle::SC_TitleBarMaxButton; 6246 break; 6247 case kWindowTitleTextRgn: 6248 sc = QStyle::SC_TitleBarLabel; 6249 break; 6250 default: 6251 qDebug("got something else %d", hit); 6252 break; 6253 } 6254 } 6255 } 6256 break; 6257 */ 6258 default: 6259 sc = QCommonStyle::hitTestComplexControl(cc, opt, pt, widget); 6260 break; 6261 } 6262 return sc; 6263 } 6264 6265 QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, 6266 const QWidget *widget) const 6267 { 6268 Q_D(const QMacStyle); 6269 QRect ret; 6270 switch (cc) { 6271 case CC_Slider: 6272 case CC_ScrollBar: 6273 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6274 HIThemeTrackDrawInfo tdi; 6275 d->getSliderInfo(cc, slider, &tdi, widget); 6276 HIRect macRect; 6277 QCFType<HIShapeRef> shape; 6278 bool scrollBar = cc == CC_ScrollBar; 6279 if ((scrollBar && sc == SC_ScrollBarSlider) 6280 || (!scrollBar && sc == SC_SliderHandle)) { 6281 HIThemeGetTrackThumbShape(&tdi, &shape); 6282 ptrHIShapeGetBounds(shape, &macRect); 6283 } else if (!scrollBar && sc == SC_SliderGroove) { 6284 HIThemeGetTrackBounds(&tdi, &macRect); 6285 } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available... 6286 HIThemeGetTrackDragRect(&tdi, &macRect); 6287 } else { 6288 ControlPartCode cpc; 6289 if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) { 6290 cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart 6291 : kControlPageUpPart; 6292 } else { 6293 cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart 6294 : kControlDownButtonPart; 6295 if (slider->direction == Qt::RightToLeft 6296 && slider->orientation == Qt::Horizontal) { 6297 if (cpc == kControlDownButtonPart) 6298 cpc = kControlUpButtonPart; 6299 else if (cpc == kControlUpButtonPart) 6300 cpc = kControlDownButtonPart; 6301 } 5749 case CC_ComboBox: 5750 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){ 5751 HIThemeButtonDrawInfo bdi; 5752 d->initComboboxBdi(combo, &bdi, widget, tds); 5753 HIRect rect = qt_hirectForQRect(combo->rect); 5754 if (combo->editable && usingYosemiteOrLater) 5755 rect.origin.y += tds == kThemeStateInactive ? 1 : 2; 5756 if (tds != kThemeStateInactive) 5757 QMacStylePrivate::drawCombobox(rect, bdi, p); 5758 else if (!widget && combo->editable && usingYosemiteOrLater) { 5759 QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); 5760 NSView *cb = d->cocoaControl(cw); 5761 QRect r = combo->rect.adjusted(3, 0, 0, 0); 5762 d->drawNSViewInRect(cw, cb, r, p, widget != 0); 5763 } else 5764 d->drawColorlessButton(rect, &bdi, p, opt); 6302 5765 } 6303 HIThemeGetTrackPartBounds(&tdi, cpc, &macRect);6304 }6305 ret = qt_qrectForHIRect(macRect);6306 6307 // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons6308 // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover6309 // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't.6310 if (slider->orientation == Qt::Horizontal) {6311 if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine)6312 ret.adjust(0, 0, 1, 0);6313 else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine)6314 ret.adjust(-1, 0, 1, 0);6315 } else if (sc == SC_ScrollBarAddLine) {6316 ret.adjust(0, -1, 0, 1);6317 }6318 }6319 break;6320 case CC_TitleBar:6321 if (const QStyleOptionTitleBar *titlebar6322 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) {6323 HIThemeWindowDrawInfo wdi;6324 memset(&wdi, 0, sizeof(wdi));6325 wdi.version = qt_mac_hitheme_version;6326 wdi.state = kThemeStateActive;6327 wdi.windowType = QtWinType;6328 wdi.titleHeight = titlebar->rect.height();6329 wdi.titleWidth = titlebar->rect.width();6330 wdi.attributes = kThemeWindowHasTitleText;6331 if (titlebar->subControls & SC_TitleBarCloseButton)6332 wdi.attributes |= kThemeWindowHasCloseBox;6333 if (titlebar->subControls & SC_TitleBarMaxButton6334 | SC_TitleBarNormalButton)6335 wdi.attributes |= kThemeWindowHasFullZoom;6336 if (titlebar->subControls & SC_TitleBarMinButton)6337 wdi.attributes |= kThemeWindowHasCollapseBox;6338 WindowRegionCode wrc = kWindowGlobalPortRgn;6339 6340 if (sc == SC_TitleBarCloseButton)6341 wrc = kWindowCloseBoxRgn;6342 else if (sc == SC_TitleBarMinButton)6343 wrc = kWindowCollapseBoxRgn;6344 else if (sc == SC_TitleBarMaxButton)6345 wrc = kWindowZoomBoxRgn;6346 else if (sc == SC_TitleBarLabel)6347 wrc = kWindowTitleTextRgn;6348 else if (sc == SC_TitleBarSysMenu)6349 ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight,6350 titlebar, widget));6351 if (wrc != kWindowGlobalPortRgn) {6352 QCFType<HIShapeRef> region;6353 QRect tmpRect = titlebar->rect;6354 HIRect titleRect = qt_hirectForQRect(tmpRect);6355 HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, ®ion);6356 ptrHIShapeGetBounds(region, &titleRect);6357 CFRelease(region);6358 tmpRect.translate(tmpRect.x() - int(titleRect.origin.x),6359 tmpRect.y() - int(titleRect.origin.y));6360 titleRect = qt_hirectForQRect(tmpRect);6361 HIThemeGetWindowShape(&titleRect, &wdi, wrc, ®ion);6362 ptrHIShapeGetBounds(region, &titleRect);6363 ret = qt_qrectForHIRect(titleRect);6364 }6365 }6366 break;6367 case CC_ComboBox:6368 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {6369 HIThemeButtonDrawInfo bdi;6370 d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state));6371 6372 switch (sc) {6373 case SC_ComboBoxEditField:{6374 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);6375 // 10.10 and above need a slight shift6376 ret.setHeight(ret.height() - 1);6377 break; }6378 case SC_ComboBoxArrow:{6379 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);6380 ret.setX(ret.x() + ret.width());6381 ret.setWidth(combo->rect.right() - ret.right());6382 break; }6383 case SC_ComboBoxListBoxPopup:{6384 if (combo->editable) {6385 HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind);6386 QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);6387 const int comboTop = combo->rect.top();6388 ret = QRect(qRound(inner.origin.x),6389 comboTop,6390 qRound(inner.origin.x - combo->rect.left() + inner.size.width),6391 editRect.bottom() - comboTop + 2);6392 } else {6393 QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);6394 ret = QRect(combo->rect.x() + 4 - 11,6395 combo->rect.y() + 1,6396 editRect.width() + 10 + 11,6397 1);6398 }6399 break; }6400 default:6401 5766 break; 6402 } 6403 } 6404 break; 6405 case CC_GroupBox: 6406 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { 6407 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; 6408 const bool flat = groupBox->features & QStyleOptionFrame::Flat; 6409 bool hasNoText = !checkable && groupBox->text.isEmpty(); 6410 switch (sc) { 6411 case SC_GroupBoxLabel: 6412 case SC_GroupBoxCheckBox: { 6413 // Cheat and use the smaller font if we need to 6414 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; 6415 bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)) 6416 || !QApplication::desktopSettingsAware(); 6417 int tw; 6418 int h; 6419 int margin = flat || hasNoText ? 0 : 9; 6420 ret = groupBox->rect.adjusted(margin, 0, -margin, 0); 6421 6422 if (!fontIsSet) { 6423 HIThemeTextInfo tti; 6424 tti.version = qt_mac_hitheme_version; 6425 tti.state = kThemeStateActive; 6426 tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont; 6427 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 6428 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 6429 tti.options = kHIThemeTextBoxOptionNone; 6430 tti.truncationPosition = kHIThemeTextTruncationNone; 6431 tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n')); 6432 CGFloat width; 6433 CGFloat height; 6434 QCFString groupText = qt_mac_removeMnemonics(groupBox->text); 6435 HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0); 6436 tw = qRound(width); 6437 h = qCeil(height); 6438 } else { 6439 QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics); 6440 h = qCeil(fm.height()); 6441 tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width()); 6442 } 6443 ret.setHeight(h); 6444 6445 QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, 6446 QSize(tw, h), ret); 6447 if (flat && checkable) 6448 labelRect.moveLeft(labelRect.left() + 4); 6449 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); 6450 bool rtl = groupBox->direction == Qt::RightToLeft; 6451 if (sc == SC_GroupBoxLabel) { 6452 if (checkable) { 6453 int newSum = indicatorWidth + 1; 6454 int newLeft = labelRect.left() + (rtl ? -newSum : newSum); 6455 labelRect.moveLeft(newLeft); 6456 if (flat) 6457 labelRect.moveTop(labelRect.top() + 3); 5767 case CC_TitleBar: 5768 if (const QStyleOptionTitleBar *titlebar 5769 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { 5770 if (titlebar->state & State_Active) { 5771 if (titlebar->titleBarState & State_Active) 5772 tds = kThemeStateActive; 6458 5773 else 6459 labelRect.moveTop(labelRect.top() + 4); 6460 } else if (flat) { 6461 int newLeft = labelRect.left() - (rtl ? 3 : -3); 6462 labelRect.moveLeft(newLeft); 6463 labelRect.moveTop(labelRect.top() + 3); 5774 tds = kThemeStateInactive; 6464 5775 } else { 6465 int newLeft = labelRect.left() - (rtl ? 3 : 2); 6466 labelRect.moveLeft(newLeft); 6467 labelRect.moveTop(labelRect.top() + 4); 5776 tds = kThemeStateInactive; 5777 } 5778 5779 HIThemeWindowDrawInfo wdi; 5780 wdi.version = qt_mac_hitheme_version; 5781 wdi.state = tds; 5782 wdi.windowType = QtWinType; 5783 wdi.titleHeight = titlebar->rect.height(); 5784 wdi.titleWidth = titlebar->rect.width(); 5785 wdi.attributes = kThemeWindowHasTitleText; 5786 // It seems HIThemeDrawTitleBarWidget is not able to draw a dirty 5787 // close button, so use HIThemeDrawWindowFrame instead. 5788 if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton) 5789 wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty; 5790 5791 HIRect titleBarRect; 5792 HIRect tmpRect = qt_hirectForQRect(titlebar->rect); 5793 { 5794 QCFType<HIShapeRef> titleRegion; 5795 QRect newr = titlebar->rect.adjusted(0, 0, 2, 0); 5796 HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); 5797 ptrHIShapeGetBounds(titleRegion, &tmpRect); 5798 newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); 5799 titleBarRect = qt_hirectForQRect(newr); 5800 } 5801 HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); 5802 if (titlebar->subControls & (SC_TitleBarCloseButton 5803 | SC_TitleBarMaxButton 5804 | SC_TitleBarMinButton 5805 | SC_TitleBarNormalButton)) { 5806 HIThemeWindowWidgetDrawInfo wwdi; 5807 wwdi.version = qt_mac_hitheme_version; 5808 wwdi.widgetState = tds; 5809 if (titlebar->state & State_MouseOver) 5810 wwdi.widgetState = kThemeStateRollover; 5811 wwdi.windowType = QtWinType; 5812 wwdi.attributes = wdi.attributes | kThemeWindowHasFullZoom | kThemeWindowHasCloseBox | kThemeWindowHasCollapseBox; 5813 wwdi.windowState = wdi.state; 5814 wwdi.titleHeight = wdi.titleHeight; 5815 wwdi.titleWidth = wdi.titleWidth; 5816 ThemeDrawState savedControlState = wwdi.widgetState; 5817 uint sc = SC_TitleBarMinButton; 5818 ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox; 5819 bool active = titlebar->state & State_Active; 5820 5821 while (sc <= SC_TitleBarCloseButton) { 5822 if (sc & titlebar->subControls) { 5823 uint tmp = sc; 5824 wwdi.widgetState = savedControlState; 5825 wwdi.widgetType = tbw; 5826 if (sc == SC_TitleBarMinButton) 5827 tmp |= SC_TitleBarNormalButton; 5828 if (active && (titlebar->activeSubControls & tmp) 5829 && (titlebar->state & State_Sunken)) 5830 wwdi.widgetState = kThemeStatePressed; 5831 // Draw all sub controllers except the dirty close button 5832 // (it is already handled by HIThemeDrawWindowFrame). 5833 if (!(widget && widget->isWindowModified() && tbw == kThemeWidgetCloseBox)) { 5834 HIThemeDrawTitleBarWidget(&titleBarRect, &wwdi, cg, kHIThemeOrientationNormal); 5835 p->paintEngine()->syncState(); 5836 } 5837 } 5838 sc = sc << 1; 5839 tbw = tbw >> 1; 5840 } 5841 } 5842 p->paintEngine()->syncState(); 5843 if (titlebar->subControls & SC_TitleBarLabel) { 5844 int iw = 0; 5845 if (!titlebar->icon.isNull()) { 5846 QCFType<HIShapeRef> titleRegion2; 5847 HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn, 5848 &titleRegion2); 5849 ptrHIShapeGetBounds(titleRegion2, &tmpRect); 5850 if (tmpRect.size.width != 1) { 5851 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 5852 iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width(); 5853 } 5854 } 5855 if (!titlebar->text.isEmpty()) { 5856 p->save(); 5857 QCFType<HIShapeRef> titleRegion3; 5858 HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3); 5859 ptrHIShapeGetBounds(titleRegion3, &tmpRect); 5860 p->setClipRect(qt_qrectForHIRect(tmpRect)); 5861 QRect br = p->clipRegion().boundingRect(); 5862 int x = br.x(), 5863 y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2); 5864 if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2)) 5865 x += iw; 5866 else 5867 x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2; 5868 if (iw) { 5869 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 5870 p->drawPixmap(x - iw, y, 5871 titlebar->icon.pixmap(window, QSize(iconExtent, iconExtent), QIcon::Normal)); 5872 } 5873 drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive, 5874 titlebar->text, QPalette::Text); 5875 p->restore(); 5876 } 6468 5877 } 6469 ret = labelRect;6470 }6471 6472 if (sc == SC_GroupBoxCheckBox) {6473 int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left() - 1;6474 int top = flat ? ret.top() + 1 : ret.top() + 5;6475 ret.setRect(left, top,6476 indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget));6477 5878 } 6478 5879 break; 6479 } 6480 case SC_GroupBoxContents: 6481 case SC_GroupBoxFrame: { 6482 QFontMetrics fm = groupBox->fontMetrics; 6483 int yOffset = 3; 6484 if (!flat) { 6485 if (widget && !widget->testAttribute(Qt::WA_SetFont) 6486 && QApplication::desktopSettingsAware()) 6487 fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); 6488 yOffset = 5; 6489 } 6490 6491 if (hasNoText) 6492 yOffset = -qCeil(QFontMetricsF(fm).height()); 6493 ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0); 6494 if (sc == SC_GroupBoxContents) { 6495 if (flat) 6496 ret.adjust(3, -5, -3, -4); // guess too 5880 case CC_GroupBox: 5881 if (const QStyleOptionGroupBox *gb 5882 = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { 5883 5884 QStyleOptionGroupBox groupBox(*gb); 5885 const bool flat = groupBox.features & QStyleOptionFrame::Flat; 5886 if (!flat) 5887 groupBox.state |= QStyle::State_Mini; // Force mini-sized checkbox to go with small-sized label 6497 5888 else 6498 ret.adjust(3, 3, -3, -4); // guess 5889 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame; // We don't like frames and ugly lines 5890 5891 bool didModifySubControls = false; 5892 if ((!widget || !widget->testAttribute(Qt::WA_SetFont)) 5893 && QApplication::desktopSettingsAware()) { 5894 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel; 5895 didModifySubControls = true; 5896 } 5897 QCommonStyle::drawComplexControl(cc, &groupBox, p, widget); 5898 if (didModifySubControls) { 5899 p->save(); 5900 CGContextSetShouldAntialias(cg, true); 5901 CGContextSetShouldSmoothFonts(cg, true); 5902 HIThemeTextInfo tti; 5903 tti.version = qt_mac_hitheme_version; 5904 tti.state = tds; 5905 QColor textColor = groupBox.palette.windowText().color(); 5906 CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()), 5907 static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) }; 5908 CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); 5909 CGContextSetFillColor(cg, colorComp); 5910 tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont; 5911 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 5912 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 5913 tti.options = kHIThemeTextBoxOptionNone; 5914 tti.truncationPosition = kHIThemeTextTruncationNone; 5915 tti.truncationMaxLines = 1 + groupBox.text.count(QLatin1Char('\n')); 5916 QCFString groupText = qt_mac_removeMnemonics(groupBox.text); 5917 QRect r = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget); 5918 HIRect bounds = qt_hirectForQRect(r); 5919 HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal); 5920 p->restore(); 5921 } 6499 5922 } 6500 }6501 break;6502 default:6503 ret = QCommonStyle::subControlRect(cc, groupBox, sc, widget);6504 5923 break; 6505 } 6506 } 6507 break; 6508 #if QT_CONFIG(spinbox) 6509 case CC_SpinBox: 6510 if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 6511 QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget); 6512 int spinner_w; 6513 int spinBoxSep; 6514 int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget); 6515 switch (aquaSize) { 6516 default: 6517 case QAquaSizeUnknown: 6518 case QAquaSizeLarge: 6519 spinner_w = 14; 6520 spinBoxSep = 2; 5924 case CC_ToolButton: 5925 if (const QStyleOptionToolButton *tb 5926 = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) { 5927 #ifndef QT_NO_ACCESSIBILITY 5928 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { 5929 if (tb->subControls & SC_ToolButtonMenu) { 5930 QStyleOption arrowOpt = *tb; 5931 arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); 5932 arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); 5933 arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); 5934 proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); 5935 } else if ((tb->features & QStyleOptionToolButton::HasMenu) 5936 && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { 5937 drawToolbarButtonArrow(tb->rect, tds, cg); 5938 } 5939 if (tb->state & State_On) { 5940 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { 5941 QWindow *window = 0; 5942 if (widget && widget->window()) 5943 window = widget->window()->windowHandle(); 5944 else if (opt->styleObject) 5945 window = opt->styleObject->property("_q_styleObjectWindow").value<QWindow *>(); 5946 5947 NSView *view = window ? (NSView *)window->winId() : nil; 5948 bool isKey = false; 5949 if (view) 5950 isKey = [view.window isKeyWindow]; 5951 5952 QBrush brush(isKey ? QColor(0, 0, 0, 28) 5953 : QColor(0, 0, 0, 21)); 5954 QPainterPath path; 5955 path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); 5956 p->setRenderHint(QPainter::Antialiasing); 5957 p->fillPath(path, brush); 5958 } else { 5959 static QPixmap pm(QLatin1String(":/qt-project.org/mac/style/images/leopard-unified-toolbar-on.png")); 5960 p->save(); 5961 p->setRenderHint(QPainter::SmoothPixmapTransform); 5962 QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2); 5963 p->restore(); 5964 } 5965 } 5966 proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); 5967 } else { 5968 ThemeButtonKind bkind = kThemeBevelButton; 5969 switch (d->aquaSizeConstrain(opt, widget)) { 5970 case QAquaSizeUnknown: 5971 case QAquaSizeLarge: 5972 bkind = kThemeBevelButton; 5973 break; 5974 case QAquaSizeMini: 5975 case QAquaSizeSmall: 5976 bkind = kThemeSmallBevelButton; 5977 break; 5978 } 5979 5980 QRect button, menuarea; 5981 button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); 5982 menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); 5983 State bflags = tb->state, 5984 mflags = tb->state; 5985 if (tb->subControls & SC_ToolButton) 5986 bflags |= State_Sunken; 5987 if (tb->subControls & SC_ToolButtonMenu) 5988 mflags |= State_Sunken; 5989 5990 if (tb->subControls & SC_ToolButton) { 5991 if (bflags & (State_Sunken | State_On | State_Raised)) { 5992 HIThemeButtonDrawInfo bdi; 5993 bdi.version = qt_mac_hitheme_version; 5994 bdi.state = tds; 5995 bdi.adornment = kThemeAdornmentNone; 5996 bdi.kind = bkind; 5997 bdi.value = kThemeButtonOff; 5998 if (tb->state & State_HasFocus) 5999 bdi.adornment = kThemeAdornmentFocus; 6000 if (tb->state & State_Sunken) 6001 bdi.state = kThemeStatePressed; 6002 if (tb->state & State_On) 6003 bdi.value = kThemeButtonOn; 6004 6005 QRect off_rct(0, 0, 0, 0); 6006 HIRect myRect, macRect; 6007 myRect = CGRectMake(tb->rect.x(), tb->rect.y(), 6008 tb->rect.width(), tb->rect.height()); 6009 HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); 6010 off_rct.setRect(int(myRect.origin.x - macRect.origin.x), 6011 int(myRect.origin.y - macRect.origin.y), 6012 int(macRect.size.width - myRect.size.width), 6013 int(macRect.size.height - myRect.size.height)); 6014 6015 myRect = qt_hirectForQRect(button, off_rct); 6016 HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0); 6017 } 6018 } 6019 6020 if (tb->subControls & SC_ToolButtonMenu) { 6021 HIThemeButtonDrawInfo bdi; 6022 bdi.version = qt_mac_hitheme_version; 6023 bdi.state = tds; 6024 bdi.value = kThemeButtonOff; 6025 bdi.adornment = kThemeAdornmentNone; 6026 bdi.kind = bkind; 6027 if (tb->state & State_HasFocus) 6028 bdi.adornment = kThemeAdornmentFocus; 6029 if (tb->state & (State_On | State_Sunken) 6030 || (tb->activeSubControls & SC_ToolButtonMenu)) 6031 bdi.state = kThemeStatePressed; 6032 HIRect hirect = qt_hirectForQRect(menuarea); 6033 HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0); 6034 QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8); 6035 HIThemePopupArrowDrawInfo padi; 6036 padi.version = qt_mac_hitheme_version; 6037 padi.state = tds; 6038 padi.orientation = kThemeArrowDown; 6039 padi.size = kThemeArrow7pt; 6040 hirect = qt_hirectForQRect(r); 6041 HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); 6042 } else if (tb->features & QStyleOptionToolButton::HasMenu) { 6043 drawToolbarButtonArrow(tb->rect, tds, cg); 6044 } 6045 QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); 6046 int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); 6047 QStyleOptionToolButton label = *tb; 6048 label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); 6049 proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); 6050 } 6051 #endif 6052 } 6521 6053 break; 6522 case QAquaSizeSmall: 6523 spinner_w = 12; 6524 spinBoxSep = 2; 6054 #ifndef QT_NO_DIAL 6055 case CC_Dial: 6056 if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt)) 6057 QStyleHelper::drawDial(dial, p); 6525 6058 break; 6526 case QAquaSizeMini: 6527 spinner_w = 10;6528 spinBoxSep = 1;6059 #endif 6060 default: 6061 QCommonStyle::drawComplexControl(cc, opt, p, widget); 6529 6062 break; 6530 } 6531 6532 switch (sc) { 6533 case SC_SpinBoxUp: 6534 case SC_SpinBoxDown: { 6535 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) 6536 break; 6537 6538 const int y = fw; 6539 const int x = spin->rect.width() - spinner_w; 6540 ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2); 6541 HIThemeButtonDrawInfo bdi; 6542 bdi.version = qt_mac_hitheme_version; 6543 bdi.kind = kThemeIncDecButton; 6544 int hackTranslateX; 6545 switch (aquaSize) { 6546 default: 6547 case QAquaSizeUnknown: 6548 case QAquaSizeLarge: 6549 bdi.kind = kThemeIncDecButton; 6550 hackTranslateX = 0; 6551 break; 6552 case QAquaSizeSmall: 6553 bdi.kind = kThemeIncDecButtonSmall; 6554 hackTranslateX = -2; 6555 break; 6556 case QAquaSizeMini: 6557 bdi.kind = kThemeIncDecButtonMini; 6558 hackTranslateX = -1; 6559 break; 6063 } 6064 } 6065 6066 QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, 6067 const QStyleOptionComplex *opt, 6068 const QPoint &pt, const QWidget *widget) const 6069 { 6070 Q_D(const QMacStyle); 6071 SubControl sc = QStyle::SC_None; 6072 switch (cc) { 6073 case CC_ComboBox: 6074 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 6075 sc = QCommonStyle::hitTestComplexControl(cc, cmb, pt, widget); 6076 if (!cmb->editable && sc != QStyle::SC_None) 6077 sc = SC_ComboBoxArrow; // A bit of a lie, but what we want 6560 6078 } 6561 bdi.state = kThemeStateActive; 6562 bdi.value = kThemeButtonOff; 6563 bdi.adornment = kThemeAdornmentNone; 6564 HIRect hirect = qt_hirectForQRect(ret); 6565 6566 HIRect outRect; 6567 HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect); 6568 ret = qt_qrectForHIRect(outRect); 6569 switch (sc) { 6570 case SC_SpinBoxUp: 6571 ret.setHeight(ret.height() / 2); 6572 break; 6573 case SC_SpinBoxDown: 6574 ret.setY(ret.y() + ret.height() / 2); 6575 break; 6576 default: 6577 Q_ASSERT(0); 6578 break; 6079 break; 6080 case CC_Slider: 6081 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6082 HIThemeTrackDrawInfo tdi; 6083 d->getSliderInfo(cc, slider, &tdi, widget); 6084 ControlPartCode part; 6085 HIPoint pos = CGPointMake(pt.x(), pt.y()); 6086 if (HIThemeHitTestTrack(&tdi, &pos, &part)) { 6087 if (part == kControlPageUpPart || part == kControlPageDownPart) 6088 sc = SC_SliderGroove; 6089 else 6090 sc = SC_SliderHandle; 6091 } 6579 6092 } 6580 ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this)6581 ret = visualRect(spin->direction, spin->rect, ret);6582 6093 break; 6583 } 6584 case SC_SpinBoxEditField: 6585 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) { 6586 ret.setRect(fw, fw, 6587 spin->rect.width() - fw * 2, 6588 spin->rect.height() - fw * 2); 6589 } else { 6590 ret.setRect(fw, fw, 6591 spin->rect.width() - fw * 2 - spinBoxSep - spinner_w, 6592 spin->rect.height() - fw * 2); 6094 case CC_ScrollBar: 6095 if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6096 HIScrollBarTrackInfo sbi; 6097 sbi.version = qt_mac_hitheme_version; 6098 if (!(sb->state & State_Active)) 6099 sbi.enableState = kThemeTrackInactive; 6100 else if (sb->state & State_Enabled) 6101 sbi.enableState = kThemeTrackActive; 6102 else 6103 sbi.enableState = kThemeTrackDisabled; 6104 6105 // The arrow buttons are not drawn if the scroll bar is to short, 6106 // exclude them from the hit test. 6107 const int scrollBarLength = (sb->orientation == Qt::Horizontal) 6108 ? sb->rect.width() : sb->rect.height(); 6109 if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget, opt))) 6110 sbi.enableState = kThemeTrackNothingToScroll; 6111 6112 sbi.viewsize = sb->pageStep; 6113 HIPoint pos = CGPointMake(pt.x(), pt.y()); 6114 6115 HIRect macSBRect = qt_hirectForQRect(sb->rect); 6116 ControlPartCode part; 6117 bool reverseHorizontal = (sb->direction == Qt::RightToLeft 6118 && sb->orientation == Qt::Horizontal); 6119 if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal, 6120 &pos, 0, &part)) { 6121 if (part == kControlUpButtonPart) 6122 sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine; 6123 else if (part == kControlDownButtonPart) 6124 sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine; 6125 } else { 6126 HIThemeTrackDrawInfo tdi; 6127 d->getSliderInfo(cc, sb, &tdi, widget); 6128 if(tdi.enableState == kThemeTrackInactive) 6129 tdi.enableState = kThemeTrackActive; 6130 if (HIThemeHitTestTrack(&tdi, &pos, &part)) { 6131 if (part == kControlPageUpPart) 6132 sc = reverseHorizontal ? SC_ScrollBarAddPage 6133 : SC_ScrollBarSubPage; 6134 else if (part == kControlPageDownPart) 6135 sc = reverseHorizontal ? SC_ScrollBarSubPage 6136 : SC_ScrollBarAddPage; 6137 else 6138 sc = SC_ScrollBarSlider; 6139 } 6140 } 6593 6141 } 6594 ret = visualRect(spin->direction, spin->rect, ret);6595 6142 break; 6143 /* 6144 I don't know why, but we only get kWindowContentRgn here, which isn't what we want at all. 6145 It would be very nice if this would work. 6146 case QStyle::CC_TitleBar: 6147 if (const QStyleOptionTitleBar *tbar = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { 6148 HIThemeWindowDrawInfo wdi; 6149 memset(&wdi, 0, sizeof(wdi)); 6150 wdi.version = qt_mac_hitheme_version; 6151 wdi.state = kThemeStateActive; 6152 wdi.windowType = QtWinType; 6153 wdi.titleWidth = tbar->rect.width(); 6154 wdi.titleHeight = tbar->rect.height(); 6155 if (tbar->titleBarState) 6156 wdi.attributes |= kThemeWindowHasFullZoom | kThemeWindowHasCloseBox 6157 | kThemeWindowHasCollapseBox; 6158 else if (tbar->titleBarFlags & Qt::WindowSystemMenuHint) 6159 wdi.attributes |= kThemeWindowHasCloseBox; 6160 QRect tmpRect = tbar->rect; 6161 tmpRect.setHeight(tmpRect.height() + 100); 6162 HIRect hirect = qt_hirectForQRect(tmpRect); 6163 WindowRegionCode hit; 6164 HIPoint hipt = CGPointMake(pt.x(), pt.y()); 6165 if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) { 6166 switch (hit) { 6167 case kWindowCloseBoxRgn: 6168 sc = QStyle::SC_TitleBarCloseButton; 6169 break; 6170 case kWindowCollapseBoxRgn: 6171 sc = QStyle::SC_TitleBarMinButton; 6172 break; 6173 case kWindowZoomBoxRgn: 6174 sc = QStyle::SC_TitleBarMaxButton; 6175 break; 6176 case kWindowTitleTextRgn: 6177 sc = QStyle::SC_TitleBarLabel; 6178 break; 6179 default: 6180 qDebug("got something else %d", hit); 6181 break; 6182 } 6183 } 6184 } 6185 break; 6186 */ 6596 6187 default: 6597 ret = QCommonStyle::subControlRect(cc, spin, sc, widget);6188 sc = QCommonStyle::hitTestComplexControl(cc, opt, pt, widget); 6598 6189 break; 6599 }6600 6190 } 6601 break; 6191 return sc; 6192 } 6193 6194 QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, 6195 const QWidget *widget) const 6196 { 6197 Q_D(const QMacStyle); 6198 QRect ret; 6199 switch (cc) { 6200 case CC_Slider: 6201 case CC_ScrollBar: 6202 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6203 HIThemeTrackDrawInfo tdi; 6204 d->getSliderInfo(cc, slider, &tdi, widget); 6205 HIRect macRect; 6206 QCFType<HIShapeRef> shape; 6207 bool scrollBar = cc == CC_ScrollBar; 6208 if ((scrollBar && sc == SC_ScrollBarSlider) 6209 || (!scrollBar && sc == SC_SliderHandle)) { 6210 HIThemeGetTrackThumbShape(&tdi, &shape); 6211 ptrHIShapeGetBounds(shape, &macRect); 6212 } else if (!scrollBar && sc == SC_SliderGroove) { 6213 HIThemeGetTrackBounds(&tdi, &macRect); 6214 } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available... 6215 HIThemeGetTrackDragRect(&tdi, &macRect); 6216 } else { 6217 ControlPartCode cpc; 6218 if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) { 6219 cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart 6220 : kControlPageUpPart; 6221 } else { 6222 cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart 6223 : kControlDownButtonPart; 6224 if (slider->direction == Qt::RightToLeft 6225 && slider->orientation == Qt::Horizontal) { 6226 if (cpc == kControlDownButtonPart) 6227 cpc = kControlUpButtonPart; 6228 else if (cpc == kControlUpButtonPart) 6229 cpc = kControlDownButtonPart; 6230 } 6231 } 6232 HIThemeGetTrackPartBounds(&tdi, cpc, &macRect); 6233 } 6234 ret = qt_qrectForHIRect(macRect); 6235 6236 // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons 6237 // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover 6238 // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't. 6239 if (slider->orientation == Qt::Horizontal) { 6240 if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine) 6241 ret.adjust(0, 0, 1, 0); 6242 else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine) 6243 ret.adjust(-1, 0, 1, 0); 6244 } else if (sc == SC_ScrollBarAddLine) { 6245 ret.adjust(0, -1, 0, 1); 6246 } 6247 } 6248 break; 6249 case CC_TitleBar: 6250 if (const QStyleOptionTitleBar *titlebar 6251 = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { 6252 HIThemeWindowDrawInfo wdi; 6253 memset(&wdi, 0, sizeof(wdi)); 6254 wdi.version = qt_mac_hitheme_version; 6255 wdi.state = kThemeStateActive; 6256 wdi.windowType = QtWinType; 6257 wdi.titleHeight = titlebar->rect.height(); 6258 wdi.titleWidth = titlebar->rect.width(); 6259 wdi.attributes = kThemeWindowHasTitleText; 6260 if (titlebar->subControls & SC_TitleBarCloseButton) 6261 wdi.attributes |= kThemeWindowHasCloseBox; 6262 if (titlebar->subControls & SC_TitleBarMaxButton 6263 | SC_TitleBarNormalButton) 6264 wdi.attributes |= kThemeWindowHasFullZoom; 6265 if (titlebar->subControls & SC_TitleBarMinButton) 6266 wdi.attributes |= kThemeWindowHasCollapseBox; 6267 WindowRegionCode wrc = kWindowGlobalPortRgn; 6268 6269 if (sc == SC_TitleBarCloseButton) 6270 wrc = kWindowCloseBoxRgn; 6271 else if (sc == SC_TitleBarMinButton) 6272 wrc = kWindowCollapseBoxRgn; 6273 else if (sc == SC_TitleBarMaxButton) 6274 wrc = kWindowZoomBoxRgn; 6275 else if (sc == SC_TitleBarLabel) 6276 wrc = kWindowTitleTextRgn; 6277 else if (sc == SC_TitleBarSysMenu) 6278 ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight, 6279 titlebar, widget)); 6280 if (wrc != kWindowGlobalPortRgn) { 6281 QCFType<HIShapeRef> region; 6282 QRect tmpRect = titlebar->rect; 6283 HIRect titleRect = qt_hirectForQRect(tmpRect); 6284 HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, ®ion); 6285 ptrHIShapeGetBounds(region, &titleRect); 6286 CFRelease(region); 6287 tmpRect.translate(tmpRect.x() - int(titleRect.origin.x), 6288 tmpRect.y() - int(titleRect.origin.y)); 6289 titleRect = qt_hirectForQRect(tmpRect); 6290 HIThemeGetWindowShape(&titleRect, &wdi, wrc, ®ion); 6291 ptrHIShapeGetBounds(region, &titleRect); 6292 ret = qt_qrectForHIRect(titleRect); 6293 } 6294 } 6295 break; 6296 case CC_ComboBox: 6297 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) { 6298 HIThemeButtonDrawInfo bdi; 6299 d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); 6300 6301 switch (sc) { 6302 case SC_ComboBoxEditField:{ 6303 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); 6304 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) 6305 ret.setHeight(ret.height() - 1); 6306 break; } 6307 case SC_ComboBoxArrow:{ 6308 ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); 6309 ret.setX(ret.x() + ret.width()); 6310 ret.setWidth(combo->rect.right() - ret.right()); 6311 break; } 6312 case SC_ComboBoxListBoxPopup:{ 6313 if (combo->editable) { 6314 HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind); 6315 QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); 6316 const int comboTop = combo->rect.top(); 6317 ret = QRect(qRound(inner.origin.x), 6318 comboTop, 6319 qRound(inner.origin.x - combo->rect.left() + inner.size.width), 6320 editRect.bottom() - comboTop + 2); 6321 } else { 6322 QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); 6323 ret = QRect(combo->rect.x() + 4 - 11, 6324 combo->rect.y() + 1, 6325 editRect.width() + 10 + 11, 6326 1); 6327 } 6328 break; } 6329 default: 6330 break; 6331 } 6332 } 6333 break; 6334 case CC_GroupBox: 6335 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) { 6336 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; 6337 const bool flat = groupBox->features & QStyleOptionFrame::Flat; 6338 bool hasNoText = !checkable && groupBox->text.isEmpty(); 6339 switch (sc) { 6340 case SC_GroupBoxLabel: 6341 case SC_GroupBoxCheckBox: { 6342 // Cheat and use the smaller font if we need to 6343 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; 6344 bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)) 6345 || !QApplication::desktopSettingsAware(); 6346 int tw; 6347 int h; 6348 int margin = flat || hasNoText ? 0 : 9; 6349 ret = groupBox->rect.adjusted(margin, 0, -margin, 0); 6350 6351 if (!fontIsSet) { 6352 HIThemeTextInfo tti; 6353 tti.version = qt_mac_hitheme_version; 6354 tti.state = kThemeStateActive; 6355 tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont; 6356 tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; 6357 tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; 6358 tti.options = kHIThemeTextBoxOptionNone; 6359 tti.truncationPosition = kHIThemeTextTruncationNone; 6360 tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n')); 6361 CGFloat width; 6362 CGFloat height; 6363 QCFString groupText = qt_mac_removeMnemonics(groupBox->text); 6364 HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0); 6365 tw = qRound(width); 6366 h = qCeil(height); 6367 } else { 6368 QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics); 6369 h = qCeil(fm.height()); 6370 tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width()); 6371 } 6372 ret.setHeight(h); 6373 6374 QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, 6375 QSize(tw, h), ret); 6376 if (flat && checkable) 6377 labelRect.moveLeft(labelRect.left() + 4); 6378 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); 6379 bool rtl = groupBox->direction == Qt::RightToLeft; 6380 if (sc == SC_GroupBoxLabel) { 6381 if (checkable) { 6382 int newSum = indicatorWidth + 1; 6383 int newLeft = labelRect.left() + (rtl ? -newSum : newSum); 6384 labelRect.moveLeft(newLeft); 6385 if (flat) 6386 labelRect.moveTop(labelRect.top() + 3); 6387 else 6388 labelRect.moveTop(labelRect.top() + 4); 6389 } else if (flat) { 6390 int newLeft = labelRect.left() - (rtl ? 3 : -3); 6391 labelRect.moveLeft(newLeft); 6392 labelRect.moveTop(labelRect.top() + 3); 6393 } else { 6394 int newLeft = labelRect.left() - (rtl ? 3 : 2); 6395 labelRect.moveLeft(newLeft); 6396 labelRect.moveTop(labelRect.top() + 4); 6397 } 6398 ret = labelRect; 6399 } 6400 6401 if (sc == SC_GroupBoxCheckBox) { 6402 int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left() - 1; 6403 int top = flat ? ret.top() + 1 : ret.top() + 5; 6404 ret.setRect(left, top, 6405 indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget)); 6406 } 6407 break; 6408 } 6409 case SC_GroupBoxContents: 6410 case SC_GroupBoxFrame: { 6411 QFontMetrics fm = groupBox->fontMetrics; 6412 int yOffset = 3; 6413 if (!flat) { 6414 if (widget && !widget->testAttribute(Qt::WA_SetFont) 6415 && QApplication::desktopSettingsAware()) 6416 fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); 6417 yOffset = 5; 6418 } 6419 6420 if (hasNoText) 6421 yOffset = -qCeil(QFontMetricsF(fm).height()); 6422 ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0); 6423 if (sc == SC_GroupBoxContents) { 6424 if (flat) 6425 ret.adjust(3, -5, -3, -4); // guess too 6426 else 6427 ret.adjust(3, 3, -3, -4); // guess 6428 } 6429 } 6430 break; 6431 default: 6432 ret = QCommonStyle::subControlRect(cc, groupBox, sc, widget); 6433 break; 6434 } 6435 } 6436 break; 6437 #ifndef QT_NO_SPINBOX 6438 case CC_SpinBox: 6439 if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 6440 QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget); 6441 int spinner_w; 6442 int spinBoxSep; 6443 int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget); 6444 switch (aquaSize) { 6445 default: 6446 case QAquaSizeUnknown: 6447 case QAquaSizeLarge: 6448 spinner_w = 14; 6449 spinBoxSep = 2; 6450 break; 6451 case QAquaSizeSmall: 6452 spinner_w = 12; 6453 spinBoxSep = 2; 6454 break; 6455 case QAquaSizeMini: 6456 spinner_w = 10; 6457 spinBoxSep = 1; 6458 break; 6459 } 6460 6461 switch (sc) { 6462 case SC_SpinBoxUp: 6463 case SC_SpinBoxDown: { 6464 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) 6465 break; 6466 6467 const int y = fw; 6468 const int x = spin->rect.width() - spinner_w; 6469 ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2); 6470 HIThemeButtonDrawInfo bdi; 6471 bdi.version = qt_mac_hitheme_version; 6472 bdi.kind = kThemeIncDecButton; 6473 int hackTranslateX; 6474 switch (aquaSize) { 6475 default: 6476 case QAquaSizeUnknown: 6477 case QAquaSizeLarge: 6478 bdi.kind = kThemeIncDecButton; 6479 hackTranslateX = 0; 6480 break; 6481 case QAquaSizeSmall: 6482 bdi.kind = kThemeIncDecButtonSmall; 6483 hackTranslateX = -2; 6484 break; 6485 case QAquaSizeMini: 6486 bdi.kind = kThemeIncDecButtonMini; 6487 hackTranslateX = -1; 6488 break; 6489 } 6490 bdi.state = kThemeStateActive; 6491 bdi.value = kThemeButtonOff; 6492 bdi.adornment = kThemeAdornmentNone; 6493 HIRect hirect = qt_hirectForQRect(ret); 6494 6495 HIRect outRect; 6496 HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect); 6497 ret = qt_qrectForHIRect(outRect); 6498 switch (sc) { 6499 case SC_SpinBoxUp: 6500 ret.setHeight(ret.height() / 2); 6501 break; 6502 case SC_SpinBoxDown: 6503 ret.setY(ret.y() + ret.height() / 2); 6504 break; 6505 default: 6506 Q_ASSERT(0); 6507 break; 6508 } 6509 ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this) 6510 ret = visualRect(spin->direction, spin->rect, ret); 6511 break; 6512 } 6513 case SC_SpinBoxEditField: 6514 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) { 6515 ret.setRect(fw, fw, 6516 spin->rect.width() - fw * 2, 6517 spin->rect.height() - fw * 2); 6518 } else { 6519 ret.setRect(fw, fw, 6520 spin->rect.width() - fw * 2 - spinBoxSep - spinner_w, 6521 spin->rect.height() - fw * 2); 6522 } 6523 ret = visualRect(spin->direction, spin->rect, ret); 6524 break; 6525 default: 6526 ret = QCommonStyle::subControlRect(cc, spin, sc, widget); 6527 break; 6528 } 6529 } 6530 break; 6602 6531 #endif 6603 case CC_ToolButton:6604 ret = QCommonStyle::subControlRect(cc, opt, sc, widget);6605 if (sc == SC_ToolButtonMenu6532 case CC_ToolButton: 6533 ret = QCommonStyle::subControlRect(cc, opt, sc, widget); 6534 if (sc == SC_ToolButtonMenu 6606 6535 #ifndef QT_NO_ACCESSIBILITY 6607 && !QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)6536 && !QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar) 6608 6537 #endif 6609 ) { 6610 ret.adjust(-1, 0, 0, 0); 6538 ) { 6539 ret.adjust(-1, 0, 0, 0); 6540 } 6541 break; 6542 default: 6543 ret = QCommonStyle::subControlRect(cc, opt, sc, widget); 6544 break; 6611 6545 } 6612 break; 6613 default: 6614 ret = QCommonStyle::subControlRect(cc, opt, sc, widget); 6615 break; 6546 return ret; 6616 6547 } 6617 return ret; 6618 } 6619 6620 QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, 6621 const QSize &csz, const QWidget *widget) const 6622 { 6623 Q_D(const QMacStyle); 6624 QSize sz(csz); 6625 bool useAquaGuideline = true; 6626 6627 switch (ct) { 6628 #if QT_CONFIG(spinbox) 6629 case CT_SpinBox: 6630 if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 6631 // Add button + frame widths 6632 int buttonWidth = 20; 6633 int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget); 6634 sz += QSize(buttonWidth + 2*fw, 2*fw - 3); 6635 } 6636 break; 6548 6549 QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, 6550 const QSize &csz, const QWidget *widget) const 6551 { 6552 Q_D(const QMacStyle); 6553 QSize sz(csz); 6554 bool useAquaGuideline = true; 6555 6556 switch (ct) { 6557 #ifndef QT_NO_SPINBOX 6558 case CT_SpinBox: 6559 if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { 6560 // Add button + frame widths 6561 int buttonWidth = 20; 6562 int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget); 6563 sz += QSize(buttonWidth + 2*fw, 2*fw - 3); 6564 } 6565 break; 6637 6566 #endif 6638 case QStyle::CT_TabWidget:6639 // the size between the pane and the "contentsRect" (+4,+4)6640 // (the "contentsRect" is on the inside of the pane)6641 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget);6642 /**6643 This is supposed to show the relationship between the tabBar and6644 the stack widget of a QTabWidget.6645 Unfortunately ascii is not a good way of representing graphics.....6646 PS: The '=' line is the painted frame.6647 6648 top ---+6649 6650 6651 6652 6653 6654 TAB BAR +=====^============ | +2 pixels6655 6656 6657 6658 6659 6660 bottom ------+ <-+ +14 pixels6661 6662 6663 ------------------------------ <- top of stack widget6664 6665 6666 To summarize:6667 * 2 is the distance between the pane and the contentsRect6668 * The 14 and the 1's are the distance from the contentsRect to the stack widget.6669 (same value as used in SE_TabWidgetTabContents)6670 * overlap is how much the pane should overlap the tab bar6671 */6672 // then add the size between the stackwidget and the "contentsRect"6673 #if QT_CONFIG(tabwidget)6674 if (const QStyleOptionTabWidgetFrame *twf6675 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {6676 QSize extra(0,0);6677 const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget);6678 const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap;6679 6680 if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) {6681 extra = QSize(2, gapBetweenTabbarAndStackWidget + 1);6682 } else {6683 extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2);6684 }6685 sz+= extra;6686 }6567 case QStyle::CT_TabWidget: 6568 // the size between the pane and the "contentsRect" (+4,+4) 6569 // (the "contentsRect" is on the inside of the pane) 6570 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); 6571 /** 6572 This is supposed to show the relationship between the tabBar and 6573 the stack widget of a QTabWidget. 6574 Unfortunately ascii is not a good way of representing graphics..... 6575 PS: The '=' line is the painted frame. 6576 6577 top ---+ 6578 | 6579 | 6580 | 6581 | vvv just outside the painted frame is the "pane" 6582 - -|- - - - - - - - - - <-+ 6583 TAB BAR +=====^============ | +2 pixels 6584 - - -|- - -|- - - - - - - <-+ 6585 | | ^ ^^^ just inside the painted frame is the "contentsRect" 6586 | | | 6587 | overlap | 6588 | | | 6589 bottom ------+ <-+ +14 pixels 6590 | 6591 v 6592 ------------------------------ <- top of stack widget 6593 6594 6595 To summarize: 6596 * 2 is the distance between the pane and the contentsRect 6597 * The 14 and the 1's are the distance from the contentsRect to the stack widget. 6598 (same value as used in SE_TabWidgetTabContents) 6599 * overlap is how much the pane should overlap the tab bar 6600 */ 6601 // then add the size between the stackwidget and the "contentsRect" 6602 #ifndef QT_NO_TABWIDGET 6603 if (const QStyleOptionTabWidgetFrame *twf 6604 = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) { 6605 QSize extra(0,0); 6606 const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); 6607 const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; 6608 6609 if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { 6610 extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); 6611 } else { 6612 extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); 6613 } 6614 sz+= extra; 6615 } 6687 6616 #endif 6688 break;6689 #if QT_CONFIG(tabbar)6690 case QStyle::CT_TabBarTab:6691 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {6692 const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget);6693 const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont))6694 || !QApplication::desktopSettingsAware();6695 ThemeTabDirection ttd = getTabDirection(tab->shape);6696 bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;6697 if (vertTabs)6698 sz = sz.transposed();6699 int defaultTabHeight;6700 int extraHSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget);6701 QFontMetrics fm = opt->fontMetrics;6702 switch (AquaSize) {6703 case QAquaSizeUnknown:6704 case QAquaSizeLarge:6705 if (tab->documentMode)6706 defaultTabHeight = 24;6707 else6708 defaultTabHeight = 21;6709 6617 break; 6710 case QAquaSizeSmall: 6711 defaultTabHeight = 18; 6618 #ifndef QT_NO_TABBAR 6619 case QStyle::CT_TabBarTab: 6620 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { 6621 const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); 6622 const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) 6623 || !QApplication::desktopSettingsAware(); 6624 ThemeTabDirection ttd = getTabDirection(tab->shape); 6625 bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; 6626 if (vertTabs) 6627 sz = sz.transposed(); 6628 int defaultTabHeight; 6629 int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK) 6630 QFontMetrics fm = opt->fontMetrics; 6631 switch (AquaSize) { 6632 case QAquaSizeUnknown: 6633 case QAquaSizeLarge: 6634 if (tab->documentMode) 6635 defaultTabHeight = 23; 6636 else 6637 defaultTabHeight = 21; 6638 break; 6639 case QAquaSizeSmall: 6640 defaultTabHeight = 18; 6641 break; 6642 case QAquaSizeMini: 6643 defaultTabHeight = 16; 6644 break; 6645 } 6646 bool setWidth = false; 6647 if (differentFont || !tab->icon.isNull()) { 6648 sz.rheight() = qMax(defaultTabHeight, sz.height()); 6649 } else { 6650 QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); 6651 sz.rheight() = qMax(defaultTabHeight, textSize.height()); 6652 sz.rwidth() = textSize.width() + defaultExtraSpace; 6653 setWidth = true; 6654 } 6655 6656 if (vertTabs) 6657 sz = sz.transposed(); 6658 6659 int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); 6660 int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); 6661 6662 int widgetWidth = 0; 6663 int widgetHeight = 0; 6664 int padding = 0; 6665 if (tab->leftButtonSize.isValid()) { 6666 padding += 8; 6667 widgetWidth += tab->leftButtonSize.width(); 6668 widgetHeight += tab->leftButtonSize.height(); 6669 } 6670 if (tab->rightButtonSize.isValid()) { 6671 padding += 8; 6672 widgetWidth += tab->rightButtonSize.width(); 6673 widgetHeight += tab->rightButtonSize.height(); 6674 } 6675 6676 if (vertTabs) { 6677 sz.setHeight(sz.height() + widgetHeight + padding); 6678 sz.setWidth(qMax(sz.width(), maxWidgetWidth)); 6679 } else { 6680 if (setWidth) 6681 sz.setWidth(sz.width() + widgetWidth + padding); 6682 sz.setHeight(qMax(sz.height(), maxWidgetHeight)); 6683 } 6684 } 6712 6685 break; 6713 case QAquaSizeMini: 6714 defaultTabHeight = 16; 6686 #endif 6687 case QStyle::CT_PushButton: 6688 // By default, we fit the contents inside a normal rounded push button. 6689 // Do this by add enough space around the contents so that rounded 6690 // borders (including highlighting when active) will show. 6691 sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; 6692 if (opt->state & QStyle::State_Small) 6693 sz.rheight() += 14; 6694 else 6695 sz.rheight() += 4; 6715 6696 break; 6716 } 6717 bool setWidth = false; 6718 if (differentFont || !tab->icon.isNull()) { 6719 sz.rheight() = qMax(defaultTabHeight, sz.height()); 6720 } else { 6721 QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); 6722 sz.rheight() = qMax(defaultTabHeight, textSize.height()); 6723 sz.rwidth() = textSize.width(); 6724 setWidth = true; 6725 } 6726 sz.rwidth() += extraHSpace; 6727 6728 if (vertTabs) 6729 sz = sz.transposed(); 6730 6731 int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); 6732 int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); 6733 6734 int widgetWidth = 0; 6735 int widgetHeight = 0; 6736 int padding = 0; 6737 if (tab->leftButtonSize.isValid()) { 6738 padding += 8; 6739 widgetWidth += tab->leftButtonSize.width(); 6740 widgetHeight += tab->leftButtonSize.height(); 6741 } 6742 if (tab->rightButtonSize.isValid()) { 6743 padding += 8; 6744 widgetWidth += tab->rightButtonSize.width(); 6745 widgetHeight += tab->rightButtonSize.height(); 6746 } 6747 6748 if (vertTabs) { 6749 sz.setHeight(sz.height() + widgetHeight + padding); 6750 sz.setWidth(qMax(sz.width(), maxWidgetWidth)); 6751 } else { 6752 if (setWidth) 6753 sz.setWidth(sz.width() + widgetWidth + padding); 6754 sz.setHeight(qMax(sz.height(), maxWidgetHeight)); 6755 } 6756 } 6757 break; 6697 case QStyle::CT_MenuItem: 6698 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 6699 int maxpmw = mi->maxIconWidth; 6700 #ifndef QT_NO_COMBOBOX 6701 const QComboBox *comboBox = qobject_cast<const QComboBox *>(widget); 6758 6702 #endif 6759 case QStyle::CT_PushButton: 6760 // By default, we fit the contents inside a normal rounded push button. 6761 // Do this by add enough space around the contents so that rounded 6762 // borders (including highlighting when active) will show. 6763 sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; 6764 if (opt->state & QStyle::State_Small) 6765 sz.rheight() += 14; 6766 else 6767 sz.rheight() += 4; 6768 break; 6769 case QStyle::CT_MenuItem: 6770 if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { 6771 int maxpmw = mi->maxIconWidth; 6772 #if QT_CONFIG(combobox) 6773 const QComboBox *comboBox = qobject_cast<const QComboBox *>(widget); 6703 int w = sz.width(), 6704 h = sz.height(); 6705 if (mi->menuItemType == QStyleOptionMenuItem::Separator) { 6706 w = 10; 6707 SInt16 ash; 6708 GetThemeMenuSeparatorHeight(&ash); 6709 h = ash; 6710 } else { 6711 h = mi->fontMetrics.height() + 2; 6712 if (!mi->icon.isNull()) { 6713 #ifndef QT_NO_COMBOBOX 6714 if (comboBox) { 6715 const QSize &iconSize = comboBox->iconSize(); 6716 h = qMax(h, iconSize.height() + 4); 6717 maxpmw = qMax(maxpmw, iconSize.width()); 6718 } else 6774 6719 #endif 6775 int w = sz.width(), 6776 h = sz.height(); 6777 if (mi->menuItemType == QStyleOptionMenuItem::Separator) { 6778 w = 10; 6779 SInt16 ash; 6780 GetThemeMenuSeparatorHeight(&ash); 6781 h = ash; 6782 } else { 6783 h = mi->fontMetrics.height() + 2; 6784 if (!mi->icon.isNull()) { 6785 #if QT_CONFIG(combobox) 6786 if (comboBox) { 6787 const QSize &iconSize = comboBox->iconSize(); 6788 h = qMax(h, iconSize.height() + 4); 6789 maxpmw = qMax(maxpmw, iconSize.width()); 6720 { 6721 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 6722 h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); 6723 } 6724 } 6725 } 6726 if (mi->text.contains(QLatin1Char('\t'))) 6727 w += 12; 6728 if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) 6729 w += 20; 6730 if (maxpmw) 6731 w += maxpmw + 6; 6732 // add space for a check. All items have place for a check too. 6733 w += 20; 6734 #ifndef QT_NO_COMBOBOX 6735 if (comboBox && comboBox->isVisible()) { 6736 QStyleOptionComboBox cmb; 6737 cmb.initFrom(comboBox); 6738 cmb.editable = false; 6739 cmb.subControls = QStyle::SC_ComboBoxEditField; 6740 cmb.activeSubControls = QStyle::SC_None; 6741 w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb, 6742 QStyle::SC_ComboBoxEditField, 6743 comboBox).width()); 6790 6744 } else 6791 6745 #endif 6792 6746 { 6793 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); 6794 h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); 6747 w += 12; 6795 6748 } 6749 sz = QSize(w, h); 6796 6750 } 6751 break; 6752 case CT_MenuBarItem: 6753 if (!sz.isEmpty()) 6754 sz += QSize(12, 4); // Constants from QWindowsStyle 6755 break; 6756 case CT_ToolButton: 6757 sz.rwidth() += 10; 6758 sz.rheight() += 10; 6759 return sz; 6760 case CT_ComboBox: { 6761 sz.rwidth() += 50; 6762 const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt); 6763 if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable)) 6764 sz.rheight() += 2; 6765 break; 6797 6766 } 6798 if (mi->text.contains(QLatin1Char('\t'))) 6799 w += 12; 6800 if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) 6801 w += 20; 6802 if (maxpmw) 6803 w += maxpmw + 6; 6804 // add space for a check. All items have place for a check too. 6805 w += 20; 6806 #if QT_CONFIG(combobox) 6807 if (comboBox && comboBox->isVisible()) { 6808 QStyleOptionComboBox cmb; 6809 cmb.initFrom(comboBox); 6810 cmb.editable = false; 6811 cmb.subControls = QStyle::SC_ComboBoxEditField; 6812 cmb.activeSubControls = QStyle::SC_None; 6813 w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb, 6814 QStyle::SC_ComboBoxEditField, 6815 comboBox).width()); 6816 } else 6817 #endif 6818 { 6819 w += 12; 6820 } 6821 sz = QSize(w, h); 6822 } 6823 break; 6824 case CT_MenuBarItem: 6825 if (!sz.isEmpty()) 6826 sz += QSize(12, 4); // Constants from QWindowsStyle 6827 break; 6828 case CT_ToolButton: 6829 sz.rwidth() += 10; 6830 sz.rheight() += 10; 6831 return sz; 6832 case CT_ComboBox: { 6833 sz.rwidth() += 50; 6834 const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt); 6835 if (cb && !cb->editable) 6836 sz.rheight() += 2; 6837 break; 6838 } 6839 case CT_Menu: { 6840 if (proxy() == this) { 6841 sz = csz; 6842 } else { 6843 QStyleHintReturnMask menuMask; 6844 QStyleOption myOption = *opt; 6845 myOption.rect.setSize(sz); 6846 if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) 6847 sz = menuMask.region.boundingRect().size(); 6848 } 6849 break; } 6850 case CT_HeaderSection:{ 6851 const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt); 6852 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); 6853 if (header->text.contains(QLatin1Char('\n'))) 6854 useAquaGuideline = false; 6855 break; } 6856 case CT_ScrollBar : 6857 // Make sure that the scroll bar is large enough to display the thumb indicator. 6858 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6859 const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, widgetSizePolicy(widget, opt)); 6860 if (slider->orientation == Qt::Horizontal) 6861 sz = sz.expandedTo(QSize(minimumSize, sz.height())); 6862 else 6863 sz = sz.expandedTo(QSize(sz.width(), minimumSize)); 6864 } 6865 break; 6866 case CT_ItemViewItem: 6867 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) { 6868 sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget); 6869 sz.setHeight(sz.height() + 2); 6870 } 6871 break; 6872 6873 default: 6874 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); 6875 } 6876 6877 if (useAquaGuideline){ 6878 QSize macsz; 6879 if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) { 6880 if (macsz.width() != -1) 6881 sz.setWidth(macsz.width()); 6882 if (macsz.height() != -1) 6883 sz.setHeight(macsz.height()); 6884 } 6885 } 6886 6887 // The sizes that Carbon and the guidelines gives us excludes the focus frame. 6888 // We compensate for this by adding some extra space here to make room for the frame when drawing: 6889 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){ 6890 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); 6891 int bkind = 0; 6892 switch (widgetSize) { 6893 default: 6894 case QAquaSizeLarge: 6895 bkind = combo->editable ? kThemeComboBox : kThemePopupButton; 6896 break; 6897 case QAquaSizeSmall: 6898 bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall); 6899 break; 6900 case QAquaSizeMini: 6901 bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini; 6902 break; 6903 } 6904 HIRect tmpRect = {{0, 0}, {0, 0}}; 6905 HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind); 6906 sz.rwidth() -= qRound(diffRect.size.width); 6907 sz.rheight() -= qRound(diffRect.size.height); 6908 } else if (ct == CT_PushButton || ct == CT_ToolButton){ 6909 ThemeButtonKind bkind; 6910 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); 6911 switch (ct) { 6912 default: 6913 case CT_PushButton: 6914 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 6915 if (btn->features & QStyleOptionButton::CommandLinkButton) { 6916 return QCommonStyle::sizeFromContents(ct, opt, sz, widget); 6767 case CT_Menu: { 6768 if (proxy() == this) { 6769 sz = csz; 6770 } else { 6771 QStyleHintReturnMask menuMask; 6772 QStyleOption myOption = *opt; 6773 myOption.rect.setSize(sz); 6774 if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) 6775 sz = menuMask.region.boundingRect().size(); 6776 } 6777 break; } 6778 case CT_HeaderSection:{ 6779 const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt); 6780 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); 6781 if (header->text.contains(QLatin1Char('\n'))) 6782 useAquaGuideline = false; 6783 break; } 6784 case CT_ScrollBar : 6785 // Make sure that the scroll bar is large enough to display the thumb indicator. 6786 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { 6787 const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, widgetSizePolicy(widget, opt)); 6788 if (slider->orientation == Qt::Horizontal) 6789 sz = sz.expandedTo(QSize(minimumSize, sz.height())); 6790 else 6791 sz = sz.expandedTo(QSize(sz.width(), minimumSize)); 6917 6792 } 6918 }6919 6920 switch (widgetSize) {6921 default:6922 case QAquaSizeLarge:6923 bkind = kThemePushButton;6924 break;6925 case QAquaSizeSmall:6926 bkind = kThemePushButtonSmall;6927 6793 break; 6928 case QAquaSizeMini: 6929 bkind = kThemePushButtonMini; 6794 case CT_ItemViewItem: 6795 if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) { 6796 sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget); 6797 sz.setHeight(sz.height() + 2); 6798 } 6930 6799 break; 6800 6801 default: 6802 sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); 6803 } 6804 6805 if (useAquaGuideline){ 6806 QSize macsz; 6807 if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) { 6808 if (macsz.width() != -1) 6809 sz.setWidth(macsz.width()); 6810 if (macsz.height() != -1) 6811 sz.setHeight(macsz.height()); 6931 6812 } 6932 break; 6933 case CT_ToolButton: 6813 } 6814 6815 // The sizes that Carbon and the guidelines gives us excludes the focus frame. 6816 // We compensate for this by adding some extra space here to make room for the frame when drawing: 6817 if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){ 6818 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); 6819 int bkind = 0; 6934 6820 switch (widgetSize) { 6935 default: 6936 case QAquaSizeLarge: 6937 bkind = kThemeLargeBevelButton; 6938 break; 6939 case QAquaSizeMini: 6940 case QAquaSizeSmall: 6941 bkind = kThemeSmallBevelButton; 6821 default: 6822 case QAquaSizeLarge: 6823 bkind = combo->editable ? kThemeComboBox : kThemePopupButton; 6824 break; 6825 case QAquaSizeSmall: 6826 bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall); 6827 break; 6828 case QAquaSizeMini: 6829 bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini; 6830 break; 6942 6831 } 6943 break; 6832 HIRect tmpRect = {{0, 0}, {0, 0}}; 6833 HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind); 6834 sz.rwidth() -= qRound(diffRect.size.width); 6835 sz.rheight() -= qRound(diffRect.size.height); 6836 } else if (ct == CT_PushButton || ct == CT_ToolButton){ 6837 ThemeButtonKind bkind; 6838 QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); 6839 switch (ct) { 6840 default: 6841 case CT_PushButton: 6842 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) { 6843 if (btn->features & QStyleOptionButton::CommandLinkButton) { 6844 return QCommonStyle::sizeFromContents(ct, opt, sz, widget); 6845 } 6846 } 6847 6848 switch (widgetSize) { 6849 default: 6850 case QAquaSizeLarge: 6851 bkind = kThemePushButton; 6852 break; 6853 case QAquaSizeSmall: 6854 bkind = kThemePushButtonSmall; 6855 break; 6856 case QAquaSizeMini: 6857 bkind = kThemePushButtonMini; 6858 break; 6859 } 6860 break; 6861 case CT_ToolButton: 6862 switch (widgetSize) { 6863 default: 6864 case QAquaSizeLarge: 6865 bkind = kThemeLargeBevelButton; 6866 break; 6867 case QAquaSizeMini: 6868 case QAquaSizeSmall: 6869 bkind = kThemeSmallBevelButton; 6870 } 6871 break; 6872 } 6873 6874 HIThemeButtonDrawInfo bdi; 6875 bdi.version = qt_mac_hitheme_version; 6876 bdi.state = kThemeStateActive; 6877 bdi.kind = bkind; 6878 bdi.value = kThemeButtonOff; 6879 bdi.adornment = kThemeAdornmentNone; 6880 HIRect macRect, myRect; 6881 myRect = CGRectMake(0, 0, sz.width(), sz.height()); 6882 HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); 6883 // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess), 6884 if (bkind == kThemePushButtonMini) 6885 macRect.size.height += 8.; 6886 else if (bkind == kThemePushButtonSmall) 6887 macRect.size.height -= 10; 6888 sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width)); 6889 sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height)); 6944 6890 } 6945 6946 HIThemeButtonDrawInfo bdi; 6947 bdi.version = qt_mac_hitheme_version; 6948 bdi.state = kThemeStateActive; 6949 bdi.kind = bkind; 6950 bdi.value = kThemeButtonOff; 6951 bdi.adornment = kThemeAdornmentNone; 6952 HIRect macRect, myRect; 6953 myRect = CGRectMake(0, 0, sz.width(), sz.height()); 6954 HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); 6955 // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess), 6956 if (bkind == kThemePushButtonMini) 6957 macRect.size.height += 8.; 6958 else if (bkind == kThemePushButtonSmall) 6959 macRect.size.height -= 10; 6960 sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width)); 6961 sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height)); 6891 return sz; 6962 6892 } 6963 return sz; 6964 } 6965 6966 void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, 6967 bool enabled, const QString &text, QPalette::ColorRole textRole) const 6968 { 6969 if(flags & Qt::TextShowMnemonic) 6970 flags |= Qt::TextHideMnemonic; 6971 QCommonStyle::drawItemText(p, r, flags, pal, enabled, text, textRole); 6972 } 6973 6974 bool QMacStyle::event(QEvent *e) 6975 { 6976 Q_D(QMacStyle); 6977 if(e->type() == QEvent::FocusIn) { 6978 QWidget *f = 0; 6979 QWidget *focusWidget = QApplication::focusWidget(); 6980 #if QT_CONFIG(graphicsview) 6981 if (QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(focusWidget)) { 6982 QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; 6983 if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { 6984 QGraphicsProxyWidget *proxy = static_cast<QGraphicsProxyWidget *>(focusItem); 6985 if (proxy->widget()) 6986 focusWidget = proxy->widget()->focusWidget(); 6893 6894 void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, 6895 bool enabled, const QString &text, QPalette::ColorRole textRole) const 6896 { 6897 if(flags & Qt::TextShowMnemonic) 6898 flags |= Qt::TextHideMnemonic; 6899 QCommonStyle::drawItemText(p, r, flags, pal, enabled, text, textRole); 6900 } 6901 6902 bool QMacStyle::event(QEvent *e) 6903 { 6904 Q_D(QMacStyle); 6905 if(e->type() == QEvent::FocusIn) { 6906 QWidget *f = 0; 6907 QWidget *focusWidget = QApplication::focusWidget(); 6908 #ifndef QT_NO_GRAPHICSVIEW 6909 if (QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(focusWidget)) { 6910 QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; 6911 if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { 6912 QGraphicsProxyWidget *proxy = static_cast<QGraphicsProxyWidget *>(focusItem); 6913 if (proxy->widget()) 6914 focusWidget = proxy->widget()->focusWidget(); 6915 } 6987 6916 } 6988 }6989 6917 #endif 6990 if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) { 6991 f = focusWidget; 6992 QWidget *top = f->parentWidget(); 6993 while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow)) 6994 top = top->parentWidget(); 6995 #if QT_CONFIG(mainwindow) 6996 if (qobject_cast<QMainWindow *>(top)) { 6997 QWidget *central = static_cast<QMainWindow *>(top)->centralWidget(); 6998 for (const QWidget *par = f; par; par = par->parentWidget()) { 6999 if (par == central) { 7000 top = central; 7001 break; 6918 if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) { 6919 f = focusWidget; 6920 QWidget *top = f->parentWidget(); 6921 while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow)) 6922 top = top->parentWidget(); 6923 #ifndef QT_NO_MAINWINDOW 6924 if (qobject_cast<QMainWindow *>(top)) { 6925 QWidget *central = static_cast<QMainWindow *>(top)->centralWidget(); 6926 for (const QWidget *par = f; par; par = par->parentWidget()) { 6927 if (par == central) { 6928 top = central; 6929 break; 6930 } 6931 if (par->isWindow()) 6932 break; 7002 6933 } 7003 if (par->isWindow())7004 break;7005 6934 } 7006 }7007 6935 #endif 6936 } 6937 if (f) { 6938 if(!d->focusWidget) 6939 d->focusWidget = new QFocusFrame(f); 6940 d->focusWidget->setWidget(f); 6941 } else if(d->focusWidget) { 6942 d->focusWidget->setWidget(0); 6943 } 6944 } else if(e->type() == QEvent::FocusOut) { 6945 if(d->focusWidget) 6946 d->focusWidget->setWidget(0); 7008 6947 } 7009 if (f) { 7010 if(!d->focusWidget) 7011 d->focusWidget = new QFocusFrame(f); 7012 d->focusWidget->setWidget(f); 7013 } else if(d->focusWidget) { 7014 d->focusWidget->setWidget(0); 7015 } 7016 } else if(e->type() == QEvent::FocusOut) { 7017 if(d->focusWidget) 7018 d->focusWidget->setWidget(0); 6948 return false; 7019 6949 } 7020 return false; 7021 } 7022 7023 QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, 7024 const QWidget *widget) const 7025 { 7026 switch (standardIcon) { 7027 default: 7028 return QCommonStyle::standardIcon(standardIcon, opt, widget); 7029 case SP_ToolBarHorizontalExtensionButton: 7030 case SP_ToolBarVerticalExtensionButton: { 7031 QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext.png")); 7032 if (standardIcon == SP_ToolBarVerticalExtensionButton) { 7033 QPixmap pix2(pixmap.height(), pixmap.width()); 7034 pix2.setDevicePixelRatio(pixmap.devicePixelRatio()); 7035 pix2.fill(Qt::transparent); 7036 QPainter p(&pix2); 7037 p.translate(pix2.width(), 0); 7038 p.rotate(90); 7039 p.drawPixmap(0, 0, pixmap); 7040 return pix2; 6950 6951 QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, 6952 const QWidget *widget) const 6953 { 6954 switch (standardIcon) { 6955 default: 6956 return QCommonStyle::standardIcon(standardIcon, opt, widget); 6957 case SP_ToolBarHorizontalExtensionButton: 6958 case SP_ToolBarVerticalExtensionButton: { 6959 QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext.png")); 6960 if (standardIcon == SP_ToolBarVerticalExtensionButton) { 6961 QPixmap pix2(pixmap.height(), pixmap.width()); 6962 pix2.setDevicePixelRatio(pixmap.devicePixelRatio()); 6963 pix2.fill(Qt::transparent); 6964 QPainter p(&pix2); 6965 p.translate(pix2.width(), 0); 6966 p.rotate(90); 6967 p.drawPixmap(0, 0, pixmap); 6968 return pix2; 6969 } 6970 return pixmap; 6971 } 7041 6972 } 7042 return pixmap;7043 6973 } 7044 } 7045 } 7046 7047 int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, 7048 QSizePolicy::ControlType control2, 7049 Qt::Orientation orientation, 7050 const QStyleOption *option, 7051 const QWidget *widget) const 7052 { 7053 const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; 7054 bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal)); 7055 int controlSize = getControlSize(option, widget); 7056 7057 if (control2 == QSizePolicy::ButtonBox) { 7058 /* 7059 AHIG seems to prefer a 12-pixel margin between group 7060 boxes and the row of buttons. The 20 pixel comes from 7061 Builder. 7062 */ 7063 if (isMetal // (AHIG, guess, guess) 6974 6975 int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, 6976 QSizePolicy::ControlType control2, 6977 Qt::Orientation orientation, 6978 const QStyleOption *option, 6979 const QWidget *widget) const 6980 { 6981 const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; 6982 bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal)); 6983 int controlSize = getControlSize(option, widget); 6984 6985 if (control2 == QSizePolicy::ButtonBox) { 6986 /* 6987 AHIG seems to prefer a 12-pixel margin between group 6988 boxes and the row of buttons. The 20 pixel comes from 6989 Builder. 6990 */ 6991 if (isMetal // (AHIG, guess, guess) 7064 6992 || (control1 & (QSizePolicy::Frame // guess 7065 6993 | QSizePolicy::GroupBox // (AHIG, guess, guess) 7066 6994 | QSizePolicy::TabWidget // guess 7067 6995 | ButtonMask))) { // AHIG 7068 return_SIZE(14, 8, 8); 7069 } else if (control1 == QSizePolicy::LineEdit) { 7070 return_SIZE(8, 8, 8); // Interface Builder 7071 } else { 7072 return_SIZE(20, 7, 7); // Interface Builder 7073 } 7074 } 7075 7076 if ((control1 | control2) & ButtonMask) { 7077 if (control1 == QSizePolicy::LineEdit) 7078 return_SIZE(8, 8, 8); // Interface Builder 7079 else if (control2 == QSizePolicy::LineEdit) { 7080 if (orientation == Qt::Vertical) 6996 return_SIZE(14, 8, 8); 6997 } else if (control1 == QSizePolicy::LineEdit) { 6998 return_SIZE(8, 8, 8); // Interface Builder 6999 } else { 7081 7000 return_SIZE(20, 7, 7); // Interface Builder 7082 else 7083 return_SIZE(20, 8, 8); 7001 } 7084 7002 } 7085 return_SIZE(14, 8, 8); // Interface Builder 7086 } 7087 7088 switch (CT2(control1, control2)) { 7089 case CT1(QSizePolicy::Label): // guess 7090 case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): // guess 7091 case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): // AHIG 7092 case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): // AHIG 7093 case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): // guess 7094 case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): // AHIG 7095 case CT2(QSizePolicy::Label, QSizePolicy::Slider): // guess 7096 case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): // guess 7097 case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): // guess 7098 return_SIZE(8, 6, 5); 7099 case CT1(QSizePolicy::ToolButton): 7100 return 8; // AHIG 7101 case CT1(QSizePolicy::CheckBox): 7102 case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): 7103 case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): 7104 if (orientation == Qt::Vertical) 7105 return_SIZE(8, 8, 7); // AHIG and Builder 7106 break; 7107 case CT1(QSizePolicy::RadioButton): 7108 if (orientation == Qt::Vertical) 7109 return 5; // (Builder, guess, AHIG) 7110 } 7111 7112 if (orientation == Qt::Horizontal 7003 7004 if ((control1 | control2) & ButtonMask) { 7005 if (control1 == QSizePolicy::LineEdit) 7006 return_SIZE(8, 8, 8); // Interface Builder 7007 else if (control2 == QSizePolicy::LineEdit) { 7008 if (orientation == Qt::Vertical) 7009 return_SIZE(20, 7, 7); // Interface Builder 7010 else 7011 return_SIZE(20, 8, 8); 7012 } 7013 return_SIZE(14, 8, 8); // Interface Builder 7014 } 7015 7016 switch (CT2(control1, control2)) { 7017 case CT1(QSizePolicy::Label): // guess 7018 case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): // guess 7019 case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): // AHIG 7020 case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): // AHIG 7021 case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): // guess 7022 case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): // AHIG 7023 case CT2(QSizePolicy::Label, QSizePolicy::Slider): // guess 7024 case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): // guess 7025 case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): // guess 7026 return_SIZE(8, 6, 5); 7027 case CT1(QSizePolicy::ToolButton): 7028 return 8; // AHIG 7029 case CT1(QSizePolicy::CheckBox): 7030 case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): 7031 case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): 7032 if (orientation == Qt::Vertical) 7033 return_SIZE(8, 8, 7); // AHIG and Builder 7034 break; 7035 case CT1(QSizePolicy::RadioButton): 7036 if (orientation == Qt::Vertical) 7037 return 5; // (Builder, guess, AHIG) 7038 } 7039 7040 if (orientation == Qt::Horizontal 7113 7041 && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton))) 7114 return_SIZE(12, 10, 8); // guess 7115 7116 if ((control1 | control2) & (QSizePolicy::Frame 7117 | QSizePolicy::GroupBox 7118 | QSizePolicy::TabWidget)) { 7042 return_SIZE(12, 10, 8); // guess 7043 7044 if ((control1 | control2) & (QSizePolicy::Frame 7045 | QSizePolicy::GroupBox 7046 | QSizePolicy::TabWidget)) { 7047 /* 7048 These values were chosen so that nested container widgets 7049 look good side by side. Builder uses 8, which looks way 7050 too small, and AHIG doesn't say anything. 7051 */ 7052 return_SIZE(16, 10, 10); // guess 7053 } 7054 7055 if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider)) 7056 return_SIZE(12, 10, 8); // AHIG 7057 7058 if ((control1 | control2) & QSizePolicy::LineEdit) 7059 return_SIZE(10, 8, 8); // AHIG 7060 7119 7061 /* 7120 These values were chosen so that nested container widgets 7121 look good side by side. Builder uses 8, which looks way 7122 too small, and AHIG doesn't say anything. 7123 */ 7124 return_SIZE(16, 10, 10); // guess 7062 AHIG and Builder differ by up to 4 pixels for stacked editable 7063 comboboxes. We use some values that work fairly well in all 7064 cases. 7065 */ 7066 if ((control1 | control2) & QSizePolicy::ComboBox) 7067 return_SIZE(10, 8, 7); // guess 7068 7069 /* 7070 Builder defaults to 8, 6, 5 in lots of cases, but most of the time the 7071 result looks too cramped. 7072 */ 7073 return_SIZE(10, 8, 6); // guess 7125 7074 } 7126 7127 if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider)) 7128 return_SIZE(12, 10, 8); // AHIG 7129 7130 if ((control1 | control2) & QSizePolicy::LineEdit) 7131 return_SIZE(10, 8, 8); // AHIG 7132 7133 /* 7134 AHIG and Builder differ by up to 4 pixels for stacked editable 7135 comboboxes. We use some values that work fairly well in all 7136 cases. 7137 */ 7138 if ((control1 | control2) & QSizePolicy::ComboBox) 7139 return_SIZE(10, 8, 7); // guess 7140 7075 7141 7076 /* 7142 Builder defaults to 8, 6, 5 in lots of cases, but most of the time the 7143 result looks too cramped. 7144 */ 7145 return_SIZE(10, 8, 6); // guess 7146 } 7147 7148 /* 7149 FontHash::FontHash() 7150 { 7151 QHash<QByteArray, QFont>::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts()); 7152 } 7153 7154 Q_GLOBAL_STATIC(FontHash, app_fonts) 7155 FontHash *qt_app_fonts_hash() 7156 { 7157 return app_fonts(); 7158 } 7159 */ 7160 QT_END_NAMESPACE 7077 FontHash::FontHash() 7078 { 7079 QHash<QByteArray, QFont>::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts()); 7080 } 7081 7082 Q_GLOBAL_STATIC(FontHash, app_fonts) 7083 FontHash *qt_app_fonts_hash() 7084 { 7085 return app_fonts(); 7086 } 7087 */ 7088 QT_END_NAMESPACE 7089 No newline at end of file