~ubuntu-branches/ubuntu/oneiric/koffice/oneiric-updates

« back to all changes in this revision

Viewing changes to kspread/Condition.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2010-10-27 17:52:57 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101027175257-s04zqqk5bs8ckm9o
Tags: 1:2.2.83-0ubuntu1
* Merge with Debian git remaining changes:
 - Add build-deps on librcps-dev, opengtl-dev, libqtgtl-dev, freetds-dev,
   create-resources, libspnav-dev
 - Remove needless build-dep on libwv2-dev
 - koffice-libs recommends create-resources
 - krita recommends pstoedit
 - Keep our patches
* New upstream release 2.3 beta 3
  - Remove debian/patches fixed by upstream
  - Update install files

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* This file is part of the KDE project
 
2
   Copyright 2010 Marijn Kruisselbrink <m.kruisselbrink@student.tue.nl>
2
3
   Copyright 1998, 1999 Torben Weis <weis@kde.org>
3
4
   Copyright 1999- 2006 The KSpread Team <koffice-devel@kde.org>
4
5
 
24
25
#include <float.h>
25
26
 
26
27
#include "Cell.h"
 
28
#include "Formula.h"
 
29
#include "Map.h"
 
30
#include "NamedAreaManager.h"
 
31
#include "Region.h"
27
32
#include "Sheet.h"
28
33
#include "Style.h"
29
34
#include "StyleManager.h"
30
35
#include "Util.h"
 
36
#include "ValueCalc.h"
 
37
#include "ValueConverter.h"
 
38
#include "ValueParser.h"
31
39
 
32
40
#include <KoGenStyles.h>
33
41
 
45
53
/////////////////////////////////////////////////////////////////////////////
46
54
 
47
55
Conditional::Conditional()
48
 
        : val1(0.0)
49
 
        , val2(0.0)
50
 
        , strVal1(0)
51
 
        , strVal2(0)
52
 
        , colorcond(0)
53
 
        , fontcond(0)
54
 
        , styleName(0)
55
 
        , cond(None)
56
 
{
57
 
}
58
 
 
59
 
Conditional::~Conditional()
60
 
{
61
 
    delete strVal1;
62
 
    delete strVal2;
63
 
    delete colorcond;
64
 
    delete fontcond;
65
 
    delete styleName;
66
 
}
67
 
 
68
 
Conditional::Conditional(const Conditional& o)
69
 
{
70
 
    strVal1 = o.strVal1 ? new QString(*o.strVal1) : 0;
71
 
    strVal2 = o.strVal2 ? new QString(*o.strVal2) : 0;
72
 
    styleName = o.styleName ? new QString(*o.styleName) : 0;
73
 
    fontcond = o.fontcond ? new QFont(*o.fontcond) : 0;
74
 
    colorcond = o.colorcond ? new QColor(*o.colorcond) : 0;
75
 
    val1  = o.val1;
76
 
    val2  = o.val2;
77
 
    cond  = o.cond;
78
 
}
79
 
 
80
 
Conditional& Conditional::operator=(const Conditional & o)
81
 
{
82
 
    delete strVal1;
83
 
    delete strVal2;
84
 
    delete styleName;
85
 
    delete fontcond;
86
 
    delete colorcond;
87
 
    strVal1 = o.strVal1 ? new QString(*o.strVal1) : 0;
88
 
    strVal2 = o.strVal2 ? new QString(*o.strVal2) : 0;
89
 
    styleName = o.styleName ? new QString(*o.styleName) : 0;
90
 
    fontcond = o.fontcond ? new QFont(*o.fontcond) : 0;
91
 
    colorcond = o.colorcond ? new QColor(*o.colorcond) : 0;
92
 
    val1  = o.val1;
93
 
    val2  = o.val2;
94
 
    cond  = o.cond;
95
 
 
96
 
    return *this;
97
 
}
98
 
 
99
 
bool Conditional::operator==(const Conditional& other) const
100
 
