~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kexi/kexidb/field.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
 
3
   Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
 
4
   Copyright (C) 2003-2007 Jarosław Staniek <staniek@kde.org>
 
5
 
 
6
   This library is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Library General Public
 
8
   License as published by the Free Software Foundation; either
 
9
   version 2 of the License, or (at your option) any later version.
 
10
 
 
11
   This library is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
   Library General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU Library General Public License
 
17
   along with this library; see the file COPYING.LIB.  If not, write to
 
18
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA 02110-1301, USA.
 
20
 */
 
21
 
 
22
#include "field.h"
 
23
#include "connection.h"
 
24
#include "driver.h"
 
25
#include "expression.h"
 
26
#include "utils.h"
 
27
 
 
28
// we use here i18n() but this depends on kde libs: TODO: add #ifdefs
 
29
#include <kdebug.h>
 
30
#include <klocale.h>
 
31
 
 
32
#include <qdatetime.h>
 
33
 
 
34
#include <assert.h>
 
35
 
 
36
#include "kexidb_global.h"
 
37
 
 
38
using namespace KexiDB;
 
39
 
 
40
Field::FieldTypeNames Field::m_typeNames;
 
41
Field::FieldTypeGroupNames Field::m_typeGroupNames;
 
42
 
 
43
Field::Field()
 
44
{
 
45
    init();
 
46
    setConstraints(NoConstraints);
 
47
}
 
48
 
 
49
 
 
50
Field::Field(TableSchema *tableSchema)
 
51
{
 
52
    init();
 
53
    m_parent = tableSchema;
 
54
    m_order = tableSchema->fieldCount();
 
55
    setConstraints(NoConstraints);
 
56
}
 
57
 
 
58
Field::Field(QuerySchema *querySchema, BaseExpr* expr)
 
59
{
 
60
    init();
 
61
    m_parent = querySchema;
 
62
    m_order = querySchema->fieldCount();
 
63
    setConstraints(NoConstraints);
 
64
    if (expr)
 
65
        setExpression(expr);
 
66
}
 
67
 
 
68
Field::Field(const QString& name, Type ctype,
 
69
             uint cconst, uint options, uint length, uint precision,
 
70
             QVariant defaultValue, const QString& caption, const QString& description,
 
71
             uint width)
 
72
        : m_parent(0)
 
73
        , m_name(name.toLower())
 
74
        , m_length(length)
 
75
        , m_precision(precision)
 
76
        , m_visibleDecimalPlaces(-1)
 
77
        , m_options(options)
 
78
        , m_defaultValue(defaultValue)
 
79
        , m_order(-1)
 
80
        , m_caption(caption)
 
81
        , m_desc(description)
 
82
        , m_width(width)
 
83
        , m_expr(0)
 
84
        , m_customProperties(0)
 
85
        , m_type(ctype)
 
86
{
 
87
    setConstraints(cconst);
 
88
    if (m_length == 0) {//0 means default length:
 
89
        if (m_type == Field::Text)
 
90
            m_length = defaultTextLength();
 
91
    }
 
92
}
 
93
 
 
94
/*! Copy constructor. */
 
95
Field::Field(const Field& f)
 
96
{
 
97
    (*this) = f;
 
98
    if (f.m_customProperties)
 
99
        m_customProperties = new CustomPropertiesMap(f.customProperties());
 
100
 
 
101
    if (f.m_expr) {//deep copy the expression
 
102
//TODO  m_expr = new BaseExpr(*f.m_expr);
 
103
 
 
104
//  m_expr->m_field = this;
 
105
    } else
 
106
        m_expr = 0;
 
107
}
 
108
 
 
109
Field::~Field()
 
110
{
 
111
    delete m_expr;
 
112
    delete m_customProperties;
 
113
}
 
114
 
 
115
Field* Field::copy() const
 
116
{
 
117
    return new Field(*this);
 
118
}
 
119
 
 
120
void Field::init()
 
