Esempio n. 1
0
 def display_mapfile_validity(self):
     """Display on GUI the validity of current mapfile."""
     if self.editor.getText() <> '' and self.temp_mapfile and os.path.exists(self.temp_mapfile):
         self.update_file()
         renderer = MapfileRenderer(self.temp_mapfile)
         message = renderer.load_mapfile()
         if self.messageTextEdit is not None:
             self.messageTextEdit.append(message)
         mapobj = renderer.getMapObj()
         if mapobj is None:
             self.addLayerButton.setEnabled(False)
             self.replaceLayerButton.setEnabled(False)
         else:
             self.addLayerButton.setEnabled(True)
             self.replaceLayerButton.setEnabled(True)
             self.editor.markerDeleteAll()
         # display error line
         regexp = re.compile('.*\(line ([0-9]*)\)')
         try:
             # get error line number
             linenb = int(regexp.findall(message.split("\n")[-1])[-1])
             # add a marker on error line in editor
             # FIXME : move this code into editor's mark_error()
             self.editor.markerAdd(linenb - 1, self.editor.ARROW_MARKER_NUM)
         except ValueError:
             # error with no line number, just ignore
             pass
         except IndexError:
             pass
Esempio n. 2
0
 def display_mapfile_validity(self):
     """Display on GUI the validity of current mapfile."""
     if self.editor.getText(
     ) <> '' and self.temp_mapfile and os.path.exists(self.temp_mapfile):
         self.update_file()
         renderer = MapfileRenderer(self.temp_mapfile)
         message = renderer.load_mapfile()
         if self.messageTextEdit is not None:
             self.messageTextEdit.append(message)
         mapobj = renderer.getMapObj()
         if mapobj is None:
             self.addLayerButton.setEnabled(False)
             self.replaceLayerButton.setEnabled(False)
         else:
             self.addLayerButton.setEnabled(True)
             self.replaceLayerButton.setEnabled(True)
             self.editor.markerDeleteAll()
         # display error line
         regexp = re.compile('.*\(line ([0-9]*)\)')
         try:
             # get error line number
             linenb = int(regexp.findall(message.split("\n")[-1])[-1])
             # add a marker on error line in editor
             # FIXME : move this code into editor's mark_error()
             self.editor.markerAdd(linenb - 1, self.editor.ARROW_MARKER_NUM)
         except ValueError:
             # error with no line number, just ignore
             pass
         except IndexError:
             pass
