source: orange/source/orangeqt/curve.h @ 10931:7066de073e23

Revision 10931:7066de073e23, 8.6 KB checked in by mstajdohar, 22 months ago (diff)

Smooth update.

Line 
1/*
2    This file is part of the plot module for Orange
3    Copyright (C) 2011  Miha Čančula <miha@noughmad.eu>
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef CURVE_H
20#define CURVE_H
21
22#include "plotitem.h"
23#include "point.h"
24
25#include <QtGui/QPen>
26#include <QtGui/QBrush>
27#include <QtCore/QtConcurrentMap>
28#include <QtCore/QFutureWatcher>
29#include <QtCore/QParallelAnimationGroup>
30#include <QtCore/QtConcurrentRun>
31
32struct PointPosMapper{
33  PointPosMapper(const QTransform& t) : t(t) {}
34  typedef QPointF result_type;
35  result_type operator()(Point* p)
36  {
37    return t.map(p->coordinates());
38  }
39 
40private:
41    QTransform t;
42};
43
44struct PointUpdater
45{
46    PointUpdater(int symbol, QColor color, int size, Point::DisplayMode mode)
47    {
48        m_symbol = symbol;
49        m_color = color;
50        m_size = size;
51        m_mode = mode;
52    }
53   
54    void operator()(Point* point)
55    {
56        point->set_symbol(m_symbol);
57        point->set_color(m_color);
58        point->set_size(m_size);
59        point->set_display_mode(m_mode);
60    }
61   
62    private:
63     int m_symbol;
64     QColor m_color;
65     int m_size;
66     Point::DisplayMode m_mode;
67     QTransform m_scale;
68};
69
70struct Updater
71{
72    Updater(double scale, const QPen& pen, const QBrush& brush, const QPainterPath& path)
73    {
74        m_scale = scale;
75        m_pen = pen;
76        m_brush = brush;
77        m_path = path;
78    }
79   
80    void operator()(QGraphicsPathItem* item)
81    {
82        item->setBrush(m_brush);
83        item->setPen(m_pen);
84        item->setScale(m_scale);
85        item->setPath(m_path);
86    }
87   
88    double m_scale;
89    QPen m_pen;
90    QBrush m_brush;
91    QPainterPath m_path;
92};
93 
94typedef QList< DataPoint > Data;
95
96class Curve : public PlotItem
97{
98    Q_OBJECT
99 
100public:
101  enum Style {
102    Points = Qt::NoPen,
103    Lines = Qt::SolidLine,
104    Dots = Qt::DotLine,
105    Sticks = 20,
106    Steps,
107    LinesPoints,
108    UserCurve = 100
109  };
110 
111  /**
112   * @brief Default constructor
113   *
114   * Constructs a Curve from a series of data points
115   *
116   * @param x_data A list of x coordinates of data points
117   * @param y_data A list of y coordinates of data points
118   * @param parent parent item
119   **/
120  Curve(const QList< double >& x_data, const QList< double >& y_data, QGraphicsItem* parent = 0);
121  explicit Curve(QGraphicsItem* parent = 0);
122  /**
123   * Default destructor
124   *
125   **/
126  virtual ~Curve();
127   
128  /**
129   * @brief Update the curve
130   *
131   * Moves all the points to their current locations, and changes their color, shape and size.
132   * Subclasses should reimplement this method to update their specific properties.
133   *
134   **/
135   virtual void update_properties();
136 
137  Point* point_item(double x, double y, int size = 0, QGraphicsItem* parent = 0);
138 
139  QColor color() const;
140  void set_color(const QColor& color);
141 
142  QPen pen() const;
143  void set_pen(QPen pen);
144 
145  QBrush brush() const;
146  void set_brush(QBrush brush);
147 
148  int point_size() const;
149  void set_point_size(int size);
150 
151  int symbol() const;
152  void set_symbol(int symbol);
153 
154  bool is_continuous() const;
155  void set_continuous(bool continuous);
156
157  Data data() const;
158  void set_data(const QList<double> x_data, const QList<double> y_data);
159 
160  virtual QTransform graph_transform() const;
161  virtual void set_graph_transform(const QTransform& transform);
162  virtual void register_points();
163 
164  QRectF graphArea() const;
165  void setGraphArea(const QRectF& area);
166 
167  int style() const;
168  void set_style(int style);
169 
170  bool auto_update() const;
171  void set_auto_update(bool auto_update);
172 
173  QTransform zoom_transform();
174  virtual void set_zoom_transform(const QTransform& transform);
175 
176  QPainterPath continuous_path();
177
178  enum UpdateFlag
179  {
180    UpdateNumberOfItems = 0x01,
181    UpdatePosition = 0x02,
182    UpdateSymbol = 0x04,
183    UpdateSize = 0x08,
184    UpdatePen = 0x10,
185    UpdateBrush = 0x20,
186    UpdateContinuous = 0x40,
187    UpdateZoom = 0x80,
188    UpdateAll = 0xFF
189  };
190 
191  Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag)
192 
193  void set_dirty(UpdateFlags flags = UpdateAll);
194 
195  template <class Sequence, class Updater>
196  void update_items(const Sequence& sequence, Updater updater, Curve::UpdateFlag flag);
197   
198  template <class T>
199  void update_point_properties(const QByteArray& property, const QList< T >& values, bool animate = true);
200
201  template <class T>
202  void update_point_properties_threaded(const QByteArray& property, const QList<T>& values);
203 
204  void update_point_properties_same(const QByteArray& property, const QVariant& value, bool animate);
205 
206  template <class T>
207  void resize_item_list(QList< T* >& list, int size);
208
209  void set_points(const QList<Point*>& points);
210  QList<Point*> points();
211 
212  bool labels_on_marked();
213  void set_labels_on_marked(bool value);
214
215  QMap<UpdateFlag, QFuture<void> > m_currentUpdate;
216
217protected:
218  Curve::UpdateFlags needs_update();
219  void set_updated(Curve::UpdateFlags flags);
220 
221  void cancel_all_updates();
222  void update_number_of_items();
223 
224  void checkForUpdate();
225  void changeContinuous();
226 
227  bool use_animations();
228 
229public slots:
230    void update_point_coordinates();
231    void update_point_positions();
232 
233private slots:
234    void pointMapFinished();
235
236private:
237  QColor m_color;
238  int m_pointSize;
239  int m_symbol;
240  int m_style;
241  bool m_continuous;
242  Data m_data;
243  QTransform m_graphTransform;
244  QList<Point*> m_pointItems;
245  UpdateFlags m_needsUpdate;
246  bool m_autoUpdate;
247  QGraphicsPathItem* m_lineItem;
248  bool m_labels_on_marked;
249
250  QPen m_pen;
251  QBrush m_brush;
252  QTransform m_zoom_transform;
253  QMap<QByteArray, QFuture<void> > m_property_updates;
254  QFutureWatcher<QPointF> m_pos_watcher;
255  QFutureWatcher<void> m_coords_watcher;
256 
257};
258
259template <class Sequence, class Updater>
260void Curve::update_items(const Sequence& sequence, Updater updater, Curve::UpdateFlag flag)
261{
262    if (m_currentUpdate.contains(flag) && m_currentUpdate[flag].isRunning())
263    {
264        m_currentUpdate[flag].cancel();
265        m_currentUpdate[flag].waitForFinished();
266    }
267    if (!sequence.isEmpty())
268    {
269        m_currentUpdate[flag] = QtConcurrent::map(sequence, updater);
270    }
271}
272
273template < class T >
274void Curve::update_point_properties(const QByteArray& property, const QList< T >& values, bool animate)
275{
276    if (m_property_updates.contains(property))
277    {
278        m_property_updates[property].cancel();
279        m_property_updates[property].waitForFinished();
280    }
281   
282    update_number_of_items();
283   
284    int n = m_pointItems.size();
285    if (n != values.size())
286    {
287        if (values.isEmpty())
288        {
289            update_point_properties_same(property, T(), animate);
290        }
291        else
292        {
293            update_point_properties_same(property, values.first(), animate);
294        }
295       
296        return;
297    }
298   
299    if (animate && use_animations())
300    {
301        QParallelAnimationGroup* group = new QParallelAnimationGroup(this);
302        for (int i = 0; i < n; ++i)
303        {
304            QPropertyAnimation* a = new QPropertyAnimation(m_pointItems[i], property, m_pointItems[i]);
305            a->setEndValue(values[i]);
306            group->addAnimation(a);
307        }
308        group->start(QAbstractAnimation::DeleteWhenStopped);
309    }
310    else
311    {
312        m_property_updates[property] = QtConcurrent::run(this, &Curve::update_point_properties_threaded<T>, property, values);
313    }
314}
315
316template < class T >
317void Curve::update_point_properties_threaded(const QByteArray& property, const QList< T >& values)
318{
319    const int n = values.size();
320    if (n != m_pointItems.size())
321    {
322    return;
323    }
324    for (int i = 0; i < n; ++i)
325    {
326        m_pointItems[i]->setProperty(property, QVariant::fromValue<T>(values[i]));
327    }
328}
329
330template <class T>
331void Curve::resize_item_list(QList< T* >& list, int size)
332{
333    int n = list.size(); 
334    if (n > size)
335  {
336    qDeleteAll(list.constBegin() + size, list.constEnd());
337    list.erase(list.begin() + size, list.end());
338  }
339  else if (n < size)
340  { 
341#if QT_VERSION >= 0x040700
342    list.reserve(size);
343#endif
344    for (int i = 0; i < (size-n); ++i)
345    {
346      list << new T(this);
347    }
348  }
349}
350
351
352Q_DECLARE_OPERATORS_FOR_FLAGS(Curve::UpdateFlags)
353
354
355#endif // CURVE_H
Note: See TracBrowser for help on using the repository browser.