KReport

KReportItemChart.cpp
1/* This file is part of the KDE project
2 * Copyright (C) 2007-2010 by Adam Pigg (adam@piggz.co.uk)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "KReportItemChart.h"
19
20#include "KReportRenderObjects.h"
21#include "KReportUtils.h"
22
23#include <KDChartBarDiagram>
24#include <KDChartThreeDBarAttributes>
25#include <KDChartLineDiagram>
26#include <KDChartThreeDLineAttributes>
27#include <KDChartPieDiagram>
28#include <KDChartThreeDPieAttributes>
29#include <KDChartLegend>
30#include <KDChartCartesianAxis>
31#include <KDChartChart>
32#include <KDChartBackgroundAttributes>
33#include <KDChartAbstractDiagram>
34#include <KDChartAbstractCoordinatePlane>
35#include <KDChartPosition>
36
37#include <KProperty>
38#include <KPropertySet>
39
40#include "kreportplugin_debug.h"
41#include <QFontDatabase>
42
44
45KReportItemChart::KReportItemChart()
46 : m_reportData(nullptr)
47{
48 createProperties();
49}
50
51KReportItemChart::KReportItemChart(QDomNode *element)
52 : KReportItemChart()
53{
54 QDomElement e = element->toElement();
55 m_name->setValue(KReportUtils::readNameAttribute(e));
56 setItemDataSource(e.attribute("report:item-data-source"));
57 Z = e.attribute("report:z-index").toDouble();
58 m_chartType->setValue(e.attribute("report:chart-type").toInt());
59 m_chartSubType->setValue(e.attribute("report:chart-sub-type").toInt());
60 m_threeD->setValue(e.attribute("report:three-dimensions"));
61
62 m_colorScheme->setValue(e.attribute("report:chart-color-scheme"));
63 m_aa->setValue(e.attribute("report:antialiased"));
64 m_xTitle->setValue(e.attribute("report:title-x-axis"));
65 m_yTitle->setValue(e.attribute("report:title-y-axis"));
66 m_backgroundColor->setValue(e.attribute("report:background-color"));
67 m_displayLegend->setValue(e.attribute("report:display-legend"));
68 m_legendPosition->setValue(e.attribute("report:legend-position"));
69 m_legendOrientation->setValue(e.attribute("report:legend-orientation"));
70 m_linkMaster->setValue(e.attribute("report:link-master"));
71 m_linkChild->setValue(e.attribute("report:link-child"));
72
73 parseReportRect(e, &m_pos, &m_size);
74}
75
76
77KReportItemChart::~KReportItemChart()
78{
79 delete m_set;
80}
81
82void KReportItemChart::createProperties()
83{
84 m_chartWidget = 0;
85 m_set = new KPropertySet;
86
87 createDataSourceProperty();
88
89 m_font = new KProperty("font", QFontDatabase::systemFont(QFontDatabase::GeneralFont), tr("Font"), tr("Field Font"));
90
91 QList<QVariant> keys;
92 keys << 1 << 2 << 3 << 4 << 5;
93 QStringList strings;
94 strings << tr("Bar") << tr("Line") << tr("Pie") << tr("Ring") << tr("Polar");
95 KProperty::ListData *typeData = new KProperty::ListData(keys, strings);
96 m_chartType = new KProperty("chart-type", typeData, 1, tr("Chart Type"));
97
98 keys.clear();
99 strings.clear();
100 keys << 0 << 1 << 2 << 3;
101 strings << tr("Normal") << tr("Stacked") << tr("Percent") << tr("Rows");
102
103 KProperty::ListData *subData = new KProperty::ListData(keys, strings);
104
105 m_chartSubType = new KProperty("chart-sub-type", subData, 0, tr("Chart Sub Type"));
106
107 keys.clear();
108 strings.clear();
109 QStringList stringkeys;
110 stringkeys << "default" << "rainbow" << "subdued";
111 strings << tr("Default") << tr("Rainbow") << tr("Subdued");
112 m_colorScheme = new KProperty("chart-color-scheme", stringkeys, strings, "default", tr("Color Scheme"));
113
114 m_threeD = new KProperty("three-dimensions", QVariant(false),
115 tr("3D", "Three dimensions"));
116 m_aa = new KProperty("antialiased", QVariant(false), tr("Antialiased"));
117
118 m_xTitle = new KProperty("title-x-axis", QString(), tr("X Axis Title"));
119 m_yTitle = new KProperty("title-y-axis", QString(), tr("Y Axis Title"));
120
121 m_displayLegend = new KProperty("display-legend", true, tr("Display Legend"));
122
123 keys.clear();
124 strings.clear();
125 keys << (int)KDChartEnums::PositionNorth
126 << (int)KDChartEnums::PositionEast
127 << (int)KDChartEnums::PositionSouth
128 << (int)KDChartEnums::PositionWest;
129 QStringList names = KDChart::Position::printableNames();
130 foreach (const QVariant &pos, keys) {
131 strings << names[pos.toInt()-1];
132 }
133 subData = new KProperty::ListData(keys, strings);
134 m_legendPosition = new KProperty("legend-position", subData, (int)KDChartEnums::PositionEast, tr("Legend Position"));
135
136 keys.clear();
137 strings.clear();
138 keys << Qt::Horizontal << Qt::Vertical;
139 strings << tr("Horizontal") << tr("Vertical");
140 subData = new KProperty::ListData(keys, strings);
141 m_legendOrientation = new KProperty("legend-orientation", subData, Qt::Vertical, tr("Legend Orientation"));
142
143 m_backgroundColor = new KProperty("background-color", Qt::white,
144 tr("Background Color"));
145
146 m_linkMaster = new KProperty("link-master", QString(), tr("Link Master"),
147 tr("Fields from master data source"));
148 m_linkChild = new KProperty("link-child", QString(), tr("Link Child"),
149 tr("Fields from child data source"));
150
151 addDefaultProperties();
152 m_set->addProperty(m_chartType);
153 m_set->addProperty(m_chartSubType);
154 m_set->addProperty(m_font);
155 m_set->addProperty(m_colorScheme);
156 m_set->addProperty(m_threeD);
157 m_set->addProperty(m_aa);
158 m_set->addProperty(m_xTitle);
159 m_set->addProperty(m_yTitle);
160 m_set->addProperty(m_backgroundColor);
161 m_set->addProperty(m_displayLegend);
162 m_set->addProperty(m_legendPosition);
163 m_set->addProperty(m_legendOrientation);
164 m_set->addProperty(m_linkMaster);
165 m_set->addProperty(m_linkChild);
166
167 set3D(false);
168 setAA(false);
169 setColorScheme("default");
170}
171
172void KReportItemChart::set3D(bool td)
173{
174 if (m_chartWidget && m_chartWidget->barDiagram()) {
175 KDChart::BarDiagram *bar = m_chartWidget->barDiagram();
176 bar->setPen(QPen(Qt::black));
177
178 KDChart::ThreeDBarAttributes threed = bar->threeDBarAttributes();
179 threed.setEnabled(td);
180 threed.setDepth(10);
181 threed.setAngle(15);
182 threed.setUseShadowColors(true);
183 bar->setThreeDBarAttributes(threed);
184 }
185
186}
187void KReportItemChart::setAA(bool aa)
188{
189 if (m_chartWidget && m_chartWidget->diagram()) {
190 m_chartWidget->diagram()->setAntiAliasing(aa);
191 }
192}
193
194void KReportItemChart::setColorScheme(const QString &cs)
195{
196 if (m_chartWidget && m_chartWidget->diagram()) {
197 if (cs == "rainbow") {
198 m_chartWidget->diagram()->useRainbowColors();
199 } else if (cs == "subdued") {
200 m_chartWidget->diagram()->useSubduedColors();
201 } else {
202 m_chartWidget->diagram()->useDefaultColors();
203 }
204 }
205}
206
207void KReportItemChart::setConnection(const KReportData *c)
208{
209 m_reportData = c;
210 populateData();
211}
212
213void KReportItemChart::populateData()
214{
216 QStringList labels;
217
218 QStringList fn;
219
220
221 delete m_chartWidget;
222 m_chartWidget = 0;
223
224 if (m_reportData) {
225 QString src = itemDataSource();
226
227 if (!src.isEmpty()) {
228 KReportData *curs = m_reportData->create(src);
229 if (curs) {
230 const QStringList keys = m_links.keys();
231 foreach(const QString& field, keys) {
232 //kreportpluginDebug() << "Adding Expression:" << field << m_links[field];
233 curs->addExpression(field, m_links[field], '=');
234 }
235 }
236 if (curs && curs->open()) {
237 fn = curs->fieldNames();
238 //resize the data lists to match the number of columns
239 int cols = fn.count() - 1;
240 if ( cols > 0 ) {
241 data.resize(cols);
242 }
243
244 m_chartWidget = new KDChart::Widget();
245 m_chartWidget->setType((KDChart::Widget::ChartType) m_chartType->value().toInt());
246 m_chartWidget->setSubType((KDChart::Widget::SubType) m_chartSubType->value().toInt());
247 set3D(m_threeD->value().toBool());
248 setAA(m_aa->value().toBool());
249 setColorScheme(m_colorScheme->value().toString());
250 setBackgroundColor(m_backgroundColor->value().value<QColor>());
251 curs->moveFirst();
252 //bool status = true;
253 do {
254 labels << curs->value(0).toString();
255 for (int i = 1; i <= cols; ++i) {
256 data[i - 1] << curs->value(i).toDouble();
257 }
258 } while (curs->moveNext());
259
260 for (int i = 1; i <= cols; ++i) {
261 m_chartWidget->setDataset(i - 1, data[i - 1], fn[i]);
262 }
263
264 setLegend(m_displayLegend->value().toBool(), fn);
265
266 //Add the axis
267 setAxis(m_xTitle->value().toString(), m_yTitle->value().toString());
268
269 //Add the bottom labels
270 if (m_chartWidget->barDiagram() || m_chartWidget->lineDiagram()) {
271 KDChart::AbstractCartesianDiagram *dia = static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram());
272
273 foreach(KDChart::CartesianAxis* axis, dia->axes()) {
274 if (axis->position() == KDChart::CartesianAxis::Bottom) {
275 axis->setLabels(labels);
276 }
277 }
278 }
279 } else {
280 kreportpluginWarning() << "Unable to open data set";
281 }
282 delete curs;
283 curs = 0;
284 } else {
285 kreportpluginWarning() << "No source set";
286 }
287 } else {
288 kreportpluginWarning() << "No connection!";
289 }
290}
291
292QStringList KReportItemChart::masterFields() const
293{
294 return m_linkMaster->value().toString().split(',');
295}
296
297void KReportItemChart::setLinkData(QString fld, QVariant val)
298{
299 //kreportpluginDebug() << "Field: " << fld << "is" << val;
300 m_links[fld] = val;
301}
302
303void KReportItemChart::setAxis(const QString& xa, const QString &ya)
304{
305 if (!m_chartWidget) {
306 return;
307 }
308 Q_ASSERT(m_chartWidget);
309
310 if (m_chartWidget->barDiagram() || m_chartWidget->lineDiagram()) {
311 KDChart::AbstractCartesianDiagram *dia = static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram());
312 KDChart::CartesianAxis *xAxis = 0;
313 KDChart::CartesianAxis *yAxis = 0;
314
315 //delete existing axis
316 foreach(KDChart::CartesianAxis* axis, dia->axes()) {
317 if (axis->position() == KDChart::CartesianAxis::Bottom) {
318 xAxis = axis;
319 }
320 if (axis->position() == KDChart::CartesianAxis::Left) {
321 yAxis = axis;
322 }
323 }
324
325 if (!xAxis) {
326 xAxis = new KDChart::CartesianAxis(static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram()));
327 xAxis->setPosition(KDChart::CartesianAxis::Bottom);
328 dia->addAxis(xAxis);
329 }
330
331 if (!yAxis) {
332 yAxis = new KDChart::CartesianAxis(static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram()));
333 yAxis->setPosition(KDChart::CartesianAxis::Left);
334 dia->addAxis(yAxis);
335 }
336
337 xAxis->setTitleText(xa);
338 yAxis->setTitleText(ya);
339 }
340}
341
342void KReportItemChart::setBackgroundColor(const QColor&)
343{
344 //Set the background color
345 if (!m_chartWidget) {
346 return;
347 }
348 KDChart::Chart *cht = m_chartWidget->diagram()->coordinatePlane()->parent();
349
350 KDChart::BackgroundAttributes ba;
351
352 ba.setVisible(true);
353 ba.setBrush(m_backgroundColor->value().value<QColor>());
354 cht->setBackgroundAttributes(ba);
355}
356
357void KReportItemChart::setLegend(bool le, const QStringList &legends)
358{
359 //Add the legend
360 if (m_chartWidget) {
361 if (le && ! legends.isEmpty()) {
362 m_chartWidget->addLegend(KDChart::Position((KDChartEnums::PositionValue)m_legendPosition->value().toInt()));
363 m_chartWidget->legend()->setOrientation((Qt::Orientation) m_legendOrientation->value().toInt());
364 m_chartWidget->legend()->setTitleText("Legend");
365 for (int i = 1; i < legends.count(); ++i) {
366 m_chartWidget->legend()->setText(i - 1, legends[i]);
367 }
368
369 m_chartWidget->legend()->setShowLines(true);
370 } else {
371 if (m_chartWidget->legend()) {
372 m_chartWidget->takeLegend(m_chartWidget->legend());
373 }
374 }
375 }
376}
377
378// RTTI
379QString KReportItemChart::typeName() const
380{
381 return "chart";
382}
383
384int KReportItemChart::renderReportData(OROPage *page, OROSection *section, const QPointF &offset,
385 KReportData *data, KReportScriptHandler *script)
386{
387 Q_UNUSED(script);
388
389 setConnection(data);
390
391 QStringList masters = masterFields();
392 for (int i = 0; i < masters.size(); ++i) {
393 if (!masters[i].simplified().isEmpty()) {
394 setLinkData(masters[i], data->value(masters[i]));
395 }
396 }
397 populateData();
398 if (widget()) {
399 OROPicture * pic = new OROPicture();
400 widget()->setFixedSize(m_size.toScene().toSize());
401
402 QPainter p(pic->picture());
403
404 widget()->diagram()->coordinatePlane()->parent()->paint(&p, QRect(QPoint(0, 0), m_size.toScene().toSize()));
405
406 QPointF pos = m_pos.toScene();
407 QSizeF size = m_size.toScene();
408
409 pos += offset;
410
411 pic->setPosition(pos);
412 pic->setSize(size);
413 if (page) page->addPrimitive(pic);
414
415 OROPicture *p2 = static_cast<OROPicture*>(pic->clone());
416 if (p2) {
417 p2->setPosition(m_pos.toPoint());
418 if (section) {
419 section->addPrimitive(p2);
420 }
421 }
422 }
423
424 return 0;
425}
QVariant value() const
QSizeF size() const
Return the size in points.
QString itemDataSource() const
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
Defines a picture. A picture is different to an image, in that it is drawn using commands.
Represents a single a single row in a document and may contain zero or more OROPrimitives.
QString attribute(const QString &name, const QString &defValue) const const
QDomElement toElement() const const
QFont systemFont(SystemFont type)
void clear()
qsizetype count() const const
bool isEmpty() const const
void resize(qsizetype size)
qsizetype size() const const
T value(qsizetype i) const const
QList< Key > keys() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
Horizontal
bool toBool() const const
int toInt(bool *ok) const const
QString toString() const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:58 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.