121
{
 
122
    m_parent = 0;
 
123
    m_name = "";
 
124
    m_type = InvalidType;
 
125
    m_length = 0;
 
126
    m_precision = 0;
 
127
    m_visibleDecimalPlaces = -1;
 
128
    m_options = NoOptions;
 
129
    m_defaultValue = QVariant(QString());
 
130
    m_order = -1;
 
131
    m_width = 0;
 
132
    m_expr = 0;
 
133
    m_customProperties = 0;
 
134
}
 
135
 
 
136
Field::Type Field::type() const
 
137
{
 
138
    if (m_expr)
 
139
        return m_expr->type();
 
140
    return m_type;
 
141
}
 
142
 
 
143
QVariant::Type Field::variantType(uint type)
 
144
{
 
145
    switch (type) {
 
146
    case Byte:
 
147
    case ShortInteger:
 
148
    case Integer:
 
149
    case BigInteger:
 
150
        return QVariant::Int;
 
151
    case Boolean:
 
152
        return QVariant::Bool;
 
153
    case Date:
 
154
        return QVariant::Date;
 
155
    case DateTime:
 
156
        return QVariant::DateTime;
 
157
    case Time:
 
158
        return QVariant::Time;
 
159
    case Float:
 
160
    case Double:
 
161
        return QVariant::Double;
 
162
    case Text:
 
163
    case LongText:
 
164
        return QVariant::String;
 
165
    case BLOB:
 
166
        return QVariant::ByteArray;
 
167
    default:
 
168
        return QVariant::Invalid;
 
169
    }
 
170
 
 
171
    return QVariant::Invalid;
 
172
}
 
173
 
 
174
QString Field::typeName(uint type)
 
175
{
 
176
    m_typeNames.init();
 
177
    return m_typeNames.value(type, QString::number(type));
 
178
}
 
179
 
 
180
QStringList Field::typeNames()
 
181
{
 
182
    return m_typeNames.names;
 
183
}
 
184
 
 
185
QString Field::typeString(uint type)
 
186
{
 
187
    m_typeNames.init();
 
188
    return (type <= LastType) ? m_typeNames.at((int)LastType + 1 + type) : QString("Type%1").arg(type);
 
189
}
 
190
 
 
191
QString Field::typeGroupName(uint typeGroup)
 
192
{
 
193
    m_typeGroupNames.init();
 
194
    return (typeGroup <= LastTypeGroup) ? m_typeGroupNames.at(typeGroup) : typeGroupString(typeGroup);
 
195
}
 
196
 
 
197
QStringList Field::typeGroupNames()
 
198
{
 
199
    return m_typeGroupNames.names;
 
200
}
 
201
 
 
202
QString Field::typeGroupString(uint typeGroup)
 
203
{
 
204
    m_typeGroupNames.init();
 
205
    return m_typeGroupNames.value((int)LastTypeGroup + 1 + typeGroup, QString("TypeGroup%1").arg(typeGroup));
 
206
}
 
207
 
 
208
Field::Type Field::typeForString(const QString& typeString)
 
209
{
 
210
    m_typeNames.init();
 
211
    return m_typeNames.str2num.value(typeString.toLower(), InvalidType);
 
212
}
 
213
 
 
214
Field::TypeGroup Field::typeGroupForString(const QString& typeGroupString)
 
215
{
 
216
    m_typeGroupNames.init();
 
217
    return m_typeGroupNames.str2num.value(typeGroupString.toLower(), InvalidGroup);
 
218
}
 
219
 
 
220
bool Field::isIntegerType(uint type)
 
221
{
 
222
    switch (type) {
 
223
    case Field::Byte:
 
224
    case Field::ShortInteger:
 
225
    case Field::Integer:
 
226
    case Field::BigInteger:
 
227
        return true;
 
228
    default:;
 
229
    }
 
230
    return false;
 
231
}
 
232
 
 
233
bool Field::isNumericType(uint type)
 
