Skip to content

Commit 3943e8a

Browse files
author
Arunmozhi
committed
smart groups implemented
1 parent dec6216 commit 3943e8a

File tree

11 files changed

+889
-45
lines changed

11 files changed

+889
-45
lines changed

resources/symbology-ng-style.db

1 KB
Binary file not shown.

scripts/symbol_xml2db.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@
5252
"name TEXT,"\
5353
"parent INTEGER)"
5454

55-
create_tables = [ _symbol, _colorramp, _tag, _tagmap, _symgroup ]
55+
_smartgroup = "CREATE TABLE smartgroup("\
56+
"id INTEGER PRIMARY KEY,"\
57+
"name TEXT,"\
58+
"xml TEXT)"
59+
60+
create_tables = [ _symbol, _colorramp, _tag, _tagmap, _symgroup, _smartgroup ]
5661

5762
# Create the DB with required Schema
5863
conn = sqlite3.connect( dbfile )

src/core/symbology-ng/qgsstylev2.cpp

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#include <QDomDocument>
2727
#include <QDomElement>
28+
#include <QDomNode>
29+
#include <QDomNodeList>
2830
#include <QFile>
2931
#include <QTextStream>
3032
#include <QByteArray>
@@ -572,6 +574,8 @@ void QgsStyleV2::rename( StyleEntity type, int id, QString newName )
572574
break;
573575
case ColorrampEntity : query = sqlite3_mprintf( "UPDATE colorramp SET name='%q' WHERE id=%d;", nameArray.constData(), id );
574576
break;
577+
case SmartgroupEntity : query = sqlite3_mprintf( "UPDATE smartgroup SET name='%q' WHERE id=%d;", nameArray.constData(), id );
578+
break;
575579
default : QgsDebugMsg( "Invalid Style Entity indicated" );
576580
return;
577581
}
@@ -616,6 +620,8 @@ void QgsStyleV2::remove( StyleEntity type, int id )
616620
break;
617621
case ColorrampEntity : query = sqlite3_mprintf( "DELETE FROM colorramp WHERE id=%d;", id );
618622
break;
623+
case SmartgroupEntity : query = sqlite3_mprintf( "DELETE FROM smartgroup WHERE id=%d;", id );
624+
break;
619625
default : QgsDebugMsg( "Invalid Style Entity indicated" );
620626
return;
621627
}
@@ -864,3 +870,289 @@ int QgsStyleV2::groupId( QString name )
864870
sqlite3_finalize( ppStmt );
865871
return groupid;
866872
}
873+
874+
int QgsStyleV2::tagId( QString name )
875+
{
876+
int tagid = 0;
877+
char *query;
878+
sqlite3_stmt *ppStmt;
879+
QByteArray array = name.toUtf8();
880+
query = sqlite3_mprintf( "SELECT id FROM tag WHERE name='%q';", array.constData() );
881+
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
882+
if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
883+
{
884+
tagid = sqlite3_column_int( ppStmt, 0 );
885+
}
886+
sqlite3_finalize( ppStmt );
887+
return tagid;
888+
}
889+
890+
891+
int QgsStyleV2::addSmartgroup( QString name, QString op, QgsSmartConditionMap conditions )
892+
{
893+
int sgId = 0;
894+
895+
QDomDocument doc( "dummy" );
896+
QDomElement smartEl = doc.createElement( "smartgroup" );
897+
smartEl.setAttribute( "name", name );
898+
smartEl.setAttribute( "operator", op );
899+
900+
QStringList constraints;
901+
constraints << "tag" << "group" << "name" << "!tag" << "!group" << "!name" ;
902+
903+
foreach ( const QString &constraint, constraints )
904+
{
905+
QStringList parameters = conditions.values( constraint );
906+
foreach ( const QString &param, parameters )
907+
{
908+
QDomElement condEl = doc.createElement( "condition" );
909+
condEl.setAttribute( "constraint", constraint);
910+
condEl.setAttribute( "param", param );
911+
smartEl.appendChild( condEl );
912+
}
913+
}
914+
915+
QByteArray *xmlArray = new QByteArray();
916+
QTextStream stream( xmlArray );
917+
smartEl.save( stream, 4 );
918+
QByteArray nameArray = name.toUtf8();
919+
char *query = sqlite3_mprintf( "INSERT INTO smartgroup VALUES (NULL, '%q', '%q');",
920+
nameArray.constData(), xmlArray->constData() );
921+
922+
if ( !runEmptyQuery( query ) )
923+
{
924+
QgsDebugMsg( "Couldnot insert symbol into the Database!" );
925+
}
926+
else
927+
{
928+
sgId = (int)sqlite3_last_insert_rowid( mCurrentDB );
929+
}
930+
return sgId;
931+
}
932+
933+
QgsSymbolGroupMap QgsStyleV2::smartgroupsListMap()
934+
{
935+
if( mCurrentDB == NULL )
936+
{
937+
QgsDebugMsg( "Cannot open database for listing groups" );
938+
return QgsSymbolGroupMap();
939+
}
940+
char *query;
941+
int nError;
942+
sqlite3_stmt *ppStmt;
943+
QgsSymbolGroupMap groupNames;
944+
945+
query = sqlite3_mprintf( "SELECT * FROM smartgroup;" );
946+
947+
// Now run the query and retrive the group names
948+
nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
949+
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
950+
{
951+
QString group = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, SmartgroupName ) ) );
952+
groupNames.insert( sqlite3_column_int( ppStmt, SmartgroupId ), group );
953+
}
954+
sqlite3_finalize( ppStmt );
955+
return groupNames;
956+
}
957+
958+
QStringList QgsStyleV2::smartgroupNames()
959+
{
960+
QStringList groups;
961+
962+
if( mCurrentDB == NULL )
963+
{
964+
QgsDebugMsg( "Cannot open database for listing groups" );
965+
return QStringList();
966+
}
967+
char *query;
968+
int nError;
969+
sqlite3_stmt *ppStmt;
970+
971+
query = sqlite3_mprintf( "SELECT name FROM smartgroup;" );
972+
// Now run the query and retrive the group names
973+
nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
974+
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
975+
{
976+
groups.append( QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, 0 ) ) ) );
977+
}
978+
sqlite3_finalize( ppStmt );
979+
return groups;
980+
}
981+
982+
QStringList QgsStyleV2::symbolsOfSmartgroup( int id )
983+
{
984+
char *query;
985+
int nErr;
986+
sqlite3_stmt *ppStmt;
987+
988+
QStringList symbols;
989+
bool firstSet = true;
990+
991+
query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d;", id );
992+
nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
993+
if ( !( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) )
994+
{
995+
sqlite3_finalize( ppStmt );
996+
return QStringList();
997+
}
998+
else
999+
{
1000+
QDomDocument doc;
1001+
QString xmlstr = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, 0 ) ) );
1002+
if ( !doc.setContent( xmlstr ) )
1003+
{
1004+
QgsDebugMsg( "Cannot open smartgroup id: " + id );
1005+
}
1006+
QDomElement smartEl = doc.documentElement();
1007+
QString op = smartEl.attribute( "operator" );
1008+
QDomNodeList conditionNodes = smartEl.childNodes();
1009+
1010+
for ( int i = 0; i < conditionNodes.count(); i++ )
1011+
{
1012+
QDomElement condEl = conditionNodes.at( i ).toElement();
1013+
QString constraint = condEl.attribute( "constraint" );
1014+
QString param = condEl.attribute( "param" );
1015+
1016+
QStringList resultNames;
1017+
// perform suitable action for the given constraint
1018+
if ( constraint == "tag" )
1019+
{
1020+
resultNames = symbolsWithTag( tagId( param ) );
1021+
}
1022+
else if ( constraint == "group" )
1023+
{
1024+
// XXX Validating group id might be a good idea here
1025+
resultNames = symbolsOfGroup( groupId( param ) );
1026+
}
1027+
else if ( constraint == "name" )
1028+
{
1029+
resultNames = symbolNames().filter( param, Qt::CaseInsensitive );
1030+
}
1031+
else if ( constraint == "!tag" )
1032+
{
1033+
resultNames = symbolNames();
1034+
QStringList unwanted = symbolsWithTag( tagId( param ) );
1035+
foreach( QString name, unwanted )
1036+
{
1037+
resultNames.removeOne( name );
1038+
}
1039+
}
1040+
else if ( constraint == "!group" )
1041+
{
1042+
resultNames = symbolNames();
1043+
QStringList unwanted = symbolsOfGroup( groupId( param ) );
1044+
foreach( QString name, unwanted )
1045+
{
1046+
resultNames.removeOne( name );
1047+
}
1048+
}
1049+
else if ( constraint == "!name" )
1050+
{
1051+
QStringList all = symbolNames();
1052+
foreach ( const QString &str, all )
1053+
{
1054+
if ( !str.contains( param, Qt::CaseInsensitive ) )
1055+
resultNames.append( str );
1056+
}
1057+
}
1058+
1059+
// not apply the operator
1060+
if ( firstSet )
1061+
{
1062+
symbols = resultNames;
1063+
firstSet = false;
1064+
}
1065+
else
1066+
{
1067+
if ( op == "OR" )
1068+
{
1069+
symbols.append( resultNames );
1070+
}
1071+
else if ( op == "AND" )
1072+
{
1073+
QStringList dummy = symbols;
1074+
symbols.clear();
1075+
foreach ( const QString &result, resultNames )
1076+
{
1077+
if ( dummy.contains( result ) )
1078+
symbols.append( result );
1079+
}
1080+
}
1081+
}
1082+
} // DOM loop ends here
1083+
}
1084+
sqlite3_finalize( ppStmt );
1085+
return symbols;
1086+
}
1087+
1088+
QgsSmartConditionMap QgsStyleV2::smartgroup( int id )
1089+
{
1090+
if( mCurrentDB == NULL )
1091+
{
1092+
QgsDebugMsg( "Cannot open database for listing groups" );
1093+
return QgsSmartConditionMap();
1094+
}
1095+
char *query;
1096+
int nError;
1097+
sqlite3_stmt *ppStmt;
1098+
1099+
QgsSmartConditionMap condition;
1100+
1101+
query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d;", id );
1102+
nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
1103+
if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
1104+
{
1105+
QDomDocument doc;
1106+
QString xmlstr = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, 0 ) ) );
1107+
if ( !doc.setContent( xmlstr ) )
1108+
{
1109+
QgsDebugMsg( "Cannot open smartgroup id: " + id );
1110+
}
1111+
QDomElement smartEl = doc.documentElement();
1112+
QString op = smartEl.attribute( "operator" );
1113+
QDomNodeList conditionNodes = smartEl.childNodes();
1114+
1115+
for ( int i = 0; i < conditionNodes.count(); i++ )
1116+
{
1117+
QDomElement condEl = conditionNodes.at( i ).toElement();
1118+
QString constraint = condEl.attribute( "constraint" );
1119+
QString param = condEl.attribute( "param" );
1120+
1121+
condition.insert( constraint, param );
1122+
}
1123+
}
1124+
sqlite3_finalize( ppStmt );
1125+
1126+
return condition;
1127+
}
1128+
1129+
QString QgsStyleV2::smartgroupOperator( int id )
1130+
{
1131+
if( mCurrentDB == NULL )
1132+
{
1133+
QgsDebugMsg( "Cannot open database for listing groups" );
1134+
return QString();
1135+
}
1136+
char *query;
1137+
int nError;
1138+
sqlite3_stmt *ppStmt;
1139+
1140+
QString op;
1141+
1142+
query = sqlite3_mprintf( "SELECT xml FROM smartgroup WHERE id=%d;", id );
1143+
nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, NULL );
1144+
if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
1145+
{
1146+
QDomDocument doc;
1147+
QString xmlstr = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, 0 ) ) );
1148+
if ( !doc.setContent( xmlstr ) )
1149+
{
1150+
QgsDebugMsg( "Cannot open smartgroup id: " + id );
1151+
}
1152+
QDomElement smartEl = doc.documentElement();
1153+
op = smartEl.attribute( "operator" );
1154+
}
1155+
sqlite3_finalize( ppStmt );
1156+
1157+
return op;
1158+
}

