QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qwt5_histogram_item.h
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * Qwt Widget Library
3  * Copyright (C) 1997 Josef Wilgen
4  * Copyright (C) 2002 Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 #ifndef HISTOGRAM_ITEM_H
11 #define HISTOGRAM_ITEM_H
12 
13 #include <qglobal.h>
14 #include <qcolor.h>
15 
16 #include "qwt_plot_item.h"
17 
18 class QwtIntervalData;
19 class QString;
20 
21 class HistogramItem: public QwtPlotItem
22 {
23  public:
24  explicit HistogramItem( const QString &title = QString::null );
25  explicit HistogramItem( const QwtText &title );
26  virtual ~HistogramItem();
27 
28  void setData( const QwtIntervalData &data );
29  const QwtIntervalData &data() const;
30 
31  void setColor( const QColor & );
32  QColor color() const;
33 
34  virtual QwtDoubleRect boundingRect() const;
35 
36  virtual int rtti() const;
37 
38  virtual void draw( QPainter *, const QwtScaleMap &xMap,
39  const QwtScaleMap &yMap, const QRect & ) const;
40 
41  virtual void updateLegend( QwtLegend * ) const;
42 
43  void setBaseline( double reference );
44  double baseline() const;
45 
47  {
48  Auto = 0,
49  Xfy = 1
50  };
51 
52  void setHistogramAttribute( HistogramAttribute, bool on = true );
54 
55  protected:
56  virtual void drawBar( QPainter *,
57  Qt::Orientation o, const QRect & ) const;
58 
59  private:
60  void init();
61 
62  class PrivateData;
63  PrivateData *d_data;
64 };
65 
66 #include <qstring.h>
67 #include <qpainter.h>
68 #include <qwt_plot.h>
69 #include <qwt_interval_data.h>
70 #include <qwt_painter.h>
71 #include <qwt_scale_map.h>
72 #include <qwt_legend_item.h>
73 
75 {
76  public:
78  QwtIntervalData data;
79  QColor color;
80  double reference;
81 };
82 
83 HistogramItem::HistogramItem( const QwtText &title ):
84  QwtPlotItem( title )
85 {
86  init();
87 }
88 
89 HistogramItem::HistogramItem( const QString &title ):
90  QwtPlotItem( QwtText( title ) )
91 {
92  init();
93 }
94 
96 {
97  delete d_data;
98 }
99 
100 void HistogramItem::init()
101 {
102  d_data = new PrivateData();
103  d_data->reference = 0.0;
105 
106  setItemAttribute( QwtPlotItem::AutoScale, true );
107  setItemAttribute( QwtPlotItem::Legend, true );
108 
109  setZ( 20.0 );
110 }
111 
112 void HistogramItem::setBaseline( double reference )
113 {
114  if ( d_data->reference != reference )
115  {
116  d_data->reference = reference;
117  itemChanged();
118  }
119 }
120 
122 {
123  return d_data->reference;
124 }
125 
126 void HistogramItem::setData( const QwtIntervalData &data )
127 {
128  d_data->data = data;
129  itemChanged();
130 }
131 
132 const QwtIntervalData &HistogramItem::data() const
133 {
134  return d_data->data;
135 }
136 
137 void HistogramItem::setColor( const QColor &color )
138 {
139  if ( d_data->color != color )
140  {
141  d_data->color = color;
142  itemChanged();
143  }
144 }
145 
146 QColor HistogramItem::color() const
147 {
148  return d_data->color;
149 }
150 
151 QwtDoubleRect HistogramItem::boundingRect() const
152 {
153  QwtDoubleRect rect = d_data->data.boundingRect();
154  if ( !rect.isValid() )
155  return rect;
156 
157  if ( d_data->attributes & Xfy )
158  {
159  rect = QwtDoubleRect( rect.y(), rect.x(),
160  rect.height(), rect.width() );
161 
162  if ( rect.left() > d_data->reference )
163  rect.setLeft( d_data->reference );
164  else if ( rect.right() < d_data->reference )
165  rect.setRight( d_data->reference );
166  }
167  else
168  {
169  if ( rect.bottom() < d_data->reference )
170  rect.setBottom( d_data->reference );
171  else if ( rect.top() > d_data->reference )
172  rect.setTop( d_data->reference );
173  }
174 
175  return rect;
176 }
177 
178 
180 {
181  return QwtPlotItem::Rtti_PlotHistogram;
182 }
183 
185 {
186  if ( bool( d_data->attributes & attribute ) == on )
187  return;
188 
189  if ( on )
190  d_data->attributes |= attribute;
191  else
192  d_data->attributes &= ~attribute;
193 
194  itemChanged();
195 }
196 
198 {
199  return d_data->attributes & attribute;
200 }
201 
202 void HistogramItem::draw( QPainter *painter, const QwtScaleMap &xMap,
203  const QwtScaleMap &yMap, const QRect & ) const
204 {
205  const QwtIntervalData &iData = d_data->data;
206 
207  painter->setPen( QPen( d_data->color ) );
208 
209  const int x0 = xMap.transform( baseline() );
210  const int y0 = yMap.transform( baseline() );
211 
212  for ( int i = 0; i < ( int )iData.size(); i++ )
213  {
214  if ( d_data->attributes & HistogramItem::Xfy )
215  {
216  const int x2 = xMap.transform( iData.value( i ) );
217  if ( x2 == x0 )
218  continue;
219 
220  int y1 = yMap.transform( iData.interval( i ).minValue() );
221  int y2 = yMap.transform( iData.interval( i ).maxValue() );
222  if ( y1 > y2 )
223  qSwap( y1, y2 );
224 
225  if ( i < ( int )iData.size() - 2 )
226  {
227  const int yy1 = yMap.transform( iData.interval( i + 1 ).minValue() );
228  const int yy2 = yMap.transform( iData.interval( i + 1 ).maxValue() );
229 
230  if ( y2 == qwtMin( yy1, yy2 ) )
231  {
232  const int xx2 = xMap.transform(
233  iData.interval( i + 1 ).minValue() );
234  if ( xx2 != x0 && (( xx2 < x0 && x2 < x0 ) ||
235  ( xx2 > x0 && x2 > x0 ) ) )
236  {
237  // One pixel distance between neighboured bars
238  y2++;
239  }
240  }
241  }
242 
243  drawBar( painter, Qt::Horizontal,
244  QRect( x0, y1, x2 - x0, y2 - y1 ) );
245  }
246  else
247  {
248  const int y2 = yMap.transform( iData.value( i ) );
249  if ( y2 == y0 )
250  continue;
251 
252  int x1 = xMap.transform( iData.interval( i ).minValue() );
253  int x2 = xMap.transform( iData.interval( i ).maxValue() );
254  if ( x1 > x2 )
255  qSwap( x1, x2 );
256 
257  if ( i < ( int )iData.size() - 2 )
258  {
259  const int xx1 = xMap.transform( iData.interval( i + 1 ).minValue() );
260  const int xx2 = xMap.transform( iData.interval( i + 1 ).maxValue() );
261 
262  if ( x2 == qwtMin( xx1, xx2 ) )
263  {
264  const int yy2 = yMap.transform( iData.value( i + 1 ) );
265  if ( yy2 != y0 && (( yy2 < y0 && y2 < y0 ) ||
266  ( yy2 > y0 && y2 > y0 ) ) )
267  {
268  // One pixel distance between neighboured bars
269  x2--;
270  }
271  }
272  }
273  drawBar( painter, Qt::Vertical,
274  QRect( x1, y0, x2 - x1, y2 - y0 ) );
275  }
276  }
277 }
278 
279 void HistogramItem::drawBar( QPainter *painter,
280  Qt::Orientation, const QRect& rect ) const
281 {
282  painter->save();
283 
284  const QColor color( painter->pen().color() );
285 #if QT_VERSION >= 0x040000
286  const QRect r = rect.normalized();
287 #else
288  const QRect r = rect.normalize();
289 #endif
290 
291  const int factor = 125;
292  const QColor light( color.light( factor ) );
293  const QColor dark( color.dark( factor ) );
294 
295  painter->setBrush( color );
296  painter->setPen( Qt::NoPen );
297  QwtPainter::drawRect( painter, r.x() + 1, r.y() + 1,
298  r.width() - 2, r.height() - 2 );
299  painter->setBrush( Qt::NoBrush );
300 
301  painter->setPen( QPen( light, 2 ) );
302 #if QT_VERSION >= 0x040000
303  QwtPainter::drawLine( painter,
304  r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2 );
305 #else
306  QwtPainter::drawLine( painter,
307  r.left(), r.top() + 2, r.right() + 1, r.top() + 2 );
308 #endif
309 
310  painter->setPen( QPen( dark, 2 ) );
311 #if QT_VERSION >= 0x040000
312  QwtPainter::drawLine( painter,
313  r.left() + 1, r.bottom(), r.right() + 1, r.bottom() );
314 #else
315  QwtPainter::drawLine( painter,
316  r.left(), r.bottom(), r.right() + 1, r.bottom() );
317 #endif
318 
319  painter->setPen( QPen( light, 1 ) );
320 
321 #if QT_VERSION >= 0x040000
322  QwtPainter::drawLine( painter,
323  r.left(), r.top() + 1, r.left(), r.bottom() );
324  QwtPainter::drawLine( painter,
325  r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1 );
326 #else
327  QwtPainter::drawLine( painter,
328  r.left(), r.top() + 1, r.left(), r.bottom() + 1 );
329  QwtPainter::drawLine( painter,
330  r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() );
331 #endif
332 
333  painter->setPen( QPen( dark, 1 ) );
334 
335 #if QT_VERSION >= 0x040000
336  QwtPainter::drawLine( painter,
337  r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() );
338  QwtPainter::drawLine( painter,
339  r.right(), r.top() + 2, r.right(), r.bottom() - 1 );
340 #else
341  QwtPainter::drawLine( painter,
342  r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1 );
343  QwtPainter::drawLine( painter,
344  r.right(), r.top() + 2, r.right(), r.bottom() );
345 #endif
346 
347  painter->restore();
348 }
349 
351 // this was adapted from QwtPlotCurve::updateLegend()
352 void HistogramItem::updateLegend( QwtLegend *legend ) const
353 {
354  if ( !legend )
355  return;
356 
357  QwtPlotItem::updateLegend( legend );
358 
359  QWidget *widget = legend->find( this );
360  if ( !widget || !widget->inherits( "QwtLegendItem" ) )
361  return;
362 
363  QwtLegendItem *legendItem = ( QwtLegendItem * )widget;
364 
365 #if QT_VERSION < 0x040000
366  const bool doUpdate = legendItem->isUpdatesEnabled();
367 #else
368  const bool doUpdate = legendItem->updatesEnabled();
369 #endif
370  legendItem->setUpdatesEnabled( false );
371 
372  const int policy = legend->displayPolicy();
373 
374  if ( policy == QwtLegend::FixedIdentifier )
375  {
376  int mode = legend->identifierMode();
377 
378  legendItem->setCurvePen( QPen( color() ) );
379 
380  if ( mode & QwtLegendItem::ShowText )
381  legendItem->setText( title() );
382  else
383  legendItem->setText( QwtText() );
384 
385  legendItem->setIdentifierMode( mode );
386  }
387  else if ( policy == QwtLegend::AutoIdentifier )
388  {
389  int mode = 0;
390 
391  legendItem->setCurvePen( QPen( color() ) );
392  mode |= QwtLegendItem::ShowLine;
393  if ( !title().isEmpty() )
394  {
395  legendItem->setText( title() );
396  mode |= QwtLegendItem::ShowText;
397  }
398  else
399  {
400  legendItem->setText( QwtText() );
401  }
402  legendItem->setIdentifierMode( mode );
403  }
404 
405  legendItem->setUpdatesEnabled( doUpdate );
406  legendItem->update();
407 }
408 
409 #endif