234
{
 
235
    switch (type) {
 
236
    case Field::Byte:
 
237
    case Field::ShortInteger:
 
238
    case Field::Integer:
 
239
    case Field::BigInteger:
 
240
    case Field::Float:
 
241
    case Field::Double:
 
242
        return true;
 
243
    default:;
 
244
    }
 
245
    return false;
 
246
}
 
247
 
 
248
bool Field::isFPNumericType(uint type)
 
249
{
 
250
    return type == Field::Float || type == Field::Double;
 
251
}
 
252
 
 
253
bool Field::isDateTimeType(uint type)
 
254
{
 
255
    switch (type) {
 
256
    case Field::Date:
 
257
    case Field::DateTime:
 
258
    case Field::Time:
 
259
        return true;
 
260
    default:;
 
261
    }
 
262
    return false;
 
263
}
 
264
 
 
265
bool Field::isTextType(uint type)
 
266
{
 
267
    switch (type) {
 
268
    case Field::Text:
 
269
    case Field::LongText:
 
270
        return true;
 
271
    default:;
 
272
    }
 
273
    return false;
 
274
}
 
275
 
 
276
bool Field::hasEmptyProperty(uint type)
 
277
{
 
278
    return Field::isTextType(type) || type == BLOB;
 
279
}
 
280
 
 
281
bool Field::isAutoIncrementAllowed(uint type)
 
282
{
 
283
    return Field::isIntegerType(type);
 
284
}
 
285
 
 
286
Field::TypeGroup Field::typeGroup(uint type)
 
287
{
 
288
    if (Field::isTextType(type))
 
289
        return TextGroup;
 
290
    else if (Field::isIntegerType(type))
 
291
        return IntegerGroup;
 
292
    else if (Field::isFPNumericType(type))
 
293
        return FloatGroup;
 
294
    else if (type == Boolean)
 
295
        return BooleanGroup;
 
296
    else if (Field::isDateTimeType(type))
 
297
        return DateTimeGroup;
 
298
    else if (type == BLOB)
 
299
        return BLOBGroup;
 
300
 
 
301
    return InvalidGroup; //unknown
 
302
}
 
303
 
 
304
TableSchema*
 
305
Field::table() const
 
306
{
 
307
    return dynamic_cast<TableSchema*>(m_parent);
 
308
}
 
309
 
 
310
void
 
311
Field::setTable(TableSchema *tableSchema)
 
312
{
 
313
    m_parent = tableSchema;
 
314
}
 
315
 
 
316
QuerySchema*
 
317
Field::query() const
 
318
{
 
319
    return dynamic_cast<QuerySchema*>(m_parent);
 
320
}
 
321
 
 
322
void
 
323
Field::setQuery(QuerySchema *querySchema)
 
324
{
 
325
    m_parent = querySchema;
 
326
}
 
327
 
 
328
void
 
329
Field::setName(const QString& n)
 
330
{
 
331
    m_name = n.toLower();
 
332
}
 
333
 
 
334
void
 
335
Field::setType(Type t)
 
336
{
 
337
    if (m_expr) {
 
338
        KexiDBWarn << QString("Field::setType(%1)").arg(t)
 
339
        << " could not set type because the field has expression assigned!";
 
340
        return;
 
341
    }
 
342
    m_type = t;
 
343
}
 
344
 
 
345
void
 
346
Field::setConstraints(uint c)
 
347
{
 
348
    m_constraints = c;
 
349
    //pkey must be unique notnull
 
350
    if (isPrimaryKey()) {
 
351
        setPrimaryKey(true);
 
352
    }
 
353
    if (isIndexed()) {
 
354
        setIndexed(true);
 
355
    }
 
356
    if (isAutoIncrement() && !isAutoIncrementAllowed()) {
 
357
        setAutoIncrement(false);
 
358
    }
 
359
}
 
360
 
 
361
void
 
362
Field::setLength(uint l)
 
363
{
 
364
    if (type() != Field::Text)
 
365
        return;
 
366
    m_length = l;
 
367
}
 
