1/* This file is part of the KDE project
2 Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
3 Copyright 2003,2004 Ariya Hidayat <ariya@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; only
8 version 2 of the License.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "Value.h"
22#include "CalculationSettings.h"
23#include "CellStorage.h"
24#include "ValueStorage.h"
25
26#include <kdebug.h>
27#include <klocale.h>
28
29#include <QString>
30#include <QTextStream>
31
32#include <float.h>
33#include <math.h>
34#include <limits.h>
35
36using namespace Calligra::Sheets;
37
38class ValueArray
39{
40public:
41 ValueArray() : m_size(0, 0) {}
42 ValueArray(const ValueStorage& storage, const QSize& size) : m_size(size), m_storage(storage) {}
43
44 ValueStorage& storage() { return m_storage; }
45 int rows() const { return qMax(m_size.height(), m_storage.rows()); }
46 int columns() const { return qMax(m_size.width(), m_storage.columns()); }
47
48 bool operator==(const ValueArray& a) const { return rows() == a.rows() && columns() == a.columns() && m_storage == a.m_storage; }
49private:
50 QSize m_size;
51 ValueStorage m_storage;
52};
53
54class Value::Private : public QSharedData
55{
56public:
57
58 Value::Type type: 4;
59 Value::Format format: 4;
60
61 union { // 64 bits at max!
62 // b is also secondarily used to indicate a null value if type == Empty,
63 // without using up space for an explicit member variable.
64 bool b;
65 qint64 i;
66 Number f;
67 complex<Number>* pc;
68 QString* ps;
69 ValueArray* pa;
70 };
71
72 // create empty data
73 Private() : type(Value::Empty), format(Value::fmt_None), ps(0) {}
74
75 Private(const Private& o)
76 : QSharedData(o)
77 , type(o.type)
78 , format(o.format) {
79 switch (type) {
80 case Value::Empty:
81 default:
82 ps = 0;
83 break;
84 case Value::Boolean:
85 b = o.b;
86 break;
87 case Value::Integer:
88 i = o.i;
89 break;
90 case Value::Float:
91 f = o.f;
92 break;
93 case Value::Complex:
94 pc = new complex<Number>(*o.pc);
95 break;
96 case Value::String:
97 case Value::Error:
98 ps = new QString(*o.ps);
99 break;
100 case Value::Array:
101 pa = new ValueArray(*o.pa);
102 break;
103 }
104 }
105
106 // destroys data
107 ~Private() {
108 if (this == s_null)
109 s_null = 0;
110 clear();
111 }
112
113 // static empty data to be shared
114 static Private* null() {
115 if (!s_null) s_null = new Private; return s_null;
116 }
117
118 // true if it's null (which is shared)
119 bool isNull() {
120 return this == s_null;
121 }
122
123 /** Deletes all data. */
124 void clear() {
125 if (type == Value::Array) delete pa;
126 if (type == Value::Complex) delete pc;
127 if (type == Value::Error) delete ps;
128 if (type == Value::String) delete ps;
129 type = Value::Empty;
130 b = 0;
131 }
132
133 /** set most probable formatting based on the type */
134 void setFormatByType();
135
136private:
137 void operator=(const Value::Private& o);
138
139 static Private* s_null;
140};
141
142void Value::Private::setFormatByType()
143{
144 switch (type) {
145 case Value::Empty:
146 format = Value::fmt_None;
147 break;
148 case Value::Boolean:
149 format = Value::fmt_Boolean;
150 break;
151 case Value::Integer:
152 case Value::Float:
153 case Value::Complex:
154 format = Value::fmt_Number;
155 break;
156 case Value::String:
157 format = Value::fmt_String;
158 break;
159 case Value::Array:
160 format = Value::fmt_None;
161 break;
162 case Value::CellRange:
163 format = Value::fmt_None;
164 break;
165 case Value::Error:
166 format = Value::fmt_String;
167 break;
168 };
169}
170
171// to be shared between all empty value
172Value::Private* Value::Private::s_null = 0;
173
174// static things
175Value ks_value_empty;
176Value ks_value_null;
177Value ks_error_circle;
178Value ks_error_depend;
179Value ks_error_div0;
180Value ks_error_na;
181Value ks_error_name;
182Value ks_error_null;
183Value ks_error_num;
184Value ks_error_parse;
185Value ks_error_ref;
186Value ks_error_value;
187
188// create an empty value
189Value::Value()
190 : d(Private::null())
191{
192}
193
194// destructor
195Value::~Value()
196{
197}
198
199// create value of certain type
200Value::Value(Value::Type _type)
201 : d(Private::null())
202{
203 d->type = _type;
204 d->setFormatByType();
205}
206
207// copy constructor
208Value::Value(const Value& _value)
209 : d(_value.d)
210{
211}
212
213// assignment operator
214Value& Value::operator=(const Value & _value)
215{
216 d = _value.d;
217 return *this;
218}
219
220// comparison operator - returns true only if strictly identical, unlike equal()/compare()
221bool Value::operator==(const Value& o) const
222{
223 if (d->type != o.d->type)
224 return false;
225 switch (d->type) {
226 // null() (d->b == 1) and empty() (d->b == 0) are equal to this operator
227 case Empty: return true;
228 case Boolean: return o.d->b == d->b;
229 case Integer: return o.d->i == d->i;
230 case Float: return compare(o.d->f, d->f) == 0;
231 case Complex: return (!d->pc && !o.d->pc) || ((d->pc && o.d->pc) && (*o.d->pc == *d->pc));
232 case String: return (!d->ps && !o.d->ps) || ((d->ps && o.d->ps) && (*o.d->ps == *d->ps));
233 case Array: return (!d->pa && !o.d->pa) || ((d->pa && o.d->pa) && (*o.d->pa == *d->pa));
234 case Error: return (!d->ps && !o.d->ps) || ((d->ps && o.d->ps) && (*o.d->ps == *d->ps));
235 default: break;
236 }
237 kWarning() << "Unhandled type in Value::operator==: " << d->type;
238 return false;
239}
240
241// create a boolean value
242Value::Value(bool b)
243 : d(Private::null())
244{
245 d->type = Boolean;
246 d->b = b;
247 d->format = fmt_Boolean;
248}
249
250// create an integer value
251Value::Value(qint64 i)
252 : d(Private::null())
253{
254 d->type = Integer;
255 d->i = i;
256 d->format = fmt_Number;
257}
258
259// create an integer value
260Value::Value(int i)
261 : d(Private::null())
262{
263 d->type = Integer;
264 d->i = static_cast<qint64>(i);
265 d->format = fmt_Number;
266}
267
268// create a floating-point value
269Value::Value(double f)
270 : d(Private::null())
271{
272 d->type = Float;
273 d->f = Number(f);
274 d->format = fmt_Number;
275}
276
277// create a floating-point value
278Value::Value(long double f)
279 : d(Private::null())
280{
281 d->type = Float;
282 d->f = Number(f);
283 d->format = fmt_Number;
284}
285
286
287#ifdef CALLIGRA_SHEETS_HIGH_PRECISION_SUPPORT
288// create a floating-point value
289Value::Value(Number f)
290 : d(Private::null())
291{
292 d->type = Float;
293 d->f = f;
294 d->format = fmt_Number;
295}
296#endif // CALLIGRA_SHEETS_HIGH_PRECISION_SUPPORT
297
298// create a complex number value
299Value::Value(const complex<Number>& c)
300 : d(Private::null())
301{
302 d->type = Complex;
303 d->pc = new complex<Number>(c);
304 d->format = fmt_Number;
305}
306
307// create a string value
308Value::Value(const QString& s)
309 : d(Private::null())
310{
311 d->type = String;
312 d->ps = new QString(s);
313 d->format = fmt_String;
314}
315
316// create a string value
317Value::Value(const char *s)
318 : d(Private::null())
319{
320 d->type = String;
321 d->ps = new QString(s);
322 d->format = fmt_String;
323}
324
325// create a floating-point value from date/time
326Value::Value(const QDateTime& dt, const CalculationSettings* settings)
327 : d(Private::null())
328{
329 const QDate refDate(settings->referenceDate());
330 const QTime refTime(0, 0); // reference time is midnight
331 d->type = Float;
332 d->f = Number(refDate.daysTo(dt.date()));
333 d->f += static_cast<double>(refTime.msecsTo(dt.time())) / 86400000.0; // 24*60*60*1000
334 d->format = fmt_DateTime;
335}
336
337// create a floating-point value from time
338Value::Value(const QTime& time, const CalculationSettings* settings)
339 : d(Private::null())
340{
341 Q_UNUSED(settings);
342 const QTime refTime(0, 0); // reference time is midnight
343
344 d->type = Float;
345 d->f = Number(static_cast<double>(refTime.msecsTo(time)) / 86400000.0); // 24*60*60*1000
346 d->format = fmt_Time;
347}
348
349// create a floating-point value from date
350Value::Value(const QDate& date, const CalculationSettings* settings)
351 : d(Private::null())
352{
353 const QDate refDate(settings->referenceDate());
354
355 d->type = Integer;
356 d->i = refDate.daysTo(date);
357 d->format = fmt_Date;
358}
359
360// create an array value
361Value::Value(const ValueStorage& array, const QSize& size)
362 : d(Private::null())
363{
364 d->type = Array;
365 d->pa = new ValueArray(array, size);
366 d->format = fmt_None;
367}
368
369// return type of the value
370Value::Type Value::type() const
371{
372 return d ? d->type : Empty;
373}
374
375bool Value::isNull() const
376{
377 return d ? d->type == Empty && d->b : false;
378}
379
380// get the value as boolean
381bool Value::asBoolean() const
382{
383 bool result = false;
384
385 if (type() == Value::Boolean)
386 result = d->b;
387
388 return result;
389}
390
391// get the value as integer
392qint64 Value::asInteger() const
393{
394 qint64 result = 0;
395 if (type() == Integer)
396 result = d->i;
397 else if (type() == Float)
398 result = static_cast<qint64>(floor(numToDouble(d->f)));
399 else if (type() == Complex)
400 result = static_cast<qint64>(floor(numToDouble(d->pc->real())));
401 return result;
402}
403
404// get the value as floating-point
405Number Value::asFloat() const
406{
407 Number result = 0.0;
408 if (type() == Float)
409 result = d->f;
410 else if (type() == Integer)
411 result = static_cast<Number>(d->i);
412 else if (type() == Complex)
413 result = d->pc->real();
414 return result;
415}
416
417// get the value as complex number
418complex<Number> Value::asComplex() const
419{
420 complex<Number> result(0.0, 0.0);
421 if (type() == Complex)
422 result = *d->pc;
423 else if (type() == Float)
424 result = d->f;
425 else if (type() == Integer)
426 result = static_cast<Number>(d->i);
427 return result;
428}
429
430// get the value as string
431QString Value::asString() const
432{
433 QString result;
434
435 if (type() == Value::String)
436 if (d->ps)
437 result = QString(*d->ps);
438
439 return result;
440}
441
442QString Value::asStringWithDoubleQuotes() const
443{
444 QString s = asString();
445 if (type() == Value::String) {
446 if (!(s.startsWith("\"") && s.endsWith("\""))) {
447 if (s.startsWith("'") && s.endsWith("'"))
448 s = s.mid(1, s.length()-2);
449 s = "\"" + s + "\"";
450 }
451 }
452 return s;
453}
454
455// get the value as QVariant
456QVariant Value::asVariant() const
457{
458 QVariant result;
459
460 switch (d->type) {
461 case Value::Empty:
462 default:
463 result = 0;
464 break;
465 case Value::Boolean:
466 result = d->b;
467 break;
468 case Value::Integer:
469 result = d->i;
470 break;
471 case Value::Float:
472 result = (double) numToDouble(d->f);
473 break;
474 case Value::Complex:
475 // FIXME: add support for complex numbers
476 // pc = new complex<Number>( *o.pc );
477 break;
478 case Value::String:
479 case Value::Error:
480 result = *d->ps;
481 break;
482 case Value::Array:
483 // FIXME: not supported yet
484 //result = ValueArray( d->pa );
485 break;
486 }
487
488 return result;
489}
490
491// set error message
492void Value::setError(const QString& msg)
493{
494 d->clear();
495 d->type = Error;
496 d->ps = new QString(msg);
497}
498
499// get error message
500QString Value::errorMessage() const
501{
502 QString result;
503
504 if (type() == Value::Error)
505 if (d->ps)
506 result = QString(*d->ps);
507
508 return result;
509}
510
511// get the value as date/time
512QDateTime Value::asDateTime(const CalculationSettings* settings) const
513{
514 QDateTime datetime(settings->referenceDate(), QTime(), Qt::UTC);
515
516 const int days = asInteger();
517 const int msecs = qRound((numToDouble(asFloat() - double(days))) * 86400000.0); // 24*60*60*1000
518 datetime = datetime.addDays(days);
519 datetime = datetime.addMSecs(msecs);
520
521 return datetime;
522}
523
524// get the value as date
525QDate Value::asDate(const CalculationSettings* settings) const
526{
527 QDate dt(settings->referenceDate());
528
529 int i = asInteger();
530 dt = dt.addDays(i);
531
532 return dt;
533}
534
535// get the value as time
536QTime Value::asTime(const CalculationSettings* settings) const
537{
538 Q_UNUSED(settings);
539 QTime dt;
540
541 const int days = asInteger();
542 const int msecs = qRound(numToDouble(asFloat() - double(days)) * 86400000.0); // 24*60*60*1000
543 dt = dt.addMSecs(msecs);
544
545 return dt;
546}
547
548Value::Format Value::format() const
549{
550 return d ? d->format : fmt_None;
551}
552
553void Value::setFormat(Value::Format fmt)
554{
555 d->format = fmt;
556}
557
558Value Value::element(unsigned column, unsigned row) const
559{
560 if (d->type != Array) return *this;
561 if (!d->pa) return empty();
562 return d->pa->storage().lookup(column + 1, row + 1);
563}
564
565Value Value::element(unsigned index) const
566{
567 if (d->type != Array) return *this;
568 if (!d->pa) return empty();
569 return d->pa->storage().data(index);
570}
571
572void Value::setElement(unsigned column, unsigned row, const Value& v)
573{
574 if (d->type != Array) return;
575 if (!d->pa) d->pa = new ValueArray();
576 d->pa->storage().insert(column + 1, row + 1, v);
577}
578
579unsigned Value::columns() const
580{
581 if (d->type != Array) return 1;
582 if (!d->pa) return 1;
583 return d->pa->columns();
584}
585
586unsigned Value::rows() const
587{
588 if (d->type != Array) return 1;
589 if (!d->pa) return 1;
590 return d->pa->rows();
591}
592
593unsigned Value::count() const
594{
595 if (d->type != Array) return 1;
596 if (!d->pa) return 1;
597 return d->pa->storage().count();
598}
599
600// reference to empty value
601const Value& Value::empty()
602{
603 return ks_value_empty;
604}
605
606// reference to null value
607const Value& Value::null()
608{
609 if (!ks_value_null.isNull())
610 ks_value_null.d->b = true;
611 return ks_value_null;
612}
613
614// reference to #CIRCLE! error
615const Value& Value::errorCIRCLE()
616{
617 if (!ks_error_circle.isError())
618 ks_error_circle.setError(i18nc("Error: circular formula dependency", "#CIRCLE!"));
619 return ks_error_circle;
620}
621
622// reference to #DEPEND! error
623const Value& Value::errorDEPEND()
624{
625 if (!ks_error_depend.isError())
626 ks_error_depend.setError(i18nc("Error: broken cell reference", "#DEPEND!"));
627 return ks_error_depend;
628}
629
630// reference to #DIV/0! error
631const Value& Value::errorDIV0()
632{
633 if (!ks_error_div0.isError())
634 ks_error_div0.setError(i18nc("Error: division by zero", "#DIV/0!"));
635 return ks_error_div0;
636}
637
638// reference to #N/A error
639const Value& Value::errorNA()
640{
641 if (!ks_error_na.isError())
642 ks_error_na.setError(i18nc("Error: not available", "#N/A"));
643 return ks_error_na;
644}
645
646// reference to #NAME? error
647const Value& Value::errorNAME()
648{
649 if (!ks_error_name.isError())
650 ks_error_name.setError(i18nc("Error: unknown function name", "#NAME?"));
651 return ks_error_name;
652}
653
654// reference to #NUM! error
655const Value& Value::errorNUM()
656{
657 if (!ks_error_num.isError())
658 ks_error_num.setError(i18nc("Error: number out of range", "#NUM!"));
659 return ks_error_num;
660}
661
662// reference to #NULL! error
663const Value& Value::errorNULL()
664{
665 if (!ks_error_null.isError())
666 ks_error_null.setError(i18nc("Error: empty intersecting area", "#NULL!"));
667 return ks_error_null;
668}
669
670// reference to #PARSE! error
671const Value& Value::errorPARSE()
672{
673 if (!ks_error_parse.isError())
674 ks_error_parse.setError(i18nc("Error: formula not parseable", "#PARSE!"));
675 return ks_error_parse;
676}
677
678// reference to #REF! error
679const Value& Value::errorREF()
680{
681 if (!ks_error_ref.isError())
682 ks_error_ref.setError(i18nc("Error: invalid cell/array reference", "#REF!"));
683 return ks_error_ref;
684}
685
686// reference to #VALUE! error
687const Value& Value::errorVALUE()
688{
689 if (!ks_error_value.isError())
690 ks_error_value.setError(i18nc("Error: wrong (number of) function argument(s)", "#VALUE!"));
691 return ks_error_value;
692}
693
694int Value::compare(Number v1, Number v2)
695{
696 Number v3 = v1 - v2;
697 if (v3 > DBL_EPSILON) return 1;
698 if (v3 < -DBL_EPSILON) return -1;
699 return 0;
700}
701
702bool Value::isZero(Number v)
703{
704 return abs(v) < DBL_EPSILON;
705}
706
707bool Value::isZero() const
708{
709 if (!isNumber()) return false;
710 return isZero(asFloat());
711}
712
713bool Value::allowComparison(const Value& v) const
714{
715 Value::Type t1 = d->type;
716 Value::Type t2 = v.type();
717
718 if ((t1 == Empty) && (t2 == Empty)) return true;
719 if ((t1 == Empty) && (t2 == String)) return true;
720 if ((t1 == Empty) && (t2 == Integer)) return true;
721 if ((t1 == Empty) && (t2 == Float)) return true;
722 if ((t1 == Empty) && (t2 == Boolean)) return true;
723
724 if ((t1 == Boolean) && (t2 == Boolean)) return true;
725 if ((t1 == Boolean) && (t2 == Integer)) return true;
726 if ((t1 == Boolean) && (t2 == Float)) return true;
727 if ((t1 == Boolean) && (t2 == String)) return true;
728
729 if ((t1 == Integer) && (t2 == Boolean)) return true;
730 if ((t1 == Integer) && (t2 == Integer)) return true;
731 if ((t1 == Integer) && (t2 == Float)) return true;
732 if ((t1 == Integer) && (t2 == String)) return true;
733
734 if ((t1 == Float) && (t2 == Boolean)) return true;
735 if ((t1 == Float) && (t2 == Integer)) return true;
736 if ((t1 == Float) && (t2 == Float)) return true;
737 if ((t1 == Float) && (t2 == String)) return true;
738
739 if ((t1 == Complex) && (t2 == Boolean)) return true;
740 if ((t1 == Complex) && (t2 == Integer)) return true;
741 if ((t1 == Complex) && (t2 == Float)) return true;
742 if ((t1 == Complex) && (t2 == String)) return true;
743
744 if ((t1 == String) && (t2 == Empty)) return true;
745 if ((t1 == String) && (t2 == Boolean)) return true;
746 if ((t1 == String) && (t2 == Integer)) return true;
747 if ((t1 == String) && (t2 == Float)) return true;
748 if ((t1 == String) && (t2 == Complex)) return true;
749 if ((t1 == String) && (t2 == String)) return true;
750
751 // errors can be compared too ...
752 if ((t1 == Error) && (t2 == Error)) return true;
753
754 return false;
755}
756
757// compare values. looks strange in order to be compatible with Excel
758int Value::compare(const Value& v, Qt::CaseSensitivity cs) const
759{
760 Value::Type t1 = d->type;
761 Value::Type t2 = v.type();
762
763 // errors always less than everything else
764 if ((t1 == Error) && (t2 != Error))
765 return -1;
766 if ((t2 == Error) && (t1 != Error))
767 return 1;
768
769 // comparing errors only yields 0 if they are the same
770 if ((t1 == Error) && (t2 == Error))
771 return errorMessage() != v.errorMessage();
772
773 // empty == empty
774 if ((t1 == Empty) && (t2 == Empty))
775 return 0;
776
777 // empty value is always less than string
778 // (except when the string is empty)
779 if ((t1 == Empty) && (t2 == String))
780 return(v.asString().isEmpty()) ? 0 : -1;
781
782 // empty vs integer
783 if ((t1 == Empty) && (t2 == Integer))
784 return -1;
785
786 // empty vs float
787 if ((t1 == Empty) && (t2 == Float))
788 return -1;
789
790 // empty vs boolean
791 if ((t1 == Empty) && (t2 == Boolean))
792 return -1;
793
794 // boolean vs boolean
795 if ((t1 == Boolean) && (t2 == Boolean)) {
796 bool p = asBoolean();
797 bool q = v.asBoolean();
798 if (p) return q ? 0 : 1;
799 else return q ? -1 : 0;
800 }
801
802 // boolean is always greater than integer
803 if ((t1 == Boolean) && (t2 == Integer))
804 return 1;
805
806 // boolean is always greater than float
807 if ((t1 == Boolean) && (t2 == Float))
808 return 1;
809
810 // boolean is always greater than string
811 if ((t1 == Boolean) && (t2 == String))
812 return 1;
813
814 // integer is always less than boolean
815 if ((t1 == Integer) && (t2 == Boolean))
816 return -1;
817
818 // integer vs integer
819 if ((t1 == Integer) && (t2 == Integer)) {
820 qint64 p = asInteger();
821 qint64 q = v.asInteger();
822 return (p == q) ? 0 : (p < q) ? -1 : 1;
823 }
824
825 // integer vs float
826 if ((t1 == Integer) && (t2 == Float))
827 return compare(asFloat(), v.asFloat());
828
829 // integer is always less than string
830 if ((t1 == Integer) && (t2 == String))
831 return -1;
832
833 // float is always less than boolean
834 if ((t1 == Float) && (t2 == Boolean))
835 return -1;
836
837 // float vs integer
838 if ((t1 == Float) && (t2 == Integer))
839 return compare(asFloat(), v.asFloat());
840
841 // float vs float
842 if ((t1 == Float) && (t2 == Float))
843 return compare(asFloat(), v.asFloat());
844
845 // float is always less than string
846 if ((t1 == Float) && (t2 == String))
847 return -1;
848
849 // TODO Stefan: Complex
850
851 // string is always greater than empty value
852 // (except when the string is empty)
853 if ((t1 == String) && (t2 == Empty))
854 return(asString().isEmpty()) ? 0 : 1;
855
856 // string is always less than boolean
857 if ((t1 == String) && (t2 == Boolean))
858 return -1;
859
860 // string is always greater than integer
861 if ((t1 == String) && (t2 == Integer))
862 return 1;
863
864 // string is always greater than float
865 if ((t1 == String) && (t2 == Float))
866 return 1;
867
868 // The-Real-String comparison
869 if ((t1 == String) && (t2 == String))
870 return asString().compare(v.asString(), cs);
871
872 // Undefined, actually allowComparison would return false
873 return 0;
874}
875
876bool Value::equal(const Value& v, Qt::CaseSensitivity cs) const
877{
878 if (!allowComparison(v)) return false;
879 return compare(v, cs) == 0;
880}
881
882bool Value::less(const Value& v, Qt::CaseSensitivity cs) const
883{
884 if (!allowComparison(v)) return false;
885 return compare(v, cs) < 0;
886}
887
888bool Value::greater(const Value& v, Qt::CaseSensitivity cs) const
889{
890 if (!allowComparison(v)) return false;
891 return compare(v, cs) > 0;
892}
893
894QTextStream& operator<<(QTextStream& ts, Value::Type type)
895{
896 switch (type) {
897 case Value::Empty: ts << "Empty"; break;
898 case Value::Boolean: ts << "Boolean"; break;
899 case Value::Integer: ts << "Integer"; break;
900 case Value::Float: ts << "Float"; break;
901 case Value::Complex: ts << "Complex"; break;
902 case Value::String: ts << "String"; break;
903 case Value::Array: ts << "Array"; break;
904 case Value::Error: ts << "Error"; break;
905 default: ts << "Unknown!"; break;
906 };
907 return ts;
908}
909
910QTextStream& operator<<(QTextStream& ts, Value value)
911{
912 ts << value.type();
913 switch (value.type()) {
914 case Value::Empty: break;
915
916 case Value::Boolean:
917 ts << ": ";
918 if (value.asBoolean()) ts << "TRUE";
919 else ts << "FALSE"; break;
920
921 case Value::Integer:
922 ts << ": " << value.asInteger(); break;
923
924 case Value::Float:
925 ts << ": " << (double) numToDouble(value.asFloat()); break;
926
927 case Value::Complex: {
928 const complex<Number> complex(value.asComplex());
929 ts << ": " << (double) numToDouble(complex.real());
930 if (complex.imag() >= 0.0)
931 ts << '+';
932 ts << (double) numToDouble(complex.imag()) << 'i';
933 break;
934 }
935
936 case Value::String:
937 ts << ": " << value.asString(); break;
938
939 case Value::Array: {
940 ts << ": {" << value.asString();
941 const int cols = value.columns();
942 const int rows = value.rows();
943 for (int row = 0; row < rows; ++row) {
944 for (int col = 0; col < cols; ++col) {
945 ts << value.element(col, row);
946 if (col < cols - 1)
947 ts << ';';
948 }
949 if (row < rows - 1)
950 ts << '|';
951 }
952 ts << '}';
953 break;
954 }
955
956 case Value::Error:
957 ts << '(' << value.errorMessage() << ')'; break;
958
959 default: break;
960 }
961 return ts;
962}
963
964/***************************************************************************
965 QHash/QSet support
966****************************************************************************/
967
968namespace Calligra
969{
970namespace Sheets
971{
972uint qHash(const Value& value)
973{
974 switch (value.type()) {
975 case Value::Empty:
976 case Value::CellRange:
977 return 0;
978 case Value::Boolean:
979 return ::qHash(value.asBoolean());
980 case Value::Integer:
981 return ::qHash(value.asInteger());
982 case Value::Float:
983 return ::qHash((qint64)numToDouble(value.asFloat()));
984 case Value::Complex:
985 return ::qHash((qint64)value.asComplex().real());
986 case Value::String:
987 return ::qHash(value.asString());
988 case Value::Array:
989 return qHash(value.element(0, 0));
990 case Value::Error:
991 return ::qHash(value.errorMessage());
992 }
993 return 0;
994}
995} // namespace Sheets
996} // namespace Calligra
997
998/***************************************************************************
999 kDebug support
1000****************************************************************************/
1001
1002QDebug operator<<(QDebug str, const Calligra::Sheets::Value& v)
1003{
1004 QString string;
1005 QTextStream stream(&string);
1006 stream << v;
1007 str << string;
1008 return str;
1009}
1010
1011QDebug operator<<(QDebug stream, const Calligra::Sheets::Value::Format& f)
1012{
1013 switch (f) {
1014 case Calligra::Sheets::Value::fmt_None: stream << "None"; break;
1015 case Calligra::Sheets::Value::fmt_Boolean: stream << "Boolean"; break;
1016 case Calligra::Sheets::Value::fmt_Number: stream << "Number"; break;
1017 case Calligra::Sheets::Value::fmt_Percent: stream << "Percent"; break;
1018 case Calligra::Sheets::Value::fmt_Money: stream << "Money"; break;
1019 case Calligra::Sheets::Value::fmt_DateTime: stream << "DateTime"; break;
1020 case Calligra::Sheets::Value::fmt_Date: stream << "Date"; break;
1021 case Calligra::Sheets::Value::fmt_Time: stream << "Time"; break;
1022 case Calligra::Sheets::Value::fmt_String: stream << "String"; break;
1023 }
1024 return stream;
1025}
1026