Skip to content

Commit ca105e4

Browse files
author
Arunmozhi
committedJul 9, 2012
Converted symbology style from XML to SQlite
- Adds a python script, and the resulting default .db file - Cannot SAVE new symbols into the DB still Added the Grouping of symbols in Style Manager - Can read groups from the DB and load them - Limited to read-only operations
1 parent bb0b6e4 commit ca105e4

File tree

10 files changed

+514
-192
lines changed

10 files changed

+514
-192
lines changed
 

‎resources/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
INSTALL(FILES srs.db qgis.db qgis_help.db symbology-ng-style.xml spatialite.db customization.xml
1+
INSTALL(FILES srs.db qgis.db qgis_help.db symbology-ng-style.db spatialite.db customization.xml
22
DESTINATION ${QGIS_DATA_DIR}/resources)
33

44
ADD_SUBDIRECTORY(context_help)

‎resources/symbology-ng-style.db

47 KB
Binary file not shown.

‎scripts/symbol_xml2db.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/python
2+
"""
3+
/***************************************************************************
4+
symbol_xml2db.py
5+
-------------------
6+
begin : 26-5-2012
7+
copyright : (C) 2012 by Arunmozhi
8+
email : aruntheguy at gmail dot com
9+
***************************************************************************/
10+
11+
/***************************************************************************
12+
* *
13+
* This program is free software; you can redistribute it and/or modify *
14+
* it under the terms of the GNU General Public License as published by *
15+
* the Free Software Foundation; either version 2 of the License, or *
16+
* (at your option) any later version. *
17+
* *
18+
***************************************************************************/
19+
20+
The script creates a sqlite3 Db for storing the symbols which will be
21+
shipped with QGIS by default. It then converts symbols and colorramps
22+
in the symbology_ng_style.xml to the database table entries.
23+
"""
24+
import sqlite3
25+
26+
from xml.dom.minidom import parse, parseString
27+
28+
xmlfile = "../resources/symbology-ng-style.xml"
29+
dbfile = "../resources/symbology-ng-style.db"
30+
31+
_symbol = "CREATE TABLE symbol("\
32+
"id INTEGER PRIMARY KEY,"\
33+
"name TEXT UNIQUE,"\
34+
"xml TEXT,"\
35+
"groupid INTEGER)"
36+
37+
_colorramp = "CREATE TABLE colorramp("\
38+
"id INTEGER PRIMARY KEY,"\
39+
"name TEXT,"\
40+
"xml TEXT)"
41+
42+
_tag = "CREATE TABLE tag("\
43+
"id INTEGER PRIMARY KEY,"\
44+
"name TEXT)"
45+
46+
_tagmap = "CREATE TABLE tagmap("\
47+
"tag_id INTEGER NOT NULL,"\
48+
"symbol_id INTEGER)"
49+
50+
_symgroup = "CREATE TABLE symgroup("\
51+
"id INTEGER PRIMARY KEY,"\
52+
"name TEXT,"\
53+
"parent INTEGER)"
54+
55+
create_tables = [ _symbol, _colorramp, _tag, _tagmap, _symgroup ]
56+
57+
# Create the DB with required Schema
58+
conn = sqlite3.connect( dbfile )
59+
c = conn.cursor()
60+
print "Creating tables in the Database\n"
61+
for table in create_tables:
62+
try:
63+
c.execute( table )
64+
print table
65+
except sqlite3.OperationalError as e:
66+
pass
67+
conn.commit()
68+
69+
# parse the XML file & write symbol into DB
70+
dom = parse( xmlfile )
71+
symbols = dom.getElementsByTagName( "symbol" )
72+
for symbol in symbols:
73+
symbol_name = symbol.getAttribute( "name" )
74+
if '@' in symbol_name:
75+
parts = symbol_name.split('@')
76+
parent_name = parts[1]
77+
layerno = int(parts[2])
78+
c.execute( "SELECT xml FROM symbol WHERE name=(?)", (parent_name,) )
79+
symdom = parseString( c.fetchone()[0] ).getElementsByTagName( 'symbol' )[0]
80+
symdom.getElementsByTagName( "layer" )[ layerno ].appendChild( symbol )
81+
c.execute( "UPDATE symbol SET xml=? WHERE name=?", ( symdom.toxml(), parent_name ))
82+
else:
83+
c.execute( "INSERT INTO symbol VALUES (?,?,?,?)", ( None, symbol_name, symbol.toxml(), None ) )
84+
conn.commit()
85+
86+
87+
# ColorRamps
88+
colorramps = dom.getElementsByTagName( "colorramp" )
89+
for ramp in colorramps:
90+
ramp_name = ramp.getAttribute( "name" )
91+
c.execute( "INSERT INTO colorramp VALUES (?,?,?)", ( None, ramp_name, ramp.toxml() ) )
92+
conn.commit()
93+
94+
# Finally close the sqlite cursor
95+
c.close()

‎src/core/qgsapplication.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,12 @@ const QString QgsApplication::svgPath()
516516

517517
const QString QgsApplication::userStyleV2Path()
518518
{
519-
return qgisSettingsDirPath() + QString( "symbology-ng-style.xml" );
519+
return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
520520
}
521521

522522
const QString QgsApplication::defaultStyleV2Path()
523523
{
524-
return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.xml" );
524+
return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
525525
}
526526

527527
const QString QgsApplication::libraryPath()

‎src/core/symbology-ng/qgsstylev2.cpp

Lines changed: 121 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#include <QDomElement>
2828
#include <QFile>
2929
#include <QTextStream>
30+
#include <QByteArray>
31+
32+
#include <sqlite3.h>
3033

3134
#define STYLE_CURRENT_VERSION "0"
3235

@@ -167,69 +170,71 @@ QStringList QgsStyleV2::colorRampNames()
167170
return mColorRamps.keys();
168171
}
169172