class MapfileLayer(QgsPluginLayer):

  LAYER_TYPE="mapfile"

  def __init__(self, messageTextEdit, mapfile = "", name = None):
    QgsPluginLayer.__init__(self, MapfileLayer.LAYER_TYPE, "Mapfile Tools plugin layer")
    self.setValid(True)

    self.messageTextEdit = messageTextEdit
    self.mapfile = mapfile 
    self.layers = ""
    self.maprenderer = None
    self.pixmap = None

    if self.mapfile:
      self.loadMapfile(mapfile, (), name)

  def setupPaintArea(self, rendererContext):
    rasterScaleFactor = rendererContext.rasterScaleFactor()
    invRasterScaleFactor = 1.0/rasterScaleFactor

    # setup painter
    painter = rendererContext.painter()
    painter.scale(invRasterScaleFactor, invRasterScaleFactor)

    # get dimensions of painter area (so it is also correctly scaled in print composer)
    extent = rendererContext.extent()
    mapToPixel = rendererContext.mapToPixel()
    topleft = mapToPixel.transform(extent.xMinimum(), extent.yMaximum())
    bottomright = mapToPixel.transform(extent.xMaximum(), extent.yMinimum())

    topleft.multiply(rasterScaleFactor)
    bottomright.multiply(rasterScaleFactor)

    return QgsRectangle(topleft, bottomright)

  def drawUntiled(self, painter, extent, viewport):
    img, message = self.maprenderer.render(extent, (viewport.width(), viewport.height()))
    self.messageTextEdit.append(message)
    self.pixmap.loadFromData(img)
    painter.drawPixmap(viewport.xMinimum(), viewport.yMinimum(), self.pixmap)

  def drawTiled(self, painter, extent, viewport, maxWidth, maxHeight):
    # dimensions
    mapMinX = extent.xMinimum()
    mapMaxX = extent.xMaximum()
    mapMinY = extent.yMinimum()
    mapMaxY = extent.yMaximum()
    viewportWidth = viewport.width()
    viewportHeight = viewport.height()
    pixelToMapUnitsX = (mapMaxX - mapMinX) / viewportWidth
    pixelToMapUnitsY = (mapMaxY - mapMinY) / viewportHeight

    # draw tiles
    nx = int( math.ceil(viewportWidth / maxWidth) )
    ny = int( math.ceil(viewportHeight / maxHeight) )
    for i in range(0,nx):
      for j in range(0,ny):
        # tile size
        left = i * maxWidth
        right = min((i+1) * maxWidth, viewportWidth)
        top = j * maxHeight
        bottom = min((j+1) * maxHeight, viewportHeight)
        width = right - left
        height = bottom - top

        # tile extents
        mapBottomLeft = QgsPoint(mapMinX + left * pixelToMapUnitsX, mapMaxY - bottom * pixelToMapUnitsY)
        mapTopRight = QgsPoint(mapMinX + right * pixelToMapUnitsX, mapMaxY - top * pixelToMapUnitsY)
        bbox = "%f,%f,%f,%f" % (mapBottomLeft.x(), mapBottomLeft.y(), mapTopRight.x(), mapTopRight.y())

        # render and compose image
        img, message = self.maprenderer.render(bbox, (width, height))
        self.messageTextEdit.append(message)
        self.pixmap.loadFromData(img)
        painter.drawPixmap(viewport.xMinimum() + left, viewport.yMinimum() + top, self.pixmap)

  def draw(self, rendererContext):
    if self.maprenderer == None:
      return True

    painter = rendererContext.painter()
    painter.save()

    maxSize = self.maprenderer.getMaxSize()
    extent = rendererContext.extent()
    viewport = self.setupPaintArea(rendererContext)

    maxWidth = min(viewport.width(), maxSize)
    maxHeight = min(viewport.height(), maxSize)
    if maxWidth < viewport.width() or maxHeight < viewport.height():
      # compose image from tiles with maxSize
      self.drawTiled(painter, extent, viewport, maxWidth, maxHeight)
    else:
      self.drawUntiled(painter, extent, viewport)

    painter.restore()

    return True

  def readXml(self, node):
    # custom properties
    mapfile = node.toElement().attribute("mapfile", "")
    layers = str(node.toElement().attribute("layers", ""))
    self.loadMapfile(mapfile, layers)
    return True

  def writeXml(self, node, doc):
    element = node.toElement();
    # write plugin layer type to project (essential to be read from project)
    element.setAttribute("type", "plugin")
    element.setAttribute("name", MapfileLayer.LAYER_TYPE);
    # custom properties
    element.setAttribute("mapfile", str(self.mapfile))
    element.setAttribute("layers", str(self.layers))
    return True

  def reload(self, layers = (), name = None):
    self.loadMapfile(self.mapfile, layers, name)

  def loadMapfile(self, mapfile, layers = (), name = None):
    message = ''
    self.mapfile = mapfile
    self.layers = layers
    if self.mapfile == "":
      return False

    # open mapfile
    self.maprenderer = MapfileRenderer(str(self.mapfile))
    message = self.maprenderer.load_mapfile()
    self.messageTextEdit.append(message)
    mapobj = self.maprenderer.getMapObj()
    if mapobj is None:
      return False

    if name is None:
        self.setLayerName(mapobj.name)
    else:
        self.setLayerName(name)

    # get projection as EPSG
    crs = QgsCoordinateReferenceSystem()
    crs.createFromProj4(self.maprenderer.getProj())
    if not crs.isValid():
      crs.validate()

    srs = "EPSG:%d" % crs.epsg()

    # always use default format for now
    self.maprenderer.setup(self.layers, srs)

    # set projection
    self.setCrs(crs)

    # TODO: set extents
