Files
cbh/ElaWidgetTools/DeveloperComponents/ElaComboBoxStyle.cpp
2025-09-20 01:41:33 +08:00

217 lines
9.2 KiB
C++

#include "ElaComboBoxStyle.h"
#include <QDebug>
#include <QPainter>
#include <QPainterPath>
#include <QStyleOption>
#include "ElaTheme.h"
ElaComboBoxStyle::ElaComboBoxStyle(QStyle *style) {
_pExpandIconRotate = 0;
_pExpandMarkWidth = 0;
_themeMode = eTheme->getThemeMode();
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
}
ElaComboBoxStyle::~ElaComboBoxStyle() {}
void ElaComboBoxStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
switch (element) {
case QStyle::PE_Widget:
case QStyle::PE_PanelLineEdit: {
return;
}
#ifndef Q_OS_WIN
case PE_PanelMenu: {
return;
}
case PE_IndicatorArrowDown: {
return;
}
#endif
default: {
break;
}
}
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
void ElaComboBoxStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
switch (element) {
case QStyle::CE_ComboBoxLabel: {
return;
}
case QStyle::CE_ShapedFrame: {
// container区域
if (widget->objectName() == "ElaComboBoxContainer") {
QRect viewRect = option->rect;
painter->save();
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
eTheme->drawEffectShadow(painter, viewRect, _shadowBorderWidth, 6);
QRect foregroundRect(viewRect.x() + _shadowBorderWidth, viewRect.y(), viewRect.width() - 2 * _shadowBorderWidth,
viewRect.height() - _shadowBorderWidth);
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
painter->setBrush(ElaThemeColor(_themeMode, PopupBase));
painter->drawRoundedRect(foregroundRect, 3, 3);
painter->restore();
}
return;
}
case QStyle::CE_ItemViewItem: {
// 覆盖高亮
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
int margin = 2;
painter->save();
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter->setPen(Qt::NoPen);
QPainterPath path;
QRect optionRect = option->rect;
optionRect.adjust(margin, margin, -margin, -margin);
#ifndef Q_OS_WIN
optionRect.adjust(6, 0, -6, 0);
#endif
path.addRoundedRect(optionRect, 5, 5);
if (option->state & QStyle::State_Selected) {
if (option->state & QStyle::State_MouseOver) {
// 选中时覆盖
painter->setBrush(ElaThemeColor(_themeMode, BasicSelectedHoverAlpha));
painter->drawPath(path);
} else {
// 选中
painter->setBrush(ElaThemeColor(_themeMode, BasicSelectedAlpha));
painter->drawPath(path);
}
// 选中Mark
painter->setPen(Qt::NoPen);
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
painter->drawRoundedRect(
QRectF(optionRect.x() + 3, optionRect.y() + optionRect.height() * 0.2, 3, optionRect.height() - +optionRect.height() * 0.4), 2,
2);
} else {
if (option->state & QStyle::State_MouseOver) {
// 覆盖时颜色
painter->setBrush(ElaThemeColor(_themeMode, BasicHoverAlpha));
painter->drawPath(path);
}
}
// 文字绘制
painter->setPen(ElaThemeColor(_themeMode, BasicText));
painter->drawText(QRect(option->rect.x() + 15, option->rect.y(), option->rect.width() - 15, option->rect.height()), Qt::AlignVCenter,
vopt->text);
painter->restore();
}
return;
}
default: {
break;
}
}
QProxyStyle::drawControl(element, option, painter, widget);
}
void ElaComboBoxStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const {
switch (control) {
case QStyle::CC_ComboBox: {
// 主体显示绘制
if (const QStyleOptionComboBox *copt = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
painter->save();
painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
// 背景绘制
bool isEnabled = copt->state.testFlag(QStyle::State_Enabled);
painter->setPen(ElaThemeColor(_themeMode, BasicBorder));
painter->setBrush(isEnabled ? (copt->state.testFlag(QStyle::State_HasFocus) && copt->editable) ? ElaThemeColor(_themeMode, DialogBase)
: copt->state.testFlag(QStyle::State_MouseOver) ? ElaThemeColor(_themeMode, BasicHover)
: ElaThemeColor(_themeMode, BasicBase)
: ElaThemeColor(_themeMode, BasicDisable));
QRect comboBoxRect = copt->rect;
comboBoxRect.adjust(_shadowBorderWidth, 1, -_shadowBorderWidth, -1);
painter->drawRoundedRect(comboBoxRect, 3, 3);
// 底边线绘制
painter->setPen(ElaThemeColor(_themeMode, BasicBaseLine));
painter->drawLine(comboBoxRect.x() + 3, comboBoxRect.y() + comboBoxRect.height(), comboBoxRect.x() + comboBoxRect.width() - 3,
comboBoxRect.y() + comboBoxRect.height());
// 文字绘制
if (!copt->editable) {
QRect textRect = subControlRect(QStyle::CC_ComboBox, copt, QStyle::SC_ScrollBarSubLine, widget);
painter->setPen(isEnabled ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable));
painter->drawText(textRect, Qt::AlignVCenter | Qt::AlignLeft, copt->currentText);
}
// 展开指示器绘制
painter->setPen(Qt::NoPen);
painter->setBrush(ElaThemeColor(_themeMode, PrimaryNormal));
painter->drawRoundedRect(
QRectF(comboBoxRect.center().x() - _pExpandMarkWidth, comboBoxRect.y() + comboBoxRect.height() - 3, _pExpandMarkWidth * 2, 3), 2, 2);
// 展开图标绘制
QRect expandIconRect = subControlRect(QStyle::CC_ComboBox, copt, QStyle::SC_ScrollBarAddPage, widget);
if (expandIconRect.isValid()) {
QFont iconFont = QFont("ElaAwesome");
iconFont.setPixelSize(17);
painter->setFont(iconFont);
painter->setPen(isEnabled ? ElaThemeColor(_themeMode, BasicText) : ElaThemeColor(_themeMode, BasicTextDisable));
painter->translate(expandIconRect.x() + (qreal)expandIconRect.width() / 2, expandIconRect.y() + (qreal)expandIconRect.height() / 2);
painter->rotate(_pExpandIconRotate);
painter->translate(-expandIconRect.x() - (qreal)expandIconRect.width() / 2, -expandIconRect.y() - (qreal)expandIconRect.height() / 2);
painter->drawText(expandIconRect, Qt::AlignCenter, QChar((unsigned short)ElaIconType::AngleDown));
painter->restore();
}
}
return;
}
default: {
break;
}
}
QProxyStyle::drawComplexControl(control, option, painter, widget);
}
QRect ElaComboBoxStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const {
switch (cc) {
case QStyle::CC_ComboBox: {
switch (sc) {
case QStyle::SC_ScrollBarSubLine: {
// 文字区域
QRect textRect = QProxyStyle::subControlRect(cc, opt, sc, widget);
textRect.setLeft(16);
textRect.setRight(textRect.right() - 15);
return textRect;
}
case QStyle::SC_ScrollBarAddPage: {
// 展开图标区域
QRect expandIconRect = QProxyStyle::subControlRect(cc, opt, sc, widget);
expandIconRect.setLeft(expandIconRect.left() - 25);
return expandIconRect;
}
default: {
break;
}
}
break;
}
default: {
break;
}
}
return QProxyStyle::subControlRect(cc, opt, sc, widget);
}
QSize ElaComboBoxStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const {
switch (type) {
case QStyle::CT_ItemViewItem: {
QSize itemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
itemSize.setHeight(35);
return itemSize;
}
case QStyle::CT_ComboBox: {
QSize comboBoxSize = QProxyStyle::sizeFromContents(type, option, size, widget);
comboBoxSize.setWidth(comboBoxSize.width() + 26);
return comboBoxSize;
}
default: {
break;
}
}
return QProxyStyle::sizeFromContents(type, option, size, widget);
}