LeechCraft 0.6.70-14794-g33744ae6ce
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
plotitem.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#include "plotitem.h"
10#include <vector>
11#include <memory>
12#include <QStyleOption>
13#include <QColor>
14#include <QPen>
15#include <util/sll/prelude.h>
16#include <qwt_plot.h>
17#include <qwt_plot_curve.h>
18#include <qwt_plot_renderer.h>
19#include <qwt_plot_grid.h>
20#include <qwt_scale_draw.h>
21#include <qwt_text_label.h>
22#include <qwt_plot_canvas.h>
23
25
26namespace LC::Util
27{
28 PlotItem::PlotItem (QQuickItem *parent)
29 : QQuickPaintedItem { parent }
30 , Color_ { 0xFF, 0x4B, 0x10 }
31 {
32 setFlag (ItemHasContents, true);
33 }
34
36 {
37 return Points_;
38 }
39
41 {
42 if (pts == Points_)
43 return;
44
45 Points_ = pts;
46 emit pointsChanged ();
47 update ();
48 }
49
50 QVariant PlotItem::GetMultipoints () const
51 {
52 QVariantList result;
53 for (const auto& set : Multipoints_)
54 {
55 QVariantMap map
56 {
57 { "color", QVariant::fromValue (set.Color_) },
58 { "points", QVariant::fromValue (set.Points_) }
59 };
60
61 if (set.BrushColor_)
62 map [QStringLiteral ("brushColor")] = *set.BrushColor_;
63
64 result << map;
65 }
66 return result;
67 }
68
69 namespace
70 {
71 struct UnsupportedType
72 {
73 const char * const Field_;
74 const QVariant Value_;
75 };
76 }
77
78 void PlotItem::SetMultipoints (const QVariant& variant)
79 {
80 Multipoints_.clear ();
81
82 try
83 {
84 for (const auto& set : variant.toList ())
85 {
86 const auto& map = set.toMap ();
87
88 const auto& colorVar = map [QStringLiteral ("color")];
89 const auto& color = colorVar.toString ();
90 if (color.isEmpty ())
91 throw UnsupportedType { "`color` expected to be a QString", colorVar };
92
93 const auto& pointsVar = map [QStringLiteral ("points")];
95 if (pointsVar.canConvert<QList<QPointF>> ())
96 points = pointsVar.value<QList<QPointF>> ();
97 else if (pointsVar.canConvert<QVariantList> ())
98 points = Util::Map (pointsVar.toList (),
99 [] (const QVariant& var)
100 {
101 if (var.canConvert<QPointF> ())
102 return var.toPointF ();
103 else
104 throw UnsupportedType { "point element expected to be a QPointF", var };
105 });
106
107 std::optional<QColor> brushColor;
108 if (const auto& brushVar = map [QStringLiteral ("brushColor")];
109 !brushVar.isNull ())
110 {
111 if (!brushVar.canConvert<QString> ())
112 throw UnsupportedType { "`brush` expected to be a QString", brushVar };
113 brushColor = QColor { brushVar.toString () };
114 }
115
116 Multipoints_.append ({ color, brushColor, points });
117 }
118 }
119 catch (const UnsupportedType& ty)
120 {
121 qCritical () << Q_FUNC_INFO
122 << "invalid multipoints map: "
123 << ty.Field_
124 << " but got instead"
125 << ty.Value_;
126 return;
127 }
128
129 update ();
130 }
131
133 {
134 return MinXValue_;
135 }
136
137 void PlotItem::SetMinXValue (double val)
138 {
139 SetNewValue (val, MinXValue_, [this] { emit minXValueChanged (); });
140 }
141
143 {
144 return MaxXValue_;
145 }
146
147 void PlotItem::SetMaxXValue (double val)
148 {
149 SetNewValue (val, MaxXValue_, [this] { emit maxXValueChanged (); });
150 }
151
153 {
154 return MinYValue_;
155 }
156
157 void PlotItem::SetMinYValue (double val)
158 {
159 SetNewValue (val, MinYValue_, [this] { emit minYValueChanged (); });
160 }
161
163 {
164 return MaxYValue_;
165 }
166
167 void PlotItem::SetMaxYValue (double val)
168 {
169 SetNewValue (val, MaxYValue_, [this] { emit maxYValueChanged (); });
170 }
171
173 {
174 return YGridEnabled_;
175 }
176
178 {
179 SetNewValue (val, YGridEnabled_, [this] { emit yGridChanged (); });
180 }
181
183 {
184 return YMinorGridEnabled_;
185 }
186
188 {
189 SetNewValue (val, YMinorGridEnabled_, [this] { emit yMinorGridChanged (); });
190 }
191
192 double PlotItem::GetAlpha () const
193 {
194 return Alpha_;
195 }
196
197 void PlotItem::SetAlpha (double a)
198 {
199 Alpha_ = a;
200 emit alphaChanged ();
201 }
202
203 QColor PlotItem::GetColor () const
204 {
205 return Color_;
206 }
207
208 void PlotItem::SetColor (const QColor& color)
209 {
210 SetNewValue (color, Color_, [this] { emit colorChanged (); });
211 }
212
214 {
215 return LeftAxisEnabled_;
216 }
217
219 {
220 SetNewValue (enabled, LeftAxisEnabled_, [this] { emit leftAxisEnabledChanged (); });
221 }
222
224 {
225 return BottomAxisEnabled_;
226 }
227
229 {
230 SetNewValue (enabled, BottomAxisEnabled_, [this] { emit bottomAxisEnabledChanged (); });
231 }
232
234 {
235 return LeftAxisTitle_;
236 }
237
238 void PlotItem::SetLeftAxisTitle (const QString& title)
239 {
240 SetNewValue (title, LeftAxisTitle_, [this] { emit leftAxisTitleChanged (); });
241 }
242
244 {
245 return BottomAxisTitle_;
246 }
247
248 void PlotItem::SetBottomAxisTitle (const QString& title)
249 {
250 SetNewValue (title, BottomAxisTitle_, [this] { emit bottomAxisTitleChanged (); });
251 }
252
253 QString PlotItem::GetPlotTitle () const
254 {
255 return PlotTitle_;
256 }
257
258 void PlotItem::SetPlotTitle (const QString& title)
259 {
260 SetNewValue (title, PlotTitle_, [this] { emit plotTitleChanged (); });
261 }
262
264 {
265 return BackgroundColor_;
266 }
267
268 void PlotItem::SetBackground (const QColor& bg)
269 {
270 SetNewValue (bg, BackgroundColor_, [this] { emit backgroundChanged (); });
271 }
272
274 {
275 return TextColor_;
276 }
277
278 void PlotItem::SetTextColor (const QColor& color)
279 {
280 SetNewValue (color, TextColor_, [this] { emit textColorChanged (); });
281 }
282
284 {
285 return GridLinesColor_;
286 }
287
288 void PlotItem::SetGridLinesColor (const QColor& color)
289 {
290 SetNewValue (color, GridLinesColor_, [this] { emit gridLinesColorChanged (); });
291 }
292
294 {
295 return XExtent_;
296 }
297
299 {
300 return YExtent_;
301 }
302
303 void PlotItem::paint (QPainter *painter)
304 {
305 const auto& rect = contentsBoundingRect ().toRect ();
306
307 if (!Plot_)
308 {
309 Plot_ = std::make_shared<QwtPlot> ();
310 Plot_->setFrameShape (QFrame::NoFrame);
311 Plot_->setFrameShadow (QFrame::Plain);
312 Plot_->setLineWidth (0);
313 Plot_->setMidLineWidth (0);
314
315 if (const auto canvas = qobject_cast<QwtPlotCanvas*> (Plot_->canvas ()))
316 canvas->setBorderRadius (0);
317 }
318
319 auto& plot = *Plot_;
320 plot.enableAxis (QwtPlot::yLeft, LeftAxisEnabled_);
321 plot.enableAxis (QwtPlot::xBottom, BottomAxisEnabled_);
322 plot.setAxisTitle (QwtPlot::yLeft, LeftAxisTitle_);
323 plot.setAxisTitle (QwtPlot::xBottom, BottomAxisTitle_);
324
325 if (plot.size () != rect.size ())
326 plot.resize (rect.size ());
327
328 auto setPaletteColor = [&plot] (const QColor& color, QPalette::ColorRole role)
329 {
330 if (!color.isValid ())
331 return;
332
333 auto pal = plot.palette ();
334 pal.setColor (role, { color });
335 plot.setPalette (pal);
336 };
337
338 setPaletteColor (BackgroundColor_, QPalette::Window);
339 setPaletteColor (TextColor_, QPalette::WindowText);
340 setPaletteColor (TextColor_, QPalette::Text);
341
342 if (!PlotTitle_.isEmpty ())
343 plot.setTitle (QwtText { PlotTitle_ });
344
345 if (MinYValue_ < MaxYValue_)
346 {
347 plot.setAxisAutoScale (QwtPlot::yLeft, false);
348 plot.setAxisScale (QwtPlot::yLeft, MinYValue_, MaxYValue_);
349 }
350 plot.setAutoFillBackground (false);
351 plot.setCanvasBackground (Qt::transparent);
352
353 if (YGridEnabled_)
354 {
355 auto grid = new QwtPlotGrid;
356 grid->enableYMin (YMinorGridEnabled_);
357 grid->enableX (false);
358 grid->setMajorPen (QPen (GridLinesColor_, 1, Qt::SolidLine));
359 grid->setMinorPen (QPen (GridLinesColor_, 1, Qt::DashLine));
360 grid->attach (&plot);
361 }
362
363 auto items = Multipoints_;
364 if (items.isEmpty ())
365 items.push_back ({ Color_, {}, Points_ });
366
367 if (MinXValue_ < MaxXValue_)
368 plot.setAxisScale (QwtPlot::xBottom, MinXValue_, MaxXValue_);
369 else if (const auto ptsCount = items.first ().Points_.size ())
370 plot.setAxisScale (QwtPlot::xBottom, 0, ptsCount - 1);
371
372 std::vector<std::unique_ptr<QwtPlotCurve>> curves;
373 for (const auto& item : items)
374 {
375 curves.emplace_back (new QwtPlotCurve);
376 const auto curve = curves.back ().get ();
377
378 curve->setPen (QPen (item.Color_));
379
380 if (item.BrushColor_)
381 curve->setBrush (*item.BrushColor_);
382 else
383 {
384 auto brushColor = item.Color_;
385 brushColor.setAlphaF (Alpha_);
386 curve->setBrush (brushColor);
387 }
388
389 curve->setRenderHint (QwtPlotItem::RenderAntialiased);
390 curve->attach (&plot);
391
392 curve->setSamples (item.Points_.toVector ());
393 }
394
395 plot.replot ();
396
397 QwtPlotRenderer {}.render (&plot, painter, rect);
398
399 const auto xExtent = CalcXExtent (plot);
400 const auto yExtent = CalcYExtent (plot);
401 if (xExtent != XExtent_ || yExtent != YExtent_)
402 {
403 XExtent_ = xExtent;
404 YExtent_ = yExtent;
405 emit extentsChanged ();
406 }
407 }
408
409 template<typename T, typename Notifier>
410 void PlotItem::SetNewValue (T val, T& ourVal, Notifier&& notifier)
411 {
412 if (val == ourVal)
413 return;
414
415 ourVal = val;
416 notifier ();
417 update ();
418 }
419
420 int PlotItem::CalcXExtent (QwtPlot& plot) const
421 {
422 int result = 0;
423 if (LeftAxisEnabled_)
424 result += plot.axisScaleDraw (QwtPlot::yLeft)->extent (plot.axisFont (QwtPlot::yLeft));
425 return result;
426 }
427
428 int PlotItem::CalcYExtent (QwtPlot& plot) const
429 {
430 int result = 0;
431 if (BottomAxisEnabled_)
432 result += plot.axisScaleDraw (QwtPlot::xBottom)->extent (plot.axisFont (QwtPlot::xBottom));
433 if (!PlotTitle_.isEmpty ())
434 result += plot.titleLabel ()->sizeHint ().height ();
435 return result;
436 }
437}
int GetYExtent() const
Definition: plotitem.cpp:298
void bottomAxisEnabledChanged()
void SetLeftAxisTitle(const QString &)
Definition: plotitem.cpp:238
bool GetYGridEnabled() const
Definition: plotitem.cpp:172
QColor GetBackground() const
Definition: plotitem.cpp:263
double GetMaxYValue() const
Definition: plotitem.cpp:162
double GetAlpha() const
Definition: plotitem.cpp:192
void leftAxisTitleChanged()
void SetPlotTitle(const QString &)
Definition: plotitem.cpp:258
void SetBottomAxisEnabled(bool)
Definition: plotitem.cpp:228
void SetMinYValue(double)
Definition: plotitem.cpp:157
double GetMinYValue() const
Definition: plotitem.cpp:152
bool GetLeftAxisEnabled() const
Definition: plotitem.cpp:213
void SetMaxXValue(double)
Definition: plotitem.cpp:147
void SetMinXValue(double)
Definition: plotitem.cpp:137
QColor GetColor() const
Definition: plotitem.cpp:203
bool GetYMinorGridEnabled() const
Definition: plotitem.cpp:182
QString GetLeftAxisTitle() const
Definition: plotitem.cpp:233
QList< QPointF > GetPoints() const
Definition: plotitem.cpp:35
void SetMaxYValue(double)
Definition: plotitem.cpp:167
void SetTextColor(const QColor &)
Definition: plotitem.cpp:278
QString GetBottomAxisTitle() const
Definition: plotitem.cpp:243
QString GetPlotTitle() const
Definition: plotitem.cpp:253
void leftAxisEnabledChanged()
void SetBackground(const QColor &)
Definition: plotitem.cpp:268
double GetMinXValue() const
Definition: plotitem.cpp:132
int GetXExtent() const
Definition: plotitem.cpp:293
void SetMultipoints(const QVariant &)
Definition: plotitem.cpp:78
void SetPoints(const QList< QPointF > &)
Definition: plotitem.cpp:40
PlotItem(QQuickItem *=nullptr)
Definition: plotitem.cpp:28
bool GetBottomAxisEnabled() const
Definition: plotitem.cpp:223
QColor GetGridLinesColor() const
Definition: plotitem.cpp:283
void SetLeftAxisEnabled(bool)
Definition: plotitem.cpp:218
void SetBottomAxisTitle(const QString &)
Definition: plotitem.cpp:248
QColor GetTextColor() const
Definition: plotitem.cpp:273
void paint(QPainter *) override
Definition: plotitem.cpp:303
QList< QPointF > points
Definition: plotitem.h:25
void gridLinesColorChanged()
void SetGridLinesColor(const QColor &)
Definition: plotitem.cpp:288
void SetYMinorGridEnabled(bool)
Definition: plotitem.cpp:187
QVariant GetMultipoints() const
Definition: plotitem.cpp:50
void SetColor(const QColor &)
Definition: plotitem.cpp:208
double GetMaxXValue() const
Definition: plotitem.cpp:142
void bottomAxisTitleChanged()
void SetAlpha(double)
Definition: plotitem.cpp:197
void SetYGridEnabled(bool)
Definition: plotitem.cpp:177
auto Map(Container &&c, F f)
Definition: prelude.h:143
const char *const Field_
Definition: plotitem.cpp:73
const QVariant Value_
Definition: plotitem.cpp:74
Q_DECLARE_METATYPE(QVariantList *)