Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 更改checkbox和radio实现方式为dci图标,增加动效 #236

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 156 additions & 53 deletions styleplugins/chameleon/chameleonstyle.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd.
* SPDX-FileCopyrightText: 2017 - 2024 UnionTech Software Technology Co., Ltd.
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "chameleonstyle.h"
Expand Down Expand Up @@ -439,67 +439,31 @@
return;
}
case PE_IndicatorRadioButton: {
QRect standard = opt->rect;
auto radioButton = qobject_cast<QRadioButton *>(opt->styleObject);
if (!radioButton)
radioButton = dynamic_cast<QRadioButton *>(p->device());

p->setRenderHint(QPainter::Antialiasing, true);

if (opt->state & State_On) { //Qt::Checked
int padding = qCeil(standard.width() / 2.0 / 2.0);
QPainterPath path;

path.addEllipse(standard);
path.addEllipse(standard.adjusted(padding, padding, -padding, -padding));

p->fillPath(path, getColor(opt, DPalette::Highlight));

// 内圈填充
QPainterPath innerCirclePath;
innerCirclePath.addEllipse(standard.adjusted(padding, padding, -padding, -padding));
p->fillPath(innerCirclePath, getThemTypeColor(Qt::white, Qt::black));
} else if (opt->state & State_Off) {
p->setPen(QPen(getColor(opt, DPalette::WindowText), 1));
p->drawEllipse(standard.adjusted(1, 1, -1, -1));
if (!radioButton)
return;

// 内圈填充
QPainterPath innerCirclePath;
innerCirclePath.addEllipse(standard.adjusted(1, 1, -1, -1));
p->fillPath(innerCirclePath, getThemTypeColor(Qt::transparent, QColor(0, 0, 0, qCeil(255 * 0.5))));
}
auto dciIconPlayer = dciIconPlayers.value(radioButton);

p->setRenderHint(QPainter::SmoothPixmapTransform);
p->drawImage(opt->rect.adjusted(-1, -1, 1, 1), dciIconPlayer->currentImage());
return;
}
case PE_IndicatorCheckBox: {
QRectF standard = opt->rect;

if (opt->state & State_NoChange) { //Qt::PartiallyChecked
DDrawUtils::drawBorder(p, standard, getColor(opt, DPalette::WindowText), 1, 2);

// 内部矩形填充
p->setBrush(getThemTypeColor(Qt::transparent, QColor(0, 0, 0, qCeil(255 * 0.5))));
p->drawRoundedRect(standard.adjusted(1, 1, -1, -1), 2, 2);

QRectF lineRect(0, 0, standard.width() / 2.0, 2);
lineRect.moveCenter(standard.center());
p->fillRect(lineRect, getColor(opt, DPalette::TextTitle, w));
} else if (opt->state & State_On) { //Qt::Checked
// 填充整个矩形
p->setPen(Qt::NoPen);
p->setBrush(getThemTypeColor(Qt::transparent, Qt::black));
p->drawRoundedRect(standard.adjusted(1, 1, -1, -1), 2, 2);

p->setPen(getColor(opt, DPalette::Highlight));
p->setBrush(Qt::NoBrush);
auto checkBox = qobject_cast<QCheckBox *>(opt->styleObject);
if (!checkBox)
checkBox = dynamic_cast<QCheckBox *>(p->device());

QIcon icon = QIcon::fromTheme("checked");
icon.paint(p, opt->rect.adjusted(-1, -1, 1, 1));
} else {
DDrawUtils::drawBorder(p, standard, getColor(opt, DPalette::WindowText), 1, 2);
if (!checkBox)
return;

// 内部矩形填充
p->setBrush(getThemTypeColor(Qt::transparent, getThemTypeColor(Qt::transparent, QColor(0, 0, 0, qCeil(255 * 0.5)))));
p->drawRoundedRect(standard.adjusted(1, 1, -1, -1), 2, 2);
}
auto dciIconPlayer = dciIconPlayers.value(checkBox);

p->setRenderHint(QPainter::SmoothPixmapTransform);
p->drawImage(opt->rect.adjusted(-1, -1, 1, 1), dciIconPlayer->currentImage());
return;
}
case PE_IndicatorTabClose: {
Expand Down Expand Up @@ -4495,6 +4459,145 @@
scrollbar->setProperty("_d_dtk_scrollbar_visible", true);
scrollbar->setAttribute(Qt::WA_OpaquePaintEvent, !polish);
}

if (auto radioButton = qobject_cast<QRadioButton *>(w)) {
if (polish) {
radioButton->installEventFilter(this);
} else {
radioButton->removeEventFilter(this);
}
auto dciIconPlayer = new DDciIconPlayer(radioButton);
connect(dciIconPlayer, &DDciIconPlayer::updated, radioButton, [radioButton]() {
radioButton->update();
});
dciIconPlayers.insert(radioButton, dciIconPlayer);
}

if (auto checkBox = qobject_cast<QCheckBox *>(w)) {
if (polish) {
checkBox->installEventFilter(this);
} else {
checkBox->removeEventFilter(this);
}
auto dciIconPlayer = new DDciIconPlayer(checkBox);
connect(dciIconPlayer, &DDciIconPlayer::updated, checkBox, [checkBox]() {
checkBox->update();
});
dciIconPlayers.insert(checkBox, dciIconPlayer);
}
}

static void playDci(DDciIconPlayer *player, const DDciIcon &icon, DDciIcon::Mode mode)
{
player->setIcon(icon);
player->play(mode);
}

