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 }