LeechCraft  0.6.70-3565-g2d86529
Modular cross-platform feature rich live environment.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "plotitem.h"
31 #include <cmath>
32 #include <limits>
33 #include <vector>
34 #include <memory>
35 #include <QStyleOption>
36 #include <QColor>
37 #include <qwt_plot.h>
38 #include <qwt_plot_curve.h>
39 #include <qwt_plot_renderer.h>
40 #include <qwt_plot_grid.h>
41 #include <qwt_scale_draw.h>
42 #include <qwt_text_label.h>
43 #include <util.h>
44 
46 
47 namespace LeechCraft
48 {
49 namespace Util
50 {
51 #if QT_VERSION < 0x050000
52  PlotItem::PlotItem (QDeclarativeItem *parent)
53  : QDeclarativeItem { parent }
54 #else
55  PlotItem::PlotItem (QQuickItem *parent)
56  : QQuickPaintedItem { parent }
57 #endif
58  , Color_ { "#FF4B10" }
59  {
60 #if QT_VERSION < 0x050000
61  setFlag (QGraphicsItem::ItemHasNoContents, false);
62 #else
63  setFlag (ItemHasContents, true);
64 #endif
65  }
66 
68  {
69  return Points_;
70  }
71 
73  {
74  if (pts == Points_)
75  return;
76 
77  Points_ = pts;
78  emit pointsChanged ();
79  update ();
80  }
81 
82  QVariant PlotItem::GetMultipoints () const
83  {
84  QVariantList result;
85  for (const auto& set : Multipoints_)
86  result << Util::MakeMap<QString, QVariant> ({
87  { "color", QVariant::fromValue (set.Color_) },
88  { "points", QVariant::fromValue (set.Points_) }
89  });
90  return result;
91  }
92 
93  void PlotItem::SetMultipoints (const QVariant& variant)
94  {
95  Multipoints_.clear ();
96 
97  for (const auto& set : variant.toList ())
98  {
99  const auto& map = set.toMap ();
100 
101  const auto& colorVar = map ["color"];
102  const auto& pointsVar = map ["points"];
103 
104  if (!colorVar.canConvert<QString> () ||
105  !pointsVar.canConvert<QList<QPointF>> ())
106  {
107  qWarning () << Q_FUNC_INFO
108  << "invalid map"
109  << map;
110  qWarning () << Q_FUNC_INFO
111  << "ignoring this point";
112  continue;
113  }
114 
115  Multipoints_.append ({
116  map ["color"].toString (),
117  map ["points"].value<QList<QPointF>> ()
118  });
119  }
120  update ();
121  }
122 
123  double PlotItem::GetMinXValue () const
124  {
125  return MinXValue_;
126  }
127 
128  void PlotItem::SetMinXValue (double val)
129  {
130  SetNewValue (val, MinXValue_, [this] { emit minXValueChanged (); });
131  }
132 
133  double PlotItem::GetMaxXValue () const
134  {
135  return MaxXValue_;
136  }
137 
138  void PlotItem::SetMaxXValue (double val)
139  {
140  SetNewValue (val, MaxXValue_, [this] { emit maxXValueChanged (); });
141  }
142 
143  double PlotItem::GetMinYValue () const
144  {
145  return MinYValue_;
146  }
147 
148  void PlotItem::SetMinYValue (double val)
149  {
150  SetNewValue (val, MinYValue_, [this] { emit minYValueChanged (); });
151  }
152 
153  double PlotItem::GetMaxYValue () const
154  {
155  return MaxYValue_;
156  }
157 
158  void PlotItem::SetMaxYValue (double val)
159  {
160  SetNewValue (val, MaxYValue_, [this] { emit maxYValueChanged (); });
161  }
162 
164  {
165  return YGridEnabled_;
166  }
167 
169  {
170  SetNewValue (val, YGridEnabled_, [this] { emit yGridChanged (); });
171  }
172 
174  {
175  return YMinorGridEnabled_;
176  }
177 
179  {
180  SetNewValue (val, YMinorGridEnabled_, [this] { emit yMinorGridChanged (); });
181  }
182 
183  double PlotItem::GetAlpha () const
184  {
185  return Alpha_;
186  }
187 
188  void PlotItem::SetAlpha (double a)
189  {
190  Alpha_ = a;
191  emit alphaChanged ();
192  }
193 
194  QColor PlotItem::GetColor () const
195  {
196  return Color_;
197  }
198 
199  void PlotItem::SetColor (const QColor& color)
200  {
201  SetNewValue (color, Color_, [this] { emit colorChanged (); });
202  }
203 
205  {
206  return LeftAxisEnabled_;
207  }
208 
209  void PlotItem::SetLeftAxisEnabled (bool enabled)
210  {
211  SetNewValue (enabled, LeftAxisEnabled_, [this] { emit leftAxisEnabledChanged (); });
212  }
213 
215  {
216  return BottomAxisEnabled_;
217  }
218 
219  void PlotItem::SetBottomAxisEnabled (bool enabled)
220  {
221  SetNewValue (enabled, BottomAxisEnabled_, [this] { emit bottomAxisEnabledChanged (); });
222  }
223 
224  QString PlotItem::GetLeftAxisTitle () const
225  {
226  return LeftAxisTitle_;
227  }
228 
229  void PlotItem::SetLeftAxisTitle (const QString& title)
230  {
231  SetNewValue (title, LeftAxisTitle_, [this] { emit leftAxisTitleChanged (); });
232  }
233 
235  {
236  return BottomAxisTitle_;
237  }
238 
239  void PlotItem::SetBottomAxisTitle (const QString& title)
240  {
241  SetNewValue (title, BottomAxisTitle_, [this] { emit bottomAxisTitleChanged (); });
242  }
243 
244  QString PlotItem::GetPlotTitle () const
245  {
246  return PlotTitle_;
247  }
248 
249  void PlotItem::SetPlotTitle (const QString& title)
250  {
251  SetNewValue (title, PlotTitle_, [this] { emit plotTitleChanged (); });
252  }
253 
254  QColor PlotItem::GetBackground () const
255  {
256  return BackgroundColor_;
257  }
258 
259  void PlotItem::SetBackground (const QColor& bg)
260  {
261  SetNewValue (bg, BackgroundColor_, [this] { emit backgroundChanged (); });
262  }
263 
264  QColor PlotItem::GetTextColor () const
265  {
266  return TextColor_;
267  }
268 
269  void PlotItem::SetTextColor (const QColor& color)
270  {
271  SetNewValue (color, TextColor_, [this] { emit textColorChanged (); });
272  }
273 
275  {
276  return GridLinesColor_;
277  }
278 
279  void PlotItem::SetGridLinesColor (const QColor& color)
280  {
281  SetNewValue (color, GridLinesColor_, [this] { emit gridLinesColorChanged (); });
282  }
283 
284  int PlotItem::GetXExtent () const
285  {
286  return XExtent_;
287  }
288 
289  int PlotItem::GetYExtent () const
290  {
291  return YExtent_;
292  }
293 
294 #if QT_VERSION < 0x050000
295  void PlotItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget*)
296  {
297  const auto& rect = option->rect;
298 #else
299  void PlotItem::paint (QPainter *painter)
300  {
301  const auto& rect = contentsBoundingRect ().toRect ();
302 #endif
303 
304  if (!Plot_)
305  {
306  Plot_ = std::make_shared<QwtPlot> ();
307  Plot_->setFrameShape (QFrame::NoFrame);
308  Plot_->setFrameShadow (QFrame::Plain);
309  Plot_->setLineWidth (0);
310  Plot_->setMidLineWidth (0);
311  }
312 
313  auto& plot = *Plot_;
314  plot.enableAxis (QwtPlot::yLeft, LeftAxisEnabled_);
315  plot.enableAxis (QwtPlot::xBottom, BottomAxisEnabled_);
316  plot.setAxisTitle (QwtPlot::yLeft, LeftAxisTitle_);
317  plot.setAxisTitle (QwtPlot::xBottom, BottomAxisTitle_);
318 
319  if (plot.size () != rect.size ())
320  plot.resize (rect.size ());
321 
322  auto setPaletteColor = [&plot] (const QColor& color, QPalette::ColorRole role)
323  {
324  if (!color.isValid ())
325  return;
326 
327  auto pal = plot.palette ();
328  pal.setColor (role, { color });
329  plot.setPalette (pal);
330  };
331 
332  setPaletteColor (BackgroundColor_, QPalette::Window);
333  setPaletteColor (TextColor_, QPalette::WindowText);
334  setPaletteColor (TextColor_, QPalette::Text);
335 
336  if (!PlotTitle_.isEmpty ())
337  plot.setTitle (QwtText { PlotTitle_ });
338 
339  if (MinYValue_ < MaxYValue_)
340  {
341  plot.setAxisAutoScale (QwtPlot::yLeft, false);
342  plot.setAxisScale (QwtPlot::yLeft, MinYValue_, MaxYValue_);
343  }
344  plot.setAutoFillBackground (false);
345  plot.setCanvasBackground (Qt::transparent);
346 
347  if (YGridEnabled_)
348  {
349  auto grid = new QwtPlotGrid;
350  grid->enableYMin (YMinorGridEnabled_);
351  grid->enableX (false);
352 #if QWT_VERSION >= 0x060100
353  grid->setMajorPen (QPen (GridLinesColor_, 1, Qt::SolidLine));
354  grid->setMinorPen (QPen (GridLinesColor_, 1, Qt::DashLine));
355 #else
356  grid->setMajPen (QPen (GridLinesColor_, 1, Qt::SolidLine));
357  grid->setMinPen (QPen (GridLinesColor_, 1, Qt::DashLine));
358 #endif
359  grid->attach (&plot);
360  }
361 
362  auto items = Multipoints_;
363  if (items.isEmpty ())
364  items.push_back ({ Color_, Points_ });
365 
366  if (MinXValue_ < MaxXValue_)
367  plot.setAxisScale (QwtPlot::xBottom, MinXValue_, MaxXValue_);
368  else if (const auto ptsCount = items.first ().Points_.size ())
369  plot.setAxisScale (QwtPlot::xBottom, 0, ptsCount - 1);
370 
371  std::vector<std::unique_ptr<QwtPlotCurve>> curves;
372  for (const auto& item : items)
373  {
374  curves.emplace_back (new QwtPlotCurve);
375  const auto curve = curves.back ().get ();
376 
377  curve->setPen (QPen (item.Color_));
378  auto transpColor = item.Color_;
379  transpColor.setAlphaF (Alpha_);
380  curve->setBrush (transpColor);
381 
382  curve->setRenderHint (QwtPlotItem::RenderAntialiased);
383  curve->attach (&plot);
384 
385  curve->setSamples (item.Points_.toVector ());
386  }
387 
388  plot.replot ();
389 
390  QwtPlotRenderer {}.render (&plot, painter, rect);
391 
392  const auto xExtent = CalcXExtent (plot);
393  const auto yExtent = CalcYExtent (plot);
394  if (xExtent != XExtent_ || yExtent != YExtent_)
395  {
396  XExtent_ = xExtent;
397  YExtent_ = yExtent;
398  emit extentsChanged ();
399  }
400  }
401 
402  template<typename T>
403  void PlotItem::SetNewValue (T val, T& ourVal, const std::function<void ()>& notifier)
404  {
405  if (val == ourVal)
406  return;
407 
408  ourVal = val;
409  notifier ();
410  update ();
411  }
412 
413  int PlotItem::CalcXExtent (QwtPlot& plot) const
414  {
415  int result = 0;
416  if (LeftAxisEnabled_)
417  result += plot.axisScaleDraw (QwtPlot::yLeft)->
418  extent (plot.axisFont (QwtPlot::yLeft));
419  return result;
420  }
421 
422  int PlotItem::CalcYExtent (QwtPlot& plot) const
423  {
424  int result = 0;
425  if (BottomAxisEnabled_)
426  result += plot.axisScaleDraw (QwtPlot::xBottom)->
427  extent (plot.axisFont (QwtPlot::xBottom));
428  if (!PlotTitle_.isEmpty ())
429  result += plot.titleLabel ()->sizeHint ().height ();
430  return result;
431  }
432 }
433 }
QList< QPointF > GetPoints() const
Definition: plotitem.cpp:67
QColor GetTextColor() const
Definition: plotitem.cpp:264
double GetMinXValue() const
Definition: plotitem.cpp:123
double GetMaxXValue() const
Definition: plotitem.cpp:133
QString GetBottomAxisTitle() const
Definition: plotitem.cpp:234
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override
Definition: plotitem.cpp:295
bool GetLeftAxisEnabled() const
Definition: plotitem.cpp:204
QList< PointsSet > Multipoints_
Definition: plotitem.h:91
void SetGridLinesColor(const QColor &)
Definition: plotitem.cpp:279
void SetBottomAxisTitle(const QString &)
Definition: plotitem.cpp:239
void SetLeftAxisTitle(const QString &)
Definition: plotitem.cpp:229
void SetPoints(const QList< QPointF > &)
Definition: plotitem.cpp:72
QColor GetColor() const
Definition: plotitem.cpp:194
void SetYMinorGridEnabled(bool)
Definition: plotitem.cpp:178
QString GetPlotTitle() const
Definition: plotitem.cpp:244
QString GetLeftAxisTitle() const
Definition: plotitem.cpp:224
void SetMultipoints(const QVariant &)
Definition: plotitem.cpp:93
bool GetBottomAxisEnabled() const
Definition: plotitem.cpp:214
bool GetYMinorGridEnabled() const
Definition: plotitem.cpp:173
std::shared_ptr< QwtPlot > Plot_
Definition: plotitem.h:120
double GetAlpha() const
Definition: plotitem.cpp:183
QList< QPointF > Points_
Definition: plotitem.h:84
double GetMaxYValue() const
Definition: plotitem.cpp:153
double GetMinYValue() const
Definition: plotitem.cpp:143
QVariant GetMultipoints() const
Definition: plotitem.cpp:82
void SetColor(const QColor &)
Definition: plotitem.cpp:199
void SetBackground(const QColor &)
Definition: plotitem.cpp:259
unsigned long Window
Definition: xwrapper.h:50
bool GetYGridEnabled() const
Definition: plotitem.cpp:163
Q_DECLARE_METATYPE(LeechCraft::ANFieldData)
void SetPlotTitle(const QString &)
Definition: plotitem.cpp:249
QColor GetGridLinesColor() const
Definition: plotitem.cpp:274
QColor GetBackground() const
Definition: plotitem.cpp:254
PlotItem(QDeclarativeItem *=0)
Definition: plotitem.cpp:52
void SetBottomAxisEnabled(bool)
Definition: plotitem.cpp:219
void SetTextColor(const QColor &)
Definition: plotitem.cpp:269