170-
171-
bool QgsStyleV2::load( QString filename )
173+
sqlite3* QgsStyleV2::openDB( QString filename )
172174
{
173-
mErrorString = QString();
175+
sqlite3 *db;
176+
int rc;
174177

175-
// import xml file
176-
QDomDocument doc( "style" );
177-
QFile f( filename );
178-
if ( !f.open( QFile::ReadOnly ) )
178+
QByteArray namearray = filename.toUtf8();
179+
rc = sqlite3_open( namearray.constData(), &db );
180+
if ( rc )
179181
{
180-
mErrorString = "Couldn't open the style file: " + filename;
181-
return false;
182+
mErrorString = "Couldn't open the style DB: " + QString( sqlite3_errmsg( db ) );
183+
sqlite3_close( db );
184+
return NULL;
182185
}
183186

184-
// parse the document
185-
if ( !doc.setContent( &f ) )
186-
{
187-
mErrorString = "Couldn't parse the style file: " + filename;
188-
f.close();
189-
return false;
190-
}
191-
f.close();
187+
return db;
188+
}
192189

193-
QDomElement docElem = doc.documentElement();
194-
if ( docElem.tagName() != "qgis_style" )
195-
{
196-
mErrorString = "Incorrect root tag in style: " + docElem.tagName();
197-
return false;
198-
}
190+
bool QgsStyleV2::load( QString filename )
191+
{
192+
mErrorString = QString();
199193

200-
// check for style version
201-
QString version = docElem.attribute( "version" );
202-
if ( version != STYLE_CURRENT_VERSION )
203-
{
204-
mErrorString = "Unknown style file version: " + version;
194+
// Open the sqlite DB
195+
sqlite3* db = openDB( filename );
196+
if ( db == NULL )
205197
return false;
206-
}
207-
208-
// load symbols
209-
QDomElement symbolsElement = docElem.firstChildElement( "symbols" );
210-
if ( !symbolsElement.isNull() )
198+
// First create all the Main symbols
199+
sqlite3_stmt *ppStmt;
200+
const char *query = "SELECT * FROM symbol;";
201+
int nError = sqlite3_prepare_v2( db, query, -1, &ppStmt, NULL );
202+
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
211203
{
212-
mSymbols = QgsSymbolLayerV2Utils::loadSymbols( symbolsElement );
204+
QDomDocument doc;
205+
QString symbol_name = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, SymbolName ) ) );
206+
QString xmlstring = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, SymbolXML ) ) );
207+
if( !doc.setContent( xmlstring ) )
208+
{
209+
QgsDebugMsg( "Cannot open symbol" + symbol_name );
210+
continue;
211+
}
212+
QDomElement symElement = doc.documentElement();
213+
QgsSymbolV2 *symbol = QgsSymbolLayerV2Utils::loadSymbol( symElement );
214+
if ( symbol != NULL )
215+
mSymbols.insert( symbol_name, symbol );
213216
}
217+
sqlite3_finalize( ppStmt );
214218

