~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/qgssearchtreenode.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/***************************************************************************
2
 
                          qgssearchtreenode.cpp 
 
2
                          qgssearchtreenode.cpp
3
3
                  Implementation for evaluating parsed tree
4
4
                          --------------------
5
5
    begin                : 2005-07-26
15
15
 *   (at your option) any later version.                                   *
16
16
 *                                                                         *
17
17
 ***************************************************************************/
18
 
 /* $Id: qgssearchtreenode.cpp 5939 2006-10-12 16:24:55Z wonder $ */
 
18
/* $Id$ */
19
19
 
20
20
#include "qgslogger.h"
 
21
#include "qgsfield.h"
 
22
#include "qgsgeometry.h"
21
23
#include "qgssearchtreenode.h"
22
 
#include <qregexp.h>
23
 
#include <qobject.h>
 
24
#include <QRegExp>
 
25
#include <QObject>
 
26
#include <QSettings>
24
27
#include <iostream>
25
28
 
 
29
#ifndef Q_OS_MACX
 
30
#include <cmath>
 
31
#else
 
32
#include <math.h>
 
33
#endif
 
34
 
 
35
 
26
36
 
27
37
#define EVAL_STR(x) (x.length() ? x : "(empty)")
28
38
 
29
 
QgsSearchTreeNode::QgsSearchTreeNode(double number)
 
39
QgsSearchTreeNode::QgsSearchTreeNode( double number )
30
40
{
31
41
  mType   = tNumber;
32
42
  mNumber = number;
35
45
}
36
46
 
37
47
 
38
 
QgsSearchTreeNode::QgsSearchTreeNode(Operator op, QgsSearchTreeNode* left,
39
 
                                      QgsSearchTreeNode* right)
 
48
QgsSearchTreeNode::QgsSearchTreeNode( Operator op, QgsSearchTreeNode* left,
 
49
                                      QgsSearchTreeNode* right )
40
50
{
41
51
  mType  = tOperator;
42
52
  mOp    = op;
43
53
  mLeft  = left;
44
54
  mRight = right;
 
55
 
 
56
  if ( mOp == opLENGTH || mOp == opAREA )
 
57
  {
 
58
    //initialize QgsDistanceArea
 
59
    mCalc.setProjectionsEnabled( false );
 
60
    QSettings settings;
 
61
    QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();
 
62
    mCalc.setEllipsoid( ellipsoid );
 
63
  }
45
64
}
46
65
 
47
66
 
48
 
QgsSearchTreeNode::QgsSearchTreeNode(QString text, bool isColumnRef)
 
