Warning, file /libraries/kreport/src/items/text/KReportItemText.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0003  * Copyright (C) 2019 Jarosław Staniek <staniek@kde.org>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2.1 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public
0016  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 #include "KReportItemText.h"
0020 #include "KReportRenderObjects.h"
0021 #include "KReportUtils.h"
0022 #include "KReportUtils_p.h"
0023 #include "kreportplugin_debug.h"
0024 
0025 #include <KPropertyListData>
0026 #include <KPropertySet>
0027 
0028 #include <QPrinter>
0029 #include <QApplication>
0030 #include <QPalette>
0031 #include <QFontMetrics>
0032 #include <QDomNodeList>
0033 #include <QRegularExpression>
0034 
0035 KReportItemText::KReportItemText()
0036     : m_bottomPadding(0.0)
0037 {
0038     createProperties();
0039 }
0040 
0041 KReportItemText::KReportItemText(const QDomNode & element)
0042   : KReportItemText()
0043 {
0044     nameProperty()->setValue(KReportUtils::readNameAttribute(element.toElement()));
0045     setItemDataSource(element.toElement().attribute(QLatin1String("report:item-data-source")));
0046     m_itemValue->setValue(element.toElement().attribute(QLatin1String("report:value")));
0047     setZ(element.toElement().attribute(QLatin1String("report:z-index")).toDouble());
0048     m_horizontalAlignment->setValue(element.toElement().attribute(QLatin1String("report:horizontal-align")));
0049     m_verticalAlignment->setValue(element.toElement().attribute(QLatin1String("report:vertical-align")));
0050     m_bottomPadding = element.toElement().attribute(QLatin1String("report:bottom-padding")).toDouble();
0051 
0052     parseReportRect(element.toElement());
0053 
0054     QDomNodeList nl = element.childNodes();
0055     QString n;
0056     QDomNode node;
0057     for (int i = 0; i < nl.count(); i++) {
0058         node = nl.item(i);
0059         n = node.nodeName();
0060 
0061         if (n == QLatin1String("report:text-style")) {
0062             KReportTextStyleData ts;
0063             if (parseReportTextStyleData(node.toElement(), &ts)) {
0064                 m_backgroundColor->setValue(ts.backgroundColor);
0065                 m_foregroundColor->setValue(ts.foregroundColor);
0066                 m_backgroundOpacity->setValue(ts.backgroundOpacity);
0067                 m_font->setValue(ts.font);
0068 
0069             }
0070         } else if (n == QLatin1String("report:line-style")) {
0071             KReportLineStyle ls;
0072             if (parseReportLineStyleData(node.toElement(), &ls)) {
0073                 m_lineWeight->setValue(ls.weight());
0074                 m_lineColor->setValue(ls.color());
0075                 m_lineStyle->setValue(static_cast<int>(ls.penStyle()));
0076             }
0077         } else {
0078             kreportpluginWarning() << "while parsing field element encountered unknown element: " << n;
0079         }
0080     }
0081 
0082 }
0083 
0084 KReportItemText::~KReportItemText()
0085 {
0086 }
0087 
0088 Qt::Alignment KReportItemText::textFlags() const
0089 {
0090     Qt::Alignment align;
0091     QString t;
0092     t = m_horizontalAlignment->value().toString();
0093     if (t == QLatin1String("center"))
0094         align = Qt::AlignHCenter;
0095     else if (t == QLatin1String("right"))
0096         align = Qt::AlignRight;
0097     else
0098         align = Qt::AlignLeft;
0099 
0100     t = m_verticalAlignment->value().toString();
0101     if (t == QLatin1String("center"))
0102         align |= Qt::AlignVCenter;
0103     else if (t == QLatin1String("bottom"))
0104         align |= Qt::AlignBottom;
0105     else
0106         align |= Qt::AlignTop;
0107 
0108     return align;
0109 }
0110 
0111 void KReportItemText::createProperties()
0112 {
0113     createDataSourceProperty();
0114 
0115     m_itemValue = new KProperty("value", QString(), tr("Value"), tr("Value used if not bound to a field"));
0116 
0117     KPropertyListData *listData = new KPropertyListData(
0118         { QLatin1String("left"), QLatin1String("center"), QLatin1String("right") },
0119         QVariantList{ tr("Left"), tr("Center"), tr("Right") });
0120     m_horizontalAlignment = new KProperty("horizontal-align", listData, QLatin1String("left"),
0121                                           tr("Horizontal Alignment"));
0122 
0123     listData = new KPropertyListData(
0124         { QLatin1String("top"), QLatin1String("center"), QLatin1String("bottom") },
0125         QVariantList{ tr("Top"), tr("Center"), tr("Bottom") });
0126     m_verticalAlignment = new KProperty("vertical-align", listData, QLatin1String("center"),
0127                                         tr("Vertical Alignment"));
0128 
0129     m_font = new KProperty("font", QApplication::font(), tr("Font"));
0130 
0131     m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color"));
0132     m_foregroundColor = new KProperty("foreground-color", QColor(Qt::black), tr("Foreground Color"));
0133 
0134     m_lineWeight = new KProperty("line-weight", 1.0, tr("Line Weight"));
0135     m_lineWeight->setOption("step", 1.0);
0136     m_lineColor = new KProperty("line-color", QColor(Qt::black), tr("Line Color"));
0137     m_lineStyle = new KProperty("line-style", static_cast<int>(Qt::NoPen), tr("Line Style"), QString(), KProperty::LineStyle);
0138     m_backgroundOpacity = new KProperty("background-opacity", QVariant(0), tr("Background Opacity"));
0139     m_backgroundOpacity->setOption("max", 100);
0140     m_backgroundOpacity->setOption("min", 0);
0141     m_backgroundOpacity->setOption("suffix", QLatin1String("%"));
0142 
0143     propertySet()->addProperty(m_itemValue);
0144     propertySet()->addProperty(m_horizontalAlignment);
0145     propertySet()->addProperty(m_verticalAlignment);
0146     propertySet()->addProperty(m_font);
0147     propertySet()->addProperty(m_backgroundColor);
0148     propertySet()->addProperty(m_foregroundColor);
0149     propertySet()->addProperty(m_backgroundOpacity);
0150     propertySet()->addProperty(m_lineWeight);
0151     propertySet()->addProperty(m_lineColor);
0152     propertySet()->addProperty(m_lineStyle);
0153 
0154 }
0155 
0156 qreal KReportItemText::bottomPadding() const
0157 {
0158     return m_bottomPadding;
0159 }
0160 
0161 void KReportItemText::setBottomPadding(qreal bp)
0162 {
0163     if (m_bottomPadding != bp) {
0164         m_bottomPadding = bp;
0165     }
0166 }
0167 
0168 KReportTextStyleData KReportItemText::textStyle() const
0169 {
0170     KReportTextStyleData d;
0171     d.backgroundColor = m_backgroundColor->value().value<QColor>();
0172     d.foregroundColor = m_foregroundColor->value().value<QColor>();
0173     d.font = m_font->value().value<QFont>();
0174     d.backgroundOpacity = m_backgroundOpacity->value().toInt();
0175     return d;
0176 }
0177 
0178 KReportLineStyle KReportItemText::lineStyle() const
0179 {
0180     KReportLineStyle ls;
0181     ls.setWeight(m_lineWeight->value().toReal());
0182     ls.setColor(m_lineColor->value().value<QColor>());
0183     ls.setPenStyle((Qt::PenStyle)m_lineStyle->value().toInt());
0184     return ls;
0185 }
0186 
0187 // RTTI
0188 QString KReportItemText::typeName() const
0189 {
0190     return QLatin1String("text");
0191 }
0192 
0193 int KReportItemText::renderSimpleData(OROPage *page, OROSection *section, const QPointF &offset,
0194                                        const QVariant &data, KReportScriptHandler *script)
0195 
0196 {
0197     Q_UNUSED(script);
0198 
0199     QString qstrValue;
0200 
0201     QString cs = itemDataSource();
0202 
0203     if (!cs.isEmpty()) {
0204         qstrValue = data.toString();
0205     } else {
0206         qstrValue = m_itemValue->value().toString();
0207     }
0208 
0209     QPointF pos = scenePosition(position());
0210     QSizeF siz = sceneSize(size());
0211     pos += offset;
0212 
0213     QRectF trf(pos, siz);
0214     qreal intStretch = trf.top() - offset.y();
0215 
0216     if (!qstrValue.isEmpty()) {
0217         QRectF rect = trf;
0218 
0219         int pos = 0;
0220         QChar separator;
0221         QRegularExpression re(QLatin1String("\\s"));
0222         const QFontMetricsF fm(font(), KReportPrivate::highResolutionPrinter());
0223 
0224         const int intRectWidth
0225             = (int)((size().width() / 72) * KReportPrivate::highResolutionPrinter()->resolution());
0226         int     intLineCounter  = 0;
0227         qreal   intBaseTop      = trf.top();
0228         qreal   intRectHeight   = trf.height();
0229 
0230         while (!qstrValue.isEmpty()) {
0231             QRegularExpressionMatch match = re.match(qstrValue);
0232             int idx = match.capturedStart(pos);
0233             if (idx == -1) {
0234                 idx = qstrValue.length();
0235                 separator = QLatin1Char('\n');
0236             } else
0237                 separator = qstrValue.at(idx);
0238 
0239             if (fm.boundingRect(qstrValue.left(idx)).width() < intRectWidth || pos == 0) {
0240                 pos = idx + 1;
0241                 if (separator == QLatin1Char('\n')) {
0242                     QString line = qstrValue.left(idx);
0243 
0244                     qstrValue.remove(0, idx + 1);
0245 
0246                     pos = 0;
0247 
0248                     rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
0249                     rect.setBottom(rect.top() + intRectHeight);
0250 
0251                     OROTextBox * tb = new OROTextBox();
0252                     tb->setPosition(rect.topLeft());
0253                     tb->setSize(rect.size());
0254                     tb->setFont(font());
0255                     tb->setText(line);
0256                     tb->setFlags(textFlags());
0257                     tb->setTextStyle(textStyle());
0258                     tb->setLineStyle(lineStyle());
0259 
0260                     if (page) {
0261                         page->insertPrimitive(tb);
0262                     }
0263 
0264                     if (section) {
0265                         OROTextBox *tb2 = dynamic_cast<OROTextBox*>(tb->clone());
0266                         if (tb2) {
0267                             tb2->setPosition(scenePosition(position()));
0268                             section->addPrimitive(tb2);
0269                         }
0270                     }
0271 
0272                     if (!page) {
0273                         delete tb;
0274                     }
0275 
0276                     intStretch += intRectHeight;
0277                     intLineCounter++;
0278                 }
0279             } else {
0280                 QString line = qstrValue.left(pos - 1);
0281                 qstrValue.remove(0, pos);
0282                 pos = 0;
0283 
0284                 rect.setTop(intBaseTop + (intLineCounter * intRectHeight));
0285                 rect.setBottom(rect.top() + intRectHeight);
0286 
0287                 OROTextBox * tb = new OROTextBox();
0288                 tb->setPosition(rect.topLeft());
0289                 tb->setSize(rect.size());
0290                 tb->setFont(font());
0291                 tb->setText(line);
0292                 tb->setFlags(textFlags());
0293                 tb->setTextStyle(textStyle());
0294                 tb->setLineStyle(lineStyle());
0295                 if (page) {
0296                     page->insertPrimitive(tb);
0297                 } else {
0298                     delete tb;
0299                 }
0300 
0301                 intStretch += intRectHeight;
0302                 intLineCounter++;
0303             }
0304         }
0305 
0306         intStretch += (m_bottomPadding / 100.0);
0307     }
0308 
0309     return intStretch; //Item returns its required section height
0310 }