diff options
Diffstat (limited to 'src/widgets/styles')
-rw-r--r-- | src/widgets/styles/qandroidstyle.cpp | 386 | ||||
-rw-r--r-- | src/widgets/styles/qandroidstyle_p.h | 9 | ||||
-rw-r--r-- | src/widgets/styles/qcommonstyle.cpp | 194 | ||||
-rw-r--r-- | src/widgets/styles/qfusionstyle.cpp | 148 | ||||
-rw-r--r-- | src/widgets/styles/qgtkstyle.cpp | 2 | ||||
-rw-r--r-- | src/widgets/styles/qmacstyle_mac.mm | 83 | ||||
-rw-r--r-- | src/widgets/styles/qstyle.cpp | 10 | ||||
-rw-r--r-- | src/widgets/styles/qstyle.h | 6 | ||||
-rw-r--r-- | src/widgets/styles/qstyleanimation.cpp | 25 | ||||
-rw-r--r-- | src/widgets/styles/qstyleanimation_p.h | 15 | ||||
-rw-r--r-- | src/widgets/styles/qstyleoption.cpp | 2 | ||||
-rw-r--r-- | src/widgets/styles/qstyleoption.h | 24 | ||||
-rw-r--r-- | src/widgets/styles/qstylesheetstyle.cpp | 22 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle.cpp | 245 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle_p_p.h | 11 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsvistastyle.cpp | 279 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsvistastyle_p_p.h | 2 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle.cpp | 422 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle_p_p.h | 129 |
19 files changed, 1210 insertions, 804 deletions
diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/widgets/styles/qandroidstyle.cpp index ceb95aa125..9f241c42e1 100644 --- a/src/widgets/styles/qandroidstyle.cpp +++ b/src/widgets/styles/qandroidstyle.cpp @@ -118,6 +118,7 @@ QAndroidStyle::QAndroidStyle() : QFusionStyle() { QPixmapCache::clear(); + checkBoxControl = NULL; QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH"))); const QLatin1Char slashChar('/'); if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar)) @@ -127,8 +128,7 @@ QAndroidStyle::QAndroidStyle() if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar)) androidTheme += slashChar; - if (stylePath.isEmpty()) - { + if (stylePath.isEmpty()) { stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/") + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar; } @@ -143,7 +143,7 @@ QAndroidStyle::QAndroidStyle() QJsonParseError error; QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error); - if (document.isNull()) { + if (document.isNull()) { qCritical() << error.errorString(); return; } @@ -155,8 +155,8 @@ QAndroidStyle::QAndroidStyle() QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - QHash<int, QPalette> * palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes")); - QHash<int, QFont> * fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts")); + QHash<int, QPalette> *palettes = reinterpret_cast<QHash<int, QPalette> *>(nativeInterface->nativeResourceForIntegration("AndroidStylePalettes")); + QHash<int, QFont> *fonts = reinterpret_cast<QHash<int, QFont> *>(nativeInterface->nativeResourceForIntegration("AndroidStyleFonts")); palettes->clear(); fonts->clear(); QJsonObject object = document.object(); @@ -214,7 +214,7 @@ QAndroidStyle::QAndroidStyle() } if (!qtClassName.isEmpty()) QApplication::setFont(font, qtClassName.toUtf8()); - if (ft>-1) + if (ft > -1) fonts->insert(ft, font); // Extract font information } @@ -256,6 +256,9 @@ QAndroidStyle::QAndroidStyle() 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); @@ -516,16 +519,31 @@ void QAndroidStyle::drawPrimitive(PrimitiveElement pe, ? m_androidControlsHash.find(itemType) : m_androidControlsHash.end(); if (it != m_androidControlsHash.end()) { - if (itemType != QC_EditText) + if (itemType != QC_EditText) { it.value()->drawControl(opt, p, w); - else { + } else { QStyleOption copy(*opt); copy.state &= ~QStyle::State_Sunken; it.value()->drawControl(©, p, w); } - } - else + } else if (pe == PE_FrameGroupBox) { + if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { + const QStyleOptionFrameV2 *frame2 = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt); + if (frame2 && (frame2->features & QStyleOptionFrameV2::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); + } } @@ -575,6 +593,36 @@ void QAndroidStyle::drawControl(QStyle::ControlElement element, default: break; } + } else if (element == CE_ItemViewItem) { + const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt); + if (vopt && vopt->features & QStyleOptionViewItem::HasCheckIndicator) { + p->save(); + p->setClipRect(opt->rect); + + QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, w); + + // draw the background + proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, w); + + // draw the check mark + QStyleOptionViewItem option(*vopt); + option.rect = checkRect; + option.state = option.state & ~QStyle::State_HasFocus; + + switch (vopt->checkState) { + case Qt::Unchecked: + option.state |= QStyle::State_Off; + break; + default: + option.state |= QStyle::State_On; + break; + } + QPixmap pixmap = checkBoxControl->imgCheckBox(&option); + p->drawPixmap(checkRect, pixmap); + p->restore(); + } else { + QFusionStyle::drawControl(element, opt, p, w); + } } else { QFusionStyle::drawControl(element, opt, p, w); } @@ -584,6 +632,8 @@ QRect QAndroidStyle::subElementRect(SubElement subElement, const QStyleOption *option, const QWidget *widget) const { + if (subElement == SE_LineEditContents) // fix spinbox display problem + return QFusionStyle::subElementRect(subElement, option, widget); const ItemType itemType = qtControl(subElement); AndroidControlsHash::const_iterator it = itemType != QC_UnknownType ? m_androidControlsHash.find(itemType) @@ -602,10 +652,74 @@ void QAndroidStyle::drawComplexControl(ComplexControl cc, AndroidControlsHash::const_iterator it = itemType != QC_UnknownType ? m_androidControlsHash.find(itemType) : m_androidControlsHash.end(); - if (it != m_androidControlsHash.end()) + if (it != m_androidControlsHash.end()) { it.value()->drawControl(opt, p, widget); - else - QFusionStyle::drawComplexControl(cc, opt, p, widget); + return; + } + if (cc == CC_GroupBox) { + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(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) { + QStyleOptionFrameV2 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, @@ -649,6 +763,52 @@ QRect QAndroidStyle::subControlRect(ComplexControl cc, : 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<const QStyleOptionGroupBox *>(opt)) { + QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); + QSize checkBoxSize = checkBoxControl->sizeCheckBox(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); } @@ -664,6 +824,10 @@ int QAndroidStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, case PM_SpinBoxFrameWidth: case PM_ScrollBarExtent: return 0; + case PM_IndicatorWidth: + return checkBoxControl->sizeCheckBox(option).width(); + case PM_IndicatorHeight: + return checkBoxControl->sizeCheckBox(option).height(); default: return QFusionStyle::pixelMetric(metric, option, widget); } @@ -676,12 +840,61 @@ QSize QAndroidStyle::sizeFromContents(ContentsType ct, const QWidget *w) const { QSize sz = QFusionStyle::sizeFromContents(ct, opt, contentsSize, w); + if (ct == CT_HeaderSection) { + if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { + bool nullIcon = hdr->icon.isNull(); + int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, w); + int iconSize = nullIcon ? 0 : checkBoxControl->sizeCheckBox(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<const QStyleOptionGroupBox *>(opt)) { + QSize textSize = opt->fontMetrics.boundingRect(groupBox->text).size() + QSize(2, 2); + QSize checkBoxSize = checkBoxControl->sizeCheckBox(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; } @@ -712,7 +925,7 @@ int QAndroidStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, return RSIP_OnMouseClick; default: - return QFusionStyle::styleHint(hint,option, widget, returnData); + return QFusionStyle::styleHint(hint, option, widget, returnData); } } @@ -761,6 +974,13 @@ QSize QAndroidStyle::AndroidDrawable::size() const return QSize(); } +QPixmap QAndroidStyle::AndroidDrawable::img() const +{ + if (type() == Image || type() == NinePatch) + return static_cast<const QAndroidStyle::AndroidImageDrawable *>(this)->img(); + + return QPixmap(); +} QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidDrawable::fromMap(const QVariantMap &drawable, ItemType itemType) @@ -828,6 +1048,18 @@ void QAndroidStyle::AndroidImageDrawable::draw(QPainter *painter, const QStyleOp painter->drawPixmap(opt->rect.x(), (opt->rect.height() - pm.height()) / 2, pm); } +QPixmap QAndroidStyle::AndroidImageDrawable::img() 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); + } + return pm; +} QSize QAndroidStyle::AndroidImageDrawable::size() const { @@ -886,7 +1118,7 @@ void QAndroidStyle::Android9PatchDrawable::extractIntArray(const QVariantList &v } -void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyleOption *opt) const +void QAndroidStyle::Android9PatchDrawable::draw(QPainter *painter, const QStyleOption *opt) const { if (m_hashKey.isEmpty()) m_hashKey = QFileInfo(m_filePath).fileName(); @@ -897,7 +1129,7 @@ void QAndroidStyle::Android9PatchDrawable::draw(QPainter * painter, const QStyle QPixmapCache::insert(m_hashKey, pixmap); } - const QRect &bounds=opt->rect; + const QRect &bounds = opt->rect; // shamelessly stolen from Android's sources (NinepatchImpl.cpp) and adapted for Qt const int pixmapWidth = pixmap.width(); @@ -1052,11 +1284,11 @@ QAndroidStyle::AndroidGradientDrawable::AndroidGradientDrawable(const QVariantMa QVariantList colors = drawable.value(QLatin1String("colors")).toList(); QVariantList positions = drawable.value(QLatin1String("positions")).toList(); - int min=colors.size() < positions.size() ? colors.size() : positions.size(); + 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(); + 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 @@ -1089,43 +1321,43 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + m_gradient.setStart(0, 0); + m_gradient.setFinalStop(width, height); break; } @@ -1140,7 +1372,7 @@ void QAndroidStyle::AndroidGradientDrawable::draw(QPainter *painter, const QStyl QSize QAndroidStyle::AndroidGradientDrawable::size() const { - return QSize(m_radius*2, m_radius*2); + return QSize(m_radius * 2, m_radius * 2); } QAndroidStyle::AndroidClipDrawable::AndroidClipDrawable(const QVariantMap &drawable, @@ -1172,9 +1404,9 @@ void QAndroidStyle::AndroidClipDrawable::draw(QPainter *painter, const QStyleOpt { QStyleOption copy(*opt); if (m_orientation == Qt::Horizontal) - copy.rect.setWidth(copy.rect.width()*m_factor); + copy.rect.setWidth(copy.rect.width() * m_factor); else - copy.rect.setHeight(copy.rect.height()*m_factor); + copy.rect.setHeight(copy.rect.height() * m_factor); m_drawable->draw(painter, ©); } @@ -1212,12 +1444,28 @@ QAndroidStyle::AndroidDrawableType QAndroidStyle::AndroidStateDrawable::type() c void QAndroidStyle::AndroidStateDrawable::draw(QPainter *painter, const QStyleOption *opt) const { - const AndroidDrawable *drawable=bestAndroidStateMatch(opt); + const AndroidDrawable *drawable = bestAndroidStateMatch(opt); if (drawable) drawable->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; +} +QPixmap QAndroidStyle::AndroidStateDrawable::img(const QStyleOption *opt) const +{ + QPixmap pm; + const AndroidDrawable *drawable = bestAndroidStateMatch(opt); + if (drawable) + pm = drawable->img(); + return pm; +} -const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const +const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::bestAndroidStateMatch(const QStyleOption *opt) const { const AndroidDrawable *bestMatch = 0; if (!opt) { @@ -1226,7 +1474,7 @@ const QAndroidStyle::AndroidDrawable* QAndroidStyle::AndroidStateDrawable::bestA return bestMatch; } - uint bestCost=0xffff; + uint bestCost = 0xffff; foreach (const StateType & state, m_states) { if (int(opt->state) == state.first) return state.second; @@ -1376,15 +1624,13 @@ void QAndroidStyle::AndroidLayerDrawable::setFactor(int id, double factor, Qt::O void QAndroidStyle::AndroidLayerDrawable::draw(QPainter *painter, const QStyleOption *opt) const { - foreach (const LayerType &layer, m_layers) - { - if (layer.first == m_id) - { + foreach (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); + copy.rect.setWidth(copy.rect.width() * m_factor); else - copy.rect.setHeight(copy.rect.height()*m_factor); + copy.rect.setHeight(copy.rect.height() * m_factor); layer.second->draw(painter, ©); } else { layer.second->draw(painter, opt); @@ -1418,7 +1664,7 @@ QAndroidStyle::AndroidControl::AndroidControl(const QVariantMap &control, m_background = 0; it = control.find(QLatin1String("View_minWidth")); - if (it!=control.end()) + if (it != control.end()) m_minSize.setWidth(it.value().toInt()); it = control.find(QLatin1String("View_minHeight")); @@ -1534,10 +1780,9 @@ QSize QAndroidStyle::AndroidControl::sizeFromContents(const QStyleOption *opt, QMargins QAndroidStyle::AndroidControl::padding() { - if (const AndroidDrawable *drawable = m_background) - { + if (const AndroidDrawable *drawable = m_background) { if (drawable->type() == State) - drawable=static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0); + drawable = static_cast<const AndroidStateDrawable *>(m_background)->bestAndroidStateMatch(0); return drawable->padding(); } return QMargins(); @@ -1573,8 +1818,17 @@ void QAndroidStyle::AndroidCompoundButtonControl::drawControl(const QStyleOption if (m_button) m_button->draw(p, opt); } - -const QAndroidStyle::AndroidDrawable *QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const +QSize QAndroidStyle::AndroidCompoundButtonControl::sizeCheckBox(const QStyleOption *opt) const +{ + const AndroidDrawable *drawable = m_button; + return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->sizeImage(opt); +} +QPixmap QAndroidStyle::AndroidCompoundButtonControl::imgCheckBox(const QStyleOption *opt) const +{ + const AndroidDrawable *drawable = m_button; + return static_cast<const QAndroidStyle::AndroidStateDrawable *>(drawable)->img(opt); +} +const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidCompoundButtonControl::backgroundDrawable() const { return m_background ? m_background : m_button; } @@ -1637,10 +1891,10 @@ void QAndroidStyle::AndroidProgressBarControl::drawControl(const QStyleOption *o if (m_progressDrawable->type() == QAndroidStyle::Layer) { QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId); if (clipDrawable->type() == QAndroidStyle::Clip) - static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum), + static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum), progressBarV2.orientation); else - static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId,double(progressBarV2.progress)/double(progressBarV2.maximum-progressBarV2.minimum), + static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, double(progressBarV2.progress) / double(progressBarV2.maximum - progressBarV2.minimum), progressBarV2.orientation); } m_progressDrawable->draw(p, option); @@ -1659,11 +1913,11 @@ QRect QAndroidStyle::AndroidProgressBarControl::subElementRect(QStyle::SubElemen return option->rect; QMargins padding = m_background->padding(); - QRect p(padding.left(), padding.top(), padding.right()-padding.left(), padding.bottom()-padding.top()); + 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()); + 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()); + 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()); @@ -1734,26 +1988,27 @@ void QAndroidStyle::AndroidSeekBarControl::drawControl(const QStyleOption *optio if (const QStyleOptionSlider *styleOption = qstyleoption_cast<const QStyleOptionSlider *>(option)) { - double factor = double(styleOption->sliderPosition)/double(styleOption->maximum-styleOption->minimum); - if (m_progressDrawable->type()==QAndroidStyle::Layer) { + double factor = double(styleOption->sliderPosition - styleOption->minimum) + / double(styleOption->maximum - styleOption->minimum); + if (m_progressDrawable->type() == QAndroidStyle::Layer) { QAndroidStyle::AndroidDrawable *clipDrawable = static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->layer(m_progressId); if (clipDrawable->type() == QAndroidStyle::Clip) static_cast<QAndroidStyle::AndroidClipDrawable *>(clipDrawable)->setFactor(factor, styleOption->orientation); else static_cast<QAndroidStyle::AndroidLayerDrawable *>(m_progressDrawable)->setFactor(m_progressId, factor, styleOption->orientation); } - const AndroidDrawable *drawable=m_seekBarThumb; + const AndroidDrawable *drawable = m_seekBarThumb; if (drawable->type() == State) drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option); QStyleOption copy(*option); - copy.rect.setY((copy.rect.height()-m_minSize.height())/2); + copy.rect.setY((copy.rect.height() - m_minSize.height()) / 2); copy.rect.setHeight(m_minSize.height()); copy.rect.setWidth(copy.rect.width() - drawable->size().width()); - copy.rect.translate(drawable->size().width()/2, 0); + copy.rect.translate(drawable->size().width() / 2, 0); m_progressDrawable->draw(p, ©); if (styleOption->orientation == Qt::Vertical) qCritical() << "Vertical slider are not supported"; - int pos = copy.rect.width()*factor - drawable->size().width()/2; + int pos = copy.rect.width()*factor - drawable->size().width() / 2; copy.rect.translate(pos, 0); copy.rect.setSize(drawable->size()); m_seekBarThumb->draw(p, ©); @@ -1767,7 +2022,7 @@ QSize QAndroidStyle::AndroidSeekBarControl::sizeFromContents(const QStyleOption QSize sz = AndroidProgressBarControl::sizeFromContents(opt, contentsSize, w); if (!m_seekBarThumb) return sz; - const AndroidDrawable *drawable=m_seekBarThumb; + const AndroidDrawable *drawable = m_seekBarThumb; if (drawable->type() == State) drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(opt); return sz.expandedTo(drawable->size()); @@ -1786,7 +2041,8 @@ QRect QAndroidStyle::AndroidSeekBarControl::subControlRect(const QStyleOptionCom drawable = static_cast<const QAndroidStyle::AndroidStateDrawable *>(m_seekBarThumb)->bestAndroidStateMatch(option); QRect r(option->rect); - double factor = double(styleOption->sliderPosition) / (styleOption->maximum - styleOption->minimum); + double factor = double(styleOption->sliderPosition - styleOption->minimum) + / (styleOption->maximum - styleOption->minimum); int pos = option->rect.width() * factor - double(drawable->size().width() / 2); r.setX(r.x() + pos); r.setSize(drawable->size()); diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/widgets/styles/qandroidstyle_p.h index d64e37b9db..5334882908 100644 --- a/src/widgets/styles/qandroidstyle_p.h +++ b/src/widgets/styles/qandroidstyle_p.h @@ -132,6 +132,7 @@ public: static AndroidDrawable *fromMap(const QVariantMap &drawable, ItemType itemType); static QMargins extractMargins(const QVariantMap &value); virtual void setPaddingLeftToSizeWidth(); + QPixmap img() const; protected: ItemType m_itemType; QMargins m_padding; @@ -156,6 +157,7 @@ public: virtual void draw(QPainter *painter,const QStyleOption *opt) const; virtual QSize size() const; + QPixmap img() const; protected: QString m_filePath; mutable QString m_hashKey; @@ -228,7 +230,8 @@ public: inline const AndroidDrawable *bestAndroidStateMatch(const QStyleOption *opt) const; static int extractState(const QVariantMap &value); virtual void setPaddingLeftToSizeWidth(); - + QSize sizeImage(const QStyleOption *opt) const; + QPixmap img(const QStyleOption *opt) const; private: typedef QPair<int, const AndroidDrawable *> StateType; QList<StateType> m_states; @@ -281,7 +284,8 @@ public: AndroidCompoundButtonControl(const QVariantMap &control, ItemType itemType); virtual ~AndroidCompoundButtonControl(); virtual void drawControl(const QStyleOption *opt, QPainter *p, const QWidget *w); - + QSize sizeCheckBox(const QStyleOption *opt) const; + QPixmap imgCheckBox(const QStyleOption *opt) const; protected: virtual const AndroidDrawable * backgroundDrawable() const; const AndroidDrawable *m_button; @@ -387,6 +391,7 @@ private: typedef QHash<int, AndroidControl *> AndroidControlsHash; AndroidControlsHash m_androidControlsHash; QPalette m_standardPalette; + AndroidCompoundButtonControl *checkBoxControl; }; #endif // QT_NO_STYLE_ANDROID diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 27fef46772..6fbae53804 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -321,22 +321,24 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { QPen oldPen = p->pen(); if (header->sortIndicator & QStyleOptionHeader::SortUp) { - QPolygon pa(3); p->setPen(QPen(opt->palette.light(), 0)); p->drawLine(opt->rect.x() + opt->rect.width(), opt->rect.y(), opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); p->setPen(QPen(opt->palette.dark(), 0)); - pa.setPoint(0, opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()); - pa.setPoint(1, opt->rect.x(), opt->rect.y()); - pa.setPoint(2, opt->rect.x() + opt->rect.width(), opt->rect.y()); - p->drawPolyline(pa); + const QPoint points[] = { + QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x(), opt->rect.y()), + QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y()), + }; + p->drawPolyline(points, sizeof points / sizeof *points); } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { - QPolygon pa(3); p->setPen(QPen(opt->palette.light(), 0)); - pa.setPoint(0, opt->rect.x(), opt->rect.y() + opt->rect.height()); - pa.setPoint(1, opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()); - pa.setPoint(2, opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); - p->drawPolyline(pa); + const QPoint points[] = { + QPoint(opt->rect.x(), opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x() + opt->rect.width(), opt->rect.y() + opt->rect.height()), + QPoint(opt->rect.x() + opt->rect.width() / 2, opt->rect.y()), + }; + p->drawPolyline(points, sizeof points / sizeof *points); p->setPen(QPen(opt->palette.dark(), 0)); p->drawLine(opt->rect.x(), opt->rect.y() + opt->rect.height(), opt->rect.x() + opt->rect.width() / 2, opt->rect.y()); @@ -519,11 +521,6 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q if (pe == PE_IndicatorSpinUp && fw) --sy; - QPolygon a; - if (pe == PE_IndicatorSpinDown) - a.setPoints(3, 0, 1, sw-1, 1, sh-2, sh-1); - else - a.setPoints(3, 0, sh-1, sw-1, sh-1, sh-2, 1); int bsx = 0; int bsy = 0; if (opt->state & State_Sunken) { @@ -535,7 +532,13 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q p->setPen(opt->palette.buttonText().color()); p->setBrush(opt->palette.buttonText()); p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(a); + if (pe == PE_IndicatorSpinDown) { + const QPoint points[] = { QPoint(0, 1), QPoint(sw-1, 1), QPoint(sh-2, sh-1) }; + p->drawPolygon(points, sizeof points / sizeof *points); + } else { + const QPoint points[] = { QPoint(0, sh-1), QPoint(sw-1, sh-1), QPoint(sh-2, 1) }; + p->drawPolygon(points, sizeof points / sizeof *points); + } p->restore(); break; } #endif // QT_NO_SPINBOX @@ -1156,7 +1159,7 @@ void QCommonStylePrivate::startAnimation(QStyleAnimation *animation) const stopAnimation(animation->target()); q->connect(animation, SIGNAL(destroyed()), SLOT(_q_removeAnimation()), Qt::UniqueConnection); animations.insert(animation->target(), animation); - animation->start(QAbstractAnimation::DeleteWhenStopped); + animation->start(); } /*! \internal */ @@ -1644,30 +1647,33 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, break; case CE_ToolBoxTabShape: if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) { + p->setPen(tb->palette.mid().color().darker(150)); + bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); + p->setRenderHint(QPainter::Qt4CompatiblePainting); int d = 20 + tb->rect.height() - 3; - QPolygon a(7); if (tb->direction != Qt::RightToLeft) { - a.setPoint(0, -1, tb->rect.height() + 1); - a.setPoint(1, -1, 1); - a.setPoint(2, tb->rect.width() - d, 1); - a.setPoint(3, tb->rect.width() - 20, tb->rect.height() - 2); - a.setPoint(4, tb->rect.width() - 1, tb->rect.height() - 2); - a.setPoint(5, tb->rect.width() - 1, tb->rect.height() + 1); - a.setPoint(6, -1, tb->rect.height() + 1); + const QPoint points[] = { + QPoint(-1, tb->rect.height() + 1), + QPoint(-1, 1), + QPoint(tb->rect.width() - d, 1), + QPoint(tb->rect.width() - 20, tb->rect.height() - 2), + QPoint(tb->rect.width() - 1, tb->rect.height() - 2), + QPoint(tb->rect.width() - 1, tb->rect.height() + 1), + QPoint(-1, tb->rect.height() + 1), + }; + p->drawPolygon(points, sizeof points / sizeof *points); } else { - a.setPoint(0, tb->rect.width(), tb->rect.height() + 1); - a.setPoint(1, tb->rect.width(), 1); - a.setPoint(2, d - 1, 1); - a.setPoint(3, 20 - 1, tb->rect.height() - 2); - a.setPoint(4, 0, tb->rect.height() - 2); - a.setPoint(5, 0, tb->rect.height() + 1); - a.setPoint(6, tb->rect.width(), tb->rect.height() + 1); + const QPoint points[] = { + QPoint(tb->rect.width(), tb->rect.height() + 1), + QPoint(tb->rect.width(), 1), + QPoint(d - 1, 1), + QPoint(20 - 1, tb->rect.height() - 2), + QPoint(0, tb->rect.height() - 2), + QPoint(0, tb->rect.height() + 1), + QPoint(tb->rect.width(), tb->rect.height() + 1), + }; + p->drawPolygon(points, sizeof points / sizeof *points); } - - p->setPen(tb->palette.mid().color().darker(150)); - bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); - p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(a); p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting); p->setPen(tb->palette.light().color()); if (tb->direction != Qt::RightToLeft) { @@ -2914,7 +2920,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, QRect closeRect; if (canClose) { - QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, opt, widget).actualSize(QSize(iconSize, iconSize)); sz += QSize(buttonMargin, buttonMargin); if (verticalTitleBar) @@ -2931,7 +2937,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, QRect floatRect; if (canFloat) { - QSize sz = standardIcon(QStyle::SP_TitleBarNormalButton, + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, opt, widget).actualSize(QSize(iconSize, iconSize)); sz += QSize(buttonMargin, buttonMargin); if (verticalTitleBar) @@ -3039,7 +3045,18 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, #ifndef QT_NO_DIAL -static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) +// in lieu of std::array, minimal API +template <int N> +struct StaticPolygonF +{ + QPointF data[N]; + + Q_DECL_CONSTEXPR int size() const { return N; } + Q_DECL_CONSTEXPR const QPointF *cbegin() const { return data; } + Q_DECL_CONSTEXPR const QPointF &operator[](int idx) const { return data[idx]; } +}; + +static StaticPolygonF<3> calcArrow(const QStyleOptionSlider *dial, qreal &a) { int width = dial->rect.width(); int height = dial->rect.height(); @@ -3063,13 +3080,14 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) len = 5; int back = len / 2; - QPolygonF arrow(3); - arrow[0] = QPointF(0.5 + xc + len * qCos(a), - 0.5 + yc - len * qSin(a)); - arrow[1] = QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6), - 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)); - arrow[2] = QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6), - 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)); + StaticPolygonF<3> arrow = {{ + QPointF(0.5 + xc + len * qCos(a), + 0.5 + yc - len * qSin(a)), + QPointF(0.5 + xc + back * qCos(a + Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a + Q_PI * 5 / 6)), + QPointF(0.5 + xc + back * qCos(a - Q_PI * 5 / 6), + 0.5 + yc - back * qSin(a - Q_PI * 5 / 6)), + }}; return arrow; } @@ -3394,9 +3412,9 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl || qobject_cast<const QDockWidget *>(widget) #endif ) - pm = standardIcon(SP_DockWidgetCloseButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_DockWidgetCloseButton, &tool, widget).pixmap(10, 10); else - pm = standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3415,7 +3433,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget); down = tb->activeSubControls & SC_TitleBarMaxButton && (opt->state & State_Sunken); - pm = standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3433,7 +3451,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl && !(tb->titleBarState & Qt::WindowMinimized)) { ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget); down = tb->activeSubControls & SC_TitleBarMinButton && (opt->state & State_Sunken); - pm = standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3455,7 +3473,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl if (drawNormalButton) { ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget); down = tb->activeSubControls & SC_TitleBarNormalButton && (opt->state & State_Sunken); - pm = standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3473,7 +3491,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl && !(tb->titleBarState & Qt::WindowMinimized)) { ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget); down = (tb->activeSubControls & SC_TitleBarShadeButton && (opt->state & State_Sunken)); - pm = standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3491,7 +3509,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget); down = tb->activeSubControls & SC_TitleBarUnshadeButton && (opt->state & State_Sunken); - pm = standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3507,7 +3525,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget); down = tb->activeSubControls & SC_TitleBarContextHelpButton && (opt->state & State_Sunken); - pm = standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(10, 10); + pm = proxy()->standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(10, 10); tool.rect = ir; tool.state = down ? State_Sunken : State_Raised; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); @@ -3524,7 +3542,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl tb->icon.paint(p, ir); } else { int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); - pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize); + pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize); tool.rect = ir; p->save(); proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm); @@ -3571,12 +3589,12 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl p->drawArc(br, 240 * 16, 180 * 16); qreal a; - QPolygonF arrow(calcArrow(dial, a)); + const StaticPolygonF<3> arrow = calcArrow(dial, a); p->setPen(Qt::NoPen); p->setBrush(pal.button()); p->setRenderHint(QPainter::Qt4CompatiblePainting); - p->drawPolygon(arrow); + p->drawPolygon(arrow.cbegin(), arrow.size()); a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]); p->setBrush(Qt::NoBrush); @@ -3711,7 +3729,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl } btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget); proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); - QPixmap pm = standardIcon(SP_TitleBarCloseButton).pixmap(16, 16); + QPixmap pm = proxy()->standardIcon(SP_TitleBarCloseButton).pixmap(16, 16); proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); } if (opt->subControls & QStyle::SC_MdiNormalButton) { @@ -3728,7 +3746,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl } btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget); proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); - QPixmap pm = standardIcon(SP_TitleBarNormalButton).pixmap(16, 16); + QPixmap pm = proxy()->standardIcon(SP_TitleBarNormalButton).pixmap(16, 16); proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); } if (opt->subControls & QStyle::SC_MdiMinButton) { @@ -3745,7 +3763,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl } btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget); proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget); - QPixmap pm = standardIcon(SP_TitleBarMinButton).pixmap(16, 16); + QPixmap pm = proxy()->standardIcon(SP_TitleBarMinButton).pixmap(16, 16); proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm); } } @@ -4679,6 +4697,9 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid case PM_SubMenuOverlap: ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget); break; + case PM_TreeViewIndentation: + ret = int(QStyleHelper::dpiScaled(20.)); + break; default: ret = 0; break; @@ -4932,6 +4953,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget ret = hint.toChar().unicode(); break; } + case SH_LineEdit_PasswordMaskDelay: + ret = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::PasswordMaskDelay).toInt(); + break; case SH_ToolBox_SelectedPageTitleBold: ret = 1; break; @@ -5108,6 +5132,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget case SH_TabBar_CloseButtonPosition: ret = QTabBar::RightSide; break; + case SH_TabBar_ChangeCurrentDelay: + ret = 500; + break; #endif case SH_DockWidget_ButtonsHaveFrame: ret = true; @@ -5155,6 +5182,17 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget return ret; } +static QPixmap cachedPixmapFromXPM(const char * const *xpm) +{ + QPixmap result; + const QString tag = QString().sprintf("xpm:0x%p", static_cast<const void*>(xpm)); + if (!QPixmapCache::find(tag, &result)) { + result = QPixmap(xpm); + QPixmapCache::insert(tag, result); + } + return result; +} + /*! \reimp */ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, const QWidget *widget) const @@ -5350,13 +5388,13 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti im = im.convertToFormat(QImage::Format_ARGB32).mirrored(true, false); return QPixmap::fromImage(im); } - return QPixmap(tb_extension_arrow_h_xpm); + return cachedPixmapFromXPM(tb_extension_arrow_h_xpm); case SP_ToolBarVerticalExtensionButton: - return QPixmap(tb_extension_arrow_v_xpm); + return cachedPixmapFromXPM(tb_extension_arrow_v_xpm); case SP_FileDialogStart: - return QPixmap(filedialog_start_xpm); + return cachedPixmapFromXPM(filedialog_start_xpm); case SP_FileDialogEnd: - return QPixmap(filedialog_end_xpm); + return cachedPixmapFromXPM(filedialog_end_xpm); #endif #ifndef QT_NO_IMAGEFORMAT_PNG case SP_CommandLink: @@ -5472,31 +5510,31 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti #ifndef QT_NO_IMAGEFORMAT_XPM switch (sp) { case SP_TitleBarMenuButton: - return QPixmap(qt_menu_xpm); + return cachedPixmapFromXPM(qt_menu_xpm); case SP_TitleBarShadeButton: - return QPixmap(qt_shade_xpm); + return cachedPixmapFromXPM(qt_shade_xpm); case SP_TitleBarUnshadeButton: - return QPixmap(qt_unshade_xpm); + return cachedPixmapFromXPM(qt_unshade_xpm); case SP_TitleBarNormalButton: - return QPixmap(qt_normalizeup_xpm); + return cachedPixmapFromXPM(qt_normalizeup_xpm); case SP_TitleBarMinButton: - return QPixmap(qt_minimize_xpm); + return cachedPixmapFromXPM(qt_minimize_xpm); case SP_TitleBarMaxButton: - return QPixmap(qt_maximize_xpm); + return cachedPixmapFromXPM(qt_maximize_xpm); case SP_TitleBarCloseButton: - return QPixmap(qt_close_xpm); + return cachedPixmapFromXPM(qt_close_xpm); case SP_TitleBarContextHelpButton: - return QPixmap(qt_help_xpm); + return cachedPixmapFromXPM(qt_help_xpm); case SP_DockWidgetCloseButton: - return QPixmap(dock_widget_close_xpm); + return cachedPixmapFromXPM(dock_widget_close_xpm); case SP_MessageBoxInformation: - return QPixmap(information_xpm); + return cachedPixmapFromXPM(information_xpm); case SP_MessageBoxWarning: - return QPixmap(warning_xpm); + return cachedPixmapFromXPM(warning_xpm); case SP_MessageBoxCritical: - return QPixmap(critical_xpm); + return cachedPixmapFromXPM(critical_xpm); case SP_MessageBoxQuestion: - return QPixmap(question_xpm); + return cachedPixmapFromXPM(question_xpm); default: break; } diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 012f5ea18f..989f277c58 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -749,6 +749,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->drawRect(rect); QColor checkMarkColor = option->palette.text().color().darker(120); + const int checkMarkPadding = QStyleHelper::dpiScaled(3); if (checkbox->state & State_NoChange) { gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()); @@ -759,10 +760,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, checkMarkColor.setAlpha(180); painter->setPen(QPen(checkMarkColor, 1)); painter->setBrush(gradient); - painter->drawRect(rect.adjusted(3, 3, -3, -3)); + painter->drawRect(rect.adjusted(checkMarkPadding, checkMarkPadding, -checkMarkPadding, -checkMarkPadding)); } else if (checkbox->state & (State_On)) { - QPen checkPen = QPen(checkMarkColor, 1.8); + QPen checkPen = QPen(checkMarkColor, QStyleHelper::dpiScaled(1.8)); checkMarkColor.setAlpha(210); painter->translate(-1, 0.5); painter->setPen(checkPen); @@ -771,9 +772,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, // Draw checkmark QPainterPath path; - path.moveTo(5, rect.height() / 2.0); - path.lineTo(rect.width() / 2.0 - 0, rect.height() - 3); - path.lineTo(rect.width() - 2.5, 3); + path.moveTo(2 + checkMarkPadding, rect.height() / 2.0); + path.lineTo(rect.width() / 2.0, rect.height() - checkMarkPadding); + path.lineTo(rect.width() - checkMarkPadding - 0.5, checkMarkPadding); painter->drawPath(path.translated(rect.topLeft())); } } @@ -786,7 +787,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color()); painter->setRenderHint(QPainter::Antialiasing, true); QPainterPath circle; - circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5); + const QPointF circleCenter = rect.center() + QPoint(1, 1); + const qreal outlineRadius = (rect.width() + (rect.width() + 1) % 2) / 2.0 - 1; + circle.addEllipse(circleCenter, outlineRadius, outlineRadius); painter->setPen(QPen(option->palette.background().color().darker(150))); if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) painter->setPen(QPen(highlightedOutline)); @@ -794,7 +797,8 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, if (state & (State_On )) { circle = QPainterPath(); - circle.addEllipse(rect.center() + QPoint(1, 1), 2.8, 2.8); + const qreal checkmarkRadius = outlineRadius / 2.32; + circle.addEllipse(circleCenter, checkmarkRadius, checkmarkRadius); QColor checkMarkColor = option->palette.text().color().darker(120); checkMarkColor.setAlpha(200); painter->setPen(checkMarkColor); @@ -955,7 +959,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, { Q_D(const QFusionStyle); if (d->tabBarcloseButtonIcon.isNull()) - d->tabBarcloseButtonIcon = standardIcon(SP_DialogCloseButton, option, widget); + d->tabBarcloseButtonIcon = proxy()->standardIcon(SP_DialogCloseButton, option, widget); if ((option->state & State_Enabled) && (option->state & State_MouseOver)) proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); @@ -1604,8 +1608,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio else pixmap = menuItem->icon.pixmap(iconSize, mode); - int pixw = pixmap.width(); - int pixh = pixmap.height(); + const int pixw = pixmap.width() / pixmap.devicePixelRatio(); + const int pixh = pixmap.height() / pixmap.devicePixelRatio(); QRect pmr(0, 0, pixw, pixh); pmr.moveCenter(vCheckRect.center()); @@ -2379,7 +2383,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption } else { QStyleOption tool(0); tool.palette = titleBar->palette; - QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); + QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); tool.rect = iconRect; painter->save(); proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); @@ -3016,97 +3020,120 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption */ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { + int val = -1; switch (metric) { case PM_SliderTickmarkOffset: - return 4; + val = 4; + break; case PM_HeaderMargin: - return 2; case PM_ToolTipLabelFrameWidth: - return 2; + val = 2; + break; case PM_ButtonDefaultIndicator: - return 0; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: - return 0; + val = 0; + break; case PM_MessageBoxIconSize: - return 48; + val = 48; + break; case PM_ListViewIconSize: - return 24; + val = 24; + break; case PM_DialogButtonsSeparator: case PM_ScrollBarSliderMin: - return 26; + val = 26; + break; case PM_TitleBarHeight: - return 24; + val = 24; + break; case PM_ScrollBarExtent: - return 14; + val = 14; + break; case PM_SliderThickness: - return 15; case PM_SliderLength: - return 15; + val = 15; + break; case PM_DockWidgetTitleMargin: - return 1; - case PM_DefaultFrameWidth: - return 1; + val = 1; + break; case PM_SpinBoxFrameWidth: - return 3; + val = 3; + break; case PM_MenuVMargin: case PM_MenuHMargin: - return 0; case PM_MenuPanelWidth: - return 0; + val = 0; + break; case PM_MenuBarItemSpacing: - return 6; + val = 6; + break; case PM_MenuBarVMargin: - return 0; case PM_MenuBarHMargin: - return 0; case PM_MenuBarPanelWidth: - return 0; + val = 0; + break; case PM_ToolBarHandleExtent: - return 9; + val = 9; + break; case PM_ToolBarItemSpacing: - return 1; + val = 1; + break; case PM_ToolBarFrameWidth: - return 2; case PM_ToolBarItemMargin: - return 2; + val = 2; + break; case PM_SmallIconSize: - return 16; case PM_ButtonIconSize: - return 16; + val = 16; + break; case PM_DockWidgetTitleBarButtonMargin: - return 2; + val = 2; + break; case PM_MaximumDragDistance: - return -1; + val = -1; + break; case PM_TabCloseIndicatorWidth: case PM_TabCloseIndicatorHeight: - return 20; + val = 20; + break; case PM_TabBarTabVSpace: - return 12; + val = 12; + break; case PM_TabBarTabOverlap: - return 1; + val = 1; + break; case PM_TabBarBaseOverlap: - return 2; + val = 2; + break; case PM_SubMenuOverlap: - return -1; + val = -1; + break; case PM_DockWidgetHandleExtent: case PM_SplitterWidth: - return 4; + val = 4; + break; case PM_IndicatorHeight: case PM_IndicatorWidth: case PM_ExclusiveIndicatorHeight: case PM_ExclusiveIndicatorWidth: - return 14; + val = 14; + break; case PM_ScrollView_ScrollBarSpacing: - return 0; + val = 0; + break; case PM_ScrollView_ScrollBarOverlap: if (proxy()->styleHint(SH_ScrollBar_Transient, option, widget)) return proxy()->pixelMetric(PM_ScrollBarExtent, option, widget); - return 0; - default: + val = 0; break; + case PM_DefaultFrameWidth: + return 1; // Do not dpi-scale because the drawn frame is always exactly 1 pixel thick + break; + default: + return QCommonStyle::pixelMetric(metric, option, widget); } - return QCommonStyle::pixelMetric(metric, option, widget); + return QStyleHelper::dpiScaled(val); } /*! @@ -3309,14 +3336,15 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom break; case SC_SliderGroove: { QPoint grooveCenter = slider->rect.center(); + const int grooveThickness = QStyleHelper::dpiScaled(7); if (slider->orientation == Qt::Horizontal) { - rect.setHeight(7); + rect.setHeight(grooveThickness); if (slider->tickPosition & QSlider::TicksAbove) grooveCenter.ry() += tickSize; if (slider->tickPosition & QSlider::TicksBelow) grooveCenter.ry() -= tickSize; } else { - rect.setWidth(7); + rect.setWidth(grooveThickness); if (slider->tickPosition & QSlider::TicksAbove) grooveCenter.rx() += tickSize; if (slider->tickPosition & QSlider::TicksBelow) @@ -3332,27 +3360,25 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom break; case CC_SpinBox: if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { - QSize bs; int center = spinbox->rect.height() / 2; - int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + int fw = spinbox->frame ? 3 : 0; // Is drawn with 3 pixels width in drawComplexControl, independently from PM_SpinBoxFrameWidth int y = fw; - bs.setHeight(qMax(8, spinbox->rect.height()/2 - y)); - bs.setWidth(14); + const int buttonWidth = QStyleHelper::dpiScaled(14); int x, lx, rx; - x = spinbox->rect.width() - y - bs.width() + 2; + x = spinbox->rect.width() - y - buttonWidth + 2; lx = fw; rx = x - fw; switch (subControl) { case SC_SpinBoxUp: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); - rect = QRect(x, fw, bs.width(), center - fw); + rect = QRect(x, fw, buttonWidth, center - fw); break; case SC_SpinBoxDown: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) return QRect(); - rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - fw + 1); + rect = QRect(x, center, buttonWidth, spinbox->rect.bottom() - center - fw + 1); break; case SC_SpinBoxEditField: if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) { diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 9fa056960a..991d635854 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -1774,7 +1774,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom } else { QStyleOption tool(0); tool.palette = titleBar->palette; - QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); + QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); tool.rect = iconRect; painter->save(); proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d74e032412..f0a45548f6 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -152,13 +152,32 @@ static uint qHash(const QPointer<QObject> &ptr) return qHash(ptr.data()); } -// These colors specify the titlebar gradient colors on -// Leopard. Ideally we should get them from the system. -static const QColor titlebarGradientActiveBegin(220, 220, 220); -static const QColor titlebarGradientActiveEnd(151, 151, 151); +// 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 titlebarGradientInactiveBegin(241, 241, 241); -static const QColor titlebarGradientInactiveEnd(207, 207, 207); static const QColor titlebarSeparatorLineInactive(131, 131, 131); // Gradient colors used for the dock widget title bar and @@ -475,6 +494,18 @@ static QString qt_mac_removeMnemonics(const QString &original) --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; @@ -526,25 +557,6 @@ public: }; } // anonymous namespace -static QColor qcolorFromCGColor(CGColorRef cgcolor) -{ - QColor pc; - CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor)); - const CGFloat *components = CGColorGetComponents(cgcolor); - if (model == kCGColorSpaceModelRGB) { - pc.setRgbF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelCMYK) { - pc.setCmykF(components[0], components[1], components[2], components[3]); - } else if (model == kCGColorSpaceModelMonochrome) { - pc.setRgbF(components[0], components[0], components[0], components[1]); - } else { - // Colorspace we can't deal with. - qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model); - Q_ASSERT(false); - } - return pc; -} - OSStatus qt_mac_shape2QRegionHelper(int inMessage, HIShapeRef, const CGRect *inRect, void *inRefcon) { QRegion *region = static_cast<QRegion *>(inRefcon); @@ -702,7 +714,6 @@ static bool qt_macWindowMainWindow(const QWidget *window) 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 macItemVMargin = 2; // menu item ver 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. @@ -2985,7 +2996,7 @@ QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOpt return QCommonStyle::standardPixmap(standardPixmap, opt, widget); recursionGuard = true; - QIcon icon = standardIcon(standardPixmap, opt, widget); + QIcon icon = proxy()->standardIcon(standardPixmap, opt, widget); recursionGuard = false; int size; switch (standardPixmap) { @@ -3301,7 +3312,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai [triangleCell setButtonType:NSOnOffButton]; [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; [triangleCell setBezelStyle:NSDisclosureBezelStyle]; - [triangleCell setBackgroundStyle:((opt->state & State_Selected) && w->hasFocus()) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; + bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); + [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; CGContextSaveGState(cg); [NSGraphicsContext saveGraphicsState]; @@ -3414,14 +3426,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai } break; case PE_PanelStatusBar: { // Fill the status bar with the titlebar gradient. - QLinearGradient linearGrad(0, opt->rect.top(), 0, opt->rect.bottom()); + QLinearGradient linearGrad; if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) { - linearGrad.setColorAt(0, titlebarGradientActiveBegin); - linearGrad.setColorAt(1, titlebarGradientActiveEnd); + linearGrad = titlebarGradientActive(); } else { - linearGrad.setColorAt(0, titlebarGradientInactiveBegin); - linearGrad.setColorAt(1, titlebarGradientInactiveEnd); + 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. @@ -5096,7 +5109,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, QRect closeRect; if (canClose) { - QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, opt, widget).actualSize(QSize(iconSize, iconSize)); sz += QSize(buttonMargin, buttonMargin); if (verticalTitleBar) @@ -5113,7 +5126,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, QRect floatRect; if (canFloat) { - QSize sz = standardIcon(QStyle::SP_TitleBarNormalButton, + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, opt, widget).actualSize(QSize(iconSize, iconSize)); sz += QSize(buttonMargin, buttonMargin); if (verticalTitleBar) diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 4c5c7cd17e..c3be177732 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1470,6 +1470,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value PM_TabCloseIndicatorWidth The default width of a close button on a tab in a tab bar. \value PM_TabCloseIndicatorHeight The default height of a close button on a tab in a tab bar. + \value PM_TreeViewIndentation The indentation of items in a tree view. + This enum value has been introduced in Qt 5.4. + \value PM_CustomBase Base value for custom pixel metrics. Custom values must be greater than this value. @@ -1784,6 +1787,9 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_LineEdit_PasswordCharacter The Unicode character to be used for passwords. + \value SH_LineEdit_PasswordMaskDelay Determines the delay before visible character is masked + with password character, in milliseconds. This enum value was added in Qt 5.4. + \value SH_Table_GridLineColor The RGB value of the grid for a table. \value SH_UnderlineShortcut Whether shortcuts are underlined. @@ -1927,6 +1933,10 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SH_Splitter_OpaqueResize Determines if resizing is opaque This enum value has been introduced in Qt 5.2 + \value SH_TabBar_ChangeCurrentDelay Determines the delay before the current + tab is changed while dragging over the tabbar, in milliseconds. This + enum value has been introduced in Qt 5.4 + \sa styleHint() */ diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index 136daa9abd..c647513dca 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -66,6 +66,9 @@ class Q_WIDGETS_EXPORT QStyle : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QStyle) + Q_ENUMS(StateFlag PrimitiveElement ControlElement SubElement ComplexControl) + Q_ENUMS(SubControl PixelMetric ContentsType RequestSoftwareInputPanel StyleHint) + Q_ENUMS(StandardPixmap) protected: QStyle(QStylePrivate &dd); @@ -553,6 +556,7 @@ public: PM_ScrollView_ScrollBarSpacing, PM_ScrollView_ScrollBarOverlap, PM_SubMenuOverlap, + PM_TreeViewIndentation, // do not add any values below/greater than this PM_CustomBase = 0xf0000000 @@ -703,6 +707,8 @@ public: SH_Widget_Animate, SH_Splitter_OpaqueResize, SH_ComboBox_UseNativePopup, + SH_LineEdit_PasswordMaskDelay, + SH_TabBar_ChangeCurrentDelay, // Add new style hint values here SH_CustomBase = 0xf0000000 diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp index 6668be8307..65d011f01f 100644 --- a/src/widgets/styles/qstyleanimation.cpp +++ b/src/widgets/styles/qstyleanimation.cpp @@ -53,7 +53,7 @@ static const qreal ScrollBarFadeOutDuration = 200.0; static const qreal ScrollBarFadeOutDelay = 450.0; QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(target), - _delay(0), _duration(-1), _startTime(QTime::currentTime()) + _delay(0), _duration(-1), _startTime(QTime::currentTime()), _fps(ThirtyFps), _skip(0) { } @@ -96,6 +96,16 @@ void QStyleAnimation::setStartTime(const QTime &time) _startTime = time; } +QStyleAnimation::FrameRate QStyleAnimation::frameRate() const +{ + return _fps; +} + +void QStyleAnimation::setFrameRate(FrameRate fps) +{ + _fps = fps; +} + void QStyleAnimation::updateTarget() { QEvent event(QEvent::StyleAnimationUpdate); @@ -105,6 +115,12 @@ void QStyleAnimation::updateTarget() stop(); } +void QStyleAnimation::start() +{ + _skip = 0; + QAbstractAnimation::start(DeleteWhenStopped); +} + bool QStyleAnimation::isUpdateNeeded() const { return currentTime() > _delay; @@ -112,8 +128,11 @@ bool QStyleAnimation::isUpdateNeeded() const void QStyleAnimation::updateCurrentTime(int) { - if (target() && isUpdateNeeded()) - updateTarget(); + if (++_skip >= _fps) { + _skip = 0; + if (target() && isUpdateNeeded()) + updateTarget(); + } } QProgressStyleAnimation::QProgressStyleAnimation(int speed, QObject *target) : diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h index 33868a3440..526722d09a 100644 --- a/src/widgets/styles/qstyleanimation_p.h +++ b/src/widgets/styles/qstyleanimation_p.h @@ -80,8 +80,21 @@ public: QTime startTime() const; void setStartTime(const QTime &time); + enum FrameRate { + DefaultFps, + SixtyFps, + ThirtyFps, + TwentyFps + }; + + FrameRate frameRate() const; + void setFrameRate(FrameRate fps); + void updateTarget(); +public Q_SLOTS: + void start(); + protected: virtual bool isUpdateNeeded() const; virtual void updateCurrentTime(int time); @@ -90,6 +103,8 @@ private: int _delay; int _duration; QTime _startTime; + FrameRate _fps; + int _skip; }; class QProgressStyleAnimation : public QStyleAnimation diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index 5913b2f261..f642a05d13 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -3702,6 +3702,8 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version) of the painter used to draw the item. By default, if no transformations are applied, its value is 1. If zoomed out 1:2, the level of detail will be 0.5, and if zoomed in 2:1, its value is 2. + + \sa QGraphicsScene::minimumRenderSize() */ qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform) { diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 4f817a3353..94ec55002a 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -666,9 +666,10 @@ protected: template <typename T> T qstyleoption_cast(const QStyleOption *opt) { - if (opt && opt->version >= static_cast<T>(0)->Version && (opt->type == static_cast<T>(0)->Type - || int(static_cast<T>(0)->Type) == QStyleOption::SO_Default - || (int(static_cast<T>(0)->Type) == QStyleOption::SO_Complex + typedef typename QtPrivate::remove_cv<typename QtPrivate::remove_pointer<T>::type>::type Opt; + if (opt && opt->version >= Opt::Version && (opt->type == Opt::Type + || int(Opt::Type) == QStyleOption::SO_Default + || (int(Opt::Type) == QStyleOption::SO_Complex && opt->type > QStyleOption::SO_Complex))) return static_cast<T>(opt); return 0; @@ -677,9 +678,10 @@ T qstyleoption_cast(const QStyleOption *opt) template <typename T> T qstyleoption_cast(QStyleOption *opt) { - if (opt && opt->version >= static_cast<T>(0)->Version && (opt->type == static_cast<T>(0)->Type - || int(static_cast<T>(0)->Type) == QStyleOption::SO_Default - || (int(static_cast<T>(0)->Type) == QStyleOption::SO_Complex + typedef typename QtPrivate::remove_cv<typename QtPrivate::remove_pointer<T>::type>::type Opt; + if (opt && opt->version >= Opt::Version && (opt->type == Opt::Type + || int(Opt::Type) == QStyleOption::SO_Default + || (int(Opt::Type) == QStyleOption::SO_Complex && opt->type > QStyleOption::SO_Complex))) return static_cast<T>(opt); return 0; @@ -727,8 +729,9 @@ public: template <typename T> T qstyleoption_cast(const QStyleHintReturn *hint) { - if (hint && hint->version <= static_cast<T>(0)->Version && - (hint->type == static_cast<T>(0)->Type || int(static_cast<T>(0)->Type) == QStyleHintReturn::SH_Default)) + typedef typename QtPrivate::remove_cv<typename QtPrivate::remove_pointer<T>::type>::type Opt; + if (hint && hint->version <= Opt::Version && + (hint->type == Opt::Type || int(Opt::Type) == QStyleHintReturn::SH_Default)) return static_cast<T>(hint); return 0; } @@ -736,8 +739,9 @@ T qstyleoption_cast(const QStyleHintReturn *hint) template <typename T> T qstyleoption_cast(QStyleHintReturn *hint) { - if (hint && hint->version <= static_cast<T>(0)->Version && - (hint->type == static_cast<T>(0)->Type || int(static_cast<T>(0)->Type) == QStyleHintReturn::SH_Default)) + typedef typename QtPrivate::remove_cv<typename QtPrivate::remove_pointer<T>::type>::type Opt; + if (hint && hint->version <= Opt::Version && + (hint->type == Opt::Type || int(Opt::Type) == QStyleHintReturn::SH_Default)) return static_cast<T>(hint); return 0; } diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 60bfc8e075..4d9f3a48e2 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -645,6 +645,7 @@ static const char *knownStyleHints[] = { "icon-size", "leftarrow-icon", "lineedit-password-character", + "lineedit-password-mask-delay", "mdi-fill-space-on-maximize", "menu-scrollable", "menubar-altkey-navigation", @@ -2044,7 +2045,6 @@ bool QStyleSheetStyle::hasStyleRule(const QObject *obj, int part) const } QString pseudoElement = QLatin1String(knownPseudoElements[part].name); - QVector<Declaration> declarations; for (int i = 0; i < rules.count(); i++) { const Selector& selector = rules.at(i).selectors.at(0); if (pseudoElement.compare(selector.pseudoElement(), Qt::CaseInsensitive) == 0) { @@ -5143,6 +5143,7 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi QString s; switch (sh) { case SH_LineEdit_PasswordCharacter: s = QLatin1String("lineedit-password-character"); break; + case SH_LineEdit_PasswordMaskDelay: s = QLatin1String("lineedit-password-mask-delay"); break; case SH_DitherDisabledText: s = QLatin1String("dither-disabled-text"); break; case SH_EtchDisabledText: s = QLatin1String("etch-disabled-text"); break; case SH_ItemView_ActivateItemOnSingleClick: s = QLatin1String("activate-on-singleclick"); break; @@ -5804,6 +5805,25 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c break; #endif //QT_NO_TOOLBAR + // On mac we make pixel adjustments to layouts which are not + // desireable when you have custom style sheets on them + case SE_CheckBoxLayoutItem: + case SE_ComboBoxLayoutItem: + case SE_DateTimeEditLayoutItem: + case SE_LabelLayoutItem: + case SE_ProgressBarLayoutItem: + case SE_PushButtonLayoutItem: + case SE_RadioButtonLayoutItem: + case SE_SliderLayoutItem: + case SE_SpinBoxLayoutItem: + case SE_ToolButtonLayoutItem: + case SE_FrameLayoutItem: + case SE_GroupBoxLayoutItem: + case SE_TabWidgetLayoutItem: + if (!rule.hasNativeBorder()) + return opt->rect; + break; + default: break; } diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 9ab8f8f08a..2f04a20cd0 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -118,6 +118,9 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* \internal */ + +int QWindowsStylePrivate::m_appDevicePixelRatio = 0; + QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -130,6 +133,13 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } +int QWindowsStylePrivate::appDevicePixelRatio() +{ + if (!QWindowsStylePrivate::m_appDevicePixelRatio) + QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); + return QWindowsStylePrivate::m_appDevicePixelRatio; +} + // Returns \c true if the toplevel parent of \a widget has seen the Alt-key bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const { @@ -295,32 +305,123 @@ void QWindowsStyle::polish(QPalette &pal) QCommonStyle::polish(pal); } +int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget) +{ + switch (pm) { +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + case QStyle::PM_DockWidgetFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CXFRAME); +# else + return GetSystemMetrics(SM_CXDLGFRAME); +# endif + break; + + case QStyle::PM_TitleBarHeight: + if (widget && (widget->windowType() == Qt::Tool)) { + // MS always use one less than they say +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYSMCAPTION) - 1; +# else + return GetSystemMetrics(SM_CYCAPTION) - 1; +# endif + } + return GetSystemMetrics(SM_CYCAPTION) - 1; + +# ifndef Q_OS_WINCE + case QStyle::PM_ScrollBarExtent: + { + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + return qMax(ncm.iScrollHeight, ncm.iScrollWidth); + } + break; +# endif // !Q_OS_WINCE + + case QStyle::PM_MdiSubWindowFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYFRAME); +# else + return GetSystemMetrics(SM_CYDLGFRAME); +# endif +#else + Q_UNUSED(widget) +#endif // Q_OS_WIN + + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + +int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) +{ + switch (pm) { + case QStyle::PM_ToolBarItemSpacing: + return 0; + case QStyle::PM_ButtonDefaultIndicator: + case QStyle::PM_ButtonShiftHorizontal: + case QStyle::PM_ButtonShiftVertical: + case QStyle::PM_MenuHMargin: + case QStyle::PM_MenuVMargin: + case QStyle::PM_ToolBarItemMargin: + return 1; + break; + case QStyle::PM_DockWidgetSeparatorExtent: + return 4; +#ifndef QT_NO_TABBAR + case QStyle::PM_TabBarTabShiftHorizontal: + return 0; + case QStyle::PM_TabBarTabShiftVertical: + return 2; +#endif + +#ifndef QT_NO_SLIDER + case QStyle::PM_SliderLength: + return 11; +#endif // QT_NO_SLIDER + +#ifndef QT_NO_MENU + case QStyle::PM_MenuBarHMargin: + case QStyle::PM_MenuBarVMargin: + case QStyle::PM_MenuBarPanelWidth: + return 0; + case QStyle::PM_SmallIconSize: + return 16; + case QStyle::PM_LargeIconSize: + return 32; + case QStyle::PM_DockWidgetTitleMargin: + return 2; + case QStyle::PM_DockWidgetTitleBarButtonMargin: + case QStyle::PM_DockWidgetFrameWidth: + return 4; + +#endif // QT_NO_MENU + case QStyle::PM_ToolBarHandleExtent: + return 10; + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { - int ret; + int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); + if (ret != QWindowsStylePrivate::InvalidMetric) + return ret / QWindowsStylePrivate::devicePixelRatio(widget); + + ret = QWindowsStylePrivate::fixedPixelMetric(pm); + if (ret != QWindowsStylePrivate::InvalidMetric) + return int(QStyleHelper::dpiScaled(ret)); + + ret = 0; switch (pm) { - case PM_ButtonDefaultIndicator: - case PM_ButtonShiftHorizontal: - case PM_ButtonShiftVertical: - case PM_MenuHMargin: - case PM_MenuVMargin: - ret = 1; - break; - case PM_DockWidgetSeparatorExtent: - ret = int(QStyleHelper::dpiScaled(4.)); - break; -#ifndef QT_NO_TABBAR - case PM_TabBarTabShiftHorizontal: - ret = 0; - break; - case PM_TabBarTabShiftVertical: - ret = 2; - break; -#endif case PM_MaximumDragDistance: ret = QCommonStyle::pixelMetric(PM_MaximumDragDistance); if (ret == -1) @@ -328,10 +429,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #ifndef QT_NO_SLIDER - case PM_SliderLength: - ret = int(QStyleHelper::dpiScaled(11.)); - 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. @@ -357,116 +454,18 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW if (space > 0) thick += (space * 2) / (n + 2); ret = thick; - } else { - ret = 0; } break; #endif // QT_NO_SLIDER -#ifndef QT_NO_MENU - case PM_MenuBarHMargin: - ret = 0; - break; - - case PM_MenuBarVMargin: - ret = 0; - break; - - case PM_MenuBarPanelWidth: - 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_DockWidgetTitleMargin: - ret = int(QStyleHelper::dpiScaled(2.)); - break; - case PM_DockWidgetTitleBarButtonMargin: - ret = int(QStyleHelper::dpiScaled(4.)); - break; -#if defined(Q_WS_WIN) - case PM_DockWidgetFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CXDLGFRAME); -#else - ret = GetSystemMetrics(SM_CXFRAME); -#endif - break; -#else - case PM_DockWidgetFrameWidth: - ret = 4; - break; -#endif // Q_WS_WIN - break; - -#endif // QT_NO_MENU - - -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // There is no title bar in Windows Runtime applications - case PM_TitleBarHeight: - if (widget && (widget->windowType() == Qt::Tool)) { - // MS always use one less than they say -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYCAPTION) - 1; -#else - ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; -#endif - } else { - ret = GetSystemMetrics(SM_CYCAPTION) - 1; - } - - break; -#endif // !Q_OS_WINRT - - case PM_ScrollBarExtent: - { -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) - ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); - else -#endif // !Q_OS_WINCE && !Q_OS_WINRT - ret = QCommonStyle::pixelMetric(pm, opt, widget); - } - break; -#endif // Q_OS_WIN - case PM_SplitterWidth: - ret = qMax(4, QApplication::globalStrut().width()); + ret = qMax(int(QStyleHelper::dpiScaled(4)), QApplication::globalStrut().width()); break; -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // Mdi concept not available for WinRT applications - case PM_MdiSubWindowFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYDLGFRAME); -#else - ret = GetSystemMetrics(SM_CYFRAME); -#endif - break; -#endif // !Q_OS_WINRT -#endif // Q_OS_WIN - case PM_ToolBarItemMargin: - ret = 1; - break; - case PM_ToolBarItemSpacing: - ret = 0; - break; - case PM_ToolBarHandleExtent: - ret = int(QStyleHelper::dpiScaled(10.)); - break; default: ret = QCommonStyle::pixelMetric(pm, opt, widget); break; @@ -909,7 +908,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, int xOffset = 0; int yOffset = 0; int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); - int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth); + int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight); if (ir.width() > indicatorWidth) xOffset += (ir.width() - indicatorWidth)/2; if (ir.height() > indicatorHeight) diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 872b6f0e9e..93994abf6d 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -68,7 +68,14 @@ class QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: + enum { InvalidMetric = -23576 }; + QWindowsStylePrivate(); + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int fixedPixelMetric(QStyle::PixelMetric pm); + static int devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); } + bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; @@ -90,6 +97,10 @@ public: windowsRightBorder = 15, // right border on windows windowsCheckMarkWidth = 12 // checkmarks width on windows }; + +private: + static int appDevicePixelRatio(); + static int m_appDevicePixelRatio; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index bc78ea3296..bdc5a6ce0e 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -82,66 +82,16 @@ static const int windowsRightBorder = 15; // right border on windows # define CMDLGS_DISABLED 4 #endif -// Runtime resolved theme engine function calls - - -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); -typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); -typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); -typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); -typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); -typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); -typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); -typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); -typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); -typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); -typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); -typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); -typedef HRESULT (WINAPI *PtrIsThemePartDefined)(HTHEME hTheme, int iPartId, int iStateId); -typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); -typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); - -static PtrIsThemePartDefined pIsThemePartDefined = 0; -static PtrOpenThemeData pOpenThemeData = 0; -static PtrCloseThemeData pCloseThemeData = 0; -static PtrDrawThemeBackground pDrawThemeBackground = 0; -static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; -static PtrGetCurrentThemeName pGetCurrentThemeName = 0; -static PtrGetThemeBool pGetThemeBool = 0; -static PtrGetThemeColor pGetThemeColor = 0; -static PtrGetThemeEnumValue pGetThemeEnumValue = 0; -static PtrGetThemeFilename pGetThemeFilename = 0; -static PtrGetThemeFont pGetThemeFont = 0; -static PtrGetThemeInt pGetThemeInt = 0; -static PtrGetThemeIntList pGetThemeIntList = 0; -static PtrGetThemeMargins pGetThemeMargins = 0; -static PtrGetThemeMetric pGetThemeMetric = 0; -static PtrGetThemePartSize pGetThemePartSize = 0; -static PtrGetThemePosition pGetThemePosition = 0; -static PtrGetThemeRect pGetThemeRect = 0; -static PtrGetThemeString pGetThemeString = 0; -static PtrGetThemeTransitionDuration pGetThemeTransitionDuration= 0; -static PtrSetWindowTheme pSetWindowTheme = 0; -static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; - /* \internal Checks if we should use Vista style , or if we should fall back to Windows style. */ bool QWindowsVistaStylePrivate::useVista() { - return (QWindowsVistaStylePrivate::useXP() && - (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && - (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))); + return (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) + && QWindowsVistaStylePrivate::useXP() + && QWindowsVistaStylePrivate::pGetThemeTransitionDuration != Q_NULLPTR; } /* \internal @@ -392,7 +342,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt //translate state flags to UXTHEME states : if (element == PE_FrameLineEdit) { - theme = pOpenThemeData(0, L"Edit"); + theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Edit"); partId = EP_EDITBORDER_NOSCROLL; if (oldState & State_MouseOver) @@ -410,7 +360,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt toState = ETS_NORMAL; } else { - theme = pOpenThemeData(0, L"Button"); + theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Button"); if (element == PE_IndicatorRadioButton) partId = BP_RADIOBUTTON; else if (element == PE_IndicatorCheckBox) @@ -423,7 +373,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt } // Retrieve the transition time between the states from the system. - if (theme && pGetThemeTransitionDuration(theme, partId, fromState, toState, + if (theme && QWindowsXPStylePrivate::pGetThemeTransitionDuration(theme, partId, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) { t->setDuration(duration); @@ -459,9 +409,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme); static int decoration_size = 0; if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); - decoration_size = qMax(size.cx, size.cy); + XPThemeData themeSize = theme; + themeSize.partId = TVP_HOTGLYPH; + themeSize.stateId = GLPS_OPENED; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = 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; @@ -541,7 +493,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt EP_EDITBORDER_HVSCROLL, stateId, option->rect); // Since EP_EDITBORDER_HVSCROLL does not us borderfill, theme.noContent cannot be used for clipping int borderSize = 1; - pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); + QWindowsXPStylePrivate::pGetThemeInt(theme.handle(), theme.partId, theme.stateId, TMT_BORDERSIZE, &borderSize); QRegion clipRegion = option->rect; QRegion content = option->rect.adjusted(borderSize, borderSize, -borderSize, -borderSize); clipRegion ^= content; @@ -593,7 +545,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt return; } int bgType; - pGetThemeEnumValue( theme.handle(), + QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(), partId, stateId, TMT_BGTYPE, @@ -604,11 +556,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt QBrush fillColor = option->palette.brush(QPalette::Base); if (!isEnabled) { PROPERTYORIGIN origin = PO_NOTFOUND; - pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + QWindowsXPStylePrivate::pGetThemePropertyOrigin(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; - pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); } } @@ -944,11 +896,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption int duration = 0; - HTHEME theme = pOpenThemeData(0, L"Button"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(0, L"Button"); int fromState = buttonStateId(oldState, BP_PUSHBUTTON); int toState = buttonStateId(option->state, BP_PUSHBUTTON); - if (pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) + if (QWindowsXPStylePrivate::pGetThemeTransitionDuration(theme, BP_PUSHBUTTON, fromState, toState, TMT_TRANSITIONDURATIONS, &duration) == S_OK) t->setDuration(duration); else t->setDuration(0); @@ -1040,10 +992,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - SIZE size; - if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + mbiw = size.width(); + mbih = size.height(); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1233,13 +1185,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption // windows always has a check column, regardless whether we have an icon or not int checkcol = 25; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, int(3 + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1291,20 +1244,20 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); - SIZE size; - MARGINS margins; - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, - TMT_CONTENTMARGINS, NULL, &margins); - QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , - size.cy + margins.cyBottomHeight + margins.cyTopHeight); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, size.width() + margins.left() + margins.right(), + size.height() + margins.bottom() + margins.top()); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(0, 0, size.cx, size.cy); + checkRect = QRect(QPoint(0, 0), size); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1421,15 +1374,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } break; case CE_DockWidgetTitle: - if (const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget)) { + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { + const QDockWidget *dockWidget = qobject_cast<const QDockWidget *>(widget); QRect rect = option->rect; - if (dockWidget->isFloating()) { + if (dockWidget && dockWidget->isFloating()) { QWindowsXPStyle::drawControl(element, option, painter, widget); break; //otherwise fall through } - if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { - const QStyleOptionDockWidgetV2 *v2 = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(dwOpt); bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; @@ -1458,12 +1410,12 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QRect titleRect = r; if (dwOpt->closable) { - QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10)); + 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 = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); + QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10)); titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0); } @@ -1490,7 +1442,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } } break; - } #ifndef QT_NO_ITEMVIEWS case CE_ItemViewItem: { @@ -1806,7 +1757,6 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle stateId = SCRBS_NORMAL; // Draw handle - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; theme.stateId = stateId; d->drawBackground(theme); @@ -1815,29 +1765,21 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsXPStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) / 2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { @@ -1935,15 +1877,16 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); int minimumHeight; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); - sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(size.height() + margins.bottom() + margins.top(), sz.height()); + sz.rwidth() += size.width() + margins.left() + margins.right(); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { @@ -2003,7 +1946,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { MARGINS borderSize; - HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"Button"); if (theme) { int stateId = PBS_NORMAL; if (!(option->state & State_Enabled)) @@ -2018,7 +1961,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); rect = option->rect.adjusted(border, border, -border, -border); - int result = pGetThemeMargins(theme, + int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, @@ -2051,10 +1994,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - SIZE size; - if (pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - arrowWidth = size.cx; - arrowHeight = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + arrowWidth = size.width(); + arrowHeight = size.height(); } } if (option->state & State_Horizontal) { @@ -2247,7 +2190,8 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - int(QStyleHelper::dpiScaled(4)); const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; @@ -2320,28 +2264,36 @@ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl cont return QWindowsXPStyle::hitTestComplexControl(control, option, pos, widget); } -/*! - \internal - */ -int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +int QWindowsVistaStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm) { - if (!QWindowsVistaStylePrivate::useVista()) { - return QWindowsStyle::pixelMetric(metric, option, widget); - } - switch (metric) { - - case PM_DockWidgetTitleBarButtonMargin: - return int(QStyleHelper::dpiScaled(5.)); - case PM_ScrollBarSliderMin: - return int(QStyleHelper::dpiScaled(18.)); - case PM_MenuHMargin: - case PM_MenuVMargin: + 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 PM_MenuPanelWidth: + 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 = QWindowsStylePrivate::fixedPixelMetric(metric); + if (ret != QWindowsStylePrivate::InvalidMetric) + return int(QStyleHelper::dpiScaled(ret)); + return QWindowsXPStyle::pixelMetric(metric, option, widget); } @@ -2384,9 +2336,9 @@ void QWindowsVistaStyle::polish(QWidget *widget) //we do not have to care about unpolishing widget->setContentsMargins(3, 0, 4, 0); COLORREF bgRef; - HTHEME theme = pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); + HTHEME theme = QWindowsXPStylePrivate::pOpenThemeData(widget ? QWindowsVistaStylePrivate::winId(widget) : 0, L"TOOLTIP"); if (theme) { - if (pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemeColor(theme, TTP_STANDARD, TTSS_NORMAL, TMT_TEXTCOLOR, &bgRef) == S_OK) { QColor textColor = QColor::fromRgb(bgRef); QPalette pal; pal.setColor(QPalette::All, QPalette::ToolTipText, textColor); @@ -2494,7 +2446,6 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : QWindowsXPStylePrivate(), m_treeViewHelper(0) { - resolveSymbols(); } QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() @@ -2513,43 +2464,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const return false; } -/*! \internal - Returns \c true if all the necessary theme engine symbols were - resolved. -*/ -bool QWindowsVistaStylePrivate::resolveSymbols() -{ - static bool tried = false; - if (!tried) { - tried = true; - QSystemLibrary themeLib(QLatin1String("uxtheme")); - pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); - pIsThemePartDefined = (PtrIsThemePartDefined )themeLib.resolve("IsThemePartDefined"); - pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); - pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); - pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); - pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); - pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); - pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); - pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); - pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); - pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); - pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); - pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); - pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); - pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); - pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); - pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); - pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); - pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); - pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); - pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); - pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); - pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); - } - return pGetThemeTransitionDuration != 0; -} - /* * We need to set the windows "explorer" theme explicitly on a native * window and open the "TREEVIEW" theme handle passing its window handle @@ -2586,7 +2500,7 @@ bool QWindowsVistaStylePrivate::initTreeViewTheming() qWarning("%s: Unable to create the treeview helper window.", Q_FUNC_INFO); return false; } - const HRESULT hr = pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); + const HRESULT hr = QWindowsXPStylePrivate::pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); if (hr != S_OK) { qErrnoWarning("%s: SetWindowTheme() failed.", Q_FUNC_INFO); return false; @@ -2621,14 +2535,13 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); QIcon linkGlyph; - QPixmap pm = QPixmap(size.cx, size.cy); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h index f2f208fbb5..9f54ec8f21 100644 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p_p.h @@ -171,7 +171,7 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate public: QWindowsVistaStylePrivate(); ~QWindowsVistaStylePrivate(); - static bool resolveSymbols(); + static int fixedPixelMetric(QStyle::PixelMetric pm); static inline bool useVista(); bool transitionsEnabled() const; diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index e694eb4e7e..8dc3c6cb48 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -77,56 +77,76 @@ QT_BEGIN_NAMESPACE // Runtime resolved theme engine function calls -typedef bool (WINAPI *PtrIsAppThemed)(); -typedef bool (WINAPI *PtrIsThemeActive)(); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); -typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); -typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); -typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); -typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); -typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); -typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); -typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); -typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); -typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); -typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); -typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); -typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); -typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); -typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); -typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); -typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); -typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); -typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); - -static PtrIsAppThemed pIsAppThemed = 0; -static PtrIsThemeActive pIsThemeActive = 0; -static PtrOpenThemeData pOpenThemeData = 0; -static PtrCloseThemeData pCloseThemeData = 0; -static PtrDrawThemeBackground pDrawThemeBackground = 0; -static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx = 0; -static PtrGetCurrentThemeName pGetCurrentThemeName = 0; -static PtrGetThemeBool pGetThemeBool = 0; -static PtrGetThemeColor pGetThemeColor = 0; -static PtrGetThemeEnumValue pGetThemeEnumValue = 0; -static PtrGetThemeFilename pGetThemeFilename = 0; -static PtrGetThemeFont pGetThemeFont = 0; -static PtrGetThemeInt pGetThemeInt = 0; -static PtrGetThemeIntList pGetThemeIntList = 0; -static PtrGetThemeMargins pGetThemeMargins = 0; -static PtrGetThemeMetric pGetThemeMetric = 0; -static PtrGetThemePartSize pGetThemePartSize = 0; -static PtrGetThemePosition pGetThemePosition = 0; -static PtrGetThemePropertyOrigin pGetThemePropertyOrigin = 0; -static PtrGetThemeRect pGetThemeRect = 0; -static PtrGetThemeString pGetThemeString = 0; -static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion = 0; -static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty = 0; -static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent = 0; + +QWindowsUxThemeLib::PtrIsAppThemed QWindowsUxThemeLib::pIsAppThemed = Q_NULLPTR; +QWindowsUxThemeLib::PtrIsThemeActive QWindowsUxThemeLib::pIsThemeActive = Q_NULLPTR; +QWindowsUxThemeLib::PtrOpenThemeData QWindowsUxThemeLib::pOpenThemeData = Q_NULLPTR; +QWindowsUxThemeLib::PtrCloseThemeData QWindowsUxThemeLib::pCloseThemeData = Q_NULLPTR; +QWindowsUxThemeLib::PtrDrawThemeBackground QWindowsUxThemeLib::pDrawThemeBackground = Q_NULLPTR; +QWindowsUxThemeLib::PtrDrawThemeBackgroundEx QWindowsUxThemeLib::pDrawThemeBackgroundEx = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetCurrentThemeName QWindowsUxThemeLib::pGetCurrentThemeName = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeBool QWindowsUxThemeLib::pGetThemeBool = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeColor QWindowsUxThemeLib::pGetThemeColor = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeEnumValue QWindowsUxThemeLib::pGetThemeEnumValue = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeFilename QWindowsUxThemeLib::pGetThemeFilename = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeFont QWindowsUxThemeLib::pGetThemeFont = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeInt QWindowsUxThemeLib::pGetThemeInt = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeIntList QWindowsUxThemeLib::pGetThemeIntList = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeMargins QWindowsUxThemeLib::pGetThemeMargins = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeMetric QWindowsUxThemeLib::pGetThemeMetric = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePartSize QWindowsUxThemeLib::pGetThemePartSize = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePosition QWindowsUxThemeLib::pGetThemePosition = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemePropertyOrigin QWindowsUxThemeLib::pGetThemePropertyOrigin = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeRect QWindowsUxThemeLib::pGetThemeRect = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeString QWindowsUxThemeLib::pGetThemeString = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeBackgroundRegion QWindowsUxThemeLib::pGetThemeBackgroundRegion = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeDocumentationProperty QWindowsUxThemeLib::pGetThemeDocumentationProperty = Q_NULLPTR; +QWindowsUxThemeLib::PtrIsThemeBackgroundPartiallyTransparent + QWindowsUxThemeLib::pIsThemeBackgroundPartiallyTransparent = Q_NULLPTR; +QWindowsUxThemeLib::PtrSetWindowTheme QWindowsUxThemeLib::pSetWindowTheme = Q_NULLPTR; +QWindowsUxThemeLib::PtrGetThemeTransitionDuration QWindowsUxThemeLib::pGetThemeTransitionDuration = Q_NULLPTR; + +bool QWindowsUxThemeLib::resolveSymbols() +{ + static bool tried = false; + if (tried) + return pIsAppThemed != Q_NULLPTR; + tried = true; + QSystemLibrary themeLib(QLatin1String("uxtheme")); + if (!themeLib.load()) + return false; + pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); + if (!pIsAppThemed) + return false; + pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); + pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); + pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); + pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); + pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); + pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); + pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); + pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); + pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); + pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); + pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); + pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); + pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); + pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); + pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); + pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); + pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); + pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); + pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); + pGetThemeBackgroundRegion = (PtrGetThemeBackgroundRegion )themeLib.resolve("GetThemeBackgroundRegion"); + pGetThemeDocumentationProperty = (PtrGetThemeDocumentationProperty )themeLib.resolve("GetThemeDocumentationProperty"); + pIsThemeBackgroundPartiallyTransparent = (PtrIsThemeBackgroundPartiallyTransparent)themeLib.resolve("IsThemeBackgroundPartiallyTransparent"); + pSetWindowTheme = (PtrSetWindowTheme )themeLib.resolve("SetWindowTheme"); + if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) + pGetThemeTransitionDuration = (PtrGetThemeTransitionDuration)themeLib.resolve("GetThemeTransitionDuration"); + return true; +} // General const values static const int windowsItemFrame = 2; // menu item frame width @@ -211,7 +231,7 @@ RECT XPThemeData::toRECT(const QRect &qr) */ HRGN XPThemeData::mask(QWidget *widget) { - if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) + if (!QWindowsXPStylePrivate::pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) return 0; HRGN hrgn; @@ -219,7 +239,7 @@ HRGN XPThemeData::mask(QWidget *widget) if (widget) dc = hdcForWidgetBackingStore(widget); RECT nativeRect = toRECT(rect); - pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); + QWindowsXPStylePrivate::pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); return hrgn; } @@ -264,7 +284,7 @@ bool QWindowsXPStylePrivate::useXP(bool update) { if (!update) return use_xp; - return (use_xp = resolveSymbols() && pIsThemeActive() + return (use_xp = QWindowsUxThemeLib::resolveSymbols() && pIsThemeActive() && (pIsAppThemed() || !QApplication::instance())); } @@ -391,22 +411,21 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) 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 *) +const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { - SIZE sz; XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); + tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); - theme.rect = QRect(0, 0, sz.cx, sz.cy); + 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(sz.cx, 1); - painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); - painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); + 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; } @@ -1213,9 +1232,9 @@ void QWindowsXPStyle::polish(QWidget *widget) // Get text color for group box labels COLORREF cref; XPThemeData theme(0, 0, QWindowsXPStylePrivate::ButtonTheme, 0, 0); - pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); - pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); // Where does this color come from? //pGetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); @@ -1340,7 +1359,7 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget); rect = option->rect.adjusted(border, border, -border, -border); - int result = pGetThemeMargins(theme, + int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, @@ -1535,10 +1554,10 @@ case PE_Frame: else stateId = ETS_NORMAL; int fillType; - if (pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { + if (QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), partId, stateId, TMT_BGTYPE, &fillType) == S_OK) { if (fillType == BT_BORDERFILL) { COLORREF bcRef; - pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &bcRef); QColor bordercolor(qRgb(GetRValue(bcRef), GetGValue(bcRef), GetBValue(bcRef))); QPen oldPen = p->pen(); // int borderSize = 1; @@ -1619,7 +1638,7 @@ case PE_Frame: return; } int bgType; - pGetThemeEnumValue( theme.handle(), + QWindowsXPStylePrivate::pGetThemeEnumValue( theme.handle(), partId, stateId, TMT_BGTYPE, @@ -1636,11 +1655,11 @@ case PE_Frame: if (!isEnabled) { PROPERTYORIGIN origin = PO_NOTFOUND; - pGetThemePropertyOrigin(theme.handle(), theme.partId, theme.stateId, TMT_FILLCOLOR, &origin); + QWindowsXPStylePrivate::pGetThemePropertyOrigin(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; - pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); + QWindowsXPStylePrivate::pGetThemeColor(theme.handle(), partId, stateId, TMT_FILLCOLOR, &bgRef); fillColor = QBrush(qRgb(GetRValue(bgRef), GetGValue(bgRef), GetBValue(bgRef))); } } @@ -1666,7 +1685,7 @@ case PE_Frame: 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 (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { + if (QWindowsXPStylePrivate::pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { wchar_t *offset = 0; if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { offset++; @@ -1982,25 +2001,24 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op { themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; - SIZE sz; XPThemeData theme(0, p, themeNumber, partId, 0); - pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); - --sz.cy; + QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) { switch (sg->corner) { case Qt::BottomRightCorner: - rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size); break; case Qt::BottomLeftCorner: - rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size); hMirrored = true; break; case Qt::TopRightCorner: - rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size); vMirrored = true; break; case Qt::TopLeftCorner: - rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(rect.topLeft() + QPoint(1, 1), size); hMirrored = vMirrored = true; } } @@ -2055,10 +2073,9 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + mbiw = size.width(); + mbih = size.height(); } QRect ir = btn->rect; @@ -2450,10 +2467,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); int result = TST_NONE; - pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); if (result != TST_NONE) { COLORREF textShadowRef; - pGetThemeColor(theme.handle(), WP_SMALLCAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QWindowsXPStylePrivate::pGetThemeColor(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), @@ -2741,7 +2758,6 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo stateId = SCRBS_NORMAL; // Draw handle - theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget); theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT; theme.stateId = stateId; d->drawBackground(theme); @@ -2750,28 +2766,19 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - - - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) /2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty()) { @@ -3062,10 +3069,10 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget); int result = TST_NONE; - pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); + QWindowsXPStylePrivate::pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result); if (result != TST_NONE) { COLORREF textShadowRef; - pGetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef); + QWindowsXPStylePrivate::pGetThemeColor(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(), @@ -3093,9 +3100,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } else { theme.partId = partId; theme.stateId = stateId; - SIZE sz; - pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); - if (sz.cx == 0 || sz.cy == 0) { + 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(); @@ -3310,23 +3315,63 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } +static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0) +{ + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) + return pb2->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 = 0; + int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); + if (res != QWindowsStylePrivate::InvalidMetric) + return res / QWindowsStylePrivate::devicePixelRatio(widget); + + res = 0; switch (pm) { case PM_MenuBarPanelWidth: + case PM_ButtonDefaultIndicator: res = 0; break; case PM_DefaultFrameWidth: - if (qobject_cast<const QListView*>(widget)) - res = 2; - else - res = 1; + res = qobject_cast<const QListView*>(widget) ? 2 : 1; break; case PM_MenuPanelWidth: case PM_SpinBoxFrameWidth: @@ -3344,6 +3389,8 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con switch (tab->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: res = 1; break; case QTabBar::RoundedSouth: @@ -3354,10 +3401,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con case QTabBar::TriangularEast: res = 3; break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - res = 1; - break; } } break; @@ -3366,77 +3409,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); break; - case PM_IndicatorWidth: - case PM_IndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ExclusiveIndicatorWidth: - case PM_ExclusiveIndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ProgressBarChunkWidth: - { - Qt::Orientation orient = Qt::Horizontal; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) - orient = pb2->orientation; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ProgressTheme, - (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (orient == Qt::Horizontal) ? size.cx : size.cy; - } - } - break; - - case PM_SliderThickness: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, - TKP_THUMB); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cy; - } - } - break; - - case PM_TitleBarHeight: - { - if (widget && (widget->windowType() == Qt::Tool)) - res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - else - res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - } - break; - - case PM_MdiSubWindowFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); - res = size.cx-1; - } - } - break; - case PM_MdiSubWindowMinimizedWidth: res = 160; break; @@ -3447,33 +3419,14 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con break; #endif // QT_NO_TOOLBAR - case PM_DockWidgetFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cx; - } - } - break; case PM_DockWidgetSeparatorExtent: - res = int(QStyleHelper::dpiScaled(4.)); - break; case PM_DockWidgetTitleMargin: res = int(QStyleHelper::dpiScaled(4.)); break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: - if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) - res = 1; - else - res = 0; - break; - - case PM_ButtonDefaultIndicator: - res = 0; + res = qstyleoption_cast<const QStyleOptionToolButton *>(option) ? 1 : 0; break; default: @@ -3553,8 +3506,11 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + const int buttonMargin = int(QStyleHelper::dpiScaled(4)); + int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); @@ -3746,20 +3702,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt case CT_LineEdit: case CT_ComboBox: { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme); - HTHEME theme = buttontheme.handle(); - MARGINS borderSize; - if (theme) { - int result = pGetThemeMargins(theme, - NULL, - BP_PUSHBUTTON, - PBS_NORMAL, - TMT_CONTENTMARGINS, - NULL, - &borderSize); - if (result == S_OK) { - sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, - borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); + XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); + if (buttontheme.isValid()) { + const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!borderSize.isNull()) { + sz.rwidth() += borderSize.left() + borderSize.right() - 2; + sz.rheight() += borderSize.bottom() + borderSize.top() - 2; } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3929,9 +3877,8 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE sz; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); - return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } } @@ -3964,13 +3911,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - SIZE size; - pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -3999,14 +3945,13 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; theme.partId = WP_CLOSEBUTTON; // #### - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4036,13 +3981,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - SIZE size; - pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 7327fa5581..6e1cfe6db5 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -219,9 +219,19 @@ public: HRGN mask(QWidget *widget); HTHEME handle(); - RECT toRECT(const QRect &qr); + static RECT toRECT(const QRect &qr); bool isValid(); + QSize size(); + QMargins margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMargins margins(int propId = TMT_CONTENTMARGINS); + + static QSize themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMargins 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 QMargins 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; @@ -282,7 +292,65 @@ struct ThemeMapData { hasAlphaChannel(false), wasAlphaSwapped(false), hadInvalidAlpha(false) {} }; -class QWindowsXPStylePrivate : public QWindowsStylePrivate +struct QWindowsUxThemeLib { + typedef bool (WINAPI *PtrIsAppThemed)(); + typedef bool (WINAPI *PtrIsThemeActive)(); + typedef HTHEME (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); + typedef HRESULT (WINAPI *PtrCloseThemeData)(HTHEME hTheme); + typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); + typedef HRESULT (WINAPI *PtrDrawThemeBackgroundEx)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const DTBGOPTS *pOptions); + typedef HRESULT (WINAPI *PtrGetCurrentThemeName)(OUT LPWSTR pszThemeFileName, int cchMaxNameChars, OUT OPTIONAL LPWSTR pszColorBuff, int cchMaxColorChars, OUT OPTIONAL LPWSTR pszSizeBuff, int cchMaxSizeChars); + typedef HRESULT (WINAPI *PtrGetThemeDocumentationProperty)(LPCWSTR pszThemeName, LPCWSTR pszPropertyName, OUT LPWSTR pszValueBuff, int cchMaxValChars); + typedef HRESULT (WINAPI *PtrGetThemeBool)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT BOOL *pfVal); + typedef HRESULT (WINAPI *PtrGetThemeColor)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); + typedef HRESULT (WINAPI *PtrGetThemeEnumValue)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemeFilename)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszThemeFileName, int cchMaxBuffChars); + typedef HRESULT (WINAPI *PtrGetThemeFont)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT LOGFONT *pFont); + typedef HRESULT (WINAPI *PtrGetThemeInt)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemeIntList)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT INTLIST *pIntList); + typedef HRESULT (WINAPI *PtrGetThemeMargins)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OPTIONAL RECT *prc, OUT MARGINS *pMargins); + typedef HRESULT (WINAPI *PtrGetThemeMetric)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, OUT int *piVal); + typedef HRESULT (WINAPI *PtrGetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); + typedef HRESULT (WINAPI *PtrGetThemePosition)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT POINT *pPoint); + typedef HRESULT (WINAPI *PtrGetThemePropertyOrigin)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT enum PROPERTYORIGIN *pOrigin); + typedef HRESULT (WINAPI *PtrGetThemeRect)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT RECT *pRect); + typedef HRESULT (WINAPI *PtrGetThemeString)(HTHEME hTheme, int iPartId, int iStateId, int iPropId, OUT LPWSTR pszBuff, int cchMaxBuffChars); + typedef HRESULT (WINAPI *PtrGetThemeBackgroundRegion)(HTHEME hTheme, OPTIONAL HDC hdc, int iPartId, int iStateId, const RECT *pRect, OUT HRGN *pRegion); + typedef BOOL (WINAPI *PtrIsThemeBackgroundPartiallyTransparent)(HTHEME hTheme, int iPartId, int iStateId); + typedef HRESULT (WINAPI *PtrSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + typedef HRESULT (WINAPI *PtrGetThemeTransitionDuration)(HTHEME hTheme, int iPartId, int iStateFromId, int iStateToId, int iPropId, int *pDuration); + + static bool resolveSymbols(); + + static PtrIsAppThemed pIsAppThemed; + static PtrIsThemeActive pIsThemeActive; + static PtrOpenThemeData pOpenThemeData; + static PtrCloseThemeData pCloseThemeData; + static PtrDrawThemeBackground pDrawThemeBackground; + static PtrDrawThemeBackgroundEx pDrawThemeBackgroundEx; + static PtrGetCurrentThemeName pGetCurrentThemeName; + static PtrGetThemeBool pGetThemeBool; + static PtrGetThemeColor pGetThemeColor; + static PtrGetThemeEnumValue pGetThemeEnumValue; + static PtrGetThemeFilename pGetThemeFilename; + static PtrGetThemeFont pGetThemeFont; + static PtrGetThemeInt pGetThemeInt; + static PtrGetThemeIntList pGetThemeIntList; + static PtrGetThemeMargins pGetThemeMargins; + static PtrGetThemeMetric pGetThemeMetric; + static PtrGetThemePartSize pGetThemePartSize; + static PtrGetThemePosition pGetThemePosition; + static PtrGetThemePropertyOrigin pGetThemePropertyOrigin; + static PtrGetThemeRect pGetThemeRect; + static PtrGetThemeString pGetThemeString; + static PtrGetThemeBackgroundRegion pGetThemeBackgroundRegion; + static PtrGetThemeDocumentationProperty pGetThemeDocumentationProperty; + static PtrIsThemeBackgroundPartiallyTransparent pIsThemeBackgroundPartiallyTransparent; + static PtrSetWindowTheme pSetWindowTheme; + static PtrGetThemeTransitionDuration pGetThemeTransitionDuration; // Windows Vista onwards. +}; + +class QWindowsXPStylePrivate : public QWindowsStylePrivate, public QWindowsUxThemeLib { Q_DECLARE_PUBLIC(QWindowsXPStyle) public: @@ -316,6 +384,9 @@ public: ~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); @@ -374,6 +445,60 @@ private: static HTHEME m_themes[NThemes]; }; +inline QSize XPThemeData::size() +{ + QSize result(0, 0); + if (isValid()) { + SIZE size; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) + result = QSize(size.cx, size.cy); + } + return result; +} + +inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + RECT rect = XPThemeData::toRECT(qRect); + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, &rect, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QMargins XPThemeData::margins(int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.size(); +} + +inline QMargins 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 QMargins 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 // QT_NO_STYLE_WINDOWS QT_END_NAMESPACE |