File indexing completed on 2024-05-12 16:35:28
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998-2002 The KSpread Team <calligra-devel@kde.org> 0003 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; only 0008 version 2 of the License. 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 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 // built-in conversion functions 0022 0023 #include "ConversionModule.h" 0024 0025 #include "Function.h" 0026 #include "FunctionModuleRegistry.h" 0027 #include "ValueCalc.h" 0028 #include "ValueConverter.h" 0029 0030 #include <QByteArray> 0031 0032 using namespace Calligra::Sheets; 0033 0034 // prototypes 0035 Value func_arabic(valVector args, ValueCalc *calc, FuncExtra *); 0036 Value func_carx(valVector args, ValueCalc *calc, FuncExtra *); 0037 Value func_cary(valVector args, ValueCalc *calc, FuncExtra *); 0038 Value func_decsex(valVector args, ValueCalc *calc, FuncExtra *); 0039 Value func_polr(valVector args, ValueCalc *calc, FuncExtra *); 0040 Value func_pola(valVector args, ValueCalc *calc, FuncExtra *); 0041 Value func_roman(valVector args, ValueCalc *calc, FuncExtra *); 0042 Value func_sexdec(valVector args, ValueCalc *calc, FuncExtra *); 0043 Value func_AsciiToChar(valVector args, ValueCalc *calc, FuncExtra *); 0044 Value func_CharToAscii(valVector args, ValueCalc *calc, FuncExtra *); 0045 Value func_inttobool(valVector args, ValueCalc *calc, FuncExtra *); 0046 Value func_booltoint(valVector args, ValueCalc *calc, FuncExtra *); 0047 Value func_ToString(valVector args, ValueCalc *calc, FuncExtra *); 0048 0049 0050 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadconversionmodule.json", ConversionModule) 0051 0052 0053 ConversionModule::ConversionModule(QObject* parent, const QVariantList&) 0054 : FunctionModule(parent) 0055 { 0056 Function *f; 0057 0058 f = new Function("ARABIC", func_arabic); 0059 add(f); 0060 f = new Function("CARX", func_carx); 0061 f->setParamCount(2); 0062 add(f); 0063 f = new Function("CARY", func_cary); 0064 f->setParamCount(2); 0065 add(f); 0066 f = new Function("DECSEX", func_decsex); 0067 add(f); 0068 f = new Function("POLR", func_polr); 0069 f->setParamCount(2); 0070 add(f); 0071 f = new Function("POLA", func_pola); 0072 f->setParamCount(2); 0073 add(f); 0074 f = new Function("ROMAN", func_roman); 0075 f->setParamCount(1, 2); 0076 add(f); 0077 f = new Function("SEXDEC", func_sexdec); 0078 f->setParamCount(1, 3); 0079 add(f); 0080 f = new Function("ASCIITOCHAR", func_AsciiToChar); 0081 f->setParamCount(1, -1); 0082 f->setAcceptArray(); 0083 add(f); 0084 f = new Function("CHARTOASCII", func_CharToAscii); 0085 add(f); 0086 f = new Function("BOOL2INT", func_booltoint); 0087 add(f); 0088 f = new Function("INT2BOOL", func_inttobool); 0089 add(f); 0090 f = new Function("BOOL2STRING", func_ToString); 0091 add(f); 0092 f = new Function("NUM2STRING", func_ToString); 0093 add(f); 0094 f = new Function("STRING", func_ToString); 0095 add(f); 0096 } 0097 0098 QString ConversionModule::descriptionFileName() const 0099 { 0100 return QString("conversion.xml"); 0101 } 0102 0103 0104 // Function: POLR 0105 Value func_polr(valVector args, ValueCalc *calc, FuncExtra *) 0106 { 0107 // sqrt (a^2 + b^2) 0108 Value a = args[0]; 0109 Value b = args[1]; 0110 Value res = calc->sqrt(calc->add(calc->sqr(a), calc->sqr(b))); 0111 return res; 0112 } 0113 0114 // Function: POLA 0115 Value func_pola(valVector args, ValueCalc *calc, FuncExtra *) 0116 { 0117 // acos (a / polr(a,b)) 0118 Value polr = func_polr(args, calc, 0); 0119 if (calc->isZero(polr)) 0120 return Value::errorDIV0(); 0121 Value res = calc->acos(calc->div(args[0], polr)); 0122 return res; 0123 } 0124 0125 // Function: CARX 0126 Value func_carx(valVector args, ValueCalc *calc, FuncExtra *) 0127 { 0128 // a * cos(b) 0129 Value res = calc->mul(args[0], calc->cos(args[1])); 0130 return res; 0131 } 0132 0133 // Function: CARY 0134 Value func_cary(valVector args, ValueCalc *calc, FuncExtra *) 0135 { 0136 // a * sin(b) 0137 Value res = calc->mul(args[0], calc->sin(args[1])); 0138 return res; 0139 } 0140 0141 // Function: DECSEX 0142 Value func_decsex(valVector args, ValueCalc *calc, FuncExtra *) 0143 { 0144 // original function was very complicated, but I see no reason for that, 0145 // when it can be done as simply as this ... 0146 // maybe it was due to all the infrastructure not being ready back then 0147 return calc->conv()->asTime(calc->div(args[0], 24)); 0148 } 0149 0150 // Function: SEXDEC 0151 Value func_sexdec(valVector args, ValueCalc *calc, FuncExtra *) 0152 { 0153 if (args.count() == 1) { 0154 // convert given value to number 0155 Value time = calc->conv()->asTime(args[0]); 0156 return calc->mul(calc->conv()->asFloat(time), 24); 0157 } 0158 0159 // convert h/m/s to number of hours 0160 Value h = args[0]; 0161 Value m = args[1]; 0162 0163 Value res = calc->add(h, calc->div(m, 60)); 0164 if (args.count() == 3) { 0165 Value s = args[2]; 0166 res = calc->add(res, calc->div(s, 3600)); 0167 } 0168 return res; 0169 } 0170 0171 // Function: ROMAN 0172 Value func_roman(valVector args, ValueCalc *calc, FuncExtra *) 0173 { 0174 static const QString RNUnits[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; 0175 static const QString RNTens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; 0176 static const QString RNHundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; 0177 static const QString RNThousands[] = {"", "M", "MM", "MMM"}; 0178 0179 // precision loss is not a problem here, as we only use the 0-3999 range 0180 qint64 value = calc->conv()->asInteger(args[0]).asInteger(); 0181 if ((value < 0) || (value > 3999)) { 0182 return Value::errorNA(); 0183 } 0184 0185 // There is an optional argument, but the specification only covers the case 0186 // where it is zero for conciseness, and zero is the default. So we just 0187 // ignore it. 0188 QString result = RNThousands[(value / 1000)] + 0189 RNHundreds[(value / 100) % 10] + 0190 RNTens[(value / 10) % 10] + 0191 RNUnits[(value) % 10]; 0192 return Value(result); 0193 } 0194 0195 // convert single roman character to decimal 0196 // return < 0 if invalid 0197 int func_arabic_helper(QChar c) 0198 { 0199 switch (c.toUpper().unicode()) { 0200 case 'M': return 1000; 0201 case 'D': return 500; 0202 case 'C': return 100; 0203 case 'L': return 50; 0204 case 'X': return 10; 0205 case 'V': return 5; 0206 case 'I': return 1; 0207 } 0208 return -1; 0209 } 0210 0211 // Function: ARABIC 0212 Value func_arabic(valVector args, ValueCalc *calc, FuncExtra *) 0213 { 0214 QString roman = calc->conv()->asString(args[0]).asString(); 0215 if (roman.isEmpty()) return Value::errorVALUE(); 0216 0217 int val = 0, lastd = 0, d = 0; 0218 0219 for (int i = 0; i < roman.length(); i++) { 0220 d = func_arabic_helper(roman[i]); 0221 if (d < 0) return Value::errorVALUE(); 0222 0223 if (lastd < d) val -= lastd; 0224 else val += lastd; 0225 lastd = d; 0226 } 0227 if (lastd < d) val -= lastd; 0228 else val += lastd; 0229 0230 return Value(val); 0231 } 0232 0233 // helper for AsciiToChar 0234 void func_a2c_helper(ValueCalc *calc, QString &s, Value val) 0235 { 0236 if (val.isArray()) { 0237 for (uint row = 0; row < val.rows(); ++row) 0238 for (uint col = 0; col < val.columns(); ++col) 0239 func_a2c_helper(calc, s, val.element(col, row)); 0240 } else { 0241 int v = calc->conv()->asInteger(val).asInteger(); 0242 if (v == 0) return; 0243 QChar c(v); 0244 s = s + c; 0245 } 0246 } 0247 0248 // Function: AsciiToChar 0249 Value func_AsciiToChar(valVector args, ValueCalc *calc, FuncExtra *) 0250 { 0251 QString str; 0252 for (int i = 0; i < args.count(); i++) 0253 func_a2c_helper(calc, str, args[i]); 0254 return Value(str); 0255 } 0256 0257 // Function: CharToAscii 0258 Value func_CharToAscii(valVector args, ValueCalc *calc, FuncExtra *) 0259 { 0260 QString val = calc->conv()->asString(args[0]).asString(); 0261 if (val.length() == 1) 0262 return Value(QString(val[0])); 0263 return Value::errorVALUE(); 0264 } 0265 0266 // Function: inttobool 0267 Value func_inttobool(valVector args, ValueCalc *calc, FuncExtra *) 0268 { 0269 return calc->conv()->asBoolean(args[0]); 0270 } 0271 0272 // Function: booltoint 0273 Value func_booltoint(valVector args, ValueCalc *calc, FuncExtra *) 0274 { 0275 return calc->conv()->asInteger(args[0]); 0276 } 0277 0278 // Function: BoolToString, NumberToString, String 0279 Value func_ToString(valVector args, ValueCalc *calc, FuncExtra *) 0280 { 0281 return calc->conv()->asString(args[0]); 0282 } 0283 0284 #include "conversion.moc"