1/* This file is part of the KDE project
2 Copyright 2004 Tomas Mecir <mecirt@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20// Local
21#include "ValueConverter.h"
22
23#include "CalculationSettings.h"
24#include "Localization.h"
25#include "ValueParser.h"
26
27using namespace Calligra::Sheets;
28
29ValueConverter::ValueConverter(const ValueParser* parser)
30 : m_parser(parser)
31{
32}
33
34const CalculationSettings* ValueConverter::settings() const
35{
36 return m_parser->settings();
37}
38
39Value ValueConverter::asBoolean(const Value &value, bool* ok) const
40{
41 Value val;
42
43 if (ok)
44 *ok = true;
45 bool okay = true;
46
47 switch (value.type()) {
48 case Value::Empty:
49 val = Value(false);
50 break;
51 case Value::Boolean:
52 val = value;
53 break;
54 case Value::Integer:
55 val = Value(value.asInteger() ? true : false);
56 break;
57 case Value::Float:
58 val = Value((value.asFloat() == 0.0) ? false : true);
59 break;
60 case Value::Complex:
61 val = Value((value.asComplex().real() == complex<Number>(0.0, 0.0)) ? false : true);
62 break;
63 case Value::String:
64 val = m_parser->tryParseBool(value.asString(), &okay);
65 if (!okay)
66 val = Value(false);
67 if (ok)
68 *ok = okay;
69 break;
70 case Value::Array:
71 val = asBoolean(value.element(0, 0));
72 break;
73 case Value::CellRange:
74 /* NOTHING */
75 break;
76 case Value::Error:
77 val = Value(false);
78 break;
79 };
80
81 return val;
82}
83
84Value ValueConverter::asInteger(const Value &value, bool* ok) const
85{
86 Value val;
87
88 if (ok)
89 *ok = true;
90
91 switch (value.type()) {
92 case Value::Empty:
93 val = Value(0);
94 break;
95 case Value::Boolean:
96 val = Value(value.asBoolean() ? 1 : 0);
97 break;
98 case Value::Integer:
99 val = value;
100 break;
101 case Value::Float:
102 val = Value(value.asInteger());
103 break;
104 case Value::Complex:
105 val = Value(value.asInteger());
106 break;
107 case Value::String:
108 val = m_parser->parse(value.asString());
109 if (!val.isNumber()) {
110 val = Value(0);
111 if (ok)
112 *ok = false;
113 }
114 val = Value(val.asInteger());
115 break;
116 case Value::Array:
117 val = asInteger(value.element(0, 0));
118 break;
119 case Value::CellRange:
120 /* NOTHING */
121 break;
122 case Value::Error:
123 val = Value(0);
124 break;
125 };
126
127 return val;
128}
129
130Value ValueConverter::asFloat(const Value &value, bool* ok) const
131{
132 Value val;
133
134 if (ok)
135 *ok = true;
136
137 switch (value.type()) {
138 case Value::Empty:
139 val = Value(0.0);
140 break;
141 case Value::Boolean:
142 val = Value(value.asBoolean() ? 1.0 : 0.0);
143 break;
144 case Value::Integer:
145 val = Value(value.asFloat());
146 break;
147 case Value::Float:
148 val = value;
149 break;
150 case Value::Complex:
151 val = Value(value.asFloat());
152 break;
153 case Value::String:
154 val = m_parser->parse(value.asString());
155 if (!val.isNumber()) {
156 val = Value(0.0);
157 if (ok)
158 *ok = false;
159 }
160 val = Value(val.asFloat());
161 break;
162 case Value::Array:
163 val = asFloat(value.element(0, 0));
164 break;
165 case Value::CellRange:
166 /* NOTHING */
167 break;
168 case Value::Error:
169 val = Value(0.0);
170 break;
171 };
172
173 return val;
174}
175
176Value ValueConverter::asComplex(const Value &value, bool* ok) const
177{
178 Value val;
179
180 if (ok)
181 *ok = true;
182
183 switch (value.type()) {
184 case Value::Empty:
185 val = Value(complex<Number>(0.0, 0.0));
186 break;
187 case Value::Boolean:
188 val = Value(complex<Number>(value.asBoolean() ? 1.0 : 0.0, 0.0));
189 break;
190 case Value::Integer:
191 case Value::Float:
192 val = Value(complex<Number>(value.asFloat(), 0.0));
193 break;
194 case Value::Complex:
195 val = value;
196 break;
197 case Value::String:
198 val = m_parser->parse(value.asString());
199 if (!val.isNumber()) {
200 val = Value(complex<Number>(0.0, 0.0));
201 if (ok)
202 *ok = false;
203 }
204 val = Value(val.asComplex());
205 break;
206 case Value::Array:
207 val = asComplex(value.element(0, 0));
208 break;
209 case Value::CellRange:
210 /* NOTHING */
211 break;
212 case Value::Error:
213 val = Value(complex<Number>(0.0, 0.0));
214 break;
215 };
216
217 return val;
218}
219
220Value ValueConverter::asNumeric(const Value &value, bool* ok) const
221{
222 Value val;
223
224 if (ok)
225 *ok = true;
226
227 switch (value.type()) {
228 case Value::Empty:
229 val = Value(0.0);
230 break;
231 case Value::Boolean:
232 val = Value(value.asBoolean() ? 1.0 : 0.0);
233 break;
234 case Value::Integer:
235 case Value::Float:
236 case Value::Complex:
237 val = value;
238 break;
239 case Value::String:
240 val = m_parser->parse(value.asString());
241 if (!val.isNumber()) {
242 val = Value(0.0);
243 if (ok)
244 *ok = false;
245 }
246 break;
247 case Value::Array:
248 val = asNumeric(value.element(0, 0));
249 break;
250 case Value::CellRange:
251 /* NOTHING */
252 break;
253 case Value::Error:
254 val = Value(0.0);
255 break;
256 };
257
258 return val;
259}
260
261Value ValueConverter::asString(const Value &value) const
262{
263 // This is a simpler version of ValueFormatter... We cannot use that one,
264 // as we sometimes want to generate the string differently ...
265
266 Value val;
267 QString s;
268 Value::Format fmt;
269 int pos;
270 switch (value.type()) {
271 case Value::Empty:
272 val = Value(QString());
273 break;
274 case Value::Boolean:
275 val = Value(value.asBoolean() ? ki18n("True").toString(m_parser->settings()->locale()) :
276 ki18n("False").toString(m_parser->settings()->locale()));
277 break;
278 case Value::Integer: {
279 fmt = value.format();
280 if (fmt == Value::fmt_Percent)
281 val = Value(QString::number(value.asInteger() * 100) + " %");
282 else if (fmt == Value::fmt_DateTime)
283 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings())));
284 else if (fmt == Value::fmt_Date)
285 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings())));
286 else if (fmt == Value::fmt_Time)
287 val = Value(m_parser->settings()->locale()->formatTime(value.asTime(settings())));
288 else
289 val = Value(QString::number(value.asInteger()));
290 }
291 break;
292 case Value::Float:
293 fmt = value.format();
294 if (fmt == Value::fmt_DateTime)
295 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings())));
296 else if (fmt == Value::fmt_Date)
297 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings()), KLocale::ShortDate));
298 else if (fmt == Value::fmt_Time)
299 val = Value(m_parser->settings()->locale()->formatTime(value.asTime(settings())));
300 else {
301 //convert the number, change decimal point from English to local
302 s = QString::number(numToDouble(value.asFloat()), 'g', 10);
303 const QString decimalSymbol = m_parser->settings()->locale()->decimalSymbol();
304 if (!decimalSymbol.isNull() && ((pos = s.indexOf('.')) != -1))
305 s.replace(pos, 1, decimalSymbol);
306 if (fmt == Value::fmt_Percent)
307 s += " %";
308 val = Value(s);
309 }
310 break;
311 case Value::Complex:
312 fmt = value.format();
313 if (fmt == Value::fmt_DateTime)
314 val = Value(m_parser->settings()->locale()->formatDateTime(value.asDateTime(settings())));
315 else if (fmt == Value::fmt_Date)
316 val = Value(m_parser->settings()->locale()->formatDate(value.asDate(settings()), KLocale::ShortDate));
317 else if (fmt == Value::fmt_Time)
318 val = Value(m_parser->settings()->locale()->formatTime(value.asTime(settings())));
319 else {
320 //convert the number, change decimal point from English to local
321 const QString decimalSymbol = m_parser->settings()->locale()->decimalSymbol();
322 QString real = QString::number(numToDouble(value.asComplex().real()), 'g', 10);
323 if (!decimalSymbol.isNull() && ((pos = real.indexOf('.')) != -1))
324 real.replace(pos, 1, decimalSymbol);
325 QString imag = QString::number(numToDouble(value.asComplex().imag()), 'g', 10);
326 if (!decimalSymbol.isNull() && ((pos = imag.indexOf('.')) != -1))
327 imag.replace(pos, 1, decimalSymbol);
328 s = real;
329 if (value.asComplex().imag() >= 0.0)
330 s += '+';
331 // TODO Stefan: Some prefer 'j'. Configure option? Spec?
332 s += imag + 'i';
333 // NOTE Stefan: Never recognized a complex percentage anywhere. ;-)
334// if (fmt == Value::fmt_Percent)
335// s += " %";
336 val = Value(s);
337 }
338 break;
339 case Value::String:
340 val = value;
341 break;
342 case Value::Array:
343 val = Value(asString(value.element(0, 0)));
344 break;
345 case Value::CellRange:
346 /* NOTHING */
347 break;
348 case Value::Error:
349 val = Value(value.errorMessage());
350 break;
351 };
352
353 return val;
354}
355
356Value ValueConverter::asDateTime(const Value &value, bool* ok) const
357{
358 Value val;
359
360 if (ok)
361 *ok = true;
362 bool okay = true;
363
364 switch (value.type()) {
365 case Value::Empty:
366 val = Value(QDateTime::currentDateTime(), settings());
367 break;
368 case Value::Boolean:
369 //ignore the bool value... any better idea? ;)
370 val = Value(QDateTime::currentDateTime(), settings());
371 break;
372 case Value::Integer:
373 case Value::Float:
374 case Value::Complex:
375 val = Value(value.asFloat());
376 val.setFormat(Value::fmt_DateTime);
377 break;
378 case Value::String:
379 //no DateTime m_parser, so we parse as Date, hoping for the best ...
380 val = m_parser->tryParseDate(value.asString(), &okay);
381 if (!okay)
382 val = Value::errorVALUE();
383 if (ok)
384 *ok = okay;
385 val.setFormat(Value::fmt_DateTime);
386 break;
387 case Value::Array:
388 val = asDateTime(value.element(0, 0));
389 break;
390 case Value::CellRange:
391 /* NOTHING */
392 break;
393 case Value::Error:
394 break;
395 };
396
397 return val;
398}
399
400Value ValueConverter::asDate(const Value &value, bool* ok) const
401{
402 Value val;
403
404 if (ok)
405 *ok = true;
406 bool okay = true;
407
408 switch (value.type()) {
409 case Value::Empty:
410 val = Value(QDate::currentDate(), settings());
411 break;
412 case Value::Boolean:
413 //ignore the bool value... any better idea? ;)
414 val = Value(QDate::currentDate(), settings());
415 break;
416 case Value::Integer:
417 case Value::Float:
418 case Value::Complex:
419 val = Value(value.asFloat());
420 val.setFormat(Value::fmt_Date);
421 break;
422 case Value::String:
423 val = m_parser->tryParseDate(value.asString(), &okay);
424 if (!okay)
425 val = Value::errorVALUE();
426 if (ok)
427 *ok = okay;
428 break;
429 case Value::Array:
430 val = asDate(value.element(0, 0));
431 break;
432 case Value::CellRange:
433 /* NOTHING */
434 break;
435 case Value::Error:
436 break;
437 };
438
439 return val;
440}
441
442Value ValueConverter::asTime(const Value &value, bool* ok) const
443{
444 Value val;
445
446 if (ok)
447 *ok = true;
448 bool okay = true;
449
450 switch (value.type()) {
451 case Value::Empty:
452 val = Value(QTime::currentTime(), settings());
453 break;
454 case Value::Boolean:
455 //ignore the bool value... any better idea? ;)
456 val = Value(QTime::currentTime(), settings());
457 break;
458 case Value::Integer:
459 case Value::Float:
460 case Value::Complex:
461 val = Value(value.asFloat());
462 val.setFormat(Value::fmt_Time);
463 break;
464 case Value::String:
465 val = m_parser->tryParseTime(value.asString(), &okay);
466 if (!okay)
467 val = Value::errorVALUE();
468 if (ok)
469 *ok = okay;
470 break;
471 case Value::Array:
472 val = asTime(value.element(0, 0));
473 break;
474 case Value::CellRange:
475 /* NOTHING */
476 break;
477 case Value::Error:
478 break;
479 };
480
481 return val;
482}
483
484bool ValueConverter::toBoolean(const Value& value) const
485{
486 return asBoolean(value).asBoolean();
487}
488
489int ValueConverter::toInteger(const Value& value) const
490{
491 return asInteger(value).asInteger();
492}
493
494Number ValueConverter::toFloat(const Value& value) const
495{
496 return asFloat(value).asFloat();
497}
498
499complex<Number> ValueConverter::toComplex(const Value& value) const
500{
501 return asComplex(value).asComplex();
502}
503
504QString ValueConverter::toString(const Value& value) const
505{
506 return asString(value).asString();
507}
508
509QDateTime ValueConverter::toDateTime(const Value& value) const
510{
511 return asDateTime(value).asDateTime(settings());
512}
513
514QDate ValueConverter::toDate(const Value& value) const
515{
516 return asDate(value).asDate(settings());
517}
518
519QTime ValueConverter::toTime(const Value& value) const
520{
521 return asTime(value).asTime(settings());
522}
523