368
 
 
369
void
 
370
Field::setPrecision(uint p)
 
371
{
 
372
    if (!isFPNumericType())
 
373
        return;
 
374
    m_precision = p;
 
375
}
 
376
 
 
377
void
 
378
Field::setScale(uint s)
 
379
{
 
380
    if (!isFPNumericType())
 
381
        return;
 
382
    m_length = s;
 
383
}
 
384
 
 
385
void
 
386
Field::setVisibleDecimalPlaces(int p)
 
387
{
 
388
    if (!KexiDB::supportsVisibleDecimalPlacesProperty(type()))
 
389
        return;
 
390
    m_visibleDecimalPlaces = p < 0 ? -1 : p;
 
391
}
 
392
 
 
393
void
 
394
Field::setUnsigned(bool u)
 
395
{
 
396
    m_options |= Unsigned;
 
397
    m_options ^= (!u * Unsigned);
 
398
}
 
399
 
 
400
void
 
401
Field::setDefaultValue(const QVariant& def)
 
402
{
 
403
    m_defaultValue = def;
 
404
}
 
405
 
 
406
bool
 
407
Field::setDefaultValue(const QByteArray& def)
 
408
{
 
409
    if (def.isNull()) {
 
410
        m_defaultValue = QVariant();
 
411
        return true;
 
412
    }
 
413
 
 
414
    bool ok;
 
415
    switch (type()) {
 
416
    case Byte: {
 
417
        unsigned int v = def.toUInt(&ok);
 
418
        if (!ok || v > 255)
 
419
            m_defaultValue = QVariant();
 
420
        else
 
421
            m_defaultValue = QVariant(v);
 
422
        break;
 
423
    }
 
424
    case ShortInteger: {
 
425
        int v = def.toInt(&ok);
 
426
        if (!ok || (!(m_options & Unsigned) && (v < -32768 || v > 32767)) || ((m_options & Unsigned) && (v < 0 || v > 65535)))
 
427
            m_defaultValue = QVariant();
 
428
        else
 
429
            m_defaultValue = QVariant(v);
 
430
        break;
 
431
    }
 
432
    case Integer: {//4 bytes
 
433
        long v = def.toLong(&ok);
 
434
//js: FIXME   if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))) || ((m_options & Unsigned) && (v < 0 || v > 0x100000000)))
 
435
        if (!ok || (!(m_options & Unsigned) && (-v > (int)0x07FFFFFFF || v > (int)(0x080000000 - 1))))
 
436
            m_defaultValue = QVariant();
 
437
        else
 
438
            m_defaultValue = QVariant((qint64)v);
 
439
        break;
 
440
    }
 
441
    case BigInteger: {//8 bytes
 
442
//! @todo BigInteger support
 
443
        /*
 
444
              qint64 long v = def.toLongLong(&ok);
 
445
        //TODO: 2-part decoding
 
446
              if (!ok || (!(m_options & Unsigned) && (-v > 0x080000000 || v > (0x080000000-1))))
 
447
                m_defaultValue = QVariant();
 
448
              else
 
449
                if (m_options & Unsigned)
 
450
                  m_defaultValue=QVariant((quint64) v);
 
451
                else
 
452
                  m_defaultValue = QVariant((qint64)v);*/
 
453
        break;
 
454
    }
 
455
    case Boolean: {
 
456
        unsigned short v = def.toUShort(&ok);
 
457
        if (!ok || v > 1)
 
458
            m_defaultValue = QVariant();
 
459
        else
 
460
            m_defaultValue = QVariant((bool)v);
 
461
        break;
 
462
    }
 
463
    case Date: {//YYYY-MM-DD
 
464
        QDate date = QDate::fromString(def, Qt::ISODate);
 
465
        if (!date.isValid())
 
466
            m_defaultValue = QVariant();
 
467
        else
 
468
            m_defaultValue = QVariant(date);
 
469
        break;
 
470
    }
 
471
    case DateTime: {//YYYY-MM-DDTHH:MM:SS
 
472
        QDateTime dt = QDateTime::fromString(def, Qt::ISODate);
 
473
        if (!dt.isValid())
 
474
            m_defaultValue = QVariant();
 
475
        else
 
476
            m_defaultValue = QVariant(dt);
 
477
        break;
 
478
    }
 
479
    case Time: {//HH:MM:SS
 
480
        QTime time = QTime::fromString(def, Qt::ISODate);
 
481
        if (!time.isValid())
 
482
            m_defaultValue = QVariant();
 
483
        else
 
484
            m_defaultValue = QVariant(time);
 
485
        break;
 
486
    }
 
487
    case Float: {
 
488
        float v = def.toFloat(&ok);
 
489
        if (!ok || ((m_options & Unsigned) && (v < 0.0)))
 
490
            m_defaultValue = QVariant();
 
491
        else
 
492
            m_defaultValue = QVariant(v);
 
493
        break;
 
494
    }
 
495
    case Double: {
 
496
        double v = def.toDouble(&ok);
 
497
        if (!ok || ((m_options & Unsigned) && (v < 0.0)))
 
498
            m_defaultValue = QVariant();
 
499
        else
 
500
            m_defaultValue = QVariant(v);
 
501
        break;
 
502
    }
 
503
    case Text: {
 
504
        if (def.isNull() || (def.length() > 255))
 
505
            m_defaultValue = QVariant();
 
506
        else
 
507
            m_defaultValue = QVariant((QString)def);
 
508
        break;
 
509
    }
 
510
    case LongText: {
 
511
        if (def.isNull())
 
512
            m_defaultValue = QVariant();
 
513
        else
 
514
            m_defaultValue = QVariant((QString)def);
 
515
        break;
 
516
    }
 
517
    case BLOB: {
 
518
//TODO
 
519
        if (def.isNull())
 
520
            m_defaultValue = QVariant();
 
521
        else
 
522
            m_defaultValue = QVariant(def);
 
523
        break;
 
524
    }
 
525
    default:
 
526
        m_defaultValue = QVariant();
 
527
    }
 
528
    return m_defaultValue.isNull();
 
529
}
 
