source: ntrip/trunk/BNC/qwt/qwt_plot_barchart.cpp@ 8963

Last change on this file since 8963 was 8127, checked in by stoecker, 7 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

File size: 11.3 KB
Line 
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#include "qwt_plot_barchart.h"
11#include "qwt_scale_map.h"
12#include "qwt_column_symbol.h"
13#include "qwt_painter.h"
14#include <qpainter.h>
15
16class QwtPlotBarChart::PrivateData
17{
18public:
19 PrivateData():
20 symbol( NULL ),
21 legendMode( QwtPlotBarChart::LegendChartTitle )
22 {
23 }
24
25 ~PrivateData()
26 {
27 delete symbol;
28 }
29
30 QwtColumnSymbol *symbol;
31 QwtPlotBarChart::LegendMode legendMode;
32};
33
34/*!
35 Constructor
36 \param title Title of the curve
37*/
38QwtPlotBarChart::QwtPlotBarChart( const QwtText &title ):
39 QwtPlotAbstractBarChart( title )
40{
41 init();
42}
43
44/*!
45 Constructor
46 \param title Title of the curve
47*/
48QwtPlotBarChart::QwtPlotBarChart( const QString &title ):
49 QwtPlotAbstractBarChart( QwtText( title ) )
50{
51 init();
52}
53
54//! Destructor
55QwtPlotBarChart::~QwtPlotBarChart()
56{
57 delete d_data;
58}
59
60void QwtPlotBarChart::init()
61{
62 d_data = new PrivateData;
63 setData( new QwtPointSeriesData() );
64}
65
66//! \return QwtPlotItem::Rtti_PlotBarChart
67int QwtPlotBarChart::rtti() const
68{
69 return QwtPlotItem::Rtti_PlotBarChart;
70}
71
72/*!
73 Initialize data with an array of points
74
75 \param samples Vector of points
76 \note QVector is implicitly shared
77 \note QPolygonF is derived from QVector<QPointF>
78*/
79void QwtPlotBarChart::setSamples(
80 const QVector<QPointF> &samples )
81{
82 setData( new QwtPointSeriesData( samples ) );
83}
84
85/*!
86 Initialize data with an array of doubles
87
88 The indices in the array are taken as x coordinate,
89 while the doubles are interpreted as y values.
90
91 \param samples Vector of y coordinates
92 \note QVector is implicitly shared
93*/
94void QwtPlotBarChart::setSamples(
95 const QVector<double> &samples )
96{
97 QVector<QPointF> points;
98 for ( int i = 0; i < samples.size(); i++ )
99 points += QPointF( i, samples[ i ] );
100
101 setData( new QwtPointSeriesData( points ) );
102}
103
104/*!
105 Assign a series of samples
106
107 setSamples() is just a wrapper for setData() without any additional
108 value - beside that it is easier to find for the developer.
109
110 \param data Data
111 \warning The item takes ownership of the data object, deleting
112 it when its not used anymore.
113*/
114void QwtPlotBarChart::setSamples( QwtSeriesData<QPointF> *data )
115{
116 setData( data );
117}
118
119/*!
120 \brief Assign a symbol
121
122 The bar chart will take the ownership of the symbol, hence the previously
123 set symbol will be delete by setting a new one. If \p symbol is
124 \c NULL no symbol will be drawn.
125
126 \param symbol Symbol
127 \sa symbol()
128*/
129void QwtPlotBarChart::setSymbol( QwtColumnSymbol *symbol )
130{
131 if ( symbol != d_data->symbol )
132 {
133 delete d_data->symbol;
134 d_data->symbol = symbol;
135
136 legendChanged();
137 itemChanged();
138 }
139}
140
141/*!
142 \return Current symbol or NULL, when no symbol has been assigned
143 \sa setSymbol()
144*/
145const QwtColumnSymbol *QwtPlotBarChart::symbol() const
146{
147 return d_data->symbol;
148}
149
150/*!
151 Set the mode that decides what to display on the legend
152
153 In case of LegendBarTitles barTitle() needs to be overloaded
154 to return individual titles for each bar.
155
156 \param mode New mode
157 \sa legendMode(), legendData(), barTitle(), QwtPlotItem::ItemAttribute
158 */
159void QwtPlotBarChart::setLegendMode( LegendMode mode )
160{
161 if ( mode != d_data->legendMode )
162 {
163 d_data->legendMode = mode;
164 legendChanged();
165 }
166}
167
168/*!
169 \return Legend mode
170 \sa setLegendMode()
171 */
172QwtPlotBarChart::LegendMode QwtPlotBarChart::legendMode() const
173{
174 return d_data->legendMode;
175}
176
177/*!
178 \return Bounding rectangle of all samples.
179 For an empty series the rectangle is invalid.
180*/
181QRectF QwtPlotBarChart::boundingRect() const
182{
183 const size_t numSamples = dataSize();
184 if ( numSamples == 0 )
185 return QwtPlotSeriesItem::boundingRect();
186
187 QRectF rect = QwtPlotSeriesItem::boundingRect();
188 if ( rect.height() >= 0 )
189 {
190 const double baseLine = baseline();
191
192 if ( rect.bottom() < baseLine )
193 rect.setBottom( baseLine );
194
195 if ( rect.top() > baseLine )
196 rect.setTop( baseLine );
197 }
198
199 if ( orientation() == Qt::Horizontal )
200 rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
201
202 return rect;
203}
204
205/*!
206 Draw an interval of the bar chart
207
208 \param painter Painter
209 \param xMap Maps x-values into pixel coordinates.
210 \param yMap Maps y-values into pixel coordinates.
211 \param canvasRect Contents rect of the canvas
212 \param from Index of the first point to be painted
213 \param to Index of the last point to be painted. If to < 0 the
214 curve will be painted to its last point.
215
216 \sa drawSymbols()
217*/
218void QwtPlotBarChart::drawSeries( QPainter *painter,
219 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
220 const QRectF &canvasRect, int from, int to ) const
221{
222 if ( to < 0 )
223 to = dataSize() - 1;
224
225 if ( from < 0 )
226 from = 0;
227
228 if ( from > to )
229 return;
230
231
232 const QRectF br = data()->boundingRect();
233 const QwtInterval interval( br.left(), br.right() );
234
235 painter->save();
236
237 for ( int i = from; i <= to; i++ )
238 {
239 drawSample( painter, xMap, yMap,
240 canvasRect, interval, i, sample( i ) );
241 }
242
243 painter->restore();
244}
245
246/*!
247 Draw a sample
248
249 \param painter Painter
250 \param xMap x map
251 \param yMap y map
252 \param canvasRect Contents rect of the canvas
253 \param boundingInterval Bounding interval of sample values
254 \param index Index of the sample
255 \param sample Value of the sample
256
257 \sa drawSeries()
258*/
259void QwtPlotBarChart::drawSample( QPainter *painter,
260 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
261 const QRectF &canvasRect, const QwtInterval &boundingInterval,
262 int index, const QPointF &sample ) const
263{
264 QwtColumnRect barRect;
265
266 if ( orientation() == Qt::Horizontal )
267 {
268 const double barHeight = sampleWidth( yMap, canvasRect.height(),
269 boundingInterval.width(), sample.y() );
270
271 const double x1 = xMap.transform( baseline() );
272 const double x2 = xMap.transform( sample.y() );
273
274 const double y = yMap.transform( sample.x() );
275 const double y1 = y - 0.5 * barHeight;
276 const double y2 = y + 0.5 * barHeight;
277
278 barRect.direction = ( x1 < x2 ) ?
279 QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft;
280
281 barRect.hInterval = QwtInterval( x1, x2 ).normalized();
282 barRect.vInterval = QwtInterval( y1, y2 );
283 }
284 else
285 {
286 const double barWidth = sampleWidth( xMap, canvasRect.width(),
287 boundingInterval.width(), sample.y() );
288
289 const double x = xMap.transform( sample.x() );
290 const double x1 = x - 0.5 * barWidth;
291 const double x2 = x + 0.5 * barWidth;
292
293 const double y1 = yMap.transform( baseline() );
294 const double y2 = yMap.transform( sample.y() );
295
296 barRect.direction = ( y1 < y2 ) ?
297 QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop;
298
299 barRect.hInterval = QwtInterval( x1, x2 );
300 barRect.vInterval = QwtInterval( y1, y2 ).normalized();
301 }
302
303 drawBar( painter, index, sample, barRect );
304}
305
306/*!
307 Draw a bar
308
309 \param painter Painter
310 \param sampleIndex Index of the sample represented by the bar
311 \param sample Value of the sample
312 \param rect Bounding rectangle of the bar
313 */
314void QwtPlotBarChart::drawBar( QPainter *painter,
315 int sampleIndex, const QPointF &sample,
316 const QwtColumnRect &rect ) const
317{
318 const QwtColumnSymbol *specialSym =
319 specialSymbol( sampleIndex, sample );
320
321 const QwtColumnSymbol *sym = specialSym;
322 if ( sym == NULL )
323 sym = d_data->symbol;
324
325 if ( sym )
326 {
327 sym->draw( painter, rect );
328 }
329 else
330 {
331 // we build a temporary default symbol
332 QwtColumnSymbol sym( QwtColumnSymbol::Box );
333 sym.setLineWidth( 1 );
334 sym.setFrameStyle( QwtColumnSymbol::Plain );
335 sym.draw( painter, rect );
336 }
337
338 delete specialSym;
339}
340
341/*!
342 Needs to be overloaded to return a
343 non default symbol for a specific sample
344
345 \param sampleIndex Index of the sample represented by the bar
346 \param sample Value of the sample
347
348 \return NULL, indicating to use the default symbol
349 */
350QwtColumnSymbol *QwtPlotBarChart::specialSymbol(
351 int sampleIndex, const QPointF &sample ) const
352{
353 Q_UNUSED( sampleIndex );
354 Q_UNUSED( sample );
355
356 return NULL;
357}
358
359/*!
360 \brief Return the title of a bar
361
362 In LegendBarTitles mode the title is displayed on
363 the legend entry corresponding to a bar.
364
365 The default implementation is a dummy, that is intended
366 to be overloaded.
367
368 \param sampleIndex Index of the bar
369 \return An empty text
370 \sa LegendBarTitles
371 */
372QwtText QwtPlotBarChart::barTitle( int sampleIndex ) const
373{
374 Q_UNUSED( sampleIndex );
375 return QwtText();
376}
377
378/*!
379 \brief Return all information, that is needed to represent
380 the item on the legend
381
382 In case of LegendBarTitles an entry for each bar is returned,
383 otherwise the chart is represented like any other plot item
384 from its title() and the legendIcon().
385
386 \return Information, that is needed to represent the item on the legend
387 \sa title(), setLegendMode(), barTitle(), QwtLegend, QwtPlotLegendItem
388 */
389QList<QwtLegendData> QwtPlotBarChart::legendData() const
390{
391 QList<QwtLegendData> list;
392
393 if ( d_data->legendMode == LegendBarTitles )
394 {
395 const size_t numSamples = dataSize();
396 for ( size_t i = 0; i < numSamples; i++ )
397 {
398 QwtLegendData data;
399
400 QVariant titleValue;
401 qVariantSetValue( titleValue, barTitle( i ) );
402 data.setValue( QwtLegendData::TitleRole, titleValue );
403
404 if ( !legendIconSize().isEmpty() )
405 {
406 QVariant iconValue;
407 qVariantSetValue( iconValue,
408 legendIcon( i, legendIconSize() ) );
409
410 data.setValue( QwtLegendData::IconRole, iconValue );
411 }
412
413 list += data;
414 }
415 }
416 else
417 {
418 return QwtPlotAbstractBarChart::legendData();
419 }
420
421 return list;
422}
423
424/*!
425 \return Icon representing a bar or the chart on the legend
426
427 When the legendMode() is LegendBarTitles the icon shows
428 the bar corresponding to index - otherwise the bar
429 displays the default symbol.
430
431 \param index Index of the legend entry
432 \param size Icon size
433
434 \sa setLegendMode(), drawBar(),
435 QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData()
436 */
437QwtGraphic QwtPlotBarChart::legendIcon(
438 int index, const QSizeF &size ) const
439{
440 QwtColumnRect column;
441 column.hInterval = QwtInterval( 0.0, size.width() - 1.0 );
442 column.vInterval = QwtInterval( 0.0, size.height() - 1.0 );
443
444 QwtGraphic icon;
445 icon.setDefaultSize( size );
446 icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
447
448 QPainter painter( &icon );
449 painter.setRenderHint( QPainter::Antialiasing,
450 testRenderHint( QwtPlotItem::RenderAntialiased ) );
451
452 int barIndex = -1;
453 if ( d_data->legendMode == QwtPlotBarChart::LegendBarTitles )
454 barIndex = index;
455
456 drawBar( &painter, barIndex, QPointF(), column );
457
458 return icon;
459}
Note: See TracBrowser for help on using the repository browser.