framelesshelper/src/widgets/standardsystembutton.cpp

561 lines
14 KiB
C++

/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "standardsystembutton.h"
#include "standardsystembutton_p.h"
#include <QtGui/qpainter.h>
#include <QtWidgets/qtooltip.h>
#include <framelessmanager_p.h>
#include <utils.h>
FRAMELESSHELPER_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcStandardSystemButton, "wangwenx190.framelesshelper.widgets.standardsystembutton")
#define INFO qCInfo(lcStandardSystemButton)
#define DEBUG qCDebug(lcStandardSystemButton)
#define WARNING qCWarning(lcStandardSystemButton)
#define CRITICAL qCCritical(lcStandardSystemButton)
using namespace Global;
StandardSystemButtonPrivate::StandardSystemButtonPrivate(StandardSystemButton *q) : QObject(q)
{
Q_ASSERT(q);
if (!q) {
return;
}
q_ptr = q;
initialize();
}
StandardSystemButtonPrivate::~StandardSystemButtonPrivate() = default;
StandardSystemButtonPrivate *StandardSystemButtonPrivate::get(StandardSystemButton *pub)
{
Q_ASSERT(pub);
if (!pub) {
return nullptr;
}
return pub->d_func();
}
const StandardSystemButtonPrivate *StandardSystemButtonPrivate::get(const StandardSystemButton *pub)
{
Q_ASSERT(pub);
if (!pub) {
return nullptr;
}
return pub->d_func();
}
QString StandardSystemButtonPrivate::getCode() const
{
return m_code;
}
void StandardSystemButtonPrivate::setCode(const QString &value)
{
Q_ASSERT(!value.isEmpty());
if (value.isEmpty()) {
return;
}
if (m_code == value) {
return;
}
m_code = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->codeChanged();
}
SystemButtonType StandardSystemButtonPrivate::getButtonType() const
{
return m_buttonType;
}
void StandardSystemButtonPrivate::setButtonType(const SystemButtonType type)
{
Q_ASSERT(type != SystemButtonType::Unknown);
if (type == SystemButtonType::Unknown) {
return;
}
if (m_buttonType == type) {
return;
}
m_buttonType = type;
setCode(Utils::getSystemButtonIconCode(m_buttonType));
Q_Q(StandardSystemButton);
q->update();
}
QSize StandardSystemButtonPrivate::getRecommendedButtonSize() const
{
return kDefaultSystemButtonSize;
}
bool StandardSystemButtonPrivate::isHovered() const
{
return m_hovered;
}
bool StandardSystemButtonPrivate::isPressed() const
{
return m_pressed;
}
QColor StandardSystemButtonPrivate::getHoverColor() const
{
return m_hoverColor;
}
QColor StandardSystemButtonPrivate::getPressColor() const
{
return m_pressColor;
}
QColor StandardSystemButtonPrivate::getNormalColor() const
{
return m_normalColor;
}
QColor StandardSystemButtonPrivate::getActiveForegroundColor() const
{
return m_activeForegroundColor;
}
QColor StandardSystemButtonPrivate::getInactiveForegroundColor() const
{
return m_inactiveForegroundColor;
}
bool StandardSystemButtonPrivate::isActive() const
{
return m_active;
}
int StandardSystemButtonPrivate::iconSize2() const
{
return m_iconSize2.value_or(FramelessManagerPrivate::getIconFont().pointSize());
}
void StandardSystemButtonPrivate::setHovered(const bool value)
{
if (m_hovered == value) {
return;
}
m_hovered = value;
Q_Q(StandardSystemButton);
q->update();
if (m_hovered) {
const QString toolTip = q->toolTip();
if (!toolTip.isEmpty() && !QToolTip::isVisible()) {
const int yPos = [q]() -> int {
static const int h = kDefaultSystemButtonSize.height();
if (const QWidget * const window = q->window()) {
if (Utils::windowStatesToWindowState(window->windowState()) == Qt::WindowMaximized) {
return qRound(h * 0.5);
}
}
return -qRound(h * 1.3);
}();
QToolTip::showText(q->mapToGlobal(QPoint(-2, yPos)), toolTip, q, q->geometry());
}
} else {
if (QToolTip::isVisible()) {
QToolTip::hideText();
}
}
Q_EMIT q->hoveredChanged();
}
void StandardSystemButtonPrivate::setPressed(const bool value)
{
if (m_pressed == value) {
return;
}
m_pressed = value;
Q_Q(StandardSystemButton);
q->setDown(m_pressed);
q->update();
Q_EMIT q->pressedChanged();
if (m_pressed) {
Q_EMIT q->pressed();
} else {
Q_EMIT q->released();
}
}
void StandardSystemButtonPrivate::setHoverColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_hoverColor == value) {
return;
}
m_hoverColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->hoverColorChanged();
}
void StandardSystemButtonPrivate::setPressColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_pressColor == value) {
return;
}
m_pressColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->pressColorChanged();
}
void StandardSystemButtonPrivate::setNormalColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_normalColor == value) {
return;
}
m_normalColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->normalColorChanged();
}
void StandardSystemButtonPrivate::setActiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_activeForegroundColor == value) {
return;
}
m_activeForegroundColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->activeForegroundColorChanged();
}
void StandardSystemButtonPrivate::setInactiveForegroundColor(const QColor &value)
{
Q_ASSERT(value.isValid());
if (!value.isValid()) {
return;
}
if (m_inactiveForegroundColor == value) {
return;
}
m_inactiveForegroundColor = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->inactiveForegroundColorChanged();
}
void StandardSystemButtonPrivate::setActive(const bool value)
{
if (m_active == value) {
return;
}
m_active = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->activeChanged();
}
void StandardSystemButtonPrivate::setIconSize2(const int value)
{
Q_ASSERT(value > 0);
if (value <= 0) {
return;
}
if (iconSize2() == value) {
return;
}
m_iconSize2 = value;
Q_Q(StandardSystemButton);
q->update();
Q_EMIT q->iconSize2Changed();
}
void StandardSystemButtonPrivate::enterEventHandler(QT_ENTER_EVENT_TYPE *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
setHovered(true);
}
void StandardSystemButtonPrivate::leaveEventHandler(QEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
setHovered(false);
}
void StandardSystemButtonPrivate::paintEventHandler(QPaintEvent *event)
{
Q_ASSERT(event);
if (!event) {
return;
}
Q_Q(StandardSystemButton);
QPainter painter(q);
painter.save();
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing
| QPainter::SmoothPixmapTransform);
const QColor backgroundColor = [this]() -> QColor {
// The pressed state has higher priority than the hovered state.
if (m_pressed && m_pressColor.isValid()) {
return m_pressColor;
}
if (m_hovered && m_hoverColor.isValid()) {
return m_hoverColor;
}
if (m_normalColor.isValid()) {
return m_normalColor;
}
return {};
}();
const QRect buttonRect = {QPoint(0, 0), q->size()};
if (backgroundColor.isValid()) {
painter.fillRect(buttonRect, backgroundColor);
}
if (!m_code.isEmpty()) {
painter.setPen([this]() -> QColor {
if (!m_hovered && !m_active && m_inactiveForegroundColor.isValid()) {
return m_inactiveForegroundColor;
}
if (m_activeForegroundColor.isValid()) {
return m_activeForegroundColor;
}
return kDefaultBlackColor;
}());
painter.setFont([this]() -> QFont {
QFont font = FramelessManagerPrivate::getIconFont();
if (m_iconSize2.has_value()) {
font.setPointSize(m_iconSize2.value());
}
return font;
}());
painter.drawText(buttonRect, Qt::AlignCenter, m_code);
}
painter.restore();
}
void StandardSystemButtonPrivate::initialize()
{
FramelessManagerPrivate::initializeIconFont();
Q_Q(StandardSystemButton);
q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
q->setFixedSize(kDefaultSystemButtonSize);
q->setIconSize(kDefaultSystemButtonIconSize);
connect(q, &StandardSystemButton::pressed, this, [this](){ setPressed(true); });
connect(q, &StandardSystemButton::released, this, [this](){ setPressed(false); });
}
StandardSystemButton::StandardSystemButton(QWidget *parent)
: QAbstractButton(parent), d_ptr(new StandardSystemButtonPrivate(this))
{
}
StandardSystemButton::StandardSystemButton(const SystemButtonType type, QWidget *parent)
: StandardSystemButton(parent)
{
setButtonType(type);
}
StandardSystemButton::~StandardSystemButton() = default;
QSize StandardSystemButton::sizeHint() const
{
Q_D(const StandardSystemButton);
return d->getRecommendedButtonSize();
}
SystemButtonType StandardSystemButton::buttonType()
{
Q_D(const StandardSystemButton);
return d->getButtonType();
}
QString StandardSystemButton::code() const
{
Q_D(const StandardSystemButton);
return d->getCode();
}
void StandardSystemButton::setButtonType(const SystemButtonType value)
{
Q_D(StandardSystemButton);
d->setButtonType(value);
}
void StandardSystemButton::setCode(const QString &code)
{
Q_D(StandardSystemButton);
d->setCode(code);
}
bool StandardSystemButton::isHovered() const
{
Q_D(const StandardSystemButton);
return d->isHovered();
}
void StandardSystemButton::setHovered(const bool value)
{
Q_D(StandardSystemButton);
d->setHovered(value);
}
bool StandardSystemButton::isPressed() const
{
Q_D(const StandardSystemButton);
return d->isPressed();
}
void StandardSystemButton::setPressed(const bool value)
{
Q_D(StandardSystemButton);
d->setPressed(value);
}
QColor StandardSystemButton::hoverColor() const
{
Q_D(const StandardSystemButton);
return d->getHoverColor();
}
void StandardSystemButton::setHoverColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setHoverColor(value);
}
QColor StandardSystemButton::pressColor() const
{
Q_D(const StandardSystemButton);
return d->getPressColor();
}
QColor StandardSystemButton::normalColor() const
{
Q_D(const StandardSystemButton);
return d->getNormalColor();
}
QColor StandardSystemButton::activeForegroundColor() const
{
Q_D(const StandardSystemButton);
return d->getActiveForegroundColor();
}
QColor StandardSystemButton::inactiveForegroundColor() const
{
Q_D(const StandardSystemButton);
return d->getInactiveForegroundColor();
}
bool StandardSystemButton::isActive() const
{
Q_D(const StandardSystemButton);
return d->isActive();
}
int StandardSystemButton::iconSize2() const
{
Q_D(const StandardSystemButton);
return d->iconSize2();
}
void StandardSystemButton::setPressColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setPressColor(value);
}
void StandardSystemButton::setNormalColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setNormalColor(value);
}
void StandardSystemButton::setActiveForegroundColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setActiveForegroundColor(value);
}
void StandardSystemButton::setInactiveForegroundColor(const QColor &value)
{
Q_D(StandardSystemButton);
d->setInactiveForegroundColor(value);
}
void StandardSystemButton::setActive(const bool value)
{
Q_D(StandardSystemButton);
d->setActive(value);
}
void StandardSystemButton::setIconSize2(const int value)
{
Q_D(StandardSystemButton);
d->setIconSize2(value);
}
void StandardSystemButton::enterEvent(QT_ENTER_EVENT_TYPE *event)
{
QAbstractButton::enterEvent(event);
Q_D(StandardSystemButton);
d->enterEventHandler(event);
}
void StandardSystemButton::leaveEvent(QEvent *event)
{
QAbstractButton::leaveEvent(event);
Q_D(StandardSystemButton);
d->leaveEventHandler(event);
}
void StandardSystemButton::paintEvent(QPaintEvent *event)
{
Q_D(StandardSystemButton);
d->paintEventHandler(event);
}
FRAMELESSHELPER_END_NAMESPACE