{
101
 
    return (cond == other.cond &&
102
 
            val1 == other.val1 &&
103
 
            val2 == other.val2 &&
104
 
            (strVal1 && other.strVal1) ? (*strVal1 == *other.strVal1) : (strVal1 == other.strVal1) &&
105
 
            (strVal2 && other.strVal2) ? (*strVal2 == *other.strVal2) : (strVal2 == other.strVal2) &&
106
 
            (colorcond && other.strVal2) ? (*colorcond == *other.colorcond) : (colorcond == other.colorcond) &&
107
 
            (fontcond && other.fontcond) ? (*fontcond == *other.fontcond) : (fontcond == other.fontcond) &&
108
 
            (styleName && other.styleName) ? (*styleName == *other.styleName) : (styleName == other.styleName) );
109
 
}
110
 
 
111
 
 
 
56
    : cond(None)
 
57
{
 
58
}
 
59
 
 
60
bool Conditional::operator==(const Conditional &other) const
 
61
{
 
62
    if (cond != other.cond) {
 
63
        return false;
 
64
    }
 
65
    if (!value1.equal(other.value1)) {
 
66
        return false;
 
67
    }
 
68
    if (!value2.equal(other.value2)) {
 
69
        return false;
 
70
    }
 
71
    return styleName == other.styleName;
 
72
}
112
73
/////////////////////////////////////////////////////////////////////////////
113
74
//
114
75
// Conditions
119
80
{
120
81
public:
121
82
    QLinkedList<Conditional> conditionList;
 
83
    Style defaultStyle;
122
84
};
123
85
 
124
86
Conditions::Conditions()
140
102
    return d->conditionList.isEmpty();
141
103
}
142
104
 
143
 
Style* Conditions::testConditions(const Cell& cell, const StyleManager* styleManager) const
 
105
Style Conditions::testConditions( const Cell& cell ) const
144
106
{
145
107
    Conditional condition;
146
 
    if (currentCondition(cell, condition) && condition.styleName)
147
 
        return styleManager->style(*condition.styleName);
148
 
    else
149
 
        return 0;
 
108
    if (currentCondition(cell, condition)) {
 
109
        StyleManager *const styleManager = cell.sheet()->map()->styleManager();
 
110
        Style *const style = styleManager->style(condition.styleName);
 
111
        if (style)
 
112
            return *style;
 
113
    }
 
114
    return d->defaultStyle;
150
115
}
151
116
 
