From 4f3249f32dbe5c20aabbfd9b4f9c558aaf449e48 Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 27 Feb 2017 18:39:44 -0800 Subject: Pluginize the platform styles This enforces decoupling and in the case of QMacStyle, isolates QtWidgets and therefore end user applications, from Carbon/HITheme. Windows and Fusion are platform independent, so they remain built-in (but mostly because the Windows style is tightly coupled to other styles like QStylesheetStyle). Task-number: QTBUG-59428 Change-Id: Id6519fe0c5269c1bce5b5921f9db06257032a1c9 Reviewed-by: Qt CI Bot Reviewed-by: Gabriel de Dietrich --- src/widgets/kernel/qapplication.cpp | 3 +- src/widgets/kernel/qapplication_p.h | 2 +- src/widgets/kernel/qwidgetwindow.cpp | 2 +- src/widgets/styles/qandroidstyle.cpp | 1809 ------- src/widgets/styles/qandroidstyle_p.h | 395 -- src/widgets/styles/qcommonstyle_p.h | 2 +- src/widgets/styles/qfusionstyle_p.h | 2 +- src/widgets/styles/qmacstyle.qdoc | 207 - src/widgets/styles/qmacstyle_mac.mm | 7041 --------------------------- src/widgets/styles/qmacstyle_mac_p.h | 133 - src/widgets/styles/qmacstyle_mac_p_p.h | 257 - src/widgets/styles/qstyleanimation_p.h | 10 +- src/widgets/styles/qstylefactory.cpp | 46 - src/widgets/styles/qstylehelper_p.h | 16 +- src/widgets/styles/qwindowsstyle_p.h | 2 +- src/widgets/styles/qwindowsstyle_p_p.h | 2 +- src/widgets/styles/qwindowsvistastyle.cpp | 2491 ---------- src/widgets/styles/qwindowsvistastyle_p.h | 110 - src/widgets/styles/qwindowsvistastyle_p_p.h | 184 - src/widgets/styles/qwindowsxpstyle.cpp | 4227 ---------------- src/widgets/styles/qwindowsxpstyle_p.h | 109 - src/widgets/styles/qwindowsxpstyle_p_p.h | 345 -- src/widgets/styles/styles.pri | 21 - src/widgets/widgets/qcombobox_p.h | 2 +- src/widgets/widgets/qtabbar_p.h | 2 +- 25 files changed, 22 insertions(+), 17398 deletions(-) delete mode 100644 src/widgets/styles/qandroidstyle.cpp delete mode 100644 src/widgets/styles/qandroidstyle_p.h delete mode 100644 src/widgets/styles/qmacstyle.qdoc delete mode 100644 src/widgets/styles/qmacstyle_mac.mm delete mode 100644 src/widgets/styles/qmacstyle_mac_p.h delete mode 100644 src/widgets/styles/qmacstyle_mac_p_p.h delete mode 100644 src/widgets/styles/qwindowsvistastyle.cpp delete mode 100644 src/widgets/styles/qwindowsvistastyle_p.h delete mode 100644 src/widgets/styles/qwindowsvistastyle_p_p.h delete mode 100644 src/widgets/styles/qwindowsxpstyle.cpp delete mode 100644 src/widgets/styles/qwindowsxpstyle_p.h delete mode 100644 src/widgets/styles/qwindowsxpstyle_p_p.h (limited to 'src/widgets') diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 1716d36ac5..d7282d8c26 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2726,7 +2726,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, case enter/leave events are genereated by the underlying windowing system. */ extern QPointer qt_last_mouse_receiver; -extern QWidget *qt_button_down; +extern Q_WIDGETS_EXPORT QWidget *qt_button_down; void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) { #ifndef QT_NO_CURSOR @@ -3751,7 +3751,6 @@ static void grabForPopup(QWidget *popup) } } -extern QWidget *qt_button_down; extern QWidget *qt_popup_down; extern bool qt_replay_popup_mouse_event; diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 271844a23e..f20d10fe6f 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -92,7 +92,7 @@ extern QClipboard *qt_clipboard; #endif typedef QHash FontHash; -FontHash *qt_app_fonts_hash(); +Q_WIDGETS_EXPORT FontHash *qt_app_fonts_hash(); typedef QHash PaletteHash; PaletteHash *qt_app_palettes_hash(); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 44fd4b6a80..5b695d9f30 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets(); -QWidget *qt_button_down = 0; // widget got last button-down +Q_WIDGETS_EXPORT QWidget *qt_button_down = 0; // widget got last button-down // popup control QWidget *qt_popup_down = 0; // popup that contains the pressed widget diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp deleted file mode 100644 index 110153d0f6..0000000000 --- a/src/widgets/styles/qandroidstyle.cpp +++ /dev/null @@ -1,1809 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 BogDan Vatra -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qandroidstyle_p.h" - -#if QT_CONFIG(style_android) || defined(QT_PLUGIN) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace { - const quint32 NO_COLOR = 1; - const quint32 TRANSPARENT_COLOR = 0; -} - -QAndroidStyle::QAndroidStyle() - : QFusionStyle() -{ - QPixmapCache::clear(); - checkBoxControl = NULL; - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - QPalette *standardPalette = reinterpret_cast(nativeInterface->nativeResourceForIntegration("AndroidStandardPalette")); - if (standardPalette) - m_standardPalette = *standardPalette; - - QHash *qwidgetsFonts = reinterpret_cast *>(nativeInterface->nativeResourceForIntegration("AndroidQWidgetFonts")); - if (qwidgetsFonts) { - for (auto it = qwidgetsFonts->constBegin(); it != qwidgetsFonts->constEnd(); ++it) - QApplication::setFont(it.value(), it.key()); - qwidgetsFonts->clear(); // free the memory - } - - QJsonObject *object = reinterpret_cast(nativeInterface->nativeResourceForIntegration("AndroidStyleData")); - if (!object) - return; - - for (QJsonObject::const_iterator objectIterator = object->constBegin(); - objectIterator != object->constEnd(); - ++objectIterator) { - QString key = objectIterator.key(); - QJsonValue value = objectIterator.value(); - if (Q_UNLIKELY(!value.isObject())) { - qWarning("Style.json structure is unrecognized."); - continue; - } - - QJsonObject item = value.toObject(); - QAndroidStyle::ItemType itemType = qtControl(key); - if (QC_UnknownType == itemType) - continue; - - switch (itemType) { - case QC_Checkbox: - checkBoxControl = new AndroidCompoundButtonControl(item.toVariantMap(), itemType); - m_androidControlsHash[int(itemType)] = checkBoxControl; - break; - case QC_RadioButton: - m_androidControlsHash[int(itemType)] = new AndroidCompoundButtonControl(item.toVariantMap(), - itemType); - break; - - case QC_ProgressBar: - m_androidControlsHash[int(itemType)] = new AndroidProgressBarControl(item.toVariantMap(), - itemType); - break; - - case QC_Slider: - m_androidControlsHash[int(itemType)] = new AndroidSeekBarControl(item.toVariantMap(), - itemType); - break; - - case QC_Combobox: - m_androidControlsHash[int(itemType)] = new AndroidSpinnerControl(item.toVariantMap(), - itemType); - break; - - default: - m_androidControlsHash[int(itemType)] = new AndroidControl(item.toVariantMap(), - itemType); - break; - } - } - *object = QJsonObject(); // free memory -} - -QAndroidStyle::~QAndroidStyle() -{ - qDeleteAll(m_androidControlsHash); -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(const QString &android) -{ - if (android == QLatin1String("buttonStyle")) - return QC_Button; - if (android == QLatin1String("editTextStyle")) - return QC_EditText; - if (android == QLatin1String("radioButtonStyle")) - return QC_RadioButton; - if (android == QLatin1String("checkboxStyle")) - return QC_Checkbox; - if (android == QLatin1String("textViewStyle")) - return QC_View; - if (android == QLatin1String("buttonStyleToggle")) - return QC_Switch; - if (android == QLatin1String("spinnerStyle")) - return QC_Combobox; - if (android == QLatin1String("progressBarStyleHorizontal")) - return QC_ProgressBar; - if (android == QLatin1String("seekBarStyle")) - return QC_Slider; - - return QC_UnknownType; -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ComplexControl control) -{ - switch (control) { - case CC_ComboBox: - return QC_Combobox; - case CC_Slider: - return QC_Slider; - default: - return QC_UnknownType; - } -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ContentsType contentsType) -{ - switch (contentsType) { - case CT_PushButton: - return QC_Button; - case CT_CheckBox: - return QC_Checkbox; - case CT_RadioButton: - return QC_RadioButton; - case CT_ComboBox: - return QC_Combobox; - case CT_ProgressBar: - return QC_ProgressBar; - case CT_Slider: - return QC_Slider; - case CT_ScrollBar: - return QC_Slider; - case CT_TabWidget: - return QC_Tab; - case CT_TabBarTab: - return QC_TabButton; - case CT_LineEdit: - return QC_EditText; - case CT_GroupBox: - return QC_GroupBox; - default: - return QC_UnknownType; - } -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::ControlElement controlElement) -{ - switch (controlElement) { - case CE_PushButton: - case CE_PushButtonBevel: - case CE_PushButtonLabel: - return QC_Button; - - case CE_CheckBox: - case CE_CheckBoxLabel: - return QC_Checkbox; - - case CE_RadioButton: - case CE_RadioButtonLabel: - return QC_RadioButton; - - case CE_TabBarTab: - case CE_TabBarTabShape: - case CE_TabBarTabLabel: - return QC_Tab; - - case CE_ProgressBar: - case CE_ProgressBarGroove: - case CE_ProgressBarContents: - case CE_ProgressBarLabel: - return QC_ProgressBar; - - case CE_ComboBoxLabel: - return QC_Combobox; - - case CE_ShapedFrame: - return QC_View; - - default: - return QC_UnknownType; - } -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::PrimitiveElement primitiveElement) -{ - switch (primitiveElement) { - case QStyle::PE_PanelLineEdit: - case QStyle::PE_FrameLineEdit: - return QC_EditText; - - case QStyle::PE_IndicatorViewItemCheck: - case QStyle::PE_IndicatorCheckBox: - return QC_Checkbox; - - case QStyle::PE_FrameWindow: - case QStyle::PE_Widget: - case QStyle::PE_Frame: - case QStyle::PE_FrameFocusRect: - return QC_View; - default: - return QC_UnknownType; - } -} - -QAndroidStyle::ItemType QAndroidStyle::qtControl(QStyle::SubElement subElement) -{ - switch (subElement) { - case QStyle::SE_LineEditContents: - return QC_EditText; - - case QStyle::SE_PushButtonContents: - case QStyle::SE_PushButtonFocusRect: - return QC_Button; - - case SE_RadioButtonContents: - return QC_RadioButton; - - case SE_CheckBoxContents: - return QC_Checkbox; - - default: - return QC_UnknownType; - } -} - -void QAndroidStyle::drawPrimitive(PrimitiveElement pe, - const QStyleOption *opt, - QPainter *p, - const QWidget *w) const -{ - const ItemType itemType = qtControl(pe); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) { - if (itemType != QC_EditText) { - it.value()->drawControl(opt, p, w); - } else { - QStyleOption copy(*opt); - copy.state &= ~QStyle::State_Sunken; - it.value()->drawControl(©, p, w); - } - } else if (pe == PE_FrameGroupBox) { - if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { - if (frame->features & QStyleOptionFrame::Flat) { - QRect fr = frame->rect; - QPoint p1(fr.x(), fr.y() + 1); - QPoint p2(fr.x() + fr.width(), p1.y()); - qDrawShadeLine(p, p1, p2, frame->palette, true, - frame->lineWidth, frame->midLineWidth); - } else { - qDrawShadeRect(p, frame->rect.x(), frame->rect.y(), frame->rect.width(), - frame->rect.height(), frame->palette, true, - frame->lineWidth, frame->midLineWidth); - } - } - } else { - QFusionStyle::drawPrimitive(pe, opt, p, w); - } -} - - -void QAndroidStyle::drawControl(QStyle::ControlElement element, - const QStyleOption *opt, - QPainter *p, - const QWidget *w) const -{ - const ItemType itemType = qtControl(element); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) { - AndroidControl *androidControl = it.value(); - androidControl->drawControl(opt, p, w); - - switch (itemType) { - case QC_Button: - if (const QStyleOptionButton *buttonOption = - qstyleoption_cast(opt)) { - QMargins padding = androidControl->padding(); - QStyleOptionButton copy(*buttonOption); - copy.rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom()); - QFusionStyle::drawControl(CE_PushButtonLabel, ©, p, w); - } - break; - case QC_Checkbox: - case QC_RadioButton: - if (const QStyleOptionButton *btn = - qstyleoption_cast(opt)) { - const bool isRadio = (element == CE_RadioButton); - QStyleOptionButton subopt(*btn); - subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents - : SE_CheckBoxContents, btn, w); - QFusionStyle::drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, w); - } - break; - case QC_Combobox: - if (const QStyleOptionComboBox *comboboxOption = - qstyleoption_cast(opt)) { - QMargins padding = androidControl->padding(); - QStyleOptionComboBox copy (*comboboxOption); - copy.rect.adjust(padding.left(), padding.top(), -padding.right(), -padding.bottom()); - QFusionStyle::drawControl(CE_ComboBoxLabel, comboboxOption, p, w); - } - break; - default: - QFusionStyle::drawControl(element, opt, p, w); - break; - } - } else { - QFusionStyle::drawControl(element, opt, p, w); - } -} - -QRect QAndroidStyle::subElementRect(SubElement subElement, - const QStyleOption *option, - const QWidget *widget) const -{ - const ItemType itemType = qtControl(subElement); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) - return it.value()->subElementRect(subElement, option, widget); - return QFusionStyle::subElementRect(subElement, option, widget); -} - -void QAndroidStyle::drawComplexControl(ComplexControl cc, - const QStyleOptionComplex *opt, - QPainter *p, - const QWidget *widget) const -{ - const ItemType itemType = qtControl(cc); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) { - it.value()->drawControl(opt, p, widget); - return; - } - if (cc == CC_GroupBox) { - if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { - // Draw frame - QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget); - QRect checkBoxRect; - if (groupBox->subControls & SC_GroupBoxCheckBox) - checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget); - if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { - QStyleOptionFrame frame; - frame.QStyleOption::operator=(*groupBox); - frame.features = groupBox->features; - frame.lineWidth = groupBox->lineWidth; - frame.midLineWidth = groupBox->midLineWidth; - frame.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget); - p->save(); - QRegion region(groupBox->rect); - if (!groupBox->text.isEmpty()) { - bool ltr = groupBox->direction == Qt::LeftToRight; - QRect finalRect; - if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) { - finalRect = checkBoxRect.united(textRect); - finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); - } else { - finalRect = textRect; - } - region -= finalRect; - } - p->setClipRegion(region); - drawPrimitive(PE_FrameGroupBox, &frame, p, widget); - p->restore(); - } - - // Draw title - if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { - QColor textColor = groupBox->textColor; - if (textColor.isValid()) - p->setPen(textColor); - int alignment = int(groupBox->textAlignment); - if (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget)) - alignment |= Qt::TextHideMnemonic; - - drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment, - groupBox->palette, groupBox->state & State_Enabled, groupBox->text, - textColor.isValid() ? QPalette::NoRole : QPalette::WindowText); - - if (groupBox->state & State_HasFocus) { - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*groupBox); - fropt.rect = textRect; - drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); - } - } - - // Draw checkbox - if (groupBox->subControls & SC_GroupBoxCheckBox) { - QStyleOptionButton box; - box.QStyleOption::operator=(*groupBox); - box.rect = checkBoxRect; - checkBoxControl->drawControl(&box, p, widget); - } - } - return; - } - QFusionStyle::drawComplexControl(cc, opt, p, widget); -} - -QStyle::SubControl QAndroidStyle::hitTestComplexControl(ComplexControl cc, - const QStyleOptionComplex *opt, - const QPoint &pt, - const QWidget *widget) const -{ - const ItemType itemType = qtControl(cc); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) { - switch (cc) { - case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - QRect r = it.value()->subControlRect(slider, SC_SliderHandle, widget); - if (r.isValid() && r.contains(pt)) { - return SC_SliderHandle; - } else { - r = it.value()->subControlRect(slider, SC_SliderGroove, widget); - if (r.isValid() && r.contains(pt)) - return SC_SliderGroove; - } - } - break; - default: - break; - } - } - return QFusionStyle::hitTestComplexControl(cc, opt, pt, widget); -} - -QRect QAndroidStyle::subControlRect(ComplexControl cc, - const QStyleOptionComplex *opt, - SubControl sc, - const QWidget *widget) const -{ - const ItemType itemType = qtControl(cc); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) - return it.value()->subControlRect(opt, sc, widget); - QRect rect = opt->rect; - switch (cc) { - case CC_GroupBox: { - if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { - QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); - QSize checkBoxSize = checkBoxControl->size(opt); - int indicatorWidth = checkBoxSize.width(); - int indicatorHeight = checkBoxSize.height(); - QRect checkBoxRect; - if (opt->subControls & QStyle::SC_GroupBoxCheckBox) { - checkBoxRect.setWidth(indicatorWidth); - checkBoxRect.setHeight(indicatorHeight); - } - checkBoxRect.moveLeft(1); - QRect textRect = checkBoxRect; - textRect.setSize(textSize); - if (opt->subControls & QStyle::SC_GroupBoxCheckBox) - textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2); - if (sc == SC_GroupBoxFrame) { - rect = opt->rect.adjusted(0, 0, 0, 0); - rect.translate(0, textRect.height() / 2); - rect.setHeight(rect.height() - textRect.height() / 2); - } else if (sc == SC_GroupBoxContents) { - QRect frameRect = opt->rect.adjusted(0, 0, 0, -groupBox->lineWidth); - int margin = 3; - int leftMarginExtension = 0; - int topMargin = qMax(pixelMetric(PM_ExclusiveIndicatorHeight), opt->fontMetrics.height()) + groupBox->lineWidth; - frameRect.adjust(leftMarginExtension + margin, margin + topMargin, -margin, -margin - groupBox->lineWidth); - frameRect.translate(0, textRect.height() / 2); - rect = frameRect; - rect.setHeight(rect.height() - textRect.height() / 2); - } else if (sc == SC_GroupBoxCheckBox) { - rect = checkBoxRect; - } else if (sc == SC_GroupBoxLabel) { - rect = textRect; - } - return visualRect(opt->direction, opt->rect, rect); - } - - return rect; - } - - default: - break; - } - - - return QFusionStyle::subControlRect(cc, opt, sc, widget); -} - -int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, - const QWidget *widget) const -{ - switch (metric) { - case PM_ButtonMargin: - case PM_FocusFrameVMargin: - case PM_FocusFrameHMargin: - case PM_ComboBoxFrameWidth: - case PM_SpinBoxFrameWidth: - case PM_ScrollBarExtent: - return 0; - case PM_IndicatorWidth: - return checkBoxControl->size(option).width(); - case PM_IndicatorHeight: - return checkBoxControl->size(option).height(); - default: - return QFusionStyle::pixelMetric(metric, option, widget); - } - -} - -QSize QAndroidStyle::sizeFromContents(ContentsType ct, - const QStyleOption *opt, - const QSize &contentsSize, - const QWidget *w) const -{ - QSize sz = QFusionStyle::sizeFromContents(ct, opt, contentsSize, w); - if (ct == CT_HeaderSection) { - if (const QStyleOptionHeader *hdr = qstyleoption_cast(opt)) { - bool nullIcon = hdr->icon.isNull(); - int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w); - int iconSize = nullIcon ? 0 : checkBoxControl->size(opt).width(); - QSize txt; -/* - * These next 4 lines are a bad hack to fix a bug in case a QStyleSheet is applied at QApplication level. - * In that case, even if the stylesheet does not refer to headers, the header font is changed to application - * font, which is wrong. Even worst, hdr->fontMetrics(...) does not report the proper size. - */ - if (qApp->styleSheet().isEmpty()) - txt = hdr->fontMetrics.size(0, hdr->text); - else - txt = qApp->fontMetrics().size(0, hdr->text); - - sz.setHeight(margin + qMax(iconSize, txt.height()) + margin); - sz.setWidth((nullIcon ? 0 : margin) + iconSize - + (hdr->text.isNull() ? 0 : margin) + txt.width() + margin); - if (hdr->sortIndicator != QStyleOptionHeader::None) { - int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w); - if (hdr->orientation == Qt::Horizontal) - sz.rwidth() += sz.height() + margin; - else - sz.rheight() += sz.width() + margin; - } - return sz; - } - } - const ItemType itemType = qtControl(ct); - AndroidControlsHash::const_iterator it = itemType != QC_UnknownType - ? m_androidControlsHash.find(itemType) - : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) - return it.value()->sizeFromContents(opt, sz, w); - if (ct == CT_GroupBox) { - if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { - QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); - QSize checkBoxSize = checkBoxControl->size(opt); - int indicatorWidth = checkBoxSize.width(); - int indicatorHeight = checkBoxSize.height(); - QRect checkBoxRect; - if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) { - checkBoxRect.setWidth(indicatorWidth); - checkBoxRect.setHeight(indicatorHeight); - } - checkBoxRect.moveLeft(1); - QRect textRect = checkBoxRect; - textRect.setSize(textSize); - if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) - textRect.translate(indicatorWidth + 5, (indicatorHeight - textSize.height()) / 2); - QRect u = textRect.united(checkBoxRect); - sz = QSize(sz.width(), sz.height() + u.height()); - } - } - return sz; -} - -QPixmap QAndroidStyle::standardPixmap(StandardPixmap standardPixmap, - const QStyleOption *opt, - const QWidget *widget) const -{ - return QFusionStyle::standardPixmap(standardPixmap, opt, widget); -} - -QPixmap QAndroidStyle::generatedIconPixmap(QIcon::Mode iconMode, - const QPixmap &pixmap, - const QStyleOption *opt) const -{ - return QFusionStyle::generatedIconPixmap(iconMode, pixmap, opt); -} - -int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const -{ - switch (hint) { - case SH_Slider_AbsoluteSetButtons: - return Qt::LeftButton; - - case SH_Slider_PageSetButtons: - return 0; - - case SH_RequestSoftwareInputPanel: - return RSIP_OnMouseClick; - - default: - return QFusionStyle::styleHint(hint, option, widget, returnData); - } -} - -QPalette QAndroidStyle::standardPalette() const -{ - return m_standardPalette; -} - -void QAndroidStyle::polish(QWidget *widget) -{ - widget->setAttribute(Qt::WA_StyledBackground, true); -} - -void QAndroidStyle::unpolish(QWidget *widget) -{ - widget->setAttribute(Qt::WA_StyledBackground, false); -} - -QAndroidStyle::AndroidDrawable::AndroidDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) -{ - initPadding(drawable); - m_itemType = itemType; -} - -QAndroidStyle::AndroidDrawable::~AndroidDrawable() -{ -} - -void QAndroidStyle::AndroidDrawable::initPadding(const QVariantMap &drawable) -{ - QVariantMap::const_iterator it = drawable.find(QLatin1String("padding")); - if (it != drawable.end()) - m_padding = extractMargins(it.value().toMap()); -} - -const QMargins &QAndroidStyle::AndroidDrawable::padding() const -{ - return m_padding; -} - -QSize QAndroidStyle::AndroidDrawable::size() const -{ - if (type() == Image || type() == NinePatch) - return static_cast(this)->size(); - - return QSize(); -} - -QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable, - ItemType itemType) -{ - const QString type = drawable.value(QLatin1String("type")).toString(); - if (type == QLatin1String("image")) - return new QAndroidStyle::AndroidImageDrawable(drawable, itemType); - if (type == QLatin1String("9patch")) - return new QAndroidStyle::Android9PatchDrawable(drawable, itemType); - if (type == QLatin1String("stateslist")) - return new QAndroidStyle::AndroidStateDrawable(drawable, itemType); - if (type == QLatin1String("layer")) - return new QAndroidStyle::AndroidLayerDrawable(drawable, itemType); - if (type == QLatin1String("gradient")) - return new QAndroidStyle::AndroidGradientDrawable(drawable, itemType); - if (type == QLatin1String("clipDrawable")) - return new QAndroidStyle::AndroidClipDrawable(drawable, itemType); - if (type == QLatin1String("color")) - return new QAndroidStyle::AndroidColorDrawable(drawable, itemType); - return 0; -} - -QMargins QAndroidStyle::AndroidDrawable::extractMargins(const QVariantMap &value) -{ - QMargins m; - m.setLeft(value.value(QLatin1String("left")).toInt()); - m.setRight(value.value(QLatin1String("right")).toInt()); - m.setTop(value.value(QLatin1String("top")).toInt()); - m.setBottom(value.value(QLatin1String("bottom")).toInt()); - return m; -} - -void QAndroidStyle::AndroidDrawable::setPaddingLeftToSizeWidth() -{ - QSize sz = size(); - if (m_padding.isNull() && !sz.isNull()) - m_padding.setLeft(sz.width()); -} - - -QAndroidStyle::AndroidImageDrawable::AndroidImageDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidDrawable(drawable, itemType) -{ - m_filePath = drawable.value(QLatin1String("path")).toString(); - m_size.setHeight(drawable.value(QLatin1String("height")).toInt()); - m_size.setWidth(drawable.value(QLatin1String("width")).toInt()); -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidImageDrawable::type() const -{ - return QAndroidStyle::Image; -} - -void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - if (m_hashKey.isEmpty()) - m_hashKey = QFileInfo(m_filePath).fileName(); - - QPixmap pm; - if (!QPixmapCache::find(m_hashKey, &pm)) { - pm.load(m_filePath); - QPixmapCache::insert(m_hashKey, pm); - } - - painter->drawPixmap(opt->rect.x(), opt->rect.y() + (opt->rect.height() - pm.height()) / 2, pm); -} - -QSize QAndroidStyle::AndroidImageDrawable::size() const -{ - return m_size; -} - -QAndroidStyle::AndroidColorDrawable::AndroidColorDrawable(const QVariantMap &drawable, - ItemType itemType) - : AndroidDrawable(drawable, itemType) -{ - m_color.setRgba(QRgb(drawable.value(QLatin1String("color")).toInt())); -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidColorDrawable::type() const -{ - return QAndroidStyle::Color; -} - -void QAndroidStyle::AndroidColorDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - painter->fillRect(opt->rect, m_color); -} - -QAndroidStyle::Android9PatchDrawable::Android9PatchDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidImageDrawable(drawable.value(QLatin1String("drawable")).toMap(), itemType) -{ - initPadding(drawable); - QVariantMap chunk = drawable.value(QLatin1String("chunkInfo")).toMap(); - extractIntArray(chunk.value(QLatin1String("xdivs")).toList(), m_chunkData.xDivs); - extractIntArray(chunk.value(QLatin1String("ydivs")).toList(), m_chunkData.yDivs); - extractIntArray(chunk.value(QLatin1String("colors")).toList(), m_chunkData.colors); -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::Android9PatchDrawable::type() const -{ - return QAndroidStyle::NinePatch; -} - -int QAndroidStyle::Android9PatchDrawable::calculateStretch(int boundsLimit, - int startingPoint, - int srcSpace, - int numStrechyPixelsRemaining, - int numFixedPixelsRemaining) -{ - int spaceRemaining = boundsLimit - startingPoint; - int stretchySpaceRemaining = spaceRemaining - numFixedPixelsRemaining; - return (float(srcSpace) * stretchySpaceRemaining / numStrechyPixelsRemaining + .5); -} - -void QAndroidStyle::Android9PatchDrawable::extractIntArray(const QVariantList &values, - QVector & array) -{ - for (const QVariant &value : values) - array << value.toInt(); -} - - -void QAndroidStyle::Android9PatchDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - if (m_hashKey.isEmpty()) - m_hashKey = QFileInfo(m_filePath).fileName(); - - QPixmap pixmap; - if (!QPixmapCache::find(m_hashKey, &pixmap)) { - pixmap.load(m_filePath); - QPixmapCache::insert(m_hashKey, pixmap); - } - - const QRect &bounds = opt->rect; - - // shamelessly stolen from Android's sources (NinepatchImpl.cpp) and adapted for Qt - const int pixmapWidth = pixmap.width(); - const int pixmapHeight = pixmap.height(); - - if (bounds.isNull() || !pixmapWidth || !pixmapHeight) - return; - - QPainter::RenderHints savedHints = painter->renderHints(); - - // The patchs doesn't need smooth transform ! - painter->setRenderHints(QPainter::SmoothPixmapTransform, false); - - QRectF dst; - QRectF src; - - const qint32 x0 = m_chunkData.xDivs[0]; - const qint32 y0 = m_chunkData.yDivs[0]; - const quint8 numXDivs = m_chunkData.xDivs.size(); - const quint8 numYDivs = m_chunkData.yDivs.size(); - int i; - int j; - int colorIndex = 0; - quint32 color; - bool xIsStretchable; - const bool initialXIsStretchable = (x0 == 0); - bool yIsStretchable = (y0 == 0); - const int bitmapWidth = pixmap.width(); - const int bitmapHeight = pixmap.height(); - - int *dstRights = static_cast(alloca((numXDivs + 1) * sizeof(int))); - bool dstRightsHaveBeenCached = false; - - int numStretchyXPixelsRemaining = 0; - for (i = 0; i < numXDivs; i += 2) - numStretchyXPixelsRemaining += m_chunkData.xDivs[i + 1] - m_chunkData.xDivs[i]; - - int numFixedXPixelsRemaining = bitmapWidth - numStretchyXPixelsRemaining; - int numStretchyYPixelsRemaining = 0; - for (i = 0; i < numYDivs; i += 2) - numStretchyYPixelsRemaining += m_chunkData.yDivs[i + 1] - m_chunkData.yDivs[i]; - - int numFixedYPixelsRemaining = bitmapHeight - numStretchyYPixelsRemaining; - src.setTop(0); - dst.setTop(bounds.top()); - // The first row always starts with the top being at y=0 and the bottom - // being either yDivs[1] (if yDivs[0]=0) of yDivs[0]. In the former case - // the first row is stretchable along the Y axis, otherwise it is fixed. - // The last row always ends with the bottom being bitmap.height and the top - // being either yDivs[numYDivs-2] (if yDivs[numYDivs-1]=bitmap.height) or - // yDivs[numYDivs-1]. In the former case the last row is stretchable along - // the Y axis, otherwise it is fixed. - // - // The first and last columns are similarly treated with respect to the X - // axis. - // - // The above is to help explain some of the special casing that goes on the - // code below. - - // The initial yDiv and whether the first row is considered stretchable or - // not depends on whether yDiv[0] was zero or not. - for (j = yIsStretchable ? 1 : 0; - j <= numYDivs && src.top() < bitmapHeight; - j++, yIsStretchable = !yIsStretchable) { - src.setLeft(0); - dst.setLeft(bounds.left()); - if (j == numYDivs) { - src.setBottom(bitmapHeight); - dst.setBottom(bounds.bottom()); - } else { - src.setBottom(m_chunkData.yDivs[j]); - const int srcYSize = src.bottom() - src.top(); - if (yIsStretchable) { - dst.setBottom(dst.top() + calculateStretch(bounds.bottom(), dst.top(), - srcYSize, - numStretchyYPixelsRemaining, - numFixedYPixelsRemaining)); - numStretchyYPixelsRemaining -= srcYSize; - } else { - dst.setBottom(dst.top() + srcYSize); - numFixedYPixelsRemaining -= srcYSize; - } - } - - xIsStretchable = initialXIsStretchable; - // The initial xDiv and whether the first column is considered - // stretchable or not depends on whether xDiv[0] was zero or not. - for (i = xIsStretchable ? 1 : 0; - i <= numXDivs && src.left() < bitmapWidth; - i++, xIsStretchable = !xIsStretchable) { - color = m_chunkData.colors[colorIndex++]; - if (color != TRANSPARENT_COLOR) - color = NO_COLOR; - if (i == numXDivs) { - src.setRight(bitmapWidth); - dst.setRight(bounds.right()); - } else { - src.setRight(m_chunkData.xDivs[i]); - if (dstRightsHaveBeenCached) { - dst.setRight(dstRights[i]); - } else { - const int srcXSize = src.right() - src.left(); - if (xIsStretchable) { - dst.setRight(dst.left() + calculateStretch(bounds.right(), dst.left(), - srcXSize, - numStretchyXPixelsRemaining, - numFixedXPixelsRemaining)); - numStretchyXPixelsRemaining -= srcXSize; - } else { - dst.setRight(dst.left() + srcXSize); - numFixedXPixelsRemaining -= srcXSize; - } - dstRights[i] = dst.right(); - } - } - // If this horizontal patch is too small to be displayed, leave - // the destination left edge where it is and go on to the next patch - // in the source. - if (src.left() >= src.right()) { - src.setLeft(src.right()); - continue; - } - // Make sure that we actually have room to draw any bits - if (dst.right() <= dst.left() || dst.bottom() <= dst.top()) { - goto nextDiv; - } - // If this patch is transparent, skip and don't draw. - if (color == TRANSPARENT_COLOR) - goto nextDiv; - if (color != NO_COLOR) - painter->fillRect(dst, QRgb(color)); - else - painter->drawPixmap(dst, pixmap, src); -nextDiv: - src.setLeft(src.right()); - dst.setLeft(dst.right()); - } - src.setTop(src.bottom()); - dst.setTop(dst.bottom()); - dstRightsHaveBeenCached = true; - } - painter->setRenderHints(savedHints); -} - -QAndroidStyle::AndroidGradientDrawable::AndroidGradientDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidDrawable(drawable, itemType), m_orientation(TOP_BOTTOM) -{ - m_radius = drawable.value(QLatin1String("radius")).toInt(); - if (m_radius < 0) - m_radius = 0; - - QVariantList colors = drawable.value(QLatin1String("colors")).toList(); - QVariantList positions = drawable.value(QLatin1String("positions")).toList(); - int min = colors.size() < positions.size() ? colors.size() : positions.size(); - for (int i = 0; i < min; i++) - m_gradient.setColorAt(positions.at(i).toDouble(), QRgb(colors.at(i).toInt())); - - QByteArray orientation = drawable.value(QLatin1String("orientation")).toByteArray(); - if (orientation == "TOP_BOTTOM") // draw the gradient from the top to the bottom - m_orientation = TOP_BOTTOM; - else if (orientation == "TR_BL") // draw the gradient from the top-right to the bottom-left - m_orientation = TR_BL; - else if (orientation == "RIGHT_LEFT") // draw the gradient from the right to the left - m_orientation = RIGHT_LEFT; - else if (orientation == "BR_TL") // draw the gradient from the bottom-right to the top-left - m_orientation = BR_TL; - else if (orientation == "BOTTOM_TOP") // draw the gradient from the bottom to the top - m_orientation = BOTTOM_TOP; - else if (orientation == "BL_TR") // draw the gradient from the bottom-left to the top-right - m_orientation = BL_TR; - else if (orientation == "LEFT_RIGHT") // draw the gradient from the left to the right - m_orientation = LEFT_RIGHT; - else if (orientation == "TL_BR") // draw the gradient from the top-left to the bottom-right - m_orientation = TL_BR; - else - qWarning("AndroidGradientDrawable: unknown orientation"); -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidGradientDrawable::type() const -{ - return QAndroidStyle::Gradient; -} - -void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - const int width = opt->rect.width(); - const int height = opt->rect.height(); - switch (m_orientation) { - case TOP_BOTTOM: - // draw the gradient from the top to the bottom - m_gradient.setStart(width / 2, 0); - m_gradient.setFinalStop(width / 2, height); - break; - case TR_BL: - // draw the gradient from the top-right to the bottom-left - m_gradient.setStart(width, 0); - m_gradient.setFinalStop(0, height); - break; - case RIGHT_LEFT: - // draw the gradient from the right to the left - m_gradient.setStart(width, height / 2); - m_gradient.setFinalStop(0, height / 2); - break; - case BR_TL: - // draw the gradient from the bottom-right to the top-left - m_gradient.setStart(width, height); - m_gradient.setFinalStop(0, 0); - break; - case BOTTOM_TOP: - // draw the gradient from the bottom to the top - m_gradient.setStart(width / 2, height); - m_gradient.setFinalStop(width / 2, 0); - break; - case BL_TR: - // draw the gradient from the bottom-left to the top-right - m_gradient.setStart(0, height); - m_gradient.setFinalStop(width, 0); - break; - case LEFT_RIGHT: - // draw the gradient from the left to the right - m_gradient.setStart(0, height / 2); - m_gradient.setFinalStop(width, height / 2); - break; - case TL_BR: - // draw the gradient from the top-left to the bottom-right - m_gradient.setStart(0, 0); - m_gradient.setFinalStop(width, height); - break; - } - - const QBrush &oldBrush = painter->brush(); - const QPen oldPen = painter->pen(); - painter->setPen(Qt::NoPen); - painter->setBrush(m_gradient); - painter->drawRoundedRect(opt->rect, m_radius, m_radius); - painter->setBrush(oldBrush); - painter->setPen(oldPen); -} - -QSize QAndroidStyle::AndroidGradientDrawable::size() const -{ - return QSize(m_radius * 2, m_radius * 2); -} - -QAndroidStyle::AndroidClipDrawable::AndroidClipDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidDrawable(drawable, itemType) -{ - m_drawable = fromMap(drawable.value(QLatin1String("drawable")).toMap(), itemType); - m_factor = 0; - m_orientation = Qt::Horizontal; -} - -QAndroidStyle::AndroidClipDrawable::~AndroidClipDrawable() -{ - delete m_drawable; -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidClipDrawable::type() const -{ - return QAndroidStyle::Clip; -} - -void QAndroidStyle::AndroidClipDrawable::setFactor(double factor, Qt::Orientation orientation) -{ - m_factor = factor; - m_orientation = orientation; -} - -void QAndroidStyle::AndroidClipDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - QStyleOption copy(*opt); - if (m_orientation == Qt::Horizontal) - copy.rect.setWidth(copy.rect.width() * m_factor); - else - copy.rect.setHeight(copy.rect.height() * m_factor); - - m_drawable->draw(painter, ©); -} - -QAndroidStyle::AndroidStateDrawable::AndroidStateDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidDrawable(drawable, itemType) -{ - const QVariantList states = drawable.value(QLatin1String("stateslist")).toList(); - for (const QVariant &stateVariant : states) { - QVariantMap state = stateVariant.toMap(); - const int s = extractState(state.value(QLatin1String("states")).toMap()); - if (-1 == s) - continue; - const AndroidDrawable *ad = fromMap(state.value(QLatin1String("drawable")).toMap(), itemType); - if (!ad) - continue; - StateType item; - item.first = s; - item.second = ad; - m_states<draw(painter, opt); -} -QSize QAndroidStyle::AndroidStateDrawable::sizeImage(const QStyleOption *opt) const -{ - QSize s; - const AndroidDrawable *drawable = bestAndroidStateMatch(opt); - if (drawable) - s = drawable->size(); - return s; -} - -const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const -{ - const AndroidDrawable *bestMatch = 0; - if (!opt) { - if (m_states.size()) - return m_states[0].second; - return bestMatch; - } - - uint bestCost = 0xffff; - for (const StateType & state : m_states) { - if (int(opt->state) == state.first) - return state.second; - uint cost = 1; - - int difference = int(opt->state^state.first); - - if (difference & QStyle::State_Active) - cost <<= 1; - - if (difference & QStyle::State_Enabled) - cost <<= 1; - - if (difference & QStyle::State_Raised) - cost <<= 1; - - if (difference & QStyle::State_Sunken) - cost <<= 1; - - if (difference & QStyle::State_Off) - cost <<= 1; - - if (difference & QStyle::State_On) - cost <<= 1; - - if (difference & QStyle::State_HasFocus) - cost <<= 1; - - if (difference & QStyle::State_Selected) - cost <<= 1; - - if (cost < bestCost) { - bestCost = cost; - bestMatch = state.second; - } - } - return bestMatch; -} - -int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value) -{ - QStyle::State state = QStyle::State_Enabled | QStyle::State_Active;; - for (auto it = value.cbegin(), end = value.cend(); it != end; ++it) { - const QString &key = it.key(); - bool val = it.value().toString() == QLatin1String("true"); - if (key == QLatin1String("enabled")) { - state.setFlag(QStyle::State_Enabled, val); - continue; - } - - if (key == QLatin1String("window_focused")) { - state.setFlag(QStyle::State_Active, val); - continue; - } - - if (key == QLatin1String("focused")) { - state.setFlag(QStyle::State_HasFocus, val); - continue; - } - - if (key == QLatin1String("checked")) { - state |= val ? QStyle::State_On : QStyle::State_Off; - continue; - } - - if (key == QLatin1String("pressed")) { - state |= val ? QStyle::State_Sunken : QStyle::State_Raised; - continue; - } - - if (key == QLatin1String("selected")) { - state.setFlag(QStyle::State_Selected, val); - continue; - } - - if (key == QLatin1String("active")) { - state.setFlag(QStyle::State_Active, val); - continue; - } - - if (key == QLatin1String("multiline")) - return 0; - - if (key == QLatin1String("background") && val) - return -1; - } - return static_cast(state); -} - -void QAndroidStyle::AndroidStateDrawable::setPaddingLeftToSizeWidth() -{ - for (const StateType &type : qAsConst(m_states)) - const_cast(type.second)->setPaddingLeftToSizeWidth(); -} - -QAndroidStyle::AndroidLayerDrawable::AndroidLayerDrawable(const QVariantMap &drawable, - QAndroidStyle::ItemType itemType) - : AndroidDrawable(drawable, itemType) -{ - m_id = 0; - m_factor = 1; - m_orientation = Qt::Horizontal; - const QVariantList layers = drawable.value(QLatin1String("layers")).toList(); - for (const QVariant &layer : layers) { - QVariantMap layerMap = layer.toMap(); - AndroidDrawable *ad = fromMap(layerMap, itemType); - if (ad) { - LayerType l; - l.second = ad; - l.first = layerMap.value(QLatin1String("id")).toInt(); - m_layers << l; - } - } -} - -QAndroidStyle::AndroidLayerDrawable::~AndroidLayerDrawable() -{ - for (const LayerType &layer : qAsConst(m_layers)) - delete layer.second; -} - -QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidLayerDrawable::type() const -{ - return QAndroidStyle::Layer; -} - -void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::Orientation orientation) -{ - m_id = id; - m_factor = factor; - m_orientation = orientation; -} - -void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const -{ - for (const LayerType &layer : m_layers) { - if (layer.first == m_id) { - QStyleOption copy(*opt); - if (m_orientation == Qt::Horizontal) - copy.rect.setWidth(copy.rect.width() * m_factor); - else - copy.rect.setHeight(copy.rect.height() * m_factor); - layer.second->draw(painter, ©); - } else { - layer.second->draw(painter, opt); - } - } -} - -QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidLayerDrawable::layer(int id) const -{ - for (const LayerType &layer : m_layers) - if (layer.first == id) - return layer.second; - return 0; -} - -QSize QAndroidStyle::AndroidLayerDrawable::size() const -{ - QSize sz; - for (const LayerType &layer : m_layers) - sz = sz.expandedTo(layer.second->size()); - return sz; -} - -QAndroidStyle::AndroidControl::AndroidControl(const QVariantMap &control, - QAndroidStyle::ItemType itemType) -{ - QVariantMap::const_iterator it = control.find(QLatin1String("View_background")); - if (it != control.end()) - m_background = AndroidDrawable::fromMap(it.value().toMap(), itemType); - else - m_background = 0; - - it = control.find(QLatin1String("View_minWidth")); - if (it != control.end()) - m_minSize.setWidth(it.value().toInt()); - - it = control.find(QLatin1String("View_minHeight")); - if (it != control.end()) - m_minSize.setHeight(it.value().toInt()); - - it = control.find(QLatin1String("View_maxWidth")); - if (it != control.end()) - m_maxSize.setWidth(it.value().toInt()); - - it = control.find(QLatin1String("View_maxHeight")); - if (it != control.end()) - m_maxSize.setHeight(it.value().toInt()); -} - -QAndroidStyle::AndroidControl::~AndroidControl() -{ - delete m_background; -} - -void QAndroidStyle::AndroidControl::drawControl(const QStyleOption *opt, QPainter *p, const QWidget * /* w */) -{ - if (m_background) { - m_background->draw(p, opt); - } else { - if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { - if ((frame->state & State_Sunken) || (frame->state & State_Raised)) { - qDrawShadePanel(p, frame->rect, frame->palette, frame->state & State_Sunken, - frame->lineWidth); - } else { - qDrawPlainRect(p, frame->rect, frame->palette.foreground().color(), frame->lineWidth); - } - } else { - if (const QStyleOptionFocusRect *fropt = qstyleoption_cast(opt)) { - QColor bg = fropt->backgroundColor; - QPen oldPen = p->pen(); - if (bg.isValid()) { - int h, s, v; - bg.getHsv(&h, &s, &v); - if (v >= 128) - p->setPen(Qt::black); - else - p->setPen(Qt::white); - } else { - p->setPen(opt->palette.foreground().color()); - } - QRect focusRect = opt->rect.adjusted(1, 1, -1, -1); - p->drawRect(focusRect.adjusted(0, 0, -1, -1)); //draw pen inclusive - p->setPen(oldPen); - } else { - p->fillRect(opt->rect, opt->palette.brush(QPalette::Background)); - } - } - } -} - -QRect QAndroidStyle::AndroidControl::subElementRect(QStyle::SubElement /* subElement */, - const QStyleOption *option, - const QWidget * /* widget */) const -{ - if (const AndroidDrawable *drawable = backgroundDrawable()) { - if (drawable->type() == State) - drawable = static_cast(backgroundDrawable())->bestAndroidStateMatch(option); - - const QMargins &padding = drawable->padding(); - - QRect r = option->rect.adjusted(padding.left(), padding.top(), - -padding.right(), -padding.bottom()); - - if (r.width() < m_minSize.width()) - r.setWidth(m_minSize.width()); - - if (r.height() < m_minSize.height()) - r.setHeight(m_minSize.height()); - - return visualRect(option->direction, option->rect, r); - } - return option->rect; -} - -QRect QAndroidStyle::AndroidControl::subControlRect(const QStyleOptionComplex *option, - QStyle::SubControl /*sc*/, - const QWidget *widget) const -{ - return subElementRect(QStyle::SE_CustomBase, option, widget); -} - -QSize QAndroidStyle::AndroidControl::sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, - const QWidget * /* w */) const -{ - QSize sz; - if (const AndroidDrawable *drawable = backgroundDrawable()) { - - if (drawable->type() == State) - drawable = static_cast(backgroundDrawable())->bestAndroidStateMatch(opt); - const QMargins &padding = drawable->padding(); - sz.setWidth(padding.left() + padding.right()); - sz.setHeight(padding.top() + padding.bottom()); - if (sz.isEmpty()) - sz = drawable->size(); - } - sz += contentsSize; - if (contentsSize.height() < opt->fontMetrics.height()) - sz.setHeight(sz.height() + (opt->fontMetrics.height() - contentsSize.height())); - if (sz.height() < m_minSize.height()) - sz.setHeight(m_minSize.height()); - if (sz.width() < m_minSize.width()) - sz.setWidth(m_minSize.width()); - return sz; -} - -QMargins QAndroidStyle::AndroidControl::padding() -{ - if (const AndroidDrawable *drawable = m_background) { - if (drawable->type() == State) - drawable = static_cast(m_background)->bestAndroidStateMatch(0); - return drawable->padding(); - } - return QMargins(); -} - -QSize QAndroidStyle::AndroidControl::size(const QStyleOption *option) -{ - if (const AndroidDrawable *drawable = backgroundDrawable()) { - if (drawable->type() == State) - drawable = static_cast(backgroundDrawable())->bestAndroidStateMatch(option); - return drawable->size(); - } - return QSize(); -} - -const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidControl::backgroundDrawable() const -{ - return m_background; -} - -QAndroidStyle::AndroidCompoundButtonControl::AndroidCompoundButtonControl(const QVariantMap &control, - ItemType itemType) - : AndroidControl(control, itemType) -{ - QVariantMap::const_iterator it = control.find(QLatin1String("CompoundButton_button")); - if (it != control.end()) { - m_button = AndroidDrawable::fromMap(it.value().toMap(), itemType); - const_cast(m_button)->setPaddingLeftToSizeWidth(); - } else { - m_button = 0; - } -} - -QAndroidStyle::AndroidCompoundButtonControl::~AndroidCompoundButtonControl() -{ - delete m_button; -} - -void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption *opt, - QPainter *p, - const QWidget *w) -{ - AndroidControl::drawControl(opt, p, w); - if (m_button) - m_button->draw(p, opt); -} - -QMargins QAndroidStyle::AndroidCompoundButtonControl::padding() -{ - if (m_button) - return m_button->padding(); - return AndroidControl::padding(); -} - -QSize QAndroidStyle::AndroidCompoundButtonControl::size(const QStyleOption *option) -{ - if (m_button) { - if (m_button->type() == State) - return static_cast(m_button)->bestAndroidStateMatch(option)->size(); - return m_button->size(); - } - return AndroidControl::size(option); -} - -const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const -{ - return m_background ? m_background : m_button; -} - -QAndroidStyle::AndroidProgressBarControl::AndroidProgressBarControl(const QVariantMap &control, - ItemType itemType) - : AndroidControl(control, itemType) -{ - QVariantMap::const_iterator it = control.find(QLatin1String("ProgressBar_indeterminateDrawable")); - if (it != control.end()) - m_indeterminateDrawable = AndroidDrawable::fromMap(it.value().toMap(), itemType); - else - m_indeterminateDrawable = 0; - - it = control.find(QLatin1String("ProgressBar_progressDrawable")); - if (it != control.end()) - m_progressDrawable = AndroidDrawable::fromMap(it.value().toMap(), itemType); - else - m_progressDrawable = 0; - - it = control.find(QLatin1String("ProgressBar_progress_id")); - if (it != control.end()) - m_progressId = it.value().toInt(); - - it = control.find(QLatin1String("ProgressBar_secondaryProgress_id")); - if (it != control.end()) - m_secondaryProgress_id = it.value().toInt(); - - it = control.find(QLatin1String("ProgressBar_minWidth")); - if (it != control.end()) - m_minSize.setWidth(it.value().toInt()); - - it = control.find(QLatin1String("ProgressBar_minHeight")); - if (it != control.end()) - m_minSize.setHeight(it.value().toInt()); - - it = control.find(QLatin1String("ProgressBar_maxWidth")); - if (it != control.end()) - m_maxSize.setWidth(it.value().toInt()); - - it = control.find(QLatin1String("ProgressBar_maxHeight")); - if (it != control.end()) - m_maxSize.setHeight(it.value().toInt()); -} - -QAndroidStyle::AndroidProgressBarControl::~AndroidProgressBarControl() -{ - delete m_progressDrawable; - delete m_indeterminateDrawable; -} - -void QAndroidStyle::AndroidProgressBarControl::drawControl(const QStyleOption *option, QPainter *p, const QWidget * /* w */) -{ - if (!m_progressDrawable) - return; - - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) { - if (m_progressDrawable->type() == QAndroidStyle::Layer) { - const double fraction = double(qint64(pb->progress) - pb->minimum) / (qint64(pb->maximum) - pb->minimum); - QAndroidStyle::AndroidDrawable *clipDrawable = static_cast(m_progressDrawable)->layer(m_progressId); - if (clipDrawable->type() == QAndroidStyle::Clip) - static_cast(clipDrawable)->setFactor(fraction, pb->orientation); - else - static_cast(m_progressDrawable)->setFactor(m_progressId, fraction, pb->orientation); - } - m_progressDrawable->draw(p, option); - } -} - -QRect QAndroidStyle::AndroidProgressBarControl::subElementRect(QStyle::SubElement subElement, - const QStyleOption *option, - const QWidget *widget) const -{ - if (const QStyleOptionProgressBar *progressBarOption = - qstyleoption_cast(option)) { - const bool horizontal = progressBarOption->orientation == Qt::Vertical; - if (!m_background) - return option->rect; - - QMargins padding = m_background->padding(); - QRect p(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top()); - padding = m_indeterminateDrawable->padding(); - p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top()); - padding = m_progressDrawable->padding(); - p |= QRect(padding.left(), padding.top(), padding.right() - padding.left(), padding.bottom() - padding.top()); - QRect r = option->rect.adjusted(p.left(), p.top(), -p.right(), -p.bottom()); - - if (horizontal) { - if (r.height()m_maxSize.height()) - r.setHeight(m_maxSize.height()); - } else { - if (r.width()m_maxSize.width()) - r.setWidth(m_maxSize.width()); - } - return visualRect(option->direction, option->rect, r); - } - return AndroidControl::subElementRect(subElement, option, widget); -} - -QSize QAndroidStyle::AndroidProgressBarControl::sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, - const QWidget * /* w */) const -{ - QSize sz(contentsSize); - if (sz.height() < m_minSize.height()) - sz.setHeight(m_minSize.height()); - if (sz.width() < m_minSize.width()) - sz.setWidth(m_minSize.width()); - - if (const QStyleOptionProgressBar *progressBarOption = - qstyleoption_cast(opt)) { - if (progressBarOption->orientation == Qt::Vertical) { - if (sz.height() > m_maxSize.height()) - sz.setHeight(m_maxSize.height()); - } else { - if (sz.width() > m_maxSize.width()) - sz.setWidth(m_maxSize.width()); - } - } - return contentsSize; -} - -QAndroidStyle::AndroidSeekBarControl::AndroidSeekBarControl(const QVariantMap &control, - ItemType itemType) - : AndroidProgressBarControl(control, itemType) -{ - QVariantMap::const_iterator it = control.find(QLatin1String("SeekBar_thumb")); - if (it != control.end()) - m_seekBarThumb = AndroidDrawable::fromMap(it.value().toMap(), itemType); - else - m_seekBarThumb = 0; -} - -QAndroidStyle::AndroidSeekBarControl::~AndroidSeekBarControl() -{ - delete m_seekBarThumb; -} - -void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *option, - QPainter *p, - const QWidget * /* w */) -{ - if (!m_seekBarThumb || !m_progressDrawable) - return; - - if (const QStyleOptionSlider *styleOption = - qstyleoption_cast(option)) { - double factor = double(styleOption->sliderPosition - styleOption->minimum) - / double(styleOption->maximum - styleOption->minimum); - - // Android does not have a vertical slider. To support the vertical orientation, we rotate - // the painter and pretend that we are horizontal. - if (styleOption->orientation == Qt::Vertical) - factor = 1 - factor; - - if (m_progressDrawable->type() == QAndroidStyle::Layer) { - QAndroidStyle::AndroidDrawable *clipDrawable = static_cast(m_progressDrawable)->layer(m_progressId); - if (clipDrawable->type() == QAndroidStyle::Clip) - static_cast(clipDrawable)->setFactor(factor, Qt::Horizontal); - else - static_cast(m_progressDrawable)->setFactor(m_progressId, factor, Qt::Horizontal); - } - const AndroidDrawable *drawable = m_seekBarThumb; - if (drawable->type() == State) - drawable = static_cast(m_seekBarThumb)->bestAndroidStateMatch(option); - QStyleOption copy(*option); - - p->save(); - - if (styleOption->orientation == Qt::Vertical) { - // rotate the painter, and transform the rectangle to match - p->rotate(90); - copy.rect = QRect(copy.rect.y(), copy.rect.x() - copy.rect.width(), copy.rect.height(), copy.rect.width()); - } - - copy.rect.setHeight(m_progressDrawable->size().height()); - copy.rect.setWidth(copy.rect.width() - drawable->size().width()); - const int yTranslate = abs(drawable->size().height() - copy.rect.height()) / 2; - copy.rect.translate(drawable->size().width() / 2, yTranslate); - m_progressDrawable->draw(p, ©); - int pos = copy.rect.width() * factor - drawable->size().width() / 2; - copy.rect.translate(pos, -yTranslate); - copy.rect.setSize(drawable->size()); - m_seekBarThumb->draw(p, ©); - - p->restore(); - } -} - -QSize QAndroidStyle::AndroidSeekBarControl::sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, - const QWidget *w) const -{ - QSize sz = AndroidProgressBarControl::sizeFromContents(opt, contentsSize, w); - if (!m_seekBarThumb) - return sz; - const AndroidDrawable *drawable = m_seekBarThumb; - if (drawable->type() == State) - drawable = static_cast(m_seekBarThumb)->bestAndroidStateMatch(opt); - return sz.expandedTo(drawable->size()); -} - -QRect QAndroidStyle::AndroidSeekBarControl::subControlRect(const QStyleOptionComplex *option, - SubControl sc, - const QWidget * /* widget */) const -{ - const QStyleOptionSlider *styleOption = - qstyleoption_cast(option); - - if (m_seekBarThumb && sc == SC_SliderHandle && styleOption) { - const AndroidDrawable *drawable = m_seekBarThumb; - if (drawable->type() == State) - drawable = static_cast(m_seekBarThumb)->bestAndroidStateMatch(option); - - QRect r(option->rect); - double factor = double(styleOption->sliderPosition - styleOption->minimum) - / (styleOption->maximum - styleOption->minimum); - if (styleOption->orientation == Qt::Vertical) { - int pos = option->rect.height() * (1 - factor) - double(drawable->size().height() / 2); - r.setY(r.y() + pos); - } else { - int pos = option->rect.width() * factor - double(drawable->size().width() / 2); - r.setX(r.x() + pos); - } - r.setSize(drawable->size()); - return r; - } - return option->rect; -} - -QAndroidStyle::AndroidSpinnerControl::AndroidSpinnerControl(const QVariantMap &control, - QAndroidStyle::ItemType itemType) - : AndroidControl(control, itemType) -{} - -QRect QAndroidStyle::AndroidSpinnerControl::subControlRect(const QStyleOptionComplex *option, - SubControl sc, - const QWidget *widget) const -{ - if (sc == QStyle::SC_ComboBoxListBoxPopup) - return option->rect; - if (sc == QStyle::SC_ComboBoxArrow) { - const QRect editField = subControlRect(option, QStyle::SC_ComboBoxEditField, widget); - return QRect(editField.topRight(), QSize(option->rect.width() - editField.width(), option->rect.height())); - } - return AndroidControl::subControlRect(option, sc, widget); -} - -QT_END_NAMESPACE - -#endif // QT_CONFIG(style_android) || defined(QT_PLUGIN) diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h deleted file mode 100644 index caff0afada..0000000000 --- a/src/widgets/styles/qandroidstyle_p.h +++ /dev/null @@ -1,395 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 BogDan Vatra -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QANDROIDSTYLE_P_H -#define QANDROIDSTYLE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qstylefactory.cpp. This header may change from version to version -// without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include -#include "qfusionstyle_p.h" - -QT_BEGIN_NAMESPACE - -#if QT_CONFIG(style_android) - -class Q_WIDGETS_EXPORT QAndroidStyle : public QFusionStyle -{ - Q_OBJECT - -public: - enum ItemType - { - QC_UnknownType = -1, - QC_View, - QC_GroupBox, - QC_Button, - QC_Checkbox, - QC_RadioButton, - QC_Slider, - QC_Switch, - QC_EditText, - QC_Combobox, - QC_BusyIndicator, - QC_ProgressBar, - QC_Tab, - QC_TabButton, - QC_RatingIndicator, - QC_SearchBox, - QC_CustomControl=0xf00, - QC_ControlMask=0xfff - }; - - struct Android9PatchChunk - { - QVector xDivs; - QVector yDivs; - QVector colors; - }; - - struct AndroidItemStateInfo - { - AndroidItemStateInfo():state(0){} - int state; - QByteArray filePath; - QByteArray hashKey; - Android9PatchChunk chunkData; - QSize size; - QMargins padding; - }; - - enum AndroidDrawableType - { - Color, - Image, - Clip, - NinePatch, - Gradient, - State, - Layer - }; - - class AndroidDrawable - { - public: - AndroidDrawable(const QVariantMap &drawable, ItemType itemType); - virtual ~AndroidDrawable(); - virtual void initPadding(const QVariantMap &drawable); - virtual AndroidDrawableType type() const = 0; - virtual void draw(QPainter *painter,const QStyleOption *opt) const = 0; - const QMargins &padding() const; - virtual QSize size() const; - static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType); - static QMargins extractMargins(const QVariantMap &value); - virtual void setPaddingLeftToSizeWidth(); - protected: - ItemType m_itemType; - QMargins m_padding; - }; - - class AndroidColorDrawable: public AndroidDrawable - { - public: - AndroidColorDrawable(const QVariantMap &drawable, ItemType itemType); - virtual AndroidDrawableType type() const; - virtual void draw(QPainter *painter,const QStyleOption *opt) const; - - protected: - QColor m_color; - }; - - class AndroidImageDrawable: public AndroidDrawable - { - public: - AndroidImageDrawable(const QVariantMap &drawable, ItemType itemType); - virtual AndroidDrawableType type() const; - virtual void draw(QPainter *painter,const QStyleOption *opt) const; - virtual QSize size() const; - - protected: - QString m_filePath; - mutable QString m_hashKey; - QSize m_size; - }; - - class Android9PatchDrawable: public AndroidImageDrawable - { - public: - Android9PatchDrawable(const QVariantMap &drawable, ItemType itemType); - virtual AndroidDrawableType type() const; - virtual void draw(QPainter *painter, const QStyleOption *opt) const; - private: - static int calculateStretch(int boundsLimit, int startingPoint, - int srcSpace, int numStrechyPixelsRemaining, - int numFixedPixelsRemaining); - void extractIntArray(const QVariantList &values, QVector &array); - private: - Android9PatchChunk m_chunkData; - }; - - class AndroidGradientDrawable: public AndroidDrawable - { - public: - enum GradientOrientation - { - TOP_BOTTOM, - TR_BL, - RIGHT_LEFT, - BR_TL, - BOTTOM_TOP, - BL_TR, - LEFT_RIGHT, - TL_BR - }; - - public: - AndroidGradientDrawable(const QVariantMap &drawable, ItemType itemType); - virtual AndroidDrawableType type() const; - virtual void draw(QPainter *painter, const QStyleOption *opt) const; - QSize size() const; - private: - mutable QLinearGradient m_gradient; - GradientOrientation m_orientation; - int m_radius; - }; - - class AndroidClipDrawable: public AndroidDrawable - { - public: - AndroidClipDrawable(const QVariantMap &drawable, ItemType itemType); - ~AndroidClipDrawable(); - virtual AndroidDrawableType type() const; - virtual void setFactor(double factor, Qt::Orientation orientation); - virtual void draw(QPainter *painter, const QStyleOption *opt) const; - - private: - double m_factor; - Qt::Orientation m_orientation; - const AndroidDrawable *m_drawable; - }; - - class AndroidStateDrawable: public AndroidDrawable - { - public: - AndroidStateDrawable(const QVariantMap &drawable, ItemType itemType); - ~AndroidStateDrawable(); - virtual AndroidDrawableType type() const; - virtual void draw(QPainter *painter, const QStyleOption *opt) const; - inline const AndroidDrawable *bestAndroidStateMatch(const QStyleOption *opt) const; - static int extractState(const QVariantMap &value); - virtual void setPaddingLeftToSizeWidth(); - QSize sizeImage(const QStyleOption *opt) const; - private: - typedef QPair StateType; - QList m_states; - }; - - class AndroidLayerDrawable: public AndroidDrawable - { - public: - AndroidLayerDrawable(const QVariantMap &drawable, QAndroidStyle::ItemType itemType); - ~AndroidLayerDrawable(); - virtual AndroidDrawableType type() const; - virtual void setFactor(int id, double factor, Qt::Orientation orientation); - virtual void draw(QPainter *painter, const QStyleOption *opt) const; - AndroidDrawable *layer(int id) const; - QSize size() const; - private: - typedef QPair LayerType; - QList m_layers; - int m_id; - double m_factor; - Qt::Orientation m_orientation; - }; - - class AndroidControl - { - public: - AndroidControl(const QVariantMap &control, ItemType itemType); - virtual ~AndroidControl(); - virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w); - virtual QRect subElementRect(SubElement subElement, - const QStyleOption *option, - const QWidget *widget = 0) const; - virtual QRect subControlRect(const QStyleOptionComplex *option, - SubControl sc, - const QWidget *widget = 0) const; - virtual QSize sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, - const QWidget *w) const; - virtual QMargins padding(); - virtual QSize size(const QStyleOption *option); - protected: - virtual const AndroidDrawable * backgroundDrawable() const; - const AndroidDrawable *m_background; - QSize m_minSize; - QSize m_maxSize; - }; - - class AndroidCompoundButtonControl : public AndroidControl - { - public: - AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType); - virtual ~AndroidCompoundButtonControl(); - virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w); - virtual QMargins padding(); - virtual QSize size(const QStyleOption *option); - protected: - virtual const AndroidDrawable * backgroundDrawable() const; - const AndroidDrawable *m_button; - }; - - class AndroidProgressBarControl : public AndroidControl - { - public: - AndroidProgressBarControl(const QVariantMap &control, ItemType itemType); - virtual ~AndroidProgressBarControl(); - virtual void drawControl(const QStyleOption *option, QPainter *p, const QWidget *w); - virtual QRect subElementRect(SubElement subElement, - const QStyleOption *option, - const QWidget *widget = 0) const; - - QSize sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, - const QWidget *w) const; - protected: - AndroidDrawable *m_progressDrawable; - AndroidDrawable *m_indeterminateDrawable; - int m_secondaryProgress_id; - int m_progressId; - }; - - class AndroidSeekBarControl : public AndroidProgressBarControl - { - public: - AndroidSeekBarControl(const QVariantMap &control, ItemType itemType); - virtual ~AndroidSeekBarControl(); - virtual void drawControl(const QStyleOption *option, QPainter *p, const QWidget *w); - QSize sizeFromContents(const QStyleOption *opt, - const QSize &contentsSize, const QWidget *w) const; - QRect subControlRect(const QStyleOptionComplex *option, SubControl sc, - const QWidget *widget = 0) const; - private: - AndroidDrawable *m_seekBarThumb; - }; - - class AndroidSpinnerControl : public AndroidControl - { - public: - AndroidSpinnerControl(const QVariantMap &control, ItemType itemType); - virtual ~AndroidSpinnerControl(){} - virtual QRect subControlRect(const QStyleOptionComplex *option, - SubControl sc, - const QWidget *widget = 0) const; - }; - - typedef QList AndroidItemStateInfoList; - -public: - QAndroidStyle(); - ~QAndroidStyle(); - - virtual void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, - const QWidget *w = 0) const; - - virtual void drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, - const QWidget *w = 0) const; - - virtual QRect subElementRect(SubElement subElement, const QStyleOption *option, - const QWidget *widget = 0) const; - virtual void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, - const QWidget *widget = 0) const; - virtual SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, - const QPoint &pt, const QWidget *widget = 0) const; - virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, - SubControl sc, const QWidget *widget = 0) const; - - virtual int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, - const QWidget *widget = 0) const; - - virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, - const QSize &contentsSize, const QWidget *w = 0) const; - - virtual QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt = 0, - const QWidget *widget = 0) const; - - virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, - const QStyleOption *opt) const; - - int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, - QStyleHintReturn *returnData = 0) const; - - virtual QPalette standardPalette() const; - void polish(QWidget *widget); - void unpolish(QWidget *widget); - -private: - Q_DISABLE_COPY(QAndroidStyle) - static ItemType qtControl(QStyle::ComplexControl control); - static ItemType qtControl(QStyle::ContentsType contentsType); - static ItemType qtControl(QStyle::ControlElement controlElement); - static ItemType qtControl(QStyle::PrimitiveElement primitiveElement); - static ItemType qtControl(QStyle::SubElement subElement); - static ItemType qtControl(const QString &android); - -private: - typedef QHash AndroidControlsHash; - AndroidControlsHash m_androidControlsHash; - QPalette m_standardPalette; - AndroidCompoundButtonControl *checkBoxControl; -}; - -#endif // style_android - -QT_END_NAMESPACE - -#endif // QANDROIDSTYLE_P_H diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h index 2ef7f30d21..ebfc06139c 100644 --- a/src/widgets/styles/qcommonstyle_p.h +++ b/src/widgets/styles/qcommonstyle_p.h @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE class QStringList; // Private class -class QCommonStylePrivate : public QStylePrivate +class Q_WIDGETS_EXPORT QCommonStylePrivate : public QStylePrivate { Q_DECLARE_PUBLIC(QCommonStyle) public: diff --git a/src/widgets/styles/qfusionstyle_p.h b/src/widgets/styles/qfusionstyle_p.h index aac27e51ab..10f76045d5 100644 --- a/src/widgets/styles/qfusionstyle_p.h +++ b/src/widgets/styles/qfusionstyle_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE #if QT_CONFIG(style_fusion) class QFusionStylePrivate; -class QFusionStyle : public QCommonStyle +class Q_WIDGETS_EXPORT QFusionStyle : public QCommonStyle { Q_OBJECT Q_DECLARE_PRIVATE(QFusionStyle) diff --git a/src/widgets/styles/qmacstyle.qdoc b/src/widgets/styles/qmacstyle.qdoc deleted file mode 100644 index fcbc813844..0000000000 --- a/src/widgets/styles/qmacstyle.qdoc +++ /dev/null @@ -1,207 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Free Documentation License Usage -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. Please review the following information to ensure -** the GNU Free Documentation License version 1.3 requirements -** will be met: https://www.gnu.org/licenses/fdl-1.3.html. -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -/*! - \class QMacStyle - \brief The QMacStyle class provides a \macos style using the Apple Appearance Manager. - - \ingroup appearance - \inmodule QtWidgets - \internal - - This class is implemented as a wrapper to the HITheme - APIs, allowing applications to be styled according to the current - theme in use on \macos. This is done by having primitives - in QStyle implemented in terms of what \macos would normally theme. - - \warning This style is only available on \macos because it relies on the - HITheme APIs. - - There are additional issues that should be taken - into consideration to make an application compatible with the - \l{Apple Human Interface Guidelines}{Apple Human Interface Guidelines}. Some of these issues are outlined - below. - - \list - - \li Layout - The restrictions on window layout are such that some - aspects of layout that are style-dependent cannot be achieved - using QLayout. Changes are being considered (and feedback would be - appreciated) to make layouts QStyle-able. Some of the restrictions - involve horizontal and vertical widget alignment and widget size - (covered below). - - \li Widget size - \macos allows widgets to have specific fixed sizes. Qt - does not fully implement this behavior so as to maintain cross-platform - compatibility. As a result some widgets sizes may be inappropriate (and - subsequently not rendered correctly by the HITheme APIs).The - QWidget::sizeHint() will return the appropriate size for many - managed widgets (widgets enumerated in \l QStyle::ContentsType). - - \li Effects - QMacStyle uses HITheme for performing most of the drawing, but - also uses emulation in a few cases where HITheme does not provide the - required functionality (for example, tab bars on Panther, the toolbar - separator, etc). We tried to make the emulation as close to the original as - possible. Please report any issues you see in effects or non-standard - widgets. - - \endlist - - There are other issues that need to be considered in the feel of - your application (including the general color scheme to match the - Aqua colors). The Guidelines mentioned above will remain current - with new advances and design suggestions for \macos. - - Note that the functions provided by QMacStyle are - reimplementations of QStyle functions; see QStyle for their - documentation. - - \image qmacstyle.png - \sa QWindowsVistaStyle, QWindowsStyle, QFusionStyle -*/ - - -/*! - \enum QMacStyle::WidgetSizePolicy - - \value SizeSmall - \value SizeLarge - \value SizeMini - \value SizeDefault -*/ - -/*! \fn QMacStyle::QMacStyle() - Constructs a QMacStyle object. -*/ - -/*! \fn QMacStyle::~QMacStyle() - Destructs a QMacStyle object. -*/ - -/*! \fn void QMacStyle::polish(QPalette &pal) - \reimp -*/ - -/*! \fn void QMacStyle::polish(QApplication *) - \reimp -*/ - -/*! \fn void QMacStyle::unpolish(QApplication *) - \reimp -*/ - -/*! \fn void QMacStyle::polish(QWidget* w) - \reimp -*/ - -/*! \fn void QMacStyle::unpolish(QWidget* w) - \reimp -*/ - -/*! \fn int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const - \reimp -*/ - -/*! \fn QPalette QMacStyle::standardPalette() const - \reimp -*/ - -/*! \fn int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, QStyleHintReturn *hret) const - \reimp -*/ - -/*! \fn QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const - \reimp -*/ - -/*! \fn QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const - \reimp -*/ - -/*! \fn void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy) - - \obsolete - - Call QWidget::setAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, - or Qt::WA_MacNormalSize instead. -*/ - -/*! \fn QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt = 0) - \obsolete - - Call QWidget::testAttribute() with Qt::WA_MacMiniSize, Qt::WA_MacSmallSize, - or Qt::WA_MacNormalSize instead. -*/ - -/*! \fn void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const - - \reimp -*/ - -/*! \fn void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, const QWidget *w) const - - \reimp -*/ - -/*! \fn QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *widget) const - - \reimp -*/ - -/*! \fn void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const - \reimp -*/ - -/*! \fn QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *widget) const - \reimp -*/ - -/*! \fn QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const - \reimp -*/ - -/*! \fn QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &csz, const QWidget *widget) const - \reimp -*/ - -/*! \fn void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const - \reimp -*/ - -/*! \fn bool QMacStyle::event(QEvent *e) - \reimp -*/ - -/*! \fn QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, const QWidget *widget) const - \reimp -*/ - -/*! \fn int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const - \reimp -*/ - diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm deleted file mode 100644 index 47193f2a84..0000000000 --- a/src/widgets/styles/qmacstyle_mac.mm +++ /dev/null @@ -1,7041 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - Note: The qdoc comments for QMacStyle are contained in - .../doc/src/qstyles.qdoc. -*/ - -#include - -#include "qmacstyle_mac_p.h" -#include "qmacstyle_mac_p_p.h" - -#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN -//#define DEBUG_SIZE_CONSTRAINT - -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(dialogbuttonbox) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_USE_NAMESPACE - -static QWindow *qt_getWindow(const QWidget *widget) -{ - return widget ? widget->window()->windowHandle() : 0; -} - -@interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject { -QMacStylePrivate *mPrivate; -} -- (id)initWithPrivate:(QMacStylePrivate *)priv; -- (void)scrollBarStyleDidChange:(NSNotification *)notification; -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(NotificationReceiver); - -@implementation NotificationReceiver -- (id)initWithPrivate:(QMacStylePrivate *)priv -{ - self = [super init]; - mPrivate = priv; - return self; -} - -- (void)scrollBarStyleDidChange:(NSNotification *)notification -{ - Q_UNUSED(notification); - - // purge destroyed scroll bars: - QMacStylePrivate::scrollBars.removeAll(QPointer()); - - QEvent event(QEvent::StyleChange); - for (const auto &o : QMacStylePrivate::scrollBars) - QCoreApplication::sendEvent(o, &event); -} -@end - -QT_BEGIN_NAMESPACE - -// The following constants are used for adjusting the size -// of push buttons so that they are drawn inside their bounds. -const int QMacStylePrivate::PushButtonLeftOffset = 6; -const int QMacStylePrivate::PushButtonTopOffset = 4; -const int QMacStylePrivate::PushButtonRightOffset = 12; -const int QMacStylePrivate::PushButtonBottomOffset = 12; -const int QMacStylePrivate::MiniButtonH = 26; -const int QMacStylePrivate::SmallButtonH = 30; -const int QMacStylePrivate::BevelButtonW = 50; -const int QMacStylePrivate::BevelButtonH = 22; -const int QMacStylePrivate::PushButtonContentPadding = 6; - -QVector > QMacStylePrivate::scrollBars; - -// Title bar gradient colors for Lion were determined by inspecting PSDs exported -// using CoreUI's CoreThemeDocument; there is no public API to retrieve them - -static QLinearGradient titlebarGradientActive() -{ - static QLinearGradient gradient; - if (gradient == QLinearGradient()) { - gradient.setColorAt(0, QColor(235, 235, 235)); - gradient.setColorAt(0.5, QColor(210, 210, 210)); - gradient.setColorAt(0.75, QColor(195, 195, 195)); - gradient.setColorAt(1, QColor(180, 180, 180)); - } - return gradient; -} - -static QLinearGradient titlebarGradientInactive() -{ - static QLinearGradient gradient; - if (gradient == QLinearGradient()) { - gradient.setColorAt(0, QColor(250, 250, 250)); - gradient.setColorAt(1, QColor(225, 225, 225)); - } - return gradient; -} - -static const QColor titlebarSeparatorLineActive(111, 111, 111); -static const QColor titlebarSeparatorLineInactive(131, 131, 131); - -// Gradient colors used for the dock widget title bar and -// non-unifed tool bar bacground. -static const QColor mainWindowGradientBegin(240, 240, 240); -static const QColor mainWindowGradientEnd(200, 200, 200); - -static const int DisclosureOffset = 4; - -// Tab bar colors -// active: window is active -// selected: tab is selected -// hovered: tab is hovered -static const QColor tabBarTabBackgroundActive(190, 190, 190); -static const QColor tabBarTabBackgroundActiveHovered(178, 178, 178); -static const QColor tabBarTabBackgroundActiveSelected(211, 211, 211); -static const QColor tabBarTabBackground(227, 227, 227); -static const QColor tabBarTabBackgroundSelected(246, 246, 246); -static const QColor tabBarTabLineActive(160, 160, 160); -static const QColor tabBarTabLineActiveHovered(150, 150, 150); -static const QColor tabBarTabLine(210, 210, 210); -static const QColor tabBarTabLineSelected(189, 189, 189); -static const QColor tabBarCloseButtonBackgroundHovered(162, 162, 162); -static const QColor tabBarCloseButtonBackgroundPressed(153, 153, 153); -static const QColor tabBarCloseButtonBackgroundSelectedHovered(192, 192, 192); -static const QColor tabBarCloseButtonBackgroundSelectedPressed(181, 181, 181); -static const QColor tabBarCloseButtonCross(100, 100, 100); -static const QColor tabBarCloseButtonCrossSelected(115, 115, 115); - -static const int closeButtonSize = 14; -static const qreal closeButtonCornerRadius = 2.0; - -// Resolve these at run-time, since the functions was moved in Leopard. -typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *); -static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0; - -#ifndef QT_NO_TABBAR -static bool isVerticalTabs(const QTabBar::Shape shape) { - return (shape == QTabBar::RoundedEast - || shape == QTabBar::TriangularEast - || shape == QTabBar::RoundedWest - || shape == QTabBar::TriangularWest); -} -#endif - -static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) -{ - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - QPlatformNativeInterface::NativeResourceForIntegrationFunction function = - nativeInterface->nativeResourceFunctionForIntegration("testContentBorderPosition"); - if (!function) - return false; // Not Cocoa platform plugin. - - typedef bool (*TestContentBorderPositionFunction)(QWindow *, int); - return (reinterpret_cast(function))(window, windowY); -} - - -void drawTabCloseButton(QPainter *p, bool hover, bool selected, bool pressed) -{ - p->setRenderHints(QPainter::Antialiasing); - QRect rect(0, 0, closeButtonSize, closeButtonSize); - const int width = rect.width(); - const int height = rect.height(); - - if (hover) { - // draw background circle - QColor background; - if (selected) { - background = pressed ? tabBarCloseButtonBackgroundSelectedPressed : tabBarCloseButtonBackgroundSelectedHovered; - } else { - background = pressed ? tabBarCloseButtonBackgroundPressed : tabBarCloseButtonBackgroundHovered; - } - p->setPen(Qt::transparent); - p->setBrush(background); - p->drawRoundedRect(rect, closeButtonCornerRadius, closeButtonCornerRadius); - } - - // draw cross - const int margin = 3; - QPen crossPen; - crossPen.setColor(selected ? tabBarCloseButtonCrossSelected : tabBarCloseButtonCross); - crossPen.setWidthF(1.1); - crossPen.setCapStyle(Qt::FlatCap); - p->setPen(crossPen); - p->drawLine(margin, margin, width - margin, height - margin); - p->drawLine(margin, height - margin, width - margin, margin); -} - -#ifndef QT_NO_TABBAR -QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) -{ - if (isVerticalTabs(shape)) { - int newX, newY, newRot; - if (shape == QTabBar::RoundedEast - || shape == QTabBar::TriangularEast) { - newX = tabRect.width(); - newY = tabRect.y(); - newRot = 90; - } else { - newX = 0; - newY = tabRect.y() + tabRect.height(); - newRot = -90; - } - tabRect.setRect(0, 0, tabRect.height(), tabRect.width()); - QMatrix m; - m.translate(newX, newY); - m.rotate(newRot); - p->setMatrix(m, true); - } - return tabRect; -} - -void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, int tabOverlap) -{ - QRect rect = tabOpt->rect; - - switch (tabOpt->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - rect.adjust(-tabOverlap, 0, 0, 0); - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - rect.adjust(0, -tabOverlap, 0, 0); - break; - default: - break; - } - - p->translate(rect.x(), rect.y()); - rect.moveLeft(0); - rect.moveTop(0); - const QRect tabRect = rotateTabPainter(p, tabOpt->shape, rect); - - const int width = tabRect.width(); - const int height = tabRect.height(); - const bool active = (tabOpt->state & QStyle::State_Active); - const bool selected = (tabOpt->state & QStyle::State_Selected); - - const QRect bodyRect(1, 1, width - 2, height - 2); - const QRect topLineRect(1, 0, width - 2, 1); - const QRect bottomLineRect(1, height - 1, width - 2, 1); - if (selected) { - // fill body - if (tabOpt->documentMode && isUnified) { - p->save(); - p->setCompositionMode(QPainter::CompositionMode_Source); - p->fillRect(tabRect, QColor(Qt::transparent)); - p->restore(); - } else if (active) { - p->fillRect(bodyRect, tabBarTabBackgroundActiveSelected); - // top line - p->fillRect(topLineRect, tabBarTabLineSelected); - } else { - p->fillRect(bodyRect, tabBarTabBackgroundSelected); - } - } else { - // when the mouse is over non selected tabs they get a new color - const bool hover = (tabOpt->state & QStyle::State_MouseOver); - if (hover) { - // fill body - p->fillRect(bodyRect, tabBarTabBackgroundActiveHovered); - // bottom line - p->fillRect(bottomLineRect, tabBarTabLineActiveHovered); - } - } - - // separator lines between tabs - const QRect leftLineRect(0, 1, 1, height - 2); - const QRect rightLineRect(width - 1, 1, 1, height - 2); - const QColor separatorLineColor = active ? tabBarTabLineActive : tabBarTabLine; - p->fillRect(leftLineRect, separatorLineColor); - p->fillRect(rightLineRect, separatorLineColor); -} - -void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w) -{ - QRect r = tbb->rect; - if (isVerticalTabs(tbb->shape)) { - r.setWidth(w->width()); - } else { - r.setHeight(w->height()); - } - const QRect tabRect = rotateTabPainter(p, tbb->shape, r); - const int width = tabRect.width(); - const int height = tabRect.height(); - const bool active = (tbb->state & QStyle::State_Active); - - // fill body - const QRect bodyRect(0, 1, width, height - 1); - const QColor bodyColor = active ? tabBarTabBackgroundActive : tabBarTabBackground; - p->fillRect(bodyRect, bodyColor); - - // top line - const QRect topLineRect(0, 0, width, 1); - const QColor topLineColor = active ? tabBarTabLineActive : tabBarTabLine; - p->fillRect(topLineRect, topLineColor); - - // bottom line - const QRect bottomLineRect(0, height - 1, width, 1); - const QColor bottomLineColor = active ? tabBarTabLineActive : tabBarTabLine; - p->fillRect(bottomLineRect, bottomLineColor); -} -#endif - -static int getControlSize(const QStyleOption *option, const QWidget *widget) -{ - switch (QStyleHelper::widgetSizePolicy(widget, option)) { - case QStyleHelper::SizeSmall: - return QAquaSizeSmall; - case QStyleHelper::SizeMini: - return QAquaSizeMini; - default: - break; - } - return QAquaSizeLarge; -} - - -#ifndef QT_NO_TREEVIEW -static inline bool isTreeView(const QWidget *widget) -{ - return (widget && widget->parentWidget() && - (qobject_cast(widget->parentWidget()) - )); -} -#endif - -#ifndef QT_NO_TABBAR -static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) -{ - ThemeTabDirection ttd; - switch (shape) { - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - ttd = kThemeTabSouth; - break; - default: // Added to remove the warning, since all values are taken care of, really! - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - ttd = kThemeTabNorth; - break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - ttd = kThemeTabWest; - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - ttd = kThemeTabEast; - break; - } - return ttd; -} -#endif - -static QString qt_mac_removeMnemonics(const QString &original) -{ - QString returnText(original.size(), 0); - int finalDest = 0; - int currPos = 0; - int l = original.length(); - while (l) { - if (original.at(currPos) == QLatin1Char('&') - && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { - ++currPos; - --l; - if (l == 0) - break; - } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 && - original.at(currPos + 1) == QLatin1Char('&') && - original.at(currPos + 2) != QLatin1Char('&') && - original.at(currPos + 3) == QLatin1Char(')')) { - /* remove mnemonics its format is "\s*(&X)" */ - int n = 0; - while (finalDest > n && returnText.at(finalDest - n - 1).isSpace()) - ++n; - finalDest -= n; - currPos += 4; - l -= 4; - continue; - } - returnText[finalDest] = original.at(currPos); - ++currPos; - ++finalDest; - --l; - } - returnText.truncate(finalDest); - return returnText; -} - -OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon) -{ - QRegion *region = static_cast(inRefcon); - if (!region) - return paramErr; - - switch (inMessage) { - case kHIShapeEnumerateRect: - *region += QRect(inRect->origin.x, inRect->origin.y, - inRect->size.width, inRect->size.height); - break; - case kHIShapeEnumerateInit: - // Assume the region is already setup correctly - case kHIShapeEnumerateTerminate: - default: - break; - } - return noErr; -} - -/*! - \internal - Create's a mutable shape, it's the caller's responsibility to release. - WARNING: this function clamps the coordinates to SHRT_MIN/MAX on 10.4 and below. -*/ -HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) -{ - HIMutableShapeRef shape = HIShapeCreateMutable(); - if (region.rectCount() < 2 ) { - QRect qtRect = region.boundingRect(); - CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } else { - for (const QRect &qtRect : region) { - CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); - HIShapeUnionWithRect(shape, &cgRect); - } - } - return shape; -} - -QRegion qt_mac_fromHIShapeRef(HIShapeRef shape) -{ - QRegion returnRegion; - //returnRegion.detach(); - HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, qt_mac_shape2QRegionHelper, &returnRegion); - return returnRegion; -} - -bool qt_macWindowIsTextured(const QWidget *window) -{ - if (QWindow *w = window->windowHandle()) - if (w->handle()) - if (NSWindow *nswindow = static_cast(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("NSWindow"), w))) - return ([nswindow styleMask] & NSTexturedBackgroundWindowMask) ? true : false; - return false; -} - -static bool qt_macWindowMainWindow(const QWidget *window) -{ - if (QWindow *w = window->windowHandle()) { - if (w->handle()) { - if (NSWindow *nswindow = static_cast(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("nswindow"), w))) { - return [nswindow isMainWindow]; - } - } - } - return false; -} - -/***************************************************************************** - QMacCGStyle globals - *****************************************************************************/ -const int qt_mac_hitheme_version = 0; //the HITheme version we speak -const int macItemFrame = 2; // menu item frame width -const int macItemHMargin = 3; // menu item hor text margin -const int macRightBorder = 12; // right border on mac -const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar. -QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background. - -/***************************************************************************** - QMacCGStyle utility functions - *****************************************************************************/ -static inline int qt_mac_hitheme_tab_version() -{ - return 1; -} - -static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect()) -{ - return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(), - convertRect.width() - rect.width(), convertRect.height() - rect.height()); -} - -static inline const QRect qt_qrectForHIRect(const HIRect &hirect) -{ - return QRect(QPoint(int(hirect.origin.x), int(hirect.origin.y)), - QSize(int(hirect.size.width), int(hirect.size.height))); -} - -inline bool qt_mac_is_metal(const QWidget *w) -{ - for (; w; w = w->parentWidget()) { - if (w->testAttribute(Qt::WA_MacBrushedMetal)) - return true; - if (w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) { // If not created will fall through to the opaque check and be fine anyway. - return qt_macWindowIsTextured(w); - } -#ifndef QT_NO_ACCESSIBILITY - if (w->d_func()->isOpaque) - break; -#endif - } - return false; -} - -static int qt_mac_aqua_get_metric(ThemeMetric met) -{ - SInt32 ret; - GetThemeMetric(met, &ret); - return ret; -} - -static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg, QSize szHint, - QAquaWidgetSize sz) -{ - QSize ret(-1, -1); - if (sz != QAquaSizeSmall && sz != QAquaSizeLarge && sz != QAquaSizeMini) { - qDebug("Not sure how to return this..."); - return ret; - } - if ((widg && widg->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware()) { - // If you're using a custom font and it's bigger than the default font, - // then no constraints for you. If you are smaller, we can try to help you out - QFont font = qt_app_fonts_hash()->value(widg->metaObject()->className(), QFont()); - if (widg->font().pointSize() > font.pointSize()) - return ret; - } - - if (ct == QStyle::CT_CustomBase && widg) { -#if QT_CONFIG(pushbutton) - if (qobject_cast(widg)) - ct = QStyle::CT_PushButton; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_RadioButton; -#if QT_CONFIG(checkbox) - else if (qobject_cast(widg)) - ct = QStyle::CT_CheckBox; -#endif -#ifndef QT_NO_COMBOBOX - else if (qobject_cast(widg)) - ct = QStyle::CT_ComboBox; -#endif -#ifndef QT_NO_TOOLBUTTON - else if (qobject_cast(widg)) - ct = QStyle::CT_ToolButton; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_Slider; -#ifndef QT_NO_PROGRESSBAR - else if (qobject_cast(widg)) - ct = QStyle::CT_ProgressBar; -#endif -#ifndef QT_NO_LINEEDIT - else if (qobject_cast(widg)) - ct = QStyle::CT_LineEdit; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_HeaderSection; -#ifndef QT_NO_MENUBAR - else if (qobject_cast(widg)) - ct = QStyle::CT_MenuBar; -#endif -#ifndef QT_NO_SIZEGRIP - else if (qobject_cast(widg)) - ct = QStyle::CT_SizeGrip; -#endif - else - return ret; - } - - switch (ct) { -#if QT_CONFIG(pushbutton) - case QStyle::CT_PushButton: { - const QPushButton *psh = qobject_cast(widg); - // If this comparison is false, then the widget was not a push button. - // This is bad and there's very little we can do since we were requested to find a - // sensible size for a widget that pretends to be a QPushButton but is not. - if(psh) { - QString buttonText = qt_mac_removeMnemonics(psh->text()); - if (buttonText.contains(QLatin1Char('\n'))) - ret = QSize(-1, -1); - else if (sz == QAquaSizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); - else if (sz == QAquaSizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); - else if (sz == QAquaSizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); - - if (!psh->icon().isNull()){ - // If the button got an icon, and the icon is larger than the - // button, we can't decide on a default size - ret.setWidth(-1); - if (ret.height() < psh->iconSize().height()) - ret.setHeight(-1); - } - else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){ - // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels. - // However, this doesn't work for German, therefore only do it for English, - // I suppose it would be better to do some sort of lookups for languages - // that like to have really long words. - ret.setWidth(77 - 8); - } - } else { - // The only sensible thing to do is to return whatever the style suggests... - if (sz == QAquaSizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); - else if (sz == QAquaSizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight)); - else if (sz == QAquaSizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight)); - else - // Since there's no default size we return the large size... - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight)); - } -#endif -#if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam - } else if (ct == QStyle::CT_RadioButton) { - QRadioButton *rdo = static_cast(widg); - // Exception for case where multiline radio button text requires no size constrainment - if (rdo->text().find('\n') != -1) - return ret; - if (sz == QAquaSizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight)); - else if (sz == QAquaSizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight)); - else if (sz == QAquaSizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight)); - } else if (ct == QStyle::CT_CheckBox) { - if (sz == QAquaSizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight)); - else if (sz == QAquaSizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight)); - else if (sz == QAquaSizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight)); -#endif - break; - } - case QStyle::CT_SizeGrip: - if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) { - HIRect r; - HIPoint p = { 0, 0 }; - HIThemeGrowBoxDrawInfo gbi; - gbi.version = 0; - gbi.state = kThemeStateActive; - gbi.kind = kHIThemeGrowBoxKindNormal; - gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown - : kThemeGrowRight | kThemeGrowDown; - gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; - if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { - int width = 0; -#ifndef QT_NO_MDIAREA - if (widg && qobject_cast(widg->parentWidget())) - width = r.size.width; -#endif - ret = QSize(width, r.size.height); - } - } - break; - case QStyle::CT_ComboBox: - switch (sz) { - case QAquaSizeLarge: - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight)); - break; - case QAquaSizeSmall: - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight)); - break; - case QAquaSizeMini: - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight)); - break; - default: - break; - } - break; - case QStyle::CT_ToolButton: - if (sz == QAquaSizeSmall) { - int width = 0, height = 0; - if (szHint == QSize(-1, -1)) { //just 'guess'.. -#ifndef QT_NO_TOOLBUTTON - const QToolButton *bt = qobject_cast(widg); - // If this conversion fails then the widget was not what it claimed to be. - if(bt) { - if (!bt->icon().isNull()) { - QSize iconSize = bt->iconSize(); - QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal); - width = qMax(width, qMax(iconSize.width(), pmSize.width())); - height = qMax(height, qMax(iconSize.height(), pmSize.height())); - } - if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) { - int text_width = bt->fontMetrics().width(bt->text()), - text_height = bt->fontMetrics().height(); - if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) { - width = qMax(width, text_width); - height += text_height; - } else { - width += text_width; - width = qMax(height, text_height); - } - } - } else -#endif - { - // Let's return the size hint... - width = szHint.width(); - height = szHint.height(); - } - } else { - width = szHint.width(); - height = szHint.height(); - } - width = qMax(20, width + 5); //border - height = qMax(20, height + 5); //border - ret = QSize(width, height); - } - break; - case QStyle::CT_Slider: { - int w = -1; - const QSlider *sld = qobject_cast(widg); - // If this conversion fails then the widget was not what it claimed to be. - if(sld) { - if (sz == QAquaSizeLarge) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth); - } - } else if (sz == QAquaSizeSmall) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth); - } - } else if (sz == QAquaSizeMini) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth); - } - } - } else { - // This is tricky, we were requested to find a size for a slider which is not - // a slider. We don't know if this is vertical or horizontal or if we need to - // have tick marks or not. - // For this case we will return an horizontal slider without tick marks. - w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight); - w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight); - } - if (sld->orientation() == Qt::Horizontal) - ret.setHeight(w); - else - ret.setWidth(w); - break; - } -#ifndef QT_NO_PROGRESSBAR - case QStyle::CT_ProgressBar: { - int finalValue = -1; - Qt::Orientation orient = Qt::Horizontal; - if (const QProgressBar *pb = qobject_cast(widg)) - orient = pb->orientation(); - - if (sz == QAquaSizeLarge) - finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness) - + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset); - else - finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness) - + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset); - if (orient == Qt::Horizontal) - ret.setHeight(finalValue); - else - ret.setWidth(finalValue); - break; - } -#endif -#ifndef QT_NO_COMBOBOX - case QStyle::CT_LineEdit: - if (!widg || !qobject_cast(widg->parentWidget())) { - //should I take into account the font dimentions of the lineedit? -Sam - if (sz == QAquaSizeLarge) - ret = QSize(-1, 21); - else - ret = QSize(-1, 19); - } - break; -#endif - case QStyle::CT_HeaderSection: -#ifndef QT_NO_TREEVIEW - if (isTreeView(widg)) - ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight)); -#endif - break; - case QStyle::CT_MenuBar: - if (sz == QAquaSizeLarge) { - ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]); - // In the qt_mac_set_native_menubar(false) case, - // we come it here with a zero-height main menu, - // preventing the in-window menu from displaying. - // Use 22 pixels for the height, by observation. - if (ret.height() <= 0) - ret.setHeight(22); - } - break; - default: - break; - } - return ret; -} - - -#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) -static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini) -{ - Q_UNUSED(widg); - - if (large == QSize(-1, -1)) { - if (small != QSize(-1, -1)) - return QAquaSizeSmall; - if (mini != QSize(-1, -1)) - return QAquaSizeMini; - return QAquaSizeUnknown; - } else if (small == QSize(-1, -1)) { - if (mini != QSize(-1, -1)) - return QAquaSizeMini; - return QAquaSizeLarge; - } else if (mini == QSize(-1, -1)) { - return QAquaSizeLarge; - } - -#ifndef QT_NO_MAINWINDOW - if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) { - //if (small.width() != -1 || small.height() != -1) - return QAquaSizeSmall; - } else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) { - return QAquaSizeMini; - } -#endif - -#if 0 - /* Figure out which size we're closer to, I just hacked this in, I haven't - tested it as it would probably look pretty strange to have some widgets - big and some widgets small in the same window?? -Sam */ - int large_delta=0; - if (large.width() != -1) { - int delta = large.width() - widg->width(); - large_delta += delta * delta; - } - if (large.height() != -1) { - int delta = large.height() - widg->height(); - large_delta += delta * delta; - } - int small_delta=0; - if (small.width() != -1) { - int delta = small.width() - widg->width(); - small_delta += delta * delta; - } - if (small.height() != -1) { - int delta = small.height() - widg->height(); - small_delta += delta * delta; - } - int mini_delta=0; - if (mini.width() != -1) { - int delta = mini.width() - widg->width(); - mini_delta += delta * delta; - } - if (mini.height() != -1) { - int delta = mini.height() - widg->height(); - mini_delta += delta * delta; - } - if (mini_delta < small_delta && mini_delta < large_delta) - return QAquaSizeMini; - else if (small_delta < large_delta) - return QAquaSizeSmall; -#endif - return QAquaSizeLarge; -} -#endif - -void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const -{ - const qreal pixelRatio = p->device()->devicePixelRatioF(); - static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4"); - const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio); - QPixmap focusRingPixmap; - const qreal size = radius * 2 + 5; - - if (!QPixmapCache::find(key, focusRingPixmap)) { - focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio); - focusRingPixmap.fill(Qt::transparent); - focusRingPixmap.setDevicePixelRatio(pixelRatio); - { - const CGFloat focusRingWidth = radius > 0 ? 3.5 : 6; - QMacAutoReleasePool pool; - QMacCGContext ctx(&focusRingPixmap); - CGContextBeginTransparencyLayer(ctx, NULL); - CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx - flipped:NO]]; - CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size); - NSBezierPath *focusRingPath; - if (radius > 0) { - const CGFloat roundedRectInset = -1.5; - focusRingPath = [NSBezierPath bezierPathWithRoundedRect:CGRectInset(focusRingRect, roundedRectInset, roundedRectInset) - xRadius:radius - yRadius:radius]; - } else { - const CGFloat outerClipInset = -focusRingWidth / 2; - NSBezierPath *focusRingClipPath = [NSBezierPath bezierPathWithRect:CGRectInset(focusRingRect, outerClipInset, outerClipInset)]; - const CGFloat innerClipInset = 1; - NSBezierPath *focusRingInnerClipPath = [NSBezierPath bezierPathWithRect:CGRectInset(focusRingRect, innerClipInset, innerClipInset)]; - [focusRingClipPath appendBezierPath:focusRingInnerClipPath.bezierPathByReversingPath]; - [focusRingClipPath setClip]; - focusRingPath = [NSBezierPath bezierPathWithRect:focusRingRect]; - focusRingPath.lineJoinStyle = NSRoundLineJoinStyle; - } - - focusRingPath.lineWidth = focusRingWidth; - [[NSColor keyboardFocusIndicatorColor] setStroke]; - [focusRingPath stroke]; - - CGContextEndTransparencyLayer(ctx); - [NSGraphicsContext restoreGraphicsState]; - } - QPixmapCache::insert(key, focusRingPixmap); - } - - // Add 2 for the actual ring tickness going inwards - const qreal hCornerSize = 2 + hMargin + radius; - const qreal vCornerSize = 2 + vMargin + radius; - const qreal shCornerSize = hCornerSize * pixelRatio; - const qreal svCornerSize = vCornerSize * pixelRatio; - // top-left corner - p->drawPixmap(QPointF(targetRect.left(), targetRect.top()), focusRingPixmap, - QRectF(0, 0, shCornerSize, svCornerSize)); - // top-right corner - p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.top()), focusRingPixmap, - QRectF(focusRingPixmap.width() - shCornerSize, 0, shCornerSize, svCornerSize)); - // bottom-left corner - p->drawPixmap(QPointF(targetRect.left(), targetRect.bottom() - vCornerSize + 1), focusRingPixmap, - QRectF(0, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); - // bottom-right corner - p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.bottom() - vCornerSize + 1), focusRingPixmap, - QRect(focusRingPixmap.width() - shCornerSize, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); - // top edge - p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.top(), targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, - QRect(shCornerSize, 0, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); - // bottom edge - p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.bottom() - vCornerSize + 1, targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, - QRect(shCornerSize, focusRingPixmap.height() - svCornerSize, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); - // left edge - p->drawPixmap(QRectF(targetRect.left(), targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, - QRect(0, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); - // right edge - p->drawPixmap(QRectF(targetRect.right() - hCornerSize + 1, targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, - QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); -} - -#ifndef QT_NO_TABBAR -void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect) const -{ - Q_ASSERT(textRect); - QRect tr = opt->rect; - const bool verticalTabs = opt->shape == QTabBar::RoundedEast - || opt->shape == QTabBar::RoundedWest - || opt->shape == QTabBar::TriangularEast - || opt->shape == QTabBar::TriangularWest; - if (verticalTabs) - tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform - - int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); - int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); - const int hpadding = 4; - const int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; - if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) - verticalShift = -verticalShift; - tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); - - // left widget - if (!opt->leftButtonSize.isEmpty()) { - const int buttonSize = verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width(); - tr.setLeft(tr.left() + 4 + buttonSize); - // make text aligned to center - if (opt->rightButtonSize.isEmpty()) - tr.setRight(tr.right() - 4 - buttonSize); - } - // right widget - if (!opt->rightButtonSize.isEmpty()) { - const int buttonSize = verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width(); - tr.setRight(tr.right() - 4 - buttonSize); - // make text aligned to center - if (opt->leftButtonSize.isEmpty()) - tr.setLeft(tr.left() + 4 + buttonSize); - } - - if (!verticalTabs) - tr = proxyStyle->visualRect(opt->direction, opt->rect, tr); - - *textRect = tr; -} -#endif //QT_NO_TABBAR - -QAquaWidgetSize QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, - const QWidget *widg, - QStyle::ContentsType ct, - QSize szHint, QSize *insz) const -{ - QAquaWidgetSize sz = aquaSizeConstrain(option, widg, ct, szHint, insz); - if (sz == QAquaSizeUnknown) - return QAquaSizeLarge; - return sz; -} - -QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, - QStyle::ContentsType ct, QSize szHint, QSize *insz) const -{ -#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) - if (option) { - if (option->state & QStyle::State_Small) - return QAquaSizeSmall; - if (option->state & QStyle::State_Mini) - return QAquaSizeMini; - } - - if (!widg) { - if (insz) - *insz = QSize(); - if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) - return QAquaSizeSmall; - if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) - return QAquaSizeMini; - return QAquaSizeUnknown; - } - - QSize large = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeLarge), - small = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeSmall), - mini = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeMini); - bool guess_size = false; - QAquaWidgetSize ret = QAquaSizeUnknown; - QStyleHelper::WidgetSizePolicy wsp = QStyleHelper::widgetSizePolicy(widg); - if (wsp == QStyleHelper::SizeDefault) - guess_size = true; - else if (wsp == QStyleHelper::SizeMini) - ret = QAquaSizeMini; - else if (wsp == QStyleHelper::SizeSmall) - ret = QAquaSizeSmall; - else if (wsp == QStyleHelper::SizeLarge) - ret = QAquaSizeLarge; - if (guess_size) - ret = qt_aqua_guess_size(widg, large, small, mini); - - QSize *sz = 0; - if (ret == QAquaSizeSmall) - sz = &small; - else if (ret == QAquaSizeLarge) - sz = &large; - else if (ret == QAquaSizeMini) - sz = &mini; - if (insz) - *insz = sz ? *sz : QSize(-1, -1); -#ifdef DEBUG_SIZE_CONSTRAINT - if (sz) { - const char *size_desc = "Unknown"; - if (sz == &small) - size_desc = "Small"; - else if (sz == &large) - size_desc = "Large"; - else if (sz == &mini) - size_desc = "Mini"; - qDebug("%s - %s: %s taken (%d, %d) [%d, %d]", - widg ? widg->objectName().toLatin1().constData() : "*Unknown*", - widg ? widg->metaObject()->className() : "*Unknown*", size_desc, widg->width(), widg->height(), - sz->width(), sz->height()); - } -#endif - return ret; -#else - if (insz) - *insz = QSize(); - Q_UNUSED(widg); - Q_UNUSED(ct); - Q_UNUSED(szHint); - return QAquaSizeUnknown; -#endif -} - -/** - Returns the free space awailable for contents inside the - button (and not the size of the contents itself) -*/ -HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn, - const HIThemeButtonDrawInfo *bdi) const -{ - HIRect outerBounds = qt_hirectForQRect(btn->rect); - // Adjust the bounds to correct for - // carbon not calculating the content bounds fully correct - if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){ - outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; - outerBounds.size.height -= QMacStylePrivate::PushButtonBottomOffset; - } else if (bdi->kind == kThemePushButtonMini) { - outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; - } - - HIRect contentBounds; - HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds); - return contentBounds; -} - -/** - Calculates the size of the button contents. - This includes both the text and the icon. -*/ -QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const -{ - Q_Q(const QMacStyle); - QSize csz(0, 0); - QSize iconSize = btn->icon.isNull() ? QSize(0, 0) - : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0)); - QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1) - : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text); - csz.setWidth(iconSize.width() + textRect.width() - + ((btn->features & QStyleOptionButton::HasMenu) - ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0)); - csz.setHeight(qMax(iconSize.height(), textRect.height())); - return csz; -} - -/** - Checks if the actual contents of btn fits inside the free content bounds of - 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' - for determining which button kind to use for drawing. -*/ -bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn, - HIThemeButtonDrawInfo *bdi, - ThemeButtonKind buttonKindToCheck) const -{ - ThemeButtonKind tmp = bdi->kind; - bdi->kind = buttonKindToCheck; - QSize contentSize = pushButtonSizeFromContents(btn); - QRect freeContentRect = qt_qrectForHIRect(pushButtonContentBounds(btn, bdi)); - bdi->kind = tmp; - return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(), - contentSize.width(), contentSize.height())); -} - -/** - Creates a HIThemeButtonDrawInfo structure that specifies the correct button - kind and other details to use for drawing the given push button. Which - button kind depends on the size of the button, the size of the contents, - explicit user style settings, etc. -*/ -void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, - const QWidget *widget, - const ThemeDrawState tds, - HIThemeButtonDrawInfo *bdi) const -{ - ThemeDrawState tdsModified = tds; - if (btn->state & QStyle::State_On) - tdsModified = kThemeStatePressed; - bdi->version = qt_mac_hitheme_version; - bdi->state = tdsModified; - bdi->value = kThemeButtonOff; - - if (tds == kThemeStateInactive) - bdi->state = kThemeStateActive; - if (btn->state & QStyle::State_HasFocus) - bdi->adornment = kThemeAdornmentFocus; - else - bdi->adornment = kThemeAdornmentNone; - - - if (btn->features & (QStyleOptionButton::Flat)) { - bdi->kind = kThemeBevelButton; - } else { - switch (aquaSizeConstrain(btn, widget)) { - case QAquaSizeSmall: - bdi->kind = kThemePushButtonSmall; - break; - case QAquaSizeMini: - bdi->kind = kThemePushButtonMini; - break; - case QAquaSizeLarge: - // ... We should honor if the user is explicit about using the - // large button. But right now Qt will specify the large button - // as default rather than QAquaSizeUnknown. - // So we treat it like QAquaSizeUnknown - // to get the dynamic choosing of button kind. - case QAquaSizeUnknown: - // Choose the button kind that closest match the button rect, but at the - // same time displays the button contents without clipping. - bdi->kind = kThemeBevelButton; - if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){ - if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { - if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){ - if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) - bdi->kind = kThemePushButtonMini; - } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){ - if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) - bdi->kind = kThemePushButtonSmall; - } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { - bdi->kind = kThemePushButton; - } - } else { - bdi->kind = kThemePushButton; - } - } - } - } -} - -#if QT_CONFIG(pushbutton) -bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option) -{ - QMacStyle *macStyle = qobject_cast(pushButton->style()); - if (!macStyle) - return false; - HIThemeButtonDrawInfo bdi; - macStyle->d_func()->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); - return bdi.kind == kThemeBevelButton; -} -#endif - -/** - Creates a HIThemeButtonDrawInfo structure that specifies the correct button - kind and other details to use for drawing the given combobox. Which button - kind depends on the size of the combo, wether or not it is editable, - explicit user style settings, etc. -*/ -void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, - const QWidget *widget, const ThemeDrawState &tds) const -{ - bdi->version = qt_mac_hitheme_version; - bdi->adornment = kThemeAdornmentArrowLeftArrow; - bdi->value = kThemeButtonOff; - if (combo->state & QStyle::State_HasFocus) - bdi->adornment = kThemeAdornmentFocus; - if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) - bdi->state = kThemeStatePressed; - else - bdi->state = tds; - - QAquaWidgetSize aSize = aquaSizeConstrain(combo, widget); - switch (aSize) { - case QAquaSizeMini: - bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) - : ThemeButtonKind(kThemePopupButtonMini); - break; - case QAquaSizeSmall: - bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall) - : ThemeButtonKind(kThemePopupButtonSmall); - break; - case QAquaSizeUnknown: - case QAquaSizeLarge: - // Unless the user explicitly specified large buttons, determine the - // kind by looking at the combox size. - // ... specifying small and mini-buttons it not a current feature of - // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add - // an extra check here before using the mini and small buttons. - int h = combo->rect.size().height(); - if (combo->editable){ -#ifndef QT_NO_DATETIMEEDIT - if (qobject_cast(widget)) { - // Except when, you know, we get a QDateTimeEdit with calendarPopup - // enabled. And then things get weird, basically because it's a - // transvestite spinbox with editable combobox tendencies. Meaning - // that it wants to look a combobox, except that it isn't one, so it - // doesn't get all those extra free margins around. (Don't know whose - // idea those margins were, but now it looks like we're stuck with - // them forever). So anyway, the height threshold should be smaller - // in this case, or the style gets confused when it needs to render - // or return any subcontrol size of the poor thing. - if (h < 9) - bdi->kind = kThemeComboBoxMini; - else if (h < 22) - bdi->kind = kThemeComboBoxSmall; - else - bdi->kind = kThemeComboBox; - } else -#endif - { - if (h < 21) - bdi->kind = kThemeComboBoxMini; - else if (h < 26) - bdi->kind = kThemeComboBoxSmall; - else - bdi->kind = kThemeComboBox; - } - } else { - // Even if we specify that we want the kThemePopupButton, Carbon - // will use the kThemePopupButtonSmall if the size matches. So we - // do the same size check explicit to have the size of the inner - // text field be correct. Therefore, do this even if the user specifies - // the use of LargeButtons explicit. - if (h < 21) - bdi->kind = kThemePopupButtonMini; - else if (h < 26) - bdi->kind = kThemePopupButtonSmall; - else - bdi->kind = kThemePopupButton; - } - break; - } -} - -/** - Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain - the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. -*/ -HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int buttonKind) -{ - HIRect innerBounds = outerBounds; - // Carbon draw parts of the view outside the rect. - // So make the rect a bit smaller to compensate - // (I wish HIThemeGetButtonBackgroundBounds worked) - switch (buttonKind){ - case kThemePopupButton: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - break; - case kThemePopupButtonSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 6; - innerBounds.size.height -= 7; - break; - case kThemePopupButtonMini: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - break; - case kThemeComboBox: - innerBounds.origin.x += 3; - innerBounds.origin.y += 2; - innerBounds.size.width -= 6; - innerBounds.size.height -= 8; - break; - case kThemeComboBoxSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 7; - innerBounds.size.height -= 8; - break; - case kThemeComboBoxMini: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 4; - innerBounds.size.height -= 8; - break; - default: - break; - } - return innerBounds; -} - -/** - Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind - of combobox we choose to draw. This function calculates and returns this size. -*/ -QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi) -{ - QRect ret = outerBounds; - switch (bdi.kind){ - case kThemeComboBox: - ret.adjust(5, 5, -22, -5); - break; - case kThemeComboBoxSmall: - ret.adjust(4, 5, -18, 0); - ret.setHeight(16); - break; - case kThemeComboBoxMini: - ret.adjust(4, 5, -16, 0); - ret.setHeight(13); - break; - case kThemePopupButton: - ret.adjust(10, 2, -23, -4); - break; - case kThemePopupButtonSmall: - ret.adjust(9, 3, -20, -3); - break; - case kThemePopupButtonMini: - ret.adjust(8, 3, -19, 0); - ret.setHeight(13); - break; - } - return ret; -} - -/** - Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version, - create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop - it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. -*/ -void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p) -{ - if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ - // We have an unscaled combobox, or popup-button; use Carbon directly. - HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind); - HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0); - } else { - QPixmap buffer; - QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment)); - if (!QPixmapCache::find(key, buffer)) { - HIRect innerBoundsSmallCombo = {{3, 3}, {29, 25}}; - buffer = QPixmap(35, 28); - buffer.fill(Qt::transparent); - QPainter buffPainter(&buffer); - HIThemeDrawButton(&innerBoundsSmallCombo, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); - buffPainter.end(); - QPixmapCache::insert(key, buffer); - } - - const int bwidth = 20; - const int fwidth = 10; - const int fheight = 10; - int w = qRound(outerBounds.size.width); - int h = qRound(outerBounds.size.height); - int bstart = w - bwidth; - int blower = fheight + 1; - int flower = h - fheight; - int sheight = flower - fheight; - int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2; - - // Draw upper and lower gap - p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight); - p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight); - // Draw left and right gap. Right gap is drawn top and bottom separatly - p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1); - p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1); - p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1); - // Draw arrow - p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6); - // Draw corners - p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight); - p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight); - p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight); - p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower); - } -} - -/** - Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header - onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget. -*/ -void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds, - bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p) -{ - static SInt32 headerHeight = 0; - static OSStatus err = GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight); - Q_UNUSED(err); - - QPixmap buffer; - QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value)); - if (!QPixmapCache::find(key, buffer)) { - HIRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}}; - buffer = QPixmap(headerNormalRect.size.width, headerNormalRect.size.height); - buffer.fill(Qt::transparent); - QPainter buffPainter(&buffer); - HIThemeDrawButton(&headerNormalRect, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); - buffPainter.end(); - QPixmapCache::insert(key, buffer); - } - const int buttonw = qRound(outerBounds.size.width); - const int buttonh = qRound(outerBounds.size.height); - const int framew = 1; - const int frameh_n = 4; - const int frameh_s = 3; - const int transh = buffer.height() - frameh_n - frameh_s; - int center = buttonh - frameh_s - int(transh / 2.0f) + 1; // Align bottom; - - int skipTopBorder = 0; - if (!drawTopBorder) - skipTopBorder = 1; - - p->translate(outerBounds.origin.x, outerBounds.origin.y); - - p->drawPixmap(QRect(QRect(0, -skipTopBorder, buttonw - framew , frameh_n)), buffer, QRect(framew, 0, 1, frameh_n)); - p->drawPixmap(QRect(0, buttonh - frameh_s, buttonw - framew, frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, frameh_s)); - // Draw upper and lower center blocks - p->drawPixmap(QRect(0, frameh_n - skipTopBorder, buttonw - framew, center - frameh_n + skipTopBorder), buffer, QRect(framew, frameh_n, 1, 1)); - p->drawPixmap(QRect(0, center, buttonw - framew, buttonh - center - frameh_s), buffer, QRect(framew, buffer.height() - frameh_s, 1, 1)); - // Draw right center block borders - p->drawPixmap(QRect(buttonw - framew, frameh_n - skipTopBorder, framew, center - frameh_n), buffer, QRect(buffer.width() - framew, frameh_n, framew, 1)); - p->drawPixmap(QRect(buttonw - framew, center, framew, buttonh - center - 1), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, 1)); - // Draw right corners - p->drawPixmap(QRect(buttonw - framew, -skipTopBorder, framew, frameh_n), buffer, QRect(buffer.width() - framew, 0, framew, frameh_n)); - p->drawPixmap(QRect(buttonw - framew, buttonh - frameh_s, framew, frameh_s), buffer, QRect(buffer.width() - framew, buffer.height() - frameh_s, framew, frameh_s)); - // Draw center transition block - p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), buttonw - framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(framew, frameh_n + 1, 1, transh)); - // Draw right center transition block border - p->drawPixmap(QRect(buttonw - framew, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(buffer.width() - framew, frameh_n + 1, framew, transh)); - if (drawLeftBorder){ - // Draw left center block borders - p->drawPixmap(QRect(0, frameh_n - skipTopBorder, framew, center - frameh_n + skipTopBorder), buffer, QRect(0, frameh_n, framew, 1)); - p->drawPixmap(QRect(0, center, framew, buttonh - center - 1), buffer, QRect(0, buffer.height() - frameh_s, framew, 1)); - // Draw left corners - p->drawPixmap(QRect(0, -skipTopBorder, framew, frameh_n), buffer, QRect(0, 0, framew, frameh_n)); - p->drawPixmap(QRect(0, buttonh - frameh_s, framew, frameh_s), buffer, QRect(0, buffer.height() - frameh_s, framew, frameh_s)); - // Draw left center transition block border - p->drawPixmap(QRect(0, center - qRound(transh / 2.0f), framew, buffer.height() - frameh_n - frameh_s), buffer, QRect(0, frameh_n + 1, framew, transh)); - } - - p->translate(-outerBounds.origin.x, -outerBounds.origin.y); -} - -/* - Returns cutoff sizes for scroll bars. - thumbIndicatorCutoff is the smallest size where the thumb indicator is drawn. - scrollButtonsCutoff is the smallest size where the up/down buttons is drawn. -*/ -enum ScrollBarCutoffType { thumbIndicatorCutoff = 0, scrollButtonsCutoff = 1 }; -static int scrollButtonsCutoffSize(ScrollBarCutoffType cutoffType, QStyleHelper::WidgetSizePolicy widgetSize) -{ - // Mini scroll bars do not exist as of version 10.4. - if (widgetSize == QStyleHelper::SizeMini) - return 0; - - const int sizeIndex = (widgetSize == QStyleHelper::SizeSmall) ? 1 : 0; - static const int sizeTable[2][2] = { { 61, 56 }, { 49, 44 } }; - return sizeTable[sizeIndex][cutoffType]; -} - -void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, - HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const -{ - memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another... - tdi->version = qt_mac_hitheme_version; - tdi->reserved = 0; - tdi->filler1 = 0; - bool isScrollbar = (cc == QStyle::CC_ScrollBar); - switch (aquaSizeConstrain(slider, needToRemoveMe)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - if (isScrollbar) - tdi->kind = kThemeMediumScrollBar; - else - tdi->kind = kThemeMediumSlider; - break; - case QAquaSizeMini: - if (isScrollbar) - tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented - else - tdi->kind = kThemeMiniSlider; - break; - case QAquaSizeSmall: - if (isScrollbar) - tdi->kind = kThemeSmallScrollBar; - else - tdi->kind = kThemeSmallSlider; - break; - } - - bool usePlainKnob = slider->tickPosition == QSlider::NoTicks - || slider->tickPosition == QSlider::TicksBothSides; - - tdi->bounds = qt_hirectForQRect(slider->rect); - if (isScrollbar) { - tdi->min = slider->minimum; - tdi->max = slider->maximum; - tdi->value = slider->sliderPosition; - } else { - // Fix min and max positions. HITheme seems confused when it comes to rendering - // a slider at those positions. We give it a hand by extending and offsetting - // the slider range accordingly. See also comment for CC_Slider in drawComplexControl() - tdi->min = 0; - if (slider->orientation == Qt::Horizontal) - tdi->max = 10 * slider->rect.width(); - else - tdi->max = 10 * slider->rect.height(); - - int range = slider->maximum - slider->minimum; - if (range == 0) { - tdi->value = 0; - } else if (usePlainKnob || slider->orientation == Qt::Horizontal) { - int endsCorrection = usePlainKnob ? 25 : 10; - tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum) / range - endsCorrection; - } else { - tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum) / range - 20; - } - } - tdi->attributes = kThemeTrackShowThumb; - if (slider->upsideDown) - tdi->attributes |= kThemeTrackRightToLeft; - if (slider->orientation == Qt::Horizontal) { - tdi->attributes |= kThemeTrackHorizontal; - if (isScrollbar && slider->direction == Qt::RightToLeft) { - if (!slider->upsideDown) - tdi->attributes |= kThemeTrackRightToLeft; - else - tdi->attributes &= ~kThemeTrackRightToLeft; - } - } - - // Tiger broke reverse scroll bars so put them back and "fake it" - if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) { - tdi->attributes &= ~kThemeTrackRightToLeft; - tdi->value = tdi->max - tdi->value; - } - - tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive - : kThemeTrackDisabled; - if (!isScrollbar) { - if (slider->state & QStyle::QStyle::State_HasFocus) - tdi->attributes |= kThemeTrackHasFocus; - if (usePlainKnob) - tdi->trackInfo.slider.thumbDir = kThemeThumbPlain; - else if (slider->tickPosition == QSlider::TicksAbove) - tdi->trackInfo.slider.thumbDir = kThemeThumbUpward; - else - tdi->trackInfo.slider.thumbDir = kThemeThumbDownward; - } else { - tdi->trackInfo.scrollbar.viewsize = slider->pageStep; - } -} - -void QMacStylePrivate::setAutoDefaultButton(QObject *button) const -{ - if (autoDefaultButton != button) { - if (QStyleAnimation *anim = animation(autoDefaultButton)) { - anim->updateTarget(); - stopAnimation(autoDefaultButton); - } - autoDefaultButton = button; - } - if (autoDefaultButton && !animation(autoDefaultButton)) - startAnimation(new QStyleAnimation(autoDefaultButton)); -} - -QMacStylePrivate::QMacStylePrivate() - : mouseDown(false), backingStoreNSView(nil) -{ - defaultButtonStart = CFAbsoluteTimeGetCurrent(); - memset(&buttonState, 0, sizeof(ButtonState)); - - if (ptrHIShapeGetBounds == 0) { - QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon")); - library.setLoadHints(QLibrary::ExportExternalSymbolsHint); - ptrHIShapeGetBounds = reinterpret_cast(library.resolve("HIShapeGetBounds")); - } - -} - -QMacStylePrivate::~QMacStylePrivate() -{ - QMacAutoReleasePool pool; - Q_FOREACH (NSView *b, cocoaControls) - [b release]; -} - -ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) -{ - ThemeDrawState tds = kThemeStateActive; - if (flags & QStyle::State_Sunken) { - tds = kThemeStatePressed; - } else if (flags & QStyle::State_Active) { - if (!(flags & QStyle::State_Enabled)) - tds = kThemeStateUnavailable; - } else { - if (flags & QStyle::State_Enabled) - tds = kThemeStateInactive; - else - tds = kThemeStateUnavailableInactive; - } - return tds; -} - -static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind) -{ - QCocoaWidget w; - - switch (kind) { - case kThemePopupButton: - case kThemePopupButtonSmall: - case kThemePopupButtonMini: - w.first = QCocoaPopupButton; - break; - case kThemeComboBox: - w.first = QCocoaComboBox; - break; - case kThemeArrowButton: - w.first = QCocoaArrowButton; - break; - case kThemeCheckBox: - case kThemeCheckBoxSmall: - case kThemeCheckBoxMini: - w.first = QCocoaCheckBox; - break; - case kThemeRadioButton: - case kThemeRadioButtonSmall: - case kThemeRadioButtonMini: - w.first = QCocoaRadioButton; - break; - case kThemePushButton: - case kThemePushButtonSmall: - case kThemePushButtonMini: - w.first = QCocoaPushButton; - break; - default: - break; - } - - switch (kind) { - case kThemePushButtonSmall: - case kThemePopupButtonSmall: - case kThemeCheckBoxSmall: - case kThemeRadioButtonSmall: - w.second = QAquaSizeSmall; - break; - case kThemePushButtonMini: - case kThemePopupButtonMini: - case kThemeCheckBoxMini: - case kThemeRadioButtonMini: - w.second = QAquaSizeMini; - break; - default: - w.second = QAquaSizeLarge; - break; - } - - return w; -} - -NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const -{ - NSView *bv = cocoaControls[widget]; - if (!bv) { - - if (widget.first == QCocoaPopupButton - || widget.first == QCocoaPullDownButton) - bv = [[NSPopUpButton alloc] init]; - else if (widget.first == QCocoaComboBox) - bv = [[NSComboBox alloc] init]; - else if (widget.first == QCocoaHorizontalSlider) - bv = [[NSSlider alloc] init]; - else if (widget.first == QCocoaVerticalSlider) - // Cocoa sets the orientation from the view's frame - // at construction time, and it cannot be changed later. - bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 10, 100)]; - else - bv = [[NSButton alloc] init]; - - switch (widget.first) { - case QCocoaArrowButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSOnOffButton; - bc.bezelStyle = NSDisclosureBezelStyle; - break; - } - case QCocoaCheckBox: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSSwitchButton; - break; - } - case QCocoaRadioButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSRadioButton; - break; - } - case QCocoaPushButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSMomentaryLightButton; - bc.bezelStyle = NSRoundedBezelStyle; - break; - } - case QCocoaPullDownButton: { - NSPopUpButton *bc = (NSPopUpButton *)bv; - bc.pullsDown = YES; - break; - } - default: - break; - } - - if ([bv isKindOfClass:[NSButton class]]) { - NSButton *bc = (NSButton *)bv; - bc.title = @""; - } - - if ([bv isKindOfClass:[NSControl class]]) { - NSCell *bcell = [(NSControl *)bv cell]; - switch (widget.second) { - case QAquaSizeSmall: - bcell.controlSize = NSSmallControlSize; - break; - case QAquaSizeMini: - bcell.controlSize = NSMiniControlSize; - break; - default: - break; - } - } - - const_cast(this)->cocoaControls.insert(widget, bv); - } - - return bv; -} - -void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, QCocoaDrawRectBlock drawRectBlock) const -{ - QPoint offset; - if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeLarge)) - offset.setY(2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeSmall)) - offset = QPoint(-1, 2); - else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeMini)) - offset.setY(2); - else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeSmall) - || widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeLarge)) - offset.setY(1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeSmall)) - offset.setX(-1); - else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeMini)) - offset = QPoint(7, 5); - else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini)) - offset = QPoint(2, -1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge)) - offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall)) - offset = QPoint(2, 1); - else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini)) - offset = QPoint(5, 0); - else if (widget == QCocoaWidget(QCocoaComboBox, QAquaSizeLarge)) - offset = QPoint(3, 0); - - QMacCGContext ctx(p); - CGContextSaveGState(ctx); - CGContextTranslateCTM(ctx, offset.x(), offset.y()); - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:ctx flipped:YES]]; - - NSRect rect = NSMakeRect(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); - - [backingStoreNSView addSubview:view]; - view.frame = rect; - if (drawRectBlock) - drawRectBlock(rect, (CGContextRef)ctx); - else - [view drawRect:rect]; - [view removeFromSuperviewWithoutNeedingDisplay]; - - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(ctx); -} - -void QMacStylePrivate::resolveCurrentNSView(QWindow *window) -{ - backingStoreNSView = window ? (NSView *)window->winId() : nil; -} - -void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, - QPainter *p, const QStyleOption *opt) const -{ - int xoff = 0, - yoff = 0, - extraWidth = 0, - extraHeight = 0, - finalyoff = 0; - - const bool combo = opt->type == QStyleOption::SO_ComboBox; - const bool editableCombo = bdi->kind == kThemeComboBox - || bdi->kind == kThemeComboBoxSmall - || bdi->kind == kThemeComboBoxMini; - const bool button = opt->type == QStyleOption::SO_Button; - const bool viewItem = opt->type == QStyleOption::SO_ViewItem; - const bool pressed = bdi->state == kThemeStatePressed; - - if (button && pressed) { - if (bdi->kind == kThemePushButton) { - extraHeight = 2; - } else if (bdi->kind == kThemePushButtonSmall) { - xoff = 1; - extraWidth = 2; - extraHeight = 5; - } - } - - int devicePixelRatio = p->device()->devicePixelRatioF(); - int width = devicePixelRatio * (int(macRect.size.width) + extraWidth); - int height = devicePixelRatio * (int(macRect.size.height) + extraHeight); - - if (width <= 0 || height <= 0) - return; // nothing to draw - - QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_') - + QString::number(bdi->value) + QLatin1Char('_') - + (button ? QString::number(bdi->state) + QLatin1Char('_') : QString()) - + QLatin1Char('_') + QString::number(width) + QLatin1Char('_') + QString::number(height); - QPixmap pm; - if (!QPixmapCache::find(key, pm)) { - QPixmap activePixmap(width, height); - activePixmap.setDevicePixelRatio(devicePixelRatio); - activePixmap.fill(Qt::transparent); - { - if (combo){ - // Carbon combos don't scale. Therefore we draw it - // ourselves, if a scaled version is needed. - QPainter tmpPainter(&activePixmap); - QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter); - } else { - QMacCGContext cg(&activePixmap); - HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); - if (button && pressed) - bdi->state = kThemeStateActive; - else if (viewItem) - bdi->state = kThemeStateInactive; - HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); - } - } - - if (!combo && !button && bdi->value == kThemeButtonOff) { - pm = activePixmap; - } else if ((combo && !editableCombo) || button) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi->kind); - NSButton *bc = (NSButton *)cocoaControl(cw); - [bc highlight:pressed]; - bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; - bc.allowsMixedState = YES; - bc.state = bdi->value == kThemeButtonOn ? NSOnState : - bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState; - // The view frame may differ from what we pass to HITheme - QRect rect = opt->rect; - if (bdi->kind == kThemePopupButtonMini) - rect.adjust(0, 0, -5, 0); - drawNSViewInRect(cw, bc, rect, p); - return; - } else if (editableCombo || viewItem) { - QImage image = activePixmap.toImage(); - - for (int y = 0; y < height; ++y) { - QRgb *scanLine = reinterpret_cast(image.scanLine(y)); - - for (int x = 0; x < width; ++x) { - QRgb &pixel = scanLine[x]; - int gray = qRed(pixel); // We know the image is grayscale - int alpha = qAlpha(pixel); - - if (gray == 128 && alpha == 128) { - pixel = qRgba(255, 255, 255, 255); - } else if (alpha == 0) { - pixel = 0; - } else { - bool belowThreshold = (alpha * gray) / 255 + 255 - alpha < 128; - gray = belowThreshold ? 0 : 2 * gray - 255; - alpha = belowThreshold ? 0 : 2 * alpha - 255; - pixel = qRgba(gray, gray, gray, alpha); - } - } - } - pm = QPixmap::fromImage(image); - } else { - QImage activeImage = activePixmap.toImage(); - QImage colorlessImage; - { - QPixmap colorlessPixmap(width, height); - colorlessPixmap.setDevicePixelRatio(devicePixelRatio); - colorlessPixmap.fill(Qt::transparent); - - QMacCGContext cg(&colorlessPixmap); - HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); - int oldValue = bdi->value; - bdi->value = kThemeButtonOff; - HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); - bdi->value = oldValue; - colorlessImage = colorlessPixmap.toImage(); - } - - for (int y = 0; y < height; ++y) { - QRgb *colorlessScanLine = reinterpret_cast(colorlessImage.scanLine(y)); - const QRgb *activeScanLine = reinterpret_cast(activeImage.scanLine(y)); - - for (int x = 0; x < width; ++x) { - QRgb &colorlessPixel = colorlessScanLine[x]; - QRgb activePixel = activeScanLine[x]; - - if (activePixel != colorlessPixel) { - int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)), - qBlue(activePixel)); - QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel)); - if (qGray(newPixel) < qGray(colorlessPixel) - || qAlpha(newPixel) > qAlpha(colorlessPixel)) - colorlessPixel = newPixel; - } - } - } - pm = QPixmap::fromImage(colorlessImage); - } - QPixmapCache::insert(key, pm); - } - p->drawPixmap(int(macRect.origin.x) - xoff, int(macRect.origin.y) + finalyoff, width / devicePixelRatio, height / devicePixelRatio , pm); -} - -QMacStyle::QMacStyle() - : QCommonStyle(*new QMacStylePrivate) -{ - Q_D(QMacStyle); - QMacAutoReleasePool pool; - - d->receiver = [[NotificationReceiver alloc] initWithPrivate:d]; - NotificationReceiver *receiver = static_cast(d->receiver); - - [[NSNotificationCenter defaultCenter] addObserver:receiver - selector:@selector(scrollBarStyleDidChange:) - name:NSPreferredScrollerStyleDidChangeNotification - object:nil]; - - d->nsscroller = [[NSScroller alloc] init]; - d->indicatorBranchButtonCell = nil; -} - -QMacStyle::~QMacStyle() -{ - Q_D(QMacStyle); - QMacAutoReleasePool pool; - - [reinterpret_cast(d->nsscroller) release]; - - NotificationReceiver *receiver = static_cast(d->receiver); - [[NSNotificationCenter defaultCenter] removeObserver:receiver]; - [receiver release]; - - delete qt_mac_backgroundPattern; - qt_mac_backgroundPattern = 0; -} - -/*! \internal - Generates the standard widget background pattern. -*/ -QPixmap QMacStylePrivate::generateBackgroundPattern() const -{ - QMacAutoReleasePool pool; - QPixmap px(4, 4); - QMacCGContext cg(&px); - HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); - const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); - CGContextFillRect(cg, cgRect); - return px; -} - -/*! \internal - Fills the given \a rect with the pattern stored in \a brush. As an optimization, - HIThemeSetFill us used directly if we are filling with the standard background. -*/ -void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) -{ -#if 0 - QPoint dummy; - const QPaintDevice *target = painter->device(); - const QPaintDevice *redirected = QPainter::redirected(target, &dummy); - //const bool usePainter = redirected && redirected != target; - - if (!usePainter && qt_mac_backgroundPattern - && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { - - painter->setClipRegion(rgn); - - QMacCGContext cg(target); - CGContextSaveGState(cg); - HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); - - for (const QRect &rect : rgn) { - // Anchor the pattern to the top so it stays put when the window is resized. - CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height())); - CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - CGContextFillRect(cg, mac_rect); - } - - CGContextRestoreGState(cg); - } else { -#endif - const QRect rect(rgn.boundingRect()); - painter->setClipRegion(rgn); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); -// } -} - -void QMacStyle::polish(QPalette &pal) -{ - Q_D(QMacStyle); - if (!qt_mac_backgroundPattern) { - if (!qApp) - return; - qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); - } - - - QCFString theme; - const OSErr err = CopyThemeIdentifier(&theme); - if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) { - pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240)); - } else { - pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254)); - } -} - -void QMacStyle::polish(QApplication *) -{ -} - -void QMacStyle::unpolish(QApplication *) -{ -} - -void QMacStyle::polish(QWidget* w) -{ - if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) { - // Set a clear brush so that the metal shines through. - QPalette pal = w->palette(); - QBrush background(Qt::transparent); - pal.setBrush(QPalette::All, QPalette::Window, background); - pal.setBrush(QPalette::All, QPalette::Button, background); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); - } - -#ifndef QT_NO_MENU - if (qobject_cast(w) -#ifndef QT_NO_COMBOBOX - || qobject_cast(w) -#endif - ) { - w->setWindowOpacity(0.985); - if (!w->testAttribute(Qt::WA_SetPalette)) { - QPixmap px(64, 64); - px.fill(Qt::white); - HIThemeMenuDrawInfo mtinfo; - mtinfo.version = qt_mac_hitheme_version; - mtinfo.menuType = kThemeMenuTypePopUp; - // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); - // ### - //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), - // kHIThemeOrientationNormal); - QPalette pal = w->palette(); - QBrush background(px); - pal.setBrush(QPalette::All, QPalette::Window, background); - pal.setBrush(QPalette::All, QPalette::Button, background); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); - } - } -#endif - -#ifndef QT_NO_TABBAR - if (QTabBar *tb = qobject_cast(w)) { - if (tb->documentMode()) { - w->setAttribute(Qt::WA_Hover); - w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont())); - QPalette p = w->palette(); - p.setColor(QPalette::WindowText, QColor(17, 17, 17)); - w->setPalette(p); - } - } -#endif - - QCommonStyle::polish(w); - - if (QRubberBand *rubber = qobject_cast(w)) { - rubber->setWindowOpacity(0.25); - rubber->setAttribute(Qt::WA_PaintOnScreen, false); - rubber->setAttribute(Qt::WA_NoSystemBackground, false); - } - - if (qobject_cast(w)) { - w->setAttribute(Qt::WA_OpaquePaintEvent, false); - w->setAttribute(Qt::WA_Hover, true); - w->setMouseTracking(true); - } -} - -void QMacStyle::unpolish(QWidget* w) -{ - if (( -#ifndef QT_NO_MENU - qobject_cast(w) || -#endif - qt_mac_is_metal(w) - ) && !w->testAttribute(Qt::WA_SetPalette)) { - QPalette pal = qApp->palette(w); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); - w->setWindowOpacity(1.0); - } - -#ifndef QT_NO_COMBOBOX - if (QComboBox *combo = qobject_cast(w)) { - if (!combo->isEditable()) { - if (QWidget *widget = combo->findChild()) - widget->setWindowOpacity(1.0); - } - } -#endif - - if (QRubberBand *rubber = qobject_cast(w)) { - rubber->setWindowOpacity(1.0); - rubber->setAttribute(Qt::WA_PaintOnScreen, true); - rubber->setAttribute(Qt::WA_NoSystemBackground, true); - } - - if (QFocusFrame *frame = qobject_cast(w)) - frame->setAttribute(Qt::WA_NoSystemBackground, true); - - QCommonStyle::unpolish(w); - - if (qobject_cast(w)) { - w->setAttribute(Qt::WA_OpaquePaintEvent, true); - w->setAttribute(Qt::WA_Hover, false); - w->setMouseTracking(false); - } -} - -int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const -{ - Q_D(const QMacStyle); - int controlSize = getControlSize(opt, widget); - SInt32 ret = 0; - - switch (metric) { - case PM_TabCloseIndicatorWidth: - case PM_TabCloseIndicatorHeight: - ret = closeButtonSize; - break; - case PM_ToolBarIconSize: - ret = proxy()->pixelMetric(PM_LargeIconSize); - break; - case PM_FocusFrameVMargin: - case PM_FocusFrameHMargin: - GetThemeMetric(kThemeMetricFocusRectOutset, &ret); - break; - case PM_DialogButtonsSeparator: - ret = -5; - break; - case PM_DialogButtonsButtonHeight: { - QSize sz; - ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); - if (sz == QSize(-1, -1)) - ret = 32; - else - ret = sz.height(); - break; } - case PM_DialogButtonsButtonWidth: { - QSize sz; - ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); - if (sz == QSize(-1, -1)) - ret = 70; - else - ret = sz.width(); - break; } - - case PM_MenuBarHMargin: - ret = 8; - break; - - case PM_MenuBarVMargin: - ret = 0; - break; - - case PM_MenuBarPanelWidth: - ret = 0; - break; - - case QStyle::PM_MenuDesktopFrameWidth: - ret = 5; - break; - - case PM_CheckBoxLabelSpacing: - case PM_RadioButtonLabelSpacing: - ret = 2; - break; - case PM_MenuScrollerHeight: -#if 0 - SInt16 ash, asw; - GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw); - ret = ash; -#else - ret = 15; // I hate having magic numbers in here... -#endif - break; - case PM_DefaultFrameWidth: -#ifndef QT_NO_MAINWINDOW - if (widget && (widget->isWindow() || !widget->parentWidget() - || (qobject_cast(widget->parentWidget()) - && static_cast(widget->parentWidget())->centralWidget() == widget)) - && qobject_cast(widget)) - ret = 0; - else -#endif - // The combo box popup has no frame. - if (qstyleoption_cast(opt) != 0) - ret = 0; - else - ret = 1; - break; - case PM_MaximumDragDistance: - ret = -1; - break; - case PM_ScrollBarSliderMin: - ret = 24; - break; - case PM_SpinBoxFrameWidth: - GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret); - switch (d->aquaSizeConstrain(opt, widget)) { - default: - ret += 2; - break; - case QAquaSizeMini: - ret += 1; - break; - } - break; - case PM_ButtonShiftHorizontal: - case PM_ButtonShiftVertical: - ret = 0; - break; - case PM_SliderLength: - ret = 17; - break; - // Returns the number of pixels to use for the business part of the - // slider (i.e., the non-tickmark portion). The remaining space is shared - // equally between the tickmark regions. - case PM_SliderControlThickness: - if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { - int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); - int ticks = sl->tickPosition; - int n = 0; - if (ticks & QSlider::TicksAbove) - ++n; - if (ticks & QSlider::TicksBelow) - ++n; - if (!n) { - ret = space; - break; - } - - int thick = 6; // Magic constant to get 5 + 16 + 5 - if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) - thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; - - space -= thick; - if (space > 0) - thick += (space * 2) / (n + 2); - ret = thick; - } else { - ret = 0; - } - break; - case PM_SmallIconSize: - ret = int(QStyleHelper::dpiScaled(16.)); - break; - - case PM_LargeIconSize: - ret = int(QStyleHelper::dpiScaled(32.)); - break; - - case PM_IconViewIconSize: - ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); - break; - - case PM_ButtonDefaultIndicator: - ret = 0; - break; - case PM_TitleBarHeight: - // Always use NSTitledWindowMask since we never need any other type of window here - ret = int([NSWindow frameRectForContentRect:NSZeroRect - styleMask:NSTitledWindowMask].size.height); - break; - case QStyle::PM_TabBarTabHSpace: - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeLarge: - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - case QAquaSizeSmall: - ret = 20; - break; - case QAquaSizeMini: - ret = 16; - break; - case QAquaSizeUnknown: - const QStyleOptionTab *tb = qstyleoption_cast(opt); - if (tb && tb->documentMode) - ret = 30; - else - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - } - break; - case PM_TabBarTabVSpace: - ret = 4; - break; - case PM_TabBarTabShiftHorizontal: - case PM_TabBarTabShiftVertical: - ret = 0; - break; - case PM_TabBarBaseHeight: - ret = 21; - break; - case PM_TabBarTabOverlap: - ret = 1; - break; - case PM_TabBarBaseOverlap: - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - ret = 11; - break; - case QAquaSizeSmall: - ret = 8; - break; - case QAquaSizeMini: - ret = 7; - break; - } - break; - case PM_ScrollBarExtent: { - const QAquaWidgetSize size = d->effectiveAquaSizeConstrain(opt, widget); - ret = static_cast([NSScroller - scrollerWidthForControlSize:static_cast(size) - scrollerStyle:[NSScroller preferredScrollerStyle]]); - break; } - case PM_IndicatorHeight: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - GetThemeMetric(kThemeMetricCheckBoxHeight, &ret); - break; - case QAquaSizeMini: - GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret); - break; - case QAquaSizeSmall: - GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret); - break; - } - break; } - case PM_IndicatorWidth: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - GetThemeMetric(kThemeMetricCheckBoxWidth, &ret); - break; - case QAquaSizeMini: - GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret); - break; - case QAquaSizeSmall: - GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret); - break; - } - ++ret; - break; } - case PM_ExclusiveIndicatorHeight: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - GetThemeMetric(kThemeMetricRadioButtonHeight, &ret); - break; - case QAquaSizeMini: - GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret); - break; - case QAquaSizeSmall: - GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret); - break; - } - break; } - case PM_ExclusiveIndicatorWidth: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - GetThemeMetric(kThemeMetricRadioButtonWidth, &ret); - break; - case QAquaSizeMini: - GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret); - break; - case QAquaSizeSmall: - GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret); - break; - } - ++ret; - break; } - case PM_MenuVMargin: - ret = 4; - break; - case PM_MenuPanelWidth: - ret = 0; - break; - case PM_ToolTipLabelFrameWidth: - ret = 0; - break; - case PM_SizeGripSize: { - QAquaWidgetSize aSize; - if (widget && widget->window()->windowType() == Qt::Tool) - aSize = QAquaSizeSmall; - else - aSize = QAquaSizeLarge; - const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize); - ret = size.width(); - break; } - case PM_MdiSubWindowFrameWidth: - ret = 1; - break; - case PM_DockWidgetFrameWidth: - ret = 0; - break; - case PM_DockWidgetTitleMargin: - ret = 0; - break; - case PM_DockWidgetSeparatorExtent: - ret = 1; - break; - case PM_ToolBarHandleExtent: - ret = 11; - break; - case PM_ToolBarItemMargin: - ret = 0; - break; - case PM_ToolBarItemSpacing: - ret = 4; - break; - case PM_SplitterWidth: - ret = qMax(7, QApplication::globalStrut().width()); - break; - case PM_LayoutLeftMargin: - case PM_LayoutTopMargin: - case PM_LayoutRightMargin: - case PM_LayoutBottomMargin: - { - bool isWindow = false; - if (opt) { - isWindow = (opt->state & State_Window); - } else if (widget) { - isWindow = widget->isWindow(); - } - - if (isWindow) { - bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal); - if (isMetal) { - if (metric == PM_LayoutTopMargin) { - return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */); - } else if (metric == PM_LayoutBottomMargin) { - return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */); - } else { - return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */); - } - } else { - /* - AHIG would have (20, 8, 10) here but that makes - no sense. It would also have 14 for the top margin - but this contradicts both Builder and most - applications. - */ - return_SIZE(20, 10, 10); // AHIG - } - } else { - // hack to detect QTabWidget - if (widget && widget->parentWidget() - && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) { - if (metric == PM_LayoutTopMargin) { - /* - Builder would have 14 (= 20 - 6) instead of 12, - but that makes the tab look disproportionate. - */ - return_SIZE(12, 6, 6); // guess - } else { - return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */); - } - } else { - /* - Child margins are highly inconsistent in AHIG and Builder. - */ - return_SIZE(12, 8, 6); // guess - } - } - } - case PM_LayoutHorizontalSpacing: - case PM_LayoutVerticalSpacing: - return -1; - case PM_MenuHMargin: - ret = 0; - break; - case PM_ToolBarExtensionExtent: - ret = 21; - break; - case PM_ToolBarFrameWidth: - ret = 1; - break; - case PM_ScrollView_ScrollBarOverlap: - ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ? - pixelMetric(PM_ScrollBarExtent, opt, widget) : 0; - break; - default: - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - } - return ret; -} - -QPalette QMacStyle::standardPalette() const -{ - QPalette pal = QCommonStyle::standardPalette(); - pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); - pal.setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); - pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); - return pal; -} - -int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, - QStyleHintReturn *hret) const -{ - QMacAutoReleasePool pool; - - SInt32 ret = 0; - switch (sh) { - case SH_Slider_SnapToValue: - case SH_PrintDialog_RightAlignButtons: - case SH_FontDialog_SelectAssociatedText: - case SH_MenuBar_MouseTracking: - case SH_Menu_MouseTracking: - case SH_ComboBox_ListMouseTracking: - case SH_MainWindow_SpaceBelowMenuBar: - case SH_ItemView_ChangeHighlightOnFocus: - ret = 1; - break; - case SH_ToolBox_SelectedPageTitleBold: - ret = 0; - break; - case SH_DialogButtonBox_ButtonsHaveIcons: - ret = 0; - break; - case SH_Menu_SelectionWrap: - ret = false; - break; - case SH_Menu_KeyboardSearch: - ret = true; - break; - case SH_Menu_SpaceActivatesItem: - ret = true; - break; - case SH_Slider_AbsoluteSetButtons: - ret = Qt::LeftButton|Qt::MidButton; - break; - case SH_Slider_PageSetButtons: - ret = 0; - break; - case SH_ScrollBar_ContextMenu: - ret = false; - break; - case SH_TitleBar_AutoRaise: - ret = true; - break; - case SH_Menu_AllowActiveAndDisabled: - ret = false; - break; - case SH_Menu_SubMenuPopupDelay: - ret = 100; - break; - case SH_Menu_SubMenuUniDirection: - ret = true; - break; - case SH_Menu_SubMenuSloppySelectOtherActions: - ret = false; - break; - case SH_Menu_SubMenuResetWhenReenteringParent: - ret = true; - break; - case SH_Menu_SubMenuDontStartSloppyOnLeave: - ret = true; - break; - - case SH_ScrollBar_LeftClickAbsolutePosition: { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - bool result = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; - if(QApplication::keyboardModifiers() & Qt::AltModifier) - ret = !result; - else - ret = result; - break; } - case SH_TabBar_PreferNoArrows: - ret = true; - break; - /* - case SH_DialogButtons_DefaultButton: - ret = QDialogButtons::Reject; - break; - */ - case SH_GroupBox_TextLabelVerticalAlignment: - ret = Qt::AlignTop; - break; - case SH_ScrollView_FrameOnlyAroundContents: - ret = QCommonStyle::styleHint(sh, opt, w, hret); - break; - case SH_Menu_FillScreenWithScroll: - ret = false; - break; - case SH_Menu_Scrollable: - ret = true; - break; - case SH_RichText_FullWidthSelection: - ret = true; - break; - case SH_BlinkCursorWhenTextSelected: - ret = false; - break; - case SH_ScrollBar_StopMouseOverSlider: - ret = true; - break; - case SH_ListViewExpand_SelectMouseType: - ret = QEvent::MouseButtonRelease; - break; - case SH_TabBar_SelectMouseType: -#ifndef QT_NO_TABBAR - if (const QStyleOptionTabBarBase *opt2 = qstyleoption_cast(opt)) { - ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; - } else -#endif - { - ret = QEvent::MouseButtonRelease; - } - break; - case SH_ComboBox_Popup: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) - ret = !cmb->editable; - else - ret = 0; - break; - case SH_Workspace_FillSpaceOnMaximize: - ret = true; - break; - case SH_Widget_ShareActivation: - ret = true; - break; - case SH_Header_ArrowAlignment: - ret = Qt::AlignRight; - break; - case SH_TabBar_Alignment: { -#ifndef QT_NO_TABWIDGET - if (const QTabWidget *tab = qobject_cast(w)) { - if (tab->documentMode()) { - ret = Qt::AlignLeft; - break; - } - } -#endif -#ifndef QT_NO_TABBAR - if (const QTabBar *tab = qobject_cast(w)) { - if (tab->documentMode()) { - ret = Qt::AlignLeft; - break; - } - } -#endif - ret = Qt::AlignCenter; - } break; - case SH_UnderlineShortcut: - ret = false; - break; - case SH_ToolTipLabel_Opacity: - ret = 242; // About 95% - break; - case SH_Button_FocusPolicy: - ret = Qt::TabFocus; - break; - case SH_EtchDisabledText: - ret = false; - break; - case SH_FocusFrame_Mask: { - ret = true; - if(QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { - const uchar fillR = 192, fillG = 191, fillB = 190; - QImage img; - - QSize pixmapSize = opt->rect.size(); - if (!pixmapSize.isEmpty()) { - QPixmap pix(pixmapSize); - pix.fill(QColor(fillR, fillG, fillB)); - QPainter pix_paint(&pix); - proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w); - pix_paint.end(); - img = pix.toImage(); - } - - const QRgb *sptr = (QRgb*)img.bits(), *srow; - const int sbpl = img.bytesPerLine(); - const int w = sbpl/4, h = img.height(); - - QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32); - QRgb *dptr = (QRgb*)img_mask.bits(), *drow; - const int dbpl = img_mask.bytesPerLine(); - - for (int y = 0; y < h; ++y) { - srow = sptr+((y*sbpl)/4); - drow = dptr+((y*dbpl)/4); - for (int x = 0; x < w; ++x) { - const int redDiff = qRed(*srow) - fillR; - const int greenDiff = qGreen(*srow) - fillG; - const int blueDiff = qBlue(*srow) - fillB; - const int diff = (redDiff * redDiff) + (greenDiff * greenDiff) + (blueDiff * blueDiff); - (*drow++) = (diff < 10) ? 0xffffffff : 0xff000000; - ++srow; - } - } - QBitmap qmask = QBitmap::fromImage(img_mask); - mask->region = QRegion(qmask); - } - break; } - case SH_TitleBar_NoBorder: - ret = 1; - break; - case SH_RubberBand_Mask: - ret = 0; - break; - case SH_ComboBox_LayoutDirection: - ret = Qt::LeftToRight; - break; - case SH_ItemView_EllipsisLocation: - ret = Qt::AlignHCenter; - break; - case SH_ItemView_ShowDecorationSelected: - ret = true; - break; - case SH_TitleBar_ModifyNotification: - ret = false; - break; - case SH_ScrollBar_RollBetweenButtons: - ret = true; - break; - case SH_WindowFrame_Mask: - ret = 1; - if (QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { - mask->region = opt->rect; - mask->region -= QRect(opt->rect.left(), opt->rect.top(), 5, 1); - mask->region -= QRect(opt->rect.left(), opt->rect.top() + 1, 3, 1); - mask->region -= QRect(opt->rect.left(), opt->rect.top() + 2, 2, 1); - mask->region -= QRect(opt->rect.left(), opt->rect.top() + 3, 1, 2); - - mask->region -= QRect(opt->rect.right() - 4, opt->rect.top(), 5, 1); - mask->region -= QRect(opt->rect.right() - 2, opt->rect.top() + 1, 3, 1); - mask->region -= QRect(opt->rect.right() - 1, opt->rect.top() + 2, 2, 1); - mask->region -= QRect(opt->rect.right() , opt->rect.top() + 3, 1, 2); - } - break; - case SH_TabBar_ElideMode: - ret = Qt::ElideRight; - break; -#if QT_CONFIG(dialogbuttonbox) - case SH_DialogButtonLayout: - ret = QDialogButtonBox::MacLayout; - break; -#endif - case SH_FormLayoutWrapPolicy: - ret = QFormLayout::DontWrapRows; - break; - case SH_FormLayoutFieldGrowthPolicy: - ret = QFormLayout::FieldsStayAtSizeHint; - break; - case SH_FormLayoutFormAlignment: - ret = Qt::AlignHCenter | Qt::AlignTop; - break; - case SH_FormLayoutLabelAlignment: - ret = Qt::AlignRight; - break; - case SH_ComboBox_PopupFrameStyle: - ret = QFrame::NoFrame | QFrame::Plain; - break; - case SH_MessageBox_TextInteractionFlags: - ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; - break; - case SH_SpellCheckUnderlineStyle: - ret = QTextCharFormat::DashUnderline; - break; - case SH_MessageBox_CenterButtons: - ret = false; - break; - case SH_MenuBar_AltKeyNavigation: - ret = false; - break; - case SH_ItemView_MovementWithoutUpdatingSelection: - ret = false; - break; - case SH_FocusFrame_AboveWidget: - ret = true; - break; -#ifndef QT_NO_WIZARD - case SH_WizardStyle: - ret = QWizard::MacStyle; - break; -#endif - case SH_ItemView_ArrowKeysNavigateIntoChildren: - ret = false; - break; - case SH_Menu_FlashTriggeredItem: - ret = true; - break; - case SH_Menu_FadeOutOnHide: - ret = true; - break; - case SH_Menu_Mask: - if (opt) { - if (QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { - ret = true; - HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, - opt->rect.width(), opt->rect.height() - 8); - HIThemeMenuDrawInfo mdi; - mdi.version = 0; -#ifndef QT_NO_MENU - if (w && qobject_cast(w->parentWidget())) - mdi.menuType = kThemeMenuTypeHierarchical; - else -#endif - mdi.menuType = kThemeMenuTypePopUp; - QCFType shape; - HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape); - - mask->region = qt_mac_fromHIShapeRef(shape); - } - } - break; - case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: - ret = true; - break; -#ifndef QT_NO_TABBAR - case SH_TabBar_CloseButtonPosition: - ret = QTabBar::LeftSide; - break; -#endif - case SH_DockWidget_ButtonsHaveFrame: - ret = false; - break; - case SH_ScrollBar_Transient: - if ((qobject_cast(w) && w->parent() && - qobject_cast(w->parent()->parent())) -#ifndef QT_NO_ACCESSIBILITY - || (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar)) -#endif - ) { - ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; - } - break; - case SH_ItemView_ScrollMode: - ret = QAbstractItemView::ScrollPerPixel; - break; - case SH_TitleBar_ShowToolTipsOnButtons: - // min/max/close buttons on windows don't show tool tips - ret = false; - break; - default: - ret = QCommonStyle::styleHint(sh, opt, w, hret); - break; - } - return ret; -} - -QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, - const QStyleOption *opt) const -{ - switch (iconMode) { - case QIcon::Disabled: { - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - int imgh = img.height(); - int imgw = img.width(); - QRgb pixel; - for (int y = 0; y < imgh; ++y) { - for (int x = 0; x < imgw; ++x) { - pixel = img.pixel(x, y); - img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), - qAlpha(pixel) / 2)); - } - } - return QPixmap::fromImage(img); - } - default: - ; - } - return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); -} - - -QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, - const QWidget *widget) const -{ - // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap() - // I don't want infinite recursion so if we do get in that situation, just return the Window's - // standard pixmap instead (since there is no mac-specific icon then). This should be fine until - // someone changes how Windows standard - // pixmap works. - static bool recursionGuard = false; - - if (recursionGuard) - return QCommonStyle::standardPixmap(standardPixmap, opt, widget); - - recursionGuard = true; - QIcon icon = proxy()->standardIcon(standardPixmap, opt, widget); - recursionGuard = false; - int size; - switch (standardPixmap) { - default: - size = 32; - break; - case SP_MessageBoxCritical: - case SP_MessageBoxQuestion: - case SP_MessageBoxInformation: - case SP_MessageBoxWarning: - size = 64; - break; - } - return icon.pixmap(qt_getWindow(widget), QSize(size, size)); -} - -void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, - const QWidget *w) const -{ - Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); - QMacCGContext cg(p); - QWindow *window = w && w->window() ? w->window()->windowHandle() : - QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); - switch (pe) { - case PE_IndicatorArrowUp: - case PE_IndicatorArrowDown: - case PE_IndicatorArrowRight: - case PE_IndicatorArrowLeft: { - p->save(); - p->setRenderHint(QPainter::Antialiasing); - int xOffset = opt->direction == Qt::LeftToRight ? 2 : -1; - QMatrix matrix; - matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); - QPainterPath path; - switch(pe) { - default: - case PE_IndicatorArrowDown: - break; - case PE_IndicatorArrowUp: - matrix.rotate(180); - break; - case PE_IndicatorArrowLeft: - matrix.rotate(90); - break; - case PE_IndicatorArrowRight: - matrix.rotate(-90); - break; - } - path.moveTo(0, 5); - path.lineTo(-4, -3); - path.lineTo(4, -3); - p->setMatrix(matrix); - p->setPen(Qt::NoPen); - p->setBrush(QColor(0, 0, 0, 135)); - p->drawPath(path); - p->restore(); - break; } -#ifndef QT_NO_TABBAR - case PE_FrameTabBarBase: - if (const QStyleOptionTabBarBase *tbb - = qstyleoption_cast(opt)) { - if (tbb->documentMode) { - p->save(); - drawTabBase(p, tbb, w); - p->restore(); - return; - } - - QRegion region(tbb->rect); - region -= tbb->tabBarRect; - p->save(); - p->setClipRegion(region); - QStyleOptionTabWidgetFrame twf; - twf.QStyleOption::operator=(*tbb); - twf.shape = tbb->shape; - switch (getTabDirection(twf.shape)) { - case kThemeTabNorth: - twf.rect = twf.rect.adjusted(0, 0, 0, 10); - break; - case kThemeTabSouth: - twf.rect = twf.rect.adjusted(0, -10, 0, 0); - break; - case kThemeTabWest: - twf.rect = twf.rect.adjusted(0, 0, 10, 0); - break; - case kThemeTabEast: - twf.rect = twf.rect.adjusted(0, -10, 0, 0); - break; - } - proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w); - p->restore(); - } - break; -#endif - case PE_PanelTipLabel: - p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase)); - break; - case PE_FrameGroupBox: - if (const QStyleOptionFrame *groupBox = qstyleoption_cast(opt)) { - if (groupBox->features & QStyleOptionFrame::Flat) { - QCommonStyle::drawPrimitive(pe, groupBox, p, w); - } else { - HIThemeGroupBoxDrawInfo gdi; - gdi.version = qt_mac_hitheme_version; - gdi.state = tds; -#ifndef QT_NO_GROUPBOX - if (w && qobject_cast(w->parentWidget())) - gdi.kind = kHIThemeGroupBoxKindSecondary; - else -#endif - gdi.kind = kHIThemeGroupBoxKindPrimary; - HIRect hirect = qt_hirectForQRect(opt->rect); - HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal); - } - } - break; - case PE_IndicatorToolBarSeparator: { - QPainterPath path; - if (opt->state & State_Horizontal) { - int xpoint = opt->rect.center().x(); - path.moveTo(xpoint + 0.5, opt->rect.top() + 1); - path.lineTo(xpoint + 0.5, opt->rect.bottom()); - } else { - int ypoint = opt->rect.center().y(); - path.moveTo(opt->rect.left() + 2 , ypoint + 0.5); - path.lineTo(opt->rect.right() + 1, ypoint + 0.5); - } - QPainterPathStroker theStroker; - theStroker.setCapStyle(Qt::FlatCap); - theStroker.setDashPattern(QVector() << 1 << 2); - path = theStroker.createStroke(path); - p->fillPath(path, QColor(0, 0, 0, 119)); - } - break; - case PE_FrameWindow: - break; - case PE_IndicatorDockWidgetResizeHandle: { - // The docwidget resize handle is drawn as a one-pixel wide line. - p->save(); - if (opt->state & State_Horizontal) { - p->setPen(QColor(160, 160, 160)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - } else { - p->setPen(QColor(145, 145, 145)); - p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); - } - p->restore(); - } break; - case PE_IndicatorToolBarHandle: { - p->save(); - QPainterPath path; - int x = opt->rect.x() + 6; - int y = opt->rect.y() + 7; - static const int RectHeight = 2; - if (opt->state & State_Horizontal) { - while (y < opt->rect.height() - RectHeight - 5) { - path.moveTo(x, y); - path.addEllipse(x, y, RectHeight, RectHeight); - y += 6; - } - } else { - while (x < opt->rect.width() - RectHeight - 5) { - path.moveTo(x, y); - path.addEllipse(x, y, RectHeight, RectHeight); - x += 6; - } - } - p->setPen(Qt::NoPen); - QColor dark = opt->palette.dark().color().darker(); - dark.setAlphaF(0.50); - p->fillPath(path, dark); - p->restore(); - - break; - } - case PE_IndicatorHeaderArrow: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - // In HITheme, up is down, down is up and hamburgers eat people. - if (header->sortIndicator != QStyleOptionHeader::None) - proxy()->drawPrimitive( - (header->sortIndicator == QStyleOptionHeader::SortDown) ? - PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w); - } - break; - case PE_IndicatorMenuCheckMark: { - if (!(opt->state & State_On)) - break; - QColor pc; - if (opt->state & State_Selected) - pc = opt->palette.highlightedText().color(); - else - pc = opt->palette.text().color(); - QCFType checkmarkColor = CGColorCreateGenericRGB(static_cast(pc.redF()), - static_cast(pc.greenF()), - static_cast(pc.blueF()), - static_cast(pc.alphaF())); - // kCTFontUIFontSystem and others give the same result - // as kCTFontUIFontMenuItemMark. However, the latter is - // more reminiscent to HITheme's kThemeMenuItemMarkFont. - // See also the font for small- and mini-sized widgets, - // where we end up using the generic system font type. - const CTFontUIFontType fontType = (opt->state & State_Mini) ? kCTFontUIFontMiniSystem : - (opt->state & State_Small) ? kCTFontUIFontSmallSystem : - kCTFontUIFontMenuItemMark; - // Similarly for the font size, where there is a small difference - // between regular combobox and item view items, and and menu items. - // However, we ignore any difference for small- and mini-sized widgets. - const CGFloat fontSize = fontType == kCTFontUIFontMenuItemMark ? opt->fontMetrics.height() : 0.0; - QCFType checkmarkFont = CTFontCreateUIFontForLanguage(fontType, fontSize, NULL); - - CGContextSaveGState(cg); - CGContextSetShouldSmoothFonts(cg, NO); // Same as HITheme and Cocoa menu checkmarks - - // Baseline alignment tweaks for QComboBox and QMenu - const CGFloat vOffset = (opt->state & State_Mini) ? 0.0 : - (opt->state & State_Small) ? 1.0 : - 0.75; - - CGContextTranslateCTM(cg, 0, opt->rect.bottom()); - CGContextScaleCTM(cg, 1, -1); - // Translate back to the original position and add rect origin and offset - CGContextTranslateCTM(cg, opt->rect.x(), vOffset); - - // CTFont has severe difficulties finding the checkmark character among its - // glyphs. Fortunately, CTLine knows its ways inside the Cocoa labyrinth. - static const CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; - static const int numValues = sizeof(keys) / sizeof(keys[0]); - const CFTypeRef values[] = { (CFTypeRef)checkmarkFont, (CFTypeRef)checkmarkColor }; - Q_STATIC_ASSERT((sizeof(values) / sizeof(values[0])) == numValues); - QCFType attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, - numValues, NULL, NULL); - // U+2713: CHECK MARK - QCFType checkmarkString = CFAttributedStringCreate(kCFAllocatorDefault, (CFStringRef)@"\u2713", attributes); - QCFType line = CTLineCreateWithAttributedString(checkmarkString); - - CTLineDraw((CTLineRef)line, cg); - CGContextFlush(cg); // CTLineDraw's documentation says it doesn't flush - - CGContextRestoreGState(cg); - break; } - case PE_IndicatorViewItemCheck: - case PE_IndicatorRadioButton: - case PE_IndicatorCheckBox: { - bool drawColorless = tds == kThemeStateInactive; - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = tds; - if (drawColorless) - bdi.state = kThemeStateActive; - bdi.adornment = kThemeDrawIndicatorOnly; - if (opt->state & State_HasFocus) - bdi.adornment |= kThemeAdornmentFocus; - bool isRadioButton = (pe == PE_IndicatorRadioButton); - switch (d->aquaSizeConstrain(opt, w)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - if (isRadioButton) - bdi.kind = kThemeRadioButton; - else - bdi.kind = kThemeCheckBox; - break; - case QAquaSizeMini: - if (isRadioButton) - bdi.kind = kThemeMiniRadioButton; - else - bdi.kind = kThemeMiniCheckBox; - break; - case QAquaSizeSmall: - if (isRadioButton) - bdi.kind = kThemeSmallRadioButton; - else - bdi.kind = kThemeSmallCheckBox; - break; - } - if (opt->state & State_NoChange) - bdi.value = kThemeButtonMixed; - else if (opt->state & State_On) - bdi.value = kThemeButtonOn; - else - bdi.value = kThemeButtonOff; - HIRect macRect = qt_hirectForQRect(opt->rect); - if (!drawColorless) - HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0); - else - d->drawColorlessButton(macRect, &bdi, p, opt); - break; } - case PE_FrameFocusRect: - // Use the our own focus widget stuff. - break; - case PE_IndicatorBranch: { - if (!(opt->state & State_Children)) - break; - if (!d->indicatorBranchButtonCell) - const_cast(d)->indicatorBranchButtonCell = (void *)[[NSButtonCell alloc] init]; - NSButtonCell *triangleCell = (NSButtonCell *)d->indicatorBranchButtonCell; - [triangleCell setButtonType:NSOnOffButton]; - [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; - [triangleCell setBezelStyle:NSDisclosureBezelStyle]; - bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); - [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; - - CGContextSaveGState(cg); - [NSGraphicsContext saveGraphicsState]; - - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; - - QRect qtRect = opt->rect.adjusted(DisclosureOffset, 0, -DisclosureOffset, 0); - CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); - CGContextTranslateCTM(cg, rect.origin.x, rect.origin.y + rect.size.height); - CGContextScaleCTM(cg, 1, -1); - CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y); - - [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; - - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(cg); - break; } - - case PE_Frame: { - QPen oldPen = p->pen(); - p->setPen(opt->palette.base().color().darker(140)); - p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); - p->setPen(opt->palette.base().color().darker(180)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(oldPen); - break; } - - case PE_FrameLineEdit: - if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { - if (frame->state & State_Sunken) { - QColor baseColor(frame->palette.background().color()); - HIThemeFrameDrawInfo fdi; - fdi.version = qt_mac_hitheme_version; - fdi.state = tds; - SInt32 frame_size; - fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : - kHIThemeFrameTextFieldSquare; - GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); - if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled)) - fdi.state = kThemeStateInactive; - else if (fdi.state == kThemeStatePressed) - // This pressed state doesn't make sense for a line edit frame. - // And Yosemite agrees with us. Otherwise it starts showing yellow pixels. - fdi.state = kThemeStateActive; - fdi.isFocused = (frame->state & State_HasFocus); - int lw = frame->lineWidth; - if (lw <= 0) - lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w); - { //clear to base color - p->save(); - p->setPen(QPen(baseColor, lw)); - p->setBrush(Qt::NoBrush); - p->drawRect(frame->rect); - p->restore(); - } - HIRect hirect = qt_hirectForQRect(frame->rect, - QRect(frame_size, frame_size, - frame_size * 2, frame_size * 2)); - - HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); - } else { - QCommonStyle::drawPrimitive(pe, opt, p, w); - } - } - break; - case PE_PanelLineEdit: - QCommonStyle::drawPrimitive(pe, opt, p, w); - // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). - // Focus frame is drawn outside the rectangle passed in the option-rect. - if (const QStyleOptionFrame *panel = qstyleoption_cast(opt)) { -#ifndef QT_NO_LINEEDIT - if ((opt->state & State_HasFocus) && !qobject_cast(w)) { - int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); - int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); - QStyleOptionFrame focusFrame = *panel; - focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); - drawControl(CE_FocusFrame, &focusFrame, p, w); - } -#endif - } - - break; -#ifndef QT_NO_TABWIDGET - case PE_FrameTabWidget: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - HIRect hirect = qt_hirectForQRect(twf->rect); - HIThemeTabPaneDrawInfo tpdi; - tpdi.version = qt_mac_hitheme_tab_version(); - tpdi.state = tds; - tpdi.direction = getTabDirection(twf->shape); - tpdi.size = kHIThemeTabSizeNormal; - tpdi.kind = kHIThemeTabKindNormal; - tpdi.adornment = kHIThemeTabPaneAdornmentNormal; - HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal); - } - break; -#endif - case PE_PanelScrollAreaCorner: { - const QBrush brush(opt->palette.brush(QPalette::Base)); - p->fillRect(opt->rect, brush); - p->setPen(QPen(QColor(217, 217, 217))); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); - } break; - case PE_FrameStatusBarItem: - break; - case PE_IndicatorTabClose: { - // Make close button visible only on the hovered tab. - if (QTabBar *tabBar = qobject_cast(w->parentWidget())) { - const QTabBarPrivate *tabBarPrivate = static_cast(QObjectPrivate::get(tabBar)); - const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex(); - if (hoveredTabIndex != -1 && ((w == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || - (w == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide)))) { - const bool hover = (opt->state & State_MouseOver); - const bool selected = (opt->state & State_Selected); - const bool pressed = (opt->state & State_Sunken); - drawTabCloseButton(p, hover, selected, pressed); - } - } - } break; - case PE_PanelStatusBar: { - // Fill the status bar with the titlebar gradient. - QLinearGradient linearGrad; - if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) { - linearGrad = titlebarGradientActive(); - } else { - linearGrad = titlebarGradientInactive(); - } - - linearGrad.setStart(0, opt->rect.top()); - linearGrad.setFinalStop(0, opt->rect.bottom()); - p->fillRect(opt->rect, linearGrad); - - // Draw the black separator line at the top of the status bar. - if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) - p->setPen(titlebarSeparatorLineActive); - else - p->setPen(titlebarSeparatorLineInactive); - p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top()); - - break; - } - - default: - QCommonStyle::drawPrimitive(pe, opt, p, w); - break; - } -} - -static inline QPixmap darkenPixmap(const QPixmap &pixmap) -{ - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - int imgh = img.height(); - int imgw = img.width(); - int h, s, v, a; - QRgb pixel; - for (int y = 0; y < imgh; ++y) { - for (int x = 0; x < imgw; ++x) { - pixel = img.pixel(x, y); - a = qAlpha(pixel); - QColor hsvColor(pixel); - hsvColor.getHsv(&h, &s, &v); - s = qMin(100, s * 2); - v = v / 2; - hsvColor.setHsv(h, s, v); - pixel = hsvColor.rgb(); - img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a)); - } - } - return QPixmap::fromImage(img); -} - - - -void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, - const QWidget *w) const -{ - Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); - QMacCGContext cg(p); - QWindow *window = w && w->window() ? w->window()->windowHandle() : - QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); - switch (ce) { - case CE_HeaderSection: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - State flags = header->state; - QRect ir = header->rect; - bdi.kind = kThemeListHeaderButton; - bdi.adornment = kThemeAdornmentNone; - bdi.state = kThemeStateActive; - - if (flags & State_On) - bdi.value = kThemeButtonOn; - else - bdi.value = kThemeButtonOff; - - if (header->orientation == Qt::Horizontal){ - switch (header->position) { - case QStyleOptionHeader::Beginning: - ir.adjust(-1, -1, 0, 0); - break; - case QStyleOptionHeader::Middle: - ir.adjust(-1, -1, 0, 0); - break; - case QStyleOptionHeader::OnlyOneSection: - case QStyleOptionHeader::End: - ir.adjust(-1, -1, 1, 0); - break; - default: - break; - } - - if (header->position != QStyleOptionHeader::Beginning - && header->position != QStyleOptionHeader::OnlyOneSection) { - bdi.adornment = header->direction == Qt::LeftToRight - ? kThemeAdornmentHeaderButtonLeftNeighborSelected - : kThemeAdornmentHeaderButtonRightNeighborSelected; - } - } - - if (flags & State_Active) { - if (!(flags & State_Enabled)) - bdi.state = kThemeStateUnavailable; - else if (flags & State_Sunken) - bdi.state = kThemeStatePressed; - } else { - if (flags & State_Enabled) - bdi.state = kThemeStateInactive; - else - bdi.state = kThemeStateUnavailableInactive; - } - - if (header->sortIndicator != QStyleOptionHeader::None) { - bdi.value = kThemeButtonOn; - if (header->sortIndicator == QStyleOptionHeader::SortDown) - bdi.adornment = kThemeAdornmentHeaderButtonSortUp; - } - if (flags & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - - ir = visualRect(header->direction, header->rect, ir); - HIRect bounds = qt_hirectForQRect(ir); - - bool noVerticalHeader = true; -#ifndef QT_NO_TABLEVIEW - if (w) - if (const QTableView *table = qobject_cast(w->parentWidget())) - noVerticalHeader = !table->verticalHeader()->isVisible(); -#endif - - bool drawTopBorder = header->orientation == Qt::Horizontal; - bool drawLeftBorder = header->orientation == Qt::Vertical - || header->position == QStyleOptionHeader::OnlyOneSection - || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); - d->drawTableHeader(bounds, drawTopBorder, drawLeftBorder, bdi, p); - } - break; - case CE_HeaderLabel: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - p->save(); - QRect textr = header->rect; - if (!header->icon.isNull()) { - QIcon::Mode mode = QIcon::Disabled; - if (opt->state & State_Enabled) - mode = QIcon::Normal; - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - QPixmap pixmap = header->icon.pixmap(window, QSize(iconExtent, iconExtent), mode); - - QRect pixr = header->rect; - pixr.setY(header->rect.center().y() - (pixmap.height() / pixmap.devicePixelRatio() - 1) / 2); - proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); - textr.translate(pixmap.width() / pixmap.devicePixelRatio() + 2, 0); - } - - proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette, - header->state & State_Enabled, header->text, QPalette::ButtonText); - p->restore(); - } - break; - case CE_ToolButtonLabel: - if (const QStyleOptionToolButton *tb = qstyleoption_cast(opt)) { - QStyleOptionToolButton myTb = *tb; - myTb.state &= ~State_AutoRaise; -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { - QRect cr = tb->rect; - int shiftX = 0; - int shiftY = 0; - bool needText = false; - int alignment = 0; - bool down = tb->state & (State_Sunken | State_On); - if (down) { - shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w); - shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w); - } - // The down state is special for QToolButtons in a toolbar on the Mac - // The text is a bit bolder and gets a drop shadow and the icons are also darkened. - // This doesn't really fit into any particular case in QIcon, so we - // do the majority of the work ourselves. - if (!(tb->features & QStyleOptionToolButton::Arrow)) { - Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; - if (tb->icon.isNull() && !tb->text.isEmpty()) - tbstyle = Qt::ToolButtonTextOnly; - - switch (tbstyle) { - case Qt::ToolButtonTextOnly: { - needText = true; - alignment = Qt::AlignCenter; - break; } - case Qt::ToolButtonIconOnly: - case Qt::ToolButtonTextBesideIcon: - case Qt::ToolButtonTextUnderIcon: { - QRect pr = cr; - QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled; - QIcon::State iconState = (tb->state & State_On) ? QIcon::On - : QIcon::Off; - QPixmap pixmap = tb->icon.pixmap(window, - tb->rect.size().boundedTo(tb->iconSize), - iconMode, iconState); - - // Draw the text if it's needed. - if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { - needText = true; - if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { - pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6); - cr.adjust(0, pr.bottom(), 0, -3); - alignment |= Qt::AlignCenter; - } else { - pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8); - cr.adjust(pr.right(), 0, 0, 0); - alignment |= Qt::AlignLeft | Qt::AlignVCenter; - } - } - if (opt->state & State_Sunken) { - pr.translate(shiftX, shiftY); - pixmap = darkenPixmap(pixmap); - } - proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); - break; } - default: - Q_ASSERT(false); - break; - } - - if (needText) { - QPalette pal = tb->palette; - QPalette::ColorRole role = QPalette::NoRole; - if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w)) - alignment |= Qt::TextHideMnemonic; - if (down) - cr.translate(shiftX, shiftY); - if (tbstyle == Qt::ToolButtonTextOnly - || (tbstyle != Qt::ToolButtonTextOnly && !down)) { - QPen pen = p->pen(); - QColor light = down ? Qt::black : Qt::white; - light.setAlphaF(0.375f); - p->setPen(light); - p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text); - p->setPen(pen); - if (down && tbstyle == Qt::ToolButtonTextOnly) { - pal = QApplication::palette("QMenu"); - pal.setCurrentColorGroup(tb->palette.currentColorGroup()); - role = QPalette::HighlightedText; - } - } - proxy()->drawItemText(p, cr, alignment, pal, - tb->state & State_Enabled, tb->text, role); - } - } else { - QCommonStyle::drawControl(ce, &myTb, p, w); - } - } else { - QCommonStyle::drawControl(ce, &myTb, p, w); - } -#else - Q_UNUSED(tb) -#endif - } - break; - case CE_ToolBoxTabShape: - QCommonStyle::drawControl(ce, opt, p, w); - break; - case CE_PushButtonBevel: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - if (!(btn->state & (State_Raised | State_Sunken | State_On))) - break; - - if (btn->features & QStyleOptionButton::CommandLinkButton) { - QCommonStyle::drawControl(ce, opt, p, w); - break; - } - - // No default button pulsating animation on Yosemite, - // so we have to do few things differently. - - // a focused auto-default button within an active window - // takes precedence over a normal default button - if (btn->features & QStyleOptionButton::AutoDefaultButton - && opt->state & State_Active && opt->state & State_HasFocus) { - d->autoDefaultButton = opt->styleObject; - } else if (d->autoDefaultButton == opt->styleObject) { - d->setAutoDefaultButton(0); - } - - if (!d->autoDefaultButton) { - if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) { - d->defaultButton = opt->styleObject; - } else if (d->defaultButton == opt->styleObject) { - if (QStyleAnimation *animation = d->animation(opt->styleObject)) { - animation->updateTarget(); - d->stopAnimation(opt->styleObject); - } - d->defaultButton = 0; - } - } - - // TODO: find out the pressed button in a qwidget independent way - extern QWidget *qt_button_down; // qwidgetwindow.cpp - if (opt->styleObject == qt_button_down) - d->pressedButton = opt->styleObject; - else if (d->pressedButton == opt->styleObject) - d->pressedButton = 0; - - bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - HIThemeButtonDrawInfo bdi; - d->initHIThemePushButton(btn, w, tds, &bdi); - - if (!hasMenu) { - // HITheme is not drawing a nice focus frame around buttons. - // We'll do it ourselves further down. - bdi.adornment &= ~kThemeAdornmentFocus; - - // We can't rely on an animation existing to test for the default look. That means a bit - // more logic (notice that the logic is slightly different for the bevel and the label). - if (tds == kThemeStateActive - && (btn->features & QStyleOptionButton::DefaultButton - || (btn->features & QStyleOptionButton::AutoDefaultButton - && d->autoDefaultButton == btn->styleObject))) - bdi.adornment |= kThemeAdornmentDefault; - } - - // Unlike Carbon, we want the button to always be drawn inside its bounds. - // Therefore, make the button a bit smaller, so that even if it got focus, - // the focus 'shadow' will be inside. - HIRect newRect = qt_hirectForQRect(btn->rect); - if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) { - newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset; - newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; - newRect.size.width -= QMacStylePrivate::PushButtonRightOffset; - newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset; - } else if (bdi.kind == kThemePushButtonMini) { - newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2; - newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; - newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; - } - - if (hasMenu && bdi.kind != kThemeBevelButton) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); - cw.first = QCocoaPullDownButton; - NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); - [pdb highlight:(bdi.state == kThemeStatePressed)]; - pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; - QRect rect = opt->rect; - rect.adjust(0, 0, cw.second == QAquaSizeSmall ? -4 : cw.second == QAquaSizeMini ? -9 : -6, 0); - d->drawNSViewInRect(cw, pdb, rect, p, w != 0); - } else if (hasMenu && bdi.state == kThemeStatePressed) - d->drawColorlessButton(newRect, &bdi, p, opt); - else - HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); - - if (btn->state & State_HasFocus) { - CGRect focusRect = newRect; - if (bdi.kind == kThemePushButton) - focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. - else if (bdi.kind == kThemePushButtonMini) - focusRect.size.height = 15; // Our QPushButton sizes are really weird - - if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) { - if (bdi.kind == kThemePushButtonSmall) { - focusRect = CGRectInset(focusRect, -1, 0); - } else if (bdi.kind == kThemePushButtonMini) { - focusRect = CGRectInset(focusRect, 1, 0); - } - } else { - if (bdi.kind == kThemePushButton) { - focusRect = CGRectInset(focusRect, 1, 1); - } else if (bdi.kind == kThemePushButtonSmall) { - focusRect = CGRectInset(focusRect, 0, 2); - } else if (bdi.kind == kThemePushButtonMini) { - focusRect = CGRectInset(focusRect, 2, 1); - } - } - - const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 4; - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); - const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height); - d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); - } - - if (hasMenu && bdi.kind == kThemeBevelButton) { - int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); - QRect ir = btn->rect; - int arrowXOffset = bdi.kind == kThemePushButton ? 6 : - bdi.kind == kThemePushButtonSmall ? 7 : 8; - int arrowYOffset = bdi.kind == kThemePushButton ? 3 : - bdi.kind == kThemePushButtonSmall ? 1 : 2; - if (!w) { - // adjustment for Qt Quick Controls - arrowYOffset -= ir.top(); - if (bdi.kind == kThemePushButtonSmall) - arrowYOffset += 1; - } - QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset, - ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2); - ar = visualRect(btn->direction, ir, ar); - HIRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height()); - - HIThemePopupArrowDrawInfo pdi; - pdi.version = qt_mac_hitheme_version; - pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; - pdi.orientation = kThemeArrowDown; - if (bdi.kind == kThemePushButtonMini) - pdi.size = kThemeArrow5pt; - else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) - pdi.size = kThemeArrow7pt; - HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); - } - } - break; - case CE_PushButtonLabel: - if (const QStyleOptionButton *b = qstyleoption_cast(opt)) { - QStyleOptionButton btn(*b); - // We really don't want the label to be drawn the same as on - // windows style if it has an icon and text, then it should be more like a - // tab. So, cheat a little here. However, if it *is* only an icon - // the windows style works great, so just use that implementation. - bool hasMenu = btn.features & QStyleOptionButton::HasMenu; - bool hasIcon = !btn.icon.isNull(); - bool hasText = !btn.text.isEmpty(); - - if (!hasMenu) { - if (tds == kThemeStatePressed - || (tds == kThemeStateActive - && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) - || d->autoDefaultButton == btn.styleObject))) - btn.palette.setColor(QPalette::ButtonText, Qt::white); - } - - if (!hasIcon && !hasMenu) { - // ### this is really overly difficult, simplify. - // It basically tries to get the right font for "small" and "mini" icons. - QFont oldFont = p->font(); - QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont()); - ThemeFontID themeId = kThemePushButtonFont; - if (oldFont == newFont) { // Yes, use HITheme to draw the text for small sizes. - switch (d->aquaSizeConstrain(opt, w)) { - default: - break; - case QAquaSizeSmall: - themeId = kThemeSmallSystemFont; - break; - case QAquaSizeMini: - themeId = kThemeMiniSystemFont; - break; - } - } - - if (themeId == kThemePushButtonFont) { - QCommonStyle::drawControl(ce, &btn, p, w); - } else { - p->save(); - CGContextSetShouldAntialias(cg, true); - CGContextSetShouldSmoothFonts(cg, true); - HIThemeTextInfo tti; - tti.version = qt_mac_hitheme_version; - tti.state = tds; - QColor textColor; - textColor = btn.palette.buttonText().color(); - CGFloat colorComp[] = { static_cast(textColor.redF()), static_cast(textColor.greenF()), - static_cast(textColor.blueF()), static_cast(textColor.alphaF()) }; - CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); - CGContextSetFillColor(cg, colorComp); - tti.fontID = themeId; - tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; - tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; - tti.options = kHIThemeTextBoxOptionNone; - tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1 + btn.text.count(QLatin1Char('\n')); - QCFString buttonText = qt_mac_removeMnemonics(btn.text); - QRect r = btn.rect; - HIRect bounds = qt_hirectForQRect(r); - HIThemeDrawTextBox(buttonText, &bounds, &tti, - cg, kHIThemeOrientationNormal); - p->restore(); - } - } else { - if (hasIcon && !hasText) { - QCommonStyle::drawControl(ce, &btn, p, w); - } else { - QRect freeContentRect = btn.rect; - QRect textRect = itemTextRect( - btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); - if (hasMenu) { - textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls - } - // Draw the icon: - if (hasIcon) { - int contentW = textRect.width(); - if (hasMenu) - contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; - QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled; - if (mode == QIcon::Normal && btn.state & State_HasFocus) - mode = QIcon::Active; - // Decide if the icon is should be on or off: - QIcon::State state = QIcon::Off; - if (btn.state & State_On) - state = QIcon::On; - QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state); - int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); - int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); - contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding; - int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; - int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2; - QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight); - QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect); - proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); - int newOffset = iconDestRect.x() + iconDestRect.width() - + QMacStylePrivate::PushButtonContentPadding - textRect.x(); - textRect.adjust(newOffset, 0, newOffset, 0); - } - // Draw the text: - if (hasText) { - textRect = visualRect(btn.direction, freeContentRect, textRect); - proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, - (btn.state & State_Enabled), btn.text, QPalette::ButtonText); - } - } - } - } - break; - case CE_ComboBoxLabel: - if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { - QStyleOptionComboBox comboCopy = *cb; - comboCopy.direction = Qt::LeftToRight; - QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); - } - break; -#ifndef QT_NO_TABBAR - case CE_TabBarTabShape: - if (const QStyleOptionTab *tabOpt = qstyleoption_cast(opt)) { - if (tabOpt->documentMode) { - p->save(); - bool isUnified = false; - if (w) { - QRect tabRect = tabOpt->rect; - QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft()); - isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y()); - } - - const int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, opt, w); - drawTabShape(p, tabOpt, isUnified, tabOverlap); - - p->restore(); - return; - } - - HIThemeTabDrawInfo tdi; - tdi.version = 1; - tdi.style = kThemeTabNonFront; - tdi.direction = getTabDirection(tabOpt->shape); - switch (d->aquaSizeConstrain(opt, w)) { - default: - case QAquaSizeUnknown: - case QAquaSizeLarge: - tdi.size = kHIThemeTabSizeNormal; - break; - case QAquaSizeSmall: - tdi.size = kHIThemeTabSizeSmall; - break; - case QAquaSizeMini: - tdi.size = kHIThemeTabSizeMini; - break; - } - bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast; - QRect tabRect = tabOpt->rect; - - bool selected = tabOpt->state & State_Selected; - if (selected) { - if (!(tabOpt->state & State_Active)) - tdi.style = kThemeTabFrontUnavailable; - else if (!(tabOpt->state & State_Enabled)) - tdi.style = kThemeTabFrontInactive; - else - tdi.style = kThemeTabFront; - } else if (!(tabOpt->state & State_Active)) { - tdi.style = kThemeTabNonFrontUnavailable; - } else if (!(tabOpt->state & State_Enabled)) { - tdi.style = kThemeTabNonFrontInactive; - } else if (tabOpt->state & State_Sunken) { - tdi.style = kThemeTabNonFrontPressed; - } - if (tabOpt->state & State_HasFocus) - tdi.adornment = kHIThemeTabAdornmentFocus; - else - tdi.adornment = kHIThemeTabAdornmentNone; - tdi.kind = kHIThemeTabKindNormal; - - QStyleOptionTab::TabPosition tp = tabOpt->position; - QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; - if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { - if (sp == QStyleOptionTab::NextIsSelected) - sp = QStyleOptionTab::PreviousIsSelected; - else if (sp == QStyleOptionTab::PreviousIsSelected) - sp = QStyleOptionTab::NextIsSelected; - switch (tp) { - case QStyleOptionTab::Beginning: - tp = QStyleOptionTab::End; - break; - case QStyleOptionTab::End: - tp = QStyleOptionTab::Beginning; - break; - default: - break; - } - } - bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22); - - switch (tp) { - case QStyleOptionTab::Beginning: - tdi.position = kHIThemeTabPositionFirst; - if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) - tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; - break; - case QStyleOptionTab::Middle: - tdi.position = kHIThemeTabPositionMiddle; - if (selected) - tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; - if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected. - tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; - break; - case QStyleOptionTab::End: - tdi.position = kHIThemeTabPositionLast; - if (selected) - tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; - break; - case QStyleOptionTab::OnlyOneTab: - tdi.position = kHIThemeTabPositionOnly; - break; - } - // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. - if (stretchTabs) { - HIRect hirect = CGRectMake(0, 0, 23, 23); - QPixmap pm(23, 23); - pm.fill(Qt::transparent); - { - QMacCGContext pmcg(&pm); - HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0); - } - QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7); - } else { - HIRect hirect = qt_hirectForQRect(tabRect); - HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0); - } - } - break; - case CE_TabBarTabLabel: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - QStyleOptionTab myTab = *tab; - ThemeTabDirection ttd = getTabDirection(myTab.shape); - bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; - - // Check to see if we use have the same as the system font - // (QComboMenuItem is internal and should never be seen by the - // outside world, unless they read the source, in which case, it's - // their own fault). - bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); - if (verticalTabs || nonDefaultFont || !tab->icon.isNull() - || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) { - int heightOffset = 0; - if (verticalTabs) { - heightOffset = -1; - } else if (nonDefaultFont) { - if (p->fontMetrics().height() == myTab.rect.height()) - heightOffset = 2; - } - myTab.rect.setHeight(myTab.rect.height() + heightOffset); - - QCommonStyle::drawControl(ce, &myTab, p, w); - } else { - p->save(); - CGContextSetShouldAntialias(cg, true); - CGContextSetShouldSmoothFonts(cg, true); - HIThemeTextInfo tti; - tti.version = qt_mac_hitheme_version; - tti.state = tds; - QColor textColor = myTab.palette.windowText().color(); - CGFloat colorComp[] = { static_cast(textColor.redF()), static_cast(textColor.greenF()), - static_cast(textColor.blueF()), static_cast(textColor.alphaF()) }; - CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); - CGContextSetFillColor(cg, colorComp); - switch (d->aquaSizeConstrain(opt, w)) { - default: - case QAquaSizeUnknown: - case QAquaSizeLarge: - tti.fontID = kThemeSystemFont; - break; - case QAquaSizeSmall: - tti.fontID = kThemeSmallSystemFont; - break; - case QAquaSizeMini: - tti.fontID = kThemeMiniSystemFont; - break; - } - tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; - tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; - tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone; - tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n')); - QCFString tabText = qt_mac_removeMnemonics(myTab.text); - QRect r = myTab.rect.adjusted(0, 0, 0, -1); - HIRect bounds = qt_hirectForQRect(r); - HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal); - p->restore(); - } - } - break; -#endif -#ifndef QT_NO_DOCKWIDGET - case CE_DockWidgetTitle: - if (const QDockWidget *dockWidget = qobject_cast(w)) { - bool floating = dockWidget->isFloating(); - if (floating) { - ThemeDrawState tds = d->getDrawState(opt->state); - HIThemeWindowDrawInfo wdi; - wdi.version = qt_mac_hitheme_version; - wdi.state = tds; - wdi.windowType = kThemeMovableDialogWindow; - wdi.titleHeight = opt->rect.height(); - wdi.titleWidth = opt->rect.width(); - wdi.attributes = 0; - - HIRect titleBarRect; - HIRect tmpRect = qt_hirectForQRect(opt->rect); - { - QCFType titleRegion; - QRect newr = opt->rect.adjusted(0, 0, 2, 0); - HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); - ptrHIShapeGetBounds(titleRegion, &tmpRect); - newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); - titleBarRect = qt_hirectForQRect(newr); - } - QMacCGContext cg(p); - HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); - } else { - // fill title bar background - QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); - linearGrad.setColorAt(0, mainWindowGradientBegin); - linearGrad.setColorAt(1, mainWindowGradientEnd); - p->fillRect(opt->rect, linearGrad); - - // draw horizontal lines at top and bottom - p->save(); - p->setPen(mainWindowGradientBegin.lighter(114)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(mainWindowGradientEnd.darker(114)); - p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); - p->restore(); - } - } - - // Draw the text... - if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(opt)) { - if (!dwOpt->title.isEmpty()) { - - const bool verticalTitleBar = dwOpt->verticalTitleBar; - - QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, opt, w); - if (verticalTitleBar) { - QRect rect = dwOpt->rect; - QRect r = rect.transposed(); - - titleRect = QRect(r.left() + rect.bottom() - - titleRect.bottom(), - r.top() + titleRect.left() - rect.left(), - titleRect.height(), titleRect.width()); - - p->translate(r.left(), r.top() + r.width()); - p->rotate(-90); - p->translate(-r.left(), -r.top()); - } - - QFont oldFont = p->font(); - p->setFont(qt_app_fonts_hash()->value("QToolButton", p->font())); - QString text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, - titleRect.width()); - drawItemText(p, titleRect, - Qt::AlignCenter | Qt::TextShowMnemonic, dwOpt->palette, - dwOpt->state & State_Enabled, text, - QPalette::WindowText); - p->setFont(oldFont); - } - } - break; -#endif - case CE_FocusFrame: { - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); - d->drawFocusRing(p, opt->rect, hMargin, vMargin); - break; } - case CE_MenuItem: - case CE_MenuEmptyArea: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - p->fillRect(mi->rect, opt->palette.background()); - QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w); - int tabwidth = mi->tabWidth; - int maxpmw = mi->maxIconWidth; - bool active = mi->state & State_Selected; - bool enabled = mi->state & State_Enabled; - HIRect menuRect = qt_hirectForQRect(mi->menuRect); - HIRect itemRect = qt_hirectForQRect(mi->rect); - HIThemeMenuItemDrawInfo mdi; - mdi.version = qt_mac_hitheme_version; - mdi.itemType = kThemeMenuItemPlain; - if (!mi->icon.isNull()) - mdi.itemType |= kThemeMenuItemHasIcon; - if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) - mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground; - else - mdi.itemType |= kThemeMenuItemPopUpBackground; - if (enabled) - mdi.state = kThemeMenuActive; - else - mdi.state = kThemeMenuDisabled; - if (active) - mdi.state |= kThemeMenuSelected; - QRect contentRect; - if (mi->menuItemType == QStyleOptionMenuItem::Separator) { - // First arg should be &menurect, but wacky stuff happens then. - HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi, - cg, kHIThemeOrientationNormal); - break; - } else { - HIRect cr; - bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent; - if (needAlpha) { - CGContextSaveGState(cg); - CGContextSetAlpha(cg, 0.0); - } - HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, - cg, kHIThemeOrientationNormal, &cr); - if (needAlpha) - CGContextRestoreGState(cg); - if (ce == CE_MenuEmptyArea) - break; - contentRect = qt_qrectForHIRect(cr); - } - int xpos = contentRect.x() + 18; - int checkcol = maxpmw; - if (!enabled) - p->setPen(mi->palette.text().color()); - else if (active) - p->setPen(mi->palette.highlightedText().color()); - else - p->setPen(mi->palette.buttonText().color()); - - if (mi->checked) { - QStyleOption checkmarkOpt; - checkmarkOpt.initFrom(w); - - const int mw = checkcol + macItemFrame; - const int mh = contentRect.height() + macItemFrame; - const int xp = contentRect.x() + macItemFrame; - checkmarkOpt.rect = QRect(xp, contentRect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh); - - checkmarkOpt.state |= State_On; // Always on. Never rendered when off. - checkmarkOpt.state.setFlag(State_Selected, active); - checkmarkOpt.state.setFlag(State_Enabled, enabled); - if (widgetSize == QAquaSizeMini) - checkmarkOpt.state |= State_Mini; - else if (widgetSize == QAquaSizeSmall) - checkmarkOpt.state |= State_Small; - - // We let drawPrimitive(PE_IndicatorMenuCheckMark) pick the right color - checkmarkOpt.palette.setColor(QPalette::HighlightedText, p->pen().color()); - checkmarkOpt.palette.setColor(QPalette::Text, p->pen().color()); - - proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &checkmarkOpt, p, w); - } - if (!mi->icon.isNull()) { - QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled; - // Always be normal or disabled to follow the Mac style. - int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize); - QSize iconSize(smallIconSize, smallIconSize); -#ifndef QT_NO_COMBOBOX - if (const QComboBox *comboBox = qobject_cast(w)) { - iconSize = comboBox->iconSize(); - } -#endif - QPixmap pixmap = mi->icon.pixmap(window, iconSize, mode); - int pixw = pixmap.width() / pixmap.devicePixelRatio(); - int pixh = pixmap.height() / pixmap.devicePixelRatio(); - QRect cr(xpos, contentRect.y(), checkcol, contentRect.height()); - QRect pmr(0, 0, pixw, pixh); - pmr.moveCenter(cr.center()); - p->drawPixmap(pmr.topLeft(), pixmap); - xpos += pixw + 6; - } - - QString s = mi->text; - if (!s.isEmpty()) { - int t = s.indexOf(QLatin1Char('\t')); - int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic - | Qt::TextSingleLine | Qt::AlignAbsolute; - int yPos = contentRect.y(); - if (widgetSize == QAquaSizeMini) - yPos += 1; - p->save(); - if (t >= 0) { - p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); - int xp = contentRect.right() - tabwidth - macRightBorder - - macItemHMargin - macItemFrame + 1; - p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags, - s.mid(t + 1)); - s = s.left(t); - } - - const int xm = macItemFrame + maxpmw + macItemHMargin; - QFont myFont = mi->font; - // myFont may not have any "hard" flags set. We override - // the point size so that when it is resolved against the device, this font will win. - // This is mainly to handle cases where someone sets the font on the window - // and then the combo inherits it and passes it onward. At that point the resolve mask - // is very, very weak. This makes it stonger. - myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF()); - p->setFont(myFont); - p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1, - contentRect.height(), text_flags ^ Qt::AlignRight, s); - p->restore(); - } - } - break; - case CE_MenuHMargin: - case CE_MenuVMargin: - case CE_MenuTearoff: - case CE_MenuScroller: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - p->fillRect(mi->rect, opt->palette.background()); - - HIRect menuRect = qt_hirectForQRect(mi->menuRect); - HIRect itemRect = qt_hirectForQRect(mi->rect); - HIThemeMenuItemDrawInfo mdi; - mdi.version = qt_mac_hitheme_version; - if (!(opt->state & State_Enabled)) - mdi.state = kThemeMenuDisabled; - else if (opt->state & State_Selected) - mdi.state = kThemeMenuSelected; - else - mdi.state = kThemeMenuActive; - if (ce == CE_MenuScroller) { - if (opt->state & State_DownArrow) - mdi.itemType = kThemeMenuItemScrollDownArrow; - else - mdi.itemType = kThemeMenuItemScrollUpArrow; - } else { - mdi.itemType = kThemeMenuItemPlain; - } - HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, - cg, - kHIThemeOrientationNormal, 0); - if (ce == CE_MenuTearoff) { - p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine)); - p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1, - mi->rect.x() + mi->rect.width() - 4, - mi->rect.y() + mi->rect.height() / 2 - 1); - p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine)); - p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2, - mi->rect.x() + mi->rect.width() - 4, - mi->rect.y() + mi->rect.height() / 2); - } - } - break; - case CE_MenuBarItem: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - HIRect menuRect = qt_hirectForQRect(mi->menuRect); - HIRect itemRect = qt_hirectForQRect(mi->rect); - - const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken); - if (selected) { - // Draw a selected menu item background: - HIThemeMenuItemDrawInfo mdi; - mdi.version = qt_mac_hitheme_version; - mdi.state = kThemeMenuSelected; - mdi.itemType = kThemeMenuItemPlain; - HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0); - } else { - // Draw the toolbar background: - HIThemeMenuBarDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeMenuBarNormal; - bdi.attributes = 0; - HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal); - } - - if (!mi->icon.isNull()) { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - drawItemPixmap(p, mi->rect, - Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip - | Qt::TextSingleLine, - mi->icon.pixmap(window, QSize(iconExtent, iconExtent), - (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled)); - } else { - drawItemText(p, mi->rect, - Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip - | Qt::TextSingleLine, - mi->palette, mi->state & State_Enabled, - mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText); - } - } - break; - case CE_MenuBarEmptyArea: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - HIThemeMenuBarDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeMenuBarNormal; - bdi.attributes = 0; - HIRect hirect = qt_hirectForQRect(mi->rect); - HIThemeDrawMenuBarBackground(&hirect, &bdi, cg, - kHIThemeOrientationNormal); - break; - } - case CE_ProgressBarContents: - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { - HIThemeTrackDrawInfo tdi; - tdi.version = qt_mac_hitheme_version; - tdi.reserved = 0; - bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0); - const bool vertical = pb->orientation == Qt::Vertical; - const bool inverted = pb->invertedAppearance; - bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)); - if (inverted) - reverse = !reverse; - switch (d->aquaSizeConstrain(opt, w)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - tdi.kind = !isIndeterminate ? kThemeLargeProgressBar - : kThemeLargeIndeterminateBar; - break; - case QAquaSizeMini: - case QAquaSizeSmall: - tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar; - break; - } - tdi.bounds = qt_hirectForQRect(pb->rect); - tdi.max = pb->maximum; - tdi.min = pb->minimum; - tdi.value = pb->progress; - tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - - if (isIndeterminate) { - if (QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject))) - tdi.trackInfo.progress.phase = animation->animationStep(); - else if (opt->styleObject) - d->startAnimation(new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject)); - } else { - d->stopAnimation(opt->styleObject); - } - if (!(pb->state & State_Active)) - tdi.enableState = kThemeTrackInactive; - else if (!(pb->state & State_Enabled)) - tdi.enableState = kThemeTrackDisabled; - else - tdi.enableState = kThemeTrackActive; - HIThemeOrientation drawOrientation = kHIThemeOrientationNormal; - if (reverse) { - if (vertical) { - drawOrientation = kHIThemeOrientationInverted; - } else { - CGContextSaveGState(cg); - CGContextTranslateCTM(cg, pb->rect.width(), 0); - CGContextScaleCTM(cg, -1, 1); - } - } - HIThemeDrawTrack(&tdi, 0, cg, drawOrientation); - if (reverse && !vertical) - CGContextRestoreGState(cg); - } - break; - case CE_ProgressBarLabel: - case CE_ProgressBarGroove: - break; - case CE_SizeGrip: { - if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { - HIThemeGrowBoxDrawInfo gdi; - gdi.version = qt_mac_hitheme_version; - gdi.state = tds; - gdi.kind = kHIThemeGrowBoxKindNormal; - gdi.direction = kThemeGrowRight | kThemeGrowDown; - gdi.size = kHIThemeGrowBoxSizeNormal; - HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y()); - HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal); - } else { - // It isn't possible to draw a transparent size grip with the - // native API, so we do it ourselves here. - const bool metal = qt_mac_is_metal(w); - QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192); - QPen metalHighlight = QColor(5, 5, 5, 192); - lineColor.setWidth(1); - p->save(); - p->setRenderHint(QPainter::Antialiasing); - p->setPen(lineColor); - const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); - const int NumLines = metal ? 4 : 3; - for (int l = 0; l < NumLines; ++l) { - const int offset = (l * 4 + (metal ? 2 : 3)); - QPoint start, end; - if (layoutDirection == Qt::LeftToRight) { - start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); - end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); - } else { - start = QPoint(offset, opt->rect.height() - 1); - end = QPoint(1, opt->rect.height() - offset); - } - p->drawLine(start, end); - if (metal) { - p->setPen(metalHighlight); - p->setRenderHint(QPainter::Antialiasing, false); - p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1)); - p->setRenderHint(QPainter::Antialiasing, true); - p->setPen(lineColor); - } - } - p->restore(); - } - break; - } - case CE_Splitter: - if (opt->rect.width() > 1 && opt->rect.height() > 1){ - HIThemeSplitterDrawInfo sdi; - sdi.version = qt_mac_hitheme_version; - sdi.state = tds; - sdi.adornment = kHIThemeSplitterAdornmentMetal; - HIRect hirect = qt_hirectForQRect(opt->rect); - HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal); - } else { - QPen oldPen = p->pen(); - p->setPen(opt->palette.dark().color()); - if (opt->state & QStyle::State_Horizontal) - p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); - else - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(oldPen); - } - break; - case CE_RubberBand: - if (const QStyleOptionRubberBand *rubber = qstyleoption_cast(opt)) { - QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight)); - if (!rubber->opaque) { - QColor strokeColor; - // I retrieved these colors from the Carbon-Dev mailing list - strokeColor.setHsvF(0, 0, 0.86, 1.0); - fillColor.setHsvF(0, 0, 0.53, 0.25); - if (opt->rect.width() * opt->rect.height() <= 3) { - p->fillRect(opt->rect, strokeColor); - } else { - QPen oldPen = p->pen(); - QBrush oldBrush = p->brush(); - QPen pen(strokeColor); - p->setPen(pen); - p->setBrush(fillColor); - QRect adjusted = opt->rect.adjusted(1, 1, -1, -1); - if (adjusted.isValid()) - p->drawRect(adjusted); - p->setPen(oldPen); - p->setBrush(oldBrush); - } - } else { - p->fillRect(opt->rect, fillColor); - } - } - break; -#ifndef QT_NO_TOOLBAR - case CE_ToolBar: { - const QStyleOptionToolBar *toolBar = qstyleoption_cast(opt); - - // Unified title and toolbar drawing. In this mode the cocoa platform plugin will - // fill the top toolbar area part with a background gradient that "unifies" with - // the title bar. The following code fills the toolBar area with transparent pixels - // to make that gradient visible. - if (w) { -#ifndef QT_NO_MAINWINDOW - if (QMainWindow * mainWindow = qobject_cast(w->window())) { - if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) { - - // fill with transparent pixels. - p->save(); - p->setCompositionMode(QPainter::CompositionMode_Source); - p->fillRect(opt->rect, Qt::transparent); - p->restore(); - - // Drow a horizontal sepearator line at the toolBar bottom if the "unified" area ends here. - // There might be additional toolbars or other widgets such as tab bars in document - // mode below. Determine this by making a unified toolbar area test for the row below - // this toolbar. - QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); - bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); - if (isEndOfUnifiedArea) { - SInt32 margin; - GetThemeMetric(kThemeMetricSeparatorSize, &margin); - CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); - HIThemeSeparatorDrawInfo separatorDrawInfo; - separatorDrawInfo.version = 0; - separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive; - QMacCGContext cg(p); - HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal); - } - break; - } - } -#endif - } - - // draw background gradient - QLinearGradient linearGrad; - if (opt->state & State_Horizontal) - linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom()); - else - linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0); - - linearGrad.setColorAt(0, mainWindowGradientBegin); - linearGrad.setColorAt(1, mainWindowGradientEnd); - p->fillRect(opt->rect, linearGrad); - - p->save(); - if (opt->state & State_Horizontal) { - p->setPen(mainWindowGradientBegin.lighter(114)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(mainWindowGradientEnd.darker(114)); - p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight()); - - } else { - p->setPen(mainWindowGradientBegin.lighter(114)); - p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); - p->setPen(mainWindowGradientEnd.darker(114)); - p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); - } - p->restore(); - - - } break; -#endif - default: - QCommonStyle::drawControl(ce, opt, p, w); - break; - } -} - -static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir) -{ - if (dir == Qt::RightToLeft) { - rect->adjust(-right, top, -left, bottom); - } else { - rect->adjust(left, top, right, bottom); - } -} - -QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - QRect rect; - int controlSize = getControlSize(opt, widget); - - switch (sr) { - case SE_ItemViewItemText: - if (const QStyleOptionViewItem *vopt = qstyleoption_cast(opt)) { - int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget); - // We add the focusframeargin between icon and text in commonstyle - rect = QCommonStyle::subElementRect(sr, opt, widget); - if (vopt->features & QStyleOptionViewItem::HasDecoration) - rect.adjust(-fw, 0, 0, 0); - } - break; - case SE_ToolBoxTabContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); - break; - case SE_PushButtonContents: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - // Unlike Carbon, we want the button to always be drawn inside its bounds. - // Therefore, the button is a bit smaller, so that even if it got focus, - // the focus 'shadow' will be inside. Adjust the content rect likewise. - HIThemeButtonDrawInfo bdi; - d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi); - HIRect contentRect = d->pushButtonContentBounds(btn, &bdi); - rect = qt_qrectForHIRect(contentRect); - } - break; - case SE_HeaderLabel: { - int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); - rect.setRect(opt->rect.x() + margin, opt->rect.y(), - opt->rect.width() - margin * 2, opt->rect.height() - 2); - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - // Subtract width needed for arrow, if there is one - if (header->sortIndicator != QStyleOptionHeader::None) { - if (opt->state & State_Horizontal) - rect.setWidth(rect.width() - (opt->rect.height() / 2) - (margin * 2)); - else - rect.setHeight(rect.height() - (opt->rect.width() / 2) - (margin * 2)); - } - } - rect = visualRect(opt->direction, opt->rect, rect); - break; - } - case SE_ProgressBarGroove: - // Wrong in the secondary dimension, but accurate enough in the main dimension. - rect = opt->rect; - break; - case SE_ProgressBarLabel: - break; - case SE_ProgressBarContents: - rect = opt->rect; - break; - case SE_TreeViewDisclosureItem: { - HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(), - opt->rect.width(), opt->rect.height()); - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeStateActive; - bdi.kind = kThemeDisclosureButton; - bdi.value = kThemeDisclosureRight; - bdi.adornment = kThemeAdornmentNone; - HIRect contentRect; - HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect); - QCFType shape; - HIRect outRect; - HIThemeGetButtonShape(&inRect, &bdi, &shape); - ptrHIShapeGetBounds(shape, &outRect); - rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y), - int(contentRect.origin.x - outRect.origin.x + DisclosureOffset), - int(outRect.size.height)); - break; - } -#ifndef QT_NO_TABWIDGET - case SE_TabWidgetLeftCorner: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - switch (twf->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize); - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()), - twf->leftCornerWidgetSize); - break; - default: - break; - } - rect = visualRect(twf->direction, twf->rect, rect); - } - break; - case SE_TabWidgetRightCorner: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - switch (twf->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0), - twf->rightCornerWidgetSize); - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), - twf->rect.height() - twf->rightCornerWidgetSize.height()), - twf->rightCornerWidgetSize); - break; - default: - break; - } - rect = visualRect(twf->direction, twf->rect, rect); - } - break; - case SE_TabWidgetTabContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - if (twf->lineWidth != 0) { - switch (getTabDirection(twf->shape)) { - case kThemeTabNorth: - rect.adjust(+1, +14, -1, -1); - break; - case kThemeTabSouth: - rect.adjust(+1, +1, -1, -14); - break; - case kThemeTabWest: - rect.adjust(+14, +1, -1, -1); - break; - case kThemeTabEast: - rect.adjust(+1, +1, -14, -1); - } - } - } - break; - case SE_TabBarTabText: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - d->tabLayout(tab, widget, &rect); - } - break; - case SE_TabBarTabLeftButton: - case SE_TabBarTabRightButton: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - bool selected = tab->state & State_Selected; - int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); - int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); - int hpadding = 5; - - bool verticalTabs = tab->shape == QTabBar::RoundedEast - || tab->shape == QTabBar::RoundedWest - || tab->shape == QTabBar::TriangularEast - || tab->shape == QTabBar::TriangularWest; - - QRect tr = tab->rect; - if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth) - verticalShift = -verticalShift; - if (verticalTabs) { - qSwap(horizontalShift, verticalShift); - horizontalShift *= -1; - verticalShift *= -1; - } - if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest) - horizontalShift = -horizontalShift; - - tr.adjust(0, 0, horizontalShift, verticalShift); - if (selected) - { - tr.setBottom(tr.bottom() - verticalShift); - tr.setRight(tr.right() - horizontalShift); - } - - QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize; - int w = size.width(); - int h = size.height(); - int midHeight = static_cast(qCeil(float(tr.height() - h) / 2)); - int midWidth = ((tr.width() - w) / 2); - - bool atTheTop = true; - switch (tab->shape) { - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - atTheTop = (sr == SE_TabBarTabLeftButton); - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - atTheTop = (sr == SE_TabBarTabRightButton); - break; - default: - if (sr == SE_TabBarTabLeftButton) - rect = QRect(tab->rect.x() + hpadding, midHeight, w, h); - else - rect = QRect(tab->rect.right() - w - hpadding, midHeight, w, h); - rect = visualRect(tab->direction, tab->rect, rect); - } - if (verticalTabs) { - if (atTheTop) - rect = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h); - else - rect = QRect(midWidth, tr.y() + hpadding, w, h); - } - } - break; -#endif - case SE_LineEditContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); -#ifndef QT_NO_COMBOBOX - if (widget && qobject_cast(widget->parentWidget())) - rect.adjust(-1, -2, 0, 0); - else -#endif - rect.adjust(-1, -1, 0, +1); - break; - case SE_CheckBoxLayoutItem: - rect = opt->rect; - if (controlSize == QAquaSizeLarge) { - setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction); - } else if (controlSize == QAquaSizeSmall) { - setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction); - } else { - setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction); - } - break; - case SE_ComboBoxLayoutItem: -#ifndef QT_NO_TOOLBAR - if (widget && qobject_cast(widget->parentWidget())) { - // Do nothing, because QToolbar needs the entire widget rect. - // Otherwise it will be clipped. Equivalent to - // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without - // all the hassle. - } else -#endif - { - rect = opt->rect; - if (controlSize == QAquaSizeLarge) { - rect.adjust(+3, +2, -3, -4); - } else if (controlSize == QAquaSizeSmall) { - setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction); - } else { - setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction); - } - } - break; - case SE_LabelLayoutItem: - rect = opt->rect; - setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction); - break; - case SE_ProgressBarLayoutItem: { - rect = opt->rect; - int bottom = SIZE(3, 8, 8); - if (opt->state & State_Horizontal) { - rect.adjust(0, +1, 0, -bottom); - } else { - setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction); - } - break; - } - case SE_PushButtonLayoutItem: - if (const QStyleOptionButton *buttonOpt - = qstyleoption_cast(opt)) { - if ((buttonOpt->features & QStyleOptionButton::Flat)) - break; // leave rect alone - } - rect = opt->rect; - if (controlSize == QAquaSizeLarge) { - rect.adjust(+6, +4, -6, -8); - } else if (controlSize == QAquaSizeSmall) { - rect.adjust(+5, +4, -5, -6); - } else { - rect.adjust(+1, 0, -1, -2); - } - break; - case SE_RadioButtonLayoutItem: - rect = opt->rect; - if (controlSize == QAquaSizeLarge) { - setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */, - 0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction); - } else if (controlSize == QAquaSizeSmall) { - rect.adjust(0, +6, 0 /* fix */, -5); - } else { - rect.adjust(0, +6, 0 /* fix */, -7); - } - break; - case SE_SliderLayoutItem: - if (const QStyleOptionSlider *sliderOpt - = qstyleoption_cast(opt)) { - rect = opt->rect; - if (sliderOpt->tickPosition == QSlider::NoTicks) { - int above = SIZE(3, 0, 2); - int below = SIZE(4, 3, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.adjust(0, +above, 0, -below); - } else { - rect.adjust(+above, 0, -below, 0); //### Seems that QSlider flip the position of the ticks in reverse mode. - } - } else if (sliderOpt->tickPosition == QSlider::TicksAbove) { - int below = SIZE(3, 2, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.setHeight(rect.height() - below); - } else { - rect.setWidth(rect.width() - below); - } - } else if (sliderOpt->tickPosition == QSlider::TicksBelow) { - int above = SIZE(3, 2, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.setTop(rect.top() + above); - } else { - rect.setLeft(rect.left() + above); - } - } - } - break; - case SE_FrameLayoutItem: - // hack because QStyleOptionFrame doesn't have a frameStyle member - if (const QFrame *frame = qobject_cast(widget)) { - rect = opt->rect; - switch (frame->frameStyle() & QFrame::Shape_Mask) { - case QFrame::HLine: - rect.adjust(0, +1, 0, -1); - break; - case QFrame::VLine: - rect.adjust(+1, 0, -1, 0); - break; - default: - ; - } - } - break; - case SE_GroupBoxLayoutItem: - rect = opt->rect; - if (const QStyleOptionGroupBox *groupBoxOpt = - qstyleoption_cast(opt)) { - /* - AHIG is very inconsistent when it comes to group boxes. - Basically, we make sure that (non-checkable) group boxes - and tab widgets look good when laid out side by side. - */ - if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox - | QStyle::SC_GroupBoxLabel)) { - int delta; - if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) { - delta = SIZE(8, 4, 4); // guess - } else { - delta = SIZE(15, 12, 12); // guess - } - rect.setTop(rect.top() + delta); - } - } - rect.setBottom(rect.bottom() - 1); - break; -#ifndef QT_NO_TABWIDGET - case SE_TabWidgetLayoutItem: - if (const QStyleOptionTabWidgetFrame *tabWidgetOpt = - qstyleoption_cast(opt)) { - /* - AHIG specifies "12 or 14" as the distance from the window - edge. We choose 14 and since the default top margin is 20, - the overlap is 6. - */ - rect = tabWidgetOpt->rect; - if (tabWidgetOpt->shape == QTabBar::RoundedNorth) - rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */)); - } - break; -#endif -#ifndef QT_NO_DOCKWIDGET - case SE_DockWidgetCloseButton: - case SE_DockWidgetFloatButton: - case SE_DockWidgetTitleBarText: - case SE_DockWidgetIcon: { - int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); - int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); - QRect srect = opt->rect; - - const QStyleOptionDockWidget *dwOpt - = qstyleoption_cast(opt); - bool canClose = dwOpt == 0 ? true : dwOpt->closable; - bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; - - const bool verticalTitleBar = dwOpt->verticalTitleBar; - - // If this is a vertical titlebar, we transpose and work as if it was - // horizontal, then transpose again. - if (verticalTitleBar) - srect = srect.transposed(); - - do { - int right = srect.right(); - int left = srect.left(); - - QRect closeRect; - if (canClose) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, - opt, widget).actualSize(QSize(iconSize, iconSize)); - sz += QSize(buttonMargin, buttonMargin); - if (verticalTitleBar) - sz = sz.transposed(); - closeRect = QRect(left, - srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - left = closeRect.right() + 1; - } - if (sr == SE_DockWidgetCloseButton) { - rect = closeRect; - break; - } - - QRect floatRect; - if (canFloat) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, - opt, widget).actualSize(QSize(iconSize, iconSize)); - sz += QSize(buttonMargin, buttonMargin); - if (verticalTitleBar) - sz = sz.transposed(); - floatRect = QRect(left, - srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - left = floatRect.right() + 1; - } - if (sr == SE_DockWidgetFloatButton) { - rect = floatRect; - break; - } - - QRect iconRect; - if (const QDockWidget *dw = qobject_cast(widget)) { - QIcon icon; - if (dw->isFloating()) - icon = dw->windowIcon(); - if (!icon.isNull() - && icon.cacheKey() != QApplication::windowIcon().cacheKey()) { - QSize sz = icon.actualSize(QSize(rect.height(), rect.height())); - if (verticalTitleBar) - sz = sz.transposed(); - iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - right = iconRect.left() - 1; - } - } - if (sr == SE_DockWidgetIcon) { - rect = iconRect; - break; - } - - QRect textRect = QRect(left, srect.top(), - right - left, srect.height()); - if (sr == SE_DockWidgetTitleBarText) { - rect = textRect; - break; - } - } while (false); - - if (verticalTitleBar) { - rect = QRect(srect.left() + rect.top() - srect.top(), - srect.top() + srect.right() - rect.right(), - rect.height(), rect.width()); - } else { - rect = visualRect(opt->direction, srect, rect); - } - break; - } -#endif - default: - rect = QCommonStyle::subElementRect(sr, opt, widget); - break; - } - return rect; -} - -static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg) -{ - QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5); - HIThemePopupArrowDrawInfo padi; - padi.version = qt_mac_hitheme_version; - padi.state = tds; - padi.orientation = kThemeArrowDown; - padi.size = kThemeArrow7pt; - HIRect hirect = qt_hirectForQRect(arrowRect); - HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); -} - -void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); - QMacCGContext cg(p); - QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : - QStyleHelper::styleObjectWindow(opt->styleObject); - const_cast(d)->resolveCurrentNSView(window); - switch (cc) { - case CC_Slider: - case CC_ScrollBar: - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - if (slider->state & State_Sunken) { - if (cc == CC_Slider) { - if (slider->activeSubControls == SC_SliderHandle) - tdi.trackInfo.slider.pressState = kThemeThumbPressed; - else if (slider->activeSubControls == SC_SliderGroove) - tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed; - } else { - if (slider->activeSubControls == SC_ScrollBarSubLine - || slider->activeSubControls == SC_ScrollBarAddLine) { - // This test looks complex but it basically boils down - // to the following: The "RTL look" on the mac also - // changed the directions of the controls, that's not - // what people expect (an arrow is an arrow), so we - // kind of fake and say the opposite button is hit. - // This works great, up until 10.4 which broke the - // scroll bars, so I also have actually do something - // similar when I have an upside down scroll bar - // because on Tiger I only "fake" the reverse stuff. - bool reverseHorizontal = (slider->direction == Qt::RightToLeft - && slider->orientation == Qt::Horizontal); - - if ((reverseHorizontal - && slider->activeSubControls == SC_ScrollBarAddLine) - || (!reverseHorizontal - && slider->activeSubControls == SC_ScrollBarSubLine)) { - tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed - | kThemeLeftOutsideArrowPressed; - } else { - tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed - | kThemeRightOutsideArrowPressed; - } - } else if (slider->activeSubControls == SC_ScrollBarAddPage) { - tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed; - } else if (slider->activeSubControls == SC_ScrollBarSubPage) { - tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed; - } else if (slider->activeSubControls == SC_ScrollBarSlider) { - tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed; - } - } - } - HIRect macRect; - bool tracking = slider->sliderPosition == slider->sliderValue; - if (!tracking) { - // Small optimization, the same as q->subControlRect - QCFType shape; - HIThemeGetTrackThumbShape(&tdi, &shape); - ptrHIShapeGetBounds(shape, &macRect); - tdi.value = slider->sliderValue; - } - - // Remove controls from the scroll bar if it is to short to draw them correctly. - // This is done in two stages: first the thumb indicator is removed when it is - // no longer possible to move it, second the up/down buttons are removed when - // there is not enough space for them. - if (cc == CC_ScrollBar) { - if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject)) - QMacStylePrivate::scrollBars.append(QPointer(opt->styleObject)); - const int scrollBarLength = (slider->orientation == Qt::Horizontal) - ? slider->rect.width() : slider->rect.height(); - const QStyleHelper::WidgetSizePolicy sizePolicy = QStyleHelper::widgetSizePolicy(widget, opt); - if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy)) - tdi.attributes &= ~kThemeTrackShowThumb; - if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy)) - tdi.enableState = kThemeTrackNothingToScroll; - } else { - if (!(slider->subControls & SC_SliderHandle)) - tdi.attributes &= ~kThemeTrackShowThumb; - if (!(slider->subControls & SC_SliderGroove)) - tdi.attributes |= kThemeTrackHideTrack; - } - - const bool isHorizontal = slider->orientation == Qt::Horizontal; - - if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) { - bool wasActive = false; - CGFloat opacity = 0.0; - CGFloat expandScale = 1.0; - CGFloat expandOffset = -1.0; - bool shouldExpand = false; - const CGFloat maxExpandScale = tdi.kind == kThemeSmallScrollBar ? 11.0 / 7.0 : 13.0 / 9.0; - - if (QObject *styleObject = opt->styleObject) { - int oldPos = styleObject->property("_q_stylepos").toInt(); - int oldMin = styleObject->property("_q_stylemin").toInt(); - int oldMax = styleObject->property("_q_stylemax").toInt(); - QRect oldRect = styleObject->property("_q_stylerect").toRect(); - QStyle::State oldState = static_cast(styleObject->property("_q_stylestate").value()); - uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); - - // a scrollbar is transient when the scrollbar itself and - // its sibling are both inactive (ie. not pressed/hovered/moved) - bool transient = !opt->activeSubControls && !(slider->state & State_On); - - if (!transient || - oldPos != slider->sliderPosition || - oldMin != slider->minimum || - oldMax != slider->maximum || - oldRect != slider->rect || - oldState != slider->state || - oldActiveControls != slider->activeSubControls) { - - // if the scrollbar is transient or its attributes, geometry or - // state has changed, the opacity is reset back to 100% opaque - opacity = 1.0; - - styleObject->setProperty("_q_stylepos", slider->sliderPosition); - styleObject->setProperty("_q_stylemin", slider->minimum); - styleObject->setProperty("_q_stylemax", slider->maximum); - styleObject->setProperty("_q_stylerect", slider->rect); - styleObject->setProperty("_q_stylestate", static_cast(slider->state)); - styleObject->setProperty("_q_stylecontrols", static_cast(slider->activeSubControls)); - - QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); - if (transient) { - if (!anim) { - anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject); - d->startAnimation(anim); - } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) { - // the scrollbar was already fading out while the - // state changed -> restart the fade out animation - anim->setCurrentTime(0); - } - } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { - d->stopAnimation(styleObject); - } - } - - QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); - if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { - // once a scrollbar was active (hovered/pressed), it retains - // the active look even if it's no longer active while fading out - if (oldActiveControls) - anim->setActive(true); - - wasActive = anim->wasActive(); - opacity = anim->currentValue(); - } - - shouldExpand = (opt->activeSubControls || wasActive); - if (shouldExpand) { - if (!anim && !oldActiveControls) { - // Start expand animation only once and when entering - anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject); - d->startAnimation(anim); - } - if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) { - expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue(); - expandOffset = 5.5 * anim->currentValue() - 1; - } else { - // Keep expanded state after the animation ends, and when fading out - expandScale = maxExpandScale; - expandOffset = 4.5; - } - } - } - - CGContextSaveGState(cg); - [NSGraphicsContext saveGraphicsState]; - - [NSGraphicsContext setCurrentContext:[NSGraphicsContext - graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]]; - NSScroller *scroller = reinterpret_cast(d->nsscroller); - [scroller initWithFrame:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; - // mac os behaviour: as soon as one color channel is >= 128, - // the bg is considered bright, scroller is dark - const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); - const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && - bgColor.blue() < 128; - if (isDarkBg) - [scroller setKnobStyle:NSScrollerKnobStyleLight]; - else - [scroller setKnobStyle:NSScrollerKnobStyleDefault]; - - [scroller setControlSize:(tdi.kind == kThemeSmallScrollBar ? NSMiniControlSize - : NSRegularControlSize)]; - [scroller setBounds:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())]; - [scroller setScrollerStyle:NSScrollerStyleOverlay]; - - CGContextBeginTransparencyLayer(cg, NULL); - CGContextSetAlpha(cg, opacity); - - // Draw the track when hovering - if (opt->activeSubControls || wasActive) { - NSRect rect = [scroller bounds]; - if (shouldExpand) { - if (isHorizontal) - rect.origin.y += 4.5 - expandOffset; - else - rect.origin.x += 4.5 - expandOffset; - } - [scroller drawKnobSlotInRect:rect highlight:YES]; - } - - const qreal length = slider->maximum - slider->minimum + slider->pageStep; - const qreal proportion = slider->pageStep / length; - qreal value = (slider->sliderValue - slider->minimum) / length; - if (isHorizontal && slider->direction == Qt::RightToLeft) - value = 1.0 - value - proportion; - - [scroller setKnobProportion:1.0]; - - const int minKnobWidth = 26; - - if (isHorizontal) { - const qreal plannedWidth = proportion * slider->rect.width(); - const qreal width = qMax(minKnobWidth, plannedWidth); - const qreal totalWidth = slider->rect.width() + plannedWidth - width; - [scroller setFrame:NSMakeRect(0, 0, width, slider->rect.height())]; - if (shouldExpand) { - CGContextScaleCTM(cg, 1, expandScale); - CGContextTranslateCTM(cg, value * totalWidth, -expandOffset); - } else { - CGContextTranslateCTM(cg, value * totalWidth, 1); - } - } else { - const qreal plannedHeight = proportion * slider->rect.height(); - const qreal height = qMax(minKnobWidth, plannedHeight); - const qreal totalHeight = slider->rect.height() + plannedHeight - height; - [scroller setFrame:NSMakeRect(0, 0, slider->rect.width(), height)]; - if (shouldExpand) { - CGContextScaleCTM(cg, expandScale, 1); - CGContextTranslateCTM(cg, -expandOffset, value * totalHeight); - } else { - CGContextTranslateCTM(cg, 1, value * totalHeight); - } - } - if (length > 0.0) { - [scroller layout]; - [scroller drawKnob]; - } - - CGContextEndTransparencyLayer(cg); - - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(cg); - } else { - d->stopAnimation(opt->styleObject); - - if (cc == CC_Slider) { - // Fix min and max positions. (See also getSliderInfo() - // for the slider values adjustments.) - // HITheme seems to have forgotten how to render - // a slide at those positions, leaving a gap between - // the knob and the ends of the track. - // We fix this by rendering the track first, and then - // the knob on top. However, in order to not clip the - // knob, we reduce the the drawing rect for the track. - HIRect bounds = tdi.bounds; - if (isHorizontal) { - tdi.bounds.size.width -= 2; - tdi.bounds.origin.x += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) - tdi.bounds.origin.y -= 2; - else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) - tdi.bounds.origin.y += 3; - } else { - tdi.bounds.size.height -= 2; - tdi.bounds.origin.y += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right - tdi.bounds.origin.x -= 4; - else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left - tdi.bounds.origin.x += 2; - } - - // Yosemite demands its blue progress track when no tickmarks are present - if (!(slider->subControls & SC_SliderTickmarks)) { - QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; - QCocoaWidget cw = QCocoaWidget(sliderKind, QAquaSizeLarge); - NSSlider *sl = (NSSlider *)d->cocoaControl(cw); - sl.minValue = slider->minimum; - sl.maxValue = slider->maximum; - sl.intValue = slider->sliderValue; - sl.enabled = slider->state & QStyle::State_Enabled; - d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(NSRect rect, CGContextRef ctx) { - if (slider->upsideDown) { - if (isHorizontal) { - CGContextTranslateCTM(ctx, rect.size.width, 0); - CGContextScaleCTM(ctx, -1, 1); - } - } else if (!isHorizontal) { - CGContextTranslateCTM(ctx, 0, rect.size.height); - CGContextScaleCTM(ctx, 1, -1); - } - [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:NO]; - // No need to restore the CTM later, the context has been saved - // and will be restored at the end of drawNSViewInRect() - }); - tdi.attributes |= kThemeTrackHideTrack; - } else { - tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus); - HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, - kHIThemeOrientationNormal); - tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb; - } - - tdi.bounds = bounds; - } - - if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) { - - HIRect bounds; - // As part of fixing the min and max positions, - // we need to adjust the tickmarks as well - bounds = tdi.bounds; - if (slider->orientation == Qt::Horizontal) { - tdi.bounds.size.width += 2; - tdi.bounds.origin.x -= 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) - tdi.bounds.origin.y -= 2; - } else { - tdi.bounds.size.height += 3; - tdi.bounds.origin.y -= 3; - tdi.bounds.origin.y += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left - tdi.bounds.origin.x -= 2; - } - - if (qt_mac_is_metal(widget)) { - if (tdi.enableState == kThemeTrackInactive) - tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like - } - int interval = slider->tickInterval; - if (interval == 0) { - interval = slider->pageStep; - if (interval == 0) - interval = slider->singleStep; - if (interval == 0) - interval = 1; - } - int numMarks = 1 + ((slider->maximum - slider->minimum) / interval); - - if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) { - // They asked for both, so we'll give it to them. - tdi.trackInfo.slider.thumbDir = kThemeThumbDownward; - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; - // 10.10 and above need a slight shift - if (slider->orientation == Qt::Vertical) - tdi.bounds.origin.x -= 2; - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - // Reset to plain thumb to be drawn further down - tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; - } else { - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - } - - tdi.bounds = bounds; - } - - if (cc == CC_Slider) { - // Still as part of fixing the min and max positions, - // we also adjust the knob position. We can do this - // because it's rendered separately from the track. - if (slider->orientation == Qt::Vertical) { - if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right - tdi.bounds.origin.x -= 2; - } - } - - HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, - kHIThemeOrientationNormal); - } - } - break; -#ifndef QT_NO_SPINBOX - case CC_SpinBox: - if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { - QStyleOptionSpinBox newSB = *sb; - if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { - SInt32 frame_size; - GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size); - - QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); - lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size); - - HIThemeFrameDrawInfo fdi; - fdi.version = qt_mac_hitheme_version; - fdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; - fdi.kind = kHIThemeFrameTextFieldSquare; - fdi.isFocused = false; - HIRect hirect = qt_hirectForQRect(lineeditRect); - HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal); - } - if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget); - switch (aquaSize) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - bdi.kind = kThemeIncDecButton; - break; - case QAquaSizeMini: - bdi.kind = kThemeIncDecButtonMini; - break; - case QAquaSizeSmall: - bdi.kind = kThemeIncDecButtonSmall; - break; - } - if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled - | QAbstractSpinBox::StepDownEnabled))) - tds = kThemeStateUnavailable; - if (sb->activeSubControls == SC_SpinBoxDown - && (sb->state & State_Sunken)) - tds = kThemeStatePressedDown; - else if (sb->activeSubControls == SC_SpinBoxUp - && (sb->state & State_Sunken)) - tds = kThemeStatePressedUp; - if (tds == kThemeStateInactive) - bdi.state = kThemeStateActive; - else - bdi.state = tds; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - - QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); - - updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); - HIRect newRect = qt_hirectForQRect(updown); - QRect off_rct; - HIRect outRect; - HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect); - off_rct.setRect(int(newRect.origin.x - outRect.origin.x), - int(newRect.origin.y - outRect.origin.y), - int(outRect.size.width - newRect.size.width), - int(outRect.size.height - newRect.size.height)); - - newRect = qt_hirectForQRect(updown, off_rct); - if (tds == kThemeStateInactive) - d->drawColorlessButton(newRect, &bdi, p, sb); - else - HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); - } - } - break; -#endif - case CC_ComboBox: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - HIThemeButtonDrawInfo bdi; - d->initComboboxBdi(combo, &bdi, widget, tds); - HIRect rect = qt_hirectForQRect(combo->rect); - if (combo->editable) - rect.origin.y += tds == kThemeStateInactive ? 1 : 2; - if (tds != kThemeStateInactive) - QMacStylePrivate::drawCombobox(rect, bdi, p); - else if (!widget && combo->editable) { - QCocoaWidget cw = cocoaWidgetFromHIThemeButtonKind(bdi.kind); - NSView *cb = d->cocoaControl(cw); - QRect r = combo->rect.adjusted(3, 0, 0, 0); - d->drawNSViewInRect(cw, cb, r, p, widget != 0); - } else - d->drawColorlessButton(rect, &bdi, p, opt); - } - break; - case CC_TitleBar: - if (const QStyleOptionTitleBar *titlebar - = qstyleoption_cast(opt)) { - if (titlebar->state & State_Active) { - if (titlebar->titleBarState & State_Active) - tds = kThemeStateActive; - else - tds = kThemeStateInactive; - } else { - tds = kThemeStateInactive; - } - - HIThemeWindowDrawInfo wdi; - wdi.version = qt_mac_hitheme_version; - wdi.state = tds; - wdi.windowType = QtWinType; - wdi.titleHeight = titlebar->rect.height(); - wdi.titleWidth = titlebar->rect.width(); - wdi.attributes = kThemeWindowHasTitleText; - // It seems HIThemeDrawTitleBarWidget is not able to draw a dirty - // close button, so use HIThemeDrawWindowFrame instead. - if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton) - wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty; - - HIRect titleBarRect; - HIRect tmpRect = qt_hirectForQRect(titlebar->rect); - { - QCFType titleRegion; - QRect newr = titlebar->rect.adjusted(0, 0, 2, 0); - HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion); - ptrHIShapeGetBounds(titleRegion, &tmpRect); - newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y)); - titleBarRect = qt_hirectForQRect(newr); - } - HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0); - if (titlebar->subControls & (SC_TitleBarCloseButton - | SC_TitleBarMaxButton - | SC_TitleBarMinButton - | SC_TitleBarNormalButton)) { - HIThemeWindowWidgetDrawInfo wwdi; - wwdi.version = qt_mac_hitheme_version; - wwdi.widgetState = tds; - if (titlebar->state & State_MouseOver) - wwdi.widgetState = kThemeStateRollover; - wwdi.windowType = QtWinType; - wwdi.attributes = wdi.attributes | kThemeWindowHasFullZoom | kThemeWindowHasCloseBox | kThemeWindowHasCollapseBox; - wwdi.windowState = wdi.state; - wwdi.titleHeight = wdi.titleHeight; - wwdi.titleWidth = wdi.titleWidth; - ThemeDrawState savedControlState = wwdi.widgetState; - uint sc = SC_TitleBarMinButton; - ThemeTitleBarWidget tbw = kThemeWidgetCollapseBox; - bool active = titlebar->state & State_Active; - - while (sc <= SC_TitleBarCloseButton) { - if (sc & titlebar->subControls) { - uint tmp = sc; - wwdi.widgetState = savedControlState; - wwdi.widgetType = tbw; - if (sc == SC_TitleBarMinButton) - tmp |= SC_TitleBarNormalButton; - if (active && (titlebar->activeSubControls & tmp) - && (titlebar->state & State_Sunken)) - wwdi.widgetState = kThemeStatePressed; - // Draw all sub controllers except the dirty close button - // (it is already handled by HIThemeDrawWindowFrame). - if (!(widget && widget->isWindowModified() && tbw == kThemeWidgetCloseBox)) { - HIThemeDrawTitleBarWidget(&titleBarRect, &wwdi, cg, kHIThemeOrientationNormal); - p->paintEngine()->syncState(); - } - } - sc = sc << 1; - tbw = tbw >> 1; - } - } - p->paintEngine()->syncState(); - if (titlebar->subControls & SC_TitleBarLabel) { - int iw = 0; - if (!titlebar->icon.isNull()) { - QCFType titleRegion2; - HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn, - &titleRegion2); - ptrHIShapeGetBounds(titleRegion2, &tmpRect); - if (tmpRect.size.width != 1) { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width(); - } - } - if (!titlebar->text.isEmpty()) { - p->save(); - QCFType titleRegion3; - HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3); - ptrHIShapeGetBounds(titleRegion3, &tmpRect); - p->setClipRect(qt_qrectForHIRect(tmpRect)); - QRect br = p->clipRegion().boundingRect(); - int x = br.x(), - y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2); - if (br.width() <= (p->fontMetrics().width(titlebar->text) + iw * 2)) - x += iw; - else - x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2; - if (iw) { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - p->drawPixmap(x - iw, y, - titlebar->icon.pixmap(window, QSize(iconExtent, iconExtent), QIcon::Normal)); - } - drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive, - titlebar->text, QPalette::Text); - p->restore(); - } - } - } - break; - case CC_GroupBox: - if (const QStyleOptionGroupBox *gb - = qstyleoption_cast(opt)) { - - QStyleOptionGroupBox groupBox(*gb); - const bool flat = groupBox.features & QStyleOptionFrame::Flat; - if (!flat) - groupBox.state |= QStyle::State_Mini; // Force mini-sized checkbox to go with small-sized label - else - groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame; // We don't like frames and ugly lines - - bool didModifySubControls = false; - if ((!widget || !widget->testAttribute(Qt::WA_SetFont)) - && QApplication::desktopSettingsAware()) { - groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel; - didModifySubControls = true; - } - QCommonStyle::drawComplexControl(cc, &groupBox, p, widget); - if (didModifySubControls) { - p->save(); - CGContextSetShouldAntialias(cg, true); - CGContextSetShouldSmoothFonts(cg, true); - HIThemeTextInfo tti; - tti.version = qt_mac_hitheme_version; - tti.state = tds; - QColor textColor = groupBox.palette.windowText().color(); - CGFloat colorComp[] = { static_cast(textColor.redF()), static_cast(textColor.greenF()), - static_cast(textColor.blueF()), static_cast(textColor.alphaF()) }; - CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace()); - CGContextSetFillColor(cg, colorComp); - tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont; - tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; - tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; - tti.options = kHIThemeTextBoxOptionNone; - tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1 + groupBox.text.count(QLatin1Char('\n')); - QCFString groupText = qt_mac_removeMnemonics(groupBox.text); - QRect r = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget); - HIRect bounds = qt_hirectForQRect(r); - HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal); - p->restore(); - } - } - break; - case CC_ToolButton: - if (const QStyleOptionToolButton *tb - = qstyleoption_cast(opt)) { -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { - if (tb->subControls & SC_ToolButtonMenu) { - QStyleOption arrowOpt = *tb; - arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); - arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); - arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); - } else if ((tb->features & QStyleOptionToolButton::HasMenu) - && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { - drawToolbarButtonArrow(tb->rect, tds, cg); - } - if (tb->state & State_On) { - QWindow *window = 0; - if (widget && widget->window()) - window = widget->window()->windowHandle(); - else if (opt->styleObject) - window = opt->styleObject->property("_q_styleObjectWindow").value(); - - NSView *view = window ? (NSView *)window->winId() : nil; - bool isKey = false; - if (view) - isKey = [view.window isKeyWindow]; - - QBrush brush(isKey ? QColor(0, 0, 0, 28) - : QColor(0, 0, 0, 21)); - QPainterPath path; - path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); - p->setRenderHint(QPainter::Antialiasing); - p->fillPath(path, brush); - } - proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); - } else { - ThemeButtonKind bkind = kThemeBevelButton; - switch (d->aquaSizeConstrain(opt, widget)) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - bkind = kThemeBevelButton; - break; - case QAquaSizeMini: - case QAquaSizeSmall: - bkind = kThemeSmallBevelButton; - break; - } - - QRect button, menuarea; - button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); - menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); - State bflags = tb->state, - mflags = tb->state; - if (tb->subControls & SC_ToolButton) - bflags |= State_Sunken; - if (tb->subControls & SC_ToolButtonMenu) - mflags |= State_Sunken; - - if (tb->subControls & SC_ToolButton) { - if (bflags & (State_Sunken | State_On | State_Raised)) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = tds; - bdi.adornment = kThemeAdornmentNone; - bdi.kind = bkind; - bdi.value = kThemeButtonOff; - if (tb->state & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - if (tb->state & State_Sunken) - bdi.state = kThemeStatePressed; - if (tb->state & State_On) - bdi.value = kThemeButtonOn; - - QRect off_rct(0, 0, 0, 0); - HIRect myRect, macRect; - myRect = CGRectMake(tb->rect.x(), tb->rect.y(), - tb->rect.width(), tb->rect.height()); - HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); - off_rct.setRect(int(myRect.origin.x - macRect.origin.x), - int(myRect.origin.y - macRect.origin.y), - int(macRect.size.width - myRect.size.width), - int(macRect.size.height - myRect.size.height)); - - myRect = qt_hirectForQRect(button, off_rct); - HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0); - } - } - - if (tb->subControls & SC_ToolButtonMenu) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = tds; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - bdi.kind = bkind; - if (tb->state & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - if (tb->state & (State_On | State_Sunken) - || (tb->activeSubControls & SC_ToolButtonMenu)) - bdi.state = kThemeStatePressed; - HIRect hirect = qt_hirectForQRect(menuarea); - HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0); - QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8); - HIThemePopupArrowDrawInfo padi; - padi.version = qt_mac_hitheme_version; - padi.state = tds; - padi.orientation = kThemeArrowDown; - padi.size = kThemeArrow7pt; - hirect = qt_hirectForQRect(r); - HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal); - } else if (tb->features & QStyleOptionToolButton::HasMenu) { - drawToolbarButtonArrow(tb->rect, tds, cg); - } - QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); - int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); - QStyleOptionToolButton label = *tb; - label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); - proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); - } -#endif - } - break; -#ifndef QT_NO_DIAL - case CC_Dial: - if (const QStyleOptionSlider *dial = qstyleoption_cast(opt)) - QStyleHelper::drawDial(dial, p); - break; -#endif - default: - QCommonStyle::drawComplexControl(cc, opt, p, widget); - break; - } -} - -QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, - const QStyleOptionComplex *opt, - const QPoint &pt, const QWidget *widget) const -{ - Q_D(const QMacStyle); - SubControl sc = QStyle::SC_None; - switch (cc) { - case CC_ComboBox: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { - sc = QCommonStyle::hitTestComplexControl(cc, cmb, pt, widget); - if (!cmb->editable && sc != QStyle::SC_None) - sc = SC_ComboBoxArrow; // A bit of a lie, but what we want - } - break; - case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - ControlPartCode part; - HIPoint pos = CGPointMake(pt.x(), pt.y()); - if (HIThemeHitTestTrack(&tdi, &pos, &part)) { - if (part == kControlPageUpPart || part == kControlPageDownPart) - sc = SC_SliderGroove; - else - sc = SC_SliderHandle; - } - } - break; - case CC_ScrollBar: - if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { - HIScrollBarTrackInfo sbi; - sbi.version = qt_mac_hitheme_version; - if (!(sb->state & State_Active)) - sbi.enableState = kThemeTrackInactive; - else if (sb->state & State_Enabled) - sbi.enableState = kThemeTrackActive; - else - sbi.enableState = kThemeTrackDisabled; - - // The arrow buttons are not drawn if the scroll bar is to short, - // exclude them from the hit test. - const int scrollBarLength = (sb->orientation == Qt::Horizontal) - ? sb->rect.width() : sb->rect.height(); - if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, QStyleHelper::widgetSizePolicy(widget, opt))) - sbi.enableState = kThemeTrackNothingToScroll; - - sbi.viewsize = sb->pageStep; - HIPoint pos = CGPointMake(pt.x(), pt.y()); - - HIRect macSBRect = qt_hirectForQRect(sb->rect); - ControlPartCode part; - bool reverseHorizontal = (sb->direction == Qt::RightToLeft - && sb->orientation == Qt::Horizontal); - if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal, - &pos, 0, &part)) { - if (part == kControlUpButtonPart) - sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine; - else if (part == kControlDownButtonPart) - sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine; - } else { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, sb, &tdi, widget); - if(tdi.enableState == kThemeTrackInactive) - tdi.enableState = kThemeTrackActive; - if (HIThemeHitTestTrack(&tdi, &pos, &part)) { - if (part == kControlPageUpPart) - sc = reverseHorizontal ? SC_ScrollBarAddPage - : SC_ScrollBarSubPage; - else if (part == kControlPageDownPart) - sc = reverseHorizontal ? SC_ScrollBarSubPage - : SC_ScrollBarAddPage; - else - sc = SC_ScrollBarSlider; - } - } - } - break; -/* - I don't know why, but we only get kWindowContentRgn here, which isn't what we want at all. - It would be very nice if this would work. - case QStyle::CC_TitleBar: - if (const QStyleOptionTitleBar *tbar = qstyleoption_cast(opt)) { - HIThemeWindowDrawInfo wdi; - memset(&wdi, 0, sizeof(wdi)); - wdi.version = qt_mac_hitheme_version; - wdi.state = kThemeStateActive; - wdi.windowType = QtWinType; - wdi.titleWidth = tbar->rect.width(); - wdi.titleHeight = tbar->rect.height(); - if (tbar->titleBarState) - wdi.attributes |= kThemeWindowHasFullZoom | kThemeWindowHasCloseBox - | kThemeWindowHasCollapseBox; - else if (tbar->titleBarFlags & Qt::WindowSystemMenuHint) - wdi.attributes |= kThemeWindowHasCloseBox; - QRect tmpRect = tbar->rect; - tmpRect.setHeight(tmpRect.height() + 100); - HIRect hirect = qt_hirectForQRect(tmpRect); - WindowRegionCode hit; - HIPoint hipt = CGPointMake(pt.x(), pt.y()); - if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) { - switch (hit) { - case kWindowCloseBoxRgn: - sc = QStyle::SC_TitleBarCloseButton; - break; - case kWindowCollapseBoxRgn: - sc = QStyle::SC_TitleBarMinButton; - break; - case kWindowZoomBoxRgn: - sc = QStyle::SC_TitleBarMaxButton; - break; - case kWindowTitleTextRgn: - sc = QStyle::SC_TitleBarLabel; - break; - default: - qDebug("got something else %d", hit); - break; - } - } - } - break; -*/ - default: - sc = QCommonStyle::hitTestComplexControl(cc, opt, pt, widget); - break; - } - return sc; -} - -QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - QRect ret; - switch (cc) { - case CC_Slider: - case CC_ScrollBar: - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - HIRect macRect; - QCFType shape; - bool scrollBar = cc == CC_ScrollBar; - if ((scrollBar && sc == SC_ScrollBarSlider) - || (!scrollBar && sc == SC_SliderHandle)) { - HIThemeGetTrackThumbShape(&tdi, &shape); - ptrHIShapeGetBounds(shape, &macRect); - } else if (!scrollBar && sc == SC_SliderGroove) { - HIThemeGetTrackBounds(&tdi, &macRect); - } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available... - HIThemeGetTrackDragRect(&tdi, &macRect); - } else { - ControlPartCode cpc; - if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) { - cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart - : kControlPageUpPart; - } else { - cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart - : kControlDownButtonPart; - if (slider->direction == Qt::RightToLeft - && slider->orientation == Qt::Horizontal) { - if (cpc == kControlDownButtonPart) - cpc = kControlUpButtonPart; - else if (cpc == kControlUpButtonPart) - cpc = kControlDownButtonPart; - } - } - HIThemeGetTrackPartBounds(&tdi, cpc, &macRect); - } - ret = qt_qrectForHIRect(macRect); - - // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons - // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover - // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't. - if (slider->orientation == Qt::Horizontal) { - if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine) - ret.adjust(0, 0, 1, 0); - else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine) - ret.adjust(-1, 0, 1, 0); - } else if (sc == SC_ScrollBarAddLine) { - ret.adjust(0, -1, 0, 1); - } - } - break; - case CC_TitleBar: - if (const QStyleOptionTitleBar *titlebar - = qstyleoption_cast(opt)) { - HIThemeWindowDrawInfo wdi; - memset(&wdi, 0, sizeof(wdi)); - wdi.version = qt_mac_hitheme_version; - wdi.state = kThemeStateActive; - wdi.windowType = QtWinType; - wdi.titleHeight = titlebar->rect.height(); - wdi.titleWidth = titlebar->rect.width(); - wdi.attributes = kThemeWindowHasTitleText; - if (titlebar->subControls & SC_TitleBarCloseButton) - wdi.attributes |= kThemeWindowHasCloseBox; - if (titlebar->subControls & SC_TitleBarMaxButton - | SC_TitleBarNormalButton) - wdi.attributes |= kThemeWindowHasFullZoom; - if (titlebar->subControls & SC_TitleBarMinButton) - wdi.attributes |= kThemeWindowHasCollapseBox; - WindowRegionCode wrc = kWindowGlobalPortRgn; - - if (sc == SC_TitleBarCloseButton) - wrc = kWindowCloseBoxRgn; - else if (sc == SC_TitleBarMinButton) - wrc = kWindowCollapseBoxRgn; - else if (sc == SC_TitleBarMaxButton) - wrc = kWindowZoomBoxRgn; - else if (sc == SC_TitleBarLabel) - wrc = kWindowTitleTextRgn; - else if (sc == SC_TitleBarSysMenu) - ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight, - titlebar, widget)); - if (wrc != kWindowGlobalPortRgn) { - QCFType region; - QRect tmpRect = titlebar->rect; - HIRect titleRect = qt_hirectForQRect(tmpRect); - HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, ®ion); - ptrHIShapeGetBounds(region, &titleRect); - CFRelease(region); - tmpRect.translate(tmpRect.x() - int(titleRect.origin.x), - tmpRect.y() - int(titleRect.origin.y)); - titleRect = qt_hirectForQRect(tmpRect); - HIThemeGetWindowShape(&titleRect, &wdi, wrc, ®ion); - ptrHIShapeGetBounds(region, &titleRect); - ret = qt_qrectForHIRect(titleRect); - } - } - break; - case CC_ComboBox: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { - HIThemeButtonDrawInfo bdi; - d->initComboboxBdi(combo, &bdi, widget, d->getDrawState(opt->state)); - - switch (sc) { - case SC_ComboBoxEditField:{ - ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - // 10.10 and above need a slight shift - ret.setHeight(ret.height() - 1); - break; } - case SC_ComboBoxArrow:{ - ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - ret.setX(ret.x() + ret.width()); - ret.setWidth(combo->rect.right() - ret.right()); - break; } - case SC_ComboBoxListBoxPopup:{ - if (combo->editable) { - HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind); - QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - const int comboTop = combo->rect.top(); - ret = QRect(qRound(inner.origin.x), - comboTop, - qRound(inner.origin.x - combo->rect.left() + inner.size.width), - editRect.bottom() - comboTop + 2); - } else { - QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - ret = QRect(combo->rect.x() + 4 - 11, - combo->rect.y() + 1, - editRect.width() + 10 + 11, - 1); - } - break; } - default: - break; - } - } - break; - case CC_GroupBox: - if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { - bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; - const bool flat = groupBox->features & QStyleOptionFrame::Flat; - bool hasNoText = !checkable && groupBox->text.isEmpty(); - switch (sc) { - case SC_GroupBoxLabel: - case SC_GroupBoxCheckBox: { - // Cheat and use the smaller font if we need to - bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; - bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)) - || !QApplication::desktopSettingsAware(); - int tw; - int h; - int margin = flat || hasNoText ? 0 : 9; - ret = groupBox->rect.adjusted(margin, 0, -margin, 0); - - if (!fontIsSet) { - HIThemeTextInfo tti; - tti.version = qt_mac_hitheme_version; - tti.state = kThemeStateActive; - tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont; - tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; - tti.verticalFlushness = kHIThemeTextVerticalFlushCenter; - tti.options = kHIThemeTextBoxOptionNone; - tti.truncationPosition = kHIThemeTextTruncationNone; - tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n')); - CGFloat width; - CGFloat height; - QCFString groupText = qt_mac_removeMnemonics(groupBox->text); - HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0); - tw = qRound(width); - h = qCeil(height); - } else { - QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics); - h = qCeil(fm.height()); - tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width()); - } - ret.setHeight(h); - - QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, - QSize(tw, h), ret); - if (flat && checkable) - labelRect.moveLeft(labelRect.left() + 4); - int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); - bool rtl = groupBox->direction == Qt::RightToLeft; - if (sc == SC_GroupBoxLabel) { - if (checkable) { - int newSum = indicatorWidth + 1; - int newLeft = labelRect.left() + (rtl ? -newSum : newSum); - labelRect.moveLeft(newLeft); - if (flat) - labelRect.moveTop(labelRect.top() + 3); - else - labelRect.moveTop(labelRect.top() + 4); - } else if (flat) { - int newLeft = labelRect.left() - (rtl ? 3 : -3); - labelRect.moveLeft(newLeft); - labelRect.moveTop(labelRect.top() + 3); - } else { - int newLeft = labelRect.left() - (rtl ? 3 : 2); - labelRect.moveLeft(newLeft); - labelRect.moveTop(labelRect.top() + 4); - } - ret = labelRect; - } - - if (sc == SC_GroupBoxCheckBox) { - int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left() - 1; - int top = flat ? ret.top() + 1 : ret.top() + 5; - ret.setRect(left, top, - indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget)); - } - break; - } - case SC_GroupBoxContents: - case SC_GroupBoxFrame: { - QFontMetrics fm = groupBox->fontMetrics; - int yOffset = 3; - if (!flat) { - if (widget && !widget->testAttribute(Qt::WA_SetFont) - && QApplication::desktopSettingsAware()) - fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); - yOffset = 5; - } - - if (hasNoText) - yOffset = -qCeil(QFontMetricsF(fm).height()); - ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0); - if (sc == SC_GroupBoxContents) { - if (flat) - ret.adjust(3, -5, -3, -4); // guess too - else - ret.adjust(3, 3, -3, -4); // guess - } - } - break; - default: - ret = QCommonStyle::subControlRect(cc, groupBox, sc, widget); - break; - } - } - break; -#ifndef QT_NO_SPINBOX - case CC_SpinBox: - if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { - QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget); - int spinner_w; - int spinBoxSep; - int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget); - switch (aquaSize) { - default: - case QAquaSizeUnknown: - case QAquaSizeLarge: - spinner_w = 14; - spinBoxSep = 2; - break; - case QAquaSizeSmall: - spinner_w = 12; - spinBoxSep = 2; - break; - case QAquaSizeMini: - spinner_w = 10; - spinBoxSep = 1; - break; - } - - switch (sc) { - case SC_SpinBoxUp: - case SC_SpinBoxDown: { - if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) - break; - - const int y = fw; - const int x = spin->rect.width() - spinner_w; - ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2); - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.kind = kThemeIncDecButton; - int hackTranslateX; - switch (aquaSize) { - default: - case QAquaSizeUnknown: - case QAquaSizeLarge: - bdi.kind = kThemeIncDecButton; - hackTranslateX = 0; - break; - case QAquaSizeSmall: - bdi.kind = kThemeIncDecButtonSmall; - hackTranslateX = -2; - break; - case QAquaSizeMini: - bdi.kind = kThemeIncDecButtonMini; - hackTranslateX = -1; - break; - } - bdi.state = kThemeStateActive; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - HIRect hirect = qt_hirectForQRect(ret); - - HIRect outRect; - HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect); - ret = qt_qrectForHIRect(outRect); - switch (sc) { - case SC_SpinBoxUp: - ret.setHeight(ret.height() / 2); - break; - case SC_SpinBoxDown: - ret.setY(ret.y() + ret.height() / 2); - break; - default: - Q_ASSERT(0); - break; - } - ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this) - ret = visualRect(spin->direction, spin->rect, ret); - break; - } - case SC_SpinBoxEditField: - if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) { - ret.setRect(fw, fw, - spin->rect.width() - fw * 2, - spin->rect.height() - fw * 2); - } else { - ret.setRect(fw, fw, - spin->rect.width() - fw * 2 - spinBoxSep - spinner_w, - spin->rect.height() - fw * 2); - } - ret = visualRect(spin->direction, spin->rect, ret); - break; - default: - ret = QCommonStyle::subControlRect(cc, spin, sc, widget); - break; - } - } - break; -#endif - case CC_ToolButton: - ret = QCommonStyle::subControlRect(cc, opt, sc, widget); - if (sc == SC_ToolButtonMenu -#ifndef QT_NO_ACCESSIBILITY - && !QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar) -#endif - ) { - ret.adjust(-1, 0, 0, 0); - } - break; - default: - ret = QCommonStyle::subControlRect(cc, opt, sc, widget); - break; - } - return ret; -} - -QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, - const QSize &csz, const QWidget *widget) const -{ - Q_D(const QMacStyle); - QSize sz(csz); - bool useAquaGuideline = true; - - switch (ct) { -#ifndef QT_NO_SPINBOX - case CT_SpinBox: - if (const QStyleOptionSpinBox *vopt = qstyleoption_cast(opt)) { - // Add button + frame widths - int buttonWidth = 20; - int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget); - sz += QSize(buttonWidth + 2*fw, 2*fw - 3); - } - break; -#endif - case QStyle::CT_TabWidget: - // the size between the pane and the "contentsRect" (+4,+4) - // (the "contentsRect" is on the inside of the pane) - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - /** - This is supposed to show the relationship between the tabBar and - the stack widget of a QTabWidget. - Unfortunately ascii is not a good way of representing graphics..... - PS: The '=' line is the painted frame. - - top ---+ - | - | - | - | vvv just outside the painted frame is the "pane" - - -|- - - - - - - - - - <-+ - TAB BAR +=====^============ | +2 pixels - - - -|- - -|- - - - - - - <-+ - | | ^ ^^^ just inside the painted frame is the "contentsRect" - | | | - | overlap | - | | | - bottom ------+ <-+ +14 pixels - | - v - ------------------------------ <- top of stack widget - - - To summarize: - * 2 is the distance between the pane and the contentsRect - * The 14 and the 1's are the distance from the contentsRect to the stack widget. - (same value as used in SE_TabWidgetTabContents) - * overlap is how much the pane should overlap the tab bar - */ - // then add the size between the stackwidget and the "contentsRect" -#ifndef QT_NO_TABWIDGET - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - QSize extra(0,0); - const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); - const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; - - if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { - extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); - } else { - extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); - } - sz+= extra; - } -#endif - break; -#ifndef QT_NO_TABBAR - case QStyle::CT_TabBarTab: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget); - const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) - || !QApplication::desktopSettingsAware(); - ThemeTabDirection ttd = getTabDirection(tab->shape); - bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; - if (vertTabs) - sz = sz.transposed(); - int defaultTabHeight; - int extraHSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); - QFontMetrics fm = opt->fontMetrics; - switch (AquaSize) { - case QAquaSizeUnknown: - case QAquaSizeLarge: - if (tab->documentMode) - defaultTabHeight = 24; - else - defaultTabHeight = 21; - break; - case QAquaSizeSmall: - defaultTabHeight = 18; - break; - case QAquaSizeMini: - defaultTabHeight = 16; - break; - } - bool setWidth = false; - if (differentFont || !tab->icon.isNull()) { - sz.rheight() = qMax(defaultTabHeight, sz.height()); - } else { - QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); - sz.rheight() = qMax(defaultTabHeight, textSize.height()); - sz.rwidth() = textSize.width(); - setWidth = true; - } - sz.rwidth() += extraHSpace; - - if (vertTabs) - sz = sz.transposed(); - - int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); - int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); - - int widgetWidth = 0; - int widgetHeight = 0; - int padding = 0; - if (tab->leftButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->leftButtonSize.width(); - widgetHeight += tab->leftButtonSize.height(); - } - if (tab->rightButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->rightButtonSize.width(); - widgetHeight += tab->rightButtonSize.height(); - } - - if (vertTabs) { - sz.setHeight(sz.height() + widgetHeight + padding); - sz.setWidth(qMax(sz.width(), maxWidgetWidth)); - } else { - if (setWidth) - sz.setWidth(sz.width() + widgetWidth + padding); - sz.setHeight(qMax(sz.height(), maxWidgetHeight)); - } - } - break; -#endif - case QStyle::CT_PushButton: - // By default, we fit the contents inside a normal rounded push button. - // Do this by add enough space around the contents so that rounded - // borders (including highlighting when active) will show. - sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; - if (opt->state & QStyle::State_Small) - sz.rheight() += 14; - else - sz.rheight() += 4; - break; - case QStyle::CT_MenuItem: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - int maxpmw = mi->maxIconWidth; -#ifndef QT_NO_COMBOBOX - const QComboBox *comboBox = qobject_cast(widget); -#endif - int w = sz.width(), - h = sz.height(); - if (mi->menuItemType == QStyleOptionMenuItem::Separator) { - w = 10; - SInt16 ash; - GetThemeMenuSeparatorHeight(&ash); - h = ash; - } else { - h = mi->fontMetrics.height() + 2; - if (!mi->icon.isNull()) { -#ifndef QT_NO_COMBOBOX - if (comboBox) { - const QSize &iconSize = comboBox->iconSize(); - h = qMax(h, iconSize.height() + 4); - maxpmw = qMax(maxpmw, iconSize.width()); - } else -#endif - { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); - } - } - } - if (mi->text.contains(QLatin1Char('\t'))) - w += 12; - if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 20; - if (maxpmw) - w += maxpmw + 6; - // add space for a check. All items have place for a check too. - w += 20; -#ifndef QT_NO_COMBOBOX - if (comboBox && comboBox->isVisible()) { - QStyleOptionComboBox cmb; - cmb.initFrom(comboBox); - cmb.editable = false; - cmb.subControls = QStyle::SC_ComboBoxEditField; - cmb.activeSubControls = QStyle::SC_None; - w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb, - QStyle::SC_ComboBoxEditField, - comboBox).width()); - } else -#endif - { - w += 12; - } - sz = QSize(w, h); - } - break; - case CT_MenuBarItem: - if (!sz.isEmpty()) - sz += QSize(12, 4); // Constants from QWindowsStyle - break; - case CT_ToolButton: - sz.rwidth() += 10; - sz.rheight() += 10; - return sz; - case CT_ComboBox: { - sz.rwidth() += 50; - const QStyleOptionComboBox *cb = qstyleoption_cast(opt); - if (cb && !cb->editable) - sz.rheight() += 2; - break; - } - case CT_Menu: { - if (proxy() == this) { - sz = csz; - } else { - QStyleHintReturnMask menuMask; - QStyleOption myOption = *opt; - myOption.rect.setSize(sz); - if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) - sz = menuMask.region.boundingRect().size(); - } - break; } - case CT_HeaderSection:{ - const QStyleOptionHeader *header = qstyleoption_cast(opt); - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - if (header->text.contains(QLatin1Char('\n'))) - useAquaGuideline = false; - break; } - case CT_ScrollBar : - // Make sure that the scroll bar is large enough to display the thumb indicator. - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, QStyleHelper::widgetSizePolicy(widget, opt)); - if (slider->orientation == Qt::Horizontal) - sz = sz.expandedTo(QSize(minimumSize, sz.height())); - else - sz = sz.expandedTo(QSize(sz.width(), minimumSize)); - } - break; - case CT_ItemViewItem: - if (const QStyleOptionViewItem *vopt = qstyleoption_cast(opt)) { - sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget); - sz.setHeight(sz.height() + 2); - } - break; - - default: - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - } - - if (useAquaGuideline){ - QSize macsz; - if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) { - if (macsz.width() != -1) - sz.setWidth(macsz.width()); - if (macsz.height() != -1) - sz.setHeight(macsz.height()); - } - } - - // The sizes that Carbon and the guidelines gives us excludes the focus frame. - // We compensate for this by adding some extra space here to make room for the frame when drawing: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); - int bkind = 0; - switch (widgetSize) { - default: - case QAquaSizeLarge: - bkind = combo->editable ? kThemeComboBox : kThemePopupButton; - break; - case QAquaSizeSmall: - bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall); - break; - case QAquaSizeMini: - bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini; - break; - } - HIRect tmpRect = {{0, 0}, {0, 0}}; - HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind); - sz.rwidth() -= qRound(diffRect.size.width); - sz.rheight() -= qRound(diffRect.size.height); - } else if (ct == CT_PushButton || ct == CT_ToolButton){ - ThemeButtonKind bkind; - QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget); - switch (ct) { - default: - case CT_PushButton: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - if (btn->features & QStyleOptionButton::CommandLinkButton) { - return QCommonStyle::sizeFromContents(ct, opt, sz, widget); - } - } - - switch (widgetSize) { - default: - case QAquaSizeLarge: - bkind = kThemePushButton; - break; - case QAquaSizeSmall: - bkind = kThemePushButtonSmall; - break; - case QAquaSizeMini: - bkind = kThemePushButtonMini; - break; - } - break; - case CT_ToolButton: - switch (widgetSize) { - default: - case QAquaSizeLarge: - bkind = kThemeLargeBevelButton; - break; - case QAquaSizeMini: - case QAquaSizeSmall: - bkind = kThemeSmallBevelButton; - } - break; - } - - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeStateActive; - bdi.kind = bkind; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - HIRect macRect, myRect; - myRect = CGRectMake(0, 0, sz.width(), sz.height()); - HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); - // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess), - if (bkind == kThemePushButtonMini) - macRect.size.height += 8.; - else if (bkind == kThemePushButtonSmall) - macRect.size.height -= 10; - sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width)); - sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height)); - } - return sz; -} - -void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, - bool enabled, const QString &text, QPalette::ColorRole textRole) const -{ - if(flags & Qt::TextShowMnemonic) - flags |= Qt::TextHideMnemonic; - QCommonStyle::drawItemText(p, r, flags, pal, enabled, text, textRole); -} - -bool QMacStyle::event(QEvent *e) -{ - Q_D(QMacStyle); - if(e->type() == QEvent::FocusIn) { - QWidget *f = 0; - QWidget *focusWidget = QApplication::focusWidget(); -#ifndef QT_NO_GRAPHICSVIEW - if (QGraphicsView *graphicsView = qobject_cast(focusWidget)) { - QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; - if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { - QGraphicsProxyWidget *proxy = static_cast(focusItem); - if (proxy->widget()) - focusWidget = proxy->widget()->focusWidget(); - } - } -#endif - if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) { - f = focusWidget; - QWidget *top = f->parentWidget(); - while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow)) - top = top->parentWidget(); -#ifndef QT_NO_MAINWINDOW - if (qobject_cast(top)) { - QWidget *central = static_cast(top)->centralWidget(); - for (const QWidget *par = f; par; par = par->parentWidget()) { - if (par == central) { - top = central; - break; - } - if (par->isWindow()) - break; - } - } -#endif - } - if (f) { - if(!d->focusWidget) - d->focusWidget = new QFocusFrame(f); - d->focusWidget->setWidget(f); - } else if(d->focusWidget) { - d->focusWidget->setWidget(0); - } - } else if(e->type() == QEvent::FocusOut) { - if(d->focusWidget) - d->focusWidget->setWidget(0); - } - return false; -} - -QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, - const QWidget *widget) const -{ - switch (standardIcon) { - default: - return QCommonStyle::standardIcon(standardIcon, opt, widget); - case SP_ToolBarHorizontalExtensionButton: - case SP_ToolBarVerticalExtensionButton: { - QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext.png")); - if (standardIcon == SP_ToolBarVerticalExtensionButton) { - QPixmap pix2(pixmap.height(), pixmap.width()); - pix2.setDevicePixelRatio(pixmap.devicePixelRatio()); - pix2.fill(Qt::transparent); - QPainter p(&pix2); - p.translate(pix2.width(), 0); - p.rotate(90); - p.drawPixmap(0, 0, pixmap); - return pix2; - } - return pixmap; - } - } -} - -int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, - QSizePolicy::ControlType control2, - Qt::Orientation orientation, - const QStyleOption *option, - const QWidget *widget) const -{ - const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; - bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal)); - int controlSize = getControlSize(option, widget); - - if (control2 == QSizePolicy::ButtonBox) { - /* - AHIG seems to prefer a 12-pixel margin between group - boxes and the row of buttons. The 20 pixel comes from - Builder. - */ - if (isMetal // (AHIG, guess, guess) - || (control1 & (QSizePolicy::Frame // guess - | QSizePolicy::GroupBox // (AHIG, guess, guess) - | QSizePolicy::TabWidget // guess - | ButtonMask))) { // AHIG - return_SIZE(14, 8, 8); - } else if (control1 == QSizePolicy::LineEdit) { - return_SIZE(8, 8, 8); // Interface Builder - } else { - return_SIZE(20, 7, 7); // Interface Builder - } - } - - if ((control1 | control2) & ButtonMask) { - if (control1 == QSizePolicy::LineEdit) - return_SIZE(8, 8, 8); // Interface Builder - else if (control2 == QSizePolicy::LineEdit) { - if (orientation == Qt::Vertical) - return_SIZE(20, 7, 7); // Interface Builder - else - return_SIZE(20, 8, 8); - } - return_SIZE(14, 8, 8); // Interface Builder - } - - switch (CT2(control1, control2)) { - case CT1(QSizePolicy::Label): // guess - case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): // guess - case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): // guess - case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::Slider): // guess - case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): // guess - case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): // guess - return_SIZE(8, 6, 5); - case CT1(QSizePolicy::ToolButton): - return 8; // AHIG - case CT1(QSizePolicy::CheckBox): - case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): - case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): - if (orientation == Qt::Vertical) - return_SIZE(8, 8, 7); // AHIG and Builder - break; - case CT1(QSizePolicy::RadioButton): - if (orientation == Qt::Vertical) - return 5; // (Builder, guess, AHIG) - } - - if (orientation == Qt::Horizontal - && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton))) - return_SIZE(12, 10, 8); // guess - - if ((control1 | control2) & (QSizePolicy::Frame - | QSizePolicy::GroupBox - | QSizePolicy::TabWidget)) { - /* - These values were chosen so that nested container widgets - look good side by side. Builder uses 8, which looks way - too small, and AHIG doesn't say anything. - */ - return_SIZE(16, 10, 10); // guess - } - - if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider)) - return_SIZE(12, 10, 8); // AHIG - - if ((control1 | control2) & QSizePolicy::LineEdit) - return_SIZE(10, 8, 8); // AHIG - - /* - AHIG and Builder differ by up to 4 pixels for stacked editable - comboboxes. We use some values that work fairly well in all - cases. - */ - if ((control1 | control2) & QSizePolicy::ComboBox) - return_SIZE(10, 8, 7); // guess - - /* - Builder defaults to 8, 6, 5 in lots of cases, but most of the time the - result looks too cramped. - */ - return_SIZE(10, 8, 6); // guess -} - -/* -FontHash::FontHash() -{ - QHash::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts()); -} - -Q_GLOBAL_STATIC(FontHash, app_fonts) -FontHash *qt_app_fonts_hash() -{ - return app_fonts(); -} -*/ -QT_END_NAMESPACE diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h deleted file mode 100644 index 03f5d7280f..0000000000 --- a/src/widgets/styles/qmacstyle_mac_p.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMACSTYLE_MAC_P_H -#define QMACSTYLE_MAC_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - - -#if QT_CONFIG(style_mac) - -class QPalette; - -class QPushButton; -class QStyleOptionButton; -class QMacStylePrivate; -class QMacStyle : public QCommonStyle -{ - Q_OBJECT -public: - QMacStyle(); - virtual ~QMacStyle(); - - void polish(QWidget *w); - void unpolish(QWidget *w); - - void polish(QApplication*); - void unpolish(QApplication*); - - void polish(QPalette &pal); - - void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, - const QWidget *w = 0) const; - void drawControl(ControlElement element, const QStyleOption *opt, QPainter *p, - const QWidget *w = 0) const; - QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; - void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, - const QWidget *w = 0) const; - SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, - const QPoint &pt, const QWidget *w = 0) const; - QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, - const QWidget *w = 0) const; - QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, - const QSize &contentsSize, const QWidget *w = 0) const; - - int pixelMetric(PixelMetric pm, const QStyleOption *opt = 0, const QWidget *widget = 0) const; - - QPalette standardPalette() const; - - virtual int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0, - QStyleHintReturn *shret = 0) const; - - QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *opt, - const QWidget *widget = 0) const; - - QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, - const QStyleOption *opt) const; - - virtual void drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, - bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; - - bool event(QEvent *e); - - QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *opt = 0, - const QWidget *widget = 0) const; - int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, - Qt::Orientation orientation, const QStyleOption *option = 0, - const QWidget *widget = 0) const; - -private: - Q_DISABLE_COPY(QMacStyle) - Q_DECLARE_PRIVATE(QMacStyle) - -#if QT_CONFIG(pushbutton) - friend bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); -#endif -}; - -#endif - -QT_END_NAMESPACE - -#endif // QMACSTYLE_MAC_P_H diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h deleted file mode 100644 index 9bbd0995a5..0000000000 --- a/src/widgets/styles/qmacstyle_mac_p_p.h +++ /dev/null @@ -1,257 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QMACSTYLE_MAC_P_P_H -#define QMACSTYLE_MAC_P_P_H - -#include -#undef check - -#include -#include "qmacstyle_mac_p.h" -#include "qcommonstyle_p.h" -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(checkbox) -#include -#endif -#include -#if QT_CONFIG(dialogbuttonbox) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_NAMESPACE - -/* - AHIG: - Apple Human Interface Guidelines - http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/ - - Builder: - Apple Interface Builder v. 3.1.1 -*/ - -// this works as long as we have at most 16 different control types -#define CT1(c) CT2(c, c) -#define CT2(c1, c2) ((uint(c1) << 16) | uint(c2)) - -enum QAquaWidgetSize { QAquaSizeLarge = 0, QAquaSizeSmall = 1, QAquaSizeMini = 2, - QAquaSizeUnknown = -1 }; - -enum QCocoaWidgetKind { - QCocoaArrowButton, // Disclosure triangle, like in QTreeView - QCocoaCheckBox, - QCocoaComboBox, // Editable QComboBox - QCocoaPopupButton, // Non-editable QComboBox - QCocoaPullDownButton, // QPushButton with menu - QCocoaPushButton, - QCocoaRadioButton, - QCocoaHorizontalSlider, - QCocoaVerticalSlider -}; - -typedef QPair QCocoaWidget; - -typedef void (^QCocoaDrawRectBlock)(NSRect, CGContextRef); - -#define SIZE(large, small, mini) \ - (controlSize == QAquaSizeLarge ? (large) : controlSize == QAquaSizeSmall ? (small) : (mini)) - -// same as return SIZE(...) but optimized -#define return_SIZE(large, small, mini) \ - do { \ - static const int sizes[] = { (large), (small), (mini) }; \ - return sizes[controlSize]; \ - } while (0) - -#if QT_CONFIG(pushbutton) -bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOptionButton *option); -#endif - -class QMacStylePrivate : public QCommonStylePrivate -{ - Q_DECLARE_PUBLIC(QMacStyle) -public: - QMacStylePrivate(); - ~QMacStylePrivate(); - - // Ideally these wouldn't exist, but since they already exist we need some accessors. - static const int PushButtonLeftOffset; - static const int PushButtonTopOffset; - static const int PushButtonRightOffset; - static const int PushButtonBottomOffset; - static const int MiniButtonH; - static const int SmallButtonH; - static const int BevelButtonW; - static const int BevelButtonH; - static const int PushButtonContentPadding; - - enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar }; - static ThemeDrawState getDrawState(QStyle::State flags); - QAquaWidgetSize aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, - QStyle::ContentsType ct = QStyle::CT_CustomBase, - QSize szHint=QSize(-1, -1), QSize *insz = 0) const; - QAquaWidgetSize effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg, - QStyle::ContentsType ct = QStyle::CT_CustomBase, - QSize szHint=QSize(-1, -1), QSize *insz = 0) const; - void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, - HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const; - inline int animateSpeed(Animates) const { return 33; } - - // Utility functions - void drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, - QPainter *p, const QStyleOption *opt) const; - - QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const; - - HIRect pushButtonContentBounds(const QStyleOptionButton *btn, - const HIThemeButtonDrawInfo *bdi) const; - - void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, - const QWidget *widget, const ThemeDrawState &tds) const; - - static HIRect comboboxInnerBounds(const HIRect &outerBounds, int buttonKind); - - static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); - - static void drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p); - static void drawTableHeader(const HIRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, - const HIThemeButtonDrawInfo &bdi, QPainter *p); - bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, - ThemeButtonKind buttonKindToCheck) const; - void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget, - const ThemeDrawState tds, - HIThemeButtonDrawInfo *bdi) const; - QPixmap generateBackgroundPattern() const; - - void setAutoDefaultButton(QObject *button) const; - - NSView *cocoaControl(QCocoaWidget widget) const; - - void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const; - void resolveCurrentNSView(QWindow *window); - - void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; - -#ifndef QT_NO_TABBAR - void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect) const; -#endif - -public: - mutable QPointer pressedButton; - mutable QPointer defaultButton; - mutable QPointer autoDefaultButton; - static QVector > scrollBars; - - struct ButtonState { - int frame; - enum { ButtonDark, ButtonLight } dir; - } buttonState; - mutable QPointer focusWidget; - CFAbsoluteTime defaultButtonStart; - bool mouseDown; - void* receiver; - void *nsscroller; - void *indicatorBranchButtonCell; - NSView *backingStoreNSView; - QHash cocoaControls; -}; - -QT_END_NAMESPACE - -#endif // QMACSTYLE_MAC_P_P_H diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h index 3b10eeea27..e5cfe0bbee 100644 --- a/src/widgets/styles/qstyleanimation_p.h +++ b/src/widgets/styles/qstyleanimation_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE // We mean it. // -class QStyleAnimation : public QAbstractAnimation +class Q_WIDGETS_EXPORT QStyleAnimation : public QAbstractAnimation { Q_OBJECT @@ -106,7 +106,7 @@ private: int _skip; }; -class QProgressStyleAnimation : public QStyleAnimation +class Q_WIDGETS_EXPORT QProgressStyleAnimation : public QStyleAnimation { Q_OBJECT @@ -127,7 +127,7 @@ private: mutable int _step; }; -class QNumberStyleAnimation : public QStyleAnimation +class Q_WIDGETS_EXPORT QNumberStyleAnimation : public QStyleAnimation { Q_OBJECT @@ -151,7 +151,7 @@ private: mutable qreal _prev; }; -class QBlendStyleAnimation : public QStyleAnimation +class Q_WIDGETS_EXPORT QBlendStyleAnimation : public QStyleAnimation { Q_OBJECT @@ -178,7 +178,7 @@ private: QImage _current; }; -class QScrollbarStyleAnimation : public QNumberStyleAnimation +class Q_WIDGETS_EXPORT QScrollbarStyleAnimation : public QNumberStyleAnimation { Q_OBJECT diff --git a/src/widgets/styles/qstylefactory.cpp b/src/widgets/styles/qstylefactory.cpp index e29794aeb1..c959994d2c 100644 --- a/src/widgets/styles/qstylefactory.cpp +++ b/src/widgets/styles/qstylefactory.cpp @@ -46,16 +46,6 @@ #include "qwindowsstyle_p.h" #if QT_CONFIG(style_fusion) #include "qfusionstyle_p.h" -#if QT_CONFIG(style_android) -#include "qandroidstyle_p.h" -#endif -#endif -#if QT_CONFIG(style_windowsvista) -#include "qwindowsvistastyle_p.h" -#endif - -#if QT_CONFIG(style_mac) -# include "qmacstyle_mac_p.h" #endif QT_BEGIN_NAMESPACE @@ -105,29 +95,10 @@ QStyle *QStyleFactory::create(const QString& key) ret = new QWindowsStyle; else #endif -#if QT_CONFIG(style_windowsvista) - if (style == QLatin1String("windowsvista")) - ret = new QWindowsVistaStyle; - else -#endif #if QT_CONFIG(style_fusion) if (style == QLatin1String("fusion")) ret = new QFusionStyle; else -#endif -#if QT_CONFIG(style_android) - if (style == QLatin1String("android")) - ret = new QAndroidStyle; - else -#endif -#if QT_CONFIG(style_mac) - if (style.startsWith(QLatin1String("macintosh"))) { - ret = new QMacStyle; -# if 0 // Used to be included in Qt4 for Q_WS_MAC - if (style == QLatin1String("macintosh")) - style += QLatin1String(" (aqua)"); -# endif - } else #endif { } // Keep these here - they make the #ifdefery above work if (!ret) @@ -156,26 +127,9 @@ QStringList QStyleFactory::keys() if (!list.contains(QLatin1String("Windows"))) list << QLatin1String("Windows"); #endif -#if QT_CONFIG(style_windowsvista) - if (!list.contains(QLatin1String("WindowsVista")) && - (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))) - list << QLatin1String("WindowsVista"); -#endif -#if QT_CONFIG(style_android) - if (!list.contains(QLatin1String("Android"))) - list << QLatin1String("Android"); -#endif #if QT_CONFIG(style_fusion) if (!list.contains(QLatin1String("Fusion"))) list << QLatin1String("Fusion"); -#endif -#if QT_CONFIG(style_mac) - QString mstyle = QLatin1String("Macintosh"); -# if 0 // Used to be included in Qt4 for Q_WS_MAC - mstyle += QLatin1String(" (aqua)"); -# endif - if (!list.contains(mstyle)) - list << mstyle; #endif return list; } diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h index 8c30d3f4eb..aa6cbaad78 100644 --- a/src/widgets/styles/qstylehelper_p.h +++ b/src/widgets/styles/qstylehelper_p.h @@ -71,27 +71,27 @@ class QWindow; namespace QStyleHelper { QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size); - qreal dpiScaled(qreal value); + Q_WIDGETS_EXPORT qreal dpiScaled(qreal value); #ifndef QT_NO_DIAL qreal angle(const QPointF &p1, const QPointF &p2); QPolygonF calcLines(const QStyleOptionSlider *dial); int calcBigLineSize(int radius); - void drawDial(const QStyleOptionSlider *dial, QPainter *painter); + Q_WIDGETS_EXPORT void drawDial(const QStyleOptionSlider *dial, QPainter *painter); #endif //QT_NO_DIAL - void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, + Q_WIDGETS_EXPORT void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect, int left = 0, int top = 0, int right = 0, int bottom = 0); #ifndef QT_NO_ACCESSIBILITY - bool isInstanceOf(QObject *obj, QAccessible::Role role); - bool hasAncestor(QObject *obj, QAccessible::Role role); + Q_WIDGETS_EXPORT bool isInstanceOf(QObject *obj, QAccessible::Role role); + Q_WIDGETS_EXPORT bool hasAncestor(QObject *obj, QAccessible::Role role); #endif - QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0); - QWindow *styleObjectWindow(QObject *so); + Q_WIDGETS_EXPORT QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0); + Q_WIDGETS_EXPORT QWindow *styleObjectWindow(QObject *so); enum WidgetSizePolicy { SizeSmall, SizeLarge, SizeMini, SizeDefault }; void setWidgetSizePolicy(const QWidget *w, WidgetSizePolicy policy); - WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0); + Q_WIDGETS_EXPORT WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0); } diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h index a1d65610ff..12a682f330 100644 --- a/src/widgets/styles/qwindowsstyle_p.h +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QWindowsStylePrivate; -class QWindowsStyle : public QCommonStyle +class Q_WIDGETS_EXPORT QWindowsStyle : public QCommonStyle { Q_OBJECT public: diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 5023fd1042..8b387b6ab9 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QTime; -class QWindowsStylePrivate : public QCommonStylePrivate +class Q_WIDGETS_EXPORT QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp deleted file mode 100644 index 5a53627e95..0000000000 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ /dev/null @@ -1,2491 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowsvistastyle_p.h" -#include "qwindowsvistastyle_p_p.h" -#include -#include -#include -#include -#include -#include -#include - -#if QT_CONFIG(style_windowsvista) || defined(QT_PLUGIN) - -QT_BEGIN_NAMESPACE - -static const int windowsItemFrame = 2; // menu item frame width -static const int windowsItemHMargin = 3; // menu item hor text margin -static const int windowsItemVMargin = 4; // menu item ver text margin -static const int windowsArrowHMargin = 6; // arrow horizontal margin -static const int windowsRightBorder = 15; // right border on windows - -#ifndef TMT_CONTENTMARGINS -# define TMT_CONTENTMARGINS 3602 -#endif -#ifndef TMT_SIZINGMARGINS -# define TMT_SIZINGMARGINS 3601 -#endif -#ifndef LISS_NORMAL -# define LISS_NORMAL 1 -# define LISS_HOT 2 -# define LISS_SELECTED 3 -# define LISS_DISABLED 4 -# define LISS_SELECTEDNOTFOCUS 5 -# define LISS_HOTSELECTED 6 -#endif -#ifndef BP_COMMANDLINK -# define BP_COMMANDLINK 6 -# define BP_COMMANDLINKGLYPH 7 -# define CMDLGS_NORMAL 1 -# define CMDLGS_HOT 2 -# define CMDLGS_PRESSED 3 -# define CMDLGS_DISABLED 4 -#endif - -/* \internal - Checks if we should use Vista style , or if we should - fall back to Windows style. -*/ -bool QWindowsVistaStylePrivate::useVista() -{ - return (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA - && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) - && QWindowsVistaStylePrivate::useXP(); -} - -/* \internal - Checks and returns the style object -*/ -inline QObject *styleObject(const QStyleOption *option) { - return option ? option->styleObject : 0; -} - -/* \internal - Checks if we can animate on a style option -*/ -bool canAnimate(const QStyleOption *option) { - return option - && option->styleObject - && !option->styleObject->property("_q_no_animation").toBool(); -} - -static inline QImage createAnimationBuffer(const QStyleOption *option, const QWidget *widget) -{ - const int devicePixelRatio = widget ? widget->devicePixelRatio() : 1; - QImage result(option->rect.size() * devicePixelRatio, QImage::Format_ARGB32_Premultiplied); - result.setDevicePixelRatio(devicePixelRatio); - result.fill(0); - return result; -} - -/* \internal - Used by animations to clone a styleoption and shift its offset -*/ -QStyleOption *clonedAnimationStyleOption(const QStyleOption*option) { - QStyleOption *styleOption = 0; - if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) - styleOption = new QStyleOptionSlider(*slider); - else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) - styleOption = new QStyleOptionSpinBox(*spinbox); - else if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) - styleOption = new QStyleOptionGroupBox(*groupBox); - else if (const QStyleOptionComboBox *combo = qstyleoption_cast(option)) - styleOption = new QStyleOptionComboBox(*combo); - else if (const QStyleOptionButton *button = qstyleoption_cast(option)) - styleOption = new QStyleOptionButton(*button); - else - styleOption = new QStyleOption(*option); - styleOption->rect = QRect(QPoint(0,0), option->rect.size()); - return styleOption; -} - -/* \internal - Used by animations to delete cloned styleoption -*/ -void deleteClonedAnimationStyleOption(const QStyleOption *option) -{ - if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) - delete slider; - else if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast(option)) - delete spinbox; - else if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(option)) - delete groupBox; - else if (const QStyleOptionComboBox *combo = qstyleoption_cast(option)) - delete combo; - else if (const QStyleOptionButton *button = qstyleoption_cast(option)) - delete button; - else - delete option; -} - -/*! - \class QWindowsVistaStyle - \brief The QWindowsVistaStyle class provides a look and feel suitable for applications on Microsoft Windows Vista. - \since 4.3 - \ingroup appearance - \inmodule QtWidgets - \internal - - \warning This style is only available on the Windows Vista platform - because it makes use of Windows Vista's style engine. - - \sa QMacStyle, QWindowsXPStyle, QFusionStyle -*/ - -/*! - Constructs a QWindowsVistaStyle object. -*/ -QWindowsVistaStyle::QWindowsVistaStyle() - : QWindowsXPStyle(*new QWindowsVistaStylePrivate) -{ -} - -/*! - Destructor. -*/ -QWindowsVistaStyle::~QWindowsVistaStyle() -{ -} - -//convert Qt state flags to uxtheme button states -static int buttonStateId(int flags, int partId) -{ - int stateId = 0; - if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) { - if (!(flags & QStyle::State_Enabled)) - stateId = RBS_UNCHECKEDDISABLED; - else if (flags & QStyle::State_Sunken) - stateId = RBS_UNCHECKEDPRESSED; - else if (flags & QStyle::State_MouseOver) - stateId = RBS_UNCHECKEDHOT; - else - stateId = RBS_UNCHECKEDNORMAL; - - if (flags & QStyle::State_On) - stateId += RBS_CHECKEDNORMAL-1; - - } else if (partId == BP_PUSHBUTTON) { - if (!(flags & QStyle::State_Enabled)) - stateId = PBS_DISABLED; - else if (flags & (QStyle::State_Sunken | QStyle::State_On)) - stateId = PBS_PRESSED; - else if (flags & QStyle::State_MouseOver) - stateId = PBS_HOT; - else - stateId = PBS_NORMAL; - } else { - Q_ASSERT(1); - } - return stateId; -} - -bool QWindowsVistaAnimation::isUpdateNeeded() const -{ - return QWindowsVistaStylePrivate::useVista(); -} - -void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option) -{ - painter->drawImage(option->rect, currentImage()); -} - -static inline bool supportsStateTransition(QStyle::PrimitiveElement element, - const QStyleOption *option, - const QWidget *widget) -{ - bool result = false; - switch (element) { - case QStyle::PE_IndicatorRadioButton: - case QStyle::PE_IndicatorCheckBox: - result = true; - break; - // QTBUG-40634, do not animate when color is set in palette for PE_PanelLineEdit. - case QStyle::PE_FrameLineEdit: - result = !QWindowsXPStylePrivate::isLineEditBaseColorSet(option, widget); - break; - default: - break; - } - return result; -} - -/*! - \internal - - Animations are used for some state transitions on specific widgets. - - Only one running animation can exist for a widget at any specific - time. Animations can be added through - QWindowsVistaStylePrivate::startAnimation(Animation *) and any - existing animation on a widget can be retrieved with - QWindowsVistaStylePrivate::widgetAnimation(Widget *). - - Once an animation has been started, - QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will - continuously call update() on the widget until it is stopped, - meaning that drawPrimitive will be called many times until the - transition has completed. During this time, the result will be - retrieved by the Animation::paint(...) function and not by the style - itself. - - To determine if a transition should occur, the style needs to know - the previous state of the widget as well as the current one. This is - solved by updating dynamic properties on the widget every time the - function is called. - - Transitions interrupting existing transitions should always be - smooth, so whenever a hover-transition is started on a pulsating - button, it uses the current frame of the pulse-animation as the - starting image for the hover transition. - - */ - -void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget) const -{ - QWindowsVistaStylePrivate *d = const_cast(d_func()); - - int state = option->state; - if (!QWindowsVistaStylePrivate::useVista()) { - QWindowsStyle::drawPrimitive(element, option, painter, widget); - return; - } - - if ((option->state & State_Enabled) && d->transitionsEnabled() && canAnimate(option)) { - { - QRect oldRect; - QRect newRect; - - if (supportsStateTransition(element, option, widget)) { - // Retrieve and update the dynamic properties tracking - // the previous state of the widget: - QObject *styleObject = option->styleObject; - styleObject->setProperty("_q_no_animation", true); - - int oldState = styleObject->property("_q_stylestate").toInt(); - oldRect = styleObject->property("_q_stylerect").toRect(); - newRect = option->rect; - styleObject->setProperty("_q_stylestate", (int)option->state); - styleObject->setProperty("_q_stylerect", option->rect); - - bool doTransition = oldState && - ((state & State_Sunken) != (oldState & State_Sunken) || - (state & State_On) != (oldState & State_On) || - (state & State_MouseOver) != (oldState & State_MouseOver)); - - if (oldRect != newRect || - (state & State_Enabled) != (oldState & State_Enabled) || - (state & State_Active) != (oldState & State_Active)) - d->stopAnimation(styleObject); - - if (option->state & State_ReadOnly && element == PE_FrameLineEdit) // Do not animate read only line edits - doTransition = false; - - if (doTransition) { - QStyleOption *styleOption = clonedAnimationStyleOption(option); - styleOption->state = (QStyle::State)oldState; - - QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject)); - QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject); - - // We create separate images for the initial and final transition states and store them in the - // Transition object. - QImage startImage = createAnimationBuffer(option, widget); - QPainter startPainter(&startImage); - - QImage endImage = createAnimationBuffer(option, widget); - QPainter endPainter(&endImage); - - // If we have a running animation on the widget already, we will use that to paint the initial - // state of the new transition, this ensures a smooth transition from a current animation such as a - // pulsating default button into the intended target state. - if (!anim) - proxy()->drawPrimitive(element, styleOption, &startPainter, widget); - else - anim->paint(&startPainter, styleOption); - - t->setStartImage(startImage); - - // The end state of the transition is simply the result we would have painted - // if the style was not animated. - styleOption->styleObject = 0; - styleOption->state = option->state; - proxy()->drawPrimitive(element, styleOption, &endPainter, widget); - - - t->setEndImage(endImage); - - HTHEME theme; - int partId; - DWORD duration; - int fromState = 0; - int toState = 0; - - //translate state flags to UXTHEME states : - if (element == PE_FrameLineEdit) { - theme = OpenThemeData(0, L"Edit"); - partId = EP_EDITBORDER_NOSCROLL; - - if (oldState & State_MouseOver) - fromState = ETS_HOT; - else if (oldState & State_HasFocus) - fromState = ETS_FOCUSED; - else - fromState = ETS_NORMAL; - - if (state & State_MouseOver) - toState = ETS_HOT; - else if (state & State_HasFocus) - toState = ETS_FOCUSED; - else - toState = ETS_NORMAL; - - } else { - theme = OpenThemeData(0, L"Button"); - if (element == PE_IndicatorRadioButton) - partId = BP_RADIOBUTTON; - else if (element == PE_IndicatorCheckBox) - partId = BP_CHECKBOX; - else - partId = BP_PUSHBUTTON; - - fromState = buttonStateId(oldState, partId); - toState = buttonStateId(option->state, partId); - } - - // Retrieve the transition time between the states from the system. - if (theme - && SUCCEEDED(GetThemeTransitionDuration(theme, partId, fromState, toState, - TMT_TRANSITIONDURATIONS, &duration))) { - t->setDuration(duration); - } - t->setStartTime(QTime::currentTime()); - - deleteClonedAnimationStyleOption(styleOption); - d->startAnimation(t); - } - styleObject->setProperty("_q_no_animation", false); - } - - } // End of animation part - } - - QRect rect = option->rect; - - switch (element) { - case PE_IndicatorHeaderArrow: - if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { - int stateId = HSAS_SORTEDDOWN; - if (header->sortIndicator & QStyleOptionHeader::SortDown) - stateId = HSAS_SORTEDUP; //note that the uxtheme sort down indicator is the inverse of ours - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::HeaderTheme, - HP_HEADERSORTARROW, stateId, option->rect); - d->drawBackground(theme); - } - break; - - case PE_IndicatorBranch: - { - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::VistaTreeViewTheme); - static int decoration_size = 0; - if (!decoration_size && theme.isValid()) { - XPThemeData themeSize = theme; - themeSize.partId = TVP_HOTGLYPH; - themeSize.stateId = GLPS_OPENED; - const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - decoration_size = qRound(qMax(size.width(), size.height())); - } - int mid_h = option->rect.x() + option->rect.width() / 2; - int mid_v = option->rect.y() + option->rect.height() / 2; - int bef_h = mid_h; - int bef_v = mid_v; - int aft_h = mid_h; - int aft_v = mid_v; - if (option->state & State_Children) { - int delta = decoration_size / 2; - theme.rect = QRect(bef_h - delta, bef_v - delta, decoration_size, decoration_size); - theme.partId = option->state & State_MouseOver ? TVP_HOTGLYPH : TVP_GLYPH; - theme.stateId = option->state & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; - if (option->direction == Qt::RightToLeft) - theme.mirrorHorizontally = true; - d->drawBackground(theme); - bef_h -= delta + 2; - bef_v -= delta + 2; - aft_h += delta - 2; - aft_v += delta - 2; - } -#if 0 - QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); - if (option->state & State_Item) { - if (option->direction == Qt::RightToLeft) - painter->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); - else - painter->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); - } - if (option->state & State_Sibling && option->rect.bottom() > aft_v) - painter->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); - if (option->state & (State_Open | State_Children | State_Item | State_Sibling) && (bef_v > option->rect.y())) - painter->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); -#endif - } - break; - - case PE_PanelButtonBevel: - case PE_IndicatorCheckBox: - case PE_IndicatorRadioButton: - { - if (QWindowsVistaAnimation *a = - qobject_cast(d->animation(styleObject(option)))){ - a->paint(painter, option); - } else { - QWindowsXPStyle::drawPrimitive(element, option, painter, widget); - } - } - break; - - case PE_FrameMenu: - { - int stateId = option->state & State_Active ? MB_ACTIVE : MB_INACTIVE; - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPBORDERS, stateId, option->rect); - d->drawBackground(theme); - } - break; - case PE_Frame: { -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::isInstanceOf(option->styleObject, QAccessible::EditableText) - || QStyleHelper::isInstanceOf(option->styleObject, QAccessible::StaticText) || -#else - if ( -#endif - (widget && widget->inherits("QTextEdit"))) { - painter->save(); - int stateId = ETS_NORMAL; - if (!(state & State_Enabled)) - stateId = ETS_DISABLED; - else if (state & State_ReadOnly) - stateId = ETS_READONLY; - else if (state & State_HasFocus) - stateId = ETS_SELECTED; - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::EditTheme, - EP_EDITBORDER_HVSCROLL, stateId, option->rect); - // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping - int borderSize = 1; - GetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); - QRegion clipRegion = option->rect; - QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); - clipRegion ^= content; - painter->setClipRegion(clipRegion); - d->drawBackground(theme); - painter->restore(); - } else { - QWindowsXPStyle::drawPrimitive(element, option, painter, widget); - } - } - break; - - case PE_PanelLineEdit: - if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { - bool isEnabled = option->state & State_Enabled; - if (QWindowsXPStylePrivate::isLineEditBaseColorSet(option, widget)) { - painter->fillRect(panel->rect, panel->palette.brush(QPalette::Base)); - } else { - int partId = EP_BACKGROUND; - int stateId = EBS_NORMAL; - if (!isEnabled) - stateId = EBS_DISABLED; - else if (state & State_ReadOnly) - stateId = EBS_READONLY; - else if (state & State_MouseOver) - stateId = EBS_HOT; - - XPThemeData theme(0, painter, QWindowsXPStylePrivate::EditTheme, - partId, stateId, rect); - if (!theme.isValid()) { - QWindowsStyle::drawPrimitive(element, option, painter, widget); - return; - } - int bgType; - GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &bgType); - if( bgType == BT_IMAGEFILE ) { - d->drawBackground(theme); - } else { - QBrush fillColor = option->palette.brush(QPalette::Base); - if (!isEnabled) { - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); - // Use only if the fill property comes from our part - if ((origin == PO_PART || origin == PO_STATE)) { - COLORREF bgRef; - GetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); - fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); - } - } - painter->fillRect(option->rect, fillColor); - } - } - if (panel->lineWidth > 0) - proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget); - return; - } - break; - - case PE_FrameLineEdit: - if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject(option)))) { - anim->paint(painter, option); - } else { - QPainter *p = painter; - if (QWindowsXPStylePrivate::isItemViewDelegateLineEdit(widget)) { - // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. - QPen oldPen = p->pen(); - // Inner white border - p->setPen(QPen(option->palette.base().color(), 1)); - p->drawRect(option->rect.adjusted(1, 1, -2, -2)); - // Outer dark border - p->setPen(QPen(option->palette.shadow().color(), 1)); - p->drawRect(option->rect.adjusted(0, 0, -1, -1)); - p->setPen(oldPen); - return; - } else { - int stateId = ETS_NORMAL; - if (!(state & State_Enabled)) - stateId = ETS_DISABLED; - else if (state & State_ReadOnly) - stateId = ETS_READONLY; - else if (state & State_MouseOver) - stateId = ETS_HOT; - else if (state & State_HasFocus) - stateId = ETS_SELECTED; - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::EditTheme, - EP_EDITBORDER_NOSCROLL, stateId, option->rect); - theme.noContent = true; - painter->save(); - QRegion clipRegion = option->rect; - clipRegion -= option->rect.adjusted(2, 2, -2, -2); - painter->setClipRegion(clipRegion); - d->drawBackground(theme); - painter->restore(); - } - } - break; - - case PE_IndicatorToolBarHandle: - { - XPThemeData theme; - QRect rect; - if (option->state & State_Horizontal) { - theme = XPThemeData(widget, painter, - QWindowsXPStylePrivate::RebarTheme, - RP_GRIPPER, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); - rect = option->rect.adjusted(0, 1, 0, -2); - rect.setWidth(4); - } else { - theme = XPThemeData(widget, painter, QWindowsXPStylePrivate::RebarTheme, - RP_GRIPPERVERT, ETS_NORMAL, option->rect.adjusted(0, 1, -2, -2)); - rect = option->rect.adjusted(1, 0, -1, 0); - rect.setHeight(4); - } - theme.rect = rect; - d->drawBackground(theme); - } - break; - - case PE_IndicatorToolBarSeparator: - { - QPen pen = painter->pen(); - int margin = 3; - painter->setPen(option->palette.background().color().darker(114)); - if (option->state & State_Horizontal) { - int x1 = option->rect.center().x(); - painter->drawLine(QPoint(x1, option->rect.top() + margin), QPoint(x1, option->rect.bottom() - margin)); - } else { - int y1 = option->rect.center().y(); - painter->drawLine(QPoint(option->rect.left() + margin, y1), QPoint(option->rect.right() - margin, y1)); - } - painter->setPen(pen); - } - break; - - case PE_PanelTipLabel: { - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::ToolTipTheme, - TTP_STANDARD, TTSS_NORMAL, option->rect); - d->drawBackground(theme); - break; - } - - case PE_PanelItemViewItem: - { - const QStyleOptionViewItem *vopt; - bool newStyle = true; - QAbstractItemView::SelectionBehavior selectionBehavior = QAbstractItemView::SelectRows; - QAbstractItemView::SelectionMode selectionMode = QAbstractItemView::NoSelection; - if (const QAbstractItemView *view = qobject_cast(widget)) { - newStyle = !qobject_cast(view); - selectionBehavior = view->selectionBehavior(); - selectionMode = view->selectionMode(); -#ifndef QT_NO_ACCESSIBILITY - } else if (!widget) { - newStyle = !QStyleHelper::hasAncestor(option->styleObject, QAccessible::MenuItem) ; -#endif - } - - if (newStyle && (vopt = qstyleoption_cast(option))) { - bool selected = vopt->state & QStyle::State_Selected; - const bool hover = selectionMode != QAbstractItemView::NoSelection && (vopt->state & QStyle::State_MouseOver); - bool active = vopt->state & QStyle::State_Active; - - if (vopt->features & QStyleOptionViewItem::Alternate) - painter->fillRect(vopt->rect, vopt->palette.alternateBase()); - - QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled - ? QPalette::Normal : QPalette::Disabled; - if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) - cg = QPalette::Inactive; - - QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(-1, 0, 1, 0); - itemRect.setTop(vopt->rect.top()); - itemRect.setBottom(vopt->rect.bottom()); - - QSize sectionSize = itemRect.size(); - if (vopt->showDecorationSelected) - sectionSize = vopt->rect.size(); - - if (selectionBehavior == QAbstractItemView::SelectRows) - sectionSize.setWidth(vopt->rect.width()); - QPixmap pixmap; - - if (vopt->backgroundBrush.style() != Qt::NoBrush) { - const QPointF oldBrushOrigin = painter->brushOrigin(); - painter->setBrushOrigin(vopt->rect.topLeft()); - painter->fillRect(vopt->rect, vopt->backgroundBrush); - painter->setBrushOrigin(oldBrushOrigin); - } - - if (hover || selected) { - if (sectionSize.width() > 0 && sectionSize.height() > 0) { - QString key = QString::fromLatin1("qvdelegate-%1-%2-%3-%4-%5").arg(sectionSize.width()) - .arg(sectionSize.height()).arg(selected).arg(active).arg(hover); - if (!QPixmapCache::find(key, pixmap)) { - pixmap = QPixmap(sectionSize); - pixmap.fill(Qt::transparent); - - int state; - if (selected && hover) - state = LISS_HOTSELECTED; - else if (selected && !active) - state = LISS_SELECTEDNOTFOCUS; - else if (selected) - state = LISS_SELECTED; - else - state = LISS_HOT; - - QPainter pixmapPainter(&pixmap); - XPThemeData theme(widget, &pixmapPainter, - QWindowsXPStylePrivate::VistaTreeViewTheme, - LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height())); - if (theme.isValid()) { - d->drawBackground(theme); - } else { - QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget); - break;; - } - QPixmapCache::insert(key, pixmap); - } - } - - if (vopt->showDecorationSelected) { - const int frame = 2; //Assumes a 2 pixel pixmap border - QRect srcRect = QRect(0, 0, sectionSize.width(), sectionSize.height()); - QRect pixmapRect = vopt->rect; - bool reverse = vopt->direction == Qt::RightToLeft; - bool leftSection = vopt->viewItemPosition == QStyleOptionViewItem::Beginning; - bool rightSection = vopt->viewItemPosition == QStyleOptionViewItem::End; - if (vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne - || vopt->viewItemPosition == QStyleOptionViewItem::Invalid) - painter->drawPixmap(pixmapRect.topLeft(), pixmap); - else if (reverse ? rightSection : leftSection){ - painter->drawPixmap(QRect(pixmapRect.topLeft(), - QSize(frame, pixmapRect.height())), pixmap, - QRect(QPoint(0, 0), QSize(frame, pixmapRect.height()))); - painter->drawPixmap(pixmapRect.adjusted(frame, 0, 0, 0), - pixmap, srcRect.adjusted(frame, 0, -frame, 0)); - } else if (reverse ? leftSection : rightSection) { - painter->drawPixmap(QRect(pixmapRect.topRight() - QPoint(frame - 1, 0), - QSize(frame, pixmapRect.height())), pixmap, - QRect(QPoint(pixmapRect.width() - frame, 0), - QSize(frame, pixmapRect.height()))); - painter->drawPixmap(pixmapRect.adjusted(0, 0, -frame, 0), - pixmap, srcRect.adjusted(frame, 0, -frame, 0)); - } else if (vopt->viewItemPosition == QStyleOptionViewItem::Middle) - painter->drawPixmap(pixmapRect, pixmap, - srcRect.adjusted(frame, 0, -frame, 0)); - } else { - if (vopt->text.isEmpty() && vopt->icon.isNull()) - break; - painter->drawPixmap(itemRect.topLeft(), pixmap); - } - } - } else { - QWindowsXPStyle::drawPrimitive(element, option, painter, widget); - } - break; - } - case PE_Widget: - { -#if QT_CONFIG(dialogbuttonbox) - const QDialogButtonBox *buttonBox = 0; - - if (qobject_cast (widget)) - buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); -#ifndef QT_NO_INPUTDIALOG - else if (qobject_cast (widget)) - buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); -#endif // QT_NO_INPUTDIALOG - - if (buttonBox) { - //draw white panel part - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::TaskDialogTheme, - TDLG_PRIMARYPANEL, 0, option->rect); - QRect toprect = option->rect; - toprect.setBottom(buttonBox->geometry().top()); - theme.rect = toprect; - d->drawBackground(theme); - - //draw bottom panel part - QRect buttonRect = option->rect; - buttonRect.setTop(buttonBox->geometry().top()); - theme.rect = buttonRect; - theme.partId = TDLG_SECONDARYPANEL; - d->drawBackground(theme); - } -#endif - } - break; - default: - QWindowsXPStyle::drawPrimitive(element, option, painter, widget); - break; - } -} - - -/*! - \internal - - see drawPrimitive for comments on the animation support - */ -void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget) const -{ - QWindowsVistaStylePrivate *d = const_cast(d_func()); - - if (!QWindowsVistaStylePrivate::useVista()) { - QWindowsStyle::drawControl(element, option, painter, widget); - return; - } - - bool selected = option->state & State_Selected; - bool pressed = option->state & State_Sunken; - bool disabled = !(option->state & State_Enabled); - - int state = option->state; - int themeNumber = -1; - - QRect rect(option->rect); - State flags = option->state; - int partId = 0; - int stateId = 0; - - if (d->transitionsEnabled() && canAnimate(option)) - { - if (element == CE_PushButtonBevel) { - QRect oldRect; - QRect newRect; - - QObject *styleObject = option->styleObject; - - int oldState = styleObject->property("_q_stylestate").toInt(); - oldRect = styleObject->property("_q_stylerect").toRect(); - newRect = option->rect; - styleObject->setProperty("_q_stylestate", (int)option->state); - styleObject->setProperty("_q_stylerect", option->rect); - - bool wasDefault = false; - bool isDefault = false; - if (const QStyleOptionButton *button = qstyleoption_cast(option)) { - wasDefault = styleObject->property("_q_isdefault").toBool(); - isDefault = button->features & QStyleOptionButton::DefaultButton; - styleObject->setProperty("_q_isdefault", isDefault); - } - - bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || - (state & State_On) != (oldState & State_On) || - (state & State_MouseOver) != (oldState & State_MouseOver)); - - if (oldRect != newRect || (wasDefault && !isDefault)) { - doTransition = false; - d->stopAnimation(styleObject); - } - - if (doTransition) { - styleObject->setProperty("_q_no_animation", true); - - QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject); - QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject)); - QStyleOption *styleOption = clonedAnimationStyleOption(option); - styleOption->state = (QStyle::State)oldState; - - QImage startImage = createAnimationBuffer(option, widget); - QPainter startPainter(&startImage); - - // Use current state of existing animation if already one is running - if (!anim) { - proxy()->drawControl(element, styleOption, &startPainter, widget); - } else { - anim->paint(&startPainter, styleOption); - d->stopAnimation(styleObject); - } - - t->setStartImage(startImage); - QImage endImage = createAnimationBuffer(option, widget); - QPainter endPainter(&endImage); - styleOption->state = option->state; - proxy()->drawControl(element, styleOption, &endPainter, widget); - t->setEndImage(endImage); - - - DWORD duration = 0; - const HTHEME theme = OpenThemeData(0, L"Button"); - - int fromState = buttonStateId(oldState, BP_PUSHBUTTON); - int toState = buttonStateId(option->state, BP_PUSHBUTTON); - if (GetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) - t->setDuration(duration); - else - t->setDuration(0); - t->setStartTime(QTime::currentTime()); - styleObject->setProperty("_q_no_animation", false); - - deleteClonedAnimationStyleOption(styleOption); - d->startAnimation(t); - } - - QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject)); - if (anim) { - anim->paint(painter, option); - return; - } - - } - } - switch (element) { - case CE_PushButtonBevel: - if (const QStyleOptionButton *btn = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_PUSHBUTTON; - if (btn->features & QStyleOptionButton::CommandLinkButton) - partId = BP_COMMANDLINK; - bool justFlat = (btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken)); - if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) - stateId = PBS_DISABLED; - else if (justFlat) - ; - else if (flags & (State_Sunken | State_On)) - stateId = PBS_PRESSED; - else if (flags & State_MouseOver) - stateId = PBS_HOT; - else if (btn->features & QStyleOptionButton::DefaultButton && (state & State_Active)) - stateId = PBS_DEFAULTED; - else - stateId = PBS_NORMAL; - - if (!justFlat) { - - if (d->transitionsEnabled() && (btn->features & QStyleOptionButton::DefaultButton) && - !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) && - (state & State_Enabled) && (state & State_Active)) - { - QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject(option))); - - if (!anim) { - QImage startImage = createAnimationBuffer(option, widget); - QImage alternateImage = createAnimationBuffer(option, widget); - - QWindowsVistaPulse *pulse = new QWindowsVistaPulse(styleObject(option)); - - QPainter startPainter(&startImage); - stateId = PBS_DEFAULTED; - XPThemeData theme(widget, &startPainter, themeNumber, partId, stateId, rect); - d->drawBackground(theme); - - QPainter alternatePainter(&alternateImage); - theme.stateId = PBS_DEFAULTED_ANIMATING; - theme.painter = &alternatePainter; - d->drawBackground(theme); - pulse->setStartImage(startImage); - pulse->setEndImage(alternateImage); - pulse->setStartTime(QTime::currentTime()); - pulse->setDuration(2000); - d->startAnimation(pulse); - anim = pulse; - } - - if (anim) - anim->paint(painter, option); - else { - XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); - d->drawBackground(theme); - } - } - else { - XPThemeData theme(widget, painter, themeNumber, partId, stateId, rect); - d->drawBackground(theme); - } - } - - if (btn->features & QStyleOptionButton::HasMenu) { - int mbiw = 0, mbih = 0; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, - TP_DROPDOWNBUTTON); - if (theme.isValid()) { - const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - if (!size.isEmpty()) { - mbiw = qRound(size.width()); - mbih = qRound(size.height()); - } - } - QRect ir = subElementRect(SE_PushButtonContents, option, 0); - QStyleOptionButton newBtn = *btn; - newBtn.rect = QStyle::visualRect(option->direction, option->rect, - QRect(ir.right() - mbiw - 2, - option->rect.top() + (option->rect.height()/2) - (mbih/2), - mbiw + 1, mbih + 1)); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); - } - return; - } - break; - - case CE_ProgressBarContents: - if (const QStyleOptionProgressBar *bar - = qstyleoption_cast(option)) { - bool isIndeterminate = (bar->minimum == 0 && bar->maximum == 0); - const bool vertical = bar->orientation == Qt::Vertical; - const bool inverted = bar->invertedAppearance; - - if (isIndeterminate || (bar->progress > 0 && (bar->progress < bar->maximum) && d->transitionsEnabled())) { - if (!d->animation(styleObject(option))) - d->startAnimation(new QProgressStyleAnimation(d->animationFps, styleObject(option))); - } else { - d->stopAnimation(styleObject(option)); - } - - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::ProgressTheme, - vertical ? PP_FILLVERT : PP_FILL); - theme.rect = option->rect; - bool reverse = (bar->direction == Qt::LeftToRight && inverted) || (bar->direction == Qt::RightToLeft && !inverted); - QTime current = QTime::currentTime(); - - if (isIndeterminate) { - if (QProgressStyleAnimation *a = qobject_cast(d->animation(styleObject(option)))) { - int glowSize = 120; - int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); - int animOffset = a->startTime().msecsTo(current) / 4; - if (animOffset > animationWidth) - a->setStartTime(QTime::currentTime()); - painter->save(); - painter->setClipRect(theme.rect); - QRect animRect; - QSize pixmapSize(14, 14); - if (vertical) { - animRect = QRect(theme.rect.left(), - inverted ? rect.top() - glowSize + animOffset : - rect.bottom() + glowSize - animOffset, - rect.width(), glowSize); - pixmapSize.setHeight(animRect.height()); - } else { - animRect = QRect(rect.left() - glowSize + animOffset, - rect.top(), glowSize, rect.height()); - animRect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, - option->rect, animRect); - pixmapSize.setWidth(animRect.width()); - } - QString name = QString::fromLatin1("qiprogress-%1-%2").arg(pixmapSize.width()).arg(pixmapSize.height()); - QPixmap pixmap; - if (!QPixmapCache::find(name, pixmap)) { - QImage image(pixmapSize, QImage::Format_ARGB32); - image.fill(Qt::transparent); - QPainter imagePainter(&image); - theme.painter = &imagePainter; - theme.partId = vertical ? PP_FILLVERT : PP_FILL; - theme.rect = QRect(QPoint(0,0), animRect.size()); - QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(), - vertical ? image.height() : 0); - alphaGradient.setColorAt(0, QColor(0, 0, 0, 0)); - alphaGradient.setColorAt(0.5, QColor(0, 0, 0, 220)); - alphaGradient.setColorAt(1, QColor(0, 0, 0, 0)); - imagePainter.fillRect(image.rect(), alphaGradient); - imagePainter.setCompositionMode(QPainter::CompositionMode_SourceIn); - d->drawBackground(theme); - imagePainter.end(); - pixmap = QPixmap::fromImage(image); - QPixmapCache::insert(name, pixmap); - } - painter->drawPixmap(animRect, pixmap); - painter->restore(); - } - } - else { - qint64 progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar - - if (vertical) { - int maxHeight = option->rect.height(); - int minHeight = 0; - double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxHeight); - int height = isIndeterminate ? maxHeight: qMax(int(vc6_workaround), minHeight); - theme.rect.setHeight(height); - if (!inverted) - theme.rect.moveTop(rect.height() - theme.rect.height()); - } else { - int maxWidth = option->rect.width(); - int minWidth = 0; - double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth); - int width = isIndeterminate ? maxWidth : qMax(int(vc6_workaround), minWidth); - theme.rect.setWidth(width); - theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, - option->rect, theme.rect); - } - d->drawBackground(theme); - - if (QProgressStyleAnimation *a = qobject_cast(d->animation(styleObject(option)))) { - int glowSize = 140; - int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); - int animOffset = a->startTime().msecsTo(current) / 4; - theme.partId = vertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY; - if (animOffset > animationWidth) { - if (bar->progress < bar->maximum) - a->setStartTime(QTime::currentTime()); - else - d->stopAnimation(styleObject(option)); //we stop the glow motion only after it has - //moved out of view - } - painter->save(); - painter->setClipRect(theme.rect); - if (vertical) { - theme.rect = QRect(theme.rect.left(), - inverted ? rect.top() - glowSize + animOffset : - rect.bottom() + glowSize - animOffset, - rect.width(), glowSize); - } else { - theme.rect = QRect(rect.left() - glowSize + animOffset,rect.top(), glowSize, rect.height()); - theme.rect = QStyle::visualRect(reverse ? Qt::RightToLeft : Qt::LeftToRight, option->rect, theme.rect); - } - d->drawBackground(theme); - painter->restore(); - } - } - } - break; - - case CE_MenuBarItem: - { - - if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) - { - if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) - break; - - QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText; - QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); - - uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) - alignment |= Qt::TextHideMnemonic; - - if (widget && mbi->palette.color(QPalette::Window) != Qt::transparent) { // Not needed for QtQuick Controls - //The rect adjustment is a workaround for the menu not really filling its background. - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1)); - d->drawBackground(theme); - } - - int stateId = MBI_NORMAL; - if (disabled) - stateId = MBI_DISABLED; - else if (pressed) - stateId = MBI_PUSHED; - else if (selected) - stateId = MBI_HOT; - - XPThemeData theme2(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_BARITEM, stateId, option->rect); - d->drawBackground(theme2); - - if (!pix.isNull()) - drawItemPixmap(painter, mbi->rect, alignment, pix); - else - drawItemText(painter, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); - } - } - break; -#ifndef QT_NO_MENU - case CE_MenuItem: - if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { - // windows always has a check column, regardless whether we have an icon or not - const qreal factor = QWindowsXPStylePrivate::nativeMetricScaleFactor(widget); - int checkcol = qRound(qreal(25) * factor); - const int gutterWidth = qRound(qreal(3) * factor); - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPCHECKBACKGROUND, MBI_HOT); - XPThemeData themeSize = theme; - themeSize.partId = MENU_POPUPCHECK; - themeSize.stateId = 0; - const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right())); - } - QRect rect = option->rect; - - //draw vertical menu line - if (option->direction == Qt::LeftToRight) - checkcol += rect.x(); - QPoint p1 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.top())); - QPoint p2 = QStyle::visualPos(option->direction, menuitem->rect, QPoint(checkcol, rect.bottom())); - QRect gutterRect(p1.x(), p1.y(), gutterWidth, p2.y() - p1.y() + 1); - XPThemeData theme2(widget, painter, QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPGUTTER, stateId, gutterRect); - d->drawBackground(theme2); - - int x, y, w, h; - menuitem->rect.getRect(&x, &y, &w, &h); - int tab = menuitem->tabWidth; - bool dis = !(menuitem->state & State_Enabled); - bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable - ? menuitem->checked : false; - bool act = menuitem->state & State_Selected; - - if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { - int yoff = y-2 + h / 2; - const int separatorSize = qRound(qreal(6) * QWindowsStylePrivate::nativeMetricScaleFactor(widget)); - QPoint p1 = QPoint(x + checkcol, yoff); - QPoint p2 = QPoint(x + w + separatorSize, yoff); - stateId = MBI_HOT; - QRect subRect(p1.x() + (gutterWidth - menuitem->rect.x()), p1.y(), - p2.x() - p1.x(), separatorSize); - subRect = QStyle::visualRect(option->direction, option->rect, subRect ); - XPThemeData theme2(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPSEPARATOR, stateId, subRect); - d->drawBackground(theme2); - return; - } - - QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), - menuitem->rect.y(), checkcol - (gutterWidth + menuitem->rect.x()), menuitem->rect.height())); - - if (act) { - stateId = dis ? MBI_DISABLED : MBI_HOT; - XPThemeData theme2(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPITEM, stateId, option->rect); - d->drawBackground(theme2); - } - - if (checked) { - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPCHECKBACKGROUND, - menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); - XPThemeData themeSize = theme; - themeSize.partId = MENU_POPUPCHECK; - themeSize.stateId = 0; - const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()), - qRound(size.height() + margins.bottom() + margins.top())); - checkRect.moveCenter(vCheckRect.center()); - theme.rect = checkRect; - - d->drawBackground(theme); - - if (menuitem->icon.isNull()) { - checkRect = QRect(QPoint(0, 0), size.toSize()); - checkRect.moveCenter(theme.rect.center()); - theme.rect = checkRect; - - theme.partId = MENU_POPUPCHECK; - bool bullet = menuitem->checkType & QStyleOptionMenuItem::Exclusive; - if (dis) - theme.stateId = bullet ? MC_BULLETDISABLED: MC_CHECKMARKDISABLED; - else - theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL; - d->drawBackground(theme); - } - } - - if (!menuitem->icon.isNull()) { - QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; - if (act && !dis) - mode = QIcon::Active; - QPixmap pixmap; - if (checked) - pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On); - else - pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode); - const int pixw = pixmap.width() / pixmap.devicePixelRatio(); - const int pixh = pixmap.height() / pixmap.devicePixelRatio(); - QRect pmr(0, 0, pixw, pixh); - pmr.moveCenter(vCheckRect.center()); - painter->setPen(menuitem->palette.text().color()); - painter->drawPixmap(pmr.topLeft(), pixmap); - } - - painter->setPen(menuitem->palette.buttonText().color()); - - const QColor textColor = menuitem->palette.text().color(); - if (dis) - painter->setPen(textColor); - - int xm = windowsItemFrame + checkcol + windowsItemHMargin + (gutterWidth - menuitem->rect.x()) - 1; - int xpos = menuitem->rect.x() + xm; - QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); - QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); - QString s = menuitem->text; - if (!s.isEmpty()) { // draw text - painter->save(); - int t = s.indexOf(QLatin1Char('\t')); - int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) - text_flags |= Qt::TextHideMnemonic; - text_flags |= Qt::AlignLeft; - if (t >= 0) { - QRect vShortcutRect = visualRect(option->direction, menuitem->rect, - QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); - painter->drawText(vShortcutRect, text_flags, s.mid(t + 1)); - s = s.left(t); - } - QFont font = menuitem->font; - if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) - font.setBold(true); - painter->setFont(font); - painter->setPen(textColor); - painter->drawText(vTextRect, text_flags, s.left(t)); - painter->restore(); - } - if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow - int dim = (h - 2 * windowsItemFrame) / 2; - PrimitiveElement arrow; - arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; - xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; - QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); - QStyleOptionMenuItem newMI = *menuitem; - newMI.rect = vSubMenuRect; - newMI.state = dis ? State_None : State_Enabled; - proxy()->drawPrimitive(arrow, &newMI, painter, widget); - } - } - break; -#endif // QT_NO_MENU - case CE_HeaderSection: - if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { - partId = HP_HEADERITEM; - if (flags & State_Sunken) - stateId = HIS_PRESSED; - else if (flags & State_MouseOver) - stateId = HIS_HOT; - else - stateId = HIS_NORMAL; - - if (header->sortIndicator != QStyleOptionHeader::None) - stateId += 3; - - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::HeaderTheme, - partId, stateId, option->rect); - d->drawBackground(theme); - } - break; - case CE_MenuBarEmptyArea: - { - stateId = MBI_NORMAL; - if (!(state & State_Enabled)) - stateId = MBI_DISABLED; - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::MenuTheme, - MENU_BARBACKGROUND, stateId, option->rect); - d->drawBackground(theme); - } - break; - case CE_ToolBar: - if (const QStyleOptionToolBar *toolbar = qstyleoption_cast(option)) { - QPalette pal = option->palette; - pal.setColor(QPalette::Dark, option->palette.background().color().darker(130)); - QStyleOptionToolBar copyOpt = *toolbar; - copyOpt.palette = pal; - QWindowsStyle::drawControl(element, ©Opt, painter, widget); - } - break; - case CE_DockWidgetTitle: - if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) { - const QDockWidget *dockWidget = qobject_cast(widget); - QRect rect = option->rect; - if (dockWidget && dockWidget->isFloating()) { - QWindowsXPStyle::drawControl(element, option, painter, widget); - break; //otherwise fall through - } - - const bool verticalTitleBar = dwOpt->verticalTitleBar; - - if (verticalTitleBar) { - rect = rect.transposed(); - - painter->translate(rect.left() - 1, rect.top() + rect.width()); - painter->rotate(-90); - painter->translate(-rect.left() + 1, -rect.top()); - } - - painter->setBrush(option->palette.background().color().darker(110)); - painter->setPen(option->palette.background().color().darker(130)); - painter->drawRect(rect.adjusted(0, 1, -1, -3)); - - int buttonMargin = 4; - int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); - int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); - const QDockWidget *dw = qobject_cast(widget); - bool isFloating = dw != 0 && dw->isFloating(); - - QRect r = option->rect.adjusted(0, 2, -1, -3); - QRect titleRect = r; - - if (dwOpt->closable) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); - titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); - } - - if (dwOpt->floatable) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); - titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); - } - - if (isFloating) { - titleRect.adjust(0, -fw, 0, 0); - if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey()) - titleRect.adjust(titleRect.height() + mw, 0, 0, 0); - } else { - titleRect.adjust(mw, 0, 0, 0); - if (!dwOpt->floatable && !dwOpt->closable) - titleRect.adjust(0, 0, -mw, 0); - } - if (!verticalTitleBar) - titleRect = visualRect(dwOpt->direction, r, titleRect); - - if (!dwOpt->title.isEmpty()) { - QString titleText = painter->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, - verticalTitleBar ? titleRect.height() : titleRect.width()); - const int indent = 4; - drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1), - Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette, - dwOpt->state & State_Enabled, titleText, - QPalette::WindowText); - } - } - break; -#ifndef QT_NO_ITEMVIEWS - case CE_ItemViewItem: - { - const QStyleOptionViewItem *vopt; - - const QAbstractItemView *view = qobject_cast(widget); - bool newStyle = true; - - if (qobject_cast(widget)) - newStyle = false; - - if (newStyle && view && (vopt = qstyleoption_cast(option))) { - /* - // We cannot currently get the correct selection color for "explorer style" views - COLORREF cref = 0; - XPThemeData theme(d->treeViewHelper(), 0, QLatin1String("LISTVIEW"), 0, 0); - unsigned int res = GetThemeColor(theme.handle(), LVP_LISTITEM, LISS_SELECTED, TMT_TEXTCOLOR, &cref); - QColor textColor(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - */ - QPalette palette = vopt->palette; - palette.setColor(QPalette::All, QPalette::HighlightedText, palette.color(QPalette::Active, QPalette::Text)); - // Note that setting a saturated color here results in ugly XOR colors in the focus rect - palette.setColor(QPalette::All, QPalette::Highlight, palette.base().color().darker(108)); - QStyleOptionViewItem adjustedOption = *vopt; - adjustedOption.palette = palette; - // We hide the focusrect in singleselection as it is not required - if ((view->selectionMode() == QAbstractItemView::SingleSelection) - && !(vopt->state & State_KeyboardFocusChange)) - adjustedOption.state &= ~State_HasFocus; - QWindowsXPStyle::drawControl(element, &adjustedOption, painter, widget); - } else { - QWindowsXPStyle::drawControl(element, option, painter, widget); - } - break; - } -#endif // QT_NO_ITEMVIEWS -#ifndef QT_NO_COMBOBOX - case CE_ComboBoxLabel: - QCommonStyle::drawControl(element, option, painter, widget); - break; -#endif // QT_NO_COMBOBOX - default: - QWindowsXPStyle::drawControl(element, option, painter, widget); - break; - } -} - -/*! - \internal - - see drawPrimitive for comments on the animation support - - */ -void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, - QPainter *painter, const QWidget *widget) const -{ - QWindowsVistaStylePrivate *d = const_cast(d_func()); - if (!QWindowsVistaStylePrivate::useVista()) { - QWindowsStyle::drawComplexControl(control, option, painter, widget); - return; - } - - State state = option->state; - SubControls sub = option->subControls; - QRect r = option->rect; - - int partId = 0; - int stateId = 0; - - State flags = option->state; - if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) - flags |= State_MouseOver; - - if (d->transitionsEnabled() && canAnimate(option)) - { - - if (control == CC_ScrollBar || control == CC_SpinBox ) { - - QObject *styleObject = option->styleObject; // Can be widget or qquickitem - - int oldState = styleObject->property("_q_stylestate").toInt(); - int oldActiveControls = styleObject->property("_q_stylecontrols").toInt(); - - QRect oldRect = styleObject->property("_q_stylerect").toRect(); - styleObject->setProperty("_q_stylestate", (int)option->state); - styleObject->setProperty("_q_stylecontrols", (int)option->activeSubControls); - styleObject->setProperty("_q_stylerect", option->rect); - - bool doTransition = ((state & State_Sunken) != (oldState & State_Sunken) || - (state & State_On) != (oldState & State_On) || - (state & State_MouseOver) != (oldState & State_MouseOver) || - oldActiveControls != int(option->activeSubControls)); - - if (qstyleoption_cast(option)) { - QRect oldSliderPos = styleObject->property("_q_stylesliderpos").toRect(); - QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); - styleObject->setProperty("_q_stylesliderpos", currentPos); - if (oldSliderPos != currentPos) { - doTransition = false; - d->stopAnimation(styleObject); - } - } else if (control == CC_SpinBox) { - //spinboxes have a transition when focus changes - if (!doTransition) - doTransition = (state & State_HasFocus) != (oldState & State_HasFocus); - } - - if (oldRect != option->rect) { - doTransition = false; - d->stopAnimation(styleObject); - } - - if (doTransition) { - QImage startImage = createAnimationBuffer(option, widget); - QPainter startPainter(&startImage); - - QImage endImage = createAnimationBuffer(option, widget); - QPainter endPainter(&endImage); - - QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject)); - QWindowsVistaTransition *t = new QWindowsVistaTransition(styleObject); - - // Draw the image that ends the animation by using the current styleoption - QStyleOptionComplex *styleOption = qstyleoption_cast(clonedAnimationStyleOption(option)); - - styleObject->setProperty("_q_no_animation", true); - - // Draw transition source - if (!anim) { - styleOption->state = (QStyle::State)oldState; - styleOption->activeSubControls = (QStyle::SubControl)oldActiveControls; - proxy()->drawComplexControl(control, styleOption, &startPainter, widget); - } else { - anim->paint(&startPainter, option); - } - t->setStartImage(startImage); - - // Draw transition target - styleOption->state = option->state; - styleOption->activeSubControls = option->activeSubControls; - proxy()->drawComplexControl(control, styleOption, &endPainter, widget); - - styleObject->setProperty("_q_no_animation", false); - - t->setEndImage(endImage); - t->setStartTime(QTime::currentTime()); - - if (option->state & State_MouseOver || option->state & State_Sunken) - t->setDuration(150); - else - t->setDuration(500); - - deleteClonedAnimationStyleOption(styleOption); - d->startAnimation(t); - } - if (QWindowsVistaAnimation *anim = qobject_cast(d->animation(styleObject))) { - anim->paint(painter, option); - return; - } - } - } - - switch (control) { - case CC_ComboBox: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) - { - if (cmb->editable) { - if (sub & SC_ComboBoxEditField) { - partId = EP_EDITBORDER_NOSCROLL; - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else if (flags & State_MouseOver) - stateId = ETS_HOT; - else if (flags & State_HasFocus) - stateId = ETS_FOCUSED; - else - stateId = ETS_NORMAL; - - XPThemeData theme(widget, painter, - QWindowsXPStylePrivate::EditTheme, - partId, stateId, r); - - d->drawBackground(theme); - } - if (sub & SC_ComboBoxArrow) { - QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ComboboxTheme); - theme.rect = subRect; - partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT; - - if (!(cmb->state & State_Enabled)) - stateId = CBXS_DISABLED; - else if (cmb->state & State_Sunken || cmb->state & State_On) - stateId = CBXS_PRESSED; - else if (cmb->state & State_MouseOver && option->activeSubControls & SC_ComboBoxArrow) - stateId = CBXS_HOT; - else - stateId = CBXS_NORMAL; - - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - - } else { - if (sub & SC_ComboBoxFrame) { - QStyleOptionButton btn; - btn.QStyleOption::operator=(*option); - btn.rect = option->rect.adjusted(-1, -1, 1, 1); - if (sub & SC_ComboBoxArrow) - btn.features = QStyleOptionButton::HasMenu; - proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget); - } - } - } - break; - case CC_ScrollBar: - if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) - { - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ScrollBarTheme); - bool maxedOut = (scrollbar->maximum == scrollbar->minimum); - if (maxedOut) - flags &= ~State_Enabled; - - bool isHorz = flags & State_Horizontal; - bool isRTL = option->direction == Qt::RightToLeft; - if (sub & SC_ScrollBarAddLine) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget); - partId = SBP_ARROWBTN; - if (!(flags & State_Enabled)) - stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED); - else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken)) - stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED); - else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver)) - stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT); - else if (scrollbar->state & State_MouseOver) - stateId = (isHorz ? (isRTL ? ABS_LEFTHOVER : ABS_RIGHTHOVER) : ABS_DOWNHOVER); - else - stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL); - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarSubLine) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget); - partId = SBP_ARROWBTN; - if (!(flags & State_Enabled)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED); - else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED); - else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT); - else if (scrollbar->state & State_MouseOver) - stateId = (isHorz ? (isRTL ? ABS_RIGHTHOVER : ABS_LEFTHOVER) : ABS_UPHOVER); - else - stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL); - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (maxedOut) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); - theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); - theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget)); - partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; - stateId = SCRBS_DISABLED; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } else { - if (sub & SC_ScrollBarSubPage) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget); - partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT; - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else - stateId = SCRBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarAddPage) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget); - partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else - stateId = SCRBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarSlider) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else if (option->state & State_MouseOver) - stateId = SCRBS_HOVER; - else - stateId = SCRBS_NORMAL; - - // Draw handle - theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; - theme.stateId = stateId; - d->drawBackground(theme); - - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) { - const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme); - // Draw gripper if there is enough space - if (!gripperBounds.isEmpty() && flags & State_Enabled) { - painter->save(); - XPThemeData grippBackground = theme; - grippBackground.partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; - theme.rect = gripperBounds; - painter->setClipRegion(d->region(theme));// Only change inside the region of the gripper - d->drawBackground(grippBackground);// The gutter is the grippers background - d->drawBackground(theme); // Transparent gripper ontop of background - painter->restore(); - } - } - } - } - } - break; -#ifndef QT_NO_SPINBOX - case CC_SpinBox: - if (const QStyleOptionSpinBox *sb = qstyleoption_cast(option)) - { - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::SpinTheme); - if (sb->frame && (sub & SC_SpinBoxFrame)) { - partId = EP_EDITBORDER_NOSCROLL; - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else if (flags & State_MouseOver) - stateId = ETS_HOT; - else if (flags & State_HasFocus) - stateId = ETS_SELECTED; - else - stateId = ETS_NORMAL; - - XPThemeData ftheme(widget, painter, - QWindowsXPStylePrivate::EditTheme, - partId, stateId, r); - // The spinbox in Windows QStyle is drawn with frameless QLineEdit inside it - // That however breaks with QtQuickControls where this results in transparent - // spinbox background, so if there's no "widget" passed (QtQuickControls case), - // let ftheme.noContent be false, which fixes the spinbox rendering in QQC - ftheme.noContent = (widget != NULL); - d->drawBackground(ftheme); - } - if (sub & SC_SpinBoxUp) { - theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1); - partId = SPNP_UP; - if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled)) - stateId = UPS_DISABLED; - else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) - stateId = UPS_PRESSED; - else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver)) - stateId = UPS_HOT; - else - stateId = UPS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_SpinBoxDown) { - theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); - partId = SPNP_DOWN; - if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled)) - stateId = DNS_DISABLED; - else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) - stateId = DNS_PRESSED; - else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver)) - stateId = DNS_HOT; - else - stateId = DNS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - } - break; -#endif // QT_NO_SPINBOX - default: - QWindowsXPStyle::drawComplexControl(control, option, painter, widget); - break; - } -} - -/*! - \internal - */ -QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option, - const QSize &size, const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) - return QWindowsStyle::sizeFromContents(type, option, size, widget); - - QSize sz(size); - switch (type) { - case CT_MenuItem: - sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); - int minimumHeight; - { - XPThemeData theme(widget, 0, - QWindowsXPStylePrivate::MenuTheme, - MENU_POPUPCHECKBACKGROUND, MBI_HOT); - XPThemeData themeSize = theme; - themeSize.partId = MENU_POPUPCHECK; - themeSize.stateId = 0; - const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height()); - sz.rwidth() += qRound(size.width() + margins.left() + margins.right()); - } - - if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { - if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) - sz.setHeight(minimumHeight); - } - return sz; -#ifndef QT_NO_MENUBAR - case CT_MenuBarItem: - if (!sz.isEmpty()) - sz += QSize(windowsItemHMargin * 5 + 1, 5); - return sz; -#endif - case CT_ItemViewItem: - sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); - sz.rheight() += 2; - return sz; - case CT_SpinBox: - { - //Spinbox adds frame twice - sz = QWindowsStyle::sizeFromContents(type, option, size, widget); - int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); - sz -= QSize(2*border, 2*border); - } - return sz; - case CT_HeaderSection: - { - // When there is a sort indicator it adds to the width but it is shown - // above the text natively and not on the side - if (QStyleOptionHeader *hdr = qstyleoption_cast(const_cast(option))) { - QStyleOptionHeader::SortIndicator sortInd = hdr->sortIndicator; - hdr->sortIndicator = QStyleOptionHeader::None; - sz = QWindowsXPStyle::sizeFromContents(type, hdr, size, widget); - hdr->sortIndicator = sortInd; - return sz; - } - break; - } - default: - break; - } - return QWindowsXPStyle::sizeFromContents(type, option, size, widget); -} - -/*! - \internal - */ -QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) - return QWindowsStyle::subElementRect(element, option, widget); - - QRect rect = QWindowsXPStyle::subElementRect(element, option, widget); - switch (element) { - - case SE_PushButtonContents: - if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { - MARGINS borderSize; - const HTHEME theme = OpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); - if (theme) { - int stateId = PBS_NORMAL; - if (!(option->state & State_Enabled)) - stateId = PBS_DISABLED; - else if (option->state & State_Sunken) - stateId = PBS_PRESSED; - else if (option->state & State_MouseOver) - stateId = PBS_HOT; - else if (btn->features & QStyleOptionButton::DefaultButton) - stateId = PBS_DEFAULTED; - - int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); - rect = option->rect.adjusted(border, border, -border, -border); - - if (SUCCEEDED(GetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, TMT_CONTENTMARGINS, NULL, &borderSize))) { - rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, - -borderSize.cxRightWidth, -borderSize.cyBottomHeight); - rect = visualRect(option->direction, option->rect, rect); - } - } - } - break; - - case SE_HeaderArrow: - { - QRect r = rect; - int h = option->rect.height(); - int w = option->rect.width(); - int x = option->rect.x(); - int y = option->rect.y(); - int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget); - - XPThemeData theme(widget, 0, - QWindowsXPStylePrivate::HeaderTheme, - HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect); - - int arrowWidth = 13; - int arrowHeight = 5; - if (theme.isValid()) { - const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget); - if (!size.isEmpty()) { - arrowWidth = qRound(size.width()); - arrowHeight = qRound(size.height()); - } - } - if (option->state & State_Horizontal) { - r.setRect(x + w/2 - arrowWidth/2, y , arrowWidth, arrowHeight); - } else { - int vert_size = w / 2; - r.setRect(x + 5, y + h - margin * 2 - vert_size, - w - margin * 2 - 5, vert_size); - } - rect = visualRect(option->direction, option->rect, r); - } - break; - - case SE_HeaderLabel: - { - int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget); - QRect r = option->rect; - r.setRect(option->rect.x() + margin, option->rect.y() + margin, - option->rect.width() - margin * 2, option->rect.height() - margin * 2); - if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { - // Subtract width needed for arrow, if there is one - if (header->sortIndicator != QStyleOptionHeader::None) { - if (!(option->state & State_Horizontal)) //horizontal arrows are positioned on top - r.setHeight(r.height() - (option->rect.width() / 2) - (margin * 2)); - } - } - rect = visualRect(option->direction, option->rect, r); - } - break; - case SE_ProgressBarContents: - rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget); - break; - case SE_ItemViewItemDecoration: - if (qstyleoption_cast(option)) - rect.adjust(-2, 0, 2, 0); - break; - case SE_ItemViewItemFocusRect: - if (const QStyleOptionViewItem *vopt = qstyleoption_cast(option)) { - QRect textRect = subElementRect(QStyle::SE_ItemViewItemText, option, widget); - QRect displayRect = subElementRect(QStyle::SE_ItemViewItemDecoration, option, widget); - if (!vopt->icon.isNull()) - rect = textRect.united(displayRect); - else - rect = textRect; - rect = rect.adjusted(1, 0, -1, 0); - } - break; - default: - break; - } - return rect; -} - - -/* - This function is used by subControlRect to check if a button - should be drawn for the given subControl given a set of window flags. -*/ -static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){ - - bool isMinimized = tb->titleBarState & Qt::WindowMinimized; - bool isMaximized = tb->titleBarState & Qt::WindowMaximized; - const uint flags = tb->titleBarFlags; - bool retVal = false; - switch (sc) { - case QStyle::SC_TitleBarContextHelpButton: - if (flags & Qt::WindowContextHelpButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarMinButton: - if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarNormalButton: - if (isMinimized && (flags & Qt::WindowMinimizeButtonHint)) - retVal = true; - else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarMaxButton: - if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarShadeButton: - if (!isMinimized && flags & Qt::WindowShadeButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarUnshadeButton: - if (isMinimized && flags & Qt::WindowShadeButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarCloseButton: - if (flags & Qt::WindowSystemMenuHint) - retVal = true; - break; - case QStyle::SC_TitleBarSysMenu: - if (flags & Qt::WindowSystemMenuHint) - retVal = true; - break; - default : - retVal = true; - } - return retVal; -} - - -/*! \internal */ -int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, - QStyleHintReturn *returnData) const -{ - QWindowsVistaStylePrivate *d = const_cast(d_func()); - int ret = 0; - switch (hint) { - case SH_MessageBox_CenterButtons: - ret = false; - break; - case SH_ToolTip_Mask: - if (option) { - if (QStyleHintReturnMask *mask = qstyleoption_cast(returnData)) { - ret = true; - XPThemeData themeData(widget, 0, - QWindowsXPStylePrivate::ToolTipTheme, - TTP_STANDARD, TTSS_NORMAL, option->rect); - mask->region = d->region(themeData); - } - } - break; - case SH_Table_GridLineColor: - if (option) - ret = option->palette.color(QPalette::Base).darker(118).rgb(); - else - ret = -1; - break; - case SH_Header_ArrowAlignment: - ret = Qt::AlignTop | Qt::AlignHCenter; - break; - default: - ret = QWindowsXPStyle::styleHint(hint, option, widget, returnData); - break; - } - return ret; -} - - -/*! - \internal - */ -QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, - SubControl subControl, const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) - return QWindowsStyle::subControlRect(control, option, subControl, widget); - - QRect rect = QWindowsXPStyle::subControlRect(control, option, subControl, widget); - switch (control) { -#ifndef QT_NO_COMBOBOX - case CC_ComboBox: - if (const QStyleOptionComboBox *cb = qstyleoption_cast(option)) { - int x = cb->rect.x(), - y = cb->rect.y(), - wi = cb->rect.width(), - he = cb->rect.height(); - int xpos = x; - int margin = cb->frame ? 3 : 0; - int bmarg = cb->frame ? 2 : 0; - int arrowButtonWidth = bmarg + 16; - xpos += wi - arrowButtonWidth; - - switch (subControl) { - case SC_ComboBoxFrame: - rect = cb->rect; - break; - case SC_ComboBoxArrow: - rect.setRect(xpos, y , arrowButtonWidth, he); - break; - case SC_ComboBoxEditField: - rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin); - break; - case SC_ComboBoxListBoxPopup: - rect = cb->rect; - break; - default: - break; - } - rect = visualRect(cb->direction, cb->rect, rect); - return rect; - } -#endif // QT_NO_COMBOBOX - case CC_TitleBar: - if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { - if (!buttonVisible(subControl, tb)) - return rect; - const bool isToolTitle = false; - const int height = tb->rect.height(); - const int width = tb->rect.width(); - const int buttonWidth = - qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * QWindowsStylePrivate::nativeMetricScaleFactor(widget) - - QStyleHelper::dpiScaled(4)); - - const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); - const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; - const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; - const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; - const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; - const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; - - switch (subControl) { - case SC_TitleBarLabel: - rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); - if (isToolTitle) { - if (sysmenuHint) { - rect.adjust(0, 0, -buttonWidth - 3, 0); - } - if (minimizeHint || maximizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - } else { - if (sysmenuHint) { - const int leftOffset = height - 8; - rect.adjust(leftOffset, 0, 0, 4); - } - if (minimizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (maximizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (contextHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (shadeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - } - rect.translate(0, 2); - rect = visualRect(option->direction, option->rect, rect); - break; - case SC_TitleBarSysMenu: - { - const int controlTop = 6; - const int controlHeight = height - controlTop - 3; - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); - if (tb->icon.isNull()) - iconSize = QSize(controlHeight, controlHeight); - int hPad = (controlHeight - iconSize.height())/2; - int vPad = (controlHeight - iconSize.width())/2; - rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); - rect.translate(0, 3); - rect = visualRect(option->direction, option->rect, rect); - } - break; - default: - break; - } - } - break; - default: - break; - } - return rect; -} - -/*! - \internal - */ -QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, - const QPoint &pos, const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) { - return QWindowsStyle::hitTestComplexControl(control, option, pos, widget); - } - return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); -} - -int QWindowsVistaStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) -{ - switch (pm) { - case QStyle::PM_DockWidgetTitleBarButtonMargin: - return 5; - case QStyle::PM_ScrollBarSliderMin: - return 18; - case QStyle::PM_MenuHMargin: - case QStyle::PM_MenuVMargin: - return 0; - case QStyle::PM_MenuPanelWidth: - return 3; - default: - break; - } - return QWindowsVistaStylePrivate::InvalidMetric; -} - -/*! - \internal - */ -int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) - return QWindowsStyle::pixelMetric(metric, option, widget); - - int ret = QWindowsVistaStylePrivate::fixedPixelMetric(metric); - if (ret != QWindowsStylePrivate::InvalidMetric) - return int(QStyleHelper::dpiScaled(ret)); - - return QWindowsXPStyle::pixelMetric(metric, option, widget); -} - -/*! - \internal - */ -QPalette QWindowsVistaStyle::standardPalette() const -{ - return QWindowsXPStyle::standardPalette(); -} - -/*! - \internal - */ -void QWindowsVistaStyle::polish(QApplication *app) -{ - QWindowsXPStyle::polish(app); -} - -/*! - \internal - */ -void QWindowsVistaStyle::polish(QWidget *widget) -{ - QWindowsXPStyle::polish(widget); -#ifndef QT_NO_LINEEDIT - if (qobject_cast(widget)) - widget->setAttribute(Qt::WA_Hover); - else -#endif // QT_NO_LINEEDIT - if (qobject_cast(widget)) - widget->setAttribute(Qt::WA_Hover); - else if (qobject_cast(widget)) { - QFont buttonFont = widget->font(); - buttonFont.setFamily(QLatin1String("Segoe UI")); - widget->setFont(buttonFont); - } - else if (widget->inherits("QTipLabel")){ - //note that since tooltips are not reused - //we do not have to care about unpolishing - widget->setContentsMargins(3, 0, 4, 0); - COLORREF bgRef; - HTHEME theme = OpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); - if (theme && SUCCEEDED(GetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef))) { - QColor textColor = QColor::fromRgb(bgRef); - QPalette pal; - pal.setColor(QPalette::All, QPalette::ToolTipText, textColor); - widget->setPalette(pal); - } - } else if (qobject_cast (widget)) { - widget->setAttribute(Qt::WA_StyledBackground); -#if QT_CONFIG(dialogbuttonbox) - QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); - if (buttonBox) - buttonBox->setContentsMargins(0, 9, 0, 0); -#endif - } -#ifndef QT_NO_INPUTDIALOG - else if (qobject_cast (widget)) { - widget->setAttribute(Qt::WA_StyledBackground); -#if QT_CONFIG(dialogbuttonbox) - QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); - if (buttonBox) - buttonBox->setContentsMargins(0, 9, 0, 0); -#endif - } -#endif // QT_NO_INPUTDIALOG - else if (QTreeView *tree = qobject_cast (widget)) { - tree->viewport()->setAttribute(Qt::WA_Hover); - } - else if (QListView *list = qobject_cast (widget)) { - list->viewport()->setAttribute(Qt::WA_Hover); - } -} - -/*! - \internal - */ -void QWindowsVistaStyle::unpolish(QWidget *widget) -{ - QWindowsXPStyle::unpolish(widget); - - QWindowsVistaStylePrivate *d = d_func(); - - d->stopAnimation(widget); - -#ifndef QT_NO_LINEEDIT - if (qobject_cast(widget)) - widget->setAttribute(Qt::WA_Hover, false); - else -#endif // QT_NO_LINEEDIT - if (qobject_cast(widget)) - widget->setAttribute(Qt::WA_Hover, false); - else if (qobject_cast (widget)) { - widget->setAttribute(Qt::WA_StyledBackground, false); -#if QT_CONFIG(dialogbuttonbox) - QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_msgbox_buttonbox")); - if (buttonBox) - buttonBox->setContentsMargins(0, 0, 0, 0); -#endif - } -#ifndef QT_NO_INPUTDIALOG - else if (qobject_cast (widget)) { - widget->setAttribute(Qt::WA_StyledBackground, false); -#if QT_CONFIG(dialogbuttonbox) - QDialogButtonBox *buttonBox = widget->findChild(QLatin1String("qt_inputdlg_buttonbox")); - if (buttonBox) - buttonBox->setContentsMargins(0, 0, 0, 0); -#endif - } -#endif // QT_NO_INPUTDIALOG - else if (QTreeView *tree = qobject_cast (widget)) { - tree->viewport()->setAttribute(Qt::WA_Hover, false); - } else if (qobject_cast(widget)) { - QFont font = QApplication::font("QCommandLinkButton"); - QFont widgetFont = widget->font(); - widgetFont.setFamily(font.family()); //Only family set by polish - widget->setFont(widgetFont); - } -} - - -/*! - \internal - */ -void QWindowsVistaStyle::unpolish(QApplication *app) -{ - QWindowsXPStyle::unpolish(app); -} - -/*! - \internal - */ -void QWindowsVistaStyle::polish(QPalette &pal) -{ - QWindowsStyle::polish(pal); - pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(104)); -} - -/*! - \internal - */ -QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, - const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) { - return QWindowsStyle::standardPixmap(standardPixmap, option, widget); - } - return QWindowsXPStyle::standardPixmap(standardPixmap, option, widget); -} - -QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : - QWindowsXPStylePrivate() -{ -} - -bool QWindowsVistaStylePrivate::transitionsEnabled() const -{ - BOOL animEnabled = false; - if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0)) - { - if (animEnabled) - return true; - } - return false; -} - -/*! -\reimp -*/ -QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, - const QStyleOption *option, - const QWidget *widget) const -{ - if (!QWindowsVistaStylePrivate::useVista()) { - return QWindowsStyle::standardIcon(standardIcon, option, widget); - } - - QWindowsVistaStylePrivate *d = const_cast(d_func()); - switch(standardIcon) { - case SP_CommandLink: - { - XPThemeData theme(0, 0, - QWindowsXPStylePrivate::ButtonTheme, - BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); - if (theme.isValid()) { - const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - QIcon linkGlyph; - QPixmap pm(size); - pm.fill(Qt::transparent); - QPainter p(&pm); - theme.painter = &p; - theme.rect = QRect(QPoint(0, 0), size); - d->drawBackground(theme); - linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal - pm.fill(Qt::transparent); - - theme.stateId = CMDLGS_PRESSED; - d->drawBackground(theme); - linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed - pm.fill(Qt::transparent); - - theme.stateId = CMDLGS_HOT; - d->drawBackground(theme); - linkGlyph.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover - pm.fill(Qt::transparent); - - theme.stateId = CMDLGS_DISABLED; - d->drawBackground(theme); - linkGlyph.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled - return linkGlyph; - } - } - break; - default: - break; - } - return QWindowsXPStyle::standardIcon(standardIcon, option, widget); -} - -QT_END_NAMESPACE - -#endif //QT_NO_WINDOWSVISTA diff --git a/src/widgets/styles/qwindowsvistastyle_p.h b/src/widgets/styles/qwindowsvistastyle_p.h deleted file mode 100644 index 8fbd1dc380..0000000000 --- a/src/widgets/styles/qwindowsvistastyle_p.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSVISTASTYLE_P_H -#define QWINDOWSVISTASTYLE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - - -#if QT_CONFIG(style_windowsvista) - -class QWindowsVistaStylePrivate; -class QWindowsVistaStyle : public QWindowsXPStyle -{ - Q_OBJECT -public: - QWindowsVistaStyle(); - ~QWindowsVistaStyle(); - - void drawPrimitive(PrimitiveElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget = 0) const; - void drawControl(ControlElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget) const; - void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, - QPainter *painter, const QWidget *widget) const; - QSize sizeFromContents(ContentsType type, const QStyleOption *option, - const QSize &size, const QWidget *widget) const; - - QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const; - QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, - SubControl sc, const QWidget *widget) const; - - SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, - const QPoint &pos, const QWidget *widget = 0) const; - - QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0, - const QWidget *widget = 0) const; - QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, - const QWidget *widget = 0) const; - int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; - int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0, - QStyleHintReturn *returnData = 0) const; - - void polish(QWidget *widget); - void unpolish(QWidget *widget); - void polish(QPalette &pal); - void polish(QApplication *app); - void unpolish(QApplication *app); - QPalette standardPalette() const; - -private: - Q_DISABLE_COPY(QWindowsVistaStyle) - Q_DECLARE_PRIVATE(QWindowsVistaStyle) - friend class QStyleFactory; -}; -#endif // style_windowsvista - -QT_END_NAMESPACE - -#endif // QWINDOWSVISTASTYLE_P_H diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h deleted file mode 100644 index db358e6f6c..0000000000 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSVISTASTYLE_P_P_H -#define QWINDOWSVISTASTYLE_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qwindowsvistastyle_p.h" - -#if QT_CONFIG(style_windowsvista) -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(dialogbuttonbox) -#include -#endif -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -#if !defined(SCHEMA_VERIFY_VSSYM32) -#define TMT_ANIMATIONDURATION 5006 -#define TMT_TRANSITIONDURATIONS 6000 -#define EP_EDITBORDER_NOSCROLL 6 -#define EP_EDITBORDER_HVSCROLL 9 -#define EP_BACKGROUND 3 -#define EBS_NORMAL 1 -#define EBS_HOT 2 -#define EBS_DISABLED 3 -#define EBS_READONLY 5 -#define PBS_DEFAULTED_ANIMATING 6 -#define MBI_NORMAL 1 -#define MBI_HOT 2 -#define MBI_PUSHED 3 -#define MBI_DISABLED 4 -#define MB_ACTIVE 1 -#define MB_INACTIVE 2 -#define PP_FILL 5 -#define PP_FILLVERT 6 -#define PP_MOVEOVERLAY 8 -#define PP_MOVEOVERLAYVERT 10 -#define MENU_BARBACKGROUND 7 -#define MENU_BARITEM 8 -#define MENU_POPUPCHECK 11 -#define MENU_POPUPCHECKBACKGROUND 12 -#define MENU_POPUPGUTTER 13 -#define MENU_POPUPITEM 14 -#define MENU_POPUPBORDERS 10 -#define MENU_POPUPSEPARATOR 15 -#define MC_CHECKMARKNORMAL 1 -#define MC_CHECKMARKDISABLED 2 -#define MC_BULLETNORMAL 3 -#define MC_BULLETDISABLED 4 -#define ABS_UPHOVER 17 -#define ABS_DOWNHOVER 18 -#define ABS_LEFTHOVER 19 -#define ABS_RIGHTHOVER 20 -#define CP_DROPDOWNBUTTONRIGHT 6 -#define CP_DROPDOWNBUTTONLEFT 7 -#define SCRBS_HOVER 5 -#define TVP_HOTGLYPH 4 -#define SPI_GETCLIENTAREAANIMATION 0x1042 -#define TDLG_PRIMARYPANEL 1 -#define TDLG_SECONDARYPANEL 8 -#endif - -class QWindowsVistaAnimation : public QBlendStyleAnimation -{ - Q_OBJECT -public: - QWindowsVistaAnimation(Type type, QObject *target) : QBlendStyleAnimation(type, target) { } - - virtual bool isUpdateNeeded() const; - void paint(QPainter *painter, const QStyleOption *option); -}; - - -// Handles state transition animations -class QWindowsVistaTransition : public QWindowsVistaAnimation -{ - Q_OBJECT -public: - QWindowsVistaTransition(QObject *target) : QWindowsVistaAnimation(Transition, target) {} -}; - - -// Handles pulse animations (default buttons) -class QWindowsVistaPulse: public QWindowsVistaAnimation -{ - Q_OBJECT -public: - QWindowsVistaPulse(QObject *target) : QWindowsVistaAnimation(Pulse, target) {} -}; - - -class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate -{ - Q_DECLARE_PUBLIC(QWindowsVistaStyle) - -public: - QWindowsVistaStylePrivate(); - - static int fixedPixelMetric(QStyle::PixelMetric pm); - static inline bool useVista(); - bool transitionsEnabled() const; -}; - -QT_END_NAMESPACE - -#endif // style_windowsvista - -#endif // QWINDOWSVISTASTYLE_P_P_H diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp deleted file mode 100644 index 2fd40a57af..0000000000 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ /dev/null @@ -1,4227 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "qwindowsxpstyle_p.h" -#include "qwindowsxpstyle_p_p.h" - -#if QT_CONFIG(style_windowsvista) || defined(QT_PLUGIN) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -// General const values -static const int windowsItemFrame = 2; // menu item frame width -static const int windowsItemHMargin = 3; // menu item hor text margin -static const int windowsItemVMargin = 0; // menu item ver text margin -static const int windowsArrowHMargin = 6; // arrow horizontal margin -static const int windowsRightBorder = 12; // right border on windows - -// External function calls -extern Q_WIDGETS_EXPORT HDC qt_win_display_dc(); -extern QRegion qt_region_from_HRGN(HRGN rgn); - -// Theme names matching the QWindowsXPStylePrivate::Theme enumeration. -static const wchar_t *themeNames[QWindowsXPStylePrivate::NThemes] = -{ - L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW", - L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN", - L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR", - L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW" -}; - -static inline QBackingStore *backingStoreForWidget(const QWidget *widget) -{ - if (QBackingStore *backingStore = widget->backingStore()) - return backingStore; - if (const QWidget *topLevel = widget->nativeParentWidget()) - if (QBackingStore *topLevelBackingStore = topLevel->backingStore()) - return topLevelBackingStore; - return 0; -} - -static inline HDC hdcForWidgetBackingStore(const QWidget *widget) -{ - if (QBackingStore *backingStore = backingStoreForWidget(widget)) { - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - return static_cast(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore)); - } - return 0; -} - -// Theme data helper ------------------------------------------------------------------------------ -/* \internal - Returns \c true if the themedata is valid for use. -*/ -bool XPThemeData::isValid() -{ - return QWindowsXPStylePrivate::useXP() && theme >= 0 && handle(); -} - - -/* \internal - Returns the theme engine handle to the specific class. - If the handle hasn't been opened before, it opens the data, and - adds it to a static map, for caching. -*/ -HTHEME XPThemeData::handle() -{ - if (!QWindowsXPStylePrivate::useXP()) - return 0; - - if (!htheme) - htheme = QWindowsXPStylePrivate::createTheme(theme, QWindowsXPStylePrivate::winId(widget)); - return htheme; -} - -/* \internal - Converts a QRect to the native RECT structure. -*/ -RECT XPThemeData::toRECT(const QRect &qr) -{ - RECT r; - r.left = qr.x(); - r.right = qr.x() + qr.width(); - r.top = qr.y(); - r.bottom = qr.y() + qr.height(); - return r; -} - -/* \internal - Returns the native region of a part, if the part is considered - transparent. The region is scaled to the parts size (rect). -*/ -HRGN XPThemeData::mask(QWidget *widget) -{ - if (!IsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) - return 0; - - HRGN hrgn; - HDC dc = 0; - if (widget) - dc = hdcForWidgetBackingStore(widget); - RECT nativeRect = toRECT(rect); - GetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); - return hrgn; -} - -// QWindowsXPStylePrivate ------------------------------------------------------------------------- -// Static initializations -QPixmap *QWindowsXPStylePrivate::tabbody = 0; -HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = 0; -HTHEME QWindowsXPStylePrivate::m_themes[NThemes]; -bool QWindowsXPStylePrivate::use_xp = false; -QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting - -static void qt_add_rect(HRGN &winRegion, QRect r) -{ - HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - if (rgn) { - HRGN dest = CreateRectRgn(0,0,0,0); - int result = CombineRgn(dest, winRegion, rgn, RGN_OR); - if (result) { - DeleteObject(winRegion); - winRegion = dest; - } - DeleteObject(rgn); - } -} - -static HRGN qt_hrgn_from_qregion(const QRegion ®ion) -{ - HRGN hRegion = CreateRectRgn(0,0,0,0); - if (region.rectCount() == 1) { - qt_add_rect(hRegion, region.boundingRect()); - return hRegion; - } - for (const QRect &rect : region) - qt_add_rect(hRegion, rect); - return hRegion; -} - -/* \internal - Checks if the theme engine can/should be used, or if we should - fall back to Windows style. -*/ -bool QWindowsXPStylePrivate::useXP(bool update) -{ - if (!update) - return use_xp; - return use_xp = IsThemeActive() && (IsAppThemed() || !QApplication::instance()); -} - -/* \internal - Handles refcounting, and queries the theme engine for usage. -*/ -void QWindowsXPStylePrivate::init(bool force) -{ - if (ref.ref() && !force) - return; - if (!force) // -1 based atomic refcounting - ref.ref(); - - useXP(true); - std::fill(m_themes, m_themes + NThemes, HTHEME(0)); -} - -/* \internal - Cleans up all static data. -*/ -void QWindowsXPStylePrivate::cleanup(bool force) -{ - if(bufferBitmap) { - if (bufferDC && nullBitmap) - SelectObject(bufferDC, nullBitmap); - DeleteObject(bufferBitmap); - bufferBitmap = 0; - } - - if(bufferDC) - DeleteDC(bufferDC); - bufferDC = 0; - - if (ref.deref() && !force) - return; - if (!force) // -1 based atomic refcounting - ref.deref(); - - use_xp = false; - cleanupHandleMap(); - delete tabbody; - tabbody = 0; -} - -/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch), - * we need to set the windows "explorer" theme explicitly on a native - * window and open the "TREEVIEW" theme handle passing its window handle - * in order to get Vista-style item view themes (particulary drawBackground() - * for selected items needs this). - * We invoke a service of the native Windows interface to create - * a non-visible window handle, open the theme on it and insert it into - * the cache so that it is found by XPThemeData::handle() first. - */ - -static inline HWND createTreeViewHelperWindow() -{ - if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) { - void *hwnd = 0; - void *wndProc = reinterpret_cast(DefWindowProc); - if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, - Q_RETURN_ARG(void *, hwnd), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), - Q_ARG(void *, wndProc)) && hwnd) { - return reinterpret_cast(hwnd); - } - } - return 0; -} - -bool QWindowsXPStylePrivate::initVistaTreeViewTheming() -{ - if (m_vistaTreeViewHelper) - return true; - - m_vistaTreeViewHelper = createTreeViewHelperWindow(); - if (!m_vistaTreeViewHelper) { - qWarning("Unable to create the treeview helper window."); - return false; - } - if (FAILED(SetWindowTheme(m_vistaTreeViewHelper, L"explorer", NULL))) { - qErrnoWarning("SetWindowTheme() failed."); - cleanupVistaTreeViewTheming(); - return false; - } - return true; -} - -void QWindowsXPStylePrivate::cleanupVistaTreeViewTheming() -{ - if (m_vistaTreeViewHelper) { - DestroyWindow(m_vistaTreeViewHelper); - m_vistaTreeViewHelper = 0; - } -} - -/* \internal - Closes all open theme data handles to ensure that we don't leak - resources, and that we don't refere to old handles when for - example the user changes the theme style. -*/ -void QWindowsXPStylePrivate::cleanupHandleMap() -{ - for (int i = 0; i < NThemes; ++i) - if (m_themes[i]) { - CloseThemeData(m_themes[i]); - m_themes[i] = 0; - } - QWindowsXPStylePrivate::cleanupVistaTreeViewTheming(); -} - -HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd) -{ - if (Q_UNLIKELY(theme < 0 || theme >= NThemes || !hwnd)) { - qWarning("Invalid parameters #%d, %p", theme, hwnd); - return 0; - } - if (!m_themes[theme]) { - const wchar_t *name = themeNames[theme]; - if (theme == VistaTreeViewTheme && QWindowsXPStylePrivate::initVistaTreeViewTheming()) - hwnd = QWindowsXPStylePrivate::m_vistaTreeViewHelper; - m_themes[theme] = OpenThemeData(hwnd, name); - if (Q_UNLIKELY(!m_themes[theme])) - qErrnoWarning("OpenThemeData() failed for theme %d (%s).", - theme, qPrintable(themeName(theme))); - } - return m_themes[theme]; -} - -QString QWindowsXPStylePrivate::themeName(int theme) -{ - return theme >= 0 && theme < NThemes ? - QString::fromWCharArray(themeNames[theme]) : - QString(); -} - -bool QWindowsXPStylePrivate::isItemViewDelegateLineEdit(const QWidget *widget) -{ - if (!widget) - return false; - const QWidget *parent1 = widget->parentWidget(); - // Exlude dialogs or other toplevels parented on item views. - if (!parent1 || parent1->isWindow()) - return false; - const QWidget *parent2 = parent1->parentWidget(); - return parent2 && widget->inherits("QLineEdit") - && parent2->inherits("QAbstractItemView"); -} - -// Returns whether base color is set for this widget -bool QWindowsXPStylePrivate::isLineEditBaseColorSet(const QStyleOption *option, const QWidget *widget) -{ - uint resolveMask = option->palette.resolve(); - if (widget) { - // Since spin box includes a line edit we need to resolve the palette mask also from - // the parent, as while the color is always correct on the palette supplied by panel, - // the mask can still be empty. If either mask specifies custom base color, use that. -#ifndef QT_NO_SPINBOX - if (const QAbstractSpinBox *spinbox = qobject_cast(widget->parentWidget())) - resolveMask |= spinbox->palette().resolve(); -#endif // QT_NO_SPINBOX - } - return (resolveMask & (1 << QPalette::Base)) != 0; -} - -/*! \internal - This function will always return a valid window handle, and might - create a limbo widget to do so. - We often need a window handle to for example open theme data, so - this function ensures that we get one. -*/ -HWND QWindowsXPStylePrivate::winId(const QWidget *widget) -{ - if (widget) - if (const HWND hwnd = QApplicationPrivate::getHWNDForWidget(const_cast(widget))) - return hwnd; - - // Find top level with native window (there might be dialogs that do not have one). - const auto topLevels = QApplication::topLevelWidgets(); - for (const QWidget *toplevel : topLevels) { - if (toplevel->windowHandle() && toplevel->windowHandle()->handle()) - if (const HWND topLevelHwnd = QApplicationPrivate::getHWNDForWidget(toplevel)) - return topLevelHwnd; - } - - return GetDesktopWindow(); -} - -/*! \internal - Returns the pointer to a tab widgets body pixmap, scaled to the - height of the screen. This way the theme engine doesn't need to - scale the body for every time we ask for it. (Speed optimization) -*/ -const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) -{ - if (!tabbody) { - XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - - tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); - QPainter painter(tabbody); - theme.rect = QRect(QPoint(0, 0), size); - drawBackground(theme); - // We fill with the last line of the themedata, that - // way we don't get a tiled pixmap inside big tabs - QPixmap temp(size.width(), 1); - painter.drawPixmap(0, 0, temp, 0, size.height() - 1, -1, -1); - painter.drawTiledPixmap(0, size.height(), size.width(), tabbody->height() - size.height(), temp); - } - return tabbody; -} - -/*! \internal - Returns a native buffer (DIB section) of at least the size of - ( \a x , \a y ). The buffer has a 32 bit depth, to not lose - the alpha values on proper alpha-pixmaps. -*/ -HBITMAP QWindowsXPStylePrivate::buffer(int w, int h) -{ - // If we already have a HBITMAP which is of adequate size, just return that - if (bufferBitmap) { - if (bufferW >= w && bufferH >= h) - return bufferBitmap; - // Not big enough, discard the old one - if (bufferDC && nullBitmap) - SelectObject(bufferDC, nullBitmap); - DeleteObject(bufferBitmap); - bufferBitmap = 0; - } - - w = qMax(bufferW, w); - h = qMax(bufferH, h); - - if (!bufferDC) { - HDC displayDC = GetDC(0); - bufferDC = CreateCompatibleDC(displayDC); - ReleaseDC(0, displayDC); - } - - // Define the header - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - - // Create the pixmap - bufferPixels = 0; - bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, (void **) &bufferPixels, 0, 0); - GdiFlush(); - nullBitmap = (HBITMAP)SelectObject(bufferDC, bufferBitmap); - - if (Q_UNLIKELY(!bufferBitmap)) { - qErrnoWarning("QWindowsXPStylePrivate::buffer(%dx%d), CreateDIBSection() failed.", w, h); - bufferW = 0; - bufferH = 0; - return 0; - } - if (Q_UNLIKELY(!bufferPixels)) { - qErrnoWarning("QWindowsXPStylePrivate::buffer(%dx%d), CreateDIBSection() did not allocate pixel data.", w, h); - bufferW = 0; - bufferH = 0; - return 0; - } - bufferW = w; - bufferH = h; -#ifdef DEBUG_XP_STYLE - qDebug("Creating new dib section (%d, %d)", w, h); -#endif - return bufferBitmap; -} - -/*! \internal - Returns \c true if the part contains any transparency at all. This does - not indicate what kind of transparency we're dealing with. It can be - - Alpha transparency - - Masked transparency -*/ -bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData) -{ - return IsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId, - themeData.stateId); -} - - -/*! \internal - Returns a QRegion of the region of the part -*/ -QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) -{ - HRGN hRgn = 0; - RECT rect = themeData.toRECT(themeData.rect); - if (!SUCCEEDED(GetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId, - themeData.stateId, &rect, &hRgn))) { - return QRegion(); - } - - HRGN dest = CreateRectRgn(0, 0, 0, 0); - const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR; - - QRegion region; - - if (success) { - int numBytes = GetRegionData(dest, 0, 0); - if (numBytes == 0) - return QRegion(); - - char *buf = new char[numBytes]; - if (buf == 0) - return QRegion(); - - RGNDATA *rd = reinterpret_cast(buf); - if (GetRegionData(dest, numBytes, rd) == 0) { - delete [] buf; - return QRegion(); - } - - RECT *r = reinterpret_cast(rd->Buffer); - for (uint i = 0; i < rd->rdh.nCount; ++i) { - QRect rect; - rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); - ++r; - region |= rect; - } - - delete [] buf; - } - - DeleteObject(hRgn); - DeleteObject(dest); - - return region; -} - -/*! \internal - Sets the parts region on a window. -*/ -void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData) -{ - HRGN hrgn = themeData.mask(widget); - if (hrgn && widget) - SetWindowRgn(winId(widget), hrgn, true); -} - -/*! \internal - Returns \c true if the native doublebuffer contains pixels with - varying alpha value. -*/ -bool QWindowsXPStylePrivate::hasAlphaChannel(const QRect &rect) -{ - const int startX = rect.left(); - const int startY = rect.top(); - const int w = rect.width(); - const int h = rect.height(); - - int firstAlpha = -1; - for (int y = startY; y < h/2; ++y) { - DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); - for (int x = startX; x < w; ++x, ++buffer) { - int alpha = (*buffer) >> 24; - if (firstAlpha == -1) - firstAlpha = alpha; - else if (alpha != firstAlpha) - return true; - } - } - return false; -} - -/*! \internal - When the theme engine paints both a true alpha pixmap and a glyph - into our buffer, the glyph might not contain a proper alpha value. - The rule of thumb for premultiplied pixmaps is that the color - values of a pixel can never be higher than the alpha values, so - we use this to our advantage here, and fix all instances where - this occures. -*/ -bool QWindowsXPStylePrivate::fixAlphaChannel(const QRect &rect) -{ - const int startX = rect.left(); - const int startY = rect.top(); - const int w = rect.width(); - const int h = rect.height(); - bool hasFixedAlphaValue = false; - - for (int y = startY; y < h; ++y) { - DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); - for (int x = startX; x < w; ++x, ++buffer) { - uint pixel = *buffer; - int alpha = qAlpha(pixel); - if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) { - *buffer |= 0xff000000; - hasFixedAlphaValue = true; - } - } - } - return hasFixedAlphaValue; -} - -/*! \internal - Swaps the alpha values on certain pixels: - 0xFF?????? -> 0x00?????? - 0x00?????? -> 0xFF?????? - Used to determin the mask of a non-alpha transparent pixmap in - the native doublebuffer, and swap the alphas so we may paint - the image as a Premultiplied QImage with drawImage(), and obtain - the mask transparency. -*/ -bool QWindowsXPStylePrivate::swapAlphaChannel(const QRect &rect, bool allPixels) -{ - const int startX = rect.left(); - const int startY = rect.top(); - const int w = rect.width(); - const int h = rect.height(); - bool valueChange = false; - - // Flip the alphas, so that 255-alpha pixels are 0, and 0-alpha are 255. - for (int y = startY; y < h; ++y) { - DWORD *buffer = (DWORD*)bufferPixels + (y * bufferW); - for (int x = startX; x < w; ++x, ++buffer) { - if (allPixels) { - *buffer |= 0xFF000000; - continue; - } - unsigned int alphaValue = (*buffer) & 0xFF000000; - if (alphaValue == 0xFF000000) { - *buffer = 0; - valueChange = true; - } else if (alphaValue == 0) { - *buffer |= 0xFF000000; - valueChange = true; - } - } - } - return valueChange; -} - -enum TransformType { SimpleTransform, HighDpiScalingTransform, ComplexTransform }; - -static inline TransformType transformType(const QTransform &transform, qreal devicePixelRatio) -{ - if (transform.type() <= QTransform::TxTranslate) - return SimpleTransform; - if (transform.type() > QTransform::TxScale) - return ComplexTransform; - return qFuzzyCompare(transform.m11(), devicePixelRatio) - && qFuzzyCompare(transform.m22(), devicePixelRatio) - ? HighDpiScalingTransform : ComplexTransform; -} - -/*! \internal - Main theme drawing function. - Determines the correct lowlevel drawing method depending on several - factors. - Use drawBackgroundThruNativeBuffer() if: - - Painter does not have an HDC - - Theme part is flipped (mirrored horizontally) - else use drawBackgroundDirectly(). - \note drawBackgroundThruNativeBuffer() can return false for large - sizes due to buffer()/CreateDIBSection() failing. -*/ -bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) -{ - if (themeData.rect.isEmpty()) - return true; - - QPainter *painter = themeData.painter; - Q_ASSERT_X(painter != 0, "QWindowsXPStylePrivate::drawBackground()", "Trying to draw a theme part without a painter"); - if (!painter || !painter->isActive()) - return false; - - painter->save(); - - // Access paintDevice via engine since the painter may - // return the clip device which can still be a widget device in case of grabWidget(). - - bool translucentToplevel = false; - const QPaintDevice *paintDevice = painter->device(); - const qreal aditionalDevicePixelRatio = themeData.widget ? themeData.widget->devicePixelRatioF() : qreal(1); - if (paintDevice->devType() == QInternal::Widget) { - const QWidget *window = static_cast(paintDevice)->window(); - translucentToplevel = window->testAttribute(Qt::WA_TranslucentBackground); - } - - const TransformType tt = transformType(painter->deviceTransform(), aditionalDevicePixelRatio); - - bool canDrawDirectly = false; - if (themeData.widget && painter->opacity() == 1.0 && !themeData.rotate - && tt != ComplexTransform && !themeData.mirrorVertically - && !translucentToplevel) { - // Draw on backing store DC only for real widgets or backing store images. - const QPaintDevice *enginePaintDevice = painter->paintEngine()->paintDevice(); - switch (enginePaintDevice->devType()) { - case QInternal::Widget: - canDrawDirectly = true; - break; - case QInternal::Image: - // Ensure the backing store has received as resize and is initialized. - if (QBackingStore *bs = backingStoreForWidget(themeData.widget)) - if (bs->size().isValid() && bs->paintDevice() == enginePaintDevice) - canDrawDirectly = true; - } - } - - const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : HDC(0); - const bool result = dc - ? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio) - : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio); - painter->restore(); - return result; -} - -static inline QRectF scaleRect(const QRectF &r, qreal factor) -{ - return r.isValid() && factor > 1 - ? QRectF(r.topLeft() * factor, r.size() * factor) - : r; -} - -static QRegion scaleRegion(const QRegion ®ion, qreal factor) -{ - if (region.isEmpty() || qFuzzyCompare(factor, qreal(1))) - return region; - if (region.rectCount() == 1) - return QRegion(scaleRect(QRectF(region.boundingRect()), factor).toRect()); - QRegion result; - foreach (const QRect &rect, region.rects()) - result += QRectF(QPointF(rect.topLeft()) * factor, QSizeF(rect.size() * factor)).toRect(); - return result; -} - -/*! \internal - This function draws the theme parts directly to the paintengines HDC. - Do not use this if you need to perform other transformations on the - resulting data. -*/ -bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal additionalDevicePixelRatio) -{ - QPainter *painter = themeData.painter; - - const QPointF redirectionDelta(painter->deviceMatrix().dx(), painter->deviceMatrix().dy()); - const QRect area = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio).translated(redirectionDelta).toRect(); - - QRegion sysRgn = painter->paintEngine()->systemClip(); - if (sysRgn.isEmpty()) - sysRgn = area; - else - sysRgn &= area; - if (painter->hasClipping()) - sysRgn &= scaleRegion(painter->clipRegion(), additionalDevicePixelRatio).translated(redirectionDelta.toPoint()); - HRGN hrgn = qt_hrgn_from_qregion(sysRgn); - SelectClipRgn(dc, hrgn); - -#ifdef DEBUG_XP_STYLE - printf("---[ DIRECT PAINTING ]------------------> Name(%-10s) Part(%d) State(%d)\n", - qPrintable(themeData.name), themeData.partId, themeData.stateId); - showProperties(themeData); -#endif - - RECT drawRECT = themeData.toRECT(area); - DTBGOPTS drawOptions; - memset(&drawOptions, 0, sizeof(drawOptions)); - drawOptions.dwSize = sizeof(drawOptions); - drawOptions.rcClip = themeData.toRECT(sysRgn.boundingRect()); - drawOptions.dwFlags = DTBG_CLIPRECT - | (themeData.noBorder ? DTBG_OMITBORDER : 0) - | (themeData.noContent ? DTBG_OMITCONTENT : 0) - | (themeData.mirrorHorizontally ? DTBG_MIRRORDC : 0); - - const HRESULT result = DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawRECT), &drawOptions); - SelectClipRgn(dc, 0); - DeleteObject(hrgn); - return SUCCEEDED(result); -} - -/*! \internal - This function uses a secondary Native doublebuffer for painting parts. - It should only be used when the painteengine doesn't provide a proper - HDC for direct painting (e.g. when doing a grabWidget(), painting to - other pixmaps etc), or when special transformations are needed (e.g. - flips (horizonal mirroring only, vertical are handled by the theme - engine). -*/ -bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData, - qreal additionalDevicePixelRatio) -{ - QPainter *painter = themeData.painter; - QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio); - - if ((themeData.rotate + 90) % 180 == 0) { // Catch 90,270,etc.. degree flips. - rectF = QRectF(0, 0, rectF.height(), rectF.width()); - } - rectF.moveTo(0, 0); - QRect rect = rectF.toRect(); - int partId = themeData.partId; - int stateId = themeData.stateId; - int w = rect.width(); - int h = rect.height(); - - // Values initialized later, either from cached values, or from function calls - AlphaChannelType alphaType = UnknownAlpha; - bool stateHasData = true; // We assume so; - bool hasAlpha = false; - bool partIsTransparent; - bool potentialInvalidAlpha; - - QString pixmapCacheKey = QStringLiteral("$qt_xp_"); - pixmapCacheKey.append(themeName(themeData.theme)); - pixmapCacheKey.append(QLatin1Char('p')); - pixmapCacheKey.append(QString::number(partId)); - pixmapCacheKey.append(QLatin1Char('s')); - pixmapCacheKey.append(QString::number(stateId)); - pixmapCacheKey.append(QLatin1Char('s')); - pixmapCacheKey.append(themeData.noBorder ? QLatin1Char('0') : QLatin1Char('1')); - pixmapCacheKey.append(QLatin1Char('b')); - pixmapCacheKey.append(themeData.noContent ? QLatin1Char('0') : QLatin1Char('1')); - pixmapCacheKey.append(QString::number(w)); - pixmapCacheKey.append(QLatin1Char('w')); - pixmapCacheKey.append(QString::number(h)); - pixmapCacheKey.append(QLatin1Char('h')); - pixmapCacheKey.append(QString::number(additionalDevicePixelRatio)); - pixmapCacheKey.append(QLatin1Char('d')); - - QPixmap cachedPixmap; - ThemeMapKey key(themeData); - ThemeMapData data = alphaCache.value(key); - - bool haveCachedPixmap = false; - bool isCached = data.dataValid; - if (isCached) { - partIsTransparent = data.partIsTransparent; - hasAlpha = data.hasAlphaChannel; - alphaType = data.alphaType; - potentialInvalidAlpha = data.hadInvalidAlpha; - - haveCachedPixmap = QPixmapCache::find(pixmapCacheKey, cachedPixmap); - -#ifdef DEBUG_XP_STYLE - char buf[25]; - ::sprintf(buf, "+ Pixmap(%3d, %3d) ]", w, h); - printf("---[ CACHED %s--------> Name(%-10s) Part(%d) State(%d)\n", - haveCachedPixmap ? buf : "]-------------------", - qPrintable(themeData.name), themeData.partId, themeData.stateId); -#endif - } else { - // Not cached, so get values from Theme Engine - BOOL tmt_borderonly = false; - COLORREF tmt_transparentcolor = 0x0; - PROPERTYORIGIN proporigin = PO_NOTFOUND; - GetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERONLY, &tmt_borderonly); - GetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, TMT_TRANSPARENTCOLOR, &tmt_transparentcolor); - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_CAPTIONMARGINS, &proporigin); - - partIsTransparent = isTransparent(themeData); - - potentialInvalidAlpha = false; - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &proporigin); - if (proporigin == PO_PART || proporigin == PO_STATE) { - int tmt_glyphtype = GT_NONE; - GetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, TMT_GLYPHTYPE, &tmt_glyphtype); - potentialInvalidAlpha = partIsTransparent && tmt_glyphtype == GT_IMAGEGLYPH; - } - -#ifdef DEBUG_XP_STYLE - printf("---[ NOT CACHED ]-----------------------> Name(%-10s) Part(%d) State(%d)\n", - qPrintable(themeData.name), themeData.partId, themeData.stateId); - printf("-->partIsTransparen = %d\n", partIsTransparent); - printf("-->potentialInvalidAlpha = %d\n", potentialInvalidAlpha); - showProperties(themeData); -#endif - } - bool wasAlphaSwapped = false; - bool wasAlphaFixed = false; - - // OLD PSDK Workaround ------------------------------------------------------------------------ - // See if we need extra clipping for the older PSDK, which does - // not have a DrawThemeBackgroundEx function for DTGB_OMITBORDER - // and DTGB_OMITCONTENT - bool addBorderContentClipping = false; - QRegion extraClip; - QRect area = rect; - if (themeData.noBorder || themeData.noContent) { - extraClip = area; - // We are running on a system where the uxtheme.dll does not have - // the DrawThemeBackgroundEx function, so we need to clip away - // borders or contents manually. - - int borderSize = 0; - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin); - GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize); - - // Clip away border region - if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) { - if (themeData.noBorder) { - extraClip &= area; - area = area.adjusted(-borderSize, -borderSize, borderSize, borderSize); - } - - // Clip away content region - if (themeData.noContent) { - QRegion content = area.adjusted(borderSize, borderSize, -borderSize, -borderSize); - extraClip ^= content; - } - } - addBorderContentClipping = (themeData.noBorder | themeData.noContent); - } - - QImage img; - if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! ------------------------- - if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size - return false; - HDC dc = bufferHDC(); - - // Clear the buffer - if (alphaType != NoAlpha) { - // Consider have separate "memset" function for small chunks for more speedup - memset(bufferPixels, 0x00, bufferW * h * 4); - } - - // Difference between area and rect - int dx = area.x() - rect.x(); - int dy = area.y() - rect.y(); - - // Adjust so painting rect starts from Origo - rect.moveTo(0,0); - area.moveTo(dx,dy); - DTBGOPTS drawOptions; - drawOptions.dwSize = sizeof(drawOptions); - drawOptions.rcClip = themeData.toRECT(rect); - drawOptions.dwFlags = DTBG_CLIPRECT - | (themeData.noBorder ? DTBG_OMITBORDER : 0) - | (themeData.noContent ? DTBG_OMITCONTENT : 0); - - // Drawing the part into the backing store - RECT wRect(themeData.toRECT(area)); - DrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &wRect, &drawOptions); - - // If not cached, analyze the buffer data to figure - // out alpha type, and if it contains data - if (!isCached) { - // SHORTCUT: If the part's state has no data, cache it for NOOP later - if (!stateHasData) { - memset(&data, 0, sizeof(data)); - data.dataValid = true; - alphaCache.insert(key, data); - return true; - } - hasAlpha = hasAlphaChannel(rect); - if (!hasAlpha && partIsTransparent) - potentialInvalidAlpha = true; -#if defined(DEBUG_XP_STYLE) && 1 - dumpNativeDIB(w, h); -#endif - } - - // Fix alpha values, if needed - if (potentialInvalidAlpha) - wasAlphaFixed = fixAlphaChannel(rect); - - QImage::Format format; - if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) { - format = QImage::Format_ARGB32_Premultiplied; - alphaType = RealAlpha; - } else if (wasAlphaSwapped) { - format = QImage::Format_ARGB32_Premultiplied; - alphaType = MaskAlpha; - } else { - format = QImage::Format_RGB32; - // The image data we got from the theme engine does not have any transparency, - // thus the alpha channel is set to 0. - // However, Format_RGB32 requires the alpha part to be set to 0xff, thus - // we must flip it from 0x00 to 0xff - swapAlphaChannel(rect, true); - alphaType = NoAlpha; - } -#if defined(DEBUG_XP_STYLE) && 1 - printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha"); -#endif - img = QImage(bufferPixels, bufferW, bufferH, format); - img.setDevicePixelRatio(additionalDevicePixelRatio); - } - - // Blitting backing store - bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped; - - QRegion newRegion; - QRegion oldRegion; - if (useRegion) { - newRegion = region(themeData); - oldRegion = painter->clipRegion(); - painter->setClipRegion(newRegion); -#if defined(DEBUG_XP_STYLE) && 0 - printf("Using region:\n"); - for (const QRect &r : newRegion) - printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom()); -#endif - } - - if (addBorderContentClipping) - painter->setClipRegion(extraClip, Qt::IntersectClip); - - if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) { - if (!haveCachedPixmap) - painter->drawImage(themeData.rect, img, rect); - else - painter->drawPixmap(themeData.rect, cachedPixmap); - } else { - // This is _slow_! - // Make a copy containing only the necessary data, and mirror - // on all wanted axes. Then draw the copy. - // If cached, the normal pixmap is cached, instead of caching - // all possible orientations for each part and state. - QImage imgCopy; - if (!haveCachedPixmap) - imgCopy = img.copy(rect); - else - imgCopy = cachedPixmap.toImage(); - - if (themeData.rotate) { - QMatrix rotMatrix; - rotMatrix.rotate(themeData.rotate); - imgCopy = imgCopy.transformed(rotMatrix); - } - if (themeData.mirrorHorizontally || themeData.mirrorVertically) { - imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically); - } - painter->drawImage(themeData.rect, - imgCopy); - } - - if (useRegion || addBorderContentClipping) { - if (oldRegion.isEmpty()) - painter->setClipping(false); - else - painter->setClipRegion(oldRegion); - } - - // Cache the pixmap to avoid expensive swapAlphaChannel() calls - if (!haveCachedPixmap && w && h) { - QPixmap pix = QPixmap::fromImage(img).copy(rect); - QPixmapCache::insert(pixmapCacheKey, pix); -#ifdef DEBUG_XP_STYLE - printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n", - w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey)); -#endif - } - - // Add to theme part cache - if (!isCached) { - memset(&data, 0, sizeof(data)); - data.dataValid = true; - data.partIsTransparent = partIsTransparent; - data.alphaType = alphaType; - data.hasAlphaChannel = hasAlpha; - data.wasAlphaSwapped = wasAlphaSwapped; - data.hadInvalidAlpha = wasAlphaFixed; - alphaCache.insert(key, data); - } - return true; -} - - -// ------------------------------------------------------------------------------------------------ - -/*! - \class QWindowsXPStyle - \brief The QWindowsXPStyle class provides a Microsoft Windows XP-like look and feel. - - \ingroup appearance - \inmodule QtWidgets - \internal - - \warning This style is only available on the Windows XP platform - because it makes use of Windows XP's style engine. - - Most of the functions are documented in the base classes - QWindowsStyle, QCommonStyle, and QStyle, but the - QWindowsXPStyle overloads of drawComplexControl(), drawControl(), - drawControlMask(), drawPrimitive(), proxy()->subControlRect(), and - sizeFromContents(), are documented here. - - \image qwindowsxpstyle.png - \sa QMacStyle, QWindowsStyle, QFusionStyle -*/ - -/*! - Constructs a QWindowsStyle -*/ -QWindowsXPStyle::QWindowsXPStyle() - : QWindowsStyle(*new QWindowsXPStylePrivate) -{ -} - -/*! - Destroys the style. -*/ -QWindowsXPStyle::~QWindowsXPStyle() -{ -} - -/*! \reimp */ -void QWindowsXPStyle::unpolish(QApplication *app) -{ - QWindowsStyle::unpolish(app); -} - -/*! \reimp */ -void QWindowsXPStyle::polish(QApplication *app) -{ - QWindowsStyle::polish(app); - if (!QWindowsXPStylePrivate::useXP()) - return; -} - -/*! \reimp */ -void QWindowsXPStyle::polish(QWidget *widget) -{ - QWindowsStyle::polish(widget); - if (!QWindowsXPStylePrivate::useXP()) - return; - - if (false -#if QT_CONFIG(abstractbutton) - || qobject_cast(widget) -#endif - || qobject_cast(widget) - || qobject_cast(widget) -#ifndef QT_NO_COMBOBOX - || qobject_cast(widget) -#endif // QT_NO_COMBOBOX - || qobject_cast(widget) - || qobject_cast(widget) - || qobject_cast(widget) -#ifndef QT_NO_SPINBOX - || qobject_cast(widget) - || qobject_cast(widget) -#endif // QT_NO_SPINBOX - ) { - widget->setAttribute(Qt::WA_Hover); - } - -#ifndef QT_NO_RUBBERBAND - if (qobject_cast(widget)) { - widget->setWindowOpacity(0.6); - } -#endif - if (qobject_cast(widget) && - qobject_cast(widget->parent())) - widget->parentWidget()->setAttribute(Qt::WA_ContentsPropagated); - - Q_D(QWindowsXPStyle); - if (!d->hasInitColors) { - // Get text color for group box labels - COLORREF cref; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, 0, 0); - GetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); - d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - GetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); - d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - // Where does this color come from? - //GetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); - d->sliderTickColor = qRgb(165, 162, 148); - d->hasInitColors = true; - } -} - -/*! \reimp */ -void QWindowsXPStyle::polish(QPalette &pal) -{ - QWindowsStyle::polish(pal); - pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110)); -} - -/*! \reimp */ -void QWindowsXPStyle::unpolish(QWidget *widget) -{ -#ifndef QT_NO_RUBBERBAND - if (qobject_cast(widget)) { - widget->setWindowOpacity(1.0); - } -#endif - Q_D(QWindowsXPStyle); - // Unpolish of widgets is the first thing that - // happens when a theme changes, or the theme - // engine is turned off. So we detect it here. - bool oldState = QWindowsXPStylePrivate::useXP(); - bool newState = QWindowsXPStylePrivate::useXP(true); - if ((oldState != newState) && newState) { - d->cleanup(true); - d->init(true); - } else { - // Cleanup handle map, if just changing style, - // or turning it on. In both cases the values - // already in the map might be old (other style). - d->cleanupHandleMap(); - } - if (false -#if QT_CONFIG(abstractbutton) - || qobject_cast(widget) -#endif - || qobject_cast(widget) - || qobject_cast(widget) -#ifndef QT_NO_COMBOBOX - || qobject_cast(widget) -#endif // QT_NO_COMBOBOX - || qobject_cast(widget) - || qobject_cast(widget) - || qobject_cast(widget) -#ifndef QT_NO_SPINBOX - || qobject_cast(widget) - || qobject_cast(widget) -#endif // QT_NO_SPINBOX - ) { - widget->setAttribute(Qt::WA_Hover, false); - } - QWindowsStyle::unpolish(widget); -} - -/*! \reimp */ -QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) { - return QWindowsStyle::subElementRect(sr, option, widget); - } - - QRect rect(option->rect); - switch(sr) { - case SE_DockWidgetCloseButton: - case SE_DockWidgetFloatButton: - rect = QWindowsStyle::subElementRect(sr, option, widget); - return rect.translated(0, 1); - break; - case SE_TabWidgetTabContents: - if (qstyleoption_cast(option)) - { - rect = QWindowsStyle::subElementRect(sr, option, widget); - if (sr == SE_TabWidgetTabContents) { - if (const QTabWidget *tabWidget = qobject_cast(widget)) { - if (tabWidget->documentMode()) - break; - } - - rect.adjust(0, 0, -2, -2); - } - } - break; - case SE_TabWidgetTabBar: { - rect = QWindowsStyle::subElementRect(sr, option, widget); - const QStyleOptionTabWidgetFrame *twfOption = - qstyleoption_cast(option); - if (twfOption && twfOption->direction == Qt::RightToLeft - && (twfOption->shape == QTabBar::RoundedNorth - || twfOption->shape == QTabBar::RoundedSouth)) - { - QStyleOptionTab otherOption; - otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth - ? QTabBar::RoundedEast : QTabBar::RoundedSouth); - int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget); - int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); - rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0); - } - break;} - - case SE_PushButtonContents: - if (const QStyleOptionButton *btn = qstyleoption_cast(option)) { - MARGINS borderSize; - if (widget) { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme); - HTHEME theme = buttontheme.handle(); - if (theme) { - int stateId; - if (!(option->state & State_Enabled)) - stateId = PBS_DISABLED; - else if (option->state & State_Sunken) - stateId = PBS_PRESSED; - else if (option->state & State_MouseOver) - stateId = PBS_HOT; - else if (btn->features & QStyleOptionButton::DefaultButton) - stateId = PBS_DEFAULTED; - else - stateId = PBS_NORMAL; - - int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); - rect = option->rect.adjusted(border, border, -border, -border); - - if (SUCCEEDED(GetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, TMT_CONTENTMARGINS, NULL, &borderSize))) { - rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, - -borderSize.cxRightWidth, -borderSize.cyBottomHeight); - rect = visualRect(option->direction, option->rect, rect); - } - } - } - } - break; - case SE_ProgressBarContents: - rect = QCommonStyle::subElementRect(SE_ProgressBarGroove, option, widget); - if (option->state & QStyle::State_Horizontal) - rect.adjust(4, 3, -4, -3); - else - rect.adjust(3, 2, -3, -2); - break; - default: - rect = QWindowsStyle::subElementRect(sr, option, widget); - } - return rect; -} - -/*! - \reimp -*/ -void QWindowsXPStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p, - const QWidget *widget) const -{ - QWindowsXPStylePrivate *d = const_cast(d_func()); - - if (!QWindowsXPStylePrivate::useXP()) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - - int themeNumber = -1; - int partId = 0; - int stateId = 0; - QRect rect = option->rect; - State flags = option->state; - bool hMirrored = false; - bool vMirrored = false; - bool noBorder = false; - bool noContent = false; - int rotate = 0; - - switch (pe) { - case PE_FrameTabBarBase: - if (const QStyleOptionTabBarBase *tbb - = qstyleoption_cast(option)) { - p->save(); - switch (tbb->shape) { - case QTabBar::RoundedNorth: - p->setPen(QPen(tbb->palette.dark(), 0)); - p->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); - break; - case QTabBar::RoundedWest: - p->setPen(QPen(tbb->palette.dark(), 0)); - p->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); - break; - case QTabBar::RoundedSouth: - p->setPen(QPen(tbb->palette.dark(), 0)); - p->drawLine(tbb->rect.left(), tbb->rect.top(), - tbb->rect.right(), tbb->rect.top()); - break; - case QTabBar::RoundedEast: - p->setPen(QPen(tbb->palette.dark(), 0)); - p->drawLine(tbb->rect.topLeft(), tbb->rect.bottomLeft()); - break; - case QTabBar::TriangularNorth: - case QTabBar::TriangularEast: - case QTabBar::TriangularWest: - case QTabBar::TriangularSouth: - p->restore(); - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - p->restore(); - } - return; - case PE_PanelButtonBevel: - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_PUSHBUTTON; - if (!(flags & State_Enabled)) - stateId = PBS_DISABLED; - else if ((flags & State_Sunken) || (flags & State_On)) - stateId = PBS_PRESSED; - else if (flags & State_MouseOver) - stateId = PBS_HOT; - //else if (flags & State_ButtonDefault) - // stateId = PBS_DEFAULTED; - else - stateId = PBS_NORMAL; - break; - - case PE_PanelButtonTool: - if (widget && widget->inherits("QDockWidgetTitleButton")) { - if (const QWidget *dw = widget->parentWidget()) - if (dw->isWindow()) - return; - } - themeNumber = QWindowsXPStylePrivate::ToolBarTheme; - partId = TP_BUTTON; - if (!(flags & State_Enabled)) - stateId = TS_DISABLED; - else if (flags & State_Sunken) - stateId = TS_PRESSED; - else if (flags & State_MouseOver) - stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; - else if (flags & State_On) - stateId = TS_CHECKED; - else if (!(flags & State_AutoRaise)) - stateId = TS_HOT; - else - stateId = TS_NORMAL; - break; - - case PE_IndicatorButtonDropDown: - themeNumber = QWindowsXPStylePrivate::ToolBarTheme; - partId = TP_SPLITBUTTONDROPDOWN; - if (!(flags & State_Enabled)) - stateId = TS_DISABLED; - else if (flags & State_Sunken) - stateId = TS_PRESSED; - else if (flags & State_MouseOver) - stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; - else if (flags & State_On) - stateId = TS_CHECKED; - else if (!(flags & State_AutoRaise)) - stateId = TS_HOT; - else - stateId = TS_NORMAL; - if (option->direction == Qt::RightToLeft) - hMirrored = true; - break; - - case PE_IndicatorCheckBox: - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_CHECKBOX; - if (!(flags & State_Enabled)) - stateId = CBS_UNCHECKEDDISABLED; - else if (flags & State_Sunken) - stateId = CBS_UNCHECKEDPRESSED; - else if (flags & State_MouseOver) - stateId = CBS_UNCHECKEDHOT; - else - stateId = CBS_UNCHECKEDNORMAL; - - if (flags & State_On) - stateId += CBS_CHECKEDNORMAL-1; - else if (flags & State_NoChange) - stateId += CBS_MIXEDNORMAL-1; - - break; - - case PE_IndicatorRadioButton: - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_RADIOBUTTON; - if (!(flags & State_Enabled)) - stateId = RBS_UNCHECKEDDISABLED; - else if (flags & State_Sunken) - stateId = RBS_UNCHECKEDPRESSED; - else if (flags & State_MouseOver) - stateId = RBS_UNCHECKEDHOT; - else - stateId = RBS_UNCHECKEDNORMAL; - - if (flags & State_On) - stateId += RBS_CHECKEDNORMAL-1; - break; - - case PE_IndicatorDockWidgetResizeHandle: - return; - -case PE_Frame: - { - if (flags & State_Raised) - return; - themeNumber = QWindowsXPStylePrivate::ListViewTheme; - partId = LVP_LISTGROUP; - XPThemeData theme(widget, 0, themeNumber, partId, 0); - - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else - stateId = ETS_NORMAL; - int fillType; - if (GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { - if (fillType == BT_BORDERFILL) { - COLORREF bcRef; - GetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); - QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef))); - QPen oldPen = p->pen(); - // int borderSize = 1; - // GetThemeInt(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &borderSize); - - // Inner white border - p->setPen(QPen(option->palette.base().color(), 1)); - p->drawRect(option->rect.adjusted(1, 1, -2, -2)); - // Outer dark border - p->setPen(QPen(bordercolor, 1)); - p->drawRect(option->rect.adjusted(0, 0, -1, -1)); - p->setPen(oldPen); - return; - } else if (fillType == BT_NONE) { - return; - } else { - break; - } - } - } - case PE_FrameLineEdit: { - // we try to check if this lineedit is a delegate on a QAbstractItemView-derived class. - if (QWindowsXPStylePrivate::isItemViewDelegateLineEdit(widget)) { - QPen oldPen = p->pen(); - // Inner white border - p->setPen(QPen(option->palette.base().color(), 1)); - p->drawRect(option->rect.adjusted(1, 1, -2, -2)); - // Outer dark border - p->setPen(QPen(option->palette.shadow().color(), 1)); - p->drawRect(option->rect.adjusted(0, 0, -1, -1)); - p->setPen(oldPen); - return; - } else if (qstyleoption_cast(option)) { - themeNumber = QWindowsXPStylePrivate::EditTheme; - partId = EP_EDITTEXT; - noContent = true; - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else - stateId = ETS_NORMAL; - } - break; - } - - case PE_PanelLineEdit: - if (const QStyleOptionFrame *panel = qstyleoption_cast(option)) { - themeNumber = QWindowsXPStylePrivate::EditTheme; - partId = EP_EDITTEXT; - noBorder = true; - bool isEnabled = flags & State_Enabled; - - stateId = isEnabled ? ETS_NORMAL : ETS_DISABLED; - - if (QWindowsXPStylePrivate::isLineEditBaseColorSet(option, widget)) { - p->fillRect(panel->rect, panel->palette.brush(QPalette::Base)); - } else { - XPThemeData theme(0, p, themeNumber, partId, stateId, rect); - if (!theme.isValid()) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - int bgType; - GetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &bgType); - if( bgType == BT_IMAGEFILE ) { - theme.mirrorHorizontally = hMirrored; - theme.mirrorVertically = vMirrored; - theme.noBorder = noBorder; - theme.noContent = noContent; - theme.rotate = rotate; - d->drawBackground(theme); - } else { - QBrush fillColor = option->palette.brush(QPalette::Base); - - if (!isEnabled) { - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); - // Use only if the fill property comes from our part - if ((origin == PO_PART || origin == PO_STATE)) { - COLORREF bgRef; - GetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); - fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); - } - } - p->fillRect(option->rect, fillColor); - } - } - - if (panel->lineWidth > 0) - proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget); - return; - } - break; - - case PE_FrameTabWidget: - if (const QStyleOptionTabWidgetFrame *tab = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::TabTheme; - partId = TABP_PANE; - - if (widget) { - bool useGradient = true; - const int maxlength = 256; - wchar_t themeFileName[maxlength]; - wchar_t themeColor[maxlength]; - // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it - if (GetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { - wchar_t *offset = 0; - if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { - offset++; - if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) { - useGradient = false; - } - } - } - // This should work, but currently there's an error in the ::drawBackgroundDirectly() - // code, when using the HDC directly.. - if (useGradient) { - QStyleOptionTabWidgetFrame frameOpt = *tab; - frameOpt.rect = widget->rect(); - QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt, widget); - QRegion reg = option->rect; - reg -= contentsRect; - p->setClipRegion(reg); - XPThemeData theme(widget, p, themeNumber, partId, stateId, rect); - theme.mirrorHorizontally = hMirrored; - theme.mirrorVertically = vMirrored; - d->drawBackground(theme); - p->setClipRect(contentsRect); - partId = TABP_BODY; - } - } - switch (tab->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - vMirrored = true; - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - rotate = 90; - break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - rotate = 90; - hMirrored = true; - break; - default: - break; - } - } - break; - - case PE_FrameMenu: - p->save(); - p->setPen(option->palette.dark().color()); - p->drawRect(rect.adjusted(0, 0, -1, -1)); - p->restore(); - return; - - case PE_PanelMenuBar: - break; - - case PE_FrameDockWidget: - if (const QStyleOptionFrame *frm = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::WindowTheme; - if (flags & State_Active) - stateId = FS_ACTIVE; - else - stateId = FS_INACTIVE; - - int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget); - - XPThemeData theme(widget, p, themeNumber, 0, stateId); - if (!theme.isValid()) - break; - theme.rect = QRect(frm->rect.x(), frm->rect.y(), frm->rect.x()+fwidth, frm->rect.height()-fwidth); theme.partId = WP_SMALLFRAMELEFT; - d->drawBackground(theme); - theme.rect = QRect(frm->rect.width()-fwidth, frm->rect.y(), fwidth, frm->rect.height()-fwidth); - theme.partId = WP_SMALLFRAMERIGHT; - d->drawBackground(theme); - theme.rect = QRect(frm->rect.x(), frm->rect.bottom()-fwidth+1, frm->rect.width(), fwidth); - theme.partId = WP_SMALLFRAMEBOTTOM; - d->drawBackground(theme); - return; - } - break; - - case PE_IndicatorHeaderArrow: - { -#if 0 // XP theme engine doesn't know about this :( - name = QWindowsXPStylePrivate::HeaderTheme; - partId = HP_HEADERSORTARROW; - if (flags & State_Down) - stateId = HSAS_SORTEDDOWN; - else - stateId = HSAS_SORTEDUP; -#else - if (const QStyleOptionHeader *header = qstyleoption_cast(option)) { - p->save(); - p->setPen(option->palette.dark().color()); - p->translate(0, option->rect.height()/2 - 4); - if (header->sortIndicator & QStyleOptionHeader::SortUp) { // invert logic to follow Windows style guide - p->drawLine(option->rect.x(), option->rect.y(), option->rect.x()+8, option->rect.y()); - p->drawLine(option->rect.x()+1, option->rect.y()+1, option->rect.x()+7, option->rect.y()+1); - p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); - p->drawLine(option->rect.x()+3, option->rect.y()+3, option->rect.x()+5, option->rect.y()+3); - p->drawPoint(option->rect.x()+4, option->rect.y()+4); - } else if(header->sortIndicator & QStyleOptionHeader::SortDown) { - p->drawLine(option->rect.x(), option->rect.y()+4, option->rect.x()+8, option->rect.y()+4); - p->drawLine(option->rect.x()+1, option->rect.y()+3, option->rect.x()+7, option->rect.y()+3); - p->drawLine(option->rect.x()+2, option->rect.y()+2, option->rect.x()+6, option->rect.y()+2); - p->drawLine(option->rect.x()+3, option->rect.y()+1, option->rect.x()+5, option->rect.y()+1); - p->drawPoint(option->rect.x()+4, option->rect.y()); - } - p->restore(); - return; - } -#endif - } - break; - - case PE_FrameStatusBarItem: - themeNumber = QWindowsXPStylePrivate::StatusTheme; - partId = SP_PANE; - break; - - case PE_FrameGroupBox: - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_GROUPBOX; - if (!(flags & State_Enabled)) - stateId = GBS_DISABLED; - else - stateId = GBS_NORMAL; - if (const QStyleOptionFrame *frame = qstyleoption_cast(option)) { - if (frame->features & QStyleOptionFrame::Flat) { - // Windows XP does not have a theme part for a flat GroupBox, paint it with the windows style - QRect fr = frame->rect; - QPoint p1(fr.x(), fr.y() + 1); - QPoint p2(fr.x() + fr.width(), p1.y() + 1); - rect = QRect(p1, p2); - themeNumber = -1; - } - } - break; - - case PE_IndicatorProgressChunk: - { - Qt::Orientation orient = Qt::Horizontal; - bool inverted = false; - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) { - orient = pb->orientation; - inverted = pb->invertedAppearance; - } - if (orient == Qt::Horizontal) { - partId = PP_CHUNK; - rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height() ); - if (inverted && option->direction == Qt::LeftToRight) - hMirrored = true; - } else { - partId = PP_CHUNKVERT; - rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.height()); - } - themeNumber = QWindowsXPStylePrivate::ProgressTheme; - stateId = 1; - } - break; - - case PE_FrameWindow: - if (const QStyleOptionFrame *frm = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::WindowTheme; - if (flags & State_Active) - stateId = FS_ACTIVE; - else - stateId = FS_INACTIVE; - - int fwidth = frm->lineWidth + frm->midLineWidth; - - XPThemeData theme(0, p, themeNumber, 0, stateId); - if (!theme.isValid()) - break; - - // May fail due to too-large buffers for large widgets, fall back to Windows style. - theme.rect = QRect(option->rect.x(), option->rect.y()+fwidth, option->rect.x()+fwidth, option->rect.height()-fwidth); - theme.partId = WP_FRAMELEFT; - if (!d->drawBackground(theme)) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - theme.rect = QRect(option->rect.width()-fwidth, option->rect.y()+fwidth, fwidth, option->rect.height()-fwidth); - theme.partId = WP_FRAMERIGHT; - if (!d->drawBackground(theme)) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - theme.rect = QRect(option->rect.x(), option->rect.height()-fwidth, option->rect.width(), fwidth); - theme.partId = WP_FRAMEBOTTOM; - if (!d->drawBackground(theme)) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - theme.rect = QRect(option->rect.x(), option->rect.y(), option->rect.width(), option->rect.y()+fwidth); - theme.partId = WP_CAPTION; - if (!d->drawBackground(theme)) - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - break; - - case PE_IndicatorBranch: - { - static const int decoration_size = 9; - int mid_h = option->rect.x() + option->rect.width() / 2; - int mid_v = option->rect.y() + option->rect.height() / 2; - int bef_h = mid_h; - int bef_v = mid_v; - int aft_h = mid_h; - int aft_v = mid_v; - QBrush brush(option->palette.dark().color(), Qt::Dense4Pattern); - if (option->state & State_Item) { - if (option->direction == Qt::RightToLeft) - p->fillRect(option->rect.left(), mid_v, bef_h - option->rect.left(), 1, brush); - else - p->fillRect(aft_h, mid_v, option->rect.right() - aft_h + 1, 1, brush); - } - if (option->state & State_Sibling) - p->fillRect(mid_h, aft_v, 1, option->rect.bottom() - aft_v + 1, brush); - if (option->state & (State_Open | State_Children | State_Item | State_Sibling)) - p->fillRect(mid_h, option->rect.y(), 1, bef_v - option->rect.y(), brush); - if (option->state & State_Children) { - int delta = decoration_size / 2; - bef_h -= delta; - bef_v -= delta; - aft_h += delta; - aft_v += delta; - XPThemeData theme(0, p, QWindowsXPStylePrivate::XpTreeViewTheme); - theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size); - theme.partId = TVP_GLYPH; - theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; - d->drawBackground(theme); - } - } - return; - - case PE_IndicatorToolBarSeparator: - if (option->rect.height() < 3) { - // XP style requires a few pixels for the separator - // to be visible. - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - themeNumber = QWindowsXPStylePrivate::ToolBarTheme; - partId = TP_SEPARATOR; - - if (option->state & State_Horizontal) - partId = TP_SEPARATOR; - else - partId = TP_SEPARATORVERT; - - break; - - case PE_IndicatorToolBarHandle: - - themeNumber = QWindowsXPStylePrivate::RebarTheme; - partId = RP_GRIPPER; - if (option->state & State_Horizontal) { - partId = RP_GRIPPER; - rect.adjust(0, 0, -2, 0); - } - else { - partId = RP_GRIPPERVERT; - rect.adjust(0, 0, 0, -2); - } - break; - - case PE_IndicatorItemViewItemCheck: { - QStyleOptionButton button; - button.QStyleOption::operator=(*option); - button.state &= ~State_MouseOver; - proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, p, widget); - return; - } - - default: - break; - } - - XPThemeData theme(widget, p, themeNumber, partId, stateId, rect); - if (!theme.isValid()) { - QWindowsStyle::drawPrimitive(pe, option, p, widget); - return; - } - theme.mirrorHorizontally = hMirrored; - theme.mirrorVertically = vMirrored; - theme.noBorder = noBorder; - theme.noContent = noContent; - theme.rotate = rotate; - d->drawBackground(theme); -} - -/*! - \reimp -*/ -void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *p, - const QWidget *widget) const -{ - QWindowsXPStylePrivate *d = const_cast(d_func()); - if (!QWindowsXPStylePrivate::useXP()) { - QWindowsStyle::drawControl(element, option, p, widget); - return; - } - - QRect rect(option->rect); - State flags = option->state; - - int rotate = 0; - bool hMirrored = false; - bool vMirrored = false; - - int themeNumber = -1; - int partId = 0; - int stateId = 0; - switch (element) { - case CE_SizeGrip: - { - themeNumber = QWindowsXPStylePrivate::StatusTheme; - partId = SP_GRIPPER; - XPThemeData theme(0, p, themeNumber, partId, 0); - QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - size.rheight()--; - if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { - switch (sg->corner) { - case Qt::BottomRightCorner: - rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size); - break; - case Qt::BottomLeftCorner: - rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size); - hMirrored = true; - break; - case Qt::TopRightCorner: - rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size); - vMirrored = true; - break; - case Qt::TopLeftCorner: - rect = QRect(rect.topLeft() + QPoint(1, 1), size); - hMirrored = vMirrored = true; - } - } - } - break; - - case CE_HeaderSection: - themeNumber = QWindowsXPStylePrivate::HeaderTheme; - partId = HP_HEADERITEM; - if (flags & State_Sunken) - stateId = HIS_PRESSED; - else if (flags & State_MouseOver) - stateId = HIS_HOT; - else - stateId = HIS_NORMAL; - break; - - case CE_Splitter: - p->eraseRect(option->rect); - return; - - case CE_PushButtonBevel: - if (const QStyleOptionButton *btn = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::ButtonTheme; - partId = BP_PUSHBUTTON; - bool justFlat = ((btn->features & QStyleOptionButton::Flat) && !(flags & (State_On|State_Sunken))) - || ((btn->features & QStyleOptionButton::CommandLinkButton) - && !(flags & State_MouseOver) - && !(btn->features & QStyleOptionButton::DefaultButton)); - if (!(flags & State_Enabled) && !(btn->features & QStyleOptionButton::Flat)) - stateId = PBS_DISABLED; - else if (justFlat) - ; - else if (flags & (State_Sunken | State_On)) - stateId = PBS_PRESSED; - else if (flags & State_MouseOver) - stateId = PBS_HOT; - else if (btn->features & QStyleOptionButton::DefaultButton) - stateId = PBS_DEFAULTED; - else - stateId = PBS_NORMAL; - - if (!justFlat) { - XPThemeData theme(widget, p, themeNumber, partId, stateId, rect); - d->drawBackground(theme); - } - - if (btn->features & QStyleOptionButton::HasMenu) { - int mbiw = 0, mbih = 0; - XPThemeData theme(widget, 0, - QWindowsXPStylePrivate::ToolBarTheme, - TP_SPLITBUTTONDROPDOWN); - if (theme.isValid()) { - const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - mbiw = size.width(); - mbih = size.height(); - } - - QRect ir = btn->rect; - QStyleOptionButton newBtn = *btn; - newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); - } - return; - } - break; - case CE_TabBarTab: - if (const QStyleOptionTab *tab = qstyleoption_cast(option)) - { - stateId = tab->state & State_Enabled ? TIS_NORMAL : TIS_DISABLED; - } - break; - - case CE_TabBarTabShape: - if (const QStyleOptionTab *tab = qstyleoption_cast(option)) - { - themeNumber = QWindowsXPStylePrivate::TabTheme; - bool isDisabled = !(tab->state & State_Enabled); - bool hasFocus = tab->state & State_HasFocus; - bool isHot = tab->state & State_MouseOver; - bool selected = tab->state & State_Selected; - bool lastTab = tab->position == QStyleOptionTab::End; - bool firstTab = tab->position == QStyleOptionTab::Beginning; - bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; - bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft; - bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter; - int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget); - int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget); - - if (isDisabled) - stateId = TIS_DISABLED; - else if (selected) - stateId = TIS_SELECTED; - else if (hasFocus) - stateId = TIS_FOCUSED; - else if (isHot) - stateId = TIS_HOT; - else - stateId = TIS_NORMAL; - - // Selecting proper part depending on position - if (firstTab || onlyOne) { - if (leftAligned) { - partId = TABP_TABITEMLEFTEDGE; - } else if (centerAligned) { - partId = TABP_TABITEM; - } else { // rightAligned - partId = TABP_TABITEMRIGHTEDGE; - } - } else { - partId = TABP_TABITEM; - } - - if (tab->direction == Qt::RightToLeft - && (tab->shape == QTabBar::RoundedNorth - || tab->shape == QTabBar::RoundedSouth)) { - bool temp = firstTab; - firstTab = lastTab; - lastTab = temp; - } - bool begin = firstTab || onlyOne; - bool end = lastTab || onlyOne; - switch (tab->shape) { - case QTabBar::RoundedNorth: - if (selected) - rect.adjust(begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap, borderThickness); - else - rect.adjust(begin? tabOverlap : 0, tabOverlap, end ? -tabOverlap : 0, 0); - break; - case QTabBar::RoundedSouth: - //vMirrored = true; - rotate = 180; // Not 100% correct, but works - if (selected) - rect.adjust(begin ? 0 : -tabOverlap , -borderThickness, end ? 0 : tabOverlap, 0); - else - rect.adjust(begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0 , -tabOverlap); - break; - case QTabBar::RoundedEast: - rotate = 90; - if (selected) { - rect.adjust(-borderThickness, begin ? 0 : -tabOverlap, 0, end ? 0 : tabOverlap); - }else{ - rect.adjust(0, begin ? tabOverlap : 0, -tabOverlap, end ? -tabOverlap : 0); - } - break; - case QTabBar::RoundedWest: - hMirrored = true; - rotate = 90; - if (selected) { - rect.adjust(0, begin ? 0 : -tabOverlap, borderThickness, end ? 0 : tabOverlap); - }else{ - rect.adjust(tabOverlap, begin ? tabOverlap : 0, 0, end ? -tabOverlap : 0); - } - break; - default: - themeNumber = -1; // Do our own painting for triangular - break; - } - - if (!selected) { - switch (tab->shape) { - case QTabBar::RoundedNorth: - rect.adjust(0,0, 0,-1); - break; - case QTabBar::RoundedSouth: - rect.adjust(0,1, 0,0); - break; - case QTabBar::RoundedEast: - rect.adjust( 1,0, 0,0); - break; - case QTabBar::RoundedWest: - rect.adjust(0,0, -1,0); - break; - default: - break; - } - } - } - break; - - case CE_ProgressBarGroove: - { - Qt::Orientation orient = Qt::Horizontal; - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) - orient = pb->orientation; - partId = (orient == Qt::Horizontal) ? PP_BAR : PP_BARVERT; - themeNumber = QWindowsXPStylePrivate::ProgressTheme; - stateId = 1; - } - break; - - case CE_MenuEmptyArea: - case CE_MenuItem: - if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) - { - int tab = menuitem->tabWidth; - bool dis = !(menuitem->state & State_Enabled); - bool act = menuitem->state & State_Selected; - bool checkable = menuitem->menuHasCheckableItems; - bool checked = checkable ? menuitem->checked : false; - - // windows always has a check column, regardless whether we have an icon or not - int checkcol = qMax(menuitem->maxIconWidth, 12); - - int x, y, w, h; - rect.getRect(&x, &y, &w, &h); - - QBrush fill = menuitem->palette.brush(act ? QPalette::Highlight : QPalette::Button); - p->fillRect(rect, fill); - - if (element == CE_MenuEmptyArea) - break; - - // draw separator ------------------------------------------------- - if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { - int yoff = y-1 + h / 2; - p->setPen(menuitem->palette.dark().color()); - p->drawLine(x, yoff, x+w, yoff); - ++yoff; - p->setPen(menuitem->palette.light().color()); - p->drawLine(x, yoff, x+w, yoff); - return; - } - - int xpos = x; - - // draw icon ------------------------------------------------------ - if (!menuitem->icon.isNull()) { - QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; - if (act && !dis) - mode = QIcon::Active; - QPixmap pixmap = checked ? - menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) : - menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode); - const int pixw = pixmap.width() / pixmap.devicePixelRatio(); - const int pixh = pixmap.height() / pixmap.devicePixelRatio(); - QRect iconRect(0, 0, pixw, pixh); - iconRect.moveCenter(QRect(xpos, y, checkcol, h).center()); - QRect vIconRect = visualRect(option->direction, option->rect, iconRect); - p->setPen(menuitem->palette.text().color()); - p->setBrush(Qt::NoBrush); - if (checked) - p->drawRect(vIconRect.adjusted(-1, -1, 0, 0)); - p->drawPixmap(vIconRect.topLeft(), pixmap); - - // draw checkmark ------------------------------------------------- - } else if (checked) { - QStyleOptionMenuItem newMi = *menuitem; - newMi.state = State_None; - if (!dis) - newMi.state |= State_Enabled; - if (act) - newMi.state |= State_On; - - QRect checkMarkRect = QRect(menuitem->rect.x() + windowsItemFrame, - menuitem->rect.y() + windowsItemFrame, - checkcol - 2 * windowsItemFrame, - menuitem->rect.height() - 2*windowsItemFrame); - newMi.rect = visualRect(option->direction, option->rect, checkMarkRect); - proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget); - } - - QColor textColor = dis ? menuitem->palette.text().color() : - act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color(); - p->setPen(textColor); - - // draw text ------------------------------------------------------ - int xm = windowsItemFrame + checkcol + windowsItemHMargin; - xpos = menuitem->rect.x() + xm; - QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); - QRect vTextRect = visualRect(option->direction, option->rect, textRect); - QString s = menuitem->text; - if (!s.isEmpty()) { - p->save(); - int t = s.indexOf(QLatin1Char('\t')); - int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignLeft; - if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) - text_flags |= Qt::TextHideMnemonic; - // draw tab text ---------------- - if (t >= 0) { - QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight())); - if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { - p->setPen(menuitem->palette.light().color()); - p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1)); - p->setPen(textColor); - } - p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); - s = s.left(t); - } - QFont font = menuitem->font; - if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) - font.setBold(true); - p->setFont(font); - if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { - p->setPen(menuitem->palette.light().color()); - p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t)); - p->setPen(textColor); - } - p->drawText(vTextRect, text_flags, s); - p->restore(); - } - - // draw sub menu arrow -------------------------------------------- - if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { - int dim = (h - 2) / 2; - PrimitiveElement arrow; - arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; - xpos = x + w - windowsArrowHMargin - windowsItemFrame - dim; - QRect vSubMenuRect = visualRect(option->direction, option->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim)); - QStyleOptionMenuItem newMI = *menuitem; - newMI.rect = vSubMenuRect; - newMI.state = dis ? State_None : State_Enabled; - if (act) - newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color()); - proxy()->drawPrimitive(arrow, &newMI, p, widget); - } - } - return; - - case CE_MenuBarItem: - if (const QStyleOptionMenuItem *mbi = qstyleoption_cast(option)) - { - if (mbi->menuItemType == QStyleOptionMenuItem::DefaultItem) - break; - - bool act = mbi->state & State_Selected; - bool dis = !(mbi->state & State_Enabled); - - QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button); - QPalette::ColorRole textRole = dis ? QPalette::Text: - act ? QPalette::HighlightedText : QPalette::ButtonText; - QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal); - - uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) - alignment |= Qt::TextHideMnemonic; - - p->fillRect(rect, fill); - if (!pix.isNull()) - drawItemPixmap(p, mbi->rect, alignment, pix); - else - drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); - } - return; -#ifndef QT_NO_DOCKWIDGET - case CE_DockWidgetTitle: - if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast(option)) - { - int buttonMargin = 4; - int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget); - int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget); - bool isFloating = widget && widget->isWindow(); - bool isActive = dwOpt->state & State_Active; - - const bool verticalTitleBar = dwOpt->verticalTitleBar; - - if (verticalTitleBar) { - rect = rect.transposed(); - - p->translate(rect.left() - 1, rect.top() + rect.width()); - p->rotate(-90); - p->translate(-rect.left() + 1, -rect.top()); - } - QRect r = rect.adjusted(0, 2, -1, -3); - QRect titleRect = r; - - if (dwOpt->closable) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); - titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); - } - - if (dwOpt->floatable) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); - titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); - } - - if (isFloating) { - titleRect.adjust(0, -fw, 0, 0); - if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey()) - titleRect.adjust(titleRect.height() + mw, 0, 0, 0); - } else { - titleRect.adjust(mw, 0, 0, 0); - if (!dwOpt->floatable && !dwOpt->closable) - titleRect.adjust(0, 0, -mw, 0); - } - - if (!verticalTitleBar) - titleRect = visualRect(dwOpt->direction, r, titleRect); - - if (!isFloating) { - QPen oldPen = p->pen(); - QString titleText = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); - p->setPen(dwOpt->palette.color(QPalette::Dark)); - p->drawRect(r); - - if (!titleText.isEmpty()) { - drawItemText(p, titleRect, - Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, - dwOpt->state & State_Enabled, titleText, - QPalette::WindowText); - } - - p->setPen(oldPen); - } else { - themeNumber = QWindowsXPStylePrivate::WindowTheme; - if (isActive) - stateId = CS_ACTIVE; - else - stateId = CS_INACTIVE; - - int titleHeight = rect.height() - 2; - rect = rect.adjusted(-fw, -fw, fw, 0); - - XPThemeData theme(widget, p, themeNumber, 0, stateId); - if (!theme.isValid()) - break; - - // Draw small type title bar - theme.rect = rect; - theme.partId = WP_SMALLCAPTION; - d->drawBackground(theme); - - // Figure out maximal button space on title bar - - QIcon ico = widget->windowIcon(); - bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey()); - if (hasIcon) { - QPixmap pxIco = ico.pixmap(titleHeight); - if (!verticalTitleBar && dwOpt->direction == Qt::RightToLeft) - p->drawPixmap(rect.width() - titleHeight - pxIco.width(), rect.bottom() - titleHeight - 2, pxIco); - else - p->drawPixmap(fw, rect.bottom() - titleHeight - 2, pxIco); - } - if (!dwOpt->title.isEmpty()) { - QPen oldPen = p->pen(); - QFont oldFont = p->font(); - QFont titleFont = oldFont; - titleFont.setBold(true); - p->setFont(titleFont); - QString titleText - = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); - - int result = TST_NONE; - GetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); - if (result != TST_NONE) { - COLORREF textShadowRef; - GetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); - QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); - p->setPen(textShadow); - drawItemText(p, titleRect.adjusted(1, 1, 1, 1), - Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, - dwOpt->state & State_Enabled, titleText); - } - - COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); - QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); - p->setPen(textColor); - drawItemText(p, titleRect, - Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette, - dwOpt->state & State_Enabled, titleText); - p->setFont(oldFont); - p->setPen(oldPen); - } - - } - - return; - } - break; -#endif // QT_NO_DOCKWIDGET -#ifndef QT_NO_RUBBERBAND - case CE_RubberBand: - if (qstyleoption_cast(option)) { - QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight); - p->save(); - p->setPen(highlight.darker(120)); - QColor dimHighlight(qMin(highlight.red()/2 + 110, 255), - qMin(highlight.green()/2 + 110, 255), - qMin(highlight.blue()/2 + 110, 255), - (widget && widget->isTopLevel())? 255 : 127); - p->setBrush(dimHighlight); - p->drawRect(option->rect.adjusted(0, 0, -1, -1)); - p->restore(); - return; - } -#endif // QT_NO_RUBBERBAND - case CE_HeaderEmptyArea: - if (option->state & State_Horizontal) - { - themeNumber = QWindowsXPStylePrivate::HeaderTheme; - stateId = HIS_NORMAL; - } - else { - QWindowsStyle::drawControl(CE_HeaderEmptyArea, option, p, widget); - return; - } - break; - default: - break; - } - - XPThemeData theme(widget, p, themeNumber, partId, stateId, rect); - if (!theme.isValid()) { - QWindowsStyle::drawControl(element, option, p, widget); - return; - } - - theme.rotate = rotate; - theme.mirrorHorizontally = hMirrored; - theme.mirrorVertically = vMirrored; - d->drawBackground(theme); -} - -QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const QWidget *widget, XPThemeData *theme) -{ - const bool horizontal = flags & QStyle::State_Horizontal; - const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget); - const QMargins contentsMargin = - (theme->margins(theme->rect, TMT_SIZINGMARGINS) * factor).toMargins(); - theme->partId = horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - const QSize size = (theme->size() * factor).toSize(); - - const int hSpace = theme->rect.width() - size.width(); - const int vSpace = theme->rect.height() - size.height(); - const bool sufficientSpace = (horizontal && hSpace > (contentsMargin.left() + contentsMargin.right())) - || vSpace > contentsMargin.top() + contentsMargin.bottom(); - return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect(); -} - -/*! - \reimp -*/ -void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, - QPainter *p, const QWidget *widget) const -{ - QWindowsXPStylePrivate *d = const_cast(d_func()); - - if (!QWindowsXPStylePrivate::useXP()) { - QWindowsStyle::drawComplexControl(cc, option, p, widget); - return; - } - - State flags = option->state; - SubControls sub = option->subControls; - QRect r = option->rect; - - int partId = 0; - int stateId = 0; - if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow()) - flags |= State_MouseOver; - - switch (cc) { -#ifndef QT_NO_SPINBOX - case CC_SpinBox: - if (const QStyleOptionSpinBox *sb = qstyleoption_cast(option)) - { - XPThemeData theme(widget, p, QWindowsXPStylePrivate::SpinTheme); - - if (sb->frame && (sub & SC_SpinBoxFrame)) { - partId = EP_EDITTEXT; - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else if (flags & State_HasFocus) - stateId = ETS_FOCUSED; - else - stateId = ETS_NORMAL; - - XPThemeData ftheme(widget, p, QWindowsXPStylePrivate::EditTheme, - partId, stateId, r); - ftheme.noContent = true; - d->drawBackground(ftheme); - } - if (sub & SC_SpinBoxUp) { - theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget); - partId = SPNP_UP; - if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled)) - stateId = UPS_DISABLED; - else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken)) - stateId = UPS_PRESSED; - else if (sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_MouseOver)) - stateId = UPS_HOT; - else - stateId = UPS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_SpinBoxDown) { - theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget); - partId = SPNP_DOWN; - if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled)) - stateId = DNS_DISABLED; - else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken)) - stateId = DNS_PRESSED; - else if (sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_MouseOver)) - stateId = DNS_HOT; - else - stateId = DNS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - } - break; -#endif // QT_NO_SPINBOX -#ifndef QT_NO_COMBOBOX - case CC_ComboBox: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) - { - if (sub & SC_ComboBoxEditField) { - if (cmb->frame) { - partId = EP_EDITTEXT; - if (!(flags & State_Enabled)) - stateId = ETS_DISABLED; - else if (flags & State_HasFocus) - stateId = ETS_FOCUSED; - else - stateId = ETS_NORMAL; - XPThemeData theme(widget, p, QWindowsXPStylePrivate::EditTheme, partId, stateId, r); - d->drawBackground(theme); - } else { - QBrush editBrush = cmb->palette.brush(QPalette::Base); - p->fillRect(option->rect, editBrush); - } - if (!cmb->editable) { - QRect re = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget); - if (option->state & State_HasFocus) { - p->fillRect(re, option->palette.highlight()); - p->setPen(option->palette.highlightedText().color()); - p->setBackground(option->palette.highlight()); - } else { - p->fillRect(re, option->palette.base()); - p->setPen(option->palette.text().color()); - p->setBackground(option->palette.base()); - } - } - } - - if (sub & SC_ComboBoxArrow) { - XPThemeData theme(widget, p, QWindowsXPStylePrivate::ComboboxTheme); - theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget); - partId = CP_DROPDOWNBUTTON; - if (!(flags & State_Enabled)) - stateId = CBXS_DISABLED; - else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_Sunken)) - stateId = CBXS_PRESSED; - else if (cmb->activeSubControls == SC_ComboBoxArrow && (cmb->state & State_MouseOver)) - stateId = CBXS_HOT; - else - stateId = CBXS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - } - break; -#endif // QT_NO_COMBOBOX - case CC_ScrollBar: - if (const QStyleOptionSlider *scrollbar = qstyleoption_cast(option)) - { - XPThemeData theme(widget, p, QWindowsXPStylePrivate::ScrollBarTheme); - bool maxedOut = (scrollbar->maximum == scrollbar->minimum); - if (maxedOut) - flags &= ~State_Enabled; - - bool isHorz = flags & State_Horizontal; - bool isRTL = option->direction == Qt::RightToLeft; - if (sub & SC_ScrollBarAddLine) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget); - partId = SBP_ARROWBTN; - if (!(flags & State_Enabled)) - stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED); - else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_Sunken)) - stateId = (isHorz ? (isRTL ? ABS_LEFTPRESSED : ABS_RIGHTPRESSED) : ABS_DOWNPRESSED); - else if (scrollbar->activeSubControls & SC_ScrollBarAddLine && (scrollbar->state & State_MouseOver)) - stateId = (isHorz ? (isRTL ? ABS_LEFTHOT : ABS_RIGHTHOT) : ABS_DOWNHOT); - else - stateId = (isHorz ? (isRTL ? ABS_LEFTNORMAL : ABS_RIGHTNORMAL) : ABS_DOWNNORMAL); - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarSubLine) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget); - partId = SBP_ARROWBTN; - if (!(flags & State_Enabled)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED); - else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_Sunken)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTPRESSED : ABS_LEFTPRESSED) : ABS_UPPRESSED); - else if (scrollbar->activeSubControls & SC_ScrollBarSubLine && (scrollbar->state & State_MouseOver)) - stateId = (isHorz ? (isRTL ? ABS_RIGHTHOT : ABS_LEFTHOT) : ABS_UPHOT); - else - stateId = (isHorz ? (isRTL ? ABS_RIGHTNORMAL : ABS_LEFTNORMAL) : ABS_UPNORMAL); - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (maxedOut) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); - theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget)); - theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget)); - partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; - stateId = SCRBS_DISABLED; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } else { - if (sub & SC_ScrollBarSubPage) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget); - partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT; - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarSubPage && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else - stateId = SCRBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarAddPage) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget); - partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT; - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarAddPage && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else - stateId = SCRBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_ScrollBarSlider) { - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); - if (!(flags & State_Enabled)) - stateId = SCRBS_DISABLED; - else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken)) - stateId = SCRBS_PRESSED; - else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_MouseOver)) - stateId = SCRBS_HOT; - else - stateId = SCRBS_NORMAL; - - // Draw handle - theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; - theme.stateId = stateId; - d->drawBackground(theme); - - const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme); - // Draw gripper if there is enough space - if (!gripperBounds.isEmpty()) { - p->save(); - theme.rect = gripperBounds; - p->setClipRegion(d->region(theme));// Only change inside the region of the gripper - d->drawBackground(theme); // Transparent gripper ontop of background - p->restore(); - } - } - } - } - break; - -#ifndef QT_NO_SLIDER - case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast(option)) - { - XPThemeData theme(widget, p, QWindowsXPStylePrivate::TrackBarTheme); - QRect slrect = slider->rect; - QRegion tickreg = slrect; - if (sub & SC_SliderGroove) { - theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); - if (slider->orientation == Qt::Horizontal) { - partId = TKP_TRACK; - stateId = TRS_NORMAL; - theme.rect = QRect(slrect.left(), theme.rect.center().y() - 2, slrect.width(), 4); - } else { - partId = TKP_TRACKVERT; - stateId = TRVS_NORMAL; - theme.rect = QRect(theme.rect.center().x() - 2, slrect.top(), 4, slrect.height()); - } - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - tickreg -= theme.rect; - } - if (sub & SC_SliderTickmarks) { - int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget); - int ticks = slider->tickPosition; - int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget); - int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); - int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); - int interval = slider->tickInterval; - if (interval <= 0) { - interval = slider->singleStep; - if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, - available) - - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, - 0, available) < 3) - interval = slider->pageStep; - } - if (!interval) - interval = 1; - int fudge = len / 2; - int pos; - int bothOffset = (ticks & QSlider::TicksAbove && ticks & QSlider::TicksBelow) ? 1 : 0; - p->setPen(d->sliderTickColor); - QVarLengthArray lines; - int v = slider->minimum; - while (v <= slider->maximum + 1) { - if (v == slider->maximum + 1 && interval == 1) - break; - const int v_ = qMin(v, slider->maximum); - int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3; - pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, - v_, available) + fudge; - if (slider->orientation == Qt::Horizontal) { - if (ticks & QSlider::TicksAbove) - lines.append(QLine(pos, tickOffset - 1 - bothOffset, - pos, tickOffset - 1 - bothOffset - tickLength)); - - if (ticks & QSlider::TicksBelow) - lines.append(QLine(pos, tickOffset + thickness + bothOffset, - pos, tickOffset + thickness + bothOffset + tickLength)); - } else { - if (ticks & QSlider::TicksAbove) - lines.append(QLine(tickOffset - 1 - bothOffset, pos, - tickOffset - 1 - bothOffset - tickLength, pos)); - - if (ticks & QSlider::TicksBelow) - lines.append(QLine(tickOffset + thickness + bothOffset, pos, - tickOffset + thickness + bothOffset + tickLength, pos)); - } - // in the case where maximum is max int - int nextInterval = v + interval; - if (nextInterval < v) - break; - v = nextInterval; - } - if (lines.size() > 0) { - p->save(); - p->translate(slrect.topLeft()); - p->drawLines(lines.constData(), lines.size()); - p->restore(); - } - } - if (sub & SC_SliderHandle) { - theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); - if (slider->orientation == Qt::Horizontal) { - if (slider->tickPosition == QSlider::TicksAbove) - partId = TKP_THUMBTOP; - else if (slider->tickPosition == QSlider::TicksBelow) - partId = TKP_THUMBBOTTOM; - else - partId = TKP_THUMB; - - if (!(slider->state & State_Enabled)) - stateId = TUS_DISABLED; - else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) - stateId = TUS_PRESSED; - else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) - stateId = TUS_HOT; - else if (flags & State_HasFocus) - stateId = TUS_FOCUSED; - else - stateId = TUS_NORMAL; - } else { - if (slider->tickPosition == QSlider::TicksLeft) - partId = TKP_THUMBLEFT; - else if (slider->tickPosition == QSlider::TicksRight) - partId = TKP_THUMBRIGHT; - else - partId = TKP_THUMBVERT; - - if (!(slider->state & State_Enabled)) - stateId = TUVS_DISABLED; - else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_Sunken)) - stateId = TUVS_PRESSED; - else if (slider->activeSubControls & SC_SliderHandle && (slider->state & State_MouseOver)) - stateId = TUVS_HOT; - else if (flags & State_HasFocus) - stateId = TUVS_FOCUSED; - else - stateId = TUVS_NORMAL; - } - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (slider->state & State_HasFocus) { - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*slider); - fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget); - proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); - } - } - break; -#endif -#ifndef QT_NO_TOOLBUTTON - case CC_ToolButton: - if (const QStyleOptionToolButton *toolbutton - = qstyleoption_cast(option)) { - QRect button, menuarea; - button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); - menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); - - State bflags = toolbutton->state & ~State_Sunken; - State mflags = bflags; - bool autoRaise = flags & State_AutoRaise; - if (autoRaise) { - if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { - bflags &= ~State_Raised; - } - } - - if (toolbutton->state & State_Sunken) { - if (toolbutton->activeSubControls & SC_ToolButton) { - bflags |= State_Sunken; - mflags |= State_MouseOver | State_Sunken; - } else if (toolbutton->activeSubControls & SC_ToolButtonMenu) { - mflags |= State_Sunken; - bflags |= State_MouseOver; - } - } - - QStyleOption tool = *toolbutton; - if (toolbutton->subControls & SC_ToolButton) { - if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) { - if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) { - XPThemeData theme(widget, p, QWindowsXPStylePrivate::ToolBarTheme); - theme.partId = TP_SPLITBUTTON; - theme.rect = button; - if (!(bflags & State_Enabled)) - stateId = TS_DISABLED; - else if (bflags & State_Sunken) - stateId = TS_PRESSED; - else if (bflags & State_MouseOver || !(flags & State_AutoRaise)) - stateId = flags & State_On ? TS_HOTCHECKED : TS_HOT; - else if (bflags & State_On) - stateId = TS_CHECKED; - else - stateId = TS_NORMAL; - if (option->direction == Qt::RightToLeft) - theme.mirrorHorizontally = true; - theme.stateId = stateId; - d->drawBackground(theme); - } else { - tool.rect = option->rect; - tool.state = bflags; - if (autoRaise) // for tool bars - proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); - else - proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); - } - } - } - - if (toolbutton->state & State_HasFocus) { - QStyleOptionFocusRect fr; - fr.QStyleOption::operator=(*toolbutton); - fr.rect.adjust(3, 3, -3, -3); - if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) - fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, - toolbutton, widget), 0); - proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); - } - QStyleOptionToolButton label = *toolbutton; - label.state = bflags; - int fw = 2; - if (!autoRaise) - label.state &= ~State_Sunken; - label.rect = button.adjusted(fw, fw, -fw, -fw); - proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); - - if (toolbutton->subControls & SC_ToolButtonMenu) { - tool.rect = menuarea; - tool.state = mflags; - if (autoRaise) { - proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); - } else { - tool.state = mflags; - menuarea.adjust(-2, 0, 0, 0); - // Draw menu button - if ((bflags & State_Sunken) != (mflags & State_Sunken)){ - p->save(); - p->setClipRect(menuarea); - tool.rect = option->rect; - proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, 0); - p->restore(); - } - // Draw arrow - p->save(); - p->setPen(option->palette.dark().color()); - p->drawLine(menuarea.left(), menuarea.top() + 3, - menuarea.left(), menuarea.bottom() - 3); - p->setPen(option->palette.light().color()); - p->drawLine(menuarea.left() - 1, menuarea.top() + 3, - menuarea.left() - 1, menuarea.bottom() - 3); - - tool.rect = menuarea.adjusted(2, 3, -2, -1); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); - p->restore(); - } - } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { - int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); - QRect ir = toolbutton->rect; - QStyleOptionToolButton newBtn = *toolbutton; - newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); - } - } - break; -#endif // QT_NO_TOOLBUTTON - - case CC_TitleBar: - { - if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) - { - bool isActive = tb->titleBarState & QStyle::State_Active; - XPThemeData theme(widget, p, QWindowsXPStylePrivate::WindowTheme); - if (sub & SC_TitleBarLabel) { - - partId = (tb->titleBarState & Qt::WindowMinimized) ? WP_MINCAPTION : WP_CAPTION; - theme.rect = option->rect; - if (widget && !widget->isEnabled()) - stateId = CS_DISABLED; - else if (isActive) - stateId = CS_ACTIVE; - else - stateId = CS_INACTIVE; - - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - - QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); - - int result = TST_NONE; - GetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); - if (result != TST_NONE) { - COLORREF textShadowRef; - GetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); - QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef)); - p->setPen(textShadow); - p->drawText(ir.x() + 3, ir.y() + 2, ir.width() - 1, ir.height(), - Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); - } - COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT); - QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText)); - p->setPen(textColor); - p->drawText(ir.x() + 2, ir.y() + 1, ir.width() - 2, ir.height(), - Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text); - } - if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget); - partId = WP_SYSBUTTON; - if ((widget && !widget->isEnabled()) || !isActive) - stateId = SBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_Sunken)) - stateId = SBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarSysMenu && (option->state & State_MouseOver)) - stateId = SBS_HOT; - else - stateId = SBS_NORMAL; - if (!tb->icon.isNull()) { - tb->icon.paint(p, theme.rect); - } else { - theme.partId = partId; - theme.stateId = stateId; - if (theme.size().isEmpty()) { - int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); - QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); - p->save(); - drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm); - p->restore(); - } else { - d->drawBackground(theme); - } - } - } - - if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint - && !(tb->titleBarState & Qt::WindowMinimized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget); - partId = WP_MINBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint - && !(tb->titleBarState & Qt::WindowMaximized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget); - partId = WP_MAXBUTTON; - if (widget && !widget->isEnabled()) - stateId = MAXBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_Sunken)) - stateId = MAXBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_MouseOver)) - stateId = MAXBS_HOT; - else if (!isActive) - stateId = MAXBS_INACTIVE; - else - stateId = MAXBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_TitleBarContextHelpButton - && tb->titleBarFlags & Qt::WindowContextHelpButtonHint) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget); - partId = WP_HELPBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - bool drawNormalButton = (sub & SC_TitleBarNormalButton) - && (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) - && (tb->titleBarState & Qt::WindowMinimized)) - || ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) - && (tb->titleBarState & Qt::WindowMaximized))); - if (drawNormalButton) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget); - partId = WP_RESTOREBUTTON; - if (widget && !widget->isEnabled()) - stateId = RBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_Sunken)) - stateId = RBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_MouseOver)) - stateId = RBS_HOT; - else if (!isActive) - stateId = RBS_INACTIVE; - else - stateId = RBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint - && !(tb->titleBarState & Qt::WindowMinimized)) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget); - partId = WP_MINBUTTON; - if (widget && !widget->isEnabled()) - stateId = MINBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_Sunken)) - stateId = MINBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_MouseOver)) - stateId = MINBS_HOT; - else if (!isActive) - stateId = MINBS_INACTIVE; - else - stateId = MINBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint - && tb->titleBarState & Qt::WindowMinimized) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget); - partId = WP_RESTOREBUTTON; - if (widget && !widget->isEnabled()) - stateId = RBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_Sunken)) - stateId = RBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_MouseOver)) - stateId = RBS_HOT; - else if (!isActive) - stateId = RBS_INACTIVE; - else - stateId = RBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) { - theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget); - //partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON; - partId = WP_CLOSEBUTTON; - if (widget && !widget->isEnabled()) - stateId = CBS_DISABLED; - else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_Sunken)) - stateId = CBS_PUSHED; - else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_MouseOver)) - stateId = CBS_HOT; - else if (!isActive) - stateId = CBS_INACTIVE; - else - stateId = CBS_NORMAL; - theme.partId = partId; - theme.stateId = stateId; - d->drawBackground(theme); - } - } - } - break; - -#ifndef QT_NO_MDIAREA - case CC_MdiControls: - { - QRect buttonRect; - XPThemeData theme(widget, p, QWindowsXPStylePrivate::WindowTheme, WP_MDICLOSEBUTTON, CBS_NORMAL); - - if (option->subControls & SC_MdiCloseButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDICLOSEBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiCloseButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiCloseButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } - } - if (option->subControls & SC_MdiNormalButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDIRESTOREBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiNormalButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiNormalButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } - } - if (option->subControls & QStyle::SC_MdiMinButton) { - buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget); - if (theme.isValid()) { - theme.partId = WP_MDIMINBUTTON; - theme.rect = buttonRect; - if (!(flags & State_Enabled)) - theme.stateId = CBS_INACTIVE; - else if (flags & State_Sunken && (option->activeSubControls & SC_MdiMinButton)) - theme.stateId = CBS_PUSHED; - else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiMinButton)) - theme.stateId = CBS_HOT; - else - theme.stateId = CBS_NORMAL; - d->drawBackground(theme); - } - } - } - break; -#endif //QT_NO_MDIAREA -#ifndef QT_NO_DIAL - case CC_Dial: - if (const QStyleOptionSlider *dial = qstyleoption_cast(option)) - QStyleHelper::drawDial(dial, p); - break; -#endif // QT_NO_DIAL - default: - QWindowsStyle::drawComplexControl(cc, option, p, widget); - break; - } -} - -static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0) -{ - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) - return pb->orientation; - return Qt::Horizontal; -} - -int QWindowsXPStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option, const QWidget *widget) -{ - switch (pm) { - case QStyle::PM_IndicatorWidth: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width(); - case QStyle::PM_IndicatorHeight: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height(); - case QStyle::PM_ExclusiveIndicatorWidth: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width(); - case QStyle::PM_ExclusiveIndicatorHeight: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height(); - case QStyle::PM_ProgressBarChunkWidth: - return progressBarOrientation(option) == Qt::Horizontal - ? XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNK).width() - : XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNKVERT).height(); - case QStyle::PM_SliderThickness: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, TKP_THUMB).height(); - case QStyle::PM_TitleBarHeight: - return widget && (widget->windowType() == Qt::Tool) - ? GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME) - : GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - case QStyle::PM_MdiSubWindowFrameWidth: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width(); - case QStyle::PM_DockWidgetFrameWidth: - return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width(); - default: - break; - } - return QWindowsXPStylePrivate::InvalidMetric; -} - -/*! \reimp */ -int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) - return QWindowsStyle::pixelMetric(pm, option, widget); - - int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); - if (res != QWindowsStylePrivate::InvalidMetric) - return qRound(qreal(res) * QWindowsStylePrivate::nativeMetricScaleFactor(widget)); - - res = 0; - switch (pm) { - case PM_MenuBarPanelWidth: - case PM_ButtonDefaultIndicator: - res = 0; - break; - - case PM_DefaultFrameWidth: - res = qobject_cast(widget) ? 2 : 1; - break; - case PM_MenuPanelWidth: - case PM_SpinBoxFrameWidth: - res = 1; - break; - - case PM_TabBarTabOverlap: - case PM_MenuHMargin: - case PM_MenuVMargin: - res = 2; - break; - - case PM_TabBarBaseOverlap: - if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { - switch (tab->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - res = 1; - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - res = 2; - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - res = 3; - break; - } - } - break; - - case PM_SplitterWidth: - res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); - break; - - case PM_MdiSubWindowMinimizedWidth: - res = 160; - break; - -#ifndef QT_NO_TOOLBAR - case PM_ToolBarHandleExtent: - res = int(QStyleHelper::dpiScaled(8.)); - break; - -#endif // QT_NO_TOOLBAR - case PM_DockWidgetSeparatorExtent: - case PM_DockWidgetTitleMargin: - res = int(QStyleHelper::dpiScaled(4.)); - break; - - case PM_ButtonShiftHorizontal: - case PM_ButtonShiftVertical: - res = qstyleoption_cast(option) ? 1 : 0; - break; - - default: - res = QWindowsStyle::pixelMetric(pm, option, widget); - } - - return res; -} - -/* - This function is used by subControlRect to check if a button - should be drawn for the given subControl given a set of window flags. -*/ -static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBar *tb){ - - bool isMinimized = tb->titleBarState & Qt::WindowMinimized; - bool isMaximized = tb->titleBarState & Qt::WindowMaximized; - const uint flags = tb->titleBarFlags; - bool retVal = false; - switch (sc) { - case QStyle::SC_TitleBarContextHelpButton: - if (flags & Qt::WindowContextHelpButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarMinButton: - if (!isMinimized && (flags & Qt::WindowMinimizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarNormalButton: - if (isMinimized && (flags & Qt::WindowMinimizeButtonHint)) - retVal = true; - else if (isMaximized && (flags & Qt::WindowMaximizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarMaxButton: - if (!isMaximized && (flags & Qt::WindowMaximizeButtonHint)) - retVal = true; - break; - case QStyle::SC_TitleBarShadeButton: - if (!isMinimized && flags & Qt::WindowShadeButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarUnshadeButton: - if (isMinimized && flags & Qt::WindowShadeButtonHint) - retVal = true; - break; - case QStyle::SC_TitleBarCloseButton: - if (flags & Qt::WindowSystemMenuHint) - retVal = true; - break; - case QStyle::SC_TitleBarSysMenu: - if (flags & Qt::WindowSystemMenuHint) - retVal = true; - break; - default : - retVal = true; - } - return retVal; -} - -/*! - \reimp -*/ -QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, - SubControl subControl, const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) - return QWindowsStyle::subControlRect(cc, option, subControl, widget); - - QRect rect; - - switch (cc) { - case CC_TitleBar: - if (const QStyleOptionTitleBar *tb = qstyleoption_cast(option)) { - if (!buttonVisible(subControl, tb)) - return rect; - const bool isToolTitle = false; - const int height = tb->rect.height(); - const int width = tb->rect.width(); - const int buttonMargin = int(QStyleHelper::dpiScaled(4)); - const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget); - int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) * factor) - - buttonMargin; - int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor) - - buttonMargin; - const int delta = buttonWidth + 2; - int controlTop = option->rect.bottom() - buttonHeight - 2; - const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); - const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; - const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0; - const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0; - const bool contextHint = (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) != 0; - const bool shadeHint = (tb->titleBarFlags & Qt::WindowShadeButtonHint) != 0; - bool isMinimized = tb->titleBarState & Qt::WindowMinimized; - bool isMaximized = tb->titleBarState & Qt::WindowMaximized; - int offset = 0; - - switch (subControl) { - case SC_TitleBarLabel: - rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height); - if (isToolTitle) { - if (sysmenuHint) { - rect.adjust(0, 0, -buttonWidth - 3, 0); - } - if (minimizeHint || maximizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - } else { - if (sysmenuHint) { - const int leftOffset = height - 8; - rect.adjust(leftOffset, 0, 0, 0); - } - if (minimizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (maximizeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (contextHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - if (shadeHint) - rect.adjust(0, 0, -buttonWidth - 2, 0); - } - break; - - case SC_TitleBarContextHelpButton: - if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) - offset += delta; - Q_FALLTHROUGH(); - case SC_TitleBarMinButton: - if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) - offset += delta; - else if (subControl == SC_TitleBarMinButton) - break; - Q_FALLTHROUGH(); - case SC_TitleBarNormalButton: - if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) - offset += delta; - else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) - offset += delta; - else if (subControl == SC_TitleBarNormalButton) - break; - Q_FALLTHROUGH(); - case SC_TitleBarMaxButton: - if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) - offset += delta; - else if (subControl == SC_TitleBarMaxButton) - break; - Q_FALLTHROUGH(); - case SC_TitleBarShadeButton: - if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) - offset += delta; - else if (subControl == SC_TitleBarShadeButton) - break; - Q_FALLTHROUGH(); - case SC_TitleBarUnshadeButton: - if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) - offset += delta; - else if (subControl == SC_TitleBarUnshadeButton) - break; - Q_FALLTHROUGH(); - case SC_TitleBarCloseButton: - if (tb->titleBarFlags & Qt::WindowSystemMenuHint) - offset += delta; - else if (subControl == SC_TitleBarCloseButton) - break; - - rect.setRect(width - offset - controlTop + 1, controlTop, - buttonWidth, buttonHeight); - break; - - case SC_TitleBarSysMenu: - { - const int controlTop = 6; - const int controlHeight = height - controlTop - 3; - const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent)); - if (tb->icon.isNull()) - iconSize = QSize(controlHeight, controlHeight); - int hPad = (controlHeight - iconSize.height())/2; - int vPad = (controlHeight - iconSize.width())/2; - rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height()); - } - break; - default: - break; - } - } - break; - - case CC_ComboBox: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(option)) { - int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height(); - int xpos = x; - xpos += wi - 1 - 16; - - switch (subControl) { - case SC_ComboBoxFrame: - rect = cmb->rect; - break; - - case SC_ComboBoxArrow: - rect = QRect(xpos, y+1, 16, he-2); - break; - - case SC_ComboBoxEditField: - rect = QRect(x+2, y+2, wi-3-16, he-4); - break; - - case SC_ComboBoxListBoxPopup: - rect = cmb->rect; - break; - - default: - break; - } - } - break; -#ifndef QT_NO_MDIAREA - case CC_MdiControls: - { - int numSubControls = 0; - if (option->subControls & SC_MdiCloseButton) - ++numSubControls; - if (option->subControls & SC_MdiMinButton) - ++numSubControls; - if (option->subControls & SC_MdiNormalButton) - ++numSubControls; - if (numSubControls == 0) - break; - - int buttonWidth = option->rect.width() / numSubControls; - int offset = 0; - switch (subControl) { - case SC_MdiCloseButton: - // Only one sub control, no offset needed. - if (numSubControls == 1) - break; - offset += buttonWidth; - Q_FALLTHROUGH(); - case SC_MdiNormalButton: - // No offset needed if - // 1) There's only one sub control - // 2) We have a close button and a normal button (offset already added in SC_MdiClose) - if (numSubControls == 1 || (numSubControls == 2 && !(option->subControls & SC_MdiMinButton))) - break; - if (option->subControls & SC_MdiNormalButton) - offset += buttonWidth; - break; - default: - break; - } - rect = QRect(offset, 0, buttonWidth, option->rect.height()); - break; - } -#endif // QT_NO_MDIAREA - - default: - rect = visualRect(option->direction, option->rect, - QWindowsStyle::subControlRect(cc, option, subControl, widget)); - break; - } - return visualRect(option->direction, option->rect, rect); -} - -/*! - \reimp -*/ -QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *option, - const QSize &contentsSize, const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) - return QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); - - QSize sz(contentsSize); - switch (ct) { - case CT_LineEdit: - case CT_ComboBox: - { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); - if (buttontheme.isValid()) { - const qreal factor = QWindowsXPStylePrivate::nativeMetricScaleFactor(widget); - const QMarginsF borderSize = buttontheme.margins() * factor; - if (!borderSize.isNull()) { - const qreal margin = qreal(2) * factor; - sz.rwidth() += qRound(borderSize.left() + borderSize.right() - margin); - sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin - + qreal(1) / factor - 1); - } - const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); - sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) - + textMargins, 23), 0); //arrow button - } - } - break; - case CT_SpinBox: - { - //Spinbox adds frame twice - sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget); - int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget); - sz -= QSize(2*border, 2*border); - } - break; - case CT_TabWidget: - sz += QSize(6, 6); - break; - case CT_Menu: - sz += QSize(1, 0); - break; -#ifndef QT_NO_MENUBAR - case CT_MenuBarItem: - if (!sz.isEmpty()) - sz += QSize(windowsItemHMargin * 5 + 1, 6); - break; -#endif - case CT_MenuItem: - if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) - { - if (menuitem->menuItemType != QStyleOptionMenuItem::Separator) { - sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); - sz.setHeight(sz.height() - 2); - return sz; - } - } - sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); - break; - - case CT_MdiControls: - if (const QStyleOptionComplex *styleOpt = qstyleoption_cast(option)) { - int width = 0; - if (styleOpt->subControls & SC_MdiMinButton) - width += 17 + 1; - if (styleOpt->subControls & SC_MdiNormalButton) - width += 17 + 1; - if (styleOpt->subControls & SC_MdiCloseButton) - width += 17 + 1; - sz = QSize(width, 19); - } else { - sz = QSize(54, 19); - } - break; - - default: - sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget); - break; - } - - return sz; -} - - -/*! \reimp */ -int QWindowsXPStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, - QStyleHintReturn *returnData) const -{ - QWindowsXPStylePrivate *d = const_cast(d_func()); - if (!QWindowsXPStylePrivate::useXP()) - return QWindowsStyle::styleHint(hint, option, widget, returnData); - - int res = 0; - switch (hint) { - - case SH_EtchDisabledText: - res = (qobject_cast(widget) != 0); - break; - - case SH_SpinControls_DisableOnBounds: - res = 0; - break; - - case SH_TitleBar_AutoRaise: - case SH_TitleBar_NoBorder: - res = 1; - break; - - case SH_GroupBox_TextLabelColor: - if (!widget || (widget && widget->isEnabled())) - res = d->groupBoxTextColor; - else - res = d->groupBoxTextColorDisabled; - break; - - case SH_Table_GridLineColor: - res = 0xC0C0C0; - break; - - case SH_WindowFrame_Mask: - { - res = 1; - QStyleHintReturnMask *mask = qstyleoption_cast(returnData); - const QStyleOptionTitleBar *titlebar = qstyleoption_cast(option); - if (mask && titlebar) { - // Note certain themes will not return the whole window frame but only the titlebar part when - // queried This function needs to return the entire window mask, hence we will only fetch the mask for the - // titlebar itself and add the remaining part of the window rect at the bottom. - int tbHeight = proxy()->pixelMetric(PM_TitleBarHeight, option, widget); - QRect titleBarRect = option->rect; - titleBarRect.setHeight(tbHeight); - XPThemeData themeData; - if (titlebar->titleBarState & Qt::WindowMinimized) { - themeData = XPThemeData(widget, 0, - QWindowsXPStylePrivate::WindowTheme, - WP_MINCAPTION, CS_ACTIVE, titleBarRect); - } else - themeData = XPThemeData(widget, 0, - QWindowsXPStylePrivate::WindowTheme, - WP_CAPTION, CS_ACTIVE, titleBarRect); - mask->region = d->region(themeData) + - QRect(0, tbHeight, option->rect.width(), option->rect.height() - tbHeight); - } - } - break; -#ifndef QT_NO_RUBBERBAND - case SH_RubberBand_Mask: - if (qstyleoption_cast(option)) { - res = 0; - break; - } -#endif // QT_NO_RUBBERBAND - - case SH_ItemView_DrawDelegateFrame: - res = 1; - break; - - default: - res =QWindowsStyle::styleHint(hint, option, widget, returnData); - } - - return res; -} - -/*! \reimp */ -QPalette QWindowsXPStyle::standardPalette() const -{ - if (QWindowsXPStylePrivate::useXP() && QApplicationPrivate::sys_pal) - return *QApplicationPrivate::sys_pal; - else - return QWindowsStyle::standardPalette(); -} - -/*! - \reimp -*/ -QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, - const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) - return QWindowsStyle::standardPixmap(standardPixmap, option, widget); - - switch(standardPixmap) { - case SP_TitleBarMaxButton: - case SP_TitleBarCloseButton: - if (qstyleoption_cast(option)) - { - if (widget && widget->isWindow()) { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); - if (theme.isValid()) { - const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); - } - } - } - break; - default: - break; - } - return QWindowsStyle::standardPixmap(standardPixmap, option, widget); -} - -/*! - \reimp -*/ -QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, - const QStyleOption *option, - const QWidget *widget) const -{ - if (!QWindowsXPStylePrivate::useXP()) { - return QWindowsStyle::standardIcon(standardIcon, option, widget); - } - - QWindowsXPStylePrivate *d = const_cast(d_func()); - switch(standardIcon) { - case SP_TitleBarMaxButton: - if (qstyleoption_cast(option)) - { - if (d->dockFloat.isNull()) { - XPThemeData themeSize(0, 0, QWindowsXPStylePrivate::WindowTheme, - WP_SMALLCLOSEBUTTON, CBS_NORMAL); - XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, - WP_MAXBUTTON, MAXBS_NORMAL); - if (theme.isValid()) { - const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - QPixmap pm(size); - pm.fill(Qt::transparent); - QPainter p(&pm); - theme.painter = &p; - theme.rect = QRect(QPoint(0, 0), size); - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal - pm.fill(Qt::transparent); - theme.stateId = MAXBS_PUSHED; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed - pm.fill(Qt::transparent); - theme.stateId = MAXBS_HOT; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover - pm.fill(Qt::transparent); - theme.stateId = MAXBS_INACTIVE; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled - } - } - if (widget && widget->isWindow()) - return d->dockFloat; - - } - break; - case SP_TitleBarCloseButton: - if (qstyleoption_cast(option)) - { - if (d->dockClose.isNull()) { - XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, - WP_SMALLCLOSEBUTTON, CBS_NORMAL); - if (theme.isValid()) { - const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - QPixmap pm(size); - pm.fill(Qt::transparent); - QPainter p(&pm); - theme.painter = &p; - theme.partId = WP_CLOSEBUTTON; // #### - theme.rect = QRect(QPoint(0, 0), size); - d->drawBackground(theme); - d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal - pm.fill(Qt::transparent); - theme.stateId = CBS_PUSHED; - d->drawBackground(theme); - d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed - pm.fill(Qt::transparent); - theme.stateId = CBS_HOT; - d->drawBackground(theme); - d->dockClose.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover - pm.fill(Qt::transparent); - theme.stateId = CBS_INACTIVE; - d->drawBackground(theme); - d->dockClose.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled - } - } - if (widget && widget->isWindow()) - return d->dockClose; - } - break; - case SP_TitleBarNormalButton: - if (qstyleoption_cast(option)) - { - if (d->dockFloat.isNull()) { - XPThemeData themeSize(0, 0, QWindowsXPStylePrivate::WindowTheme, - WP_SMALLCLOSEBUTTON, CBS_NORMAL); - XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, - WP_RESTOREBUTTON, RBS_NORMAL); - if (theme.isValid()) { - const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize(); - QPixmap pm(size); - pm.fill(Qt::transparent); - QPainter p(&pm); - theme.painter = &p; - theme.rect = QRect(QPoint(0, 0), size); - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal - pm.fill(Qt::transparent); - theme.stateId = RBS_PUSHED; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::On); // Pressed - pm.fill(Qt::transparent); - theme.stateId = RBS_HOT; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Active, QIcon::Off); // Hover - pm.fill(Qt::transparent); - theme.stateId = RBS_INACTIVE; - d->drawBackground(theme); - d->dockFloat.addPixmap(pm, QIcon::Disabled, QIcon::Off); // Disabled - } - } - if (widget && widget->isWindow()) - return d->dockFloat; - - } - break; - default: - break; - } - - return QWindowsStyle::standardIcon(standardIcon, option, widget); -} - -/*! - \internal - - Constructs a QWindowsXPStyle object. -*/ -QWindowsXPStyle::QWindowsXPStyle(QWindowsXPStylePrivate &dd) : QWindowsStyle(dd) -{ -} - - -// Debugging code ---------------------------------------------------------------------[ START ]--- -// The code for this point on is not compiled by default, but only used as assisting -// debugging code when you uncomment the DEBUG_XP_STYLE define at the top of the file. - -#ifdef DEBUG_XP_STYLE -// The schema file expects these to be defined by the user. -#define TMT_ENUMDEF 8 -#define TMT_ENUMVAL TEXT('A') -#define TMT_ENUM TEXT('B') -#define SCHEMA_STRINGS // For 2nd pass on schema file -QT_BEGIN_INCLUDE_NAMESPACE -#include -QT_END_INCLUDE_NAMESPACE - -// A property's value, type and name combo -struct PropPair { - int propValue; - int propType; - LPCWSTR propName; -}; - -// Operator for sorting of PropPairs -bool operator<(PropPair a, PropPair b) { - return wcscmp(a.propName, b.propName) < 0; -} - -// Our list of all possible properties -static QList all_props; - - -/*! \internal - Dumps a portion of the full native DIB section double buffer. - The DIB section double buffer is only used when doing special - transformations to the theme part, or when the real double - buffer in the paintengine does not have an HDC we may use - directly. - Since we cannot rely on the pixel data we get from Microsoft - when drawing into the DIB section, we use this function to - see the actual data we got, and can determin the appropriate - action. -*/ -void QWindowsXPStylePrivate::dumpNativeDIB(int w, int h) -{ - if (w && h) { - static int pCount = 0; - DWORD *bufPix = (DWORD*)bufferPixels; - - char *bufferDump = new char[bufferH * bufferW * 16]; - char *bufferPos = bufferDump; - - memset(bufferDump, 0, sizeof(bufferDump)); - bufferPos += sprintf(bufferPos, "const int pixelBufferW%d = %d;\n", pCount, w); - bufferPos += sprintf(bufferPos, "const int pixelBufferH%d = %d;\n", pCount, h); - bufferPos += sprintf(bufferPos, "const unsigned DWORD pixelBuffer%d[] = {", pCount); - for (int iy = 0; iy < h; ++iy) { - bufferPos += sprintf(bufferPos, "\n "); - bufPix = (DWORD*)(bufferPixels + (iy * bufferW * 4)); - for (int ix = 0; ix < w; ++ix) { - bufferPos += sprintf(bufferPos, "0x%08x, ", *bufPix); - ++bufPix; - } - } - bufferPos += sprintf(bufferPos, "\n};\n\n"); - printf(bufferDump); - - delete[] bufferDump; - ++pCount; - } -} - -/*! \internal - Shows the value of a given property for a part. -*/ -static void showProperty(XPThemeData &themeData, const PropPair &prop) -{ - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); - const char *originStr; - switch(origin) { - case PO_STATE: - originStr = "State "; - break; - case PO_PART: - originStr = "Part "; - break; - case PO_CLASS: - originStr = "Class "; - break; - case PO_GLOBAL: - originStr = "Globl "; - break; - case PO_NOTFOUND: - default: - originStr = "Unkwn "; - break; - } - - switch(prop.propType) { - case TMT_STRING: - { - wchar_t buffer[512]; - GetThemeString(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); - printf(" (%sString) %-20S: %S\n", originStr, prop.propName, buffer); - } - break; - case TMT_ENUM: - { - int result = -1; - GetThemeEnumValue(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sEnum) %-20S: %d\n", originStr, prop.propName, result); - } - break; - case TMT_INT: - { - int result = -1; - GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sint) %-20S: %d\n", originStr, prop.propName, result); - } - break; - case TMT_BOOL: - { - BOOL result = false; - GetThemeBool(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sbool) %-20S: %d\n", originStr, prop.propName, result); - } - break; - case TMT_COLOR: - { - COLORREF result = 0; - GetThemeColor(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%scolor) %-20S: 0x%08X\n", originStr, prop.propName, result); - } - break; - case TMT_MARGINS: - { - MARGINS result; - memset(&result, 0, sizeof(result)); - GetThemeMargins(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, 0, &result); - printf(" (%smargins) %-20S: (%d, %d, %d, %d)\n", originStr, - prop.propName, result.cxLeftWidth, result.cyTopHeight, result.cxRightWidth, result.cyBottomHeight); - } - break; - case TMT_FILENAME: - { - wchar_t buffer[512]; - GetThemeFilename(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, buffer, 512); - printf(" (%sfilename)%-20S: %S\n", originStr, prop.propName, buffer); - } - break; - case TMT_SIZE: - { - SIZE result1; - SIZE result2; - SIZE result3; - memset(&result1, 0, sizeof(result1)); - memset(&result2, 0, sizeof(result2)); - memset(&result3, 0, sizeof(result3)); - GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_MIN, &result1); - GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_TRUE, &result2); - GetThemePartSize(themeData.handle(), 0, themeData.partId, themeData.stateId, 0, TS_DRAW, &result3); - printf(" (%ssize) %-20S: Min (%d, %d), True(%d, %d), Draw(%d, %d)\n", originStr, prop.propName, - result1.cx, result1.cy, result2.cx, result2.cy, result3.cx, result3.cy); - } - break; - case TMT_POSITION: - { - POINT result; - memset(&result, 0, sizeof(result)); - GetThemePosition(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sPosition)%-20S: (%d, %d)\n", originStr, prop.propName, result.x, result.y); - } - break; - case TMT_RECT: - { - RECT result; - memset(&result, 0, sizeof(result)); - GetThemeRect(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sRect) %-20S: (%d, %d, %d, %d)\n", originStr, prop.propName, result.left, result.top, result.right, result.bottom); - } - break; - case TMT_FONT: - { - LOGFONT result; - memset(&result, 0, sizeof(result)); - GetThemeFont(themeData.handle(), 0, themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sFont) %-20S: %S height(%d) width(%d) weight(%d)\n", originStr, prop.propName, - result.lfFaceName, result.lfHeight, result.lfWidth, result.lfWeight); - } - break; - case TMT_INTLIST: - { - INTLIST result; - memset(&result, 0, sizeof(result)); - GetThemeIntList(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &result); - printf(" (%sInt list)%-20S: { ", originStr, prop.propName); - for (int i = 0; i < result.iValueCount; ++i) - printf("%d ", result.iValues[i]); - printf("}\n"); - } - break; - default: - printf(" %s%S : Unknown property type (%d)!\n", originStr, prop.propName, prop.propType); - } -} - -/*! \internal - Dump all valid properties for a part. - If it's the first time this function is called, then the name, - enum value and documentation of all properties are shown, as - well as all global properties. -*/ -void QWindowsXPStylePrivate::showProperties(XPThemeData &themeData) -{ - if (!all_props.count()) { - const TMSCHEMAINFO *infoTable = GetSchemaInfo(); - for (int i = 0; i < infoTable->iPropCount; ++i) { - int propType = infoTable->pPropTable[i].bPrimVal; - int propValue = infoTable->pPropTable[i].sEnumVal; - LPCWSTR propName = infoTable->pPropTable[i].pszName; - - switch(propType) { - case TMT_ENUMDEF: - case TMT_ENUMVAL: - continue; - default: - if (propType != propValue) { - PropPair prop; - prop.propValue = propValue; - prop.propName = propName; - prop.propType = propType; - all_props.append(prop); - } - } - } - std::sort(all_props.begin(), all_props.end()); - - {// List all properties - printf("part properties count = %d:\n", all_props.count()); - printf(" Enum Property Name Description\n"); - printf("-----------------------------------------------------------\n"); - wchar_t themeName[256]; - pGetCurrentThemeName(themeName, 256, 0, 0, 0, 0); - for (int j = 0; j < all_props.count(); ++j) { - PropPair prop = all_props.at(j); - wchar_t buf[500]; - GetThemeDocumentationProperty(themeName, prop.propName, buf, 500); - printf("%3d: (%4d) %-20S %S\n", j, prop.propValue, prop.propName, buf); - } - } - - {// Show Global values - printf("Global Properties:\n"); - for (int j = 0; j < all_props.count(); ++j) { - PropPair prop = all_props.at(j); - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); - if (origin == PO_GLOBAL) { - showProperty(themeData, prop); - } - } - } - } - - for (int j = 0; j < all_props.count(); ++j) { - PropPair prop = all_props.at(j); - PROPERTYORIGIN origin = PO_NOTFOUND; - GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, prop.propValue, &origin); - if (origin != PO_NOTFOUND) - { - showProperty(themeData, prop); - } - } -} -#endif -// Debugging code -----------------------------------------------------------------------[ END ]--- - - -QT_END_NAMESPACE - -#endif //QT_NO_WINDOWSXP diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/widgets/styles/qwindowsxpstyle_p.h deleted file mode 100644 index 83c96abb7d..0000000000 --- a/src/widgets/styles/qwindowsxpstyle_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSXPSTYLE_P_H -#define QWINDOWSXPSTYLE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - - -#if QT_CONFIG(style_windowsvista) - -class QWindowsXPStylePrivate; -class QWindowsXPStyle : public QWindowsStyle -{ - Q_OBJECT -public: - QWindowsXPStyle(); - QWindowsXPStyle(QWindowsXPStylePrivate &dd); - ~QWindowsXPStyle(); - - void unpolish(QApplication*); - void polish(QApplication*); - void polish(QWidget*); - void polish(QPalette&); - void unpolish(QWidget*); - - void drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p, - const QWidget *widget = 0) const; - void drawControl(ControlElement element, const QStyleOption *option, QPainter *p, - const QWidget *wwidget = 0) const; - QRect subElementRect(SubElement r, const QStyleOption *option, const QWidget *widget = 0) const; - QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, - const QWidget *widget = 0) const; - void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, QPainter *p, - const QWidget *widget = 0) const; - QSize sizeFromContents(ContentsType ct, const QStyleOption *option, const QSize &contentsSize, - const QWidget *widget = 0) const; - int pixelMetric(PixelMetric pm, const QStyleOption *option = 0, - const QWidget *widget = 0) const; - int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, - QStyleHintReturn *returnData = 0) const; - - QPalette standardPalette() const; - QPixmap standardPixmap(StandardPixmap standardIcon, const QStyleOption *option, - const QWidget *widget = 0) const; - QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0, - const QWidget *widget = 0) const; - -private: - Q_DISABLE_COPY(QWindowsXPStyle) - Q_DECLARE_PRIVATE(QWindowsXPStyle) - friend class QStyleFactory; -}; - -#endif // style_windowsvista - -QT_END_NAMESPACE - -#endif // QWINDOWSXPSTYLE_P_H diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h deleted file mode 100644 index 8cac01950c..0000000000 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ /dev/null @@ -1,345 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSXPSTYLE_P_P_H -#define QWINDOWSXPSTYLE_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include "qwindowsxpstyle_p.h" -#include "qwindowsstyle_p_p.h" -#include -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -// TMT_TEXTSHADOWCOLOR is wrongly defined in mingw -#if TMT_TEXTSHADOWCOLOR != 3818 -#undef TMT_TEXTSHADOWCOLOR -#define TMT_TEXTSHADOWCOLOR 3818 -#endif -#ifndef TST_NONE -# define TST_NONE 0 -#endif - -// These defines are missing from the tmschema, but still exist as -// states for their parts -#ifndef MINBS_INACTIVE -#define MINBS_INACTIVE 5 -#endif -#ifndef MAXBS_INACTIVE -#define MAXBS_INACTIVE 5 -#endif -#ifndef RBS_INACTIVE -#define RBS_INACTIVE 5 -#endif -#ifndef HBS_INACTIVE -#define HBS_INACTIVE 5 -#endif -#ifndef CBS_INACTIVE -#define CBS_INACTIVE 5 -#endif - -// Uncomment define below to build debug assisting code, and output -// #define DEBUG_XP_STYLE - -#if QT_CONFIG(style_windowsvista) - -// Declarations ----------------------------------------------------------------------------------- -class XPThemeData -{ -public: - explicit XPThemeData(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, - int part = 0, int state = 0, const QRect &r = QRect()) - : widget(w), painter(p), theme(themeIn), htheme(0), partId(part), stateId(state), - mirrorHorizontally(false), mirrorVertically(false), noBorder(false), - noContent(false), rotate(0), rect(r) - {} - - HRGN mask(QWidget *widget); - HTHEME handle(); - - static RECT toRECT(const QRect &qr); - bool isValid(); - - QSizeF size(); - QMarginsF margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); - QMarginsF margins(int propId = TMT_CONTENTMARGINS); - - static QSizeF themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); - static QMarginsF themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, - int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); - static QMarginsF themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, - int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); - - const QWidget *widget; - QPainter *painter; - - int theme; - HTHEME htheme; - int partId; - int stateId; - - uint mirrorHorizontally : 1; - uint mirrorVertically : 1; - uint noBorder : 1; - uint noContent : 1; - uint rotate; - QRect rect; -}; - -struct ThemeMapKey { - int theme; - int partId; - int stateId; - bool noBorder; - bool noContent; - - ThemeMapKey() : partId(-1), stateId(-1) {} - ThemeMapKey(const XPThemeData &data) - : theme(data.theme), partId(data.partId), stateId(data.stateId), - noBorder(data.noBorder), noContent(data.noContent) {} - -}; - -inline uint qHash(const ThemeMapKey &key) -{ return key.theme ^ key.partId ^ key.stateId; } - -inline bool operator==(const ThemeMapKey &k1, const ThemeMapKey &k2) -{ - return k1.theme == k2.theme - && k1.partId == k2.partId - && k1.stateId == k2.stateId; -} - -enum AlphaChannelType { - UnknownAlpha = -1, // Alpha of part & state not yet known - NoAlpha, // Totally opaque, no need to touch alpha (RGB) - MaskAlpha, // Alpha channel must be fixed (ARGB) - RealAlpha // Proper alpha values from Windows (ARGB_Premultiplied) -}; - -struct ThemeMapData { - AlphaChannelType alphaType; // Which type of alpha on part & state - - bool dataValid : 1; // Only used to detect if hash value is ok - bool partIsTransparent : 1; - bool hasAlphaChannel : 1; // True = part & state has real Alpha - bool wasAlphaSwapped : 1; // True = alpha channel needs to be swapped - bool hadInvalidAlpha : 1; // True = alpha channel contained invalid alpha values - - ThemeMapData() : dataValid(false), partIsTransparent(false), - hasAlphaChannel(false), wasAlphaSwapped(false), hadInvalidAlpha(false) {} -}; - -class QWindowsXPStylePrivate : public QWindowsStylePrivate -{ - Q_DECLARE_PUBLIC(QWindowsXPStyle) -public: - enum Theme { - ButtonTheme, - ComboboxTheme, - EditTheme, - HeaderTheme, - ListViewTheme, - MenuTheme, - ProgressTheme, - RebarTheme, - ScrollBarTheme, - SpinTheme, - TabTheme, - TaskDialogTheme, - ToolBarTheme, - ToolTipTheme, - TrackBarTheme, - XpTreeViewTheme, // '+'/'-' shape treeview indicators (XP) - WindowTheme, - StatusTheme, - VistaTreeViewTheme, // arrow shape treeview indicators (Vista) obtained from "explorer" theme. - NThemes - }; - - QWindowsXPStylePrivate() - : QWindowsStylePrivate(), hasInitColors(false), bufferDC(0), bufferBitmap(0), nullBitmap(0), - bufferPixels(0), bufferW(0), bufferH(0) - { init(); } - - ~QWindowsXPStylePrivate() - { cleanup(); } - - static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); - static int fixedPixelMetric(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); - - static HWND winId(const QWidget *widget); - - void init(bool force = false); - void cleanup(bool force = false); - void cleanupHandleMap(); - const QPixmap *tabBody(QWidget *widget); - - HBITMAP buffer(int w = 0, int h = 0); - HDC bufferHDC() - { return bufferDC;} - - static bool useXP(bool update = false); - static QRect scrollBarGripperBounds(QStyle::State flags, const QWidget *widget, XPThemeData *theme); - - bool isTransparent(XPThemeData &themeData); - QRegion region(XPThemeData &themeData); - - void setTransparency(QWidget *widget, XPThemeData &themeData); - bool drawBackground(XPThemeData &themeData); - bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio); - bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio); - - bool hasAlphaChannel(const QRect &rect); - bool fixAlphaChannel(const QRect &rect); - bool swapAlphaChannel(const QRect &rect, bool allPixels = false); - - QRgb groupBoxTextColor; - QRgb groupBoxTextColorDisabled; - QRgb sliderTickColor; - bool hasInitColors; - - static HTHEME createTheme(int theme, HWND hwnd); - static QString themeName(int theme); - static inline bool hasTheme(int theme) { return theme >= 0 && theme < NThemes && m_themes[theme]; } - static bool isItemViewDelegateLineEdit(const QWidget *widget); - static bool isLineEditBaseColorSet(const QStyleOption *option, const QWidget *widget); - - QIcon dockFloat, dockClose; - -private: -#ifdef DEBUG_XP_STYLE - void dumpNativeDIB(int w, int h); - void showProperties(XPThemeData &themeData); -#endif - - static bool initVistaTreeViewTheming(); - static void cleanupVistaTreeViewTheming(); - - static QBasicAtomicInt ref; - static bool use_xp; - static QPixmap *tabbody; - - QHash alphaCache; - HDC bufferDC; - HBITMAP bufferBitmap; - HBITMAP nullBitmap; - uchar *bufferPixels; - int bufferW, bufferH; - - static HWND m_vistaTreeViewHelper; - static HTHEME m_themes[NThemes]; -}; - -inline QSizeF XPThemeData::size() -{ - QSizeF result(0, 0); - if (isValid()) { - SIZE size; - if (SUCCEEDED(GetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) - result = QSize(size.cx, size.cy); - } - return result; -} - -inline QMarginsF XPThemeData::margins(const QRect &qRect, int propId) -{ - QMarginsF result(0, 0, 0 ,0); - if (isValid()) { - MARGINS margins; - RECT rect = XPThemeData::toRECT(qRect); - if (SUCCEEDED(GetThemeMargins(handle(), 0, partId, stateId, propId, &rect, &margins))) - result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); - } - return result; -} - -inline QMarginsF XPThemeData::margins(int propId) -{ - QMarginsF result(0, 0, 0 ,0); - if (isValid()) { - MARGINS margins; - if (SUCCEEDED(GetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) - result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); - } - return result; -} - -inline QSizeF XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) -{ - XPThemeData theme(w, p, themeIn, part, state); - return theme.size(); -} - -inline QMarginsF XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, - int part, int state, int propId) -{ - XPThemeData theme(w, p, themeIn, part, state); - return theme.margins(rect, propId); -} - -inline QMarginsF XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, - int part, int state, int propId) -{ - XPThemeData theme(w, p, themeIn, part, state); - return theme.margins(propId); -} - -#endif // style_windows - -QT_END_NAMESPACE - -#endif //QWINDOWSXPSTYLE_P_P_H diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri index 4c13311ebc..0c0f8b7bc7 100644 --- a/src/widgets/styles/styles.pri +++ b/src/widgets/styles/styles.pri @@ -37,22 +37,6 @@ RESOURCES += styles/qstyle.qrc include($$OUT_PWD/qtwidgets-config.pri) -qtConfig(style-mac) { - HEADERS += \ - styles/qmacstyle_mac_p.h \ - styles/qmacstyle_mac_p_p.h - OBJECTIVE_SOURCES += styles/qmacstyle_mac.mm - LIBS_PRIVATE += -framework Carbon -} - -qtConfig(style-windowsvista) { - HEADERS += styles/qwindowsvistastyle_p.h styles/qwindowsvistastyle_p_p.h - SOURCES += styles/qwindowsvistastyle.cpp - - HEADERS += styles/qwindowsxpstyle_p.h styles/qwindowsxpstyle_p_p.h - SOURCES += styles/qwindowsxpstyle.cpp -} - qtConfig(style-windows) { HEADERS += styles/qwindowsstyle_p.h styles/qwindowsstyle_p_p.h SOURCES += styles/qwindowsstyle.cpp @@ -62,8 +46,3 @@ qtConfig(style-fusion) { HEADERS += styles/qfusionstyle_p.h styles/qfusionstyle_p_p.h SOURCES += styles/qfusionstyle.cpp } - -qtConfig(style-android) { - HEADERS += styles/qandroidstyle_p.h - SOURCES += styles/qandroidstyle.cpp -} diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 6c36359f81..2340f06954 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -212,7 +212,7 @@ private: bool fast; }; -class Q_AUTOTEST_EXPORT QComboBoxPrivateContainer : public QFrame +class Q_WIDGETS_EXPORT QComboBoxPrivateContainer : public QFrame { Q_OBJECT diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index 7c653a95e9..7b14b636d1 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -81,7 +81,7 @@ private: QPixmap m_pixmap; }; -class QTabBarPrivate : public QWidgetPrivate +class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QTabBar) public: -- cgit v1.2.3