215-
// load color ramps
216-
QDomElement rampsElement = docElem.firstChildElement( "colorramps" );
217-
QDomElement e = rampsElement.firstChildElement();
218-
while ( !e.isNull() )
219+
const char *rquery = "SELECT * FROM colorramp;";
220+
nError = sqlite3_prepare_v2( db, rquery, -1, &ppStmt, NULL );
221+
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
219222
{
220-
if ( e.tagName() == "colorramp" )
223+
QDomDocument doc;
224+
QString ramp_name = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, ColorrampName ) ) );
225+
QString xmlstring = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, ColorrampXML ) ) );
226+
if( !doc.setContent( xmlstring ) )
221227
{
222-
QgsVectorColorRampV2* ramp = QgsSymbolLayerV2Utils::loadColorRamp( e );
223-
if ( ramp != NULL )
224-
addColorRamp( e.attribute( "name" ), ramp );
228+
QgsDebugMsg( "Cannot open symbol" + ramp_name );
229+
continue;
225230
}
226-
else
227-
{
228-
QgsDebugMsg( "unknown tag: " + e.tagName() );
229-
}
230-
e = e.nextSiblingElement();
231+
QDomElement rampElement = doc.documentElement();
232+
QgsVectorColorRampV2* ramp = QgsSymbolLayerV2Utils::loadColorRamp( rampElement );
233+
if ( ramp != NULL )
234+
addColorRamp( ramp_name, ramp );
231235
}
232236

237+
sqlite3_close( db );
233238
mFileName = filename;
234239
return true;
235240
}
@@ -242,6 +247,9 @@ bool QgsStyleV2::save( QString filename )
242247
if ( filename.isEmpty() )
243248
filename = mFileName;
244249

250+
// TODO evaluate the requirement of this function and change implementation accordingly
251+
252+
/*
245253
QDomDocument doc( "qgis_style" );
246254
QDomElement root = doc.createElement( "qgis_style" );
247255
root.setAttribute( "version", STYLE_CURRENT_VERSION );
@@ -271,6 +279,7 @@ bool QgsStyleV2::save( QString filename )
271279
QTextStream ts( &f );
272280
doc.save( ts, 2 );
273281
f.close();
282+
*/
274283