152
117
bool Conditions::currentCondition(const Cell& cell, Conditional & condition) const
153
118
{
154
119
    /* for now, the first condition that is true is the one that will be used */
155
120
 
 
121
    const Value value = cell.value();
 
122
    ValueCalc *const calc = cell.sheet()->map()->calc();
 
123
 
156
124
    QLinkedList<Conditional>::const_iterator it;
157
 
    double value   = numToDouble(cell.value().asFloat());
158
 
    QString strVal = cell.value().asString();
159
 
 
160
 
 
161
125
    for (it = d->conditionList.begin(); it != d->conditionList.end(); ++it) {
162
126
        condition = *it;
 
127
//         kDebug() << "Checking condition resulting in applying" << it->styleName;
163
128
 
164
 
        if (condition.strVal1 && cell.value().isNumber())
 
129
        // The first value of the condition is always used and has to be
 
130
        // comparable to the cell's value.
 
131
        if (!value.allowComparison(condition.value1)) {
165
132
            continue;
 
133
        }
166
134
 
167
135
        switch (condition.cond) {
168
136
        case Conditional::Equal:
169
 
            if (condition.strVal1) {
170
 
                if (strVal == *condition.strVal1)
171
 
                    return true;
172
 
            } else
173
 
                if (value - condition.val1 < DBL_EPSILON &&
174
 
                        value - condition.val1 > (0.0 - DBL_EPSILON)) {
175
 
                    return true;
176
 
                }
 
137
            if (value.equal(condition.value1)) {
 
138
                return true;
 
139
            }
177
140
            break;
178
 
 
179
141
        case Conditional::Superior:
180
 
            if (condition.strVal1) {
181
 
                if (strVal > *condition.strVal1)
182
 
                    return true;
183
 
            } else
184
 
                if (value > condition.val1) {
185
 
                    return true;
186
 
                }
 
142
            if (value.greater(condition.value1)) {
 
143
                return true;
 
144
            }
187
145
            break;
188
 
 
189
146
        case Conditional::Inferior:
190
 
            if (condition.strVal1) {
191
 
                if (strVal < *condition.strVal1)
192
 
                    return true;
193
 
            } else
194
 
                if (value < condition.val1) {
195
 
                    return true;
196
 
                }
197
 
            break;
198
 
 
199
 
        case Conditional::SuperiorEqual :
200
 
            if (condition.strVal1) {
201
 
                if (strVal >= *condition.strVal1)
202
 
                    return true;
203
 
            } else
204
 
                if (value >= condition.val1) {
205
 
                    return true;
206
 
                }
207
 
            break;
208
 
 
209
 
        case Conditional::InferiorEqual :
210
 
            if (condition.strVal1) {
211
 
                if (strVal <= *condition.strVal1)
212
 
                    return true;
213
 
            } else
214
 
                if (value <= condition.val1) {
215
 
                    return true;
216
 
                }
217
 
            break;
218
 
 
219
 
        case Conditional::Between :
220
 
            if (condition.strVal1 && condition.strVal2) {
221
 
                if (strVal > *condition.strVal1 && strVal < *condition.strVal2)
222
 
                    return true;
223
 
            } else
224
 
                if ((value > qMin(condition.val1, condition.val2))
225
 
                        && (value < qMax(condition.val1, condition.val2))) {
226
 
                    return true;
227
 
                }
228
 
            break;
229
 
 
230
 
        case Conditional::Different :
231
 
            if (condition.strVal1 && condition.strVal2) {
232
 
                if (strVal < *condition.strVal1 || strVal > *condition.strVal2)
233
 
                    return true;
234
 
            } else
235
 
                if ((value < qMin(condition.val1, condition.val2))
236
 
                        || (value > qMax(condition.val1, condition.val2))) {
237
 
                    return true;
238
 
                }
239
 
            break;
240
 
        case Conditional::DifferentTo :
241
 
            if (condition.strVal1) {
242
 
                if (strVal != *condition.strVal1)
243
 
                    return true;
244
 
            } else
245
 
                if (value != condition.val1) {
246
 
                    return true;
247
 
                }
248
 
            break;
249
 
 
 
147
            if (value.less(condition.value1)) {
 
148
                return true;
 
149
            }
 
150
            break;
 
151
        case Conditional::SuperiorEqual:
 
152
            if (value.compare(condition.value1) >= 0) {
 
153
                return true;
 
154
            }
 
155
            break;
 
156
        case Conditional::InferiorEqual:
 
157
            if (value.compare(condition.value1) <= 0) {
 
158
                return true;
 
159
            }
 
160
            break;
 
161
        case Conditional::Between: {
 
162
            const QVector<Value> values(QVector<Value>() << condition.value1 << condition.value2);
 
163
            const Value min = calc->min(values);
 
164
            const Value max = calc->max(values);
 
165
            if (value.compare(min) >= 0 && value.compare(max) <= 0) {
 
166
                return true;
 
167
            }
 
168
            break;
 
169
        }
 
170
        case Conditional::Different: {
 
171
            const QVector<Value> values(QVector<Value>() << condition.value1 << condition.value2);
 
172
            const Value min = calc->min(values);
 
173
            const Value max = calc->max(values);
 
174
            if (value.greater(max) || value.less(min)) {
 
175
                return true;
 
176
            }
 
177
            break;
 
178
        }
 
179
        case Conditional::DifferentTo:
 
180
            if (!value.equal(condition.value1)) {
 
181
                return true;
 
182
            }
 
183
            break;
 
184
        case Conditional::IsTrueFormula:
 
185
            // TODO: do some caching
 
186
            if (isTrueFormula(cell, condition.value1.asString(), condition.baseCellAddress)) {
 
187
                return true;
 
188
            }
 
189
            break;
250
190
        default:
251
191
            break;
252
192
        }
254
194
    return false;
255
195
}
256
196
 
 
197
bool Conditions::isTrueFormula(const Cell &cell, const QString &formula, const QString &baseCellAddress) const
 
198
{
 
199
    Map* const map = cell.sheet()->map();
 
200
    ValueCalc *const calc = map->calc();
 
201
    Formula f(cell.sheet(), cell);
 
202
    f.setExpression('=' + formula);
 
203
    Region r(baseCellAddress, map, cell.sheet());
 
204
    if (r.isValid() && r.isSingular()) {
 
205
        QPoint basePoint = static_cast<Region::Point*>(*r.constBegin())->pos();
 
206
        QString newFormula('=');
 
207
        const Tokens tokens = f.tokens();
 
208
        for (int t = 0; t < tokens.count(); ++t) {
 
209
            const Token token = tokens[t];
 
210
            if (token.type() == Token::Cell || token.type() == Token::Range) {
 
211
                if (map->namedAreaManager()->contains(token.text())) {
 
212
                    newFormula.append(token.text());
 
213
                    continue;
 
214
                }
 
215
                const Region region(token.text(), map, cell.sheet());
 
216
                if (!region.isValid() || !region.isContiguous()) {
 
217
                    newFormula.append(token.text());
 
218
                    continue;
 
219
                }
 
220
                if (region.firstSheet() != r.firstSheet()) {
 
221
                    newFormula.append(token.text());
 
222
                    continue;
 
223
                }
 
224
                Region::Element* element = *region.constBegin();
 
225
                if (element->type() == Region::Element::Point) {
 
226
                    Region::Point* point = static_cast<Region::Point*>(element);
 
227
                    QPoint pos = point->pos();
 
228
                    if (!point->isRowFixed()) {
 
229
                        int delta = pos.y() - basePoint.y();
 
230
                        pos.setY(cell.row() + delta);
 
231
                    }
 
232
                    if (!point->isColumnFixed()) {
 
233
                        int delta = pos.x() - basePoint.x();
 
234
                        pos.setX(cell.column() + delta);
 
235
                    }
 
236
                    newFormula.append(Region(pos, cell.sheet()).name());
 
237
                } else {
 
238
                    Region::Range* range = static_cast<Region::Range*>(element);
 
239
                    QRect r = range->rect();
 
240
                    if (!range->isTopFixed()) {
 
241
                        int delta = r.top() - basePoint.y();
 
242
                        r.setTop(cell.row() + delta);
 
243
                    }
 
244
                    if (!range->isBottomFixed()) {
 
245
                        int delta = r.bottom() - basePoint.y();
 
246
                        r.setBottom(cell.row() + delta);
 
247
                    }
 
248
                    if (!range->isLeftFixed()) {
 
249
                        int delta = r.left() - basePoint.x();
 
250
                        r.setLeft(cell.column() + delta);
 
251
                    }
 
252
                    if (!range->isRightFixed()) {
 
253
                        int delta = r.right() - basePoint.x();
 
254
                        r.setRight(cell.column() + delta);
 
255
                    }
 
256
                    newFormula.append(Region(r, cell.sheet()).name());
 
257
                }
 
258
            } else {
 
259
                newFormula.append(token.text());
 
260
            }
 
261
        }
 
262
        f.setExpression(newFormula);
 
263
    }
 
264
    Value val = f.eval();
 
265
    return calc->conv()->asBoolean(val).asBoolean();
 
266
}
 
267
 
257
268
QLinkedList<Conditional> Conditions::conditionList() const
258
269
{
259
270
    return d->conditionList;
264
275
    d->conditionList = list;
265
276
}
266
277
 
267
 
void Conditions::saveOdfConditions(KoGenStyle &currentCellStyle) const
 
278
Style Conditions::defaultStyle() const
 
279
{
 
280
    return d->defaultStyle;
 
281
}
 
282
 
 
283
void Conditions::setDefaultStyle(const Style &style)
 
284
{
 
285
    d->defaultStyle = style;
 
286
}
 
287
 
 
288
void Conditions::saveOdfConditions(KoGenStyle &currentCellStyle, ValueConverter *converter) const
268
289
{
269
290
    //todo fix me with kspread old format!!!
270
291
    if (d->conditionList.isEmpty())
275
296
        Conditional condition = *it;
276
297
        //<style:map style:condition="cell-content()=45" style:apply-style-name="Default" style:base-cell-address="Sheet1.E10"/>
277
298
        QMap<QString, QString> map;
278
 
        map.insert("style:condition", saveOdfConditionValue(condition));
279
 
        map.insert("style:apply-style-name",  *(condition.styleName));
280
 
        //map.insert( ""style:base-cell-address", "..." );//todo
 
299
        map.insert("style:condition", saveOdfConditionValue(condition, converter));
 
300
        map.insert("style:apply-style-name", condition.styleName);
 
301
        if (!condition.baseCellAddress.isEmpty())
 
302
            map.insert("style:base-cell-address", condition.baseCellAddress);
281
303
        currentCellStyle.addStyleMap(map);
282
304
    }
283
305
}
284
306
 
