2008-01-10 04:49:11 +00:00
#***************************************************************************
# ms_export.py
# --------------------------------------
# Date : Sun Sep 16 12:33:46 AKDT 2007
# Copyright : (C) 2008 by Gary E. Sherman
# Email : sherman at mrcc dot com
#***************************************************************************
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU General Public License as published by *
#* the Free Software Foundation; either version 2 of the License, or *
#* (at your option) any later version. *
#* *
#***************************************************************************/
# This class exports a QGIS project file to a mapserver .map file.
# All the work is done in the writeMapFile method. The msexport binary
# presents a Qt based GUI that collects the needed information for this
# script.
2008-04-25 19:19:02 +00:00
# Matthew Perry contributed major portions of this work.
2009-11-07 16:59:29 +00:00
# Adapted by Erik van de Pol, B3Partners BV.
2008-01-10 04:49:11 +00:00
#
# CHANGES SHOULD NOT BE MADE TO THE writeMapFile METHOD UNLESS YOU
# ARE CHANGING THE QgsMapserverExport CLASS AND YOU KNOW WHAT YOU ARE
# DOING
2009-11-07 16:59:29 +00:00
from xml . dom import minidom
2008-01-10 04:49:11 +00:00
from string import *
2009-11-07 16:59:29 +00:00
from qgis . core import QgsDataSourceURI
from qgis . core import QgsMapLayerRegistry
#from qgis.core import QgsProject
from PyQt4 . QtCore import QString
from PyQt4 . QtCore import QVariant
2008-01-10 04:49:11 +00:00
# symbol map
2009-11-07 16:59:29 +00:00
qgis2map_symbol = {
" hard:circle " : " circle " ,
" hard:triangle " : " triangle " ,
" hard:equilateral_triangle " : " equilateral-triangle " ,
" hard:rectangle " : " square " ,
" hard:regular_star " : " star " ,
" hard:diamond " : " diamond "
}
# alignment/position map
qgis2map_aligment2position = {
" center " : " cc " ,
" above " : " uc " ,
" right " : " cr " ,
" below " : " lc " ,
" left " : " cl " ,
" aboveright " : " ur " ,
" belowright " : " lr " ,
" belowleft " : " ll " ,
" aboveleft " : " ul "
}
# the keys are fonts that must be available in QGis
# the values in this dictionary must correspond to
# the fonts in the file denoted by the FONTSET in the mapfile
#
# "MS Shell Dlg 2" is the default label font in QGis.
# The automatic mapping to "Tahoma" is correct for Windows 2000, Windows XP,
# Windows Server 2003, Windows Vista and Windows 7.
# See: http://msdn.microsoft.com/en-us/library/dd374112%28VS.85%29.aspx
qgis2map_fontset = {
" Arial " : " arial " ,
" Courier " : " courier " ,
" Georgia " : " georgia " ,
" Times New Roman " : " times " ,
" Trebuchet MS " : " trebuchet_ms " ,
" Verdana " : " verdana " ,
" Tahoma " : " tahoma " ,
" MS Shell Dlg 2 " : " tahoma "
}
# Note that tahoma-italic and tahoma-bold-italic do not exist.
# Therefore a mapping to the corresponding verdana-variants is made
# in the fonts file pointed to by the fontsPath. Feel free to map to another font there.
bool2str = { True : " true " , False : " false " }
# This is a magic number now. Rationale?
symbolSizeMultiplier = 3.5
class Qgis2MapDefaults : pass
defaults = Qgis2MapDefaults ( )
defaults . fontsPath = " ./fonts/fonts.txt "
defaults . symbolsPath = " ./symbols/symbols.txt "
defaults . mapServerUrl = " http://my.host.com/cgi-bin/mapserv.exe "
defaults . width = " 100 "
defaults . height = " 100 "
defaults . dump = True
defaults . force = True
defaults . partials = True
defaults . antialias = True
2008-01-10 04:49:11 +00:00
class Qgis2Map :
def __init__ ( self , projectFile , mapFile ) :
self . project = projectFile
self . mapFile = mapFile
# create the DOM
2008-01-17 18:58:30 +00:00
self . qgs = minidom . parse ( projectFile )
2008-01-10 04:49:11 +00:00
# init the other members that are not set by the constructor
2009-11-07 16:59:29 +00:00
self . mapServerUrl = defaults . mapServerUrl
self . fontsPath = defaults . fontsPath
self . symbolsPath = defaults . symbolsPath
2008-01-10 04:49:11 +00:00
self . units = ' '
self . imageType = ' '
self . mapName = ' '
2009-11-07 16:59:29 +00:00
self . width = defaults . width
self . height = defaults . height
2008-10-24 11:00:31 +00:00
self . minimumScale = ' '
self . maximumScale = ' '
2008-01-10 04:49:11 +00:00
self . template = ' '
self . header = ' '
self . footer = ' '
2009-11-07 16:59:29 +00:00
self . dump = bool2str [ defaults . dump ]
self . force = bool2str [ defaults . force ]
self . antialias = bool2str [ defaults . antialias ]
self . partials = bool2str [ defaults . partials ]
2008-01-10 04:49:11 +00:00
self . symbolQueue = { }
2009-11-07 16:59:29 +00:00
2008-01-10 04:49:11 +00:00
# Set the options collected from the GUI
2009-11-07 20:11:29 +00:00
def setOptions ( self , msUrl , units , image , mapname , width , height , template , header , footer , dump , force , antialias , partials , exportLayersOnly , fontsPath , symbolsPath ) :
2009-11-07 16:59:29 +00:00
if msUrl . encode ( ' utf-8 ' ) != " " :
self . mapServerUrl = msUrl . encode ( ' utf-8 ' )
if fontsPath . encode ( ' utf-8 ' ) != " " :
self . fontsPath = fontsPath . encode ( ' utf-8 ' )
if symbolsPath . encode ( ' utf-8 ' ) != " " :
self . symbolsPath = symbolsPath . encode ( ' utf-8 ' )
if width . encode ( ' utf-8 ' ) != " " :
self . width = width . encode ( ' utf-8 ' )
if height . encode ( ' utf-8 ' ) != " " :
self . height = height . encode ( ' utf-8 ' )
2009-01-19 19:53:23 +00:00
self . units = units . encode ( ' utf-8 ' )
self . imageType = image . encode ( ' utf-8 ' )
self . mapName = mapname . encode ( ' utf-8 ' )
2009-11-07 16:59:29 +00:00
2008-10-24 11:00:31 +00:00
#self.minimumScale = minscale
#self.maximumScale = maxscale
2009-01-19 19:53:23 +00:00
self . template = template . encode ( ' utf-8 ' )
self . header = header . encode ( ' utf-8 ' )
self . footer = footer . encode ( ' utf-8 ' )
#print units, image, mapname, width, height, template, header, footer
2008-01-10 04:49:11 +00:00
2009-11-07 20:11:29 +00:00
self . dump = bool2str [ dump ]
self . force = bool2str [ force ]
self . antialias = bool2str [ antialias ]
self . partials = bool2str [ partials ]
self . exportLayersOnly = exportLayersOnly
2009-11-07 16:59:29 +00:00
2008-01-10 04:49:11 +00:00
## All real work happens here by calling methods to write the
## various sections of the map file
def writeMapFile ( self ) :
# open the output file
print " creating the map file "
self . outFile = open ( self . mapFile , ' w ' )
2009-11-07 20:11:29 +00:00
logmsg = " Starting \n "
if self . exportLayersOnly == False :
# write the general map and web settings
print " --- python : map section "
self . writeMapSection ( )
logmsg + = " Wrote map section \n "
print " --- python : map section done "
# write the projection section
print " --- python : proj section "
self . writeProjectionSection ( )
logmsg + = " Wrote projection section \n "
print " --- python : proj section done "
# write the output format section
print " --- python : outputformat section "
self . writeOutputFormat ( )
logmsg + = " Wrote output format section \n "
print " --- python : outputformat section done "
# write the legend section
print " --- python : legend section "
self . writeLegendSection ( )
logmsg + = " Wrote legend section \n "
print " --- python : legend section done "
# write the WEB section
print " --- python : web section "
self . writeWebSection ( )
logmsg + = " Wrote web section \n "
print " --- python : web section done "
2008-01-10 04:49:11 +00:00
# write the LAYER sections
print " --- python : layer section "
2009-11-07 20:11:29 +00:00
layersMsg = self . writeMapLayers ( )
2008-01-10 04:49:11 +00:00
logmsg + = " Wrote map layers \n "
2009-11-07 20:11:29 +00:00
logmsg + = layersMsg
2008-01-10 04:49:11 +00:00
print " --- python : layer section done "
2009-11-07 20:11:29 +00:00
if self . exportLayersOnly == False :
# we use an external synbol set instead
# write the symbol defs section
# must happen after layers so we can build a symbol queue
#print " --- python : symbol section "
#self.writeSymbolSection()
#logmsg += "Wrote symbol section\n"
#print " --- python : symbol section done"
2008-01-10 04:49:11 +00:00
2009-11-07 20:11:29 +00:00
# END and close the map file
self . outFile . write ( " END " )
self . outFile . close ( )
2008-01-10 04:49:11 +00:00
logmsg + = " Map file completed for " + self . project + " \n "
logmsg + = " Map file saved as " + self . mapFile + " \n "
return logmsg
# Write the general parts of the map section
def writeMapSection ( self ) :
2009-01-19 19:53:23 +00:00
self . outFile . write ( " # Map file created from QGIS project file " + self . project . encode ( ' utf-8 ' ) + " \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " # Edit this file to customize for your map interface \n " )
self . outFile . write ( " # (Created with PyQgis MapServer Export plugin) \n " )
self . outFile . write ( " MAP \n " )
2009-11-07 20:11:29 +00:00
self . outFile . write ( " NAME \" " + self . mapName + " \" \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " # Map image size \n " )
2009-11-07 16:59:29 +00:00
if self . width == ' ' or self . height == ' ' :
self . outFile . write ( " SIZE 0 0 \n " )
else :
self . outFile . write ( " SIZE " + str ( self . width ) + " " + str ( self . height ) + " \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " UNITS %s \n " % ( self . units ) )
self . outFile . write ( " \n " )
# extents
2009-11-07 16:59:29 +00:00
self . outFile . write ( self . getExtentString ( ) )
self . outFile . write ( " FONTSET ' " + self . fontsPath + " ' \n " )
# B3Partners uses external symbol set
self . outFile . write ( " SYMBOLSET ' " + self . symbolsPath + " ' \n " )
def getExtentString ( self ) :
stringToAddTo = " "
2008-01-10 04:49:11 +00:00
xmin = self . qgs . getElementsByTagName ( " xmin " )
2009-11-07 16:59:29 +00:00
stringToAddTo + = " EXTENT "
stringToAddTo + = xmin [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
stringToAddTo + = " "
2008-01-10 04:49:11 +00:00
ymin = self . qgs . getElementsByTagName ( " ymin " )
2009-11-07 16:59:29 +00:00
stringToAddTo + = ymin [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
stringToAddTo + = " "
2008-01-10 04:49:11 +00:00
xmax = self . qgs . getElementsByTagName ( " xmax " )
2009-11-07 16:59:29 +00:00
stringToAddTo + = xmax [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
stringToAddTo + = " "
2008-01-10 04:49:11 +00:00
ymax = self . qgs . getElementsByTagName ( " ymax " )
2009-11-07 16:59:29 +00:00
stringToAddTo + = ymax [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
stringToAddTo + = " \n "
return stringToAddTo
2008-01-10 04:49:11 +00:00
# Write the OUTPUTFORMAT section
def writeOutputFormat ( self ) :
self . outFile . write ( " # Background color for the map canvas -- change as desired \n " )
2009-11-07 20:11:29 +00:00
self . outFile . write ( " IMAGECOLOR 255 255 255 \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " IMAGEQUALITY 95 \n " )
self . outFile . write ( " IMAGETYPE " + self . imageType + " \n " )
2009-11-07 16:59:29 +00:00
self . outFile . write ( " \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " OUTPUTFORMAT \n " )
self . outFile . write ( " NAME " + self . imageType + " \n " )
self . outFile . write ( " DRIVER ' GD/ " + self . imageType . upper ( ) + " ' \n " )
self . outFile . write ( " MIMETYPE ' image/ " + lower ( self . imageType ) + " ' \n " )
2009-11-07 16:59:29 +00:00
if self . imageType . lower ( ) != " gif " :
self . outFile . write ( " IMAGEMODE RGBA \n " )
#self.outFile.write(" #IMAGEMODE PC256\n")
2008-01-10 04:49:11 +00:00
self . outFile . write ( " EXTENSION ' " + lower ( self . imageType ) + " ' \n " )
self . outFile . write ( " END \n " )
# Write Projection section
def writeProjectionSection ( self ) :
# Need to get the destination srs from one of the map layers since
# the project file doesn't contain the epsg id or proj4 text for
# the map apart from that defined in each layer
self . outFile . write ( " PROJECTION \n " )
# Get the proj4 text from the first map layer's destination SRS
destsrs = self . qgs . getElementsByTagName ( " destinationsrs " ) [ 0 ]
proj4Text = destsrs . getElementsByTagName ( " proj4 " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# the proj4 text string needs to be reformatted to make mapserver happy
self . outFile . write ( self . formatProj4 ( proj4Text ) )
self . outFile . write ( " END \n \n " )
# Write the LEGEND section
def writeLegendSection ( self ) :
self . outFile . write ( " # Legend \n " )
self . outFile . write ( " LEGEND \n " )
self . outFile . write ( " IMAGECOLOR 255 255 255 \n " )
self . outFile . write ( " STATUS ON \n " )
self . outFile . write ( " KEYSIZE 18 12 \n " )
self . outFile . write ( " LABEL \n " )
self . outFile . write ( " TYPE BITMAP \n " )
self . outFile . write ( " SIZE MEDIUM \n " )
self . outFile . write ( " COLOR 0 0 89 \n " )
self . outFile . write ( " END \n " )
self . outFile . write ( " END \n \n " )
2009-11-07 16:59:29 +00:00
# groups are ignored as of yet
self . legendlayerfileNodesById = { }
for legendlayerfileNode in self . qgs . getElementsByTagName ( " legend " ) [ 0 ] . getElementsByTagName ( " legendlayerfile " ) :
key = legendlayerfileNode . getAttribute ( " layerid " ) . encode ( " utf-8 " )
if ( key != " " ) :
self . legendlayerfileNodesById [ key ] = legendlayerfileNode
2008-01-10 04:49:11 +00:00
# Write the symbol definitions
def writeSymbolSection ( self ) :
for symbol in self . symbolQueue . keys ( ) :
self . outFile . write ( self . symbolQueue [ symbol ] )
self . outFile . write ( " \n " )
# Write the WEB section of the map file
def writeWebSection ( self ) :
self . outFile . write ( " # Web interface definition. Only the template parameter \n " )
self . outFile . write ( " # is required to display a map. See MapServer documentation \n " )
self . outFile . write ( " WEB \n " )
self . outFile . write ( " # Set IMAGEPATH to the path where MapServer should \n " )
self . outFile . write ( " # write its output. \n " )
self . outFile . write ( " IMAGEPATH ' /tmp/ ' \n " )
self . outFile . write ( " \n " )
self . outFile . write ( " # Set IMAGEURL to the url that points to IMAGEPATH \n " )
self . outFile . write ( " # as defined in your web server configuration \n " )
self . outFile . write ( " IMAGEURL ' /tmp/ ' \n " )
self . outFile . write ( " \n " )
2009-11-07 16:59:29 +00:00
destsrs = self . qgs . getElementsByTagName ( " destinationsrs " ) [ 0 ]
epsg = destsrs . getElementsByTagName ( " epsg " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( " utf-8 " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " # WMS server settings \n " )
self . outFile . write ( " METADATA \n " )
2009-11-07 16:59:29 +00:00
self . outFile . write ( " ' wms_title ' ' " + self . mapName + " ' \n " )
self . outFile . write ( " ' wms_onlineresource ' ' " + self . mapServerUrl + " ? " + " map " + " = " + self . mapFile + " ' \n " )
self . outFile . write ( " ' wms_srs ' ' EPSG: " + epsg + " ' \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " END \n \n " )
self . outFile . write ( " #Scale range at which web interface will operate \n " )
2008-10-24 11:00:31 +00:00
if self . minimumScale != " " :
self . outFile . write ( " MINSCALE " + self . minimumScale + " \n " )
if self . maximumScale != " " :
self . outFile . write ( " MAXSCALE " + self . maximumScale + " \n " )
2008-01-10 04:49:11 +00:00
self . outFile . write ( " # Template and header/footer settings \n " )
self . outFile . write ( " # Only the template parameter is required to display a map. See MapServer documentation \n " )
if self . template != " " :
self . outFile . write ( " TEMPLATE ' " + self . template + " ' \n " )
if self . header != " " :
self . outFile . write ( " HEADER ' " + self . header + " ' \n " )
if self . footer != " " :
self . outFile . write ( " FOOTER ' " + self . footer + " ' \n " )
self . outFile . write ( " END \n \n " )
2008-04-25 19:19:02 +00:00
# Write the map layers - we have to defer writing to disk so we
# can invert the order of the layes, since they are opposite in QGIS
# compared to mapserver
2008-01-10 04:49:11 +00:00
def writeMapLayers ( self ) :
2008-04-25 19:19:02 +00:00
# get the list of legend nodes so the layers can be written in the
# proper order
2009-11-07 20:11:29 +00:00
resultMsg = ' '
2008-04-25 19:19:02 +00:00
legend_nodes = self . qgs . getElementsByTagName ( " legendlayer " )
self . z_order = list ( )
for legend_node in legend_nodes :
self . z_order . append ( legend_node . getAttribute ( " name " ) . encode ( ' utf-8 ' ) . replace ( " \" " , " " ) )
2008-01-10 04:49:11 +00:00
# get the list of maplayer nodes
maplayers = self . qgs . getElementsByTagName ( " maplayer " )
print " Processing " , len ( maplayers ) , " layers "
count = 0
2008-04-25 19:19:02 +00:00
layer_list = dict ( )
2008-01-10 04:49:11 +00:00
for lyr in maplayers :
count + = 1
print " Processing layer " , count
# The attributes of the maplayer tag contain the scale dependent settings,
# visibility, and layer type
2008-04-25 19:19:02 +00:00
layer_def = " LAYER \n "
2009-11-07 20:11:29 +00:00
# store name of the layer - replace space with underscore for wms compliance
layer_name = lyr . getElementsByTagName ( " layername " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) . replace ( " \" " , " " ) . replace ( " " , " _ " )
2008-04-07 03:22:56 +00:00
# first check to see if there is a name
2009-11-07 20:11:29 +00:00
if len ( layer_name ) > 0 :
layer_def + = " NAME ' %s ' \n " % layer_name
2008-04-07 03:22:56 +00:00
else :
2008-04-25 19:19:02 +00:00
# if no name for the layer, manufacture one
layer_def + = " NAME ' LAYER %s ' \n " % count
2008-01-10 04:49:11 +00:00
if lyr . getAttribute ( " type " ) . encode ( ' utf-8 ' ) == ' vector ' :
2008-04-25 19:19:02 +00:00
layer_def + = " TYPE " + lyr . getAttribute ( " geometry " ) . encode ( ' utf-8 ' ) . upper ( ) + " \n "
2008-01-10 04:49:11 +00:00
elif lyr . getAttribute ( " type " ) . encode ( ' utf-8 ' ) == ' raster ' :
2008-04-25 19:19:02 +00:00
layer_def + = " TYPE " + lyr . getAttribute ( " type " ) . encode ( ' utf-8 ' ) . upper ( ) + " \n "
2009-11-07 16:59:29 +00:00
# Uses default value from the gui
layer_def + = " DUMP " + self . dump + " \n "
2008-01-10 04:49:11 +00:00
# Set min/max scales
2008-10-24 11:00:31 +00:00
if lyr . getAttribute ( ' hasScaleBasedVisibilityFlag ' ) . encode ( ' utf-8 ' ) == 1 :
layer_def + = " MINSCALE " + lyr . getAttribute ( ' minimumScale ' ) . encode ( ' utf-8 ' ) + " \n "
layer_def + = " MAXSCALE " + lyr . getAttribute ( ' maximumScale ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
2009-11-07 16:59:29 +00:00
layer_def + = self . getExtentString ( )
2008-01-10 04:49:11 +00:00
# data
dataString = lyr . getElementsByTagName ( " datasource " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# test if it is a postgis, grass or WMS layer
# is there a better way to do this? probably.
try :
providerString = lyr . getElementsByTagName ( " provider " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
except :
# if providerString is null
providerString = ' '
if providerString == ' postgres ' :
2009-11-07 16:59:29 +00:00
2008-01-10 04:49:11 +00:00
# it's a postgis layer
2008-12-13 14:43:34 +00:00
uri = QgsDataSourceURI ( dataString )
2008-04-25 19:19:02 +00:00
layer_def + = " CONNECTIONTYPE postgis \n "
2008-12-13 14:43:34 +00:00
layer_def + = " CONNECTION \" " + uri . connectionInfo ( ) + " \" \n "
2009-11-07 16:59:29 +00:00
# EvdP: it seems that the uri.geometryColumn() is quoted automaticly by PostGIS.
# To prevent double quoting, we don't quote here.
# Now we are unable to process uri.geometryColumn()s with special characters (uppercase... etc.)
#layer_def += " DATA '\"" + uri.geometryColumn() + "\" FROM " + uri.quotedTablename() + "'\n"
#layer_def += " DATA '" + uri.geometryColumn() + " FROM " + uri.quotedTablename() + "'\n"
layer_id = lyr . getElementsByTagName ( " id " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( " utf-8 " )
uniqueId = self . getPrimaryKey ( layer_id , uri . table ( ) )
2009-11-07 20:11:29 +00:00
# %tablename% is returned when no uniqueId is found: inform user
if uniqueId . find ( " % " ) > = 0 :
resultMsg + = " ! No primary key found for postgres layer ' " + layer_name + \
" ' \n Make sure you edit the mapfile and change the DATA-string \n containing ' " + uniqueId + " ' \n "
2009-11-07 16:59:29 +00:00
epsg = self . getEpsg ( lyr )
layer_def + = " DATA ' " + uri . geometryColumn ( ) + " FROM " + uri . quotedTablename ( ) + " USING UNIQUE " + uniqueId + " USING srid= " + epsg + " ' \n "
2008-04-25 19:19:02 +00:00
# don't write the filter keyword if there isn't one
2008-12-13 14:43:34 +00:00
if uri . sql ( ) != " " :
layer_def + = " FILTER ( " + uri . sql ( ) + " ) \n "
2008-01-10 04:49:11 +00:00
elif providerString == ' wms ' and lyr . getAttribute ( " type " ) . encode ( ' utf-8 ' ) . upper ( ) == ' RASTER ' :
# it's a WMS layer
2008-04-25 19:19:02 +00:00
layer_def + = " CONNECTIONTYPE WMS \n "
layer_def + = " CONNECTION ' " + dataString + " ' \n "
2008-01-10 04:49:11 +00:00
rasterProp = lyr . getElementsByTagName ( " rasterproperties " ) [ 0 ]
# loop thru wmsSubLayers
wmsSubLayers = rasterProp . getElementsByTagName ( ' wmsSublayer ' )
wmsNames = [ ]
wmsStyles = [ ]
for wmsLayer in wmsSubLayers :
wmsNames . append ( wmsLayer . getElementsByTagName ( ' name ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) . replace ( " \" " , " " ) )
try :
wmsStyles . append ( wmsLayer . getElementsByTagName ( ' style ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) )
except :
wmsStyles . append ( ' ' )
# Create necesssary wms metadata
format = rasterProp . getElementsByTagName ( ' wmsFormat ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
2008-04-25 19:19:02 +00:00
layer_def + = " METADATA \n "
layer_def + = " ' wms_name ' ' " + ' , ' . join ( wmsNames ) + " ' \n "
layer_def + = " ' wms_server_version ' ' 1.1.1 ' \n "
2008-01-10 04:49:11 +00:00
try :
2009-11-07 16:59:29 +00:00
#ct = lyr.getElementsByTagName('coordinatetransform')[0]
#srs = ct.getElementsByTagName('sourcesrs')[0].getElementsByTagName('spatialrefsys')[0]
#epsg = srs.getElementsByTagName('epsg')[0].childNodes[0].nodeValue.encode('utf-8')
#layer_def += " 'wms_srs' 'EPSG:4326 EPSG:" + epsg + "'\n"
layer_def + = " ' wms_srs ' ' EPSG: " + self . getEpsg ( lyr ) + " ' \n "
# TODO: add epsg to all METADATA tags??
2008-01-10 04:49:11 +00:00
except :
pass
2008-04-25 19:19:02 +00:00
layer_def + = " ' wms_format ' ' " + format + " ' \n "
layer_def + = " ' wms_style ' ' " + ' , ' . join ( wmsStyles ) + " ' \n "
layer_def + = " END \n "
2008-01-10 04:49:11 +00:00
else :
# its a standard ogr, gdal or grass layer
2008-04-25 19:19:02 +00:00
layer_def + = " DATA ' " + dataString + " ' \n "
2008-01-10 04:49:11 +00:00
# WMS settings for all layers
2008-04-25 19:19:02 +00:00
layer_def + = " METADATA \n "
layer_def + = " ' wms_title ' ' " + lyr . getElementsByTagName ( " layername " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) . replace ( " \" " , " " ) + " ' \n "
layer_def + = " END \n "
2008-01-10 04:49:11 +00:00
2009-11-07 16:59:29 +00:00
layer_def + = " STATUS OFF \n "
# turn status in MapServer on or off based on visibility in QGis:
# layer_id = lyr.getElementsByTagName("id")[0].childNodes[0].nodeValue.encode("utf-8")
# legendLayerNode = self.legendlayerfileNodesById[layer_id]
# if legendLayerNode.getAttribute("visible").encode("utf-8") == "1":
# layer_def += " STATUS ON\n"
# else:
# layer_def += " STATUS OFF\n"
2008-01-10 04:49:11 +00:00
opacity = int ( 100.0 *
float ( lyr . getElementsByTagName ( " transparencyLevelInt " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) ) / 255.0 )
2008-04-25 19:19:02 +00:00
layer_def + = " TRANSPARENCY " + str ( opacity ) + " \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
layer_def + = " PROJECTION \n "
2009-11-07 20:11:29 +00:00
# Get the data srs for this layer and use it to create the projection section
datasrs = lyr . getElementsByTagName ( " srs " ) [ 0 ]
proj4Text = datasrs . getElementsByTagName ( " proj4 " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
2008-01-10 04:49:11 +00:00
# the proj4 text string needs to be reformatted to make mapserver happy
2008-04-25 19:19:02 +00:00
layer_def + = self . formatProj4 ( proj4Text )
layer_def + = " END \n "
2008-10-24 11:00:31 +00:00
scaleDependent = lyr . getAttribute ( " hasScaleBasedVisibilityFlag " ) . encode ( ' utf-8 ' )
2008-01-10 04:49:11 +00:00
if scaleDependent == ' 1 ' :
# get the min and max scale settings
2008-10-24 11:00:31 +00:00
minscale = lyr . getAttribute ( " minimumScale " ) . encode ( ' utf-8 ' )
maxscale = lyr . getAttribute ( " maximumScale " ) . encode ( ' utf-8 ' )
2008-01-10 04:49:11 +00:00
if minscale > ' ' :
2008-04-25 19:19:02 +00:00
layer_def + = " MINSCALE " + minscale + " \n "
2008-01-10 04:49:11 +00:00
if maxscale > ' ' :
2008-04-25 19:19:02 +00:00
layer_def + = " MAXSCALE " + maxscale + " \n "
2008-01-10 04:49:11 +00:00
# Check for label field (ie LABELITEM) and label status
try :
labelOn = lyr . getElementsByTagName ( " label " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
labelField = lyr . getElementsByTagName ( " labelfield " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
if labelField != ' ' and labelField is not None and labelOn == " 1 " :
2008-04-25 19:19:02 +00:00
layer_def + = " LABELITEM ' " + labelField + " ' \n "
2008-01-10 04:49:11 +00:00
except :
# no labels
pass
# write the CLASS section for rendering
# First see if there is a single symbol renderer
if lyr . getElementsByTagName ( " singlesymbol " ) . length > 0 :
2009-11-07 16:59:29 +00:00
layer_def + = self . simpleRenderer ( lyr , lyr . getElementsByTagName ( " singlesymbol " ) [ 0 ] . getElementsByTagName ( ' symbol ' ) [ 0 ] )
2008-01-10 04:49:11 +00:00
elif lyr . getElementsByTagName ( " graduatedsymbol " ) . length > 0 :
2008-04-25 19:19:02 +00:00
layer_def + = self . graduatedRenderer ( lyr , lyr . getElementsByTagName ( " graduatedsymbol " ) [ 0 ] . getElementsByTagName ( ' symbol ' ) [ 0 ] )
2008-01-10 04:49:11 +00:00
elif lyr . getElementsByTagName ( " continuoussymbol " ) . length > 0 :
2008-04-25 19:19:02 +00:00
layer_def + = self . continuousRenderer ( lyr , lyr . getElementsByTagName ( " continuoussymbol " ) [ 0 ] )
2008-01-10 04:49:11 +00:00
elif lyr . getElementsByTagName ( " uniquevalue " ) . length > 0 :
2008-04-25 19:19:02 +00:00
layer_def + = self . uniqueRenderer ( lyr , lyr . getElementsByTagName ( " uniquevalue " ) [ 0 ] . getElementsByTagName ( ' symbol ' ) [ 0 ] )
2008-01-10 04:49:11 +00:00
# end of LAYER
2008-04-25 19:19:02 +00:00
layer_def + = " END \n \n "
# add the layer to the list
layer_list [ layer_name ] = layer_def
# all layers have been processed, reverse the list and write
# not necessary since z-order is mapped by the legend list order
2009-11-07 20:11:29 +00:00
# self.z_order.reverse()
2008-04-25 19:19:02 +00:00
for layer in self . z_order :
self . outFile . write ( layer_list [ layer ] )
2009-11-07 20:11:29 +00:00
return resultMsg
2008-04-25 19:19:02 +00:00
2009-11-07 16:59:29 +00:00
def getEpsg ( self , lyr ) :
srs = lyr . getElementsByTagName ( ' srs ' ) [ 0 ] . getElementsByTagName ( ' spatialrefsys ' ) [ 0 ]
return srs . getElementsByTagName ( ' epsg ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
def getPrimaryKey ( self , layerId , tableName ) :
"""
Since we have no Python bindings for " src \ providers \ postgres \ qgspostgresprovider.cpp "
we approximate the primary key by finding an integer type field containing " fid " or " id "
This is obviously a lousy solution at best .
This script requires the project you export to be open in QGis .
"""
mlr = QgsMapLayerRegistry . instance ( )
layers = mlr . mapLayers ( )
layer = layers [ QString ( layerId ) ]
dataProvider = layer . dataProvider ( )
fields = dataProvider . fields ( )
intTypes = [ QVariant . Int , QVariant . LongLong , QVariant . UInt , QVariant . ULongLong ]
integerFields = [ ]
for id , field in fields . iteritems ( ) :
if field . type ( ) in intTypes :
integerFields . append ( id )
# fid end
fidIntegerFields = [ ]
for id in integerFields :
if fields [ id ] . name ( ) . endsWith ( " fid " ) :
fidIntegerFields . append ( id )
if len ( fidIntegerFields ) == 1 :
2009-11-07 20:11:29 +00:00
return str ( fields [ fidIntegerFields [ 0 ] ] . name ( ) )
2008-01-10 04:49:11 +00:00
2009-11-07 16:59:29 +00:00
# fid start
fidIntegerFields [ : ] = [ ]
for id in integerFields :
if fields [ id ] . name ( ) . startsWith ( " fid " ) :
fidIntegerFields . append ( id )
if len ( fidIntegerFields ) == 1 :
2009-11-07 20:11:29 +00:00
return str ( fields [ fidIntegerFields [ 0 ] ] . name ( ) )
2009-11-07 16:59:29 +00:00
# id end
idIntegerFields = [ ]
for id in integerFields :
if fields [ id ] . name ( ) . endsWith ( " id " ) :
idIntegerFields . append ( id )
if len ( idIntegerFields ) == 1 :
2009-11-07 20:11:29 +00:00
return str ( fields [ idIntegerFields [ 0 ] ] . name ( ) )
2009-11-07 16:59:29 +00:00
# id start
idIntegerFields [ : ] = [ ]
for id in integerFields :
if fields [ id ] . name ( ) . startsWith ( " id " ) :
idIntegerFields . append ( id )
if len ( idIntegerFields ) == 1 :
2009-11-07 20:11:29 +00:00
return str ( fields [ idIntegerFields [ 0 ] ] . name ( ) )
2009-11-07 16:59:29 +00:00
# if we arrive here we have ambiguous or no primary keys
#print "Error: Could not find primary key from field type and field name information.\n"
# using a mapfile pre-processor, the proper id field can be substituted in the following:
2009-11-07 20:11:29 +00:00
return str ( " % " + tableName + " _id % " )
2008-01-10 04:49:11 +00:00
# Simple renderer ouput
# We need the layer node and symbol node
def simpleRenderer ( self , layerNode , symbolNode ) :
# get the layers geometry type
geometry = layerNode . getAttribute ( " geometry " ) . encode ( ' utf-8 ' ) . upper ( )
2008-04-25 19:19:02 +00:00
class_def = " CLASS \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " NAME ' " + layerNode . getElementsByTagName ( " layername " ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) . replace ( " \" " , " " ) + " ' \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " STYLE \n "
2008-01-10 04:49:11 +00:00
# use the point symbol map to lookup the mapserver symbol type
symbol = self . msSymbol ( geometry , symbolNode )
2008-04-25 19:19:02 +00:00
class_def + = " SYMBOL " + symbol + " \n "
2009-11-07 16:59:29 +00:00
class_def + = self . getSymbolSizeString ( symbolNode )
2008-01-10 04:49:11 +00:00
# outline color
outlineNode = symbolNode . getElementsByTagName ( ' outlinecolor ' ) [ 0 ]
2009-01-19 19:53:23 +00:00
class_def + = " OUTLINECOLOR " + outlineNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' + outlineNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' + outlineNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
# color
colorNode = symbolNode . getElementsByTagName ( ' fillcolor ' ) [ 0 ]
2009-01-19 19:53:23 +00:00
class_def + = " COLOR " + colorNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' + colorNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' + colorNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = self . msLabel ( layerNode )
2008-01-10 04:49:11 +00:00
# end of CLASS
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
return class_def
2009-11-07 16:59:29 +00:00
def getSymbolSizeString ( self , symbolNode ) :
size = float ( symbolNode . getElementsByTagName ( ' pointsize ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) )
symbolSize = size * symbolSizeMultiplier
return " SIZE " + str ( symbolSize ) + " \n "
2008-01-10 04:49:11 +00:00
# Graduated symbol renderer output
def graduatedRenderer ( self , layerNode , symbolNode ) :
# get the layers geometry type
geometry = layerNode . getAttribute ( " geometry " ) . encode ( ' utf-8 ' ) . upper ( )
# get the renderer field for building up the classes
classField = layerNode . getElementsByTagName ( ' classificationattribute ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# write the render item
2008-04-25 19:19:02 +00:00
class_def = " CLASSITEM ' " + classField + " ' \n "
2008-01-10 04:49:11 +00:00
# write the rendering info for each class
classes = layerNode . getElementsByTagName ( ' symbol ' )
for cls in classes :
2008-04-25 19:19:02 +00:00
class_def + = " CLASS \n "
2008-01-10 04:49:11 +00:00
lower = cls . getElementsByTagName ( ' lowervalue ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
upper = cls . getElementsByTagName ( ' uppervalue ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# If there's a label use it, otherwise autogenerate one
try :
label = cls . getElementsByTagName ( ' label ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
2008-04-25 19:19:02 +00:00
class_def + = " NAME ' " + label + " ' \n "
2008-01-10 04:49:11 +00:00
except :
2008-04-25 19:19:02 +00:00
class_def + = " NAME ' " + lower + " < " + classField + " < " + upper + " ' \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " EXPRESSION ( ([ " + classField + " ] >= " + lower + " ) AND ([ " + classField + " ] <= " + upper + " ) ) \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " STYLE \n "
2008-01-10 04:49:11 +00:00
symbol = self . msSymbol ( geometry , symbolNode )
2008-04-25 19:19:02 +00:00
class_def + = " SYMBOL " + symbol + " \n "
2008-01-10 04:49:11 +00:00
# Symbol size
if geometry == ' POINT ' or geometry == ' LINE ' :
2009-11-07 16:59:29 +00:00
class_def + = self . getSymbolSizeString ( cls )
2008-01-10 04:49:11 +00:00
# outline color
outlineNode = cls . getElementsByTagName ( ' outlinecolor ' ) [ 0 ]
2009-01-19 19:53:23 +00:00
class_def + = " OUTLINECOLOR " + outlineNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' + outlineNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' + outlineNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
# color
colorNode = cls . getElementsByTagName ( ' fillcolor ' ) [ 0 ]
2009-01-19 19:53:23 +00:00
class_def + = " COLOR " + colorNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' + colorNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' + colorNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
2008-01-10 04:49:11 +00:00
# label
2008-04-25 19:19:02 +00:00
class_def + = self . msLabel ( layerNode )
2008-01-10 04:49:11 +00:00
# end of CLASS
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
return class_def
2008-01-10 04:49:11 +00:00
# Continuous symbol renderer output
def continuousRenderer ( self , layerNode , symbolNode ) :
# get the layers geometry type
geometry = layerNode . getAttribute ( " geometry " ) . encode ( ' utf-8 ' ) . upper ( )
# get the renderer field for building up the classes
classField = layerNode . getElementsByTagName ( ' classificationattribute ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# write the rendering info for each class
2009-01-19 19:53:23 +00:00
class_def = " CLASS \n "
2008-01-10 04:49:11 +00:00
# Class name irrelevant for color ramps since mapserver can't render their legend
#self.outFile.write(" NAME '" + classField + "'\n")
# color
lower = symbolNode . getElementsByTagName ( ' lowestsymbol ' ) [ 0 ] . getElementsByTagName ( ' symbol ' ) [ 0 ]
upper = symbolNode . getElementsByTagName ( ' highestsymbol ' ) [ 0 ] . getElementsByTagName ( ' symbol ' ) [ 0 ]
lowerColor = lower . getElementsByTagName ( ' fillcolor ' ) [ 0 ]
upperColor = upper . getElementsByTagName ( ' fillcolor ' ) [ 0 ]
# outline color
outlineNode = lower . getElementsByTagName ( ' outlinecolor ' ) [ 0 ]
2008-04-25 19:19:02 +00:00
class_def + = " STYLE \n "
2008-01-10 04:49:11 +00:00
# The first and last color of the ramp ( r g b r g b )
2009-01-19 19:53:23 +00:00
class_def + = " COLORRANGE " + lowerColor . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + " " + lowerColor . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + " " + lowerColor . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " " + upperColor . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + " " + upperColor . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + " " + upperColor . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-01-10 04:49:11 +00:00
# The range of values over which to ramp the colors
2008-04-25 19:19:02 +00:00
class_def + = " DATARANGE " + lower . getElementsByTagName ( ' lowervalue ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) + ' ' + upper . getElementsByTagName ( ' lowervalue ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) + ' \n '
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " RANGEITEM ' " + classField + " ' \n "
class_def + = " END \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " STYLE \n "
2009-01-19 19:53:23 +00:00
class_def + = " OUTLINECOLOR " + outlineNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + " " + outlineNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + " " + outlineNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) + " \n "
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
2008-01-10 04:49:11 +00:00
# label
2008-04-25 19:19:02 +00:00
class_def + = self . msLabel ( layerNode )
2008-01-10 04:49:11 +00:00
# end of CLASS
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
return class_def
2008-01-10 04:49:11 +00:00
# Unique value renderer output
def uniqueRenderer ( self , layerNode , symbolNode ) :
# get the renderer field for building up the classes
classField = layerNode . getElementsByTagName ( ' classificationattribute ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
# get the layers geometry type
geometry = layerNode . getAttribute ( " geometry " ) . encode ( ' utf-8 ' ) . upper ( )
# write the render item
2008-04-25 19:19:02 +00:00
class_def = " CLASSITEM ' " + classField + " ' \n "
2008-01-10 04:49:11 +00:00
# write the rendering info for each class
classes = layerNode . getElementsByTagName ( ' symbol ' )
for cls in classes :
2008-04-25 19:19:02 +00:00
class_def + = " CLASS \n "
2008-01-10 04:49:11 +00:00
try :
lower = cls . getElementsByTagName ( ' lowervalue ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
except IndexError :
# set to blank in the case where the field used for rendering has no value
lower = " "
# If there's a label use it, otherwise autogenerate one
try :
label = cls . getElementsByTagName ( ' label ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' )
2008-04-25 19:19:02 +00:00
class_def + = " NAME ' " + label + " ' \n "
2008-01-10 04:49:11 +00:00
except :
2008-04-25 19:19:02 +00:00
class_def + = " NAME ' " + classField + " = " + lower + " ' \n "
2008-01-10 04:49:11 +00:00
2008-04-25 19:19:02 +00:00
class_def + = " EXPRESSION ' " + lower + " ' \n "
2008-01-10 04:49:11 +00:00
# Get the symbol name
symbol = self . msSymbol ( geometry , symbolNode )
2008-04-25 19:19:02 +00:00
class_def + = " STYLE \n "
class_def + = " SYMBOL " + symbol + " \n "
2008-01-10 04:49:11 +00:00
# Symbol size
if geometry == ' POINT ' or geometry == ' LINE ' :
2009-11-07 16:59:29 +00:00
class_def + = self . getSymbolSizeString ( cls )
2008-01-10 04:49:11 +00:00
# outline color
outlineNode = cls . getElementsByTagName ( ' outlinecolor ' ) [ 0 ]
2008-04-25 19:19:02 +00:00
class_def + = " OUTLINECOLOR " \
2009-01-19 19:53:23 +00:00
+ outlineNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' \
+ outlineNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' \
+ outlineNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) \
2008-04-25 19:19:02 +00:00
+ " \n "
2008-01-10 04:49:11 +00:00
# color
colorNode = cls . getElementsByTagName ( ' fillcolor ' ) [ 0 ]
2008-04-25 19:19:02 +00:00
class_def + = " COLOR " \
2009-01-19 19:53:23 +00:00
+ colorNode . getAttribute ( ' red ' ) . encode ( ' utf-8 ' ) + ' ' \
+ colorNode . getAttribute ( ' green ' ) . encode ( ' utf-8 ' ) + ' ' \
+ colorNode . getAttribute ( ' blue ' ) . encode ( ' utf-8 ' ) \
2008-04-25 19:19:02 +00:00
+ " \n "
class_def + = " END \n "
2008-01-10 04:49:11 +00:00
# label
2008-04-25 19:19:02 +00:00
class_def + = self . msLabel ( layerNode )
2008-01-10 04:49:11 +00:00
# end of CLASS
2008-04-25 19:19:02 +00:00
class_def + = " END \n "
return class_def
2008-01-10 04:49:11 +00:00
# Utility method to format a proj4 text string into mapserver format
def formatProj4 ( self , proj4text ) :
parms = proj4text . split ( " " )
ret = " "
for p in parms :
p = p . replace ( " + " , " " )
ret = ret + " ' " + p + " ' \n "
return ret
2009-11-07 16:59:29 +00:00
def getProj4 ( self , proj4text ) :
""" Returns the proj4 string as a dictionary with key value pairs. """
parms = proj4text . split ( " " )
ret = { }
for p in parms :
p = p . replace ( " + " , " " )
keyValue = p . split ( " = " )
key = keyValue [ 0 ]
value = " "
try : value = keyValue [ 1 ]
except : value = " "
if key != " " :
ret [ key ] = value
return ret
2008-01-10 04:49:11 +00:00
# Determines the symbol name and adds it to the symbol queue
def msSymbol ( self , geometry , symbolNode ) :
# contains the same markup for a layer regardless of type
# so we infer a symbol type based on the geometry
symbolName = ' '
symbol = ' 0 '
if geometry == ' POLYGON ' :
symbol = ' 0 '
elif geometry == ' LINE ' :
symbol = ' 0 '
elif geometry == ' POINT ' :
try :
2009-11-07 16:59:29 +00:00
symbolName = qgis2map_symbol [ symbolNode . getElementsByTagName ( ' pointsymbol ' ) [ 0 ] . childNodes [ 0 ] . nodeValue . encode ( ' utf-8 ' ) ]
2008-01-10 04:49:11 +00:00
except :
2009-11-07 16:59:29 +00:00
symbolName = " circle "
# make sure it's double quoted
symbol = " \" " + symbolName + " \" "
# a symbol set in an external symbol.txt file is used; see comment on top of this file
# if symbolName == 'CIRCLE':
# self.symbolQueue['CIRCLE'] = """
# #Circle symbol
# SYMBOL
# NAME 'CIRCLE'
# TYPE ellipse
# FILLED true
# POINTS
# 1 1
# END
# END """
#
# if symbolName == 'TRIANGLE':
# self.symbolQueue['TRIANGLE'] = """
# SYMBOL
# NAME "TRIANGLE"
# TYPE vector
# FILLED true
# POINTS
# 0 1
# .5 0
# 1 1
# 0 1
# END
# END """
2008-01-10 04:49:11 +00:00
return symbol
# Label block creation
def msLabel ( self , layerNode ) :
# currently a very basic bitmap font
labelNode = layerNode . getElementsByTagName ( ' labelattributes ' ) [ 0 ]
2009-11-07 16:59:29 +00:00
#labelField = labelNode.getElementsByTagName('label')[0].getAttribute('field').encode('utf-8')
# why was the attribute 'field' and not 'fieldname'?
labelField = labelNode . getElementsByTagName ( ' label ' ) [ 0 ] . getAttribute ( ' fieldname ' ) . encode ( ' utf-8 ' )
2008-01-10 04:49:11 +00:00
if labelField != ' ' and labelField is not None :
labelBlock = " LABEL \n "
2009-11-07 16:59:29 +00:00
# see comment at 'qgis2ms_fontset'
fontQgis = labelNode . getElementsByTagName ( ' family ' ) [ 0 ] . getAttribute ( ' name ' ) . encode ( ' utf-8 ' )
fontMs = " "
try :
fontMs = qgis2map_fontset [ fontQgis ]
except :
# we default to the first font in the fontset, if any are present
if len ( qgis2map_fontset ) > 0 :
try :
fontMs = qgis2map_fontset [ " MS Shell Dialog 2 " ]
except :
sortedKeys = qgis2map_fontset . keys ( )
sortedKeys . sort ( )
fontMs = qgis2map_fontset [ sortedKeys [ 0 ] ]
else :
fontMs = " "
bold = bool ( int ( labelNode . getElementsByTagName ( ' bold ' ) [ 0 ] . getAttribute ( ' on ' ) . encode ( " utf-8 " ) ) )
italic = bool ( int ( labelNode . getElementsByTagName ( ' italic ' ) [ 0 ] . getAttribute ( ' on ' ) . encode ( " utf-8 " ) ) )
# "-bold" and "-italic" must correspond with the fontset file
# font can be both bold and italic
labelBlock + = " FONT " + fontMs
if bold : labelBlock + = " -bold "
if italic : labelBlock + = " -italic "
labelBlock + = " \n "
labelBlock + = " TYPE truetype \n "
size = self . getFieldName ( labelNode , ' size ' )
if size == " " :
sizeNode = labelNode . getElementsByTagName ( ' size ' ) [ 0 ]
units = sizeNode . getAttribute ( " units " ) . encode ( " utf-8 " )
sizeValue = int ( sizeNode . getAttribute ( " value " ) . encode ( " utf-8 " ) )
# we must convert to px for use in the mapfile
sizePx = 11 # default
sizePx = sizeValue
#if units == "pt": sizePx = int(sizeValue / 0.75)
# TODO: find appropriate conversion metric from map units to pixels
#elif unit == "mu":
#proj4Elem = labelNode.parentNode.getElementsByTagName("proj4")[0].childNodes[0]
#proj4str = proj4Elem.nodeValue.encode('utf-8')
#proj4Dict = self.getProj4(proj4str)
#for i,j in proj4Dict.iteritems():
#labelBlock += str(i) + ":: " + str(j) + "\n"
#
#sizePx = ????? proj4Dict["units"] ??
# non-used unit types:
#elif unit == "em": sizePx = int(size * 16.0)
#elif unit == "px": sizePx = size
size = str ( sizePx )
labelBlock + = " SIZE " + size + " \n "
color = self . getFieldName ( labelNode , ' color ' )
if color == " " :
colorNode = labelNode . getElementsByTagName ( ' color ' ) [ 0 ]
r = int ( colorNode . getAttribute ( " red " ) )
g = int ( colorNode . getAttribute ( " green " ) )
b = int ( colorNode . getAttribute ( " blue " ) )
color = str ( r ) + " " + str ( g ) + " " + str ( b )
labelBlock + = " COLOR " + color + " \n "
2008-01-10 04:49:11 +00:00
# Include label angle if specified
2009-11-07 16:59:29 +00:00
# Note that angles only work for truetype fonts
angle = self . getFieldName ( labelNode , ' angle ' )
if angle == " " :
angle = labelNode . getElementsByTagName ( ' angle ' ) [ 0 ] . getAttribute ( ' value ' ) . encode ( ' utf-8 ' )
2008-01-10 04:49:11 +00:00
labelBlock + = " ANGLE " + angle + " \n "
# Include label buffer if specified
# Note that the buffer has different meaning in qgis vs mapserver
# mapserver just adds blank space around the label while
# qgis uses a fill color around the label
2009-11-07 16:59:29 +00:00
# Note that buffer only works for truetype fonts
2008-01-10 04:49:11 +00:00
buffer = labelNode . getElementsByTagName ( ' buffersize ' ) [ 0 ] . getAttribute ( ' value ' ) . encode ( ' utf-8 ' )
labelBlock + = " BUFFER " + buffer + " \n "
2009-11-07 16:59:29 +00:00
# alignment in QGis corresponds to position in MapServer
alignment = labelNode . getElementsByTagName ( ' alignment ' ) [ 0 ] . getAttribute ( ' value ' ) . encode ( ' utf-8 ' )
try :
labelBlock + = " POSITION " + qgis2map_aligment2position [ alignment ] + " \n "
except :
# default to center if we encounter a nonsensical value
labelBlock + = " POSITION cc \n "
#values from the gui:
labelBlock + = " FORCE " + self . force + " \n "
labelBlock + = " ANTIALIAS " + self . antialias + " \n "
labelBlock + = " PARTIALS " + self . partials + " \n "
2008-01-10 04:49:11 +00:00
labelBlock + = " END \n "
return labelBlock
else :
return ' '
2009-11-07 16:59:29 +00:00
def getFieldName ( self , parentNode , nodeName ) :
""" Returns the fieldname-attribute-value of a nodeName with a given parentNode
as a string surrounded by brackets ( ' [ ' and ' ] ' ) or
an empty string if the fieldname - attribute does not exist . """
try :
fieldname = parentNode . getElementsByTagName ( nodeName ) [ 0 ] . getAttribute ( ' fieldname ' ) . encode ( ' utf-8 ' )
if fieldname != " " :
return " [ " + fieldname + " ] "
else :
return " "
except :
return " "