#    extents = self.maprenderer.getExtents()
#    self.setExtent(QgsRectangle(extents[0], extents[1], extents[2], extents[3]))

    if self.pixmap == None:
      self.pixmap = QPixmap()

    # trigger repaint
    self.setCacheImage(None)
    self.emit(SIGNAL("repaintRequested()"))
    return True

  def openMapfile(self):
    mapfile = QFileDialog.getOpenFileName(None, "Mapfile", ".", "MapServer map files (*.map);;All files (*.*)","Filter list for selecting files from a dialog box")
    if mapfile != "":
      return self.loadMapfile(str(mapfile), ())
    return False

  def showProperties(self):
    return False # Not supported for now - see http://hub.qgis.org/issues/1

    # create and show the dialog
    dlg = MapfileLayerDialog()

    # show the dialog
    dlg.ui.leMapfile.setText(self.mapfile)
    dlg.updateInfo()
    dlg.show()

    # See if OK was pressed
    if dlg.exec_() == 1:
      mapfile = dlg.ui.leMapfile.text()

      # selected layers
      items = dlg.ui.listLayers.selectedItems()
      layerlist = []
      for item in items:
        layerlist.append(str(item.text()))
      layers = string.join(layerlist, ",")

      self.loadMapfile(mapfile, layers)
      return True

    return False