bool ChameleonStyle::eventFilter(QObject *watched, QEvent *event)
{
if (auto radioButton = qobject_cast<QRadioButton *>(watched)) {

auto player = dciIconPlayers.value(radioButton);
if (!player)
return DStyle::eventFilter(watched, event);

DDciIcon icon = radioButton->isChecked() ? DDciIcon::fromTheme("radio_checked") : DDciIcon::fromTheme("radio_unchecked");
auto pa = DDciIconPalette::fromQPalette(radioButton->palette());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto player = dciIconPlayers.value(radioButton)
if (!player)
    return DStyle::eventFilter(watched, event)

switch (event->type()) {
case QEvent::Paint:
player->setPalette(pa);
player->setDevicePixelRatio(qApp->devicePixelRatio());
player->setTheme(DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType
? DDciIcon::Theme::Dark
: DDciIcon::Theme::Light);
break;
case QEvent::WindowActivate:
player->setIcon(icon);
player->setMode(DDciIcon::Normal);
break;
case QEvent::MouseButtonPress:
playDci(player, icon, DDciIcon::Pressed);
break;
case QEvent::HoverEnter:
playDci(player, icon, DDciIcon::Hover);
break;
case QEvent::MouseButtonRelease:
icon = !radioButton->isChecked() ? DDciIcon::fromTheme("radio_checked") : DDciIcon::fromTheme("radio_unchecked");
playDci(player, icon, DDciIcon::Hover);
break;
case QEvent::HoverLeave:
playDci(player, icon, DDciIcon::Normal);
break;
case QEvent::KeyPress:
if (auto key = dynamic_cast<QKeyEvent *>(event)) {
if (key->key() == Qt::Key_Space) {
playDci(player, icon, DDciIcon::Pressed);
}
}
break;
case QEvent::KeyRelease:
if (auto key = dynamic_cast<QKeyEvent *>(event)) {
if (key->key() == Qt::Key_Space) {
icon = !radioButton->isChecked() ? DDciIcon::fromTheme("radio_checked") : DDciIcon::fromTheme("radio_checked");

Check warning on line 4542 in styleplugins/chameleon/chameleonstyle.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Finding the same expression in both branches of ternary operator is suspicious as the same code is executed regardless of the condition.
playDci(player, icon, DDciIcon::Normal);
}
}
break;
}
}
if (auto checkBox = qobject_cast<QCheckBox *>(watched)) {

auto player = dciIconPlayers.value(checkBox);
if (!player)
return DStyle::eventFilter(watched, event);

DDciIcon icon = checkBox->isChecked() ? DDciIcon::fromTheme("checkbox_checked") : DDciIcon::fromTheme("checkbox_unchecked");
auto pa = DDciIconPalette::fromQPalette(checkBox->palette());

switch (event->type()) {
case QEvent::Paint:
player->setPalette(pa);
player->setDevicePixelRatio(qApp->devicePixelRatio());
player->setTheme(DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType
? DDciIcon::Theme::Dark
: DDciIcon::Theme::Light);
break;
case QEvent::WindowActivate:
player->setIcon(icon);
player->setMode(DDciIcon::Normal);
break;
case QEvent::MouseButtonPress:
playDci(player, icon, DDciIcon::Pressed);
break;
case QEvent::HoverEnter:
playDci(player, icon, DDciIcon::Hover);
break;
case QEvent::MouseButtonRelease:
icon = !checkBox->isChecked() ? DDciIcon::fromTheme("checkbox_checked") : DDciIcon::fromTheme("checkbox_unchecked");
playDci(player, icon, DDciIcon::Hover);
break;
case QEvent::HoverLeave:
playDci(player, icon, DDciIcon::Normal);
break;
case QEvent::KeyPress:
if (auto key = dynamic_cast<QKeyEvent *>(event)) {
if (key->key() == Qt::Key_Space) {
playDci(player, icon, DDciIcon::Pressed);
}
}
break;
case QEvent::KeyRelease:
if (auto key = dynamic_cast<QKeyEvent *>(event)) {
if (key->key() == Qt::Key_Space) {
icon = !checkBox->isChecked() ? DDciIcon::fromTheme("checkbox_checked") : DDciIcon::fromTheme("checkbox_checked");

Check warning on line 4593 in styleplugins/chameleon/chameleonstyle.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Finding the same expression in both branches of ternary operator is suspicious as the same code is executed regardless of the condition.
playDci(player, icon, DDciIcon::Normal);
}
}
break;
}
}
return DStyle::eventFilter(watched, event);
}

static void updateWeekendTextFormat(QCalendarWidget *calendar, QColor)
Expand Down
6 changes: 5 additions & 1 deletion styleplugins/chameleon/chameleonstyle.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/*
* SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd.
* SPDX-FileCopyrightText: 2017 - 2024 UnionTech Software Technology Co., Ltd.
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef CHAMELEONSTYLE_H
#define CHAMELEONSTYLE_H

#include <DStyle>
#include <DDciIconPlayer>
#include <QVariantAnimation>

DWIDGET_USE_NAMESPACE
Expand Down Expand Up @@ -125,6 +126,9 @@ class ChameleonStyle : public DStyle

private:
mutable QHash<const QObject*, dstyle::DStyleAnimation*> animations;
mutable QHash<const QObject*, DDciIconPlayer* > dciIconPlayers;

bool eventFilter(QObject *watched, QEvent *event) override;
};
} // namespace chameleon

Expand Down
Loading