#include "ElaToolButtonStyle.h" #include #include #include #include #include #include "ElaTheme.h" ElaToolButtonStyle::ElaToolButtonStyle(QStyle *style) { _pIsSelected = false; _pIsTransparent = true; _pExpandIconRotate = 0; _pBorderRadius = 4; _themeMode = eTheme->getThemeMode(); connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; }); } ElaToolButtonStyle::~ElaToolButtonStyle() {} void ElaToolButtonStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { switch (control) { case QStyle::CC_ToolButton: { // 内容绘制 if (const QStyleOptionToolButton *bopt = qstyleoption_cast(option)) { if (bopt->arrowType != Qt::NoArrow) { break; } QRect toolButtonRect = bopt->rect; if (!_pIsTransparent) { // 边框距离 toolButtonRect.adjust(1, 1, -1, -1); } painter->save(); painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); painter->setPen(_pIsTransparent ? Qt::transparent : ElaThemeColor(_themeMode, BasicBorder)); // 背景绘制 if (bopt->state.testFlag(QStyle::State_Enabled)) { if (bopt->state.testFlag(QStyle::State_Sunken)) { painter->setBrush(_pIsTransparent ? ElaThemeColor(_themeMode, BasicPressAlpha) : ElaThemeColor(_themeMode, BasicPress)); painter->drawRoundedRect(toolButtonRect, _pBorderRadius, _pBorderRadius); } else { if (_pIsSelected) { painter->setBrush(_pIsTransparent ? ElaThemeColor(_themeMode, BasicSelectedAlpha) : ElaThemeColor(_themeMode, BasicHover)); painter->drawRoundedRect(toolButtonRect, _pBorderRadius, _pBorderRadius); } else { if (bopt->state.testFlag(QStyle::State_MouseOver) || bopt->state.testFlag(QStyle::State_On)) { painter->setBrush(_pIsTransparent ? ElaThemeColor(_themeMode, BasicHoverAlpha) : ElaThemeColor(_themeMode, BasicHover)); painter->drawRoundedRect(toolButtonRect, _pBorderRadius, _pBorderRadius); } else { if (!_pIsTransparent) { painter->setBrush(ElaThemeColor(_themeMode, BasicBase)); painter->drawRoundedRect(toolButtonRect, _pBorderRadius, _pBorderRadius); // 底边线绘制 painter->setPen(ElaThemeColor(_themeMode, BasicBaseLine)); painter->drawLine(toolButtonRect.x() + _pBorderRadius, toolButtonRect.y() + toolButtonRect.height(), toolButtonRect.x() + toolButtonRect.width() - _pBorderRadius, toolButtonRect.y() + toolButtonRect.height()); } } } } } // 指示器绘制 _drawIndicator(painter, bopt, widget); // 图标绘制 QRect contentRect = subControlRect(control, bopt, QStyle::SC_ScrollBarAddLine, widget); int heightOffset = contentRect.height() * 0.05; contentRect.adjust(0, heightOffset, 0, -heightOffset); _drawIcon(painter, contentRect, bopt, widget); // 文字绘制 _drawText(painter, contentRect, bopt); painter->restore(); } return; } default: { break; } } QProxyStyle::drawComplexControl(control, option, painter, widget); } QSize ElaToolButtonStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const { if (type == QStyle::CT_ToolButton) { if (const QStyleOptionToolButton *bopt = qstyleoption_cast(option)) { QSize toolButtonSize = QProxyStyle::sizeFromContents(type, option, size, widget); if (bopt->features.testFlag(QStyleOptionToolButton::HasMenu) && !bopt->features.testFlag(QStyleOptionToolButton::MenuButtonPopup)) { toolButtonSize.setWidth(toolButtonSize.width() + _contentMargin + 0.65 * std::min(bopt->iconSize.width(), bopt->iconSize.height())); } return toolButtonSize; } } return QProxyStyle::sizeFromContents(type, option, size, widget); } void ElaToolButtonStyle::_drawIndicator(QPainter *painter, const QStyleOptionToolButton *bopt, const QWidget *widget) const { if (bopt->features.testFlag(QStyleOptionToolButton::MenuButtonPopup)) { QRect indicatorRect = subControlRect(QStyle::CC_ToolButton, bopt, QStyle::SC_ScrollBarSubLine, widget); // 指示器区域 if (bopt->state.testFlag(QStyle::State_Enabled) && bopt->activeSubControls.testFlag(QStyle::SC_ScrollBarSubLine)) { painter->setBrush(ElaThemeColor(_themeMode, BasicIndicator)); QPainterPath path; path.moveTo(indicatorRect.topLeft()); path.lineTo(indicatorRect.right() - 4, indicatorRect.y()); path.arcTo(QRect(indicatorRect.right() - 8, indicatorRect.y(), 8, 8), 90, -90); path.lineTo(indicatorRect.right(), indicatorRect.bottom() - 4); path.arcTo(QRect(indicatorRect.right() - 8, indicatorRect.bottom() - 8, 8, 8), 0, -90); path.lineTo(indicatorRect.bottomLeft()); path.closeSubpath(); painter->drawPath(path); } // 指示器 painter->setBrush(bopt->state.testFlag(QStyle::State_Enabled) ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable)); QPainterPath indicatorPath; qreal indicatorHeight = qCos(30 * M_PI / 180.0) * indicatorRect.width() * 0.85; indicatorPath.moveTo(indicatorRect.x() + indicatorRect.width() * 0.15, indicatorRect.center().y()); indicatorPath.lineTo(indicatorRect.right() - indicatorRect.width() * 0.15, indicatorRect.center().y()); indicatorPath.lineTo(indicatorRect.center().x(), indicatorRect.center().y() + indicatorHeight / 2); indicatorPath.closeSubpath(); painter->drawPath(indicatorPath); } else if (bopt->features.testFlag(QStyleOptionToolButton::HasMenu)) { // 展开指示器 QSize iconSize = bopt->iconSize; painter->save(); QRect toolButtonRect = bopt->rect; QFont iconFont = QFont("ElaAwesome"); iconFont.setPixelSize(0.75 * std::min(iconSize.width(), iconSize.height())); painter->setFont(iconFont); int indicatorWidth = painter->fontMetrics().horizontalAdvance(QChar((unsigned short)ElaIconType::AngleDown)); QRect expandIconRect(toolButtonRect.right() - _contentMargin - indicatorWidth, toolButtonRect.y() + 1, indicatorWidth, toolButtonRect.height()); painter->setPen(ElaThemeColor(_themeMode, BasicText)); painter->translate(expandIconRect.center().x(), expandIconRect.y() + (qreal)expandIconRect.height() / 2); painter->rotate(_pExpandIconRotate); painter->translate(-expandIconRect.center().x() - 1, -expandIconRect.y() - (qreal)expandIconRect.height() / 2); painter->drawText(expandIconRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::AngleDown)); painter->restore(); } } void ElaToolButtonStyle::_drawIcon(QPainter *painter, QRectF iconRect, const QStyleOptionToolButton *bopt, const QWidget *widget) const { if (bopt->toolButtonStyle != Qt::ToolButtonTextOnly) { QSize iconSize = bopt->iconSize; if (widget->property("ElaIconType").toString().isEmpty()) { // 绘制QIcon QIcon icon = bopt->icon; if (!icon.isNull()) { QPixmap iconPix = icon.pixmap(iconSize, (bopt->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled, (bopt->state & State_Selected) ? QIcon::On : QIcon::Off); switch (bopt->toolButtonStyle) { case Qt::ToolButtonIconOnly: { painter->drawPixmap(QRect(QPoint(iconRect.x(), iconRect.center().y() - iconSize.height() / 2), iconSize), iconPix); break; } case Qt::ToolButtonFollowStyle: case Qt::ToolButtonTextBesideIcon: { painter->drawPixmap(QRect(QPoint(iconRect.x() + _contentMargin, iconRect.center().y() - iconSize.height() / 2), iconSize), iconPix); break; } case Qt::ToolButtonTextUnderIcon: { if (bopt->features.testFlag(QStyleOptionToolButton::HasMenu) && !bopt->features.testFlag(QStyleOptionToolButton::MenuButtonPopup)) { iconRect.setRight(iconRect.right() - _calculateExpandIndicatorWidth(bopt, painter)); } painter->drawPixmap(QRect(QPoint(iconRect.center().x() - iconSize.width() / 2, iconRect.y()), iconSize), iconPix); break; } default: { break; } } } } else { // 绘制ElaIcon painter->save(); if (bopt->state.testFlag(QStyle::State_Enabled)) { painter->setPen(ElaThemeColor(_themeMode, BasicText)); } else { painter->setPen(ElaThemeColor(_themeMode, BasicTextDisable)); } QFont iconFont = QFont("ElaAwesome"); switch (bopt->toolButtonStyle) { case Qt::ToolButtonIconOnly: { iconFont.setPixelSize(0.75 * std::min(iconSize.width(), iconSize.height())); painter->setFont(iconFont); painter->drawText(iconRect, Qt::AlignCenter, widget->property("ElaIconType").toString()); break; } case Qt::ToolButtonFollowStyle: case Qt::ToolButtonTextBesideIcon: { QRect adjustIconRect(iconRect.x() + _contentMargin, iconRect.y(), iconSize.width(), iconRect.height()); iconFont.setPixelSize(0.75 * std::min(iconSize.width(), iconSize.height())); painter->setFont(iconFont); painter->drawText(adjustIconRect, Qt::AlignCenter, widget->property("ElaIconType").toString()); break; } case Qt::ToolButtonTextUnderIcon: { if (bopt->features.testFlag(QStyleOptionToolButton::HasMenu) && !bopt->features.testFlag(QStyleOptionToolButton::MenuButtonPopup)) { iconRect.setRight(iconRect.right() - _calculateExpandIndicatorWidth(bopt, painter)); } QRect adjustIconRect(iconRect.center().x() - iconSize.width() / 2, iconRect.y() + 0.2 * std::min(iconSize.width(), iconSize.height()), iconSize.width(), iconSize.height()); iconFont.setPixelSize(0.8 * std::min(iconSize.width(), iconSize.height())); painter->setFont(iconFont); painter->drawText(adjustIconRect, Qt::AlignHCenter, widget->property("ElaIconType").toString()); break; } default: { break; } } painter->restore(); } } } void ElaToolButtonStyle::_drawText(QPainter *painter, QRect contentRect, const QStyleOptionToolButton *bopt) const { if (!bopt->text.isEmpty()) { if (bopt->state.testFlag(QStyle::State_Enabled)) { painter->setPen(ElaThemeColor(_themeMode, BasicText)); } else { painter->setPen(ElaThemeColor(_themeMode, BasicTextDisable)); } switch (bopt->toolButtonStyle) { case Qt::ToolButtonTextOnly: { contentRect.setLeft(contentRect.left() + _contentMargin); painter->drawText(contentRect, Qt::AlignLeft | Qt::AlignVCenter, bopt->text); break; } case Qt::ToolButtonTextBesideIcon: { painter->drawText(QRect(contentRect.x() + _contentMargin * 2 + bopt->iconSize.width(), contentRect.y(), contentRect.width() - bopt->iconSize.width(), contentRect.height()), Qt::AlignLeft | Qt::AlignVCenter, bopt->text); break; } case Qt::ToolButtonTextUnderIcon: { if (bopt->features.testFlag(QStyleOptionToolButton::HasMenu) && !bopt->features.testFlag(QStyleOptionToolButton::MenuButtonPopup)) { contentRect.setLeft(contentRect.left() + _contentMargin); painter->drawText(contentRect, Qt::AlignBottom | Qt::AlignLeft, bopt->text); } else { painter->drawText(contentRect, Qt::AlignBottom | Qt::AlignHCenter, bopt->text); } break; } case Qt::ToolButtonFollowStyle: { break; } default: { break; } } } } qreal ElaToolButtonStyle::_calculateExpandIndicatorWidth(const QStyleOptionToolButton *bopt, QPainter *painter) const { // 展开指示器 QSize iconSize = bopt->iconSize; painter->save(); QFont iconFont = QFont("ElaAwesome"); iconFont.setPixelSize(0.75 * std::min(iconSize.width(), iconSize.height())); painter->setFont(iconFont); int indicatorWidth = painter->fontMetrics().horizontalAdvance(QChar((unsigned short)ElaIconType::AngleDown)); painter->restore(); return indicatorWidth; }