diff --git a/src/common/KReportUtils.cpp b/src/common/KReportUtils.cpp index 547b7d76..2795bd91 100644 --- a/src/common/KReportUtils.cpp +++ b/src/common/KReportUtils.cpp @@ -1,567 +1,585 @@ /* This file is part of the KDE project Copyright (C) 2010-2015 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KReportUtils.h" #include "KReportUnit.h" #include "KReportItemBase.h" #include "KReportLineStyle.h" #include #include #include #include QString KReportUtils::attr(const QDomElement &el, const QString &attrName, const QString &defaultValue) { const QString val = el.attribute(attrName); return val.isEmpty() ? defaultValue : val; } QByteArray KReportUtils::attr(const QDomElement &el, const QString &attrName, const QByteArray &defaultValue) { const QByteArray val = el.attribute(attrName).toLatin1(); return val.isEmpty() ? defaultValue : val; } bool KReportUtils::attr(const QDomElement &el, const QString &attrName, bool defaultValue) { const QString val = el.attribute(attrName); return val.isEmpty() ? defaultValue : QVariant(val).toBool(); } int KReportUtils::attr(const QDomElement &el, const QString &attrName, int defaultValue) { const QString val = el.attribute(attrName); if (val.isEmpty()) { return defaultValue; } bool ok; const int result = QVariant(val).toInt(&ok); return ok ? result : defaultValue; } qreal KReportUtils::attr(const QDomElement &el, const QString &attrName, qreal defaultValue) { const QString val = el.attribute(attrName); return KReportUnit::parseValue(val, defaultValue); } QColor KReportUtils::attr(const QDomElement &el, const QString &attrName, const QColor &defaultValue) { const QString val = el.attribute(attrName); if (val.isEmpty()) { return defaultValue; } return QColor(val); } qreal KReportUtils::attrPercent(const QDomElement& el, const QString &attrName, qreal defaultValue) { QString str(el.attribute(attrName)); if (str.isEmpty() || !str.endsWith(QLatin1Char('%'))) { return defaultValue; } str.chop(1); bool ok; const qreal result = QVariant(str).toReal(&ok) / 100.0; if (!ok) { return defaultValue; } return result; } Qt::PenStyle KReportUtils::penStyle(const QString& str, Qt::PenStyle defaultValue) { const QByteArray s(str.toLatin1()); if (s == "nopen" || s == "none") { return Qt::NoPen; } else if (s == "solid") { return Qt::SolidLine; } else if (s == "dash" || s == "wave" /*we have nothing better for now*/) { return Qt::DashLine; } else if (s == "dot" || s == "dotted") { return Qt::DotLine; } else if (s == "dashdot" || s == "dot-dash") { return Qt::DashDotLine; } else if (s == "dashdotdot" || s == "dot-dot-dash") { return Qt::DashDotDotLine; } else { return defaultValue; } } Qt::Alignment KReportUtils::verticalAlignment(const QString &str, Qt::Alignment defaultValue) { const QByteArray s(str.toLatin1()); if (s == "center") { return Qt::AlignVCenter; } else if (s == "top") { return Qt::AlignTop; } else if (s == "bottom") { return Qt::AlignBottom; } else { return defaultValue; } } Qt::Alignment KReportUtils::horizontalAlignment(const QString &str, Qt::Alignment defaultValue) { const QByteArray s(str.toLatin1()); if (s == "center") { return Qt::AlignHCenter; } else if (s == "right") { return Qt::AlignRight; } else if (s == "left") { return Qt::AlignLeft; } else { return defaultValue; } } QString KReportUtils::verticalToString(Qt::Alignment alignment) { if (alignment.testFlag(Qt::AlignVCenter)) { return QLatin1String("center"); } else if (alignment.testFlag(Qt::AlignTop)) { return QLatin1String("top"); } else if (alignment.testFlag(Qt::AlignBottom)) { return QLatin1String("bottom"); } return QString(); } QString KReportUtils::horizontalToString(Qt::Alignment alignment) { if (alignment.testFlag(Qt::AlignHCenter)) { return QLatin1String("center"); } else if (alignment.testFlag(Qt::AlignLeft)) { return QLatin1String("left"); } else if (alignment.testFlag(Qt::AlignRight)) { return QLatin1String("right"); } return QString(); } QString KReportUtils::readNameAttribute(const QDomElement &el, const QString &defaultValue) { return attr(el, QLatin1String("report:name"), defaultValue); } QSizeF KReportUtils::readSizeAttributes(const QDomElement &el, const QSizeF &defaultValue) { QSizeF val; val.setWidth(attr(el, QLatin1String("svg:width"), defaultValue.width())); if (val.width() < 0.0) { val.setWidth(defaultValue.width()); } val.setHeight(attr(el, QLatin1String("svg:height"), defaultValue.height())); if (val.height() < 0.0) { val.setHeight(defaultValue.height()); } return val; } QRectF KReportUtils::readRectAttributes(const QDomElement &el, const QRectF &defaultValue) { QRectF val; val.setX(attr(el, QLatin1String("svg:x"), defaultValue.x())); val.setY(attr(el, QLatin1String("svg:y"), defaultValue.y())); val.setSize(readSizeAttributes(el, defaultValue.size())); return val; } qreal KReportUtils::readZAttribute(const QDomElement &el, qreal defaultValue) { return KReportUtils::attr(el, QLatin1String("report:z-index"), defaultValue); } int KReportUtils::readPercent(const QDomElement& el, const QString &attrName, int defaultPercentValue, bool *ok) { QString percent(el.attribute(attrName)); if (percent.isEmpty()) { if (ok) *ok = true; return defaultPercentValue; } if (!percent.endsWith(QLatin1Char('%'))) { if (ok) *ok = false; return 0; } percent.chop(1); if (ok) *ok = true; return percent.toInt(ok); } QString KReportUtils::readSectionTypeNameAttribute(const QDomElement &el, const QString &defaultValue) { return attr(el, QLatin1String("report:section-type"), defaultValue); } //! @return string representation of @a value, cuts of zeros; precision is set to 2 static QString roundValueToString(qreal value) { QString s(QString::number(value, 'g', 2)); if (s.endsWith(QLatin1String(".00"))) return QString::number(qRound(value)); return s; } //! Used by readFontAttributes() static QFont::Capitalization readFontCapitalization(const QByteArray& fontVariant, const QByteArray& textTransform) { if (fontVariant == "small-caps") return QFont::SmallCaps; if (textTransform == "uppercase") return QFont::AllUppercase; if (textTransform == "lowercase") return QFont::AllLowercase; if (textTransform == "capitalize") return QFont::Capitalize; // default, "normal" return QFont::MixedCase; } void KReportUtils::readFontAttributes(const QDomElement& el, QFont *font) { Q_ASSERT(font); const QFont::Capitalization cap = readFontCapitalization( attr(el, QLatin1String("fo:font-variant"), QByteArray()), attr(el, QLatin1String("fo:text-transform"), QByteArray())); font->setCapitalization(cap); // weight const QByteArray fontWeight(attr(el, QLatin1String("fo:font-weight"), QByteArray())); int weight = -1; if (fontWeight == "bold") { weight = QFont::Bold; } if (fontWeight == "normal") { weight = QFont::Normal; } else if (!fontWeight.isEmpty()) { // Remember : Qt and CSS/XSL doesn't have the same scale. It's 100-900 instead of Qt's 0-100 // See http://www.w3.org/TR/2001/REC-xsl-20011015/slice7.html#font-weight // and http://www.w3.org/TR/CSS2/fonts.html#font-boldness bool ok; qreal boldness = fontWeight.toUInt(&ok); if (ok) { boldness = qMin(boldness, 900.0); boldness = qMax(boldness, 100.0); weight = (boldness - 100.0) * 0.12375 /*== 99/800*/; // 0..99 } } if (weight >= 0) { font->setWeight(weight); } font->setItalic(attr(el, QLatin1String("fo:font-style"), QByteArray()) == "italic"); font->setFixedPitch(attr(el, QLatin1String("style:font-pitch"), QByteArray()) == "fixed"); font->setFamily(attr(el, QLatin1String("fo:font-family"), font->family())); font->setKerning(attr(el, QLatin1String("style:letter-kerning"), font->kerning())); // underline const QByteArray underlineType( attr(el, QLatin1String("style:text-underline-type"), QByteArray())); font->setUnderline(!underlineType.isEmpty() && underlineType != "none"); // double or single (we don't recognize them) // stricken-out const QByteArray strikeOutType(attr(el, QLatin1String("style:text-line-through-type"), QByteArray())); font->setStrikeOut(!strikeOutType.isEmpty() && strikeOutType != "none"); // double or single (we don't recognize them) //! @todo support fo:font-size-rel? //! @todo support fo:font-size in px font->setPointSizeF(KReportUtils::attr(el, QLatin1String("fo:font-size"), font->pointSizeF())); // letter spacing // §7.16.2 of [XSL] http://www.w3.org/TR/xsl11/#letter-spacing font->setLetterSpacing(QFont::PercentageSpacing, 100.0 * KReportUtils::attrPercent( el, QLatin1String("fo:letter-spacing"), font->letterSpacing())); } void KReportUtils::writeFontAttributes(QDomElement *el, const QFont &font) { Q_ASSERT(el); switch (font.capitalization()) { case QFont::SmallCaps: el->setAttribute(QLatin1String("fo:font-variant"), QLatin1String("small-caps")); break; case QFont::MixedCase: // default: "normal", do not save break; case QFont::AllUppercase: el->setAttribute(QLatin1String("fo:text-transform"), QLatin1String("uppercase")); break; case QFont::AllLowercase: el->setAttribute(QLatin1String("fo:text-transform"), QLatin1String("lowercase")); break; case QFont::Capitalize: el->setAttribute(QLatin1String("fo:text-transform"), QLatin1String("capitalize")); break; } // Remember : Qt and CSS/XSL doesn't have the same scale. It's 100-900 instead of Qt's 0-100 // See http://www.w3.org/TR/2001/REC-xsl-20011015/slice7.html#font-weight // and http://www.w3.org/TR/CSS2/fonts.html#font-boldness if (font.weight() == QFont::Light) { el->setAttribute(QLatin1String("fo:font-weight"), 200); } else if (font.weight() == QFont::Normal) { // Default //el->setAttribute("fo:font-weight", "normal"); // 400 } else if (font.weight() == QFont::DemiBold) { el->setAttribute(QLatin1String("fo:font-weight"), 600); } else if (font.weight() == QFont::Bold) { el->setAttribute(QLatin1String("fo:font-weight"), QLatin1String("bold")); // 700 } else if (font.weight() == QFont::Black) { el->setAttribute(QLatin1String("fo:font-weight"), 900); } else { el->setAttribute(QLatin1String("fo:font-weight"), qBound(10, font.weight(), 90) * 10); } // italic, default is "normal" if (font.italic()) { el->setAttribute(QLatin1String("fo:font-style"), QLatin1String("italic")); } // pitch, default is "variable" if (font.fixedPitch()) { el->setAttribute(QLatin1String("style:font-pitch"), QLatin1String("fixed")); } if (!font.family().isEmpty()) { el->setAttribute(QLatin1String("fo:font-family"), font.family()); } // kerning, default is "true" - el->setAttribute(QLatin1String("style:letter-kerning"), - font.kerning() ? QLatin1String("true") : QLatin1String("false")); + KReportUtils::setAttribute(el, QLatin1String("style:letter-kerning"), font.kerning()); // underline, default is "none" if (font.underline()) { el->setAttribute(QLatin1String("style:text-underline-type"), QLatin1String("single")); } // stricken-out, default is "none" if (font.strikeOut()) { el->setAttribute(QLatin1String("style:text-line-through-type"), QLatin1String("single")); } el->setAttribute(QLatin1String("fo:font-size"), font.pointSize()); // letter spacing, default is "normal" // §7.16.2 of [XSL] http://www.w3.org/TR/xsl11/#letter-spacing if (font.letterSpacingType() == QFont::PercentageSpacing) { // A value of 100 will keep the spacing unchanged; a value of 200 will enlarge // the spacing after a character by the width of the character itself. if (font.letterSpacing() != 100.0) { el->setAttribute(QLatin1String("fo:letter-spacing"), roundValueToString(font.letterSpacing()) + QLatin1Char('%')); } } else { // QFont::AbsoluteSpacing // A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing. el->setAttribute(QLatin1String("fo:letter-spacing"), roundValueToString(font.letterSpacing())); } } void KReportUtils::buildXMLRect(QDomElement *entity, const QPointF &pos, const QSizeF &size) { Q_ASSERT(entity); KReportUtils::setAttribute(entity, pos); KReportUtils::setAttribute(entity, size ); } void KReportUtils::buildXMLTextStyle(QDomDocument *doc, QDomElement *entity, const KReportTextStyleData &ts) { Q_ASSERT(doc); Q_ASSERT(entity); QDomElement element = doc->createElement(QLatin1String("report:text-style")); element.setAttribute(QLatin1String("fo:background-color"), ts.backgroundColor.name()); element.setAttribute(QLatin1String("fo:foreground-color"), ts.foregroundColor.name()); element.setAttribute(QLatin1String("fo:background-opacity"), QString::number(ts.backgroundOpacity) + QLatin1Char('%')); KReportUtils::writeFontAttributes(&element, ts.font); entity->appendChild(element); } void KReportUtils::buildXMLLineStyle(QDomDocument *doc, QDomElement *entity, const KReportLineStyle &ls) { Q_ASSERT(doc); Q_ASSERT(entity); QDomElement element = doc->createElement(QLatin1String("report:line-style")); element.setAttribute(QLatin1String("report:line-color"), ls.color().name()); element.setAttribute(QLatin1String("report:line-weight"), ls.weight()); QString l; switch (ls.penStyle()) { case Qt::NoPen: l = QLatin1String("nopen"); break; case Qt::SolidLine: l = QLatin1String("solid"); break; case Qt::DashLine: l = QLatin1String("dash"); break; case Qt::DotLine: l = QLatin1String("dot"); break; case Qt::DashDotLine: l = QLatin1String("dashdot"); break; case Qt::DashDotDotLine: l = QLatin1String("dashdotdot"); break; default: l = QLatin1String("solid"); } element.setAttribute(QLatin1String("report:line-style"), l); entity->appendChild(element); } void KReportUtils::addPropertyAsAttribute(QDomElement* e, KProperty* p) { Q_ASSERT(e); Q_ASSERT(p); const QString name = QLatin1String("report:") + QString::fromLatin1(p->name().toLower()); - switch (p->value().type()) { - case QVariant::Int : + switch (p->type()) { + case QVariant::Int: e->setAttribute(name, p->value().toInt()); break; case QVariant::Double: e->setAttribute(name, p->value().toDouble()); break; case QVariant::Bool: - e->setAttribute(name, p->value().toInt()); + e->setAttribute(name, p->value().toBool()); break; default: e->setAttribute(name, p->value().toString()); break; } } +bool KReportUtils::setPropertyValue(KProperty *p, const QDomElement &e) +{ + const QString name = QStringLiteral("report:") + QString::fromLatin1(p->name()); + if (!e.hasAttribute(name)) { + return false; + } + QVariant value = e.attribute(name); // string + if (!value.convert(p->type())) { + return false; + } + p->setValue(value); + return true; +} + void KReportUtils::setAttribute(QDomElement *e, const QString &attribute, double value) { Q_ASSERT(e); QString s; s.setNum(value, 'f', DBL_DIG); e->setAttribute(attribute, s + QLatin1String("pt")); } void KReportUtils::setAttribute(QDomElement *e, const QPointF &value) { Q_ASSERT(e); KReportUtils::setAttribute(e, QLatin1String("svg:x"), value.x()); KReportUtils::setAttribute(e, QLatin1String("svg:y"), value.y()); } void KReportUtils::setAttribute(QDomElement *e, const QSizeF &value) { Q_ASSERT(e); KReportUtils::setAttribute(e, QLatin1String("svg:width"), value.width()); KReportUtils::setAttribute(e, QLatin1String("svg:height"), value.height()); } +void KReportUtils::setAttribute(QDomElement *e, const QString &attribute, bool value) +{ + e->setAttribute(attribute, value ? QStringLiteral("true") : QStringLiteral("false")); +} + bool KReportUtils::parseReportTextStyleData(const QDomElement & elemSource, KReportTextStyleData *ts) { Q_ASSERT(ts); if (elemSource.tagName() != QLatin1String("report:text-style")) return false; ts->backgroundColor = QColor(elemSource.attribute( QLatin1String("fo:background-color"), QLatin1String("#ffffff"))); ts->foregroundColor = QColor(elemSource.attribute( QLatin1String("fo:foreground-color"), QLatin1String("#000000"))); bool ok; ts->backgroundOpacity = KReportUtils::readPercent( elemSource, QLatin1String("fo:background-opacity"), 100, &ok); if (!ok) { return false; } KReportUtils::readFontAttributes(elemSource, &ts->font); return true; } bool KReportUtils::parseReportLineStyleData(const QDomElement & elemSource, KReportLineStyle *ls) { Q_ASSERT(ls); if (elemSource.tagName() == QLatin1String("report:line-style")) { ls->setColor(QColor(elemSource.attribute(QLatin1String("report:line-color"), QLatin1String("#ffffff")))); ls->setWeight(elemSource.attribute(QLatin1String("report:line-weight"), QLatin1String("0.0")).toDouble()); QString l = elemSource.attribute(QLatin1String("report:line-style"), QLatin1String("nopen")); if (l == QLatin1String("nopen")) { ls->setPenStyle(Qt::NoPen); } else if (l == QLatin1String("solid")) { ls->setPenStyle(Qt::SolidLine); } else if (l == QLatin1String("dash")) { ls->setPenStyle(Qt::DashLine); } else if (l == QLatin1String("dot")) { ls->setPenStyle(Qt::DotLine); } else if (l == QLatin1String("dashdot")) { ls->setPenStyle(Qt::DashDotLine); } else if (l == QLatin1String("dashdotdot")) { ls->setPenStyle(Qt::DashDotDotLine); } return true; } return false; } class PageIds : private QHash { public: PageIds() {} QPageSize::PageSizeId id(const QString &key) { if (isEmpty()) { for (int i = 0; i < QPageSize::LastPageSize; ++i) { QString key(QPageSize::key(static_cast(i))); if (key.isEmpty()) { break; } insert(key, static_cast(i)); } } return value(key); } }; Q_GLOBAL_STATIC(PageIds, s_pageIds) QPageSize::PageSizeId KReportUtils::pageSizeId(const QString &key) { return s_pageIds->id(key); } QPageSize KReportUtils::pageSize(const QString &key) { return QPageSize(s_pageIds->id(key)); } diff --git a/src/common/KReportUtils.h b/src/common/KReportUtils.h index 46c98b1f..129d3bed 100644 --- a/src/common/KReportUtils.h +++ b/src/common/KReportUtils.h @@ -1,152 +1,159 @@ /* This file is part of the KDE project Copyright (C) 2010-2015 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KREPORTUTILS_H #define KREPORTUTILS_H #include "kreport_export.h" #include #include #include #include class QDomDocument; class QDomElement; class QFont; class QPointF; class KProperty; class KReportTextStyleData; class KReportLineStyle; namespace KReportUtils { KREPORT_EXPORT QString attr(const QDomElement &el, const QString &attrName, const QString &defaultValue = QString()); KREPORT_EXPORT QByteArray attr(const QDomElement &el, const QString &attrName, const QByteArray &defaultValue = QByteArray()); KREPORT_EXPORT bool attr(const QDomElement &el, const QString &attrName, bool defaultValue = false); KREPORT_EXPORT int attr(const QDomElement &el, const QString &attrName, int defaultValue = 0); KREPORT_EXPORT qreal attr(const QDomElement &el, const QString &attrName, qreal defaultValue = 0.0); KREPORT_EXPORT QColor attr(const QDomElement &el, const QString &attrName, const QColor &defaultValue = QColor()); //! @return percent value converted to qreal, e.g. 1.0 for "100%", 0.505 for "50.5%". //! @a defaultValue is returned if there is not "%" suffix or no proper number. KREPORT_EXPORT qreal attrPercent(const QDomElement& el, const QString &attrName, qreal defaultValue = 0.0); //! @return pen style from @a str or @a defaultValue //! Values from ODF 1.2 19.493 style:line-style are also recognized. KREPORT_EXPORT Qt::PenStyle penStyle(const QString &str, Qt::PenStyle defaultValue); //! @return vertical alignment flag from @a str or @a defaultValue KREPORT_EXPORT Qt::Alignment verticalAlignment(const QString &str, Qt::Alignment defaultValue); //! @return horizontal alignment flag from @a str or @a defaultValue KREPORT_EXPORT Qt::Alignment horizontalAlignment(const QString &str, Qt::Alignment defaultValue); //! @return vertical alignment flag name from @a alignment KREPORT_EXPORT QString verticalToString(Qt::Alignment alignment); //! @return horizontal alignment flag from @a alignment KREPORT_EXPORT QString horizontalToString(Qt::Alignment alignment); //! @return name value read from report:name attribute of @a el. //! If the attribute is missing, @a defaultValue is returned. KREPORT_EXPORT QString readNameAttribute( const QDomElement &el, const QString &defaultValue = QString()); //! @return size value read from svg:width and svg:height attributes of @a el. //! If any of the attributes are missing, @a defaultValue is returned. //! @a defaultValue should be specified in Points. KREPORT_EXPORT QSizeF readSizeAttributes( const QDomElement &el, const QSizeF &defaultValue = QSizeF()); //! @return rectangle value read from svg:x, svg:y, svg:width, svg:height attributes of @a el. //! If any of the attributes are missing, @a defaultValue is returned. //! @a defaultValue should be specified in Points. KREPORT_EXPORT QRectF readRectAttributes( const QDomElement &el, const QRectF &defaultValue = QRectF()); //! @return Z index value read from report:z-index attribute of @a el. //! If the attribute is missing @a defaultValue is returned. //! @a defaultValue should be specified in Points. KREPORT_EXPORT qreal readZAttribute(const QDomElement &el, qreal defaultValue = 0.0); //! @return name of section type read from report:section-type attribute of @a el. //! If the attribute is missing, @a defaultValue is returned. KREPORT_EXPORT QString readSectionTypeNameAttribute( const QDomElement &el, const QString &defaultValue = QString()); //! @return percent value for element @a name. If the element is missing, returns @a defaultPercentValue. //! If @a ok is not 0, *ok is set to the result. KREPORT_EXPORT int readPercent(const QDomElement &el, const QString &attrName, int defaultPercentValue, bool *ok); //! Reads all font attributes for element @a el into @a font. //! @todo add unit tests KREPORT_EXPORT void readFontAttributes(const QDomElement& el, QFont* font); //! Writes all attributes of font @a font into element @a el. //! @todo add unit tests KREPORT_EXPORT void writeFontAttributes(QDomElement *el, const QFont &font); //! Writes attributes for the rect position @a pos, @a siz KREPORT_EXPORT void buildXMLRect(QDomElement *entity, const QPointF &pos, const QSizeF &size); //! Writes attributes for text style @a ts KREPORT_EXPORT void buildXMLTextStyle(QDomDocument *doc, QDomElement *entity, const KReportTextStyleData &ts); //! Writes attributes for line style @a ls KREPORT_EXPORT void buildXMLLineStyle(QDomDocument *doc, QDomElement *entity, const KReportLineStyle &ls); //! Writes attributes for the property @a p KREPORT_EXPORT void addPropertyAsAttribute(QDomElement* e, KProperty* p); + /** + * Sets value of property @a p if element @e e has attribute named report:X where X is the name of @a p. + * + * Otherwise it does nothing and return @c false. + */ + KREPORT_EXPORT bool setPropertyValue(KProperty *p, const QDomElement &e); + //! Writes @a attribute to element @a e, @a value is stored in points with unit 'pt' KREPORT_EXPORT void setAttribute(QDomElement *e, const QString &attribute, double value); //! Writes point @a value as attributes to element @a e KREPORT_EXPORT void setAttribute(QDomElement *e, const QPointF &value); //! Writes size @a value as attributes to element @a e KREPORT_EXPORT void setAttribute(QDomElement *e, const QSizeF &value); //! Writes @a attribute to element @a e, @a value is stored as boolean KREPORT_EXPORT void setAttribute(QDomElement *e, const QString &attribute, bool value); //! Reads attributes from @a elemSource into text style @a ts KREPORT_EXPORT bool parseReportTextStyleData(const QDomElement & elemSource, KReportTextStyleData *ts); //! Reads attributes from @a elemSource into line style @a ls KREPORT_EXPORT bool parseReportLineStyleData(const QDomElement & elemSource, KReportLineStyle *ls); //! @return page size ID for page key (the PPD standard mediaOption keyword, e.g. "A4") //! @note It's an efficient workaround because QPageSize misses this function. KREPORT_EXPORT QPageSize::PageSizeId pageSizeId(const QString &key); //! Like QPageSize::PageSizeId pageSizeId(const QString &key) but returns entire QPageSize object. KREPORT_EXPORT QPageSize pageSize(const QString &key); } // KReportUtils #endif diff --git a/src/items/field/KReportItemField.cpp b/src/items/field/KReportItemField.cpp index 0cc9ae78..73982976 100644 --- a/src/items/field/KReportItemField.cpp +++ b/src/items/field/KReportItemField.cpp @@ -1,270 +1,269 @@ /* This file is part of the KDE project * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "KReportItemField.h" #include "KReportRenderObjects.h" #include "KReportUtils.h" #include "kreportplugin_debug.h" #ifdef KREPORT_SCRIPTING #include "KReportScriptHandler.h" #endif #include #include #include #include #include #include KReportItemField::KReportItemField() { createProperties(); } KReportItemField::KReportItemField(const QDomNode & element) : KReportItemField() { nameProperty()->setValue(KReportUtils::readNameAttribute(element.toElement())); setItemDataSource(element.toElement().attribute(QLatin1String("report:item-data-source"))); m_itemValue->setValue(element.toElement().attribute(QLatin1String("report:value"))); setZ(element.toElement().attribute(QLatin1String("report:z-index")).toDouble()); m_horizontalAlignment->setValue(element.toElement().attribute(QLatin1String("report:horizontal-align"))); m_verticalAlignment->setValue(element.toElement().attribute(QLatin1String("report:vertical-align"))); - - m_canGrow->setValue(element.toElement().attribute(QLatin1String("report:can-grow"))); - m_wordWrap->setValue(element.toElement().attribute(QLatin1String("report:word-wrap"))); + KReportUtils::setPropertyValue(m_canGrow, element.toElement()); + KReportUtils::setPropertyValue(m_wordWrap, element.toElement()); parseReportRect(element.toElement()); QDomNodeList nl = element.childNodes(); QString n; QDomNode node; for (int i = 0; i < nl.count(); i++) { node = nl.item(i); n = node.nodeName(); if (n == QLatin1String("report:text-style")) { KReportTextStyleData ts; if (parseReportTextStyleData(node.toElement(), &ts)) { m_backgroundColor->setValue(ts.backgroundColor); m_foregroundColor->setValue(ts.foregroundColor); m_backgroundOpacity->setValue(ts.backgroundOpacity); m_font->setValue(ts.font); } } else if (n == QLatin1String("report:line-style")) { KReportLineStyle ls; if (parseReportLineStyleData(node.toElement(), &ls)) { m_lineWeight->setValue(ls.weight()); m_lineColor->setValue(ls.color()); m_lineStyle->setValue(static_cast(ls.penStyle())); } } else { kreportpluginWarning() << "while parsing field element encountered unknown element: " << n; } } } KReportItemField::~KReportItemField() { } void KReportItemField::createProperties() { createDataSourceProperty(); m_itemValue = new KProperty("value", QString(), tr("Value"), tr("Value used if not bound to a field")); KPropertyListData *listData = new KPropertyListData( { QLatin1String("left"), QLatin1String("center"), QLatin1String("right") }, QVariantList{ tr("Left"), tr("Center"), tr("Right") }); m_horizontalAlignment = new KProperty("horizontal-align", listData, QLatin1String("left"), tr("Horizontal Alignment")); listData = new KPropertyListData( { QLatin1String("top"), QLatin1String("center"), QLatin1String("bottom") }, QVariantList{ tr("Top"), tr("Center"), tr("Bottom") }); m_verticalAlignment = new KProperty("vertical-align", listData, QLatin1String("center"), tr("Vertical Alignment")); m_font = new KProperty("font", QApplication::font(), tr("Font")); m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color")); m_foregroundColor = new KProperty("foreground-color", QColor(Qt::black), tr("Foreground Color")); m_backgroundOpacity = new KProperty("background-opacity", QVariant(0), tr("Background Opacity")); m_backgroundOpacity->setOption("max", 100); m_backgroundOpacity->setOption("min", 0); m_backgroundOpacity->setOption("suffix", QLatin1String("%")); m_lineWeight = new KProperty("line-weight", 1.0, tr("Line Weight")); m_lineWeight->setOption("step", 1.0); m_lineColor = new KProperty("line-color", QColor(Qt::black), tr("Line Color")); m_lineStyle = new KProperty("line-style", static_cast(Qt::NoPen), tr("Line Style"), QString(), KProperty::LineStyle); m_wordWrap = new KProperty("word-wrap", QVariant(false), tr("Word Wrap")); m_canGrow = new KProperty("can-grow", QVariant(false), tr("Can Grow")); //! @todo I do not think we need these #if 0 //Field Totals m_trackTotal = new KProperty("trackTotal", QVariant(false), futureI18n("Track Total")); m_trackBuiltinFormat = new KProperty("trackBuiltinFormat", QVariant(false), futureI18n("Track Builtin Format")); _useSubTotal = new KProperty("useSubTotal", QVariant(false), futureI18n("Use Sub Total"_)); _trackTotalFormat = new KProperty("trackTotalFormat", QString(), futureI18n("Track Total Format")); #endif propertySet()->addProperty(m_itemValue); propertySet()->addProperty(m_horizontalAlignment); propertySet()->addProperty(m_verticalAlignment); propertySet()->addProperty(m_font); propertySet()->addProperty(m_backgroundColor); propertySet()->addProperty(m_foregroundColor); propertySet()->addProperty(m_backgroundOpacity); propertySet()->addProperty(m_lineWeight); propertySet()->addProperty(m_lineColor); propertySet()->addProperty(m_lineStyle); propertySet()->addProperty(m_wordWrap); propertySet()->addProperty(m_canGrow); //_set->addProperty ( _trackTotal ); //_set->addProperty ( _trackBuiltinFormat ); //_set->addProperty ( _useSubTotal ); //_set->addProperty ( _trackTotalFormat ); } int KReportItemField::textFlags() const { int flags; QString t; t = m_horizontalAlignment->value().toString(); if (t == QLatin1String("center")) flags = Qt::AlignHCenter; else if (t == QLatin1String("right")) flags = Qt::AlignRight; else flags = Qt::AlignLeft; t = m_verticalAlignment->value().toString(); if (t == QLatin1String("center")) flags |= Qt::AlignVCenter; else if (t == QLatin1String("bottom")) flags |= Qt::AlignBottom; else flags |= Qt::AlignTop; if (m_wordWrap->value().toBool() == true) { flags |= Qt::TextWordWrap; } return flags; } KReportTextStyleData KReportItemField::textStyle() const { KReportTextStyleData d; d.backgroundColor = m_backgroundColor->value().value(); d.foregroundColor = m_foregroundColor->value().value(); d.font = m_font->value().value(); d.backgroundOpacity = m_backgroundOpacity->value().toInt(); return d; } KReportLineStyle KReportItemField::lineStyle() const { KReportLineStyle ls; ls.setWeight(m_lineWeight->value().toReal()); ls.setColor(m_lineColor->value().value()); ls.setPenStyle((Qt::PenStyle)m_lineStyle->value().toInt()); return ls; } // RTTI QString KReportItemField::typeName() const { return QLatin1String("field"); } int KReportItemField::renderSimpleData(OROPage *page, OROSection *section, const QPointF &offset, const QVariant &data, KReportScriptHandler *script) { OROTextBox * tb = new OROTextBox(); tb->setPosition(scenePosition(position()) + offset); tb->setSize(sceneSize(size())); tb->setFont(font()); tb->setFlags(textFlags()); tb->setTextStyle(textStyle()); tb->setLineStyle(lineStyle()); tb->setCanGrow(m_canGrow->value().toBool()); tb->setWordWrap(m_wordWrap->value().toBool()); QString str; QString ids = itemDataSource(); if (!ids.isEmpty()) { #ifdef KREPORT_SCRIPTING if (ids.left(1) == QLatin1String("=") && script) { //Everything after = is treated as code if (!ids.contains(QLatin1String("PageTotal()"))) { QVariant v = script->evaluate(ids.mid(1)); str = v.toString(); } else { str = ids.mid(1); tb->setRequiresPostProcessing(true); } } else #else Q_UNUSED(script); #endif str = data.toString(); } else { str = m_itemValue->value().toString(); } tb->setText(str); //Work out the size of the text if (tb->canGrow()) { QRectF r; if (tb->wordWrap()) { //Grow vertically QFontMetricsF metrics(font()); QRectF temp(tb->position().x(), tb->position().y(), tb->size().width(), 5000); // a large vertical height r = metrics.boundingRect(temp, tb->flags(), str); } else { //Grow Horizontally QFontMetricsF metrics(font()); QRectF temp(tb->position().x(), tb->position().y(), 5000, tb->size().height()); // a large vertical height r = metrics.boundingRect(temp, tb->flags(), str); } tb->setSize(r.size() + QSize(4,4)); } if (page) { page->insertPrimitive(tb); } if (section) { OROPrimitive *clone = tb->clone(); clone->setPosition(scenePosition(position())); section->addPrimitive(clone); } int height = scenePosition(position()).y() + tb->size().height(); //If there is no page to add the item to, delete it now because it wont be deleted later if (!page) { delete tb; } return height; }