Example #1
0
class MapTool(QgsMapTool):
    geometry_changed = pyqtSignal(QgsGeometry, bool)
    tool_deactivated = pyqtSignal()

    def __init__(self, canvas, cursorstyle=Qt.CrossCursor):
        self.canvas = canvas
        QgsMapTool.__init__(self, canvas)
        self.caller = self.sender()
        self.cursorStyle = cursorstyle
        self.active = False
        # get selection color
        selcolor = self.canvas.selectionColor()
        mycolor = QColor(selcolor.red(), selcolor.green(), selcolor.blue(), 40)
        self.rb = QgsRubberBand(self.canvas)
        self.rb.setStrokeColor(QColor(255, 0, 0, 40))
        self.rb.setFillColor(mycolor)
        self.rb.setLineStyle(Qt.PenStyle(Qt.SolidLine))
        self.rb.setWidth(2)

    def setCursorStyle(self):
        cursor = QCursor()
        cursor.setShape(self.cursorStyle)
        self.setCursor(cursor)

    def activate(self):
        self.caller.setChecked(True)
        self.setCursorStyle()

    def deactivate(self):
        self.canvas.scene().removeItem(self.rb)
        self.tool_deactivated.emit()
        self.caller.setChecked(False)
        QgsMapTool.deactivate(self)

    def setGeometry(self, geo):
        self.rb.setToGeometry(geo)

    def canvasReleaseEvent(self, mouseEvent):
        if mouseEvent.button() == Qt.LeftButton:
            if not self.active:
                self.active = True
                self.geometry_changed.emit(QgsGeometry(), False)
                self.rb.reset(QgsWkbTypes.LineGeometry)
            self.rb.addPoint(mouseEvent.mapPoint())
            if self.rb.numberOfVertices() > 1:
                self.geometry_changed.emit(self.rb.asGeometry(), False)
        elif mouseEvent.button() == Qt.RightButton:
            if self.rb.numberOfVertices() > 2:
                self.active = False
                self.rb.removeLastPoint()
                geo = self.rb.asGeometry()
                self.geometry_changed.emit(geo, True)
            else:
                self.rb.reset(QgsWkbTypes.LineGeometry)

    def canvasMoveEvent(self, mouseEvent):
        if self.rb.numberOfVertices() > 1 and self.active:
            self.rb.removeLastPoint()
            self.rb.addPoint(mouseEvent.mapPoint())
        pass
Example #2
0
    def highlight():
      rb = QgsRubberBand( self.canvas, QGis.Polygon)
      rb.setBorderColor( QColor( 255,  0, 0 ) )
      rb.setWidth( 2 )
      rb.setToGeometry( geomRB, None )

      return rb
    def drawTileGrid(self, tile_min, tile_max, z):
        canvas = iface.mapCanvas()
        epsg = canvas.mapSettings().destinationCrs().authid()
        crsSrc = QgsCoordinateReferenceSystem(epsg)
        crsDest = QgsCoordinateReferenceSystem(4326)  # WGS 84 / UTM zone 33N
        xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance())

        for x in range(tile_min.x, tile_max.x):
            for y in range(tile_min.y, tile_max.y):
                p1 = ul(x, y, z)
                p2 = ul(x + 1, y + 1, z)

                t1 = xform.transform(QgsPointXY(p1.lng, p1.lat),
                                     QgsCoordinateTransform.ReverseTransform)
                t2 = xform.transform(QgsPointXY(p2.lng, p2.lat),
                                     QgsCoordinateTransform.ReverseTransform)

                print(f"polyline {t1} {t2}")

                polyline = QgsRubberBand(canvas)
                points = [
                    QgsPoint(t1.x(), t1.y()),
                    QgsPoint(t2.x(), t1.y()),
                    QgsPoint(t2.x(), t2.y()),
                    QgsPoint(t1.x(), t2.y())
                ]
                polyline.setToGeometry(QgsGeometry.fromPolyline(points), None)
                polyline.setColor(QColor(255, 255, 0))
                polyline.setWidth(2)
	def loadLines(self, lines, points, markers, suffix):
		no = self.project.readEntry("TUVIEW", "lines{0}no".format(suffix))[0]
		if no:
			no = int(no)
			for i in range(no):
				a = self.project.readEntry("TUVIEW", 'lines{0}x{1}'.format(suffix, i))[0]
				a = a.split('~~')
				b = self.project.readEntry("TUVIEW", 'lines{0}y{1}'.format(suffix, i))[0]
				b = b.split('~~')
				points.clear()
				for j in range(len(a)):
					x = float(a[j])
					y = float(b[j])
					point = QgsPoint(x, y)
					points.append(point)
					if i + 1 == no:
						marker = QgsVertexMarker(self.tuView.canvas)
						if suffix == 'cs':
							marker.setColor(Qt.red)
							marker.setIconSize(10)
							marker.setIconType(QgsVertexMarker.ICON_BOX)
						else:  # 'q'
							marker.setColor(Qt.blue)
							marker.setIconSize(12)
							marker.setIconType(QgsVertexMarker.ICON_DOUBLE_TRIANGLE)
						marker.setCenter(QgsPointXY(point))
						markers.append(marker)
				line = QgsRubberBand(self.tuView.canvas, False)
				line.setWidth(2)
				if suffix == 'cs':
					line.setColor(QColor(Qt.red))
				else:  # 'q'
					line.setColor(QColor(Qt.blue))
				line.setToGeometry(QgsGeometry.fromPolyline(points), None)
				lines.append(line)
Example #5
0
    def _draw_rubberband(self, geometry, colour, width):
        """Draw a rubber band on the canvas.

        .. versionadded: 2.2.0

        :param geometry: Extent that the rubber band should be drawn for.
        :type geometry: QgsGeometry

        :param colour: Colour for the rubber band.
        :type colour: QColor

        :param width: The width for the rubber band pen stroke.
        :type width: int

        :returns: Rubber band that should be set to the extent.
        :rtype: QgsRubberBand
        """
        # noinspection PyArgumentList
        rubber_band = QgsRubberBand(self._map_canvas,
                                    geometryType=QGis.Polygon)
        rubber_band.setBrushStyle(Qt.NoBrush)
        rubber_band.setColor(colour)
        rubber_band.setWidth(width)
        rubber_band.setToGeometry(geometry, None)
        return rubber_band
    def zoomAndShowWKT(self, wtk):
        geom = QgsGeometry.fromWkt(wtk)
        canvas = self.iface.mapCanvas() 
        self.clear()

        r = QgsRubberBand(canvas, geom.type() == 3 )
        r.setToGeometry(geom, None)
        r.setColor(QColor(0, 0, 255))
        r.setFillColor(QColor(0, 0, 255, 50))
        r.setWidth(3)

        pt = geom.pointOnSurface().asPoint()
        m = QgsVertexMarker(canvas)
        m.setCenter( pt )
        m.setColor(QColor(0, 0, 255))
        m.setIconSize(5)
        m.setIconType(QgsVertexMarker.ICON_BOX)  
        m.setPenWidth(3)

        if geom.type() == 3 or geom.type() == 2:
           rec = geom.boundingBox()
           canvas.setExtent(rec)
        else:
           self.moveMapTo( pt[0], pt[1], 0)

        self.graphics.append(r) 
        self.graphics.append(m) 
        self._refresh_layers()
Example #7
0
    def _draw_rubberband(self, geometry, colour, width):
        """Draw a rubber band on the canvas.

        .. versionadded: 2.2.0

        :param geometry: Extent that the rubber band should be drawn for.
        :type geometry: QgsGeometry

        :param colour: Colour for the rubber band.
        :type colour: QColor

        :param width: The width for the rubber band pen stroke.
        :type width: int

        :returns: Rubber band that should be set to the extent.
        :rtype: QgsRubberBand
        """
        # noinspection PyArgumentList
        rubber_band = QgsRubberBand(
            self._map_canvas, geometryType=QGis.Polygon)
        rubber_band.setBrushStyle(Qt.NoBrush)
        rubber_band.setColor(colour)
        rubber_band.setWidth(width)
        rubber_band.setToGeometry(geometry, None)
        return rubber_band
class MapTool(QgsMapTool):
    geometry_changed = pyqtSignal(QgsGeometry,bool)
    tool_deactivated =  pyqtSignal()

    def __init__(self, canvas, cursorstyle = Qt.CrossCursor):
        self.canvas = canvas
        QgsMapTool.__init__(self, canvas)
        self.caller = self.sender()
        self.cursorStyle=cursorstyle
        self.active = False
        self.center=None
        # get selection color
        selcolor =self.canvas.selectionColor()
        mycolor = QColor(selcolor.red(), selcolor.green(), selcolor.blue(), 40)
        self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry)
        self.rb.setStrokeColor(QColor(255, 0, 0, 40))
        self.rb.setFillColor(mycolor)
        self.rb.setLineStyle(Qt.PenStyle(Qt.SolidLine))
        self.rb.setWidth(2)

    def setCursorStyle(self):
        cursor = QCursor()
        cursor.setShape(self.cursorStyle)
        self.setCursor(cursor)

    def activate(self):
        self.caller.setChecked(True)
        self.setCursorStyle()

    def deactivate(self):
        self.canvas.scene().removeItem(self.rb)
        self.tool_deactivated.emit()
        self.caller.setChecked(False)
        QgsMapTool.deactivate(self)

    def setGeometry(self,geo):
        self.rb.setToGeometry(geo)

    def canvasReleaseEvent(self, mouseevent):
        if mouseevent.button() == Qt.LeftButton:
            self.active = False
            self.geometry_changed.emit(self.rb.asGeometry(),True)
        pass

    def canvasMoveEvent(self, mouseEvent):
        if self.active:
            cp = self.toMapCoordinates(mouseEvent.pos())
            rec = QgsRectangle(self.center, cp)
            self.rb.setToGeometry(QgsGeometry.fromRect(rec))
            self.geometry_changed.emit(self.rb.asGeometry(),True)
        pass

    def canvasPressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.active = True
            self.center = self.toMapCoordinates(e.pos())
            self.geometry_changed.emit(QgsGeometry(),False)
            self.rb.reset()
        pass
 def addGraphic(self, geom):
     canvas = self.iface.mapCanvas()
     rBand = QgsRubberBand(canvas, True)
     self.graphics.append(rBand)
     rBand.setToGeometry(geom, None)
     rBand.setColor(QColor(0, 0, 255, 70))
     rBand.setStrokeColor(QColor(0, 0, 250, 220))
     rBand.setWidth(3)
 def addGraphic(self, geom ):
     canvas = self.iface.mapCanvas()      
     rBand = QgsRubberBand(canvas, True) 
     self.graphics.append( rBand )
     rBand.setToGeometry( geom, None )
     rBand.setColor(QtGui.QColor(0,0,255, 70))
     if QGis.QGIS_VERSION_INT >= 20600:
         rBand.setBorderColor( QtGui.QColor(0,0,250, 220) )
     rBand.setWidth(3)
Example #11
0
 def build_rubber_band(self, points):
     rubber_band = QgsRubberBand(self.canvas(), False)  # False = not a polygon
     rubber_band.setToGeometry(QgsGeometry.fromPolyline(points), None)
     # for point in points:
     #     rubber_band.addPoint(point)
     rubber_band.setColor(QColor(255, 128, 128))
     rubber_band.setWidth(1)
     rubber_band.setBrushStyle(Qt.Dense4Pattern)
     return rubber_band
 def addGraphic(self, geom):
     canvas = self.iface.mapCanvas()
     rBand = QgsRubberBand(canvas, True)
     self.graphics.append(rBand)
     rBand.setToGeometry(geom, None)
     rBand.setColor(QtGui.QColor(0, 0, 255, 70))
     if QGis.QGIS_VERSION_INT >= 20600:
         rBand.setBorderColor(QtGui.QColor(0, 0, 250, 220))
     rBand.setWidth(3)
Example #13
0
 def _setRubberBandMarker(self, geom):
     m = QgsRubberBand(self.qgisIface.mapCanvas(), False)  # not polygon
     if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry:
         linegeom = geom
     elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PolygonGeometry:
         linegeom = QgsGeometry.fromPolylineXY(geom.asPolygon()[0])
     m.setToGeometry(linegeom, None)
     m.setColor(QColor(self.config['rubber_color']))
     m.setWidth(self.config['rubber_width'])
     return m
    def onClickedHighlight(self):
        def removeRB():
            rb.reset(True)
            self.qgisCanvas.scene().removeItem(rb)

        rb = QgsRubberBand(self.qgisCanvas, QGis.Polygon)
        rb.setBorderColor(QColor(255, 0, 0))
        rb.setWidth(2)
        rb.setToGeometry(QgsGeometry.fromRect(self.canvas.extent()), None)
        QTimer.singleShot(2000, removeRB)
Example #15
0
 def _setRubberBandMarker(self, geom):
     m = QgsRubberBand(self.qgisIface.mapCanvas(), False)  # not polygon
     if QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.LineGeometry:
         linegeom = geom
     elif QgsWkbTypes.geometryType(geom.wkbType()) == QgsWkbTypes.PolygonGeometry:
         linegeom = QgsGeometry.fromPolylineXY(geom.asPolygon()[0])
     m.setToGeometry(linegeom, None)
     m.setColor(QColor(self.config['rubber_color']))
     m.setWidth(self.config['rubber_width'])
     return m
Example #16
0
    def _highlight(self, canvas, extent):
        def removeRB():
            rb.reset(True)
            canvas.scene().removeItem(rb)

        rb = QgsRubberBand(canvas, QGis.Polygon)
        rb.setBorderColor(QColor(255, 0, 0))
        rb.setWidth(2)
        rb.setToGeometry(QgsGeometry.fromRect(extent), None)
        QTimer.singleShot(2000, removeRB)
 def onClickedHighlight(self):
   def removeRB():
     rb.reset( True )
     self.qgisCanvas.scene().removeItem( rb )
   
   rb = QgsRubberBand( self.qgisCanvas, QGis.Polygon)
   rb.setBorderColor( QColor( 255,  0, 0 ) )
   rb.setWidth( 2 )
   rb.setToGeometry( QgsGeometry.fromRect( self.canvas.extent() ), None )
   QTimer.singleShot( 2000, removeRB )
Example #18
0
class CurrentSelection(QgsRubberBand):
    """
    Position marker for the current location in the viewer.
    """

    class AniObject(QObject):
        def __init__(self, band):
            super(CurrentSelection.AniObject, self).__init__()
            self.color = QColor()

        @pyqtProperty(int)
        def alpha(self):
            return self.color.alpha()

        @alpha.setter
        def alpha(self, value):
            self.color.setAlpha(value)

    def __init__(self, canvas):
        super(CurrentSelection, self).__init__(canvas)
        self.outline = QgsRubberBand(canvas)
        self.outline.setBrushStyle(Qt.NoBrush)
        self.outline.setWidth(5)
        self.outline.setIconSize(30)
        self.aniobject = CurrentSelection.AniObject(self)
        self.anim = QPropertyAnimation(self.aniobject, "alpha")
        self.anim.setDuration(500)
        self.anim.setStartValue(50)
        self.anim.setEndValue(100)
        self.anim.valueChanged.connect(self.value_changed)

    def setOutlineColour(self, color):
        self.outline.setColor(color)

    def setToGeometry(self, geom, layer):
        super(CurrentSelection, self).setToGeometry(geom, layer)
        self.outline.setToGeometry(geom, layer)
        self.anim.stop()
        self.anim.start()

    def reset(self, geomtype=QGis.Line):
        super(CurrentSelection, self).reset(geomtype)
        self.outline.reset(geomtype)
        self.anim.stop()

    def value_changed(self, value):
        self.setColor(self.aniobject.color)
        self.update()

    def setColor(self, color):
        self.aniobject.color = color
        super(CurrentSelection, self).setColor(color)
Example #19
0
class CurrentSelection(QgsRubberBand):
    """
    Position marker for the current location in the viewer.
    """

    class AniObject(QObject):
        def __init__(self, band):
            super(CurrentSelection.AniObject, self).__init__()
            self.color = QColor()

        @pyqtProperty(int)
        def alpha(self):
            return self.color.alpha()

        @alpha.setter
        def alpha(self, value):
            self.color.setAlpha(value)

    def __init__(self, canvas):
        super(CurrentSelection, self).__init__(canvas)
        self.outline = QgsRubberBand(canvas)
        self.outline.setBrushStyle(Qt.NoBrush)
        self.outline.setWidth(5)
        self.outline.setIconSize(30)
        self.aniobject = CurrentSelection.AniObject(self)
        self.anim = QPropertyAnimation(self.aniobject, "alpha")
        self.anim.setDuration(500)
        self.anim.setStartValue(50)
        self.anim.setEndValue(100)
        self.anim.valueChanged.connect(self.value_changed)

    def setOutlineColour(self, color):
        self.outline.setColor(color)

    def setToGeometry(self, geom, layer):
        super(CurrentSelection, self).setToGeometry(geom, layer)
        self.outline.setToGeometry(geom, layer)
        self.anim.stop()
        self.anim.start()

    def reset(self, geomtype=QGis.Line):
        super(CurrentSelection, self).reset(geomtype)
        self.outline.reset(geomtype)
        self.anim.stop()

    def value_changed(self, value):
        self.setColor(self.aniobject.color)
        self.update()

    def setColor(self, color):
        self.aniobject.color = color
        super(CurrentSelection, self).setColor(color)
Example #20
0
class MapTool(QgsMapToolIdentify):
    geometry_changed = pyqtSignal(QgsGeometry, bool)
    tool_deactivated = pyqtSignal()

    def __init__(self, canvas, cursorstyle=Qt.CrossCursor):
        self.canvas = canvas
        QgsMapTool.__init__(self, canvas)
        self.caller = self.sender()
        self.cursorStyle = cursorstyle
        self.active = False
        # get selection color
        selcolor = self.canvas.selectionColor()
        mycolor = QColor(selcolor.red(), selcolor.green(), selcolor.blue(), 40)
        self.rb = QgsRubberBand(self.canvas)
        self.rb.setStrokeColor(QColor(255, 0, 0, 40))
        self.rb.setFillColor(mycolor)
        self.rb.setLineStyle(Qt.PenStyle(Qt.SolidLine))
        self.rb.setWidth(2)
        self.center = None
        self.cercle = 120  #circle of 30 segments

    def setCursorStyle(self):
        cursor = QCursor()
        cursor.setShape(self.cursorStyle)
        self.setCursor(cursor)

    def activate(self):
        self.caller.setChecked(True)
        self.setCursorStyle()

    def deactivate(self):
        self.canvas.scene().removeItem(self.rb)
        self.tool_deactivated.emit()
        self.caller.setChecked(False)
        QgsMapTool.deactivate(self)

    def setGeometry(self, geo):
        self.rb.setToGeometry(geo)

    def canvasReleaseEvent(self, mouseEvent):
        self.geometry_changed.emit(QgsGeometry(), False)
        if mouseEvent.button() == Qt.LeftButton:
            results = self.identify(mouseEvent.x(), mouseEvent.y(),
                                    self.ActiveLayer, self.VectorLayer)
            for res in results:
                if res.mFeature and res.mLayer:
                    geo = res.mFeature.geometry()
                    self.rb.setToGeometry(geo)
                    self.geometry_changed.emit(geo, True)
                    break
        pass
    def update_map(self, north, east, south, west):
        """
        This updates the map to add the new bounding box
        specified by the north, east, south, west parameters.
        :param north: The name of the north point
        :param east: The name of the east point
        :param south: The name of the south point
        :param west: The name of the west point
        :return:
        """

        from qgis.utils import iface
        from qgis.PyQt.QtCore import Qt

        # Creates map canvas within the widget in the window
        canvas = QgsMapCanvas(self.dlg.QgsMapCanvas_wid)
        canvas.setMinimumSize(460, 250)

        # Gets the basemap from the server and displays only that layer
        canvas_layer_list = [self.raster, self.raster]
        canvas.setLayers(canvas_layer_list)

        # Sets the coordinate reference system
        crsDest = QgsCoordinateReferenceSystem(4326)  # destination
        crsSrc = canvas.mapSettings().destinationCrs()  # source
        xform = QgsCoordinateTransform()
        xform.setSourceCrs(crsSrc)
        xform.setDestinationCrs(crsDest)
        canvas.setDestinationCrs(crsDest)

        # Creating the rubber band rectangle
        r = QgsRubberBand(canvas, True)  # True = a polygon
        # Sepcifying the points of rectangle
        points = [[
            QgsPointXY(west, north),
            QgsPointXY(east, north),
            QgsPointXY(east, south),
            QgsPointXY(west, south)
        ]]
        r.setToGeometry(QgsGeometry.fromPolygonXY(points), None)
        r.setFillColor(QColor(255, 0, 0, 50))  #R,G,B,Transparency
        r.setWidth(3)
        canvas.zoomWithCenter(north - south, east - west, True)
        canvas.setExtent(self.raster.extent())
        canvas.zoomToFullExtent()
        canvas.zoomScale(2000000000)  # scaling for tmp raster
        #canvas.zoomWithCenter(north-south,east-west,True)
        canvas.show()
