ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
QRoundProgressBar.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "QRoundProgressBar.h"
9 
10 #include <QtGui/QPainter>
11 #include <QtGui/QPainterPath>
12 
14  : QWidget(parent),
15  m_min(0),
16  m_max(100),
17  m_value(25),
18  m_nullPosition(PositionTop),
19  m_barStyle(StyleDonut),
20  m_outlinePenWidth(1),
21  m_dataPenWidth(1),
22  m_rebuildBrush(false),
23  m_format("%p%"),
24  m_decimals(1),
25  m_updateFlags(UF_PERCENT) {}
26 
27 void QRoundProgressBar::setRange(double min, double max) {
28  m_min = min;
29  m_max = max;
30 
31  if (m_max < m_min) qSwap(m_max, m_min);
32 
33  if (m_value < m_min)
34  m_value = m_min;
35  else if (m_value > m_max)
36  m_value = m_max;
37 
38  if (!m_gradientData.isEmpty()) m_rebuildBrush = true;
39 
40  update();
41 }
42 
43 void QRoundProgressBar::setMinimum(double min) { setRange(min, m_max); }
44 
45 void QRoundProgressBar::setMaximum(double max) { setRange(m_min, max); }
46 
47 void QRoundProgressBar::setValue(double val) {
48  if (m_value != val) {
49  if (val < m_min)
50  m_value = m_min;
51  else if (val > m_max)
52  m_value = m_max;
53  else
54  m_value = val;
55 
56  update();
57  }
58 }
59 
60 void QRoundProgressBar::setValue(int val) { setValue(double(val)); }
61 
63  if (position != m_nullPosition) {
65 
66  if (!m_gradientData.isEmpty()) m_rebuildBrush = true;
67 
68  update();
69  }
70 }
71 
73  if (style != m_barStyle) {
74  m_barStyle = style;
75 
76  update();
77  }
78 }
79 
81  if (penWidth != m_outlinePenWidth) {
82  m_outlinePenWidth = penWidth;
83 
84  update();
85  }
86 }
87 
88 void QRoundProgressBar::setDataPenWidth(double penWidth) {
89  if (penWidth != m_dataPenWidth) {
90  m_dataPenWidth = penWidth;
91 
92  update();
93  }
94 }
95 
96 void QRoundProgressBar::setDataColors(const QGradientStops &stopPoints) {
97  if (stopPoints != m_gradientData) {
98  m_gradientData = stopPoints;
99  m_rebuildBrush = true;
100 
101  update();
102  }
103 }
104 
105 void QRoundProgressBar::setFormat(const QString &format) {
106  if (format != m_format) {
107  m_format = format;
108 
110  }
111 }
112 
114  m_format = QString();
115 
117 }
118 
120  if (count >= 0 && count != m_decimals) {
121  m_decimals = count;
122 
124  }
125 }
126 
127 void QRoundProgressBar::paintEvent(QPaintEvent * /*event*/) {
128  double outerRadius = qMin(width(), height());
129  QRectF baseRect(1, 1, outerRadius - 2, outerRadius - 2);
130 
131  QImage buffer(outerRadius, outerRadius,
132  QImage::Format_ARGB32_Premultiplied);
133 
134  QPainter p(&buffer);
135  p.setRenderHint(QPainter::Antialiasing);
136 
137  // data brush
139 
140  // background
141  drawBackground(p, buffer.rect());
142 
143  // base circle
144  drawBase(p, baseRect);
145 
146  // data circle
147  double arcStep = 360.0 / (m_max - m_min) * m_value;
148  drawValue(p, baseRect, m_value, arcStep);
149 
150  // center circle
151  double innerRadius(0);
152  QRectF innerRect;
153  calculateInnerRect(baseRect, outerRadius, innerRect, innerRadius);
154  drawInnerBackground(p, innerRect);
155 
156  // text
157  drawText(p, innerRect, innerRadius, m_value);
158 
159  // finally draw the bar
160  p.end();
161 
162  QPainter painter(this);
163  // painter.fillRect(baseRect, palette().background());
164  painter.fillRect(baseRect, palette().window());
165  painter.drawImage(0, 0, buffer);
166 }
167 
168 void QRoundProgressBar::drawBackground(QPainter &p, const QRectF &baseRect) {
169  // p.fillRect(baseRect, palette().background());
170  p.fillRect(baseRect, palette().window());
171 }
172 
173 void QRoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect) {
174  switch (m_barStyle) {
175  case StyleDonut:
176  p.setPen(QPen(palette().shadow().color(), m_outlinePenWidth));
177  p.setBrush(palette().base());
178  p.drawEllipse(baseRect);
179  break;
180 
181  case StylePie:
182  p.setPen(QPen(palette().base().color(), m_outlinePenWidth));
183  p.setBrush(palette().base());
184  p.drawEllipse(baseRect);
185  break;
186 
187  case StyleLine:
188  p.setPen(QPen(palette().base().color(), m_outlinePenWidth));
189  p.setBrush(Qt::NoBrush);
190  p.drawEllipse(baseRect.adjusted(
193  break;
194 
195  default:;
196  }
197 }
198 
200  const QRectF &baseRect,
201  double value,
202  double arcLength) {
203  // nothing to draw
204  if (value == m_min) return;
205 
206  // for Line style
207  if (m_barStyle == StyleLine) {
208  p.setPen(QPen(palette().highlight().color(), m_dataPenWidth));
209  p.setBrush(Qt::NoBrush);
210  p.drawArc(baseRect.adjusted(
213  m_nullPosition * 16, -arcLength * 16);
214  return;
215  }
216 
217  // for Pie and Donut styles
218  QPainterPath dataPath;
219  dataPath.setFillRule(Qt::WindingFill);
220 
221  // pie segment outer
222  dataPath.moveTo(baseRect.center());
223  dataPath.arcTo(baseRect, m_nullPosition, -arcLength);
224  dataPath.lineTo(baseRect.center());
225 
226  p.setBrush(palette().highlight());
227  p.setPen(QPen(palette().shadow().color(), m_dataPenWidth));
228  p.drawPath(dataPath);
229 }
230 
231 void QRoundProgressBar::calculateInnerRect(const QRectF & /*baseRect*/,
232  double outerRadius,
233  QRectF &innerRect,
234  double &innerRadius) {
235  // for Line style
236  if (m_barStyle == StyleLine) {
237  innerRadius = outerRadius - m_outlinePenWidth;
238  } else // for Pie and Donut styles
239  {
240  innerRadius = outerRadius * 0.75;
241  }
242 
243  double delta = (outerRadius - innerRadius) / 2;
244  innerRect = QRectF(delta, delta, innerRadius, innerRadius);
245 }
246 
248  const QRectF &innerRect) {
249  if (m_barStyle == StyleDonut) {
250  p.setBrush(palette().alternateBase());
251  p.drawEllipse(innerRect);
252  }
253 }
254 
256  const QRectF &innerRect,
257  double innerRadius,
258  double value) {
259  if (m_format.isEmpty()) return;
260 
261  // !!! to revise
262  QFont f(font());
263  f.setPixelSize(innerRadius *
264  qMax(0.05, (0.35 - (double)m_decimals * 0.08)));
265  p.setFont(f);
266 
267  QRectF textRect(innerRect);
268  p.setPen(palette().text().color());
269  p.drawText(textRect, Qt::AlignCenter, valueToText(value));
270 }
271 
272 QString QRoundProgressBar::valueToText(double value) const {
273  QString textToDraw(m_format);
274 
275  if (m_updateFlags & UF_VALUE)
276  textToDraw.replace("%v", QString::number(value, 'f', m_decimals));
277 
278  if (m_updateFlags & UF_PERCENT) {
279  double procent = (value - m_min) / (m_max - m_min) * 100.0;
280  textToDraw.replace("%p", QString::number(procent, 'f', m_decimals));
281  }
282 
283  if (m_updateFlags & UF_MAX)
284  textToDraw.replace("%m",
285  QString::number(m_max - m_min + 1, 'f', m_decimals));
286 
287  return textToDraw;
288 }
289 
291  m_updateFlags = 0;
292 
293  if (m_format.contains("%v")) m_updateFlags |= UF_VALUE;
294 
295  if (m_format.contains("%p")) m_updateFlags |= UF_PERCENT;
296 
297  if (m_format.contains("%m")) m_updateFlags |= UF_MAX;
298 
299  update();
300 }
301 
303  if (m_rebuildBrush) {
304  m_rebuildBrush = false;
305 
306  QConicalGradient dataBrush;
307  dataBrush.setCenter(0.5, 0.5);
308  dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode);
309 
310  // invert colors
311  for (int i = 0; i < m_gradientData.count(); i++) {
312  dataBrush.setColorAt(1.0 - m_gradientData.at(i).first,
313  m_gradientData.at(i).second);
314  }
315 
316  // angle
317  dataBrush.setAngle(m_nullPosition);
318 
319  QPalette p(palette());
320  p.setBrush(QPalette::Highlight, dataBrush);
321  setPalette(p);
322  }
323 }
filament::Texture::InternalFormat format
int width
int height
int count
math::float4 color
math::float3 position
void setDataPenWidth(double penWidth)
Sets width of the data circle pen.
void setValue(double val)
Sets a value which will be shown on the widget.
virtual void calculateInnerRect(const QRectF &baseRect, double outerRadius, QRectF &innerRect, double &innerRadius)
void setMinimum(double min)
Defines minimum of the allowed value range. If the current value does not fit into the range,...
virtual void drawText(QPainter &p, const QRectF &innerRect, double innerRadius, double value)
static const int UF_MAX
void setOutlinePenWidth(double penWidth)
Sets width of the outline circle pen.
virtual void drawBackground(QPainter &p, const QRectF &baseRect)
void setDecimals(int count)
Sets number of decimals to show after the comma (default is 1).
double value() const
Returns current value shown on the widget.
void setMaximum(double max)
Defines maximum of the allowed value range. If the current value does not fit into the range,...
virtual void drawValue(QPainter &p, const QRectF &baseRect, double value, double arcLength)
QRoundProgressBar(QWidget *parent=0)
virtual void drawBase(QPainter &p, const QRectF &baseRect)
void setBarStyle(BarStyle style)
Sets visual style of the widget.
void setFormat(const QString &format)
Defines the string used to generate the current text. If no format is set, no text will be shown.
static const int UF_VALUE
virtual void valueFormatChanged()
virtual void paintEvent(QPaintEvent *event)
virtual void drawInnerBackground(QPainter &p, const QRectF &innerRect)
virtual QString valueToText(double value) const
void setNullPosition(double position)
Defines position of minimum value.
static const int UF_PERCENT
QGradientStops m_gradientData
QString format() const
Returns the string used to generate the current text.
void setRange(double min, double max)
Defines minimum und maximum of the allowed value range. If the current value does not fit into the ra...
BarStyle
The BarStyle enum defines general look of the progress bar.
@ StylePie
Pie style (filled pie segment with the text in center)
@ StyleLine
Line style (thin round line around the text)
@ StyleDonut
Donut style (filled torus around the text)
void resetFormat()
Sets format string to empty string. No text will be shown therefore. See setFormat() for more informa...
void setDataColors(const QGradientStops &stopPoints)
Sets colors of the visible data and makes gradient brush from them. Gradient colors can be set for Do...