summaryrefslogtreecommitdiff
path: root/noncore/apps/tableviewer/db/common.cpp
Unidiff
Diffstat (limited to 'noncore/apps/tableviewer/db/common.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/tableviewer/db/common.cpp1470
1 files changed, 1470 insertions, 0 deletions
diff --git a/noncore/apps/tableviewer/db/common.cpp b/noncore/apps/tableviewer/db/common.cpp
new file mode 100644
index 0000000..4c70e54
--- a/dev/null
+++ b/noncore/apps/tableviewer/db/common.cpp
@@ -0,0 +1,1470 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20#include <stdlib.h>
21#include <qstring.h>
22#include <qheader.h>
23#include <qvector.h>
24#include <qdatetime.h>
25#include <timestring.h>
26#include "common.h"
27#include "datacache.h"
28#include <assert.h>
29
30static const int del_flag = 0x1;
31static const int new_flag = 0x2;
32
33/* Helper function */
34
35int parseNextNumber(QString *q) {
36 QChar c;
37 uint i;
38 int result = 0;
39
40 bool found_digits = FALSE;
41 for(i = 0; i < q->length(); i++) {
42 c = q->at(i);
43 if (c.isDigit()) {
44 if (found_digits)
45 result *= 10;
46 found_digits = TRUE;
47 result += c.digitValue();
48 } else {
49 if (found_digits)
50 break;
51 /* just skip this char */
52 }
53 }
54 /* now truncate q */
55 if (found_digits)
56 q->remove(0, i);
57 return result;
58}
59
60/*!
61 \class QStringVector
62 \brief A Vector of QStrings that can be sorted and searched
63
64 Implmented in order to allow reverse lookup on the string name
65
66*/
67
68/*!
69 This function implements the compare function in order to allow the
70 searching and sorting of the QStringVector to occur
71
72 \returns an int which is either
73 <UL>
74 <LI> < 0 if the first string is smaller than the second,</LI>
75 <LI> > 0 if the first string is bigger then the second,</LI>
76 <LI> == 0 if the first string is equal to the second.</LI>
77 </UL>
78*/
79int QStringVector::compareItems(Item a, Item b)
80{
81 QString *qa = (QString *)a;
82 QString *qb = (QString *)b;
83
84 return QString::compare(*qa, *qb);
85}
86
87/*!
88 \class TVVariant
89 A way of abstracting void * and keeping information on
90 the keytypes and behaviours in one place
91*/
92
93TVVariantPrivate::TVVariantPrivate()
94{
95 typ = TVVariant::Invalid;
96}
97
98TVVariantPrivate::TVVariantPrivate( TVVariantPrivate *d)
99{
100 switch(d->typ)
101 {
102 case TVVariant::Invalid:
103 break;
104 case TVVariant::String:
105 value.ptr = new QString(*((QString *)d->value.ptr));
106 break;
107 case TVVariant::Date:
108 value.ptr = new QDate(*((QDate *)d->value.ptr));
109 break;
110 case TVVariant::Time:
111 value.ptr = new QTime(*((QTime *)d->value.ptr));
112 break;
113 case TVVariant::Int:
114 value.i = d->value.i;
115 break;
116 default:
117 ASSERT( 0 );
118 }
119
120 typ = d->typ;
121}
122
123TVVariantPrivate::~TVVariantPrivate()
124{
125 clear();
126}
127
128void TVVariantPrivate::clear()
129{
130 switch( typ )
131 {
132 case TVVariant::String:
133 delete (QString *)value.ptr;
134 break;
135 case TVVariant::Date:
136 delete (QDate *)value.ptr;
137 break;
138 case TVVariant::Time:
139 delete (QTime *)value.ptr;
140 break;
141 case TVVariant::Invalid:
142 case TVVariant::Int:
143 break;
144 }
145
146 typ = TVVariant::Invalid;
147}
148
149/*!
150 \class TVVariant
151 blah
152*/
153
154TVVariant::TVVariant()
155{
156 d = new TVVariantPrivate;
157}
158
159TVVariant::~TVVariant()
160{
161 if (d->deref())
162 delete d;
163}
164
165TVVariant::TVVariant(const TVVariant& p)
166{
167 d = new TVVariantPrivate;
168 *this = p;
169}
170
171TVVariant::TVVariant(QDataStream& s)
172{
173 d = new TVVariantPrivate;
174 s >> *this;
175}
176
177TVVariant::TVVariant(const QString &val)
178{
179 d = new TVVariantPrivate;
180 d->typ = String;
181 d->value.ptr = new QString(val);
182}
183
184TVVariant::TVVariant(const QDate &val)
185{
186 d = new TVVariantPrivate;
187 d->typ = Date;
188 d->value.ptr = new QDate(val);
189}
190
191TVVariant::TVVariant(const QTime &val)
192{
193 d = new TVVariantPrivate;
194 d->typ = Time;
195 d->value.ptr = new QTime(val);
196}
197
198TVVariant::TVVariant( int val )
199{
200 d = new TVVariantPrivate;
201 d->typ = Int;
202 d->value.i = val;
203}
204
205TVVariant& TVVariant::operator=(const TVVariant& variant )
206{
207 TVVariant& other = (TVVariant&) variant;
208
209 other.d->ref();
210 if ( d->deref() )
211 delete d;
212
213 d = other.d;
214
215 return *this;
216}
217
218void TVVariant::detach()
219{
220 if (d->count == 1)
221 return;
222
223 d->deref();
224 d = new TVVariantPrivate(d);
225}
226
227const QString TVVariant::typeName() const
228{
229 return typeToName(d->typ);
230}
231
232void TVVariant::clear()
233{
234 if (d->count > 1)
235 {
236 d->deref();
237 d = new TVVariantPrivate;
238 return;
239 }
240
241 d->clear();
242}
243
244const QString TVVariant::typeToName(KeyType typ)
245{
246 switch(typ) {
247 case String:
248 return QString("String");
249 case Date:
250 return QString("Date");
251 case Time:
252 return QString("Time");
253 case Int:
254 return QString("Int");
255 case Invalid:
256 default:
257 return QString("Invalid");
258 }
259 return QString("Invalid");
260}
261
262TVVariant::KeyType TVVariant::nameToType(const QString &name)
263{
264 if(!qstrcmp("String", name))
265 return String;
266 if(!qstrcmp("Date", name))
267 return Date;
268 if(!qstrcmp("Time", name))
269 return Time;
270 if(!qstrcmp("Int", name))
271 return Int;
272
273 return Invalid;
274}
275
276void TVVariant::load(QDataStream &s )
277{
278 KeyType t;
279 s >> t;
280
281 d->typ = t;
282 switch(t) {
283 case Invalid:
284 d->typ = t;
285 break;
286 case String:
287 {
288 QString *x = new QString;
289 s >> *x;
290 d->value.ptr = x;
291 }
292 break;
293 case Time:
294 {
295 QTime *x = new QTime;
296 s >> *x;
297 d->value.ptr = x;
298 }
299 break;
300 case Date:
301 {
302 QDate *x = new QDate;
303 s >> *x;
304 d->value.ptr = x;
305 }
306 break;
307 case Int:
308 {
309 int x;
310 s >> x;
311 d->value.i = x;
312 }
313 break;
314 default:
315 qFatal("Unrecognized data type");
316 }
317}
318
319void TVVariant::save( QDataStream &s ) const
320{
321 s << type();
322
323 switch( d->typ ) {
324 case String:
325 s << *((QString *)d->value.ptr);
326 break;
327 case Date:
328 s << *((QDate *)d->value.ptr);
329 break;
330 case Time:
331 s << *((QTime *)d->value.ptr);
332 break;
333 case Int:
334 s << d->value.i;
335 break;
336 case Invalid:
337 break;
338 }
339}
340
341QDataStream& operator>>(QDataStream& s, TVVariant& p)
342{
343 p.load( s );
344 return s;
345}
346
347QDataStream& operator<<(QDataStream &s, const TVVariant& p)
348{
349 p.save( s );
350 return s;
351}
352
353QDataStream& operator>> (QDataStream &s, TVVariant::KeyType& p)
354{
355 Q_UINT8 u = 0;
356 s >> u;
357 p = (TVVariant::KeyType) u;
358
359 return s;
360}
361
362QDataStream& operator<< (QDataStream& s, const TVVariant::KeyType& p)
363{
364 s << (Q_UINT8)p;
365 return s;
366}
367
368const QString TVVariant::toString() const
369{
370 switch(d->typ) {
371 case String:
372 return *((QString*)d->value.ptr);
373 case Date:
374 return ((QDate*)d->value.ptr)->toString();
375 case Time:
376 return ((QTime*)d->value.ptr)->toString();
377 case Int:
378 return QString::number(d->value.i);
379 case Invalid:
380 default:
381 return QString::null;
382 }
383 return QString::null;
384}
385
386// TODO DO, this properly, */
387int TVVariant::toInt() const
388{
389 if(d->typ == Int)
390 return d->value.i;
391
392 if(d->typ == String) {
393 QString tmpq(*(QString *)d->value.ptr);
394 return parseNextNumber(&tmpq);
395 }
396
397 return 0;
398}
399
400const QDate TVVariant::toDate() const
401{
402 if(d->typ == Date)
403 return *((QDate *)d->value.ptr);
404
405 if(d->typ == String) {
406 QString q = toString();
407
408 /* date format is day mon d yyyy */
409 /* ignore the first three letters, read the next
410 three for month.. etc */
411
412 int day = parseNextNumber(&q);
413 int month = parseNextNumber(&q);
414 int year = parseNextNumber(&q);
415 if (!QDate::isValid(year, month, day))
416 return QDate();
417 return QDate(year, month, day);
418 }
419
420
421 return QDate();
422}
423
424const QTime TVVariant::toTime() const
425{
426 if(d->typ == Time)
427 return *((QTime *)d->value.ptr);
428
429 if(d->typ == String) {
430 QString q = toString();
431 int hour = parseNextNumber(&q);
432 int minute = parseNextNumber(&q);
433 int second = parseNextNumber(&q);
434 int msecond = parseNextNumber(&q);
435 if (!QTime::isValid(hour, minute, second, msecond))
436 return QTime();
437 return QTime(hour, minute, second, msecond);
438 }
439
440 return QTime();
441}
442
443#define TV_VARIANT_AS( f ) Q##f& TVVariant::as##f() { \
444 if ( d->typ != f ) \
445 *this = TVVariant( to##f() ); \
446 else \
447 detach(); \
448 return *((Q##f*)d->value.ptr); }
449
450TV_VARIANT_AS(String)
451TV_VARIANT_AS(Date)
452TV_VARIANT_AS(Time)
453
454#undef TV_VARIANT_AS
455
456int& TVVariant::asInt()
457{
458 detach();
459 if (d->typ != Int) {
460 d->value.i = toInt();
461 d->typ = Int;
462 }
463 return d->value.i;
464}
465
466/*!
467 valid cast is
468 anything to String
469 same to same
470*/
471bool TVVariant::canCast(KeyType t) const
472{
473 if(d->typ == t)
474 return TRUE;
475
476 if(t == String)
477 return TRUE;
478
479 if(t == Int) {
480 if (d->typ == Date)
481 return TRUE;
482 if (d->typ == Time)
483 return TRUE;
484 if (d->typ == String)
485 return TRUE;
486 }
487
488 return FALSE;
489}
490
491bool TVVariant::operator==( const TVVariant &v ) const
492{
493 switch(d->typ) {
494 case String:
495 return v.toString() == toString();
496 case Date:
497 return v.toDate() == toDate();
498 case Time:
499 return v.toTime() == toTime();
500 case Int:
501 return v.toInt() == toInt();
502 case Invalid:
503 break;
504 }
505
506 return FALSE;
507}
508
509bool TVVariant::operator!=( const TVVariant &v ) const
510{
511 return !( v == *this);
512}
513
514bool TVVariant::operator<( const TVVariant &v ) const
515{
516 switch(d->typ) {
517 case String:
518 return toString().lower() < v.toString().lower();
519 case Date:
520 return toDate() < v.toDate();
521 case Time:
522 return toTime() < v.toTime();
523 case Int:
524 return toInt() < v.toInt();
525 case Invalid:
526 default:
527 break;
528 }
529 return FALSE;
530}
531
532bool TVVariant::operator>( const TVVariant &v ) const
533{
534 switch(d->typ) {
535 case String:
536 return toString().lower() > v.toString().lower();
537 case Date:
538 return toDate() > v.toDate();
539 case Time:
540 return toTime() > v.toTime();
541 case Int:
542 return toInt() > v.toInt();
543 case Invalid:
544 default:
545 break;
546 }
547 return FALSE;
548}
549
550/*! True if n is closer to this than o */
551bool TVVariant::closer(TVVariant n, TVVariant o)
552{
553 /* Nothing is close to an invalid, so nothing can be closer */
554 if(d->typ == Invalid)
555 return FALSE;
556
557 /* can't be closer if of different type */
558 if(n.type() != type())
559 return FALSE;
560
561 /* if new shares type, and old doesn't, then new is closer */
562 if(o.type() != type())
563 return TRUE;
564
565 switch(type()){
566 case String: {
567 /* case for strings is close is a substring.. closer is
568 * earlier alphabetically */
569 QString qs1 = n.toString().lower();
570 QString qs2 = o.toString().lower();
571 QString qsv = toString().lower();
572
573 if (!qs1.startsWith(qsv))
574 return FALSE;
575
576 /* contains sub-str, if later than is not closer */
577 if(QString::compare(qs1, qs2) > 0)
578 return FALSE;
579 return TRUE;
580 }
581 case Int: {
582 /* case for int is smallest absolute difference */
583 int i1 = n.toInt();
584 int i2 = o.toInt();
585 int iv = toInt();
586
587 int diff1 = (i1 - iv);
588 if (diff1 < 0)
589 diff1 = -diff1;
590 int diff2 = (i2 - iv);
591 if (diff2 < 0)
592 diff2 = -diff2;
593
594 if (diff1 < diff2)
595 return TRUE;
596 return FALSE;
597 }
598 case Date: {
599 QDate i1 = n.toDate();
600 QDate i2 = o.toDate();
601 QDate iv = toDate();
602
603 /* definition of closer is the least difference in days */
604 int diff1 = i1.daysTo(iv);
605 if (diff1 < 0)
606 diff1 = -diff1;
607 int diff2 = i2.daysTo(iv);
608 if (diff2 < 0)
609 diff2 = -diff2;
610
611 if (diff1 < diff2)
612 return TRUE;
613 return FALSE;
614 }
615 case Time: {
616 QTime i1 = n.toTime();
617 QTime i2 = o.toTime();
618 QTime iv = toTime();
619
620 /* definition of closer is the least difference in days */
621 int diff1 = i1.msecsTo(iv);
622 if (diff1 < 0)
623 diff1 = -diff1;
624 int diff2 = i2.msecsTo(iv);
625 if (diff2 < 0)
626 diff2 = -diff2;
627 if (diff1 < diff2)
628 return TRUE;
629 return FALSE;
630 }
631 default:
632 /* don't know how to do 'closer' on this type, hence never closer
633 * or even close */
634 break;
635 }
636 return FALSE;
637}
638
639/*! True if n is close to this */
640bool TVVariant::close(TVVariant n)
641{
642 /* Nothing is close to an invalid, so nothing can be closer */
643 if(type() == Invalid)
644 return FALSE;
645
646 /* can't be close if of different type */
647 if(n.type() != type())
648 return FALSE;
649
650 switch(type()){
651 case String: {
652 /* case for strings is close is a substring.. closer is
653 * earlier alphabetically */
654 QString qs1 = n.toString().lower();
655 QString qsv = toString().lower();
656
657 if (!qs1.startsWith(qsv))
658 return FALSE;
659 return TRUE;
660 }
661 case Int:
662 case Date:
663 case Time:
664 return TRUE;
665 default:
666 /* don't know how to do 'closer' on this type, hence never closer
667 * or even close */
668 break;
669 }
670 return FALSE;
671}
672
673/*!
674 \class Key
675 \brief document me!
676
677 document me!
678*/
679
680Key::Key() : kname(), kexample(), kflags(0) { }
681
682Key::Key(QString name, TVVariant example, int flags = 0) :
683 kname(name), kexample(example), kflags(flags) { }
684
685Key::Key(const Key &other)
686{
687 kname = other.kname;
688 kexample = other.kexample;
689 kflags = other.kflags;
690}
691
692Key& Key::operator=(const Key& key)
693{
694 kname = key.kname;
695 kexample = key.kexample;
696 kflags = key.kflags;
697 return *this;
698}
699
700QString Key::name() const
701{
702 return QString(kname);
703}
704
705TVVariant Key::example() const
706{
707 return TVVariant(kexample);
708}
709
710TVVariant::KeyType Key::type() const
711{
712 return kexample.type();
713}
714
715void Key::setName(const QString &name)
716{
717 kname = QString(name);
718}
719
720void Key::setExample(const TVVariant &e)
721{
722 kexample = TVVariant(e);
723}
724
725int Key::flags() const
726{
727 return kflags;
728}
729
730void Key::setFlags(int fl)
731{
732 kflags = fl;
733}
734
735bool Key::delFlag() const
736{
737 if(kflags & del_flag)
738 return TRUE;
739 return FALSE;
740}
741
742bool Key::newFlag() const
743{
744 if(kflags & new_flag)
745 return TRUE;
746 return FALSE;
747}
748
749void Key::setDelFlag(bool v)
750{
751 if(delFlag() != v)
752 kflags = kflags ^ del_flag;
753}
754
755void Key::setNewFlag(bool v)
756{
757 if(newFlag() != v)
758 kflags = kflags ^ new_flag;
759}
760
761/*!
762 \class KeyList
763 \brief A represntation of keys used for a table.
764
765 The KeyList class is used to store the representation of keys used in table
766 headings by DBStore. It stores the names and types of the keys
767*/
768
769/*!
770 Constructs a KeyList
771*/
772KeyList::KeyList() : QIntDict<Key>(20)
773{
774 setAutoDelete(TRUE);
775}
776
777/* Should be deep copy, but isn't */
778KeyList::KeyList(const KeyList &k) : QIntDict<Key>(k)
779{
780 KeyListIterator it(k);
781 while(it.current()) {
782 replace(it.currentKey(), new Key(*it.current()));
783 ++it;
784 }
785
786 setAutoDelete(TRUE);
787}
788
789/*!
790 Destroys a KeyList
791*/
792KeyList::~KeyList() {
793}
794
795/* Do a comparision base on Keys */
796bool KeyList::operator!=(const KeyList &other)
797{
798 KeyListIterator it(*this);
799
800 if (other.getNumFields() != getNumFields())
801 return TRUE;
802
803 while(it.current()) {
804 //it.currentKey(), it.current();
805 if (other.getKeyName(it.currentKey()) != getKeyName(it.currentKey()))
806 return TRUE;
807 if (other.getKeyType(it.currentKey()) != getKeyType(it.currentKey()))
808 return TRUE;
809 ++it;
810 }
811 return FALSE;
812}
813
814/*!
815 Returns the number of keys stored in the KeyList
816*/
817int KeyList::getNumFields() const
818{
819 return count();
820}
821
822/*!
823 Adds a new key to the KeyList
824
825 \param name the name of the new key
826 \param type the type of the new key
827*/
828int KeyList::addKey(QString name, TVVariant example)
829{
830 int i = count();
831 while(find(i) && (i > -1))
832 i--;
833 replace(i, new Key(name, example, 0));
834 return i;
835}
836
837int KeyList::addKey(QString name, TVVariant::KeyType type)
838{
839 /* generate a valid type for the example? */
840 TVVariant e = TVVariant("0");
841 switch(type) {
842 case TVVariant::String:
843 return addKey(name, TVVariant("<undefined>").asString());
844 break;
845 case TVVariant::Date:
846 return addKey(name, TVVariant(QDate::currentDate()).asDate());
847 break;
848 case TVVariant::Time:
849 return addKey(name, TVVariant(QTime(0,0,0)).toTime());
850 break;
851 case TVVariant::Int:
852 return addKey(name, TVVariant(0).toInt());
853 break;
854 default:
855 qWarning(QObject::tr("KeyList::addKey() Cannot make default "
856 "value for type %1, Key not added.").arg(type));
857 break;
858 }
859 return -1;
860}
861
862void KeyList::setKeyFlags(int i, int flag)
863{
864 if(find(i))
865 find(i)->setFlags(flag);
866}
867
868int KeyList::getKeyFlags(int i) const
869{
870 if(find(i))
871 return find(i)->flags();
872 return 0;
873}
874
875bool KeyList::checkNewFlag(int i) const
876{
877 if (find(i))
878 return find(i)->newFlag();
879 return false;
880}
881
882void KeyList::setNewFlag(int i, bool f)
883{
884 if(!find(i))
885 return;
886 find(i)->setNewFlag(f);
887}
888
889bool KeyList::checkDeleteFlag(int i) const
890{
891 if (find(i))
892 return find(i)->delFlag();
893 return false;
894}
895
896void KeyList::setDeleteFlag(int i, bool f)
897{
898 if(!find(i))
899 return;
900 find(i)->setDelFlag(f);
901}
902
903/*!
904 Returns the name of the key at index i
905*/
906QString KeyList::getKeyName(int i) const
907{
908 if (find (i))
909 return find(i)->name();
910 return QString();
911}
912
913void KeyList::setKeyName(int i, const QString &n)
914{
915 if(find(i))
916 find(i)->setName(n);
917}
918
919/*!
920 Returns the type of the key at index i
921*/
922TVVariant::KeyType KeyList::getKeyType(int i) const
923{
924 if(find(i))
925 return find(i)->type();
926 return TVVariant::Invalid;
927}
928
929void KeyList::setKeyType(int i, TVVariant::KeyType t)
930{
931 if(!find(i))
932 return;
933 switch(t) {
934 case TVVariant::String:
935 find(i)->setExample(TVVariant(QString("default")));
936 return;
937 case TVVariant::Int:
938 find(i)->setExample(TVVariant(int(0)));
939 return;
940 case TVVariant::Date:
941 find(i)->setExample(TVVariant(QDate::currentDate()));
942 return;
943 case TVVariant::Time:
944 find(i)->setExample(TVVariant(QTime(0,0,0,0)));
945 return;
946 default:
947 break;
948 }
949 return;
950}
951
952TVVariant KeyList::getKeyExample(int i) const
953{
954 if(find(i))
955 return find(i)->example();
956 return TVVariant();
957}
958
959void KeyList::setKeyExample(int i, TVVariant example)
960{
961 if(find(i))
962 find(i)->setExample(example);
963}
964
965/*!
966 Returns the index of the key with name q
967*/
968int KeyList::getKeyIndex(QString q) const
969{
970 KeyListIterator it(*this);
971
972 while(it.current()) {
973 if(it.current()->name() == q)
974 return it.currentKey();
975 ++it;
976 }
977 return -1;
978}
979
980bool KeyList::validIndex(int i) const
981{
982 if(!find(i))
983 return FALSE;
984 if(find(i)->delFlag())
985 return FALSE;
986 return TRUE;
987}
988
989QDataStream &operator<<( QDataStream &s, const KeyList &k)
990{
991 s << k.getNumFields();
992
993 KeyListIterator it(k);
994
995 while(it.current()) {
996 s << (Q_UINT16)it.currentKey();
997 s << it.current()->name();
998 s << it.current()->example();
999 s << (Q_UINT16)it.current()->flags();
1000 ++it;
1001 }
1002 return s;
1003}
1004
1005QDataStream &operator>>( QDataStream &s, KeyList &k)
1006{
1007 int i;
1008 int size;
1009 int index = 0;
1010 int flags = 0;
1011 TVVariant type = TVVariant();
1012 QString name;
1013
1014 s >> size;
1015
1016 for (i=0; i < size; i++) {
1017 s >> (Q_UINT16 &)index;
1018 s >> name;
1019 s >> type;
1020 s >> (Q_UINT16 &)flags;
1021 k.replace(index, new Key(name, type, flags));
1022 }
1023 return s;
1024}
1025
1026/*!
1027 \class DataElem
1028 \brief A class representing a single row or element of a table in a DBStore
1029
1030 This class holds the data of a row in a table.
1031*/
1032
1033
1034/*!
1035 Constructs a DataElem. This function needs a container because the
1036 size, types of keys and primary key are all defined by the containing
1037 database
1038*/
1039DataElem::DataElem(DBStore *c) : values(20)
1040{
1041 int size;
1042 contained = c;
1043 size = c->getNumFields();
1044 values.setAutoDelete(TRUE);
1045}
1046
1047/*!
1048 Destroys a DataElem and frees memory used by the DataElem
1049*/
1050DataElem::~DataElem() {
1051}
1052
1053
1054
1055QDataStream &operator<<( QDataStream &s, const DataElem &d)
1056{
1057 int size = d.getNumFields();
1058
1059 s << size; /* redundent data but makes streaming easier */
1060 KeyList k = d.getKeys();
1061
1062 KeyListIterator it(k);
1063
1064 while(it.current()) {
1065 s << (Q_UINT16)it.currentKey();
1066 s << d.getField(it.currentKey());
1067 ++it;
1068 }
1069 return s;
1070}
1071
1072QDataStream &operator>>( QDataStream &s, DataElem &d)
1073{
1074 int i;
1075 int size;
1076 TVVariant t;
1077 int index = 0;
1078
1079 s >> size; /* redundent data but makes streaming easier */
1080 if (size != d.getNumFields()) {
1081 qWarning("DataSize mis-match");
1082 return s; /* sanity check failed.. don't load */
1083 }
1084
1085 for(i = 0; i < size; i++) {
1086 s >> (Q_UINT16)index;
1087 s >> t;
1088 d.setField(index, t);
1089 }
1090 return s;
1091}
1092
1093/*! Returns the number of possible (not valid) fields in the data element */
1094int DataElem::getNumFields() const
1095{
1096 return contained->getNumFields();
1097}
1098
1099KeyList DataElem::getKeys() const
1100{
1101 return *(contained->getKeys());
1102}
1103
1104/*!
1105 This function determines whether field index i of the element has been
1106 set yet.
1107
1108 \return A boolean value that is TRUE if the specfied field of this
1109 element has been set and FALSE if the field has not yet been set
1110*/
1111bool DataElem::hasValidValue(int i) const
1112{
1113 if(!values.find(i))
1114 return FALSE;
1115 if(!contained->getKeys()->validIndex(i))
1116 return FALSE;
1117 return values.find(i)->isValid();
1118}
1119
1120/*!
1121 This function determines whether field name qs of the element has been
1122 set yet.
1123
1124 \return A boolean value that is TRUE if the specfied field of this
1125 element has been set and FALSE if the field has not yet been set
1126*/
1127bool DataElem::hasValidValue(QString qs) const
1128{
1129 int i = contained->getKeyIndex(qs);
1130 return hasValidValue(i);
1131}
1132
1133/*! returns the type of the field specified by index i */
1134TVVariant::KeyType DataElem::getFieldType(int i) const
1135{
1136 return contained->getKeyType(i);
1137}
1138
1139/*! returns the type of the field specified by name qs */
1140TVVariant::KeyType DataElem::getFieldType(QString qs) const
1141{
1142 int i = contained->getKeyIndex(qs);
1143 return contained->getKeyType(i);
1144}
1145
1146/*!
1147 returns a pointer to the data stored in field index i for this
1148 data element, (value may not be valid)
1149*/
1150TVVariant DataElem::getField(int i) const
1151{
1152 if(hasValidValue(i))
1153 return TVVariant(*values.find(i));
1154 return TVVariant();
1155}
1156
1157/*!
1158 returns a pointer to the data stored in field name qs for this
1159 data element, (value may not be valid)
1160*/
1161TVVariant DataElem::getField(QString qs) const
1162{
1163 int i = contained->getKeyIndex(qs);
1164 return getField(i);
1165}
1166
1167/*!
1168 Sets the value of the elements field index i to the value represented in
1169 the QString q.
1170
1171 \param i index of the field to set
1172 \param q a string that can be parsed to get the value to be set
1173*/
1174void DataElem::setField(int i, QString q)
1175{
1176 /* from the type of the field, parse q and store */
1177 TVVariant::KeyType kt = contained->getKeyType(i);
1178
1179 TVVariant t = TVVariant(q);
1180
1181 switch(kt) {
1182 case TVVariant::Int: {
1183 t.asInt();
1184 setField(i, t);
1185 return;
1186 }
1187 case TVVariant::String: {
1188 t.asString();
1189 setField(i, t);
1190 return;
1191 }
1192 case TVVariant::Date: {
1193 t.asDate();
1194 setField(i, t);
1195 return;
1196 }
1197 case TVVariant::Time: {
1198 t.asTime();
1199 setField(i, t);
1200 return;
1201 }
1202 default:
1203 qWarning(
1204 QObject::tr("DataElem::setField(%1, %2) No valid type found").arg(i).arg(q)
1205 );
1206 }
1207}
1208
1209/*!
1210 Sets the value of the elements field index i to the value at the pointer
1211 value.
1212
1213 \param i index of the field to set
1214 \param value a pointer to the (already allocated) value to set
1215*/
1216void DataElem::setField(int i, TVVariant value)
1217{
1218 if (value.isValid()) {
1219 values.remove(i);
1220 values.replace(i, new TVVariant(value));
1221 }
1222}
1223
1224/*!
1225 Sets the value of the elements field name qs to the value represented in
1226 the QString q.
1227
1228 \param qs name of the field to set
1229 \param q a string that can be parsed to get the value to be set
1230*/
1231void DataElem::setField(QString qs, QString q)
1232{
1233 /* from the type of the field, parse q and store */
1234 int i = contained->getKeyIndex(qs);
1235 setField(i, qs);
1236}
1237
1238/*!
1239 Sets the value of the elements field name qs to the value at the pointer
1240 value.
1241
1242 \param qs name of the field to set
1243 \param value a pointer to the (already allocated) value to set
1244*/
1245void DataElem::setField(QString qs, TVVariant value)
1246{
1247 int i = contained->getKeyIndex(qs);
1248 setField(i, value);
1249}
1250
1251void DataElem::unsetField(int i) {
1252 values.remove(i);
1253}
1254
1255void DataElem::unsetField(QString qs)
1256{
1257 int i = contained->getKeyIndex(qs);
1258 unsetField(i);
1259}
1260
1261/*!
1262 Converts the data element to a Rich Text QString
1263*/
1264QString DataElem::toQString() const
1265{
1266 /* lets make an attempt at this function */
1267 int i;
1268 QString scratch = "";
1269
1270 QIntDictIterator<TVVariant> it(values);
1271
1272 while (it.current()) {
1273 i = it.currentKey();
1274 if(hasValidValue(i)) {
1275 scratch += "<B>" + contained->getKeyName(i) + ":</B> ";
1276 scratch += getField(i).toString();
1277 scratch += "<br>";
1278 }
1279 ++it;
1280 }
1281 return scratch;
1282}
1283
1284/*! formats individual fields to strings so can be displayed */
1285QString DataElem::toQString(int i) const
1286{
1287 if(hasValidValue(i)) {
1288 return getField(i).toString();
1289 }
1290 return "";
1291}
1292/*! formats individual fields to strings so can be sorted by QListView */
1293QString DataElem::toSortableQString(int i) const
1294{
1295 QString scratch = "";
1296 if(hasValidValue(i)) {
1297 switch (contained->getKeyType(i)) {
1298 case TVVariant::String: {
1299 scratch += getField(i).toString();
1300 break;
1301 }
1302 case TVVariant::Int: {
1303 scratch.sprintf("%08d", getField(i).toInt());
1304 break;
1305 }
1306 case TVVariant::Date: {
1307 static QDate epochD(1800, 1, 1);
1308 scratch.sprintf("%08d",
1309 epochD.daysTo(getField(i).toDate()));
1310 break;
1311 }
1312 case TVVariant::Time: {
1313 static QTime epochT(0, 0, 0);
1314 scratch.sprintf("%08d",
1315 epochT.msecsTo(getField(i).toTime()));
1316 break;
1317 }
1318 default:
1319 scratch += "Unknown type";
1320 break;
1321 }
1322 }
1323 return scratch;
1324}
1325
1326/* compare functions */
1327
1328bool DataElem::lessThan(int i, TVVariant v) const
1329{
1330 if (!hasValidValue(i)) return FALSE;
1331
1332 if (getField(i).type() != v.type())
1333 return FALSE;
1334
1335 return (getField(i) < v);
1336}
1337
1338bool DataElem::moreThan(int i, TVVariant v) const
1339{
1340 if (!hasValidValue(i)) return FALSE;
1341
1342 if (getField(i).type() != v.type())
1343 return FALSE;
1344
1345 return (getField(i) > v);
1346}
1347
1348bool DataElem::equalTo(int i, TVVariant v) const
1349{
1350 if (!hasValidValue(i)) return FALSE;
1351
1352 if (getField(i).type() != v.type())
1353 return FALSE;
1354
1355 return (getField(i) == v);
1356}
1357
1358bool DataElem::contains(int i, TVVariant v) const
1359{
1360 if (!hasValidValue(i)) return FALSE;
1361
1362 if (getField(i).type() != v.type())
1363 return FALSE;
1364
1365 switch(getField(i).type()) {
1366 case TVVariant::String: {
1367 QString qs1 = getField(i).toString().lower();
1368 QString qs2 = v.toString().lower();
1369 if (qs1.contains(qs2) > 0) return TRUE;
1370 break;
1371 }
1372 /* meaningless for ints */
1373 /* meaningless for time */
1374 /* meaningless for dates */
1375 case TVVariant::Int:
1376 case TVVariant::Time:
1377 case TVVariant::Date:
1378 break;
1379 default:
1380 qWarning("Tried to compare unknown data type");
1381 }
1382 return FALSE;
1383}
1384
1385bool DataElem::startsWith(int i, TVVariant v) const
1386{
1387 if (!hasValidValue(i)) return FALSE;
1388
1389 if (getField(i).type() != v.type())
1390 return FALSE;
1391
1392 switch(getField(i).type()) {
1393 case TVVariant::String: {
1394 QString qs1 = getField(i).toString().lower();
1395 QString qs2 = v.toString().lower();
1396 return qs1.startsWith(qs2);
1397 }
1398 /* meaningless for ints */
1399 /* meaningless for time */
1400 /* meaningless for dates */
1401 case TVVariant::Int:
1402 case TVVariant::Time:
1403 case TVVariant::Date:
1404 return FALSE;
1405 default:
1406 qWarning("Tried to compare unknown data type");
1407 }
1408 return FALSE;
1409}
1410
1411bool DataElem::endsWith(int i, TVVariant v) const
1412{
1413 if (!hasValidValue(i)) return FALSE;
1414
1415 if (getField(i).type() != v.type())
1416 return FALSE;
1417
1418 switch(getField(i).type()) {
1419 case TVVariant::String: {
1420 QString qs1 = getField(i).toString().lower();
1421 QString qs2 = v.toString().lower();
1422 return qs1.startsWith(qs2);
1423 }
1424 /* meaningless for ints */
1425 /* meaningless for time */
1426 /* meaningless for dates */
1427 case TVVariant::Int:
1428 case TVVariant::Time:
1429 case TVVariant::Date:
1430 return FALSE;
1431 default:
1432 qWarning("Tried to compare unknown data type");
1433 }
1434 return FALSE;
1435}
1436
1437/*!
1438 Determins which of the first to parameters are closer to the third, target
1439 parameter.
1440
1441 \return
1442 <UL>
1443 <LI>TRUE if the first element is a closer match to the target than the
1444 second element</LI>
1445 <LI>FALSE if the first element is not a closer match to the target than
1446 the second element</LI>
1447 </UL>
1448*/
1449bool DataElem::closer(DataElem*d1, DataElem *d2, TVVariant target, int column)
1450{
1451 int type;
1452
1453 if(!d1) return FALSE;
1454
1455 if (!d1->hasValidValue(column)) return FALSE;
1456
1457 if(!target.isValid()) return FALSE;
1458
1459 type = d1->getField(column).type();
1460
1461 if(d2) {
1462 if (type != d2->getField(column).type()) {
1463 /* can't do compare */
1464 qWarning("Tried to compare two incompatable types");
1465 return FALSE;
1466 }
1467 return target.closer(d1->getField(column), d2->getField(column));
1468 }
1469 return target.close(d1->getField(column));
1470}