Skip to content

Commit 9945818

Browse files
author
jef
committed
[FEATURE] add search string support for feature ids ($id)
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@14247 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent bb21d39 commit 9945818

11 files changed

+110
-65
lines changed

python/core/qgssearchtreenode.sip

+16-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class QgsSearchTreeNode
4646
opLENGTH,
4747
opAREA,
4848

49+
// feature id
50+
opID,
51+
4952
// comparison
5053
opEQ, // =
5154
opNE, // != resp. <>
@@ -98,7 +101,10 @@ class QgsSearchTreeNode
98101
QString makeSearchString();
99102

100103
//! checks whether the node tree is valid against supplied attributes
101-
//! @note optional geom parameter added in 1.5
104+
//! @note attributes and optional geom parameter replace with feature in 1.6
105+
bool checkAgainst( const QMap<int,QgsField>& fields, QgsFeature &f );
106+
107+
//! @note deprecated
102108
bool checkAgainst( const QMap<int,QgsField>& fields, const QMap<int, QVariant>& attributes, QgsGeometry* geom = 0 );
103109

104110
//! checks if there were errors during evaluation
@@ -109,6 +115,11 @@ class QgsSearchTreeNode
109115

110116
//! wrapper around valueAgainst()
111117
//! @note added in 1.4
118+
//! @note attribute/geom replaced by feature in 1.6
119+
bool getValue( QgsSearchTreeValue& value /Out/, QgsSearchTreeNode* node,
120+
const QMap<int,QgsField>& fields, QgsFeature &f );
121+
122+
//! @note deprecated
112123
bool getValue( QgsSearchTreeValue& value /Out/, QgsSearchTreeNode* node,
113124
const QMap<int,QgsField>& fields, const QMap<int,QVariant>& attributes, QgsGeometry* geom = 0 );
114125

@@ -134,14 +145,15 @@ class QgsSearchTreeNode
134145
void setCurrentRowNumber( int rownum );
135146

136147
protected:
137-
138-
139148
//! returns scalar value of node
149+
//! @note attribute/geom replaced by feature in 1.6
150+
QgsSearchTreeValue valueAgainst( const QMap<int,QgsField>& fields, QgsFeature &f );
151+
152+
//! @note deprecated
140153
QgsSearchTreeValue valueAgainst( const QMap<int,QgsField>& fields, const QMap<int,QVariant>& attributes, QgsGeometry* geom = 0 );
141154

142155
//! strips mText when node is of string type
143156
void stripText();
144-
145157
};
146158

147159

src/app/attributetable/qgsattributetabledialog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ void QgsAttributeTableDialog::doSearch( QString searchString )
568568
QgsFeatureList selectedFeatures = mLayer->selectedFeatures();
569569
for ( QgsFeatureList::Iterator it = selectedFeatures.begin(); it != selectedFeatures.end(); ++it )
570570
{
571-
if ( searchTree->checkAgainst( mLayer->pendingFields(), it->attributeMap(), it->geometry() ) )
571+
if ( searchTree->checkAgainst( mLayer->pendingFields(), *it ) )
572572
mSelectedFeatures << it->id();
573573

574574
// check if there were errors during evaluating
@@ -583,7 +583,7 @@ void QgsAttributeTableDialog::doSearch( QString searchString )
583583

584584
while ( mLayer->nextFeature( f ) )
585585
{
586-
if ( searchTree->checkAgainst( mLayer->pendingFields(), f.attributeMap(), f.geometry() ) )
586+
if ( searchTree->checkAgainst( mLayer->pendingFields(), f ) )
587587
mSelectedFeatures << f.id();
588588

589589
// check if there were errors during evaluating

src/app/qgsfieldcalculator.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,7 @@ void QgsFieldCalculator::accept()
170170
searchTree->setCurrentRowNumber( rownum );
171171

172172
QgsSearchTreeValue value;
173-
if ( useGeometry )
174-
{
175-
searchTree->getValue( value, searchTree, mVectorLayer->pendingFields(), feature.attributeMap(), feature.geometry() );
176-
}
177-
else
178-
{
179-
searchTree->getValue( value, searchTree, mVectorLayer->pendingFields(), feature.attributeMap() );
180-
}
173+
searchTree->getValue( value, searchTree, mVectorLayer->pendingFields(), feature );
181174
if ( value.isError() )
182175
{
183176
calculationSuccess = false;

src/app/qgssearchquerybuilder.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ long QgsSearchQueryBuilder::countRecords( QString searchString )
216216

217217
while ( provider->nextFeature( feat ) )
218218
{
219-
if ( searchTree->checkAgainst( fields, feat.attributeMap(), feat.geometry() ) )
219+
if ( searchTree->checkAgainst( fields, feat ) )
220220
{
221221
count++;
222222
}

src/core/qgssearchstringlexer.ll

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ string "'"{str_char}*"'"
110110
111111
"$area" { return AREA; }
112112
"$length" { return LENGTH; }
113+
"$id" { return ID; }
113114
114115
{column_ref} { return COLUMN_REF; }
115116
{column_ref_quoted} { return COLUMN_REF; }

src/core/qgssearchstringparser.yy

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ void addToTmpNodes(QgsSearchTreeNode* node);
6868
%token ROWNUM
6969
%token AREA
7070
%token LENGTH
71+
%token ID
7172
%token NULLVALUE
7273

7374
%token STRING
@@ -151,6 +152,7 @@ scalar_exp:
151152
| ROWNUM { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opROWNUM, 0, 0); addToTmpNodes($$); }
152153
| AREA { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opAREA, 0, 0); addToTmpNodes($$); }
153154
| LENGTH { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opLENGTH, 0, 0); addToTmpNodes($$); }
155+
| ID { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opID, 0, 0); addToTmpNodes($$); }
154156
| NUMBER { $$ = new QgsSearchTreeNode($1); addToTmpNodes($$); }
155157
| STRING { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 0); addToTmpNodes($$); }
156158
| COLUMN_REF { $$ = new QgsSearchTreeNode(QString::fromUtf8(yytext), 1); addToTmpNodes($$); }

