1 /* This file is part of the KDE project
2 * Copyright (C) 2007-2008 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 "KReportDocument.h"
19 #include "KReportUnit.h"
20 #include "KReportDetailSectionData.h"
21 #include "KReportItemBase.h"
22 #include "KReportUtils_p.h"
23 #include "KReportPageSize.h"
24
25 #include <QDomElement>
26 #include <QApplication>
27 #include "kreport_debug.h"
28
29 class Q_DECL_HIDDEN KReportDocument::Private
30 {
31 public:
32 bool valid;
33 QString title;
34 QString name;
35 QString query;
36 #ifdef KREPORT_SCRIPTING
37 QString script;
38 QString interpreter;
39 #endif
40 bool externalData;
41 KReportPrivate::PageLayout pageLayout;
42 QString pageSize;
43 QString labelType;
44
45 KReportSectionData * pageHeaderFirst = nullptr;
46 KReportSectionData * pageHeaderOdd = nullptr;
47 KReportSectionData * pageHeaderEven = nullptr;
48 KReportSectionData * pageHeaderLast = nullptr;
49 KReportSectionData * pageHeaderAny = nullptr;
50
51 KReportSectionData * reportHeader = nullptr;
52 KReportSectionData * reportFooter = nullptr;
53
54 KReportSectionData * pageFooterFirst = nullptr;
55 KReportSectionData * pageFooterOdd = nullptr;
56 KReportSectionData * pageFooterEven = nullptr;
57 KReportSectionData * pageFooterLast = nullptr;
58 KReportSectionData * pageFooterAny = nullptr;
59
60 KReportDetailSectionData* detailSection = nullptr;
61 };
62
KReportDocument(QObject * parent)63 KReportDocument::KReportDocument(QObject *parent)
64 : QObject(parent),
65 d(new Private)
66 {
67 d->valid = true;
68 }
69
KReportDocument(const QDomElement & elemSource,QObject * parent)70 KReportDocument::KReportDocument(const QDomElement & elemSource, QObject *parent)
71 : QObject(parent),
72 d(new Private)
73 {
74 d->valid = false;
75
76 if (elemSource.tagName() != QLatin1String("report:content")) {
77 kreportWarning() << "QDomElement is not <report:content> tag"
78 << elemSource.text();
79 return;
80 }
81
82 QDomNodeList sections = elemSource.childNodes();
83 for (int nodeCounter = 0; nodeCounter < sections.count(); nodeCounter++) {
84 QDomElement elemThis = sections.item(nodeCounter).toElement();
85 if (elemThis.tagName() == QLatin1String("report:title")) {
86 d->title = elemThis.text();
87 #ifdef KREPORT_SCRIPTING
88 } else if (elemThis.tagName() == QLatin1String("report:script")) {
89 d->script = elemThis.text();
90 d->interpreter = elemThis.attribute(QLatin1String("report:script-interpreter"));
91 #endif
92 } else if (elemThis.tagName() == QLatin1String("report:page-style")) {
93 QString pagetype = elemThis.firstChild().nodeValue();
94
95 //Full page mode is required to allow margins to be set to whatever the user has specified
96 d->pageLayout.setMode(QPageLayout::FullPageMode);
97
98 if (pagetype == QLatin1String("predefined")) {
99 setPageSize(elemThis.attribute(QLatin1String("report:page-size"), QLatin1String("A4")));
100 d->pageLayout.setPageSize(QPageSize(KReportPageSize::pageSize(pageSize())));
101 } else if (pagetype == QLatin1String("custom")) {
102 kreportDebug() << "Setting custom page size in document to " << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm"))) << KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ;
103 QPageSize custom(QSize(KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-width"), QLatin1String("5.0cm"))) , KReportUnit::parseValue(elemThis.attribute(QLatin1String("report:custom-page-height"), QLatin1String("5.0cm"))) ), QString(), QPageSize::ExactMatch);
104
105 d->pageLayout.setPageSize(custom);
106 } else if (pagetype == QLatin1String("label")) {
107 setLabelType(elemThis.firstChild().nodeValue());
108 }
109 //! @todo add config for default margins or add within templates support
110 d->pageLayout.setUnits(QPageLayout::Point);
111 d->pageLayout.setLeftMargin(KReportUnit::parseValue(elemThis.attribute(
112 QLatin1String("fo:margin-left"), DEFAULT_PAGE_MARGIN_STRING)));
113 d->pageLayout.setRightMargin(KReportUnit::parseValue(elemThis.attribute(
114 QLatin1String("fo:margin-right"), DEFAULT_PAGE_MARGIN_STRING)));
115 d->pageLayout.setTopMargin(KReportUnit::parseValue(elemThis.attribute(
116 QLatin1String("fo:margin-top"), DEFAULT_PAGE_MARGIN_STRING)));
117 d->pageLayout.setBottomMargin(KReportUnit::parseValue(elemThis.attribute(
118 QLatin1String("fo:margin-bottom"), DEFAULT_PAGE_MARGIN_STRING)));
119 d->pageLayout.setOrientation(
120 elemThis.attribute(QLatin1String("report:print-orientation"),
121 QLatin1String("portrait"))
122 == QLatin1String("portrait")
123 ? QPageLayout::Portrait
124 : QPageLayout::Landscape);
125 } else if (elemThis.tagName() == QLatin1String("report:body")) {
126 QDomNodeList sectionlist = elemThis.childNodes();
127 QDomNode sec;
128
129 for (int s = 0; s < sectionlist.count(); ++s) {
130 sec = sectionlist.item(s);
131 if (sec.isElement()) {
132 QString sn = sec.nodeName().toLower();
133 //kreportDebug() << sn;
134 if (sn == QLatin1String("report:section")) {
135 KReportSectionData * sd = new KReportSectionData(sec.toElement(), this);
136 if (!sd->isValid()) {
137 kreportDebug() << "Invalid section";
138 delete sd;
139 } else {
140 //kreportDebug() << "Adding section of type " << sd->type();
141 switch (sd->type()) {
142 case KReportSectionData::Type::PageHeaderFirst:
143 d->pageHeaderFirst = sd;
144 break;
145 case KReportSectionData::Type::PageHeaderOdd:
146 d->pageHeaderOdd = sd;
147 break;
148 case KReportSectionData::Type::PageHeaderEven:
149 d->pageHeaderEven = sd;
150 break;
151 case KReportSectionData::Type::PageHeaderLast:
152 d->pageHeaderLast = sd;
153 break;
154 case KReportSectionData::Type::PageHeaderAny:
155 d->pageHeaderAny = sd;
156 break;
157 case KReportSectionData::Type::ReportHeader:
158 d->reportHeader = sd;
159 break;
160 case KReportSectionData::Type::ReportFooter:
161 d->reportFooter = sd;
162 break;
163 case KReportSectionData::Type::PageFooterFirst:
164 d->pageFooterFirst = sd;
165 break;
166 case KReportSectionData::Type::PageFooterOdd:
167 d->pageFooterOdd = sd;
168 break;
169 case KReportSectionData::Type::PageFooterEven:
170 d->pageFooterEven = sd;
171 break;
172 case KReportSectionData::Type::PageFooterLast:
173 d->pageFooterLast = sd;
174 break;
175 case KReportSectionData::Type::PageFooterAny:
176 d->pageFooterAny = sd;
177 break;
178 default:
179 ;
180 }
181 }
182
183 } else if (sn == QLatin1String("report:detail")) {
184 KReportDetailSectionData * dsd = new KReportDetailSectionData(sec.toElement(), this);
185
186 if (dsd->isValid()) {
187 d->detailSection = dsd;
188 } else {
189 kreportDebug() << "Invalid detail section";
190 delete dsd;
191 }
192 }
193 } else {
194 kreportWarning() << "Encountered an unknown Element: " << elemThis.tagName();
195 }
196 }
197 }
198
199 d->valid = true;
200 }
201 }
202
~KReportDocument()203 KReportDocument::~KReportDocument()
204 {
205 delete d;
206 }
207
objects() const208 QList<KReportItemBase*> KReportDocument::objects() const
209 {
210 QList<KReportItemBase*> obs;
211 for (int i = static_cast<int>(KReportSectionData::Type::PageHeaderFirst);
212 i <= static_cast<int>(KReportSectionData::Type::PageFooterAny); i++)
213 {
214 KReportSectionData *sec = section(static_cast<KReportSectionData::Type>(i));
215 if (sec) {
216 obs << sec->objects();
217 }
218 }
219
220 if (d->detailSection) {
221 //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count();
222 foreach(KReportDetailGroupSectionData* g, d->detailSection->groupList) {
223 if (g->groupHeader) {
224 obs << g->groupHeader->objects();
225 }
226 if (g->groupFooter) {
227 obs << g->groupFooter->objects();
228 }
229 }
230 if (d->detailSection->detailSection)
231 obs << d->detailSection->detailSection->objects();
232 }
233
234 /*kreportDebug() << "Object List:";
235 foreach(KReportItemBase* o, obs) {
236 kreportDebug() << o->entityName();
237 }*/
238 return obs;
239 }
240
object(const QString & n) const241 KReportItemBase* KReportDocument::object(const QString& n) const
242 {
243 QList<KReportItemBase*> obs = objects();
244
245 foreach(KReportItemBase* o, obs) {
246 if (o->entityName() == n) {
247 return o;
248 }
249 }
250 return nullptr;
251 }
252
sections() const253 QList<KReportSectionData*> KReportDocument::sections() const
254 {
255 QList<KReportSectionData*> secs;
256 for (int i = static_cast<int>(KReportSectionData::Type::PageHeaderFirst);
257 i <= static_cast<int>(KReportSectionData::Type::PageFooterAny); i++)
258 {
259 KReportSectionData *sec = section(static_cast<KReportSectionData::Type>(i));
260 if (sec) {
261 secs << sec;
262 }
263 }
264
265 if (d->detailSection) {
266 //kreportDebug() << "Number of groups: " << m_detailSection->m_groupList.count();
267 foreach(KReportDetailGroupSectionData* g, d->detailSection->groupList) {
268 if (g->groupHeader) {
269 secs << g->groupHeader;
270 }
271 if (g->groupFooter) {
272 secs << g->groupFooter;
273 }
274 }
275 if (d->detailSection->detailSection)
276 secs << d->detailSection->detailSection;
277 }
278
279 return secs;
280 }
281
section(const QString & sn) const282 KReportSectionData* KReportDocument::section(const QString& sn) const
283 {
284 QList<KReportSectionData*> secs = sections();
285
286 foreach(KReportSectionData *sec, secs) {
287 if (sec->name() == sn) {
288 return sec;
289 }
290 }
291 return nullptr;
292 }
293
section(KReportSectionData::Type type) const294 KReportSectionData* KReportDocument::section(KReportSectionData::Type type) const
295 {
296 KReportSectionData *sec;
297 switch (type) {
298 case KReportSectionData::Type::PageHeaderAny:
299 sec = d->pageHeaderAny;
300 break;
301 case KReportSectionData::Type::PageHeaderEven:
302 sec = d->pageHeaderEven;
303 break;
304 case KReportSectionData::Type::PageHeaderOdd:
305 sec = d->pageHeaderOdd;
306 break;
307 case KReportSectionData::Type::PageHeaderFirst:
308 sec = d->pageHeaderFirst;
309 break;
310 case KReportSectionData::Type::PageHeaderLast:
311 sec = d->pageHeaderLast;
312 break;
313 case KReportSectionData::Type::PageFooterAny:
314 sec = d->pageFooterAny;
315 break;
316 case KReportSectionData::Type::PageFooterEven:
317 sec = d->pageFooterEven;
318 break;
319 case KReportSectionData::Type::PageFooterOdd:
320 sec = d->pageFooterOdd;
321 break;
322 case KReportSectionData::Type::PageFooterFirst:
323 sec = d->pageFooterFirst;
324 break;
325 case KReportSectionData::Type::PageFooterLast:
326 sec = d->pageFooterLast;
327 break;
328 case KReportSectionData::Type::ReportHeader:
329 sec = d->reportHeader;
330 break;
331 case KReportSectionData::Type::ReportFooter:
332 sec = d->reportFooter;
333 break;
334 default:
335 sec = nullptr;
336 }
337 return sec;
338 }
339
pageLayout() const340 QPageLayout KReportDocument::pageLayout() const
341 {
342 return d->pageLayout;
343 }
344
isValid() const345 bool KReportDocument::isValid() const
346 {
347 return d->valid;
348 }
349
title() const350 QString KReportDocument::title() const
351 {
352 return d->title;
353 }
354
externalData() const355 bool KReportDocument::externalData() const
356 {
357 return d->externalData;
358 }
359
360 #ifdef KREPORT_SCRIPTING
script() const361 QString KReportDocument::script() const
362 {
363 return d->script;
364 }
365
interpreter() const366 QString KReportDocument::interpreter() const
367 {
368 return d->interpreter;
369 }
370 #endif
371
name() const372 QString KReportDocument::name() const
373 {
374 return d->name;
375 }
376
setName(const QString & n)377 void KReportDocument::setName(const QString& n)
378 {
379 d->name = n;
380 }
381
query() const382 QString KReportDocument::query() const
383 {
384 return d->query;
385 }
386
pageSize()387 QString KReportDocument::pageSize()
388 {
389 return d->pageSize;
390 }
391
setPageSize(const QString & size)392 void KReportDocument::setPageSize(const QString& size)
393 {
394 d->pageSize = size;
395 }
396
labelType() const397 QString KReportDocument::labelType() const
398 {
399 return d->labelType;
400 }
401
setLabelType(const QString & label)402 void KReportDocument::setLabelType(const QString& label)
403 {
404 d->labelType = label;
405 }
406
detail() const407 KReportDetailSectionData * KReportDocument::detail() const
408 {
409 return d->detailSection;
410 }
411
412