1 /* This file is part of the KDE project
2 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
3 * Copyright (C) 2016 by Dag Andersen <danders@get2net.dk>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 // clazy:excludeall=qstring-arg
20 #include "PlanReportItemText.h"
21 #include "KReportRenderObjects.h"
22
23 #include <KPropertySet>
24
25 #include <QPrinter>
26 #include <QApplication>
27 #include <QPalette>
28 #include <QFontMetrics>
29 #include <QDomNodeList>
30 #include <QTextEdit>
31 #include <QDebug>
32 #include <QLoggingCategory>
33
REPORTTEXT_LOG()34 const QLoggingCategory &REPORTTEXT_LOG()
35 {
36 static const QLoggingCategory category("calligra.plan.report.text");
37 return category;
38 }
39 #define debugText qCDebug(REPORTTEXT_LOG)<<QString("%1:").arg(__func__)
40
PlanReportItemText()41 PlanReportItemText::PlanReportItemText()
42 {
43 createProperties();
44 }
45
PlanReportItemText(const QDomNode & element)46 PlanReportItemText::PlanReportItemText(const QDomNode & element) : m_bottomPadding(0.0)
47 {
48 QDomNodeList nl = element.childNodes();
49 QString n;
50 QDomNode node;
51
52 createProperties();
53 m_name->setValue(element.toElement().attribute(QLatin1String("report:name")));
54 m_controlSource->setValue(element.toElement().attribute(QLatin1String("report:item-data-source")));
55 m_controlSource->setOption("extraValueAllowed", QLatin1String("true"));
56 m_itemValue->setValue(element.toElement().attribute(QLatin1String("report:value")));
57 Z = element.toElement().attribute(QLatin1String("report:z-index")).toDouble();
58 m_horizontalAlignment->setValue(element.toElement().attribute(QLatin1String("report:horizontal-align")));
59 m_verticalAlignment->setValue(element.toElement().attribute(QLatin1String("report:vertical-align")));
60 m_bottomPadding = element.toElement().attribute(QLatin1String("report:bottom-padding")).toDouble();
61
62 parseReportRect(element.toElement(), &m_pos, &m_size);
63
64 for (int i = 0; i < nl.count(); i++) {
65 node = nl.item(i);
66 n = node.nodeName();
67
68 if (n == QLatin1String("report:text-style")) {
69 KRTextStyleData ts;
70 if (parseReportTextStyleData(node.toElement(), &ts)) {
71 m_backgroundColor->setValue(ts.backgroundColor);
72 m_foregroundColor->setValue(ts.foregroundColor);
73 m_backgroundOpacity->setValue(ts.backgroundOpacity);
74 m_font->setValue(ts.font);
75
76 }
77 } else if (n == QLatin1String("report:line-style")) {
78 KReportLineStyle ls;
79 if (parseReportLineStyleData(node.toElement(), &ls)) {
80 m_lineWeight->setValue(ls.width());
81 m_lineColor->setValue(ls.color());
82 m_lineStyle->setValue(QPen(ls.penStyle()));
83 }
84 } else {
85 qDebug() << "while parsing field element encountered unknown element: " << n;
86 }
87 }
88
89 }
90
~PlanReportItemText()91 PlanReportItemText::~PlanReportItemText()
92 {
93 delete m_set;
94 }
95
textFlags() const96 Qt::Alignment PlanReportItemText::textFlags() const
97 {
98 Qt::Alignment align;
99 QString t;
100 t = m_horizontalAlignment->value().toString();
101 if (t == QLatin1String("center"))
102 align = Qt::AlignHCenter;
103 else if (t == QLatin1String("right"))
104 align = Qt::AlignRight;
105 else
106 align = Qt::AlignLeft;
107
108 t = m_verticalAlignment->value().toString();
109 if (t == QLatin1String("center"))
110 align |= Qt::AlignVCenter;
111 else if (t == QLatin1String("bottom"))
112 align |= Qt::AlignBottom;
113 else
114 align |= Qt::AlignTop;
115
116 return align;
117 }
118
createProperties()119 void PlanReportItemText::createProperties()
120 {
121 m_set = new KPropertySet;
122
123 //connect (set, SIGNAL (propertyChanged (KPropertySet &, KProperty &)), this, SLOT (propertyChanged (KPropertySet &, KProperty &)));
124
125 QStringList keys, strings;
126
127 //_query = new KProperty ("Query", QStringList(), QStringList(), "Data Source", "Query");
128 m_controlSource = new KProperty("item-data-source", QStringList(), QStringList(), QString(), tr("Data Source"));
129
130 m_itemValue = new KProperty("value", QString(), tr("Value"), tr("Value used if not bound to a field"));
131
132 keys << QLatin1String("left") << QLatin1String("center") << QLatin1String("right");
133 strings << tr("Left") << tr("Center") << tr("Right");
134 m_horizontalAlignment = new KProperty("horizontal-align", keys, strings, QLatin1String("left"), tr("Horizontal Alignment"));
135
136 keys.clear();
137 strings.clear();
138 keys << QLatin1String("top") << QLatin1String("center") << QLatin1String("bottom");
139 strings << tr("Top") << tr("Center") << tr("Bottom");
140 m_verticalAlignment = new KProperty("vertical-align", keys, strings, QLatin1String("center"), tr("Vertical Alignment"));
141
142 m_font = new KProperty("font", QApplication::font(), tr("Font"));
143
144 m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color"));
145 m_foregroundColor = new KProperty("foreground-color", QPalette().color(QPalette::Foreground), tr("Foreground Color"));
146
147 m_lineWeight = new KProperty("line-weight", 1, tr("Line Weight"));
148 m_lineColor = new KProperty("line-color", QColor(Qt::black), tr("Line Color"));
149 m_lineStyle = new KProperty("line-style", QPen(Qt::NoPen), tr("Line Style"), tr("Line Style"), KProperty::LineStyle);
150 m_backgroundOpacity = new KProperty("background-opacity", QVariant(0), tr("Background Opacity"));
151 m_backgroundOpacity->setOption("max", 100);
152 m_backgroundOpacity->setOption("min", 0);
153 m_backgroundOpacity->setOption("unit", QLatin1String("%"));
154
155 addDefaultProperties();
156 m_set->addProperty(m_controlSource);
157 m_set->addProperty(m_itemValue);
158 m_set->addProperty(m_horizontalAlignment);
159 m_set->addProperty(m_verticalAlignment);
160 m_set->addProperty(m_font);
161 m_set->addProperty(m_backgroundColor);
162 m_set->addProperty(m_foregroundColor);
163 m_set->addProperty(m_backgroundOpacity);
164 m_set->addProperty(m_lineWeight);
165 m_set->addProperty(m_lineColor);
166 m_set->addProperty(m_lineStyle);
167
168 }
169
itemDataSource() const170 QString PlanReportItemText::itemDataSource() const
171 {
172 return m_controlSource->value().toString();
173 }
174
bottomPadding() const175 qreal PlanReportItemText::bottomPadding() const
176 {
177 return m_bottomPadding;
178 }
179
setBottomPadding(qreal bp)180 void PlanReportItemText::setBottomPadding(qreal bp)
181 {
182 if (m_bottomPadding != bp) {
183 m_bottomPadding = bp;
184 }
185 }
186
textStyle() const187 KRTextStyleData PlanReportItemText::textStyle() const
188 {
189 KRTextStyleData d;
190 d.backgroundColor = m_backgroundColor->value().value<QColor>();
191 d.foregroundColor = m_foregroundColor->value().value<QColor>();
192 d.font = m_font->value().value<QFont>();
193 d.backgroundOpacity = m_backgroundOpacity->value().toInt();
194 return d;
195 }
196
lineStyle() const197 KReportLineStyle PlanReportItemText::lineStyle() const
198 {
199 KReportLineStyle ls;
200 ls.setWidth(m_lineWeight->value().toInt());
201 ls.setColor(m_lineColor->value().value<QColor>());
202 ls.setPenStyle((Qt::PenStyle)m_lineStyle->value().toInt());
203 return ls;
204 }
205
206 // RTTI
typeName() const207 QString PlanReportItemText::typeName() const
208 {
209 return QLatin1String("plan.text");
210 }
211
renderSimpleData(OROPage * page,OROSection * section,const QPointF & offset,const QVariant & data,KReportScriptHandler * script)212 int PlanReportItemText::renderSimpleData(OROPage *page, OROSection *section, const QPointF &offset,
213 const QVariant &data, KReportScriptHandler *script)
214
215 {
216 Q_UNUSED(script);
217
218 QString qstrValue;
219
220 QString cs = itemDataSource();
221
222 if (!cs.isEmpty()) {
223 // just convert rich text to plain text for now
224 QTextEdit te;
225 te.setText(data.toString());
226 qstrValue = te.toPlainText();
227 debugText<<qstrValue;
228 } else {
229 qstrValue = m_itemValue->value().toString();
230 debugText<<"No data source:"<<qstrValue;
231 }
232
233 QPointF pos = m_pos.toScene();
234 QSizeF size = m_size.toScene();
235 pos += offset;
236
237 QRectF trf(pos, size);
238 qreal intStretch = trf.top() - offset.y();
239
240 if (qstrValue.length()) {
241 QRectF rect = trf;
242
243 int pos = 0;
244 QChar separator;
245 QRegExp re(QLatin1String("\\s"));
246 QPrinter prnt(QPrinter::HighResolution);
247 QFontMetrics fm(font(), &prnt);
248
249 // int intRectWidth = (int)(trf.width() * prnt.resolution()) - 10;
250 int intRectWidth = (int)((m_size.toPoint().width() / 72) * prnt.resolution());
251 int intLineCounter = 0;
252 qreal intBaseTop = trf.top();
253 qreal intRectHeight = trf.height();
254
255 while (qstrValue.length()) {
256 int idx = re.indexIn(qstrValue, pos);
257 if (idx == -1) {
258 idx = qstrValue.length();
259 separator = QLatin1Char('\n');
260 } else
261 separator = qstrValue.at(idx);
262
263 if (fm.boundingRect(qstrValue.left(idx)).width() < intRectWidth || pos == 0) {
264 pos = idx + 1;
265 if (separator == QLatin1Char('\n')) {
266 QString line = qstrValue.left(idx);
267
268 qstrValue.remove(0, idx + 1);
269
270 pos = 0;
271
272 rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
273 rect.setBottom(rect.top() + intRectHeight);
274
275 OROTextBox * tb = new OROTextBox();
276 tb->setPosition(rect.topLeft());
277 tb->setSize(rect.size());
278 tb->setFont(font());
279 tb->setText(line);
280 tb->setFlags(textFlags());
281 tb->setTextStyle(textStyle());
282 tb->setLineStyle(lineStyle());
283
284 if (page) {
285 page->addPrimitive(tb);
286 }
287
288 if (section) {
289 OROTextBox *tb2 = dynamic_cast<OROTextBox*>(tb->clone());
290 tb2->setPosition(m_pos.toPoint());
291 section->addPrimitive(tb2);
292 }
293
294 if (!page) {
295 delete tb;
296 }
297
298 intStretch += intRectHeight;
299 intLineCounter++;
300 }
301 } else {
302 QString line = qstrValue.left(pos - 1);
303 qstrValue.remove(0, pos);
304 pos = 0;
305
306 rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
307 rect.setBottom(rect.top() + intRectHeight);
308
309 OROTextBox * tb = new OROTextBox();
310 tb->setPosition(rect.topLeft());
311 tb->setSize(rect.size());
312 tb->setFont(font());
313 tb->setText(line);
314 tb->setFlags(textFlags());
315 tb->setTextStyle(textStyle());
316 tb->setLineStyle(lineStyle());
317 if (page) {
318 page->addPrimitive(tb);
319 } else {
320 delete tb;
321 }
322
323 intStretch += intRectHeight;
324 intLineCounter++;
325 }
326 }
327
328 intStretch += (m_bottomPadding / 100.0);
329 }
330
331 return intStretch; //Item returns its required section height
332 }
333