##// END OF EJS Templates
Clean up static variables a bit...
Miikka Heikkinen -
r2543:979fe974d5e4
parent child
Show More
@@ -1,352 +1,352
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "chartaxiselement_p.h"
22 22 #include "qabstractaxis_p.h"
23 23 #include "chartpresenter_p.h"
24 24 #include "abstractchartlayout_p.h"
25 25 #include <qmath.h>
26 26 #include <QDateTime>
27 27
28 28 QTCOMMERCIALCHART_BEGIN_NAMESPACE
29 29
30 30 static const char *labelFormatMatchString = "%[\\-\\+#\\s\\d\\.lhjztL]*([dicuoxfegXFEG])";
31 31 static QRegExp *labelFormatMatcher = 0;
32 32 class StaticLabelFormatMatcherDeleter
33 33 {
34 34 public:
35 35 StaticLabelFormatMatcherDeleter() {}
36 36 ~StaticLabelFormatMatcherDeleter() { delete labelFormatMatcher; }
37 37 };
38 StaticLabelFormatMatcherDeleter staticLabelFormatMatcherDeleter;
38 static StaticLabelFormatMatcherDeleter staticLabelFormatMatcherDeleter;
39 39
40 40 ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis)
41 41 : ChartElement(item),
42 42 m_axis(axis),
43 43 m_animation(0),
44 44 m_grid(new QGraphicsItemGroup(item)),
45 45 m_arrow(new QGraphicsItemGroup(item)),
46 46 m_shades(new QGraphicsItemGroup(item)),
47 47 m_labels(new QGraphicsItemGroup(item)),
48 48 m_title(new QGraphicsTextItem(item)),
49 49 m_intervalAxis(intervalAxis)
50 50
51 51 {
52 52 //initial initialization
53 53 m_arrow->setHandlesChildEvents(false);
54 54 m_arrow->setZValue(ChartPresenter::AxisZValue);
55 55 m_labels->setZValue(ChartPresenter::AxisZValue);
56 56 m_shades->setZValue(ChartPresenter::ShadesZValue);
57 57 m_grid->setZValue(ChartPresenter::GridZValue);
58 58 m_title->setZValue(ChartPresenter::GridZValue);
59 59 handleVisibleChanged(axis->isVisible());
60 60 connectSlots();
61 61
62 62 setFlag(QGraphicsItem::ItemHasNoContents, true);
63 63 }
64 64
65 65 ChartAxisElement::~ChartAxisElement()
66 66 {
67 67 }
68 68
69 69 void ChartAxisElement::connectSlots()
70 70 {
71 71 QObject::connect(axis(), SIGNAL(visibleChanged(bool)), this, SLOT(handleVisibleChanged(bool)));
72 72 QObject::connect(axis(), SIGNAL(lineVisibleChanged(bool)), this, SLOT(handleArrowVisibleChanged(bool)));
73 73 QObject::connect(axis(), SIGNAL(gridVisibleChanged(bool)), this, SLOT(handleGridVisibleChanged(bool)));
74 74 QObject::connect(axis(), SIGNAL(labelsVisibleChanged(bool)), this, SLOT(handleLabelsVisibleChanged(bool)));
75 75 QObject::connect(axis(), SIGNAL(shadesVisibleChanged(bool)), this, SLOT(handleShadesVisibleChanged(bool)));
76 76 QObject::connect(axis(), SIGNAL(labelsAngleChanged(int)), this, SLOT(handleLabelsAngleChanged(int)));
77 77 QObject::connect(axis(), SIGNAL(linePenChanged(const QPen&)), this, SLOT(handleArrowPenChanged(const QPen&)));
78 78 QObject::connect(axis(), SIGNAL(labelsPenChanged(const QPen&)), this, SLOT(handleLabelsPenChanged(const QPen&)));
79 79 QObject::connect(axis(), SIGNAL(labelsBrushChanged(const QBrush&)), this, SLOT(handleLabelsBrushChanged(const QBrush&)));
80 80 QObject::connect(axis(), SIGNAL(labelsFontChanged(const QFont&)), this, SLOT(handleLabelsFontChanged(const QFont&)));
81 81 QObject::connect(axis(), SIGNAL(gridLinePenChanged(const QPen&)), this, SLOT(handleGridPenChanged(const QPen&)));
82 82 QObject::connect(axis(), SIGNAL(shadesPenChanged(const QPen&)), this, SLOT(handleShadesPenChanged(const QPen&)));
83 83 QObject::connect(axis(), SIGNAL(shadesBrushChanged(const QBrush&)), this, SLOT(handleShadesBrushChanged(const QBrush&)));
84 84 QObject::connect(axis(), SIGNAL(titleTextChanged(const QString&)), this, SLOT(handleTitleTextChanged(const QString&)));
85 85 QObject::connect(axis(), SIGNAL(titleFontChanged(const QFont&)), this, SLOT(handleTitleFontChanged(const QFont&)));
86 86 QObject::connect(axis(), SIGNAL(titlePenChanged(const QPen&)), this, SLOT(handleTitlePenChanged(const QPen&)));
87 87 QObject::connect(axis(), SIGNAL(titleBrushChanged(const QBrush&)), this, SLOT(handleTitleBrushChanged(const QBrush&)));
88 88 QObject::connect(axis(), SIGNAL(titleVisibleChanged(bool)), this, SLOT(handleTitleVisibleChanged(bool)));
89 89 QObject::connect(axis()->d_ptr.data(), SIGNAL(rangeChanged(qreal, qreal)), this, SLOT(handleRangeChanged(qreal, qreal)));
90 90 }
91 91
92 92 void ChartAxisElement::handleArrowVisibleChanged(bool visible)
93 93 {
94 94 m_arrow->setVisible(visible);
95 95 }
96 96
97 97 void ChartAxisElement::handleGridVisibleChanged(bool visible)
98 98 {
99 99 m_grid->setVisible(visible);
100 100 }
101 101
102 102 void ChartAxisElement::handleLabelsVisibleChanged(bool visible)
103 103 {
104 104 QGraphicsLayoutItem::updateGeometry();
105 105 presenter()->layout()->invalidate();
106 106 m_labels->setVisible(visible);
107 107 }
108 108
109 109 void ChartAxisElement::handleShadesVisibleChanged(bool visible)
110 110 {
111 111 m_shades->setVisible(visible);
112 112 }
113 113
114 114 void ChartAxisElement::handleTitleVisibleChanged(bool visible)
115 115 {
116 116 QGraphicsLayoutItem::updateGeometry();
117 117 presenter()->layout()->invalidate();
118 118 m_title->setVisible(visible);
119 119 }
120 120
121 121 void ChartAxisElement::handleLabelsAngleChanged(int angle)
122 122 {
123 123 foreach (QGraphicsItem *item, m_labels->childItems())
124 124 item->setRotation(angle);
125 125
126 126 QGraphicsLayoutItem::updateGeometry();
127 127 presenter()->layout()->invalidate();
128 128 }
129 129
130 130 void ChartAxisElement::handleLabelsPenChanged(const QPen &pen)
131 131 {
132 132 Q_UNUSED(pen)
133 133 }
134 134
135 135 void ChartAxisElement::handleLabelsBrushChanged(const QBrush &brush)
136 136 {
137 137 foreach (QGraphicsItem *item, m_labels->childItems())
138 138 static_cast<QGraphicsTextItem *>(item)->setDefaultTextColor(brush.color());
139 139 }
140 140
141 141 void ChartAxisElement::handleLabelsFontChanged(const QFont &font)
142 142 {
143 143 foreach (QGraphicsItem *item, m_labels->childItems())
144 144 static_cast<QGraphicsTextItem *>(item)->setFont(font);
145 145 QGraphicsLayoutItem::updateGeometry();
146 146 presenter()->layout()->invalidate();
147 147 }
148 148
149 149 void ChartAxisElement::handleTitleTextChanged(const QString &title)
150 150 {
151 151 QGraphicsLayoutItem::updateGeometry();
152 152 presenter()->layout()->invalidate();
153 153 m_title->setHtml(title);
154 154 }
155 155
156 156 void ChartAxisElement::handleTitlePenChanged(const QPen &pen)
157 157 {
158 158 Q_UNUSED(pen)
159 159 }
160 160
161 161 void ChartAxisElement::handleTitleBrushChanged(const QBrush &brush)
162 162 {
163 163 m_title->setDefaultTextColor(brush.color());
164 164 }
165 165
166 166 void ChartAxisElement::handleTitleFontChanged(const QFont &font)
167 167 {
168 168 if (m_title->font() != font) {
169 169 m_title->setFont(font);
170 170 QGraphicsLayoutItem::updateGeometry();
171 171 presenter()->layout()->invalidate();
172 172 }
173 173 }
174 174
175 175 void ChartAxisElement::handleVisibleChanged(bool visible)
176 176 {
177 177 setVisible(visible);
178 178 if (!visible) {
179 179 m_grid->setVisible(visible);
180 180 m_arrow->setVisible(visible);
181 181 m_shades->setVisible(visible);
182 182 m_labels->setVisible(visible);
183 183 m_title->setVisible(visible);
184 184 } else {
185 185 m_grid->setVisible(axis()->isGridLineVisible());
186 186 m_arrow->setVisible(axis()->isLineVisible());
187 187 m_shades->setVisible(axis()->shadesVisible());
188 188 m_labels->setVisible(axis()->labelsVisible());
189 189 m_title->setVisible(axis()->isTitleVisible());
190 190 }
191 191
192 192 if (presenter()) presenter()->layout()->invalidate();
193 193 }
194 194
195 195 void ChartAxisElement::handleRangeChanged(qreal min, qreal max)
196 196 {
197 197 Q_UNUSED(min);
198 198 Q_UNUSED(max);
199 199
200 200 if (!isEmpty()) {
201 201 QVector<qreal> layout = calculateLayout();
202 202 updateLayout(layout);
203 203 QSizeF before = effectiveSizeHint(Qt::PreferredSize);
204 204 QSizeF after = sizeHint(Qt::PreferredSize);
205 205
206 206 if (before != after) {
207 207 QGraphicsLayoutItem::updateGeometry();
208 208 // We don't want to call invalidate on layout, since it will change minimum size of
209 209 // component, which we would like to avoid since it causes nasty flips when scrolling
210 210 // or zooming, instead recalculate layout and use plotArea for extra space.
211 211 presenter()->layout()->setGeometry(presenter()->layout()->geometry());
212 212 }
213 213 }
214 214 }
215 215
216 216 bool ChartAxisElement::isEmpty()
217 217 {
218 218 return axisGeometry().isEmpty()
219 219 || gridGeometry().isEmpty()
220 220 || qFuzzyCompare(min(), max());
221 221 }
222 222
223 223 qreal ChartAxisElement::min() const
224 224 {
225 225 return m_axis->d_ptr->min();
226 226 }
227 227
228 228 qreal ChartAxisElement::max() const
229 229 {
230 230 return m_axis->d_ptr->max();
231 231 }
232 232
233 233 static void appendFormattedLabel(const QString &capStr, const QByteArray &array,
234 234 QStringList &labels, qreal value)
235 235 {
236 236 if (capStr.isEmpty()) {
237 237 labels << QString();
238 238 } else if (capStr.at(0) == QLatin1Char('d')
239 239 || capStr.at(0) == QLatin1Char('i')
240 240 || capStr.at(0) == QLatin1Char('c')) {
241 241 labels << QString().sprintf(array, (qint64)value);
242 242 } else if (capStr.at(0) == QLatin1Char('u')
243 243 || capStr.at(0) == QLatin1Char('o')
244 244 || capStr.at(0) == QLatin1Char('x')
245 245 || capStr.at(0) == QLatin1Char('X')) {
246 246 labels << QString().sprintf(array, (quint64)value);
247 247 } else if (capStr.at(0) == QLatin1Char('f')
248 248 || capStr.at(0) == QLatin1Char('F')
249 249 || capStr.at(0) == QLatin1Char('e')
250 250 || capStr.at(0) == QLatin1Char('E')
251 251 || capStr.at(0) == QLatin1Char('g')
252 252 || capStr.at(0) == QLatin1Char('G')) {
253 253 labels << QString().sprintf(array, value);
254 254 } else {
255 255 labels << QString();
256 256 }
257 257 }
258 258
259 259 QStringList ChartAxisElement::createValueLabels(qreal min, qreal max, int ticks, const QString &format)
260 260 {
261 261 QStringList labels;
262 262
263 263 if (max <= min || ticks < 1)
264 264 return labels;
265 265
266 266 int n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
267 267 n++;
268 268
269 269 if (format.isNull()) {
270 270 for (int i = 0; i < ticks; i++) {
271 271 qreal value = min + (i * (max - min) / (ticks - 1));
272 272 labels << QString::number(value, 'f', n);
273 273 }
274 274 } else {
275 275 QByteArray array = format.toLatin1();
276 276 QString capStr;
277 277 if (!labelFormatMatcher)
278 278 labelFormatMatcher = new QRegExp(labelFormatMatchString);
279 279 if (labelFormatMatcher->indexIn(format, 0) != -1)
280 280 capStr = labelFormatMatcher->cap(1);
281 281 for (int i = 0; i < ticks; i++) {
282 282 qreal value = min + (i * (max - min) / (ticks - 1));
283 283 appendFormattedLabel(capStr, array, labels, value);
284 284 }
285 285 }
286 286
287 287 return labels;
288 288 }
289 289
290 290 QStringList ChartAxisElement::createLogValueLabels(qreal min, qreal max, qreal base, int ticks, const QString &format)
291 291 {
292 292 QStringList labels;
293 293
294 294 if (max <= min || ticks < 1)
295 295 return labels;
296 296
297 297 int n = 0;
298 298 if (ticks > 1)
299 299 n = qMax(int(-qFloor(log10((max - min) / (ticks - 1)))), 0);
300 300 n++;
301 301
302 302 int firstTick;
303 303 if (base > 1)
304 304 firstTick = ceil(log10(min) / log10(base));
305 305 else
306 306 firstTick = ceil(log10(max) / log10(base));
307 307
308 308 if (format.isNull()) {
309 309 for (int i = firstTick; i < ticks + firstTick; i++) {
310 310 qreal value = qPow(base, i);
311 311 labels << QString::number(value, 'f', n);
312 312 }
313 313 } else {
314 314 QByteArray array = format.toLatin1();
315 315 QString capStr;
316 316 if (!labelFormatMatcher)
317 317 labelFormatMatcher = new QRegExp(labelFormatMatchString);
318 318 if (labelFormatMatcher->indexIn(format, 0) != -1)
319 319 capStr = labelFormatMatcher->cap(1);
320 320 for (int i = firstTick; i < ticks + firstTick; i++) {
321 321 qreal value = qPow(base, i);
322 322 appendFormattedLabel(capStr, array, labels, value);
323 323 }
324 324 }
325 325
326 326 return labels;
327 327 }
328 328
329 329 QStringList ChartAxisElement::createDateTimeLabels(qreal min, qreal max,int ticks,const QString &format)
330 330 {
331 331 QStringList labels;
332 332
333 333 if (max <= min || ticks < 1)
334 334 return labels;
335 335
336 336 int n = qMax(int(-floor(log10((max - min) / (ticks - 1)))), 0);
337 337 n++;
338 338 for (int i = 0; i < ticks; i++) {
339 339 qreal value = min + (i * (max - min) / (ticks - 1));
340 340 labels << QDateTime::fromMSecsSinceEpoch(value).toString(format);
341 341 }
342 342 return labels;
343 343 }
344 344
345 345 void ChartAxisElement::axisSelected()
346 346 {
347 347 emit clicked();
348 348 }
349 349
350 350 #include "moc_chartaxiselement_p.cpp"
351 351
352 352 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,488 +1,472
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20 #include "chartpresenter_p.h"
21 21 #include "qchart.h"
22 22 #include "chartitem_p.h"
23 23 #include "qchart_p.h"
24 24 #include "qabstractaxis.h"
25 25 #include "qabstractaxis_p.h"
26 26 #include "chartdataset_p.h"
27 27 #include "chartanimation_p.h"
28 28 #include "qabstractseries_p.h"
29 29 #include "qareaseries.h"
30 30 #include "chartaxiselement_p.h"
31 31 #include "chartbackground_p.h"
32 32 #include "cartesianchartlayout_p.h"
33 33 #include "polarchartlayout_p.h"
34 34 #include "charttitle_p.h"
35 35 #include <QTimer>
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 static QGraphicsTextItem *dummyTextItem = 0;
40 static const char *truncateMatchString = "&#?[0-9a-zA-Z]*;$";
41 static QRegExp *truncateMatcher = 0;
42
43 class StaticDummyTextDeleter
44 {
45 public:
46 StaticDummyTextDeleter() {}
47 ~StaticDummyTextDeleter()
48 {
49 delete dummyTextItem;
50 delete truncateMatcher;
51 }
52 };
53 StaticDummyTextDeleter staticDummyTextDeleter;
54
55 39 ChartPresenter::ChartPresenter(QChart *chart, QChart::ChartType type)
56 40 : QObject(chart),
57 41 m_chart(chart),
58 42 m_options(QChart::NoAnimation),
59 43 m_state(ShowState),
60 44 m_background(0),
61 45 m_plotAreaBackground(0),
62 46 m_title(0)
63 47 {
64 48 if (type == QChart::ChartTypeCartesian)
65 49 m_layout = new CartesianChartLayout(this);
66 50 else if (type == QChart::ChartTypePolar)
67 51 m_layout = new PolarChartLayout(this);
68 52 Q_ASSERT(m_layout);
69 53 }
70 54
71 55 ChartPresenter::~ChartPresenter()
72 56 {
73 57
74 58 }
75 59
76 60 void ChartPresenter::setGeometry(const QRectF rect)
77 61 {
78 62 if (m_rect != rect) {
79 63 m_rect = rect;
80 64 foreach (ChartItem *chart, m_chartItems) {
81 65 chart->domain()->setSize(rect.size());
82 66 chart->setPos(rect.topLeft());
83 67 }
84 68 }
85 69 }
86 70
87 71 QRectF ChartPresenter::geometry() const
88 72 {
89 73 return m_rect;
90 74 }
91 75
92 76 void ChartPresenter::handleAxisAdded(QAbstractAxis *axis)
93 77 {
94 78 axis->d_ptr->initializeGraphics(rootItem());
95 79 axis->d_ptr->initializeAnimations(m_options);
96 80 ChartAxisElement *item = axis->d_ptr->axisItem();
97 81 item->setPresenter(this);
98 82 item->setThemeManager(m_chart->d_ptr->m_themeManager);
99 83 m_axisItems<<item;
100 84 m_axes<<axis;
101 85 m_layout->invalidate();
102 86 }
103 87
104 88 void ChartPresenter::handleAxisRemoved(QAbstractAxis *axis)
105 89 {
106 90 ChartAxisElement *item = axis->d_ptr->m_item.take();
107 91 item->hide();
108 92 item->disconnect();
109 93 item->deleteLater();
110 94 m_axisItems.removeAll(item);
111 95 m_axes.removeAll(axis);
112 96 m_layout->invalidate();
113 97 }
114 98
115 99
116 100 void ChartPresenter::handleSeriesAdded(QAbstractSeries *series)
117 101 {
118 102 series->d_ptr->initializeGraphics(rootItem());
119 103 series->d_ptr->initializeAnimations(m_options);
120 104 ChartItem *chart = series->d_ptr->chartItem();
121 105 chart->setPresenter(this);
122 106 chart->setThemeManager(m_chart->d_ptr->m_themeManager);
123 107 chart->domain()->setSize(m_rect.size());
124 108 chart->setPos(m_rect.topLeft());
125 109 chart->handleDomainUpdated(); //this could be moved to intializeGraphics when animator is refactored
126 110 m_chartItems<<chart;
127 111 m_series<<series;
128 112 m_layout->invalidate();
129 113 }
130 114
131 115 void ChartPresenter::handleSeriesRemoved(QAbstractSeries *series)
132 116 {
133 117 ChartItem *chart = series->d_ptr->m_item.take();
134 118 chart->hide();
135 119 chart->disconnect();
136 120 chart->deleteLater();
137 121 m_chartItems.removeAll(chart);
138 122 m_series.removeAll(series);
139 123 m_layout->invalidate();
140 124 }
141 125
142 126 void ChartPresenter::setAnimationOptions(QChart::AnimationOptions options)
143 127 {
144 128 if (m_options != options) {
145 129 m_options = options;
146 130
147 131 foreach(QAbstractSeries* series, m_series){
148 132 series->d_ptr->initializeAnimations(m_options);
149 133 }
150 134 foreach(QAbstractAxis* axis, m_axes){
151 135 axis->d_ptr->initializeAnimations(m_options);
152 136 }
153 137 }
154 138 }
155 139
156 140 void ChartPresenter::setState(State state,QPointF point)
157 141 {
158 142 m_state=state;
159 143 m_statePoint=point;
160 144 }
161 145
162 146 QChart::AnimationOptions ChartPresenter::animationOptions() const
163 147 {
164 148 return m_options;
165 149 }
166 150
167 151 void ChartPresenter::createBackgroundItem()
168 152 {
169 153 if (!m_background) {
170 154 m_background = new ChartBackground(rootItem());
171 155 m_background->setPen(Qt::NoPen); // Theme doesn't touch pen so don't use default
172 156 m_background->setBrush(QChartPrivate::defaultBrush());
173 157 m_background->setZValue(ChartPresenter::BackgroundZValue);
174 158 }
175 159 }
176 160
177 161 void ChartPresenter::createPlotAreaBackgroundItem()
178 162 {
179 163 if (!m_plotAreaBackground) {
180 164 if (m_chart->chartType() == QChart::ChartTypeCartesian)
181 165 m_plotAreaBackground = new QGraphicsRectItem(rootItem());
182 166 else
183 167 m_plotAreaBackground = new QGraphicsEllipseItem(rootItem());
184 168 // Use transparent pen instead of Qt::NoPen, as Qt::NoPen causes
185 169 // antialising artifacts with axis lines for some reason.
186 170 m_plotAreaBackground->setPen(QPen(Qt::transparent));
187 171 m_plotAreaBackground->setBrush(Qt::NoBrush);
188 172 m_plotAreaBackground->setZValue(ChartPresenter::PlotAreaZValue);
189 173 m_plotAreaBackground->setVisible(false);
190 174 }
191 175 }
192 176
193 177 void ChartPresenter::createTitleItem()
194 178 {
195 179 if (!m_title) {
196 180 m_title = new ChartTitle(rootItem());
197 181 m_title->setZValue(ChartPresenter::BackgroundZValue);
198 182 }
199 183 }
200 184
201 185
202 186 void ChartPresenter::handleAnimationFinished()
203 187 {
204 188 m_animations.removeAll(qobject_cast<ChartAnimation *>(sender()));
205 189 if (m_animations.empty())
206 190 emit animationsFinished();
207 191 }
208 192
209 193 void ChartPresenter::startAnimation(ChartAnimation *animation)
210 194 {
211 195 if (animation->state() != QAbstractAnimation::Stopped) animation->stop();
212 196 QObject::connect(animation, SIGNAL(finished()), this, SLOT(handleAnimationFinished()), Qt::UniqueConnection);
213 197 if (!m_animations.isEmpty())
214 198 m_animations.append(animation);
215 199 QTimer::singleShot(0, animation, SLOT(start()));
216 200 }
217 201
218 202 void ChartPresenter::setBackgroundBrush(const QBrush &brush)
219 203 {
220 204 createBackgroundItem();
221 205 m_background->setBrush(brush);
222 206 m_layout->invalidate();
223 207 }
224 208
225 209 QBrush ChartPresenter::backgroundBrush() const
226 210 {
227 211 if (!m_background)
228 212 return QBrush();
229 213 return m_background->brush();
230 214 }
231 215
232 216 void ChartPresenter::setBackgroundPen(const QPen &pen)
233 217 {
234 218 createBackgroundItem();
235 219 m_background->setPen(pen);
236 220 m_layout->invalidate();
237 221 }
238 222
239 223 QPen ChartPresenter::backgroundPen() const
240 224 {
241 225 if (!m_background)
242 226 return QPen();
243 227 return m_background->pen();
244 228 }
245 229
246 230 void ChartPresenter::setPlotAreaBackgroundBrush(const QBrush &brush)
247 231 {
248 232 createPlotAreaBackgroundItem();
249 233 m_plotAreaBackground->setBrush(brush);
250 234 m_layout->invalidate();
251 235 }
252 236
253 237 QBrush ChartPresenter::plotAreaBackgroundBrush() const
254 238 {
255 239 if (!m_plotAreaBackground)
256 240 return QBrush();
257 241 return m_plotAreaBackground->brush();
258 242 }
259 243
260 244 void ChartPresenter::setPlotAreaBackgroundPen(const QPen &pen)
261 245 {
262 246 createPlotAreaBackgroundItem();
263 247 m_plotAreaBackground->setPen(pen);
264 248 m_layout->invalidate();
265 249 }
266 250
267 251 QPen ChartPresenter::plotAreaBackgroundPen() const
268 252 {
269 253 if (!m_plotAreaBackground)
270 254 return QPen();
271 255 return m_plotAreaBackground->pen();
272 256 }
273 257
274 258 void ChartPresenter::setTitle(const QString &title)
275 259 {
276 260 createTitleItem();
277 261 m_title->setText(title);
278 262 m_layout->invalidate();
279 263 }
280 264
281 265 QString ChartPresenter::title() const
282 266 {
283 267 if (!m_title)
284 268 return QString();
285 269 return m_title->text();
286 270 }
287 271
288 272 void ChartPresenter::setTitleFont(const QFont &font)
289 273 {
290 274 createTitleItem();
291 275 m_title->setFont(font);
292 276 m_layout->invalidate();
293 277 }
294 278
295 279 QFont ChartPresenter::titleFont() const
296 280 {
297 281 if (!m_title)
298 282 return QFont();
299 283 return m_title->font();
300 284 }
301 285
302 286 void ChartPresenter::setTitleBrush(const QBrush &brush)
303 287 {
304 288 createTitleItem();
305 289 m_title->setDefaultTextColor(brush.color());
306 290 m_layout->invalidate();
307 291 }
308 292
309 293 QBrush ChartPresenter::titleBrush() const
310 294 {
311 295 if (!m_title)
312 296 return QBrush();
313 297 return QBrush(m_title->defaultTextColor());
314 298 }
315 299
316 300 void ChartPresenter::setBackgroundVisible(bool visible)
317 301 {
318 302 createBackgroundItem();
319 303 m_background->setVisible(visible);
320 304 }
321 305
322 306
323 307 bool ChartPresenter::isBackgroundVisible() const
324 308 {
325 309 if (!m_background)
326 310 return false;
327 311 return m_background->isVisible();
328 312 }
329 313
330 314 void ChartPresenter::setPlotAreaBackgroundVisible(bool visible)
331 315 {
332 316 createPlotAreaBackgroundItem();
333 317 m_plotAreaBackground->setVisible(visible);
334 318 }
335 319
336 320 bool ChartPresenter::isPlotAreaBackgroundVisible() const
337 321 {
338 322 if (!m_plotAreaBackground)
339 323 return false;
340 324 return m_plotAreaBackground->isVisible();
341 325 }
342 326
343 327 void ChartPresenter::setBackgroundDropShadowEnabled(bool enabled)
344 328 {
345 329 createBackgroundItem();
346 330 m_background->setDropShadowEnabled(enabled);
347 331 }
348 332
349 333 bool ChartPresenter::isBackgroundDropShadowEnabled() const
350 334 {
351 335 if (!m_background)
352 336 return false;
353 337 return m_background->isDropShadowEnabled();
354 338 }
355 339
356 340
357 341 AbstractChartLayout *ChartPresenter::layout()
358 342 {
359 343 return m_layout;
360 344 }
361 345
362 346 QLegend *ChartPresenter::legend()
363 347 {
364 348 return m_chart->legend();
365 349 }
366 350
367 351 void ChartPresenter::setVisible(bool visible)
368 352 {
369 353 m_chart->setVisible(visible);
370 354 }
371 355
372 356 ChartBackground *ChartPresenter::backgroundElement()
373 357 {
374 358 return m_background;
375 359 }
376 360
377 361 QAbstractGraphicsShapeItem *ChartPresenter::plotAreaElement()
378 362 {
379 363 return m_plotAreaBackground;
380 364 }
381 365
382 366 QList<ChartAxisElement *> ChartPresenter::axisItems() const
383 367 {
384 368 return m_axisItems;
385 369 }
386 370
387 371 QList<ChartItem *> ChartPresenter::chartItems() const
388 372 {
389 373 return m_chartItems;
390 374 }
391 375
392 376 ChartTitle *ChartPresenter::titleElement()
393 377 {
394 378 return m_title;
395 379 }
396 380
397 381 QRectF ChartPresenter::textBoundingRect(const QFont &font, const QString &text, qreal angle)
398 382 {
399 if (!dummyTextItem)
400 dummyTextItem = new QGraphicsTextItem;
383 static QGraphicsTextItem dummyTextItem;
401 384
402 dummyTextItem->setFont(font);
403 dummyTextItem->setHtml(text);
404 QRectF boundingRect = dummyTextItem->boundingRect();
385 dummyTextItem.setFont(font);
386 dummyTextItem.setHtml(text);
387 QRectF boundingRect = dummyTextItem.boundingRect();
405 388
406 389 // Take rotation into account
407 390 if (angle) {
408 391 QTransform transform;
409 392 transform.rotate(angle);
410 393 boundingRect = transform.mapRect(boundingRect);
411 394 }
412 395
413 396 return boundingRect;
414 397 }
415 398
416 399 // boundingRect parameter returns the rotated bounding rect of the text
417 400 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qreal angle,
418 401 qreal maxSize, Qt::Orientation constraintOrientation,
419 402 QRectF &boundingRect)
420 403 {
421 404 QString truncatedString(text);
422 405 boundingRect = textBoundingRect(font, truncatedString, angle);
423 406 qreal checkDimension = ((constraintOrientation == Qt::Horizontal)
424 407 ? boundingRect.width() : boundingRect.height());
425 408 if (checkDimension > maxSize) {
426 409 // It can be assumed that almost any amount of string manipulation is faster
427 410 // than calculating one bounding rectangle, so first prepare a list of truncated strings
428 411 // to try.
429 if (!truncateMatcher)
430 truncateMatcher = new QRegExp(truncateMatchString);
412 static const char *truncateMatchString = "&#?[0-9a-zA-Z]*;$";
413 static QRegExp truncateMatcher(truncateMatchString);
414
431 415 QVector<QString> testStrings(text.length());
432 416 int count(0);
433 417 static QLatin1Char closeTag('>');
434 418 static QLatin1Char openTag('<');
435 419 static QLatin1Char semiColon(';');
436 420 static QLatin1String ellipsis("...");
437 421 while (truncatedString.length() > 1) {
438 422 int chopIndex(-1);
439 423 int chopCount(1);
440 424 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
441 425
442 426 if (lastChar == closeTag)
443 427 chopIndex = truncatedString.lastIndexOf(openTag);
444 428 else if (lastChar == semiColon)
445 chopIndex = truncateMatcher->indexIn(truncatedString, 0);
429 chopIndex = truncateMatcher.indexIn(truncatedString, 0);
446 430
447 431 if (chopIndex != -1)
448 432 chopCount = truncatedString.length() - chopIndex;
449 433 truncatedString.chop(chopCount);
450 434 testStrings[count] = truncatedString + ellipsis;
451 435 count++;
452 436 }
453 437
454 438 // Binary search for best fit
455 439 int minIndex(0);
456 440 int maxIndex(count - 1);
457 441 int bestIndex(count);
458 442 QRectF checkRect;
459 443 while (maxIndex >= minIndex) {
460 444 int mid = (maxIndex + minIndex) / 2;
461 445 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
462 446 checkDimension = ((constraintOrientation == Qt::Horizontal)
463 447 ? checkRect.width() : checkRect.height());
464 448 if (checkDimension > maxSize) {
465 449 // Checked index too large, all under this are also too large
466 450 minIndex = mid + 1;
467 451 } else {
468 452 // Checked index fits, all over this also fit
469 453 maxIndex = mid - 1;
470 454 bestIndex = mid;
471 455 boundingRect = checkRect;
472 456 }
473 457 }
474 458 // Default to "..." if nothing fits
475 459 if (bestIndex == count) {
476 460 boundingRect = textBoundingRect(font, ellipsis, angle);
477 461 truncatedString = ellipsis;
478 462 } else {
479 463 truncatedString = testStrings.at(bestIndex);
480 464 }
481 465 }
482 466
483 467 return truncatedString;
484 468 }
485 469
486 470 #include "moc_chartpresenter_p.cpp"
487 471
488 472 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,784 +1,781
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2013 Digia Plc
4 4 ** All rights reserved.
5 5 ** For any questions to Digia, please use contact form at http://qt.digia.com
6 6 **
7 7 ** This file is part of the Qt Commercial Charts Add-on.
8 8 **
9 9 ** $QT_BEGIN_LICENSE$
10 10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 11 ** accordance with the Qt Commercial License Agreement provided with the
12 12 ** Software or, alternatively, in accordance with the terms contained in
13 13 ** a written agreement between you and Digia.
14 14 **
15 15 ** If you have questions regarding the use of this file, please use
16 16 ** contact form at http://qt.digia.com
17 17 ** $QT_END_LICENSE$
18 18 **
19 19 ****************************************************************************/
20 20
21 21 #include "qchart.h"
22 22 #include "qchart_p.h"
23 23 #include "legendscroller_p.h"
24 24 #include "qlegend_p.h"
25 25 #include "chartbackground_p.h"
26 26 #include "qabstractaxis.h"
27 27 #include "abstractchartlayout_p.h"
28 28 #include "charttheme_p.h"
29 29 #include "chartpresenter_p.h"
30 30 #include "chartdataset_p.h"
31 31 #include <QGraphicsScene>
32 32 #include <QGraphicsSceneResizeEvent>
33 33
34 34 QTCOMMERCIALCHART_BEGIN_NAMESPACE
35 35
36 36 /*!
37 37 \enum QChart::ChartTheme
38 38
39 39 This enum describes the theme used by the chart.
40 40
41 41 \value ChartThemeLight The default theme
42 42 \value ChartThemeBlueCerulean
43 43 \value ChartThemeDark
44 44 \value ChartThemeBrownSand
45 45 \value ChartThemeBlueNcs
46 46 \value ChartThemeHighContrast
47 47 \value ChartThemeBlueIcy
48 48 */
49 49
50 50 /*!
51 51 \enum QChart::AnimationOption
52 52
53 53 For enabling/disabling animations. Defaults to NoAnimation.
54 54
55 55 \value NoAnimation
56 56 \value GridAxisAnimations
57 57 \value SeriesAnimations
58 58 \value AllAnimations
59 59 */
60 60
61 61 /*!
62 62 \enum QChart::ChartType
63 63
64 64 This enum describes the chart type.
65 65
66 66 \value ChartTypeUndefined
67 67 \value ChartTypeCartesian
68 68 \value ChartTypePolar
69 69 */
70 70
71 71 /*!
72 72 \class QChart
73 73 \brief QtCommercial chart API.
74 74
75 75 QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical
76 76 representation of different types of series and other chart related objects like legend and
77 77 axes. If you simply want to show a chart in a layout, you can use the
78 78 convenience class QChartView instead of QChart.
79 79 \sa QChartView, QPolarChart
80 80 */
81 81
82 82 /*!
83 83 \property QChart::animationOptions
84 84 The animation \a options for the chart. Animations are enabled/disabled based on this setting.
85 85 */
86 86
87 87 /*!
88 88 \property QChart::backgroundVisible
89 89 Specifies whether the chart background is visible or not.
90 90 \sa setBackgroundBrush(), setBackgroundPen(), plotAreaBackgroundVisible
91 91 */
92 92
93 93 /*!
94 94 \property QChart::dropShadowEnabled
95 95 If set to true, the background drop shadow effect is enabled. If set to false, it is disabled. Note that the drop
96 96 shadow effect depends on theme, which means the setting may be changed if you switch to another theme.
97 97 */
98 98
99 99 /*!
100 100 \property QChart::minimumMargins
101 101 Minimum margins between the plot area (axes) and the edge of the chart widget.
102 102 This property is deprecated; use margins property instead.
103 103
104 104 \sa margins
105 105 */
106 106
107 107 /*!
108 108 \property QChart::margins
109 109 Margins between the plot area (axes) and the edge of the chart widget.
110 110 */
111 111
112 112 /*!
113 113 \property QChart::theme
114 114 Theme is a built-in collection of UI style related settings applied for all visual elements of a chart, like colors,
115 115 pens, brushes, and fonts of series, axes, title, and legend. \l {Chart themes demo} shows an example with a few
116 116 different themes.
117 117 \note Changing the theme will overwrite all customizations previously applied to the series.
118 118 */
119 119
120 120 /*!
121 121 \property QChart::title
122 122 Title is the name (label) of a chart. It is shown as a headline on top of the chart. Chart title supports html formatting.
123 123 */
124 124
125 125 /*!
126 126 \property QChart::chartType
127 127 Chart type indicates if the chart is a cartesian chart or a polar chart.
128 128 This property is set internally and it is read only.
129 129 \sa QPolarChart
130 130 */
131 131
132 132 /*!
133 133 \property QChart::plotAreaBackgroundVisible
134 134 Specifies whether the chart plot area background is visible or not.
135 135 \note By default the plot area background is not visible and the plot area uses
136 136 the general chart background.
137 137 \sa setPlotAreaBackgroundBrush(), setPlotAreaBackgroundPen(), backgroundVisible
138 138 */
139 139
140 140 /*!
141 141 \internal
142 142 Constructs a chart object of \a type which is a child of a \a parent.
143 143 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
144 144 This constructor is called only by subclasses.
145 145 */
146 146 QChart::QChart(QChart::ChartType type, QGraphicsItem *parent, Qt::WindowFlags wFlags)
147 147 : QGraphicsWidget(parent, wFlags),
148 148 d_ptr(new QChartPrivate(this, type))
149 149 {
150 150 d_ptr->init();
151 151 }
152 152
153 153 /*!
154 154 Constructs a chart object which is a child of a \a parent.
155 155 Parameter \a wFlags is passed to the QGraphicsWidget constructor.
156 156 */
157 157 QChart::QChart(QGraphicsItem *parent, Qt::WindowFlags wFlags)
158 158 : QGraphicsWidget(parent, wFlags),
159 159 d_ptr(new QChartPrivate(this, ChartTypeCartesian))
160 160 {
161 161 d_ptr->init();
162 162 }
163 163
164 164 /*!
165 165 Destroys the chart object and its children, like series and axis objects added to it.
166 166 */
167 167 QChart::~QChart()
168 168 {
169 169 //start by deleting dataset, it will remove all series and axes
170 170 delete d_ptr->m_dataset;
171 171 d_ptr->m_dataset = 0;
172 172 }
173 173
174 174 /*!
175 175 Adds the \a series onto the chart and takes the ownership of it.
176 176
177 177 \note A newly added series is attached to no axes by default, including any axes that were created for the chart
178 178 using createDefaultAxes() before the series was added to the chart. If no axes are attached to
179 179 the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges
180 180 that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other
181 181 series that have properly attached axes, so always make sure you either call createDefaultAxes() after
182 182 a series has been added or explicitly attach axes for the series.
183 183
184 184 \sa removeSeries(), removeAllSeries(), createDefaultAxes(), QAbstractSeries::attachAxis()
185 185 */
186 186 void QChart::addSeries(QAbstractSeries *series)
187 187 {
188 188 Q_ASSERT(series);
189 189 d_ptr->m_dataset->addSeries(series);
190 190 }
191 191
192 192 /*!
193 193 Removes the \a series from the chart.
194 194 The chart releases its ownership of the specified \a series object.
195 195
196 196 \sa addSeries(), removeAllSeries()
197 197 */
198 198 void QChart::removeSeries(QAbstractSeries *series)
199 199 {
200 200 Q_ASSERT(series);
201 201 d_ptr->m_dataset->removeSeries(series);
202 202 }
203 203
204 204 /*!
205 205 Removes and deletes all series objects that have been added to the chart.
206 206
207 207 \sa addSeries(), removeSeries()
208 208 */
209 209 void QChart::removeAllSeries()
210 210 {
211 211 foreach (QAbstractSeries *s , d_ptr->m_dataset->series()){
212 212 removeSeries(s);
213 213 delete s;
214 214 }
215 215 }
216 216
217 217 /*!
218 218 Sets the \a brush that is used for painting the background of the chart area.
219 219 */
220 220 void QChart::setBackgroundBrush(const QBrush &brush)
221 221 {
222 222 d_ptr->m_presenter->setBackgroundBrush(brush);
223 223 }
224 224
225 225 /*!
226 226 Gets the brush that is used for painting the background of the chart area.
227 227 */
228 228 QBrush QChart::backgroundBrush() const
229 229 {
230 230 return d_ptr->m_presenter->backgroundBrush();
231 231 }
232 232
233 233 /*!
234 234 Sets the \a pen that is used for painting the background of the chart area.
235 235 */
236 236 void QChart::setBackgroundPen(const QPen &pen)
237 237 {
238 238 d_ptr->m_presenter->setBackgroundPen(pen);
239 239 }
240 240
241 241 /*!
242 242 Gets the pen that is used for painting the background of the chart area.
243 243 */
244 244 QPen QChart::backgroundPen() const
245 245 {
246 246 return d_ptr->m_presenter->backgroundPen();
247 247 }
248 248
249 249 void QChart::setTitle(const QString &title)
250 250 {
251 251 d_ptr->m_presenter->setTitle(title);
252 252 }
253 253
254 254 QString QChart::title() const
255 255 {
256 256 return d_ptr->m_presenter->title();
257 257 }
258 258
259 259 /*!
260 260 Sets the \a font that is used for drawing the chart title.
261 261 */
262 262 void QChart::setTitleFont(const QFont &font)
263 263 {
264 264 d_ptr->m_presenter->setTitleFont(font);
265 265 }
266 266
267 267 /*!
268 268 Gets the font that is used for drawing the chart title.
269 269 */
270 270 QFont QChart::titleFont() const
271 271 {
272 272 return d_ptr->m_presenter->titleFont();
273 273 }
274 274
275 275 /*!
276 276 Sets the \a brush used for drawing the title text.
277 277 */
278 278 void QChart::setTitleBrush(const QBrush &brush)
279 279 {
280 280 d_ptr->m_presenter->setTitleBrush(brush);
281 281 }
282 282
283 283 /*!
284 284 Returns the brush used for drawing the title text.
285 285 */
286 286 QBrush QChart::titleBrush() const
287 287 {
288 288 return d_ptr->m_presenter->titleBrush();
289 289 }
290 290
291 291 void QChart::setTheme(QChart::ChartTheme theme)
292 292 {
293 293 d_ptr->m_themeManager->setTheme(theme);
294 294 }
295 295
296 296 QChart::ChartTheme QChart::theme() const
297 297 {
298 298 return d_ptr->m_themeManager->theme()->id();
299 299 }
300 300
301 301 /*!
302 302 Zooms in the view by a factor of two.
303 303 */
304 304 void QChart::zoomIn()
305 305 {
306 306 d_ptr->zoomIn(2.0);
307 307 }
308 308
309 309 /*!
310 310 Zooms in the view to a maximum level at which \a rect is still fully visible.
311 311 \note This is not supported for polar charts.
312 312 */
313 313 void QChart::zoomIn(const QRectF &rect)
314 314 {
315 315 if (d_ptr->m_type == QChart::ChartTypePolar)
316 316 return;
317 317 d_ptr->zoomIn(rect);
318 318 }
319 319
320 320 /*!
321 321 Zooms out the view by a factor of two.
322 322 */
323 323 void QChart::zoomOut()
324 324 {
325 325 d_ptr->zoomOut(2.0);
326 326 }
327 327
328 328 /*!
329 329 Zooms in the view by a custom \a factor.
330 330
331 331 A factor over 1.0 zooms the view in and factor between 0.0 and 1.0 zooms out.
332 332 */
333 333 void QChart::zoom(qreal factor)
334 334 {
335 335 if (qFuzzyCompare(factor, 0))
336 336 return;
337 337
338 338 if (qFuzzyCompare(factor, (qreal)1.0))
339 339 return;
340 340
341 341 if (factor < 0)
342 342 return;
343 343
344 344 if (factor > 1.0)
345 345 d_ptr->zoomIn(factor);
346 346 else
347 347 d_ptr->zoomOut(1.0 / factor);
348 348 }
349 349
350 350 /*!
351 351 Returns a pointer to the horizontal axis attached to the specified \a series.
352 352 If no \a series is specified, the first horizontal axis added to the chart is returned.
353 353
354 354 \sa addAxis(), QAbstractSeries::attachAxis()
355 355 */
356 356 QAbstractAxis *QChart::axisX(QAbstractSeries *series) const
357 357 {
358 358 QList<QAbstractAxis *> axisList = axes(Qt::Horizontal, series);
359 359 if (axisList.count())
360 360 return axisList[0];
361 361 return 0;
362 362 }
363 363
364 364 /*!
365 365 Returns a pointer to the vertical axis attached to the specified \a series.
366 366 If no \a series is specified, the first vertical axis added to the chart is returned.
367 367
368 368 \sa addAxis(), QAbstractSeries::attachAxis()
369 369 */
370 370 QAbstractAxis *QChart::axisY(QAbstractSeries *series) const
371 371 {
372 372 QList<QAbstractAxis *> axisList = axes(Qt::Vertical, series);
373 373 if (axisList.count())
374 374 return axisList[0];
375 375 return 0;
376 376 }
377 377
378 378 /*!
379 379 Returns the axes attached to the \a series with \a orientation. If no \a series is provided,
380 380 then all axes added to the chart with the specified orientation are returned.
381 381 \sa addAxis(), createDefaultAxes()
382 382 */
383 383 QList<QAbstractAxis *> QChart::axes(Qt::Orientations orientation, QAbstractSeries *series) const
384 384 {
385 385 QList<QAbstractAxis *> result ;
386 386
387 387 if (series) {
388 388 foreach (QAbstractAxis *axis, series->attachedAxes()){
389 389 if (orientation.testFlag(axis->orientation()))
390 390 result << axis;
391 391 }
392 392 } else {
393 393 foreach (QAbstractAxis *axis, d_ptr->m_dataset->axes()){
394 394 if (orientation.testFlag(axis->orientation()) && !result.contains(axis))
395 395 result << axis;
396 396 }
397 397 }
398 398
399 399 return result;
400 400 }
401 401
402 402 /*!
403 403 Creates axes for the chart based on the series that have already been added to the chart. Any axes previously added to
404 404 the chart will be deleted.
405 405
406 406 \note This function has to be called after all series have been added to the chart. The axes created by this function
407 407 will NOT get automatically attached to any series added to the chart after this function has been called.
408 408 A series with no axes attached will by default scale to utilize the entire plot area of the chart, which can be confusing
409 409 if there are other series with properly attached axes also present.
410 410
411 411 \table
412 412 \header
413 413 \o Series type
414 414 \o X-axis
415 415 \o Y-axis
416 416 \row
417 417 \o QXYSeries
418 418 \o QValueAxis
419 419 \o QValueAxis
420 420 \row
421 421 \o QBarSeries
422 422 \o QBarCategoryAxis
423 423 \o QValueAxis
424 424 \row
425 425 \o QPieSeries
426 426 \o None
427 427 \o None
428 428 \endtable
429 429
430 430 If there are several QXYSeries derived series added to the chart and no series of other types have been added, then only one pair of axes is created.
431 431 If there are several series of different types added to the chart, then each series gets its own axes pair.
432 432
433 433 The axes specific to the series can be later obtained from the chart by providing the series as the parameter for axes() function call.
434 434 QPieSeries does not create any axes.
435 435
436 436 \sa axisX(), axisY(), axes(), setAxisX(), setAxisY(), QAbstractSeries::attachAxis()
437 437 */
438 438 void QChart::createDefaultAxes()
439 439 {
440 440 d_ptr->m_dataset->createDefaultAxes();
441 441 }
442 442
443 443 /*!
444 444 Returns the legend object of the chart. Ownership stays with the chart.
445 445 */
446 446 QLegend *QChart::legend() const
447 447 {
448 448 return d_ptr->m_legend;
449 449 }
450 450
451 451 void QChart::setMinimumMargins(const QMargins &margins)
452 452 {
453 453 qWarning() << "QChart::setMinimumMargins is deprecated. Use QChart::setMargins instead.";
454 454 d_ptr->m_presenter->layout()->setMargins(margins);
455 455 }
456 456
457 457 QMargins QChart::minimumMargins() const
458 458 {
459 459 qWarning() << "QChart::minimumMargins is deprecated. Use QChart::margins instead.";
460 460 return d_ptr->m_presenter->layout()->margins();
461 461 }
462 462
463 463 void QChart::setMargins(const QMargins &margins)
464 464 {
465 465 d_ptr->m_presenter->layout()->setMargins(margins);
466 466 }
467 467
468 468 QMargins QChart::margins() const
469 469 {
470 470 return d_ptr->m_presenter->layout()->margins();
471 471 }
472 472
473 473 QChart::ChartType QChart::chartType() const
474 474 {
475 475 return d_ptr->m_type;
476 476 }
477 477
478 478 /*!
479 479 Returns the the rectangle within which the drawing of the chart is done.
480 480 It does not include the area defined by margins.
481 481 */
482 482 QRectF QChart::plotArea() const
483 483 {
484 484 return d_ptr->m_presenter->geometry();
485 485 }
486 486
487 487 /*!
488 488 Sets the \a brush for the background of the plot area of the chart.
489 489
490 490 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundPen(), plotAreaBackgroundBrush()
491 491 */
492 492 void QChart::setPlotAreaBackgroundBrush(const QBrush &brush)
493 493 {
494 494 d_ptr->m_presenter->setPlotAreaBackgroundBrush(brush);
495 495 }
496 496
497 497 /*!
498 498 Returns the brush for the background of the plot area of the chart.
499 499
500 500 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundPen(), setPlotAreaBackgroundBrush()
501 501 */
502 502 QBrush QChart::plotAreaBackgroundBrush() const
503 503 {
504 504 return d_ptr->m_presenter->plotAreaBackgroundBrush();
505 505 }
506 506
507 507 /*!
508 508 Sets the \a pen for the background of the plot area of the chart.
509 509
510 510 \sa plotArea(), plotAreaBackgroundVisible, setPlotAreaBackgroundBrush(), plotAreaBackgroundPen()
511 511 */
512 512 void QChart::setPlotAreaBackgroundPen(const QPen &pen)
513 513 {
514 514 d_ptr->m_presenter->setPlotAreaBackgroundPen(pen);
515 515 }
516 516
517 517 /*!
518 518 Returns the pen for the background of the plot area of the chart.
519 519
520 520 \sa plotArea(), plotAreaBackgroundVisible, plotAreaBackgroundBrush(), setPlotAreaBackgroundPen()
521 521 */
522 522 QPen QChart::plotAreaBackgroundPen() const
523 523 {
524 524 return d_ptr->m_presenter->plotAreaBackgroundPen();
525 525 }
526 526
527 527 void QChart::setPlotAreaBackgroundVisible(bool visible)
528 528 {
529 529 d_ptr->m_presenter->setPlotAreaBackgroundVisible(visible);
530 530 }
531 531
532 532 bool QChart::isPlotAreaBackgroundVisible() const
533 533 {
534 534 return d_ptr->m_presenter->isPlotAreaBackgroundVisible();
535 535 }
536 536
537 537 void QChart::setAnimationOptions(AnimationOptions options)
538 538 {
539 539 d_ptr->m_presenter->setAnimationOptions(options);
540 540 }
541 541
542 542 QChart::AnimationOptions QChart::animationOptions() const
543 543 {
544 544 return d_ptr->m_presenter->animationOptions();
545 545 }
546 546
547 547 /*!
548 548 Scrolls the visible area of the chart by the distance defined in the \a dx and \a dy.
549 549
550 550 For polar charts, \a dx indicates the angle along angular axis instead of distance.
551 551 */
552 552 void QChart::scroll(qreal dx, qreal dy)
553 553 {
554 554 d_ptr->scroll(dx,dy);
555 555 }
556 556
557 557 void QChart::setBackgroundVisible(bool visible)
558 558 {
559 559 d_ptr->m_presenter->setBackgroundVisible(visible);
560 560 }
561 561
562 562 bool QChart::isBackgroundVisible() const
563 563 {
564 564 return d_ptr->m_presenter->isBackgroundVisible();
565 565 }
566 566
567 567 void QChart::setDropShadowEnabled(bool enabled)
568 568 {
569 569 d_ptr->m_presenter->setBackgroundDropShadowEnabled(enabled);
570 570 }
571 571
572 572 bool QChart::isDropShadowEnabled() const
573 573 {
574 574 return d_ptr->m_presenter->isBackgroundDropShadowEnabled();
575 575 }
576 576
577 577 /*!
578 578 Returns all series that are added to the chart.
579 579
580 580 \sa addSeries(), removeSeries(), removeAllSeries()
581 581 */
582 582 QList<QAbstractSeries *> QChart::series() const
583 583 {
584 584 return d_ptr->m_dataset->series();
585 585 }
586 586
587 587 /*!
588 588 Adds the \a axis to the chart and attaches it to the \a series as a bottom-aligned horizontal axis.
589 589 The chart takes ownership of both the \a axis and the \a series.
590 590 Any horizontal axes previously attached to the \a series are deleted.
591 591
592 592 \sa axisX(), axisY(), setAxisY(), createDefaultAxes(), QAbstractSeries::attachAxis()
593 593 */
594 594 void QChart::setAxisX(QAbstractAxis *axis ,QAbstractSeries *series)
595 595 {
596 596 QList<QAbstractAxis*> list = axes(Qt::Horizontal, series);
597 597
598 598 foreach (QAbstractAxis* a, list) {
599 599 d_ptr->m_dataset->removeAxis(a);
600 600 delete a;
601 601 }
602 602
603 603 if (!d_ptr->m_dataset->axes().contains(axis))
604 604 d_ptr->m_dataset->addAxis(axis, Qt::AlignBottom);
605 605 d_ptr->m_dataset->attachAxis(series, axis);
606 606 }
607 607
608 608 /*!
609 609 Adds the \a axis to the chart and attaches it to the \a series as a left-aligned vertical axis.
610 610 The chart takes ownership of both the \a axis and the \a series.
611 611 Any vertical axes previously attached to the \a series are deleted.
612 612
613 613 \sa axisX(), axisY(), setAxisX(), createDefaultAxes(), QAbstractSeries::attachAxis()
614 614 */
615 615 void QChart::setAxisY(QAbstractAxis *axis ,QAbstractSeries *series)
616 616 {
617 617 QList<QAbstractAxis*> list = axes(Qt::Vertical, series);
618 618
619 619 foreach (QAbstractAxis* a, list) {
620 620 d_ptr->m_dataset->removeAxis(a);
621 621 delete a;
622 622 }
623 623
624 624 if (!d_ptr->m_dataset->axes().contains(axis))
625 625 d_ptr->m_dataset->addAxis(axis, Qt::AlignLeft);
626 626 d_ptr->m_dataset->attachAxis(series, axis);
627 627 }
628 628
629 629 /*!
630 630 Adds the \a axis to the chart with \a alignment. The chart takes the ownership of the axis.
631 631
632 632 \sa removeAxis(), createDefaultAxes(), QAbstractSeries::attachAxis()
633 633 */
634 634 void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
635 635 {
636 636 d_ptr->m_dataset->addAxis(axis, alignment);
637 637 }
638 638
639 639 /*!
640 640 Removes the \a axis from the chart.
641 641 The chart releases its ownership of the specified \a axis object.
642 642
643 643 \sa addAxis(), createDefaultAxes(), QAbstractSeries::detachAxis()
644 644 */
645 645 void QChart::removeAxis(QAbstractAxis *axis)
646 646 {
647 647 d_ptr->m_dataset->removeAxis(axis);
648 648 }
649 649
650 650 /*!
651 651 Returns the value in the \a series domain that corresponds to the \a position relative to chart widget.
652 652 */
653 653 QPointF QChart::mapToValue(const QPointF &position, QAbstractSeries *series)
654 654 {
655 655 return d_ptr->m_dataset->mapToValue(position, series);
656 656 }
657 657
658 658 /*!
659 659 Returns the position on the chart widget that corresponds to the \a value in the \a series domain.
660 660 */
661 661 QPointF QChart::mapToPosition(const QPointF &value, QAbstractSeries *series)
662 662 {
663 663 return d_ptr->m_dataset->mapToPosition(value, series);
664 664 }
665 665
666 666 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
667 667
668 668 QChartPrivate::QChartPrivate(QChart *q, QChart::ChartType type):
669 669 q_ptr(q),
670 670 m_legend(0),
671 671 m_dataset(new ChartDataSet(q)),
672 672 m_presenter(new ChartPresenter(q, type)),
673 673 m_themeManager(new ChartThemeManager(q)),
674 674 m_type(type)
675 675 {
676 676 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_presenter, SLOT(handleSeriesAdded(QAbstractSeries*)));
677 677 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_presenter, SLOT(handleSeriesRemoved(QAbstractSeries*)));
678 678 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_presenter, SLOT(handleAxisAdded(QAbstractAxis*)));
679 679 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_presenter, SLOT(handleAxisRemoved(QAbstractAxis*)));
680 680 QObject::connect(m_dataset, SIGNAL(seriesAdded(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesAdded(QAbstractSeries*)));
681 681 QObject::connect(m_dataset, SIGNAL(seriesRemoved(QAbstractSeries*)), m_themeManager, SLOT(handleSeriesRemoved(QAbstractSeries*)));
682 682 QObject::connect(m_dataset, SIGNAL(axisAdded(QAbstractAxis*)), m_themeManager, SLOT(handleAxisAdded(QAbstractAxis*)));
683 683 QObject::connect(m_dataset, SIGNAL(axisRemoved(QAbstractAxis*)), m_themeManager, SLOT(handleAxisRemoved(QAbstractAxis*)));
684 684 }
685 685
686 686 QChartPrivate::~QChartPrivate()
687 687 {
688 688 }
689 689
690 690 // Hackish solution to the problem of explicitly assigning the default pen/brush/font
691 691 // to a series or axis and having theme override it:
692 692 // Initialize pens, brushes, and fonts to something nobody is likely to ever use,
693 693 // so that default theme initialization will always set these properly.
694 694 QPen &QChartPrivate::defaultPen()
695 695 {
696 static QPen *defaultPen = 0;
697 if (!defaultPen)
698 defaultPen = new QPen(QColor(1, 2, 0), 0.93247536);
699 return *defaultPen;
696 static QPen defaultPen(QColor(1, 2, 0), 0.93247536);
697 return defaultPen;
700 698 }
701 699
702 700 QBrush &QChartPrivate::defaultBrush()
703 701 {
704 static QBrush *defaultBrush = 0;
705 if (!defaultBrush)
706 defaultBrush = new QBrush(QColor(1, 2, 0), Qt::Dense7Pattern);
707 return *defaultBrush;
702 static QBrush defaultBrush(QColor(1, 2, 0), Qt::Dense7Pattern);
703 return defaultBrush;
708 704 }
709 705
710 706 QFont &QChartPrivate::defaultFont()
711 707 {
712 static QFont *defaultFont = 0;
713 if (!defaultFont) {
714 defaultFont = new QFont();
715 defaultFont->setPointSizeF(8.34563465);
708 static bool defaultFontInitialized(false);
709 static QFont defaultFont;
710 if (!defaultFontInitialized) {
711 defaultFont.setPointSizeF(8.34563465);
712 defaultFontInitialized = true;
716 713 }
717 return *defaultFont;
714 return defaultFont;
718 715 }
719 716
720 717 void QChartPrivate::init()
721 718 {
722 719 m_legend = new LegendScroller(q_ptr);
723 720 q_ptr->setTheme(QChart::ChartThemeLight);
724 721 q_ptr->setLayout(m_presenter->layout());
725 722 }
726 723
727 724 void QChartPrivate::zoomIn(qreal factor)
728 725 {
729 726 QRectF rect = m_presenter->geometry();
730 727 rect.setWidth(rect.width() / factor);
731 728 rect.setHeight(rect.height() / factor);
732 729 rect.moveCenter(m_presenter->geometry().center());
733 730 zoomIn(rect);
734 731 }
735 732
736 733 void QChartPrivate::zoomIn(const QRectF &rect)
737 734 {
738 735 if (!rect.isValid())
739 736 return;
740 737
741 738 QRectF r = rect.normalized();
742 739 const QRectF geometry = m_presenter->geometry();
743 740 r.translate(-geometry.topLeft());
744 741
745 742 if (!r.isValid())
746 743 return;
747 744
748 745 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
749 746 m_presenter->setState(ChartPresenter::ZoomInState,zoomPoint);
750 747 m_dataset->zoomInDomain(r);
751 748 m_presenter->setState(ChartPresenter::ShowState,QPointF());
752 749
753 750 }
754 751
755 752 void QChartPrivate::zoomOut(qreal factor)
756 753 {
757 754 const QRectF geometry = m_presenter->geometry();
758 755
759 756 QRectF r;
760 757 r.setSize(geometry.size() / factor);
761 758 r.moveCenter(QPointF(geometry.size().width()/2 ,geometry.size().height()/2));
762 759 if (!r.isValid())
763 760 return;
764 761
765 762 QPointF zoomPoint(r.center().x() / geometry.width(), r.center().y() / geometry.height());
766 763 m_presenter->setState(ChartPresenter::ZoomOutState,zoomPoint);
767 764 m_dataset->zoomOutDomain(r);
768 765 m_presenter->setState(ChartPresenter::ShowState,QPointF());
769 766 }
770 767
771 768 void QChartPrivate::scroll(qreal dx, qreal dy)
772 769 {
773 770 if (dx < 0) m_presenter->setState(ChartPresenter::ScrollLeftState,QPointF());
774 771 if (dx > 0) m_presenter->setState(ChartPresenter::ScrollRightState,QPointF());
775 772 if (dy < 0) m_presenter->setState(ChartPresenter::ScrollUpState,QPointF());
776 773 if (dy > 0) m_presenter->setState(ChartPresenter::ScrollDownState,QPointF());
777 774
778 775 m_dataset->scrollDomain(dx, dy);
779 776 m_presenter->setState(ChartPresenter::ShowState,QPointF());
780 777 }
781 778
782 779 #include "moc_qchart.cpp"
783 780
784 781 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now