def testLabelBinding(self): """attribute binding can be set and get""" new_label = mapscript.labelObj() assert (not new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR)) new_label.setBinding(mapscript.MS_LABEL_BINDING_COLOR, "NEW_BINDING") assert (new_label.getBinding( mapscript.MS_LABEL_BINDING_COLOR) == "NEW_BINDING")
def testSettingFonts(self): mo = mapscript.mapObj() assert mo.fontset.numfonts == 0 mo.fontset.fonts.set('Vera', os.path.join(TESTS_PATH, 'vera', 'Vera.ttf')) # NB: this does *not* increment the fonset.numfonts -- new bug mo.setSize(300, 300) mo.setExtent(-1.0, -1.0, 1.0, 1.0) lo = mapscript.layerObj() lo.type = mapscript.MS_LAYER_POINT lo.connectiontype = mapscript.MS_INLINE lo.status = mapscript.MS_DEFAULT co = mapscript.classObj() lbl = mapscript.labelObj() lbl.type = mapscript.MS_TRUETYPE lbl.font = 'Vera' lbl.size = 10 lbl.color.setHex('#000000') co.addLabel(lbl) so = mapscript.styleObj() so.symbol = 0 so.color.setHex('#000000') co.insertStyle(so) lo.insertClass(co) li = mo.insertLayer(lo) lo = mo.getLayer(li) point = mapscript.pointObj(0, 0) line = mapscript.lineObj() line.add(point) shape = mapscript.shapeObj(lo.type) shape.add(line) shape.setBounds() shape.text = 'Foo' shape.classindex = 0 lo.addFeature(shape) im = mo.draw() # im = mo.prepareImage() # shape.draw(mo, lo, im) im.save('testSettingFonts.png')
def setUp(self): # Inline feature layer self.ilayer = mapscript.layerObj() self.ilayer.type = mapscript.MS_LAYER_POLYGON self.ilayer.status = mapscript.MS_DEFAULT self.ilayer.connectiontype = mapscript.MS_INLINE cs = 'f7fcfd, e5f5f9, ccece6, 99d8c9, 66c2a4, 41ae76, 238b45, 006d2c, 00441b' colors = ['#' + h for h in cs.split(', ')] for i in range(9): # Make a class for feature ci = self.ilayer.insertClass(mapscript.classObj()) co = self.ilayer.getClass(ci) si = co.insertStyle(mapscript.styleObj()) so = co.getStyle(si) so.color.setHex(colors[i]) li = co.addLabel(mapscript.labelObj()) lbl = co.getLabel(li) lbl.color.setHex('#000000') lbl.outlinecolor.setHex('#FFFFFF') lbl.type = mapscript.MS_BITMAP lbl.size = mapscript.MS_SMALL # The shape to add is randomly generated xc = 4.0*(random() - 0.5) yc = 4.0*(random() - 0.5) r = mapscript.rectObj(xc-0.25, yc-0.25, xc+0.25, yc+0.25) s = r.toPolygon() # Classify s.classindex = i s.text = "F%d" % (i) # Add to inline feature layer self.ilayer.addFeature(s)
def testLabelBinding(self): """attribute binding can be set and get""" new_label = mapscript.labelObj() assert (not new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR)) new_label.setBinding(mapscript.MS_LABEL_BINDING_COLOR, "NEW_BINDING") assert (new_label.getBinding(mapscript.MS_LABEL_BINDING_COLOR) == "NEW_BINDING")
def __init__(self, layer, msLayer, msMap, emitFontDefinitions=False): """Serialize labels of a QGis vector layer to mapscript""" self.layer = layer self.msLayer = msLayer self.msMap = msMap labelingEngine = QgsPalLabeling() labelingEngine.loadEngineSettings() if labelingEngine and labelingEngine.willUseLayer(self.layer): ps = QgsPalLayerSettings.fromLayer(self.layer) if not ps.isExpression: self.msLayer.labelitem = unicode(ps.fieldName).encode('utf-8') else: pass msLabel = mapscript.labelObj() msLabel.type = mapscript.MS_TRUETYPE msLabel.encoding = 'utf-8' # Position, rotation and scaling msLabel.position = utils.serializeLabelPosition(ps) msLabel.offsetx = int(ps.xOffset) msLabel.offsety = int(ps.yOffset) # Data defined rotation # Please note that this is the only currently supported data defined property. if QgsPalLayerSettings.Rotation in ps.dataDefinedProperties.keys(): dd = ps.dataDefinedProperty(QgsPalLayerSettings.Rotation) rotField = unicode(dd.field()).encode('utf-8') msLabel.setBinding(mapscript.MS_LABEL_BINDING_ANGLE, rotField) else: msLabel.angle = ps.angleOffset if ps.scaleMin > 0: self.msLayer.labelminscaledenom = ps.scaleMin if ps.scaleMax > 0: self.msLayer.labelmaxscaledenom = ps.scaleMax fontDef, msLabel.size = utils.serializeFontDefinition(ps.textFont, ps.textNamedStyle) # `emitFontDefinitions` gets set based on whether a fontset path is supplied through # the plugin UI. There is no point in emitting font definitions without a valid fontset, # so in that case we fall back to using whatever default font MapServer (thus the # underlying windowing system) provides. # Please note that substituting the default font only works in MapServer 7.0.0 and above. if emitFontDefinitions == True: msLabel.font = fontDef if ps.fontSizeInMapUnits: utils.maybeSetLayerSizeUnitFromMap(QgsSymbolV2.MapUnit, self.msLayer) # Font size and color msLabel.color = utils.serializeColor(ps.textColor) if ps.fontLimitPixelSize: msLabel.minsize = ps.fontMinPixelSize msLabel.maxsize = ps.fontMaxPixelSize # Other properties wrap = unicode(ps.wrapChar).encode('utf-8') if len(wrap) == 1: msLabel.wrap = wrap[0] elif len(wrap) > 1: QgsMessageLog.logMessage( u'Skipping invalid wrap character ("%s") for labels.' % wrap.decode('utf-8'), 'RT MapServer Exporter' ) else: # No wrap char set pass # Other properties msLabel.partials = labelingEngine.isShowingPartialsLabels() msLabel.force = ps.displayAll msLabel.priority = ps.priority msLabel.buffer = int(utils.sizeUnitToPx( ps.bufferSize, QgsSymbolV2.MapUnit if ps.bufferSizeInMapUnits else QgsSymbolV2.MM )) if ps.minFeatureSize > 0: msLabel.minfeaturesize = utils.sizeUnitToPx(ps.minFeatureSize) # Label definitions gets appended to the very first class on a layer, or to a new class # if no classes exist. # if msLayer.numclasses > 0: for c in range(0, msLayer.numclasses): msLayer.getClass(c).addLabel(msLabel) else: mapscript.classObj(msLayer).addLabel(msLabel)
def accept(self): # check user inputs if self.txtMapFilePath.text() == "": QMessageBox.warning(self, "RT MapServer Exporter", "Mapfile output path is required") return # create a new ms_map ms_map = mapscript.mapObj() ms_map.name = _toUtf8( self.txtMapName.text() ) # map size (width, widthOk), (height, heightOk) = self.txtMapWidth.text().toInt(), self.txtMapHeight.text().toInt() if widthOk and heightOk: ms_map.setSize( width, height ) # map units ms_map.units = self.unitMap[ self.canvas.mapUnits() ] if self.cmbMapUnits.currentIndex() >= 0: units, ok = self.cmbMapUnits.itemData( self.cmbMapUnits.currentIndex() ).toInt() if ok: ms_map.units = units # map extent extent = self.canvas.fullExtent() ms_map.extent.minx = extent.xMinimum() ms_map.extent.miny = extent.yMinimum() ms_map.extent.maxx = extent.xMaximum() ms_map.extent.maxy = extent.yMaximum() ms_map.setProjection( _toUtf8( self.canvas.mapRenderer().destinationCrs().toProj4() ) ) if self.txtMapShapePath.text() != "": ms_map.shapepath = _toUtf8( self.getMapShapePath() ) # image section r,g,b,a = self.canvas.canvasColor().getRgb() ms_map.imagecolor.setRGB( r, g, b ) #255,255,255 ms_map.setImageType( _toUtf8( self.cmbMapImageType.currentText() ) ) ms_outformat = ms_map.getOutputFormatByName( ms_map.imagetype ) ms_outformat.transparent = self.onOffMap[ True ] # legend section #r,g,b,a = self.canvas.canvasColor().getRgb() #ms_map.legend.imageColor.setRgb( r, g, b ) #ms_map.legend.status = mapscript.MS_ON #ms_map.legend.keysizex = 18 #ms_map.legend.keysizey = 12 #ms_map.legend.label.type = mapscript.MS_BITMAP #ms_map.legend.label.size = MEDIUM?? #ms_map.legend.label.color.setRgb( 0, 0, 89 ) #ms_map.legend.label.partials = self.trueFalseMap[ self.checkBoxPartials ] #ms_map.legend.label.force = self.trueFalseMap[ self.checkBoxForce ] #ms_map.legend.template = "[templatepath]" # web section ms_map.web.imagepath = _toUtf8( self.getWebImagePath() ) ms_map.web.imageurl = _toUtf8( self.getWebImageUrl() ) ms_map.web.temppath = _toUtf8( self.getWebTemporaryPath() ) # web template ms_map.web.template = _toUtf8( self.getTemplatePath() ) ms_map.web.header = _toUtf8( self.getTemplateHeaderPath() ) ms_map.web.footer = _toUtf8( self.getTemplateFooterPath() ) # map metadata ms_map.setMetaData( "ows_title", ms_map.name ) ms_map.setMetaData( "ows_onlineresource", _toUtf8( u"%s?map=%s" % (self.txtMapServerUrl.text(), self.txtMapFilePath.text()) ) ) srsList = [] srsList.append( _toUtf8( self.canvas.mapRenderer().destinationCrs().authid() ) ) ms_map.setMetaData( "ows_srs", ' '.join(srsList) ) ms_map.setMetaData( "ows_enable_request", "*" ) for layer in self.legend.layers(): # create a layer object ms_layer = mapscript.layerObj( ms_map ) ms_layer.name = _toUtf8( layer.name() ) ms_layer.type = self.getLayerType( layer ) ms_layer.status = self.onOffMap[ self.legend.isLayerVisible( layer ) ] # layer extent extent = layer.extent() ms_layer.extent.minx = extent.xMinimum() ms_layer.extent.miny = extent.yMinimum() ms_layer.extent.maxx = extent.xMaximum() ms_layer.extent.maxy = extent.yMaximum() ms_layer.setProjection( _toUtf8( layer.crs().toProj4() ) ) if layer.hasScaleBasedVisibility(): ms_layer.minscaledenom = layer.minimumScale() ms_layer.maxscaledenom = layer.maximumScale() ms_layer.setMetaData( "ows_title", ms_layer.name ) # layer connection if layer.providerType() == 'postgres': ms_layer.setConnectionType( mapscript.MS_POSTGIS, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.connectionInfo() ) data = u"%s FROM %s" % ( uri.geometryColumn(), uri.quotedTablename() ) if uri.keyColumn() != "": data += u" USING UNIQUE %s" % uri.keyColumn() data += u" USING UNIQUE %s" % layer.crs().postgisSrid() if uri.sql() != "": data += " FILTER (%s)" % uri.sql() ms_layer.data = _toUtf8( data ) elif layer.providerType() == 'wms': ms_layer.setConnectionType( mapscript.MS_WMS, "" ) if hasattr(QgsDataSourceURI, 'paramValue'): uri = QgsDataSourceURI( layer.source() ) else: uri = QUrl( layer.source() ) uri.paramValue = uri.queryItemValue # forward to the QUrl method ms_layer.connection = _toUtf8( uri.paramValue("url") ) # loop thru wms sub layers names = [] styles = [] wmsLayerNames = uri.paramValues("layers") wmsLayerStyles = uri.paramValues("styles") for index in range(len(wmsLayerNames)): wmsNames.append( _toUtf8( wmsLayerNames[index] ) ) wmsStyles.append( _toUtf8( wmsLayerStyles[index] ) ) # output SRSs srsList = [] srsList.append( _toUtf8( layer.crs().authid() ) ) # Create necessary wms metadata ms_layer.setMetaData( "ows_name", ','.join(wmsNames) ) ms_layer.setMetaData( "wms_server_version", "1.1.1" ) ms_layer.setMetaData( "ows_srs", ' '.join(srsList) ) #ms_layer.setMetaData( "wms_format", layer.format() ) ms_layer.setMetaData( "wms_format", ','.join(wmsStyles) ) elif layer.providerType() == 'wfs': ms_layer.setConnectionType( mapscript.MS_WMS, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.uri() ) # output SRSs srsList = [] srsList.append( _toUtf8( layer.crs().authid() ) ) # Create necessary wms metadata ms_layer.setMetaData( "ows_name", ms_layer.name ) #ms_layer.setMetaData( "wfs_server_version", "1.1.1" ) ms_layer.setMetaData( "ows_srs", ' '.join(srsList) ) elif layer.providerType() == 'spatialite': ms_layer.setConnectionType( mapscript.MS_OGR, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.database() ) ms_layer.data = _toUtf8( uri.table() ) elif layer.providerType() == 'ogr': #ms_layer.setConnectionType( mapscript.MS_OGR, "" ) ms_layer.data = _toUtf8( layer.source().split('|')[0] ) else: ms_layer.data = _toUtf8( layer.source() ) # set layer style if layer.type() == QgsMapLayer.RasterLayer: if hasattr(layer, 'renderer'): # QGis >= 1.9 opacity = layer.renderer().opacity() else: opacity = int( 100 * layer.getTransparency() / 255.0 ) ms_layer.opacity = opacity else: # use a SLD file set the layer style tempSldFile = QTemporaryFile("rt_mapserver_exporter-XXXXXX.sld") tempSldFile.open() tempSldPath = tempSldFile.fileName() tempSldFile.close() # export the QGIS layer style to SLD file errMsg, ok = layer.saveSldStyle( tempSldPath ) if not ok: QgsMessageLog.logMessage( errMsg, "RT MapServer Exporter" ) else: # set the mapserver layer style from the SLD file with open( unicode(tempSldPath), 'r' ) as fin: sldContents = fin.read() if mapscript.MS_SUCCESS != ms_layer.applySLD( sldContents, ms_layer.name ): QgsMessageLog.logMessage( u"Something went wrong applying the SLD style to the layer '%s'" % ms_layer.name, "RT MapServer Exporter" ) QFile.remove( tempSldPath ) # set layer labels #XXX the following code MUST be removed when QGIS will # have SLD label support labelingEngine = self.canvas.mapRenderer().labelingEngine() if labelingEngine and labelingEngine.willUseLayer( layer ): palLayer = labelingEngine.layer( layer.id() ) if palLayer.enabled: if not palLayer.isExpression: ms_layer.labelitem = _toUtf8( palLayer.fieldName ) else: #XXX expressions won't be supported until # QGIS have SLD label support pass if palLayer.scaleMin > 0: ms_layer.labelminscaledenom = palLayer.scaleMin if palLayer.scaleMax > 0: ms_layer.labelmaxscaledenom = palLayer.scaleMax ms_label = mapscript.labelObj() ms_label.type = mapscript.MS_TRUETYPE ms_label.antialias = mapscript.MS_TRUE ms_label.position = self.getLabelPosition( palLayer ) # TODO: convert offset to pixels ms_label.offsetx = int( palLayer.xOffset ) ms_label.offsety = int( palLayer.yOffset ) ms_label.angle = palLayer.angleOffset # set label font name, size and color fontFamily = palLayer.textFont.family().replace(" ", "") fontStyle = palLayer.textNamedStyle.replace(" ", "") ms_label.font = _toUtf8( u"%s-%s" % (fontFamily, fontStyle) ) if palLayer.textFont.pixelSize() > 0: ms_label.size = int( palLayer.textFont.pixelSize() ) r,g,b,a = palLayer.textColor.getRgb() ms_label.color.setRGB( r, g, b ) if palLayer.fontLimitPixelSize: ms_label.minsize = palLayer.fontMinPixelSize ms_label.maxsize = palLayer.fontMaxPixelSize ms_label.wrap = _toUtf8( palLayer.wrapChar ) ms_label.priority = palLayer.priority # TODO: convert buffer size to pixels ms_label.buffer = int( palLayer.bufferSize ) if int( palLayer.minFeatureSize ) > 0: # TODO: convert feature size from mm to pixels ms_label.minfeaturesize = int( palLayer.minFeatureSize ) ms_class = mapscript.classObj() ms_class.addLabel( ms_label ) ms_layer.insertClass( ms_class ) # save the map file now! if mapscript.MS_SUCCESS != ms_map.save( _toUtf8( self.txtMapFilePath.text() ) ): return # Most of the following code does not use mapscript because it asserts # paths you supply exists, but this requirement is usually not meet on # the QGIS client used to generate the mafile. # get the mapfile content as string so we can manipulate on it with open( unicode(self.txtMapFilePath.text()), 'r' ) as fin: # parts holds the content lines parts = QString(fin.read()).split(u"\n") partsContentChanged = False # retrieve the list of used font aliases searching for FONT keywords fonts = [] searchFontRx = QRegExp("^\\s*FONT\\s+") for line in parts.filter( searchFontRx ): # get the font alias, remove quotes around it fontName = line.replace(searchFontRx, "")[1:-1] # remove spaces within the font name fontAlias = QString(fontName).replace(" ", "") # append the font alias to the font list if fontAlias not in fonts: fonts.append( fontAlias ) # update the font alias in the mapfile # XXX: the following lines cannot be removed since the SLD file # could refer a font whose name contains spaces. When SLD specs # ate clear on how to handle fonts than we'll think whether # remove it or not. replaceFontRx = QRegExp(u"^(\\s*FONT\\s+\")%s(\".*)$" % QRegExp.escape(fontName)) parts.replaceInStrings(replaceFontRx, u"\\1%s\\2" % fontAlias) partsContentChanged = True # create the file containing the list of font aliases used in the # mapfile if self.checkCreateFontFile.isChecked(): fontPath = QFileInfo(self.txtMapFilePath.text()).dir().filePath(u"fonts.txt") with open( unicode(fontPath), 'w' ) as fout: for fontAlias in fonts: fout.write( unicode(fontAlias) ) # add the FONTSET keyword with the associated path if self.txtMapFontsetPath.text() != "": pos = parts.indexOf( QRegExp("^MAP$") ) if pos >= 0: parts.insert( pos+1, u' FONTSET "%s"' % self.txtMapFontsetPath.text() ) partsContentChanged = True else: QgsMessageLog.logMessage( u"'FONTSET' keyword not added to the mapfile: unable to locate the 'WEB' keyword...", "RT MapServer Exporter" ) # if mapfile content changed, store the file again at the same path if partsContentChanged: with open( unicode(self.txtMapFilePath.text()), 'w' ) as fout: fout.write( unicode( parts.join(u"\n") ) ) # XXX for debugging only: let's have a look at the map result! :) # XXX it works whether the file pointed by the fontset contains ALL the # aliases of fonts referred from the mapfile. #ms_map = mapscript.mapObj( unicode( self.txtMapFilePath.text() ) ) #ms_map.draw().save( _toUtf8( self.txtMapFilePath.text() + ".png" ) , ms_map ) QDialog.accept(self)
def _get_map(self): """ Generate a mapserver mapObj. """ # create a mapscript map from scratch map = mapscript.mapObj() # Configure the map # NAME map.name = "BCCVLMap" # EXTENT ... in projection units (we use epsg:4326) WGS84 map.extent = mapscript.rectObj(-180.0, -90.0, 180.0, 90.0) # map.extent = mapscript.rectObj(-20026376.39, -20048966.10, 20026376.39, 20048966.10) # UNITS ... in projection units map.units = mapscript.MS_DD # SIZE map.setSize(256, 256) # PROJECTION ... WGS84 map.setProjection("init=epsg:4326") # IMAGETYPE map.selectOutputFormat("PNG24") # PNG, PNG24, JPEG map.outputformat.imagemode = mapscript.MS_IMAGEMODE_RGBA map.outputformat.transparent = mapscript.MS_ON # TRANSPARENT ON map.transparent = mapscript.MS_ON # IMAGECOLOR 255 255 255 # map.imagecolor = mapscript.colorObj(255, 255, 255) ... initial color if transparent is on # SYMBOLSET (needed to draw circles for CSV points) self._update_symbol_set(map) # metadata: wms_feature_info_mime_type text/htm/ application/json # WEB # TODO: check return value of setMetaData MS_SUCCESS/MS_FAILURE map.setMetaData("wms_enable_request", "*") map.setMetaData("wms_title", "BCCVL WMS Server") # allow reprojection to Web Mercator map.setMetaData("wms_srs", "EPSG:4326 EPSG:3857") # wms_enable_request enough? map.setMetaData("ows_enable_request", "*") onlineresource = urlparse.urlunsplit( (self.request.scheme, "{}:{}".format(self.request.host, self.request.host_port), self.request.path, urllib.urlencode((('DATA_URL', self.request.params.get('DATA_URL').encode('utf-8')), )), "")) map.setMetaData("wms_onlineresource", onlineresource) # TODO: metadata # title, author, xmp_dc_title # wms_onlineresource ... help to generate GetCapabilities request # ows_http_max_age ... WMS client caching hints http://www.mnot.net/cache_docs/#CACHE-CONTROL # ows_lsd_enabled ... if false ignore SLD and SLD_BODY # wms_attribution_xxx ... do we want attribution metadata? # SCALEBAR if False: # LABEL sbl = mapscript.labelObj() sbl.color = mapscript.colorObj(0, 0, 0) sbl.antialias = mapscript.MS_TRUE sbl.size = mapscript.MS_LARGE sb = mapscript.scalebarObj() sb.label = sbl sb.status = mapscript.MS_ON map.scalebar = sb # LEGEND if False: # LABEL legl = mapscript.labelObj() legl.color = mapscript.colorObj(64, 64, 64) legl.antialias = mapscript.MS_TRUE legl.offsetx = -23 legl.offsety = -1 leg = mapscript.legendObj() leg.keysizex = 32 leg.keysizey = 10 leg.keyspacingx = 5 leg.keyspacingy = -2 leg.status = mapscript.MS_ON map.legend = leg return map
def _get_map(self): """ Generate a mapserver mapObj. """ # create a mapscript map from scratch map = mapscript.mapObj() # Configure the map # NAME map.name = "BCCVLMap" # EXTENT ... in projection units (we use epsg:4326) WGS84 map.extent = mapscript.rectObj(-180.0, -90.0, 180.0, 90.0) # map.extent = mapscript.rectObj(-20026376.39, -20048966.10, 20026376.39, 20048966.10) # UNITS ... in projection units map.units = mapscript.MS_DD # SIZE map.setSize(256, 256) # PROJECTION ... WGS84 map.setProjection("init=epsg:4326") # IMAGETYPE map.selectOutputFormat("PNG24") # PNG, PNG24, JPEG map.outputformat.imagemode = mapscript.MS_IMAGEMODE_RGBA map.outputformat.transparent = mapscript.MS_ON # TRANSPARENT ON map.transparent = mapscript.MS_ON # IMAGECOLOR 255 255 255 # map.imagecolor = mapscript.colorObj(255, 255, 255) ... initial color if transparent is on # SYMBOLSET (needed to draw circles for CSV points) self._update_symbol_set(map) # metadata: wms_feature_info_mime_type text/htm/ application/json # WEB # TODO: check return value of setMetaData MS_SUCCESS/MS_FAILURE map.setMetaData("wms_enable_request", "*") map.setMetaData("wms_title", "BCCVL WMS Server") # allow reprojection to Web Mercator map.setMetaData("wms_srs", "EPSG:4326 EPSG:3857") # wms_enable_request enough? map.setMetaData("ows_enable_request", "*") onlineresource = urlparse.urlunsplit( (self.request.scheme, "{}:{}".format(self.request.host, self.request.host_port), self.request.path, urllib.urlencode( (('DATA_URL', self.request.params.get('DATA_URL')), )), "")) map.setMetaData("wms_onlineresource", onlineresource) # TODO: metadata # title, author, xmp_dc_title # wms_onlineresource ... help to generate GetCapabilities request # ows_http_max_age ... WMS client caching hints http://www.mnot.net/cache_docs/#CACHE-CONTROL # ows_lsd_enabled ... if false ignore SLD and SLD_BODY # wms_attribution_xxx ... do we want attribution metadata? # SCALEBAR if False: # LABEL sbl = mapscript.labelObj() sbl.color = mapscript.colorObj(0, 0, 0) sbl.antialias = mapscript.MS_TRUE sbl.size = mapscript.MS_LARGE sb = mapscript.scalebarObj() sb.label = sbl sb.status = mapscript.MS_ON map.scalebar = sb # LEGEND if False: # LABEL legl = mapscript.labelObj() legl.color = mapscript.colorObj(64, 64, 64) legl.antialias = mapscript.MS_TRUE legl.offsetx = -23 legl.offsety = -1 leg = mapscript.legendObj() leg.keysizex = 32 leg.keysizey = 10 leg.keyspacingx = 5 leg.keyspacingy = -2 leg.status = mapscript.MS_ON map.legend = leg return map
def accept(self): layerGroups = [] # check user inputs if self.txtMapFilePath.text() == "": QMessageBox.warning(self, "RT MapServer Exporter", "Mapfile output path is required") return # create a new ms_map ms_map = mapscript.mapObj() ms_map.name = _cleanStr( self.txtMapName.text() ) # map size (width, widthOk), (height, heightOk) = self.txtMapWidth.text().toInt(), self.txtMapHeight.text().toInt() if widthOk and heightOk: ms_map.setSize( width, height ) # map units ms_map.units = self.unitMap[ self.canvas.mapUnits() ] if self.cmbMapUnits.currentIndex() >= 0: units, ok = self.cmbMapUnits.itemData( self.cmbMapUnits.currentIndex() ).toInt() if ok: ms_map.units = units # config options ms_map.setConfigOption("MS_ERRORFILE", "/tmp/ms_"+ ms_map.name +".log") # map extent extent = self.canvas.fullExtent() ms_map.extent.minx = extent.xMinimum() ms_map.extent.miny = extent.yMinimum() ms_map.extent.maxx = extent.xMaximum() ms_map.extent.maxy = extent.yMaximum() if self.canvas.mapRenderer().destinationCrs().authid() != "": ms_map.setProjection( "+init=" + _toUtf8( self.canvas.mapRenderer().destinationCrs().authid() ).lower() ) else: ms_map.setProjection( _toUtf8( self.canvas.mapRenderer().destinationCrs().toProj4() ) ) if self.txtMapShapePath.text() != "": ms_map.shapepath = _toUtf8( self.getMapShapePath() ) # image section r,g,b,a = self.canvas.canvasColor().getRgb() ms_map.imagecolor.setRGB( r, g, b ) #255,255,255 ms_map.setImageType( _toUtf8( self.cmbMapImageType.currentText() ) ) ms_outformat = ms_map.getOutputFormatByName( ms_map.imagetype ) ms_outformat.transparent = self.onOffMap[ True ] ms_map.transparent = mapscript.MS_TRUE # legend section #r,g,b,a = self.canvas.canvasColor().getRgb() #ms_map.legend.imageColor.setRgb( r, g, b ) #ms_map.legend.status = mapscript.MS_ON #ms_map.legend.keysizex = 18 #ms_map.legend.keysizey = 12 #ms_map.legend.label.type = mapscript.MS_BITMAP #ms_map.legend.label.size = MEDIUM?? #ms_map.legend.label.color.setRgb( 0, 0, 89 ) #ms_map.legend.label.partials = self.trueFalseMap[ self.checkBoxPartials ] #ms_map.legend.label.force = self.trueFalseMap[ self.checkBoxForce ] #ms_map.legend.template = "[templatepath]" # web section ms_map.web.imagepath = _toUtf8( self.getWebImagePath() ) ms_map.web.imageurl = _toUtf8( self.getWebImageUrl() ) ms_map.web.temppath = _toUtf8( self.getWebTemporaryPath() ) # web template ms_map.web.template = _toUtf8( self.getTemplatePath() ) ms_map.web.header = _toUtf8( self.getTemplateHeaderPath() ) ms_map.web.footer = _toUtf8( self.getTemplateFooterPath() ) # map metadata if (QgsProject.instance().readBoolEntry( "WMSServiceCapabilities", "/", False )[0]): ms_map.setMetaData( "ows_title", _toUtf8( QgsProject.instance().readEntry("WMSServiceTitle", "/", "")[0] ) ) ms_map.setMetaData( "ows_abstract", _toUtf8( QgsProject.instance().readEntry("WMSServiceAbstract", "/", "")[0] ) ) ms_map.setMetaData( "ows_contactorganization", _toUtf8( QgsProject.instance().readEntry("WMSContactOrganization", "/", "")[0] ) ) ms_map.setMetaData( "ows_contactperson", _toUtf8( QgsProject.instance().readEntry("WMSContactPerson", "/", "")[0] ) ) ms_map.setMetaData( "ows_contactelectronicmailaddress", _toUtf8( QgsProject.instance().readEntry("WMSContactMail", "/", "")[0] ) ) ms_map.setMetaData( "ows_contactvoicetelephone", _toUtf8( QgsProject.instance().readEntry("WMSContactPhone", "/", "")[0] ) ) ms_map.setMetaData( "ows_keywordlist", _toUtf8( QgsProject.instance().readListEntry("WMSKeywordList", "/") [0].join(",") ) ) ms_map.setMetaData( "ows_accessconstraints", _toUtf8( QgsProject.instance().readEntry("WMSAccessConstraints", "/", "")[0] ) ) else: ms_map.setMetaData( "ows_title", _toUtf8( self.txtMapName.text() ) ) ms_map.setMetaData( "ows_onlineresource", _toUtf8( u"%s?map=%s" % (self.txtMapServerUrl.text(), self.txtMapFilePath.text()) ) ) srsList = ["EPSG:4326"] srsList.append( _toUtf8( self.canvas.mapRenderer().destinationCrs().authid() ) ) ms_map.setMetaData( "ows_srs", ' '.join(srsList) ) ms_map.setMetaData( "ows_enable_request", "*" ) ms_map.setMetaData( "wms_feature_info_mime_type", "text/html") for layer in self.legend.layers(): # do not process invisible layer if not self.legend.isLayerVisible( layer ): continue; # create a layer object ms_layer = mapscript.layerObj( ms_map ) ms_layer.name = _cleanStr( layer.name() ) ms_layer.type = self.getLayerType( layer ) ms_layer.status = mapscript.MS_ON # layer extent extent = layer.extent() ms_layer.extent.minx = extent.xMinimum() ms_layer.extent.miny = extent.yMinimum() ms_layer.extent.maxx = extent.xMaximum() ms_layer.extent.maxy = extent.yMaximum() if layer.crs().authid() != "": ms_layer.setProjection( "+init=" + _toUtf8( layer.crs().authid() ).lower() ) else: ms_layer.setProjection( _toUtf8( layer.crs().toProj4() ) ) if layer.hasScaleBasedVisibility(): ms_layer.minscaledenom = layer.minimumScale() ms_layer.maxscaledenom = layer.maximumScale() if layer.title() != "": ms_layer.setMetaData( "ows_title", _toUtf8(layer.title())) else: ms_layer.setMetaData( "ows_title", _toUtf8(layer.name())) if layer.abstract() != "": ms_layer.setMetaData( "ows_abstract", _toUtf8(layer.abstract())) arrPath = self.getGroupPath(layer) if arrPath != "": path = '/' +'/'.join(arrPath) ms_layer.setMetaData( "wms_layer_group", _cleanStr( path )) if not path in layerGroups : ms_layer_group = mapscript.layerObj( ms_map ) ms_layer_group.name = _cleanStr(arrPath[-1] ) ms_layer_group.setMetaData( "ows_title", arrPath[-1]) ms_layer_group.type = ms_layer.type ms_layer.status = mapscript.MS_ON layerGroups.append( path ) # layer connection if layer.providerType() == 'postgres': ms_layer.setConnectionType( mapscript.MS_POSTGIS, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.connectionInfo() ) data = u"%s FROM %s" % ( uri.geometryColumn(), uri.quotedTablename() ) #The keyColumn name is invalid with QGis 1.9dev if uri.keyColumn() != "": data += u" USING UNIQUE %s" % uri.keyColumn() data += u" USING srid=%s" % uri.srid() if uri.sql() != "": data += " FILTER (%s)" % uri.sql() ms_layer.data = _toUtf8( data ) elif layer.providerType() == 'wms': ms_layer.setConnectionType( mapscript.MS_WMS, "" ) q = parse_qs(_toUtf8(layer.source()), True) ms_layer.connection = q["url"][0] # loop thru wms sub layers wmsNames = [] wmsStyles = [] wmsLayerNames = q["layers"] wmsLayerStyles = q["styles"] for index in range(len(wmsLayerNames)): wmsNames.append( _toUtf8( wmsLayerNames[index] ) ) wmsStyles.append( _toUtf8( wmsLayerStyles[index] ) ) # output SRSs srsList = [] srsList.append( _toUtf8( layer.crs().authid() ) ) # Create necessary wms metadata ms_layer.setMetaData( "ows_name", ',' . join(wmsNames) ) ms_layer.setMetaData( "wms_server_version", "1.1.1" ) ms_layer.setMetaData( "ows_srs", ' ' . join(srsList) ) ms_layer.setMetaData( "wms_format", q["format"][0] ) elif layer.providerType() == 'wfs': ms_layer.setConnectionType( mapscript.MS_WFS, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.uri() ) # output SRSs srsList = [] srsList.append( _toUtf8( layer.crs().authid() ) ) # Create necessary wms metadata ms_layer.setMetaData( "ows_name", ms_layer.name ) #ms_layer.setMetaData( "wfs_server_version", "1.1.1" ) ms_layer.setMetaData( "ows_srs", ' '.join(srsList) ) elif layer.providerType() == 'spatialite': ms_layer.setConnectionType( mapscript.MS_OGR, "" ) uri = QgsDataSourceURI( layer.source() ) ms_layer.connection = _toUtf8( uri.database() ) ms_layer.data = _toUtf8( uri.table() ) elif layer.providerType() == 'ogr': #ms_layer.setConnectionType( mapscript.MS_OGR, "" ) ms_layer.data = _toUtf8( layer.source().split('|')[0] ) else: ms_layer.data = _toUtf8( layer.source() ) # set layer style if layer.type() == QgsMapLayer.RasterLayer: if hasattr(layer, 'renderer'): # QGis >= 1.9 opacity = int( 100 *layer.renderer().opacity()) else: opacity = int( 100 * layer.getTransparency() / 255.0 ) ms_layer.opacity = opacity else: # use a SLD file set the layer style tempSldFile = QTemporaryFile("rt_mapserver_exporter-XXXXXX.sld") tempSldFile.open() tempSldPath = tempSldFile.fileName() tempSldFile.close() # export the QGIS layer style to SLD file errMsg, ok = layer.saveSldStyle( tempSldPath ) if not ok: QgsMessageLog.logMessage( errMsg, "RT MapServer Exporter" ) else: # set the mapserver layer style from the SLD file with open( unicode(tempSldPath), 'r' ) as fin: sldContents = fin.read() if mapscript.MS_SUCCESS != ms_layer.applySLD( sldContents, _toUtf8( layer.name() ) ): QgsMessageLog.logMessage( u"Something went wrong applying the SLD style to the layer '%s'" % ms_layer.name, "RT MapServer Exporter" ) QFile.remove( tempSldPath ) # Convert units between QGis (mm) and MapServer (pixels) self.convertMapUnit(ms_layer) # MapServer patch : SLD "GAP" is not recognized self.patchGAP(layer, ms_layer) # set layer labels #XXX the following code MUST be removed when QGIS will # have SLD label support palLayer = QgsPalLayerSettings() palLayer.readFromLayer(layer) if palLayer.enabled: if not palLayer.isExpression: ms_layer.labelitem = _toUtf8( palLayer.fieldName ) else: #XXX expressions won't be supported until # QGIS have SLD label support pass if palLayer.scaleMin > 0: ms_layer.labelminscaledenom = palLayer.scaleMin if palLayer.scaleMax > 0: ms_layer.labelmaxscaledenom = palLayer.scaleMax ms_label = mapscript.labelObj() ms_label.type = mapscript.MS_TRUETYPE ms_label.antialias = mapscript.MS_TRUE if layer.geometryType() == QGis.Line: if palLayer.placementFlags & QgsPalLayerSettings.AboveLine: ms_label.position = mapscript.MS_UC elif palLayer.placementFlags & QgsPalLayerSettings.BelowLine: ms_label.position = mapscript.MS_LC elif palLayer.placementFlags & QgsPalLayerSettings.OnLine: ms_label.position = mapscript.MS_CC ms_label.offsety = int( mmToPixelFactor * palLayer.dist ) else: ms_label.position = self.getLabelPosition( palLayer ) # TODO: convert offset to pixels ms_label.offsetx = int( mmToPixelFactor * palLayer.xOffset ) ms_label.offsety = int( mmToPixelFactor * palLayer.yOffset ) if palLayer.placement == palLayer.Line: ms_label.anglemode = mapscript.MS_AUTO if palLayer.placement == palLayer.Curved: ms_label.anglemode = mapscript.MS_FOLLOW else: ms_label.angle = palLayer.angleOffset # set label font name, size and color fontFamily = palLayer.textFont.family().replace(" ", "") fontStyle = palLayer.textNamedStyle.replace(" ", "") ms_label.font = _toUtf8( u"%s-%s" % (fontFamily, fontStyle) ) if palLayer.textFont.pointSize() > 0: # Facteur 0.75 a ete mis en place pour s'approcher du rendu Qgis ms_label.size = palLayer.textFont.pointSize() * 0.75 r,g,b,a = palLayer.textColor.getRgb() ms_label.color.setRGB( r, g, b ) r,g,b,a = palLayer.bufferColor.getRgb() ms_label.outlinecolor.setRGB( r, g, b ) ms_label.outlinewidth = int( mmToPixelFactor * palLayer.bufferSize ) if palLayer.fontLimitPixelSize: ms_label.minsize = palLayer.fontMinPixelSize ms_label.maxsize = palLayer.fontMaxPixelSize ms_label.wrap = _toUtf8( palLayer.wrapChar ) ms_label.priority = palLayer.priority # TODO: convert buffer size to pixels # ms_label.buffer = int( mmToPixelFactor * palLayer.bufferSize ) if int( palLayer.minFeatureSize ) > 0: # TODO: convert feature size from mm to pixels ms_label.minfeaturesize = int( mmToPixelFactor * palLayer.minFeatureSize ) for n in range(0, ms_layer.numclasses): ms_class = ms_layer.getClass(n) ms_class.addLabel( ms_label ) # ms_class = mapscript.classObj() # ms_class.addLabel( ms_label ) # ms_layer.insertClass( ms_class ) # save the map file now! if mapscript.MS_SUCCESS != ms_map.save( _toUtf8( self.txtMapFilePath.text() ) ): return # Save GUI parameters self.storeProperties() # Most of the following code does not use mapscript because it asserts # paths you supply exists, but this requirement is usually not meet on # the QGIS client used to generate the mafile. # get the mapfile content as string so we can manipulate on it with open( unicode(self.txtMapFilePath.text()), 'r' ) as fin: # parts holds the content lines parts = QString(fin.read()).split(u"\n") partsContentChanged = False # retrieve the list of used font aliases searching for FONT keywords fonts = [] searchFontRx = QRegExp("^\\s*FONT\\s+") for line in parts.filter( searchFontRx ): # get the font alias, remove quotes around it fontName = line.replace(searchFontRx, "")[1:-1] # remove spaces within the font name fontAlias = QString(fontName).replace(" ", "") # append the font alias to the font list if fontAlias not in fonts: fonts.append( fontAlias ) # update the font alias in the mapfile # XXX: the following lines cannot be removed since the SLD file # could refer a font whose name contains spaces. When SLD specs # ate clear on how to handle fonts than we'll think whether # remove it or not. replaceFontRx = QRegExp(u"^(\\s*FONT\\s+\")%s(\".*)$" % QRegExp.escape(fontName)) parts.replaceInStrings(replaceFontRx, u"\\1%s\\2" % fontAlias) partsContentChanged = True # create the file containing the list of font aliases used in the # mapfile if self.checkCreateFontFile.isChecked(): fontPath = QFileInfo(self.txtMapFilePath.text()).dir().filePath(u"fonts.txt") with open( unicode(fontPath), 'w' ) as fout: for fontAlias in fonts: fout.write( unicode(fontAlias) ) # add the FONTSET keyword with the associated path if self.txtMapFontsetPath.text() != "": pos = parts.indexOf( QRegExp("^MAP$") ) if pos >= 0: parts.insert( pos+1, u' FONTSET "%s"' % self.txtMapFontsetPath.text() ) partsContentChanged = True else: QgsMessageLog.logMessage( u"'FONTSET' keyword not added to the mapfile: unable to locate the 'WEB' keyword...", "RT MapServer Exporter" ) # if mapfile content changed, store the file again at the same path if partsContentChanged: with open( unicode(self.txtMapFilePath.text()), 'w' ) as fout: fout.write( unicode( parts.join(u"\n") ) ) # XXX for debugging only: let's have a look at the map result! :) # XXX it works whether the file pointed by the fontset contains ALL the # aliases of fonts referred from the mapfile. #ms_map = mapscript.mapObj( unicode( self.txtMapFilePath.text() ) ) #ms_map.draw().save( _toUtf8( self.txtMapFilePath.text() + ".png" ) , ms_map ) QDialog.accept(self)