1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "statuswidget.h"
6#include <QPaintEvent>
7#include <QResizeEvent>
8
9class StatusWidgetPrivate
10{
11 friend class StatusWidget;
12 QRectF drawRange;
13 QTimer timer;
14 QColor color = Qt::green;
15 StatusWidget::PatternFlags flags = StatusWidget::PatternFlag::Simple;
16 int currElemIndex = -1;
17 int elem = 8;
18 StatusWidget::State state = StatusWidget::State::Stoped;
19};
20
21StatusWidget::StatusWidget(QWidget *parent)
22 : QWidget (parent)
23 , d (new StatusWidgetPrivate)
24{
25
26}
27
28StatusWidget::StatusWidget(PatternFlags flags, QWidget *parent)
29 : StatusWidget(parent)
30{
31 d->flags = flags;
32}
33
34StatusWidget::~StatusWidget()
35{
36 if (d) {
37 delete d;
38 }
39}
40
41void StatusWidget::setElemCount(int count)
42{
43 d->elem = count;
44}
45
46int StatusWidget::elemCount()
47{
48 return d->elem;
49}
50
51void StatusWidget::setPatternFlags(StatusWidget::PatternFlags flags)
52{
53 d->flags = flags;
54}
55
56StatusWidget::PatternFlags StatusWidget::patternFlags()
57{
58 return d->flags;
59}
60
61void StatusWidget::start(StatusWidget::RotaSpeed speed){
62 QObject::connect(&d->timer,&QTimer::timeout,this,[=](){
63 this->update();
64 });
65 d->timer.start(speed);
66 d->state = Running;
67}
68
69void StatusWidget::setRotaSpeed(StatusWidget::RotaSpeed speed)
70{
71 if(d->timer.interval() > 0)
72 d->timer.start(speed);
73}
74
75void StatusWidget::start()
76{
77 this->start(RotaSpeed::Usual);
78}
79
80StatusWidget::RotaSpeed StatusWidget::rotaSpeed() const
81{
82 return static_cast<RotaSpeed>(d->timer.interval());
83}
84
85void StatusWidget::stop()
86{
87 d->timer.stop();
88 d->state = Stoped;
89}
90
91bool StatusWidget::isRunning()
92{
93 if(d->timer.isActive() != (d->state == State::Running))
94 {
95 qWarning() << "unknown errorr from timer paint";
96 }
97
98 return d->timer.isActive() && d->state == State::Running;
99}
100
101bool StatusWidget::isStoped()
102{
103 return (!d->timer.isActive()) && d->state == State::Stoped;
104}
105
106void StatusWidget::setError()
107{
108 d->timer.stop();
109 d->state = Error;
110}
111
112bool StatusWidget::isError()
113{
114 return d->state == State::Error;
115}
116
117void StatusWidget::setWarning()
118{
119 d->color = Qt::yellow;
120}
121
122bool StatusWidget::isWarning()
123{
124 return d->color == Qt::yellow;
125}
126
127void StatusWidget::setRunningColor(QColor color)
128{
129 d->color = color;
130}
131
132void StatusWidget::paintEvent(QPaintEvent *event)
133{
134 Q_UNUSED(event);
135 if(d->state == State::Stoped) return;
136
137 QPainter painter(this);
138
139 if(d->drawRange.isEmpty() || d->drawRange != this->rect())
140 d->drawRange = this->rect();
141
142 if(d->elem <= 0)
143 d->elem = 8;
144
145 if(d->state == State::Error)
146 return paintError(painter);
147
148 if(d->flags.testFlag(PatternFlag::Ripple))
149 return paintRipple(painter);
150
151 if(d->flags.testFlag(PatternFlag::Twinkle))
152 return paintTwinkle(painter);
153
154 if(d->flags == PatternFlag::Ring
155 || d->flags.testFlag(PatternFlag::Simple))
156 paintSimple(painter);
157
158 if(d->flags.testFlag(PatternFlag::Radar))
159 paintRadar(painter);
160}
161
162void StatusWidget::paintError(QPainter &painter)
163{
164 QRadialGradient gradient(this->rect().center(),
165 qMax(this->width(),this->height())/2,
166 this->rect().center());
167
168 gradient.setColorAt(0, Qt::red);
169 gradient.setColorAt(1, palette().window().color());
170 gradient.setSpread(QGradient::ReflectSpread);
171 painter.setPen(Qt::red);
172 painter.setBrush(QBrush(gradient));
173 auto len = qMin(this->width(), this->height()) / 3;
174 painter.drawEllipse(this->rect().center(), len,len);
175}
176
177void StatusWidget::paintSimple(QPainter &painter)
178{
179 qreal angle = (360 / d->elem) *16;
180
181 if(d->currElemIndex == -1 || d->currElemIndex >= d->elem)
182 d->currElemIndex = 0;
183
184 // QRadialGradient gradient(this->rect().center(),
185 // qMax(this->width(),this->height())/2,
186 // this->rect().center());
187 // gradient.setColorAt(0, _color);
188 // gradient.setColorAt(1,palette().background().color());
189 // gradient.setSpread(QGradient::ReflectSpread);
190 painter.setPen(palette().window().color());
191 // painter.setBrush(QBrush(gradient));
192 painter.setBrush(QBrush(d->color));
193 painter.setRenderHint(QPainter::Antialiasing, true);
194 painter.drawPie(d->drawRange, d->currElemIndex * angle, angle);
195 d->currElemIndex ++;
196
197 if (d->flags.testFlag(PatternFlag::Ring)) paintRing(painter);
198
199}
200
201void StatusWidget::paintRadar(QPainter &painter)
202{
203 qreal angle = 360 / d->elem;
204
205 static int currPieIndex = -1;
206 if(currPieIndex == -1 || currPieIndex >= d->elem)
207 currPieIndex = 0;
208
209 QConicalGradient gradient(this->rect().center(),
210 (currPieIndex+1) * angle);
211 gradient.setColorAt(0, palette().window().color());
212 gradient.setColorAt(1, d->color);
213 gradient.setSpread(QGradient::ReflectSpread);
214 painter.setPen(palette().window().color());
215 painter.setBrush(QBrush(gradient));
216 painter.setRenderHint(QPainter::Antialiasing, true);
217 painter.drawEllipse(this->rect().center(),this->width()/2,this->height()/2);
218 currPieIndex ++;
219
220 if (d->flags.testFlag(PatternFlag::Ring)) paintRing(painter);
221}
222
223void StatusWidget::paintRing(QPainter &painter)
224{
225 auto background = this->palette().color(this->backgroundRole());
226 painter.setPen(background);
227 painter.setBrush(background);
228 painter.drawEllipse(this->rect().center(), this->width() / 3,this->height() / 3);
229}
230
231void StatusWidget::paintTwinkle(QPainter &painter)
232{
233 auto background = this->palette().window();
234 painter.setPen(background.color());
235
236 if(d->currElemIndex % 2 == 0)
237 {
238 painter.setBrush(this->palette().window());
239 }
240 else
241 {
242 painter.setBrush(QColor(d->color));
243 }
244
245 painter.drawEllipse(this->rect().center(),this->width()/3,this->height()/3);
246 d->currElemIndex ++;
247}
248
249void StatusWidget::paintRipple(QPainter &painter)
250{
251 Q_UNUSED(painter);
252}
253