If this is a set of styles that you apply as part of a routine workflow, it might be worth setting up a QML style file that can be applied to any workspace of the same type.
If the styling of elements is thematic (and you know what columns drive the theme) you can build a QML file programmatically straight out of PostgreSQL (assuming you have your data in there... I put all our data into PostgreSQL using ogr2ogr, as a matter of routine).
For example, I have a file with ~150 styles for government zone polygons (subsets of the zones have the same style). We wanted to categorise by zone_code, but have a more-informative Legend entry - and we wanted to use a colour ramp as dictated by a specific table column:
To create my QML file, I wrote a python script that looks like this -
import psycopg2
# Set up connection to database
conn_string = "host='localhost' dbname='[db]' user='[me]' password='[not telling]'"
# Connect to database
conn = psycopg2.connect(conn_string)
# set up default cursor (to run queries)
cursor = conn.cursor()
# Get LGA details; store them to a list
cursor.execute('select
xmlelement(name qgis,
xmlattributes(\'2.8.2-Wien\' as version),
xmlelement(name "renderer-v2",
xmlattributes(\'zone_code\' as attr, 0 as symbollevels, \'categorizedSymbol\' as type),
xmlelement(name symbols,
xmlagg(xmlelement(name symbol,
xmlattributes(1 as alpha, \'fill\' as type, gid-1 as name),
xmlelement(name layer,
xmlattributes(0 as pass, \'SimpleFill\' as class, 0 as locked),
xmlelement(name prop,
xmlattributes(\'color\' as k, rgba as v)),
xmlelement(name prop,
xmlattributes(\'outline_color\' as k, \'230,230,230,255\' as v)))))),
xmlelement(name categories,
xmlagg(xmlelement(name category,
xmlattributes(\'true\' as render, gid-1 as symbol, zone_code as value, zone_code||\' (\'|| description || \')\' as label))))))
from se_zones')
xml_new = ''
for row in cursor:
print row[0]
xml_new = row[0]
#print 'XML_New: ', xml_new # testing only
# pre-pend QGIS-specific DOCYTPE to XML
outStr= "<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>\n" + xml_new
# open destination XML file and save XML to it
outFile = open("Zones.qml", 'w')
outFile.write(outStr)
The script is kludgy (there's no need for the for row in cursor
since cursor
only returns one row), but result is exactly what I wanted: a QML file that I could distribute to my colleagues so that they could style Zoned data with 3 clicks.
Note that in this particular instance, zone_code and description are concatenated to give the Legend entry.
When theme files need to be built for different sets of categories, only the query has to change: we have ~25 different theme sets, and they were all constructed from that one script by changing the query and the destination file.
The output looks like this -
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM' >
<qgis version="2.8.2-Wien">
<renderer-v2 attr="zone_code" symbollevels="0" type="categorizedSymbol">
<symbols>
<symbol alpha="1" type="fill" name="0">
<layer pass="0" class="SimpleFill" locked="0">
<prop k="color" v="240,217,250,255" />
<prop k="outline_color" v="230,230,230,255" />
</layer>
<symbol>
...
</symbols>
<categories>
<category render="true" symbol="0" value="B1Z" label="B1Z (Commercial 1 Zone)" />
...
</categories>
</renderer-v2>
</qgis>
For your specific theme you would have to write the appropriate query (which means you need to know the columns that 'drive' the style categories).