File indexing completed on 2024-05-12 04:43:20
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2007-2010 by Adam Pigg (adam@piggz.co.uk) 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public 0015 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "KReportItemChart.h" 0019 0020 #include "KReportRenderObjects.h" 0021 #include "KReportUtils.h" 0022 0023 #include <KDChartBarDiagram> 0024 #include <KDChartThreeDBarAttributes> 0025 #include <KDChartLineDiagram> 0026 #include <KDChartThreeDLineAttributes> 0027 #include <KDChartPieDiagram> 0028 #include <KDChartThreeDPieAttributes> 0029 #include <KDChartLegend> 0030 #include <KDChartCartesianAxis> 0031 #include <KDChartChart> 0032 #include <KDChartBackgroundAttributes> 0033 #include <KDChartAbstractDiagram> 0034 #include <KDChartAbstractCoordinatePlane> 0035 #include <KDChartPosition> 0036 0037 #include <KProperty> 0038 #include <KPropertySet> 0039 0040 #include "kreportplugin_debug.h" 0041 #include <QFontDatabase> 0042 0043 typedef QVector<double> datalist; 0044 0045 KReportItemChart::KReportItemChart() 0046 : m_reportData(nullptr) 0047 { 0048 createProperties(); 0049 } 0050 0051 KReportItemChart::KReportItemChart(QDomNode *element) 0052 : KReportItemChart() 0053 { 0054 QDomElement e = element->toElement(); 0055 m_name->setValue(KReportUtils::readNameAttribute(e)); 0056 setItemDataSource(e.attribute("report:item-data-source")); 0057 Z = e.attribute("report:z-index").toDouble(); 0058 m_chartType->setValue(e.attribute("report:chart-type").toInt()); 0059 m_chartSubType->setValue(e.attribute("report:chart-sub-type").toInt()); 0060 m_threeD->setValue(e.attribute("report:three-dimensions")); 0061 0062 m_colorScheme->setValue(e.attribute("report:chart-color-scheme")); 0063 m_aa->setValue(e.attribute("report:antialiased")); 0064 m_xTitle->setValue(e.attribute("report:title-x-axis")); 0065 m_yTitle->setValue(e.attribute("report:title-y-axis")); 0066 m_backgroundColor->setValue(e.attribute("report:background-color")); 0067 m_displayLegend->setValue(e.attribute("report:display-legend")); 0068 m_legendPosition->setValue(e.attribute("report:legend-position")); 0069 m_legendOrientation->setValue(e.attribute("report:legend-orientation")); 0070 m_linkMaster->setValue(e.attribute("report:link-master")); 0071 m_linkChild->setValue(e.attribute("report:link-child")); 0072 0073 parseReportRect(e, &m_pos, &m_size); 0074 } 0075 0076 0077 KReportItemChart::~KReportItemChart() 0078 { 0079 delete m_set; 0080 } 0081 0082 void KReportItemChart::createProperties() 0083 { 0084 m_chartWidget = 0; 0085 m_set = new KPropertySet; 0086 0087 createDataSourceProperty(); 0088 0089 m_font = new KProperty("font", QFontDatabase::systemFont(QFontDatabase::GeneralFont), tr("Font"), tr("Field Font")); 0090 0091 QList<QVariant> keys; 0092 keys << 1 << 2 << 3 << 4 << 5; 0093 QStringList strings; 0094 strings << tr("Bar") << tr("Line") << tr("Pie") << tr("Ring") << tr("Polar"); 0095 KProperty::ListData *typeData = new KProperty::ListData(keys, strings); 0096 m_chartType = new KProperty("chart-type", typeData, 1, tr("Chart Type")); 0097 0098 keys.clear(); 0099 strings.clear(); 0100 keys << 0 << 1 << 2 << 3; 0101 strings << tr("Normal") << tr("Stacked") << tr("Percent") << tr("Rows"); 0102 0103 KProperty::ListData *subData = new KProperty::ListData(keys, strings); 0104 0105 m_chartSubType = new KProperty("chart-sub-type", subData, 0, tr("Chart Sub Type")); 0106 0107 keys.clear(); 0108 strings.clear(); 0109 QStringList stringkeys; 0110 stringkeys << "default" << "rainbow" << "subdued"; 0111 strings << tr("Default") << tr("Rainbow") << tr("Subdued"); 0112 m_colorScheme = new KProperty("chart-color-scheme", stringkeys, strings, "default", tr("Color Scheme")); 0113 0114 m_threeD = new KProperty("three-dimensions", QVariant(false), 0115 tr("3D", "Three dimensions")); 0116 m_aa = new KProperty("antialiased", QVariant(false), tr("Antialiased")); 0117 0118 m_xTitle = new KProperty("title-x-axis", QString(), tr("X Axis Title")); 0119 m_yTitle = new KProperty("title-y-axis", QString(), tr("Y Axis Title")); 0120 0121 m_displayLegend = new KProperty("display-legend", true, tr("Display Legend")); 0122 0123 keys.clear(); 0124 strings.clear(); 0125 keys << (int)KDChartEnums::PositionNorth 0126 << (int)KDChartEnums::PositionEast 0127 << (int)KDChartEnums::PositionSouth 0128 << (int)KDChartEnums::PositionWest; 0129 QStringList names = KDChart::Position::printableNames(); 0130 foreach (const QVariant &pos, keys) { 0131 strings << names[pos.toInt()-1]; 0132 } 0133 subData = new KProperty::ListData(keys, strings); 0134 m_legendPosition = new KProperty("legend-position", subData, (int)KDChartEnums::PositionEast, tr("Legend Position")); 0135 0136 keys.clear(); 0137 strings.clear(); 0138 keys << Qt::Horizontal << Qt::Vertical; 0139 strings << tr("Horizontal") << tr("Vertical"); 0140 subData = new KProperty::ListData(keys, strings); 0141 m_legendOrientation = new KProperty("legend-orientation", subData, Qt::Vertical, tr("Legend Orientation")); 0142 0143 m_backgroundColor = new KProperty("background-color", Qt::white, 0144 tr("Background Color")); 0145 0146 m_linkMaster = new KProperty("link-master", QString(), tr("Link Master"), 0147 tr("Fields from master data source")); 0148 m_linkChild = new KProperty("link-child", QString(), tr("Link Child"), 0149 tr("Fields from child data source")); 0150 0151 addDefaultProperties(); 0152 m_set->addProperty(m_chartType); 0153 m_set->addProperty(m_chartSubType); 0154 m_set->addProperty(m_font); 0155 m_set->addProperty(m_colorScheme); 0156 m_set->addProperty(m_threeD); 0157 m_set->addProperty(m_aa); 0158 m_set->addProperty(m_xTitle); 0159 m_set->addProperty(m_yTitle); 0160 m_set->addProperty(m_backgroundColor); 0161 m_set->addProperty(m_displayLegend); 0162 m_set->addProperty(m_legendPosition); 0163 m_set->addProperty(m_legendOrientation); 0164 m_set->addProperty(m_linkMaster); 0165 m_set->addProperty(m_linkChild); 0166 0167 set3D(false); 0168 setAA(false); 0169 setColorScheme("default"); 0170 } 0171 0172 void KReportItemChart::set3D(bool td) 0173 { 0174 if (m_chartWidget && m_chartWidget->barDiagram()) { 0175 KDChart::BarDiagram *bar = m_chartWidget->barDiagram(); 0176 bar->setPen(QPen(Qt::black)); 0177 0178 KDChart::ThreeDBarAttributes threed = bar->threeDBarAttributes(); 0179 threed.setEnabled(td); 0180 threed.setDepth(10); 0181 threed.setAngle(15); 0182 threed.setUseShadowColors(true); 0183 bar->setThreeDBarAttributes(threed); 0184 } 0185 0186 } 0187 void KReportItemChart::setAA(bool aa) 0188 { 0189 if (m_chartWidget && m_chartWidget->diagram()) { 0190 m_chartWidget->diagram()->setAntiAliasing(aa); 0191 } 0192 } 0193 0194 void KReportItemChart::setColorScheme(const QString &cs) 0195 { 0196 if (m_chartWidget && m_chartWidget->diagram()) { 0197 if (cs == "rainbow") { 0198 m_chartWidget->diagram()->useRainbowColors(); 0199 } else if (cs == "subdued") { 0200 m_chartWidget->diagram()->useSubduedColors(); 0201 } else { 0202 m_chartWidget->diagram()->useDefaultColors(); 0203 } 0204 } 0205 } 0206 0207 void KReportItemChart::setConnection(const KReportData *c) 0208 { 0209 m_reportData = c; 0210 populateData(); 0211 } 0212 0213 void KReportItemChart::populateData() 0214 { 0215 QVector<datalist> data; 0216 QStringList labels; 0217 0218 QStringList fn; 0219 0220 0221 delete m_chartWidget; 0222 m_chartWidget = 0; 0223 0224 if (m_reportData) { 0225 QString src = itemDataSource(); 0226 0227 if (!src.isEmpty()) { 0228 KReportData *curs = m_reportData->create(src); 0229 if (curs) { 0230 const QStringList keys = m_links.keys(); 0231 foreach(const QString& field, keys) { 0232 //kreportpluginDebug() << "Adding Expression:" << field << m_links[field]; 0233 curs->addExpression(field, m_links[field], '='); 0234 } 0235 } 0236 if (curs && curs->open()) { 0237 fn = curs->fieldNames(); 0238 //resize the data lists to match the number of columns 0239 int cols = fn.count() - 1; 0240 if ( cols > 0 ) { 0241 data.resize(cols); 0242 } 0243 0244 m_chartWidget = new KDChart::Widget(); 0245 m_chartWidget->setType((KDChart::Widget::ChartType) m_chartType->value().toInt()); 0246 m_chartWidget->setSubType((KDChart::Widget::SubType) m_chartSubType->value().toInt()); 0247 set3D(m_threeD->value().toBool()); 0248 setAA(m_aa->value().toBool()); 0249 setColorScheme(m_colorScheme->value().toString()); 0250 setBackgroundColor(m_backgroundColor->value().value<QColor>()); 0251 curs->moveFirst(); 0252 //bool status = true; 0253 do { 0254 labels << curs->value(0).toString(); 0255 for (int i = 1; i <= cols; ++i) { 0256 data[i - 1] << curs->value(i).toDouble(); 0257 } 0258 } while (curs->moveNext()); 0259 0260 for (int i = 1; i <= cols; ++i) { 0261 m_chartWidget->setDataset(i - 1, data[i - 1], fn[i]); 0262 } 0263 0264 setLegend(m_displayLegend->value().toBool(), fn); 0265 0266 //Add the axis 0267 setAxis(m_xTitle->value().toString(), m_yTitle->value().toString()); 0268 0269 //Add the bottom labels 0270 if (m_chartWidget->barDiagram() || m_chartWidget->lineDiagram()) { 0271 KDChart::AbstractCartesianDiagram *dia = static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram()); 0272 0273 foreach(KDChart::CartesianAxis* axis, dia->axes()) { 0274 if (axis->position() == KDChart::CartesianAxis::Bottom) { 0275 axis->setLabels(labels); 0276 } 0277 } 0278 } 0279 } else { 0280 kreportpluginWarning() << "Unable to open data set"; 0281 } 0282 delete curs; 0283 curs = 0; 0284 } else { 0285 kreportpluginWarning() << "No source set"; 0286 } 0287 } else { 0288 kreportpluginWarning() << "No connection!"; 0289 } 0290 } 0291 0292 QStringList KReportItemChart::masterFields() const 0293 { 0294 return m_linkMaster->value().toString().split(','); 0295 } 0296 0297 void KReportItemChart::setLinkData(QString fld, QVariant val) 0298 { 0299 //kreportpluginDebug() << "Field: " << fld << "is" << val; 0300 m_links[fld] = val; 0301 } 0302 0303 void KReportItemChart::setAxis(const QString& xa, const QString &ya) 0304 { 0305 if (!m_chartWidget) { 0306 return; 0307 } 0308 Q_ASSERT(m_chartWidget); 0309 0310 if (m_chartWidget->barDiagram() || m_chartWidget->lineDiagram()) { 0311 KDChart::AbstractCartesianDiagram *dia = static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram()); 0312 KDChart::CartesianAxis *xAxis = 0; 0313 KDChart::CartesianAxis *yAxis = 0; 0314 0315 //delete existing axis 0316 foreach(KDChart::CartesianAxis* axis, dia->axes()) { 0317 if (axis->position() == KDChart::CartesianAxis::Bottom) { 0318 xAxis = axis; 0319 } 0320 if (axis->position() == KDChart::CartesianAxis::Left) { 0321 yAxis = axis; 0322 } 0323 } 0324 0325 if (!xAxis) { 0326 xAxis = new KDChart::CartesianAxis(static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram())); 0327 xAxis->setPosition(KDChart::CartesianAxis::Bottom); 0328 dia->addAxis(xAxis); 0329 } 0330 0331 if (!yAxis) { 0332 yAxis = new KDChart::CartesianAxis(static_cast<KDChart::AbstractCartesianDiagram*>(m_chartWidget->diagram())); 0333 yAxis->setPosition(KDChart::CartesianAxis::Left); 0334 dia->addAxis(yAxis); 0335 } 0336 0337 xAxis->setTitleText(xa); 0338 yAxis->setTitleText(ya); 0339 } 0340 } 0341 0342 void KReportItemChart::setBackgroundColor(const QColor&) 0343 { 0344 //Set the background color 0345 if (!m_chartWidget) { 0346 return; 0347 } 0348 KDChart::Chart *cht = m_chartWidget->diagram()->coordinatePlane()->parent(); 0349 0350 KDChart::BackgroundAttributes ba; 0351 0352 ba.setVisible(true); 0353 ba.setBrush(m_backgroundColor->value().value<QColor>()); 0354 cht->setBackgroundAttributes(ba); 0355 } 0356 0357 void KReportItemChart::setLegend(bool le, const QStringList &legends) 0358 { 0359 //Add the legend 0360 if (m_chartWidget) { 0361 if (le && ! legends.isEmpty()) { 0362 m_chartWidget->addLegend(KDChart::Position((KDChartEnums::PositionValue)m_legendPosition->value().toInt())); 0363 m_chartWidget->legend()->setOrientation((Qt::Orientation) m_legendOrientation->value().toInt()); 0364 m_chartWidget->legend()->setTitleText("Legend"); 0365 for (int i = 1; i < legends.count(); ++i) { 0366 m_chartWidget->legend()->setText(i - 1, legends[i]); 0367 } 0368 0369 m_chartWidget->legend()->setShowLines(true); 0370 } else { 0371 if (m_chartWidget->legend()) { 0372 m_chartWidget->takeLegend(m_chartWidget->legend()); 0373 } 0374 } 0375 } 0376 } 0377 0378 // RTTI 0379 QString KReportItemChart::typeName() const 0380 { 0381 return "chart"; 0382 } 0383 0384 int KReportItemChart::renderReportData(OROPage *page, OROSection *section, const QPointF &offset, 0385 KReportData *data, KReportScriptHandler *script) 0386 { 0387 Q_UNUSED(script); 0388 0389 setConnection(data); 0390 0391 QStringList masters = masterFields(); 0392 for (int i = 0; i < masters.size(); ++i) { 0393 if (!masters[i].simplified().isEmpty()) { 0394 setLinkData(masters[i], data->value(masters[i])); 0395 } 0396 } 0397 populateData(); 0398 if (widget()) { 0399 OROPicture * pic = new OROPicture(); 0400 widget()->setFixedSize(m_size.toScene().toSize()); 0401 0402 QPainter p(pic->picture()); 0403 0404 widget()->diagram()->coordinatePlane()->parent()->paint(&p, QRect(QPoint(0, 0), m_size.toScene().toSize())); 0405 0406 QPointF pos = m_pos.toScene(); 0407 QSizeF size = m_size.toScene(); 0408 0409 pos += offset; 0410 0411 pic->setPosition(pos); 0412 pic->setSize(size); 0413 if (page) page->addPrimitive(pic); 0414 0415 OROPicture *p2 = static_cast<OROPicture*>(pic->clone()); 0416 if (p2) { 0417 p2->setPosition(m_pos.toPoint()); 0418 if (section) { 0419 section->addPrimitive(p2); 0420 } 0421 } 0422 } 0423 0424 return 0; 0425 }