285
 
QString Conditions::saveOdfConditionValue(Conditional &condition) const
 
307
QString Conditions::saveOdfConditionValue(const Conditional &condition, ValueConverter* converter) const
286
308
{
287
309
    //we can also compare text value.
288
310
    //todo adapt it.
291
313
    case Conditional::None:
292
314
        break;
293
315
    case Conditional::Equal:
294
 
        value = "cell-content()=";
295
 
        if (condition.strVal1)
296
 
            value += *condition.strVal1;
297
 
        else
298
 
            value += QString::number(condition.val1);
 
316
        value = "cell-content()=" + converter->asString(condition.value1).asString();
299
317
        break;
300
318
    case Conditional::Superior:
301
 
        value = "cell-content()>";
302
 
        if (condition.strVal1)
303
 
            value += *condition.strVal1;
304
 
        else
305
 
            value += QString::number(condition.val1);
 
319
        value = "cell-content()>" + converter->asString(condition.value1).asString();
306
320
        break;
307
321
    case Conditional::Inferior:
308
 
        value = "cell-content()<";
309
 
        if (condition.strVal1)
310
 
            value += *condition.strVal1;
311
 
        else
312
 
            value += QString::number(condition.val1);
 
322
        value = "cell-content()<" + converter->asString(condition.value1).asString();
313
323
        break;
314
324
    case Conditional::SuperiorEqual:
315
 
        value = "cell-content()>=";
316
 
        if (condition.strVal1)
317
 
            value += *condition.strVal1;
318
 
        else
319
 
            value += QString::number(condition.val1);
 
325
        value = "cell-content()>=" + converter->asString(condition.value1).asString();
320
326
        break;
321
327
    case Conditional::InferiorEqual:
322
 
        value = "cell-content()<=";
323
 
        if (condition.strVal1)
324
 
            value += *condition.strVal1;
325
 
        else
326
 
            value += QString::number(condition.val1);
 
328
        value = "cell-content()<=" + converter->asString(condition.value1).asString();
327
329
        break;
328
330
    case Conditional::Between:
329
331
        value = "cell-content-is-between(";
330
 
        if (condition.strVal1) {
331
 
            value += *condition.strVal1;
332
 
            value += ',';
333
 
            if (condition.strVal2)
334
 
                value += *condition.strVal2;
335
 
        } else {
336
 
            value += QString::number(condition.val1);
337
 
            value += ',';
338
 
            value += QString::number(condition.val2);
339
 
        }
 
332
        value += converter->asString(condition.value1).asString();
 
333
        value += ',';
 
334
        value += converter->asString(condition.value2).asString();
340
335
        value += ')';
341
336
        break;
342
337
    case Conditional::DifferentTo:
343
 
        value = "cell-content()!="; //FIXME not good here !
344
 
        if (condition.strVal1)
345
 
            value += *condition.strVal1;
346
 
        else
347
 
            value += QString::number(condition.val1);
 
338
        value = "cell-content()!=" + converter->asString(condition.value1).asString();
348
339
        break;
349
340
    case Conditional::Different:
350
341
        value = "cell-content-is-not-between(";
351
 
        if (condition.strVal1) {
352
 
            value += *condition.strVal1;
353
 
            value += ',';
354
 
            if (condition.strVal2)
355
 
                value += *condition.strVal2;
356
 
        } else {
357
 
            value += QString::number(condition.val1);
358
 
            value += ',';
359
 
            value += QString::number(condition.val2);
360
 
        }
 
342
        value += converter->asString(condition.value1).asString();
 
343
        value += ',';
 
344
        value += converter->asString(condition.value2).asString();
361
345
        value += ')';
362
346
        break;
 
347
    case Conditional::IsTrueFormula:
 
348
        value = "is-true-formula(";
 
349
        value += Odf::encodeFormula(condition.value1.asString());
 
350
        value += ")";
363
351
    }
