KD Reports API Documentation 2.2
Loading...
Searching...
No Matches
KDReportsXmlParser.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Reports library.
4**
5** SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10
12#include "KDReportsCell.h"
15#include "KDReportsHeader_p.h"
18#include "KDReportsMainTable.h"
20#include "KDReportsReport_p.h"
24#include "KDReportsXmlHelper.h"
26
27#include <QDebug>
28#include <QDomDocument>
29#include <QDomElement>
30#include <QModelIndex>
31
32/* The default report builder adds things right away into the textdocument
33 * However for table cells we want to call the Cell methods, which store the stuff
34 * until the table is added to the report.
35 */
36class CellReportBuilder : public KDReports::ReportBuilder
37{
38public:
39 CellReportBuilder(KDReports::Cell &cell, REPORTBUILDER_CTOR_ARGDEFS)
41 , m_cell(cell)
42 {
43 }
44
45 /*reimp*/ void addInlineElementPublic(const KDReports::Element &element) override
46 {
47 m_cell.addInlineElement(element);
48 }
49 /*reimp*/ void addBlockElementPublic(const KDReports::Element &element, Qt::AlignmentFlag horizontalAlignment, const QColor &color = QColor()) override
50 {
51 Q_UNUSED(color);
52 m_cell.addElement(element, horizontalAlignment);
53 }
54 /*reimp*/ void addVariablePublic(KDReports::VariableType variable) override
55 {
56 m_cell.addVariable(variable);
57 }
58 /*reimp*/ void addVerticalSpacingPublic(qreal space) override
59 {
60 m_cell.addVerticalSpacing(space);
61 }
62
63private:
64 KDReports::Cell &m_cell;
65};
66
67bool KDReports::XmlParser::parseTableContents(KDReports::TableElement &table, const QDomNode &tableNode, KDReports::ReportBuilder &builder, bool inHeader, bool inFooter)
68{
69 // Loop over elements
70 for (QDomElement element = tableNode.firstChildElement(); !element.isNull(); element = element.nextSiblingElement()) {
71 if (testForErrorAndFillErrorDetails())
72 return false;
73
74 const QString name = element.tagName();
75 if (name == QLatin1String("cell")) {
76 const int row = element.attribute(QStringLiteral("row")).toInt();
77 const int column = element.attribute(QStringLiteral("column")).toInt();
78 const int rowSpan = element.attribute(QStringLiteral("rowspan"), QStringLiteral("1")).toInt();
79 const int colSpan = element.attribute(QStringLiteral("colspan"), QStringLiteral("1")).toInt();
80 KDReports::Cell &cell = table.cell(row, column);
81 cell.setRowSpan(rowSpan);
82 cell.setColumnSpan(colSpan);
83 const QColor bgColor = KDReports::XmlHelper::readBackground(element);
84 if (bgColor.isValid())
85 cell.setBackground(bgColor);
86 CellReportBuilder cellReportBuilder(cell, builder.contentDocumentData(), builder.contentDocumentCursor(), builder.report());
87 cellReportBuilder.copyStateFrom(builder);
88
89 if (m_xmlElementHandler && !m_xmlElementHandler->startCell(cell, element))
90 continue;
91
92 if (!processNode(element, &cellReportBuilder, inHeader, inFooter))
93 return false;
94
95 if (m_xmlElementHandler && !m_xmlElementHandler->endCell(cell, element))
96 continue;
97 }
98 }
99
100 if (testForErrorAndFillErrorDetails())
101 return false;
102
103 return true;
104}
105
106void KDReports::XmlParser::parseCommonTableAttributes(KDReports::AbstractTableElement &tableElement, QDomElement &element)
107{
108 const QColor bgColor = KDReports::XmlHelper::readBackground(element);
109 if (bgColor.isValid())
110 tableElement.setBackground(bgColor);
111 if (element.hasAttribute(QStringLiteral("border")))
112 tableElement.setBorder(element.attribute(QStringLiteral("border")).toDouble());
113 if (element.hasAttribute(QStringLiteral("width"))) {
114 QString widthStr = element.attribute(QStringLiteral("width"));
115 if (widthStr.endsWith(QLatin1Char('%'))) {
116 widthStr.truncate(widthStr.length() - 1);
117 tableElement.setWidth(widthStr.toInt(), KDReports::Percent);
118 } else {
119 tableElement.setWidth(widthStr.toInt());
120 }
121 }
122}
123
125{
126 QFont font;
127 if (element.hasAttribute(QStringLiteral("pointsize"))) {
128 const int pointSize = element.attribute(QStringLiteral("pointsize")).toInt();
129 if (pointSize)
130 font.setPointSize(pointSize);
131 }
132 if (element.hasAttribute(QStringLiteral("font"))) {
133 font.setFamily(element.attribute(QStringLiteral("font")));
134 }
135 return font;
136}
137
138static void parseHeaderFooterAttribute(KDReports::Header &header, const QDomElement &element)
139{
140 if (element.hasAttribute(QStringLiteral("font")) || element.hasAttribute(QStringLiteral("pointsize"))) {
141 const QFont font = parseFontAttributes(element);
142 header.setDefaultFont(font);
143 }
144}
145
147{
148 // Top-level element should be <report>
149 QDomElement docElement = doc.documentElement();
150 if (docElement.tagName() != QLatin1String("report")) {
151 error(QObject::tr("Expected \"<report>\" as the topmost element, but found \"<%1>\"").arg(docElement.tagName()));
152 return false;
153 }
154
155 // Support for default page orientation
156 if (docElement.hasAttribute(QStringLiteral("orientation"))) {
157 const QString orientation = docElement.attribute(QStringLiteral("orientation"));
158 if (orientation == QLatin1String("landscape"))
159 m_report->setPageOrientation(QPageLayout::Landscape);
160 else if (orientation == QLatin1String("portrait"))
161 m_report->setPageOrientation(QPageLayout::Portrait);
162 }
163
164 // Support for margins
165 double marginTop = 20.0; // defaults are duplicated in KDReportsReport.cpp
166 if (docElement.hasAttribute(QStringLiteral("margin-top")))
167 marginTop = docElement.attribute(QStringLiteral("margin-top")).toDouble();
168 double marginLeft = 20.0;
169 if (docElement.hasAttribute(QStringLiteral("margin-left")))
170 marginLeft = docElement.attribute(QStringLiteral("margin-left")).toDouble();
171 double marginBottom = 20.0;
172 if (docElement.hasAttribute(QStringLiteral("margin-bottom")))
173 marginBottom = docElement.attribute(QStringLiteral("margin-bottom")).toDouble();
174 double marginRight = 20.0;
175 if (docElement.hasAttribute(QStringLiteral("margin-right")))
176 marginRight = docElement.attribute(QStringLiteral("margin-right")).toDouble();
177 m_report->setMargins(marginTop, marginLeft, marginBottom, marginRight);
178
179 if (docElement.hasAttribute(QStringLiteral("header-body-spacing")))
180 m_report->setHeaderBodySpacing(docElement.attribute(QStringLiteral("header-body-spacing")).toDouble());
181 if (docElement.hasAttribute(QStringLiteral("footer-body-spacing")))
182 m_report->setFooterBodySpacing(docElement.attribute(QStringLiteral("footer-body-spacing")).toDouble());
183
184 // Support for default font
185 if (docElement.hasAttribute(QStringLiteral("font")) || docElement.hasAttribute(QStringLiteral("pointsize"))) {
186 const QFont font = parseFontAttributes(docElement);
187 m_report->setDefaultFont(font);
188 }
189
190 if (m_xmlElementHandler && !m_xmlElementHandler->startReport(*m_report, docElement)) {
191 if (m_errorDetails)
192 *m_errorDetails = m_xmlElementHandler->errorDetails();
193
194 return false;
195 }
196
197 if (!processNode(docElement, builder, false, false))
198 return false;
199
200 if (m_xmlElementHandler)
201 m_xmlElementHandler->endReport(*m_report, docElement);
202
203 if (testForErrorAndFillErrorDetails())
204 return false;
205
206 return true;
207}
208
209void KDReports::XmlParser::addElement(KDReports::Element &reportElement, KDReports::ReportBuilder *builder, const QDomElement &element)
210{
211 if (!builder) {
212 error(QObject::tr("<%1> is only supported in WordProcessing mode").arg(element.tagName()));
213 return;
214 }
215 if (element.hasAttribute(QStringLiteral("inline"))) {
216 builder->addInlineElementPublic(reportElement);
217 } else {
219 if (element.hasAttribute(QStringLiteral("alignment")))
220 alignment = KDReports::XmlHelper::stringToAlignment(element.attribute(QStringLiteral("alignment")));
221 builder->addBlockElementPublic(reportElement, alignment);
222 }
223}
224
225bool KDReports::XmlParser::processNode(const QDomNode &node, KDReports::ReportBuilder *builder, bool inHeader, bool inFooter)
226{
227 // Loop over elements
228 for (QDomElement element = node.firstChildElement(); !element.isNull(); element = element.nextSiblingElement()) {
229
230 if (testForErrorAndFillErrorDetails())
231 return false;
232
233 const QString name = element.tagName();
234 if (name == QLatin1String("text")) {
235 // Handle <text> element
236 KDReports::TextElement textElement;
237 QString id;
238 const QString text = extractText(element, &id, m_report->d->m_currentModel, m_report->d->m_currentRow);
239 textElement.setText(text);
240 textElement.setId(id);
241 const QColor bgColor = KDReports::XmlHelper::readBackground(element);
242 if (bgColor.isValid())
243 textElement.setBackground(bgColor);
244 if (element.hasAttribute(QStringLiteral("pointsize"))) {
245 const int pointSize = element.attribute(QStringLiteral("pointsize")).toInt();
246 if (pointSize)
247 textElement.setPointSize(pointSize);
248 }
249 if (element.hasAttribute(QStringLiteral("color"))) {
250 const QString name = element.attribute(QStringLiteral("color"));
251 textElement.setTextColor(QColor(name));
252 }
253 if (element.hasAttribute(QStringLiteral("font"))) {
254 textElement.setFontFamily(element.attribute(QStringLiteral("font")));
255 }
256 if (element.hasAttribute(QStringLiteral("bold"))) {
257 bool bold = false;
258 if (element.attribute(QStringLiteral("bold")) == QLatin1String("true"))
259 bold = true;
260 textElement.setBold(bold);
261 }
262 if (element.hasAttribute(QStringLiteral("italic"))) {
263 bool italic = false;
264 if (element.attribute(QStringLiteral("italic")) == QLatin1String("true"))
265 italic = true;
266 textElement.setItalic(italic);
267 }
268 if (element.hasAttribute(QStringLiteral("strikeout"))) {
269 bool strikeOut = false;
270 if (element.attribute(QStringLiteral("strikeout")) == QLatin1String("true"))
271 strikeOut = true;
272 textElement.setStrikeOut(strikeOut);
273 }
274 if (element.hasAttribute(QStringLiteral("underline"))) {
275 bool underline = false;
276 if (element.attribute(QStringLiteral("underline")) == QLatin1String("true"))
277 underline = true;
278 textElement.setUnderline(underline);
279 }
280
281 const QString oldId = textElement.id();
282
283 if (m_xmlElementHandler && !m_xmlElementHandler->textElement(textElement, element))
284 continue;
285
286 if (textElement.id() != oldId) {
287 // The handler modified the text element's id, look up the value again.
288 const QHash<QString, QString>::const_iterator it = m_textValues.constFind(textElement.id());
289 if (it != m_textValues.constEnd()) {
290 textElement.setText(*it);
291 }
292 }
293
294 if (!builder) {
295 error(QObject::tr("<text> is only supported in WordProcessing mode"));
296 } else {
297 if (element.hasAttribute(QStringLiteral("inline"))) {
298 builder->addInlineElementPublic(textElement);
299 } else {
301 if (element.hasAttribute(QStringLiteral("alignment")))
302 alignment = KDReports::XmlHelper::stringToAlignment(element.attribute(QStringLiteral("alignment")));
303 const QColor bgColor = KDReports::XmlHelper::readColor(element, "paragraph-background");
304 builder->addBlockElementPublic(textElement, alignment, bgColor);
305 }
306 }
307
308 } else if (name == QLatin1String("html")) {
309 // Handle <html> element
310 KDReports::HtmlElement htmlElement;
311 QString id;
312 const QString text = extractText(element, &id);
313 htmlElement.setHtml(text);
314 htmlElement.setId(id);
316 if (bgColor.isValid())
317 htmlElement.setBackground(bgColor);
318
319 const QString oldId = htmlElement.id();
320
321 if (m_xmlElementHandler && !m_xmlElementHandler->htmlElement(htmlElement, element))
322 continue;
323
324 if (htmlElement.id() != oldId) {
325 // The handler modified the text element's id, look up the value again.
326 const QHash<QString, QString>::const_iterator it = m_textValues.constFind(htmlElement.id());
327 if (it != m_textValues.constEnd()) {
328 htmlElement.setHtml(*it);
329 }
330 }
331
332 addElement(htmlElement, builder, element);
333
334 } else if (name == QLatin1String("tabs")) {
335
336 if (!builder) {
337 error(QObject::tr("<tabs> is only supported in WordProcessing mode"));
338 } else {
339 parseTabs(builder, element);
340 }
341
342 } else if (name == QLatin1String("paragraph-margins")) {
343
344 if (!builder) {
345 error(QObject::tr("<paragraph-margins> is only supported in WordProcessing mode"));
346 } else {
347 parseParagraphMargins(builder, element);
348 }
349
350 } else if (name == QLatin1String("hr")) {
351 // Handle <hr> element
352 KDReports::HtmlElement htmlElement;
353 htmlElement.setHtml(QStringLiteral("<hr>"));
354 if (m_xmlElementHandler && !m_xmlElementHandler->htmlElement(htmlElement, element))
355 continue;
356
357 addElement(htmlElement, builder, element);
358
359 } else if (name == QLatin1String("vspace")) {
360 // Handle <vspace> element
361 if (!element.hasAttribute(QStringLiteral("size")))
362 continue; // size attribute is mandatory for VSpace
363 int size = element.attribute(QStringLiteral("size")).toInt();
364 if (!builder) {
365 error(QObject::tr("<vspace> is only supported in WordProcessing mode"));
366 } else {
367 if (builder != m_report->d->builder()) {
368 error(QObject::tr("<vspace> not allowed in headers, footers, or table cells"));
369 return false;
370 }
371 }
372 if (m_xmlElementHandler && !m_xmlElementHandler->vspace(size, element))
373 continue;
374 m_report->addVerticalSpacing(size);
375 } else if (name == QLatin1String("table")) {
376 // Handle <table> element
377 const QString model = element.attribute(QStringLiteral("model"));
378 if (model.isEmpty()) {
379 if (!builder) {
380 error(QObject::tr("<table> without a model is only supported in WordProcessing mode"));
381 continue;
382 }
383 KDReports::TableElement tableElement;
384 const int headerRowCount = element.attribute(QStringLiteral("headerRowCount")).toInt(); // default 0
385 tableElement.setHeaderRowCount(headerRowCount);
386 if (element.hasAttribute(QStringLiteral("cellpadding")))
387 tableElement.setPadding(element.attribute(QStringLiteral("cellpadding")).toInt());
388 parseCommonTableAttributes(tableElement, element);
389
390 if (m_xmlElementHandler && !m_xmlElementHandler->startTableElement(tableElement, element))
391 continue;
392
393 if (!parseTableContents(tableElement, element, *builder, inHeader, inFooter))
394 return false;
395
396 if (m_xmlElementHandler && !m_xmlElementHandler->endTableElement(tableElement, element))
397 continue;
398
399 addElement(tableElement, builder, element);
400
401 } else {
402 KDReports::AutoTableElement tableElement(model);
403 if (element.attribute(QStringLiteral("verticalHeaderVisible")) == QLatin1String("false"))
404 tableElement.setVerticalHeaderVisible(false);
405 if (element.attribute(QStringLiteral("horizontalHeaderVisible")) == QLatin1String("false"))
406 tableElement.setHorizontalHeaderVisible(false);
407 QColor headerBgColor = KDReports::XmlHelper::readColor(element, "header-background");
408 if (headerBgColor.isValid())
409 tableElement.setHeaderBackground(headerBgColor);
410 parseCommonTableAttributes(tableElement, element);
411 if (m_xmlElementHandler && !m_xmlElementHandler->autoTableElement(tableElement, element))
412 continue;
413
414 if (m_report->reportMode() == Report::SpreadSheet) {
415 m_report->mainTable()->setAutoTableElement(tableElement);
416 } else {
417 addElement(tableElement, builder, element);
418 }
419 }
420 } else if (name == QLatin1String("chart")) {
421 // Handle <chart> element
422
423 KDReports::ChartElement chartElement(element.attribute(QStringLiteral("model")));
425 if (bgColor.isValid())
426 chartElement.setBackground(bgColor);
427 int width = 100;
428 int height = 100;
429 Unit unit = Millimeters;
430 if (element.hasAttribute(QStringLiteral("width"))) {
431 QString str = element.attribute(QStringLiteral("width"));
432 if (str.endsWith(QLatin1Char('%'))) {
433 str.chop(1);
434 unit = Percent;
435 }
436 width = str.toInt();
437 }
438 if (element.hasAttribute(QStringLiteral("height"))) {
439 QString str = element.attribute(QStringLiteral("height"));
440 if (str.endsWith(QLatin1Char('%'))) {
441 str.chop(1);
442 unit = Percent;
443 }
444 height = str.toInt();
445 }
446 chartElement.setSize(width, height, unit);
447
448 if (m_xmlElementHandler && !m_xmlElementHandler->chartElement(chartElement, element))
449 continue;
450
451 addElement(chartElement, builder, element);
452
453 } else if (name == QLatin1String("image")) {
454 // Handle <image> element
455
456 QString id;
457 QImage image = extractImage(element, &id);
458 KDReports::ImageElement imageElement(image);
459 imageElement.setId(id);
460 if (element.hasAttribute(QStringLiteral("width"))) {
461 QString widthStr = element.attribute(QStringLiteral("width"));
462 if (widthStr.endsWith(QLatin1Char('%'))) {
463 widthStr.truncate(widthStr.length() - 1);
464 imageElement.setWidth(widthStr.toInt(), KDReports::Percent);
465 } else {
466 imageElement.setWidth(widthStr.toInt());
467 }
468 } else if (element.hasAttribute(QStringLiteral("height"))) { // mutually exclusive with "width"!
469 QString heightStr = element.attribute(QStringLiteral("height"));
470 if (heightStr.endsWith(QLatin1Char('%'))) {
471 heightStr.truncate(heightStr.length() - 1);
472 imageElement.setHeight(heightStr.toInt(), KDReports::Percent);
473 } else {
474 imageElement.setHeight(heightStr.toInt());
475 }
476 } else if (element.hasAttribute(QStringLiteral("fitToPage"))) {
477 imageElement.setFitToPage();
478 }
479
480 if (m_xmlElementHandler && !m_xmlElementHandler->imageElement(imageElement, element))
481 continue;
482
483 addElement(imageElement, builder, element);
484
485 } else if (name == QLatin1String("header")) {
486 const KDReports::HeaderLocations loc = KDReports::XmlHelper::parseHeaderLocation(element.attribute(QStringLiteral("location")));
487 KDReports::Header &header = m_report->header(loc);
488 parseHeaderFooterAttribute(header, element);
489 if (m_xmlElementHandler && !m_xmlElementHandler->startHeader(header, element))
490 continue;
491 if (!processNode(element, &header.d->m_builder, true, false))
492 return false;
493 if (m_xmlElementHandler)
494 m_xmlElementHandler->endHeader(header, element);
495 } else if (name == QLatin1String("footer")) {
496 const KDReports::HeaderLocations loc = KDReports::XmlHelper::parseHeaderLocation(element.attribute(QStringLiteral("location")));
497 KDReports::Footer &footer = m_report->footer(loc);
498 parseHeaderFooterAttribute(footer, element);
499 if (m_xmlElementHandler && !m_xmlElementHandler->startFooter(footer, element))
500 continue;
501 if (!processNode(element, &footer.d->m_builder, false, true))
502 return false;
503 if (m_xmlElementHandler)
504 m_xmlElementHandler->endFooter(footer, element);
505 } else if (name == QLatin1String("variable")) {
506 if (!inHeader && !inFooter) {
507 error(QObject::tr("<variable> tags only allowed in headers and footers"));
508 return false;
509 }
510 if (!element.hasAttribute(QStringLiteral("type"))) {
511 error(QObject::tr("<variable> tags must have a 'type' attribute"));
512 return false;
513 }
514 Q_ASSERT(builder);
515 if (builder) {
516 const QString type = element.attribute(QStringLiteral("type"));
518 if (m_xmlElementHandler && !m_xmlElementHandler->variable(vt, element))
519 continue;
520 builder->addVariablePublic(vt);
521 }
522 } else if (name == QLatin1String("page-break")) {
523 if (m_xmlElementHandler && !m_xmlElementHandler->pageBreak(element))
524 continue;
525 m_report->addPageBreak();
526 } else if (name == QLatin1String("ifdef")) {
527 if (element.hasAttribute(QStringLiteral("id"))) {
528 const QString id = element.attribute(QStringLiteral("id"));
529 const bool skip = m_textValues.value(id).isEmpty();
530 if (!skip) {
531 if (!processNode(element, builder, inHeader, inFooter))
532 return false;
533 }
534 }
535 } else if (name == QLatin1String("custom")) {
536 if (m_xmlElementHandler)
537 m_xmlElementHandler->customElement(element);
538 } else if (name == QLatin1String("hline")) {
539 KDReports::HLineElement hLineElement;
540
541 if (element.hasAttribute(QStringLiteral("thickness"))) {
542 const double thickness = element.attribute(QStringLiteral("thickness")).toDouble();
543 hLineElement.setThickness(thickness);
544 }
545
546 if (element.hasAttribute(QStringLiteral("color"))) {
547 const QColor color = KDReports::XmlHelper::readColor(element, "color");
548 hLineElement.setColor(color);
549 }
550
551 if (element.hasAttribute(QStringLiteral("margin"))) {
552 const int margin = element.attribute(QStringLiteral("margin")).toInt();
553 hLineElement.setMargin(margin);
554 }
555
556 if (m_xmlElementHandler && !m_xmlElementHandler->hLineElement(hLineElement, element))
557 continue;
558
559 addElement(hLineElement, builder, element);
560 } else {
561 error(QObject::tr("KDReports::Report::loadFromXML(): Unknown element %1").arg(name));
562 }
563 }
564
565 if (testForErrorAndFillErrorDetails())
566 return false;
567
568 return true;
569}
570
571void KDReports::XmlParser::parseTabs(KDReports::ReportBuilder *builder, const QDomElement &tabsElement)
572{
574 for (QDomElement element = tabsElement.firstChildElement(); !element.isNull(); element = element.nextSiblingElement()) {
575 if (element.tagName() == QLatin1String("tab")) {
576
578 const QString tabType = element.attribute(QStringLiteral("type"));
579 if (tabType == QLatin1String("right")) {
580 tab.type = QTextOption::RightTab;
581 } else if (tabType == QLatin1String("center")) {
582 tab.type = QTextOption::CenterTab;
583 } else if (tabType == QLatin1String("delimiter")) {
584 tab.type = QTextOption::DelimiterTab;
585 } else {
586 tab.type = QTextOption::LeftTab;
587 }
588
589 const QString delimiter = element.attribute(QStringLiteral("delimiter"));
590 if (!delimiter.isEmpty())
591 tab.delimiter = delimiter.at(0);
592
593 const QString strPos = element.attribute(QStringLiteral("position"));
594 double pos = -1;
595 if (strPos == QLatin1String("page")) {
596 tab.delimiter = QChar::fromLatin1('P');
597 } else {
598 pos = strPos.toDouble();
599 }
600 tab.position = pos;
601 tabs.append(tab);
602 }
603 }
604 if (!m_xmlElementHandler || m_xmlElementHandler->tabs(tabs, tabsElement))
605 builder->setTabPositions(tabs);
606}
607
608void KDReports::XmlParser::parseParagraphMargins(KDReports::ReportBuilder *builder, const QDomElement &element)
609{
610 qreal left = element.attribute(QStringLiteral("left")).toDouble();
611 qreal top = element.attribute(QStringLiteral("top")).toDouble();
612 qreal right = element.attribute(QStringLiteral("right")).toDouble();
613 qreal bottom = element.attribute(QStringLiteral("bottom")).toDouble();
614 if (!m_xmlElementHandler || m_xmlElementHandler->paragraphMargin(left, top, right, bottom, element))
615 builder->setParagraphMargins(left, top, right, bottom);
616}
617
618QImage KDReports::XmlParser::extractImage(const QDomElement &element, QString *pId) const
619{
620 if (element.hasAttribute(QStringLiteral("id"))) {
621 const QString id = element.attribute(QStringLiteral("id"));
622 *pId = id;
623 const QHash<QString, QImage>::const_iterator it = m_imageValues.find(id);
624 if (it != m_imageValues.end()) {
625 return *it;
626 }
627 }
628
629 QImage image;
630 if (element.hasAttribute(QStringLiteral("file"))) {
631 const QString fileName = element.attribute(QStringLiteral("file"));
632 if (!image.load(fileName)) {
633 qWarning("Image not found or invalid: %s", qPrintable(fileName));
634 }
635 }
636 return image;
637}
638
639QString KDReports::XmlParser::extractText(const QDomElement &element, QString *pId, const QAbstractItemModel *currentModel, int currentRow) const
640{
641 if (element.hasAttribute(QStringLiteral("id"))) {
642 const QString id = element.attribute(QStringLiteral("id"));
643 *pId = id;
644 const QHash<QString, QString>::const_iterator it = m_textValues.find(id);
645 if (it != m_textValues.end()) {
646 return *it;
647 }
648 } else if (element.hasAttribute(QStringLiteral("model"))) {
649 const QString modelName = element.attribute(QStringLiteral("model"));
650 QAbstractItemModel *model = KDReports::modelForKey(modelName);
651 if (model) {
652 int row;
653 if (model == currentModel && currentRow > -1) {
654 row = currentRow;
655 } else {
656 row = element.attribute(QStringLiteral("row")).toInt();
657 }
658 const int column = element.attribute(QStringLiteral("column")).toInt();
659 const QModelIndex index = model->index(row, column);
660 return model->data(index).toString();
661 }
662 }
663
664 return element.text();
665}
666
667bool KDReports::XmlParser::testForErrorAndFillErrorDetails()
668{
669 if (m_xmlElementHandler && m_xmlElementHandler->errorDetails().hasError()) {
670 if (m_errorDetails)
671 *m_errorDetails = m_xmlElementHandler->errorDetails();
672 return true;
673 }
674 return false;
675}
676
677void KDReports::XmlParser::error(const QString &errorString)
678{
679 if (m_errorDetails)
680 m_errorDetails->setDriverMessage(errorString);
681 else
682 qWarning("%s", qPrintable(errorString));
683}
#define REPORTBUILDER_CTOR_ARGNAMES
#define REPORTBUILDER_CTOR_ARGDEFS
static QFont parseFontAttributes(const QDomElement &element)
static void parseHeaderFooterAttribute(KDReports::Header &header, const QDomElement &element)
void setColumnSpan(int columnSpan)
void setRowSpan(int rowSpan)
void setBackground(const QBrush &brush)
void setColor(const QColor &color)
void setHtml(const QString &html)
void setId(const QString &id)
ReportBuilder(KDReports::TextDocumentData &contentDocument, const QTextCursor &cursor, Report *report)
void setTabPositions(const QList< QTextOption::Tab > &tabs)
virtual void addVerticalSpacingPublic(qreal space)
virtual void addBlockElementPublic(const Element &element, Qt::AlignmentFlag horizontalAlignment, const QColor &backgroundColor=QColor())
virtual void addVariablePublic(KDReports::VariableType variable)
virtual void addInlineElementPublic(const Element &element)
void setParagraphMargins(qreal left, qreal top, qreal right, qreal bottom)
TextDocumentData & contentDocumentData()
Cell & cell(int row, int column)
void setTextColor(const QColor &color)
void setFontFamily(const QString &family)
Set font attribute: family.
void setUnderline(bool underline)
Set font attribute: underline.
void setStrikeOut(bool strikeout)
Set font attribute: strike out.
void setItalic(bool italic)
Set font attribute: italic.
void setText(const QString &text)
void setPointSize(qreal size)
Set font attribute: size in points. Can be integer or decimal.
void setBold(bool bold)
Set font attribute: bold.
void setId(const QString &id)
virtual bool startCell(KDReports::Cell &cell, QDomElement &xmlElement)
virtual bool endCell(KDReports::Cell &cell, QDomElement &xmlElement)
static KDReports::VariableType stringToVariableType(const QString &type)
static Qt::AlignmentFlag stringToAlignment(const QString &str)
static QColor readBackground(const QDomElement &element)
static QColor readColor(const QDomElement &element, const char *attributeName)
static KDReports::HeaderLocations parseHeaderLocation(const QString &xmlAttr)
bool processDocument(const QDomDocument &document, KDReports::ReportBuilder *builder)
@ Percent
Percentage of the text width, i.e. the page width minus margins.
@ Millimeters
Millimeters (the default)
QAbstractItemModel * modelForKey(const QString &key)
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
QChar fromLatin1(char c)
bool isValid() const const
QDomElement documentElement() const const
QString attribute(const QString &name, const QString &defValue) const const
bool hasAttribute(const QString &name) const const
QString tagName() const const
QString text() const const
QDomElement firstChildElement(const QString &tagName) const const
bool isNull() const const
QDomElement nextSiblingElement(const QString &tagName) const const
void setFamily(const QString &family)
void setPointSize(int pointSize)
bool load(QIODevice *device, const char *format)
void append(const T &value)
QString tr(const char *sourceText, const char *disambiguation, int n)
const QChar at(int position) const const
void chop(int n)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
int length() const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
void truncate(int position)
AlignmentFlag
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
QString toString() const const

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-reports/
Generated on Wed Apr 24 2024 04:08:15 for KD Reports API Documentation by doxygen 1.9.8