src/core/symbology-ng/qgsstylev2.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define QGSSTYLEV2_H
1818

1919
#include <QMap>
20+
#include <QMultiMap>
2021
#include <QString>
2122

2223
#include <sqlite3.h>
@@ -32,16 +33,18 @@ class QDomElement;
3233

3334
typedef QMap<QString, QgsVectorColorRampV2* > QgsVectorColorRampV2Map;
3435
typedef QMap<int, QString> QgsSymbolGroupMap;
36+
typedef QMultiMap<QString, QString> QgsSmartConditionMap;
3537

3638
// Enumeraters representing sqlite DB columns
3739
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolGroupId };
3840
enum SymgroupTable { SymgroupId, SymgroupName, SymgroupParent };
3941
enum TagTable { TagId, TagName };
4042
enum TagmapTable { TagmapTagId, TagmapSymbolId };
4143
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML };
44+
enum SmartgroupTable { SmartgroupId, SmartgroupName, SmartgroupXML };
4245

4346
// Enums for types
44-
enum StyleEntity { SymbolEntity, GroupEntity, TagEntity, ColorrampEntity };
47+
enum StyleEntity { SymbolEntity, GroupEntity, TagEntity, ColorrampEntity, SmartgroupEntity };
4548

4649
class CORE_EXPORT QgsStyleV2
4750
{
@@ -84,6 +87,7 @@ class CORE_EXPORT QgsStyleV2
8487

8588
//! return the id in the style database for the given group name
8689
int groupId( QString group );
90+
int tagId( QString tag );
8791

8892
//! return the all the groups in the style
8993
QStringList groupNames();
@@ -158,6 +162,25 @@ class CORE_EXPORT QgsStyleV2
158162
//! return the tags associated with the symbol
159163
QStringList tagsOfSymbol( QString symbol );
160164

165+
//! adds the smartgroup to the database and returns the id
166+
int addSmartgroup( QString name, QString op, QgsSmartConditionMap conditions );
167+
168+
//! returns the smart groups map
169+
QgsSymbolGroupMap smartgroupsListMap();
170+
171+
//! returns the smart groups list
172+
QStringList smartgroupNames();
173+
174+
//! returns the QgsSmartConditionMap for the given id
175+
QgsSmartConditionMap smartgroup( int id );
176+
177+
//! returns the operator for the smartgroup
178+
//! @note: clumsy implementation TODO create a class for smartgroups
179+
QString smartgroupOperator( int id );
180+
181+
//! returns the symbols for the smartgroup
182+
QStringList symbolsOfSmartgroup( int id );
183+
161184
protected:
162185

163186
QgsSymbolV2Map mSymbols;

0 commit comments

Comments
 (0)