File indexing completed on 2024-04-28 16:21:38
0001 /* This file is part of the KDE project 0002 Copyright 2004 Tomas Mecir <mecirt@gmail.com> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 // Local 0021 #include "ValueConverter.h" 0022 0023 #include "CalculationSettings.h" 0024 #include "Localization.h" 0025 #include "ValueParser.h" 0026 0027 using namespace Calligra::Sheets; 0028 0029 ValueConverter::ValueConverter(const ValueParser* parser) 0030 : m_parser(parser) 0031 { 0032 } 0033 0034 const CalculationSettings* ValueConverter::settings() const 0035 { 0036 return m_parser->settings(); 0037 } 0038 0039 Value ValueConverter::asBoolean(const Value &value, bool* ok) const 0040 { 0041 Value val; 0042 0043 if (ok) 0044 *ok = true; 0045 bool okay = true; 0046 0047 switch (value.type()) { 0048 case Value::Empty: 0049 val = Value(false); 0050 break; 0051 case Value::Boolean: 0052 val = value; 0053 break; 0054 case Value::Integer: 0055 val = Value(value.asInteger() ? true : false); 0056 break; 0057 case Value::Float: 0058 val = Value((value.asFloat() == 0.0) ? false : true); 0059 break; 0060 case Value::Complex: 0061 val = Value((value.asComplex().real() == complex<Number>(0.0, 0.0)) ? false : true); 0062 break; 0063 case Value::String: 0064 val = m_parser->tryParseBool(value.asString(), &okay); 0065 if (!okay) 0066 val = Value(false); 0067 if (ok) 0068 *ok = okay; 0069 break; 0070 case Value::Array: 0071 val = asBoolean(value.element(0, 0)); 0072 break; 0073 case Value::CellRange: 0074 /* NOTHING */ 0075 break; 0076 case Value::Error: 0077 val = Value(false); 0078 break; 0079 }; 0080 0081 return val; 0082 } 0083 0084 Value ValueConverter::asInteger(const Value &value, bool* ok) const 0085 { 0086 Value val; 0087 0088 if (ok) 0089 *ok = true; 0090 0091 switch (value.type()) { 0092 case Value::Empty: 0093 val = Value(0); 0094 break; 0095 case Value::Boolean: 0096 val = Value(value.asBoolean() ? 1 : 0); 0097 break; 0098 case Value::Integer: 0099 val = value; 0100 break; 0101 case Value::Float: 0102 val = Value(value.asInteger()); 0103 break; 0104 case Value::Complex: 0105 val = Value(value.asInteger()); 0106 break; 0107 case Value::String: 0108 val = m_parser->parse(value.asString()); 0109 if (!val.isNumber()) { 0110 val = Value(0); 0111 if (ok) 0112 *ok = false; 0113 } 0114 val = Value(val.asInteger()); 0115 break; 0116 case Value::Array: 0117 val = asInteger(value.element(0, 0)); 0118 break; 0119 case Value::CellRange: 0120 /* NOTHING */ 0121 break; 0122 case Value::Error: 0123 val = Value(0); 0124 break; 0125 }; 0126 0127 return val; 0128 } 0129 0130 Value ValueConverter::asFloat(const Value &value, bool* ok) const 0131 { 0132 Value val; 0133 0134 if (ok) 0135 *ok = true; 0136 0137 switch (value.type()) { 0138 case Value::Empty: 0139 val = Value(0.0); 0140 break; 0141 case Value::Boolean: 0142 val = Value(value.asBoolean() ? 1.0 : 0.0); 0143 break; 0144 case Value::Integer: 0145 val = Value(value.asFloat()); 0146 break; 0147 case Value::Float: 0148 val = value; 0149 break; 0150 case Value::Complex: 0151 val = Value(value.asFloat()); 0152 break; 0153 case Value::String: 0154 val = m_parser->parse(value.asString()); 0155 if (!val.isNumber()) { 0156 val = Value(0.0); 0157 if (ok) 0158 *ok = false; 0159 } 0160 val = Value(val.asFloat()); 0161 break; 0162 case Value::Array: 0163 val = asFloat(value.element(0, 0)); 0164 break; 0165 case Value::CellRange: 0166 /* NOTHING */ 0167 break; 0168 case Value::Error: 0169 val = Value(0.0); 0170 break; 0171 }; 0172 0173 return val; 0174 } 0175 0176 Value ValueConverter::asComplex(const Value &value, bool* ok) const 0177 { 0178 Value val; 0179 0180 if (ok) 0181 *ok = true; 0182 0183 switch (value.type()) { 0184 case Value::Empty: 0185 val = Value(complex<Number>(0.0, 0.0)); 0186 break; 0187 case Value::Boolean: 0188 val = Value(complex<Number>(value.asBoolean() ? 1.0 : 0.0, 0.0)); 0189 break; 0190 case Value::Integer: 0191 case Value::Float: 0192 val = Value(complex<Number>(value.asFloat(), 0.0)); 0193 break; 0194 case Value::Complex: 0195 val = value; 0196 break; 0197 case Value::String: 0198 val = m_parser->parse(value.asString()); 0199 if (!val.isNumber()) { 0200 val = Value(complex<Number>(0.0, 0.0)); 0201 if (ok) 0202 *ok = false; 0203 } 0204 val = Value(val.asComplex()); 0205 break; 0206 case Value::Array: 0207 val = asComplex(value.element(0, 0)); 0208 break; 0209 case Value::CellRange: 0210 /* NOTHING */ 0211 break; 0212 case Value::Error: 0213 val = Value(complex<Number>(0.0, 0.0)); 0214 break; 0215 }; 0216 0217 return val; 0218 } 0219 0220 Value ValueConverter::asNumeric(const Value &value, bool* ok) const 0221 { 0222 Value val; 0223 0224 if (ok) 0225 *ok = true; 0226 0227 switch (value.type()) { 0228 case Value::Empty: 0229 val = Value(0.0); 0230 break; 0231 case Value::Boolean: 0232 val = Value(value.asBoolean() ? 1.0 : 0.0); 0233 break; 0234 case Value::Integer: 0235 case Value::Float: 0236 case Value::Complex: 0237 val = value; 0238 break; 0239 case Value::String: 0240 val = m_parser->parse(value.asString()); 0241 if (!val.isNumber()) { 0242 val = Value(0.0); 0243 if (ok) 0244 *ok = false; 0245 } 0246 break; 0247 case Value::Array: 0248 val = asNumeric(value.element(0, 0)); 0249 break; 0250 case Value::CellRange: 0251 /* NOTHING */ 0252 break; 0253 case Value::Error: 0254 val = Value(0.0); 0255 break; 0256 }; 0257 0258 return val; 0259 } 0260 0261 Value ValueConverter::asString(const Value &value) const 0262 { 0263 // This is a simpler version of ValueFormatter... We cannot use that one, 0264 // as we sometimes want to generate the string differently ... 0265 0266 Value val; 0267 QString s; 0268 Value::Format fmt; 0269 int pos; 0270 switch (value.type()) { 0271 case Value::Empty: 0272 val = Value(QString()); 0273 break; 0274 case Value::Boolean: { 0275 const QStringList localeCodes(m_parser->settings()->locale()->country()); 0276 val = Value(value.asBoolean() ? ki18n("True").toString(localeCodes) : 0277 ki18n("False").toString(localeCodes)); 0278 break; 0279 } 0280 case Value::Integer: { 0281 fmt = value.format(); 0282 if (fmt == Value::fmt_Percent) 0283 val = Value(QString::number(value.asInteger() * 100) + " %"); 0284 else if (fmt == Value::fmt_DateTime) 0285 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings()))); 0286 else if (fmt == Value::fmt_Date) 0287 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings()))); 0288 else if (fmt == Value::fmt_Time) 0289 val = Value(m_parser->settings()->locale()->formatTime(value.asTime())); 0290 else 0291 val = Value(QString::number(value.asInteger())); 0292 } 0293 break; 0294 case Value::Float: 0295 fmt = value.format(); 0296 if (fmt == Value::fmt_DateTime) 0297 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings()))); 0298 else if (fmt == Value::fmt_Date) 0299 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings()), KLocale::ShortDate)); 0300 else if (fmt == Value::fmt_Time) 0301 val = Value(m_parser->settings()->locale()->formatTime(value.asTime())); 0302 else { 0303 //convert the number, change decimal point from English to local 0304 s = QString::number(numToDouble(value.asFloat()), 'g', 10); 0305 const QString decimalSymbol = m_parser->settings()->locale()->decimalSymbol(); 0306 if (!decimalSymbol.isNull() && ((pos = s.indexOf('.')) != -1)) 0307 s.replace(pos, 1, decimalSymbol); 0308 if (fmt == Value::fmt_Percent) 0309 s += " %"; 0310 val = Value(s); 0311 } 0312 break; 0313 case Value::Complex: 0314 fmt = value.format(); 0315 if (fmt == Value::fmt_DateTime) 0316 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings()))); 0317 else if (fmt == Value::fmt_Date) 0318 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings()), KLocale::ShortDate)); 0319 else if (fmt == Value::fmt_Time) 0320 val = Value(m_parser->settings()->locale()->formatTime(value.asTime())); 0321 else { 0322 //convert the number, change decimal point from English to local 0323 const QString decimalSymbol = m_parser->settings()->locale()->decimalSymbol(); 0324 QString real = QString::number(numToDouble(value.asComplex().real()), 'g', 10); 0325 if (!decimalSymbol.isNull() && ((pos = real.indexOf('.')) != -1)) 0326 real.replace(pos, 1, decimalSymbol); 0327 QString imag = QString::number(numToDouble(value.asComplex().imag()), 'g', 10); 0328 if (!decimalSymbol.isNull() && ((pos = imag.indexOf('.')) != -1)) 0329 imag.replace(pos, 1, decimalSymbol); 0330 s = real; 0331 if (value.asComplex().imag() >= 0.0) 0332 s += '+'; 0333 // TODO Stefan: Some prefer 'j'. Configure option? Spec? 0334 s += imag + 'i'; 0335 // NOTE Stefan: Never recognized a complex percentage anywhere. ;-) 0336 // if (fmt == Value::fmt_Percent) 0337 // s += " %"; 0338 val = Value(s); 0339 } 0340 break; 0341 case Value::String: 0342 val = value; 0343 break; 0344 case Value::Array: 0345 val = Value(asString(value.element(0, 0))); 0346 break; 0347 case Value::CellRange: 0348 /* NOTHING */ 0349 break; 0350 case Value::Error: 0351 val = Value(value.errorMessage()); 0352 break; 0353 }; 0354 0355 return val; 0356 } 0357 0358 Value ValueConverter::asDateTime(const Value &value, bool* ok) const 0359 { 0360 Value val; 0361 0362 if (ok) 0363 *ok = true; 0364 bool okay = true; 0365 0366 switch (value.type()) { 0367 case Value::Empty: 0368 val = Value(QDateTime::currentDateTime(), settings()); 0369 break; 0370 case Value::Boolean: 0371 //ignore the bool value... any better idea? ;) 0372 val = Value(QDateTime::currentDateTime(), settings()); 0373 break; 0374 case Value::Integer: 0375 case Value::Float: 0376 case Value::Complex: 0377 val = Value(value.asFloat()); 0378 val.setFormat(Value::fmt_DateTime); 0379 break; 0380 case Value::String: 0381 //no DateTime m_parser, so we parse as Date, hoping for the best ... 0382 val = m_parser->tryParseDate(value.asString(), &okay); 0383 if (!okay) 0384 val = Value::errorVALUE(); 0385 if (ok) 0386 *ok = okay; 0387 val.setFormat(Value::fmt_DateTime); 0388 break; 0389 case Value::Array: 0390 val = asDateTime(value.element(0, 0)); 0391 break; 0392 case Value::CellRange: 0393 /* NOTHING */ 0394 break; 0395 case Value::Error: 0396 break; 0397 }; 0398 0399 return val; 0400 } 0401 0402 Value ValueConverter::asDate(const Value &value, bool* ok) const 0403 { 0404 Value val; 0405 0406 if (ok) 0407 *ok = true; 0408 bool okay = true; 0409 0410 switch (value.type()) { 0411 case Value::Empty: 0412 val = Value(QDate::currentDate(), settings()); 0413 break; 0414 case Value::Boolean: 0415 //ignore the bool value... any better idea? ;) 0416 val = Value(QDate::currentDate(), settings()); 0417 break; 0418 case Value::Integer: 0419 case Value::Float: 0420 case Value::Complex: 0421 val = Value(value.asFloat()); 0422 val.setFormat(Value::fmt_Date); 0423 break; 0424 case Value::String: 0425 val = m_parser->tryParseDate(value.asString(), &okay); 0426 if (!okay) 0427 val = Value::errorVALUE(); 0428 if (ok) 0429 *ok = okay; 0430 break; 0431 case Value::Array: 0432 val = asDate(value.element(0, 0)); 0433 break; 0434 case Value::CellRange: 0435 /* NOTHING */ 0436 break; 0437 case Value::Error: 0438 break; 0439 }; 0440 0441 return val; 0442 } 0443 0444 Value ValueConverter::asTime(const Value &value, bool* ok) const 0445 { 0446 Value val; 0447 0448 if (ok) 0449 *ok = true; 0450 bool okay = true; 0451 0452 switch (value.type()) { 0453 case Value::Empty: 0454 val = Value(QTime::currentTime()); 0455 break; 0456 case Value::Boolean: 0457 //ignore the bool value... any better idea? ;) 0458 val = Value(QTime::currentTime()); 0459 break; 0460 case Value::Integer: 0461 case Value::Float: 0462 case Value::Complex: 0463 val = Value(value.asFloat()); 0464 val.setFormat(Value::fmt_Time); 0465 break; 0466 case Value::String: 0467 val = m_parser->tryParseTime(value.asString(), &okay); 0468 if (!okay) 0469 val = Value::errorVALUE(); 0470 if (ok) 0471 *ok = okay; 0472 break; 0473 case Value::Array: 0474 val = asTime(value.element(0, 0)); 0475 break; 0476 case Value::CellRange: 0477 /* NOTHING */ 0478 break; 0479 case Value::Error: 0480 break; 0481 }; 0482 0483 return val; 0484 } 0485 0486 bool ValueConverter::toBoolean(const Value& value) const 0487 { 0488 return asBoolean(value).asBoolean(); 0489 } 0490 0491 int ValueConverter::toInteger(const Value& value) const 0492 { 0493 return asInteger(value).asInteger(); 0494 } 0495 0496 Number ValueConverter::toFloat(const Value& value) const 0497 { 0498 return asFloat(value).asFloat(); 0499 } 0500 0501 complex<Number> ValueConverter::toComplex(const Value& value) const 0502 { 0503 return asComplex(value).asComplex(); 0504 } 0505 0506 QString ValueConverter::toString(const Value& value) const 0507 { 0508 return asString(value).asString(); 0509 } 0510 0511 QDateTime ValueConverter::toDateTime(const Value& value) const 0512 { 0513 return asDateTime(value).asDateTime(settings()); 0514 } 0515 0516 QDate ValueConverter::toDate(const Value& value) const 0517 { 0518 return asDate(value).asDate(settings()); 0519 } 0520 0521 QTime ValueConverter::toTime(const Value& value) const 0522 { 0523 return asTime(value).asTime(); 0524 }