328 lines
9.0 KiB
C++
328 lines
9.0 KiB
C++
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||
*
|
||
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 3 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
*
|
||
*/
|
||
#include "switchbutton.h"
|
||
|
||
#include <QDebug>
|
||
#define THEME_QT_SCHEMA "org.ukui.style"
|
||
#define THEME_GTK_SCHEMA "org.mate.interface"
|
||
#define TIMER_INTERVAL 5 //每隔5ms动画移动一次
|
||
#define MOVING_STEPS 40 //动画总共移动40次
|
||
|
||
SwitchButton::SwitchButton(QWidget *parent, bool useDisableStyle) :
|
||
QWidget(parent)
|
||
{
|
||
// this->resize(QSize(52, 24));
|
||
this->setFixedSize(QSize(50, 24));
|
||
|
||
checked = false;
|
||
hover = false;
|
||
disabled = false;
|
||
isMoving = false;
|
||
isAnimation = true;
|
||
m_useDisableStyle = useDisableStyle;
|
||
|
||
space = 4;
|
||
rectRadius = height()/2;
|
||
|
||
mStep = width()/MOVING_STEPS;//也就是40次动画就可以走完,每次时间间隔是固定的5ms
|
||
mStartX = 0;
|
||
mEndX= 0;
|
||
|
||
mTimer = new QTimer(this);
|
||
mTimer->setInterval(TIMER_INTERVAL);//动画更新时间
|
||
connect(mTimer, SIGNAL(timeout()), this, SLOT(updatevalue()));
|
||
if(QGSettings::isSchemaInstalled(THEME_GTK_SCHEMA) && QGSettings::isSchemaInstalled(THEME_QT_SCHEMA)) {
|
||
QByteArray qtThemeID(THEME_QT_SCHEMA);
|
||
QByteArray gtkThemeID(THEME_GTK_SCHEMA);
|
||
|
||
m_gtkThemeSetting = new QGSettings(gtkThemeID,QByteArray(),this);
|
||
m_qtThemeSetting = new QGSettings(qtThemeID,QByteArray(),this);
|
||
|
||
QString style = m_qtThemeSetting->get("styleName").toString();
|
||
changeColor(style);
|
||
|
||
connect(m_qtThemeSetting,&QGSettings::changed, [this] (const QString &key) {
|
||
QString style = m_qtThemeSetting->get("styleName").toString();
|
||
if (key == "styleName") {
|
||
changeColor(style);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
SwitchButton::~SwitchButton()
|
||
{
|
||
}
|
||
|
||
void SwitchButton::paintEvent(QPaintEvent *){
|
||
|
||
QPainter painter(this);
|
||
//启用反锯齿
|
||
painter.setRenderHint(QPainter::Antialiasing, true);
|
||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||
drawBg(&painter);
|
||
if(!isAnimation)//动画如果禁用,则圆形滑块isMoving始终为false
|
||
isMoving =false;
|
||
if(isMoving)
|
||
animation(&painter);
|
||
drawSlider(&painter);
|
||
painter.end();
|
||
}
|
||
|
||
void SwitchButton::changeColor(const QString &themes) {
|
||
if (hover) {
|
||
return ;//在鼠标下,禁止切换颜色鼠标离开时切换颜色
|
||
}
|
||
if (themes == "ukui-dark" || themes == "ukui-black") {
|
||
bgColorOff = QColor(OFF_BG_DARK_COLOR);
|
||
bgColorOn = QColor(ON_BG_DARK_COLOR);
|
||
rectColorEnabled = QColor(ENABLE_RECT_DARK_COLOR);
|
||
rectColorDisabled = QColor(DISABLE_RECT_DARK_COLOR);
|
||
sliderColorDisabled = QColor(DISABLE_RECT_DARK_COLOR);
|
||
sliderColorEnabled = QColor(ENABLE_RECT_DARK_COLOR);
|
||
bgHoverOnColor = QColor(ON_HOVER_BG_DARK_COLOR);
|
||
bgHoverOffColor = QColor(OFF_HOVER_BG_DARK_COLOR);
|
||
bgColorDisabled = QColor(DISABLE_DARK_COLOR);
|
||
} else {
|
||
bgColorOff = QColor(OFF_BG_LIGHT_COLOR);
|
||
bgColorOn = QColor(ON_BG_LIGHT_COLOR);
|
||
rectColorEnabled = QColor(ENABLE_RECT_LIGHT_COLOR);
|
||
rectColorDisabled = QColor(DISABLE_RECT_LIGHT_COLOR);
|
||
sliderColorDisabled = QColor(DISABLE_RECT_LIGHT_COLOR);
|
||
sliderColorEnabled = QColor(ENABLE_RECT_LIGHT_COLOR);
|
||
bgHoverOnColor = QColor(ON_HOVER_BG_LIGHT_COLOR);
|
||
bgHoverOffColor = QColor(OFF_HOVER_BG_LIGHT_COLOR);
|
||
bgColorDisabled = QColor(DISABLE_LIGHT_COLOR);
|
||
}
|
||
}
|
||
|
||
//动画绘制
|
||
void SwitchButton::animation(QPainter *painter){
|
||
painter->save();
|
||
int h = height();
|
||
int w = width();
|
||
painter->setPen(Qt::NoPen);
|
||
//颜色设置
|
||
if(checked){
|
||
//开关在左侧时
|
||
painter->setBrush(bgColorOn);
|
||
rect.setRect(0,0,h+mStartX,h);
|
||
}else{
|
||
painter->setBrush(bgColorOff);
|
||
rect.setRect(mStartX,0,w-mStartX,h);
|
||
}
|
||
painter->drawRoundedRect(rect,rectRadius,rectRadius);
|
||
|
||
painter->restore();
|
||
}
|
||
|
||
//绘制背景
|
||
void SwitchButton::drawBg(QPainter *painter){
|
||
int w = width();
|
||
int h = height();
|
||
painter->save();
|
||
painter->setPen(Qt::NoPen);
|
||
if (disabled && m_useDisableStyle) {
|
||
painter->setPen(Qt::NoPen);
|
||
painter->setBrush(bgColorDisabled);
|
||
} else {
|
||
if(checked){
|
||
if(isMoving){
|
||
painter->setBrush(bgColorOff);
|
||
rect.setRect(mStartX,0,w-mStartX,h);
|
||
}else {
|
||
painter->setBrush(bgColorOn);
|
||
rect.setRect(0, 0, w, h);
|
||
}
|
||
}else{
|
||
if(isMoving){
|
||
painter->setBrush(bgColorOn);
|
||
rect.setRect(0,0,mStartX+h,h);
|
||
}
|
||
else {
|
||
painter->setBrush(bgColorOff);
|
||
rect.setRect(0, 0, w, h);
|
||
}
|
||
}
|
||
}
|
||
//半径为高度的一半
|
||
painter->drawRoundedRect(rect,rectRadius,rectRadius);
|
||
|
||
painter->restore();
|
||
}
|
||
|
||
//绘制滑块,也就是圆形按钮
|
||
void SwitchButton::drawSlider(QPainter *painter){
|
||
painter->save();
|
||
painter->setPen(Qt::NoPen);
|
||
|
||
if (!disabled || !m_useDisableStyle){
|
||
painter->setBrush(sliderColorEnabled);
|
||
}
|
||
else
|
||
painter->setBrush(sliderColorDisabled);
|
||
if (disabled) {
|
||
if (!checked){
|
||
QRect smallRect(8, height() / 2 - 2, 10 , 4);
|
||
painter->drawRoundedRect(smallRect,3,3);
|
||
}else{
|
||
QRect smallRect(width() - 8 * 2, height() / 2 - 2, 10 , 4);
|
||
painter->drawRoundedRect(smallRect,3,3);
|
||
}
|
||
}
|
||
|
||
QRect rect(0, 0, width(), height());
|
||
int sliderWidth = rect.height() - space * 2;
|
||
QRect sliderRect(mStartX + space, space, sliderWidth, sliderWidth);
|
||
painter->drawEllipse(sliderRect);
|
||
|
||
painter->restore();
|
||
}
|
||
|
||
void SwitchButton::mousePressEvent(QMouseEvent *){
|
||
qDebug()<<isMoving<<checked<<disabled;
|
||
if (isMoving) {
|
||
return ;
|
||
}
|
||
if(disabled){
|
||
mEndX = 0;
|
||
Q_EMIT disabledClick();
|
||
return ;
|
||
}else{
|
||
checked = !checked;
|
||
Q_EMIT checkedChanged(checked);
|
||
|
||
mStep = width() / MOVING_STEPS;
|
||
|
||
if (checked){
|
||
//circle out
|
||
// endX = width() - height() + space;
|
||
//circle in
|
||
mEndX = width() - height();
|
||
}
|
||
else {
|
||
mEndX = 0;
|
||
}
|
||
mTimer->start();
|
||
isMoving = true;
|
||
}
|
||
}
|
||
|
||
void SwitchButton::resizeEvent(QResizeEvent *){
|
||
//每次开始的x坐标都是跳过圆角,从直线的地方开始计算
|
||
mStep = width() / MOVING_STEPS;
|
||
|
||
if (checked){
|
||
//circle out
|
||
// startX = width() - height() + space;
|
||
//circle in
|
||
mStartX = width() - height();
|
||
}
|
||
else
|
||
mStartX = 0;
|
||
|
||
rectRadius = height()/2;
|
||
update();
|
||
}
|
||
void SwitchButton::enterEvent(QEvent *event) {
|
||
bgColorOn = bgHoverOnColor;
|
||
bgColorOff = bgHoverOffColor;
|
||
|
||
hover = true;
|
||
update();
|
||
return QWidget::enterEvent(event);
|
||
}
|
||
|
||
void SwitchButton::leaveEvent(QEvent *event) {
|
||
hover = false;
|
||
|
||
QString style = m_qtThemeSetting->get("styleName").toString();
|
||
changeColor(style);
|
||
|
||
update();
|
||
return QWidget::leaveEvent(event);
|
||
}
|
||
|
||
//根据事件向左还是向右移动
|
||
void SwitchButton::updatevalue(){
|
||
if (checked)
|
||
if (mStartX < mEndX-mStep){
|
||
mStartX = mStartX + mStep;
|
||
}
|
||
else{
|
||
mStartX = mEndX;
|
||
mTimer->stop();
|
||
isMoving = false;
|
||
}
|
||
else{
|
||
if (mStartX > mEndX+mStep){
|
||
mStartX = mStartX - mStep;
|
||
}
|
||
else{
|
||
mStartX = mEndX;
|
||
mTimer->stop();
|
||
isMoving = false;
|
||
}
|
||
}
|
||
update();
|
||
}
|
||
|
||
void SwitchButton::setChecked(bool checked){
|
||
if (this->checked != checked){
|
||
this->checked = checked;
|
||
Q_EMIT checkedChanged(checked);
|
||
update();
|
||
}
|
||
|
||
mStep = width() / MOVING_STEPS;
|
||
|
||
if (checked){
|
||
//circle out
|
||
// endX = width() - height() + space;
|
||
//circle in
|
||
mEndX = width() - height();
|
||
}
|
||
else{
|
||
mEndX = 0;
|
||
}
|
||
mTimer->start();
|
||
isMoving = true;
|
||
}
|
||
|
||
bool SwitchButton::isChecked(){
|
||
return this->checked;
|
||
}
|
||
|
||
void SwitchButton::setDisabledFlag(bool value)
|
||
{
|
||
disabled = value;
|
||
update();
|
||
}
|
||
|
||
bool SwitchButton::getDisabledFlag()
|
||
{
|
||
return disabled;
|
||
}
|
||
|
||
void SwitchButton::setAnimation(bool on){
|
||
isAnimation = on;
|
||
}
|
||
|