KReport

KReportItemText.cpp
1 /* This file is part of the KDE project
2  * Copyright (C) 2007-2008 by Adam Pigg ([email protected])
3  * Copyright (C) 2019 JarosÅ‚aw Staniek <[email protected]>
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 #include "KReportItemText.h"
20 #include "KReportRenderObjects.h"
21 #include "KReportUtils.h"
22 #include "KReportUtils_p.h"
23 #include "kreportplugin_debug.h"
24 
25 #include <KPropertyListData>
26 #include <KPropertySet>
27 
28 #include <QPrinter>
29 #include <QApplication>
30 #include <QPalette>
31 #include <QFontMetrics>
32 #include <QDomNodeList>
33 #include <QRegularExpression>
34 
35 KReportItemText::KReportItemText()
36  : m_bottomPadding(0.0)
37 {
38  createProperties();
39 }
40 
41 KReportItemText::KReportItemText(const QDomNode & element)
42  : KReportItemText()
43 {
44  nameProperty()->setValue(KReportUtils::readNameAttribute(element.toElement()));
45  setItemDataSource(element.toElement().attribute(QLatin1String("report:item-data-source")));
46  m_itemValue->setValue(element.toElement().attribute(QLatin1String("report:value")));
47  setZ(element.toElement().attribute(QLatin1String("report:z-index")).toDouble());
48  m_horizontalAlignment->setValue(element.toElement().attribute(QLatin1String("report:horizontal-align")));
49  m_verticalAlignment->setValue(element.toElement().attribute(QLatin1String("report:vertical-align")));
50  m_bottomPadding = element.toElement().attribute(QLatin1String("report:bottom-padding")).toDouble();
51 
52  parseReportRect(element.toElement());
53 
54  QDomNodeList nl = element.childNodes();
55  QString n;
56  QDomNode node;
57  for (int i = 0; i < nl.count(); i++) {
58  node = nl.item(i);
59  n = node.nodeName();
60 
61  if (n == QLatin1String("report:text-style")) {
62  KReportTextStyleData ts;
63  if (parseReportTextStyleData(node.toElement(), &ts)) {
64  m_backgroundColor->setValue(ts.backgroundColor);
65  m_foregroundColor->setValue(ts.foregroundColor);
66  m_backgroundOpacity->setValue(ts.backgroundOpacity);
67  m_font->setValue(ts.font);
68 
69  }
70  } else if (n == QLatin1String("report:line-style")) {
72  if (parseReportLineStyleData(node.toElement(), &ls)) {
73  m_lineWeight->setValue(ls.weight());
74  m_lineColor->setValue(ls.color());
75  m_lineStyle->setValue(static_cast<int>(ls.penStyle()));
76  }
77  } else {
78  kreportpluginWarning() << "while parsing field element encountered unknown element: " << n;
79  }
80  }
81 
82 }
83 
84 KReportItemText::~KReportItemText()
85 {
86 }
87 
88 Qt::Alignment KReportItemText::textFlags() const
89 {
90  Qt::Alignment align;
91  QString t;
92  t = m_horizontalAlignment->value().toString();
93  if (t == QLatin1String("center"))
94  align = Qt::AlignHCenter;
95  else if (t == QLatin1String("right"))
96  align = Qt::AlignRight;
97  else
98  align = Qt::AlignLeft;
99 
100  t = m_verticalAlignment->value().toString();
101  if (t == QLatin1String("center"))
102  align |= Qt::AlignVCenter;
103  else if (t == QLatin1String("bottom"))
104  align |= Qt::AlignBottom;
105  else
106  align |= Qt::AlignTop;
107 
108  return align;
109 }
110 
111 void KReportItemText::createProperties()
112 {
113  createDataSourceProperty();
114 
115  m_itemValue = new KProperty("value", QString(), tr("Value"), tr("Value used if not bound to a field"));
116 
117  KPropertyListData *listData = new KPropertyListData(
118  { QLatin1String("left"), QLatin1String("center"), QLatin1String("right") },
119  QVariantList{ tr("Left"), tr("Center"), tr("Right") });
120  m_horizontalAlignment = new KProperty("horizontal-align", listData, QLatin1String("left"),
121  tr("Horizontal Alignment"));
122 
123  listData = new KPropertyListData(
124  { QLatin1String("top"), QLatin1String("center"), QLatin1String("bottom") },
125  QVariantList{ tr("Top"), tr("Center"), tr("Bottom") });
126  m_verticalAlignment = new KProperty("vertical-align", listData, QLatin1String("center"),
127  tr("Vertical Alignment"));
128 
129  m_font = new KProperty("font", QApplication::font(), tr("Font"));
130 
131  m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color"));
132  m_foregroundColor = new KProperty("foreground-color", QColor(Qt::black), tr("Foreground Color"));
133 
134  m_lineWeight = new KProperty("line-weight", 1.0, tr("Line Weight"));
135  m_lineWeight->setOption("step", 1.0);
136  m_lineColor = new KProperty("line-color", QColor(Qt::black), tr("Line Color"));
137  m_lineStyle = new KProperty("line-style", static_cast<int>(Qt::NoPen), tr("Line Style"), QString(), KProperty::LineStyle);
138  m_backgroundOpacity = new KProperty("background-opacity", QVariant(0), tr("Background Opacity"));
139  m_backgroundOpacity->setOption("max", 100);
140  m_backgroundOpacity->setOption("min", 0);
141  m_backgroundOpacity->setOption("suffix", QLatin1String("%"));
142 
143  propertySet()->addProperty(m_itemValue);
144  propertySet()->addProperty(m_horizontalAlignment);
145  propertySet()->addProperty(m_verticalAlignment);
146  propertySet()->addProperty(m_font);
147  propertySet()->addProperty(m_backgroundColor);
148  propertySet()->addProperty(m_foregroundColor);
149  propertySet()->addProperty(m_backgroundOpacity);
150  propertySet()->addProperty(m_lineWeight);
151  propertySet()->addProperty(m_lineColor);
152  propertySet()->addProperty(m_lineStyle);
153 
154 }
155 
156 qreal KReportItemText::bottomPadding() const
157 {
158  return m_bottomPadding;
159 }
160 
161 void KReportItemText::setBottomPadding(qreal bp)
162 {
163  if (m_bottomPadding != bp) {
164  m_bottomPadding = bp;
165  }
166 }
167 
168 KReportTextStyleData KReportItemText::textStyle() const
169 {
170  KReportTextStyleData d;
171  d.backgroundColor = m_backgroundColor->value().value<QColor>();
172  d.foregroundColor = m_foregroundColor->value().value<QColor>();
173  d.font = m_font->value().value<QFont>();
174  d.backgroundOpacity = m_backgroundOpacity->value().toInt();
175  return d;
176 }
177 
178 KReportLineStyle KReportItemText::lineStyle() const
179 {
180  KReportLineStyle ls;
181  ls.setWeight(m_lineWeight->value().toReal());
182  ls.setColor(m_lineColor->value().value<QColor>());
183  ls.setPenStyle((Qt::PenStyle)m_lineStyle->value().toInt());
184  return ls;
185 }
186 
187 // RTTI
188 QString KReportItemText::typeName() const
189 {
190  return QLatin1String("text");
191 }
192 
193 int KReportItemText::renderSimpleData(OROPage *page, OROSection *section, const QPointF &offset,
194  const QVariant &data, KReportScriptHandler *script)
195 
196 {
197  Q_UNUSED(script);
198 
199  QString qstrValue;
200 
201  QString cs = itemDataSource();
202 
203  if (!cs.isEmpty()) {
204  qstrValue = data.toString();
205  } else {
206  qstrValue = m_itemValue->value().toString();
207  }
208 
209  QPointF pos = scenePosition(position());
210  QSizeF siz = sceneSize(size());
211  pos += offset;
212 
213  QRectF trf(pos, siz);
214  qreal intStretch = trf.top() - offset.y();
215 
216  if (!qstrValue.isEmpty()) {
217  QRectF rect = trf;
218 
219  int pos = 0;
220  QChar separator;
222  const QFontMetricsF fm(font(), KReportPrivate::highResolutionPrinter());
223 
224  const int intRectWidth
225  = (int)((size().width() / 72) * KReportPrivate::highResolutionPrinter()->resolution());
226  int intLineCounter = 0;
227  qreal intBaseTop = trf.top();
228  qreal intRectHeight = trf.height();
229 
230  while (!qstrValue.isEmpty()) {
231  QRegularExpressionMatch match = re.match(qstrValue);
232  int idx = match.capturedStart(pos);
233  if (idx == -1) {
234  idx = qstrValue.length();
235  separator = QLatin1Char('\n');
236  } else
237  separator = qstrValue.at(idx);
238 
239  if (fm.boundingRect(qstrValue.left(idx)).width() < intRectWidth || pos == 0) {
240  pos = idx + 1;
241  if (separator == QLatin1Char('\n')) {
242  QString line = qstrValue.left(idx);
243 
244  qstrValue.remove(0, idx + 1);
245 
246  pos = 0;
247 
248  rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
249  rect.setBottom(rect.top() + intRectHeight);
250 
251  OROTextBox * tb = new OROTextBox();
252  tb->setPosition(rect.topLeft());
253  tb->setSize(rect.size());
254  tb->setFont(font());
255  tb->setText(line);
256  tb->setFlags(textFlags());
257  tb->setTextStyle(textStyle());
258  tb->setLineStyle(lineStyle());
259 
260  if (page) {
261  page->insertPrimitive(tb);
262  }
263 
264  if (section) {
265  OROTextBox *tb2 = dynamic_cast<OROTextBox*>(tb->clone());
266  if (tb2) {
267  tb2->setPosition(scenePosition(position()));
268  section->addPrimitive(tb2);
269  }
270  }
271 
272  if (!page) {
273  delete tb;
274  }
275 
276  intStretch += intRectHeight;
277  intLineCounter++;
278  }
279  } else {
280  QString line = qstrValue.left(pos - 1);
281  qstrValue.remove(0, pos);
282  pos = 0;
283 
284  rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
285  rect.setBottom(rect.top() + intRectHeight);
286 
287  OROTextBox * tb = new OROTextBox();
288  tb->setPosition(rect.topLeft());
289  tb->setSize(rect.size());
290  tb->setFont(font());
291  tb->setText(line);
292  tb->setFlags(textFlags());
293  tb->setTextStyle(textStyle());
294  tb->setLineStyle(lineStyle());
295  if (page) {
296  page->insertPrimitive(tb);
297  } else {
298  delete tb;
299  }
300 
301  intStretch += intRectHeight;
302  intLineCounter++;
303  }
304  }
305 
306  intStretch += (m_bottomPadding / 100.0);
307  }
308 
309  return intStretch; //Item returns its required section height
310 }
typedef Alignment
int count() const const
QDomElement toElement() const const
A text box primitive it defines a box region and text that will be rendered inside that region,...
The KReportLineStyle class represents line style.
Represents a single page in a document and may contain zero or more OROPrimitive objects all of which...
void setBottom(qreal y)
QDomNode item(int index) const const
QPointF topLeft() const const
bool isEmpty() const const
int length() const const
int value() const const
QDomNodeList childNodes() const const
QString nodeName() const const
double toDouble(bool *ok) const const
QString & remove(int position, int n)
qreal top() const const
qreal y() const const
Represents a single a single row in a document and may contain zero or more OROPrimitives.
QString left(int n) const const
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
QFont font()
const QChar at(int position) const const
QSizeF size() const const
void setTop(qreal y)
QString attribute(const QString &name, const QString &defValue) const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:17:37 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.