364
352
    return value;
365
353
}
366
354
 
367
355
 
368
 
QDomElement Conditions::saveConditions(QDomDocument & doc) const
 
356
QDomElement Conditions::saveConditions(QDomDocument &doc, ValueConverter *converter) const
369
357
{
370
358
    QDomElement conditions = doc.createElement("condition");
371
359
    QLinkedList<Conditional>::const_iterator it;
387
375
        child.setAttribute("cond", (int) condition.cond);
388
376
 
389
377
        // TODO: saving in KSpread 1.1 | KSpread 1.2 format
390
 
        if (condition.strVal1) {
391
 
            child.setAttribute("strval1", *condition.strVal1);
392
 
            if (condition.strVal2)
393
 
                child.setAttribute("strval2", *condition.strVal2);
 
378
        if (condition.value1.isString()) {
 
379
            child.setAttribute("strval1", condition.value1.asString());
 
380
            if (!condition.value2.asString().isEmpty()) {
 
381
                child.setAttribute("strval2", condition.value2.asString());
 
382
            }
394
383
        } else {
395
 
            child.setAttribute("val1", condition.val1);
396
 
            child.setAttribute("val2", condition.val2);
 
384
            child.setAttribute("val1", converter->asString(condition.value1).asString());
 
385
            child.setAttribute("val2", converter->asString(condition.value2).asString());
397
386
        }
398
 
        if (condition.styleName) {
399
 
            child.setAttribute("style", *condition.styleName);
400
 
        } else {
401
 
            child.setAttribute("color", condition.colorcond->name());
402
 
            child.appendChild(NativeFormat::createElement("font", *condition.fontcond, doc));
 
387
        if (!condition.styleName.isEmpty()) {
 
388
            child.setAttribute("style", condition.styleName);
403
389
        }
404
390
 
405
391
        conditions.appendChild(child);
415
401
    }
416
402
}
417
403
 
418
 
Conditional Conditions::loadOdfCondition(const StyleManager* styleManager, const QString &conditionValue, const QString &applyStyleName)
 
404
Conditional Conditions::loadOdfCondition(const QString &conditionValue, const QString &applyStyleName,
 
405
                                         const QString& baseCellAddress, const ValueParser *parser)
419
406
{
420
 
    Q_UNUSED(styleManager);
421
 
    kDebug(36003) << "\tcondition:" << conditionValue;
 
407
    //kDebug(36003) << "\tcondition:" << conditionValue;
422
408
    Conditional newCondition;
423
 
    loadOdfConditionValue(conditionValue, newCondition);
 
409
    loadOdfConditionValue(conditionValue, newCondition, parser);
424
410
    if (!applyStyleName.isNull()) {
425
 
        kDebug(36003) << "\tstyle:" << applyStyleName;
426
 
        newCondition.styleName = new QString(applyStyleName);
 
411
        //kDebug(36003) << "\tstyle:" << applyStyleName;
 
412
        newCondition.styleName = applyStyleName;
427
413
    }
 
414
    newCondition.baseCellAddress = baseCellAddress;
428
415
    d->conditionList.append(newCondition);
429
416
    return newCondition;
430
417
}
431
418
 
432
 
void Conditions::loadOdfConditions(const StyleManager* styleManager, const KoXmlElement & element)
 
419
void Conditions::loadOdfConditions(const KoXmlElement &element, const ValueParser *parser, const StyleManager *styleManager)
433
420
{
434
421
    kDebug(36003) << "Loading conditional styles";
435
422
    KoXmlNode node(element);
 
423
 
436
424
    while (!node.isNull()) {
437
425
        KoXmlElement elementItem = node.toElement();
438
426
        if (elementItem.tagName() == "map" && elementItem.namespaceURI() == KoXmlNS::style) {
440
428
            QString applyStyleName;
441
429
            if (elementItem.hasAttributeNS(KoXmlNS::style, "apply-style-name"))
442
430
                applyStyleName = elementItem.attributeNS(KoXmlNS::style, "apply-style-name", QString());
443
 
            loadOdfCondition(styleManager, conditionValue, applyStyleName);
 
431
            if (!applyStyleName.isEmpty() && styleManager) {
 
432
                QString odfStyle = styleManager->openDocumentName(applyStyleName);
 
433
                if (!odfStyle.isEmpty()) applyStyleName = odfStyle;
 
434
            }
 
435
            QString baseCellAddress = elementItem.attributeNS(KoXmlNS::style, "base-cell-address");
 
436
            loadOdfCondition(conditionValue, applyStyleName, baseCellAddress, parser);
444
437
        }
445
438
        node = node.nextSibling();
446
439
    }
447
440
}
448
441
 
449
 
void Conditions::loadOdfConditionValue(const QString &styleCondition, Conditional &newCondition)
 
442
void Conditions::loadOdfConditionValue(const QString &styleCondition, Conditional &newCondition, const ValueParser *parser)
450
443
{
451
444
    QString val(styleCondition);
452
445
    if (val.contains("cell-content()")) {
453
446
        val = val.remove("cell-content()");
454
 
        loadOdfCondition(val, newCondition);
455
 
    }
456
 
    else if (val.contains("value()")) {
 
447
        loadOdfCondition(val, newCondition, parser);
 
448
    } else if (val.contains("value()")) {
457
449
        val = val.remove("value()");
458
 
        loadOdfCondition(val, newCondition);
 
450
        loadOdfCondition(val, newCondition, parser);
459
451
    }
460
452
 
461
453
    //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
464
456
        val = val.remove("cell-content-is-between(");
465
457
        val = val.remove(')');
466
458
        QStringList listVal = val.split(',', QString::SkipEmptyParts);
467
 
        loadOdfValidationValue(listVal, newCondition);
 
459
        loadOdfValidationValue(listVal, newCondition, parser);
468
460
        newCondition.cond = Conditional::Between;
469
 
    }
470
 
    else if (val.contains("cell-content-is-not-between(")) {
 
461
    } else if (val.contains("cell-content-is-not-between(")) {
471
462
        val = val.remove("cell-content-is-not-between(");
472
463
        val = val.remove(')');
473
464
        QStringList listVal = val.split(',', QString::SkipEmptyParts);
474
 
        loadOdfValidationValue(listVal, newCondition);
 
465
        loadOdfValidationValue(listVal, newCondition, parser);
475
466
        newCondition.cond = Conditional::Different;
 
467
    } else if (val.startsWith("is-true-formula(")) {
 
468
        val = val.mid(16);
 
469
        if (val.endsWith(")")) val = val.left(val.length() - 1);
 
470
        newCondition.cond = Conditional::IsTrueFormula;
 
471
        newCondition.value1 = Value(Odf::decodeFormula(val));
476
472
    }
477
473
}
478
474
 
