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