File indexing completed on 2024-05-12 16:35:38
0001 /* This file is part of the KDE project 0002 Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org> 0003 Copyright 1998, 1999 Torben Weis <weis@kde.org> 0004 Copyright 1999- 2006 The KSpread Team <calligra-devel@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "SheetsOdf.h" 0023 #include "SheetsOdfPrivate.h" 0024 0025 #include "Condition.h" 0026 #include "Util.h" 0027 #include "StyleManager.h" 0028 #include "ValueConverter.h" 0029 #include "ValueParser.h" 0030 0031 #include <KoGenStyles.h> 0032 #include <KoXmlNS.h> 0033 0034 // This file contains functionality to load/save a Condition 0035 0036 namespace Calligra { 0037 namespace Sheets { 0038 0039 namespace Odf { 0040 void loadCondition(QString &valExpression, Conditional &newCondition, const ValueParser *parser); 0041 void loadConditionValue(const QString &styleCondition, Conditional &newCondition, const ValueParser *parser); 0042 void loadValidationValue(const QStringList &listVal, Conditional &newCondition, const ValueParser *parser); 0043 QString saveConditionValue(const Conditional &conditionalStyle, ValueConverter *converter); 0044 } 0045 0046 void Odf::saveConditions(const Conditions *conditions, KoGenStyle ¤tCellStyle, ValueConverter *converter) 0047 { 0048 //todo fix me with kspread old format!!! 0049 if (conditions->isEmpty()) 0050 return; 0051 const QLinkedList<Conditional> list = conditions->conditionList(); 0052 QLinkedList<Conditional>::const_iterator it; 0053 int i = 0; 0054 for (it = list.begin(); it != list.end(); ++it, ++i) { 0055 Conditional conditional = *it; 0056 //<style:map style:condition="cell-content()=45" style:apply-style-name="Default" style:base-cell-address="Sheet1.E10"/> 0057 QMap<QString, QString> map; 0058 map.insert("style:condition", saveConditionValue(conditional, converter)); 0059 map.insert("style:apply-style-name", conditional.styleName); 0060 if (!conditional.baseCellAddress.isEmpty()) 0061 map.insert("style:base-cell-address", conditional.baseCellAddress); 0062 currentCellStyle.addStyleMap(map); 0063 } 0064 } 0065 0066 QString Odf::saveConditionValue(const Conditional &conditional, ValueConverter* converter) 0067 { 0068 //we can also compare text value. 0069 //todo adapt it. 0070 QString v1 = converter->asString(conditional.value1).asStringWithDoubleQuotes(); 0071 QString v2 = converter->asString(conditional.value2).asStringWithDoubleQuotes(); 0072 QString value; 0073 switch (conditional.cond) { 0074 case Conditional::None: 0075 break; 0076 case Conditional::Equal: 0077 value = "cell-content()=" + v1; 0078 break; 0079 case Conditional::Superior: 0080 value = "cell-content()>" + v1; 0081 break; 0082 case Conditional::Inferior: 0083 value = "cell-content()<" + v1; 0084 break; 0085 case Conditional::SuperiorEqual: 0086 value = "cell-content()>=" + v1; 0087 break; 0088 case Conditional::InferiorEqual: 0089 value = "cell-content()<=" + v1; 0090 break; 0091 case Conditional::Between: 0092 value = "cell-content-is-between(" + v1 + ',' + v2 + ')'; 0093 break; 0094 case Conditional::DifferentTo: 0095 value = "cell-content()!=" + v1; 0096 break; 0097 case Conditional::Different: 0098 value = "cell-content-is-not-between(" + v1 + ',' + v2 + ')'; 0099 break; 0100 case Conditional::IsTrueFormula: 0101 value = "is-true-formula(" + 0102 Odf::encodeFormula(conditional.value1.asString()) + 0103 ')'; 0104 } 0105 return value; 0106 } 0107 0108 Conditional Odf::loadCondition(Conditions *condition, const QString &conditionValue, const QString &applyStyleName, 0109 const QString& baseCellAddress, const ValueParser *parser) 0110 { 0111 //debugSheetsODF << "\tcondition:" << conditionValue; 0112 Conditional newCondition; 0113 loadConditionValue(conditionValue, newCondition, parser); 0114 if (!applyStyleName.isNull()) { 0115 //debugSheetsODF << "\tstyle:" << applyStyleName; 0116 newCondition.styleName = applyStyleName; 0117 } 0118 newCondition.baseCellAddress = baseCellAddress; 0119 condition->addCondition(newCondition); 0120 return newCondition; 0121 } 0122 0123 void Odf::loadConditions(Conditions *condition, const KoXmlElement &element, const ValueParser *parser, const StyleManager *styleManager) 0124 { 0125 debugSheetsODF << "Loading conditional styles"; 0126 KoXmlNode node(element); 0127 0128 while (!node.isNull()) { 0129 KoXmlElement elementItem = node.toElement(); 0130 if (elementItem.tagName() == "map" && elementItem.namespaceURI() == KoXmlNS::style) { 0131 QString conditionValue = elementItem.attributeNS(KoXmlNS::style, "condition", QString()); 0132 QString applyStyleName; 0133 if (elementItem.hasAttributeNS(KoXmlNS::style, "apply-style-name")) 0134 applyStyleName = elementItem.attributeNS(KoXmlNS::style, "apply-style-name", QString()); 0135 if (!applyStyleName.isEmpty() && styleManager) { 0136 QString odfStyle = styleManager->openDocumentName(applyStyleName); 0137 if (!odfStyle.isEmpty()) applyStyleName = odfStyle; 0138 } 0139 QString baseCellAddress = elementItem.attributeNS(KoXmlNS::style, "base-cell-address"); 0140 loadCondition(condition, conditionValue, applyStyleName, baseCellAddress, parser); 0141 } 0142 node = node.nextSibling(); 0143 } 0144 } 0145 0146 void Odf::loadConditionValue(const QString &styleCondition, Conditional &newCondition, const ValueParser *parser) 0147 { 0148 QString val(styleCondition); 0149 if (val.contains("cell-content()")) { 0150 val.remove("cell-content()"); 0151 loadCondition(val, newCondition, parser); 0152 } else if (val.contains("value()")) { 0153 val.remove("value()"); 0154 loadCondition(val, newCondition, parser); 0155 } 0156 0157 //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value) 0158 //for the moment we support just int/double value, not text/date/time :( 0159 if (val.contains("cell-content-is-between(")) { 0160 val.remove("cell-content-is-between("); 0161 val.remove(')'); 0162 QStringList listVal = val.split(',', QString::SkipEmptyParts); 0163 loadValidationValue(listVal, newCondition, parser); 0164 newCondition.cond = Conditional::Between; 0165 } else if (val.contains("cell-content-is-not-between(")) { 0166 val.remove("cell-content-is-not-between("); 0167 val.remove(')'); 0168 QStringList listVal = val.split(',', QString::SkipEmptyParts); 0169 loadValidationValue(listVal, newCondition, parser); 0170 newCondition.cond = Conditional::Different; 0171 } else if (val.startsWith(QLatin1String("is-true-formula("))) { 0172 val.remove(0, 16); 0173 if (val.endsWith(QLatin1Char(')'))) val.chop(1); 0174 newCondition.cond = Conditional::IsTrueFormula; 0175 newCondition.value1 = Value(Odf::decodeFormula(val)); 0176 } 0177 } 0178 0179 void Odf::loadCondition(QString &valExpression, Conditional &newCondition, const ValueParser *parser) 0180 { 0181 QString value; 0182 if (valExpression.indexOf("<=") == 0) { 0183 value = valExpression.remove(0, 2); 0184 newCondition.cond = Conditional::InferiorEqual; 0185 } else if (valExpression.indexOf(">=") == 0) { 0186 value = valExpression.remove(0, 2); 0187 newCondition.cond = Conditional::SuperiorEqual; 0188 } else if (valExpression.indexOf("!=") == 0) { 0189 //add Differentto attribute 0190 value = valExpression.remove(0, 2); 0191 newCondition.cond = Conditional::DifferentTo; 0192 } else if (valExpression.indexOf('<') == 0) { 0193 value = valExpression.remove(0, 1); 0194 newCondition.cond = Conditional::Inferior; 0195 } else if (valExpression.indexOf('>') == 0) { 0196 value = valExpression.remove(0, 1); 0197 newCondition.cond = Conditional::Superior; 0198 } else if (valExpression.indexOf('=') == 0) { 0199 value = valExpression.remove(0, 1); 0200 newCondition.cond = Conditional::Equal; 0201 } else { 0202 warnSheets << " I don't know how to parse it :" << valExpression; 0203 } 0204 //debugSheetsODF << "\tvalue:" << value; 0205 0206 if (value.length() > 1 && value[0] == '"' && value[value.length()-1] == '"') { 0207 newCondition.value1 = Value(value.mid(1, value.length()-2)); 0208 } else { 0209 newCondition.value1 = parser->parse(value); 0210 } 0211 } 0212 0213 void Odf::loadValidationValue(const QStringList &listVal, Conditional &newCondition, const ValueParser *parser) 0214 { 0215 debugSheetsODF << " listVal[0] :" << listVal[0] << " listVal[1] :" << listVal[1]; 0216 newCondition.value1 = parser->parse(listVal[0]); 0217 newCondition.value2 = parser->parse(listVal[1]); 0218 } 0219 0220 0221 0222 0223 } // Sheets 0224 } // Calligra 0225