275284
mFileName = filename;
276285
return true;
@@ -293,3 +302,68 @@ bool QgsStyleV2::renameColorRamp( QString oldName, QString newName )
293302
mColorRamps.insert( newName, mColorRamps.take( oldName ) );
294303
return true;
295304
}
305+
306+
QgsSymbolGroupMap QgsStyleV2::groupNames( QString parent )
307+
{
308+
QgsDebugMsg( "Request for groupNames for parent " + parent );
309+
// get the name list from the sqlite db and return as a QStringList
310+
sqlite3* db = openDB( mFileName );
311+
if( db == NULL )
312+
{
313+
QgsDebugMsg( "Cannot open database for listing groups" );
314+
return QgsSymbolGroupMap();
315+
}
316+
sqlite3_stmt *ppStmt;
317+
int nError;
318+
char *query;
319+
320+
if ( parent == "" || parent == QString() )
321+
{
322+
query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent IS NULL;" );
323+
}
324+
else
325+
{
326+
QByteArray parentArray = parent.toUtf8();
327+
char *subquery = sqlite3_mprintf( "SELECT * FROM symgroup WHERE name='%q';", parentArray.constData() );
328+
nError = sqlite3_prepare_v2( db, subquery, -1, &ppStmt, NULL );
329+
if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
330+
{
331+
query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent=%d;", sqlite3_column_int( ppStmt, SymgroupId ) );
332+
}
333+
sqlite3_finalize( ppStmt );
334+
}
335+
336+
QgsSymbolGroupMap groupNames;
337+
338+
nError = sqlite3_prepare_v2( db, query, -1, &ppStmt, NULL );
339+
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
340+
{
341+
QString group = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, SymgroupName ) ) );
342+
groupNames.insert( sqlite3_column_int( ppStmt, SymgroupId ), group );
343+
}
344+
sqlite3_finalize( ppStmt );
345+
sqlite3_close( db );
346+
return groupNames;
347+
}
348+
349+
QStringList QgsStyleV2::symbolsOfGroup( int groupid )
350+
{
351+
sqlite3 *db = openDB( mFileName );
352+
if( db == NULL )
353+
{
354+
QgsDebugMsg( "Cannot Open Db for getting group symbols of groupid: " + groupid );
355+
return QStringList();
356+
}
357+
358+
QStringList symbols;
359+
sqlite3_stmt *ppStmt;
360+
char *query = sqlite3_mprintf( "SELECT name FROM symbol WHERE groupid=%d;", groupid );
361+
int nErr = sqlite3_prepare_v2( db, query, -1, &ppStmt, NULL );
362+
while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
363+
{
364+
QString symbol = QString( reinterpret_cast<const char*>( sqlite3_column_text( ppStmt, 0 ) ) );
365+
symbols.append( symbol );
366+
}
367+
368+
return symbols;
369+
}

‎src/core/symbology-ng/qgsstylev2.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <QMap>
2020
#include <QString>
2121

22+
#include <sqlite3.h>
23+
2224
#include "qgssymbollayerv2utils.h" // QgsStringMap
2325

2426
class QgsSymbolV2;
@@ -29,6 +31,15 @@ class QDomDocument;
2931
class QDomElement;
3032

3133
typedef QMap<QString, QgsVectorColorRampV2* > QgsVectorColorRampV2Map;
34+
typedef QMap<int, QString> QgsSymbolGroupMap;
35+
36+
// Enumeraters representing sqlite DB columns
37+
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolGroupId };
38+
enum SymgroupTable { SymgroupId, SymgroupName, SymgroupParent };
39+
enum TagTable { TagId, TagName };
40+
enum TagmapTable { TagmapTagId, TagmapSymbolId };
41+
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML };
42+
3243

3344
class CORE_EXPORT QgsStyleV2
3445
{
@@ -65,6 +76,13 @@ class CORE_EXPORT QgsStyleV2
6576
//! return a list of names of symbols
6677
QStringList symbolNames();
6778

79+
//! return a map of all groupid and names for the given parent
80+
//! Returns the First order groups when empty QString is passed
81+
QgsSymbolGroupMap groupNames( QString parent = "" );
82+
83+
//! returns the symbolnames of a given groupid
84+
QStringList symbolsOfGroup( int groupid );
85+
6886

6987
//! add color ramp to style. takes ramp's ownership
7088
bool addColorRamp( QString name, QgsVectorColorRampV2* colorRamp );
@@ -110,6 +128,9 @@ class CORE_EXPORT QgsStyleV2
110128
QString mFileName;
111129

112130
static QgsStyleV2* mDefaultStyle;
131+
132+
//! Convinence function to open the DB and return a sqlite3 object
133+
sqlite3* openDB( QString filename );
113134
};
114135

115136

0 commit comments

Comments
 (0)
Please sign in to comment.