Fix for mapserver patch issues and updates for mapserver from Richard Duivenvoorde and Stephan Meissl

git-svn-id: http://svn.osgeo.org/qgis/trunk@11980 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
timlinux 2009-11-07 20:11:29 +00:00
parent f591389ef1
commit 4573fd4c3c
4 changed files with 76 additions and 63 deletions

View File

@ -24,7 +24,7 @@ def name():
def description(): def description():
return "Export a saved QGIS project file to a MapServer map file" return "Export a saved QGIS project file to a MapServer map file"
def version(): def version():
return "Version 0.1" return "Version 0.4"
def qgisMinimumVersion(): def qgisMinimumVersion():
return "1.0" return "1.0"
def authorName(): def authorName():

View File

@ -24,7 +24,7 @@ from PyQt4.QtGui import *
from xml.dom import minidom from xml.dom import minidom
from qgis.core import * from qgis.core import *
# Initialize Qt resources from file resources.py # Initialize Qt resources from file resources.py
import resources import resources_rc
# Import the code for the dialog # Import the code for the dialog
from mapserverexportdialog import MapServerExportDialog from mapserverexportdialog import MapServerExportDialog
# Import the ms_export script that does the real work # Import the ms_export script that does the real work
@ -133,6 +133,7 @@ class MapServerExport:
print "Creating exporter using %s and %s" % (self.dlg.ui.txtQgisFilePath.text(), self.dlg.ui.txtMapFilePath.text()) print "Creating exporter using %s and %s" % (self.dlg.ui.txtQgisFilePath.text(), self.dlg.ui.txtMapFilePath.text())
exporter = Qgis2Map(unicode(self.dlg.ui.txtQgisFilePath.text()), unicode(self.dlg.ui.txtMapFilePath.text())) exporter = Qgis2Map(unicode(self.dlg.ui.txtQgisFilePath.text()), unicode(self.dlg.ui.txtMapFilePath.text()))
print "Setting options" print "Setting options"
exporter.setOptions( exporter.setOptions(
unicode(self.dlg.ui.txtMapServerUrl.text()), unicode(self.dlg.ui.txtMapServerUrl.text()),
unicode(self.dlg.ui.cmbMapUnits.itemData( self.dlg.ui.cmbMapUnits.currentIndex() ).toString()), unicode(self.dlg.ui.cmbMapUnits.itemData( self.dlg.ui.cmbMapUnits.currentIndex() ).toString()),
@ -147,6 +148,7 @@ class MapServerExport:
self.dlg.ui.checkBoxForce.isChecked(), self.dlg.ui.checkBoxForce.isChecked(),
self.dlg.ui.checkBoxAntiAlias.isChecked(), self.dlg.ui.checkBoxAntiAlias.isChecked(),
self.dlg.ui.checkBoxPartials.isChecked(), self.dlg.ui.checkBoxPartials.isChecked(),
self.dlg.ui.chkExpLayersOnly.isChecked(),
unicode(self.dlg.ui.txtFontsetPath.text()), unicode(self.dlg.ui.txtFontsetPath.text()),
unicode(self.dlg.ui.txtSymbolsetPath.text()) unicode(self.dlg.ui.txtSymbolsetPath.text())
) )
@ -199,6 +201,9 @@ class MapServerExport:
self.dlg.ui.txtMapHeight.setEnabled(not isChecked) self.dlg.ui.txtMapHeight.setEnabled(not isChecked)
self.dlg.ui.cmbMapUnits.setEnabled(not isChecked) self.dlg.ui.cmbMapUnits.setEnabled(not isChecked)
self.dlg.ui.cmbMapImageType.setEnabled(not isChecked) self.dlg.ui.cmbMapImageType.setEnabled(not isChecked)
self.dlg.ui.txtMapServerUrl.setEnabled(not isChecked)
self.dlg.ui.txtFontsetPath.setEnabled(not isChecked)
self.dlg.ui.txtSymbolsetPath.setEnabled(not isChecked)
self.dlg.ui.txtWebTemplate.setEnabled(not isChecked) self.dlg.ui.txtWebTemplate.setEnabled(not isChecked)
self.dlg.ui.txtWebHeader.setEnabled(not isChecked) self.dlg.ui.txtWebHeader.setEnabled(not isChecked)
self.dlg.ui.txtWebFooter.setEnabled(not isChecked) self.dlg.ui.txtWebFooter.setEnabled(not isChecked)