479
 
void Conditions::loadOdfCondition(QString &valExpression, Conditional &newCondition)
 
475
void Conditions::loadOdfCondition(QString &valExpression, Conditional &newCondition, const ValueParser *parser)
480
476
{
481
477
    QString value;
482
478
    if (valExpression.indexOf("<=") == 0) {
500
496
        newCondition.cond = Conditional::Equal;
501
497
    } else
502
498
        kDebug(36003) << " I don't know how to parse it :" << valExpression;
503
 
    kDebug(36003) << "\tvalue:" << value;
504
 
    bool ok = false;
505
 
    newCondition.val1 = value.toDouble(&ok);
506
 
    if (!ok) {
507
 
        newCondition.val1 = value.toInt(&ok);
508
 
        if (!ok) {
509
 
            newCondition.strVal1 = new QString(value);
510
 
            kDebug(36003) << " Try to parse this value :" << value;
511
 
        }
 
499
    //kDebug(36003) << "\tvalue:" << value;
 
500
 
 
501
    if (value.length() > 1 && value[0] == '"' && value[value.length()-1] == '"') {
 
502
        newCondition.value1 = Value(value.mid(1, value.length()-2));
 
503
    } else {
 
504
        newCondition.value1 = parser->parse(value);
512
505
    }
513
506
}
514
507
 
515
 
void Conditions::loadOdfValidationValue(const QStringList &listVal, Conditional &newCondition)
 
508
void Conditions::loadOdfValidationValue(const QStringList &listVal, Conditional &newCondition, const ValueParser *parser)
516
509
{
517
 
    bool ok = false;
518
510
    kDebug(36003) << " listVal[0] :" << listVal[0] << " listVal[1] :" << listVal[1];
519
 
 
520
 
    newCondition.val1 = listVal[0].toDouble(&ok);
521
 
    if (!ok) {
522
 
        newCondition.val1 = listVal[0].toInt(&ok);
523
 
        if (!ok) {
524
 
            newCondition.strVal1 = new QString(listVal[0]);
525
 
            kDebug(36003) << " Try to parse this value :" << listVal[0];
526
 
        }
527
 
    }
528
 
    ok = false;
529
 
    newCondition.val2 = listVal[1].toDouble(&ok);
530
 
    if (!ok) {
531
 
        newCondition.val2 = listVal[1].toInt(&ok);
532
 
        if (!ok) {
533
 
            newCondition.strVal2 = new QString(listVal[1]);
534
 
            kDebug(36003) << " Try to parse this value :" << listVal[1];
535
 
        }
536
 
    }
 
511
    newCondition.value1 = parser->parse(listVal[0]);
 
512
    newCondition.value2 = parser->parse(listVal[1]);
537
513
}
538
514
 
539
 
void Conditions::loadConditions(const StyleManager* styleManager, const KoXmlElement & element)
 
515
void Conditions::loadConditions(const KoXmlElement &element, const ValueParser *parser)
540
516
{
541
 
    Q_UNUSED(styleManager);
542
517
    Conditional newCondition;
543
518
 
544
519
    KoXmlElement conditionElement;
545
520
    forEachElement(conditionElement, element) {
546
 
        newCondition.strVal1   = 0;
547
 
        newCondition.strVal2   = 0;
548
 
        newCondition.styleName = 0;
549
 
        newCondition.fontcond  = 0;
550
 
        newCondition.colorcond = 0;
551
 
 
552
521
        if (!conditionElement.hasAttribute("cond"))
553
522
            continue;
554
523
 
558
527
            continue;
559
528
 
560
529
        if (conditionElement.hasAttribute("val1")) {
561
 
            newCondition.val1 = conditionElement.attribute("val1").toDouble(&ok);
 
530
            newCondition.value1 = parser->parse(conditionElement.attribute("val1"));
562
531
 
563
532
            if (conditionElement.hasAttribute("val2"))
564
 
                newCondition.val2 = conditionElement.attribute("val2").toDouble(&ok);
 
533
                newCondition.value2 = parser->parse(conditionElement.attribute("val2"));
565
534
        }
566
535
 
567
536
        if (conditionElement.hasAttribute("strval1")) {
568
 
            newCondition.strVal1 = new QString(conditionElement.attribute("strval1"));
 
537
            newCondition.value1 = Value(conditionElement.attribute("strval1"));
569
538
 
570
539
            if (conditionElement.hasAttribute("strval2"))
571
 
                newCondition.strVal2 = new QString(conditionElement.attribute("strval2"));
572
 
        }
573
 
 
574
 
        if (conditionElement.hasAttribute("color")) {
575
 
            QColor color(conditionElement.attribute("color"));
576
 
            if (color.isValid())
577
 
                newCondition.colorcond = new QColor(color);
578
 
        }
579
 
 
580
 
        KoXmlElement font = conditionElement.namedItem("font").toElement();
581
 
        if (!font.isNull())
582
 
            newCondition.fontcond = new QFont(NativeFormat::toFont(font));
 
540
                newCondition.value2 = Value(conditionElement.attribute("strval2"));
 
541
        }
583
542
 
584
543
        if (conditionElement.hasAttribute("style")) {
585
 
            newCondition.styleName = new QString(conditionElement.attribute("style"));
 
544
            newCondition.styleName = conditionElement.attribute("style");
586
545
        }
587
546
 
588
547
        d->conditionList.append(newCondition);
611
570
    }
612
571
    return true;
613
572
}
 
573
 
 
574
uint KSpread::qHash(const Conditions &c)
 
575
{
 
576
    uint res = 0;
 
577
    foreach (const Conditional& co, c.conditionList()) {
 
578
        res ^= qHash(co);
 
579
    }
 
580
    return res;
 
581
}
 
582
 
 
583
uint KSpread::qHash(const Conditional& c)
 
584
{
 
585
    return static_cast<uint>(c.cond) ^ qHash(c.value1) ^ qHash(c.value2) ^ qHash(c.styleName);
 
586
}