204 lines
9.6 KiB
C++
204 lines
9.6 KiB
C++
#include "ElaMenuStyle.h"
|
|
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QStyleOption>
|
|
|
|
#include "ElaMenu.h"
|
|
#include "ElaTheme.h"
|
|
ElaMenuStyle::ElaMenuStyle(QStyle *style) {
|
|
_pMenuItemHeight = 32;
|
|
_themeMode = eTheme->getThemeMode();
|
|
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
|
}
|
|
|
|
ElaMenuStyle::~ElaMenuStyle() {}
|
|
|
|
void ElaMenuStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
|
|
switch (element) {
|
|
case QStyle::PE_PanelMenu: {
|
|
// 高性能阴影
|
|
painter->save();
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
eTheme->drawEffectShadow(painter, option->rect, _shadowBorderWidth, 6);
|
|
// 背景绘制
|
|
QRect foregroundRect(_shadowBorderWidth, _shadowBorderWidth, option->rect.width() - 2 * _shadowBorderWidth,
|
|
option->rect.height() - 2 * _shadowBorderWidth);
|
|
painter->setPen(ElaThemeColor(_themeMode, PopupBorder));
|
|
painter->setBrush(ElaThemeColor(_themeMode, PopupBase));
|
|
painter->drawRoundedRect(foregroundRect, 6, 6);
|
|
painter->restore();
|
|
return;
|
|
}
|
|
case QStyle::PE_FrameMenu: {
|
|
return;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
|
}
|
|
|
|
void ElaMenuStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const {
|
|
switch (element) {
|
|
case QStyle::CE_MenuItem: {
|
|
// 内容绘制 区分类型
|
|
if (const QStyleOptionMenuItem *mopt = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
|
if (mopt->menuItemType == QStyleOptionMenuItem::Separator) {
|
|
QRect separatorRect = mopt->rect;
|
|
painter->save();
|
|
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
|
painter->setPen(Qt::NoPen);
|
|
painter->setBrush(ElaThemeColor(_themeMode, BasicBaseLine));
|
|
painter->drawRoundedRect(QRectF(separatorRect.x() + separatorRect.width() * 0.055, separatorRect.center().y(),
|
|
separatorRect.width() - separatorRect.width() * 0.11, 1.5),
|
|
1, 1);
|
|
painter->restore();
|
|
return;
|
|
} else {
|
|
QRect menuRect = mopt->rect;
|
|
qreal contentPadding = menuRect.width() * 0.055;
|
|
qreal textLeftSpacing = 8;
|
|
painter->save();
|
|
painter->setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing);
|
|
// 覆盖效果
|
|
if (mopt->state.testFlag(QStyle::State_Enabled) &&
|
|
(mopt->state.testFlag(QStyle::State_MouseOver) || mopt->state.testFlag(QStyle::State_Selected))) {
|
|
QRect hoverRect = menuRect;
|
|
hoverRect.adjust(0, 2, 0, -2);
|
|
painter->setPen(Qt::NoPen);
|
|
painter->setBrush(ElaThemeColor(_themeMode, PopupHover));
|
|
painter->drawRoundedRect(hoverRect, 5, 5);
|
|
}
|
|
// Icon绘制
|
|
QIcon menuIcon = mopt->icon;
|
|
// check绘制
|
|
if (mopt->menuHasCheckableItems) {
|
|
painter->save();
|
|
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray
|
|
: _themeMode == ElaThemeType::Light ? Qt::black
|
|
: Qt::white);
|
|
QFont iconFont = QFont("ElaAwesome");
|
|
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
|
|
painter->setFont(iconFont);
|
|
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter,
|
|
mopt->checked ? QChar((unsigned short)ElaIconType::Check) : QChar((unsigned short)ElaIconType::None));
|
|
painter->restore();
|
|
} else {
|
|
QString iconText;
|
|
const ElaMenu *menu = dynamic_cast<const ElaMenu *>(widget);
|
|
if (menu) {
|
|
QAction *action = menu->actionAt(menuRect.center());
|
|
if (action) {
|
|
iconText = action->property("ElaIconType").toString();
|
|
}
|
|
}
|
|
if (!iconText.isEmpty()) {
|
|
painter->save();
|
|
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray
|
|
: _themeMode == ElaThemeType::Light ? Qt::black
|
|
: Qt::white);
|
|
QFont iconFont = QFont("ElaAwesome");
|
|
iconFont.setPixelSize(_pMenuItemHeight * 0.57);
|
|
painter->setFont(iconFont);
|
|
painter->drawText(QRectF(menuRect.x() + contentPadding, menuRect.y(), _iconWidth, menuRect.height()), Qt::AlignCenter,
|
|
iconText);
|
|
painter->restore();
|
|
} else {
|
|
if (!menuIcon.isNull()) {
|
|
painter->drawPixmap(QRect(menuRect.x() + contentPadding, menuRect.center().y() - _iconWidth / 2, _iconWidth, _iconWidth),
|
|
menuIcon.pixmap(_iconWidth, _iconWidth));
|
|
}
|
|
}
|
|
}
|
|
// 文字和快捷键绘制
|
|
if (!mopt->text.isEmpty()) {
|
|
QStringList textList = mopt->text.split("\t");
|
|
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray
|
|
: _themeMode == ElaThemeType::Light ? Qt::black
|
|
: Qt::white);
|
|
|
|
painter->drawText(QRectF(menuRect.x() + (_isAnyoneItemHasIcon ? contentPadding + textLeftSpacing : 0) + _iconWidth, menuRect.y(),
|
|
menuRect.width(), menuRect.height()),
|
|
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, textList[0]);
|
|
if (textList.count() > 1) {
|
|
painter->drawText(QRectF(menuRect.x() + contentPadding + _iconWidth + textLeftSpacing, menuRect.y(),
|
|
menuRect.width() - (contentPadding * 2 + _iconWidth + textLeftSpacing), menuRect.height()),
|
|
Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, textList[1]);
|
|
}
|
|
}
|
|
// 展开图标
|
|
if (mopt->menuItemType == QStyleOptionMenuItem::SubMenu) {
|
|
painter->save();
|
|
painter->setPen(!mopt->state.testFlag(QStyle::State_Enabled) ? Qt::gray
|
|
: _themeMode == ElaThemeType::Light ? Qt::black
|
|
: Qt::white);
|
|
QFont iconFont = QFont("ElaAwesome");
|
|
iconFont.setPixelSize(18);
|
|
painter->setFont(iconFont);
|
|
painter->drawText(QRect(menuRect.right() - 25, menuRect.y(), 25, menuRect.height()), Qt::AlignVCenter,
|
|
QChar((unsigned short)ElaIconType::AngleRight));
|
|
painter->restore();
|
|
}
|
|
painter->restore();
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
case QStyle::CE_MenuEmptyArea: {
|
|
return;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
QProxyStyle::drawControl(element, option, painter, widget);
|
|
}
|
|
|
|
int ElaMenuStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const {
|
|
switch (metric) {
|
|
case QStyle::PM_SmallIconSize: {
|
|
// 图标宽度
|
|
_iconWidth = _pMenuItemHeight * 0.7;
|
|
return _iconWidth;
|
|
}
|
|
case QStyle::PM_MenuPanelWidth: {
|
|
// 外围容器宽度
|
|
return _shadowBorderWidth * 1.5;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return QProxyStyle::pixelMetric(metric, option, widget);
|
|
}
|
|
|
|
QSize ElaMenuStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const {
|
|
switch (type) {
|
|
case QStyle::CT_MenuItem: {
|
|
if (const QStyleOptionMenuItem *mopt = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
|
if (mopt->menuItemType == QStyleOptionMenuItem::Separator) {
|
|
break;
|
|
}
|
|
QSize menuItemSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
|
const ElaMenu *menu = dynamic_cast<const ElaMenu *>(widget);
|
|
if (menu->isHasIcon() || mopt->menuHasCheckableItems) {
|
|
_isAnyoneItemHasIcon = true;
|
|
}
|
|
if (menu->isHasChildMenu()) {
|
|
return QSize(menuItemSize.width() + 20, _pMenuItemHeight);
|
|
} else {
|
|
return QSize(menuItemSize.width(), _pMenuItemHeight);
|
|
}
|
|
}
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return QProxyStyle::sizeFromContents(type, option, size, widget);
|
|
}
|