530
 
 
531
void
 
532
Field::setAutoIncrement(bool a)
 
533
{
 
534
    if (a && !isAutoIncrementAllowed())
 
535
        return;
 
536
    if (isAutoIncrement() != a)
 
537
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::AutoInc);
 
538
}
 
539
 
 
540
void
 
541
Field::setPrimaryKey(bool p)
 
542
{
 
543
    if (isPrimaryKey() != p)
 
544
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::PrimaryKey);
 
545
    if (p) {//also set implied constraints
 
546
        setUniqueKey(true);
 
547
        setNotNull(true);
 
548
        setNotEmpty(true);
 
549
        setIndexed(true);
 
550
    } else {
 
551
//! \todo is this ok for all engines?
 
552
        setAutoIncrement(false);
 
553
    }
 
554
}
 
555
 
 
556
void
 
557
Field::setUniqueKey(bool u)
 
558
{
 
559
    if (isUniqueKey() != u) {
 
560
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Unique);
 
561
        if (u) { //also set implied constraints
 
562
            setNotNull(true);
 
563
            setIndexed(true);
 
564
        }
 
565
    }
 
566
}
 
567
 
 
568
void
 
569
Field::setForeignKey(bool f)
 
570
{
 
571
    if (isForeignKey() != f)
 
572
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::ForeignKey);
 
573
}
 
574
 
 
575
void
 
576
Field::setNotNull(bool n)
 
577
{
 
578
    if (isNotNull() != n)
 
579
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotNull);
 
580
}
 
581
 
 
582
void Field::setNotEmpty(bool n)
 
583
{
 
584
    if (isNotEmpty() != n)
 
585
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::NotEmpty);
 
586
}
 
587
 
 
588
void Field::setIndexed(bool s)
 