67
QgsSearchTreeNode::QgsSearchTreeNode( QString text, bool isColumnRef )
49
68
{
50
69
  mLeft  = NULL;
51
70
  mRight = NULL;
52
 
  
53
 
  if (isColumnRef)
 
71
 
 
72
  if ( isColumnRef )
54
73
  {
55
74
    mType = tColumnRef;
56
75
    mText = text;
64
83
}
65
84
 
66
85
 
67
 
QgsSearchTreeNode::QgsSearchTreeNode(const QgsSearchTreeNode& node)
 
86
QgsSearchTreeNode::QgsSearchTreeNode( const QgsSearchTreeNode& node )
68
87
{
69
88
  mType = node.mType;
70
89
  mOp = node.mOp;
72
91
  mText = node.mText;
73
92
 
74
93
  // recursively copy children
75
 
  if (node.mLeft)
76
 
    mLeft =  new QgsSearchTreeNode(*node.mLeft);
 
94
  if ( node.mLeft )
 
95
    mLeft =  new QgsSearchTreeNode( *node.mLeft );
77
96
  else
78
97
    mLeft = NULL;
79
 
  
80
 
  if (node.mRight)
81
 
    mRight = new QgsSearchTreeNode(*node.mRight);
 
98
 
 
99
  if ( node.mRight )
 
100
    mRight = new QgsSearchTreeNode( *node.mRight );
82
101
  else
83
102
    mRight = NULL;
84
103
}
87
106
QgsSearchTreeNode::~QgsSearchTreeNode()
88
107
{
89
108
  // delete children
90
 
  
91
 
  if (mLeft)
 
109
 
 
110
  if ( mLeft )
92
111
    delete mLeft;
93
112
 
94
 
  if (mRight)
 
113
  if ( mRight )
95
114
    delete mRight;
96
115
}
97
116
 
98
117
void QgsSearchTreeNode::stripText()
99
118
{
100
119
  // strip single quotes on start,end
101
 
  mText = mText.mid(1, mText.length()-2);
102
 
  
 
120
  mText = mText.mid( 1, mText.length() - 2 );
 
121
 
103
122
  // make single "single quotes" from double "single quotes"
104
 
  mText.replace(QRegExp("''"), "'");
105
 
  
 
123
  mText.replace( QRegExp( "''" ), "'" );
 
124
 
106
125
  // strip \n \' etc.
107
126
  int index = 0;
108
 
  while ((index = mText.find('\\', index)) != -1)
 
127
  while (( index = mText.indexOf( '\\', index ) ) != -1 )
109
128
  {
110
 
    mText.remove(index,1); // delete backslash
 
129
    mText.remove( index, 1 ); // delete backslash
111
130
    QChar chr;
112
 
    switch (mText[index].latin1()) // evaluate backslashed character
 
131
    switch ( mText[index].toLatin1() ) // evaluate backslashed character
113
132
    {
114
133
      case 'n':  chr = '\n'; break;
115
134
      case 't':  chr = '\t'; break;
125
144
QString QgsSearchTreeNode::makeSearchString()
126
145
{
127
146
  QString str;
128
 
  if (mType == tOperator)
 
147
  if ( mType == tOperator )
129
148
  {
130
149
    str += "(";
131
 
    if (mOp != opNOT)
 
150
    if ( mOp != opNOT )
132
151
    {
133
 
      str += mLeft->makeSearchString();
134
 
      switch (mOp)
 
152
      if ( mLeft )
 
153
      {
 
154
        str += mLeft->makeSearchString();
 
155
      }
 
156
      switch ( mOp )
135
157
      {
136
158
        case opAND: str += " AND "; break;
137
159
        case opOR: str += " OR "; break;
153
175
 
154
176
        default: str += " ? ";
155
177
      }
156
 
      str += mRight->makeSearchString();
 
178
 
 
179
      if ( mRight )
 
180
      {
 
181
        str += mRight->makeSearchString();
 
182
      }
157
183
    }
158
184
    else
159
185
    {
162
188
    }
163
189
    str += ")";
164
190
  }
165
 
  else if (mType == tNumber)
 
191
  else if ( mType == tNumber )
166
192
  {
167
 
    str += QString::number(mNumber);
 
193
    str += QString::number( mNumber );
168
194
  }
169
 
  else if (mType == tString || mType == tColumnRef)
 
195
  else if ( mType == tString || mType == tColumnRef )
170
196
  {
171
197
    str += mText;
172
198
  }
173
199
  else // unknown type
174
200
  {
175
201
    str += "unknown_node_type:";
176
 
    str += QString::number(mType);
 
202
    str += QString::number( mType );
177
203
  }
178
204
 
179
205
  return str;
180
206
}
181
207
 
182
208
 
183
 
bool QgsSearchTreeNode::checkAgainst(const std::vector<QgsFeatureAttribute>& attributes)
 
209
bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes )
184
210
{
185
 
  QgsDebugMsgLevel("checkAgainst: " + makeSearchString(), 2);
 
211
  QgsDebugMsgLevel( "checkAgainst: " + makeSearchString(), 2 );
186
212
 
187
213
  mError = "";
188
 
  
 
214
 
189
215
  // this error should be caught when checking syntax, but for sure...
190
 
  if (mType != tOperator)
 
216
  if ( mType != tOperator )
191
217
  {
192
218
    mError = "Expected operator, got scalar value!";
193
219
    return false;
196
222
  QgsSearchTreeValue value1, value2;
197
223
  int res;
198
224
 
199
 
  switch (mOp)
 
225
  switch ( mOp )
200
226
  {
201
227
    case opNOT:
202
 
      return !mLeft->checkAgainst(attributes);
203
 
    
 
228
      return !mLeft->checkAgainst( fields, attributes );
 
229
 
204
230
    case opAND:
205
 
      if (!mLeft->checkAgainst(attributes))
 
231
      if ( !mLeft->checkAgainst( fields, attributes ) )
206
232
        return false;
207
 
      return mRight->checkAgainst(attributes);
208
 
    
 
233
      return mRight->checkAgainst( fields, attributes );
 
234
 
209
235
    case opOR:
210
 
      if (mLeft->checkAgainst(attributes))
 
236
      if ( mLeft->checkAgainst( fields, attributes ) )
211
237
        return true;
212
 
      return mRight->checkAgainst(attributes);
 
238
      return mRight->checkAgainst( fields, attributes );
213
239
 
214
240
    case opEQ:
215
241
    case opNE:
217
243
    case opLT:
218
244
    case opGE:
219
245
    case opLE:
220
 
        
221
 
      if (!getValue(value1, mLeft, attributes) || !getValue(value2, mRight, attributes))
222
 
            return false;
223
 
        
224
 
      res = QgsSearchTreeValue::compare(value1, value2);
225
 
        
226
 
      switch (mOp)
 
246
 
 
247
      if ( !getValue( value1, mLeft, fields, attributes ) || !getValue( value2, mRight, fields, attributes ) )
 
248
        return false;
 
249
 
 
250
      res = QgsSearchTreeValue::compare( value1, value2 );
 
251
 
 
252
      switch ( mOp )
227
253
      {
228
 
        case opEQ: return (res == 0);
229
 
        case opNE: return (res != 0);
230
 
        case opGT: return (res >  0);
231
 
        case opLT: return (res <  0);
232
 
        case opGE: return (res >= 0);
233
 
        case opLE: return (res <= 0);
234
 
        default: 
 
254
        case opEQ: return ( res == 0 );
 
255
        case opNE: return ( res != 0 );
 
256
        case opGT: return ( res >  0 );
 
257
        case opLT: return ( res <  0 );
 
258
        case opGE: return ( res >= 0 );
 
259
        case opLE: return ( res <= 0 );
 
260
        default:
235
261
          mError = "Unexpected state when evaluating operator!";
236
262
          return false;
237
263
      }
239
265
    case opRegexp:
240
266
    case opLike:
241
267
    {
242
 
      if (!getValue(value1, mLeft, attributes) || !getValue(value2, mRight, attributes))
 
268
      if ( !getValue( value1, mLeft, fields, attributes ) ||
 
269
           !getValue( value2, mRight, fields, attributes ) )
243
270
        return false;
244
 
      
 
271
 
245
272
      // value1 is string to be matched
246
273
      // value2 is regular expression
247
 
      
 
274
 
248
275
      // XXX does it make sense to use regexp on numbers?
249
276
      // in what format should they be?
250
 
      if (value1.isNumeric() || value2.isNumeric())
 
277
      if ( value1.isNumeric() || value2.isNumeric() )
251
278
      {
252
 
        mError = QObject::tr("Regular expressions on numeric values don't make sense. Use comparison insted.");
 
279
        mError = QObject::tr( "Regular expressions on numeric values don't make sense. Use comparison instead." );
253
280
        return false;
254
281
      }
255
 
      
 
282
 
256
283
      QString str = value2.string();
257
 
      if (mOp == opLike) // change from LIKE syntax to regexp
 
284
      if ( mOp == opLike ) // change from LIKE syntax to regexp
258
285
      {
259
286
        // XXX escape % and _  ???
260
 
        str.replace("%", ".*");
261
 
        str.replace("_", ".");
 
287
        str.replace( "%", ".*" );
 
288
        str.replace( "_", "." );
262
289
      }
263
 
      
264
 
      QRegExp re(str);
265
 
      res = re.search(value1.string());
266
 
      QgsDebugMsgLevel("REGEXP: " + str + " ~ " + value2.string(), 2);
267
 
      QgsDebugMsgLevel("   res: " + res, 2);
268
 
      return (res != -1);
 
290
 
 
291
      return QRegExp( str ).exactMatch( value1.string() );
269
292
    }
270
293
 
271
294
    default:
272
295
      mError = "Unknown operator: ";
273
 
      mError += QString::number(mOp);
 
296
      mError += QString::number( mOp );
274
297
      return false;
275
298
  }
276
 
 
277
 
  return false; // will never get there
278
299
}
279
300
 
280
 
bool QgsSearchTreeNode::getValue(QgsSearchTreeValue& value, QgsSearchTreeNode* node, const std::vector<QgsFeatureAttribute>& attributes)
 
301
bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
281
302
{
282
 
  value = node->valueAgainst(attributes);
283
 
  if (value.isError())
 
303
  value = node->valueAgainst( fields, attributes, geom );
 
304
  if ( value.isError() )
284
305
  {
285
 
    switch ((int)value.number())
 
306
    switch (( int )value.number() )
286
307
    {
287
308
      case 1:
288
 
        mError = QObject::tr("Referenced column wasn't found: ");
289
 
        mError += value.string();
 
309
        mError = QObject::tr( "Referenced column wasn't found: %1" ).arg( value.string() );
290
310
        break;
291
311
      case 2:
292
 
        mError = QObject::tr("Division by zero.");
 
312
        mError = QObject::tr( "Division by zero." );
293
313
        break;
294
 
        
295
 
      // these should never happen (no need to translate)
 
314
 
 
315
        // these should never happen (no need to translate)
296
316
      case 3:
297
317
        mError = "Unknown operator: ";
298
318
        mError += value.string();
305
325
        mError = "Unknown error!";
306
326
        break;
307
327
    }
308
 
    return false;        
 
328
    return false;
309
329
  }
310
330
  return true;
311
331
}
312
332
 
313
 
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst(const std::vector<QgsFeatureAttribute>& attributes)
 
333
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
314
334
{
315
 
  QgsDebugMsgLevel("valueAgainst: " + makeSearchString(), 2);
 
335
  QgsDebugMsgLevel( "valueAgainst: " + makeSearchString(), 2 );
316
336
 
317
 
  switch (mType)
 
337
  switch ( mType )
318
338
  {
319
339
 
320
340
    case tNumber:
321
 
      QgsDebugMsgLevel("number: " + QString::number(mNumber), 2);
322
 
      return QgsSearchTreeValue(mNumber);
323
 
  
 
341
      QgsDebugMsgLevel( "number: " + QString::number( mNumber ), 2 );
 
342
      return QgsSearchTreeValue( mNumber );
 
343
 
324
344
    case tString:
325
 
      QgsDebugMsgLevel("text: " + EVAL_STR(mText), 2);
326
 
      return QgsSearchTreeValue(mText);
327
 
  
 
345
      QgsDebugMsgLevel( "text: " + EVAL_STR( mText ), 2 );
 
346
      return QgsSearchTreeValue( mText );
 
347
 
328
348
    case tColumnRef:
329
349
    {
330
 
      QgsDebugMsgLevel("column (" + mText.lower() + "): ", 2);
331
 
      // find value for the column
332
 
      std::vector<QgsFeatureAttribute>::const_iterator it;
333
 
      for (it = attributes.begin(); it != attributes.end(); it++)
334
 
      {
335
 
        if ( (*it).fieldName().lower() == mText.lower()) // TODO: optimize
336
 
        {
337
 
          QString value = (*it).fieldValue();
338
 
          if ((*it).isNumeric())
339
 
          {
340
 
            QgsDebugMsgLevel("   number: " + QString::number(value.toDouble()), 2);
341
 
            return QgsSearchTreeValue(value.toDouble());
342
 
          }
343
 
          else
344
 
          {
345
 
            QgsDebugMsgLevel("   text: " + EVAL_STR(value), 2);
346
 
            return QgsSearchTreeValue(value);
347
 
          }
348
 
        }
349
 
      }
350
 
          
351
 
      // else report missing column
352
 
      QgsDebugMsgLevel("ERROR!", 2);
353
 
      return QgsSearchTreeValue(1, mText);
 
350
      QgsDebugMsgLevel( "column (" + mText.toLower() + "): ", 2 );
 
351
      // find field index for the column
 
352
      QgsFieldMap::const_iterator it;
 
353
      for ( it = fields.begin(); it != fields.end(); it++ )
 
354
      {
 
355
        if ( it->name().toLower() == mText.toLower() ) // TODO: optimize
 
356
          break;
 
357
      }
 
358
 
 
359
      if ( it == fields.end() )
 
360
      {
 
361
        // report missing column if not found
 
362
        QgsDebugMsgLevel( "ERROR!", 2 );
 
363
        return QgsSearchTreeValue( 1, mText );
 
364
      }
 
365
 
 
366
      // get the value
 
367
      QVariant val = attributes[it.key()];
 
368
      if ( val.type() == QVariant::Bool || val.type() == QVariant::Int || val.type() == QVariant::Double )
 
369
      {
 
370
        QgsDebugMsgLevel( "   number: " + QString::number( val.toDouble() ), 2 );
 
371
        return QgsSearchTreeValue( val.toDouble() );
 
372
      }
 
373
      else
 
374
      {
 
375
        QgsDebugMsgLevel( "   text: " + EVAL_STR( val.toString() ), 2 );
 
376
        return QgsSearchTreeValue( val.toString() );
 
377
      }
 
378
 
354
379
    }
355
 
    
 
380
 
356
381
    // arithmetic operators
357
382
    case tOperator:
358
 
      {
359
 
        QgsSearchTreeValue value1, value2;
360
 
        if (!getValue(value1, mLeft,  attributes)) return value1;
361
 
        if (!getValue(value2, mRight, attributes)) return value2;
362
 
        
363
 
        // convert to numbers if needed
364
 
        double val1, val2;
365
 
        if (value1.isNumeric())
366
 
          val1 = value1.number();
367
 
        else
368
 
          val1 = value1.string().toDouble();
369
 
        if (value2.isNumeric())
370
 
          val2 = value2.number();
371
 
        else
372
 
          val2 = value2.string().toDouble();
373
 
      
374
 
        switch (mOp)
375
 
        {
376
 
          case opPLUS:
377
 
            return QgsSearchTreeValue(val1 + val2);
378
 
          case opMINUS:
379
 
            return QgsSearchTreeValue(val1 - val2);
380
 
          case opMUL:
381
 
            return QgsSearchTreeValue(val1 * val2);
382
 
          case opDIV:
383
 
            if (val2 == 0)
384
 
              return QgsSearchTreeValue(2, ""); // division by zero
385
 
            else
386
 
              return QgsSearchTreeValue(val1 / val2);
387
 
          default:
388
 
            return QgsSearchTreeValue(3, QString::number(mOp)); // unknown operator
389
 
        }
390
 
      }
391
 
      
 
383
    {
 
384
      QgsSearchTreeValue value1, value2;
 
385
      if ( mLeft )
 
386
      {
 
387
        if ( !getValue( value1, mLeft, fields, attributes, geom ) ) return value1;
 
388
      }
 
389
      if ( mRight )
 
390
      {
 
391
        if ( !getValue( value2, mRight, fields, attributes, geom ) ) return value2;
 
392
      }
 
393
 
 
394
      if ( mOp == opLENGTH || mOp == opAREA )
 
395
      {
 
396
        if ( !geom )
 
397
        {
 
398
          return QgsSearchTreeValue( 2, "Geometry is 0" );
 
399
        }
 
400
 
 
401
        //check that we don't use area for lines or length for polygons
 
402
        if ( mOp == opLENGTH && geom->type() != QGis::Line )
 
403
        {
 
404
          return QgsSearchTreeValue( 0 );
 
405
        }
 
406
        if ( mOp == opAREA && geom->type() != QGis::Polygon )
 
407
        {
 
408
          return QgsSearchTreeValue( 0 );
 
409
        }
 
410
        return QgsSearchTreeValue( mCalc.measure( geom ) );
 
411
      }
 
412
 
 
413
      //string operations with one argument
 
414
      if ( !mRight && !value1.isNumeric() )
 
415
      {
 
416
        if ( mOp == opTOINT )
 
417
        {
 
418
          return QgsSearchTreeValue( value1.string().toInt() );
 
419
        }
 
420
        else if ( mOp == opTOREAL )
 
421
        {
 
422
          return QgsSearchTreeValue( value1.string().toDouble() );
 
423
        }
 
424
      }
 
425
 
 
426
      //don't convert to numbers in case of string concatenation
 
427
      if ( mLeft && mRight && !value1.isNumeric() && !value2.isNumeric() )
 
428
      {
 
429
        if ( mOp == opPLUS )
 
430
        {
 
431
          return QgsSearchTreeValue( value1.string() + value2.string() );
 
432
        }
 
433
      }
 
434
 
 
435
      // for other operators, convert strings to numbers if needed
 
436
      double val1, val2;
 
437
      if ( value1.isNumeric() )
 
438
        val1 = value1.number();
 
439
      else
 
440
        val1 = value1.string().toDouble();
 
441
      if ( value2.isNumeric() )
 
442
        val2 = value2.number();
 
443
      else
 
444
        val2 = value2.string().toDouble();
 
445
 
 
446
      switch ( mOp )
 
447
      {
 
448
        case opPLUS:
 
449
          return QgsSearchTreeValue( val1 + val2 );
 
450
        case opMINUS:
 
451
          return QgsSearchTreeValue( val1 - val2 );
 
452
        case opMUL:
 
453
          return QgsSearchTreeValue( val1 * val2 );
 
454
        case opDIV:
 
455
          if ( val2 == 0 )
 
456
            return QgsSearchTreeValue( 2, "" ); // division by zero
 
457
          else
 
458
            return QgsSearchTreeValue( val1 / val2 );
 
459
        default:
 
460
          return QgsSearchTreeValue( 3, QString::number( mOp ) ); // unknown operator
 
461
        case opPOW:
 
462
          if (( val1 == 0 && val2 < 0 ) || ( val2 < 0 && ( val2 - floor( val2 ) ) > 0 ) )
 
463
          {
 
464
            return QgsSearchTreeValue( 4, "Error in power function" );
 
465
          }
 
466
          return QgsSearchTreeValue( pow( val1, val2 ) );
 
467
        case opSQRT:
 
468
          return QgsSearchTreeValue( sqrt( val1 ) );
 
469
        case opSIN:
 
470
          return QgsSearchTreeValue( sin( val1 ) );
 
471
        case opCOS:
 
472
          return QgsSearchTreeValue( cos( val1 ) );
 
473
        case opTAN:
 
474
          return QgsSearchTreeValue( tan( val1 ) );
 
475
        case opASIN:
 
476
          return QgsSearchTreeValue( asin( val1 ) );
 
477
        case opACOS:
 
478
          return QgsSearchTreeValue( acos( val1 ) );
 
479
        case opATAN:
 
480
          return QgsSearchTreeValue( atan( val1 ) );
 
481
        case opTOINT:
 
482
          return QgsSearchTreeValue( int( val1 ) );
 
483
        case opTOREAL:
 
484
          return QgsSearchTreeValue( val1 );
 
485
        case opTOSTRING:
 
486
          return QgsSearchTreeValue( QString::number( val1 ) );
 
487
      }
 
488
    }
 
489
 
392
490
    default:
393
 
      return QgsSearchTreeValue(4, QString::number(mType)); // unknown token
 
491
      return QgsSearchTreeValue( 4, QString::number( mType ) ); // unknown token
394
492
  }
395
493
}
396
494
 
397
495
 
398
 
int QgsSearchTreeValue::compare(QgsSearchTreeValue& value1, QgsSearchTreeValue& value2)
 
496
int QgsSearchTreeValue::compare( QgsSearchTreeValue& value1, QgsSearchTreeValue& value2, Qt::CaseSensitivity cs )
399
497
{
400
 
  if (value1.isNumeric() || value2.isNumeric())
 
498
  if ( value1.isNumeric() || value2.isNumeric() )
401
499
  {
402
500
    // numeric comparison
403
 
    
 
501
 
404
502
    // convert to numbers if needed
405
503
    double val1, val2;
406
 
    if (value1.isNumeric())
 
504
    if ( value1.isNumeric() )
407
505
      val1 = value1.number();
408
506
    else
409
507
      val1 = value1.string().toDouble();
410
 
    if (value2.isNumeric())
 
508
    if ( value2.isNumeric() )
411
509
      val2 = value2.number();
412
510
    else
413
511
      val2 = value2.string().toDouble();
414
 
   
415
 
    QgsDebugMsgLevel("NUM_COMP: " + QString::number(val1) + " ~ " + QString::number(val2), 2);
416
 
 
417
 
    if (val1 < val2)
 
512
 
 
513
    QgsDebugMsgLevel( "NUM_COMP: " + QString::number( val1 ) + " ~ " + QString::number( val2 ), 2 );
 
514
 
 
515
    if ( val1 < val2 )
418
516
      return -1;
419
 
    else if (val1 > val2)
 
517
    else if ( val1 > val2 )
420
518
      return 1;
421
519
    else
422
520
      return 0;
424
522
  else
425
523
  {
426
524
    // string comparison
427
 
    return value1.string().compare(value2.string());
 
525
    return value1.string().compare( value2.string(), cs );
428
526
  }
429
527
}