Esempio n. 4
0
class MapfileLayer(QgsPluginLayer):

    LAYER_TYPE = "mapfile"

    def __init__(self, messageTextEdit, mapfile="", name=None):
        QgsPluginLayer.__init__(self, MapfileLayer.LAYER_TYPE,
                                "Mapfile Tools plugin layer")
        self.setValid(True)

        self.messageTextEdit = messageTextEdit
        self.mapfile = mapfile
        self.layers = ""
        self.maprenderer = None
        self.pixmap = None

        if self.mapfile:
            self.loadMapfile(mapfile, (), name)

    def setupPaintArea(self, rendererContext):
        rasterScaleFactor = rendererContext.rasterScaleFactor()
        invRasterScaleFactor = 1.0 / rasterScaleFactor

        # setup painter
        painter = rendererContext.painter()
        painter.scale(invRasterScaleFactor, invRasterScaleFactor)

        # get dimensions of painter area (so it is also correctly scaled in print composer)
        extent = rendererContext.extent()
        mapToPixel = rendererContext.mapToPixel()
        topleft = mapToPixel.transform(extent.xMinimum(), extent.yMaximum())
        bottomright = mapToPixel.transform(extent.xMaximum(),
                                           extent.yMinimum())

        topleft.multiply(rasterScaleFactor)
        bottomright.multiply(rasterScaleFactor)

        return QgsRectangle(topleft, bottomright)

    def drawUntiled(self, painter, extent, viewport):
        img, message = self.maprenderer.render(
            extent, (viewport.width(), viewport.height()))
        self.messageTextEdit.append(message)
        self.pixmap.loadFromData(img)
        painter.drawPixmap(viewport.xMinimum(), viewport.yMinimum(),
                           self.pixmap)

    def drawTiled(self, painter, extent, viewport, maxWidth, maxHeight):
        # dimensions
        mapMinX = extent.xMinimum()
        mapMaxX = extent.xMaximum()
        mapMinY = extent.yMinimum()
        mapMaxY = extent.yMaximum()
        viewportWidth = viewport.width()
        viewportHeight = viewport.height()
        pixelToMapUnitsX = (mapMaxX - mapMinX) / viewportWidth
        pixelToMapUnitsY = (mapMaxY - mapMinY) / viewportHeight

        # draw tiles
        nx = int(math.ceil(viewportWidth / maxWidth))
        ny = int(math.ceil(viewportHeight / maxHeight))
        for i in range(0, nx):
            for j in range(0, ny):
                # tile size
                left = i * maxWidth
                right = min((i + 1) * maxWidth, viewportWidth)
                top = j * maxHeight
                bottom = min((j + 1) * maxHeight, viewportHeight)
                width = right - left
                height = bottom - top

                # tile extents
                mapBottomLeft = QgsPoint(mapMinX + left * pixelToMapUnitsX,
                                         mapMaxY - bottom * pixelToMapUnitsY)
                mapTopRight = QgsPoint(mapMinX + right * pixelToMapUnitsX,
                                       mapMaxY - top * pixelToMapUnitsY)
                bbox = "%f,%f,%f,%f" % (mapBottomLeft.x(), mapBottomLeft.y(),
                                        mapTopRight.x(), mapTopRight.y())

                # render and compose image
                img, message = self.maprenderer.render(bbox, (width, height))
                self.messageTextEdit.append(message)
                self.pixmap.loadFromData(img)
                painter.drawPixmap(viewport.xMinimum() + left,
                                   viewport.yMinimum() + top, self.pixmap)

    def draw(self, rendererContext):
        if self.maprenderer == None:
            return True

        painter = rendererContext.painter()
        painter.save()

        maxSize = self.maprenderer.getMaxSize()
        extent = rendererContext.extent()
        viewport = self.setupPaintArea(rendererContext)

        maxWidth = min(viewport.width(), maxSize)
        maxHeight = min(viewport.height(), maxSize)
        if maxWidth < viewport.width() or maxHeight < viewport.height():
            # compose image from tiles with maxSize
            self.drawTiled(painter, extent, viewport, maxWidth, maxHeight)
        else:
            self.drawUntiled(painter, extent, viewport)

        painter.restore()

        return True

    def readXml(self, node):
        # custom properties
        mapfile = node.toElement().attribute("mapfile", "")
        layers = str(node.toElement().attribute("layers", ""))
        self.loadMapfile(mapfile, layers)
        return True

    def writeXml(self, node, doc):
        element = node.toElement()
        # write plugin layer type to project (essential to be read from project)
        element.setAttribute("type", "plugin")
        element.setAttribute("name", MapfileLayer.LAYER_TYPE)
        # custom properties
        element.setAttribute("mapfile", str(self.mapfile))
        element.setAttribute("layers", str(self.layers))
        return True

    def reload(self, layers=(), name=None):
        self.loadMapfile(self.mapfile, layers, name)

    def loadMapfile(self, mapfile, layers=(), name=None):
        message = ''
        self.mapfile = mapfile
        self.layers = layers
        if self.mapfile == "":
            return False

        # open mapfile
        self.maprenderer = MapfileRenderer(str(self.mapfile))
        message = self.maprenderer.load_mapfile()
        self.messageTextEdit.append(message)
        mapobj = self.maprenderer.getMapObj()
        if mapobj is None:
            return False

        if name is None:
            self.setLayerName(mapobj.name)
        else:
            self.setLayerName(name)

        # get projection as EPSG
        crs = QgsCoordinateReferenceSystem()
        crs.createFromProj4(self.maprenderer.getProj())
        if not crs.isValid():
            crs.validate()

        srs = "EPSG:%d" % crs.epsg()

        # always use default format for now
        self.maprenderer.setup(self.layers, srs)

        # set projection
        self.setCrs(crs)

        # TODO: set extents
        #    extents = self.maprenderer.getExtents()
        #    self.setExtent(QgsRectangle(extents[0], extents[1], extents[2], extents[3]))

        if self.pixmap == None:
            self.pixmap = QPixmap()

        # trigger repaint
        self.setCacheImage(None)
        self.emit(SIGNAL("repaintRequested()"))
        return True

    def openMapfile(self):
        mapfile = QFileDialog.getOpenFileName(
            None, "Mapfile", ".",
            "MapServer map files (*.map);;All files (*.*)",
            "Filter list for selecting files from a dialog box")
        if mapfile != "":
            return self.loadMapfile(str(mapfile), ())
        return False

    def showProperties(self):
        return False  # Not supported for now - see http://hub.qgis.org/issues/1

        # create and show the dialog
        dlg = MapfileLayerDialog()

        # show the dialog
        dlg.ui.leMapfile.setText(self.mapfile)
        dlg.updateInfo()
        dlg.show()

        # See if OK was pressed
        if dlg.exec_() == 1:
            mapfile = dlg.ui.leMapfile.text()

            # selected layers
            items = dlg.ui.listLayers.selectedItems()
            layerlist = []
            for item in items:
                layerlist.append(str(item.text()))
            layers = string.join(layerlist, ",")

            self.loadMapfile(mapfile, layers)
            return True

        return False