src/core/qgssearchtreenode.cpp

+65-41
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,15 @@ QString QgsSearchTreeNode::makeSearchString()
231231
// currently all functions take one parameter
232232
str += QString( "(%1)" ).arg( mLeft->makeSearchString() );
233233
}
234-
else if ( mOp == opLENGTH || mOp == opAREA || mOp == opROWNUM )
234+
else if ( mOp == opLENGTH || mOp == opAREA || mOp == opROWNUM || mOp == opID )
235235
{
236236
// special nullary opeators
237237
switch ( mOp )
238238
{
239239
case opLENGTH: str += "$length"; break;
240240
case opAREA: str += "$area"; break;
241241
case opROWNUM: str += "$rownum"; break;
242+
case opID: str += "$id"; break;
242243
default: str += "?";
243244
}
244245
}
@@ -374,8 +375,16 @@ bool QgsSearchTreeNode::needsGeometry()
374375
}
375376
}
376377

378+
bool QgsSearchTreeNode::checkAgainst( const QMap<int,QgsField>& fields, const QMap<int, QVariant>& attributes, QgsGeometry* geom )
379+
{
380+
QgsFeature f;
381+
f.setAttributeMap( attributes );
382+
if ( geom )
383+
f.setGeometry( *geom );
384+
return checkAgainst( fields, f );
385+
}
377386