589
{
 
590
    if (isIndexed() != s)
 
591
        m_constraints = static_cast<Field::Constraints>(m_constraints ^ Field::Indexed);
 
592
    if (!s) {//also set implied constraints
 
593
        setPrimaryKey(false);
 
594
        setUniqueKey(false);
 
595
        setNotNull(false);
 
596
        setNotEmpty(false);
 
597
    }
 
598
}
 
599
 
 
600
 
 
601
QString Field::debugString() const
 
602
{
 
603
    KexiDB::Connection *conn = table() ? table()->connection() : 0;
 
604
    QString dbg = (m_name.isEmpty() ? "<NONAME> " : m_name + " ");
 
605
    if (m_options & Field::Unsigned)
 
606
        dbg += " UNSIGNED ";
 
607
    dbg += (conn && conn->driver()) ? conn->driver()->sqlTypeName(type()) : Driver::defaultSQLTypeName(type());
 
608
    if (isFPNumericType() && m_precision > 0) {
 
609
        if (scale() > 0)
 
610
            dbg += QString::fromLatin1("(%1,%2)").arg(m_precision).arg(scale());
 
611
        else
 
612
            dbg += QString::fromLatin1("(%1)").arg(m_precision);
 
613
    } else if (m_type == Field::Text && m_length > 0)
 
614
        dbg += QString::fromLatin1("(%1)").arg(m_length);
 
615
    if (m_constraints & Field::AutoInc)
 
616
        dbg += " AUTOINC";
 
617
    if (m_constraints & Field::Unique)
 
618
        dbg += " UNIQUE";
 
619
    if (m_constraints & Field::PrimaryKey)
 
620
        dbg += " PKEY";
 
621
    if (m_constraints & Field::ForeignKey)
 
622
        dbg += " FKEY";
 
623
    if (m_constraints & Field::NotNull)
 
624
        dbg += " NOTNULL";
 
625
    if (m_constraints & Field::NotEmpty)
 
626
        dbg += " NOTEMPTY";
 
627
    if (!m_defaultValue.isNull())
 
628
        dbg += QString(" DEFAULT=[%1]").arg(m_defaultValue.typeName()) + KexiDB::variantToString(m_defaultValue);
 
629
    if (m_expr)
 
630
        dbg += " EXPRESSION=" + m_expr->debugString();
 
631
    if (m_customProperties && !m_customProperties->isEmpty()) {
 
632
        dbg += QString(" CUSTOM PROPERTIES (%1): ").arg(m_customProperties->count());
 
633
        bool first = true;
 
634
        for (CustomPropertiesMap::ConstIterator it(m_customProperties->constBegin());
 
635
                it != m_customProperties->constEnd(); ++it) {
 
636
            if (first)
 
637
                first = false;
 
638
            else
 
639
                dbg += ", ";
 
640
            dbg += QString("%1 = %2 (%3)").arg(QString(it.key())).arg(it.value().toString())
 
641
                   .arg(it.value().typeName());
 
642
        }
 
643
    }
 
644
    return dbg;
 
645
}
 
646
 
 
647
void Field::debug()
 
648
{
 
649
    KexiDBDbg << debugString();
 
650
}
 
651
 
 
652
void Field::setExpression(KexiDB::BaseExpr *expr)
 
653
{
 
654
    assert(!m_parent || dynamic_cast<QuerySchema*>(m_parent));
 
655
    if (m_expr == expr)
 
656
        return;
 
657
    if (m_expr) {
 
658
        delete m_expr;
 
659
    }
 
660
    m_expr = expr;
 
661
}
 
662
 
 
663
QVariant Field::customProperty(const QByteArray& propertyName,
 
664
                               const QVariant& defaultValue) const
 
665
{
 
666
    if (!m_customProperties)
 
667
        return defaultValue;
 
668
    return m_customProperties->value(propertyName, defaultValue);
 
669
}
 
670
 
 
671
void Field::setCustomProperty(const QByteArray& propertyName, const QVariant& value)
 