Example #22
0
    def azimuth(self):
        punto1 = self.dlg.lineEdit1.text()
        punto2 = self.dlg.lineEdit2.text()

        if (punto1 == "" or punto2 == ""):
            QMessageBox.information(self.iface.mainWindow(), "Error",
                                    "Without coordinates")
        else:
            x1 = float(punto1.split(",")[0])
            y1 = float(punto1.split(",")[1])
            x2 = float(punto2.split(",")[0])
            y2 = float(punto2.split(",")[1])

            # create points objects
            p1 = QgsPoint(x1, y1)
            p2 = QgsPoint(x2, y2)
            az = round(p1.azimuth(p2), 2)
            if (az < 0):
                self.dlg.lineEditAzimuth.setText(
                    str(az) + "  (" + str(360 + az) + ")")
            else:
                self.dlg.lineEditAzimuth.setText(str(az))
            # calculate distance
            points = [p1, p2]
            line = QgsGeometry.fromPolyline(points)
            d = QgsDistanceArea()
            crs = QgsProject.instance().crs()  # asigna el crs del proyecto
            # comprobar si es dd (6)
            if (crs.mapUnits() == 6):
                # es dd
                d.setEllipsoid('WGS84')
                m = round(d.measureLength(line), 4)
            else:  # projectada
                m = round(d.measureLength(line), 4)
            self.dlg.lineEditDistance.setText(str(m))
            self.iface.actionPan().trigger()  # vuelve el cursor al pan

            #Drawing Polyline
            polyline = QgsRubberBand(self.canvas,
                                     False)  # False = not a polygon

            points = [QgsPoint(x1, y1), QgsPoint(x2, y2)]
            polyline.setToGeometry(QgsGeometry.fromPolyline(points), None)
            polyline.setColor(QColor(255, 0, 0))
            polyline.setWidth(3)
            """
Example #23
0
class selectExtentMapTool(QgsMapTool):
    def __init__(self, parentObj):
        self.parentObj = parentObj
        self.iface = parentObj.iface
        QgsMapTool.__init__(self, self.iface.mapCanvas())
        self.contextShape = QgsRubberBand(self.iface.mapCanvas(),
                                          QgsWkbTypes.LineGeometry)
        self.contextShape.setWidth(1)
        self.contextShape.setColor(QtCore.Qt.red)
        self.pressed = False

    def canvasPressEvent(self, event):
        self.pressed = True
        self.pressx = event.pos().x()
        self.pressy = event.pos().y()
        self.movex = event.pos().x()
        self.movey = event.pos().y()
        self.PressedPoint = self.iface.mapCanvas().getCoordinateTransform(
        ).toMapCoordinates(self.pressx, self.pressy)

    def canvasMoveEvent(self, event):
        if self.pressed:
            x = event.pos().x()
            y = event.pos().y()
            movedPoint = self.iface.mapCanvas().getCoordinateTransform(
            ).toMapCoordinates(x, y)
            self.contextShape.reset()
            self.contextgeom = QgsGeometry.fromRect(
                QgsRectangle(self.PressedPoint, movedPoint)).convertToType(
                    QgsWkbTypes.LineGeometry)
            self.contextShape.setToGeometry(self.contextgeom)

    def canvasReleaseEvent(self, event):
        if self.pressed:
            x = event.pos().x()
            y = event.pos().y()
            releasedPoint = self.iface.mapCanvas().getCoordinateTransform(
            ).toMapCoordinates(x, y)
            self.pressed = False
            self.parentObj.selectedExtent = QgsRectangle(
                self.PressedPoint, releasedPoint)
            self.parentObj.iface.mapCanvas().setMapTool(None)

    def reset(self):
        self.contextShape.reset()
Example #24
0
    def add_rubberband_borehole(self, boreholeno):
        """ Warning - this method fails silently on error """
        self.remove_canvas_vertexmarkers()

        # Add new rubberband
        points = [[
            QgsPoint(6640629.039, 6087146.608),
            QgsPoint(640629.039, 6087146.608),
            QgsPoint(640629.039, 6087146.608),
            QgsPoint(6640629.039, 6087146.608)
        ]]  # lower left, upper right
        r = QgsRubberBand(iface.mapCanvas, True)  # True = a polygon
        r.setColor(QColor(0, 255, 0, 255))
        r.setWidth(3)
        r.setToGeometry(QgsGeometry.fromPolygon(points), None)

        JupiterAux.log_info(
            u'rubberband added for borehole {}'.format(boreholeno))
Example #25
0
 def create(self, canvas, line_width=2, rbs_in="main_dialog"):
     """Create the tile as a rubber band inside the canvas given"""
     rubber_band = QgsRubberBand(canvas)
     points = [QgsPointXY(self.xmin, self.ymax), QgsPointXY(self.xmax, self.ymax),
               QgsPointXY(self.xmax, self.ymin), QgsPointXY(self.xmin, self.ymin)]
     rubber_band.setToGeometry(QgsGeometry.fromPolygonXY([points]), None)
     if rbs_in == "highlight":
         rubber_band.setColor(QColor("yellow"))
     else:
         rubber_band.setColor(self.tile_color)
     rubber_band.setFillColor(QColor(0, 0, 0, 0))
     rubber_band.setWidth(line_width)
     rubber_band.show()
     if rbs_in == "main_dialog":
         self.rbs_in_main_dialog.append(rubber_band)
     if rbs_in == "nav_dialog":
         self.rbs_in_nav_dialog.append(rubber_band)
     if rbs_in == "highlight":
         return rubber_band
class ShowStreetCoordinates:
    """
    Creates temp geoms to show the start and end coordinates of a street
    """
    def __init__(self, iface):
        self.canvas = iface.mapCanvas()
        self.rb_line = QgsRubberBand(self.canvas, QGis.Line)
        self.rb_start = QgsVertexMarker(self.canvas)
        self.rb_end = QgsVertexMarker(self.canvas)
        self.style()

    def style(self):
        # Style start marker
        self.rb_start.setColor(QColor('blue'))
        self.rb_start.setIconSize(16)
        self.rb_start.setPenWidth(4)
        # Style end marker
        self.rb_end.setColor(QColor('red'))
        self.rb_end.setIconSize(16)
        self.rb_end.setPenWidth(4)
        # Style line
        self.rb_line.setColor(QColor('grey'))
        self.rb_line.setWidth(3)

    def show(self, coords):
        # Breakdown coords
        start = coords[0]
        end = coords[1]
        # Create start and end points
        start_point = QgsPoint(float(start[0]), float(start[1]))
        self.rb_start.setCenter(start_point)
        end_point = QgsPoint(float(end[0]), float(end[1]))
        self.rb_end.setCenter(end_point)
        # Create line
        line_pts = [start_point, end_point]
        line_geom = QgsGeometry().fromPolyline(line_pts)
        self.rb_line.setToGeometry(line_geom, None)

    def remove(self):
        self.canvas.scene().removeItem(self.rb_start)
        self.canvas.scene().removeItem(self.rb_end)
        self.canvas.scene().removeItem(self.rb_line)
Example #27
0
 def showSectionsInOverview(self):
     # clear existing rubberbands
     for rb in self.sectionsRbs:
         self.iface.mapCanvas().scene().removeItem(rb)
     self.sectionsRbs = []
     # add new rubberbands
     for id, sec in enumerate(self.WSMProj.sections):
         rb = QgsRubberBand(self.iface.mapCanvas(), False)
         rb_geom = QgsGeometry()
         rb_geom.fromWkb(sec.aoi)
         rb.setToGeometry(rb_geom, None)
         if id == self.currbox.value():
             fc = QtGui.QColor(self.colors[-1])
         else:
             fc = QtGui.QColor(self.colors[min(sec.status, 1)])
         rb.setColor(fc)
         fc.setAlpha(128)
         rb.setFillColor(fc)
         rb.setWidth(1)
         self.sectionsRbs.append(rb)
Example #28
0
class GeometryDisplayer:

    def __init__(self, canvas ):
        self.canvas = canvas
        # main rubber
        self.rubber1 = QgsRubberBand(self.canvas)
        self.rubber1.setWidth(2)
        self.rubber1.setBorderColor(QColor("#f00"))
        self.rubber1.setFillColor(QColor("#ff6969"))
        # old geometry rubber
        self.rubber2 = QgsRubberBand(self.canvas)
        self.rubber2.setWidth(2)
        self.rubber2.setBorderColor(QColor("#bbb"))
        self.rubber2.setFillColor(QColor("#ccc"))

    def reset(self):
        self.rubber1.reset()
        self.rubber2.reset()

    def display(self, geom1, geom2 = None):
        """
        @param geom1 base geometry (old geometry for an update)
        @param geom2 new geometry for an update
        """
        if geom2 is None:
            bbox = geom1.boundingBox()
            self.rubber1.setToGeometry(geom1, None)
        else:
            bbox = geom1.boundingBox()
            bbox.combineExtentWith(geom2.boundingBox())
            self.rubber1.setToGeometry(geom2, None)
            self.rubber2.setToGeometry(geom1, None)
        bbox.scale(1.5)
        self.canvas.setExtent(bbox)        
    def identify_all(self, complet_list, rb_list):

        self.rubber_band.reset()
        for rb in rb_list:
            rb.reset()
        for layer in complet_list['body']['data']['layersNames']:
            for feature in layer['ids']:
                points = []
                list_coord = re.search('\((.*)\)', str(feature['geometry']))
                coords = list_coord.group(1)
                polygon = coords.split(',')
                for i in range(0, len(polygon)):
                    x, y = polygon[i].split(' ')
                    point = QgsPointXY(float(x), float(y))
                    points.append(point)
                rb = QgsRubberBand(self.canvas)
                polyline = QgsGeometry.fromPolylineXY(points)
                rb.setToGeometry(polyline, None)
                rb.setColor(QColor(255, 0, 0, 100))
                rb.setWidth(5)
                rb.show()
                rb_list.append(rb)
Example #30
0
    def highlight(self,geometry):
        def processEvents():
            try:
                QtGui.qApp.processEvents()
            except:
                QtWidgets.QApplication.processEvents()

        highlight = QgsRubberBand(self.iface.mapCanvas(), geometry.type())
        highlight.setColor(QtGui.QColor("#36AF6C"))
        highlight.setFillColor(QtGui.QColor("#36AF6C"))
        highlight.setWidth(2)
        highlight.setToGeometry(geometry,self.iface.mapCanvas().currentLayer())
        processEvents()
        sleep(.1)
        highlight.hide()
        processEvents()
        sleep(.1)
        highlight.show()
        processEvents()
        sleep(.1)
        highlight.reset()
        processEvents()
 def highlight(self,geometry):
     def processEvents():
         try:
             qApp.processEvents()
         except:
             QApplication.processEvents()
             
     highlight = QgsRubberBand(self.canvas, geometry.type())
     highlight.setColor(QColor("#36AF6C"))
     highlight.setFillColor(QColor("#36AF6C"))
     highlight.setWidth(2)
     highlight.setToGeometry(geometry,self.canvas.currentLayer())
     processEvents()
     sleep(.1)
     highlight.hide()
     processEvents()
     sleep(.1)
     highlight.show()
     processEvents()
     sleep(.1)
     highlight.reset()
     processEvents()
Example #32
0
 def loadLines(self, lines, points, markers, suffix):
     no = self.project.readEntry("TUVIEW", "lines{0}no".format(suffix))[0]
     if no:
         no = int(no)
         for i in range(no):
             a = self.project.readEntry("TUVIEW",
                                        'lines{0}x{1}'.format(suffix, i))[0]
             a = a.split('~~')
             b = self.project.readEntry("TUVIEW",
                                        'lines{0}y{1}'.format(suffix, i))[0]
             b = b.split('~~')
             points.clear()
             for j in range(len(a)):
                 x = float(a[j])
                 y = float(b[j])
                 point = QgsPoint(x, y)
                 points.append(point)
                 if i + 1 == no:
                     marker = QgsVertexMarker(self.tuView.canvas)
                     if suffix == 'cs':
                         marker.setColor(Qt.red)
                         marker.setIconSize(10)
                         marker.setIconType(QgsVertexMarker.ICON_BOX)
                     else:  # 'q'
                         marker.setColor(Qt.blue)
                         marker.setIconSize(12)
                         marker.setIconType(
                             QgsVertexMarker.ICON_DOUBLE_TRIANGLE)
                     marker.setCenter(QgsPointXY(point))
                     markers.append(marker)
             line = QgsRubberBand(self.tuView.canvas, False)
             line.setWidth(2)
             if suffix == 'cs':
                 line.setColor(QColor(Qt.red))
             else:  # 'q'
                 line.setColor(QColor(Qt.blue))
             line.setToGeometry(QgsGeometry.fromPolyline(points), None)
             lines.append(line)
Example #33
0
class DistanceDialog(QDialog, Ui_place_distance):
    def __init__(self, distance, canvas):
        QDialog.__init__(self)
        self.setupUi(self)
        self.settings = MySettings()

        # this is a reference, distance observation is modified in outer class
        self.distance = distance

        self.rubber = QgsRubberBand(canvas)
        self.rubber.setColor(self.settings.value("rubberColor"))
        self.rubber.setIconSize(self.settings.value("rubberSize"))

        self.x.setText("%.3f" % distance.point.x())
        self.y.setText("%.3f" % distance.point.y())
        self.observation.setValue(distance.observation)
        self.precision.setValue(distance.precision)
        self.observation.selectAll()

    @pyqtSignature("on_observation_valueChanged(double)")
    def on_observation_valueChanged(self, v):
        self.distance.observation = v
        self.rubber.setToGeometry(self.distance.geometry(), None)

    @pyqtSignature("on_precision_valueChanged(double)")
    def on_precision_valueChanged(self, v):
        self.distance.precision = v

    def accept(self):
        self.rubber.reset()
        QDialog.accept(self)

    def reject(self):
        self.rubber.reset()
        QDialog.reject(self)

    def closeEvent(self, e):
        self.rubber.reset()
Example #34
0
class DistanceDialog(QDialog, Ui_place_distance):
    def __init__(self, distance, canvas):
        QDialog.__init__(self)
        self.setupUi(self)
        self.settings = MySettings()

        # this is a reference, distance observation is modified in outer class
        self.distance = distance

        self.rubber = QgsRubberBand(canvas)
        self.rubber.setColor(self.settings.value("rubberColor"))
        self.rubber.setIconSize(self.settings.value("rubberSize"))

        self.x.setText("%.3f" % distance.point.x())
        self.y.setText("%.3f" % distance.point.y())
        self.observation.setValue(distance.observation)
        self.precision.setValue(distance.precision)
        self.observation.selectAll()

    @pyqtSignature("on_observation_valueChanged(double)")
    def on_observation_valueChanged(self, v):
        self.distance.observation = v
        self.rubber.setToGeometry(self.distance.geometry(), None)

    @pyqtSignature("on_precision_valueChanged(double)")
    def on_precision_valueChanged(self, v):
        self.distance.precision = v

    def accept(self):
        self.rubber.reset()
        QDialog.accept(self)

    def reject(self):
        self.rubber.reset()
        QDialog.reject(self)

    def closeEvent(self, e):
        self.rubber.reset()
Example #35
0
    def visible_aoi(self):
        # first clean all rubber bands
        [rubber_band.reset() for rubber_band in self.rubber_bands]
        [rubber_band.reset() for rubber_band in self.tmp_rubber_bands]
        self.rubber_bands = []
        self.tmp_rubber_bands = []

        if self.VisibleAOI.isChecked() and self.aoi_features is not None:
            for feat in self.aoi_features.getFeatures():
                color = QColor("red")
                color.setAlpha(70)
                rubber_band = QgsRubberBand(self.canvas,
                                            QgsWkbTypes.PolygonGeometry)
                rubber_band.setToGeometry(feat.geometry())
                rubber_band.setColor(color)
                rubber_band.setWidth(3)
                self.rubber_bands.append(rubber_band)
                tmp_rubber_band = QgsRubberBand(self.canvas,
                                                QgsWkbTypes.PolygonGeometry)
                tmp_rubber_band.setToGeometry(feat.geometry())
                tmp_rubber_band.setColor(color)
                tmp_rubber_band.setWidth(3)
                tmp_rubber_band.setLineStyle(Qt.DotLine)
                self.tmp_rubber_bands.append(tmp_rubber_band)
Example #36
0
class ConnectTool(QgsMapToolEmitPoint):
    """ Map tool to conect points """
    
    line_complete = pyqtSignal(QgsPoint, QgsPoint)
    start_point = None
    end_point = None
    rubberband = None
    
    def __init__(self, canvas):
        self.canvas = canvas
        QgsMapToolEmitPoint.__init__(self, canvas)
    
    def canvasMoveEvent(self, event):
        if self.start_point:
            point = self.toMapCoordinates(event.pos())
            if self.rubberband:
                self.rubberband.reset()
            else:
                self.rubberband = QgsRubberBand(self.canvas, False)
                self.rubberband.setColor(QColor(Qt.red))
            # set the geometry for the rubberband
            point = [self.start_point, point]
            self.rubberband.setToGeometry(QgsGeometry.fromPolyline(points), None)
    
    def canvasPressEvent(self, e):
        if self.end_point is None: 
            self.start_point = self.toMapCoordinates(e.pos())
        else:
            self.end_point = self.toMapCoordinates(e.pos())
            # kill the rubberband
            self.rubberband.reset()
            # line is done, emit a signal
            self.line_complete.emit(self.start_point, self.end_point)
            # reset the points
            self.start_point = None
            self.end_point = None
Example #37
0
class lineTool(QgsMapTool):
    def __init__(self, iface, callback):
        QgsMapTool.__init__(self,iface.mapCanvas())
        self.iface  = iface
        self.canvas = iface.mapCanvas()
        self.cursor = QCursor(Qt.CrossCursor)
        self.callback   = callback
        
        self.rubberBand = QgsRubberBand(self.canvas, False)
        self.points  = []
        self.rubberBand.setColor(Qt.red)
        self.rubberBand.setWidth(1.6)

    def canvasReleaseEvent(self,event):
        if event.button() == Qt.RightButton:
          self.points.append(QgsPoint( self.toMapCoordinates( event.pos()) ) )
          if len(self.points) <= 1 :return
        
          self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None )
          self.callback( self.rubberBand )
          QgsMapTool.deactivate(self)
        else:
          self.points.append(QgsPoint( self.toMapCoordinates(event.pos()) ) )
          if len(self.points) <= 1 : return
          self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None )

    def canvasDoubleClickEvent(self,event):
        self.points.append(QgsPoint( self.toMapCoordinates( event.pos()) ))
        if len(self.points) <= 1 : return
      
        self.rubberBand.setToGeometry( QgsGeometry.fromPolyline(self.points), None )
        self.callback( self.rubberBand )
        QgsMapTool.deactivate(self)
    
    def activate(self):
      QgsMapTool.activate(self)
      self.canvas.setCursor(self.cursor)

    def isZoomTool(self):
        return False

    def setCursor(self,cursor):
        self.cursor = QCursor(cursor)
Example #38
0
class GeometryDisplayer:
    def __init__(self, canvas):
        self.canvas = canvas

        # main rubber
        self.rubber1 = QgsRubberBand(self.canvas)
        self.rubber1.setWidth(2)
        self.rubber1.setStrokeColor(self.newGeometryColor())
        self.rubber1.setFillColor(self.newGeometryColor())

        # old geometry rubber
        self.rubber2 = QgsRubberBand(self.canvas)
        self.rubber2.setWidth(2)
        self.rubber2.setStrokeColor(self.oldGeometryColor())
        self.rubber2.setFillColor(self.oldGeometryColor())

    def reset(self):
        self.rubber1.reset()
        self.rubber2.reset()

    def oldGeometryColor(self):
        return QColor("#ff5733")

    def newGeometryColor(self):
        return QColor("#00f")

    def display(self, geom1, geom2=None):
        """
        @param geom1 base geometry (old geometry for an update)
        @param geom2 new geometry for an update
        """
        if geom2 is None:
            bbox = geom1.boundingBox()
            self.rubber1.setToGeometry(geom1, None)
        else:
            bbox = geom1.boundingBox()
            bbox.combineExtentWith(geom2.boundingBox())
            self.rubber1.setToGeometry(geom2, None)
            self.rubber2.setToGeometry(geom1, None)
        bbox.scale(1.5)
        self.canvas.setExtent(bbox)
class nominatim_dlg(QDockWidget, Ui_search):

    def getHttp(self, uri, params):
        QgsApplication.setOverrideCursor(Qt.WaitCursor)
        try:
            rq = QUrl(uri)
            q = QUrlQuery()
            for (k, v) in params.items():
                q.addQueryItem(k, v)

            rq.setQuery(q)
            req = QNetworkRequest(rq)

            try:
                reply = self.nominatim_networkAccessManager.blockingGet(req)
                resource = reply.content().data().decode('utf8')
                r = json.loads(resource)

                if (isinstance(r, list)):
                    self.populateTable(r)
                else:
                    self.populateTable([r])
            except:
                self.tableResult.clearContents()

        finally:
            QgsApplication.restoreOverrideCursor()

    def searchJson(self, params, user, options, options2):
        contents = str(options).strip()
        items = contents.split(' ')

        for (k, v) in options2.items():
            if k in ['viewbox']:
                params["bounded"] = "1"
            params[k] = v

        pairs = []
        for item in items:
            pair = item.split('=', 1)
            if (pair != [''] and pair != [] and len(pair) > 1):
                pairs.append(pair)

        for (k, v) in pairs:
            if k in ['viewbox', 'countrycodes', 'limit', 'exclude_place_ids', 'addressdetails',
                     'exclude_place_ids', 'bounded', 'routewidth',
                     'osm_type', 'osm_id'] and not(k in options2.keys()):
                params[k] = v

            if k in ['viewbox']:
                params["bounded"] = "1"

        params["polygon_text"] = "1"
        params["format"] = "json"

        uri = 'https://nominatim.openstreetmap.org/search'

        self.getHttp(uri, params)

    def findNearbyJSON(self, params, user, options):
        uri = "https://nominatim.openstreetmap.org/reverse"
        params["format"] = "json"
        self.getHttp(uri, params)

    """
     Gestion de l'évènement "leave", afin d'effacer l'objet sélectionné en sortie du dock
    """
    def eventFilter(self, obj, event):
        typ = event.type()
        if typ == event.Leave:
            try:
                self.plugin.canvas.scene().removeItem(self.rubber)
            except:
                pass

        return False

    def __init__(self, parent, plugin):
        self.plugin = plugin
        QDockWidget.__init__(self, parent)
        self.setupUi(self)

        self.btnApply.setIcon(QIcon(":plugins/nominatim/arrow_green.png"))
        self.btnMask.setIcon(QIcon(":plugins/nominatim/add_mask.png"))
        self.btnLayer.setIcon(QIcon(":plugins/nominatim/add_layer.png"))

        self.tableResult.installEventFilter(self)  # cf. eventFilter method
        self.tableResult.cellDoubleClicked.connect(self.onChoose)
        self.tableResult.cellEntered.connect(self.cellEntered)

        self.editSearch.returnPressed.connect(self.onReturnPressed)
        self.btnSearch.clicked.connect(self.onReturnPressed)
        self.btnApply.clicked.connect(self.onApply)
        self.btnHelp.clicked.connect(self.plugin.do_help)
        self.btnLocalize.clicked.connect(self.doLocalize)
        self.btnMask.clicked.connect(self.onMask)
        self.btnLayer.clicked.connect(self.onLayer)

        self.MultiPolygonLayerId = None
        self.LineLayerId = None
        self.PointLayerId = None

        try:
            self.cbExtent.setChecked(self.plugin.limitSearchToExtent)
        except:
            self.cbExtent.setChecked(self.plugin.limitSearchToExtent)

        self.currentExtent = self.plugin.canvas.extent()

        self.tableResult.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

        try:
            self.editSearch.setText(self.plugin.lastSearch)
        except:
            pass

        try:
            if self.plugin.localiseOnStartup:
                self.doLocalize()
        except Exception as e:
            for m in e.args:
                QgsMessageLog.logMessage(m, 'Extensions')
            pass

        self.nominatim_networkAccessManager = QgsNetworkAccessManager.instance()

    def cellEntered(self, row, col):
        item = self.tableResult.item(row, 0)

        try:
            self.plugin.canvas.scene().removeItem(self.rubber)
            self.showItem(item)
        except:
            pass

    def onLayer(self):
        for r in self.tableResult.selectedRanges():
            item = self.tableResult.item(r.topRow(), 0)
            self.doLayer(item)

    def onMask(self):
        for r in self.tableResult.selectedRanges():
            item = self.tableResult.item(r.topRow(), 0)
            self.doMask(item)

    def populateRow(self, item, idx):
        id = item['place_id']
        name = item['display_name']

        try:
            className = QApplication.translate("nominatim", item['class'], None)
        except:
            className = ""

        try:
            typeName = QApplication.translate("nominatim", item['type'], None)
        except:
            typeName = ""

        try:
            wkt = item['geotext']
        except:
            wkt = None

        try:
            osm_type = item['osm_type']
        except:
            osm_type = None

        bbox = {}
        if osm_type == "node":
            lat = item['lat']
            lng = item['lon']

            poFD = ogr.FeatureDefn("Point")
            poFD.SetGeomType(ogr.wkbPoint)

            oFLD = ogr.FieldDefn('id', ogr.OFTString)
            poFD.AddFieldDefn(oFLD)
            oFLD = ogr.FieldDefn('name', ogr.OFTString)
            poFD.AddFieldDefn(oFLD)

            ogrFeature = ogr.Feature(poFD)
            wkt = "POINT("+str(lng)+" "+str(lat)+")"
            ogrGeom = ogr.CreateGeometryFromWkt(wkt)
        else:
            try:
                bbox = item['boundingbox']

                poFD = ogr.FeatureDefn("Rectangle")
                poFD.SetGeomType(ogr.wkbPolygon)

                oFLD = ogr.FieldDefn('id', ogr.OFTString)
                poFD.AddFieldDefn(oFLD)
                oFLD = ogr.FieldDefn('name', ogr.OFTString)
                poFD.AddFieldDefn(oFLD)

                ogrFeature = ogr.Feature(poFD)
                if wkt is None:
                    wkt = "POLYGON(("+str(bbox[2])+" "+str(bbox[0])+", "+str(bbox[2])+" " +\
                          str(bbox[1])+", "+str(bbox[3])+" "+str(bbox[1])+", "+str(bbox[3])+" " +\
                          str(bbox[0])+", "+str(bbox[2])+" "+str(bbox[0])+"))"

                ogrGeom = ogr.CreateGeometryFromWkt(wkt)
            except:
                lat = item['lat']
                lng = item['lon']

                poFD = ogr.FeatureDefn("Point")
                poFD.SetGeomType(ogr.wkbPoint)

                oFLD = ogr.FieldDefn('id', ogr.OFTString)
                poFD.AddFieldDefn(oFLD)
                oFLD = ogr.FieldDefn('name', ogr.OFTString)
                poFD.AddFieldDefn(oFLD)

                ogrFeature = ogr.Feature(poFD)
                wkt = "POINT("+str(lng)+" "+str(lat)+")"
                ogrGeom = ogr.CreateGeometryFromWkt(wkt)

        mapCrsWKT = self.plugin.canvas.mapSettings().destinationCrs().toWkt()

        sourceSRS = osr.SpatialReference()
        sourceSRS.ImportFromEPSG(4326)
        targetSRS = osr.SpatialReference()
        targetSRS.ImportFromWkt(str(mapCrsWKT))
        trsf = osr.CoordinateTransformation(sourceSRS, targetSRS)
        try:
            ogrGeom.Transform(trsf)
        except TypeError as e:
            QgsMessageLog.logMessage("Nominatim - transformation error. Check map projection.",
                                     "Extensions")

        ogrFeature.SetGeometry(ogrGeom)
        ogrFeature.SetFID(int(idx+1))
        ogrFeature.SetField(str('id'), str(id))
        ogrFeature.SetField(str('name'), name)

        item = QTableWidgetItem(name)
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        item.setData(Qt.UserRole, ogrFeature)
        self.tableResult.setItem(idx, 0, item)

        itemLibelle = QTableWidgetItem(className)
        itemLibelle.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableResult.setItem(idx, 1, itemLibelle)

        itemType = QTableWidgetItem(typeName)
        itemType.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableResult.setItem(idx, 2, itemType)

    def populateTable(self, r):
        idx = 0
        self.tableResult.clearContents()
        self.tableResult.setRowCount(len(r))
        for item in r:
            self.populateRow(item, idx)
            idx = idx+1

    def doLocalize(self):
        try:
            # center
            bbox = self.plugin.canvas.extent()
            sourceCrs = self.plugin.canvas.mapSettings().destinationCrs()
            targetCrs = QgsCoordinateReferenceSystem()
            targetCrs.createFromSrid(4326)
            xform = QgsCoordinateTransform(sourceCrs, targetCrs, QgsProject.instance())
            bbox = xform.transform(bbox)

            params = {"lon": str(bbox.center().x()), "lat": str(bbox.center().y()), "zoom": "10"}
            self.findNearbyJSON(params, self.plugin.gnUsername, self.plugin.gnOptions)

        except Exception as e:
            for m in e.args:
                QgsMessageLog.logMessage(m, 'Extensions')
            pass

    def onReturnPressed(self):
        try:
            txt = self.editSearch.text().strip()
            self.plugin.lastSearch = self.editSearch.text()
            self.plugin.limitSearchToExtent = (self.cbExtent.isChecked())
            options = self.plugin.gnOptions

            options2 = {}
            if self.plugin.limitSearchToExtent:
                sourceCrs = self.plugin.canvas.mapSettings().destinationCrs()
                targetCrs = QgsCoordinateReferenceSystem()
                targetCrs.createFromSrid(4326)
                xform = QgsCoordinateTransform(sourceCrs, targetCrs, QgsProject.instance())
                geom = xform.transform(self.plugin.canvas.extent())
                options2 = {'viewbox': str(geom.xMinimum()) + ',' +
                            str(geom.yMaximum()) + ',' +
                            str(geom.xMaximum()) + ',' +
                            str(geom.yMinimum())}

            params = {'q': txt, 'addressdetails': '0'}
            self.searchJson(params, self.plugin.gnUsername, options, options2)

        except Exception as e:
            for m in e.args:
                QgsMessageLog.logMessage(m, 'Extensions')
            pass

    def onChoose(self, row, col):
        item = self.tableResult.item(row, 0)
        self.go(item)

    def onApply(self):
        for item in self.tableResult.selectedItems():
            self.go(item)
            break

    def getBBox(self, item):
        ogrFeature = item.data(Qt.UserRole)
        geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())

        if (ogrFeature.GetDefnRef().GetGeomType() == ogr.wkbPoint):
            mapextent = self.plugin.canvas.extent()
            ww = mapextent.width()/100
            mapcrs = self.plugin.canvas.mapSettings().destinationCrs()

            x = geom.boundingBox().center().x()
            y = geom.boundingBox().center().y()

            ww = 50.0
            if mapcrs.mapUnits() == QgsUnitTypes.DistanceFeet:
                ww = 150
            if mapcrs.mapUnits() == QgsUnitTypes.DistanceDegrees:
                ww = 0.0005

            bbox = QgsRectangle(x-10*ww, y-10*ww, x+10*ww, y+10*ww)
            return bbox
        else:
            bbox = geom.boundingBox()
            rubberRect = QgsRectangle(bbox.xMinimum(), bbox.yMinimum(),
                                      bbox.xMaximum(), bbox.yMaximum())
            return rubberRect

    def showItem(self, item):
        ogrFeature = item.data(Qt.UserRole)
        geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())

        if (ogrFeature.GetDefnRef().GetGeomType() == ogr.wkbPoint):
            self.rubber = QgsRubberBand(self.plugin.canvas, QgsWkbTypes.PointGeometry)
            self.rubber.setColor(QColor(50, 50, 255, 100))
            self.rubber.setIcon(self.rubber.ICON_CIRCLE)
            self.rubber.setIconSize(15)
            self.rubber.setWidth(2)
            self.rubber.setToGeometry(geom, None)
        else:
            # dont show if it is larger than the canvas
            if self.plugin.canvas.extent().contains(geom.boundingBox()):
                pass
            else:
                geom = geom.intersection(QgsGeometry.fromRect(self.plugin.canvas.extent()))

            self.rubber = QgsRubberBand(self.plugin.canvas, QgsWkbTypes.PolygonGeometry)
            self.rubber.setColor(QColor(50, 50, 255, 100))
            self.rubber.setWidth(4)
            self.rubber.setToGeometry(geom, None)

    def go(self, item, zoom=True):
        try:
            self.plugin.canvas.scene().removeItem(self.rubber)
        except:
            pass

        if zoom:
            bbox = self.getBBox(item)
            self.plugin.canvas.setExtent(bbox)

        self.plugin.canvas.refresh()
        self.showItem(item)

    def doMask(self, item):
        mapcrs = self.plugin.canvas.mapSettings().destinationCrs()

        ogrFeature = item.data(Qt.UserRole)
        layerName = "OSM "+ogrFeature.GetFieldAsString('id')
        geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())
        if (geom.type() == QgsWkbTypes.PolygonGeometry):
            try:
                try:
                    from mask import aeag_mask
                except:
                    from mask_plugin import aeag_mask

                aeag_mask.do(mapcrs, {geom}, "Mask "+layerName)

            except:
                geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())
                toCrs = self.plugin.canvas.mapSettings().destinationCrs()

                l = max(geom.boundingBox().width(), geom.boundingBox().height())
                x = geom.boundingBox().center().x()
                y = geom.boundingBox().center().y()
                rect = QgsRectangle(x-l, y-l, x+l, y+l)  # geom.boundingBox()
                rect.scale(4)
                mask = QgsGeometry.fromRect(rect)

                mask = mask.difference(geom)

                maskLayer = QgsVectorLayer("MultiPolygon", "Mask "+layerName, "memory")
                maskLayer.setCrs(toCrs)
                QgsProject.instance().addMapLayer(maskLayer)
                pr = maskLayer.dataProvider()

                fields = QgsFields()
                fields.append(QgsField("id", QVariant.String))
                fields.append(QgsField("name",  QVariant.String))
                fet = QgsFeature()
                fet.initAttributes(2)
                fet.setGeometry(mask)
                fet.setFields(fields)
                fet.setAttribute("id", (ogrFeature.GetFieldAsString('id')))
                fet.setAttribute("name", (ogrFeature.GetFieldAsString('name')))

                pr.addAttributes(fields.toList())

                maskLayer.startEditing()
                pr.addFeatures([fet])
                maskLayer.commitChanges()
                maskLayer.updateExtents()

                # transparence, epaisseur
                renderer = maskLayer.renderer()
                s = renderer.symbol()
                s.setOpacity(0.90)
                s.setColor(QColor(255, 255, 255))
                if isinstance(s, QgsLineSymbol):
                    s.setWidth(0)

                layerTree = QgsProject.instance().layerTreeRoot().findLayer(maskLayer)
                if layerTree:
                    self.plugin.iface.layerTreeView().layerTreeModel()\
                        .refreshLayerLegend(layerTree)  # Refresh legend

            self.go(item)

    def doLayer(self, item):
        ogrFeature = item.data(Qt.UserRole)
        geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())

        fields = QgsFields()
        fields.append(QgsField("id", QVariant.String))
        fields.append(QgsField("name",  QVariant.String))
        fet = QgsFeature()
        fet.initAttributes(2)
        fet.setFields(fields)
        fet.setGeometry(geom)
        fet.setAttribute("id", (ogrFeature.GetFieldAsString('id')))
        fet.setAttribute("name", (ogrFeature.GetFieldAsString('name')))

        vl = None
        if not self.plugin.singleLayer:
            if geom.type() == QgsWkbTypes.PolygonGeometry:
                layerName = "OSMPlaceSearch Polygon"
                layerId = self.MultiPolygonLayerId
            if geom.type() == QgsWkbTypes.LineGeometry:
                layerName = "OSMPlaceSearch Line"
                layerId = self.LineLayerId
            if geom.type() == QgsWkbTypes.PointGeometry:
                layerName = "OSMPlaceSearch Point"
                layerId = self.PointLayerId

            vl = QgsProject.instance().mapLayer(layerId)
            if vl is not None:
                pr = vl.dataProvider()
            else:
                if geom.type() == QgsWkbTypes.PolygonGeometry:
                    vl = QgsVectorLayer("MultiPolygon", layerName, "memory")
                    self.MultiPolygonLayerId = vl.id()
                if geom.type() == QgsWkbTypes.LineGeometry:
                    vl = QgsVectorLayer("MultiLineString", layerName, "memory")
                    self.LineLayerId = vl.id()
                if geom.type() == QgsWkbTypes.PointGeometry:
                    vl = QgsVectorLayer("Point", layerName, "memory")
                    self.PointLayerId = vl.id()

                if vl is not None:
                    pr = vl.dataProvider()
                    # ajout de champs
                    pr.addAttributes(fields.toList())

                QgsProject.instance().addMapLayer(vl)
        else:
            layerName = "OSM "+ogrFeature.GetFieldAsString('id')

            # creer une nouvelle couche si n'existe pas encore
            if geom.type() == QgsWkbTypes.PolygonGeometry:
                vl = QgsVectorLayer("MultiPolygon", layerName, "memory")
            if geom.type() == QgsWkbTypes.LineGeometry:
                vl = QgsVectorLayer("MultiLineString", layerName, "memory")
            if geom.type() == QgsWkbTypes.PointGeometry:
                vl = QgsVectorLayer("Point", layerName, "memory")

            if vl is not None:
                pr = vl.dataProvider()
                # ajout de champs
                pr.addAttributes(fields.toList())

            QgsProject.instance().addMapLayer(vl)

        if vl is not None:
            vl.setProviderEncoding('UTF-8')
            vl.startEditing()
            pr.addFeatures([fet])
            vl.commitChanges()

            # mise a jour etendue de la couche
            vl.updateExtents()

            layerTree = QgsProject.instance().layerTreeRoot().findLayer(vl)
            if layerTree:
                self.plugin.iface.layerTreeView()\
                    .layerTreeModel().refreshLayerLegend(layerTree)  # Refresh legend

            self.go(item, False)
Example #40
0
class MoveTool(QgsMapToolAdvancedDigitizing):
    """
    Map tool class to move or copy an object
    """

    def __init__(self, iface):
        """
        Constructor
        :param iface: interface
        """
        QgsMapToolAdvancedDigitizing.__init__(self,  iface.mapCanvas(), iface.cadDockWidget())
        self.__iface = iface
        self.icon_path = ':/plugins/VDLTools/icons/move_icon.png'
        self.text = QCoreApplication.translate("VDLTools", "Move/Copy a feature")
        self.setCursor(Qt.ArrowCursor)
        self.__isEditing = False
        self.__findVertex = False
        self.__onMove = False
        self.__layer = None
        self.__confDlg = None
        self.__lastFeatureId = None
        self.__selectedFeature = None
        self.__rubberBand = None
        self.__rubberSnap = None
        self.__newFeature = None
        self.__selectedVertex = None

    def activate(self):
        """
        When the action is selected
        """
        QgsMapToolAdvancedDigitizing.activate(self)
        if self.__layer.geometryType() == QGis.Point:
            self.setMode(self.CaptureLine)
        else:
            self.setMode(self.CaptureNone)

    def deactivate(self):
        """
        When the action is deselected
        """
        self.__cancel()
        QgsMapToolAdvancedDigitizing.deactivate(self)

    def toolName(self):
        """
        To get the tool name
        :return: tool name
        """
        return QCoreApplication.translate("VDLTools", "Move/Copy")

    def startEditing(self):
        """
        To set the action as enable, as the layer is editable
        """
        self.action().setEnabled(True)
        Signal.safelyDisconnect(self.__layer.editingStarted, self.startEditing)
        self.__layer.editingStopped.connect(self.stopEditing)

    def stopEditing(self):
        """
        To set the action as disable, as the layer is not editable
        """
        self.action().setEnabled(False)
        Signal.safelyDisconnect(self.__layer.editingStopped, self.stopEditing)
        self.__layer.editingStarted.connect(self.startEditing)
        if self.canvas().mapTool() == self:
            self.__iface.actionPan().trigger()

    def setTool(self):
        """
        To set the current tool as this one
        """
        self.canvas().setMapTool(self)

    def __cancel(self):
        """
        To cancel used variables
        """
        if self.__rubberBand is not None:
            self.canvas().scene().removeItem(self.__rubberBand)
            self.__rubberBand.reset()
            self.__rubberBand = None
        if self.__rubberSnap is not None:
            self.canvas().scene().removeItem(self.__rubberSnap)
            self.__rubberSnap.reset()
            self.__rubberSnap = None
        self.__isEditing = False
        self.__findVertex = False
        self.__onMove = False
        self.__lastFeatureId = None
        self.__selectedFeature = None
        self.__confDlg = None
        self.__newFeature = None
        self.__selectedVertex = None
        self.__layer.removeSelection()
        if self.__layer.geometryType() == QGis.Point:
            self.setMode(self.CaptureLine)
        else:
            self.setMode(self.CaptureNone)

    def __removeLayer(self):
        """
        To remove the current working layer
        """
        if self.__layer is not None:
            if self.__layer.isEditable():
                Signal.safelyDisconnect(self.__layer.editingStopped, self.stopEditing)
            else:
                Signal.safelyDisconnect(self.__layer.editingStarted, self.startEditing)
            self.__layer = None

    def setEnable(self, layer):
        """
        To check if we can enable the action for the selected layer
        :param layer: selected layer
        """
        if layer is not None and layer.type() == QgsMapLayer.VectorLayer:
            if layer == self.__layer:
                return

            if self.__layer is not None:
                if self.__layer.isEditable():
                    Signal.safelyDisconnect(self.__layer.editingStopped, self.stopEditing)
                else:
                    Signal.safelyDisconnect(self.__layer.editingStarted, self.startEditing)
            self.__layer = layer

            if self.__layer.geometryType() == QGis.Point:
                self.setMode(self.CaptureLine)
            else:
                self.setMode(self.CaptureNone)

            if self.__layer.isEditable():
                self.action().setEnabled(True)
                self.__layer.editingStopped.connect(self.stopEditing)
            else:
                self.action().setEnabled(False)
                self.__layer.editingStarted.connect(self.startEditing)
                if self.canvas().mapTool() == self:
                    self.__iface.actionPan().trigger()
            return
        self.action().setEnabled(False)
        if self.canvas().mapTool() == self:
            self.__iface.actionPan().trigger()
        self.__removeLayer()

    def __pointPreview(self, point):
        """
        To create a point geometry preview (rubberBand)
        :param point: new position as mapPoint
        """
        point_v2 = GeometryV2.asPointV2(self.__selectedFeature.geometry(), self.__iface)
        self.__newFeature = QgsPointV2(point.x(), point.y())
        self.__newFeature.addZValue(point_v2.z())
        self.__rubberBand = QgsRubberBand(self.canvas(), QGis.Point)
        self.__rubberBand.setToGeometry(QgsGeometry(self.__newFeature.clone()), None)

    def __linePreview(self, point):
        """
        To create a line geometry preview (rubberBand)
        :param point: new position as mapPoint
        """
        line_v2, curved = GeometryV2.asLineV2(self.__selectedFeature.geometry(), self.__iface)
        vertex = QgsPointV2()
        line_v2.pointAt(self.__selectedVertex, vertex)
        self.__rubberBand = QgsRubberBand(self.canvas(), QGis.Line)
        dx = vertex.x() - point.x()
        dy = vertex.y() - point.y()
        if isinstance(curved, (list, tuple)):
            self.__newFeature = QgsCompoundCurveV2()
            for pos in range(line_v2.nCurves()):
                curve_v2 = self.__newCurve(curved[pos], line_v2.curveAt(pos), dx, dy)
                self.__newFeature.addCurve(curve_v2)
                if pos == 0:
                    self.__rubberBand.setToGeometry(QgsGeometry(curve_v2.curveToLine()), None)
                else:
                    self.__rubberBand.addGeometry(QgsGeometry(curve_v2.curveToLine()), None)
        else:
            self.__newFeature = self.__newCurve(curved, line_v2, dx, dy)
            self.__rubberBand.setToGeometry(QgsGeometry(self.__newFeature.curveToLine()), None)

    @staticmethod
    def __newCurve(curved, line_v2, dx, dy):
        """
        To create a new moved line
        :param curved: if the line is curved
        :param line_v2: the original line
        :param dx: x translation
        :param dy: y translation
        :return: the new line
        """
        if curved:
            newCurve = QgsCircularStringV2()
        else:
            newCurve = QgsLineStringV2()
        points = []
        for pos in range(line_v2.numPoints()):
            x = line_v2.pointN(pos).x() - dx
            y = line_v2.pointN(pos).y() - dy
            pt = QgsPointV2(x, y)
            pt.addZValue(line_v2.pointN(pos).z())
            points.append(pt)
        newCurve.setPoints(points)
        return newCurve

    def __polygonPreview(self, point):
        """
        To create a polygon geometry preview (rubberBand)
        :param point: new position as mapPoint
        """
        polygon_v2, curved = GeometryV2.asPolygonV2(self.__selectedFeature.geometry(), self.__iface)
        vertex = polygon_v2.vertexAt(GeometryV2.polygonVertexId(polygon_v2, self.__selectedVertex))
        dx = vertex.x() - point.x()
        dy = vertex.y() - point.y()
        self.__newFeature = QgsCurvePolygonV2()
        self.__rubberBand = QgsRubberBand(self.canvas(), QGis.Line)
        line_v2 = self.__newCurve(curved[0], polygon_v2.exteriorRing(), dx, dy)
        self.__newFeature.setExteriorRing(line_v2)
        self.__rubberBand.setToGeometry(QgsGeometry(line_v2.curveToLine()), None)
        for num in range(polygon_v2.numInteriorRings()):
            line_v2 = self.__newCurve(curved[num+1], polygon_v2.interiorRing(num), dx, dy)
            self.__newFeature.addInteriorRing(line_v2)
            self.__rubberBand.addGeometry(QgsGeometry(line_v2.curveToLine()), None)

    def __onConfirmCancel(self):
        """
        When the Cancel button in Move Confirm Dialog is pushed
        """
        self.__confDlg.reject()

    def __onConfirmMove(self):
        """
        When the Move button in Move Confirm Dialog is pushed
        """
        geometry = QgsGeometry(self.__newFeature)
        if not geometry.isGeosValid():
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Geos geometry problem"), level=QgsMessageBar.CRITICAL, duration=0)
        self.__layer.changeGeometry(self.__selectedFeature.id(), geometry)
        self.__confDlg.accept()
        self.__cancel()

    def __onConfirmCopy(self):
        """
        When the Copy button in Move Confirm Dialog is pushed
        """
        geometry = QgsGeometry(self.__newFeature)
        if not geometry.isGeosValid():
            self.__iface.messageBar().pushMessage(
                QCoreApplication.translate("VDLTools", "Geos geometry problem"), level=QgsMessageBar.CRITICAL, duration=0)
        feature = QgsFeature(self.__layer.pendingFields())
        feature.setGeometry(geometry)
        primaryKey = QgsDataSourceURI(self.__layer.source()).keyColumn()
        for field in self.__selectedFeature.fields():
            if field.name() != primaryKey:
                feature.setAttribute(field.name(), self.__selectedFeature.attribute(field.name()))
        if len(self.__selectedFeature.fields()) > 0 and self.__layer.editFormConfig().suppress() != \
                QgsEditFormConfig.SuppressOn:
            self.__iface.openFeatureForm(self.__layer, feature)
        else:
            self.__layer.addFeature(feature)
        self.__confDlg.accept()
        self.__cancel()

    def keyReleaseEvent(self, event):
        """
        When keyboard is pressed
        :param event: keyboard event
        """
        if event.key() == Qt.Key_Escape:
            self.__cancel()

    def cadCanvasMoveEvent(self, event):
        """
        When the mouse is moved
        :param event: mouse event
        """

        if type(event) == QMoveEvent:
            map_point = self.toMapCoordinates(event.pos())
        else:
            map_point = event.mapPoint()

        if not self.__isEditing and not self.__findVertex and not self.__onMove:
            laySettings = QgsSnappingUtils.LayerConfig(self.__layer, QgsPointLocator.All, 10,
                                                       QgsTolerance.Pixels)
            f_l = Finder.findClosestFeatureAt(map_point, self.canvas(), [laySettings])
            if f_l is not None and self.__lastFeatureId != f_l[0].id():
                self.__lastFeatureId = f_l[0].id()
                self.__layer.setSelectedFeatures([f_l[0].id()])
            if f_l is None:
                self.__layer.removeSelection()
                self.__lastFeatureId = None
        elif self.__findVertex:
            if self.__rubberBand is not None:
                self.__rubberBand.reset()
            closest = self.__selectedFeature.geometry().closestVertex(map_point)
            color = QColor("red")
            color.setAlphaF(0.78)
            self.__rubberBand.setColor(color)
            self.__rubberBand.setIcon(4)
            self.__rubberBand.setIconSize(20)
            self.__rubberBand.setToGeometry(QgsGeometry().fromPoint(closest[0]), None)
        elif self.__onMove:
            if self.__rubberBand is not None:
                self.__rubberBand.reset()
            if self.__layer.geometryType() == QGis.Polygon:
                self.__polygonPreview(map_point)
            elif self.__layer.geometryType() == QGis.Line:
                self.__linePreview(map_point)
            else:
                self.__pointPreview(map_point)
            color = QColor("red")
            color.setAlphaF(0.78)
            self.__rubberBand.setColor(color)
            self.__rubberBand.setWidth(2)
            if self.__layer.geometryType() != QGis.Point:
                self.__rubberBand.setLineStyle(Qt.DotLine)
            else:
                self.__rubberBand.setIcon(4)
                self.__rubberBand.setIconSize(8)
            if self.__rubberSnap is not None:
                self.__rubberSnap.reset()
            else:
                self.__rubberSnap = QgsRubberBand(self.canvas(), QGis.Point)
            self.__rubberSnap.setColor(color)
            self.__rubberSnap.setWidth(2)
            self.__rubberSnap.setIconSize(20)
            match = Finder.snap(map_point, self.canvas())
            if match.hasVertex() or match.hasEdge():
                point = match.point()
                if match.hasVertex():
                    if match.layer():
                        self.__rubberSnap.setIcon(4)
                    else:
                        self.__rubberSnap.setIcon(1)
                if match.hasEdge():
                    intersection = Finder.snapCurvedIntersections(point, self.canvas(), self)
                    if intersection is not None:
                        self.__rubberSnap.setIcon(1)
                        point = intersection
                    else:
                        self.__rubberSnap.setIcon(3)
                self.__rubberSnap.setToGeometry(QgsGeometry().fromPoint(point), None)

    def cadCanvasReleaseEvent(self, event):
        """
        When the mouse is clicked
        :param event: mouse event
        """
        if not self.__isEditing and not self.__findVertex and not self.__onMove:
            found_features = self.__layer.selectedFeatures()
            if len(found_features) > 0:
                if len(found_features) > 1:
                    self.__iface.messageBar().pushMessage(
                        QCoreApplication.translate("VDLTools", "One feature at a time"), level=QgsMessageBar.INFO)
                    return
                self.__selectedFeature = found_features[0]
                if self.__layer.geometryType() != QGis.Point:
                    self.__iface.messageBar().pushMessage(
                        QCoreApplication.translate("VDLTools",
                                                   "Select vertex for moving (ESC to undo)"),
                        level=QgsMessageBar.INFO, duration=3)
                    self.__findVertex = True
                    self.setMode(self.CaptureLine)
                    self.__rubberBand = QgsRubberBand(self.canvas(), QGis.Point)
                else:
                    self.setMode(self.CaptureNone)
                    self.__onMove = True
        elif self.__findVertex:
            self.__findVertex = False
            self.setMode(self.CaptureNone)
            closest = self.__selectedFeature.geometry().closestVertex(event.mapPoint())
            self.__selectedVertex = closest[1]
            self.__onMove = True
        elif self.__onMove:
            self.__onMove = False
            mapPoint = event.mapPoint()
            match = Finder.snap(event.mapPoint(), self.canvas())
            if match.hasVertex() or match.hasEdge():
                mapPoint = match.point()
                if match.hasEdge():
                    intersection = Finder.snapCurvedIntersections(mapPoint, self.canvas(), self)
                    if intersection is not None:
                        mapPoint = intersection
            self.__isEditing = True
            if self.__rubberBand is not None:
                self.__rubberBand.reset()
            if self.__layer.geometryType() == QGis.Polygon:
                self.__polygonPreview(mapPoint)
            elif self.__layer.geometryType() == QGis.Line:
                self.__linePreview(mapPoint)
            else:
                self.__pointPreview(mapPoint)
            color = QColor("red")
            color.setAlphaF(0.78)
            self.__rubberBand.setColor(color)
            if self.__layer.geometryType() != QGis.Point:
                self.__rubberBand.setWidth(2)
                self.__rubberBand.setLineStyle(Qt.DotLine)
            else:
                self.__rubberBand.setIcon(4)
                self.__rubberBand.setIconSize(20)
            self.__confDlg = MoveConfirmDialog()
            self.__confDlg.rejected.connect(self.__cancel)
            self.__confDlg.moveButton().clicked.connect(self.__onConfirmMove)
            self.__confDlg.copyButton().clicked.connect(self.__onConfirmCopy)
            self.__confDlg.cancelButton().clicked.connect(self.__onConfirmCancel)
            self.__confDlg.show()
Example #41
0
class QgepMapToolConnectNetworkElements(QgsMapTool):
    """
    This map tool connects wastewater networkelements.

    It works on two lists of layers:
      source layers with fields with a foreign key to a networkelement
      target layers which depict networkelements (reaches and network nodes)

    The tool will snap to source layers first and once one is chosen to a target layer.

    It will then ask which field(s) should be connected and perform the update on the database
    """

    def __init__(self, iface, action):
        QgsMapTool.__init__(self, iface.mapCanvas())
        self.iface = iface
        self.action = action

        self.rbline = QgsRubberBand(self.iface.mapCanvas(), QGis.Line)
        self.rbline.setColor(QColor('#f4530e'))
        self.rbline.setWidth(3)
        self.rbmarkers = QgsRubberBand(self.iface.mapCanvas(), QGis.Point)
        self.rbmarkers.setColor(QColor('#f4530e'))
        self.rbmarkers.setIconSize(6)

        self.source_snapper = QgepAreaSnapper(self.iface.mapCanvas())
        self.target_snapper = QgepAreaSnapper(self.iface.mapCanvas())

        self.source_feature = QgsFeature()
        self.rb_source_feature = QgsRubberBand(self.iface.mapCanvas())
        self.rb_source_feature.setColor(QColor('#f49e79'))
        self.rb_source_feature.setWidth(3)
        self.target_feature = QgsFeature()
        self.rb_target_feature = QgsRubberBand(self.iface.mapCanvas())
        self.rb_target_feature.setColor(QColor('#f49e79'))
        self.rb_target_feature.setWidth(3)

    def activate(self):
        """
        Called by QGIS whenever the tool is activated.
        """
        source_snap_layers = list()
        target_snap_layers = list()

        # A dict of layers and the fields that are foreign keys
        # pointing to wastewater networkelements
        self.network_element_sources = {
            QgepLayerManager.layer('vw_qgep_reach'): [
                ('rp_to_fk_wastewater_networkelement',
                 QCoreApplication.translate('QgepMapToolConnectNetworkElements', 'Reach Point To')),
                ('rp_from_fk_wastewater_networkelement',
                 QCoreApplication.translate('QgepMapToolConnectNetworkElements', 'Reach Point From'))
            ],
            QgepLayerManager.layer('od_catchment_area'): [
                ('fk_wastewater_networkelement_rw_current', QCoreApplication.translate(
                    'QgepMapToolConnectNetworkElements', 'Rainwater current')),
                ('fk_wastewater_networkelement_rw_planned', QCoreApplication.translate(
                    'QgepMapToolConnectNetworkElements', 'Rainwater planned')),
                ('fk_wastewater_networkelement_ww_current', QCoreApplication.translate(
                    'QgepMapToolConnectNetworkElements', 'Wastewater current')),
                ('fk_wastewater_networkelement_ww_planned', QCoreApplication.translate(
                    'QgepMapToolConnectNetworkElements', 'Wastewater planned'))
            ]
        }

        # A list of layers that can be used as wastewater networkelement
        # targets
        self.network_element_targets = [
            QgepLayerManager.layer('vw_wastewater_node'),
            QgepLayerManager.layer('vw_qgep_reach')
        ]

        for layer in self.network_element_sources.keys():
            if layer:
                snap_layer = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, 16, QgsTolerance.Pixels)
                source_snap_layers.append(snap_layer)

        for layer in self.network_element_targets:
            if layer:
                snap_layer = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, 16, QgsTolerance.Pixels)
                target_snap_layers.append(snap_layer)

        self.source_snapper.setLayers(source_snap_layers)
        self.source_snapper.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)

        self.target_snapper.setLayers(target_snap_layers)
        self.target_snapper.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)

        self.reset()

        self.action.setChecked(True)

        self.iface.mapCanvas().setCursor(QCursor(Qt.CrossCursor))

    def canvasMoveEvent(self, event):
        """
        When the mouse moves, update the rubberbands.
        """
        pt = event.originalMapPoint()
        snap_match = self.snapper.snapToMap(pt)

        if snap_match.isValid():
            if snap_match.type() != QgsPointLocator.Area:
                pt = snap_match.point()
            self.matchpoint = pt

            if self.source_match:
                if self.target_feature.id() != snap_match.featureId():
                    self.target_feature = self.get_feature_for_match(
                        snap_match)
                    self.rb_target_feature.setToGeometry(
                        self.target_feature.geometry(), snap_match.layer())
                self.rb_target_feature.show()
                self.rbmarkers.movePoint(pt)
            else:
                if self.source_feature.id() != snap_match.featureId():
                    self.source_feature = self.get_feature_for_match(
                        snap_match)
                    self.rb_source_feature.setToGeometry(
                        self.source_feature.geometry(), snap_match.layer())
                self.rb_source_feature.show()
                self.rbmarkers.movePoint(pt, 0)
            self.rbmarkers.show()
        else:
            self.rbmarkers.hide()
            if self.source_match:
                self.rb_target_feature.hide()
            else:
                self.rb_source_feature.hide()

        self.rbline.movePoint(pt)

        self.snapresult = snap_match

    def canvasReleaseEvent(self, event):
        """
        On a click update the rubberbands and the snapping results if it's a left click. Reset if it's a right click.
        """
        if event.button() == Qt.LeftButton:
            if self.snapresult.isValid():
                if self.source_match:
                    self.connect_features(self.source_match, self.snapresult)
                else:
                    self.rbline.show()
                    self.rbline.addPoint(self.matchpoint)
                    self.source_match = self.snapresult
                    self.snapper = self.target_snapper
        else:
            self.reset()

    def deactivate(self):
        """
        Called by QGIS whenever this tool is deactivated.
        """
        self.reset()
        self.action.setChecked(False)

    def reset(self):
        """
        Resets the tool to a pristine state
        """
        self.source_match = None
        self.rbline.hide()
        self.rbline.reset()
        self.rbmarkers.hide()
        self.rbmarkers.reset(QGis.Point)
        self.rbmarkers.addPoint(QgsPoint())
        self.snapresult = None
        self.source_match = None
        self.snapper = self.source_snapper
        self.source_feature = QgsFeature()
        self.target_feature = QgsFeature()
        self.rb_source_feature.reset()
        self.rb_target_feature.reset()

    def get_feature_for_match(self, match):
        """
        Get the feature for a snapping result
        @param match: The QgsPointLocator.SnapMatch object
        @return: A feature
        """
        return next(match.layer().getFeatures(QgsFeatureRequest().setFilterFid(match.featureId())))

    def connect_features(self, source, target):
        """
        Connects the source feature with the target feature.

        @param source: A QgsPointLocator.Match object. Its foreign key will be updated.
                       A dialog will be opened which asks the user for which foreign key(s) he wants to update.
        @param target: A QgsPointLocator.Match object. This feature will be used as link target.
                       Its obj_id attribute will be used as primary key.
        """
        dlg = QDialog(self.iface.mainWindow())
        dlg.setWindowTitle(self.tr('Select properties to connect'))
        dlg.setLayout(QFormLayout())

        properties = list()

        for prop in self.network_element_sources[source.layer()]:
            cbx = QCheckBox(prop[1])
            cbx.setObjectName(prop[0])
            properties.append(cbx)
            dlg.layout().addWidget(cbx)

        btn_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        dlg.layout().addWidget(btn_box)
        btn_box.accepted.connect(dlg.accept)
        btn_box.rejected.connect(dlg.reject)

        source_feature = self.get_feature_for_match(source)
        target_feature = self.get_feature_for_match(target)

        if dlg.exec_():
            for cbx in properties:
                if cbx.isChecked():
                    source_feature[cbx.objectName()] = target_feature['obj_id']
            if source.layer().updateFeature(source_feature):
                self.iface.messageBar().pushMessage('QGEP',
                                                    self.tr('Connected {} to {}').format(
                                                        source_feature[
                                                            'identifier'],
                                                        target_feature['identifier']),
                                                    QgsMessageBar.INFO, 5)
            else:
                self.iface.messageBar().pushMessage('QGEP',
                                                    self.tr(
                                                        'Error connecting features'),
                                                    QgsMessageBar.WARNING, 5)

        self.reset()
Example #42
0
class MainWindow(mainwindow_widget, mainwindow_base):
    """
    Main application window
    """

    def __init__(self, settings):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.settings = settings
        roam.featureform.settings = settings.settings
        self.canvaslayers = []
        self.layerbuttons = []
        self.project = None
        self.selectionbands = defaultdict(partial(QgsRubberBand, self.canvas))
        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.bar = roam.messagebaritems.MessageBar(self)

        self.actionMap.setVisible(False)

        pal = QgsPalLabeling()
        self.canvas.mapRenderer().setLabelingEngine(pal)
        self.canvas.setFrameStyle(QFrame.NoFrame)
        self.menuGroup = QActionGroup(self)
        self.menuGroup.setExclusive(True)

        self.menuGroup.addAction(self.actionMap)
        self.menuGroup.addAction(self.actionDataEntry)
        self.menuGroup.addAction(self.actionProject)
        self.menuGroup.addAction(self.actionSync)
        self.menuGroup.addAction(self.actionSettings)
        self.menuGroup.triggered.connect(self.updatePage)

        self.editgroup = QActionGroup(self)
        self.editgroup.setExclusive(True)
        self.editgroup.addAction(self.actionPan)
        self.editgroup.addAction(self.actionZoom_In)
        self.editgroup.addAction(self.actionZoom_Out)
        self.editgroup.addAction(self.actionInfo)

        #TODO Extract GPS out into a service and remove UI stuff
        self.actionGPS = GPSAction(":/icons/gps", self.canvas, self.settings, self)
        self.projecttoolbar.addAction(self.actionGPS)

        self.projectwidget = ProjectsWidget(self)
        self.projectwidget.requestOpenProject.connect(self.loadProject)
        QgsProject.instance().readProject.connect(self._readProject)
        self.project_page.layout().addWidget(self.projectwidget)

        self.syncwidget = SyncWidget()
        self.syncpage.layout().addWidget(self.syncwidget)

        self.settingswidget = SettingsWidget(settings, self)
        self.settings_page.layout().addWidget(self.settingswidget)
        self.actionSettings.toggled.connect(self.settingswidget.populateControls)
        self.actionSettings.toggled.connect(self.settingswidget.readSettings)
        self.settingswidget.settingsupdated.connect(self.settingsupdated)

        self.dataentrywidget = DataEntryWidget(self.canvas, self.bar)
        self.widgetpage.layout().addWidget(self.dataentrywidget)

        self.dataentrywidget.rejected.connect(self.formrejected)
        self.dataentrywidget.featuresaved.connect(self.featureSaved)
        self.dataentrywidget.featuredeleted.connect(self.featuredeleted)
        self.dataentrywidget.failedsave.connect(self.failSave)
        self.dataentrywidget.helprequest.connect(self.showhelp)
        self.dataentrywidget.openimage.connect(self.openimage)

        def createSpacer(width=0, height=0):
            widget = QWidget()
            widget.setMinimumWidth(width)
            widget.setMinimumHeight(height)
            return widget

        gpsspacewidget = createSpacer(30)
        sidespacewidget = createSpacer(30)
        sidespacewidget2 = createSpacer(height=20)

        sidespacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sidespacewidget2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.topspaceraction = self.projecttoolbar.insertWidget(self.actionGPS, gpsspacewidget)

        def createlabel(text):
            style = """
                QLabel {
                        color: #706565;
                        font: 14px "Calibri" ;
                        }"""
            label = QLabel(text)
            label.setStyleSheet(style)

            return label

        self.projectlabel = createlabel("Project: {project}")
        self.userlabel = createlabel("User: {user}".format(user=getpass.getuser()))
        self.positionlabel = createlabel('')
        self.statusbar.addWidget(self.projectlabel)
        self.statusbar.addWidget(self.userlabel)
        spacer = createSpacer()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.statusbar.addWidget(spacer)
        self.statusbar.addWidget(self.positionlabel)

        self.menutoolbar.insertWidget(self.actionQuit, sidespacewidget2)
        self.menutoolbar.insertWidget(self.actionProject, sidespacewidget)
        self.stackedWidget.currentChanged.connect(self.updateUIState)

        self.panels = []

        self.connectButtons()

        self.band = QgsRubberBand(self.canvas)
        self.band.setIconSize(20)
        self.band.setWidth(10)
        self.band.setColor(QColor(186, 93, 212, 76))

        self.canvas_page.layout().insertWidget(0, self.projecttoolbar)
        self.dataentrymodel = QStandardItemModel(self)
        self.dataentrycombo = QComboBox(self.projecttoolbar)
        self.dataentrycombo.setIconSize(QSize(48,48))
        self.dataentrycombo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        self.dataentrycombo.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.dataentrycombo.setModel(self.dataentrymodel)
        self.dataentrycomboaction = self.projecttoolbar.insertWidget(self.topspaceraction, self.dataentrycombo)

        self.dataentrycombo.showPopup = self.selectdataentry

        self.biglist = BigList(self.canvas)
        self.biglist.setlabel("Select data entry form")
        self.biglist.setmodel(self.dataentrymodel)
        self.biglist.itemselected.connect(self.dataentrychanged)
        self.biglist.hide()

        self.centralwidget.layout().addWidget(self.statusbar)

        self.actionGPSFeature.setProperty('dataentry', True)

        self.infodock = InfoDock(self.canvas)
        self.infodock.requestopenform.connect(self.openForm)
        self.infodock.featureupdated.connect(self.highlightfeature)
        self.infodock.resultscleared.connect(self.clearselection)
        self.infodock.openurl.connect(self.viewurl)
        self.infodock.hide()
        self.hidedataentry()
        self.canvas.extentsChanged.connect(self.updatestatuslabel)
        self.projecttoolbar.toolButtonStyleChanged.connect(self.updatecombo)

    def selectdataentry(self, ):
        if self.dataentrycombo.count() == 0:
            return

        self.biglist.show()

    def viewurl(self, url):
        """
        Open a URL in Roam
        :param url:
        :return:
        """
        key = url.toString().lstrip('file://')
        try:
            # Hack. Eww fix me.
            data, imagetype = roam.htmlviewer.images[os.path.basename(key)]
        except KeyError:
            # It's not a image so lets just pass it of as a normal
            # URL
            QDesktopServices.openUrl(url)
            return

        pix = QPixmap()
        if imagetype == 'base64':
            pix.loadFromData(data)
        else:
            pix.load(data)

        self.openimage(pix)

    def openimage(self, pixmap):
        viewer = ImageViewer(self.stackedWidget)
        viewer.resize(self.stackedWidget.size())
        viewer.openimage(pixmap)

    def updatecombo(self, *args):
        self.dataentrycombo.setMinimumHeight(0)

    def settingsupdated(self, settings):
        settings.save()
        self.show()
        self.actionGPS.updateGPSPort()
        # eww!
        roam.featureform.settings = settings.settings

    def updatestatuslabel(self):
        extent = self.canvas.extent()
        self.positionlabel.setText("Map Center: {}".format(extent.center().toString()))

    def highlightselection(self, results):
        for layer, features in results.iteritems():
            band = self.selectionbands[layer]
            band.setColor(QColor(255, 0, 0, 150))
            band.setIconSize(20)
            band.setWidth(2)
            band.setBrushStyle(Qt.NoBrush)
            band.reset(layer.geometryType())
            for feature in features:
                band.addGeometry(feature.geometry(), layer)

    def clearselection(self):
        # Clear the main selection rubber band
        self.band.reset()
        # Clear the rest
        for band in self.selectionbands.itervalues():
            band.reset()

    def highlightfeature(self, layer, feature, features):
        self.clearselection()
        self.highlightselection({layer: features})
        self.band.setToGeometry(feature.geometry(), layer)

    def showmap(self):
        self.actionMap.setVisible(True)
        self.actionMap.trigger()

    def hidedataentry(self):
        self.actionDataEntry.setVisible(False)

    def showdataentry(self):
        self.actionDataEntry.setVisible(True)
        self.actionDataEntry.trigger()

    def dataentrychanged(self, index):
        wasactive = self.clearCapatureTools()

        if not index.isValid():
            return

        modelindex = index
        # modelindex = self.dataentrymodel.index(index, 0)
        form = modelindex.data(Qt.UserRole + 1)
        self.dataentrycombo.setCurrentIndex(index.row())
        self.createCaptureButtons(form, wasactive)

    def raiseerror(self, *exinfo):
        info = traceback.format_exception(*exinfo)
        item = self.bar.pushError('Seems something has gone wrong. Press for more details',
                                  info)

    def setMapTool(self, tool, *args):
        self.canvas.setMapTool(tool)

    def homeview(self):
        """
        Zoom the mapview canvas to the extents the project was opened at i.e. the
        default extent.
        """
        self.canvas.setExtent(self.defaultextent)
        self.canvas.refresh()

    def connectButtons(self):
        def connectAction(action, tool):
            action.toggled.connect(partial(self.setMapTool, tool))

        def cursor(name):
            pix = QPixmap(name)
            pix = pix.scaled(QSize(24,24))
            return QCursor(pix)

        self.zoomInTool = QgsMapToolZoom(self.canvas, False)
        self.zoomOutTool = QgsMapToolZoom(self.canvas, True)
        self.panTool = TouchMapTool(self.canvas)
        self.moveTool = MoveTool(self.canvas, [])
        self.infoTool = InfoTool(self.canvas)

        connectAction(self.actionZoom_In, self.zoomInTool)
        connectAction(self.actionZoom_Out, self.zoomOutTool)
        connectAction(self.actionPan, self.panTool)
        connectAction(self.actionMove, self.moveTool)
        connectAction(self.actionInfo, self.infoTool)

        self.zoomInTool.setCursor(cursor(':/icons/in'))
        self.zoomOutTool.setCursor(cursor(':/icons/out'))
        self.infoTool.setCursor(cursor(':/icons/info'))

        self.actionRaster.triggered.connect(self.toggleRasterLayers)

        self.infoTool.infoResults.connect(self.showInfoResults)

        # The edit toolbutton is currently not being used but leaving it for feature.
        self.moveTool.layersupdated.connect(self.actionMove.setEnabled)
        self.moveTool.layersupdated.connect(self.actionEdit_Tools.setEnabled)

        self.actionGPSFeature.triggered.connect(self.addFeatureAtGPS)
        self.actionGPSFeature.setEnabled(self.actionGPS.isConnected)
        self.actionGPS.gpsfixed.connect(self.actionGPSFeature.setEnabled)

        self.actionHome.triggered.connect(self.homeview)
        self.actionQuit.triggered.connect(self.exit)

    def showToolError(self, label, message):
        self.bar.pushMessage(label, message, QgsMessageBar.WARNING)

    def clearCapatureTools(self):
        captureselected = False
        for action in self.projecttoolbar.actions():
            if action.objectName() == "capture" and action.isChecked():
                captureselected = True

            if action.property('dataentry'):
                self.projecttoolbar.removeAction(action)
        return captureselected

    def createCaptureButtons(self, form, wasselected):
        tool = form.getMaptool()(self.canvas)
        for action in tool.actions:
            # Create the action here.
            if action.ismaptool:
                action.toggled.connect(partial(self.setMapTool, tool))

            # Set the action as a data entry button so we can remove it later.
            action.setProperty("dataentry", True)
            self.editgroup.addAction(action)
            self.layerbuttons.append(action)
            self.projecttoolbar.insertAction(self.topspaceraction, action)

            if action.isdefault:
                action.setChecked(wasselected)

        if hasattr(tool, 'geometryComplete'):
            add = partial(self.addNewFeature, form)
            tool.geometryComplete.connect(add)
        else:
            tool.finished.connect(self.openForm)
            tool.error.connect(partial(self.showToolError, form.label))

        self.projecttoolbar.insertAction(self.topspaceraction, self.actionGPSFeature)
        self.actionGPSFeature.setVisible(not tool.isEditTool())

    def createFormButtons(self, forms):
        """
            Create buttons for each form that is defined
        """
        self.dataentrymodel.clear()
        self.clearCapatureTools()


        def captureFeature(form):
            item = QStandardItem(QIcon(form.icon), form.icontext)
            item.setData(form, Qt.UserRole + 1)
            item.setSizeHint(QSize(item.sizeHint().width(), self.projecttoolbar.height()))
            self.dataentrymodel.appendRow(item)

        capabilitityhandlers = {"capture": captureFeature}

        failedforms = []
        for form in forms:
            valid, reasons = form.valid
            if not valid:
                roam.utils.log("Form is invalid for data entry because {}".format(reasons))
                failedforms.append((form, reasons))
                continue

            for capability in form.capabilities:
                try:
                    capabilitityhandlers[capability](form)
                except KeyError:
                    # Just ignore capabilities we don't support yet.
                    continue

        if failedforms:
            for form, reasons in failedforms:
                html = "<h3>{}</h3><br>{}".format(form.label,
                                             "<br>".join(reasons))
            self.bar.pushMessage("Form errors",
                                 "Looks like some forms couldn't be loaded",
                                 level=QgsMessageBar.WARNING, extrainfo=html)

        visible = self.dataentrymodel.rowCount() > 0
        self.dataentrycomboaction.setVisible(visible)
        self.dataentrycombo.setMinimumHeight(self.projecttoolbar.height())

        index = self.dataentrymodel.index(0, 0)
        self.dataentrychanged(index)

    def addFeatureAtGPS(self):
        """
        Add a record at the current GPS location.
        """
        index = self.dataentrycombo.currentIndex()
        modelindex = self.dataentrymodel.index(index, 0)
        form = modelindex.data(Qt.UserRole + 1)
        point = self.actionGPS.position
        point = QgsGeometry.fromPoint(point)
        self.addNewFeature(form=form, geometry=point)

    def clearToolRubberBand(self):
        """
        Clear the rubber band of the active tool if it has one
        """
        tool = self.canvas.mapTool()
        try:
            tool.clearBand()
        except AttributeError:
            # No clearBand method found, but that's cool.
            pass

    def showhelp(self, url):
        help = HelpPage(self.stackedWidget)
        help.setHelpPage(url)
        help.show()

    def dataentryfinished(self):
        self.hidedataentry()
        self.showmap()
        self.cleartempobjects()
        self.infodock.refreshcurrent()

    def featuredeleted(self):
        self.dataentryfinished()
        self.bar.pushMessage("Deleted", "Feature Deleted", QgsMessageBar.INFO, 1)
        self.canvas.refresh()

    def featureSaved(self):
        self.dataentryfinished()
        self.canvas.refresh()

    def failSave(self, messages):
        self.bar.pushError("Error when saving changes.", messages)

    def cleartempobjects(self):
        self.band.reset()
        self.clearToolRubberBand()

    def formrejected(self, message, level):
        self.dataentryfinished()
        if message:
            self.bar.pushMessage("Form Message", message, level, duration=2)

        self.cleartempobjects()

    def openForm(self, form, feature):
        """
        Open the form that is assigned to the layer
        """
        self.band.setToGeometry(feature.geometry(), form.QGISLayer)
        self.showdataentry()
        self.dataentrywidget.openform(feature=feature, form=form, project=self.project)

    def addNewFeature(self, form, geometry):
        """
        Add a new new feature to the given layer
        """
        layer = form.QGISLayer
        fields = layer.pendingFields()

        feature = QgsFeature(fields)
        feature.setGeometry(geometry)

        for index in xrange(fields.count()):
            pkindexes = layer.dataProvider().pkAttributeIndexes()
            if index in pkindexes and layer.dataProvider().name() == 'spatialite':
                continue

            value = layer.dataProvider().defaultValue(index)
            feature[index] = value

        self.openForm(form, feature)

    def exit(self):
        """
        Exit the application.
        """
        QApplication.exit(0)

    def showInfoResults(self, results):
        self.infodock.clearResults()
        forms = {}
        for layer in results.keys():
            layername = layer.name()
            if not layername in forms:
                forms[layername] = list(self.project.formsforlayer(layername))

        self.infodock.setResults(results, forms)
        self.infodock.show()

    def toggleRasterLayers(self):
        """
        Toggle all raster layers on or off.
        """
        if not self.canvaslayers:
            return

        #Freeze the canvas to save on UI refresh
        self.canvas.freeze()
        for layer in self.canvaslayers:
            if layer.layer().type() == QgsMapLayer.RasterLayer:
                layer.setVisible(not layer.isVisible())
            # Really!? We have to reload the whole layer set every time?
        # WAT?
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.freeze(False)
        self.canvas.refresh()

    def missingLayers(self, layers):
        """
        Called when layers have failed to load from the current project
        """
        roam.utils.warning("Missing layers")
        map(roam.utils.warning, layers)

        missinglayers = roam.messagebaritems.MissingLayerItem(layers,
                                                              parent=self.bar)
        self.bar.pushItem(missinglayers)

    def loadprojects(self, projects):
        """
        Load the given projects into the project
        list
        """
        projects = list(projects)
        self.projectwidget.loadProjectList(projects)
        self.syncwidget.loadprojects(projects)

    def updatePage(self, action):
        """
        Update the current stack page based on the current selected
        action
        """
        page = action.property("page")
        self.stackedWidget.setCurrentIndex(page)

    def show(self):
        """
        Override show method. Handles showing the app in fullscreen
        mode or just maximized
        """
        fullscreen = self.settings.settings.get("fullscreen", False)
        if fullscreen:
            self.showFullScreen()
        else:
            self.showMaximized()

    def viewprojects(self):
        self.stackedWidget.setCurrentIndex(1)

    def updateUIState(self, page):
        """
        Update the UI state to reflect the currently selected
        page in the stacked widget
        """
        pass

    @roam.utils.timeit
    def _readProject(self, doc):
        """
        readProject is called by QgsProject once the map layer has been
        populated with all the layers
        """
        parser = ProjectParser(doc)
        canvasnode = parser.canvasnode
        self.canvas.freeze()
        self.canvas.mapRenderer().readXML(canvasnode)
        self.canvaslayers = parser.canvaslayers()
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.updateScale()
        self.projectOpened()
        self.canvas.freeze(False)
        self.canvas.refresh()
        self.showmap()

    @roam.utils.timeit
    def projectOpened(self):
        """
            Called when a new project is opened in QGIS.
        """
        projectpath = QgsProject.instance().fileName()
        self.project = Project.from_folder(os.path.dirname(projectpath))
        self.projectlabel.setText("Project: {}".format(self.project.name))
        self.createFormButtons(forms=self.project.forms)

        # Enable the raster layers button only if the project contains a raster layer.
        layers = QgsMapLayerRegistry.instance().mapLayers().values()
        hasrasters = any(layer.type() == QgsMapLayer.RasterLayer for layer in layers)
        self.actionRaster.setEnabled(hasrasters)
        self.defaultextent = self.canvas.extent()
        roam.utils.info("Extent: {}".format(self.defaultextent.toString()))

        # Show panels
        for panel in self.project.getPanels():
            self.mainwindow.addDockWidget(Qt.BottomDockWidgetArea, panel)
            self.panels.append(panel)

        # TODO Abstract this out
        if not self.project.selectlayers:
            selectionlayers = QgsMapLayerRegistry.instance().mapLayers().values()
        else:
            selectionlayers = []
            for layername in self.project.selectlayers:
                try:
                    layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0]
                except IndexError:
                    roam.utils.warning("Can't find QGIS layer for select layer {}".format(layername))
                    continue
                selectionlayers.append(layer)

        self.infoTool.selectionlayers = selectionlayers
        self.actionPan.trigger()

    #noinspection PyArgumentList
    @roam.utils.timeit
    def loadProject(self, project):
        """
        Load a project into the application .
        """
        roam.utils.log(project)
        roam.utils.log(project.name)
        roam.utils.log(project.projectfile)
        roam.utils.log(project.valid)

        (passed, message) = project.onProjectLoad()

        if not passed:
            self.bar.pushMessage("Project load rejected", "Sorry this project couldn't"
                                                          "be loaded.  Click for me details.",
                                 QgsMessageBar.WARNING, extrainfo=message)
            return

        self.actionMap.trigger()

        self.closeProject()

        self.canvas.refresh()
        self.canvas.repaint()

        self.infodock.clearResults()

        # No idea why we have to set this each time.  Maybe QGIS deletes it for
        # some reason.
        self.badLayerHandler = BadLayerHandler(callback=self.missingLayers)
        QgsProject.instance().setBadLayerHandler(self.badLayerHandler)

        self.stackedWidget.setCurrentIndex(3)
        self.projectloading_label.setText("Project {} Loading".format(project.name))
        pixmap = QPixmap(project.splash)
        w = self.projectimage.width()
        h = self.projectimage.height()
        self.projectimage.setPixmap(pixmap.scaled(w,h, Qt.KeepAspectRatio))
        QApplication.processEvents()

        QDir.setCurrent(os.path.dirname(project.projectfile))
        fileinfo = QFileInfo(project.projectfile)
        QgsProject.instance().read(fileinfo)

    def closeProject(self):
        """
        Close the current open project
        """
        self.canvas.freeze()
        QgsMapLayerRegistry.instance().removeAllMapLayers()
        self.canvas.clear()
        self.canvas.freeze(False)
        for panel in self.panels:
            self.removeDockWidget(panel)
            del panel
            # Remove all the old buttons
        for action in self.layerbuttons:
            self.editgroup.removeAction(action)

        self.dataentrymodel.clear()
        self.panels = []
        self.project = None
        self.dataentrywidget.clear()
        self.hidedataentry()
        self.infodock.close()
Example #43
0
class ProfiletoolMapTool(QgsMapTool):
    
    # Signals
    sig_clearMap = pyqtSignal()
    sig_createProfile = pyqtSignal()
    sig_changeCoord = pyqtSignal(QgsPointXY, str)


    def __init__(self, canvas, drawLineButton, showProfileButton): #buttonShowProf
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        
        self.cursor = QCursor(Qt.CrossCursor)

        # Red line
        self.rubberband = QgsRubberBand(self.canvas)
        self.rubberband.setWidth(3)
        self.rubberband.setColor(QColor(231, 28, 35))
    
        # Buttons from main dialog
        self.drawLineButton = drawLineButton
        self.buttonShowProf = showProfileButton

        # Coordinates of drawn line points
        self.pointsToDraw = []
        # Temporary save double clicks
        self.dblclktemp = None
        # Drawn line geometry
        self.drawnLine = None
        # Point markers on each end of the line
        self.markers = []
        
        # Backup the last active Tool before the pofile tool became active
        self.savedTool = self.canvas.mapTool()


    def drawLine(self):
        # Emit signal that clears map and deletes profile
        self.sig_clearMap.emit()
        self.reset()
        self.canvas.setMapTool(self)        # runs function self.activate()


    def activate(self):
        self.canvas.setCursor(self.cursor)


    def deactivate(self):
        self.canvas.setCursor(QCursor(Qt.OpenHandCursor))
        self.pointsToDraw = []
        # Stop pressing down button
        self.drawLineButton.setChecked(False)


    def reset(self):
        self.removeStueMarker()
        self.canvas.setMapTool(self.savedTool)
        self.rubberband.reset()
        self.pointsToDraw = []
        self.dblclktemp = None
        self.drawnLine = None
        
        
    def canvasMoveEvent(self, event):
        if len(self.pointsToDraw) > 0:
            self.rubberband.reset()
            line = [self.pointsToDraw[0], event.mapPoint()]
            self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(line), None)
 

    def canvasReleaseEvent(self, event):
        mapPos = event.mapPoint()
        if mapPos == self.dblclktemp:
            self.dblclktemp = None
            return
        else:
            # Mark point with marker symbol
            self.drawStueMarker(mapPos)
            
            # Klick ist first point of line
            if len(self.pointsToDraw) == 0:
                self.rubberband.reset()
                self.pointsToDraw.append(mapPos)
                return
            
            # Klick is second point of line
            elif len(self.pointsToDraw) == 1:
                self.pointsToDraw.append(mapPos)
                self.removeStueMarker()
                self.dblclktemp = mapPos
                self.drawnLine = self.createDigiFeature(self.pointsToDraw)
                self.sig_changeCoord.emit(self.pointsToDraw[0], 'A')
                self.sig_changeCoord.emit(self.pointsToDraw[1], 'E')
                self.canvas.setMapTool(self.savedTool)      # self.deactivate()


    def setCursor(self, cursor):
        self.cursor = cursor


    def updateLine(self, points):
        self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(points), None)
        self.drawnLine = self.createDigiFeature(points)
        self.drawStueMarker(points[0])
        self.drawStueMarker(points[1])


    def drawStueMarker(self, point):
        marker = QgsStueMarker(self.canvas)
        marker.setCenter(point)
        self.markers.append(marker)
        self.canvas.refresh()


    def removeStueMarker(self, position=-1):
        if position >= 0:
            marker = self.markers[position]
            self.canvas.scene().removeItem(marker)
            self.markers.pop(position)
        else:
            for marker in self.markers:
                self.canvas.scene().removeItem(marker)
            self.markers = []
        self.canvas.refresh()


    @staticmethod
    def createDigiFeature(pnts):
        line = QgsGeometry.fromPolylineXY(pnts)
        qgFeat = QgsFeature()
        qgFeat.setGeometry(line)
        return qgFeat
Example #44
0
class osmSearchDialog(QDockWidget , Ui_osmSearch ):
    def __init__(self,iface):
        self.iface = iface
        QDockWidget.__init__(self)
        self.setupUi(self)
        self.iface.addDockWidget(Qt.BottomDockWidgetArea,self)
        self.canvas = self.iface.mapCanvas()
        
        self.rb = QgsRubberBand(self.canvas, QGis.Point)
        self.rb.setColor(QColor( 255, 0, 0, 150 ))
        self.searchCacheLimit = 1000
        
        self.wgs84 = QgsCoordinateReferenceSystem()
        self.wgs84.createFromSrid(4326)
        self.proj = self.canvas.mapRenderer().destinationCrs()
        self.transform = QgsCoordinateTransform(self.wgs84, self.proj)
        
        self.bSearch.clicked.connect(self.startSearch)
        self.eOutput.currentItemChanged.connect(self.itemChanged)
        self.eOutput.clickedOutsideOfItems.connect(self.itemChanged)
        self.eText.cleared.connect(self.clearEdit)
        self.canvas.mapRenderer().destinationSrsChanged.connect(self.crsChanged)
        self.iface.newProjectCreated.connect(self.clearEdit)
        self.iface.projectRead.connect(self.clearEdit)
        self.cbCenter.stateChanged.connect(self.autocenter)
        
        db = cacheDB()
        self.autocompleteList = db.getAutocompleteList()
        db.closeConnection()
        self.completer = QCompleter(self.autocompleteList)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.eText.setCompleter(self.completer)

    def startSearch(self):
        text = self.eText.text().encode('utf-8')
        if text == "":
            self.clearEdit()
        #url = 'http://open.mapquestapi.com/nominatim/v1/search.php'
        url = 'http://nominatim.openstreetmap.org/search'
        params = urllib.urlencode({'q': text,'format': 'json','polygon_text':'1'})
        response = json.load(urllib2.urlopen(url+'?'+params))
        self.loadData(response)

    def loadData(self, data):
        self.rb.reset(QGis.Point)
        self.eOutput.clear()
        items = []
        for d in data:
            try:
                geometry = d['geotext']
            except KeyError:
                geometry = 'POINT(%s %s)' % (d['lon'], d['lat'])
            item = QTreeWidgetItem([d['display_name'], d['type']])
            item.setData(0, Qt.UserRole, geometry)
            if geometry.lower().startswith('point'):
                item.setIcon(0, QgsApplication.getThemeIcon('/mIconPointLayer.svg'))
            elif geometry.lower().startswith('linestring'):
                item.setIcon(0, QgsApplication.getThemeIcon('/mIconLineLayer.svg'))
            elif geometry.lower().startswith('polygon'):
                item.setIcon(0, QgsApplication.getThemeIcon('/mIconPolygonLayer.svg'))
            items.append(item)
        if items:
            self.eOutput.insertTopLevelItems(0, items)
            self.addSearchTerm(unicode(self.eText.text().lower()))
            
        else:
            self.iface.messageBar().pushMessage('Nothing was found!', QgsMessageBar.CRITICAL, 2)

    def itemChanged(self, current=None, previous=None):
        if current:
            wkt = str(current.data(0,Qt.UserRole))
            geom = QgsGeometry.fromWkt(wkt)
            if self.proj.srsid() != 4326:
                try:
                    geom.transform(self.transform)
                except:
                    self.iface.messageBar().pushMessage('CRS transformation error!', QgsMessageBar.CRITICAL, 2)
                    self.rb.reset(QGis.Point)
                    return
            self.rb.setToGeometry(geom, None)
            if self.cbCenter.isChecked():
                self.moveCanvas(geom.centroid().asPoint(), self.canvas.extent())
        else:
            self.rb.reset(QGis.Point)
            self.eOutput.setCurrentItem(None)

    def crsChanged(self):
        self.proj = self.canvas.mapRenderer().destinationCrs()
        self.transform = QgsCoordinateTransform(self.wgs84, self.proj)

    def clearEdit(self):
        self.eOutput.clear()
        self.eText.clear()
        if hasattr(self, 'rb'):
            self.rb.reset(QGis.Point)
    
    def setCompleter(self):
        self.completer.model().setStringList(self.autocompleteList)
    
    def addSearchTerm(self, text):
        if not text in self.autocompleteList:
            self.autocompleteList.append(text)
            self.setCompleter()
        while len(self.autocompleteList) > self.searchCacheLimit:
            self.autocompleteList.pop(0)

    def autocenter(self, state):
        if state and self.rb.size():
            self.moveCanvas(self.rb.asGeometry().centroid().asPoint(), self.canvas.extent())

    def moveCanvas(self, newCenter, oldExtent):
        newExtent = QgsRectangle(oldExtent)
        newExtent.scale(1, newCenter)
        self.canvas.setExtent(newExtent)
        self.canvas.refresh()
class DiviPluginHistoryDialog(QDialog, FORM_CLASS):

    def __init__(self, plugin, parent=None):
        """Constructor."""
        super(DiviPluginHistoryDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.plugin = plugin
        #self.iface = plugin.iface
        
        self.setupUi(self)
        self.initGui()
    
    def initGui(self):
        #Models
        self.tblChanges.setModel( ChangeModel() )
        proxyChanges = HistoryProxyModel()
        proxyChanges.setSourceModel( HistoryModel() )
        self.tblHistory.setModel( proxyChanges )
        #Signals
        self.plugin.tvIdentificationResult.model().sourceModel().on_history.connect( self.historyChanged )
        self.tblHistory.selectionModel().currentChanged.connect( self.currentHistoryChanged )
        #Widgets
        settings = QSettings()
        self.mapCanvas = QgsMapCanvas(self.vSplitter)
        self.mapCanvas.setDestinationCrs( QgsCoordinateReferenceSystem('EPSG:4326') )
        zoomFactor = settings.value( "/qgis/zoom_factor", 2.0, type=float )
        action = settings.value( "/qgis/wheel_action", 0, type=int)
        self.mapCanvas.setWheelFactor( zoomFactor )
        self.mapCanvas.enableAntiAliasing( settings.value( "/qgis/enable_anti_aliasing", False, type=bool ))
        #self.mapCanvas.useImageToRender( settings.value( "/qgis/use_qimage_to_render", False, type=bool ))
        self.toolPan = QgsMapToolPan( self.mapCanvas )
        self.mapCanvas.setMapTool( self.toolPan )
        #Canvas items
        self.new_geometry = QgsRubberBand(self.mapCanvas)
        self.new_geometry.setWidth(2)
        self.new_geometry.setIcon( QgsRubberBand.ICON_CIRCLE )
        g = QColor(0, 128, 0, 100)
        self.new_geometry.setColor( g )
        self.old_geometry = QgsRubberBand(self.mapCanvas)
        self.old_geometry.setWidth(2)
        self.old_geometry.setIcon( QgsRubberBand.ICON_CIRCLE )
        r = QColor(255, 0, 0, 100)
        self.old_geometry.setColor( r )
    
    def show(self, data=[]):
        model = self.tblHistory.model().sourceModel()
        model.addItems(data)
        if data:
            self.tblHistory.selectionModel().setCurrentIndex( model.index(0,0), QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows )
        super(DiviPluginHistoryDialog, self).show()
    
    def historyChanged(self):
        """ Reaload data if window is visible """
        if self.isVisible():
            self.plugin.showHistoryDialog()
    
    def currentHistoryChanged(self, current, previous):
        self.new_geometry.reset()
        self.old_geometry.reset()
        self.tblChanges.model().removeRows()
        if not current.isValid():
            return
        item = current.data(Qt.UserRole)
        if item is None:
            data = {}
        else:
            data = current.data(Qt.UserRole).getDetails()
        with SetLocale_CtxDec():
            extent = None
            if data.get('new_geometry'):
                wkt = CreateGeometryFromJson( json.dumps(data['new_geometry']) ).ExportToWkt()
                geom = QgsGeometry.fromWkt( wkt )
                l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory')
                self.new_geometry.setToGeometry( geom, l )
                extent = QgsRectangle(geom.boundingBox())
            if data.get('old_geometry'):
                wkt = CreateGeometryFromJson( json.dumps(data['old_geometry']) ).ExportToWkt()
                geom = QgsGeometry.fromWkt( wkt )
                l = QgsVectorLayer('Point?crs=epsg:4326', 'asd', 'memory')
                self.old_geometry.setToGeometry( geom, l )
                if extent is None:
                    extent = QgsRectangle(geom.boundingBox())
                else:
                    extent.combineExtentWith( geom.boundingBox() )
            if extent is not None:
                extent.grow(0.01)
                self.mapCanvas.setExtent( extent )
                self.mapCanvas.refresh()
        if data.get('what_attributes', []):
            self.tblChanges.model().insertRows( 0, data.get('what_attributes', []) )
class DockEditorDialog(QtGui.QDockWidget, Ui_DockEditor):
    def __init__(self, iface, mapCanvas):
        self.iface = iface
        QtGui.QDockWidget.__init__(self)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self)

        self.mapCanvas = mapCanvas

        # rubber bands
        self.featureRubber = QgsRubberBand(self.mapCanvas, False)
        self.updateFeatureRubber()

        # Gui defaults
        self.kwaliteitsklasseCombo.setVisible(False)
        self.onderzochtJaarSpinBox.setVisible(False)
        self.hersteldJaarSpinBox.setVisible(False)
        self.kwaliteitsklasseLabel.setVisible(False)
        self.monitoringObjTekst.setVisible(False)

        # GUI signals connection
        self.actionButtonBox.button(QtGui.QDialogButtonBox.Save).clicked.connect(self.applySave)
        self.actionButtonBox.button(QtGui.QDialogButtonBox.Abort).clicked.connect(self.applyCancel)
        self.deleteButton.clicked.connect(self.applyDelete)
        self.newPandButton.clicked.connect(self.applyNewPand)
        self.idButton.clicked.connect(self.zoomToFeature)
        self.adresLinkButton.clicked.connect(self.showVerblijfsObj)
        self.verseonLinkButton.clicked.connect(self.getVerseonInfo)
        self.lkiLinkButton.clicked.connect(self.showLkiInfo)

        # force Dutch for QDialogButtonBox
        self.actionButtonBox.button(QtGui.QDialogButtonBox.Save).setText("Opslaan")
        self.actionButtonBox.button(QtGui.QDialogButtonBox.Abort).setText("Annuleer");

        # enable save button when value changes
        self.bezitCombo.currentIndexChanged.connect(self.actionButtonBoxEnable)
        self.kwaliteitsklasseCombo.currentIndexChanged.connect(self.actionButtonBoxEnable)
        self.onderzochtCheckBox.stateChanged.connect(self.actionButtonBoxEnable)
        self.onderzochtJaarSpinBox.valueChanged.connect(self.actionButtonBoxEnable)
        self.hersteldCheckBox.stateChanged.connect(self.actionButtonBoxEnable)
        self.hersteldJaarSpinBox.valueChanged.connect(self.actionButtonBoxEnable)
        self.projectCombo.editTextChanged.connect(self.actionButtonBoxEnable)
        self.richtlijnCombo.editTextChanged.connect(self.actionButtonBoxEnable)
        self.handhavingCheckBox.stateChanged.connect(self.actionButtonBoxEnable)
        self.typefundCombo.editTextChanged.connect(self.actionButtonBoxEnable)
        self.paallengteSpinBox.valueChanged.connect(self.actionButtonBoxEnable)
        self.houtsoortCombo.editTextChanged.connect(self.actionButtonBoxEnable)
        self.dekkingSpinBox.valueChanged.connect(self.actionButtonBoxEnable)
        self.droogstandCheckBox.stateChanged.connect(self.actionButtonBoxEnable)
        self.opmerkingText.textChanged.connect(self.actionButtonBoxEnable)

        self.setVisible(False)

    def showEvent(self, e):

        self.newGroupBox.hide()
        self.editGroupBox.hide()
        if (getVectorLayerByName(editLayerName) == None):
            self.errorFrame.show()
        else:
            self.errorFrame.hide()

        self.editLayer = getVectorLayerByName(editLayerName)
        self.adresLayer = getVectorLayerByName(adresLayerName)
        self.geomLayer = getVectorLayerByName(geomLayerName)
        self.editFeature = None
        self.updateCombos()

    def closeEvent(self, e):

        e.ignore()
        self.featureRubber.reset()
        self.hide()

    def zoomToFeature(self):
        box = self.selectedFeature.geometry().buffer(20, 4).boundingBox()
        self.iface.mapCanvas().setExtent(box)
        self.iface.mapCanvas().refresh()

    def updateCombos(self):

        if (self.editLayer):
            FieldCombo(self.bezitCombo, self.editLayer, initField="bezit")
            FieldCombo(self.kwaliteitsklasseCombo, self.editLayer, initField="kwaliteitsklasse")
            FieldCombo(self.projectCombo, self.editLayer, initField="project")
            FieldCombo(self.richtlijnCombo, self.editLayer, initField="richtlijn")
            FieldCombo(self.typefundCombo, self.editLayer, initField="funderingtype")
            FieldCombo(self.houtsoortCombo, self.editLayer, initField="houtsoort")

    def actionButtonBoxEnable(self):
        self.actionButtonBox.setDisabled(False)

    def featureSelected(self, layer, feature):
        self.layer = layer
        self.selectedFeature = feature
        initialGeometry = QgsGeometry(feature.geometry())

        self.featureRubber.reset()
        self.featureRubber.setToGeometry(initialGeometry, layer)
        self.updateGui(feature)

    def updateGui(self, feature):
        # The important part: get the feature iterator with an expression
        request = QgsFeatureRequest().setFilterExpression ( u'"pand_id" = \'' + unicode(feature['gebouwnummer']) + '\'' )
        request.setFlags( QgsFeatureRequest.NoGeometry )
        features = self.geomLayer.getFeatures( request )

        atr = None
        fields = self.geomLayer.pendingFields()
        field_names = [field.name() for field in fields]
        for elem in features:
            self.editFeature = elem
            atr = dict(zip(field_names, elem.attributes()))

        if atr is not None:
            atr = {i:j for i,j in atr.items() if j }
            self.newGroupBox.hide()
            self.editGroupBox.show()
            self.verwijderWidget.show()
            self.showValues(feature, atr)
            self.actionButtonBox.setDisabled(True)

        else:
            self.newGroupBox.show()
            self.editGroupBox.hide()
            self.verwijderWidget.hide()

            self.editFeature = None
            self.statusNieuwLabel.setText(unicode(feature['status']))
            self.pandidLabel.setText(unicode(feature['gebouwnummer']))

    def showValues(self, feature, atr):

        self.deleteCheckBox.setChecked(False)

        self.idText.setText(unicode(atr.get("pand_id", "")))
        if (feature['vboj_count'] == 1):
            self.adresLinkButton.setText(BagadresString().request(unicode(feature['gebouwnummer'])))
        else:
            self.adresLinkButton.setText("Pand bevat " + unicode(feature['vboj_count']) + " adres(sen)")

        self.setComboTekst(self.bezitCombo, atr.get("bezit", ""))

        if (atr.get("onderzocht", "")=="t"):
            self.onderzochtCheckBox.setChecked(True)
            self.onderzochtJaarSpinBox.setValue(atr.get("onderzocht_jaar", ""))
        else:
            self.onderzochtCheckBox.setChecked(False)

        self.setComboTekst(self.kwaliteitsklasseCombo, atr.get("kwaliteitsklasse", ""))

        if (atr.get("hersteld", "")=="t"):
            self.hersteldCheckBox.setChecked(True)
            self.hersteldJaarSpinBox.setValue(atr.get("hersteld_jaar", ""))
        else:
            self.hersteldCheckBox.setChecked(False)

        self.setComboTekst(self.projectCombo, atr.get("project", ""))
        self.setComboTekst(self.richtlijnCombo, atr.get("richtlijn", ""))
        
        self.handhavingCheckBox.setChecked(toBoolean(atr.get("fumon_monitoring", "f")))
        self.monitoringObjTekst.setText(atr.get("fumon_objectcode", ""))

        self.setComboTekst(self.typefundCombo, atr.get("funderingtype", ""))
        self.paallengteSpinBox.setValue(atr.get("paallengte", 0))
        self.setComboTekst(self.houtsoortCombo, atr.get("houtsoort", ""))
        self.dekkingSpinBox.setValue(atr.get("dekking", 0))
        self.droogstandCheckBox.setChecked(toBoolean(atr.get("droogstand", "f")))

        self.opmerkingText.setPlainText(atr.get("opmerking", ""))      

        # set texts in UI
        featureStatus = unicode(feature['status'])
        featureBj = unicode(feature['bouwjaar'])

        self.statusText.setText(featureStatus)
        self.bouwjaarText.setText(featureBj)

    def showVerblijfsObj(self):
        feature = self.selectedFeature
        gebouwnummer = unicode(feature['gebouwnummer'])
        InfoBagDialog(gebouwnummer, self.iface)

    def getVerseonInfo(self):
        feature = self.selectedFeature
        gebouwnummer = unicode(feature['gebouwnummer'])
        InfoVerseonDialog(gebouwnummer, self.iface)

    def showLkiInfo(self):
        feature = self.selectedFeature
        wkt = feature.geometry().pointOnSurface().exportToWkt()
        PerceelinfoDialog(wkt, self.iface)

    def setComboTekst(self, combo, value):
        idx = combo.findText(value)
        combo.setCurrentIndex(idx)

    def updateFeatureRubber(self):
        self.featureRubber.setColor(featureRubberColor)
        self.featureRubber.setWidth(featureRubberSize)
        self.featureRubber.setBrushStyle(Qt.NoBrush)
        self.mapCanvas.refresh()

    def applySave(self):

        if not self.editLayer.isEditable():
            self.editLayer.startEditing()

        layer = self.editLayer
        layer.beginEditCommand("Funderingsgegevens")

        try:

            if (self.editFeature == None):
                idx = layer.pendingFields().indexFromName("id")
                nextId = layer.maximumValue(idx)
                feat = QgsFeature()
                feat.setFields(layer.pendingFields(), True)
                feat.setAttribute(layer.fieldNameIndex( "pand_id" ), self.pandidLabel.text())
                feat.setAttribute(layer.fieldNameIndex( "id" ), nextId + 1)
                layer.addFeature(feat, False)
                self.editFeature = feat

            fid = self.editFeature.id()

            layer.changeAttributeValue(fid, layer.fieldNameIndex( "pand_id" ), self.idText.text())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "bezit" ), self.bezitCombo.currentText())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "onderzocht" ), self.onderzochtCheckBox.isChecked())
            if (self.onderzochtCheckBox.isChecked()):
                layer.changeAttributeValue(fid, layer.fieldNameIndex( "onderzocht_jaar" ), self.onderzochtJaarSpinBox.value())
            else:
                layer.changeAttributeValue(fid, layer.fieldNameIndex( "onderzocht_jaar" ), None)
                
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "kwaliteitsklasse" ), self.kwaliteitsklasseCombo.currentText())

            layer.changeAttributeValue(fid, layer.fieldNameIndex( "hersteld" ), self.hersteldCheckBox.isChecked())
            if (self.hersteldCheckBox.isChecked()):
                layer.changeAttributeValue(fid, layer.fieldNameIndex( "hersteld_jaar" ), self.hersteldJaarSpinBox.value())
            else:
                layer.changeAttributeValue(fid, layer.fieldNameIndex( "hersteld_jaar" ), None)

            layer.changeAttributeValue(fid, layer.fieldNameIndex( "project" ), self.projectCombo.currentText())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "richtlijn" ), self.richtlijnCombo.currentText())

            layer.changeAttributeValue(fid, layer.fieldNameIndex( "funderingtype" ), self.typefundCombo.currentText())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "paallengte" ), self.paallengteSpinBox.value())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "houtsoort" ), self.houtsoortCombo.currentText())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "dekking" ), self.dekkingSpinBox.value())
            layer.changeAttributeValue(fid, layer.fieldNameIndex( "droogstand" ), self.droogstandCheckBox.isChecked())

            layer.changeAttributeValue(fid, layer.fieldNameIndex( "opmerking" ), self.opmerkingText.toPlainText())
        except Exception, e:
            raise e
            layer.destroyEditCommand()
            self.iface.messageBar().pushMessage("Funderingsherstel", "Er is wat misgegaan tijdens het opslaan van dit BAG object!", level=QgsMessageBar.CRITICAL)
        else:
Example #47
0
class addPolygon(QgsMapTool):
    cut = pyqtSignal()
    deact = pyqtSignal()

    def __init__(self, iface, action, geometryClass):
        self.canvas = iface.mapCanvas()
        self.iface = iface
        self.action = action
        self.geometryClass = geometryClass

        obj_color = QColor(254, 0, 0)
        obj_color_alpha = QColor(254, 0, 0)
        obj_color_alpha.setAlpha(60)
        vert_color = QColor(0, 0, 255)

        QgsMapTool.__init__(self, self.canvas)

        self.rubberBand = QgsRubberBand(self.canvas,
                                        QgsWkbTypes.GeometryType(3))
        self.rubberBand.setWidth(1)
        self.rubberBand.setStrokeColor(obj_color)
        self.rubberBand.setFillColor(obj_color_alpha)

        self.rubberBand_click = QgsRubberBand(self.canvas,
                                              QgsWkbTypes.GeometryType(3))
        self.rubberBand_click.setWidth(0)
        self.rubberBand_click.setFillColor(obj_color_alpha)

        # snap marker
        self.snap_mark = QgsVertexMarker(self.canvas)
        self.snap_mark.setColor(vert_color)
        self.snap_mark.setPenWidth(2)
        self.snap_mark.setIconType(QgsVertexMarker.ICON_BOX)
        self.snap_mark.setIconSize(10)

        self.points = []

    def activate(self):
        self.action.setChecked(True)
        self.setCursor(Qt.CrossCursor)

    def canvasMoveEvent(self, e):
        self.snap_mark.hide()
        self.snapPoint = False
        self.snapPoint = self.checkSnapToPoint(e.pos())

        if self.snapPoint[0]:
            self.snap_mark.setCenter(self.snapPoint[1])
            self.snap_mark.show()

        if len(self.points) > 0:
            self.rubberBand.reset(QgsWkbTypes.GeometryType(3))
            point = self.toMapCoordinates(self.canvas.mouseLastXY())
            temp_points = self.points[:]
            temp_points.append(point)
            polygon = QgsGeometry.fromPolygonXY([temp_points])
            self.rubberBand.setToGeometry(polygon, None)
            self.rubberBand.show()

    def canvasPressEvent(self, e):
        # Left mouse button
        if e.button() == Qt.LeftButton:
            if self.snapPoint[0]:
                point = self.snapPoint[1]
            else:
                point = self.toMapCoordinates(self.canvas.mouseLastXY())

            self.points.append(point)
            polygon = QgsGeometry.fromPolygonXY([self.points])
            self.rubberBand_click.reset(QgsWkbTypes.GeometryType(3))
            self.rubberBand_click.setToGeometry(polygon, None)
            self.rubberBand_click.show()

        # Right mouse button
        if e.button() == Qt.RightButton:
            geometry = QgsGeometry.fromPolygonXY([self.points])
            self.geometryClass.geometry = geometry
            self.cut.emit()
            self.reset()

    def checkSnapToPoint(self, point):
        snapped = False
        snap_point = self.toMapCoordinates(point)
        snapper = self.canvas.snappingUtils()
        snapMatch = snapper.snapToMap(point)
        if snapMatch.hasVertex():
            snap_point = snapMatch.point()
            snapped = True
        return snapped, snap_point

    def deactivate(self):
        self.action.setChecked(False)
        self.reset()
        self.deact.emit()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.reset()

    def reset(self):
        self.rubberBand_click.reset(QgsWkbTypes.GeometryType(3))
        self.rubberBand.reset(QgsWkbTypes.GeometryType(3))
        self.snap_mark.hide()
        self.points = []
Example #48
0
class ItemBrowserDock(QDockWidget, Ui_itembrowser):
    dockRemoved = pyqtSignal(str)

    def __init__(self, iface, layer, currentFeature):
        self.iface = iface
        self.layer = layer
        self.renderer = self.iface.mapCanvas().mapRenderer()
        self.settings = MySettings()
        QDockWidget.__init__(self)
        self.setupUi(self)

        self.setWindowTitle("ItemBrowser: %s" % layer.name())
        if layer.hasGeometryType() is False:
            self.panCheck.setChecked(False)
            self.panCheck.setEnabled(False)
            self.scaleCheck.setChecked(False)
            self.scaleCheck.setEnabled(False)

        self.previousButton.setArrowType(Qt.LeftArrow)
        self.nextButton.setArrowType(Qt.RightArrow)
        icon = QIcon(":/plugins/itembrowser/icons/openform.svg")
        self.editFormButton.setIcon(icon)

        # actions
        icon = QIcon(":/plugins/itembrowser/icons/action.svg")
        self.actionButton.setIcon(icon)
        self.attrAction = layer.actions()
        actions = [self.attrAction[i] for i in range(self.attrAction.size())]
        preferredAction = layer.customProperty("ItemBrowserPreferedAction", "")
        if preferredAction not in actions:
            dfltAction = self.attrAction.defaultAction()
            if dfltAction > len(actions):
                preferredAction = self.attrAction[dfltAction].name()
        preferredActionFound = False
        for i, action in enumerate(actions):
            qAction = QAction(QIcon(":/plugins/itembrowser/icons/action.svg"), action.name(), self)
            qAction.triggered.connect(lambda: self.doAction(i))
            self.actionButton.addAction(qAction)
            if action.name() == preferredAction:
                self.actionButton.setDefaultAction(qAction)
                preferredActionFound = True
        if len(actions) == 0:
            self.actionButton.setEnabled(False)
        elif not preferredActionFound:
            self.actionButton.setDefaultAction(self.actionButton.actions()[0])

        self.rubber = QgsRubberBand(self.iface.mapCanvas())
        self.selectionChanged()
        if currentFeature == self.listCombo.currentIndex():
            self.on_listCombo_currentIndexChanged(currentFeature)
        else:
            self.listCombo.setCurrentIndex(currentFeature)
        self.layer.layerDeleted.connect(self.close)
        self.layer.selectionChanged.connect(self.selectionChanged)

    def closeEvent(self, e):
        self.rubber.reset()
        try:
            self.layer.layerDeleted.disconnect(self.close)
        except TypeError:
            pass
        try:
            self.layer.selectionChanged.disconnect(self.selectionChanged)
        except TypeError:
            pass
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("itemBrowserSelection", repr([]))
        self.dockRemoved.emit(self.layer.id())
          
    def selectionChanged(self):
        self.cleanBrowserFields()
        self.rubber.reset()
        nItems = self.layer.selectedFeatureCount()
        if nItems < 2:
            self.close()
            self.layer.emit(SIGNAL("browserNoItem()"))
            return
        self.browseFrame.setEnabled(True)
        subset = self.layer.selectedFeaturesIds()
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("itemBrowserSelection", repr(subset))

        f = QgsFeature()
        title = QgsExpression(self.layer.displayExpression())
        title.prepare(self.layer.pendingFields())
        iterator = self.layer.getFeatures(QgsFeatureRequest().setFilterFids(subset))
        while iterator.nextFeature(f):
            result = title.evaluate(f)
            if title.hasEvalError():
                self.listCombo.addItem("%u" % f.id(), f.id())
            else:
                self.listCombo.addItem("%s" % result, f.id())

    def cleanBrowserFields(self):
        self.currentPosLabel.setText('0/0')
        self.listCombo.clear()
          
    def panScaleToItem(self, feature):
        if self.panCheck.isChecked() is False:
            return
        featBobo = feature.geometry().boundingBox()
        # if scaling and bobo has width and height (i.e. not a point)
        if self.scaleCheck.isChecked() and featBobo.width() != 0 and featBobo.height() != 0:
            featBobo.scale(self.settings.value("scale"))
            ul = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMinimum(), featBobo.yMaximum()))
            ur = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMaximum(), featBobo.yMaximum()))
            ll = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMinimum(), featBobo.yMinimum()))
            lr = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMaximum(), featBobo.yMinimum()))
            x = (ul.x(), ur.x(), ll.x(), lr.x())
            y = (ul.y(), ur.y(), ll.y(), lr.y())
            x0 = min(x)
            y0 = min(y)
            x1 = max(x)
            y1 = max(y)
        else:
            panTo = self.renderer.layerToMapCoordinates(self.layer, featBobo.center())
            mapBobo = self.iface.mapCanvas().extent()
            xshift = panTo.x() - mapBobo.center().x()
            yshift = panTo.y() - mapBobo.center().y()
            x0 = mapBobo.xMinimum() + xshift
            y0 = mapBobo.yMinimum() + yshift
            x1 = mapBobo.xMaximum() + xshift
            y1 = mapBobo.yMaximum() + yshift
        self.iface.mapCanvas().setExtent(QgsRectangle(x0, y0, x1, y1))
        self.iface.mapCanvas().refresh()

    def getCurrentItem(self):
        i = self.listCombo.currentIndex()
        if i == -1:
            return None
        f = QgsFeature()
        if self.layer.getFeatures(QgsFeatureRequest().setFilterFid(self.listCombo.itemData(i))).nextFeature(f):
            return f
        else:
            raise NameError("feature not found")

    def setCurrentItem(self, featureId):
        idx = self.listCombo.findText("%u" % featureId)
        self.listCombo.setCurrentIndex(idx)

    def doAction(self, i):
        f = self.getCurrentItem()
        self.actionButton.setDefaultAction(self.actionButton.actions()[i])
        self.layer.setCustomProperty("ItemBrowserPreferedAction", self.attrAction[i].name())
        self.attrAction.doActionFeature(i, f)

    @pyqtSlot(name="on_previousButton_clicked")
    def previousFeaature(self):
        i = self.listCombo.currentIndex()
        n = max(0, i-1)
        self.listCombo.setCurrentIndex(n)
        self.saveCurrentFeature(n)
          
    @pyqtSlot(name="on_nextButton_clicked")
    def nextFeature(self):
        i = self.listCombo.currentIndex()
        c = self.listCombo.count()
        n = min(i+1, c-1)
        self.listCombo.setCurrentIndex(n)
        self.saveCurrentFeature(n)

    @pyqtSlot(int, name="on_listCombo_activated")
    def saveCurrentFeature(self, i):
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("itemBrowserCurrentItem", i)

    @pyqtSlot(int, name="on_listCombo_currentIndexChanged")
    def on_listCombo_currentIndexChanged(self, i):
        feature = self.getCurrentItem()
        if feature is None: 
            return
        self.rubber.reset()
        if self.listCombo.count() > 1:
            width = self.settings.value("rubberWidth")
            color = self.settings.value("rubberColor")
            self.rubber.setColor(color)
            self.rubber.setWidth(width)
            self.rubber.setToGeometry(feature.geometry(), self.layer)
        # scale to feature
        self.panScaleToItem(feature)
        # Update browser
        self.currentPosLabel.setText("%u/%u" % (i+1, self.listCombo.count()))
        # emit signal
        self.layer.emit(SIGNAL("browserCurrentItem(long)"), feature.id())
          
    @pyqtSlot(int, name="on_panCheck_stateChanged")
    def on_panCheck_stateChanged(self, i):
        if self.panCheck.isChecked():
            self.scaleCheck.setEnabled(True)
            feature = self.getCurrentItem()
            if feature is None:
                return
            self.panScaleToItem(feature)
        else:
            self.scaleCheck.setEnabled(False)
               
    @pyqtSlot(int, name="on_scaleCheck_stateChanged")
    def on_scaleCheck_stateChanged(self, i):
        if self.scaleCheck.isChecked():
            feature = self.getCurrentItem()
            if feature is None: 
                return
            self.panScaleToItem(feature)

    @pyqtSlot(name="on_editFormButton_clicked")
    def openFeatureForm(self):
        self.iface.openFeatureForm(self.layer, self.getCurrentItem())
Example #49
0
class QMap():
    def __init__(self, iface):
        self.iface = iface
        self.actions = []
        self.panels= []
        self.navtoolbar = self.iface.mapNavToolToolBar()
        self.mainwindow = self.iface.mainWindow()
        self.iface.projectRead.connect(self.projectOpened)
        self.iface.initializationCompleted.connect(self.setupUI)
        self.actionGroup = QActionGroup(self.mainwindow)
        self.actionGroup.setExclusive(True)
        self.menuGroup = QActionGroup(self.mainwindow)
        self.menuGroup.setExclusive(True)
                
        self.movetool = MoveTool(self.iface.mapCanvas(), [])
        self.infotool = InfoTool(self.iface.mapCanvas())
        self.infotool.infoResults.connect(self.showInfoResults)
        
        self.report = PopDownReport(self.iface.messageBar())
        
        self.dialogprovider = DialogProvider(iface.mapCanvas(), iface)
        self.dialogprovider.accepted.connect(self.clearToolRubberBand)
        self.dialogprovider.rejected.connect(self.clearToolRubberBand)
        
        self.edittool = EditTool(self.iface.mapCanvas(),[])
        self.edittool.finished.connect(self.openForm)
        self.edittool.featuresfound.connect(self.showFeatureSelection)

        self.infodock = InfoDock(self.iface.mainWindow())
        self.iface.addDockWidget(Qt.RightDockWidgetArea, self.infodock)
        self.infodock.hide()

        self.band = QgsRubberBand(self.iface.mapCanvas())
        self.band.setIconSize(20)
        self.band.setWidth(10)
        self.band.setColor(QColor(186, 93, 212, 76))

    def showFeatureSelection(self, features):
        listUi = ListFeaturesForm(self.mainwindow)
        listUi.loadFeatureList(features)
        listUi.openFeatureForm.connect(self.openForm)
        listUi.exec_()

    def showInfoResults(self, results):
        self.infodock.clearResults()
        self.infodock.setResults(results)
        self.infodock.show()
        self.infodock.repaint()
        
    @property
    def _mapLayers(self):
        return QgsMapLayerRegistry.instance().mapLayers()
        
    def clearToolRubberBand(self):
        tool = self.iface.mapCanvas().mapTool()
        try:
            tool.clearBand()
        except AttributeError:
            # No clearBand method found, but that's cool.
            pass
        
    def missingLayers(self, layers):
        def showError():
            html = ["<h1>Missing Layers</h1>", "<ul>"]
            for layer in layers:
                html.append("<li>{}</li>".format(layer))
            html.append("</ul>")
            
            self.errorreport.updateHTML("".join(html))
        
        message = "Seems like {} didn't load correctly".format(utils._pluralstring('layer', len(layers)))
        
        utils.warning("Missing layers")
        map(utils.warning, layers)
            
        self.widget = self.iface.messageBar().createMessage("Missing Layers",
                                                 message, 
                                                 QIcon(":/icons/sad"))
        button = QPushButton(self.widget)
        button.setCheckable(True)
        button.setChecked(self.errorreport.isVisible())
        button.setText("Show missing layers")
        button.toggled.connect(showError)
        button.toggled.connect(functools.partial(self.errorreport.setVisible))
        self.widget.destroyed.connect(self.hideReports)
        self.widget.layout().addWidget(button)
        self.iface.messageBar().pushWidget(self.widget, QgsMessageBar.WARNING)
        
    def excepthook(self, ex_type, value, tb):
        """ 
        Custom exception hook so that we can handle errors in a
        nicer way
        """
        where = ''.join(traceback.format_tb(tb))
        msg = '{}'.format(value)
        utils.critical(msg)
        
        def showError():
            html = """
                <html>
                <body bgcolor="#FFEDED">
                <p><b>{}</b></p>
                <p align="left"><small>{}</small></p>
                </body>
                </html>
            """.format(msg, where)
            self.errorreport.updateHTML(html)
        
        self.widget = self.iface.messageBar().createMessage("oops", "Looks like an error occurred", QIcon(":/icons/sad"))
        button = QPushButton(self.widget)
        button.setCheckable(True)
        button.setChecked(self.errorreport.isVisible())
        button.setText("Show error")
        button.toggled.connect(showError)
        button.toggled.connect(functools.partial(self.errorreport.setVisible))
        self.widget.destroyed.connect(self.hideReports)
        self.widget.layout().addWidget(button)
        self.messageBar.pushWidget(self.widget, QgsMessageBar.CRITICAL)
    
    def hideReports(self):
        self.errorreport.setVisible(False)
        self.report.setVisible(False)
    
    def setupUI(self):
        """
        Set up the main QGIS interface items.  Called after QGIS has loaded
        the plugin.
        """
        self.updateAppSize()
        
        utils.settings_notify.settings_changed.connect(self.updateAppSize)

        self.navtoolbar.setMovable(False)
        self.navtoolbar.setAllowedAreas(Qt.TopToolBarArea)
        
        self.mainwindow.insertToolBar(self.toolbar, self.navtoolbar)
        self.openProjectAction.trigger()
        
    def updateAppSize(self):
        fullscreen = utils.settings.get("fullscreen", False)
        if fullscreen:
            self.mainwindow.showFullScreen()
        else:
            self.mainwindow.showMaximized()
            
    def setMapTool(self, tool):
        """
        Set the current mapview canvas tool

        tool -- The QgsMapTool to set
        """
        self.iface.mapCanvas().setMapTool(tool)

    def createToolBars(self):
        """
        Create all the needed toolbars
        """
        
        self.menutoolbar = QToolBar("Menu", self.mainwindow)
        self.menutoolbar.setMovable(False)
        self.menutoolbar.setAllowedAreas(Qt.LeftToolBarArea)
        self.mainwindow.addToolBar(Qt.LeftToolBarArea, self.menutoolbar)
        
        self.toolbar = QToolBar("QMap", self.mainwindow)
        self.mainwindow.addToolBar(Qt.TopToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        self.editingtoolbar = FloatingToolBar("Editing", self.toolbar)
        self.extraaddtoolbar = FloatingToolBar("Extra Add Tools", self.toolbar)
        self.syncactionstoolbar = FloatingToolBar("Syncing", self.toolbar)
        self.syncactionstoolbar.setOrientation(Qt.Vertical)

    def createActions(self):
        """
        Create all the actions
        """

        self.homeAction = (QAction(QIcon(":/icons/zoomfull"),
                                  "Default View", self.mainwindow))
        self.gpsAction = (GPSAction(QIcon(":/icons/gps"), self.iface.mapCanvas(),
                                   self.mainwindow))
        
        self.openProjectAction = (QAction(QIcon(":/icons/open"), "Projects",
                                         self.mainwindow))
        self.openProjectAction.setCheckable(True)
        
        self.configAction = (QAction(QIcon(":/icons/config"), "Settings",
                                         self.mainwindow))
        self.configAction.setCheckable(True)
        
        self.toggleRasterAction = (QAction(QIcon(":/icons/photo"), "Aerial Photos",
                                          self.mainwindow))
        self.syncAction = QAction(QIcon(":/icons/sync"), "Sync", self.mainwindow)
        self.syncAction.setVisible(False)
        
        self.editattributesaction = QAction(QIcon(":/icons/edit"), "Edit Attributes", self.mainwindow)
        self.editattributesaction.setCheckable(True)
        self.editattributesaction.toggled.connect(functools.partial(self.setMapTool, self.edittool))

        self.moveaction = QAction(QIcon(":/icons/move"), "Move Feature", self.mainwindow)
        self.moveaction.setCheckable(True)

        self.editingmodeaction = QAction(QIcon(":/icons/edittools"), "Edit Tools", self.mainwindow)
        self.editingmodeaction.setCheckable(True)
        
        self.infoaction = QAction(QIcon(":/icons/info"), "Info", self.mainwindow)
        self.infoaction.setCheckable(True)

        self.addatgpsaction = QAction(QIcon(":/icons/gpsadd"), "Add at GPS", self.mainwindow)
        
        self.edittool.layersupdated.connect(self.editattributesaction.setVisible)
        self.movetool.layersupdated.connect(self.moveaction.setVisible)
        self.movetool.layersupdated.connect(self.editingmodeaction.setVisible)
        
    def initGui(self):
        """
        Create all the icons and setup the tool bars.  Called by QGIS when
        loading. This is called before setupUI.
        """
        QApplication.setWindowIcon(QIcon(":/branding/logo"))
        self.mainwindow.findChildren(QMenuBar)[0].setVisible(False)
        self.mainwindow.setContextMenuPolicy(Qt.PreventContextMenu)
        self.mainwindow.setWindowTitle("IntraMaps Roam: Mobile Data Collection")
        
        # Disable QGIS logging window popups. We do our own logging
        QgsMessageLog.instance().messageReceived.disconnect()
        
        s = """
        QToolButton { 
            padding: 6px;
            color: #4f4f4f;
         }
        
        QToolButton:hover { 
            padding: 6px;
            background-color: rgb(211, 228, 255);
         }
         
        QToolBar {
         background: white;
        }
        
        QCheckBox::indicator {
             width: 40px;
             height: 40px;
         }
        
        QLabel {
            color: #4f4f4f;
        }
        
        QDialog { background-color: rgb(255, 255, 255); }
        
        QPushButton { 
            border: 1px solid #e1e1e1;
             padding: 6px;
            color: #4f4f4f;
         }
        
        QPushButton:hover { 
            border: 1px solid #e1e1e1;
             padding: 6px;
            background-color: rgb(211, 228, 255);
         }
        
        QCheckBox {
            color: #4f4f4f;
        }
        
        QComboBox::drop-down {
            width: 30px;
        }
        
        QComboBox {
            border: 1px solid #d3d3d3;
        }

        QStackedWidget {
             background-color: rgb(255, 255, 255);
        }
        """
        self.mainwindow.setStyleSheet(s)
        
        mainwidget = self.mainwindow.centralWidget()
        mainwidget.setLayout(QGridLayout())
        mainwidget.layout().setContentsMargins(0,0,0,0)
        
        newlayout = QGridLayout()
        newlayout.setContentsMargins(0,0,0,0)
        newlayout.addWidget(self.iface.mapCanvas(), 0,0,2,1)
        newlayout.addWidget(self.iface.messageBar(), 0,0,1,1)
        
        wid = QWidget()
        wid.setLayout(newlayout)
        
        self.stack = QStackedWidget(self.mainwindow)
        self.messageBar = QgsMessageBar(wid)
        self.messageBar.setSizePolicy( QSizePolicy.Minimum, QSizePolicy.Fixed )
        self.errorreport = PopDownReport(self.messageBar)

        mainwidget.layout().addWidget(self.stack, 0,0,2,1)
        mainwidget.layout().addWidget(self.messageBar, 0,0,1,1)

        self.helppage = HelpPage()
        helppath = os.path.join(os.path.dirname(__file__) , 'help',"help.html")
        self.helppage.setHelpPage(helppath)
        
        self.settingswidget = SettingsWidget(self.stack)
        
        self.projectwidget = ProjectsWidget()   
        self.projectwidget.requestOpenProject.connect(self.loadProject)
        self.stack.addWidget(wid)
        self.stack.addWidget(self.projectwidget)
        self.stack.addWidget(self.helppage)
        self.stack.addWidget(self.settingswidget)
                
        sys.excepthook = self.excepthook

        def createSpacer(width=30):
            widget = QWidget()
            widget.setMinimumWidth(width)
            return widget

        self.createToolBars()
        self.createActions()

        spacewidget = createSpacer(60)
        gpsspacewidget = createSpacer()
        gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.moveaction.toggled.connect(functools.partial(self.setMapTool, self.movetool))
        self.infoaction.toggled.connect(functools.partial(self.setMapTool, self.infotool))
        
        showediting = (functools.partial(self.editingtoolbar.showToolbar, 
                                         self.editingmodeaction,
                                         self.moveaction))
        self.editingmodeaction.toggled.connect(showediting)

        self.addatgpsaction.triggered.connect(self.addAtGPS)
        self.addatgpsaction.setEnabled(self.gpsAction.isConnected)
        self.gpsAction.gpsfixed.connect(self.addatgpsaction.setEnabled)

        self.editingtoolbar.addToActionGroup(self.moveaction)

        self.actionGroup.addAction(self.editingmodeaction)
        self.actionGroup.addAction(self.editattributesaction)
        self.actionGroup.addAction(self.infoaction)

        self.homeAction.triggered.connect(self.zoomToDefaultView)
        
        self.openProjectAction.triggered.connect(self.showOpenProjectDialog)
        self.openProjectAction.triggered.connect(functools.partial(self.stack.setCurrentIndex, 1))
        
        self.configAction.triggered.connect(functools.partial(self.stack.setCurrentIndex, 3))
        self.configAction.triggered.connect(self.settingswidget.populateControls)
        self.configAction.triggered.connect(self.settingswidget.readSettings)
        
        self.toggleRasterAction.triggered.connect(self.toggleRasterLayers)

        self.navtoolbar.insertAction(self.iface.actionZoomIn(), self.iface.actionTouch())
        self.navtoolbar.insertAction(self.iface.actionTouch(), self.homeAction)
        self.navtoolbar.insertAction(self.iface.actionTouch(), self.iface.actionZoomFullExtent())
        self.navtoolbar.insertAction(self.homeAction, self.iface.actionZoomFullExtent())

        self.navtoolbar.addAction(self.toggleRasterAction)
        self.navtoolbar.insertWidget(self.iface.actionZoomFullExtent(), spacewidget)
        self.toolbar.addAction(self.infoaction)
        self.toolbar.addAction(self.editingmodeaction)
        self.toolbar.addAction(self.editattributesaction)
        self.toolbar.addAction(self.syncAction)
        self.toolbar.addAction(self.gpsAction)
        self.toolbar.insertWidget(self.syncAction, gpsspacewidget)
        self.toolbar.insertSeparator(self.gpsAction)

        self.extraaddtoolbar.addAction(self.addatgpsaction)

        self.editingtoolbar.addAction(self.moveaction)
        
        self.mapview = QAction(QIcon(":/icons/map"), "Map", self.menutoolbar)
        self.mapview.setCheckable(True)
        self.mapview.triggered.connect(functools.partial(self.stack.setCurrentIndex, 0))
        
        self.help = QAction(QIcon(":/icons/help"), "Help", self.menutoolbar)
        self.help.setCheckable(True)
        self.help.triggered.connect(functools.partial(self.stack.setCurrentIndex, 2))
        self.help.setVisible(False)
        
        self.projectlabel = QLabel("Project: <br> None")
        self.projectlabel.setAlignment(Qt.AlignCenter)
        self.projectlabel.setStyleSheet("""
            QLabel {
                    color: #8c8c8c;
                    font: 10px "Calibri" ;
                    }""")

        self.userlabel = QLabel("User: <br> {user}".format(user=getpass.getuser()))
        self.userlabel.setAlignment(Qt.AlignCenter)
        self.userlabel.setStyleSheet("""
            QLabel {
                    color: #8c8c8c;
                    font: 10px "Calibri" ;
                    }""")
        
        self.quit = QAction(QIcon(":/icons/quit"), "Quit", self.menutoolbar)
        self.quit.triggered.connect(self.iface.actionExit().trigger)

        self.menuGroup.addAction(self.mapview)
        self.menuGroup.addAction(self.openProjectAction)
        self.menuGroup.addAction(self.help)
        self.menuGroup.addAction(self.configAction)
        
        self.menutoolbar.addAction(self.mapview)
        self.menutoolbar.addAction(self.openProjectAction)
        self.menutoolbar.addAction(self.help)
        self.menutoolbar.addAction(self.configAction)
        self.menutoolbar.addAction(self.quit)
        
        quitspacewidget = createSpacer()
        quitspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        labelaction = self.menutoolbar.insertWidget(self.configAction, self.userlabel)
        
        self.menutoolbar.insertWidget(labelaction, quitspacewidget)
        self.menutoolbar.insertWidget(labelaction, self.projectlabel)
        self.setupIcons()
        self.stack.currentChanged.connect(self.updateUIState)
        
    def updateUIState(self, page):
        """
        Update the UI state to reflect the currently selected
        page in the stacked widget
        """
        def setToolbarsActive(enabled):
            toolbars = self.mainwindow.findChildren(QToolBar)
            for toolbar in toolbars:
                if toolbar == self.menutoolbar:
                    continue
                toolbar.setEnabled(enabled)
        
        def setPanelsVisible(visible):
            for panel in self.panels:
                panel.setVisible(visible)
                
        ismapview = page == 0
        setToolbarsActive(ismapview)
        setPanelsVisible(ismapview)
        self.infodock.hide()

    def addAtGPS(self):
        """
        Add a record at the current GPS location.
        """
        action = self.actionGroup.checkedAction()
        if not action:
            return
        layer = action.data()
        if not layer:
            return
        
        point = self.gpsAction.position
        self.addNewFeature(layer=layer, geometry=point)
        
    def zoomToDefaultView(self):
        """
        Zoom the mapview canvas to the extents the project was opened at i.e. the
        default extent.
        """
        self.iface.mapCanvas().setExtent(self.defaultextent)
        self.iface.mapCanvas().refresh()

    def toggleRasterLayers(self):
        """
        Toggle all raster layers on or off.
        """
        legend = self.iface.legendInterface()
        #Freeze the canvas to save on UI refresh
        self.iface.mapCanvas().freeze()
        for layer in self._mapLayers.values():
            if layer.type() == QgsMapLayer.RasterLayer:
                isvisible = legend.isLayerVisible(layer)
                legend.setLayerVisible(layer, not isvisible)
        self.iface.mapCanvas().freeze(False)
        self.iface.mapCanvas().refresh()

    def setupIcons(self):
        """
        Update toolbars to have text and icons, change normal QGIS
        icons to new style
        """
        toolbars = self.mainwindow.findChildren(QToolBar)
        for toolbar in toolbars:
            toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            toolbar.setIconSize(QSize(32, 32))

        self.iface.actionTouch().setIconText("Pan")
        self.iface.actionTouch().setIcon(QIcon(":/icons/pan"))
        self.iface.actionZoomIn().setIcon(QIcon(":/icons/in"))
        self.iface.actionZoomOut().setIcon(QIcon(":/icons/out"))
        self.iface.actionPan().setIcon(QIcon(":/icons/pan"))
        self.iface.actionZoomFullExtent().setIcon(QIcon(":/icons/home"))
        self.iface.actionZoomFullExtent().setIconText("Home View")

        self.actionGroup.addAction(self.iface.actionZoomIn())
        self.actionGroup.addAction(self.iface.actionZoomOut())
        self.actionGroup.addAction(self.iface.actionTouch())

    def projectOpened(self):
        """
            Called when a new project is opened in QGIS.
        """
        for panel in self.panels:
            self.mainwindow.removeDockWidget(panel)
            del panel

        projectpath = QgsProject.instance().fileName()
        project = QMapProject(os.path.dirname(projectpath), self.iface)
        self.projectlabel.setText("Project: <br> {}".format(project.name))
        self.createFormButtons(projectlayers = project.getConfiguredLayers())
        
        # Enable the raster layers button only if the project contains a raster layer.
        hasrasters = any(layer.type() for layer in self._mapLayers.values())
        self.toggleRasterAction.setEnabled(hasrasters)
        self.defaultextent = self.iface.mapCanvas().extent()
        self.connectSyncProviders(project)
        
        # Show panels
        self.panels = list(project.getPanels())
        for panel in self.panels:
            self.mainwindow.addDockWidget(Qt.BottomDockWidgetArea , panel)
            
        self.iface.messageBar().popWidget()

    def captureLayer(self, layer):
        text = layer.icontext
        tool = layer.getMaptool(self.iface.mapCanvas())

        # Hack until I fix it later
        if isinstance(tool, PointTool):
            add = functools.partial(self.addNewFeature, qgslayer)
            tool.geometryComplete.connect(add)
        else:
            tool.finished.connect(self.openForm)
            tool.error.connect(functools.partial(self.showToolError, text))

        action = QAction(QIcon(layer.icon), text, self.mainwindow)
        action.setData(layer)
        action.setCheckable(True)
        action.toggled.connect(functools.partial(self.setMapTool, tool))

        self.toolbar.insertAction(self.editingmodeaction, action)

        if not tool.isEditTool():
            # Connect the GPS tools strip to the action pressed event.
            showgpstools = (functools.partial(self.extraaddtoolbar.showToolbar,
                                         action,
                                         None))

            action.toggled.connect(showgpstools)

        self.actionGroup.addAction(action)
        self.actions.append(action)

    def editLayer(self, layer):
        self.edittool.addLayer(layer.QGISLayer)
        self.edittool.searchRadius = 10

    def moveLayer(self, layer):
        self.movetool.addLayer(layer.QGISLayer)

    def createFormButtons(self, projectlayers):
        """
            Create buttons for each form that is definded
        """
        # Remove all the old buttons
        for action in self.actions:
            self.actionGroup.removeAction(action)
            self.toolbar.removeAction(action)
                
        self.edittool.layers = []
        self.movetool.layers = []
        capabilitityhandlers = { "capture" : self.captureLayer,
                                 "edit" : self.editLayer,
                                 "move" : self.moveLayer}

        for layer in projectlayers:
            try:
                qgslayer = QgsMapLayerRegistry.instance().mapLayersByName(layer.name)[0]
                if qgslayer.type() == QgsMapLayer.RasterLayer:
                    utils.log("We can't support raster layers for data entry")
                    continue
                       
                layer.QGISLayer = qgslayer
            except IndexError:
                utils.log("Layer {} not found in project".format(layer.name))
                continue

            for capability in layer.capabilities:
                try:
                    capabilitityhandlers[capability](layer)
                except NoMapToolConfigured:
                    utils.log("No map tool configured")
                    continue
                except ErrorInMapTool as error:
                    self.iface.messageBar().pushMessage("Error configuring map tool", error.message, level=QgsMessageBar.WARNING)
                    continue

    def showToolError(self, label, message):
        self.iface.messageBar().pushMessage(label, message, QgsMessageBar.WARNING)
            
    def openForm(self, layer, feature):
        if not layer.isEditable():
            layer.startEditing()

        self.band.setToGeometry(feature.geometry(), layer)
        self.dialogprovider.openDialog(feature=feature, layer=layer)
        self.band.reset()

    def addNewFeature(self, layer, geometry):
        fields = layer.pendingFields()
        
        feature = QgsFeature()
        feature.setGeometry( geometry )
        feature.initAttributes(fields.count())
        feature.setFields(fields)
        
        for indx in xrange(fields.count()):
            feature[indx] = layer.dataProvider().defaultValue(indx)

        self.openForm(layer, feature)

    def showOpenProjectDialog(self):
        """
        Show the project selection dialog.
        """
        self.stack.setCurrentIndex(1)
        self.infodock.hide()
        path = os.path.join(os.path.dirname(__file__), '..' , 'projects/')
        projects = getProjects(path, self.iface)
        self.projectwidget.loadProjectList(projects)
        
    def loadProject(self, project):
        """
        Load a project into QGIS.
        """
        utils.log(project)
        utils.log(project.name)
        utils.log(project.projectfile)
        utils.log(project.vaild)
        
        (passed, message) = project.onProjectLoad()
        
        if not passed:
            QMessageBox.warning(self.mainwindow, "Project Load Rejected", 
                                "Project couldn't be loaded because {}".format(message))
            return
        
        self.mapview.trigger()
        self.iface.newProject(False)        
        self.iface.mapCanvas().freeze()
        self.infodock.clearResults()
        # No idea why we have to set this each time.  Maybe QGIS deletes it for
        # some reason.
        self.badLayerHandler = BadLayerHandler(callback=self.missingLayers)
        QgsProject.instance().setBadLayerHandler( self.badLayerHandler )
        
        self.iface.messageBar().pushMessage("Project Loading","", QgsMessageBar.INFO)
        QApplication.processEvents()

        fileinfo = QFileInfo(project.projectfile)
        QgsProject.instance().read(fileinfo)

        self.iface.mapCanvas().updateScale()
        self.iface.mapCanvas().freeze(False)
        self.iface.mapCanvas().refresh()
        self.mainwindow.setWindowTitle("IntraMaps Roam: Mobile Data Collection")
        self.iface.projectRead.emit()
        
    def unload(self):
        del self.toolbar
        
    def connectSyncProviders(self, project):
        self.syncactionstoolbar.clear()
        
        syncactions = list(project.syncprovders())
        
        # Don't show the sync button if there is no sync providers
        if not syncactions:
            self.syncAction.setVisible(False)
            return
        
        self.syncAction.setVisible(True)
        
        for provider in syncactions:
            action = QAction(QIcon(":/icons/sync"), "Sync {}".format(provider.name), self.mainwindow)
            action.triggered.connect(functools.partial(self.syncProvider, provider))
            self.syncactionstoolbar.addAction(action)
        
        try:
            self.syncAction.toggled.disconnect()
        except TypeError:
            pass
        try:
            self.syncAction.triggered.disconnect()
        except TypeError:
            pass
        
        if len(syncactions) == 1:
            # If one provider is set then we just connect the main button.    
            self.syncAction.setCheckable(False)
            self.syncAction.setText("Sync")
            self.syncAction.triggered.connect(functools.partial(self.syncProvider, syncactions[0]))
        else:
            # the sync button because a sync menu
            self.syncAction.setCheckable(True)
            self.syncAction.setText("Sync Menu")
            showsyncoptions = (functools.partial(self.syncactionstoolbar.showToolbar, 
                                                 self.syncAction, None))
            self.syncAction.toggled.connect(showsyncoptions)

    def syncstarted(self):                   
        # Remove the old widget if it's still there.
        # I don't really like this. Seems hacky.
        try:
            self.iface.messageBar().popWidget(self.syncwidget)
        except RuntimeError:
            pass
        except AttributeError:
            pass
        
        self.iface.messageBar().findChildren(QToolButton)[0].setVisible(False)
        self.syncwidget = self.iface.messageBar().createMessage("Syncing", "Sync in progress", QIcon(":/icons/syncing"))
        button = QPushButton(self.syncwidget)
        button.setCheckable(True)
        button.setText("Status")
        button.setIcon(QIcon(":/icons/syncinfo"))
        button.toggled.connect(functools.partial(self.report.setVisible))
        pro = QProgressBar()
        pro.setMaximum(0)
        pro.setMinimum(0)
        self.syncwidget.layout().addWidget(pro)
        self.syncwidget.layout().addWidget(button)
        self.iface.messageBar().pushWidget(self.syncwidget, QgsMessageBar.INFO)
        
    def synccomplete(self):
        try:
            self.iface.messageBar().popWidget(self.syncwidget)
        except RuntimeError:
            pass
        
        stylesheet = ("QgsMessageBar { background-color: rgba(239, 255, 233); border: 0px solid #b9cfe4; } "
                     "QLabel,QTextEdit { color: #057f35; } ")
        
        closebutton = self.iface.messageBar().findChildren(QToolButton)[0]
        closebutton.setVisible(True)
        closebutton.clicked.connect(functools.partial(self.report.setVisible, False))
        self.syncwidget = self.iface.messageBar().createMessage("Syncing", "Sync Complete", QIcon(":/icons/syncdone"))
        button = QPushButton(self.syncwidget)
        button.setCheckable(True)
        button.setChecked(self.report.isVisible())
        button.setText("Sync Report")
        button.setIcon(QIcon(":/icons/syncinfo"))
        button.toggled.connect(functools.partial(self.report.setVisible))      
        pro = QProgressBar()
        pro.setMaximum(100)
        pro.setValue(100)
        self.syncwidget.layout().addWidget(pro)      
        self.syncwidget.layout().addWidget(button)
        self.iface.messageBar().pushWidget(self.syncwidget)
        self.iface.messageBar().setStyleSheet(stylesheet)
        self.iface.mapCanvas().refresh()
        
    def syncerror(self):
        try:
            self.iface.messageBar().popWidget(self.syncwidget)
        except RuntimeError:
            pass
        
        closebutton = self.iface.messageBar().findChildren(QToolButton)[0]
        closebutton.setVisible(True)
        closebutton.clicked.connect(functools.partial(self.report.setVisible, False))
        self.syncwidget = self.iface.messageBar().createMessage("Syncing", "Sync Error", QIcon(":/icons/syncfail"))
        button = QPushButton(self.syncwidget)
        button.setCheckable(True)
        button.setChecked(self.report.isVisible())
        button.setText("Sync Report")
        button.setIcon(QIcon(":/icons/syncinfo"))
        button.toggled.connect(functools.partial(self.report.setVisible))            
        self.syncwidget.layout().addWidget(button)
        self.iface.messageBar().pushWidget(self.syncwidget, QgsMessageBar.CRITICAL)
        self.iface.mapCanvas().refresh()
        
    def syncProvider(self, provider):
        self.syncAction.toggle()
        provider.syncStarted.connect(functools.partial(self.syncAction.setEnabled, False))
        provider.syncStarted.connect(self.syncstarted)
        
        provider.syncComplete.connect(self.synccomplete)
        provider.syncComplete.connect(functools.partial(self.syncAction.setEnabled, True))
        provider.syncComplete.connect(functools.partial(self.report.updateHTML))
        
        provider.syncMessage.connect(self.report.updateHTML)
        
        provider.syncError.connect(self.report.updateHTML)
        provider.syncError.connect(self.syncerror)
        provider.syncError.connect(functools.partial(self.syncAction.setEnabled, True))
        
        provider.startSync()
Example #50
0
class MetaSearchDialog(QDialog, BASE_CLASS):

    """main dialogue"""

    def __init__(self, iface):
        """init window"""

        QDialog.__init__(self)
        self.setupUi(self)

        self.iface = iface
        self.map = iface.mapCanvas()
        self.settings = QSettings()
        self.catalog = None
        self.catalog_url = None
        self.context = StaticContext()

        version = self.context.metadata.get('general', 'version')
        self.setWindowTitle('MetaSearch %s' % version)

        self.rubber_band = QgsRubberBand(self.map, True)  # True = a polygon
        self.rubber_band.setColor(QColor(255, 0, 0, 75))
        self.rubber_band.setWidth(5)

        # form inputs
        self.startfrom = 0
        self.maxrecords = 10
        self.timeout = 10
        self.constraints = []

        # Servers tab
        self.cmbConnectionsServices.activated.connect(self.save_connection)
        self.cmbConnectionsSearch.activated.connect(self.save_connection)
        self.btnServerInfo.clicked.connect(self.connection_info)
        self.btnAddDefault.clicked.connect(self.add_default_connections)
        self.btnCapabilities.clicked.connect(self.show_xml)
        self.tabWidget.currentChanged.connect(self.populate_connection_list)

        # server management buttons
        self.btnNew.clicked.connect(self.add_connection)
        self.btnEdit.clicked.connect(self.edit_connection)
        self.btnDelete.clicked.connect(self.delete_connection)
        self.btnLoad.clicked.connect(self.load_connections)
        self.btnSave.clicked.connect(save_connections)

        # Search tab
        self.treeRecords.itemSelectionChanged.connect(self.record_clicked)
        self.treeRecords.itemDoubleClicked.connect(self.show_metadata)
        self.btnSearch.clicked.connect(self.search)
        self.leKeywords.returnPressed.connect(self.search)
        # prevent dialog from closing upon pressing enter
        self.buttonBox.button(QDialogButtonBox.Close).setAutoDefault(False)
        # launch help from button
        self.buttonBox.helpRequested.connect(self.help)
        self.btnCanvasBbox.setAutoDefault(False)
        self.btnCanvasBbox.clicked.connect(self.set_bbox_from_map)
        self.btnGlobalBbox.clicked.connect(self.set_bbox_global)

        # navigation buttons
        self.btnFirst.clicked.connect(self.navigate)
        self.btnPrev.clicked.connect(self.navigate)
        self.btnNext.clicked.connect(self.navigate)
        self.btnLast.clicked.connect(self.navigate)

        self.btnAddToWms.clicked.connect(self.add_to_ows)
        self.btnAddToWfs.clicked.connect(self.add_to_ows)
        self.btnAddToWcs.clicked.connect(self.add_to_ows)
        self.btnShowXml.clicked.connect(self.show_xml)

        # settings
        self.radioTitleAsk.clicked.connect(self.set_ows_save_title_ask)
        self.radioTitleNoAsk.clicked.connect(self.set_ows_save_title_no_ask)
        self.radioTempName.clicked.connect(self.set_ows_save_temp_name)

        self.manageGui()

    def manageGui(self):
        """open window"""

        self.tabWidget.setCurrentIndex(0)
        self.populate_connection_list()
        self.btnCapabilities.setEnabled(False)
        self.spnRecords.setValue(
            self.settings.value('/MetaSearch/returnRecords', 10, int))

        key = '/MetaSearch/%s' % self.cmbConnectionsSearch.currentText()
        self.catalog_url = self.settings.value('%s/url' % key)

        self.set_bbox_global()

        self.reset_buttons()

        # get preferred connection save strategy from settings and set it
        save_strat = self.settings.value('/MetaSearch/ows_save_strategy',
                                         'title_ask')
        if save_strat == 'temp_name':
            self.radioTempName.setChecked(True)
        elif save_strat == 'title_no_ask':
            self.radioTitleNoAsk.setChecked(True)
        else:
            self.radioTitleAsk.setChecked(True)

        # install proxy handler if specified in QGIS settings
        self.install_proxy()

    # Servers tab

    def populate_connection_list(self):
        """populate select box with connections"""

        self.settings.beginGroup('/MetaSearch/')
        self.cmbConnectionsServices.clear()
        self.cmbConnectionsServices.addItems(self.settings.childGroups())
        self.cmbConnectionsSearch.clear()
        self.cmbConnectionsSearch.addItems(self.settings.childGroups())
        self.settings.endGroup()

        self.set_connection_list_position()

        if self.cmbConnectionsServices.count() == 0:
            # no connections - disable various buttons
            state_disabled = False
            self.btnSave.setEnabled(state_disabled)
            # and start with connection tab open
            self.tabWidget.setCurrentIndex(1)
            # tell the user to add services
            msg = self.tr('No services/connections defined. To get '
                          'started with MetaSearch, create a new '
                          'connection by clicking \'New\' or click '
                          '\'Add default services\'.')
            self.textMetadata.setHtml('<p><h3>%s</h3></p>' % msg)
        else:
            # connections - enable various buttons
            state_disabled = True

        self.btnServerInfo.setEnabled(state_disabled)
        self.btnEdit.setEnabled(state_disabled)
        self.btnDelete.setEnabled(state_disabled)

    def set_connection_list_position(self):
        """set the current index to the selected connection"""
        to_select = self.settings.value('/MetaSearch/selected')
        conn_count = self.cmbConnectionsServices.count()

        if conn_count == 0:
            self.btnDelete.setEnabled(False)
            self.btnServerInfo.setEnabled(False)
            self.btnEdit.setEnabled(False)

        # does to_select exist in cmbConnectionsServices?
        exists = False
        for i in range(conn_count):
            if self.cmbConnectionsServices.itemText(i) == to_select:
                self.cmbConnectionsServices.setCurrentIndex(i)
                self.cmbConnectionsSearch.setCurrentIndex(i)
                exists = True
                break

        # If we couldn't find the stored item, but there are some, default
        # to the last item (this makes some sense when deleting items as it
        # allows the user to repeatidly click on delete to remove a whole
        # lot of items)
        if not exists and conn_count > 0:
            # If to_select is null, then the selected connection wasn't found
            # by QSettings, which probably means that this is the first time
            # the user has used CSWClient, so default to the first in the list
            # of connetions. Otherwise default to the last.
            if not to_select:
                current_index = 0
            else:
                current_index = conn_count - 1

            self.cmbConnectionsServices.setCurrentIndex(current_index)
            self.cmbConnectionsSearch.setCurrentIndex(current_index)

    def save_connection(self):
        """save connection"""

        caller = self.sender().objectName()

        if caller == 'cmbConnectionsServices':  # servers tab
            current_text = self.cmbConnectionsServices.currentText()
        elif caller == 'cmbConnectionsSearch':  # search tab
            current_text = self.cmbConnectionsSearch.currentText()

        self.settings.setValue('/MetaSearch/selected', current_text)
        key = '/MetaSearch/%s' % current_text

        if caller == 'cmbConnectionsSearch':  # bind to service in search tab
            self.catalog_url = self.settings.value('%s/url' % key)

        if caller == 'cmbConnectionsServices':  # clear server metadata
            self.textMetadata.clear()

        self.btnCapabilities.setEnabled(False)

    def connection_info(self):
        """show connection info"""

        current_text = self.cmbConnectionsServices.currentText()
        key = '/MetaSearch/%s' % current_text
        self.catalog_url = self.settings.value('%s/url' % key)

        # connect to the server
        if not self._get_csw():
            return

        QApplication.restoreOverrideCursor()

        if self.catalog:  # display service metadata
            self.btnCapabilities.setEnabled(True)
            metadata = render_template('en', self.context,
                                       self.catalog,
                                       'service_metadata.html')
            style = QgsApplication.reportStyleSheet()
            self.textMetadata.clear()
            self.textMetadata.document().setDefaultStyleSheet(style)
            self.textMetadata.setHtml(metadata)

    def add_connection(self):
        """add new service"""

        conn_new = NewConnectionDialog()
        conn_new.setWindowTitle(self.tr('New Catalogue service'))
        if conn_new.exec_() == QDialog.Accepted:  # add to service list
            self.populate_connection_list()
        self.textMetadata.clear()

    def edit_connection(self):
        """modify existing connection"""

        current_text = self.cmbConnectionsServices.currentText()

        url = self.settings.value('/MetaSearch/%s/url' % current_text)

        conn_edit = NewConnectionDialog(current_text)
        conn_edit.setWindowTitle(self.tr('Edit Catalogue service'))
        conn_edit.leName.setText(current_text)
        conn_edit.leURL.setText(url)
        if conn_edit.exec_() == QDialog.Accepted:  # update service list
            self.populate_connection_list()

    def delete_connection(self):
        """delete connection"""

        current_text = self.cmbConnectionsServices.currentText()

        key = '/MetaSearch/%s' % current_text

        msg = self.tr('Remove service %s?') % current_text

        result = QMessageBox.information(self, self.tr('Confirm delete'), msg,
                                         QMessageBox.Ok | QMessageBox.Cancel)
        if result == QMessageBox.Ok:  # remove service from list
            self.settings.remove(key)
            index_to_delete = self.cmbConnectionsServices.currentIndex()
            self.cmbConnectionsServices.removeItem(index_to_delete)
            self.cmbConnectionsSearch.removeItem(index_to_delete)
            self.set_connection_list_position()

    def load_connections(self):
        """load services from list"""

        ManageConnectionsDialog(1).exec_()
        self.populate_connection_list()

    def add_default_connections(self):
        """add default connections"""

        filename = os.path.join(self.context.ppath,
                                'resources', 'connections-default.xml')
        doc = get_connections_from_file(self, filename)
        if doc is None:
            return

        self.settings.beginGroup('/MetaSearch/')
        keys = self.settings.childGroups()
        self.settings.endGroup()

        for server in doc.findall('csw'):
            name = server.attrib.get('name')
            # check for duplicates
            if name in keys:
                msg = self.tr('%s exists.  Overwrite?') % name
                res = QMessageBox.warning(self,
                                          self.tr('Loading connections'), msg,
                                          QMessageBox.Yes | QMessageBox.No)
                if res != QMessageBox.Yes:
                    continue

            # no dups detected or overwrite is allowed
            key = '/MetaSearch/%s' % name
            self.settings.setValue('%s/url' % key, server.attrib.get('url'))

        self.populate_connection_list()

    # Settings tab

    def set_ows_save_title_ask(self):
        """save ows save strategy as save ows title, ask if duplicate"""

        self.settings.setValue('/MetaSearch/ows_save_strategy', 'title_ask')

    def set_ows_save_title_no_ask(self):
        """save ows save strategy as save ows title, do NOT ask if duplicate"""

        self.settings.setValue('/MetaSearch/ows_save_strategy', 'title_no_ask')

    def set_ows_save_temp_name(self):
        """save ows save strategy as save with a temporary name"""

        self.settings.setValue('/MetaSearch/ows_save_strategy', 'temp_name')

    # Search tab

    def set_bbox_from_map(self):
        """set bounding box from map extent"""

        crs = self.map.mapRenderer().destinationCrs()
        crsid = int(crs.authid().split(':')[1])

        extent = self.map.extent()

        if crsid != 4326:  # reproject to EPSG:4326
            src = QgsCoordinateReferenceSystem(crsid)
            dest = QgsCoordinateReferenceSystem(4326)
            xform = QgsCoordinateTransform(src, dest)
            minxy = xform.transform(QgsPoint(extent.xMinimum(),
                                             extent.yMinimum()))
            maxxy = xform.transform(QgsPoint(extent.xMaximum(),
                                             extent.yMaximum()))
            minx, miny = minxy
            maxx, maxy = maxxy
        else:  # 4326
            minx = extent.xMinimum()
            miny = extent.yMinimum()
            maxx = extent.xMaximum()
            maxy = extent.yMaximum()

        self.leNorth.setText(unicode(maxy)[0:9])
        self.leSouth.setText(unicode(miny)[0:9])
        self.leWest.setText(unicode(minx)[0:9])
        self.leEast.setText(unicode(maxx)[0:9])

    def set_bbox_global(self):
        """set global bounding box"""
        self.leNorth.setText('90')
        self.leSouth.setText('-90')
        self.leWest.setText('-180')
        self.leEast.setText('180')

    def search(self):
        """execute search"""

        self.catalog = None
        self.constraints = []

        # clear all fields and disable buttons
        self.lblResults.clear()
        self.treeRecords.clear()

        self.reset_buttons()

        # save some settings
        self.settings.setValue('/MetaSearch/returnRecords',
                               self.spnRecords.cleanText())

        # set current catalogue
        current_text = self.cmbConnectionsSearch.currentText()
        key = '/MetaSearch/%s' % current_text
        self.catalog_url = self.settings.value('%s/url' % key)

        # start position and number of records to return
        self.startfrom = 0
        self.maxrecords = self.spnRecords.value()

        # set timeout
        self.timeout = self.spnTimeout.value()

        # bbox
        minx = self.leWest.text()
        miny = self.leSouth.text()
        maxx = self.leEast.text()
        maxy = self.leNorth.text()
        bbox = [minx, miny, maxx, maxy]

        # only apply spatial filter if bbox is not global
        # even for a global bbox, if a spatial filter is applied, then
        # the CSW server will skip records without a bbox
        if bbox != ['-180', '-90', '180', '90']:
            self.constraints.append(BBox(bbox))

        # keywords
        if self.leKeywords.text():
            # TODO: handle multiple word searches
            keywords = self.leKeywords.text()
            self.constraints.append(PropertyIsLike('csw:AnyText', keywords))

        if len(self.constraints) > 1:  # exclusive search (a && b)
            self.constraints = [self.constraints]

        # build request
        if not self._get_csw():
            return

        # TODO: allow users to select resources types
        # to find ('service', 'dataset', etc.)
        try:
            self.catalog.getrecords2(constraints=self.constraints,
                                     maxrecords=self.maxrecords, esn='full')
        except ExceptionReport as err:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, self.tr('Search error'),
                                self.tr('Search error: %s') % err)
            return
        except Exception as err:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, self.tr('Connection error'),
                                self.tr('Connection error: %s') % err)
            return

        if self.catalog.results['matches'] == 0:
            QApplication.restoreOverrideCursor()
            self.lblResults.setText(self.tr('0 results'))
            return

        QApplication.restoreOverrideCursor()
        self.display_results()

    def display_results(self):
        """display search results"""

        self.treeRecords.clear()

        position = self.catalog.results['returned'] + self.startfrom

        msg = self.tr('Showing %d - %d of %n result(s)', 'number of results',
                      self.catalog.results['matches']) % (self.startfrom + 1,
                                                          position)

        self.lblResults.setText(msg)

        for rec in self.catalog.records:
            item = QTreeWidgetItem(self.treeRecords)
            if self.catalog.records[rec].type:
                item.setText(0, normalize_text(self.catalog.records[rec].type))
            else:
                item.setText(0, 'unknown')
            if self.catalog.records[rec].title:
                item.setText(1,
                             normalize_text(self.catalog.records[rec].title))
            if self.catalog.records[rec].identifier:
                set_item_data(item, 'identifier',
                              self.catalog.records[rec].identifier)

        self.btnShowXml.setEnabled(True)

        if self.catalog.results["matches"] < self.maxrecords:
            disabled = False
        else:
            disabled = True

        self.btnFirst.setEnabled(disabled)
        self.btnPrev.setEnabled(disabled)
        self.btnNext.setEnabled(disabled)
        self.btnLast.setEnabled(disabled)

    def record_clicked(self):
        """record clicked signal"""

        # disable only service buttons
        self.reset_buttons(True, False, False)

        if not self.treeRecords.selectedItems():
            return

        item = self.treeRecords.currentItem()
        if not item:
            return

        identifier = get_item_data(item, 'identifier')
        try:
            record = self.catalog.records[identifier]
        except KeyError as err:
            QMessageBox.warning(self,
                                self.tr('Record parsing error'),
                                'Unable to locate record identifier')
            return

        # if the record has a bbox, show a footprint on the map
        if record.bbox is not None:
            points = bbox_to_polygon(record.bbox)
            if points is not None:
                src = QgsCoordinateReferenceSystem(4326)
                dst = self.map.mapSettings().destinationCrs()
                geom = QgsGeometry.fromPolygon(points)
                if src.postgisSrid() != dst.postgisSrid():
                    ctr = QgsCoordinateTransform(src, dst)
                    try:
                        geom.transform(ctr)
                    except Exception as err:
                        QMessageBox.warning(
                            self,
                            self.tr('Coordinate Transformation Error'),
                            unicode(err))
                self.rubber_band.setToGeometry(geom, None)

        # figure out if the data is interactive and can be operated on
        self.find_services(record, item)

    def find_services(self, record, item):
        """scan record for WMS/WMTS|WFS|WCS endpoints"""

        links = record.uris + record.references

        services = {}
        for link in links:

            if 'scheme' in link:
                link_type = link['scheme']
            elif 'protocol' in link:
                link_type = link['protocol']
            else:
                link_type = None

            if link_type is not None:
                link_type = link_type.upper()

            wmswmst_link_types = map(str.upper, link_types.WMSWMST_LINK_TYPES)
            wfs_link_types = map(str.upper, link_types.WFS_LINK_TYPES)
            wcs_link_types = map(str.upper, link_types.WCS_LINK_TYPES)

            # if the link type exists, and it is one of the acceptable
            # interactive link types, then set
            if all([link_type is not None,
                    link_type in wmswmst_link_types + wfs_link_types +
                    wcs_link_types]):
                if link_type in wmswmst_link_types:
                    services['wms'] = link['url']
                    self.btnAddToWms.setEnabled(True)
                if link_type in wfs_link_types:
                    services['wfs'] = link['url']
                    self.btnAddToWfs.setEnabled(True)
                if link_type in wcs_link_types:
                    services['wcs'] = link['url']
                    self.btnAddToWcs.setEnabled(True)

            set_item_data(item, 'link', json.dumps(services))

    def navigate(self):
        """manage navigation / paging"""

        caller = self.sender().objectName()

        if caller == 'btnFirst':
            self.startfrom = 0
        elif caller == 'btnLast':
            self.startfrom = self.catalog.results['matches'] - self.maxrecords
        elif caller == 'btnNext':
            self.startfrom += self.maxrecords
            if self.startfrom >= self.catalog.results["matches"]:
                msg = self.tr('End of results. Go to start?')
                res = QMessageBox.information(self, self.tr('Navigation'),
                                              msg,
                                              (QMessageBox.Ok |
                                               QMessageBox.Cancel))
                if res == QMessageBox.Ok:
                    self.startfrom = 0
                else:
                    return
        elif caller == "btnPrev":
            self.startfrom -= self.maxrecords
            if self.startfrom <= 0:
                msg = self.tr('Start of results. Go to end?')
                res = QMessageBox.information(self, self.tr('Navigation'),
                                              msg,
                                              (QMessageBox.Ok |
                                               QMessageBox.Cancel))
                if res == QMessageBox.Ok:
                    self.startfrom = (self.catalog.results['matches'] -
                                      self.maxrecords)
                else:
                    return

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        try:
            self.catalog.getrecords2(constraints=self.constraints,
                                     maxrecords=self.maxrecords,
                                     startposition=self.startfrom, esn='full')
        except ExceptionReport as err:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, self.tr('Search error'),
                                self.tr('Search error: %s') % err)
            return
        except Exception as err:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, self.tr('Connection error'),
                                self.tr('Connection error: %s') % err)
            return

        QApplication.restoreOverrideCursor()

        self.display_results()

    def add_to_ows(self):
        """add to OWS provider connection list"""

        conn_name_matches = []

        item = self.treeRecords.currentItem()

        if not item:
            return

        item_data = json.loads(get_item_data(item, 'link'))

        caller = self.sender().objectName()

        # stype = human name,/Qgis/connections-%s,providername
        if caller == 'btnAddToWms':
            stype = ['OGC:WMS/OGC:WMTS', 'wms', 'wms']
            data_url = item_data['wms']
        elif caller == 'btnAddToWfs':
            stype = ['OGC:WFS', 'wfs', 'WFS']
            data_url = item_data['wfs']
        elif caller == 'btnAddToWcs':
            stype = ['OGC:WCS', 'wcs', 'wcs']
            data_url = item_data['wcs']

        QApplication.restoreOverrideCursor()

        sname = '%s from MetaSearch' % stype[1]

        # store connection
        # check if there is a connection with same name
        self.settings.beginGroup('/Qgis/connections-%s' % stype[1])
        keys = self.settings.childGroups()
        self.settings.endGroup()

        for key in keys:
            if key.startswith(sname):
                conn_name_matches.append(key)
        if conn_name_matches:
            sname = conn_name_matches[-1]

        # check for duplicates
        if sname in keys:  # duplicate found
            if self.radioTitleAsk.isChecked():  # ask to overwrite
                msg = self.tr('Connection %s exists. Overwrite?') % sname
                res = QMessageBox.warning(self, self.tr('Saving server'), msg,
                                          QMessageBox.Yes | QMessageBox.No)
                if res != QMessageBox.Yes:  # assign new name with serial
                    sname = serialize_string(sname)
            elif self.radioTitleNoAsk.isChecked():  # don't ask to overwrite
                pass
            elif self.radioTempName.isChecked():  # use temp name
                sname = serialize_string(sname)

        # no dups detected or overwrite is allowed
        self.settings.beginGroup('/Qgis/connections-%s' % stype[1])
        self.settings.setValue('/%s/url' % sname, data_url)
        self.settings.endGroup()

        # open provider window
        ows_provider = QgsProviderRegistry.instance().selectWidget(stype[2],
                                                                   self)

        service_type = stype[0]

        # connect dialog signals to iface slots
        if service_type == 'OGC:WMS/OGC:WMTS':
            ows_provider.addRasterLayer.connect(self.iface.addRasterLayer)
            conn_cmb = ows_provider.findChild(QWidget, 'cmbConnections')
            connect = 'on_btnConnect_clicked'
        elif service_type == 'OGC:WFS':
            ows_provider.addWfsLayer.connect(self.iface.mainWindow().addWfsLayer)
            conn_cmb = ows_provider.findChild(QWidget, 'cmbConnections')
            connect = 'connectToServer'
        elif service_type == 'OGC:WCS':
            ows_provider.addRasterLayer.connect(self.iface.addRasterLayer)
            conn_cmb = ows_provider.findChild(QWidget, 'mConnectionsComboBox')
            connect = 'on_mConnectButton_clicked'
        ows_provider.setModal(False)
        ows_provider.show()

        # open provider dialogue against added OWS
        index = conn_cmb.findText(sname)
        if index > -1:
            conn_cmb.setCurrentIndex(index)
            # only for wfs
            if service_type == 'OGC:WFS':
                ows_provider.on_cmbConnections_activated(index)
        getattr(ows_provider, connect)()

    def show_metadata(self):
        """show record metadata"""

        if not self.treeRecords.selectedItems():
            return

        item = self.treeRecords.currentItem()
        if not item:
            return

        identifier = get_item_data(item, 'identifier')

        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            cat = CatalogueServiceWeb(self.catalog_url, timeout=self.timeout)
            cat.getrecordbyid(
                [self.catalog.records[identifier].identifier])
        except ExceptionReport as err:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self, self.tr('GetRecords error'),
                                self.tr('Error getting response: %s') % err)
            return
        except KeyError as err:
            QMessageBox.warning(self,
                                self.tr('Record parsing error'),
                                'Unable to locate record identifier')
            QApplication.restoreOverrideCursor()
            return

        QApplication.restoreOverrideCursor()

        record = cat.records[identifier]
        record.xml_url = cat.request

        crd = RecordDialog()
        metadata = render_template('en', self.context,
                                   record, 'record_metadata_dc.html')

        style = QgsApplication.reportStyleSheet()
        crd.textMetadata.document().setDefaultStyleSheet(style)
        crd.textMetadata.setHtml(metadata)
        crd.exec_()

    def show_xml(self):
        """show XML request / response"""

        crd = XMLDialog()
        request_html = highlight_xml(self.context, self.catalog.request)
        response_html = highlight_xml(self.context, self.catalog.response)
        style = QgsApplication.reportStyleSheet()
        crd.txtbrXMLRequest.clear()
        crd.txtbrXMLResponse.clear()
        crd.txtbrXMLRequest.document().setDefaultStyleSheet(style)
        crd.txtbrXMLResponse.document().setDefaultStyleSheet(style)
        crd.txtbrXMLRequest.setHtml(request_html)
        crd.txtbrXMLResponse.setHtml(response_html)
        crd.exec_()

    def reset_buttons(self, services=True, xml=True, navigation=True):
        """Convenience function to disable WMS/WMTS|WFS|WCS buttons"""

        if services:
            self.btnAddToWms.setEnabled(False)
            self.btnAddToWfs.setEnabled(False)
            self.btnAddToWcs.setEnabled(False)

        if xml:
            self.btnShowXml.setEnabled(False)

        if navigation:
            self.btnFirst.setEnabled(False)
            self.btnPrev.setEnabled(False)
            self.btnNext.setEnabled(False)
            self.btnLast.setEnabled(False)

    def help(self):
        """launch help"""

        open_url(get_help_url())

    def reject(self):
        """back out of dialogue"""

        QDialog.reject(self)
        self.rubber_band.reset()

    def _get_csw(self):
        """convenience function to init owslib.csw.CatalogueServiceWeb"""

        # connect to the server
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            self.catalog = CatalogueServiceWeb(self.catalog_url,
                                               timeout=self.timeout)
            return True
        except ExceptionReport as err:
            msg = self.tr('Error connecting to service: %s') % err
        except ValueError as err:
            msg = self.tr('Value Error: %s') % err
        except Exception as err:
            msg = self.tr('Unknown Error: %s') % err

        QMessageBox.warning(self, self.tr('CSW Connection error'), msg)
        QApplication.restoreOverrideCursor()
        return False

    def install_proxy(self):
        """set proxy if one is set in QGIS network settings"""

        # initially support HTTP for now
        if self.settings.value('/proxy/proxyEnabled') == 'true':
            if self.settings.value('/proxy/proxyType') == 'HttpProxy':
                ptype = 'http'
            else:
                return

            user = self.settings.value('/proxy/proxyUser')
            password = self.settings.value('/proxy/proxyPassword')
            host = self.settings.value('/proxy/proxyHost')
            port = self.settings.value('/proxy/proxyPort')

            proxy_up = ''
            proxy_port = ''

            if all([user != '', password != '']):
                proxy_up = '%s:%s@' % (user, password)

            if port != '':
                proxy_port = ':%s' % port

            conn = '%s://%s%s%s' % (ptype, proxy_up, host, proxy_port)
            install_opener(build_opener(ProxyHandler({ptype: conn})))
Example #51
0
class MapWidget(Ui_CanvasWidget, QMainWindow):
    def __init__(self, parent=None):
        super(MapWidget, self).__init__(parent)
        self.setupUi(self)

        self.firstshow = True
        self.layerbuttons = []
        self.editfeaturestack = []
        self.lastgpsposition = None
        self.project = None
        self.gps = None
        self.gpslogging = None
        self.selectionbands = defaultdict(partial(QgsRubberBand, self.canvas))

        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)

        if hasattr(self.canvas, 'setParallelRenderingEnabled'):
            self.canvas.setParallelRenderingEnabled(True)

        pal = QgsPalLabeling()
        self.canvas.mapRenderer().setLabelingEngine(pal)
        self.canvas.setFrameStyle(QFrame.NoFrame)

        self.editgroup = QActionGroup(self)
        self.editgroup.setExclusive(True)
        self.editgroup.addAction(self.actionPan)
        self.editgroup.addAction(self.actionZoom_In)
        self.editgroup.addAction(self.actionZoom_Out)
        self.editgroup.addAction(self.actionInfo)

        self.actionGPS = GPSAction(":/icons/gps", self.canvas, self)
        self.projecttoolbar.addAction(self.actionGPS)

        gpsspacewidget= QWidget()
        gpsspacewidget.setMinimumWidth(30)
        gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.topspaceraction = self.projecttoolbar.insertWidget(self.actionGPS, gpsspacewidget)

        self.dataentryselection = QAction(self.projecttoolbar)
        self.dataentryaction = self.projecttoolbar.insertAction(self.topspaceraction, self.dataentryselection)
        self.dataentryselection.triggered.connect(self.select_data_entry)

        self.marker = GPSMarker(self.canvas)
        self.marker.hide()

        self.currentfeatureband = QgsRubberBand(self.canvas)
        self.currentfeatureband.setIconSize(20)
        self.currentfeatureband.setWidth(10)
        self.currentfeatureband.setColor(QColor(186, 93, 212, 76))

        self.gpsband = QgsRubberBand(self.canvas)
        self.gpsband.setColor(QColor(0, 0, 212, 76))
        self.gpsband.setWidth(5)

        RoamEvents.editgeometry.connect(self.queue_feature_for_edit)
        RoamEvents.selectioncleared.connect(self.clear_selection)
        RoamEvents.selectionchanged.connect(self.highlight_selection)
        RoamEvents.featureformloaded.connect(self.feature_form_loaded)

        self.connectButtons()

    def init_qgisproject(self, doc):
        parser = ProjectParser(doc)
        canvasnode = parser.canvasnode
        self.canvas.freeze()
        self.canvas.mapRenderer().readXML(canvasnode)
        self.canvaslayers = parser.canvaslayers()
        self.canvas.setLayerSet(self.canvaslayers)
        #red = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorRedPart", 255 )[0];
        #green = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorGreenPart", 255 )[0];
        #blue = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorBluePart", 255 )[0];
        #color = QColor(red, green, blue);
        #self.canvas.setCanvasColor(color)
        self.canvas.updateScale()
        return self.canvas.mapRenderer().destinationCrs()

    def showEvent(self, *args, **kwargs):
        if self.firstshow:
            self.canvas.refresh()
            self.canvas.repaint()
            self.firstshow = False

    def feature_form_loaded(self, form, feature, project, editmode):
        self.currentfeatureband.setToGeometry(feature.geometry(), form.QGISLayer)

    def highlight_selection(self, results):
        self.clear_selection()
        for layer, features in results.iteritems():
            band = self.selectionbands[layer]
            band.setColor(QColor(255, 0, 0, 200))
            band.setIconSize(20)
            band.setWidth(2)
            band.setBrushStyle(Qt.NoBrush)
            band.reset(layer.geometryType())
            for feature in features:
                band.addGeometry(feature.geometry(), layer)

    def highlight_active_selection(self, layer, feature, features):
        self.clear_selection()
        self.highlight_selection({layer: features})
        self.currentfeatureband.setToGeometry(feature.geometry(), layer)

    def clear_selection(self):
        # Clear the main selection rubber band
        self.currentfeatureband.reset()
        # Clear the rest
        for band in self.selectionbands.itervalues():
            band.reset()

        self.editfeaturestack = []

    def queue_feature_for_edit(self, form, feature):
        def trigger_default_action():
            for action in self.projecttoolbar.actions():
                if action.property('dataentry') and action.isdefault:
                    action.trigger()
                    break

        self.editfeaturestack.append((form, feature))
        self.load_form(form)
        trigger_default_action()

    def clear_temp_objects(self):
        def clear_tool_band():
            """
            Clear the rubber band of the active tool if it has one
            """
            tool = self.canvas.mapTool()
            try:
                tool.clearBand()
            except AttributeError:
                # No clearBand method found, but that's cool.
                pass

        self.currentfeatureband.reset()
        clear_tool_band()


    def settings_updated(self, settings):
        self.actionGPS.updateGPSPort()
        gpslogging = settings.get('gpslogging', True)
        if self.gpslogging:
            self.gpslogging.logging = gpslogging

    def set_gps(self, gps, logging):
        self.gps = gps
        self.gpslogging = logging
        self.gps.gpsposition.connect(self.gps_update_canvas)
        self.gps.firstfix.connect(self.gps_first_fix)
        self.gps.gpsdisconnected.connect(self.gps_disconnected)

    def gps_update_canvas(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if self.gpslogging.logging:
            self.gpsband.addPoint(position)
            self.gpsband.show()

        if roam.config.settings.get('gpscenter', True):
            if not self.lastgpsposition == position:
                self.lastposition = position
                rect = QgsRectangle(position, position)
                extentlimt = QgsRectangle(self.canvas.extent())
                extentlimt.scale(0.95)

                if not extentlimt.contains(position):
                    self.zoom_to_location(position)

        self.marker.show()
        self.marker.setCenter(position)

    def gps_first_fix(self, postion, gpsinfo):
        zoomtolocation = roam.config.settings.get('gpszoomonfix', True)
        if zoomtolocation:
            self.canvas.zoomScale(1000)
            self.zoom_to_location(postion)

    def zoom_to_location(self, position):
        rect = QgsRectangle(position, position)
        self.canvas.setExtent(rect)
        self.canvas.refresh()

    def gps_disconnected(self):
        self.marker.hide()

    def select_data_entry(self):
        def showformerror(form):
            pass

        def actions():
            for form in self.project.forms:
                action = form.createuiaction()
                valid, failreasons = form.valid
                if not valid:
                    roam.utils.warning("Form {} failed to load".format(form.label))
                    roam.utils.warning("Reasons {}".format(failreasons))
                    action.triggered.connect(partial(showformerror, form))
                else:
                    action.triggered.connect(partial(self.load_form, form))
                yield action

        formpicker = PickActionDialog(msg="Select data entry form")
        formpicker.addactions(actions())
        formpicker.exec_()

    def project_loaded(self, project):
        self.project = project
        self.actionPan.trigger()
        try:
            firstform = project.forms[0]
            self.load_form(firstform)
            self.dataentryselection.setVisible(True)
        except IndexError:
            self.dataentryselection.setVisible(False)

        # Enable the raster layers button only if the project contains a raster layer.
        layers = QgsMapLayerRegistry.instance().mapLayers().values()
        hasrasters = any(layer.type() == QgsMapLayer.RasterLayer for layer in layers)
        self.actionRaster.setEnabled(hasrasters)
        self.defaultextent = self.canvas.extent()
        roam.utils.info("Extent: {}".format(self.defaultextent.toString()))

        self.infoTool.selectionlayers = project.selectlayersmapping()

        self.canvas.freeze(False)
        self.canvas.refresh()

    def setMapTool(self, tool, *args):
        self.canvas.setMapTool(tool)

    def connectButtons(self):
        def connectAction(action, tool):
            action.toggled.connect(partial(self.setMapTool, tool))

        def cursor(name):
            pix = QPixmap(name)
            pix = pix.scaled(QSize(24,24))
            return QCursor(pix)

        self.zoomInTool = QgsMapToolZoom(self.canvas, False)
        self.zoomOutTool = QgsMapToolZoom(self.canvas, True)
        self.panTool = PanTool(self.canvas)
        self.infoTool = InfoTool(self.canvas)

        connectAction(self.actionZoom_In, self.zoomInTool)
        connectAction(self.actionZoom_Out, self.zoomOutTool)
        connectAction(self.actionPan, self.panTool)
        connectAction(self.actionInfo, self.infoTool)

        self.zoomInTool.setCursor(cursor(':/icons/in'))
        self.zoomOutTool.setCursor(cursor(':/icons/out'))
        self.infoTool.setCursor(cursor(':/icons/info'))

        self.actionRaster.triggered.connect(self.toggleRasterLayers)

        self.infoTool.infoResults.connect(RoamEvents.selectionchanged.emit)

        self.actionHome.triggered.connect(self.homeview)

    def homeview(self):
        """
        Zoom the mapview canvas to the extents the project was opened at i.e. the
        default extent.
        """
        self.canvas.setExtent(self.defaultextent)
        self.canvas.refresh()

    def load_form(self, form):
        self.clearCapatureTools()
        self.dataentryselection.setIcon(QIcon(form.icon))
        self.dataentryselection.setText(form.icontext)
        self.create_capture_buttons(form)

    def create_capture_buttons(self, form):
        tool = form.getMaptool()(self.canvas)
        for action in tool.actions:
            # Create the action here.
            if action.ismaptool:
                action.toggled.connect(partial(self.setMapTool, tool))

            # Set the action as a data entry button so we can remove it later.
            action.setProperty("dataentry", True)
            self.editgroup.addAction(action)
            self.layerbuttons.append(action)
            self.projecttoolbar.insertAction(self.topspaceraction, action)
            action.setChecked(action.isdefault)

        if hasattr(tool, 'geometryComplete'):
            add = partial(self.add_new_feature, form)
            tool.geometryComplete.connect(add)
        else:
            tool.finished.connect(self.openForm)
            tool.error.connect(partial(self.showUIMessage, form.label))

    def add_new_feature(self, form, geometry):
        """
        Add a new new feature to the given layer
        """
        # TODO Extract into function.
        # NOTE This function is doing too much, acts as add and also edit.
        layer = form.QGISLayer
        if layer.geometryType() in [QGis.WKBMultiLineString, QGis.WKBMultiPoint, QGis.WKBMultiPolygon]:
            geometry.convertToMultiType()

        try:
            form, feature = self.editfeaturestack.pop()
            self.editfeaturegeometry(form, feature, newgeometry=geometry)
            return
        except IndexError:
            pass

        layer = form.QGISLayer
        fields = layer.pendingFields()

        feature = QgsFeature(fields)
        feature.setGeometry(geometry)

        for index in xrange(fields.count()):
            pkindexes = layer.dataProvider().pkAttributeIndexes()
            if index in pkindexes and layer.dataProvider().name() == 'spatialite':
                continue

            value = layer.dataProvider().defaultValue(index)
            feature[index] = value

        RoamEvents.open_feature_form(form, feature, editmode=False)

    def editfeaturegeometry(self, form, feature, newgeometry):
        # TODO Extract into function.
        layer = form.QGISLayer
        layer.startEditing()
        feature.setGeometry(newgeometry)
        layer.updateFeature(feature)
        saved = layer.commitChanges()
        if not saved:
            map(roam.utils.error, layer.commitErrors())
        self.canvas.refresh()
        self.currentfeatureband.setToGeometry(feature.geometry(), layer)
        RoamEvents.editgeometry_complete.emit(form, feature)

    def clearCapatureTools(self):
        captureselected = False
        for action in self.projecttoolbar.actions():
            if action.objectName() == "capture" and action.isChecked():
                captureselected = True

            if action.property('dataentry'):
                self.projecttoolbar.removeAction(action)
        return captureselected

    def toggleRasterLayers(self):
        """
        Toggle all raster layers on or off.
        """
        if not self.canvaslayers:
            return

        #Freeze the canvas to save on UI refresh
        self.canvas.freeze()
        for layer in self.canvaslayers:
            if layer.layer().type() == QgsMapLayer.RasterLayer:
                layer.setVisible(not layer.isVisible())
                # Really!? We have to reload the whole layer set every time?
            # WAT?
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.freeze(False)
        self.canvas.refresh()

    def cleanup(self):
        self.gpsband.reset()
        self.gpsband.hide()
        self.clear_selection()
        self.clear_temp_objects()
        self.clearCapatureTools()
        self.canvas.freeze()
        self.canvas.clear()
        self.canvas.freeze(False)
        for action in self.layerbuttons:
            self.editgroup.removeAction(action)
Example #52
0
class teamqgisDock(QDockWidget, Ui_teamqgis):
    dockRemoved = pyqtSignal(str)

    def __init__(self, iface, layer, currentFeature):
        self.iface = iface
        self.layer = layer
        self.proj = QgsProject.instance()
        self.renderer = self.iface.mapCanvas().mapRenderer()
        self.settings = MySettings()
        QDockWidget.__init__(self)
        self.setupUi(self)

        # Track attr warnings so they are not repeated for multiple items
        self.warned_attr_values = []

        self.setWindowTitle("teamqgis: %s" % layer.name())
        if layer.hasGeometryType() is False:
            self.panCheck.setChecked(False)
            self.panCheck.setEnabled(False)
            self.scaleCheck.setChecked(False)
            self.scaleCheck.setEnabled(False)

        self.previousButton.setArrowType(Qt.LeftArrow)
        self.nextButton.setArrowType(Qt.RightArrow)
        icon = QIcon(":/plugins/teamqgis/icons/openform.svg")
        self.editFormButton.setIcon(icon)

        # actions
        icon = QIcon(":/plugins/teamqgis/icons/action.svg")
        self.actionButton.setIcon(icon)
        self.attrAction = layer.actions()
        actions = [self.attrAction[i] for i in range(self.attrAction.size())]
        preferredAction = layer.customProperty("teamqgisPreferedAction", "")
        if preferredAction not in actions:
            dfltAction = self.attrAction.defaultAction()
            if dfltAction > len(actions):
                preferredAction = self.attrAction[dfltAction].name()
        preferredActionFound = False
        for i, action in enumerate(actions):
            qAction = QAction(QIcon(":/plugins/teamqgis/icons/action.svg"), action.name(), self)
            qAction.triggered.connect(lambda: self.doAction(i))
            self.actionButton.addAction(qAction)
            if action.name() == preferredAction:
                self.actionButton.setDefaultAction(qAction)
                preferredActionFound = True
        if len(actions) == 0:
            self.actionButton.setEnabled(False)
        elif not preferredActionFound:
            self.actionButton.setDefaultAction(self.actionButton.actions()[0])

        self.nameComboBoxes = [self.fieldOneNameComboBox, self.fieldTwoNameComboBox, self.fieldThreeNameComboBox]
        self.valueComboBoxes = [self.fieldOneValueComboBox, self.fieldTwoValueComboBox, self.fieldThreeValueComboBox]

        self.updateNameComboBoxes()

        # Restore saved nameComboBox current indices if they exist
        for nameComboBox in self.nameComboBoxes:
            fieldName = self.layer.customProperty("teamqgis" + nameComboBox.objectName())
            if fieldName != None:
                nameComboBox.setCurrentIndex(nameComboBox.findText(fieldName))

        self.rubber = QgsRubberBand(self.iface.mapCanvas())
        self.selectionChanged()
        if currentFeature == self.listCombo.currentIndex():
            self.on_listCombo_currentIndexChanged(currentFeature)
        else:
            self.listCombo.setCurrentIndex(currentFeature)
        self.layer.layerDeleted.connect(self.close)
        self.layer.selectionChanged.connect(self.selectionChanged)
        self.layer.layerModified.connect(self.layerChanged)
        self.layer.editingStopped.connect(self.editingStopped)
        self.layer.editingStarted.connect(self.editingStarted)

        QObject.connect(self.proj, SIGNAL("allowedClassesChanged()"), self.updateValueComboBoxes)

    def updateNameComboBoxes(self):
        fieldNameMap = self.layer.dataProvider().fieldNameMap()
        allFields = fieldNameMap.keys()
        if 'ID' in allFields: allFields.remove('ID')
        if 'FID' in allFields: allFields.remove('FID')
        for nameComboBox in self.nameComboBoxes:
            nameComboBox.clear()
            nameComboBox.addItems(allFields)

    def updateValueComboBoxes(self):
        feature = self.getCurrentItem()
        for (valueComboBox, nameComboBox) in zip(self.valueComboBoxes, 
                self.nameComboBoxes):
            valueComboBox.clear()
            allowedClasses, hasAllowedClasses = self.proj.readListEntry("teamqgis", "allowedClasses")
            if hasAllowedClasses:
                valueComboBox.addItems(allowedClasses)
            attr_value = str(feature[nameComboBox.currentText()])
            if (allowedClasses == None) or (attr_value not in allowedClasses) and (attr_value not in self.warned_attr_values):
                self.iface.messageBar().pushMessage("Class name not in allowed class list",
                    'Assign an allowed class or add "%s" to allowed class list'%attr_value,
                    level=QgsMessageBar.WARNING, duration=3)
                self.warned_attr_values.append(attr_value)
                valueComboBox.addItem(attr_value)
            valueComboBox.setCurrentIndex(valueComboBox.findText(attr_value))

    def setRubber(self, feature):
        self.rubber.setColor(self.settings.value("rubberColor"))
        self.rubber.setWidth(self.settings.value("rubberWidth"))
        ##self.rubber.setLineStyle(Qt.DotLine)
        self.rubber.setBrushStyle(Qt.NoBrush)
        self.rubber.setToGeometry(feature.geometry(), self.layer)

    def closeEvent(self, e):
        self.rubber.reset()
        self.layer.layerDeleted.disconnect(self.close)
        self.layer.selectionChanged.disconnect(self.selectionChanged)
        self.layer.layerModified.disconnect(self.layerChanged)
        self.layer.editingStopped.disconnect(self.editingStopped)
        self.layer.editingStarted.disconnect(self.editingStarted)
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("teamqgisSelection", repr([]))
        self.dockRemoved.emit(self.layer.id())
          
    def selectionChanged(self):
        self.cleanBrowserFields()
        self.rubber.reset()
        nItems = self.layer.selectedFeatureCount()
        if nItems < 1:
            self.close()
            self.layer.emit(SIGNAL("browserNoItem()"))
            return
        self.browseFrame.setEnabled(True)
        self.subset = self.layer.selectedFeaturesIds()
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("teamqgisSelection", repr(self.subset))
        for fid in self.subset:
            self.listCombo.addItem("%u" % fid)
        self.setRubber(self.getCurrentItem())
        self.updateValueComboBoxes()

    def layerChanged(self):
        self.applyChangesButton.setEnabled(True)

    def editingStarted(self):
        for valueComboBox in self.valueComboBoxes:
            valueComboBox.setEnabled(True)
        self.translateRightButton.setEnabled(True)
        self.translateLeftButton.setEnabled(True)
        self.translateUpButton.setEnabled(True)
        self.translateDownButton.setEnabled(True)
        self.editFormButton.setDown(True)

    def editingStopped(self):
        self.applyChangesButton.setEnabled(False)
        for valueComboBox in self.valueComboBoxes:
            valueComboBox.setEnabled(False)
        self.translateRightButton.setEnabled(False)
        self.translateLeftButton.setEnabled(False)
        self.translateUpButton.setEnabled(False)
        self.translateDownButton.setEnabled(False)
        self.editFormButton.setDown(False)

    def cleanBrowserFields(self):
        self.currentPosLabel.setText('0/0')
        self.listCombo.clear()
          
    def panScaleToItem(self, feature):
        if self.panCheck.isChecked() is False:
            return
        featBobo = feature.geometry().boundingBox()
        # if scaling and bobo has width and height (i.e. not a point)
        if self.scaleCheck.isChecked() and featBobo.width() != 0 and featBobo.height() != 0:
            featBobo.scale(self.settings.value("scale"))
            ul = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMinimum(), featBobo.yMaximum()))
            ur = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMaximum(), featBobo.yMaximum()))
            ll = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMinimum(), featBobo.yMinimum()))
            lr = self.renderer.layerToMapCoordinates(self.layer, QgsPoint(featBobo.xMaximum(), featBobo.yMinimum()))
            x = (ul.x(), ur.x(), ll.x(), lr.x())
            y = (ul.y(), ur.y(), ll.y(), lr.y())
            x0 = min(x)
            y0 = min(y)
            x1 = max(x)
            y1 = max(y)
        else:
            panTo = self.renderer.layerToMapCoordinates(self.layer, featBobo.center())
            mapBobo = self.iface.mapCanvas().extent()
            xshift = panTo.x() - mapBobo.center().x()
            yshift = panTo.y() - mapBobo.center().y()
            x0 = mapBobo.xMinimum() + xshift
            y0 = mapBobo.yMinimum() + yshift
            x1 = mapBobo.xMaximum() + xshift
            y1 = mapBobo.yMaximum() + yshift
        self.iface.mapCanvas().setExtent(QgsRectangle(x0, y0, x1, y1))
        self.iface.mapCanvas().refresh()

    def getCurrentItem(self):
        i = self.listCombo.currentIndex()
        if i == -1:
            return None
        f = QgsFeature()
        if self.layer.getFeatures(QgsFeatureRequest().setFilterFid(self.subset[i])).nextFeature(f):
            return f
        else:
            raise NameError("feature not found")

    def doAction(self, i):
        f = self.getCurrentItem()
        self.actionButton.setDefaultAction(self.actionButton.actions()[i])
        self.layer.setCustomProperty("teamqgisPreferedAction", self.attrAction[i].name())
        self.attrAction.doActionFeature(i, f)

    def doTranslate(self, trans):
        # Based on the "doaffine" function in the qgsAffine plugin
        if (self.layer.geometryType() == 2):
            start=1
        else:
            start=0
        if (not self.layer.isEditable()):
            self.iface.messageBar().pushMessage("Layer not in edit mode",
                    'Select a vector layer and choose "Toggle Editing"', level=QgsMessageBar.WARNING)
        else:
            feature = self.getCurrentItem()
            result = feature.geometry()
            i = start
            vertex = result.vertexAt(i)
            fid = feature.id()
            while (vertex != QgsPoint(0, 0)):
                newx = vertex.x() + trans[0] * float(self.settings.value("xres"))
                newy = vertex.y() + trans[1] * float(self.settings.value("yres"))
                result.moveVertex(newx, newy, i)
                i += 1
                vertex = result.vertexAt(i)
            self.layer.changeGeometry(fid, result)
            self.iface.mapCanvas().refresh()
            self.rubber.reset()
            self.setRubber(feature)

    def changeAttribute(self, i, fieldNameComboBox, fieldValueComboBox):
        fieldValueComboBox.setCurrentIndex(i)
        feature = self.getCurrentItem()
        attr_index = self.layer.dataProvider().fieldNameMap()[fieldNameComboBox.currentText()]
        self.layer.changeAttributeValue(feature.id(), attr_index, 
                fieldValueComboBox.currentText())
        self.iface.mapCanvas().refresh()
        self.updateValueComboBoxes()

    def nameComboBox_activated(self, i, nameComboBox):
        self.layer.setCustomProperty('teamqgis' + nameComboBox.objectName(), nameComboBox.currentText())

    @pyqtSlot(name="on_previousButton_clicked")
    def previousFeature(self):
        i = self.listCombo.currentIndex()
        n = max(0, i-1)
        self.listCombo.setCurrentIndex(n)
        self.saveCurrentFeature(n)

    @pyqtSlot(name="on_nextButton_clicked")
    def nextFeature(self):
        self.warned_attr_values = [] # Reset attr warnings
        i = self.listCombo.currentIndex()
        c = self.listCombo.count()
        n = min(i+1, c-1)
        self.listCombo.setCurrentIndex(n)
        self.saveCurrentFeature(n)

    @pyqtSlot(int, name="on_listCombo_activated")
    def saveCurrentFeature(self, i):
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("teamqgisCurrentItem", i)

    @pyqtSlot(int, name="on_fieldOneNameComboBox_activated")
    def fieldOneNameComboBox_activated(self, i):
        self.nameComboBox_activated(i, self.fieldOneNameComboBox)

    @pyqtSlot(int, name="on_fieldTwoNameComboBox_activated")
    def fieldTwoNameComboBox_activated(self, i):
        self.nameComboBox_activated(i, self.fieldTwoNameComboBox)

    @pyqtSlot(int, name="on_fieldThreeNameComboBox_activated")
    def fieldThreeNameComboBox_activated(self, i):
        self.nameComboBox_activated(i, self.fieldThreeNameComboBox)

    @pyqtSlot(int, name="on_listCombo_currentIndexChanged")
    def on_listCombo_currentIndexChanged(self, i):
        feature = self.getCurrentItem()
        if feature is None: 
            return
        self.rubber.reset()
        if self.listCombo.count() > 1:
            self.setRubber(feature)
            self.updateValueComboBoxes()
        # scale to feature
        self.panScaleToItem(feature)
        # Update browser
        self.currentPosLabel.setText("%u/%u" % (i+1, len(self.subset)))
        # emit signal
        self.layer.emit(SIGNAL("browserCurrentItem(long)"), feature.id())
          
    @pyqtSlot(int, name="on_panCheck_stateChanged")
    def on_panCheck_stateChanged(self, i):
        if self.panCheck.isChecked():
            self.scaleCheck.setEnabled(True)
            feature = self.getCurrentItem()
            if feature is None:
                return
            self.panScaleToItem(feature)
        else:
            self.scaleCheck.setEnabled(False)
               
    @pyqtSlot(int, name="on_scaleCheck_stateChanged")
    def on_scaleCheck_stateChanged(self, i):
        if self.scaleCheck.isChecked():
            feature = self.getCurrentItem()
            if feature is None: 
                return
            self.panScaleToItem(feature)

    @pyqtSlot(name="on_editFormButton_clicked")
    def openFeatureForm(self):
        if (self.layer.isEditable()):
            self.layer.commitChanges()
        else:
            self.layer.startEditing()

    @pyqtSlot(name="on_translateRightButton_clicked")
    def doTranslateRight(self):
        self.doTranslate((1, 0))

    @pyqtSlot(name="on_translateLeftButton_clicked")
    def doTranslateLeft(self):
        self.doTranslate((-1, 0))

    @pyqtSlot(name="on_translateUpButton_clicked")
    def doTranslateUp(self):
        self.doTranslate((0, 1))

    @pyqtSlot(name="on_translateDownButton_clicked")
    def doTranslateDown(self):
        self.doTranslate((0, -1))

    @pyqtSlot(name="on_applyChangesButton_clicked")
    def applyChanges(self):
        self.layer.commitChanges()
        self.layer.startEditing()
        self.layer.updateExtents()
        self.iface.mapCanvas().refresh()

    @pyqtSlot(int, name="on_fieldOneValueComboBox_activated")
    def on_fieldOneValueComboBox_activated(self, i):
        self.changeAttribute(i, self.fieldOneNameComboBox, self.fieldOneValueComboBox)

    @pyqtSlot(int, name="on_fieldTwoValueComboBox_activated")
    def on_fieldTwoValueComboBox_activated(self, i):
        self.changeAttribute(i, self.fieldTwoNameComboBox, self.fieldTwoValueComboBox)

    @pyqtSlot(int, name="on_fieldThreeValueComboBox_activated")
    def on_fieldThreeValueComboBox_activated(self, i):
        self.changeAttribute(i, self.fieldThreeNameComboBox, self.fieldThreeValueComboBox)
class AuditDialog(QDialog, Ui_audit, SettingDialog):
    rejectShowEvent = pyqtSignal()
    performSearchAtShowEvent = pyqtSignal()

    def __init__(self, iface, layerId=None, featureId=None):
        QDialog.__init__(self)
        self.setupUi(self)
        self.settings = MySettings()
        SettingDialog.__init__(self, self.settings, False, True)  # column chooser, advanced search options

        #init variables
        self.layerId = layerId
        self.featureId = featureId
        self.layer = None
        self.rubber = QgsRubberBand(iface.mapCanvas())
        self.mapCanvas = iface.mapCanvas()
        self.resuts = dict()

        # connect "pan and show geometry" check box to draw in rubber band
        self.panShowGeometry.clicked.connect(self.displayGeomDifference)

        # reject properly showEvent if checking fails
        self.rejectShowEvent.connect(self.reject, Qt.QueuedConnection)
        # start search directly at the end of showEvent if enough params
        self.performSearchAtShowEvent.connect(self.on_searchButton_clicked, Qt.QueuedConnection)

        # setup layer - field combo, with primary key selector as field
        self.layerComboManager = VectorLayerCombo(self.layerCombo, layerId,
                                                  {"dataProvider": "postgres", "finishInit": False,
                                                   "skipLayers": [lambda: self.settings.value("logLayer")]})
        self.layerComboManager.finishInit()

        # log layer
        self.logLayer = LogLayer()
        self.logLayer.setProgressMax.connect(self.progressBar.setMaximum)
        self.logLayer.setProgressMin.connect(self.progressBar.setMinimum)
        self.logLayer.setProgressValue.connect(self.progressBar.setValue)

        # logged actions table
        self.loggedActionsLayout = QGridLayout(self.loggedActionsWidget)
        self.loggedActionsTable = LoggedActionsTable(self.loggedActionsWidget)
        self.loggedActionsLayout.addWidget(self.loggedActionsTable, 0, 0, 1, 1)
        self.loggedActionsTable.itemSelectionChanged.connect(self.displayDifference)

        # difference viewer
        self.differenceLayout = QGridLayout(self.differenceViewerWidget)
        self.differenceViewer = DifferenceViewer(self.differenceViewerWidget)
        self.differenceLayout.addWidget(self.differenceViewer, 0, 0, 1, 1)

        # set dates
        now = QDateTime.currentDateTime()
        self.searchBeforeDate.setDateTime(now)
        self.searchAfterDate.setDateTime(now.addDays(-7))

        # finish ui
        self.buttonDisplayMode(False)
        self.restoreButton.setEnabled(False)
        if featureId is not None:
            self.featureEdit.setText("%s" % featureId)
        self.adjustSize()

    def closeEvent(self, e):
        self.rubber.reset()

    def showEvent(self, e):
        SettingDialog.showEvent(self, e)
        while not self.logLayer.isValid():
            if not LoggedActionsTableChooserDialog().exec_():
                self.rejectShowEvent.emit()
                return
        if self.layerId is not None:
            self.layerCombo.setEnabled(False)
            layer = self.layerComboManager.getLayer()
            if layer is None:
                self.rejectShowEvent.emit()
                return
            if self.featureId is not None:
                self.featureEdit.setEnabled(False)
                f = QgsFeature()
                featReq = QgsFeatureRequest().setFilterFid(self.featureId).setFlags(QgsFeatureRequest.NoGeometry)
                if layer.getFeatures(featReq).nextFeature(f) is False:
                    self.rejectShowEvent.emit()
                    return
                self.performSearchAtShowEvent.emit()
        else:
            layer = self.mapCanvas.currentLayer()
            self.layerComboManager.setLayer(layer)


    @pyqtSignature("on_layerCombo_currentIndexChanged(int)")
    def on_layerCombo_currentIndexChanged(self, i):
        self.layer = self.layerComboManager.getLayer()
        self.panShowGeometry.setEnabled(self.layer is not None and self.layer.hasGeometryType())

    @pyqtSignature("on_stopButton_clicked()")
    def on_stopButton_clicked(self):
        self.logLayer.interrupt()

    @pyqtSignature("on_searchButton_clicked()")
    def on_searchButton_clicked(self):
        self.layer = self.layerComboManager.getLayer()
        pkeyName = primaryKey(self.layer)
        if self.layer is None or pkeyName is None:
            return
        self.loggedActionsTable.geomColumn = self.layer.hasGeometryType()
        featureId = int(self.featureEdit.text() or 0)
        searchBeforeDate = QDateTime()
        if self.searchBefore.isChecked():
            searchBeforeDate = self.searchAfterDate.dateTime()
        searchAfterDate = QDateTime()
        if self.searchAfter.isChecked():
            searchAfterDate = self.searchAfterDate.dateTime()
        self.buttonDisplayMode(True)
        self.results = self.logLayer.performSearch(self.layer, featureId, pkeyName,
                                                   self.searchInserts.isChecked(), self.searchUpdates.isChecked(),
                                                   self.searchDeletes.isChecked(), self.searchOnlyGeometry.isChecked(),
                                                   searchAfterDate, searchBeforeDate)
        self.buttonDisplayMode(False)
        self.panShowGeometry.setEnabled(self.layer.hasGeometryType())
        self.displayLoggedActions()

    def buttonDisplayMode(self, searchOn):
        self.searchButton.setVisible(not searchOn)
        self.stopButton.setVisible(searchOn)
        self.progressBar.setVisible(searchOn)

    def displayLoggedActions(self):
        self.differenceViewer.clearRows()
        self.loggedActionsTable.displayColumns()
        self.loggedActionsTable.displayRows(self.results)

    def displayDifference(self):
        self.differenceViewer.clearRows()
        self.restoreButton.setEnabled(False)
        item = self.loggedActionsTable.selectedItems()
        if len(item) == 0:
            return
        rowId = item[0].data(Qt.UserRole)
        logRow = self.results[rowId]
        if logRow.featureLayer.isEditable():
            self.restoreButton.setEnabled(True)
        self.differenceViewer.display(logRow)
        self.displayGeomDifference()

    def displayGeomDifference(self):
        self.rubber.reset()
        item = self.loggedActionsTable.selectedItems()
        if len(item) == 0:
            return
        rowId = item[0].data(Qt.UserRole)
        logRow = self.results[rowId]

        if self.layer.hasGeometryType() and self.panShowGeometry.isChecked():
            geom = logRow.geometry()
            self.rubber.setToGeometry(geom, self.layer)
            panTo = self.mapCanvas.mapRenderer().layerExtentToOutputExtent(self.layer, geom.boundingBox())
            panTo.scale(1.5)
            self.mapCanvas.setExtent(panTo)
            self.mapCanvas.refresh()

    @pyqtSignature("on_columnChooserButton_clicked()")
    def on_columnChooserButton_clicked(self):
        ColumnChooserDialog().exec_()
        self.loggedActionsTable.displayColumns()
        self.loggedActionsTable.displayRows(self.results)

    @pyqtSignature("on_restoreButton_clicked()")
    def on_restoreButton_clicked(self):
        item = self.loggedActionsTable.selectedItems()
        if len(item) == 0:
            return
        rowId = item[0].data(Qt.UserRole)
        logRow = self.results[rowId]
        if not logRow.featureLayer.isEditable():
            return
        logRow.restoreFeature()
        self.mapCanvas.refresh()
Example #54
0
class DEMto3DDialog(QtGui.QDialog, Ui_DEMto3DDialogBase):
    # Layer to print
    layer = None
    ''' Region of interest properties '''
    map_crs = None
    roi_x_max = 0
    roi_x_min = 0
    roi_y_max = 0
    roi_y_min = 0
    z_max = 0
    z_min = 0
    ''' Model dimensions '''
    height = 0
    width = 0
    scale = 0
    z_scale = 0
    ''' Raster properties '''
    cell_size = 0
    cols = 0
    rows = 0
    raster_x_max = 0
    raster_x_min = 0
    raster_y_max = 0
    raster_y_min = 0

    def __init__(self, iface):
        """Constructor."""
        QDialog.__init__(self)
        self.ui = Ui_DEMto3DDialogBase()
        self.ui.setupUi(self)
        self.iface = iface
        self.canvas = iface.mapCanvas()
        try:
            self.map_crs = self.canvas.mapSettings().destinationCrs()
        except:
            self.map_crs = self.canvas.mapRenderer().destinationCrs()

        # region Layer action
        # fill layer combobox with raster visible layers in mapCanvas
        self.viewLayers = self.canvas.layers()
        self.ui.LayerComboBox.clear()
        for layer in self.viewLayers:
            if layer.type() == 1:
                self.ui.LayerComboBox.addItem(layer.name())
        self.layer = get_layer(self.ui.LayerComboBox.currentText())
        self.get_raster_properties()
        QtCore.QObject.connect(self.ui.LayerComboBox, QtCore.SIGNAL(_fromUtf8("activated(QString)")), self.get_layer)
        # endregion

        # region Extension actions
        self.extent = None
        QtCore.QObject.connect(self.ui.FullExtToolButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.full_extent)
        QtCore.QObject.connect(self.ui.LayerExtToolButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.layer_extent)
        QtCore.QObject.connect(self.ui.CustomExtToolButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.custom_extent)
        QtCore.QObject.connect(self.ui.XMinLineEdit, QtCore.SIGNAL(_fromUtf8("returnPressed()")), self.upload_extent)
        QtCore.QObject.connect(self.ui.XMaxLineEdit, QtCore.SIGNAL(_fromUtf8("returnPressed()")), self.upload_extent)
        QtCore.QObject.connect(self.ui.YMaxLineEdit, QtCore.SIGNAL(_fromUtf8("returnPressed()")), self.upload_extent)
        QtCore.QObject.connect(self.ui.YMinLineEdit, QtCore.SIGNAL(_fromUtf8("returnPressed()")), self.upload_extent)
        # endregion

        # region Dimension actions
        QtCore.QObject.connect(self.ui.HeightLineEdit, QtCore.SIGNAL(_fromUtf8("textEdited(QString)")),
                               self.upload_size_from_height)
        QtCore.QObject.connect(self.ui.WidthLineEdit, QtCore.SIGNAL(_fromUtf8("textEdited(QString)")),
                               self.upload_size_from_width)
        QtCore.QObject.connect(self.ui.ScaleLineEdit, QtCore.SIGNAL(_fromUtf8("textEdited(QString)")),
                               self.upload_size_from_scale)
        # endregion

        QtCore.QObject.connect(self.ui.ZScaleDoubleSpinBox, QtCore.SIGNAL(_fromUtf8("valueChanged(double)")),
                               self.get_height_model)
        QtCore.QObject.connect(self.ui.BaseHeightLineEdit, QtCore.SIGNAL(_fromUtf8("textEdited(QString)")),
                               self.get_height_model)

        # region Cancel, export, print buttons
        QtCore.QObject.connect(self.ui.CancelToolButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.reject)
        QtCore.QObject.connect(self.ui.STLToolButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.do_export)
        close = QtGui.QAction(self)
        self.connect(close, QtCore.SIGNAL('clicked()'), self.reject)
        # endregion

    def do_export(self):
        parameters = self.get_parameters()
        layer_name = self.ui.LayerComboBox.currentText() + '_model.stl'
        if parameters != 0:
            if parameters["spacing_mm"] < 0.5 and self.height > 100 and self.width > 100:
                reply = QMessageBox.question(self, self.tr('Export to STL'),
                                             self.tr('The construction of the STL file could takes several minutes. Do you want to continue?'),
                                             QMessageBox.Yes |
                                             QMessageBox.No, QMessageBox.No)
                if reply == QMessageBox.Yes:
                    f = QFileDialog.getSaveFileNameAndFilter(self, self.tr('Export to STL'), layer_name, filter=".stl")
                    stl_file = f[0]
                    if stl_file:
                        export_dlg = Export_dialog.Dialog(parameters, stl_file)
                        if export_dlg.exec_():
                            QMessageBox.information(self, self.tr("Attention"), self.tr("STL model generated"))
                        else:
                            QMessageBox.information(self, self.tr("Attention"), self.tr("Process canceled"))
            else:
                f = QFileDialog.getSaveFileNameAndFilter(self, self.tr('Export to STL'), layer_name, filter=".stl")
                stl_file = f[0]
                if stl_file:
                    export_dlg = Export_dialog.Dialog(parameters, stl_file)
                    if export_dlg.exec_():
                        QMessageBox.information(self, self.tr("Attention"), self.tr("STL model generated"))
                    else:
                        QMessageBox.information(self, self.tr("Attention"), self.tr("Process canceled"))
        else:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Fill the data correctly"))

    def get_layer(self, layer_name):
        if self.layer.name() != layer_name:
            self.ini_dialog()
        layermap = QgsMapLayerRegistry.instance().mapLayers()
        for name, layer in layermap.iteritems():
            if layer.name() == layer_name:
                if layer.isValid():
                    self.layer = layer
                    self.get_raster_properties()
                else:
                    self.layer = None

    def ini_dialog(self):
        self.ui.XMaxLineEdit.clear()
        self.ui.XMinLineEdit.clear()
        self.ui.YMaxLineEdit.clear()
        self.ui.YMinLineEdit.clear()
        if self.extent:
            self.canvas.scene().removeItem(self.extent)
            self.extent = None
        self.ini_dimensions()

        self.ui.ZMaxLabel.setText('0 m')
        self.ui.ZMinLabel.setText('0 m')

    def ini_dimensions(self):
        self.ui.HeightLineEdit.clear()
        self.height = 0
        self.ui.WidthLineEdit.clear()
        self.width = 0
        self.ui.ScaleLineEdit.clear()
        self.scale = 0
        self.ui.RecomSpacinglabel.setText('0.2 mm')

        self.ui.BaseHeightLineEdit.clear()
        self.ui.HeightModelLabel.setText('0 mm')

    def get_raster_properties(self):
        self.cell_size = self.layer.rasterUnitsPerPixelX()
        self.rows = self.layer.height()
        self.cols = self.layer.width()
        rec = self.layer.extent()
        self.raster_x_max = rec.xMaximum()
        self.raster_x_min = rec.xMinimum()
        self.raster_y_max = rec.yMaximum()
        self.raster_y_min = rec.yMinimum()

    # region Extension functions
    def full_extent(self):
        rec = self.canvas.fullExtent()
        self.paint_extent(rec)
        self.get_z_max_z_min()
        self.ini_dimensions()

    def layer_extent(self):
        layers = self.iface.legendInterface().layers()
        select_layer_dialog = SelectLayer_dialog.Dialog(layers)
        if select_layer_dialog.exec_():
            layer = select_layer_dialog.get_layer()
            if layer:
                rec = get_layer(layer).extent()
                source = self.layer.crs()
                target = self.map_crs
                if source != target:
                    transform = QgsCoordinateTransform(source, target)
                    rec = transform.transform(rec)
                self.paint_extent(rec)
                self.get_z_max_z_min()
                self.ini_dimensions()

    def custom_extent(self):
        self.iface.messageBar().pushMessage("Info", self.tr("Click and drag the mouse to draw print extent"),
                                            level=QgsMessageBar.INFO, duration=3)
        if self.extent:
            self.canvas.scene().removeItem(self.extent)
            self.extent = None
        ct = RectangleMapTool(self.canvas, self.get_custom_extent)
        self.canvas.setMapTool(ct)

    def get_custom_extent(self, rec):
        layer_extension = self.layer.extent()
        source = self.layer.crs()
        target = self.map_crs
        if source != target:
            transform = QgsCoordinateTransform(source, target)
            layer_extension = transform.transform(layer_extension)
        if rec.intersects(layer_extension):
            extension = rec.intersect(layer_extension)
            self.paint_extent(extension)
            self.iface.actionPan().trigger()
            self.get_z_max_z_min()
            self.ini_dimensions()
        else:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Print extent defined outside layer extent"))

    def upload_extent(self):
        try:
            self.roi_x_max = float(self.ui.XMaxLineEdit.text())
            self.roi_x_min = float(self.ui.XMinLineEdit.text())
            self.roi_y_max = float(self.ui.YMaxLineEdit.text())
            self.roi_y_min = float(self.ui.YMinLineEdit.text())
            rec = QgsRectangle(self.roi_x_min, self.roi_y_min, self.roi_x_max, self.roi_y_max)
            self.paint_extent(rec)
            self.get_z_max_z_min()
            self.ini_dimensions()
        except ValueError:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Value entered incorrect"))

    def paint_extent(self, rec):
        self.roi_x_max = rec.xMaximum()
        self.ui.XMaxLineEdit.setText(str(round(rec.xMaximum(), 3)))
        self.roi_y_min = rec.yMinimum()
        self.ui.YMinLineEdit.setText(str(round(rec.yMinimum(), 3)))
        self.roi_x_min = rec.xMinimum()
        self.ui.XMinLineEdit.setText(str(round(rec.xMinimum(), 3)))
        self.roi_y_max = rec.yMaximum()
        self.ui.YMaxLineEdit.setText(str(round(rec.yMaximum(), 3)))

        if self.extent:
            self.canvas.scene().removeItem(self.extent)
            self.extent = None
        self.extent = QgsRubberBand(self.canvas, True)
        points = [QgsPoint(self.roi_x_max, self.roi_y_min), QgsPoint(self.roi_x_max, self.roi_y_max),
                  QgsPoint(self.roi_x_min, self.roi_y_max), QgsPoint(self.roi_x_min, self.roi_y_min),
                  QgsPoint(self.roi_x_max, self.roi_y_min)]
        self.extent.setToGeometry(QgsGeometry.fromPolyline(points), None)
        self.extent.setColor(QColor(227, 26, 28, 255))
        self.extent.setWidth(5)
        self.extent.setLineStyle(Qt.PenStyle(Qt.DashLine))
        self.canvas.refresh()

    def get_z_max_z_min(self):
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))

        roi = QgsRectangle(self.roi_x_min, self.roi_y_min, self.roi_x_max, self.roi_y_max)
        source = self.map_crs
        target = self.layer.crs()
        transform = QgsCoordinateTransform(source, target)
        rec = transform.transform(roi)

        x_max = rec.xMaximum()
        x_min = rec.xMinimum()
        y_max = rec.yMaximum()
        y_min = rec.yMinimum()

        x_off = int(math.floor((x_min - self.raster_x_min) * self.cols / (self.raster_x_max - self.raster_x_min)))
        y_off = int(math.floor((self.raster_y_max - y_max) * self.rows / (self.raster_y_max - self.raster_y_min)))
        col_size = int(math.floor((x_max - x_min) / self.cell_size))
        row_size = int(math.floor((y_max - y_min) / self.cell_size))

        if x_off < 0:
            x_off = 0
        if y_off < 0:
            y_off = 0
        if x_off >= self.cols:
            x_off = self.cols - 1
        if y_off >= self.rows:
            y_off = self.rows - 1

        if x_off + col_size > self.cols:
            col_size = self.cols - x_off
        if row_size + row_size > self.rows:
            row_size = self.rows - y_off

        provider = self.layer.dataProvider()
        path = provider.dataSourceUri()
        path_layer = path.split('|')

        dem_dataset = gdal.Open(path_layer[0])
        data = self.get_dem_z(dem_dataset, x_off, y_off, col_size, row_size)
        if data is not None:
            self.z_max = max(data)
            self.z_min = self.z_max
            no_data = dem_dataset.GetRasterBand(1).GetNoDataValue()

            if min(data) == no_data:
                for z_cell in data:
                    if z_cell != no_data and z_cell < self.z_min:
                        self.z_min = z_cell
            elif math.isnan(min(data)):
                self.z_max = 0
                self.z_min = 0
                for z_cell in data:
                    if not math.isnan(z_cell):
                        if self.z_min > z_cell:
                            self.z_min = z_cell
                        if self.z_max < z_cell:
                            self.z_max = z_cell
            else:
                self.z_min = min(data)

            if self.z_min < 0:
                self.z_min = 0

            self.z_max = round(self.z_max, 3)
            self.z_min = round(self.z_min, 3)
            self.ui.ZMaxLabel.setText(str(self.z_max) + ' m')
            self.ui.ZMinLabel.setText(str(self.z_min) + ' m')
        dem_dataset = None
        band = None
        QApplication.restoreOverrideCursor()
    # endregion

    # region Dimensions function
    def get_min_spacing(self):
        min_spacing = 0
        if self.map_crs.mapUnits() == 0:  # Meters
            if self.layer.crs().mapUnits() == 0:
                width_roi = self.roi_x_max - self.roi_x_min
                min_spacing = round(self.cell_size * self.width / width_roi, 2)
            elif self.layer.crs().mapUnits() == 2:
                width_roi = self.roi_x_max - self.roi_x_min
                cell_size_m = self.cell_size * math.pi / 180 * math.cos(self.roi_y_max * math.pi / 180) * 6371000
                min_spacing = round(cell_size_m * self.width / width_roi, 2)
            # min_spacing = self.cell_size/self.scale
        elif self.map_crs.mapUnits() == 2:  # Degree
            if self.layer.crs().mapUnits() == 0:
                width_roi = self.roi_x_max - self.roi_x_min
                cell_size_deg = self.cell_size / math.pi * 180 / math.cos(self.roi_y_max * math.pi / 180) / 6371000
                min_spacing = round(cell_size_deg * self.width / width_roi, 2)
            elif self.layer.crs().mapUnits() == 2:
                width_roi = self.roi_x_max - self.roi_x_min
                min_spacing = round(self.cell_size * self.width / width_roi, 2)

        if min_spacing < 0.2:
            self.ui.RecomSpacinglabel.setText('0.2 mm')
        else:
            self.ui.RecomSpacinglabel.setText(str(min_spacing) + ' mm')

    def upload_size_from_height(self):
        try:
            width_roi = self.roi_x_max - self.roi_x_min
            height_roi = self.roi_y_max - self.roi_y_min
            self.height = float(self.ui.HeightLineEdit.text())
            self.width = round(width_roi * self.height / height_roi, 2)
            self.ui.WidthLineEdit.setText(str(self.width))
            if self.map_crs.mapUnits() == 0:  # Meters
                scale1 = height_roi / self.height * 1000
                scale2 = width_roi / self.width * 1000
                self.scale = round((scale1 + scale2) / 2, 6)
                self.ui.ScaleLineEdit.setText(str(int(self.scale)))
            elif self.map_crs.mapUnits() == 2:  # Degree
                dist = width_roi * math.pi / 180 * math.cos(self.roi_y_max * math.pi / 180) * 6371000 * 1000
                self.scale = round(dist / self.width, 6)
                self.ui.ScaleLineEdit.setText(str(int(self.scale)))
            self.get_min_spacing()
            self.get_height_model()
        except ZeroDivisionError:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Define print extent"))
            self.ui.HeightLineEdit.clear()

    def upload_size_from_width(self):
        try:
            width_roi = self.roi_x_max - self.roi_x_min
            height_roi = self.roi_y_max - self.roi_y_min
            self.width = float(self.ui.WidthLineEdit.text())
            self.height = round(height_roi * self.width / width_roi, 2)
            self.ui.HeightLineEdit.setText(str(self.height))
            if self.map_crs.mapUnits() == 0:  # Meters
                scale1 = height_roi / self.height * 1000
                scale2 = width_roi / self.width * 1000
                self.scale = round((scale1 + scale2) / 2, 6)
                self.ui.ScaleLineEdit.setText(str(int(self.scale)))
            elif self.map_crs.mapUnits() == 2:  # Degree
                dist = width_roi * math.pi / 180 * math.cos(self.roi_y_max * math.pi / 180) * 6371000 * 1000
                self.scale = round(dist / self.width, 6)
                self.ui.ScaleLineEdit.setText(str(int(self.scale)))
            self.get_min_spacing()
            self.get_height_model()
        except ZeroDivisionError:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Define size model"))
            self.ui.WidthLineEdit.clear()

    def upload_size_from_scale(self):
        try:
            width_roi = self.roi_x_max - self.roi_x_min
            height_roi = self.roi_y_max - self.roi_y_min
            self.scale = float(self.ui.ScaleLineEdit.text())
            if self.map_crs.mapUnits() == 0:  # Meters
                self.height = round(height_roi / self.scale * 1000, 2)
                self.ui.HeightLineEdit.setText(str(self.height))
                self.width = round(width_roi / self.scale * 1000, 2)
                self.ui.WidthLineEdit.setText(str(self.width))
            elif self.map_crs.mapUnits() == 2:  # Degree
                dist = width_roi * math.pi / 180 * math.cos(self.roi_y_max * math.pi / 180) * 6371000 * 1000
                self.width = round(dist / self.scale, 2)
                self.ui.WidthLineEdit.setText(str(self.width))
                self.height = round(height_roi * self.width / width_roi, 2)
                self.ui.HeightLineEdit.setText(str(self.height))
            self.get_min_spacing()
            self.get_height_model()
        except ZeroDivisionError:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Define print extent"))
            self.ui.ScaleLineEdit.clear()
            self.scale = 0
            self.ui.WidthLineEdit.clear()

    # endregion

    def get_height_model(self):
        if self.ui.BaseHeightLineEdit.text() == '':
            return
        try:
            z_base = float(self.ui.BaseHeightLineEdit.text())
            self.z_scale = self.ui.ZScaleDoubleSpinBox.value()
            h_model = round((self.z_max - z_base) / self.scale * 1000 * self.z_scale + 2, 1)
            if h_model == float("inf"):
                QMessageBox.warning(self, self.tr("Attention"), self.tr("Define size model"))
                self.ui.BaseHeightLineEdit.clear()
                return
            if z_base <= self.z_max:
                self.ui.HeightModelLabel.setText(str(h_model) + ' mm')
            else:
                QMessageBox.warning(self, self.tr("Attention"),
                                    self.tr("Height of the base must be lower than DEM highest point"))
                self.ui.BaseHeightLineEdit.clear()
        except ZeroDivisionError:
            QMessageBox.warning(self, self.tr("Attention"), self.tr("Define print extent"))
            self.ui.BaseHeightLineEdit.clear()

    def get_parameters(self):
        if self.map_crs.mapUnits() == 0:  # Meters
            projected = True
        elif self.map_crs.mapUnits() == 2:  # Degree
            projected = False
        provider = self.layer.dataProvider()
        path = provider.dataSourceUri()
        path_layer = path.split('|')
        self.z_scale = self.ui.ZScaleDoubleSpinBox.value()
        try:
            spacing_mm = float(self.ui.SpacingLineEdit.text())
            z_base = float(self.ui.BaseHeightLineEdit.text())
        except ValueError:
            return 0
        if self.ui.RevereseZCheckBox.isChecked():
            z_inv = True
        else:
            z_inv = False
        return {"layer": path_layer[0], "roi_x_max": self.roi_x_max, "roi_x_min": self.roi_x_min,
                "roi_y_max": self.roi_y_max, "roi_y_min": self.roi_y_min, "spacing_mm": spacing_mm,
                "height": self.height, "width": self.width, "z_scale": self.z_scale, "scale": self.scale,
                "z_inv": z_inv, "z_base": z_base, "projected": projected, "crs_layer": self.layer.crs(),
                "crs_map": self.map_crs}

    @staticmethod
    def get_dem_z(dem_dataset, x_off, y_off, col_size, row_size):
        band = dem_dataset.GetRasterBand(1)
        data_types = {'Byte': 'B', 'UInt16': 'H', 'Int16': 'h', 'UInt32': 'I', 'Int32': 'i', 'Float32': 'f',
                      'Float64': 'd'}
        data_type = band.DataType
        data = band.ReadRaster(x_off, y_off, col_size, row_size, col_size, row_size, data_type)
        data = struct.unpack(data_types[gdal.GetDataTypeName(band.DataType)] * col_size * row_size, data)
        return data
Example #55
0
class MainWindow(ui_mainwindow.Ui_MainWindow, QMainWindow):
    """
    Main application window
    """

    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.canvaslayers = []
        self.layerbuttons = []
        self.project = None
        self.selectionbands = defaultdict(partial(QgsRubberBand, self.canvas))
        self.canvas.setCanvasColor(Qt.white)
        self.canvas.enableAntiAliasing(True)
        self.canvas.setWheelAction(QgsMapCanvas.WheelZoomToMouseCursor)
        self.bar = roam.messagebaritems.MessageBar(self.centralwidget)

        self.actionMap.setVisible(False)
        self.actionLegend.setVisible(False)

        pal = QgsPalLabeling()
        self.canvas.mapRenderer().setLabelingEngine(pal)
        self.canvas.setFrameStyle(QFrame.NoFrame)

        self.menuGroup = QActionGroup(self)
        self.menuGroup.setExclusive(True)
        self.menuGroup.addAction(self.actionMap)
        self.menuGroup.addAction(self.actionDataEntry)
        self.menuGroup.addAction(self.actionLegend)
        self.menuGroup.addAction(self.actionProject)
        self.menuGroup.addAction(self.actionSync)
        self.menuGroup.addAction(self.actionSettings)
        self.menuGroup.addAction(self.actionGPS)
        self.menuGroup.triggered.connect(self.updatePage)

        self.editgroup = QActionGroup(self)
        self.editgroup.setExclusive(True)
        self.editgroup.addAction(self.actionPan)
        self.editgroup.addAction(self.actionZoom_In)
        self.editgroup.addAction(self.actionZoom_Out)
        self.editgroup.addAction(self.actionInfo)

        self.actionLegend.triggered.connect(self.updatelegend)

        self.actionGPS = GPSAction(":/icons/gps", self.canvas, self)
        self.projecttoolbar.addAction(self.actionGPS)

        self.projectwidget.requestOpenProject.connect(self.loadProject)
        QgsProject.instance().readProject.connect(self._readProject)

        self.gpswidget.setgps(GPS)

        self.actionSettings.toggled.connect(self.settingswidget.populateControls)
        self.actionSettings.toggled.connect(self.settingswidget.readSettings)
        self.settingswidget.settingsupdated.connect(self.settingsupdated)

        self.dataentrywidget = DataEntryWidget(self.canvas, self.bar)
        self.widgetpage.layout().addWidget(self.dataentrywidget)

        self.dataentrywidget.rejected.connect(self.formrejected)
        self.dataentrywidget.featuresaved.connect(self.featureSaved)
        self.dataentrywidget.featuredeleted.connect(self.featuredeleted)
        self.dataentrywidget.failedsave.connect(self.failSave)
        self.dataentrywidget.helprequest.connect(self.showhelp)

        def createSpacer(width=0, height=0):
            widget = QWidget()
            widget.setMinimumWidth(width)
            widget.setMinimumHeight(height)
            return widget

        gpsspacewidget = createSpacer(30)
        sidespacewidget = createSpacer(30)
        sidespacewidget2 = createSpacer(height=20)

        sidespacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sidespacewidget2.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        gpsspacewidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.topspaceraction = self.projecttoolbar.insertWidget(self.actionGPS, gpsspacewidget)

        def createlabel(text):
            style = """
                QLabel {
                        color: #706565;
                        font: 14px "Calibri" ;
                        }"""
            label = QLabel(text)
            label.setStyleSheet(style)

            return label

        self.projectlabel = createlabel("Project: {project}")
        self.userlabel = createlabel("User: {user}".format(user=getpass.getuser()))
        self.positionlabel = createlabel('')
        self.gpslabel = createlabel("GPS: Not active")
        self.statusbar.addWidget(self.projectlabel)
        self.statusbar.addWidget(self.userlabel)
        spacer = createSpacer()
        spacer2 = createSpacer()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        spacer2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.statusbar.addWidget(spacer)
        self.statusbar.addWidget(self.positionlabel)
        self.statusbar.addWidget(spacer2)
        self.statusbar.addWidget(self.gpslabel)

        self.menutoolbar.insertWidget(self.actionQuit, sidespacewidget2)
        self.menutoolbar.insertWidget(self.actionProject, sidespacewidget)

        self.panels = []

        self.connectButtons()

        self.currentfeatureband = QgsRubberBand(self.canvas)
        self.currentfeatureband.setIconSize(20)
        self.currentfeatureband.setWidth(10)
        self.currentfeatureband.setColor(QColor(186, 93, 212, 76))

        self.canvas_page.layout().insertWidget(0, self.projecttoolbar)
        self.dataentryselection = QAction(self.projecttoolbar)
        self.dataentryaction = self.projecttoolbar.insertAction(self.topspaceraction, self.dataentryselection)
        self.dataentryselection.triggered.connect(self.selectdataentry)

        self.centralwidget.layout().addWidget(self.statusbar)

        self.actionGPSFeature.setProperty('dataentry', True)

        self.infodock = InfoDock(self.canvas)
        self.infodock.featureupdated.connect(self.highlightfeature)
        self.infodock.hide()
        self.hidedataentry()
        self.canvas.extentsChanged.connect(self.updatestatuslabel)

        RoamEvents.openimage.connect(self.openimage)
        RoamEvents.openurl.connect(self.viewurl)
        RoamEvents.openfeatureform.connect(self.openForm)
        RoamEvents.openkeyboard.connect(self.openkeyboard)
        RoamEvents.selectioncleared.connect(self.clearselection)
        RoamEvents.editgeometry.connect(self.addforedit)
        RoamEvents.editgeometry_complete.connect(self.on_geometryedit)
        RoamEvents.onShowMessage.connect(self.showUIMessage)
        RoamEvents.selectionchanged.connect(self.highlightselection)
        RoamEvents.selectionchanged.connect(self.showInfoResults)

        GPS.gpspostion.connect(self.updatecanvasfromgps)
        GPS.firstfix.connect(self.gpsfirstfix)
        GPS.gpsdisconnected.connect(self.gpsdisconnected)

        self.lastgpsposition = None
        self.marker = GPSMarker(self.canvas)
        self.marker.hide()

        self.legendpage.showmap.connect(self.showmap)

        self.editfeaturestack = []
        self.currentselection = {}

    def showUIMessage(self, label, message, level=QgsMessageBar.INFO, time=0, extra=''):
        self.bar.pushMessage(label, message, level, duration=time, extrainfo=extra)

    def addforedit(self, form, feature):
        self.editfeaturestack.append((form, feature))
        self.loadform(form)
        actions = self.getcaptureactions()
        for action in actions:
            if action.isdefault:
                action.trigger()
                break

    def updatelegend(self):
        self.legendpage.updatecanvas(self.canvas)

    def gpsfirstfix(self, postion, gpsinfo):
        zoomtolocation = roam.config.settings.get('gpszoomonfix', True)
        if zoomtolocation:
            self.canvas.zoomScale(1000)

    def updatecanvasfromgps(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if not self.lastgpsposition == position:
            self.lastposition = position
            rect = QgsRectangle(position, position)
            extentlimt = QgsRectangle(self.canvas.extent())
            extentlimt.scale(0.95)

            if not extentlimt.contains(position):
                self.canvas.setExtent(rect)
                self.canvas.refresh()

        self.marker.show()
        self.marker.setCenter(position)
        self.gpslabel.setText("GPS: PDOP {}   HDOP {}    VDOP {}".format(gpsinfo.pdop,
                                                                        gpsinfo.hdop,
                                                                        gpsinfo.vdop))

    def gpsdisconnected(self):
        self.marker.hide()
        self.gpslabel.setText("GPS Not Active")

    def openkeyboard(self):
        if not roam.config.settings.get('keyboard', True):
            return

        if sys.platform == 'win32':
            try:
                programfiles = os.environ['ProgramW6432']
            except KeyError:
                programfiles = os.environ['ProgramFiles']

            cmd = r'{path}\Common Files\Microsoft Shared\ink\TabTip.exe'.format(path=programfiles)
            try:
                os.startfile(cmd)
            except WindowsError:
                roam.config.settings['keyboard'] = False
                roam.config.save()
        else:
            cmd = 'onboard'
            Popen(cmd)


    def selectdataentry(self):
        forms = self.project.forms
        formpicker = PickActionDialog(msg="Select data entry form")
        for form in forms:
            action = form.createuiaction()
            valid, failreasons = form.valid
            if not valid:
                roam.utils.warning("Form {} failed to load".format(form.label))
                roam.utils.warning("Reasons {}".format(failreasons))
                action.triggered.connect(partial(self.showformerror, form))
            else:
                action.triggered.connect(partial(self.loadform, form))
            formpicker.addAction(action)

        formpicker.exec_()

    def showformerror(self, form):
        pass

    def viewurl(self, url):
        """
        Open a URL in Roam
        :param url:
        :return:
        """
        key = url.toString().lstrip('file://')
        try:
            # Hack. Eww fix me.
            data, imagetype = roam.htmlviewer.images[os.path.basename(key)]
            pix = QPixmap()
            if imagetype == 'base64':
                pix.loadFromData(data)
            else:
                pix.load(data)
            self.openimage(pix)
        except KeyError:
            pix = QPixmap()
            pix.load(key)
            if pix.isNull():
                QDesktopServices.openUrl(url)
                return
            self.openimage(pix)

    def openimage(self, pixmap):
        viewer = ImageViewer(self.stackedWidget)
        viewer.resize(self.stackedWidget.size())
        viewer.openimage(pixmap)

    def settingsupdated(self, settings):
        self.show()
        self.actionGPS.updateGPSPort()

    def updatestatuslabel(self):
        extent = self.canvas.extent()
        self.positionlabel.setText("Map Center: {}".format(extent.center().toString()))

    def on_geometryedit(self, form, feature):
        layer = form.QGISLayer
        self.reloadselection(layer, updated=[feature])

        self.currentfeatureband.setToGeometry(feature.geometry(), layer)

    def reloadselection(self, layer, deleted=[], updated=[]):
        """
        Reload the selection after features have been updated or deleted.
        :param layer:
        :param deleted:
        :param updated:
        :return:
        """
        selectedfeatures = self.currentselection[layer]

        # Update any features that have changed.
        for updatedfeature in updated:
            oldfeatures = [f for f in selectedfeatures if f.id() == updatedfeature.id()]
            for feature in oldfeatures:
                self.currentselection[layer].remove(feature)
                self.currentselection[layer].append(updatedfeature)

        # Delete any old ones
        for deletedid in deleted:
            oldfeatures = [f for f in selectedfeatures if f.id() == deletedid]
            for feature in oldfeatures:
                self.currentselection[layer].remove(feature)

        RoamEvents.selectionchanged.emit(self.currentselection)

    def highlightselection(self, results):
        self.clearselection()
        for layer, features in results.iteritems():
            band = self.selectionbands[layer]
            band.setColor(QColor(255, 0, 0, 200))
            band.setIconSize(20)
            band.setWidth(2)
            band.setBrushStyle(Qt.NoBrush)
            band.reset(layer.geometryType())
            for feature in features:
                band.addGeometry(feature.geometry(), layer)

    def clearselection(self):
        # Clear the main selection rubber band
        self.currentfeatureband.reset()
        # Clear the rest
        for band in self.selectionbands.itervalues():
            band.reset()

        self.editfeaturestack = []

    def highlightfeature(self, layer, feature, features):
        self.clearselection()
        self.highlightselection({layer: features})
        self.currentfeatureband.setToGeometry(feature.geometry(), layer)

    def showmap(self):
        self.actionMap.setVisible(True)
        self.actionLegend.setVisible(True)
        self.actionMap.trigger()

    def hidedataentry(self):
        self.actionDataEntry.setVisible(False)

    def showdataentry(self):
        self.actionDataEntry.setVisible(True)
        self.actionDataEntry.trigger()

    def dataentrychanged(self, index):
        self.clearCapatureTools()

        if not index.isValid():
            return

        modelindex = index
        # modelindex = self.dataentrymodel.index(index, 0)
        form = modelindex.data(Qt.UserRole + 1)
        self.dataentryselection.setCurrentIndex(index.row())
        self.createCaptureButtons(form)

    def raiseerror(self, *exinfo):
        info = traceback.format_exception(*exinfo)
        item = self.bar.pushError(QApplication.translate('MainWindowPy','Seems something has gone wrong. Press for more details', None, QApplication.UnicodeUTF8),
                                  info)

    def setMapTool(self, tool, *args):
        self.canvas.setMapTool(tool)

    def homeview(self):
        """
        Zoom the mapview canvas to the extents the project was opened at i.e. the
        default extent.
        """
        self.canvas.setExtent(self.defaultextent)
        self.canvas.refresh()

    def connectButtons(self):
        def connectAction(action, tool):
            action.toggled.connect(partial(self.setMapTool, tool))

        def cursor(name):
            pix = QPixmap(name)
            pix = pix.scaled(QSize(24,24))
            return QCursor(pix)

        self.zoomInTool = QgsMapToolZoom(self.canvas, False)
        self.zoomOutTool = QgsMapToolZoom(self.canvas, True)
        self.panTool = PanTool(self.canvas)
        self.infoTool = InfoTool(self.canvas)

        connectAction(self.actionZoom_In, self.zoomInTool)
        connectAction(self.actionZoom_Out, self.zoomOutTool)
        connectAction(self.actionPan, self.panTool)
        connectAction(self.actionInfo, self.infoTool)

        self.zoomInTool.setCursor(cursor(':/icons/in'))
        self.zoomOutTool.setCursor(cursor(':/icons/out'))
        self.infoTool.setCursor(cursor(':/icons/info'))

        self.actionRaster.triggered.connect(self.toggleRasterLayers)

        self.infoTool.infoResults.connect(RoamEvents.selectionchanged.emit)

        self.actionHome.triggered.connect(self.homeview)
        self.actionQuit.triggered.connect(self.exit)

    def getcaptureactions(self):
        for action in self.projecttoolbar.actions():
            if action.property('dataentry'):
                yield action

    def clearCapatureTools(self):
        captureselected = False
        for action in self.projecttoolbar.actions():
            if action.objectName() == "capture" and action.isChecked():
                captureselected = True

            if action.property('dataentry'):
                self.projecttoolbar.removeAction(action)
        return captureselected

    def createCaptureButtons(self, form):
        tool = form.getMaptool()(self.canvas)
        for action in tool.actions:
            # Create the action here.
            if action.ismaptool:
                action.toggled.connect(partial(self.setMapTool, tool))

            # Set the action as a data entry button so we can remove it later.
            action.setProperty("dataentry", True)
            self.editgroup.addAction(action)
            self.layerbuttons.append(action)
            self.projecttoolbar.insertAction(self.topspaceraction, action)
            action.setChecked(action.isdefault)

        if hasattr(tool, 'geometryComplete'):
            add = partial(self.addNewFeature, form)
            tool.geometryComplete.connect(add)
        else:
            tool.finished.connect(self.openForm)
            tool.error.connect(partial(self.showUIMessage, form.label))

    def loadform(self, form):
        self.clearCapatureTools()
        self.dataentryselection.setIcon(QIcon(form.icon))
        self.dataentryselection.setText(form.icontext)
        self.createCaptureButtons(form)

    def clearToolRubberBand(self):
        """
        Clear the rubber band of the active tool if it has one
        """
        tool = self.canvas.mapTool()
        try:
            tool.clearBand()
        except AttributeError:
            # No clearBand method found, but that's cool.
            pass

    def showhelp(self, url):
        help = HelpPage(self.stackedWidget)
        help.setHelpPage(url)
        help.show()

    def dataentryfinished(self):
        self.hidedataentry()
        self.showmap()
        self.cleartempobjects()
        self.infodock.refreshcurrent()

    def featuredeleted(self, layer, featureid):
        self.dataentryfinished()
        self.reloadselection(layer, deleted=[featureid])
        self.canvas.refresh()

    def featureSaved(self):
        self.dataentryfinished()
        self.canvas.refresh()

    def failSave(self, messages):
        self.bar.pushError("Error when saving changes.", messages)

    def cleartempobjects(self):
        self.currentfeatureband.reset()
        self.clearToolRubberBand()

    def formrejected(self, message, level):
        self.dataentryfinished()
        if message:
            RoamEvents.raisemessage("Form Message", message, level, duration=2)

        self.cleartempobjects()

    def openForm(self, form, feature, editmode):
        """
        Open the form that is assigned to the layer
        """
        self.currentfeatureband.setToGeometry(feature.geometry(), form.QGISLayer)
        self.showdataentry()
        self.dataentrywidget.openform(feature=feature, form=form, project=self.project, editmode=editmode)

    def editfeaturegeometry(self, form, feature, newgeometry):
        layer = form.QGISLayer
        layer.startEditing()
        feature.setGeometry(newgeometry)
        layer.updateFeature(feature)
        saved = layer.commitChanges()
        map(roam.utils.error, layer.commitErrors())
        self.canvas.refresh()
        RoamEvents.editgeometry_complete.emit(form, feature)

    def addNewFeature(self, form, geometry):
        """
        Add a new new feature to the given layer
        """
        layer = form.QGISLayer
        if layer.geometryType() in [QGis.WKBMultiLineString, QGis.WKBMultiPoint, QGis.WKBMultiPolygon]:
            geometry.convertToMultiType()

        try:
            form, feature = self.editfeaturestack.pop()
            self.editfeaturegeometry(form, feature, newgeometry=geometry)
            return
        except IndexError:
            pass

        layer = form.QGISLayer
        fields = layer.pendingFields()

        feature = QgsFeature(fields)
        feature.setGeometry(geometry)

        for index in xrange(fields.count()):
            pkindexes = layer.dataProvider().pkAttributeIndexes()
            if index in pkindexes and layer.dataProvider().name() == 'spatialite':
                continue

            value = layer.dataProvider().defaultValue(index)
            feature[index] = value

        self.openForm(form, feature, editmode=False)

    def exit(self):
        """
        Exit the application.
        """
        QApplication.exit(0)

    def showInfoResults(self, results):
        forms = {}
        for layer in results.keys():
            layername = layer.name()
            if not layername in forms:
                forms[layername] = list(self.project.formsforlayer(layername))

        self.currentselection = results
        self.infodock.setResults(results, forms)
        self.infodock.show()

    def toggleRasterLayers(self):
        """
        Toggle all raster layers on or off.
        """
        if not self.canvaslayers:
            return

        #Freeze the canvas to save on UI refresh
        self.canvas.freeze()
        for layer in self.canvaslayers:
            if layer.layer().type() == QgsMapLayer.RasterLayer:
                layer.setVisible(not layer.isVisible())
            # Really!? We have to reload the whole layer set every time?
        # WAT?
        self.canvas.setLayerSet(self.canvaslayers)
        self.canvas.freeze(False)
        self.canvas.refresh()

    def missingLayers(self, layers):
        """
        Called when layers have failed to load from the current project
        """
        roam.utils.warning("Missing layers")
        map(roam.utils.warning, layers)

        missinglayers = roam.messagebaritems.MissingLayerItem(layers,
                                                              parent=self.bar)
        self.bar.pushItem(missinglayers)

    def loadprojects(self, projects):
        """
        Load the given projects into the project
        list
        """
        projects = list(projects)
        self.projectwidget.loadProjectList(projects)
        self.syncwidget.loadprojects(projects)

    def updatePage(self, action):
        """
        Update the current stack page based on the current selected
        action
        """
        page = action.property("page")
        self.stackedWidget.setCurrentIndex(page)

    def show(self):
        """
        Override show method. Handles showing the app in fullscreen
        mode or just maximized
        """
        fullscreen = roam.config.settings.get("fullscreen", False)
        if fullscreen:
            self.showFullScreen()
        else:
            self.showMaximized()

    def viewprojects(self):
        self.stackedWidget.setCurrentIndex(1)

    @roam.utils.timeit
    def _readProject(self, doc):
        """
        readProject is called by QgsProject once the map layer has been
        populated with all the layers
        """
        parser = ProjectParser(doc)
        canvasnode = parser.canvasnode
        self.canvas.freeze()
        self.canvas.mapRenderer().readXML(canvasnode)
        self.canvaslayers = parser.canvaslayers()
        self.canvas.setLayerSet(self.canvaslayers)
        #red = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorRedPart", 255 )[0];
        #green = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorGreenPart", 255 )[0];
        #blue = QgsProject.instance().readNumEntry( "Gui", "/CanvasColorBluePart", 255 )[0];
        #color = QColor(red, green, blue);
        #self.canvas.setCanvasColor(color)
        self.canvas.updateScale()
        self.projectOpened()
        self.canvas.freeze(False)
        self.canvas.refresh()
        GPS.crs = self.canvas.mapRenderer().destinationCrs()
        self.showmap()

    @roam.utils.timeit
    def projectOpened(self):
        """
            Called when a new project is opened in QGIS.
        """
        projectpath = QgsProject.instance().fileName()
        self.project = Project.from_folder(os.path.dirname(projectpath))
        self.projectlabel.setText("Project: {}".format(self.project.name))
        try:
            firstform = self.project.forms[0]
            self.loadform(self.project.forms[0])
            self.dataentryselection.setVisible(True)
        except IndexError:
            self.dataentryselection.setVisible(False)

        # Enable the raster layers button only if the project contains a raster layer.
        layers = QgsMapLayerRegistry.instance().mapLayers().values()
        hasrasters = any(layer.type() == QgsMapLayer.RasterLayer for layer in layers)
        self.actionRaster.setEnabled(hasrasters)
        self.defaultextent = self.canvas.extent()
        roam.utils.info("Extent: {}".format(self.defaultextent.toString()))

        # Show panels
        for panel in self.project.getPanels():
            self.mainwindow.addDockWidget(Qt.BottomDockWidgetArea, panel)
            self.panels.append(panel)

        self.infoTool.selectionlayers = self.project.selectlayersmapping()
        layers = self.project.legendlayersmapping().values()
        self.legendpage.updateitems(layers)
        self.actionPan.trigger()

    #noinspection PyArgumentList
    @roam.utils.timeit
    def loadProject(self, project):
        """
        Load a project into the application .
        """
        roam.utils.log(project)
        roam.utils.log(project.name)
        roam.utils.log(project.projectfile)
        roam.utils.log(project.valid)

        (passed, message) = project.onProjectLoad()

        if not passed:
            self.bar.pushMessage("Project load rejected", "Sorry this project couldn't"
                                                          "be loaded.  Click for me details.",
                                 QgsMessageBar.WARNING, extrainfo=message)
            return

        self.actionMap.trigger()

        self.closeProject()

        self.canvas.refresh()
        self.canvas.repaint()

        RoamEvents.selectioncleared.emit()

        # No idea why we have to set this each time.  Maybe QGIS deletes it for
        # some reason.
        self.badLayerHandler = BadLayerHandler(callback=self.missingLayers)
        QgsProject.instance().setBadLayerHandler(self.badLayerHandler)

        self.stackedWidget.setCurrentIndex(3)
        self.projectloading_label.setText("Project {} Loading".format(project.name))
        pixmap = QPixmap(project.splash)
        w = self.projectimage.width()
        h = self.projectimage.height()
        self.projectimage.setPixmap(pixmap.scaled(w,h, Qt.KeepAspectRatio))
        QApplication.processEvents()

        QDir.setCurrent(os.path.dirname(project.projectfile))
        fileinfo = QFileInfo(project.projectfile)
        QgsProject.instance().read(fileinfo)

    def closeProject(self):
        """
        Close the current open project
        """
        self.clearCapatureTools()
        self.canvas.freeze()
        QgsMapLayerRegistry.instance().removeAllMapLayers()
        self.canvas.clear()
        self.canvas.freeze(False)
        for panel in self.panels:
            self.removeDockWidget(panel)
            del panel
            # Remove all the old buttons
        for action in self.layerbuttons:
            self.editgroup.removeAction(action)

        self.panels = []
        self.project = None
        self.dataentrywidget.clear()
        self.hidedataentry()
        self.infodock.close()
class VoGISProfilToolMainDialog(QDialog):
    def __init__(self, interface, settings):

        self.settings = settings
        self.iface = interface
        self.selectingVisibleRasters = False
        self.thread = None

        QDialog.__init__(self, interface.mainWindow())

        # Set up the user interface from Designer.
        self.ui = Ui_VoGISProfilToolMain()
        self.ui.setupUi(self)

        if self.settings.onlyHektoMode is True:
            self.ui.IDC_widRaster.hide()
            self.adjustSize()

        validator = QIntValidator(-32768, 32768, self)
        self.ui.IDC_tbNoDataExport.setValidator(validator)

        self.ui.IDC_tbFromX.setText('-30000')
        self.ui.IDC_tbFromY.setText('240000')
        self.ui.IDC_tbToX.setText('-20000')
        self.ui.IDC_tbToY.setText('230000')

        self.__addRastersToGui()
        self.__addPolygonsToGui()

        for line_lyr in self.settings.mapData.lines.lines():
            self.ui.IDC_cbLineLayers.addItem(line_lyr.name, line_lyr)

        if self.settings.mapData.lines.count() < 1:
            self.ui.IDC_rbDigi.setChecked(True)
            self.ui.IDC_rbShapeLine.setEnabled(False)

        #Einstellungen fuer Linie zeichen
        self.action = QAction(QIcon(":/plugins/vogisprofiltoolmain/icons/icon.png"), "VoGIS-Profiltool", self.iface.mainWindow())
        self.action.setWhatsThis("VoGIS-Profiltool")
        self.canvas = self.iface.mapCanvas()
        self.tool = ProfiletoolMapTool(self.canvas, self.action)
        self.savedTool = self.canvas.mapTool()
        self.polygon = False
        self.rubberband = QgsRubberBand(self.canvas, self.polygon)
        if QGis.QGIS_VERSION_INT >= 10900:
            #self.rubberband.setBrushStyle()
            self.rubberband.setLineStyle(Qt.SolidLine)
            self.rubberband.setWidth(4.0)
            self.rubberband.setColor(QColor(0, 255, 0))
            #http://www.qgis.org/api/classQgsRubberBand.html#a6f7cdabfcf69b65dfc6c164ce2d01fab
        self.pointsToDraw = []
        self.dblclktemp = None
        self.drawnLine = None

    def accept(self):
        try:
            #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", "ACCEPTED")

            #QgsMessageLog.logMessage('nodata: {0}'.format(self.settings.nodata_value), 'VoGis')
            self.settings.nodata_value = int(self.ui.IDC_tbNoDataExport.text())
            QgsMessageLog.logMessage('maindlg: nodata: {0}'.format(self.settings.nodata_value), 'VoGis')

            if self.settings.onlyHektoMode is True and self.settings.mapData.rasters.count() > 0:
                self.settings.onlyHektoMode = False

            if self.settings.onlyHektoMode is False:
                if self.settings.mapData.rasters.count() < 1:
                    #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", u"Keine Raster vorhanden. Zum Hektometrieren Dialog neu öffnen.")
                    #return
                    retVal = QMessageBox.warning(self.iface.mainWindow(),
                                                 "VoGIS-Profiltool",
                                                 QApplication.translate('code', 'Keine Rasterebene vorhanden oder sichtbar! Nur hektometrieren?', None, QApplication.UnicodeUTF8),
                                                 QMessageBox.Yes | QMessageBox.No,
                                                 QMessageBox.Yes)
                    if retVal == QMessageBox.No:
                        return
                    else:
                        self.settings.onlyHektoMode = True
                        self.settings.createHekto = True

            if self.__getSettingsFromGui() is False:
                return

            if self.settings.onlyHektoMode is False:
                if len(self.settings.mapData.rasters.selectedRasters()) < 1:
                    #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", "Kein Raster selektiert!")
                    #msg =
                    #QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", msg)
                    QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Kein Raster selektiert!', None, QApplication.UnicodeUTF8))
                    return

            QgsMessageLog.logMessage('modeLine!=line: {0}'.format(self.settings.modeLine != enumModeLine.line), 'VoGis')
            QgsMessageLog.logMessage('customLine is None: {0}'.format(self.settings.mapData.customLine is None), 'VoGis')

            if self.settings.modeLine != enumModeLine.line and self.settings.mapData.customLine is None:
                QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Keine Profillinie vorhanden!', None, QApplication.UnicodeUTF8))
                return

            if len(self.settings.mapData.polygons.selected_polygons()) > 0 and len(self.settings.mapData.rasters.selectedRasters()) > 1:
                raster_names = list(raster.name for raster in self.settings.mapData.rasters.selectedRasters())
                sel_raster, ok_clicked = QInputDialog.getItem(
                                                self.iface.mainWindow(),
                                                u'DHM?',
                                                u'Welches DHM soll zur Flächenverschneidung verwendet werden?',
                                                raster_names,
                                                0,
                                                False
                                                )
                if ok_clicked is False:
                    return
                self.settings.intersection_dhm_idx = raster_names.index(sel_raster)

            #self.rubberband.reset(self.polygon)
            #QDialog.accept(self)

            QApplication.setOverrideCursor(Qt.WaitCursor)

            create_profile = CreateProfile(self.iface, self.settings)
            thread = QThread(self)
            create_profile.moveToThread(thread)
            create_profile.finished.connect(self.profiles_finished)
            create_profile.error.connect(self.profiles_error)
            create_profile.progress.connect(self.profiles_progress)
            thread.started.connect(create_profile.create)
            thread.start(QThread.LowestPriority)
            self.thread = thread
            self.create_profile = create_profile
            self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
        except:
            QApplication.restoreOverrideCursor()
            ex = u'{0}'.format(traceback.format_exc())
            msg = 'Unexpected ERROR:\n\n{0}'.format(ex[:2000])
            QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", msg)


    def profiles_finished(self, profiles, intersections):
        QApplication.restoreOverrideCursor()
        self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
        #self.create_profile.deleteLater()
        self.thread.quit()
        self.thread.wait()
        #self.thread.deleteLater()

        #QGIS 2.0 http://gis.stackexchange.com/a/58754 http://gis.stackexchange.com/a/57090
        self.iface.mainWindow().statusBar().showMessage('VoGIS-Profiltool, {0} Profile'.format(len(profiles)))
        QgsMessageLog.logMessage(u'Profile Count: {0}'.format(len(profiles)), 'VoGis')

        if len(profiles) < 1:
            QApplication.restoreOverrideCursor()
            QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', 'Es konnten keine Profile erstellt werden.', None, QApplication.UnicodeUTF8))
            return

        dlg = VoGISProfilToolPlotDialog(self.iface, self.settings, profiles, intersections)
        dlg.show()
        #result = self.dlg.exec_()
        dlg.exec_()


    def profiles_error(self, exception_string):
        QApplication.restoreOverrideCursor()
        QgsMessageLog.logMessage(u'Error during profile creation: {0}'.format(exception_string), 'VoGis')
        QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", exception_string)


    def profiles_progress(self, msg):
        self.iface.mainWindow().statusBar().showMessage(msg)
        self.ui.IDC_lblCreateStatus.setText(msg)
        #QgsMessageLog.logMessage(msg, 'VoGis')
        QApplication.processEvents()


    def reject(self):
        if not self.thread is None:
            if self.thread.isRunning():
                self.create_profile.abort()
                return

        self.rubberband.reset(self.polygon)
        QDialog.reject(self)


    def selectVisibleRasters(self):
        self.refreshRasterList()
        self.selectingVisibleRasters = True
        extCanvas = self.iface.mapCanvas().extent()
        #alle raster in den einstellunge deselektieren
        for r in self.settings.mapData.rasters.rasters():
            r.selected = False
        #alle raster in der ListView deselektieren
        for idx in xrange(self.ui.IDC_listRasters.count()):
            item = self.ui.IDC_listRasters.item(idx)
            item.setCheckState(Qt.Unchecked)
        #Raster im Extent selektieren
        for idx in xrange(self.ui.IDC_listRasters.count()):
            item = self.ui.IDC_listRasters.item(idx)
            if QGis.QGIS_VERSION_INT < 10900:
                raster = item.data(Qt.UserRole).toPyObject()
            else:
                raster = item.data(Qt.UserRole)
            for r in self.settings.mapData.rasters.rasters():
                if extCanvas.intersects(r.grid.extent()):
                    if r.id == raster.id:
                        r.selected = True
                        item.setCheckState(Qt.Checked)
        self.selectingVisibleRasters = False


    def lineLayerChanged(self, idx):
        if self.ui.IDC_rbShapeLine.isChecked() is False:
            self.ui.IDC_rbShapeLine.setChecked(True)
        if QGis.QGIS_VERSION_INT < 10900:
            lineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex()).toPyObject())
        else:
            lineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex()))
        lyr = lineLyr.line
        #QgsMessageLog.logMessage('{0}'.format(lyr.selectedFeatureCount()), 'VoGis')
        #QgsMessageLog.logMessage('{0}'.format(dir(lyr)), 'VoGis')
        if hasattr(lyr, 'selectedFeatureCount'):
            if(lyr.selectedFeatureCount() < 1):
                self.ui.IDC_chkOnlySelectedFeatures.setChecked(False)
            else:
                self.ui.IDC_chkOnlySelectedFeatures.setChecked(True)


    def valueChangedEquiDistance(self, val):
        if self.ui.IDC_rbEquiDistance.isChecked() is False:
            self.ui.IDC_rbEquiDistance.setChecked(True)


    def valueChangedVertexCount(self, val):
        if self.ui.IDC_rbVertexCount.isChecked() is False:
            self.ui.IDC_rbVertexCount.setChecked(True)


    def lvRasterItemChanged(self, item):
        if self.selectingVisibleRasters is True:
            return
        if item.checkState() == Qt.Checked:
            selected = True
        if item.checkState() == Qt.Unchecked:
            selected = False

        item_data = item.data(Qt.UserRole)
        if QGis.QGIS_VERSION_INT < 10900:
            raster_lyr = item_data.toPyObject()
        else:
            raster_lyr = item_data
        self.settings.mapData.rasters.getById(raster_lyr.id).selected = selected


    def lvPolygonItemChanged(self, item):
        if item.checkState() == Qt.Checked:
            selected = True
        if item.checkState() == Qt.Unchecked:
            selected = False

        item_data = item.data(Qt.UserRole)
        if QGis.QGIS_VERSION_INT < 10900:
            poly_lyr = item_data.toPyObject()
        else:
            poly_lyr = item_data
        self.settings.mapData.polygons.getById(poly_lyr.id).selected = selected


    def refreshRasterList(self):
        legend = self.iface.legendInterface()
        avail_lyrs = legend.layers()
        raster_coll = RasterCollection()

        for lyr in avail_lyrs:
            if legend.isLayerVisible(lyr):
                lyr_type = lyr.type()
                lyr_name = unicodedata.normalize('NFKD', unicode(lyr.name())).encode('ascii', 'ignore')
                if lyr_type == 1:
                    if lyr.bandCount() < 2:
                        new_raster = Raster(lyr.id(), lyr_name, lyr)
                        raster_coll.addRaster(new_raster)

        self.settings.mapData.rasters = raster_coll
        self.__addRastersToGui()

    def __addRastersToGui(self):
        self.ui.IDC_listRasters.clear()
        check = Qt.Unchecked
        if self.settings.mapData.rasters.count() == 1:
            check = Qt.Checked
            self.settings.mapData.rasters.rasters()[0].selected = True

        for raster_lyr in self.settings.mapData.rasters.rasters():
            item = QListWidgetItem(raster_lyr.name)
            item.setData(Qt.UserRole, raster_lyr)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(check)
            self.ui.IDC_listRasters.addItem(item)


    def __addPolygonsToGui(self):
        self.ui.IDC_listPolygons.clear()
        check = Qt.Unchecked
        for poly_lyr in self.settings.mapData.polygons.polygons():
            item = QListWidgetItem(poly_lyr.name)
            item.setData(Qt.UserRole, poly_lyr)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(check)
            self.ui.IDC_listPolygons.addItem(item)


    def drawLine(self):
        if self.ui.IDC_rbDigi.isChecked() is False:
            self.ui.IDC_rbDigi.setChecked(True)
        self.dblckltemp = None
        self.rubberband.reset(self.polygon)
        self.__cleanDigi()
        self.__activateDigiTool()
        self.canvas.setMapTool(self.tool)


    def __createDigiFeature(self, pnts):
        u = Util(self.iface)
        f = u.createQgLineFeature(pnts)
        self.settings.mapData.customLine = f


    def __lineFinished(self, position):
        mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"])
        newPoint = QgsPoint(mapPos.x(), mapPos.y())
        self.pointsToDraw.append(newPoint)
        #launch analyses
        self.iface.mainWindow().statusBar().showMessage(str(self.pointsToDraw))
        if len(self.pointsToDraw) < 2:
            self.__cleanDigi()
            self.pointsToDraw = []
            self.dblclktemp = newPoint
            self.drawnLine = None
            QMessageBox.warning(self, "VoGIS-Profiltool", QApplication.translate('code', 'Profillinie digitalisieren abgebrochen!', None, QApplication.UnicodeUTF8))
        self.drawnLine = self.__createDigiFeature(self.pointsToDraw)
        self.__cleanDigi()

        self.pointsToDraw = []
        self.dblclktemp = newPoint

    def __cleanDigi(self):
        self.pointsToDraw = []
        self.canvas.unsetMapTool(self.tool)
        self.canvas.setMapTool(self.savedTool)

    def __activateDigiTool(self):
        QObject.connect(self.tool, SIGNAL("moved"), self.__moved)
        QObject.connect(self.tool, SIGNAL("rightClicked"), self.__rightClicked)
        QObject.connect(self.tool, SIGNAL("leftClicked"), self.__leftClicked)
        QObject.connect(self.tool, SIGNAL("doubleClicked"), self.__doubleClicked)
        QObject.connect(self.tool, SIGNAL("deactivate"), self.__deactivateDigiTool)

    def __deactivateDigiTool(self):
        QObject.disconnect(self.tool, SIGNAL("moved"), self.__moved)
        QObject.disconnect(self.tool, SIGNAL("leftClicked"), self.__leftClicked)
        QObject.disconnect(self.tool, SIGNAL("rightClicked"), self.__rightClicked)
        QObject.disconnect(self.tool, SIGNAL("doubleClicked"), self.__doubleClicked)
        if QGis.QGIS_VERSION_INT < 10900:
            self.iface.mainWindow().statusBar().showMessage(QString(""))
        else:
            self.iface.mainWindow().statusBar().showMessage('')

    def __moved(self, position):
        if len(self.pointsToDraw) > 0:
            mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"])
            self.rubberband.reset(self.polygon)
            newPnt = QgsPoint(mapPos.x(), mapPos.y())
            if QGis.QGIS_VERSION_INT < 10900:
                for i in range(0, len(self.pointsToDraw)):
                    self.rubberband.addPoint(self.pointsToDraw[i])
                self.rubberband.addPoint(newPnt)
            else:
                pnts = self.pointsToDraw + [newPnt]
                self.rubberband.setToGeometry(QgsGeometry.fromPolyline(pnts),None)


    def __rightClicked(self, position):
        self.__lineFinished(position)

    def __leftClicked(self, position):
        mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"])
        newPoint = QgsPoint(mapPos.x(), mapPos.y())
        #if self.selectionmethod == 0:
        if newPoint == self.dblclktemp:
            self.dblclktemp = None
            return
        else:
            if len(self.pointsToDraw) == 0:
                self.rubberband.reset(self.polygon)
            self.pointsToDraw.append(newPoint)

    def __doubleClicked(self, position):
        pass

    #not in use right now
    def __lineCancel(self):
        pass

    def __getSettingsFromGui(self):
        self.settings.linesExplode = (self.ui.IDC_chkLinesExplode.checkState() == Qt.Checked)
        self.settings.linesMerge = (self.ui.IDC_chkLinesMerge.checkState() == Qt.Checked)
        self.settings.onlySelectedFeatures = (self.ui.IDC_chkOnlySelectedFeatures.checkState() == Qt.Checked)
        self.settings.equiDistance = self.ui.IDC_dblspinDistance.value()
        self.settings.vertexCnt = self.ui.IDC_dblspinVertexCnt.value()
        #self.settings.createHekto = (self.ui.IDC_chkCreateHekto.checkState() == Qt.Checked)
        self.settings.nodesAndVertices = (self.ui.IDC_chkNodesAndVertices.checkState() == Qt.Checked)

        if QGis.QGIS_VERSION_INT < 10900:
            self.settings.mapData.selectedLineLyr = (self.ui.IDC_cbLineLayers.itemData(
                                                     self.ui.IDC_cbLineLayers.currentIndex()
                                                     ).toPyObject()
                                                     )
        else:
            self.settings.mapData.selectedLineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex()))

        if self.settings.onlySelectedFeatures is True and self.settings.mapData.selectedLineLyr.line.selectedFeatureCount() < 1:
            QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate('code', u'Der gewählte Layer hat keine selektierten Elemente.', None, QApplication.UnicodeUTF8))
            return False

        if self.ui.IDC_rbDigi.isChecked():
            self.settings.modeLine = enumModeLine.customLine
        elif self.ui.IDC_rbShapeLine.isChecked():
            self.settings.modeLine = enumModeLine.line
        else:
            #self.ui.IDC_rbStraigthLine
            self.settings.modeLine = enumModeLine.straightLine

        if self.ui.IDC_rbEquiDistance.isChecked():
            self.settings.modeVertices = enumModeVertices.equiDistant
        else:
            self.settings.modeVertices = enumModeVertices.vertexCnt

        if self.ui.IDC_rbStraigthLine.isChecked():
            ut = Util(self.iface)
            if ut.isFloat(self.ui.IDC_tbFromX.text(), QApplication.translate('code', 'Rechtswert von', None, QApplication.UnicodeUTF8)) is False:
                return False
            else:
                fromX = float(self.ui.IDC_tbFromX.text())
            if ut.isFloat(self.ui.IDC_tbFromY.text(), QApplication.translate('code', 'Hochwert von', None, QApplication.UnicodeUTF8)) is False:
                return False
            else:
                fromY = float(self.ui.IDC_tbFromY.text())
            if ut.isFloat(self.ui.IDC_tbToX.text(), QApplication.translate('code', 'Rechtswert nach', None, QApplication.UnicodeUTF8)) is False:
                return False
            else:
                toX = float(self.ui.IDC_tbToX.text())
            if ut.isFloat(self.ui.IDC_tbToY.text(), QApplication.translate('code', 'Hochwert nach', None, QApplication.UnicodeUTF8)) is False:
                return False
            else:
                toY = float(self.ui.IDC_tbToY.text())

            fromPnt = QgsPoint(fromX, fromY)
            toPnt = QgsPoint(toX, toY)

            self.settings.mapData.customLine = ut.createQgLineFeature([fromPnt, toPnt])

        return True
Example #57
0
class RubberBandResultRenderer():

    def __init__(self):
        self.iface = iface

        self.srs_wgs84 = QgsCoordinateReferenceSystem(4326)
        self.transformation = QgsCoordinateTransform(self.srs_wgs84, self.srs_wgs84)

        self.rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Point)
        self.rb.setColor(QColor('magenta'))
        self.rb.setIconSize(12)

        self.features_rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Point)
        self.features_rb.setColor(QColor('green'))
        self.features_rb.setIconSize(12)
        self.features_rb.setWidth(3)

    def show_point(self, point, center=False):
        #check srs
        if self.need_transform():
            point = self.transform_point(point)

        self.rb.addPoint(point)
        if center:
            self.center_to_point(point)

    def clear(self):
        self.rb.reset(QGis.Point)

    def need_transform(self):
        return self.iface.mapCanvas().mapRenderer().destinationCrs().postgisSrid() != 4326

    def transform_point(self, point):
        dest_srs_id = self.iface.mapCanvas().mapRenderer().destinationCrs().srsid()
        self.transformation.setDestCRSID(dest_srs_id)
        try:
            return self.transformation.transform(point)
        except:
            print 'Error on transform!'  # DEBUG! need message???
            return

    def transform_bbox(self, bbox):
        dest_srs_id = self.iface.mapCanvas().mapRenderer().destinationCrs().srsid()
        self.transformation.setDestCRSID(dest_srs_id)
        try:
            return self.transformation.transformBoundingBox(bbox)
        except:
            print 'Error on transform!'  # DEBUG! need message???
            return

    def transform_geom(self, geom):
        dest_srs_id = self.iface.mapCanvas().mapRenderer().destinationCrs().srsid()
        self.transformation.setDestCRSID(dest_srs_id)
        try:
            geom.transform(self.transformation)
            return geom
        except:
            print 'Error on transform!'  # DEBUG! need message???
            return

    def center_to_point(self, point):
        canvas = self.iface.mapCanvas()
        new_extent = QgsRectangle(canvas.extent())
        new_extent.scale(1, point)
        canvas.setExtent(new_extent)
        canvas.refresh()

    def zoom_to_bbox(self, bbox):
        if self.need_transform():
            bbox = self.transform_bbox(bbox)
        self.iface.mapCanvas().setExtent(bbox)
        self.iface.mapCanvas().refresh()


    def show_feature(self, geom):
        if self.need_transform():
            geom = self.transform_geom(geom)
        self.features_rb.setToGeometry(geom, None)

    def clear_feature(self):
        self.features_rb.reset(QGis.Point)
class ItemWidgetBase(QFrame):

    checkedStateChanged = pyqtSignal()
    thumbnailChanged = pyqtSignal()

    def __init__(self, item):
        QFrame.__init__(self)
        self.item = item
        self.is_updating_checkbox = False
        self.setMouseTracking(True)
        self.setStyleSheet("ItemWidgetBase{border: 2px solid transparent;}")

    def _setup_ui(self, text, thumbnailurl):

        self.lockLabel = QLabel()
        iconSize = QSize(16, 16)
        self.lockLabel.setPixmap(LOCK_ICON.pixmap(iconSize))
        self.checkBox = QCheckBox("")
        self.checkBox.clicked.connect(self.check_box_state_changed)
        self.nameLabel = QLabel(text)
        self.iconLabel = QLabel()
        self.labelZoomTo = QLabel()
        self.labelZoomTo.setPixmap(ZOOMTO_ICON.pixmap(QSize(18, 18)))
        self.labelZoomTo.setToolTip("Zoom to extent")
        self.labelZoomTo.mousePressEvent = self.zoom_to_extent
        self.labelAddPreview = QLabel()
        self.labelAddPreview.setPixmap(ADD_PREVIEW_ICON.pixmap(QSize(18, 18)))
        self.labelAddPreview.setToolTip("Add preview layer to map")
        self.labelAddPreview.mousePressEvent = self._add_preview_clicked

        layout = QHBoxLayout()
        layout.setMargin(0)
        layout.addWidget(self.checkBox)
        layout.addWidget(self.lockLabel)
        pixmap = QPixmap(PLACEHOLDER_THUMB, "SVG")
        self.thumbnail = None
        thumb = pixmap.scaled(48, 48, Qt.KeepAspectRatio,
                              Qt.SmoothTransformation)
        self.iconLabel.setPixmap(thumb)
        self.iconLabel.setFixedSize(48, 48)
        layout.addWidget(self.iconLabel)
        if thumbnailurl is not None:
            download_thumbnail(thumbnailurl, self)
        layout.addWidget(self.nameLabel)
        layout.addStretch()
        layout.addWidget(self.labelZoomTo)
        layout.addWidget(self.labelAddPreview)
        layout.addSpacing(10)
        self.setLayout(layout)

        self.footprint = QgsRubberBand(iface.mapCanvas(),
                                       QgsWkbTypes.PolygonGeometry)
        self.footprint.setStrokeColor(PLANET_COLOR)
        self.footprint.setWidth(2)

    def set_thumbnail(self, img):
        self.thumbnail = QPixmap(img)
        thumb = self.thumbnail.scaled(48, 48, Qt.KeepAspectRatio,
                                      Qt.SmoothTransformation)
        self.iconLabel.setPixmap(thumb)
        self.thumbnailChanged.emit()

    def is_selected(self):
        return self.checkBox.checkState() == Qt.Checked

    def _geom_bbox_in_project_crs(self):
        transform = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem("EPSG:4326"),
            QgsProject.instance().crs(),
            QgsProject.instance(),
        )
        return transform.transformBoundingBox(self.geom.boundingBox())

    def _geom_in_project_crs(self):
        transform = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem("EPSG:4326"),
            QgsProject.instance().crs(),
            QgsProject.instance(),
        )
        geom = QgsGeometry(self.geom)
        geom.transform(transform)
        return geom

    def show_footprint(self):
        self.footprint.setToGeometry(self._geom_in_project_crs())

    def hide_footprint(self):
        self.footprint.reset(QgsWkbTypes.PolygonGeometry)

    def enterEvent(self, event):
        self.setStyleSheet(
            "ItemWidgetBase{border: 2px solid rgb(0, 157, 165);}")
        self.show_footprint()

    def leaveEvent(self, event):
        self.setStyleSheet("ItemWidgetBase{border: 2px solid transparent;}")
        self.hide_footprint()

    def zoom_to_extent(self, evt):
        rect = QgsRectangle(self._geom_bbox_in_project_crs())
        rect.scale(1.05)
        iface.mapCanvas().setExtent(rect)
        iface.mapCanvas().refresh()

    def _add_preview_clicked(self, evt):
        self.add_preview()

    @waitcursor
    def add_preview(self):
        send_analytics_for_preview(self.item.images())
        create_preview_group(self.name(), self.item.images())

    def check_box_state_changed(self):
        self.update_children_items()
        self.update_parent_item()
        self.checkedStateChanged.emit()

    def update_parent_item(self):
        parent = self.item.parent()
        if parent is not None:
            w = parent.treeWidget().itemWidget(parent, 0)
            w.update_checkbox()

    def update_children_items(self):
        total = self.item.childCount()
        if self.checkBox.isTristate():
            self.checkBox.setTristate(False)
            self.checkBox.setChecked(False)
        for i in range(total):
            w = self.item.treeWidget().itemWidget(self.item.child(i), 0)
            w.set_checked(self.checkBox.isChecked())

    def update_checkbox(self):
        selected = 0
        total = self.item.childCount()
        for i in range(total):
            w = self.item.treeWidget().itemWidget(self.item.child(i), 0)
            if w.is_selected():
                selected += 1
        if selected == total:
            self.checkBox.setTristate(False)
            self.checkBox.setCheckState(Qt.Checked)
        elif selected == 0:
            self.checkBox.setTristate(False)
            self.checkBox.setCheckState(Qt.Unchecked)
        else:
            self.checkBox.setTristate(True)
            self.checkBox.setCheckState(Qt.PartiallyChecked)

    def set_checked(self, checked):
        self.checkBox.setChecked(checked)
        self.update_children_items()

    def update_thumbnail(self):
        thumbnails = self.scene_thumbnails()
        if thumbnails and None not in thumbnails:
            bboxes = [img[GEOMETRY] for img in self.item.images()]
            pixmap = createCompoundThumbnail(bboxes, thumbnails)
            thumb = pixmap.scaled(48, 48, Qt.KeepAspectRatio,
                                  Qt.SmoothTransformation)
            self.iconLabel.setPixmap(thumb)
            self.thumbnailChanged.emit()

    def scene_thumbnails(self):
        thumbnails = []
        try:
            for i in range(self.item.childCount()):
                w = self.item.treeWidget().itemWidget(self.item.child(i), 0)
                thumbnails.extend(w.scene_thumbnails())
        except RuntimeError:
            # item might not exist anymore. In this case, we just return
            # an empty list
            pass
        return thumbnails
Example #59
0
class FinderBox(QComboBox):

    running = False
    toFinish = 0

    searchStarted = pyqtSignal()
    searchFinished = pyqtSignal()

    def __init__(self, finders, iface, parent=None):
        self.iface = iface
        self.mapCanvas = iface.mapCanvas()
        self.rubber = QgsRubberBand(self.mapCanvas)
        self.rubber.setColor(QColor(255, 255, 50, 200))
        self.rubber.setIcon(self.rubber.ICON_CIRCLE)
        self.rubber.setIconSize(15)
        self.rubber.setWidth(4)
        self.rubber.setBrushStyle(Qt.NoBrush)

        QComboBox.__init__(self, parent)
        self.setEditable(True)
        self.setInsertPolicy(QComboBox.InsertAtTop)
        self.setMinimumHeight(27)
        self.setSizePolicy(QSizePolicy.Expanding,
                           QSizePolicy.Fixed)

        self.insertSeparator(0)
        self.lineEdit().returnPressed.connect(self.search)

        self.resultView = QTreeView()
        self.resultView.setHeaderHidden(True)
        self.resultView.setMinimumHeight(300)
        self.resultView.activated.connect(self.itemActivated)
        self.resultView.pressed.connect(self.itemPressed)
        self.setView(self.resultView)

        self.resultModel = ResultModel(self)
        self.setModel(self.resultModel)

        self.finders = finders
        for finder in self.finders.values():
            finder.resultFound.connect(self.resultFound)
            finder.limitReached.connect(self.limitReached)
            finder.finished.connect(self.finished)

        self.clearButton = QPushButton(self)
        self.clearButton.setIcon(QIcon(":/plugins/quickfinder/icons/draft.svg"))
        self.clearButton.setText('')
        self.clearButton.setFlat(True)
        self.clearButton.setCursor(QCursor(Qt.ArrowCursor))
        self.clearButton.setStyleSheet('border: 0px; padding: 0px;')
        self.clearButton.clicked.connect(self.clear)

        layout = QHBoxLayout(self)
        self.setLayout(layout)
        layout.addStretch()
        layout.addWidget(self.clearButton)
        layout.addSpacing(20)

        buttonSize = self.clearButton.sizeHint()
        # frameWidth = self.lineEdit().style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
        padding = buttonSize.width()  # + frameWidth + 1
        self.lineEdit().setStyleSheet('QLineEdit {padding-right: %dpx; }' % padding)

    def __del__(self):
        if self.rubber:
            self.iface.mapCanvas().scene().removeItem(self.rubber)
            del self.rubber

    def clearSelection(self):
        self.resultModel.setSelected(None, self.resultView.palette())
        self.rubber.reset()

    def clear(self):
        self.clearSelection()
        self.resultModel.clearResults()
        self.lineEdit().setText('')

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.clearSelection()
        QComboBox.keyPressEvent(self, event)

    def search(self):
        if self.running:
            return

        toFind = self.lineEdit().text()
        if not toFind or toFind == '':
            return

        self.running = True
        self.searchStarted.emit()

        self.clearSelection()
        self.resultModel.clearResults()
        self.resultModel.truncateHistory(MySettings().value("historyLength"))
        self.resultModel.setLoading(True)
        self.showPopup()

        QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

        self.findersToStart = []
        for finder in self.finders.values():
            if finder.activated():
                self.findersToStart.append(finder)

        bbox = self.mapCanvas.fullExtent()

        while len(self.findersToStart) > 0:
            finder = self.findersToStart[0]
            self.findersToStart.remove(finder)
            self.resultModel.addResult(finder.name)
            finder.start(toFind, bbox=bbox)

        # For case there is no finder activated
        self.finished(None)

    def stop(self):
        self.findersToStart = []
        for finder in self.finders.values():
            if finder.isRunning():
                finder.stop()
        self.finished(None)

    def resultFound(self, finder, layername, value, geometry, srid):
        self.resultModel.addResult(finder.name, layername, value, geometry, srid)
        self.resultView.expandAll()

    def limitReached(self, finder, layername):
        self.resultModel.addEllipsys(finder.name, layername)

    def finished(self, finder):
        if len(self.findersToStart) > 0:
            return
        for finder in self.finders.values():
            if finder.isRunning():
                return

        self.running = False
        self.searchFinished.emit()

        self.resultModel.setLoading(False)

        QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

    def itemActivated(self, index):
        item = self.resultModel.itemFromIndex(index)
        self.showItem(item)

    def itemPressed(self, index):
        item = self.resultModel.itemFromIndex(index)
        if QApplication.mouseButtons() == Qt.LeftButton:
            self.showItem(item)

    def showItem(self, item):
        if isinstance(item, ResultItem):
            self.resultModel.setSelected(item, self.resultView.palette())
            geometry = self.transformGeom(item)
            self.rubber.reset(geometry.type())
            self.rubber.setToGeometry(geometry, None)
            self.zoomToRubberBand()
            return

        if isinstance(item, GroupItem):
            child = item.child(0)
            if isinstance(child, ResultItem):
                self.resultModel.setSelected(item, self.resultView.palette())
                self.rubber.reset(child.geometry.type())
                for i in xrange(0, item.rowCount()):
                    geometry = self.transformGeom(item.child(i))
                    self.rubber.addGeometry(geometry, None)
                self.zoomToRubberBand()
            return

        if item.__class__.__name__ == 'QStandardItem':
            self.clearSelection()

    def transformGeom(self, item):
        src_crs = QgsCoordinateReferenceSystem()
        src_crs.createFromSrid(item.srid)
        dest_crs = self.mapCanvas.mapRenderer().destinationCrs()
        geom = QgsGeometry(item.geometry)
        geom.transform(QgsCoordinateTransform(src_crs, dest_crs))
        return geom

    def zoomToRubberBand(self):
        geom = self.rubber.asGeometry()
        if geom:
            rect = geom.boundingBox()
            rect.scale(1.5)
            self.mapCanvas.setExtent(rect)
            self.mapCanvas.refresh()