Files
o3de/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/PushButton.cpp
T
Steve Pham 38261d0800 Shorten copyright headers by splitting into 2 lines (#2213)
* Updated all copyright headers to split the longer original copyright line into 2 shorter lines

Signed-off-by: Steve Pham <spham@amazon.com>
2021-07-16 15:25:48 -07:00

724 lines
25 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Casting/numeric_cast.h>
#include <AzQtComponents/Components/ConfigHelpers.h>
#include <AzQtComponents/Components/Style.h>
#include <AzQtComponents/Components/Widgets/PushButton.h>
#include <QDialogButtonBox>
#include <QImage>
#include <QPainter>
#include <QPixmap>
#include <QPixmapCache>
#include <QPushButton>
#include <QSettings>
#include <QStyleFactory>
#include <QStyleOption>
#include <QToolButton>
#include <QVariant>
#include <QtWidgets/private/qstyle_p.h>
#include <QtWidgets/private/qstylehelper_p.h>
namespace AzQtComponents
{
static QString g_primaryClass = QStringLiteral("Primary");
static QString g_smallIconClass = QStringLiteral("SmallIcon");
void PushButton::applyPrimaryStyle(QPushButton* button)
{
button->setDefault(true);
}
void PushButton::applySmallIconStyle(QToolButton* button)
{
Style::addClass(button, g_smallIconClass);
}
template <typename Button>
bool buttonHasMenu(Button* button)
{
if (button != nullptr)
{
return button->menu();
}
return false;
}
bool PushButton::polish(Style* style, QWidget* widget, const PushButton::Config& config)
{
QToolButton* toolButton = qobject_cast<QToolButton*>(widget);
QPushButton* pushButton = qobject_cast<QPushButton*>(widget);
if (pushButton != nullptr)
{
// Edge cases for dialog box buttons.
QDialogButtonBox* dialogButtonBox = qobject_cast<QDialogButtonBox*>(widget->parent());
// Detect if this is the first button in a dialog box.
bool isFirstInDialog = (dialogButtonBox != nullptr) &&
(dialogButtonBox->nextInFocusChain() == pushButton);
// Detect if other buttons in the dialog box have been marked as default.
bool otherButtonInDialogIsDefault = false;
if (dialogButtonBox != nullptr)
{
for (auto dialogButton : dialogButtonBox->buttons())
{
QPushButton* dialogPushButton = qobject_cast<QPushButton*>(dialogButton);
if (dialogPushButton && dialogPushButton->isDefault())
{
otherButtonInDialogIsDefault = true;
}
}
}
// For dialogs, highlight the first button if no default button has been specified.
if (pushButton->isDefault() || (isFirstInDialog && !otherButtonInDialogIsDefault))
{
AzQtComponents::Style::addClass(pushButton, g_primaryClass);
}
else
{
AzQtComponents::Style::removeClass(pushButton, g_primaryClass);
}
}
if ((style->hasClass(widget, g_smallIconClass) && (toolButton != nullptr)))
{
widget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
bool hasMenu = buttonHasMenu(toolButton) || buttonHasMenu(pushButton);
widget->setMaximumSize(config.smallIcon.width + (hasMenu ? config.smallIcon.arrowWidth : 0), config.smallIcon.frame.height);
style->repolishOnSettingsChange(widget);
return true;
}
else if (pushButton != nullptr)
{
widget->setMaximumHeight(config.defaultFrame.height);
return true;
}
return false;
}
int PushButton::buttonMargin(const Style* style, const QStyleOption* option, const QWidget* widget, const PushButton::Config& config)
{
Q_UNUSED(option);
if (style->hasClass(widget, g_smallIconClass))
{
return config.smallIcon.frame.margin;
}
int margin = -1;
const QPushButton* pushButton = qobject_cast<const QPushButton*>(widget);
if (pushButton && !pushButton->isFlat())
{
margin = config.defaultFrame.margin;
}
return margin;
}
QSize PushButton::sizeFromContents(const Style* style, QStyle::ContentsType type, const QStyleOption* option, const QSize& size, const QWidget* widget, const PushButton::Config& config)
{
QSize sz = style->QProxyStyle::sizeFromContents(type, option, size, widget);
const QPushButton* pushButton = qobject_cast<const QPushButton*>(widget);
if (style->hasClass(widget, g_smallIconClass))
{
sz.setHeight(config.smallIcon.frame.height);
}
else if (pushButton && !pushButton->isFlat())
{
sz.setHeight(config.defaultFrame.height);
}
return sz;
}
int PushButton::menuButtonIndicatorWidth(const Style* style, const QStyleOption* option, const QWidget* widget, const Config& config)
{
Q_UNUSED(style);
Q_UNUSED(option);
int size = -1;
if (auto pushButton = qobject_cast<const QPushButton*>(widget))
{
size = config.dropdownButton.menuIndicatorWidth;
}
return size;
}
bool PushButton::drawPushButtonBevel(const Style* style, const QStyleOption* option, QPainter* painter, const QWidget* widget, const PushButton::Config& config)
{
Q_UNUSED(style);
const auto* button = qobject_cast<const QPushButton*>(widget);
if (!button || button->isFlat())
{
return false;
}
const auto* buttonOption = qstyleoption_cast<const QStyleOptionButton*>(option);
const bool isDisabled = !(option->state & QStyle::State_Enabled);
Border border = isDisabled ? config.disabledBorder : config.defaultBorder;
if (!button->isFlat())
{
QRectF r = option->rect.adjusted(0, 0, -1, -1);
bool isSmallIconButton = style->hasClass(widget, g_smallIconClass);
QColor gradientStartColor;
QColor gradientEndColor;
const bool isPrimary = (style->hasClass(widget, g_primaryClass));
selectColors(option, isPrimary ? config.primary : config.secondary, isDisabled, gradientStartColor, gradientEndColor);
if (option->state & QStyle::State_HasFocus)
{
border = config.focusedBorder;
}
float radius = isSmallIconButton ? aznumeric_cast<float>(config.smallIcon.frame.radius) : aznumeric_cast<float>(config.defaultFrame.radius);
drawFilledFrame(painter, r, gradientStartColor, gradientEndColor, border, radius);
}
if (buttonOption->features & QStyleOptionButton::HasMenu)
{
const int mbi = style->pixelMetric(QStyle::PM_MenuButtonIndicator, buttonOption, widget);
QRect arrowRect(0, 0, mbi, mbi);
QRect contentRect = option->rect.adjusted(0, 0, -1, -1); // As above
arrowRect.moveCenter(contentRect.center());
arrowRect.moveRight(contentRect.right() - (config.dropdownButton.menuIndicatorPadding + border.thickness));
QStyleOptionButton downArrow = *buttonOption;
downArrow.rect = arrowRect;
style->drawPrimitive(QStyle::PE_IndicatorArrowDown, &downArrow, painter, widget);
}
return true;
}
bool PushButton::drawToolButton(const Style* style, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget, const PushButton::Config& config)
{
if (style->hasClass(widget, g_smallIconClass))
{
drawSmallIconButton(style, option, painter, widget, config);
return true;
}
const bool drawFrame = false;
drawSmallIconButton(style, option, painter, widget, config, drawFrame);
return true;
}
bool PushButton::drawIndicatorArrowDown(const Style* style, const QStyleOption* option, QPainter* painter, const QWidget* widget, const Config& config)
{
auto pushButton = qobject_cast<const QPushButton*>(widget);
if (!pushButton)
{
return false;
}
// If it's got the small icon class, arrow drawing is already done in drawToolButton
if (style->hasClass(widget, g_smallIconClass))
{
return true;
}
QIcon::Mode mode = option->state & QStyle::State_Enabled
? QIcon::Normal
: QIcon::Disabled;
const auto pixmap = style->generatedIconPixmap(mode, config.dropdownButton.indicatorArrowDown, option);
painter->drawPixmap(option->rect, pixmap, pixmap.rect());
return true;
}
bool PushButton::drawPushButtonFocusRect(const Style* /*style*/, const QStyleOption* /*option*/, QPainter* /*painter*/, const QWidget* widget, const PushButton::Config& /*config*/)
{
const auto* button = qobject_cast<const QPushButton*>(widget);
if (!button)
{
return false;
}
// no frame; handled when the bevel is drawn
return true;
}
QPixmap PushButton::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap, const QStyleOption* option, const Config& config)
{
Q_UNUSED(option);
if (iconMode == QIcon::Normal)
{
return pixmap;
}
QColor color;
switch(iconMode)
{
case QIcon::Disabled:
{
color = config.iconButton.disabledColor;
break;
}
case QIcon::Active:
{
color = config.iconButton.activeColor;
break;
}
case QIcon::Selected:
{
color = config.iconButton.selectedColor;
break;
}
default:
{
return pixmap;
}
}
QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
for (int y=0; y < image.height(); ++y)
{
auto scanLine = reinterpret_cast<QRgb*>(image.scanLine(y));
for (int x=0; x < image.width(); ++x)
{
QRgb pixel = *scanLine;
color.setAlpha(qAlpha(pixel));
*scanLine = color.rgba();
++scanLine;
}
}
return QPixmap::fromImage(image);
}
static void ReadFrame(QSettings& settings, const QString& name, PushButton::Frame& frame)
{
settings.beginGroup(name);
ConfigHelpers::read<int>(settings, QStringLiteral("Height"), frame.height);
ConfigHelpers::read<int>(settings, QStringLiteral("Radius"), frame.radius);
ConfigHelpers::read<int>(settings, QStringLiteral("Margin"), frame.margin);
settings.endGroup();
}
static void ReadGradient(QSettings& settings, const QString& name, PushButton::Gradient& gradient)
{
settings.beginGroup(name);
ConfigHelpers::read<QColor>(settings, QStringLiteral("Start"), gradient.start);
ConfigHelpers::read<QColor>(settings, QStringLiteral("End"), gradient.end);
settings.endGroup();
}
static void ReadButtonColorSet(QSettings& settings, const QString& name, PushButton::ColorSet& colorSet)
{
settings.beginGroup(name);
ReadGradient(settings, QStringLiteral("Disabled"), colorSet.disabled);
ReadGradient(settings, QStringLiteral("Sunken"), colorSet.sunken);
ReadGradient(settings, QStringLiteral("Hovered"), colorSet.hovered);
ReadGradient(settings, QStringLiteral("Normal"), colorSet.normal);
settings.endGroup();
}
static void ReadBorder(QSettings& settings, const QString& name, PushButton::Border& border)
{
settings.beginGroup(name);
ConfigHelpers::read<int>(settings, QStringLiteral("Thickness"), border.thickness);
ConfigHelpers::read<QColor>(settings, QStringLiteral("Color"), border.color);
settings.endGroup();
}
static void ReadSmallIcon(QSettings& settings, const QString& name, PushButton::SmallIcon& smallIcon)
{
settings.beginGroup(name);
ReadFrame(settings, "Frame", smallIcon.frame);
ConfigHelpers::read<QColor>(settings, QStringLiteral("EnabledArrowColor"), smallIcon.enabledArrowColor);
ConfigHelpers::read<QColor>(settings, QStringLiteral("DisabledArrowColor"), smallIcon.disabledArrowColor);
ConfigHelpers::read<int>(settings, QStringLiteral("Width"), smallIcon.width);
ConfigHelpers::read<int>(settings, QStringLiteral("ArrowWidth"), smallIcon.arrowWidth);
settings.endGroup();
}
static void ReadIconButton(QSettings& settings, const QString& name, PushButton::IconButton& iconButton)
{
ConfigHelpers::GroupGuard group(&settings, name);
ConfigHelpers::read<QColor>(settings, QStringLiteral("ActiveColor"), iconButton.activeColor);
ConfigHelpers::read<QColor>(settings, QStringLiteral("DisabledColor"), iconButton.disabledColor);
ConfigHelpers::read<QColor>(settings, QStringLiteral("SelectedColor"), iconButton.selectedColor);
}
static void ReadDropdownButton(QSettings& settings, const QString& name, PushButton::DropdownButton& dropdownButton)
{
ConfigHelpers::GroupGuard group(&settings, name);
ConfigHelpers::read<QPixmap>(settings, QStringLiteral("IndicatorArrowDown"), dropdownButton.indicatorArrowDown);
ConfigHelpers::read<int>(settings, QStringLiteral("MenuIndicatorWidth"), dropdownButton.menuIndicatorWidth);
ConfigHelpers::read<int>(settings, QStringLiteral("MenuIndicatorPadding"), dropdownButton.menuIndicatorPadding);
}
PushButton::Config PushButton::loadConfig(QSettings& settings)
{
Config config = defaultConfig();
ReadButtonColorSet(settings, QStringLiteral("PrimaryColorSet"), config.primary);
ReadButtonColorSet(settings, QStringLiteral("SecondaryColorSet"), config.secondary);
ReadBorder(settings, QStringLiteral("Border"), config.defaultBorder);
ReadBorder(settings, QStringLiteral("DisabledBorder"), config.disabledBorder);
ReadBorder(settings, QStringLiteral("FocusedBorder"), config.focusedBorder);
ReadFrame(settings, QStringLiteral("DefaultFrame"), config.defaultFrame);
ReadSmallIcon(settings, QStringLiteral("SmallIcon"), config.smallIcon);
ReadIconButton(settings, QStringLiteral("IconButton"), config.iconButton);
ReadDropdownButton(settings, QStringLiteral("DropdownButton"), config.dropdownButton);
return config;
}
PushButton::Config PushButton::defaultConfig()
{
Config config;
config.primary.disabled.start = QColor("#978DAA");
config.primary.disabled.end = QColor("#978DAA");
config.primary.sunken.start = QColor("#4D2F7B");
config.primary.sunken.end = QColor("#4D2F7B");
config.primary.hovered.start = QColor("#9F7BD7");
config.primary.hovered.end = QColor("#8B6EBA");
config.primary.normal.start = QColor("#8156CF");
config.primary.normal.end = QColor("#6441A4");
config.secondary.disabled.start = QColor("#666666");
config.secondary.disabled.end = QColor("#666666");
config.secondary.sunken.start = QColor("#444444");
config.secondary.sunken.end = QColor("#444444");
config.secondary.hovered.start = QColor("#888888");
config.secondary.hovered.end = QColor("#777777");
config.secondary.normal.start = QColor("#777777");
config.secondary.normal.end = QColor("#666666");
config.defaultBorder.thickness = 1;
config.defaultBorder.color = QColor("#000000");
config.disabledBorder.thickness = config.defaultBorder.thickness;
config.disabledBorder.color = QColor("#222222");
config.focusedBorder.thickness = 2;
config.focusedBorder.color = QColor("#C8ABFF");
config.defaultFrame.height = 32;
config.defaultFrame.radius = 4;
config.defaultFrame.margin = 4;
config.smallIcon.frame.height = 24;
config.smallIcon.frame.radius = 2;
config.smallIcon.frame.margin = 4;
config.smallIcon.enabledArrowColor = QColor("#FFFFFF");
config.smallIcon.disabledArrowColor = QColor("#BBBBBB");
config.smallIcon.width = 24;
config.smallIcon.arrowWidth = 10;
config.iconButton.activeColor = QColor("#94D2FF");
config.iconButton.disabledColor = QColor("#999999");
config.iconButton.selectedColor = QColor("#FFFFFF");
config.dropdownButton.indicatorArrowDown = QPixmap(QStringLiteral(":/stylesheet/img/UI20/dropdown-button-arrow.svg"));
config.dropdownButton.menuIndicatorWidth = 16;
config.dropdownButton.menuIndicatorPadding = 4;
return config;
}
void PushButton::drawSmallIconButton(const Style* style, const QStyleOption* option, QPainter* painter, const QWidget* widget, const PushButton::Config& config, bool drawFrame)
{
// Draws the icon and the arrow drop down together, as per the spec, which calls for no separating borders
// between the icon and the arrow.
// There aren't enough controls exposed via CSS to do this in a stylesheet.
if (const QStyleOptionToolButton* buttonOption = qstyleoption_cast<const QStyleOptionToolButton*>(option))
{
QRect buttonArea = style->subControlRect(QStyle::CC_ToolButton, buttonOption, QStyle::SC_ToolButton, widget);
QRect menuArea = style->subControlRect(QStyle::CC_ToolButton, buttonOption, QStyle::SC_ToolButtonMenu, widget);
QRect totalArea = buttonArea;
int menuButtonIndicator = style->pixelMetric(QStyle::PM_MenuButtonIndicator, buttonOption, widget);
if (!(buttonOption->subControls & QStyle::SC_ToolButtonMenu) && (buttonOption->features & QStyleOptionToolButton::HasMenu))
{
// replicating what the Qt Fusion style does
QRect ir = buttonOption->rect;
menuArea = QRect(ir.right() + 5 - menuButtonIndicator, ir.y() + ir.height() - menuButtonIndicator + 4, menuButtonIndicator - 6, menuButtonIndicator - 6);
}
QStyle::State bflags = buttonOption->state & ~QStyle::State_Sunken;
if (bflags & QStyle::State_AutoRaise)
{
if (!(bflags & QStyle::State_MouseOver) || !(bflags & QStyle::State_Enabled))
{
bflags &= ~QStyle::State_Raised;
}
}
QStyle::State mflags = bflags;
if (buttonOption->state & QStyle::State_Sunken)
{
if (buttonOption->activeSubControls & QStyle::SC_ToolButton)
{
bflags |= QStyle::State_Sunken;
}
mflags |= QStyle::State_Sunken;
}
// check if we need to deal with the menu at all
if ((buttonOption->subControls & QStyle::SC_ToolButtonMenu) || (buttonOption->features & QStyleOptionToolButton::HasMenu))
{
totalArea = buttonArea.united(menuArea);
}
if (drawFrame)
{
drawSmallIconFrame(style, option, totalArea, painter, config);
}
drawSmallIconLabel(style, buttonOption, bflags, buttonArea, painter, widget, config);
drawSmallIconArrow(style, buttonOption, mflags, menuArea, painter, widget, config);
}
}
void PushButton::drawSmallIconFrame(const Style* style, const QStyleOption* option, const QRect& frame, QPainter* painter, const PushButton::Config& config)
{
Q_UNUSED(style);
bool isDisabled = !(option->state & QStyle::State_Enabled);
PushButton::Border border = isDisabled ? config.disabledBorder : config.defaultBorder;
if (option->state & QStyle::State_HasFocus)
{
border = config.focusedBorder;
}
QColor gradientStartColor;
QColor gradientEndColor;
selectColors(option, config.secondary, isDisabled, gradientStartColor, gradientEndColor);
float radius = aznumeric_cast<float>(config.smallIcon.frame.radius);
drawFilledFrame(painter, frame, gradientStartColor, gradientEndColor, border, radius);
}
void PushButton::drawSmallIconLabel(const Style* style, const QStyleOptionToolButton* buttonOption, QStyle::State state, const QRect& buttonArea, QPainter* painter, const QWidget* widget, const PushButton::Config& config)
{
Q_UNUSED(config);
QStyleOptionToolButton label = *buttonOption;
label.state = state;
int fw = style->pixelMetric(QStyle::PM_DefaultFrameWidth, buttonOption, widget);
label.rect = buttonArea.adjusted(fw, fw, -fw, -fw);
style->drawControl(QStyle::CE_ToolButtonLabel, &label, painter, widget);
}
static QRect defaultArrowRect(const QStyleOptionToolButton* buttonOption)
{
static const QRect rect {0, 0, qRound(QStyleHelper::dpiScaled(14, QStyleHelper::dpi(buttonOption))), qRound(QStyleHelper::dpiScaled(8, QStyleHelper::dpi(buttonOption)))};
return rect;
}
static QPixmap initializeDownArrowPixmap(const QColor& arrowColor, const QStyleOptionToolButton* buttonOption, const QRect& rect, Qt::ArrowType type = Qt::DownArrow)
{
const int arrowWidth = aznumeric_cast<int>(QStyleHelper::dpiScaled(14, QStyleHelper::dpi(buttonOption)));
const int arrowHeight = aznumeric_cast<int>(QStyleHelper::dpiScaled(8, QStyleHelper::dpi(buttonOption)));
const int arrowMax = qMin(arrowHeight, arrowWidth);
const int rectMax = qMin(rect.height(), rect.width());
const int size = qMin(arrowMax, rectMax);
QPixmap cachePixmap;
cachePixmap = styleCachePixmap(rect.size());
cachePixmap.fill(Qt::transparent);
QPainter cachePainter(&cachePixmap);
QRectF arrowRect;
arrowRect.setWidth(size);
arrowRect.setHeight(arrowHeight * size / arrowWidth);
if (type == Qt::LeftArrow || type == Qt::RightArrow)
arrowRect = arrowRect.transposed();
arrowRect.moveTo((rect.width() - arrowRect.width()) / 2.0,
(rect.height() - arrowRect.height()) / 2.0);
QPolygonF triangle;
triangle.reserve(3);
switch (type) {
case Qt::DownArrow:
triangle << arrowRect.topLeft() << arrowRect.topRight() << QPointF(arrowRect.center().x(), arrowRect.bottom());
break;
case Qt::RightArrow:
triangle << arrowRect.topLeft() << arrowRect.bottomLeft() << QPointF(arrowRect.right(), arrowRect.center().y());
break;
case Qt::LeftArrow:
triangle << arrowRect.topRight() << arrowRect.bottomRight() << QPointF(arrowRect.left(), arrowRect.center().y());
break;
default:
triangle << arrowRect.bottomLeft() << arrowRect.bottomRight() << QPointF(arrowRect.center().x(), arrowRect.top());
break;
}
cachePainter.setPen(Qt::NoPen);
cachePainter.setBrush(arrowColor);
cachePainter.setRenderHint(QPainter::Antialiasing);
cachePainter.drawPolygon(triangle);
return cachePixmap;
}
static void drawArrow(const Style* style, const QStyleOptionToolButton* buttonOption, QPainter* painter, const QRect& rect, const QColor& arrowColor)
{
Q_UNUSED(style);
QString downArrowCacheKey = QStringLiteral("AzQtComponents::PushButton::DownArrow%1").arg(arrowColor.rgba());
QPixmap arrowPixmap;
if (!QPixmapCache::find(downArrowCacheKey, &arrowPixmap))
{
arrowPixmap = initializeDownArrowPixmap(arrowColor, buttonOption, defaultArrowRect(buttonOption));
QPixmapCache::insert(downArrowCacheKey, arrowPixmap);
}
QRect arrowRect;
int imageMax = qMin(arrowPixmap.height(), arrowPixmap.width());
int rectMax = qMin(rect.height(), rect.width());
int size = qMin(imageMax, rectMax);
arrowRect.setWidth(size);
arrowRect.setHeight(size);
if (arrowPixmap.width() > arrowPixmap.height())
{
arrowRect.setHeight(arrowPixmap.height() * size / arrowPixmap.width());
}
else
{
arrowRect.setWidth(arrowPixmap.width() * size / arrowPixmap.height());
}
arrowRect.moveTopLeft(rect.center() - arrowRect.center());
// force the arrow to the bottom
arrowRect.moveTop(rect.bottom() - arrowRect.height() - 1);
arrowRect.moveLeft(rect.left());
QRectF offsetArrowRect = arrowRect;
painter->save();
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::Antialiasing);
painter->drawPixmap(offsetArrowRect, arrowPixmap, QRectF(QPointF(0, 0), arrowPixmap.size()));
painter->restore();
}
void PushButton::drawSmallIconArrow(const Style* style, const QStyleOptionToolButton* buttonOption, QStyle::State state, const QRect& inputArea, QPainter* painter, const QWidget* widget, const PushButton::Config& config)
{
Q_UNUSED(config);
Q_UNUSED(widget);
Q_UNUSED(style);
// non-const version of area rect
QRect menuArea = inputArea;
bool isDisabled = !(state & QStyle::State_Enabled);
QColor color = isDisabled ? config.smallIcon.disabledArrowColor : config.smallIcon.enabledArrowColor;
bool paintArrow = false;
if (buttonOption->subControls & QStyle::SC_ToolButtonMenu)
{
if (state & (QStyle::State_Sunken | QStyle::State_On | QStyle::State_Raised))
{
paintArrow = true;
}
}
else if (buttonOption->features & QStyleOptionToolButton::HasMenu)
{
paintArrow = true;
}
if (paintArrow)
{
drawArrow(style, buttonOption, painter, menuArea, color);
}
}
void PushButton::drawFilledFrame(QPainter* painter, const QRectF& rect, const QColor& gradientStartColor, const QColor& gradientEndColor, const PushButton::Border& border, float radius)
{
painter->save();
QPainterPath path;
painter->setRenderHint(QPainter::Antialiasing);
QPen pen(border.color, border.thickness);
pen.setCosmetic(true);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
// offset the frame so that it smudges and anti-aliases a bit better
path.addRoundedRect(rect.adjusted(0.5, 0.5, -0.5f, -0.5f), radius, radius);
QLinearGradient background(rect.topLeft(), rect.bottomLeft());
background.setColorAt(0, gradientStartColor);
background.setColorAt(1, gradientEndColor);
painter->fillPath(path, background);
painter->drawPath(path);
painter->restore();
}
void PushButton::selectColors(const QStyleOption* option, const PushButton::ColorSet& colorSet, bool isDisabled, QColor& gradientStartColor, QColor& gradientEndColor)
{
if (isDisabled)
{
gradientStartColor = colorSet.disabled.start;
gradientEndColor = colorSet.disabled.end;
}
else if (option->state & QStyle::State_Sunken)
{
gradientStartColor = colorSet.sunken.start;
gradientEndColor = colorSet.sunken.end;
}
else if (option->state & QStyle::State_MouseOver)
{
gradientStartColor = colorSet.hovered.start;
gradientEndColor = colorSet.hovered.end;
}
else
{
gradientStartColor = colorSet.normal.start;
gradientEndColor = colorSet.normal.end;
}
}
} // namespace AzQtComponents