672
{
 
673
    if (propertyName.isEmpty())
 
674
        return;
 
675
    if (!m_customProperties)
 
676
        m_customProperties = new CustomPropertiesMap();
 
677
    m_customProperties->insert(propertyName, value);
 
678
}
 
679
 
 
680
//-------------------------------------------------------
 
681
#define ADDTYPE(type, i18, str) \
 
682
    (*this)[Field::type] = i18; \
 
683
    (*this)[Field::type+Field::LastType+1] = str; \
 
684
    str2num[ QString::fromLatin1(str).toLower() ] = type; \
 
685
    names.append(i18)
 
686
#define ADDGROUP(type, i18, str) \
 
687
    (*this)[Field::type] = i18; \
 
688
    (*this)[Field::type+Field::LastTypeGroup+1] = str; \
 
689
    str2num[ QString::fromLatin1(str).toLower() ] = type; \
 
690
    names.append(i18)
 
691
 
 
692
Field::FieldTypeNames::FieldTypeNames()
 
693
        : QVector<QString>()
 
694
        , m_initialized(false)
 
695
{
 
696
}
 
697
 
 
698
void Field::FieldTypeNames::init()
 
699
{
 
700
    if (m_initialized)
 
701
        return;
 
702
    m_initialized = true;
 
703
    resize((Field::LastType + 1)*2);
 
704
 
 
705
    ADDTYPE(InvalidType, i18n("Invalid Type"), "InvalidType");
 
706
    ADDTYPE(Byte, i18n("Byte"), "Byte");
 
707
    ADDTYPE(ShortInteger, i18n("Short Integer Number"), "ShortInteger");
 
708
    ADDTYPE(Integer, i18n("Integer Number"), "Integer");
 
709
    ADDTYPE(BigInteger, i18n("Big Integer Number"), "BigInteger");
 
710
    ADDTYPE(Boolean, i18n("Yes/No Value"), "Boolean");
 
711
    ADDTYPE(Date, i18n("Date"), "Date");
 
712
    ADDTYPE(DateTime, i18n("Date and Time"), "DateTime");
 
713
    ADDTYPE(Time, i18n("Time"), "Time");
 
714
    ADDTYPE(Float, i18n("Single Precision Number"), "Float");
 
715
    ADDTYPE(Double, i18n("Double Precision Number"), "Double");
 
716
    ADDTYPE(Text, i18n("Text"), "Text");
 
717
    ADDTYPE(LongText, i18n("Long Text"), "LongText");
 
718
    ADDTYPE(BLOB, i18n("Object"), "BLOB");
 
719
}
 
720
 
 
721
//-------------------------------------------------------
 
722
 
 
723
Field::FieldTypeGroupNames::FieldTypeGroupNames()
 
724
        : QVector<QString>()
 
725
        , m_initialized(false)
 
726
{
 
727
}
 
728
 
 
729
void Field::FieldTypeGroupNames::init()
 
730
{
 
731
    if (m_initialized)
 
732
        return;
 
733
    m_initialized = true;
 
734
    resize((Field::LastTypeGroup + 1)*2);
 
735
 
 
736
    ADDGROUP(InvalidGroup, i18n("Invalid Group"), "InvalidGroup");
 
737
    ADDGROUP(TextGroup, i18n("Text"), "TextGroup");
 
738
    ADDGROUP(IntegerGroup, i18n("Integer Number"), "IntegerGroup");
 
739
    ADDGROUP(FloatGroup, i18n("Floating Point Number"), "FloatGroup");
 
740
    ADDGROUP(BooleanGroup, i18n("Yes/No"), "BooleanGroup");
 
741
    ADDGROUP(DateTimeGroup, i18n("Date/Time"), "DateTimeGroup");
 
742
    ADDGROUP(BLOBGroup, i18n("Object"), "BLOBGroup");
 
743
}
 
744
 
 
745
//-------------------------------------------------------
 
746