378-
bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
387+
bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, QgsFeature &f )
379388
{
380389
QgsDebugMsgLevel( "checkAgainst: " + makeSearchString(), 2 );
381390

@@ -394,40 +403,32 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
394403
switch ( mOp )
395404
{
396405
case opNOT:
397-
return !mLeft->checkAgainst( fields, attributes, geom );
406+
return !mLeft->checkAgainst( fields, f );
398407

399408
case opAND:
400-
if ( !mLeft->checkAgainst( fields, attributes, geom ) )
409+
if ( !mLeft->checkAgainst( fields, f ) )
401410
return false;
402-
return mRight->checkAgainst( fields, attributes, geom );
411+
return mRight->checkAgainst( fields, f );
403412

404413
case opOR:
405-
if ( mLeft->checkAgainst( fields, attributes, geom ) )
414+
if ( mLeft->checkAgainst( fields, f ) )
406415
return true;
407-
return mRight->checkAgainst( fields, attributes, geom );
416+
return mRight->checkAgainst( fields, f );
408417

409418
case opISNULL:
410419
case opISNOTNULL:
411-
if ( !getValue( value1, mLeft, fields, attributes, geom ) )
420+
if ( !getValue( value1, mLeft, fields, f ) )
412421
return false;
413422

414-
if ( mOp == opISNULL )
415-
{
416-
return value1.isNull();
417-
}
418-
else if ( mOp == opISNOTNULL )
419-
{
420-
return !value1.isNull();
421-
}
423+
return ( mOp == opISNULL ) == value1.isNull();
422424

423425
case opEQ:
424426
case opNE:
425427
case opGT:
426428
case opLT:
427429
case opGE:
428430
case opLE:
429-
430-
if ( !getValue( value1, mLeft, fields, attributes, geom ) || !getValue( value2, mRight, fields, attributes, geom ) )
431+
if ( !getValue( value1, mLeft, fields, f ) || !getValue( value2, mRight, fields, f ) )
431432
return false;
432433

433434
if ( value1.isNull() || value2.isNull() )
@@ -440,12 +441,12 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
440441

441442
switch ( mOp )
442443
{
443-
case opEQ: return ( res == 0 );
444-
case opNE: return ( res != 0 );
445-
case opGT: return ( res > 0 );
446-
case opLT: return ( res < 0 );
447-
case opGE: return ( res >= 0 );
448-
case opLE: return ( res <= 0 );
444+
case opEQ: return res == 0;
445+
case opNE: return res != 0;
446+
case opGT: return res > 0;
447+
case opLT: return res < 0;
448+
case opGE: return res >= 0;
449+
case opLE: return res <= 0;
449450
default:
450451
mError = QObject::tr( "Unexpected state when evaluating operator!" );
451452
return false;
@@ -454,15 +455,15 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
454455
case opIN:
455456
case opNOTIN:
456457
{
457-
if ( !getValue( value1, mLeft, fields, attributes, geom ) ||
458+
if ( !getValue( value1, mLeft, fields, f ) ||
458459
!mRight || mRight->type() != tNodeList )
459460
{
460461
return false;
461462
}
462463

463464
foreach( QgsSearchTreeNode *node, mRight->mNodeList )
464465
{
465-
if ( !getValue( value2, node, fields, attributes, geom ) )
466+
if ( !getValue( value2, node, fields, f ) )
466467
{
467468
mError = QObject::tr( "Could not retrieve value of list value" );
468469
return false;
@@ -485,8 +486,8 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
485486
case opLike:
486487
case opILike:
487488
{
488-
if ( !getValue( value1, mLeft, fields, attributes, geom ) ||
489-
!getValue( value2, mRight, fields, attributes, geom ) )
489+
if ( !getValue( value1, mLeft, fields, f ) ||
490+
!getValue( value2, mRight, fields, f ) )
490491
return false;
491492

492493
// value1 is string to be matched
@@ -512,20 +513,29 @@ bool QgsSearchTreeNode::checkAgainst( const QgsFieldMap& fields, const QgsAttrib
512513
}
513514
else
514515
{
515-
return ( QRegExp( str ).indexIn( value1.string() ) != -1 );
516+
return QRegExp( str ).indexIn( value1.string() ) != -1;
516517
}
517-
518518
}
519519

520520
default:
521521
mError = QObject::tr( "Unknown operator: %1" ).arg( mOp );
522-
return false;
523522
}
523+
524+
return false;
524525
}
525526

526-
bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
527+
bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, const QMap<int, QVariant>& attributes, QgsGeometry* geom )
527528
{
528-
value = node->valueAgainst( fields, attributes, geom );
529+
QgsFeature f;
530+
f.setAttributeMap( attributes );
531+
if ( geom )
532+
f.setGeometry( *geom );
533+
return getValue( value, node, fields, f );
534+
}
535+
536+
bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node, const QgsFieldMap& fields, QgsFeature &f )
537+
{
538+
value = node->valueAgainst( fields, f );
529539
if ( value.isError() )
530540
{
531541
switch (( int )value.number() )
@@ -553,7 +563,16 @@ bool QgsSearchTreeNode::getValue( QgsSearchTreeValue& value, QgsSearchTreeNode*
553563
return true;
554564
}
555565

556-
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes, QgsGeometry* geom )
566+
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, const QMap<int, QVariant>& attributes, QgsGeometry* geom )
567+
{
568+
QgsFeature f;
569+
f.setAttributeMap( attributes );
570+
if ( geom )
571+
f.setGeometry( *geom );
572+
return valueAgainst( fields, f );
573+
}
574+
575+
QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, QgsFeature &f )
557576
{
558577
QgsDebugMsgLevel( "valueAgainst: " + makeSearchString(), 2 );
559578

@@ -587,7 +606,7 @@ QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, c
587606
}
588607

589608
// get the value
590-
QVariant val = attributes[it.key()];
609+
QVariant val = f.attributeMap()[it.key()];
591610
if ( val.isNull() )
592611
{
593612
QgsDebugMsgLevel( " NULL", 2 );
@@ -612,30 +631,35 @@ QgsSearchTreeValue QgsSearchTreeNode::valueAgainst( const QgsFieldMap& fields, c
612631
QgsSearchTreeValue value1, value2;
613632
if ( mLeft )
614633
{
615-
if ( !getValue( value1, mLeft, fields, attributes, geom ) ) return value1;
634+
if ( !getValue( value1, mLeft, fields, f ) ) return value1;
616635
}
617636
if ( mRight )
618637
{
619-
if ( !getValue( value2, mRight, fields, attributes, geom ) ) return value2;
638+
if ( !getValue( value2, mRight, fields, f ) ) return value2;
620639
}
621640

622641
if ( mOp == opLENGTH || mOp == opAREA )
623642
{
624-
if ( !geom )
643+
if ( !f.geometry() )
625644
{
626645
return QgsSearchTreeValue( 2, "Geometry is 0" );
627646
}
628647

629648
//check that we don't use area for lines or length for polygons
630-
if ( mOp == opLENGTH && geom->type() != QGis::Line )
649+
if ( mOp == opLENGTH && f.geometry()->type() != QGis::Line )
631650
{
632651
return QgsSearchTreeValue( 0 );
633652
}
634-
if ( mOp == opAREA && geom->type() != QGis::Polygon )
653+
if ( mOp == opAREA && f.geometry()->type() != QGis::Polygon )
635654
{
636655
return QgsSearchTreeValue( 0 );
637656
}
638-
return QgsSearchTreeValue( mCalc->measure( geom ) );
657+
return QgsSearchTreeValue( mCalc->measure( f.geometry() ) );
658+
}
659+
660+
if ( mOp == opID )
661+
{
662+
return QgsSearchTreeValue( f.id() );
639663
}
640664

641665
if ( mOp == opROWNUM )

0 commit comments

Comments
 (0)