View File

@ -19,7 +19,7 @@
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from ms_export import defaults from ms_export import defaults
from ui_mapserverexport import Ui_QgsMapserverExportBase from ui_qgsmapserverexportbase import Ui_QgsMapserverExportBase
# create the dialog for mapserver export # create the dialog for mapserver export
class MapServerExportDialog(QtGui.QDialog): class MapServerExportDialog(QtGui.QDialog):
def __init__(self): def __init__(self):

View File

@ -128,7 +128,7 @@ class Qgis2Map:
# Set the options collected from the GUI # Set the options collected from the GUI
def setOptions(self, msUrl, units, image, mapname, width, height, template, header, footer, dump, force, antialias, partials, fontsPath, symbolsPath): def setOptions(self, msUrl, units, image, mapname, width, height, template, header, footer, dump, force, antialias, partials, exportLayersOnly, fontsPath, symbolsPath):
if msUrl.encode('utf-8') != "": if msUrl.encode('utf-8') != "":
self.mapServerUrl = msUrl.encode('utf-8') self.mapServerUrl = msUrl.encode('utf-8')
@ -155,10 +155,11 @@ class Qgis2Map:
self.footer = footer.encode('utf-8') self.footer = footer.encode('utf-8')
#print units, image, mapname, width, height, template, header, footer #print units, image, mapname, width, height, template, header, footer
self.dump = bool2str[dump] self.dump = bool2str[dump]
self.force = bool2str[force] self.force = bool2str[force]
self.antialias = bool2str[antialias] self.antialias = bool2str[antialias]
self.partials = bool2str[partials] self.partials = bool2str[partials]
self.exportLayersOnly = exportLayersOnly
## All real work happens here by calling methods to write the ## All real work happens here by calling methods to write the
@ -167,50 +168,55 @@ class Qgis2Map:
# open the output file # open the output file
print "creating the map file" print "creating the map file"
self.outFile = open(self.mapFile, 'w') self.outFile = open(self.mapFile, 'w')
# write the general map and web settings logmsg = "Starting\n"
print " --- python : map section "
self.writeMapSection() if self.exportLayersOnly == False:
logmsg = "Wrote map section\n" # write the general map and web settings
print " --- python : map section done" print " --- python : map section "
# write the projection section self.writeMapSection()
print " --- python : proj section " logmsg += "Wrote map section\n"
self.writeProjectionSection() print " --- python : map section done"
logmsg += "Wrote projection section\n" # write the projection section
print " --- python : proj section done" print " --- python : proj section "
# write the output format section self.writeProjectionSection()
print " --- python : outputformat section " logmsg += "Wrote projection section\n"
self.writeOutputFormat() print " --- python : proj section done"
logmsg += "Wrote output format section\n" # write the output format section
print " --- python : outputformat section done" print " --- python : outputformat section "
# write the legend section self.writeOutputFormat()
print " --- python : legend section" logmsg += "Wrote output format section\n"
self.writeLegendSection() print " --- python : outputformat section done"
logmsg += "Wrote legend section\n" # write the legend section
print " --- python : legend section done" print " --- python : legend section"
self.writeLegendSection()
logmsg += "Wrote legend section\n"
print " --- python : legend section done"
# write the WEB section # write the WEB section
print " --- python : web section " print " --- python : web section "
self.writeWebSection() self.writeWebSection()
logmsg += "Wrote web section\n" logmsg += "Wrote web section\n"
print " --- python : web section done" print " --- python : web section done"
# write the LAYER sections # write the LAYER sections
print " --- python : layer section " print " --- python : layer section "
self.writeMapLayers() layersMsg = self.writeMapLayers()
logmsg += "Wrote map layers\n" logmsg += "Wrote map layers\n"
logmsg += layersMsg
print " --- python : layer section done" print " --- python : layer section done"
# we use an external synbol set instead if self.exportLayersOnly == False:
# write the symbol defs section # we use an external synbol set instead
# must happen after layers so we can build a symbol queue # write the symbol defs section
#print " --- python : symbol section " # must happen after layers so we can build a symbol queue
#self.writeSymbolSection() #print " --- python : symbol section "
#logmsg += "Wrote symbol section\n" #self.writeSymbolSection()
#print " --- python : symbol section done" #logmsg += "Wrote symbol section\n"
#print " --- python : symbol section done"
# END and close the map file # END and close the map file
self.outFile.write("END") self.outFile.write("END")
self.outFile.close() self.outFile.close()
logmsg += "Map file completed for " + self.project + "\n" logmsg += "Map file completed for " + self.project + "\n"
logmsg += "Map file saved as " + self.mapFile + "\n" logmsg += "Map file saved as " + self.mapFile + "\n"
@ -222,7 +228,7 @@ class Qgis2Map:
self.outFile.write("# Edit this file to customize for your map interface\n") 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("# (Created with PyQgis MapServer Export plugin)\n")
self.outFile.write("MAP\n") self.outFile.write("MAP\n")
self.outFile.write(" NAME " + self.mapName + "\n") self.outFile.write(" NAME \"" + self.mapName + "\"\n")
self.outFile.write(" # Map image size\n") self.outFile.write(" # Map image size\n")
if self.width == '' or self.height == '': if self.width == '' or self.height == '':
self.outFile.write(" SIZE 0 0\n") self.outFile.write(" SIZE 0 0\n")
@ -263,7 +269,7 @@ class Qgis2Map:
# Write the OUTPUTFORMAT section # Write the OUTPUTFORMAT section
def writeOutputFormat(self): def writeOutputFormat(self):
self.outFile.write(" # Background color for the map canvas -- change as desired\n") self.outFile.write(" # Background color for the map canvas -- change as desired\n")
self.outFile.write(" IMAGECOLOR 192 192 192\n") self.outFile.write(" IMAGECOLOR 255 255 255\n")
self.outFile.write(" IMAGEQUALITY 95\n") self.outFile.write(" IMAGEQUALITY 95\n")
self.outFile.write(" IMAGETYPE " + self.imageType + "\n") self.outFile.write(" IMAGETYPE " + self.imageType + "\n")
self.outFile.write("\n") self.outFile.write("\n")
@ -368,6 +374,7 @@ class Qgis2Map:
def writeMapLayers(self): def writeMapLayers(self):
# get the list of legend nodes so the layers can be written in the # get the list of legend nodes so the layers can be written in the
# proper order # proper order
resultMsg = ''
legend_nodes = self.qgs.getElementsByTagName("legendlayer") legend_nodes = self.qgs.getElementsByTagName("legendlayer")
self.z_order = list() self.z_order = list()
for legend_node in legend_nodes: for legend_node in legend_nodes:
@ -384,11 +391,11 @@ class Qgis2Map:
# The attributes of the maplayer tag contain the scale dependent settings, # The attributes of the maplayer tag contain the scale dependent settings,
# visibility, and layer type # visibility, and layer type
layer_def = " LAYER\n" layer_def = " LAYER\n"
# store name of the layer # 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("\"", "") layer_name = lyr.getElementsByTagName("layername")[0].childNodes[0].nodeValue.encode('utf-8').replace("\"", "").replace(" ","_")
# first check to see if there is a name # first check to see if there is a name
if len(lyr.getElementsByTagName("layername")[0].childNodes) > 0: if len(layer_name) > 0:
layer_def += " NAME '" + lyr.getElementsByTagName("layername")[0].childNodes[0].nodeValue.encode('utf-8').replace("\"", "") + "'\n" layer_def += " NAME '%s'\n" % layer_name
else: else:
# if no name for the layer, manufacture one # if no name for the layer, manufacture one
layer_def += " NAME 'LAYER%s'\n" % count layer_def += " NAME 'LAYER%s'\n" % count
@ -435,6 +442,10 @@ class Qgis2Map:
layer_id = lyr.getElementsByTagName("id")[0].childNodes[0].nodeValue.encode("utf-8") layer_id = lyr.getElementsByTagName("id")[0].childNodes[0].nodeValue.encode("utf-8")
uniqueId = self.getPrimaryKey(layer_id, uri.table()) uniqueId = self.getPrimaryKey(layer_id, uri.table())
# %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"
epsg = self.getEpsg(lyr) epsg = self.getEpsg(lyr)
layer_def += " DATA '" + uri.geometryColumn() + " FROM " + uri.quotedTablename() + " USING UNIQUE " + uniqueId + " USING srid=" + epsg + "'\n" layer_def += " DATA '" + uri.geometryColumn() + " FROM " + uri.quotedTablename() + " USING UNIQUE " + uniqueId + " USING srid=" + epsg + "'\n"
@ -485,7 +496,6 @@ class Qgis2Map:
layer_def += " END\n" layer_def += " END\n"
layer_def += " STATUS OFF\n" layer_def += " STATUS OFF\n"
#layer_def += " STATUS DEFAULT\n"
# turn status in MapServer on or off based on visibility in QGis: # turn status in MapServer on or off based on visibility in QGis:
# layer_id = lyr.getElementsByTagName("id")[0].childNodes[0].nodeValue.encode("utf-8") # layer_id = lyr.getElementsByTagName("id")[0].childNodes[0].nodeValue.encode("utf-8")
@ -496,17 +506,14 @@ class Qgis2Map:
# else: # else:
# layer_def += " STATUS OFF\n" # layer_def += " STATUS OFF\n"
opacity = int ( 100.0 * opacity = int ( 100.0 *
float(lyr.getElementsByTagName("transparencyLevelInt")[0].childNodes[0].nodeValue.encode('utf-8')) / 255.0 ) float(lyr.getElementsByTagName("transparencyLevelInt")[0].childNodes[0].nodeValue.encode('utf-8')) / 255.0 )
layer_def += " TRANSPARENCY " + str(opacity) + "\n" layer_def += " TRANSPARENCY " + str(opacity) + "\n"
layer_def += " PROJECTION\n" layer_def += " PROJECTION\n"
# Get the destination srs for this layer and use it to create # Get the data srs for this layer and use it to create the projection section
# the projection section datasrs = lyr.getElementsByTagName("srs")[0]
destsrs = self.qgs.getElementsByTagName("destinationsrs")[0] proj4Text = datasrs.getElementsByTagName("proj4")[0].childNodes[0].nodeValue.encode('utf-8')
proj4Text = destsrs.getElementsByTagName("proj4")[0].childNodes[0].nodeValue.encode('utf-8')
# the proj4 text string needs to be reformatted to make mapserver happy # the proj4 text string needs to be reformatted to make mapserver happy
layer_def += self.formatProj4(proj4Text) layer_def += self.formatProj4(proj4Text)
layer_def += " END\n" layer_def += " END\n"
@ -549,9 +556,10 @@ class Qgis2Map:
layer_list[layer_name] = layer_def layer_list[layer_name] = layer_def
# all layers have been processed, reverse the list and write # all layers have been processed, reverse the list and write
# not necessary since z-order is mapped by the legend list order # not necessary since z-order is mapped by the legend list order
self.z_order.reverse() # self.z_order.reverse()
for layer in self.z_order: for layer in self.z_order:
self.outFile.write(layer_list[layer]) self.outFile.write(layer_list[layer])
return resultMsg
def getEpsg(self, lyr): def getEpsg(self, lyr):
@ -588,7 +596,7 @@ class Qgis2Map:
fidIntegerFields.append(id) fidIntegerFields.append(id)
if len(fidIntegerFields) == 1: if len(fidIntegerFields) == 1:
return fields[fidIntegerFields[0]].name().__str__() return str(fields[fidIntegerFields[0]].name())
# fid start # fid start
fidIntegerFields[:] = [] fidIntegerFields[:] = []
@ -597,7 +605,7 @@ class Qgis2Map:
fidIntegerFields.append(id) fidIntegerFields.append(id)
if len(fidIntegerFields) == 1: if len(fidIntegerFields) == 1:
return fields[fidIntegerFields[0]].name().__str__() return str(fields[fidIntegerFields[0]].name())
# id end # id end
idIntegerFields = [] idIntegerFields = []
@ -606,7 +614,7 @@ class Qgis2Map:
idIntegerFields.append(id) idIntegerFields.append(id)
if len(idIntegerFields) == 1: if len(idIntegerFields) == 1:
return fields[idIntegerFields[0]].name().__str__() return str(fields[idIntegerFields[0]].name())
# id start # id start
idIntegerFields[:] = [] idIntegerFields[:] = []
@ -615,13 +623,13 @@ class Qgis2Map:
idIntegerFields.append(id) idIntegerFields.append(id)
if len(idIntegerFields) == 1: if len(idIntegerFields) == 1:
return fields[idIntegerFields[0]].name().__str__() return str(fields[idIntegerFields[0]].name())
# if we arrive here we have ambiguous or no primary keys # 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" #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: # using a mapfile pre-processor, the proper id field can be substituted in the following:
return "%" + tableName + "_id%" return str("%" + tableName + "_id%")
# Simple renderer ouput # Simple renderer ouput
# We need the layer node and symbol node # We need the layer node and symbol node