andre@1: /**************************************************************************** andre@1: ** Copyright (c) 2013-2014 Debao Zhang andre@1: ** All right reserved. andre@1: ** andre@1: ** Permission is hereby granted, free of charge, to any person obtaining andre@1: ** a copy of this software and associated documentation files (the andre@1: ** "Software"), to deal in the Software without restriction, including andre@1: ** without limitation the rights to use, copy, modify, merge, publish, andre@1: ** distribute, sublicense, and/or sell copies of the Software, and to andre@1: ** permit persons to whom the Software is furnished to do so, subject to andre@1: ** the following conditions: andre@1: ** andre@1: ** The above copyright notice and this permission notice shall be andre@1: ** included in all copies or substantial portions of the Software. andre@1: ** andre@1: ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, andre@1: ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF andre@1: ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND andre@1: ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE andre@1: ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION andre@1: ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION andre@1: ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. andre@1: ** andre@1: ****************************************************************************/ andre@1: #include "xlsxcellformula.h" andre@1: #include "xlsxcellformula_p.h" andre@1: #include "xlsxutility_p.h" andre@1: andre@1: #include andre@1: #include andre@1: andre@1: QT_BEGIN_NAMESPACE_XLSX andre@1: andre@1: CellFormulaPrivate::CellFormulaPrivate(const QString &formula_, const CellRange &ref_, CellFormula::FormulaType type_) andre@1: :formula(formula_), type(type_), reference(ref_), ca(false), si(0) andre@1: { andre@1: //Remove the formula '=' sign if exists andre@1: if (formula.startsWith(QLatin1String("="))) andre@1: formula.remove(0,1); andre@1: else if (formula.startsWith(QLatin1String("{=")) && formula.endsWith(QLatin1String("}"))) andre@1: formula = formula.mid(2, formula.length()-3); andre@1: } andre@1: andre@1: CellFormulaPrivate::CellFormulaPrivate(const CellFormulaPrivate &other) andre@1: : QSharedData(other) andre@1: , formula(other.formula), type(other.type), reference(other.reference) andre@1: , ca(other.ca), si(other.si) andre@1: { andre@1: andre@1: } andre@1: andre@1: CellFormulaPrivate::~CellFormulaPrivate() andre@1: { andre@1: andre@1: } andre@1: andre@1: /*! andre@1: \class CellFormula andre@1: \inmodule QtXlsx andre@1: \brief The CellFormula class provides a API that is used to handle the cell formula. andre@1: andre@1: */ andre@1: andre@1: /*! andre@1: \enum CellFormula::FormulaType andre@1: \value NormalType andre@1: \value ArrayType andre@1: \value DataTableType andre@1: \value SharedType andre@1: */ andre@1: andre@1: /*! andre@1: * Creates a new formula. andre@1: */ andre@1: CellFormula::CellFormula() andre@1: { andre@1: //The d pointer is initialized with a null pointer andre@1: } andre@1: andre@1: /*! andre@1: * Creates a new formula with the given \a formula and \a type. andre@1: */ andre@1: CellFormula::CellFormula(const char *formula, FormulaType type) andre@1: :d(new CellFormulaPrivate(QString::fromLatin1(formula), CellRange(), type)) andre@1: { andre@1: andre@1: } andre@1: andre@1: /*! andre@1: * Creates a new formula with the given \a formula and \a type. andre@1: */ andre@1: CellFormula::CellFormula(const QString &formula, FormulaType type) andre@1: :d(new CellFormulaPrivate(formula, CellRange(), type)) andre@1: { andre@1: andre@1: } andre@1: andre@1: /*! andre@1: * Creates a new formula with the given \a formula, \a ref and \a type. andre@1: */ andre@1: CellFormula::CellFormula(const QString &formula, const CellRange &ref, FormulaType type) andre@1: :d(new CellFormulaPrivate(formula, ref, type)) andre@1: { andre@1: andre@1: } andre@1: andre@1: /*! andre@1: Creates a new formula with the same attributes as the \a other formula. andre@1: */ andre@1: CellFormula::CellFormula(const CellFormula &other) andre@1: :d(other.d) andre@1: { andre@1: } andre@1: andre@1: /*! andre@1: Assigns the \a other formula to this formula, and returns a andre@1: reference to this formula. andre@1: */ andre@1: CellFormula &CellFormula::operator =(const CellFormula &other) andre@1: { andre@1: d = other.d; andre@1: return *this; andre@1: } andre@1: andre@1: /*! andre@1: * Destroys this formula. andre@1: */ andre@1: CellFormula::~CellFormula() andre@1: { andre@1: andre@1: } andre@1: andre@1: /*! andre@1: * Returns the type of the formula. andre@1: */ andre@1: CellFormula::FormulaType CellFormula::formulaType() const andre@1: { andre@1: return d ? d->type : NormalType; andre@1: } andre@1: andre@1: /*! andre@1: * Returns the contents of the formula. andre@1: */ andre@1: QString CellFormula::formulaText() const andre@1: { andre@1: return d ? d->formula : QString(); andre@1: } andre@1: andre@1: /*! andre@1: * Returns the reference cells of the formula. For normal formula, andre@1: * this will return an invalid CellRange object. andre@1: */ andre@1: CellRange CellFormula::reference() const andre@1: { andre@1: return d ? d->reference : CellRange(); andre@1: } andre@1: andre@1: /*! andre@1: * Returns whether the formula is valid. andre@1: */ andre@1: bool CellFormula::isValid() const andre@1: { andre@1: return d; andre@1: } andre@1: andre@1: /*! andre@1: * Returns the shared index for shared formula. andre@1: */ andre@1: int CellFormula::sharedIndex() const andre@1: { andre@1: return d && d->type == SharedType ? d->si : -1; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: bool CellFormula::saveToXml(QXmlStreamWriter &writer) const andre@1: { andre@1: writer.writeStartElement(QStringLiteral("f")); andre@1: QString t; andre@1: switch (d->type) { andre@1: case CellFormula::ArrayType: andre@1: t = QStringLiteral("array"); andre@1: break; andre@1: case CellFormula::SharedType: andre@1: t = QStringLiteral("shared"); andre@1: break; andre@1: default: andre@1: break; andre@1: } andre@1: if (!t.isEmpty()) andre@1: writer.writeAttribute(QStringLiteral("t"), t); andre@1: if (d->reference.isValid()) andre@1: writer.writeAttribute(QStringLiteral("ref"), d->reference.toString()); andre@1: if (d->ca) andre@1: writer.writeAttribute(QStringLiteral("ca"), QStringLiteral("1")); andre@1: if (d->type == CellFormula::SharedType) andre@1: writer.writeAttribute(QStringLiteral("si"), QString::number(d->si)); andre@1: andre@1: if (!d->formula.isEmpty()) andre@1: writer.writeCharacters(d->formula); andre@1: andre@1: writer.writeEndElement(); //f andre@1: andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: bool CellFormula::loadFromXml(QXmlStreamReader &reader) andre@1: { andre@1: Q_ASSERT(reader.name() == QLatin1String("f")); andre@1: if (!d) andre@1: d = new CellFormulaPrivate(QString(), CellRange(), NormalType); andre@1: andre@1: QXmlStreamAttributes attributes = reader.attributes(); andre@1: QString typeString = attributes.value(QLatin1String("t")).toString(); andre@1: if (typeString == QLatin1String("array")) andre@1: d->type = ArrayType; andre@1: else if (typeString == QLatin1String("shared")) andre@1: d->type = SharedType; andre@1: else andre@1: d->type = NormalType; andre@1: andre@1: if (attributes.hasAttribute(QLatin1String("ref"))) { andre@1: QString refString = attributes.value(QLatin1String("ref")).toString(); andre@1: d->reference = CellRange(refString); andre@1: } andre@1: andre@1: QString ca = attributes.value(QLatin1String("si")).toString(); andre@1: d->ca = parseXsdBoolean(ca, false); andre@1: andre@1: if (attributes.hasAttribute(QLatin1String("si"))) andre@1: d->si = attributes.value(QLatin1String("si")).toString().toInt(); andre@1: andre@1: d->formula = reader.readElementText(); andre@1: return true; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: bool CellFormula::operator ==(const CellFormula &formula) const andre@1: { andre@1: return d->formula == formula.d->formula && d->type == formula.d->type andre@1: && d->si ==formula.d->si; andre@1: } andre@1: andre@1: /*! andre@1: * \internal andre@1: */ andre@1: bool CellFormula::operator !=(const CellFormula &formula) const andre@1: { andre@1: return d->formula != formula.d->formula || d->type != formula.d->type andre@1: || d->si !=formula.d->si; andre@1: } andre@1: andre@1: QT_END_NAMESPACE_XLSX