Beispiel #1
1
    def __init__(self, iface):
        # QGIS
        self.iface = iface
        self.settings = MySettings()
        self.linkRubber = QgsRubberBand(self.iface.mapCanvas())
        self.featureHighlight = None
        # Relation management
        self.relationManager = QgsProject.instance().relationManager()
        self.relationManager.changed.connect(self.loadRelations)
        self.relation = QgsRelation()
        self.referencingFeature = QgsFeature()
        self.relationWidgetWrapper = None
        self.editorContext = QgsAttributeEditorContext()
        self.editorContext.setVectorLayerTools(self.iface.vectorLayerTools())

        # GUI
        QDockWidget.__init__(self)
        self.setupUi(self)
        SettingDialog.__init__(self, MySettings(), False, True)
        self.drawButton.setChecked(self.settings.value("drawEnabled"))

        self.relationReferenceWidget.setAllowMapIdentification(True)
        self.relationReferenceWidget.setEmbedForm(False)

        self.mapTool = QgsMapToolIdentifyFeature(self.iface.mapCanvas())
        self.mapTool.setButton(self.identifyReferencingFeatureButton)

        # Connect signal/slot
        self.relationComboBox.currentIndexChanged.connect(self.currentRelationChanged)
        self.mapTool.featureIdentified.connect(self.setReferencingFeature)

        # load relations at start
        self.loadRelations()
    def startCapturing(self):
        self.clearScene()

        self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
        self.rubberBand.setWidth(2)
        self.rubberBand.setFillColor(QColor(220, 0, 0, 120))
        self.rubberBand.setBorderColor(QColor(220, 0, 0))
        self.rubberBand.setLineStyle(Qt.DotLine)
        self.rubberBand.show()

        self.tempRubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
        self.tempRubberBand.setWidth(2)
        self.tempRubberBand.setFillColor(QColor(0, 0, 0, 0))
        self.tempRubberBand.setBorderColor(QColor(220, 0, 0))
        self.tempRubberBand.setLineStyle(Qt.DotLine)
        self.tempRubberBand.show()

        self.vertexMarker = QgsVertexMarker(self.canvas)
        self.vertexMarker.setIconType(1)
        self.vertexMarker.setColor(QColor(220, 0, 0))
        self.vertexMarker.setIconSize(16)
        self.vertexMarker.setPenWidth(3)
        self.vertexMarker.show()

        self.capturing = True
    def __init__(self, iface):
        self.iface = iface
        self.canvas = iface.mapCanvas()
        QgsMapToolEmitPoint.__init__(self, self.canvas)

        self.rasterShadow = RasterShadowMapCanvasItem(self.canvas)

        self.firstPoint = None

        self.rubberBandOrigin = QgsRubberBand(
            self.canvas, QgsWkbTypes.PointGeometry)
        self.rubberBandOrigin.setColor(Qt.red)
        self.rubberBandOrigin.setIcon(QgsRubberBand.ICON_CIRCLE)
        self.rubberBandOrigin.setIconSize(7)
        self.rubberBandOrigin.setWidth(2)

        self.rubberBandDisplacement = QgsRubberBand(
            self.canvas, QgsWkbTypes.LineGeometry)
        self.rubberBandDisplacement.setColor(Qt.red)
        self.rubberBandDisplacement.setWidth(1)

        self.rubberBandExtent = QgsRubberBand(
            self.canvas, QgsWkbTypes.LineGeometry)
        self.rubberBandExtent.setColor(Qt.red)
        self.rubberBandExtent.setWidth(2)

        self.isLayerVisible = True

        self.reset()
 def __init__(self, canvas, iface):
     """
     Tool Behaviours: (all behaviours start edition, except for rectangle one)
     1- Left Click: Clears previous selection, selects feature, sets feature layer as active layer. 
     The selection is done with the following priority: Point, Line then Polygon. 
     Selection is only done in visible layer.
     2- Control + Left Click: Adds to selection selected feature. This selection follows the priority in item 1.
     3- Right Click: Opens feature form
     4- Control + Right Click: clears selection and set feature's layer as activeLayer. activeLayer's definition
     follows priority of item 1;
     5- Shift + drag and drop: draws a rectangle, then features that intersect this rectangl'e are added to selection
     """
     self.iface = iface        
     self.canvas = canvas
     self.toolAction = None
     QgsMapTool.__init__(self, self.canvas)
     self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
     self.hoverRubberBand = QgsRubberBand(self.canvas, QGis.Polygon)
     mFillColor = QColor( 254, 178, 76, 63 )
     self.rubberBand.setColor(mFillColor)
     self.hoverRubberBand.setColor(QColor( 255, 0, 0, 90 ))
     self.rubberBand.setWidth(1)
     self.reset()
     self.blackList = self.getBlackList()
     self.cursorChanged = False
     self.cursorChangingHotkey = QtCore.Qt.Key_Alt
     self.menuHovered = False # indicates hovering actions over context menu
Beispiel #5
0
class QgepMapTool( QgsMapTool ):
    '''
    Base class for all the map tools
    '''
    
    highLightedPoints = []
    logger = logging.getLogger( __name__ )
    
    def __init__( self, iface, button ):
        QgsMapTool.__init__( self, iface.mapCanvas() )
        self.canvas = iface.mapCanvas()
        self.cursor = QCursor( Qt.CrossCursor )
        self.button = button
        self.msgBar = iface.messageBar()

        settings = QSettings()
        currentProfileColor = settings.value( "/QGEP/CurrentProfileColor", u'#FF9500' )
        
        self.rubberBand = QgsRubberBand( self.canvas )
        self.rubberBand.setColor( QColor( currentProfileColor ) )
        self.rubberBand.setWidth( 3 )

    # Gets called when the tool is activated
    def activate( self ):
        QgsMapTool.activate( self )
        self.canvas.setCursor( self.cursor )
        self.button.setChecked( True )

    # Gets called whenever the tool is deactivated directly or indirectly
    def deactivate( self ):
        QgsMapTool.deactivate( self )
        self.button.setChecked( False )

    def isZoomTool( self ):
        return False

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

    #===========================================================================
    # Events
    #===========================================================================
    
    def canvasMoveEvent( self, event ):
        try:
            self.mouseMoved( event )
        except AttributeError:
            pass

    def canvasReleaseEvent( self, event ):
        if event.button() == Qt.RightButton:
            self.rightClicked ( event )
        else:
            self.leftClicked( event )

    def canvasDoubleClickEvent( self, event ):
        try:
            self.doubleClicked( event )
        except AttributeError:
            pass
 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 )
Beispiel #7
0
 def __init__(self, iface, couleur):
     canvas = iface.mapCanvas()
     QgsMapTool.__init__(self, canvas)
     self.canvas = canvas
     self.iface = iface
     self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry)
     self.rb.setColor(couleur)
     self.rbSelect = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry)
     return None
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        super(EarthMineQGIS, self).__init__()
        self.movingfeature = None
        self.iface = iface
        self.viewer = None
        self.canvas = self.iface.mapCanvas()
        self.settings = QSettings()
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value("locale/userLocale")[0:2]
        locale_path = os.path.join(self.plugin_dir, "i18n", "EarthMineQGIS_{}.qm".format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > "4.3.3":
                QCoreApplication.installTranslator(self.translator)

        self.pointtool = QgsMapToolEmitPoint(self.canvas)
        self.pointtool.canvasClicked.connect(self.set_viewer_location)

        self.settingsdialog = SettingsDialog(self.iface.mainWindow())

        self.actions = []
        self.menu = self.tr(u"&Earthmine")

        self.toolbar = self.iface.addToolBar(u"EarthMineQGIS")
        self.toolbar.setObjectName(u"EarthMineQGIS")

        self.legend = self.iface.legendInterface()

        emcolor = QColor(1, 150, 51)
        self.tempband = QgsRubberBand(self.canvas, QGis.Line)
        self.tempband.setWidth(5)
        self.tempband.setColor(emcolor)

        self.tempbandpoints = QgsRubberBand(self.canvas, QGis.Point)
        self.tempbandpoints.setWidth(7)
        self.tempbandpoints.setColor(emcolor)

        self.movingband = QgsRubberBand(self.canvas, QGis.Point)
        self.movingband.setWidth(5)
        self.movingband.setColor(emcolor)

        self.layersignals = []
        self.marker = None
    def __init__(self, layer, feature, mapCanvas, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.settings = MySettings()
        SettingDialog.__init__(self, self.settings, False, True)
        self.mapCanvas = mapCanvas
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.feature = feature
        self.initialGeometry = QgsGeometry(feature.geometry())
        self.layer = layer

        # close if no geom, hide "sketch current point" if not needed
        geomType = layer.geometryType()
        if not geomType in (QGis.Point, QGis.Line, QGis.Polygon):
            self.close()
            return
        if geomType == QGis.Point:
            self.pointRubberGroup.hide()

        # editors management
        self.editorLayout = QGridLayout(self.editorContainer)
        self.editor = GeomEditor(layer, feature.geometry())
        self.displayCombo.setCurrentIndex(0)
        self.displayCombo.currentIndexChanged.connect(self.setEditor)
        self.setEditor()

        # rubber bands
        self.featureRubber = QgsRubberBand(mapCanvas)
        self.currentPointRubber = QgsRubberBand(mapCanvas)
        self.settings.setting("featureRubberColor").valueChanged.connect(self.updateFeatureRubber)
        self.settings.setting("featureRubberSize").valueChanged.connect(self.updateFeatureRubber)
        self.settings.setting("currentPointRubberSize").valueChanged.connect(self.updateCurrentPointRubber)
        self.settings.setting("currentPointRubberColor").valueChanged.connect(self.updateCurrentPointRubber)
        self.settings.setting("currentPointRubberIcon").valueChanged.connect(self.updateCurrentPointRubber)
        self.updateFeatureRubber()
        self.updateCurrentPointRubber()
        self.geometryChanged()

        # GUI signals connection
        self.applyButton.clicked.connect(self.applyGeometry)
        self.resetButton.clicked.connect(self.resetGeometry)
        self.sketchGeometry.clicked.connect(self.geometryChanged)
        self.displayPointRubber.clicked.connect(self.currentPointRubber.reset)
        self.layerEditable()
        layer.editingStopped.connect(self.layerEditable)
        layer.editingStarted.connect(self.layerEditable)

        # set texts in UI
        self.layerLabel.setText(layer.name())
        try:
            featureTitle = unicode(feature[layer.displayField()])
        except KeyError:
            featureTitle = ""
        if featureTitle == "":
            featureTitle = str(feature.id())
        self.featureEdit.setText(featureTitle)
    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()
Beispiel #11
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 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)
 def getSnapRubberBand(self):
     rubberBand = QgsRubberBand(self.canvas, geometryType = QGis.Point)
     rubberBand.setFillColor(QColor(255, 0, 0, 40))
     rubberBand.setBorderColor(QColor(255, 0, 0, 200))
     rubberBand.setWidth(2)
     rubberBand.setIcon(QgsRubberBand.ICON_X)
     return rubberBand        
 def __init__(self, iface, layer):
     QgsMapToolAdvancedDigitizing.__init__(self, iface.mapCanvas(), iface.cadDockWidget())
     self.iface = iface
     self.canvas = iface.mapCanvas()
     self.layer = layer
     self.rubberband = QgsRubberBand(iface.mapCanvas(), layer.geometryType())
     self.rubberband.setColor(QColor("#ee5555"))
     self.rubberband.setWidth(1)
     self.tempRubberband = QgsRubberBand(iface.mapCanvas(), layer.geometryType())
     self.tempRubberband.setColor(QColor("#ee5555"))
     self.tempRubberband.setWidth(1)
     self.tempRubberband.setLineStyle(Qt.DotLine)
Beispiel #15
0
 def __init__(self, iface, layer):
     QgsMapTool.__init__(self, iface.mapCanvas() )
     self.iface = iface
     self.canvas = iface.mapCanvas()
     self.layer = layer
     self.rubberband = QgsRubberBand( iface.mapCanvas(), layer.geometryType() )
     self.rubberband.setColor( QColor( "#ee5555" ) )
     self.rubberband.setWidth( 2 )
     self.tempRubberband = QgsRubberBand( iface.mapCanvas(), layer.geometryType() )
     self.tempRubberband.setColor( QColor( "#ee5555" ) )
     self.tempRubberband.setWidth( 2 )
     self.tempRubberband.setLineStyle(Qt.DotLine)
 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)
Beispiel #17
0
    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 __init__(self):
        self.iface = iface

        self.srs_wgs84 = QgsCoordinateReferenceSystem(4326)
        self.transform_decorator = QgsCoordinateTransform(self.srs_wgs84, self.srs_wgs84)

        self.rb = QgsRubberBand(self.iface.mapCanvas(), QGisGeometryType.Point)
        self.rb.setColor(QColor('magenta'))
        self.rb.setIconSize(12)

        self.features_rb = QgsRubberBand(self.iface.mapCanvas(), QGisGeometryType.Point)
        magenta_transp = QColor('#3388ff')
        magenta_transp.setAlpha(120)
        self.features_rb.setColor(magenta_transp)
        self.features_rb.setIconSize(12)
        self.features_rb.setWidth(2)
Beispiel #19
0
    def __init__(self, canvas, forms, snapradius = 2):
        MapTool.__init__(self, canvas, [])
        self.canvas = canvas
        self.radius = snapradius
        self.forms = forms
        
        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224,162,16))
        self.band.setWidth(3)
        
        self.selectband = None
        
        self.selectrect = QRect()
        self.dragging = False

        self.cursor = QCursor(QPixmap(["16 16 3 1",
            "      c None",
            ".     c #FF0000",
            "+     c #FFFFFF",
            "                ",
            "       +.+      ",
            "      ++.++     ",
            "     +.....+    ",
            "    +.     .+   ",
            "   +.   .   .+  ",
            "  +.    .    .+ ",
            " ++.    .    .++",
            " ... ...+... ...",
            " ++.    .    .++",
            "  +.    .    .+ ",
            "   +.   .   .+  ",
            "   ++.     .+   ",
            "    ++.....+    ",
            "      ++.++     ",
            "       +.+      "]))
 def setExtent():
   if not self.extent is None:
     self.canvas.scene().removeItem( self.extent )
   self.extent = QgsRubberBand( self.canvas, QGis.Polygon )
   self.extent.setBorderColor( QColor( 255, 0 , 0 ) )
   self.extent.setWidth( 2 )
   self._extent()
Beispiel #21
0
    def canvasPressEvent(self, event):
        self.dragging = False
        self.selectrect.setRect( 0, 0, 0, 0 )

        self.selectband = QgsRubberBand(self.canvas, QGis.Polygon )
        self.selectband.setColor(QColor.fromRgb(0,0,255, 65))
        self.selectband.setWidth(5)
    def initGui(self):
        self.actions['openInspection'] = QAction(
            QIcon(":/plugins/wincan2qgep/icons/wincan_logo.png"),
            self.tr(u"Ouvrir une inspection"),
            self.iface.mainWindow())
        self.actions['openInspection'].triggered.connect(self.openInspection)
        self.iface.addPluginToMenu(self.name, self.actions['openInspection'])
        self.iface.addToolBarIcon(self.actions['openInspection'])

        self.actions['showSettings'] = QAction(
            QIcon(":/plugins/wincan2qgep/icons/settings.svg"),
            self.tr(u"&Settings"),
            self.iface.mainWindow())
        self.actions['showSettings'].triggered.connect(self.showSettings)
        self.iface.addPluginToMenu(self.name, self.actions['showSettings'])

        self.actions['help'] = QAction(
            QIcon(":/plugins/wincan2qgep/icons/help.svg"),
            self.tr("Help"),
            self.iface.mainWindow())
        self.actions['help'].triggered.connect(lambda: QDesktopServices().openUrl(QUrl("http://3nids.github.io/wincan2qgep")))
        self.iface.addPluginToMenu(self.name, self.actions['help'])

        self.rubber = QgsRubberBand(self.iface.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)
Beispiel #23
0
    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()
Beispiel #24
0
 def __init__(self, canvas, layerfrom, layerto, 
                     mapping, validation_method):
     """
         mapping - A dict of field - field mapping with values to
                         copy to the new layer
     """
     QgsMapTool.__init__(self, canvas)
     self.layerfrom = layerfrom
     self.layerto = layerto
     self.fields = mapping
     self.validation_method = validation_method
     self.band = QgsRubberBand(canvas, QGis.Polygon )
     self.band.setColor(QColor.fromRgb(255,0,0, 65))
     self.band.setWidth(5)
     
     self.cursor = QCursor(QPixmap(["16 16 3 1",
         "      c None",
         ".     c #FF0000",
         "+     c #FFFFFF",
         "                ",
         "       +.+      ",
         "      ++.++     ",
         "     +.....+    ",
         "    +.     .+   ",
         "   +.   .   .+  ",
         "  +.    .    .+ ",
         " ++.    .    .++",
         " ... ...+... ...",
         " ++.    .    .++",
         "  +.    .    .+ ",
         "   +.   .   .+  ",
         "   ++.     .+   ",
         "    ++.....+    ",
         "      ++.++     ",
         "       +.+      "]))
Beispiel #25
0
 def run(self):
     logger.debug(u"run, processing name {}".format(self.processing_name))
     logger.debug(u"self.arg {}".format(self.arg))
     output_filename = ""
     if "NDVI" in self.processing_name:
         output_filename = terre_image_processing.ndvi(self.layer, self.working_directory)
     if "NDTI" in self.processing_name:
         output_filename = terre_image_processing.ndti(self.layer, self.working_directory)
     if "Indice de brillance" in self.processing_name:
         output_filename = terre_image_processing.brightness(self.layer, self.working_directory)
     if "Angle Spectral" in self.processing_name:
         self.rubberband = QgsRubberBand(self.canvas, QGis.Point)
         self.rubberband.setWidth(10)
         self.rubberband.setColor(QColor(Qt.yellow))
         if not self.arg:
             from spectral_angle import SpectralAngle
             self.angle_tool = SpectralAngle(self.iface, self.working_directory, self.layer, self.mirrormap_tool, self.rubberband)
             logger.debug("self.angle_tool {}".format(self.angle_tool))
             QObject.connect(self.angle_tool, SIGNAL("anglesComputed(PyQt_PyObject)"), self.display)
             self.angle_tool.get_point_for_angles(self.layer)
             # spectral_angles(self.layer, self.working_directory, self.iface)
         else:
             output_filename = self.arg
     if "KMEANS" in self.processing_name:
         if self.arg:
             output_filename = terre_image_processing.kmeans(self.layer, self.working_directory, self.arg)
         else:
             output_filename = terre_image_processing.kmeans(self.layer, self.working_directory)
     if "Seuillage" in self.processing_name and self.arg:
         logger.debug("this is thrshold")
         output_filename = terre_image_processing.threshold(self.layer, self.working_directory, self.arg)
     if output_filename:
         terre_image_gdal_system.compute_overviews(output_filename)
         logger.debug(output_filename)
         self.display(output_filename)
Beispiel #26
0
 def canvasMoveEvent(self, e):
     super(ArkMapToolInteractive, self).canvasMoveEvent(e)
     if not self._active:
         return
     e.ignore()
     if (self._panningEnabled and e.buttons() & Qt.LeftButton):
         # Pan map mode
         if not self._dragging:
             self._dragging = True
             self.setCursor(QCursor(Qt.ClosedHandCursor))
         self.canvas().panAction(e)
         e.accept()
     elif (self._zoomingEnabled and e.buttons() & Qt.RightButton):
         # Zoom map mode
         if not self._dragging:
             self._dragging = True
             self.setCursor(QCursor(Qt.ClosedHandCursor))
             self._zoomRubberBand = QgsRubberBand(self.canvas(), QGis.Polygon)
             color = QColor(Qt.blue)
             color.setAlpha(63)
             self._zoomRubberBand.setColor(color)
             self._zoomRect = QRect(0, 0, 0, 0)
             self._zoomRect.setTopLeft(e.pos())
         self._zoomRect.setBottomRight(e.pos())
         if self._zoomRubberBand is not None:
             self._zoomRubberBand.setToCanvasRectangle(self._zoomRect)
             self._zoomRubberBand.show()
         e.accept()
     elif self._snappingEnabled:
         mapPoint, snapped = self._snapCursorPoint(e.pos())
         if (snapped):
             self._createSnappingMarker(mapPoint)
         else:
             self._deleteSnappingMarker()
Beispiel #27
0
 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)
Beispiel #28
0
    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))
Beispiel #29
0
 def __init__(self, canvas, layer, column, bindto, radius ):
     QgsMapToolEmitPoint.__init__(self, canvas)
     self.layer = layer
     self.column = column
     self.bindto = bindto
     self.canvas = canvas
     self.bindto = bindto
     self.searchradius = radius
     self.canvasClicked.connect(self.findFeature)
     self.canvas.setMapTool(self)
     self.band = QgsRubberBand(self.canvas)
     self.band.setColor(Qt.blue)
     self.band.setWidth(3)
     self.rect = QgsRectangle()
     self.cursor = QCursor(QPixmap(["16 16 3 1",
         "      c None",
         ".     c #32CD32",
         "+     c #32CD32",
         "                ",
         "       +.+      ",
         "      ++.++     ",
         "     +.....+    ",
         "    +.     .+   ",
         "   +.   .   .+  ",
         "  +.    .    .+ ",
         " ++.    .    .++",
         " ... ...+... ...",
         " ++.    .    .++",
         "  +.    .    .+ ",
         "   +.   .   .+  ",
         "   ++.     .+   ",
         "    ++.....+    ",
         "      ++.++     ",
         "       +.+      "]))
    def initGui(self):
        self.actions['showSettings'] = QAction(
            QIcon(":/plugins/quickfinder/icons/settings.svg"),
            self.tr(u"&Settings"),
            self.iface.mainWindow())
        self.actions['showSettings'].triggered.connect(self.showSettings)
        self.iface.addPluginToMenu(self.name, self.actions['showSettings'])

        self.actions['help'] = QAction(
            QIcon(":/plugins/quickfinder/icons/help.svg"),
            self.tr("Help"),
            self.iface.mainWindow())
        self.actions['help'].triggered.connect(
            lambda: QDesktopServices().openUrl(
                QUrl("https://github.com/3nids/quickfinder/wiki")))
        self.iface.addPluginToMenu(self.name, self.actions['help'])

        self._initToolbar()

        self.rubber = QgsRubberBand(self.iface.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)
Beispiel #31
0
class VideoWidget(QVideoWidget):

    def __init__(self, parent=None):
        ''' Constructor '''
        super().__init__(parent)
        self.surface = VideoWidgetSurface(self)
        self.setAttribute(Qt.WA_OpaquePaintEvent)
        
        self.Tracking_Video_RubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.Censure_RubberBand = QRubberBand(QRubberBand.Rectangle, self)

        color_blue = QColor(Qt.blue)
        color_black = QColor(Qt.black)
        color_amber = QColor(252, 215, 108)
        
        pal_blue = QPalette()
        pal_blue.setBrush(QPalette.Highlight, QBrush(color_blue))
        self.Tracking_Video_RubberBand.setPalette(pal_blue)

        pal_black = QPalette()
        pal_black.setBrush(QPalette.Highlight, QBrush(color_black))
        self.Censure_RubberBand.setPalette(pal_black)

        self._interaction = InteractionState()
        self._filterSatate = FilterState()

        self._isinit = False
        self._MGRS = False
        self.gt = None

        self.drawCesure = []
        self.poly_coordinates, self.drawPtPos, self.drawLines, self.drawMeasureDistance, self.drawMeasureArea, self.drawPolygon = [], [], [], [], [], []
        # Draw Polygon Canvas Rubberband
        self.poly_Canvas_RubberBand = QgsRubberBand(
            iface.mapCanvas(), True)  # Polygon type
        # set rubber band style
        self.poly_Canvas_RubberBand.setColor(color_amber)
        self.poly_Canvas_RubberBand.setWidth(3)

        # Tracking Canvas Rubberband
        self.Track_Canvas_RubberBand = QgsRubberBand(
            iface.mapCanvas(), QgsWkbTypes.LineGeometry)
        # set rubber band style
        self.Track_Canvas_RubberBand.setColor(color_blue)
        self.Track_Canvas_RubberBand.setWidth(5)
        
        self.parent = parent.parent()

        palette = self.palette()
        palette.setColor(QPalette.Background, Qt.transparent)
        self.setPalette(palette)

        self.origin, self.dragPos = QPoint(), QPoint()
        self.tapTimer = QBasicTimer()
        self.brush = QBrush(color_black)
        self.blue_Pen = QPen(color_blue, 3)

    def removeLastLine(self):
        ''' Remove Last Line Objects '''
        if self.drawLines:
            try:
                if self.drawLines[-1][3] == "mouseMoveEvent":
                    del self.drawLines[-1]  # Remove mouseMoveEvent element
            except Exception:
                None
            for pt in range(len(self.drawLines) - 1, -1, -1):
                del self.drawLines[pt]
                try:
                    if self.drawLines[pt - 1][0] is None:
                        break
                except Exception:
                    None
            self.UpdateSurface()
            AddDrawLineOnMap(self.drawLines)
        return

    def removeLastSegmentLine(self):
        ''' Remove Last Segment Line Objects '''
        try:
            if self.drawLines[-1][3] == "mouseMoveEvent":
                del self.drawLines[-1]  # Remove mouseMoveEvent element
        except Exception:
            None
        if self.drawLines:
            if self.drawLines[-1][0] is None:
                del self.drawLines[-1]
            
            del self.drawLines[-1]
            self.UpdateSurface()
            AddDrawLineOnMap(self.drawLines)
        return

    def removeAllLines(self):
        ''' Resets Line List '''
        if self.drawLines:
            self.drawLines = []
            self.UpdateSurface()
            # Clear all Layer
            RemoveAllDrawLineOnMap()

    def ResetDrawMeasureDistance(self):
        ''' Resets Measure Distance List '''
        self.drawMeasureDistance = []
        
    def ResetDrawMeasureArea(self):
        ''' Resets Measure Area List '''
        self.drawMeasureArea = []

    def removeAllCensure(self):
        ''' Remove All Censure Objects '''
        if self.drawCesure:
            self.drawCesure = []
            self.UpdateSurface()

    def removeLastCensured(self):
        ''' Remove Last Censure Objects '''
        if self.drawCesure:
            del self.drawCesure[-1]
            self.UpdateSurface()

    def removeLastPoint(self):
        ''' Remove All Point Drawer Objects '''
        if self.drawPtPos:
            del self.drawPtPos[-1]
            self.UpdateSurface()
            RemoveLastDrawPointOnMap()
        return

    def removeAllPoint(self):
        ''' Remove All Point Drawer Objects '''
        if self.drawPtPos:
            self.drawPtPos = []
            self.UpdateSurface()
            # Clear all Layer
            RemoveAllDrawPointOnMap()
        return

    def removeAllPolygon(self):
        ''' Remove All Polygon Drawer Objects '''
        if self.drawPolygon:
            self.drawPolygon = []
            self.UpdateSurface()
            # Clear all Layer
            RemoveAllDrawPolygonOnMap()

    def removeLastPolygon(self):
        ''' Remove Last Polygon Drawer Objects '''
        if self.drawPolygon:
            try:
                if self.drawPolygon[-1][3] == "mouseMoveEvent":
                    del self.drawPolygon[-1]  # Remove mouseMoveEvent element
            except Exception:
                None
            for pt in range(len(self.drawPolygon) - 1, -1, -1):
                del self.drawPolygon[pt]
                try:
                    if self.drawPolygon[pt - 1][0] is None:
                        break
                except Exception:
                    None
            
            self.UpdateSurface()
            # remove last index layer
            RemoveLastDrawPolygonOnMap()

    def keyPressEvent(self, event):
        ''' Exit fullscreen '''
        if event.key() == Qt.Key_Escape and self.isFullScreen():
            self.setFullScreen(False)
            event.accept()
        elif event.key() == Qt.Key_Enter and event.modifiers() & Qt.Key_Alt:
            self.setFullScreen(not self.isFullScreen())
            event.accept()
        else:
            super().keyPressEvent(event)

    def mouseDoubleClickEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if GetImageHeight() == 0:
            return

        if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)):
            return

        if self.gt is not None and self._interaction.lineDrawer:
            self.drawLines.append([None, None, None])          
            return
        
        if self.gt is not None and self._interaction.measureDistance:
            self.drawMeasureDistance.append([None, None, None])
            return
        
        if self.gt is not None and self._interaction.measureArea:
            self.drawMeasureArea.append([None, None, None])
            return
        
        if self.gt is not None and self._interaction.polygonDrawer:
            
            ok = AddDrawPolygonOnMap(self.poly_coordinates)
            # Prevent invalid geometry (Polygon with 2 points)
            if not ok:
                return
            
            self.drawPolygon.append([None, None, None])

            # Empty RubberBand
            for _ in range(self.poly_Canvas_RubberBand.numberOfVertices()):
                self.poly_Canvas_RubberBand.removeLastPoint()
            # Empty List
            self.poly_coordinates = []
            return
        
        self.UpdateSurface()
        self.setFullScreen(not self.isFullScreen())
        event.accept()

    def videoSurface(self):
        ''' Return video Surface '''
        return self.surface

    def UpdateSurface(self):
        ''' Update Video Surface only is is stopped or paused '''   
        if self.parent.playerState in (QMediaPlayer.StoppedState,
                                QMediaPlayer.PausedState):
            self.update()
        QApplication.processEvents()

    def sizeHint(self):
        ''' This property holds the recommended size for the widget '''
        return self.surface.surfaceFormat().sizeHint()

    def currentFrame(self):
        ''' Return current frame QImage '''
        return self.surface.image

    def SetInvertColor(self, value):
        ''' Set Invert color filter '''
        self._filterSatate.invertColorFilter = value

    def SetObjectTracking(self, value):
        ''' Set Object Tracking '''
        self._interaction.objectTracking = value

    def SetMeasureDistance(self, value):
        ''' Set measure Distance '''
        self._interaction.measureDistance = value
        
    def SetMeasureArea(self, value):
        ''' Set measure Area '''
        self._interaction.measureArea = value

    def SetHandDraw(self, value):
        ''' Set Hand Draw '''
        self._interaction.HandDraw = value

    def SetCensure(self, value):
        ''' Set Censure Video Parts '''
        self._interaction.censure = value
        
    def SetMGRS(self, value):
        ''' Set MGRS Cursor Coordinates '''
        self._MGRS = value

    def SetGray(self, value):
        ''' Set gray scale '''
        self._filterSatate.grayColorFilter = value

    def SetMirrorH(self, value):
        ''' Set Horizontal Mirror '''
        self._filterSatate.MirroredHFilter = value

    def SetNDVI(self, value):
        ''' Set NDVI '''
        self._filterSatate.NDVI = value

    def SetEdgeDetection(self, value):
        ''' Set Canny Edge filter '''
        self._filterSatate.edgeDetectionFilter = value

    def SetAutoContrastFilter(self, value):
        ''' Set Automatic Contrast filter '''
        self._filterSatate.contrastFilter = value

    def SetMonoFilter(self, value):
        ''' Set mono filter '''
        self._filterSatate.monoFilter = value

    def RestoreFilters(self):
        ''' Remove and restore all video filters '''
        self._filterSatate.clear()

    def RestoreDrawer(self):
        ''' Remove and restore all Drawer Options '''
        self._interaction.clear()
        # Magnifier Glass
        self.dragPos = QPoint()
        self.tapTimer.stop()
        
    def RemoveCanvasRubberbands(self):
        ''' Remove Canvas Rubberbands '''
        self.poly_Canvas_RubberBand.reset()
        self.Track_Canvas_RubberBand.reset()

    def paintEvent(self, event):
        ''' Paint Event '''
        if not self.surface.isActive():
            return
        
        # print("paintEvent : " + str(event.region().boundingRect()))
        # print("Active : " + str(self.surface.isActive()))
        
        self.painter = QPainter(self)
        self.painter.setRenderHint(QPainter.HighQualityAntialiasing)
 
        region = event.region()
        self.painter.fillRect(region.boundingRect() , self.brush)  # Background painter color
 
        try:
            self.surface.paint(self.painter)
            SetImageSize(self.currentFrame().width(),
                     self.currentFrame().height())
        except Exception:
            None
            
        # Prevent draw on video if not started or finished
        if self.parent.player.position() == 0:
            self.painter.end()
            return          
        
        self.gt = GetGCPGeoTransform()
        
        # Draw On Video
        draw.drawOnVideo(self.drawPtPos, self.drawLines, self.drawPolygon,
                         self.drawMeasureDistance, self.drawMeasureArea, self.drawCesure, self.painter, self.surface, self.gt)
        
        # Draw On Video Object tracking test
        if self._interaction.objectTracking and self._isinit:
            frame = convertQImageToMat(self.currentFrame())
            offset = self.surface.videoRect()
            # Update tracker
            result = resize(frame, (offset.width(), offset.height()))
            ok, bbox = self.tracker.update(result)
            # Draw bounding box
            if ok:
                # check negative values
                x = bbox[0] + offset.x()
                y = bbox[1] + offset.y()
                if vut.IsPointOnScreen(x, y, self.surface):
                    self.painter.setPen(self.blue_Pen)
                    self.painter.drawRect(x, y, bbox[2], bbox[3])
                    
                    # Get Track object center
                    xc = x + (bbox[2] / 2)
                    yc = y + (bbox[3] / 2)
                    p = QPoint(xc, yc)
                    Longitude, Latitude, _ = vut.GetPointCommonCoords(
                        p, self.surface)
                    # Draw Rubber Band on canvas
                    self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude))
                    
            else:
                self._isinit = False
                del self.tracker
                
        # Magnifier Glass
        if self._interaction.magnifier and not self.dragPos.isNull():
            draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter)

        # Stamp On Video
        if self._interaction.stamp:
            draw.drawStampOnVideo(self, self.painter)
            
        self.painter.end()
        return

    def resizeEvent(self, _):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        self.surface.updateVideoRect()
        self.update()
        # Magnifier Glass
        if self._interaction.magnifier and not self.dragPos.isNull():
            draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter)
        # QApplication.processEvents()
        
    def AddMoveEventValue(self, values, Longitude, Latitude, Altitude):
        """
        Remove and Add move value for fluid drawing
        """
        for idx, pt in enumerate(values):
            if pt[-1] == "mouseMoveEvent":
                del values[idx]
        values.append([Longitude, Latitude, Altitude, "mouseMoveEvent"])

        self.UpdateSurface()

    def mouseMoveEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        # Magnifier mouseMoveEvent
        # Magnifier can move on black screen for show image borders
        if self._interaction.magnifier:
            if event.buttons():
                self.dragPos = event.pos()
                self.UpdateSurface()

        # check if the point  is on picture (not in black borders)
        if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)):
            self.setCursor(QCursor(Qt.ArrowCursor))
            return
        
        # Prevent draw on video if not started or finished
        if self.parent.player.position() == 0:
            return  

        # Mouser cursor drawing
        if self._interaction.pointDrawer or self._interaction.polygonDrawer or self._interaction.lineDrawer or self._interaction.measureDistance or self._interaction.measureArea or self._interaction.censure or self._interaction.objectTracking:
            self.setCursor(QCursor(Qt.CrossCursor))
            
        # Cursor Coordinates
        if self.gt is not None:

            Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                event, self.surface)
            
            if self._MGRS :
                try:
                    mgrsCoords = mgrs.toMgrs(Latitude, Longitude)
                except Exception:
                    mgrsCoords = ""
                
                txt = "<span style='font-size:9pt; font-weight:normal;'>" + \
                    ("%s" % mgrsCoords) + "</span>"
            
            else:
                
                txt = "<span style='font-size:10pt; font-weight:bold;'>Lon : </span>"
                txt += "<span style='font-size:9pt; font-weight:normal;'>" + \
                    ("%.3f" % Longitude) + "</span>"
                txt += "<span style='font-size:10pt; font-weight:bold;'> Lat : </span>"
                txt += "<span style='font-size:9pt; font-weight:normal;'>" + \
                    ("%.3f" % Latitude) + "</span>"
    
                if hasElevationModel():
                    txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>"
                    txt += "<span style='font-size:9pt; font-weight:normal;'>" + \
                        ("%.0f" % Altitude) + "</span>"
                else:
                    txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>"
                    txt += "<span style='font-size:9pt; font-weight:normal;'>-</span>"

            self.parent.lb_cursor_coord.setText(txt)

            # Polygon drawer mouseMoveEvent
            if self._interaction.polygonDrawer:
                self.AddMoveEventValue(self.drawPolygon, Longitude, Latitude, Altitude)
                
            # Line drawer mouseMoveEvent
            if self._interaction.lineDrawer:
                self.AddMoveEventValue(self.drawLines, Longitude, Latitude, Altitude)
               
            # Measure Distance drawer mouseMoveEvent
            if self._interaction.measureDistance and self.drawMeasureDistance:
                self.AddMoveEventValue(self.drawMeasureDistance, Longitude, Latitude, Altitude)
            
            # Measure Area drawer mouseMoveEvent
            if self._interaction.measureArea and self.drawMeasureArea:
                self.AddMoveEventValue(self.drawMeasureArea, Longitude, Latitude, Altitude)  

        else:
            self.parent.lb_cursor_coord.setText("<span style='font-size:10pt; font-weight:bold;'>Lon :</span>" + 
                                                "<span style='font-size:9pt; font-weight:normal;'>-</span>" + 
                                                "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>" + 
                                                "<span style='font-size:9pt; font-weight:normal;'>-</span>" + 
                                                "<span style='font-size:10pt; font-weight:bold;'> Alt :</span>" + 
                                                "<span style='font-size:9pt; font-weight:normal;'>-</span>")

        if not event.buttons():
            return

        # Object tracking rubberband
        if not self.Tracking_Video_RubberBand.isHidden():
            self.Tracking_Video_RubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

        # Censure rubberband
        if not self.Censure_RubberBand.isHidden():
            self.Censure_RubberBand.setGeometry(
                QRect(self.origin, event.pos()).normalized())

    def timerEvent(self, _):
        """ Time Event (Magnifier method)"""
        if not self._interaction.magnifier:
            self.activateMagnifier()

    def mousePressEvent(self, event):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        if GetImageHeight() == 0:
            return
        
        # Prevent draw on video if not started or finished
        if self.parent.player.position() == 0:
            return  

        if event.button() == Qt.LeftButton:
            
            # Magnifier Glass
            if self._interaction.magnifier:
                self.dragPos = event.pos()
                self.tapTimer.stop()
                self.tapTimer.start(10, self)

            if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)):
                return

            # point drawer
            if self.gt is not None and self._interaction.pointDrawer:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)

                pointIndex = len(self.drawPtPos) + 1
                AddDrawPointOnMap(pointIndex, Longitude,
                                  Latitude, Altitude)

                self.drawPtPos.append([Longitude, Latitude, Altitude])

            # polygon drawer
            if self.gt is not None and self._interaction.polygonDrawer:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)
                self.poly_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude))
                self.poly_coordinates.extend(QgsPointXY(Longitude, Latitude))
                self.drawPolygon.append([Longitude, Latitude, Altitude])

            # line drawer
            if self.gt is not None and self._interaction.lineDrawer:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)

                self.drawLines.append([Longitude, Latitude, Altitude])

                AddDrawLineOnMap(self.drawLines)

            self.origin = event.pos()
            # Object Tracking Interaction
            if self._interaction.objectTracking:
                self.Tracking_Video_RubberBand.setGeometry(
                    QRect(self.origin, QSize()))
                self.Tracking_Video_RubberBand.show()

            # Censure Interaction
            if self._interaction.censure:
                self.Censure_RubberBand.setGeometry(
                    QRect(self.origin, QSize()))
                self.Censure_RubberBand.show()

            # Measure Distance drawer
            if self.gt is not None and self._interaction.measureDistance:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)
                self.drawMeasureDistance.append([Longitude, Latitude, Altitude])

            # Measure Distance drawer
            if self.gt is not None and self._interaction.measureArea:
                Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                    event, self.surface)
                self.drawMeasureArea.append([Longitude, Latitude, Altitude])
                
            # if not called, the paint event is not triggered.
            self.UpdateSurface()

    def activateMagnifier(self):
        """ Activate Magnifier Glass """
        self.tapTimer.stop()
        self.UpdateSurface()

    def SetMagnifier(self, value):
        """ Set Magnifier Glass """
        self._interaction.magnifier = value
        # We avoid that the second time we activate the tool, save the previous position.
        # Always keep the same behavior of the tool    
        if not value:
            self.dragPos = QPoint()
            self.tapTimer.stop()
            
    def SetStamp(self, value):
        """ Set Stamp """
        self._interaction.stamp = value

    def SetPointDrawer(self, value):
        """ Set Point Drawer """
        self._interaction.pointDrawer = value

    def SetLineDrawer(self, value):
        """ Set Line Drawer """
        self._interaction.lineDrawer = value

    def SetPolygonDrawer(self, value):
        """ Set Polygon Drawer """
        self._interaction.polygonDrawer = value

    def mouseReleaseEvent(self, _):
        """
        :type event: QMouseEvent
        :param event:
        :return:
        """
        # Prevent draw on video if not started or finished
        if self.parent.player.position() == 0:
            return  

        # Censure Draw Interaction
        if self._interaction.censure:
            geom = self.Censure_RubberBand.geometry()
            self.Censure_RubberBand.hide()
            self.drawCesure.append([geom])

        # Object Tracking Interaction
        if self._interaction.objectTracking:
            geom = self.Tracking_Video_RubberBand.geometry()
            offset = self.surface.videoRect()
            bbox = (geom.x() - offset.x(), geom.y() - offset.y(), geom.width(), geom.height())
            img = self.currentFrame()
            frame = convertQImageToMat(img)
            # Remo rubberband on canvas and video
            self.Tracking_Video_RubberBand.hide()
            self.Track_Canvas_RubberBand.reset()
            
            self.tracker = TrackerMOSSE_create()
            result = resize(frame, (offset.width(), offset.height()))

            try:
                ok = self.tracker.init(result, bbox)
            except Exception:
                return
            if ok:
                self._isinit = True
                # Get Traker center
                xc = bbox[0] + (geom.width() / 2)
                yc = bbox[1] + (geom.height() / 2)
                p = QPoint(xc, yc)
                Longitude, Latitude, _ = vut.GetPointCommonCoords(
                    p, self.surface)
                # Draw Rubber Band on canvas
                self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude))
            else:
                self._isinit = False

    def leaveEvent(self, _):
        self.parent.lb_cursor_coord.setText("")
        self.setCursor(QCursor(Qt.ArrowCursor))
Beispiel #32
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()
Beispiel #33
0
class Qgis2threejsDialog(QDialog):

  def __init__(self, iface, pluginManager, exportSettings=None, lastTreeItemData=None):
    QDialog.__init__(self, iface.mainWindow())
    self.iface = iface
    self.pluginManager = pluginManager
    self._settings = exportSettings or {}
    self.lastTreeItemData = lastTreeItemData
    self.localBrowsingMode = True

    self.rb_quads = self.rb_point = None

    self.templateType = None
    self.currentItem = None
    self.currentPage = None

    # Set up the user interface from Designer.
    self.ui = ui = Ui_Qgis2threejsDialog()
    ui.setupUi(self)

    self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint)

    # output html filename
    ui.lineEdit_OutputFilename.setText(self._settings.get("OutputFilename", ""))
    ui.lineEdit_OutputFilename.setPlaceholderText("[Temporary file]")

    # settings button
    icon = QIcon(os.path.join(tools.pluginDir(), "icons", "settings.png"))
    ui.toolButton_Settings.setIcon(icon)

    # popup menu displayed when settings button is pressed
    items = [["Load Settings...", self.loadSettings],
             ["Save Settings As...", self.saveSettings],
             [None, None],
             ["Clear Settings", self.clearSettings],
             [None, None],
             ["Plugin Settings...", self.pluginSettings]]

    self.menu = QMenu()
    self.menu_actions = []
    for text, slot in items:
      if text:
        action = QAction(text, iface.mainWindow())
        action.triggered.connect(slot)
        self.menu.addAction(action)
        self.menu_actions.append(action)
      else:
        self.menu.addSeparator()

    ui.toolButton_Settings.setMenu(self.menu)
    ui.toolButton_Settings.setPopupMode(QToolButton.InstantPopup)

    # progress bar and message label
    ui.progressBar.setVisible(False)
    ui.label_MessageIcon.setVisible(False)

    # buttons
    ui.pushButton_Run.clicked.connect(self.run)
    ui.pushButton_Close.clicked.connect(self.reject)
    ui.pushButton_Help.clicked.connect(self.help)

    # set up map tool
    self.previousMapTool = None
    self.mapTool = RectangleMapTool(iface.mapCanvas())
    #self.mapTool = PointMapTool(iface.mapCanvas())

    # set up the template combo box
    self.initTemplateList()
    self.ui.comboBox_Template.currentIndexChanged.connect(self.currentTemplateChanged)

    # set up the properties pages
    self.pages = {}
    self.pages[ppages.PAGE_WORLD] = ppages.WorldPropertyPage(self)
    self.pages[ppages.PAGE_CONTROLS] = ppages.ControlsPropertyPage(self)
    self.pages[ppages.PAGE_DEM] = ppages.DEMPropertyPage(self)
    self.pages[ppages.PAGE_VECTOR] = ppages.VectorPropertyPage(self)
    container = ui.propertyPagesContainer
    for page in self.pages.values():
      page.hide()
      container.addWidget(page)

    # build object tree
    self.topItemPages = {ObjectTreeItem.ITEM_WORLD: ppages.PAGE_WORLD, ObjectTreeItem.ITEM_CONTROLS: ppages.PAGE_CONTROLS, ObjectTreeItem.ITEM_DEM: ppages.PAGE_DEM}
    self.initObjectTree()
    self.ui.treeWidget.currentItemChanged.connect(self.currentObjectChanged)
    self.ui.treeWidget.itemChanged.connect(self.objectItemChanged)
    self.currentTemplateChanged()   # update item visibility

    ui.toolButton_Browse.clicked.connect(self.browseClicked)

    #iface.mapCanvas().mapToolSet.connect(self.mapToolSet)    # to show button to enable own map tool

  def settings(self, clean=False):
    # save settings of current panel
    item = self.ui.treeWidget.currentItem()
    if item and self.currentPage:
      self.saveProperties(item, self.currentPage)

    # plugin version
    self._settings["PluginVersion"] = plugin_version

    # template and output html file path
    self._settings["Template"] = self.ui.comboBox_Template.currentText()
    self._settings["OutputFilename"] = self.ui.lineEdit_OutputFilename.text()

    if not clean:
      return self._settings

    # clean up settings - remove layers that don't exist in the layer registry
    registry = QgsProject.instance()
    for itemId in [ObjectTreeItem.ITEM_OPTDEM, ObjectTreeItem.ITEM_POINT, ObjectTreeItem.ITEM_LINE, ObjectTreeItem.ITEM_POLYGON]:
      parent = self._settings.get(itemId, {})
      for layerId in list(parent.keys()):
        if registry.mapLayer(layerId) is None:
          del parent[layerId]

    return self._settings

  def setSettings(self, settings):
    self._settings = settings

    # template and output html file path
    templateName = settings.get("Template")
    if templateName:
      cbox = self.ui.comboBox_Template
      index = cbox.findText(templateName)
      if index != -1:
        cbox.setCurrentIndex(index)

    filename = settings.get("OutputFilename")
    if filename:
      self.ui.lineEdit_OutputFilename.setText(filename)

    # update object tree
    self.ui.treeWidget.blockSignals(True)
    self.initObjectTree()
    self.ui.treeWidget.blockSignals(False)

    # update tree item visibility
    self.templateType = None
    self.currentTemplateChanged()

  def loadSettings(self):
    # file open dialog
    directory = QgsProject.instance().homePath()
    if not directory:
      directory = os.path.split(self.ui.lineEdit_OutputFilename.text())[0]
    if not directory:
      directory = QDir.homePath()
    filterString = "Settings files (*.qto3settings);;All files (*.*)"
    filename, _ = QFileDialog.getOpenFileName(self, "Load Export Settings", directory, filterString)
    if not filename:
      return

    # load settings from file (.qto3settings)
    import json
    with open(filename) as f:
      settings = json.load(f)

    self.setSettings(settings)

  def saveSettings(self, filename=None):
    if not filename:
      # file save dialog
      directory = QgsProject.instance().homePath()
      if not directory:
        directory = os.path.split(self.ui.lineEdit_OutputFilename.text())[0]
      if not directory:
        directory = QDir.homePath()
      filename, _ = QFileDialog.getSaveFileName(self, "Save Export Settings", directory, "Settings files (*.qto3settings)")
      if not filename:
        return

      # append .qto3settings extension if filename doesn't have
      if os.path.splitext(filename)[1].lower() != ".qto3settings":
        filename += ".qto3settings"

    # save settings to file (.qto3settings)
    import json
    with open(filename, "w", encoding="UTF-8") as f:
      json.dump(self.settings(True), f, ensure_ascii=False, indent=2, sort_keys=True)

    logMessage("Settings saved: {0}".format(filename))

  def clearSettings(self):
    if QMessageBox.question(self, "Qgis2threejs", "Are you sure to clear all export settings?", QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Ok:
      self.setSettings({})

  def pluginSettings(self):
    from .settingsdialog import SettingsDialog
    dialog = SettingsDialog(self)
    if dialog.exec_():
      self.pluginManager.reloadPlugins()
      self.pages[ppages.PAGE_DEM].initLayerComboBox()

  def showMessageBar(self, text, level=QgsMessageBar.INFO):
    # from src/gui/qgsmessagebaritem.cpp
    if level == QgsMessageBar.CRITICAL:
      msgIcon = "/mIconCritical.png"
      bgColor = "#d65253"
    elif level == QgsMessageBar.WARNING:
      msgIcon = "/mIconWarn.png"
      bgColor = "#ffc800"
    else:
      msgIcon = "/mIconInfo.png"
      bgColor = "#e7f5fe"
    stylesheet = "QLabel {{ background-color:{0}; }}".format(bgColor)

    label = self.ui.label_MessageIcon
    label.setPixmap(QgsApplication.getThemeIcon(msgIcon).pixmap(24))
    label.setStyleSheet(stylesheet)
    label.setVisible(True)

    label = self.ui.label_Status
    label.setText(text)
    label.setStyleSheet(stylesheet)

  def clearMessageBar(self):
    self.ui.label_MessageIcon.setVisible(False)
    self.ui.label_Status.setText("")
    self.ui.label_Status.setStyleSheet("QLabel { background-color: rgba(0, 0, 0, 0); }")

  def initTemplateList(self):
    cbox = self.ui.comboBox_Template
    cbox.clear()
    templateDir = QDir(tools.templateDir())
    for i, entry in enumerate(templateDir.entryList(["*.html", "*.htm"])):
      cbox.addItem(entry)

      config = tools.getTemplateConfig(entry)
      # get template type
      templateType = config.get("type", "plain")
      cbox.setItemData(i, templateType, Qt.UserRole)

      # set tool tip text
      desc = config.get("description", "")
      if desc:
        cbox.setItemData(i, desc, Qt.ToolTipRole)

    # select the template of the settings
    templatePath = self._settings.get("Template")

    # if no template setting, select the last used template
    if not templatePath:
      templatePath = QSettings().value("/Qgis2threejs/lastTemplate", def_vals.template, type=str)

    if templatePath:
      index = cbox.findText(templatePath)
      if index != -1:
        cbox.setCurrentIndex(index)
      return index
    return -1

  def initObjectTree(self):
    tree = self.ui.treeWidget
    tree.clear()

    # add vector and raster layers into tree widget
    topItems = {}
    for id, name in zip(ObjectTreeItem.topItemIds, ObjectTreeItem.topItemNames):
      item = QTreeWidgetItem(tree, [name])
      item.setData(0, Qt.UserRole, id)
      topItems[id] = item

    optDEMChecked = False
    for layer in getLayersInProject():
      parentId = ObjectTreeItem.parentIdByLayer(layer)
      if parentId is None:
        continue

      item = QTreeWidgetItem(topItems[parentId], [layer.name()])
      isVisible = self._settings.get(parentId, {}).get(layer.id(), {}).get("visible", False)
      check_state = Qt.Checked if isVisible else Qt.Unchecked
      item.setData(0, Qt.CheckStateRole, check_state)
      item.setData(0, Qt.UserRole, layer.id())
      if parentId == ObjectTreeItem.ITEM_OPTDEM and isVisible:
        optDEMChecked = True

    for id, item in topItems.items():
      if id != ObjectTreeItem.ITEM_OPTDEM or optDEMChecked:
        tree.expandItem(item)

    # disable additional DEM item which is selected as main DEM
    layerId = self._settings.get(ObjectTreeItem.ITEM_DEM, {}).get("comboBox_DEMLayer")
    if layerId:
      self.primaryDEMChanged(layerId)

  def saveProperties(self, item, page):
    properties = page.properties()
    parent = item.parent()
    if parent is None:
      # top level item
      self._settings[item.data(0, Qt.UserRole)] = properties
    else:
      # layer item
      parentId = parent.data(0, Qt.UserRole)
      if parentId not in self._settings:
        self._settings[parentId] = {}
      self._settings[parentId][item.data(0, Qt.UserRole)] = properties

  def setCurrentTreeItemByData(self, data):
    it = QTreeWidgetItemIterator(self.ui.treeWidget)
    while it.value():
      if it.value().data(0, Qt.UserRole) == data:
        self.ui.treeWidget.setCurrentItem(it.value())
        return True
      it += 1
    return False

  def currentTemplateChanged(self, index=None):
    cbox = self.ui.comboBox_Template
    templateType = cbox.itemData(cbox.currentIndex(), Qt.UserRole)
    if templateType == self.templateType:
      return

    # hide items unsupported by template
    tree = self.ui.treeWidget
    for i, id in enumerate(ObjectTreeItem.topItemIds):
      hidden = (templateType == "sphere" and id != ObjectTreeItem.ITEM_CONTROLS)
      tree.topLevelItem(i).setHidden(hidden)

    # set current tree item
    if templateType == "sphere":
      tree.setCurrentItem(tree.topLevelItem(ObjectTreeItem.topItemIndex(ObjectTreeItem.ITEM_CONTROLS)))
    elif self.lastTreeItemData is None or not self.setCurrentTreeItemByData(self.lastTreeItemData):   # restore selection
      tree.setCurrentItem(tree.topLevelItem(ObjectTreeItem.topItemIndex(ObjectTreeItem.ITEM_DEM)))   # default selection for plain is DEM

    # display messages
    self.clearMessageBar()
    if templateType != "sphere":
      # show message if crs unit is degrees
      mapSettings = self.iface.mapCanvas().mapSettings()
      if mapSettings.destinationCrs().mapUnits() in [QgsUnitTypes.DistanceDegrees]:
        self.showMessageBar("The unit of current CRS is degrees, so terrain may not appear well.", QgsMessageBar.WARNING)

    self.templateType = templateType

  def currentObjectChanged(self, currentItem, previousItem):
    # save properties of previous item
    if previousItem and self.currentPage:
      self.saveProperties(previousItem, self.currentPage)

    self.currentItem = currentItem
    self.currentPage = None

    # hide text browser and all pages
    self.ui.textBrowser.hide()
    for page in self.pages.values():
      page.hide()

    parent = currentItem.parent()
    if parent is None:
      topItemIndex = currentItem.data(0, Qt.UserRole)
      pageType = self.topItemPages.get(topItemIndex, ppages.PAGE_NONE)
      page = self.pages.get(pageType, None)
      if page is None:
        self.showDescription(topItemIndex)
        return

      page.setup(self._settings.get(topItemIndex))
      page.show()

    else:
      parentId = parent.data(0, Qt.UserRole)
      layerId = currentItem.data(0, Qt.UserRole)
      layer = QgsProject.instance().mapLayer(str(layerId))
      if layer is None:
        return

      layerType = layer.type()
      if layerType == QgsMapLayer.RasterLayer:
        page = self.pages[ppages.PAGE_DEM]
        page.setup(self._settings.get(parentId, {}).get(layerId, None), layer, False)
      elif layerType == QgsMapLayer.VectorLayer:
        page = self.pages[ppages.PAGE_VECTOR]
        page.setup(self._settings.get(parentId, {}).get(layerId, None), layer)
      else:
        return

      page.show()

    self.currentPage = page

  def objectItemChanged(self, item, column):
    parent = item.parent()
    if parent is None:
      return

    # checkbox of optional layer checked/unchecked
    if item == self.currentItem:
      if self.currentPage:
        # update enablement of property widgets
        self.currentPage.itemChanged(item)
    else:
      # select changed item
      self.ui.treeWidget.setCurrentItem(item)

      # set visible property
      #visible = item.data(0, Qt.CheckStateRole) == Qt.Checked
      #parentId = parent.data(0, Qt.UserRole)
      #layerId = item.data(0, Qt.UserRole)
      #self._settings.get(parentId, {}).get(layerId, {})["visible"] = visible

  def primaryDEMChanged(self, layerId):
    tree = self.ui.treeWidget
    parent = tree.topLevelItem(ObjectTreeItem.topItemIndex(ObjectTreeItem.ITEM_OPTDEM))
    tree.blockSignals(True)
    for i in range(parent.childCount()):
      item = parent.child(i)
      isPrimary = item.data(0, Qt.UserRole) == layerId
      item.setDisabled(isPrimary)
    tree.blockSignals(False)

  def showDescription(self, topItemIndex):
    fragment = {ObjectTreeItem.ITEM_OPTDEM: "additional-dem",
                ObjectTreeItem.ITEM_POINT: "point",
                ObjectTreeItem.ITEM_LINE: "line",
                ObjectTreeItem.ITEM_POLYGON: "polygon"}.get(topItemIndex)

    url = "http://qgis2threejs.readthedocs.org/en/docs-release/ExportSettings.html"
    if fragment:
      url += "#" + fragment

    html = '<a href="{0}">Online Help</a> about this item'.format(url)
    self.ui.textBrowser.setHtml(html)
    self.ui.textBrowser.show()

  def numericFields(self, layer):
    # get attributes of a sample feature and create numeric field name list
    numeric_fields = []
    f = QgsFeature()
    layer.getFeatures().nextFeature(f)
    for field in f.fields():
      isNumeric = False
      try:
        float(f.attribute(field.name()))
        isNumeric = True
      except ValueError:
        pass
      if isNumeric:
        numeric_fields.append(field.name())
    return numeric_fields

  def mapTo3d(self):
    world = self._settings.get(ObjectTreeItem.ITEM_WORLD, {})
    bs = float(world.get("lineEdit_BaseSize", def_vals.baseSize))
    ve = float(world.get("lineEdit_zFactor", def_vals.zExaggeration))
    vs = float(world.get("lineEdit_zShift", def_vals.zShift))

    return MapTo3D(self.iface.mapCanvas().mapSettings(), bs, ve, vs)

  def progress(self, percentage=None, statusMsg=None):
    ui = self.ui
    if percentage is not None:
      ui.progressBar.setValue(percentage)
      if percentage == 100:
        ui.progressBar.setVisible(False)
        ui.label_Status.setText("")
      else:
        ui.progressBar.setVisible(True)

    if statusMsg is not None:
      ui.label_Status.setText(statusMsg)
      ui.label_Status.repaint()
    QgsApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

  def run(self):
    self.endPointSelection()

    ui = self.ui
    filename = ui.lineEdit_OutputFilename.text()   # ""=Temporary file
    if filename and os.path.exists(filename):
      if QMessageBox.question(self, "Qgis2threejs", "Output file already exists. Overwrite it?", QMessageBox.Ok | QMessageBox.Cancel) != QMessageBox.Ok:
        return

    # export to web (three.js)
    export_settings = ExportSettings(self.pluginManager, self.localBrowsingMode)
    export_settings.loadSettings(self.settings())
    export_settings.setMapCanvas(self.iface.mapCanvas())

    err_msg = export_settings.checkValidity()
    if err_msg is not None:
      QMessageBox.warning(self, "Qgis2threejs", err_msg or "Invalid settings")
      return

    ui.pushButton_Run.setEnabled(False)
    ui.toolButton_Settings.setVisible(False)
    self.clearMessageBar()
    self.progress(0)

    if export_settings.exportMode == ExportSettings.PLAIN_MULTI_RES:
      # update quads and point on map canvas
      self.createRubberBands(export_settings.baseExtent, export_settings.quadtree())

    # export
    ret = exportToThreeJS(export_settings, self.progress)

    self.progress(100)
    ui.pushButton_Run.setEnabled(True)

    if not ret:
      ui.toolButton_Settings.setVisible(True)
      return

    self.clearRubberBands()

    # store last selections
    settings = QSettings()
    settings.setValue("/Qgis2threejs/lastTemplate", export_settings.templatePath)
    settings.setValue("/Qgis2threejs/lastControls", export_settings.controls)

    # open web browser
    if not tools.openHTMLFile(export_settings.htmlfilename):
      ui.toolButton_Settings.setVisible(True)
      return

    # close dialog
    QDialog.accept(self)

  def reject(self):
    # save properties of current object
    item = self.ui.treeWidget.currentItem()
    if item and self.currentPage:
      self.saveProperties(item, self.currentPage)

    self.endPointSelection()
    self.clearRubberBands()
    QDialog.reject(self)

  def help(self):
    url = "http://qgis2threejs.readthedocs.org/"

    import webbrowser
    webbrowser.open(url, new=2)    # new=2: new tab if possible

  def startPointSelection(self):
    canvas = self.iface.mapCanvas()
    if self.previousMapTool != self.mapTool:
      self.previousMapTool = canvas.mapTool()
    canvas.setMapTool(self.mapTool)
    self.pages[ppages.PAGE_DEM].toolButton_PointTool.setVisible(False)

  def endPointSelection(self):
    self.mapTool.reset()
    if self.previousMapTool is not None:
      self.iface.mapCanvas().setMapTool(self.previousMapTool)

  def mapToolSet(self, mapTool):
    return
    #TODO: unstable
    if mapTool != self.mapTool and self.currentPage is not None:
      if self.currentPage.pageType == ppages.PAGE_DEM and self.currentPage.isPrimary:
        self.currentPage.toolButton_PointTool.setVisible(True)

  def createRubberBands(self, baseExtent, quadtree):
    self.clearRubberBands()
    # create quads with rubber band
    self.rb_quads = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.LineGeometry)
    self.rb_quads.setColor(Qt.blue)
    self.rb_quads.setWidth(1)

    quads = quadtree.quads()
    for quad in quads:
      geom = baseExtent.subrectangle(quad.rect).geometry()
      self.rb_quads.addGeometry(geom, None)
    self.log("Quad count: %d" % len(quads))

    if not quadtree.focusRect:
      return

    # create a point with rubber band
    if quadtree.focusRect.width() == 0 or quadtree.focusRect.height() == 0:
      npt = quadtree.focusRect.center()
      self.rb_point = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.PointGeometry)
      self.rb_point.setColor(Qt.red)
      self.rb_point.addPoint(baseExtent.point(npt))

  def clearRubberBands(self):
    # clear quads and point
    if self.rb_quads:
      self.iface.mapCanvas().scene().removeItem(self.rb_quads)
      self.rb_quads = None
    if self.rb_point:
      self.iface.mapCanvas().scene().removeItem(self.rb_point)
      self.rb_point = None

  def browseClicked(self):
    directory = os.path.split(self.ui.lineEdit_OutputFilename.text())[0]
    if not directory:
      directory = QDir.homePath()
    filename, _ = QFileDialog.getSaveFileName(self, self.tr("Output filename"), directory, "HTML file (*.html *.htm)", options=QFileDialog.DontConfirmOverwrite)
    if not filename:
      return

    # append .html extension if filename doesn't have either .html or .htm
    if filename[-5:].lower() != ".html" and filename[-4:].lower() != ".htm":
      filename += ".html"

    self.ui.lineEdit_OutputFilename.setText(filename)

  def log(self, msg):
    if debug_mode:
      qDebug(msg)
Beispiel #34
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()
        self.layer.layerDeleted.disconnect(self.close)
        self.layer.selectionChanged.disconnect(self.selectionChanged)
        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)
        self.subset = self.layer.selectedFeaturesIds()
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("itemBrowserSelection",
                                         repr(self.subset))
        for fid in self.subset:
            self.listCombo.addItem("%u" % fid)

    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("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, 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):
        self.iface.openFeatureForm(self.layer, self.getCurrentItem())
class SimpleIntersectionMapTool(QgsMapTool):
    def __init__(self, iface):
        self.iface = iface
        self.mapCanvas = iface.mapCanvas()
        QgsMapTool.__init__(self, self.mapCanvas)
        self.settings = MySettings()
        self.rubber = QgsRubberBand(self.mapCanvas, QGis.Point)

    def deactivate(self):
        self.rubber.reset()
        QgsMapTool.deactivate(self)

    def activate(self):
        QgsMapTool.activate(self)
        self.rubber.setWidth(self.settings.value("rubberWidth"))
        self.rubber.setColor(self.settings.value("rubberColor"))
        self.checkLayer()

    def canvasMoveEvent(self, mouseEvent):
        # put the observations within tolerance in the rubber band
        self.rubber.reset(QGis.Point)
        match = self.snap_to_intersection(mouseEvent.pos())
        if match.type() == QgsPointLocator.Vertex and match.layer() is None:
            self.rubber.addPoint(match.point())

    def canvasPressEvent(self, mouseEvent):
        self.rubber.reset()
        match = self.snap_to_intersection(mouseEvent.pos())
        if match.type() != QgsPointLocator.Vertex or match.layer() is not None:
            return

        layer = self.checkLayer()
        if layer is None:
            return
        f = QgsFeature()
        initFields = layer.dataProvider().fields()
        f.setFields(initFields)
        f.initAttributes(initFields.size())
        f.setGeometry(QgsGeometry().fromPoint(match.point()))
        layer.editBuffer().addFeature(f)
        layer.triggerRepaint()

    def snap_to_intersection(self, pos):
        """ Temporarily override snapping config and snap to vertices and edges
         of any editable vector layer, to allow selection of node for editing
         (if snapped to edge, it would offer creation of a new vertex there).
        """
        map_point = self.toMapCoordinates(pos)
        tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings())
        snap_type = QgsPointLocator.Type(QgsPointLocator.Edge)

        snap_layers = []
        for layer in self.canvas().layers():
            if not isinstance(layer, QgsVectorLayer):
                continue
            snap_layers.append(
                QgsSnappingUtils.LayerConfig(layer, snap_type, tol,
                                             QgsTolerance.ProjectUnits))

        snap_util = self.canvas().snappingUtils()
        old_layers = snap_util.layers()
        old_mode = snap_util.snapToMapMode()
        old_inter = snap_util.snapOnIntersections()
        snap_util.setLayers(snap_layers)
        snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
        snap_util.setSnapOnIntersections(True)
        m = snap_util.snapToMap(map_point)
        snap_util.setLayers(old_layers)
        snap_util.setSnapToMapMode(old_mode)
        snap_util.setSnapOnIntersections(old_inter)
        return m

    def checkLayer(self):
        # check output layer is defined
        layerid = self.settings.value("simpleIntersectionLayer")
        layer = QgsMapLayerRegistry.instance().mapLayer(layerid)
        if not self.settings.value(
                "simpleIntersectionWritePoint") or layer is None:
            self.iface.messageBar().pushMessage(
                "Intersect It",
                "You must define an output layer for simple intersections",
                QgsMessageBar.WARNING, 3)
            self.mapCanvas.unsetMapTool(self)
            return None
        if not layer.isEditable():
            self.iface.messageBar().pushMessage(
                "Intersect It",
                "The output layer <b>%s must be editable</b>" % layer.name(),
                QgsMessageBar.WARNING, 3)
            self.mapCanvas.unsetMapTool(self)
            return None
        return layer
class EditTool(QgsMapTool):
    wp_clicked = pyqtSignal(int)

    def __init__(self, mission_track, canvas, msglog):
        QgsMapTool.__init__(self, canvas)
        self.setCursor(Qt.CrossCursor)
        self.mission_track = mission_track
        self.msglog = msglog
        self.dragging = False
        self.feature = None
        self.vertex = None
        self.startcoord = None
        self.layer = self.mission_track.get_mission_layer()
        logger.info(self.mission_track.get_mission_name())

        self.rubber_band = QgsRubberBand(self.canvas(), QgsWkbTypes.LineGeometry)
        self.rubber_band.setWidth(2)
        self.rubber_band.setColor(QColor("green"))

        self.point_cursor_band = QgsRubberBand(self.canvas(), QgsWkbTypes.LineGeometry)
        self.point_cursor_band.setWidth(1)
        self.point_cursor_band.setLineStyle(Qt.DashLine)
        self.point_cursor_band.setColor(QColor(255, 0, 0, 100))

        self.mid_point_band = QgsRubberBand(self.canvas(), QgsWkbTypes.PointGeometry)
        self.mid_point_band.setColor(QColor(255, 0, 0, 100))
        self.mid_point_band.setIconSize(18)

        self.rubber_band_points = QgsRubberBand(self.canvas(), QgsWkbTypes.PointGeometry)
        self.rubber_band_points.setColor(QColor("green"))
        self.rubber_band_points.setIcon(QgsRubberBand.ICON_CIRCLE)
        self.rubber_band_points.setIconSize(10)

        self.mission_track.mission_changed.connect(self.update_rubber_bands)

        self.vertex_marker = QgsVertexMarker(self.canvas())
        self.start_end_marker = StartEndMarker(canvas, self.mission_track.find_waypoints_in_mission(), QColor("green"))

        self.layer.startEditing()

        self.wp = []
        self.mCtrl = False
        # handler for mission feature
        self.update_rubber_bands(0)

        crs = canvas.mapSettings().destinationCrs()
        self.distance_calc = QgsDistanceArea()
        self.distance_calc.setSourceCrs(crs, QgsProject.instance().transformContext())
        self.distance_calc.setEllipsoid(crs.ellipsoidAcronym())

    def update_rubber_bands(self, current_wp):
        self.rubber_band.reset(QgsWkbTypes.LineGeometry)
        self.rubber_band_points.reset(QgsWkbTypes.PointGeometry)
        self.wp = self.mission_track.find_waypoints_in_mission()

        self.start_end_marker.update_markers(self.wp)

        if len(self.wp) > 0:

            for v in self.wp:
                pc = self.toLayerCoordinates(self.layer, QgsPointXY(v))
                self.rubber_band.addPoint(pc)
                self.rubber_band_points.addPoint(pc)
            logger.debug("MISSION UPDATE: now we have {} waypoints".format(len(self.wp)))

            self.vertex_marker.setCenter(QgsPointXY(self.wp[current_wp].x(), self.wp[current_wp].y()))
            self.vertex_marker.setColor(QColor(25, 255, 0))
            self.vertex_marker.setIconSize(7)
            self.vertex_marker.setIconType(QgsVertexMarker.ICON_X)  # ICON_BOX, ICON_CROSS, ICON_X
            self.vertex_marker.setPenWidth(2)
            self.vertex_marker.show()

            self.set_geometry()
        else:

            self.vertex_marker.hide()

    def set_control_state(self, state):
        self.mCtrl = state

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Control and not self.dragging:
            self.mCtrl = True
            pos = self.canvas().mouseLastXY()
            if not self.find_on_feature(pos, self.calc_tolerance()):
                self.show_dist_and_bearing_to_point()

    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Control:
            self.mCtrl = False
            pos = self.canvas().mouseLastXY()
            if not self.find_on_feature(pos, self.calc_tolerance()) and not self.dragging:
                self.show_dist_and_bearing_to_point()
        return

    def canvasDoubleClickEvent(self, event):
        self.canvasPressEvent(event)

    def canvasPressEvent(self, event):
        if self.dragging:
            self.canvasReleaseEvent(event)

        map_pt, layer_pt = self.transform_coordinates(event.pos())
        tolerance = self.calc_tolerance()

        if not self.find_on_feature(event.pos(), tolerance):
            if event.button() == Qt.LeftButton:
                # we have clicked outside the track
                logger.debug("We have clicked outside the track")
                self.point_cursor_band.reset(QgsWkbTypes.LineGeometry)
                if not self.mCtrl:
                    # add step to mission at the end
                    self.mission_track.add_step(len(self.wp), layer_pt)
                    self.show_waypoint_distances(len(self.wp)-1)
                else:
                    self.mission_track.add_step(0, layer_pt)
                    self.show_waypoint_distances(0)
        else:

            logger.debug("We have clicked on the track")
            vertex = self.find_vertex_at(event.pos(), tolerance)

            if event.button() == Qt.LeftButton:
                if vertex is None:
                    logger.debug("We have clicked between vertexs")
                    # we have clicked in between vertex, add intermediate point
                    initial_vertex = self.find_segment_at(event.pos())
                    # self.mission_track.add_step(initial_vertex + 1, layerPt)

                    intersection = intersect_point_to_line(self.toLayerCoordinates(self.layer, event.pos()),
                                                           QgsPointXY(self.wp[initial_vertex]),
                                                           QgsPointXY(self.wp[initial_vertex + 1]))
                    logger.debug("intersection point: {} {}".format(str(intersection.x()), str(intersection.y())))
                    logger.debug("{} {} {} {}".format(self.wp[initial_vertex].x(), self.wp[initial_vertex].y(),
                                 self.wp[initial_vertex + 1].x(), self.wp[initial_vertex + 1].y()))
                    # layerPtIntersection = self.toLayerCoordinates(self.layer,intersection)
                    self.mission_track.add_step(initial_vertex + 1, intersection)
                    self.mid_point_band.reset(QgsWkbTypes.PointGeometry)
                    self.show_waypoint_distances(initial_vertex+1)
                else:
                    logger.debug("We have clicked on vertex {}".format(vertex))
                    # we have clicked on a vertex

                    # Left click -> move vertex.
                    self.dragging = True
                    self.vertex = vertex
                    self.startcoord = event.pos()
                    # self.moveVertexTo(layerPt)

            elif event.button() == Qt.RightButton:
                if vertex is not None and not self.dragging:
                    # Right click -> delete vertex.
                    self.delete_vertex(vertex)

                    if self.find_on_feature(event.pos(), tolerance):  # If cursor still over track
                        vertex = self.find_vertex_at(event.pos(), tolerance)
                        if vertex is None:  # Cursor is between vertexes
                            self.show_mid_point(event.pos())
                        else:  # Cursor is over a vertex
                            self.show_waypoint_distances(vertex)
                    else:
                        self.show_dist_and_bearing_to_point()

    def transform_coordinates(self, canvas_pt):
        return (self.toMapCoordinates(canvas_pt),
                self.toLayerCoordinates(self.layer, canvas_pt))

    def canvasMoveEvent(self, event):
        if self.dragging:
            self.move_vertex_to(self.toLayerCoordinates(self.layer, event.pos()))
            self.mission_track.hide_start_end_markers()
            self.vertex_marker.hide()
            self.start_end_marker.hide_markers()
            self.show_waypoint_distances(self.vertex)

        else:
            tolerance = self.calc_tolerance()
            if self.find_on_feature(event.pos(), tolerance):  # if mouse is over the track
                self.point_cursor_band.reset(QgsWkbTypes.LineGeometry)
                self.mid_point_band.reset(QgsWkbTypes.PointGeometry)
                vertex = self.find_vertex_at(event.pos(), tolerance)

                if vertex is None:  # Cursor is between vertexes
                    self.show_mid_point(event.pos())
                else:  # Cursor is over a vertex
                    self.show_waypoint_distances(vertex)

            else:
                self.mid_point_band.reset(QgsWkbTypes.PointGeometry)
                self.show_dist_and_bearing_to_point()

    def show_dist_and_bearing_to_point(self):
        """
        Finds distance and bearing from the last point (first if pressing ctrl) to the specified point and shows them
        in the message log. Also draws a line between the points.
        """
        bearing = 0.0

        self.point_cursor_band.reset(QgsWkbTypes.LineGeometry)
        point = self.canvas().mouseLastXY()
        if len(self.wp) > 0:
            cursor_point = self.toMapCoordinates(point)
            if self.mCtrl:
                anchor_point = QgsPointXY(self.wp[0])
            else:
                anchor_point = QgsPointXY(self.wp[len(self.wp) - 1])
            self.point_cursor_band.addPoint(cursor_point)
            self.point_cursor_band.addPoint(anchor_point)
            distance = self.distance_calc.measureLine([anchor_point, cursor_point])
            if distance != 0.0:
                bearing = self.distance_calc.bearing(anchor_point, cursor_point)
            self.msglog.logMessage("")
            if self.mCtrl:
                msg = "Distance to next point: "
            else:
                msg = "Distance to previous point: "
            self.msglog.logMessage(msg + "{:.3F} m.  Bearing: {:.3F} º.".format(distance, math.degrees(bearing)),
                                   "Distance and bearing", 0)
        else:
            self.msglog.logMessage("")

    def show_mid_point(self, cursor):
        """
        Finds the projection of the cursor over the track and draws a circle in that point.
        Finds the distances between this projection point and the previous and next points in the mission
        and shows them in the message log.
        :param cursor: position to be projected over the track
        """
        prev_vertex = self.find_segment_at(cursor)
        prev_point = QgsPointXY(self.wp[prev_vertex])
        next_point = QgsPointXY(self.wp[prev_vertex + 1])
        cursor_point = self.toMapCoordinates(cursor)
        intersection = intersect_point_to_line(cursor_point, prev_point, next_point)
        self.mid_point_band.addPoint(intersection)
        distance1 = self.distance_calc.measureLine([prev_point, intersection])
        distance2 = self.distance_calc.measureLine([intersection, next_point])
        self.msglog.logMessage("")
        self.msglog.logMessage("Distance to previous point: {:.3F} m.  Distance to next point: {:.3F} m."
                               .format(distance1, distance2), "Distance between points", 0)

    def show_waypoint_distances(self, vertex):
        """
        Finds the distances to adjacent waypoints of vertex and shows them in the message log
        :param vertex: index of the waypoint from the mission
        """
        curr_point = self.rubber_band_points.getPoint(QgsWkbTypes.PointGeometry, vertex)
        if vertex == 0:
            if len(self.wp) > 1:
                next_point = QgsPointXY(self.wp[vertex+1])
                distance = self.distance_calc.measureLine([curr_point, next_point])
                bearing = self.distance_calc.bearing(next_point, curr_point)
                msg = "Distance to next point: {:.3F} m.  Bearing: {:.3F} º.".format(distance, math.degrees(bearing))
            else:
                msg = ""
            self.msglog.logMessage("")
            self.msglog.logMessage(msg+" (Waypoint {}) ".format(vertex+1), "Vertex distances", 0)
        elif vertex == len(self.wp) - 1:
            prev_point = QgsPointXY(self.wp[vertex-1])
            distance = self.distance_calc.measureLine([prev_point, curr_point])
            bearing = self.distance_calc.bearing(prev_point, curr_point)
            msg = "Distance to previous point: {:.3F} m.  Bearing: {:.3F} º.".format(distance, math.degrees(bearing))
            self.msglog.logMessage("")
            self.msglog.logMessage(msg+" (Waypoint {})".format(vertex+1), "Vertex distances", 0)
        else:
            prev_point = QgsPointXY(self.wp[vertex-1])
            next_point = QgsPointXY(self.wp[vertex+1])
            distance1 = self.distance_calc.measureLine(prev_point, curr_point)
            distance2 = self.distance_calc.measureLine(curr_point, next_point)
            msg = "Distance to previous point: {:.3F} m.  Distance to next point: {:.3F} m."\
                .format(distance1, distance2)
            self.msglog.logMessage("")
            self.msglog.logMessage(msg+" (Waypoint {})".format(vertex+1), "Vertex distances", 0)

    def hide_point_cursor_band(self):
        """
        Hides the rubber band drawn from last (or first) point to cursor
        """
        self.point_cursor_band.reset(QgsWkbTypes.LineGeometry)

    def canvasReleaseEvent(self, event):
        if self.dragging and event.button() == Qt.LeftButton:
            self.dragging = False
            self.vertex_marker.show()
            mapPt, layerPt = self.transform_coordinates(event.pos())
            # Check distance with initial point
            dist = math.sqrt(
                (self.startcoord.x() - event.pos().x()) ** 2 + (self.startcoord.y() - event.pos().y()) ** 2)
            tolerance = self.calc_tolerance()
            if dist > tolerance:
                self.move_vertex_to(layerPt)
                self.mission_track.change_position(self.vertex, layerPt)
                self.wp_clicked.emit(self.vertex)
                self.feature = None
                self.vertex = None
                self.layer.updateExtents()
            else:
                # If release point is the same, has been just a click
                self.move_vertex_to(self.toLayerCoordinates(self.layer, QgsPointXY(self.wp[self.vertex])))
                self.wp_clicked.emit(self.vertex)
                self.feature = None
                self.vertex = None

    def calc_tolerance(self):
        """
        Compute the tolerance on canvas

        :return: tolerance
        """
        # 2% of tolerance
        width_tolerance = 0.02 * self.canvas().width()
        height_tolerance =  0.02 * self.canvas().height()
        if width_tolerance < height_tolerance:
            tolerance = width_tolerance
        else:
            tolerance = height_tolerance
        return tolerance

    def move_vertex_to(self, layerPt):
        """
        Move current vertex to layerPt position.

        :param layerPt: layer point
        :type: QgsPointXY
        """
        if len(self.wp) > 1:
            self.rubber_band.movePoint(self.vertex, layerPt)
            self.rubber_band_points.movePoint(self.vertex, layerPt)
        elif len(self.wp) == 1:
            # A rubber band with PointGeometry and only 1 point acts as if it had 2 points, we need to reset it in
            # order to move the point.
            self.rubber_band_points.reset(QgsWkbTypes.PointGeometry)
            self.rubber_band_points.addPoint(layerPt)


    def delete_vertex(self, vertex):
        """
        Delete step 'vertex'.
        :param vertex: step

        """
        self.mission_track.remove_step(vertex)
        self.dragging = False
        self.vertex = None

    def find_on_feature(self, pos, tolerance):
        """
        if clicked point has some segment at a smaller distance than tolerance means that we've clicked on the track

        :param pos: The point that we've clicked
        :param tolerance: The tolerance of pos
        :return: bool
        """
        if len(self.wp) > 1:
            dist_to_segment = []
            for v in range(0, len(self.wp) - 1):
                # convert layer coordinates to canvas coordinates
                a1 = self.toCanvasCoordinates(QgsPointXY(self.wp[v]))
                b1 = self.toCanvasCoordinates(QgsPointXY(self.wp[v + 1]))

                dist_to_segment.append(
                    self.dist_to_segment(a1.x(),
                                         a1.y(),
                                         b1.x(),
                                         b1.y(),
                                         pos.x(),
                                         pos.y()))
                logger.debug("dist to segment: {}".format(dist_to_segment))
                if dist_to_segment[v] < tolerance:
                    return True

            return False
        else:
            # last waypoint
            vertex = self.find_vertex_at(pos, tolerance)
            if vertex is None:
                return False
            else:
                return True

    def find_segment_at(self, pos):
        """
        get the segment that is closer to the clicked point and return its initial vertex

        :param pos: the point that we've clicked
        :return: initial vertex of the segment
        """
        dist_to_segment = []
        for v in range(0, len(self.wp) - 1):
            a1 = self.toCanvasCoordinates(QgsPointXY(self.wp[v]))
            b1 = self.toCanvasCoordinates(QgsPointXY(self.wp[v + 1]))
            dist_to_segment.append(self.dist_to_segment(a1.x(),
                                                        a1.y(),
                                                        b1.x(),
                                                        b1.y(),
                                                        pos.x(),
                                                        pos.y()))

        vertex = dist_to_segment.index(min(dist_to_segment))
        return vertex

    def find_vertex_at(self, pos, tolerance):
        """
        get the vertex that is closer to the clicked point


        :param pos: The point that we've clicked
        :param tolerance: The tolerance of pos
        :return: vertex or None
        """
        if len(self.wp) > 0:
            dist_to_vertex = []
            logger.debug("tolerance {}".format(tolerance))
            for v in range(0, len(self.wp)):
                a1 = self.toCanvasCoordinates(QgsPointXY(self.wp[v]))
                dist_to_vertex.append(math.sqrt((pos.x() - a1.x()) ** 2 + (pos.y() - a1.y()) ** 2))
                logger.debug("dist to vertex: {}".format(dist_to_vertex))

            vertex = dist_to_vertex.index(min(dist_to_vertex))
            if min(dist_to_vertex) > tolerance:
                return None
            else:
                logger.debug("ON VERTEX")
                return vertex
        else:
            return None

    def dist_to_segment(self, ax, ay, bx, by, cx, cy):
        """
        Computes the minimum distance between a point (cx, cy) and a line segment with endpoints (ax, ay) and (bx, by).
        :param ax: endpoint 1, x-coordinate
        :param ay: endpoint 1, y-coordinate
        :param bx: endpoint 2, x-coordinate
        :param by: endpoint 2, y-coordinate
        :param cx: point, x-coordinate
        :param cy: point, x-coordinate
        :return: minimum distance between point and line segment
        """
        # calculate tolerance
        tolerance = self.calc_tolerance()
        # get distance between points c-a and c-b
        dist_to_a = math.sqrt((cx - ax) ** 2 + (cy - ay) ** 2)
        dist_to_b = math.sqrt((cx - bx) ** 2 + (cy - by) ** 2)
        # if distance to point a or distance to point b is smaller than tolerance, return -1
        if (dist_to_a < tolerance) or (dist_to_b < tolerance):
            return -1

        # if one coordinate are between a coordinates or b coordinates
        if is_between(ax, ay, bx, by, cx, cy):

            y = (by - ay)
            x = (bx - ax)

            # line defined by two points formula
            num = abs((y * cx) - (x * cy) + (bx * ay) - (by * ax))
            den = math.sqrt(y ** 2 + x ** 2)
            dl = num / den
            return dl

        else:
            return tolerance + 1

    def set_geometry(self):
        """
        Save rubber band to geometry of the layer
        """
        if self.layer.featureCount() == 0:
            # no feature yet created
            f = QgsFeature()
            if len(self.wp) == 1:
                f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(self.wp[0].x(), self.wp[0].y())))
            else:
                f.setGeometry(QgsGeometry.fromPolyline(self.wp))
            # self.layer.dataProvider().addFeatures([f])
            self.layer.addFeatures([f])
        else:
            # mission feature present, edit geometry
            feats = self.layer.getFeatures()
            for f in feats:
                if len(self.wp) == 1:
                    self.layer.changeGeometry(f.id(),
                                              QgsGeometry.fromPointXY(QgsPointXY(self.wp[0].x(), self.wp[0].y())))
                else:
                    self.layer.changeGeometry(f.id(), QgsGeometry.fromPolyline(self.wp))
        self.layer.commitChanges()
        self.layer.startEditing()

    def close_band(self):
        self.start_end_marker.close_markers()
        self.vertex_marker.hide()
        self.canvas().scene().removeItem(self.vertex_marker)
        self.vertex_marker = None
        self.mission_track.mission_changed.disconnect()
        self.layer.commitChanges()
        self.rubber_band.hide()
        self.mid_point_band.hide()
        self.rubber_band_points.hide()
        self.point_cursor_band.hide()
        self.canvas().scene().removeItem(self.rubber_band)
        self.canvas().scene().removeItem(self.mid_point_band)
        self.canvas().scene().removeItem(self.rubber_band_points)
        self.canvas().scene().removeItem(self.point_cursor_band)
        self.rubber_band = None
        self.mid_point_band = None
        self.rubber_band_points = None
        self.point_cursor_band = None
        self.msglog.logMessage("")
Beispiel #37
0
    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)
Beispiel #38
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)
Beispiel #39
0
class GeodesicMeasureDialog(QDialog, FORM_CLASS):
    def __init__(self, iface, parent):
        super(GeodesicMeasureDialog, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.pointDigitizerDialog = AddMeasurePointWidget(self, iface, parent)
        qset = QSettings()

        self.manualEntryButton.setIcon(
            QIcon(os.path.dirname(__file__) + "/images/manualpoint.png"))
        self.manualEntryButton.clicked.connect(self.showManualEntryDialog)

        self.restoreGeometry(
            qset.value("ShapeTools/MeasureDialogGeometry",
                       QByteArray(),
                       type=QByteArray))
        self.closeButton.clicked.connect(self.closeDialog)
        self.newButton.clicked.connect(self.newDialog)
        self.saveToLayerButton.clicked.connect(self.saveToLayer)
        self.saveToLayerButton.setEnabled(False)

        self.unitsComboBox.addItems(DISTANCE_LABELS)

        self.tableWidget.setColumnCount(3)
        self.tableWidget.setSortingEnabled(False)
        self.tableWidget.setHorizontalHeaderLabels(
            [tr('Heading To'),
             tr('Heading From'),
             tr('Distance')])

        self.unitsComboBox.activated.connect(self.unitsChanged)

        self.capturedPoints = []
        self.distances = []
        self.activeMeasuring = True
        self.lastMotionPt = None
        self.unitsChanged()
        self.currentDistance = 0.0

        self.pointRb = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry)
        self.pointRb.setColor(settings.rubberBandColor)
        self.pointRb.setIconSize(10)
        self.lineRb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry)
        self.lineRb.setColor(settings.rubberBandColor)
        self.lineRb.setWidth(3)
        self.tempRb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry)
        self.tempRb.setColor(settings.rubberBandColor)
        self.tempRb.setWidth(3)

    def showManualEntryDialog(self):
        self.pointDigitizerDialog.show()

    def ready(self):
        return self.activeMeasuring

    def stop(self):
        self.activeMeasuring = False
        self.lastMotionPt = None

    def closeEvent(self, event):
        self.closeDialog()

    def closeDialog(self):
        self.clear()
        QSettings().setValue("ShapeTools/MeasureDialogGeometry",
                             self.saveGeometry())
        self.close()
        self.pointDigitizerDialog.closeDialog()

    def newDialog(self):
        self.clear()
        self.initGeodLabel()

    def initGeodLabel(self):
        label = tr('Ellipsoid: ') + settings.ellipseDescription
        self.geodLabel.setText(label)

    def keyPressed(self, key):
        index = len(self.capturedPoints)
        if index <= 0:
            return
        if key == Qt.Key_Escape:
            self.endRubberband()
        if self.motionReady():
            if self.lastMotionPt is None:
                return
            (distance, startAngle,
             endAngle) = self.calcParameters(self.capturedPoints[index - 1],
                                             self.lastMotionPt)
        else:
            if index < 2:
                return
            (distance, startAngle,
             endAngle) = self.calcParameters(self.capturedPoints[index - 2],
                                             self.capturedPoints[index - 1])

        distance = self.unitDistance(distance)
        clipboard = QApplication.clipboard()
        if key == Qt.Key_1 or key == Qt.Key_F:
            s = '{:.{prec}f}'.format(startAngle,
                                     prec=settings.measureSignificantDigits)
            clipboard.setText(s)
            self.iface.messageBar().pushMessage(
                "",
                "Heading to {} copied to the clipboard".format(s),
                level=Qgis.Info,
                duration=3)
        elif key == Qt.Key_2 or key == Qt.Key_T:
            s = '{:.{prec}f}'.format(endAngle,
                                     prec=settings.measureSignificantDigits)
            clipboard.setText(s)
            self.iface.messageBar().pushMessage(
                "",
                "Heading from {} copied to the clipboard".format(s),
                level=Qgis.Info,
                duration=3)
        elif key == Qt.Key_3 or key == Qt.Key_D:
            s = '{:.{prec}f}'.format(distance,
                                     prec=settings.measureSignificantDigits)
            clipboard.setText(s)
            self.iface.messageBar().pushMessage(
                "",
                "Distance {} copied to the clipboard".format(s),
                level=Qgis.Info,
                duration=3)
        elif key == Qt.Key_4 or key == Qt.Key_A:
            total = 0.0
            num = len(self.capturedPoints)
            for i in range(1, num):
                (d, startA,
                 endA) = self.calcParameters(self.capturedPoints[i - 1],
                                             self.capturedPoints[i])
                total += d
            total = self.unitDistance(total)
            # Add in the motion distance
            if self.motionReady():
                total += distance
            s = '{:.{prec}f}'.format(total,
                                     prec=settings.measureSignificantDigits)
            clipboard.setText(s)
            self.iface.messageBar().pushMessage(
                "",
                "Total distance {} copied to the clipboard".format(s),
                level=Qgis.Info,
                duration=3)
        else:
            return

    def unitsChanged(self):
        label = "Distance [{}]".format(
            DISTANCE_LABELS[self.unitsComboBox.currentIndex()])
        item = QTableWidgetItem(label)
        self.tableWidget.setHorizontalHeaderItem(2, item)
        ptcnt = len(self.capturedPoints)
        if ptcnt >= 2:
            i = 0
            while i < ptcnt - 1:
                item = QTableWidgetItem('{:.4f}'.format(
                    self.unitDistance(self.distances[i])))
                self.tableWidget.setItem(i, 2, item)
                i += 1
            self.formatTotal()

    def motionReady(self):
        if len(self.capturedPoints) > 0 and self.activeMeasuring:
            return True
        return False

    def addPoint(self, pt, button):
        self.currentDistance = 0
        index = len(self.capturedPoints)
        if index > 0 and pt == self.capturedPoints[index - 1]:
            # the clicked point is the same as the previous so just ignore it
            return
        self.capturedPoints.append(pt)
        # Add rubber band points
        canvasCrs = self.canvas.mapSettings().destinationCrs()
        transform = QgsCoordinateTransform(epsg4326, canvasCrs,
                                           QgsProject.instance())
        ptCanvas = transform.transform(pt.x(), pt.y())
        self.pointRb.addPoint(ptCanvas, True)
        # If there is more than 1 captured point add it to the table
        if index > 0:
            self.saveToLayerButton.setEnabled(True)
            (distance, startAngle,
             endAngle) = self.calcParameters(self.capturedPoints[index - 1],
                                             self.capturedPoints[index])
            self.distances.append(distance)
            self.insertParams(index, distance, startAngle, endAngle)
            # Add Rubber Band Line
            linePts = self.getLinePts(distance, self.capturedPoints[index - 1],
                                      self.capturedPoints[index])
            self.lineRb.addGeometry(QgsGeometry.fromPolylineXY(linePts), None)
        self.formatTotal()

    def endRubberband(self):
        index = len(self.capturedPoints)
        if index <= 0:
            return
        if index == 1:
            self.newDialog()
            return
        if self.motionReady():
            if self.lastMotionPt is not None:
                self.lastMotionPt = None
                self.tempRb.reset(QgsWkbTypes.LineGeometry)
                self.tableWidget.setRowCount(self.tableWidget.rowCount() - 1)
        self.stop()
        self.currentDistance = 0
        self.formatTotal()

    def inMotion(self, pt):
        index = len(self.capturedPoints)
        if index <= 0:
            return
        (self.currentDistance, startAngle,
         endAngle) = self.calcParameters(self.capturedPoints[index - 1], pt)
        self.insertParams(index, self.currentDistance, startAngle, endAngle)
        self.formatTotal()
        linePts = self.getLinePts(self.currentDistance,
                                  self.capturedPoints[index - 1], pt)
        self.lastMotionPt = pt
        self.tempRb.setToGeometry(QgsGeometry.fromPolylineXY(linePts), None)

    def calcParameters(self, pt1, pt2):
        gline = geod.Inverse(pt1.y(), pt1.x(), pt2.y(), pt2.x())
        az2 = (gline['azi2'] + 180) % 360.0
        if az2 > 180:
            az2 = az2 - 360.0
        az1 = gline['azi1']

        # Check to see if the azimuth values should be in the range or 0 to 360
        # The default is -180 to 180
        if settings.mtAzMode:
            if az1 < 0:
                az1 += 360.0
            if az2 < 0:
                az2 += 360
        return (gline['s12'], az1, az2)

    def getLinePts(self, distance, pt1, pt2):
        canvasCrs = self.canvas.mapSettings().destinationCrs()
        transform = QgsCoordinateTransform(epsg4326, canvasCrs,
                                           QgsProject.instance())
        pt1c = transform.transform(pt1.x(), pt1.y())
        pt2c = transform.transform(pt2.x(), pt2.y())
        if distance < 10000:
            return [pt1c, pt2c]
        gline = geod.InverseLine(pt1.y(), pt1.x(), pt2.y(), pt2.x())
        n = int(math.ceil(distance / 10000.0))
        if n > 20:
            n = 20
        seglen = distance / n
        pts = [pt1c]
        for i in range(1, n):
            s = seglen * i
            g = gline.Position(
                s,
                Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL)
            ptc = transform.transform(g['lon2'], g['lat2'])
            pts.append(ptc)
        pts.append(pt2c)
        return pts

    def saveToLayer(self):
        units = self.unitDesignator()
        canvasCrs = self.canvas.mapSettings().destinationCrs()
        fields = QgsFields()
        fields.append(QgsField("label", QVariant.String))
        fields.append(QgsField("value", QVariant.Double))
        fields.append(QgsField("units", QVariant.String))
        fields.append(QgsField("heading_to", QVariant.Double))
        fields.append(QgsField("heading_from", QVariant.Double))
        fields.append(QgsField("total_dist", QVariant.Double))

        layer = QgsVectorLayer("LineString?crs={}".format(canvasCrs.authid()),
                               "Measurements", "memory")
        dp = layer.dataProvider()
        dp.addAttributes(fields)
        layer.updateFields()

        num = len(self.capturedPoints)
        total = 0.0
        for i in range(1, num):
            (distance, startA,
             endA) = self.calcParameters(self.capturedPoints[i - 1],
                                         self.capturedPoints[i])
            total += distance
        total = self.unitDistance(total)
        for i in range(1, num):
            (distance, startA,
             endA) = self.calcParameters(self.capturedPoints[i - 1],
                                         self.capturedPoints[i])
            pts = self.getLinePts(distance, self.capturedPoints[i - 1],
                                  self.capturedPoints[i])
            distance = self.unitDistance(distance)
            feat = QgsFeature(layer.fields())
            feat.setAttribute(0, "{:.2f} {}".format(distance, units))
            feat.setAttribute(1, distance)
            feat.setAttribute(2, units)
            feat.setAttribute(3, startA)
            feat.setAttribute(4, endA)
            feat.setAttribute(5, total)
            feat.setGeometry(QgsGeometry.fromPolylineXY(pts))
            dp.addFeatures([feat])

        label = QgsPalLayerSettings()
        label.fieldName = 'label'
        try:
            label.placement = QgsPalLayerSettings.Line
        except Exception:
            label.placement = QgsPalLayerSettings.AboveLine
        format = label.format()
        format.setColor(settings.measureTextColor)
        format.setNamedStyle('Bold')
        label.setFormat(format)
        labeling = QgsVectorLayerSimpleLabeling(label)
        layer.setLabeling(labeling)
        layer.setLabelsEnabled(True)
        renderer = layer.renderer()
        renderer.symbol().setColor(settings.measureLineColor)
        renderer.symbol().setWidth(0.5)

        layer.updateExtents()
        QgsProject.instance().addMapLayer(layer)

    def insertParams(self, position, distance, startAngle, endAngle):
        if position > self.tableWidget.rowCount():
            self.tableWidget.insertRow(position - 1)
        item = QTableWidgetItem('{:.4f}'.format(self.unitDistance(distance)))
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableWidget.setItem(position - 1, 2, item)
        item = QTableWidgetItem('{:.4f}'.format(startAngle))
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableWidget.setItem(position - 1, 0, item)
        item = QTableWidgetItem('{:.4f}'.format(endAngle))
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableWidget.setItem(position - 1, 1, item)

    def formatTotal(self):
        total = self.currentDistance
        ptcnt = len(self.capturedPoints)
        if ptcnt >= 2:
            i = 0
            while i < ptcnt - 1:
                total += self.distances[i]
                i += 1
        self.distanceLineEdit.setText('{:.2f}'.format(
            self.unitDistance(total)))

    def updateRBColor(self):
        self.pointRb.setColor(settings.rubberBandColor)
        self.lineRb.setColor(settings.rubberBandColor)
        self.tempRb.setColor(settings.rubberBandColor)

    def clear(self):
        self.tableWidget.setRowCount(0)
        self.capturedPoints = []
        self.distances = []
        self.activeMeasuring = True
        self.currentDistance = 0.0
        self.distanceLineEdit.setText('')
        self.pointRb.reset(QgsWkbTypes.PointGeometry)
        self.lineRb.reset(QgsWkbTypes.LineGeometry)
        self.tempRb.reset(QgsWkbTypes.LineGeometry)
        self.saveToLayerButton.setEnabled(False)
        self.updateRBColor()

    def unitDistance(self, distance):
        units = self.unitsComboBox.currentIndex()
        if units == 0:  # kilometers
            return distance / 1000.0
        elif units == 1:  # meters
            return distance
        elif units == 2:  # centimeters
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceCentimeters)
        elif units == 3:  # miles
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceMiles)
        elif units == 4:  # yards
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceYards)
        elif units == 5:  # feet
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceFeet)
        elif units == 6:  # inches
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceFeet) * 12
        elif units == 7:  # nautical miles
            return distance * QgsUnitTypes.fromUnitToUnitFactor(
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceNauticalMiles)

    def unitDesignator(self):
        units = self.unitsComboBox.currentIndex()
        return unitsAbbr[units]
Beispiel #40
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(),
                                    QgsWkbTypes.LineGeometry)
        self.rbline.setColor(QColor('#f4530e'))
        self.rbline.setWidth(3)
        self.rbmarkers = QgsRubberBand(self.iface.mapCanvas(),
                                       QgsWkbTypes.PointGeometry)
        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('#88f49e79'))
        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.
        """

        # A dict of layers
        #  and for each layer the fields to use as foreign key
        #  as well as the possible target layers
        # Reaches can be connected to reaches and nodes
        # Catchment areas only to nodes
        self.network_element_sources = {
            QgepLayerManager.layer('vw_qgep_reach'): {
                'fields': [('rp_to_fk_wastewater_networkelement',
                            QCoreApplication.translate(
                                'QgepMapToolConnectNetworkElements',
                                'Reach Point To')),
                           ('rp_from_fk_wastewater_networkelement',
                            QCoreApplication.translate(
                                'QgepMapToolConnectNetworkElements',
                                'Reach Point From'))],
                'target_layers': [
                    QgepLayerManager.layer('vw_wastewater_node'),
                    QgepLayerManager.layer('vw_qgep_reach')
                ]
            },
            QgepLayerManager.layer('catchment_area'): {
                'fields': [('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'))],
                'target_layers':
                [QgepLayerManager.layer('vw_wastewater_node')]
            }
        }

        self.setSnapLayers(self.source_snapper,
                           list(self.network_element_sources.keys()))

        self.reset()

        self.action.setChecked(True)

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

    def setSnapLayers(self, snapper, layers):
        config = QgsSnappingConfig()
        config.setMode(QgsSnappingConfig.AdvancedConfiguration)
        config.setEnabled(True)

        for layer in layers:
            if layer:
                ils = QgsSnappingConfig.IndividualLayerSettings(
                    True, QgsSnappingConfig.VertexAndSegment, 16,
                    QgsTolerance.Pixels)
                config.setIndividualLayerSettings(layer, ils)

        snapper.setConfig(config)

    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:
                # There is already a source feature : snap to target feature
                # candidates
                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:
                # Snapped to source feature, update source feature rubber band
                # and target layer snapper
                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.setSnapLayers(
                        self.target_snapper, self.network_element_sources[
                            snap_match.layer()]['target_layers'])
                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(QgsWkbTypes.PointGeometry)
        self.rbmarkers.addPoint(QgsPointXY())
        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()]['fields']:
            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 not source.layer().isEditable():
                self.iface.messageBar().pushMessage(
                    'QGEP',
                    self.tr('Layer "{layername}" is not in edit mode').format(
                        layername=source.layer().name()), Qgis.Warning, 5)
            elif source.layer().updateFeature(source_feature):
                self.iface.messageBar().pushMessage(
                    'QGEP',
                    self.tr('Connected {} to {}').format(
                        source_feature['identifier'],
                        target_feature['identifier']), Qgis.Info, 5)
            else:
                self.iface.messageBar().pushMessage(
                    'QGEP', self.tr('Error connecting features'), Qgis.Warning,
                    5)

        self.reset()
 def __init__(self, iface):
     self.iface = iface
     self.mapCanvas = iface.mapCanvas()
     QgsMapTool.__init__(self, self.mapCanvas)
     self.settings = MySettings()
     self.rubber = QgsRubberBand(self.mapCanvas, QGis.Point)
Beispiel #42
0
    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 = {}
Beispiel #43
0
class QgepMapTool(QgsMapTool):
    """
    Base class for all the map tools
    """

    highlightedPoints = []
    logger = logging.getLogger(__name__)
    snapper = None

    def __init__(self,
                 iface: QgisInterface,
                 button,
                 network_analyzer: QgepGraphManager = None):
        QgsMapTool.__init__(self, iface.mapCanvas())
        self.canvas = iface.mapCanvas()
        self.cursor = QCursor(Qt.CrossCursor)
        self.button = button
        self.msgBar = iface.messageBar()
        self.network_analyzer = network_analyzer

        settings = QSettings()
        current_profile_color = settings.value("/QGEP/CurrentProfileColor",
                                               '#FF9500')

        self.rubberBand = QgsRubberBand(self.canvas)
        self.rubberBand.setColor(QColor(current_profile_color))
        self.rubberBand.setWidth(3)

    def activate(self):
        """
        Gets called when the tool is activated
        """
        QgsMapTool.activate(self)
        self.canvas.setCursor(self.cursor)
        self.button.setChecked(True)

    def deactivate(self):
        """
        Gets called whenever the tool is deactivated directly or indirectly
        """
        QgsMapTool.deactivate(self)
        self.button.setChecked(False)

    # pylint: disable=no-self-use
    def isZoomTool(self):
        """
        Will return if this is a zoom tool
        """
        return False

    def setCursor(self, cursor):
        """
        Set the cursor for this maptool
        """
        self.cursor = QCursor(cursor)

    # ===========================================================================
    # Events
    # ===========================================================================

    def canvasReleaseEvent(self, event):
        """
        Issues rightClicked and leftClicked events
        """
        if event.button() == Qt.RightButton:
            self.rightClicked(event)
        else:
            self.leftClicked(event)

    def canvasDoubleClickEvent(self, event):
        """
        Forwards to doubleClicked
        """
        try:
            self.doubleClicked(event)
        except AttributeError:
            pass

    # ===========================================================================
    # Snapping
    # ===========================================================================
    def init_snapper(self):
        """
        Initialize snapper
        """
        if not self.snapper:
            self.node_layer = self.network_analyzer.getNodeLayer()
            self.snapper = QgsMapCanvasSnappingUtils(self.canvas)
            config = QgsSnappingConfig()
            config.setMode(QgsSnappingConfig.AdvancedConfiguration)
            config.setEnabled(True)
            ils = QgsSnappingConfig.IndividualLayerSettings(
                True, QgsSnappingConfig.VertexAndSegment, 16,
                QgsTolerance.Pixels)
            config.setIndividualLayerSettings(self.node_layer, ils)
            self.snapper.setConfig(config)

    def snap_point(self,
                   event,
                   show_menu: bool = True) -> QgsPointLocator.Match:
        """
        Snap to a point on this network
        :param event: A QMouseEvent
        :param show_menu: determines if a menu shall be shown on a map if several matches are available
        """
        clicked_point = event.pos()

        if not self.snapper:
            self.init_snapper()

        class CounterMatchFilter(QgsPointLocator.MatchFilter):
            def __init__(self):
                super().__init__()
                self.matches = list()

            def acceptMatch(self, match):
                self.matches.append(match)
                return True

        match_filter = CounterMatchFilter()
        match = self.snapper.snapToMap(clicked_point, match_filter)

        if not match.isValid() or len(match_filter.matches) == 1:
            return match
        elif len(match_filter.matches) > 1:
            point_ids = [match.featureId() for match in match_filter.matches]
            node_features = self.network_analyzer.getFeaturesById(
                self.network_analyzer.getNodeLayer(), point_ids)

            # Filter wastewater nodes
            filtered_features = {
                fid: node_features.featureById(fid)
                for fid in node_features.asDict()
                if node_features.attrAsUnicode(node_features.featureById(fid),
                                               'type') == 'wastewater_node'
            }

            # Only one wastewater node left: return this
            if len(filtered_features) == 1:
                matches = (match for match in match_filter.matches
                           if match.featureId() == next(
                               iter(filtered_features.keys())))
                return next(matches)

            # Still not sure which point to take?
            # Are there no wastewater nodes filtered? Let the user choose from the reach points
            if not filtered_features:
                filtered_features = node_features.asDict()

            # Ask the user which point he wants to use
            if not show_menu:
                return QgsPointLocator.Match()

            actions = dict()

            menu = QMenu(self.canvas)

            for _, feature in list(filtered_features.items()):
                try:
                    title = feature.attribute(
                        'description') + " (" + feature.attribute(
                            'obj_id') + ")"
                except TypeError:
                    title = " (" + feature.attribute('obj_id') + ")"
                action = QAction(title, menu)
                actions[action] = match
                menu.addAction(action)

            clicked_action = menu.exec_(self.canvas.mapToGlobal(event.pos()))

            if clicked_action is not None:
                return actions[clicked_action]

            return QgsPointLocator.Match()
Beispiel #44
0
class PipelinePlanner:
    """QGIS Plugin Implementation."""
    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        self.addPipelinePoint = QgsMapToolEmitPoint(self.canvas)
        self.rbPipeline = QgsRubberBand(self.canvas)
        self.rbPipeline.setColor(Qt.red)
        self.rbPipeline.setWidth(4)
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'PipelinePlanner_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)
            QCoreApplication.installTranslator(self.translator)

        # Declare instance attributes
        self.actions = []
        self.menu = self.tr(u'&Pipeline Planner')

        # Check if plugin was started the first time in current QGIS session
        # Must be set in initGui() to survive plugin reloads
        self.first_start = None
        self.dlg = PipelinePlannerDialog()
        self.dlg.tblImpacts.setColumnWidth(1, 75)
        self.dlg.tblImpacts.setColumnWidth(2, 250)
        self.dlg.tblImpacts.setColumnWidth(3, 75)

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('PipelinePlanner', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            # Adds plugin icon to Plugins toolbar
            self.iface.addToolBarIcon(action)

        if add_to_menu:
            self.iface.addPluginToVectorMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/pipeline_planner/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'Pipeline Planner'),
                        callback=self.run,
                        parent=self.iface.mainWindow())

        # will be set False in run()
        self.first_start = True
        self.addPipelinePoint.canvasClicked.connect(self.evaluatePipeline)

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginVectorMenu(self.tr(u'&Pipeline Planner'),
                                              action)
            self.iface.removeToolBarIcon(action)

    def run(self):
        """Run method that performs all the real work"""
        self.canvas.setMapTool(self.addPipelinePoint)

    def evaluatePipeline(self, point, button):
        if button == Qt.LeftButton:
            self.rbPipeline.addPoint(point)
            self.rbPipeline.show()
        elif button == Qt.RightButton:
            pipeline = self.rbPipeline.asGeometry()
            self.dlg.tblImpacts.setRowCount(0)

            lyrRaptor = QgsProject.instance().mapLayersByName(
                "Raptor Buffer")[0]
            raptors = lyrRaptor.getFeatures(pipeline.boundingBox())
            for raptor in raptors:
                valConstraint = raptor.attribute("recentspec")
                valID = raptor.attribute("Nest_ID")
                valStatus = raptor.attribute("recentstat")
                valDistance = pipeline.distance(raptor.geometry().centroid())
                if raptor.geometry().intersects(pipeline):
                    row = self.dlg.tblImpacts.rowCount()
                    self.dlg.tblImpacts.insertRow(row)
                    self.dlg.tblImpacts.setItem(
                        row, 0, QTableWidgetItem(valConstraint))
                    self.dlg.tblImpacts.setItem(row, 1,
                                                QTableWidgetItem(str(valID)))
                    self.dlg.tblImpacts.setItem(row, 2,
                                                QTableWidgetItem(valStatus))
                    self.dlg.tblImpacts.setItem(
                        row, 3,
                        QTableWidgetItem("{:4.5f}".format(valDistance)))

            lyrEagle = QgsProject.instance().mapLayersByName("BAEA Buffer")[0]
            eagles = lyrEagle.getFeatures(pipeline.boundingBox())
            for eagle in eagles:
                valConstraint = "BAEA Nest"
                valID = eagle.attribute("nest_id")
                valStatus = eagle.attribute("status")
                valDistance = pipeline.distance(eagle.geometry().centroid())
                if eagle.geometry().intersects(pipeline):
                    row = self.dlg.tblImpacts.rowCount()
                    self.dlg.tblImpacts.insertRow(row)
                    self.dlg.tblImpacts.setItem(
                        row, 0, QTableWidgetItem(valConstraint))
                    self.dlg.tblImpacts.setItem(row, 1,
                                                QTableWidgetItem(str(valID)))
                    self.dlg.tblImpacts.setItem(row, 2,
                                                QTableWidgetItem(valStatus))
                    self.dlg.tblImpacts.setItem(
                        row, 3,
                        QTableWidgetItem("{:4.5f}".format(valDistance)))

            lyrBUOWL = QgsProject.instance().mapLayersByName("BUOWL Buffer")[0]
            buowls = lyrBUOWL.getFeatures(pipeline.boundingBox())
            for buowl in buowls:
                valConstraint = "BUOWL Habitat"
                valID = buowl.attribute("habitat_id")
                valStatus = buowl.attribute("recentstat")
                valDistance = pipeline.distance(buowl.geometry().buffer(
                    -0.001, 5))
                if buowl.geometry().intersects(pipeline):
                    row = self.dlg.tblImpacts.rowCount()
                    self.dlg.tblImpacts.insertRow(row)
                    self.dlg.tblImpacts.setItem(
                        row, 0, QTableWidgetItem(valConstraint))
                    self.dlg.tblImpacts.setItem(row, 1,
                                                QTableWidgetItem(str(valID)))
                    self.dlg.tblImpacts.setItem(row, 2,
                                                QTableWidgetItem(valStatus))
                    self.dlg.tblImpacts.setItem(
                        row, 3,
                        QTableWidgetItem("{:4.5f}".format(valDistance)))

            self.dlg.show()

            self.rbPipeline.reset()
Beispiel #45
0
class QgepProfileMapTool(QgepMapTool):
    """
    The map tool used for PROFILE

    Allows to find the shortest path between several nodes.
    """
    profileChanged = pyqtSignal(object)
    profile = QgepProfile()
    segmentOffset = 0

    selectedPathPoints = []
    pathPolyline = []

    def __init__(self, canvas, button, network_analyzer):
        QgepMapTool.__init__(self, canvas, button, network_analyzer)
        settings = QSettings()

        helper_line_color = settings.value("/QGEP/HelperLineColor", '#FFD900')
        highlight_color = settings.value("/QGEP/HighlightColor", '#40FF40')

        # Init rubberband to visualize current status
        self.rbHelperLine = QgsRubberBand(self.canvas)
        self.rbHelperLine.setColor(QColor(helper_line_color))
        self.rbHelperLine.setWidth(2)

        self.rbHighlight = QgsRubberBand(self.canvas)
        self.rbHighlight.setColor(QColor(highlight_color))
        self.rbHighlight.setWidth(5)

        self.profile.setRubberband(self.rbHighlight)

        self.saveTool = None

    def setActive(self):
        """
        activates this map tool
        """
        self.saveTool = self.canvas.mapTool()
        self.canvas.setMapTool(self)

    def deactivate(self):
        """
        Called whenever this map tool is deactivated.
        Used to clean up code
        """
        QgepMapTool.deactivate(self)
        self.rubberBand.reset()
        self.rbHelperLine.reset()
        self.selectedPathPoints = []
        self.pathPolyline = []

    def findPath(self, start_point, end_point):
        """
        Tries to find the shortest path between pStart and pEnd.
        If it finds a path:
         * The path is visualized with a QgsRubberband
         * The profile plot is updated to represent the current path

        @param start_point: The id of the start point of the path
        @param end_point:   The id of the end point of the path
        """
        QApplication.setOverrideCursor(Qt.WaitCursor)
        # try:
        (vertices,
         edges) = self.network_analyzer.shortestPath(start_point, end_point)
        self.appendProfile(vertices, edges)
        #        except:
        #            pass
        QApplication.restoreOverrideCursor()
        if len(vertices) > 0:
            return True
        else:
            return False

    # pylint: disable=too-many-locals
    def appendProfile(self, vertices, edges):
        """
        Appends to the current profile

        @param vertices: A collection of vertices to append
        @param edges:    A collection of edges which connect the vertices
        """
        self.logger.debug('Append profile')
        self.logger.info(' * ' + repr(len(vertices)) + ' vertices')
        for v in vertices:
            self.logger.debug('   *' + repr(v))
        self.logger.info(' * ' + repr(len(edges)) + ' edges')
        for e in edges:
            self.logger.debug('   *' + repr(e))

        # Fetch all the needed edges in one batch
        edge_layer = self.network_analyzer.getEdgeLayer()
        edge_ids = [edge['feature'] for p1, p2, edge in edges]

        edge_features = self.network_analyzer.getFeaturesById(
            edge_layer, edge_ids)

        # We need some additional nodes, where we need to interpolate...
        interpolate_nodes_from = [
            edge_features.attrAsUnicode(feat, 'from_obj_id_interpolate')
            for feat in list(edge_features.asDict().values())
        ]
        interpolate_nodes_to = [
            edge_features.attrAsUnicode(feat, 'to_obj_id_interpolate')
            for feat in list(edge_features.asDict().values())
        ]
        additional_ids = [
            self.network_analyzer.vertexIds[node]
            for node in interpolate_nodes_from
        ]
        additional_ids += [
            self.network_analyzer.vertexIds[node]
            for node in interpolate_nodes_to
        ]

        # Now, fetch the nodes we need
        node_layer = self.network_analyzer.getNodeLayer()
        node_ids = vertices + additional_ids
        node_features = self.network_analyzer.getFeaturesById(
            node_layer, node_ids)

        if len(vertices) > 1:
            self.rubberBand.reset()

            elem = QgepProfileNodeElement(vertices[0], node_features, 0)
            self.profile.addElement(vertices[0], elem)

            for p1, p2, edge in edges:
                from_offset = self.segmentOffset
                to_offset = self.segmentOffset + edge['weight']

                if 'reach' == edge['objType']:
                    if self.profile.hasElement(edge['baseFeature']):
                        self.profile[edge['baseFeature']].addSegment(
                            p1, p2, edge['feature'], node_features,
                            edge_features, from_offset, to_offset)
                    else:
                        elem = QgepProfileReachElement(p1, p2, edge['feature'],
                                                       node_features,
                                                       edge_features,
                                                       from_offset, to_offset)
                        self.profile.addElement(elem.obj_id, elem)

                elif 'special_structure' == edge['objType']:
                    if self.profile.hasElement(edge['baseFeature']):
                        self.profile[edge['baseFeature']].addSegment(
                            p1, p2, edge['feature'], node_features,
                            edge_features, from_offset, to_offset)
                    else:
                        elem = QgepProfileSpecialStructureElement(
                            p1, p2, edge['feature'], node_features,
                            edge_features, from_offset, to_offset)
                        self.profile.addElement(elem.obj_id, elem)

                elem = QgepProfileNodeElement(p2, node_features, to_offset)
                self.profile.addElement(p2, elem)

                self.segmentOffset = to_offset

            self.profileChanged.emit(self.profile)

            # Create rubberband geometry
            for featId in edge_ids:
                self.pathPolyline.extend(
                    edge_features[featId].geometry().asPolyline())

            self.rubberBand.addGeometry(
                QgsGeometry.fromPolylineXY(self.pathPolyline), node_layer)
            self.profileChanged.emit(self.profile)
            return True
        else:
            return False

    def canvasMoveEvent(self, event):
        """
        Mouse moved: update helper line

        @param event: The mouse event with coordinates and all
        """
        if self.selectedPathPoints:
            self.rbHelperLine.reset()
            for point in self.selectedPathPoints:
                self.rbHelperLine.addPoint(point[1])
            mouse_pos = self.canvas.getCoordinateTransform() \
                .toMapCoordinates(event.pos().x(), event.pos().y())
            self.rbHelperLine.addPoint(mouse_pos)

    def rightClicked(self, _):
        """
        Cancel any ongoing path selection

        @param event: The mouse event with coordinates and all
        """
        self.selectedPathPoints = []
        self.pathPolyline = []
        self.rbHelperLine.reset()
        self.profile.reset()
        self.segmentOffset = 0

    def leftClicked(self, event):
        """
        Select startpoint / intermediate point / endpoint

        @param event: The mouse event with coordinates and all
        """
        match = self.snap_point(event)

        if match.isValid():
            if self.selectedPathPoints:
                pf = self.findPath(self.selectedPathPoints[-1][0],
                                   match.featureId())
                if pf:
                    self.selectedPathPoints.append(
                        (match.featureId(), QgsPointXY(match.point())))
                else:
                    msg = self.msgBar.createMessage('No path found')
                    self.msgBar.pushWidget(msg, Qgis.Info)
            else:
                self.selectedPathPoints.append(
                    (match.featureId(), QgsPointXY(match.point())))
class DivisionFusion:
    """QGIS Plugin Implementation."""
    def __init__(self, iface, ACA):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        self.CFG = None
        self.UTI = None
        self.DFS = None
        self.DBJ = None
        self.ELM = None
        self.ACA = ACA
        self.TPG = None
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'DivisionFusion_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Create the dialog (after translation) and keep reference
        self.dlg = DivisionFusionDialog(parent=iface.mainWindow(), DIV=self)

        # Declare instance attributes
        '''
        self.actions = []
        self.menu = self.tr(u'&DivisionFusion')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'DivisionFusion')
        self.toolbar.setObjectName(u'DivisionFusion')
        '''
        self.eventos = EventoDivision(iface.mapCanvas(), self,
                                      iface.cadDockWidget())
        iface.mapCanvas().setMapTool(self.eventos)
        self.VentanaAreas = VentanaAreas(self)

        self.VentanaFusion = VentanaFusionV3(iface, self)
        self.VentanaClaves = VentanaClavesV3(iface, self)
        self.rubberMarca = QgsRubberBand(iface.mapCanvas(),
                                         QgsWkbTypes.PolygonGeometry)
        self.rubberMarca.setFillColor(QColor(255, 255, 0, 12))
        self.rubberMarca.setStrokeColor(QColor(255, 150, 0, 255))
        self.rubberMarca.setWidth(2)
        self.listaNuevosPredios = []
        self.cargoPredio = False
        self.listaColores = []
        self.rubbersAreas = []

        self.dlg.btnDibujarCortes.setEnabled(False)
        self.dlg.btnEditarCortes.setEnabled(False)
        self.dlg.btnEliminarCortes.setEnabled(False)
        self.dlg.btnApagarHerramientas.setEnabled(False)
        self.dlg.btnConfirmarCortes.setEnabled(False)
        self.dlg.btnDeshacerTodo.setEnabled(False)
        self.dlg.btnCancelarSub.setEnabled(False)
        self.dlg.btnDeshacerCortes.setEnabled(False)
        self.dlg.btnLlamarCalcular.setEnabled(False)

        self.dlg.btnFusionar.clicked.connect(self.preguntarFusion)
        self.dlg.btnCargarPredio.clicked.connect(self.pasarAModoDivision)
        self.dlg.btnConfirmarCortes.clicked.connect(self.confirmarCortes)
        self.dlg.btnDibujarCortes.clicked.connect(self.encenderModoDividir)
        self.dlg.btnEliminarCortes.clicked.connect(self.encenderModoEliminar)
        self.dlg.btnApagarHerramientas.clicked.connect(self.apagarHerramientas)
        self.dlg.btnDeshacerTodo.clicked.connect(self.rollBack)
        self.dlg.btnCancelarSub.clicked.connect(self.cancelarSubdivision)
        self.dlg.btnDeshacerCortes.clicked.connect(self.vaciarLineasCorte)
        self.dlg.btnLlamarCalcular.clicked.connect(self.irAreas)
        self.dlg.btnEditarCortes.clicked.connect(self.encenderModoEditar)

        self.dlg.btnDeshacerTodo.hide()
        self.enClaves = False
        self.enSubdivision = False
        self.enFusion = False

        self.headers = {'Content-Type': 'application/json'}
        self.geomsAreas = []

    # noinspection PyMethodMayBeStatic
    def tr(self, message):
        """Get the translation for a string using Qt translation API.

        We implement this ourselves since we do not inherit QObject.

        :param message: String for translation.
        :type message: str, QString

        :returns: Translated version of message.
        :rtype: QString
        """
        # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
        return QCoreApplication.translate('DivisionFusion', message)

    def add_action(self,
                   icon_path,
                   text,
                   callback,
                   enabled_flag=True,
                   add_to_menu=True,
                   add_to_toolbar=True,
                   status_tip=None,
                   whats_this=None,
                   parent=None):
        """Add a toolbar icon to the toolbar.

        :param icon_path: Path to the icon for this action. Can be a resource
            path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
        :type icon_path: str

        :param text: Text that should be shown in menu items for this action.
        :type text: str

        :param callback: Function to be called when the action is triggered.
        :type callback: function

        :param enabled_flag: A flag indicating if the action should be enabled
            by default. Defaults to True.
        :type enabled_flag: bool

        :param add_to_menu: Flag indicating whether the action should also
            be added to the menu. Defaults to True.
        :type add_to_menu: bool

        :param add_to_toolbar: Flag indicating whether the action should also
            be added to the toolbar. Defaults to True.
        :type add_to_toolbar: bool

        :param status_tip: Optional text to show in a popup when mouse pointer
            hovers over the action.
        :type status_tip: str

        :param parent: Parent widget for the new action. Defaults None.
        :type parent: QWidget

        :param whats_this: Optional text to show in the status bar when the
            mouse pointer hovers over the action.

        :returns: The action that was created. Note that the action is also
            added to self.actions list.
        :rtype: QAction
        """

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(self.menu, action)

        self.actions.append(action)

        return action

    def initGui(self):
        """Create the menu entries and toolbar icons inside the QGIS GUI."""

        icon_path = ':/plugins/DivisionFusion/icon.png'
        self.add_action(icon_path,
                        text=self.tr(u'DivisionFusion'),
                        callback=self.run,
                        parent=self.iface.mainWindow())

    def unload(self):
        """Removes the plugin menu item and icon from QGIS GUI."""
        for action in self.actions:
            self.iface.removePluginMenu(self.tr(u'&DivisionFusion'), action)
            self.iface.removeToolBarIcon(action)
        # remove the toolbar
        del self.toolbar

    def run(self):
        """Run method that performs all the real work"""
        # show the dialog
        for x in iface.mapNavToolToolBar().actions():
            if x.objectName() == 'mActionPan':
                x.trigger()
        for x in iface.advancedDigitizeToolBar().actions():
            if x.objectName() == 'mEnableAction':
                x.trigger()
        self.dlg.show()
        # Run the dialog event loop
        iface.mapCanvas().setMapTool(self.eventos)
        result = self.dlg.exec_()
        # See if OK was pressed
        self.dlg.btnFusionar.setEnabled(True)
        self.dlg.comboPredios.setEnabled(True)
        self.dlg.btnCargarPredio.setEnabled(True)
        self.dlg.btnDibujarCortes.setEnabled(False)
        self.dlg.btnEditarCortes.setEnabled(False)
        self.dlg.btnEliminarCortes.setEnabled(False)
        self.dlg.btnApagarHerramientas.setEnabled(False)
        self.dlg.btnConfirmarCortes.setEnabled(False)
        self.dlg.btnDeshacerTodo.setEnabled(False)

        # llena los predios en el combo
        self.dlg.comboPredios.clear()
        lista = []

        capaPredios = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))

        if capaPredios is None:
            return

        # lista de features
        for predio in capaPredios.getFeatures():
            lista.append(str(predio['clave']))

        lista.sort()
        for elemento in lista:
            self.dlg.comboPredios.addItem(elemento)

        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            pass

    '''def consumirPredios(self):
        listaPredio =[]
        if iface.activeLayer() != None:
            seleccion = self.iface.activeLayer().selectedFeatures()
            for i in seleccion:
                self.id = self.consumeWSGeneral(url_cons = self.CFG.url_AU_getAllfactures + str(i['id']) )
                if not self.id:
                    return
                listaPredio.append(self.id)
            print(listaPredio)'''

    #------------------------------------------------------------------------------

    #Preguntamos si quiere fusionar
    def preguntarFusion(self):
        listaPredio = []
        #self.consumirPredios()
        if iface.activeLayer() != None:
            seleccion = self.iface.activeLayer().selectedFeatures()
            #self.VentanaFusion.dlg.close()
            if self.validarCuentaSeleccion():  #Si la seleccion es valida
                for i in seleccion:
                    self.id = self.consumeWSGeneral(
                        url_cons=self.CFG.url_AU_getAllfactures + str(i['id']))
                    if not self.id:
                        return
                    listaPredio.append(self.id)
                #print(listaPredio)
                self.enFusion = True
                #self.VentanaFusion.dlg.show()
                #self.VentanaFusion.llenarTablaComp(listaPredio[0], listaPredio[1])
                self.dlg.btnCargarPredio.setEnabled(False)
        #else:
        #self.UTI.mostrarAlerta('La fusion requiere la seleccion de exactamente 2 predios contiguos', QMessageBox().Critical, 'Error de fusion')

#------------------------------------------------------------------

#Validamosla seleccion

    def validarCuentaSeleccion(self):
        seleccion = self.iface.activeLayer().selectedFeatures()
        for i in seleccion:
            if str(i['id']) == '':
                self.UTI.mostrarAlerta(
                    'El predio ' + str(i['clave']) +
                    ' no se puede fusionar, guarde los cambios antes de continuar',
                    QMessageBox().Critical, 'Error de fusion')
                return False
        if len(seleccion) != 2:  #Cuando tenemos seleccionados no 2 elementos
            self.UTI.mostrarAlerta(
                'La fusion requiere la seleccion de exactamente 2 predios contiguos',
                QMessageBox().Critical, 'Error de fusion')
            return False
        else:
            if not self.validarContiguedad():
                self.UTI.mostrarAlerta(
                    'Los predios seleccionados no son contiguos',
                    QMessageBox().Critical, 'Error de fusion')
                return False
            else:
                return True
#-----------------------------------------------------------------------------

    def validarContiguedad(self):  #Aqui checamos si dos predios son contiguos
        seleccion = self.iface.activeLayer().selectedFeatures()
        pred1 = seleccion[0].geometry().buffer(0.0000001, 1)
        pred2 = seleccion[1].geometry().buffer(0.0000001, 1)
        #Checamos que el area de interseccion sea un valor considerable
        area = pred1.intersection(pred2).area()
        return area > 0.0000000001

#-----------------------------------------------------------------------------------

    def fusionarPredios(self, eleccion):  #Aqui fusionamos los predios

        #OBtener las capas
        capaManzana = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('manzana'))
        capaPuntos = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.num'))
        capaPredios = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))
        capaConstru = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('construcciones'))
        capaCondH = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('horizontales.geom'))

        #Puntos y eleccion de victima
        seleccion = self.iface.activeLayer().selectedFeatures()
        if seleccion == None:
            self.pluginFD.UTI.mostrarAlerta(
                'Debes seleccionar un predio destino',
                QMessageBox().Critical, 'Error de seleccion')
            return
        listaPuntos = [None, None]

        #Definimos el predio 'victima
        if eleccion == 0:
            victima = 1
        else:
            victima = 0

        #eliminamos el predio no elegido
        self.eliminarNoElegido(seleccion[victima])

        #Eliminar punto del predio no elegido
        for punto in capaPuntos.getFeatures():
            if punto.geometry().intersects(seleccion[victima].geometry(
            )):  #Bsucamos el punto del predio victima
                capaPuntos.startEditing()
                capaPuntos.dataProvider().deleteFeatures([punto.id()])
                capaPuntos.triggerRepaint()
                capaPuntos.commitChanges()
                break

        #Generar geometria del predio fusionado
        rango = len(seleccion)
        geomFusion = seleccion[0].geometry()

        featFusion = QgsFeature()
        capaPredios.startEditing()

        #Generar geometria del predio fusionado
        for i in range(0, rango):
            self.iface.activeLayer().dataProvider().deleteFeatures(
                [seleccion[i].id()])
            geomFusion = geomFusion.combine(seleccion[i].geometry())

        #self.geom
        listaFinal = []
        listaPrimera = []
        featFusion.setGeometry(geomFusion)

        #Renombrar construcciones
        cuentaConstruccion = 1
        capaConstru.startEditing()

        #--------Renombrar construcciones----
        for construccion in capaConstru.getFeatures():
            geomConstru = construccion.geometry()

            if geomConstru.buffer(-0.0000001, 1).intersects(
                    geomFusion
            ):  #Sacamos las construcciones dentro del predio fusionado
                listaPrimera.append(construccion)
            else:
                if self.contarIntegraciones(
                        geomConstru.buffer(-0.0000001, 1), 'predios.geom'
                ) == 0:  #Obtenemos los aleros del predio fusionado
                    if geomConstru.buffer(
                            0.0000001,
                            1).intersection(geomFusion).area() > 0.000000001:
                        listaPrimera.append(construccion)

        for construccion in listaPrimera:
            geomConstru = construccion.geometry()
            seIncluye = True
            for condominio in capaCondH.getFeatures():
                geomHori = condominio.geometry()
                if geomConstru.buffer(-0.0000001, 1).intersects(geomHori):
                    seIncluye = False
                    break

            if seIncluye:
                listaFinal.append(construccion)

        supConst = 0  #Renombramos ls volumenes
        for construccion in listaFinal:
            geomConstru = construccion.geometry()
            construccion['nom_volumen'] = 'V' + str(cuentaConstruccion)
            niveles = construccion['num_niveles']
            if niveles <= 0:
                niveles = 1
            capaConstru.updateFeature(construccion)
            cuentaConstruccion += 1
            supConst += (geomConstru.area() * niveles)

        capaConstru.commitChanges()
        #----------------------------------------------

        #Estableer atributos del predio fusionado
        idx1 = capaPredios.fields().lookupField('sup_terr')
        idx2 = capaPredios.fields().lookupField('sup_contruccion')
        attr = seleccion[eleccion].attributes()
        attr[idx1] = geomFusion.area()
        attr[idx2] = supConst
        featFusion.setAttributes(attr)
        capaPredios.updateFeature(featFusion)
        capaPredios.dataProvider().addFeatures([featFusion])
        capaPredios.triggerRepaint()
        capaPredios.commitChanges()

        self.UTI.mostrarAlerta('Fusion completada con exito',
                               QMessageBox().Information, 'Fusion de predios')
        self.enFusion = False
        self.dlg.close()

#-----------------------------------------------------------------------------------

#Aqui contmaos cuantas geometrias de una capa toca una geomtrias especifica

    def contarIntegraciones(self, geometria, nombreCapa):
        capa = QgsProject.instance().mapLayersByName(nombreCapa)[0]
        cuenta = 0
        for feat in capa.getFeatures():
            if geometria.intersects(feat.geometry()):
                cuenta += 1

        return cuenta

#---------------------------------------------------------------------------

#Poinemos en lista de eliminados el predio no elegido

    def eliminarNoElegido(self, feat):
        campos = {}
        campos['wkt'] = feat.geometry().asWkt()
        campos['srid'] = 32614

        campos['tabla'] = 'e_predio'
        atributos = {}
        capaPredios = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))
        nombresAtrbutos = capaPredios.fields()

        nombres = [campo.name() for campo in nombresAtrbutos]

        for x in range(0, len(nombres)):
            atributo = feat.attributes()[x]
            if str(feat.attributes()[x]) == "NULL":
                atributo = None
            atributos[str(nombres[x])] = atributo

        campos['attr'] = atributos

        campos['nuevo'] = False
        campos['eliminado'] = True

        listaTemp = QSettings().value('listaEliminada')
        listaTemp.append(campos)

        QSettings().setValue('listaEliminada', listaTemp)

#--------------------------------------------------------------------------

#Activamos el modo de division

    def pasarAModoDivision(self, predio):
        #clave = self.dlg.comboPredios.currentText() #Obtenemos la clave del predio a editar
        clave = predio
        if clave == '':
            self.UTI.mostrarAlerta(
                'Primero debes cargar una manzana de la seccion de consulta',
                QMessageBox().Critical, 'Error de cargado de predio')
            return

        capaPredios = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))
        #capaPredios.setReadOnly(False)
        #capaPredios.startEditing()

        self.predioEnDivision = None

        for predio in capaPredios.getFeatures(
        ):  #Obtenemos el feature a dividr con base en la clave elegida
            if predio.attributes()[0] == clave:
                self.predioEnDivision = predio
                break

        if self.predioEnDivision != None:

            self.atributosAHeredar = self.predioEnDivision.attributes(
            )  #Obtenemos los atributos a heredar
            self.atributosAHeredar[1] = None  #Ponemos le id como vacio

            self.rubberMarca.reset(
                QgsWkbTypes.PolygonGeometry)  #Borramos la geometria amarillita
            self.UTI.mostrarAlerta(
                "Dibuja las lineas de corte sobre el predio indicado.\nRecuerda que los cortes no pueden estar sobre construcciones o condiminios.\nAsegurate que las lineas atraviesen el predio por completo\nNOTA: Las lineas solo afectaran al predio seleccionado.",
                QMessageBox().Information, "Subdivision de predios")
            self.cargoPredio = True
            self.encenderModoDividir()  #Encendemos modo dividir

            # marca de amarillo el poligono del predio a subdividir
            self.geomEnDivision = self.predioEnDivision.geometry()
            self.pintarAreaPredioSubdiv()

            # zoom al predio a subdividir
            geometria = self.geomEnDivision

            bbox = geometria.boundingBox()
            iface.mapCanvas().setExtent(bbox)
            iface.mapCanvas().refresh()

            # comportamiento de botones
            self.dlg.btnFusionar.setEnabled(False)
            self.dlg.btnCancelarSub.setEnabled(True)
            self.dlg.btnCargarPredio.setEnabled(False)
            self.dlg.comboPredios.setEnabled(False)
            self.dlg.comboPredios.setEnabled(False)
            self.dlg.btnConfirmarCortes.setEnabled(True)
            self.dlg.btnDeshacerTodo.setEnabled(True)
            self.dlg.btnDeshacerCortes.setEnabled(True)
            self.dlg.btnLlamarCalcular.setEnabled(True)

            self.enSubdivision = True

        else:
            self.UTI.mostrarAlerta('El predio no fue encontrado',
                                   QMessageBox().Critical,
                                   'Error de cargado de predio')

#-------------------------------------------------------------------------

    def cancelarSubdivision(self):

        mensaje = "El modo de division se apagara, el progreso se perdera\nDeseas continuar?"
        respuesta = QMessageBox.question(iface.mainWindow(),
                                         "Cancelar subdivision", mensaje,
                                         QMessageBox.Yes, QMessageBox.No)

        #Si el usuario acepta....
        if respuesta == QMessageBox.Yes:

            self.vaciarRubbers()
            self.predioEnDivision = None
            self.geomEnDivision = None
            self.modoDividir = False
            self.modoEliminar = False
            self.apagarHerramientas()
            self.dlg.btnCancelarSub.setEnabled(False)
            self.dlg.btnCargarPredio.setEnabled(True)
            self.dlg.comboPredios.setEnabled(True)
            self.dlg.btnFusionar.setEnabled(True)
            self.dlg.btnConfirmarCortes.setEnabled(False)
            self.dlg.btnDeshacerCortes.setEnabled(False)
            self.dlg.btnLlamarCalcular.setEnabled(False)
            self.dlg.btnApagarHerramientas.setEnabled(False)
            self.dlg.btnEliminarCortes.setEnabled(False)
            self.dlg.btnDibujarCortes.setEnabled(False)
            self.dlg.btnEditarCortes.setEnabled(False)
            self.dlg.btnDeshacerTodo.setEnabled(False)

            self.enSubdivision = False
#-----------------------------------------------------------------------------------

#--------------------------------------------

    def confirmarCortes(self):  #Aqui cehcamos que los cortes esten en orden
        print(self.eventos.relaciones)
        #cuentaCortes = 0
        #rango = corte
        rango = len(self.eventos.relaciones) - 1

        #geoTemp = geo
        geoTemp = QgsGeometry.fromWkt(self.geomEnDivision.asWkt())
        print('------------------------------')
        print(geoTemp)
        print('------------------------------')
        cuentaSalida = self.subdividirPredio(
            geoTemp, True
        ) - 1  #Aqui enviamos una geomtria temporal, para ven en cuantos cortes quedara
        print(cuentaSalida)
        if cuentaSalida >= 2:

            listaNoTocar = []
            capaPredios = QgsProject.instance().mapLayer(
                self.ACA.obtenerIdCapa('predios.geom'))
            capaCondH = QgsProject.instance().mapLayersByName(
                'horizontales.geom')[0]
            capaCondV = QgsProject.instance().mapLayersByName('verticales')[0]
            capaConstru = QgsProject.instance().mapLayer(
                self.ACA.obtenerIdCapa('construcciones'))

            #Obtenemos los features que no deben tocarse
            for feat in capaConstru.getFeatures():
                geom = feat.geometry().buffer(-0.0000002, 1)
                if geom.intersects(self.geomEnDivision):
                    listaNoTocar.append(geom)

            for feat in capaCondH.getFeatures():
                geom = feat.geometry().buffer(-0.0000002, 1)
                if geom.intersects(self.geomEnDivision):
                    listaNoTocar.append(geom)

            for feat in capaCondV.getFeatures():
                geom = feat.geometry().buffer(-0.0000002, 1)
                if geom.intersects(self.geomEnDivision):
                    listaNoTocar.append(geom)

            bandera = True

            #Aqui checamos que cada linea no toque lo no tocable
            for i in range(0, rango):
                for comp in listaNoTocar:
                    geom = self.eventos.relaciones[i].geom
                    if geom != None:
                        if geom.buffer(0.0000001, 1).intersects(comp):
                            bandera = False
                            self.eventos.relaciones[i].rubber.setStrokeColor(
                                QColor(255, 0, 0, 255))
                        else:
                            self.eventos.relaciones[i].rubber.setStrokeColor(
                                QColor(0, 61, 240, 255))

            iface.mapCanvas().refresh()
            if bandera:  #Si todo esta en orden
                self.eventos.rubberPunto.reset(QgsWkbTypes.PointGeometry)
                self.apagarHerramientas()
                #mostramos mensaje de confirmacion
                mensaje = "La cantidad de predios que quedaran como resultado, es de: " + str(
                    cuentaSalida) + "\nDeseas continua?"
                respuesta = QMessageBox.question(
                    iface.mainWindow(), "Nota de subdivision de predio",
                    mensaje, QMessageBox.Yes, QMessageBox.No)

                #Si el usuario acepta....
                if respuesta == QMessageBox.Yes:
                    self.subdividirPredio(self.geomEnDivision, False)
                    self.rubberMarca.reset(
                        QgsWkbTypes.PolygonGeometry)  #Quitamos lo amarillito

                    for i in range(0, rango):
                        self.eventos.relaciones[i].rubber.reset(
                            QgsWkbTypes.LineGeometry)
                        self.eventos.relaciones[i].vaciarMarcadores()
                    self.eventos.recargarRelaciones()

                    capaPredios.startEditing()
                    capaPredios.dataProvider().deleteFeatures(
                        [self.predioEnDivision.id()])
                    capaPredios.triggerRepaint()
                    capaPredios.commitChanges()

                    self.VentanaAreas.close()
                    self.limpiarAreas()
                    self.vaciarRubbers()

                    self.UTI.mostrarAlerta(
                        "La division ha sido realizada con exito\nLos cambios se guardaran hasta que asignes las claves.",
                        QMessageBox().Information,
                        "Subdivision completa, Parte 1 de 2")
                    self.irAClaves(
                    )  #Mostramos la ventana que llena las claves
                    iface.actionSelect().trigger()
            else:
                self.UTI.mostrarAlerta(
                    "Las lineas de division no deben atravesar construcciones ni condominios\nLas lineas rojas presentan un corte invalido",
                    QMessageBox().Critical, "Error en subdivision")

        else:
            self.UTI.mostrarAlerta(
                "Primero debes dibujar las lineas de corte\nAsegurate que las lineas atraviesen por completo el predio",
                QMessageBox().Critical, "Error en subdivision")
            #print(cuentaSalida)
##################################################################################

    def vaciarLineasCorte(self):
        rango = len(self.eventos.relaciones) - 1
        for i in range(0, rango):
            self.eventos.relaciones[i].rubber.reset(QgsWkbTypes.LineGeometry)
            self.eventos.relaciones[i].vaciarMarcadores()

        self.eventos.recargarRelaciones()

#-------------------------------------------------------------------------------------

    def subdividirPredio(self, geometria, modoPre):  #Subdividir
        capaHori = QgsProject.instance().mapLayersByName(
            'horizontales.geom')[0]
        capaPredio = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))
        capaVert = QgsProject.instance().mapLayersByName('verticales')[0]

        self.listaNuevosPredios = []
        self.geomsAreas = []
        listaParam = []  #La lista que llega al fileteo
        #rango = corte
        rango = len(self.eventos.relaciones) - 1
        #print('**********************************************')
        #print(self.eventos.relaciones)
        #print(rango)
        #print('**********************************************')
        for i in range(0, rango):

            geom = self.eventos.relaciones[i].geom
            print('-----------------*****------------------------')
            print(self.eventos.relaciones[i])
            print(geom)
            print('-----------------*****------------------------')
            if geom != None:
                listaParam.append(
                    geom.asPolyline())  #Generamos los polyline van a partir

        #print('aaaaaaaaaaa', listaParam)
        salida = self.filetear(
            geometria,
            listaParam)  #Mandamos filetear el poligono con las lineas

        if modoPre:  #Si es modoPre, es solo para visaulizar cuantos poligonos quedarian...

            for cadaUno in salida:
                self.geomsAreas.append(cadaUno)
            return len(salida)
        else:  #Si no, efectuamos realmente el corte
            for cadaUno in salida:

                if cadaUno.isEmpty():
                    continue

                nuevoFeat = QgsFeature()
                nuevoFeat.setGeometry(cadaUno)
                #Agregamos cada predio a la capa y le ponemos sus atributos

                self.asignarAtributos(nuevoFeat)

                capaPredio.startEditing()
                capaPredio.dataProvider().addFeatures([nuevoFeat])
                capaPredio.triggerRepaint()
                capaPredio.commitChanges()

                self.listaNuevosPredios.append(nuevoFeat.geometry().asWkt())

        self.apagarHerramientas()
        self.dlg.btnCargarPredio.setEnabled(True)

##################################################################################

#Metodo para filetear los predios con lineas

    def filetear(self, poligono, lineas):
        listaActuales = []  #Lista de las geometrias en espera de ser cortadas
        listaActuales.append(
            poligono)  #Agregamos el poligono a cortar en la lista de espera
        listaSiguiente = [
            poligono
        ]  #Agregamos le poligono a cortar en la lista de la siguiente interacion

        for linea in lineas:  #Iteramos cada linea de corte

            listaActuales = listaSiguiente  #Igualamos la lista de corte a la iteracion anterior
            listaSiguiente = [
            ]  #Vaciamos la lista que dara lugar a la siguiente iteracion de corte

            for actual in listaActuales:  #Checamos cada geometria en espera

                partida = actual.splitGeometry(
                    linea, True
                )  #Aplicamos el split geometry de qgis, vamos partiendo el poligono
                if len(partida[1]
                       ) == 0:  #Esto ocurre cuando el corte no hizo nada
                    listaSiguiente.append(
                        actual
                    )  #Asi que nos quedamos con la geometria tal cual esta
                else:  #Cuando si hubo corte
                    parte1 = partida[1][
                        0]  #obtenemos la geometria resultante del corte, VER DOCUMENTACION DE SPLITGEOMETRY PARA ENTENDER
                    parte2 = actual.difference(
                        parte1
                    )  #Al poligono que se corto, le quitamos la parte previa al corte anterior
                    #De esta forma nos quedamos con la geometria partida en 2

                    if parte1.area(
                    ) > 0.0:  #Checamos que el area de esta parte sea mayor que 0, por motivos de los decimales
                        listaSiguiente.append(
                            parte1
                        )  #Si es asi, significa un fragmento que puede ser cortado por otra linea

                    if parte2.area() > 0.0:  #Lo mismo
                        listaSiguiente.append(parte2)

        temporal = poligono  #Obtenemos una geometria igualita al poligono entrannte

        for geomSal in listaSiguiente:  #Obtenemos las diferencia respeto a los poligonos obtenidos y el entrante, lo que resulte, tambien es parte del corte
            temporal = temporal.difference(geomSal.buffer(0.0000001, 1))

        listaSiguiente.append(temporal)  #Aqui ponemos todas las geometrias
        return listaSiguiente  #Retornamos la lista

#-------------------------------------------------------------------------

    def encenderModoDividir(self):  #Activamos el modo de dividir

        self.eventos.modoDividir = True
        self.eventos.modoEliminar = False
        self.eventos.modoEditar = False
        self.dlg.btnDibujarCortes.setEnabled(False)
        self.dlg.btnEditarCortes.setEnabled(True)
        self.dlg.btnEliminarCortes.setEnabled(True)
        self.dlg.btnApagarHerramientas.setEnabled(True)
        self.dlg.btnConfirmarCortes.setEnabled(True)
        self.dlg.btnDeshacerTodo.setEnabled(True)
        self.dlg.btnCargarPredio.setEnabled(False)
        #iface.mapCanvas().setCursor(self.DBJ.eventos.cursorRedondo)
        iface.mapCanvas().setCursor(self.UTI.cursorRedondo)
        if not self.eventos.botonAD.isChecked():
            self.eventos.botonAD.trigger()

#----------------------------------------------------------------------------

    def encenderModoEditar(self):  #Activamos el modo de dividir

        self.eventos.modoDividir = False
        self.eventos.modoEliminar = False
        self.eventos.modoEditar = True
        self.dlg.btnDibujarCortes.setEnabled(True)
        self.dlg.btnEditarCortes.setEnabled(False)
        self.dlg.btnEliminarCortes.setEnabled(True)
        self.dlg.btnApagarHerramientas.setEnabled(True)
        self.dlg.btnConfirmarCortes.setEnabled(True)
        self.dlg.btnDeshacerTodo.setEnabled(True)
        self.dlg.btnCargarPredio.setEnabled(False)
        #iface.mapCanvas().setCursor(self.DBJ.eventos.cursorRedondo)
        iface.mapCanvas().setCursor(self.UTI.cursorRedondo)
        if not self.eventos.botonAD.isChecked():
            self.eventos.botonAD.trigger()

#----------------------------------------------------------------------------

    def encenderModoEliminar(self):  #Activamos el modo de eliminar
        self.eventos.modoDividir = False
        self.eventos.modoEliminar = True
        self.eventos.modoEditar = False
        self.dlg.btnDibujarCortes.setEnabled(True)
        self.dlg.btnEditarCortes.setEnabled(True)
        self.dlg.btnEliminarCortes.setEnabled(False)
        self.dlg.btnApagarHerramientas.setEnabled(True)
        self.dlg.btnConfirmarCortes.setEnabled(True)
        self.dlg.btnCargarPredio.setEnabled(False)
        #iface.mapCanvas().setCursor(self.DBJ.eventos.cursorCuadro)
        iface.mapCanvas().setCursor(self.UTI.cursorCuadro)
        if self.eventos.botonAD.isChecked():
            self.eventos.botonAD.trigger()

#----------------------------------------------------------------------------

    def apagarHerramientas(self):  #Apagamos las herramientas
        self.eventos.modoDividir = False
        self.eventos.modoEliminar = False
        self.eventos.modoEditar = False

        self.dlg.btnDibujarCortes.setEnabled(True)
        self.dlg.btnEliminarCortes.setEnabled(True)
        self.dlg.btnEditarCortes.setEnabled(True)
        self.dlg.btnApagarHerramientas.setEnabled(False)
        self.dlg.btnConfirmarCortes.setEnabled(True)
        self.dlg.btnCargarPredio.setEnabled(False)
        #iface.mapCanvas().setCursor(self.DBJ.eventos.cursorCruz)
        iface.mapCanvas().setCursor(self.UTI.cursorCruz)
        if self.eventos.botonAD.isChecked():
            self.eventos.botonAD.trigger()

#-----------------------------------------------------------------

    def rollBack(self):  #Deshacemos cambios

        mensaje = "Todos los cambio se perderan, el area de trabajo se limpiara... deseas continuar?"
        respuesta = QMessageBox.question(iface.mainWindow(),
                                         "Cancelar cambios", mensaje,
                                         QMessageBox.Yes, QMessageBox.No)

        #Si el usuario acepta....
        if respuesta == QMessageBox.Yes:

            self.eventos.modoDividir = False
            self.eventos.modoEliminar = False
            self.dlg.close()
            self.VentanaClaves.dlg.close()
            self.vaciarRubbers()
            self.predioEnDivision = None
            self.geomEnDivision = None
            self.VentanaAreas.close()
            self.UTI.limpiarCanvas()

#------------------------------------------------------------

    def vaciarRubbers(self):
        rango = len(self.eventos.relaciones) - 1
        for i in range(0, rango):
            self.eventos.relaciones[i].rubber.reset(QgsWkbTypes.LineGeometry)
            #self.eventos.relaciones[i].geom = None
            self.eventos.relaciones[i].vaciarMarcadores()

        self.eventos.recargarRelaciones()
        self.rubberMarca.reset(QgsWkbTypes.PolygonGeometry)
        #self.eventos.vaciarMarcadores()

#-----------------------------------------------------------------

    def asignarAtributos(self, feat):  #Asignamos los atributos
        capaPredios = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('predios.geom'))
        campos = capaPredios.fields()
        nombres = [campo.name() for campo in campos]

        listaAsignacion = []

        for nombre in nombres:
            idx = capaPredios.fields().lookupField(nombre)
            if nombre == 'sup_terr':
                attr = feat.geometry().area()
            elif nombre == 'sup_contruccion':
                attr = self.calcularSupConst(feat)
            elif nombre == 'clave':
                attr = ''
            elif nombre == 'cve_cat':
                attr = ''
            elif nombre == 'id':
                attr = ''
            elif nombre == 'cve_usuario':
                attr = self.UTI.decodeRot13(QSettings().value('usuario'))
            else:
                attr = self.predioEnDivision.attributes()[idx]
            listaAsignacion.append(attr)

        capaPredios.startEditing()
        feat.setAttributes(listaAsignacion)
        capaPredios.triggerRepaint()
        capaPredios.commitChanges()

#------------------------------------------------------------

    def calcularSupConst(self, feat):  #calculamos superficie de construccion

        capaConstru = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('construcciones'))
        capaCondH = QgsProject.instance().mapLayer(
            self.ACA.obtenerIdCapa('horizontales.geom'))

        listaFinal = []
        listaPrimera = []

        #Renombrar construcciones
        cuentaConstruccion = 1
        capaConstru.startEditing()
        geomFeat = feat.geometry()

        #--------Renombrar construcciones----
        for construccion in capaConstru.getFeatures():
            geomConstru = construccion.geometry()

            if geomConstru.buffer(-0.0000001, 1).intersects(
                    geomFeat
            ):  #Sacamos las construcciones dentro del predio fusionado
                listaPrimera.append(construccion)
            else:
                if self.contarIntegraciones(
                        geomConstru.buffer(-0.0000001, 1), 'predios.geom'
                ) == 0:  #Obtenemos los aleros del predio fusionado
                    if geomConstru.buffer(
                            0.0000001,
                            1).intersection(geomFeat).area() > 0.000000001:
                        listaPrimera.append(construccion)

        for construccion in listaPrimera:
            geomConstru = construccion.geometry()
            seIncluye = True
            for condominio in capaCondH.getFeatures():
                geomHori = condominio.geometry()
                if geomConstru.buffer(-0.0000001, 1).intersects(geomHori):
                    seIncluye = False
                    break

            if seIncluye:
                listaFinal.append(construccion)

        supConst = 0  #Renombramos ls volumenes
        for construccion in listaFinal:
            geomConstru = construccion.geometry()
            construccion['nom_volumen'] = 'V' + str(cuentaConstruccion)
            niveles = construccion['num_niveles']
            if niveles <= 0:
                niveles = 1
            capaConstru.updateFeature(construccion)
            cuentaConstruccion += 1
            supConst += (geomConstru.area() * niveles)

        capaConstru.triggerRepaint()
        capaConstru.commitChanges()

        return supConst

#--------------------------------------------------------------------------------------------------

    def irAClaves(self):  #Pintamos la ventanita de asignar clavees
        self.VentanaClaves.predioOriginal = self.predioEnDivision
        self.VentanaClaves.obtieneCapaPredios()
        self.VentanaClaves.dlg.show()

        self.dlg.btnDibujarCortes.setEnabled(False)
        self.dlg.btnEditarCortes.setEnabled(False)
        self.dlg.btnEliminarCortes.setEnabled(False)
        self.dlg.btnApagarHerramientas.setEnabled(False)
        self.dlg.btnConfirmarCortes.setEnabled(False)
        self.dlg.btnCargarPredio.setEnabled(False)
        self.dlg.btnDeshacerCortes.setEnabled(False)
        self.dlg.btnLlamarCalcular.setEnabled(False)
        self.dlg.btnCancelarSub.setEnabled(False)
        self.dlg.comboPredios.setEnabled(False)
        self.enClaves = True

#-------------------------------------------------------------------------

    def irAreas(self):

        self.limpiarAreas()
        self.rubberMarca.reset(QgsWkbTypes.PolygonGeometry)
        geoTemp = QgsGeometry.fromWkt(self.geomEnDivision.asWkt())

        self.subdividirPredio(geoTemp, True)
        self.listaColores = []
        for geom in self.geomsAreas:
            if geom.area() <= 0:
                continue
            newRub = self.eventos.crearNuevoRubberPoly()

            # obtener una lista de vertices del tipo QgsPointXY
            listaVertices = self.UTI.obtenerVerticesPoligono(geom)

            listaVertices.append(listaVertices[0])
            rangoVertices = len(listaVertices)
            for x in range(0, rangoVertices - 2):
                newRub.addPoint(listaVertices[x], True)

            newRub.show()
            self.rubbersAreas.append(newRub)

        self.VentanaAreas.mostrarAreas()

#--------------------------------------------------------------------

    def limpiarAreas(self):
        for rub in self.rubbersAreas:
            rub.reset(QgsWkbTypes.PolygonGeometry)

        self.rubbersAreas = []

#------------------------------------------------------------------

    def quitarAreas(self):
        self.limpiarAreas()

        n = 0  #Obtenemos todos los vertices de la geometria en division
        if self.geomEnDivision == None:
            return

        self.pintarAreaPredioSubdiv()
        '''
        ver = self.geomEnDivision.vertexAt(0)
        listaVertices = []
        while(ver != QgsPoint(0,0)):
            n +=1
            ver=self.geomEnDivision.vertexAt(n)
            listaVertices.append(ver)


        listaVertices.append(listaVertices[0])
        rangoVertices = len(listaVertices)
        for x in range(0, rangoVertices-2):
            vertice = listaVertices[x]
            self.rubberMarca.addPoint(QgsPointXY(vertice.x(), vertice.y()), True)
        self.rubberMarca.show() #Aqui pintamos de amarillito la geometria en division
        '''

#--------------------------------------------------------------------------

    def pintarAreaPredioSubdiv(self, geom=None):

        if geom is None:
            geom = self.geomEnDivision

        polygon = geom.asPolygon()
        listaVertices = []

        n = len(polygon[0])

        for i in range(n):
            listaVertices.append(polygon[0][i])

        listaVertices.append(listaVertices[0])
        rangoVertices = len(listaVertices)
        for x in range(0, rangoVertices - 2):
            self.rubberMarca.addPoint(listaVertices[x], True)
        self.rubberMarca.show(
        )  #Aqui pintamos de amarillito la geometria en division

    def consumeWSGeneral(self, url_cons=""):

        url = url_cons
        data = ""

        try:
            self.headers['Authorization'] = self.UTI.obtenerToken()
            response = requests.get(url, headers=self.headers)
        except requests.exceptions.RequestException as e:
            self.createAlert(
                "Error de servidor--, 'consumeWSGeneral()' '" + str(e) + "'",
                QMessageBox().Critical, "Error de servidor")
            return

        if response.status_code == 200:
            data = response.content

        elif response.status_code == 403:
            self.createAlert('Sin Permisos para ejecutar la acción',
                             QMessageBox().Critical, "Usuarios")
            return None

        else:
            self.createAlert(
                'Error en peticion "consumeWSGeneral()":\n' + response.text,
                QMessageBox().Critical, "Error de servidor")
            return

        return json.loads(data)

    def createAlert(self,
                    mensaje,
                    icono=QMessageBox().Critical,
                    titulo='Operaciones'):
        #Create QMessageBox
        self.msg = QMessageBox()
        #Add message
        self.msg.setText(mensaje)
        #Add icon of critical error
        self.msg.setIcon(icono)
        #Add tittle
        self.msg.setWindowTitle(titulo)
        #Show of message dialog
        self.msg.show()
        # Run the dialog event loop
        result = self.msg.exec_()
class InstantPrintTool(QgsMapTool, InstantPrintDialog):
    def __init__(self, iface, populateCompositionFz=None):
        QgsMapTool.__init__(self, iface.mapCanvas())

        self.iface = iface
        projectInstance = QgsProject.instance()
        self.projectLayoutManager = projectInstance.layoutManager()
        self.rubberband = None
        self.oldrubberband = None
        self.pressPos = None
        self.printer = QPrinter()
        self.mapitem = None
        self.populateCompositionFz = populateCompositionFz

        self.dialog = InstantPrintDialog(self.iface.mainWindow())
        self.dialogui = Ui_InstantPrintDialog()
        self.dialogui.setupUi(self.dialog)
        self.dialogui.addScale.setIcon(
            QIcon(":/images/themes/default/mActionAdd.svg"))
        self.dialogui.deleteScale.setIcon(
            QIcon(":/images/themes/default/symbologyRemove.svg"))
        self.dialog.hidden.connect(self.__onDialogHidden)
        self.exportButton = self.dialogui.buttonBox.addButton(
            self.tr("Export"), QDialogButtonBox.ActionRole)
        self.printButton = self.dialogui.buttonBox.addButton(
            self.tr("Print"), QDialogButtonBox.ActionRole)
        self.helpButton = self.dialogui.buttonBox.addButton(
            self.tr("Help"), QDialogButtonBox.HelpRole)
        self.dialogui.comboBox_fileformat.addItem(
            "PDF", self.tr("PDF Document (*.pdf);;"))
        self.dialogui.comboBox_fileformat.addItem(
            "JPG", self.tr("JPG Image (*.jpg);;"))
        self.dialogui.comboBox_fileformat.addItem(
            "BMP", self.tr("BMP Image (*.bmp);;"))
        self.dialogui.comboBox_fileformat.addItem(
            "PNG", self.tr("PNG Image (*.png);;"))
        self.iface.layoutDesignerOpened.connect(
            lambda view: self.__reloadLayouts())
        self.iface.layoutDesignerWillBeClosed.connect(self.__reloadLayouts)
        self.dialogui.comboBox_layouts.currentIndexChanged.connect(
            self.__selectLayout)
        self.dialogui.comboBox_scale.lineEdit().textChanged.connect(
            self.__changeScale)
        self.dialogui.comboBox_scale.scaleChanged.connect(self.__changeScale)
        self.exportButton.clicked.connect(self.__export)
        self.printButton.clicked.connect(self.__print)
        self.helpButton.clicked.connect(self.__help)
        self.dialogui.buttonBox.button(
            QDialogButtonBox.Close).clicked.connect(lambda: self.dialog.hide())
        self.dialogui.addScale.clicked.connect(self.add_new_scale)
        self.dialogui.deleteScale.clicked.connect(self.remove_scale)
        self.deactivated.connect(self.__cleanup)
        self.setCursor(Qt.OpenHandCursor)

        settings = QSettings()
        if settings.value("instantprint/geometry") is not None:
            self.dialog.restoreGeometry(
                settings.value("instantprint/geometry"))
        if settings.value("instantprint/scales") is not None:
            for scale in settings.value("instantprint/scales").split(";"):
                if scale:
                    self.retrieve_scales(scale)
        self.check_scales()

    def __onDialogHidden(self):
        self.setEnabled(False)
        self.iface.mapCanvas().unsetMapTool(self)
        QSettings().setValue("instantprint/geometry",
                             self.dialog.saveGeometry())
        list = []
        for i in range(self.dialogui.comboBox_scale.count()):
            list.append(self.dialogui.comboBox_scale.itemText(i))
        QSettings().setValue("instantprint/scales", ";".join(list))

    def retrieve_scales(self, checkScale):
        if self.dialogui.comboBox_scale.findText(checkScale) == -1:
            self.dialogui.comboBox_scale.addItem(checkScale)

    def add_new_scale(self):
        new_layout = self.dialogui.comboBox_scale.currentText()
        if self.dialogui.comboBox_scale.findText(new_layout) == -1:
            self.dialogui.comboBox_scale.addItem(new_layout)
        self.check_scales()

    def remove_scale(self):
        layout_to_delete = self.dialogui.comboBox_scale.currentIndex()
        self.dialogui.comboBox_scale.removeItem(layout_to_delete)
        self.check_scales()

    def setEnabled(self, enabled):
        if enabled:
            self.dialog.setVisible(True)
            self.__reloadLayouts()
            self.iface.mapCanvas().setMapTool(self)
        else:
            self.dialog.setVisible(False)
            self.iface.mapCanvas().unsetMapTool(self)

    def __changeScale(self):
        if not self.mapitem:
            return
        newscale = self.dialogui.comboBox_scale.scale()
        if abs(newscale) < 1E-6:
            return
        extent = self.mapitem.extent()
        center = extent.center()
        newwidth = extent.width() / self.mapitem.scale() * newscale
        newheight = extent.height() / self.mapitem.scale() * newscale
        x1 = center.x() - 0.5 * newwidth
        y1 = center.y() - 0.5 * newheight
        x2 = center.x() + 0.5 * newwidth
        y2 = center.y() + 0.5 * newheight
        self.mapitem.setExtent(QgsRectangle(x1, y1, x2, y2))
        self.__createRubberBand()
        self.check_scales()

    def __selectLayout(self):
        if not self.dialog.isVisible():
            return
        activeIndex = self.dialogui.comboBox_layouts.currentIndex()
        if activeIndex < 0:
            return

        layoutView = self.dialogui.comboBox_layouts.itemData(activeIndex)
        maps = []
        layout_name = self.dialogui.comboBox_layouts.currentText()
        layout = self.projectLayoutManager.layoutByName(layout_name)
        for item in layoutView.items():
            if isinstance(item, QgsLayoutItemMap):
                maps.append(item)
        if len(maps) != 1:
            QMessageBox.warning(
                self.iface.mainWindow(), self.tr("Invalid layout"),
                self.tr("The layout must have exactly one map item."))
            self.exportButton.setEnabled(False)
            self.iface.mapCanvas().scene().removeItem(self.rubberband)
            self.rubberband = None
            self.dialogui.comboBox_scale.setEnabled(False)
            return

        self.dialogui.comboBox_scale.setEnabled(True)
        self.exportButton.setEnabled(True)

        self.layoutView = layoutView
        self.mapitem = layout.referenceMap()
        self.dialogui.comboBox_scale.setScale(self.mapitem.scale())
        self.__createRubberBand()

    def __createRubberBand(self):
        self.__cleanup()
        extent = self.mapitem.extent()
        center = self.iface.mapCanvas().extent().center()
        self.corner = QPointF(center.x() - 0.5 * extent.width(),
                              center.y() - 0.5 * extent.height())
        self.rect = QRectF(self.corner.x(), self.corner.y(), extent.width(),
                           extent.height())
        self.mapitem.setExtent(QgsRectangle(self.rect))
        self.rubberband = QgsRubberBand(self.iface.mapCanvas(),
                                        QgsWkbTypes.PolygonGeometry)
        self.rubberband.setToCanvasRectangle(self.__canvasRect(self.rect))
        self.rubberband.setColor(QColor(127, 127, 255, 127))

        self.pressPos = None

    def __cleanup(self):
        if self.rubberband:
            self.iface.mapCanvas().scene().removeItem(self.rubberband)
        if self.oldrubberband:
            self.iface.mapCanvas().scene().removeItem(self.oldrubberband)
        self.rubberband = None
        self.oldrubberband = None
        self.pressPos = None

    def canvasPressEvent(self, e):
        if not self.rubberband:
            return
        r = self.__canvasRect(self.rect)
        if e.button() == Qt.LeftButton and self.__canvasRect(
                self.rect).contains(e.pos()):
            self.oldrect = QRectF(self.rect)
            self.oldrubberband = QgsRubberBand(self.iface.mapCanvas(),
                                               QgsWkbTypes.PolygonGeometry)
            self.oldrubberband.setToCanvasRectangle(
                self.__canvasRect(self.oldrect))
            self.oldrubberband.setColor(QColor(127, 127, 255, 31))
            self.pressPos = (e.x(), e.y())
            self.iface.mapCanvas().setCursor(Qt.ClosedHandCursor)

    def canvasMoveEvent(self, e):
        if not self.pressPos:
            return
        mup = self.iface.mapCanvas().mapSettings().mapUnitsPerPixel()
        x = self.corner.x() + (e.x() - self.pressPos[0]) * mup
        y = self.corner.y() + (self.pressPos[1] - e.y()) * mup

        snaptol = 10 * mup
        # Left edge matches with old right
        if abs(x - (self.oldrect.x() + self.oldrect.width())) < snaptol:
            x = self.oldrect.x() + self.oldrect.width()
        # Right edge matches with old left
        elif abs(x + self.rect.width() - self.oldrect.x()) < snaptol:
            x = self.oldrect.x() - self.rect.width()
        # Left edge matches with old left
        elif abs(x - self.oldrect.x()) < snaptol:
            x = self.oldrect.x()
        # Bottom edge matches with old top
        if abs(y - (self.oldrect.y() + self.oldrect.height())) < snaptol:
            y = self.oldrect.y() + self.oldrect.height()
        # Top edge matches with old bottom
        elif abs(y + self.rect.height() - self.oldrect.y()) < snaptol:
            y = self.oldrect.y() - self.rect.height()
        # Bottom edge matches with old bottom
        elif abs(y - self.oldrect.y()) < snaptol:
            y = self.oldrect.y()

        self.rect = QRectF(x, y, self.rect.width(), self.rect.height())
        self.rubberband.setToCanvasRectangle(self.__canvasRect(self.rect))

    def canvasReleaseEvent(self, e):
        if e.button() == Qt.LeftButton and self.pressPos:
            self.corner = QPointF(self.rect.x(), self.rect.y())
            self.pressPos = None
            self.iface.mapCanvas().setCursor(Qt.OpenHandCursor)
            self.iface.mapCanvas().scene().removeItem(self.oldrubberband)
            self.oldrect = None
            self.oldrubberband = None
            self.mapitem.setExtent(QgsRectangle(self.rect))

    def __canvasRect(self, rect):
        mtp = self.iface.mapCanvas().mapSettings().mapToPixel()
        p1 = mtp.transform(QgsPoint(rect.left(), rect.top()))
        p2 = mtp.transform(QgsPoint(rect.right(), rect.bottom()))
        return QRect(p1.x(), p1.y(), p2.x() - p1.x(), p2.y() - p1.y())

    def __export(self):
        settings = QSettings()
        format = self.dialogui.comboBox_fileformat.itemData(
            self.dialogui.comboBox_fileformat.currentIndex())
        filepath = QFileDialog.getSaveFileName(
            self.iface.mainWindow(), self.tr("Export Layout"),
            settings.value("/instantprint/lastfile", ""), format)
        if not all(filepath):
            return

        # Ensure output filename has correct extension
        filename = os.path.splitext(
            filepath[0]
        )[0] + "." + self.dialogui.comboBox_fileformat.currentText().lower()
        settings.setValue("/instantprint/lastfile", filepath[0])

        if self.populateCompositionFz:
            self.populateCompositionFz(self.layoutView.composition())

        success = False
        layout_name = self.dialogui.comboBox_layouts.currentText()
        layout_item = self.projectLayoutManager.layoutByName(layout_name)
        exporter = QgsLayoutExporter(layout_item)
        if filename[-3:].lower() == u"pdf":
            success = exporter.exportToPdf(
                filepath[0], QgsLayoutExporter.PdfExportSettings())
        else:
            success = exporter.exportToImage(
                filepath[0], QgsLayoutExporter.ImageExportSettings())
        if success != 0:
            QMessageBox.warning(self.iface.mainWindow(),
                                self.tr("Export Failed"),
                                self.tr("Failed to export the layout."))

    def __print(self):
        layout_name = self.dialogui.comboBox_layouts.currentText()
        layout_item = self.projectLayoutManager.layoutByName(layout_name)
        actual_printer = QgsLayoutExporter(layout_item)

        printdialog = QPrintDialog(self.printer)
        if printdialog.exec_() != QDialog.Accepted:
            return

        success = actual_printer.print(self.printer,
                                       QgsLayoutExporter.PrintExportSettings())

        if success != 0:
            QMessageBox.warning(self.iface.mainWindow(),
                                self.tr("Print Failed"),
                                self.tr("Failed to print the layout."))

    def __reloadLayouts(self, removed=None):
        if not self.dialog.isVisible():
            # Make it less likely to hit the issue outlined in https://github.com/qgis/QGIS/pull/1938
            return

        self.dialogui.comboBox_layouts.blockSignals(True)
        prev = None
        if self.dialogui.comboBox_layouts.currentIndex() >= 0:
            prev = self.dialogui.comboBox_layouts.currentText()
        self.dialogui.comboBox_layouts.clear()
        active = 0
        for layout in self.projectLayoutManager.layouts():
            if layout != removed and layout.name():
                cur = layout.name()
                self.dialogui.comboBox_layouts.addItem(cur, layout)
                if prev == cur:
                    active = self.dialogui.comboBox_layouts.count() - 1
        self.dialogui.comboBox_layouts.setCurrentIndex(
            -1)  # Ensure setCurrentIndex below actually changes an index
        self.dialogui.comboBox_layouts.blockSignals(False)
        if self.dialogui.comboBox_layouts.count() > 0:
            self.dialogui.comboBox_layouts.setCurrentIndex(active)
            self.dialogui.comboBox_scale.setEnabled(True)
            self.exportButton.setEnabled(True)
        else:
            self.exportButton.setEnabled(False)
            self.dialogui.comboBox_scale.setEnabled(False)

    def __help(self):
        manualPath = os.path.join(os.path.dirname(__file__), "help",
                                  "documentation.pdf")
        QDesktopServices.openUrl(QUrl.fromLocalFile(manualPath))

    def scaleFromString(self, scaleText):
        locale = QLocale()
        parts = [locale.toInt(part) for part in scaleText.split(":")]
        try:
            if len(parts) == 2 and parts[0][1] and parts[1][
                    1] and parts[0][0] != 0 and parts[1][0] != 0:
                return float(parts[0][0]) / float(parts[1][0])
            else:
                return None
        except ZeroDivisionError:
            return

    def check_scales(self):
        predefScalesStr = QSettings().value("Map/scales",
                                            PROJECT_SCALES).split(",")
        predefScales = [
            self.scaleFromString(scaleString)
            for scaleString in predefScalesStr
        ]

        comboScalesStr = [
            self.dialogui.comboBox_scale.itemText(i)
            for i in range(self.dialogui.comboBox_scale.count())
        ]
        comboScales = [
            self.scaleFromString(scaleString) for scaleString in comboScalesStr
        ]

        currentScale = self.scaleFromString(
            self.dialogui.comboBox_scale.currentText())

        if not currentScale:
            self.dialogui.comboBox_scale.lineEdit().setStyleSheet(
                "background: #FF7777; color: #FFFFFF;")
            self.dialogui.addScale.setVisible(True)
            self.dialogui.addScale.setEnabled(False)
            self.dialogui.deleteScale.setVisible(False)
        else:
            self.dialogui.comboBox_scale.lineEdit().setStyleSheet("")
            if currentScale in comboScales:
                # If entry scale is already in the list, allow removing it unless it is a predefined scale
                self.dialogui.addScale.setVisible(False)
                self.dialogui.deleteScale.setVisible(True)
                self.dialogui.deleteScale.setEnabled(
                    currentScale not in predefScales)
            else:
                # Otherwise, show button to add it
                self.dialogui.addScale.setVisible(True)
                self.dialogui.addScale.setEnabled(True)
                self.dialogui.deleteScale.setVisible(False)
    def __init__(self, iface, ACA):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        self.CFG = None
        self.UTI = None
        self.DFS = None
        self.DBJ = None
        self.ELM = None
        self.ACA = ACA
        self.TPG = None
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir, 'i18n',
                                   'DivisionFusion_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        # Create the dialog (after translation) and keep reference
        self.dlg = DivisionFusionDialog(parent=iface.mainWindow(), DIV=self)

        # Declare instance attributes
        '''
        self.actions = []
        self.menu = self.tr(u'&DivisionFusion')
        # TODO: We are going to let the user set this up in a future iteration
        self.toolbar = self.iface.addToolBar(u'DivisionFusion')
        self.toolbar.setObjectName(u'DivisionFusion')
        '''
        self.eventos = EventoDivision(iface.mapCanvas(), self,
                                      iface.cadDockWidget())
        iface.mapCanvas().setMapTool(self.eventos)
        self.VentanaAreas = VentanaAreas(self)

        self.VentanaFusion = VentanaFusionV3(iface, self)
        self.VentanaClaves = VentanaClavesV3(iface, self)
        self.rubberMarca = QgsRubberBand(iface.mapCanvas(),
                                         QgsWkbTypes.PolygonGeometry)
        self.rubberMarca.setFillColor(QColor(255, 255, 0, 12))
        self.rubberMarca.setStrokeColor(QColor(255, 150, 0, 255))
        self.rubberMarca.setWidth(2)
        self.listaNuevosPredios = []
        self.cargoPredio = False
        self.listaColores = []
        self.rubbersAreas = []

        self.dlg.btnDibujarCortes.setEnabled(False)
        self.dlg.btnEditarCortes.setEnabled(False)
        self.dlg.btnEliminarCortes.setEnabled(False)
        self.dlg.btnApagarHerramientas.setEnabled(False)
        self.dlg.btnConfirmarCortes.setEnabled(False)
        self.dlg.btnDeshacerTodo.setEnabled(False)
        self.dlg.btnCancelarSub.setEnabled(False)
        self.dlg.btnDeshacerCortes.setEnabled(False)
        self.dlg.btnLlamarCalcular.setEnabled(False)

        self.dlg.btnFusionar.clicked.connect(self.preguntarFusion)
        self.dlg.btnCargarPredio.clicked.connect(self.pasarAModoDivision)
        self.dlg.btnConfirmarCortes.clicked.connect(self.confirmarCortes)
        self.dlg.btnDibujarCortes.clicked.connect(self.encenderModoDividir)
        self.dlg.btnEliminarCortes.clicked.connect(self.encenderModoEliminar)
        self.dlg.btnApagarHerramientas.clicked.connect(self.apagarHerramientas)
        self.dlg.btnDeshacerTodo.clicked.connect(self.rollBack)
        self.dlg.btnCancelarSub.clicked.connect(self.cancelarSubdivision)
        self.dlg.btnDeshacerCortes.clicked.connect(self.vaciarLineasCorte)
        self.dlg.btnLlamarCalcular.clicked.connect(self.irAreas)
        self.dlg.btnEditarCortes.clicked.connect(self.encenderModoEditar)

        self.dlg.btnDeshacerTodo.hide()
        self.enClaves = False
        self.enSubdivision = False
        self.enFusion = False

        self.headers = {'Content-Type': 'application/json'}
        self.geomsAreas = []
Beispiel #49
0
class RectangleMapTool(QgsMapToolEmitPoint):

  def __init__(self, canvas):
    QgsMapToolEmitPoint.__init__(self, canvas)

    self.canvas = canvas
    self.rubberBand = QgsRubberBand(canvas, QgsWkbTypes.PolygonGeometry)
    self.rubberBand.setColor(QColor(255, 0, 0, 180))
    self.rubberBand.setWidth(1)
    self.reset()

  def reset(self):
    self.startPoint = self.endPoint = None
    self.isDrawing = False
    self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)

  def canvasPressEvent(self, e):
    self.startPoint = self.toMapCoordinates(e.pos())
    self.endPoint = self.startPoint

    mapSettings = self.canvas.mapSettings()
    self.mupp = mapSettings.mapUnitsPerPixel()
    self.rotation = mapSettings.rotation()

    self.isDrawing = True
    self.showRect(self.startPoint, self.endPoint)

  def canvasReleaseEvent(self, e):
    self.isDrawing = False
    self.emit(SIGNAL("rectangleCreated()"))   #TODO: new style signal

  def canvasMoveEvent(self, e):
    if not self.isDrawing:
      return
    self.endPoint = self.toMapCoordinates(e.pos())
    self.showRect(self.startPoint, self.endPoint)

  def showRect(self, startPoint, endPoint):
    self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
    if startPoint.x() == endPoint.x() and startPoint.y() == endPoint.y():
      return

    for i, pt in enumerate(self._rect(startPoint, endPoint).vertices()):
      self.rubberBand.addPoint(pt, bool(i == 3))
    self.rubberBand.show()

  def _rect(self, startPoint, endPoint):
    if startPoint is None or endPoint is None:
      return None

    p0 = self.toCanvasCoordinates(startPoint)
    p1 = self.toCanvasCoordinates(endPoint)
    canvas_rect = QgsRectangle(QgsPoint(p0.x(), p0.y()), QgsPoint(p1.x(), p1.y()))
    center = QgsPoint((startPoint.x() + endPoint.x()) / 2, (startPoint.y() + endPoint.y()) / 2)
    return RotatedRect(center, self.mupp * canvas_rect.width(), self.mupp * canvas_rect.height()).rotate(self.rotation, center)

  def rectangle(self):
    return self._rect(self.startPoint, self.endPoint)

  def setRectangle(self, rect):
    if rect == self._rect(self.startPoint, self.endPoint):
      return False

    v = rect.vertices()
    self.startPoint = v[3]
    self.endPoint = v[1]
    self.showRect(self.startPoint, self.endPoint)
    return True
Beispiel #50
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
Beispiel #51
0
class GeomFilterEPSG():
    def __init__(self, iface):
        self.iface = iface

    def initGui(self):

        # cria uma ação que iniciará a configuração do plugin
        #self.myMapTool = QgsMapToolEmitPoint( self.iface.mapCanvas() )
        self.initVariables()
        self.initSignals()

    def initVariables(self):
        self.coordinates = []

        # Criação da action e da toolbar
        self.toolbar = self.iface.addToolBar("My_ToolBar")
        pai = self.iface.mainWindow()
        icon_path = ':/plugins/GeomFilterEPSG/icon.png'
        self.action = QAction(QIcon(icon_path), u"Filtro EPSG.", pai)
        self.action.setObjectName("Filtro EPSG.")
        self.action.setStatusTip(None)
        self.action.setWhatsThis(None)
        self.action.setCheckable(True)
        self.toolbar.addAction(self.action)

        self.previousMapTool = self.iface.mapCanvas().mapTool()
        self.myMapTool = QgsMapToolEmitPoint(self.iface.mapCanvas())
        self.isEditing = 0

    def initSignals(self):
        self.action.toggled.connect(self.RubberBand)
        self.myMapTool.canvasClicked.connect(self.mouseClick)

    def RubberBand(self, bolean):
        if bolean:
            self.myRubberBand = QgsRubberBand(self.iface.mapCanvas(),
                                              QGis.Polygon)
            color = QColor(78, 97, 114)
            color.setAlpha(190)
            self.myRubberBand.setColor(color)
            self.myRubberBand.setFillColor(QColor(255, 0, 0, 40))
            self.myRubberBand.setBorderColor(QColor(255, 0, 0, 200))

            # Set MapTool
            self.iface.mapCanvas().setMapTool(self.myMapTool)
            self.iface.mapCanvas().xyCoordinates.connect(self.mouseMove)
        else:
            self.disconnect()

    def disconnect(self):

        self.iface.mapCanvas().unsetMapTool(self.myMapTool)
        try:
            self.iface.mapCanvas().xyCoordinates.disconnect(self.mouseMove)
        except:
            pass

        try:
            self.myRubberBand.reset()
        except:
            pass

    def unChecked(self):
        self.action.setCheckable(False)
        self.action.setCheckable(True)

    def unload(self):
        self.disconnect()

    def mouseClick(self, currentPos, clickedButton):
        if clickedButton == Qt.LeftButton:  # and myRubberBand.numberOfVertices() == 0:
            self.myRubberBand.addPoint(QgsPoint(currentPos))
            self.coordinates.append(QgsPoint(currentPos))
            self.isEditing = 1

        elif clickedButton == Qt.RightButton and self.myRubberBand.numberOfVertices(
        ) > 2:
            self.isEditing = 0

            # create feature and set geometry.

            poly = QgsFeature()
            geomP = self.myRubberBand.asGeometry()
            poly.setGeometry(geomP)
            g = geomP.exportToWkt()  # Get WKT coordenates.
            #print g
            canvas = self.iface.mapCanvas()
            c = canvas.mapRenderer().destinationCrs().authid()  # Get EPSG.
            rep = c.replace("EPSG:", "")
            string = U"st_intersects(geom,st_geomfromewkt('SRID=" + rep + ";" + g + "'))"

            self.layers = self.iface.mapCanvas().layers()

            for layer in self.layers:
                layer.setSubsetString(string)

            self.myRubberBand.reset(QGis.Polygon)
            self.disconnect()
            self.unChecked()

    def mouseMove(self, currentPos):
        if self.isEditing == 1:
            self.myRubberBand.movePoint(QgsPoint(currentPos))
Beispiel #52
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.mapRenderer().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})))
class MeasureTool(QgsMapTool):
    '''
    classdocs
    '''


    def __init__(self, canvas, txtBearing, disType = DistanceUnits.M):
        '''
        Constructor
        '''
        self.canvas = canvas
        self.txtBearing = txtBearing
        QgsMapTool.__init__(self, self.canvas)
        self.mSnapper = QgsMapCanvasSnapper(self.canvas)
        self.rubberBand = QgsRubberBand(self.canvas,QGis.Line)
        self.rubberBand.setColor(Qt.red)
        self.rubberBand.setWidth(1)
        self.rubberBandPt = QgsRubberBand(canvas, QGis.Point)
        self.rubberBandPt.setColor(Qt.red)
        self.rubberBandPt.setWidth(10)
        self.type = disType
        self.reset()
    def reset(self):
        self.startPoint = None
        self.endPoint = None
        self.isDrawing = False
        self.distance = 0.0
    def canvasReleaseEvent(self, e):
        if ( e.button() == Qt.RightButton ):  
            self.reset()
            self.emit(SIGNAL("captureFinished"))
        else:
            self.rubberBandPt.reset(QGis.Point)
            snapPoint = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas, True)            
            if self.startPoint == None:
                self.rubberBand.reset(QGis.Line)
                if snapPoint == None:
                    self.startPoint = self.toMapCoordinates(e.pos())
                else:
                    self.startPoint = snapPoint
                self.rubberBand.addPoint(self.startPoint)
                self.isDrawing = True
            else:
                if snapPoint == None:
                    self.endPoint = self.toMapCoordinates(e.pos())
                else:
                    self.endPoint = snapPoint
                self.rubberBand.addPoint(self.endPoint)
                dist = MathHelper.calcDistance(self.startPoint, self.endPoint)
                    
                self.distance = self.distance + dist
                if self.type == DistanceUnits.M:
                    self.txtBearing.setText("%f"%round(self.distance, 4))
                elif self.type == DistanceUnits.NM:
                    self.txtBearing.setText("%f"%round(Unit.ConvertMeterToNM(self.distance), 4))
                elif self.type == DistanceUnits.FT:
                    self.txtBearing.setText("%f"%round(Unit.ConvertMeterToFeet(self.distance), 4))
                elif self.type == DistanceUnits.KM:
                    self.txtBearing.setText("%f"%round((self.distance / 1000), 4))
                elif self.type == DistanceUnits.MM:
                    self.txtBearing.setText(str(int(self.distance * 1000)))
                self.startPoint = self.endPoint
    def canvasMoveEvent(self, e):
        self.rubberBandPt.reset(QGis.Point)
        snapPoint = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas, True)
        if snapPoint != None:
            self.rubberBandPt.addPoint(snapPoint)
            self.rubberBandPt.show()
        if self.isDrawing:
            if self.isDrawing:
                if snapPoint == None:
                    self.endPoint = self.toMapCoordinates(e.pos())
                else:
                    self.endPoint = snapPoint
            self.rubberBand.movePoint(self.endPoint)
            dist1 = MathHelper.calcDistance(self.startPoint, self.endPoint)
            dist1 = self.distance + dist1    
            if self.type == DistanceUnits.M:
                self.txtBearing.setText("%f"%round(dist1, 4))
            elif self.type == DistanceUnits.NM:
                self.txtBearing.setText("%f"%round(Unit.ConvertMeterToNM(dist1), 4))
            elif self.type == DistanceUnits.FT:
                self.txtBearing.setText("%f"%round(Unit.ConvertMeterToFeet(dist1), 4))
            elif self.type == DistanceUnits.KM:
                self.txtBearing.setText("%f"%round((dist1 / 1000), 4))
            elif self.type == DistanceUnits.MM:
                self.txtBearing.setText(str(int(dist1 * 1000)))
    def deactivate(self):
        self.rubberBandPt.reset(QGis.Point)
        QgsMapTool.deactivate(self)
        self.emit(SIGNAL("deactivated()"))
Beispiel #54
0
    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()
Beispiel #55
0
class PolygonMapTool(QgsMapToolEmitPoint):
    """This class holds a map tool to create a polygon from points got by clicking
        on the map window. Points are stored in a list of point geometries, which is returned to
        the main plugin for use."""
    def __init__(self, canvas):
        self.canvas = canvas
        QgsMapToolEmitPoint.__init__(self, self.canvas)
        # rubberband class gives the user visual feedback of the drawing
        self.rubberBand = QgsRubberBand(self.canvas, True)
        # setting up outline and fill color: both red
        self.rubberBand.setColor(QColor(235, 36, 21))
        # RGB color values, last value indicates transparency (0-255)
        self.rubberBand.setFillColor(QColor(255, 79, 66, 140))
        self.rubberBand.setWidth(3)
        self.points = []
        # a flag indicating when a single polygon is finished
        self.finished = False
        self.poly_bbox = False
        self.double_click_flag = False
        self.reset()

    def reset(self):
        """Empties the canvas and the points gathered thus far"""
        self.rubberBand.reset(True)
        self.poly_bbox = False
        self.points.clear()

    def keyPressEvent(self, e):
        """Pressing ESC resets the canvas. Pressing enter connects the polygon"""
        if (e.key() == 16777216):
            self.reset()
        if (e.key() == 16777220):
            self.finishPolygon()

    def canvasDoubleClickEvent(self, e):
        self.double_click_flag = True
        self.finishPolygon()

    def canvasReleaseEvent(self, e):
        """Activated when user clicks on the canvas. Gets coordinates, draws
        them on the map and adds to the list of points."""
        if self.double_click_flag:
            self.double_click_flag = False
            return

        # if the finished flag is activated, the canvas will be must be reset
        # for a new polygon
        if self.finished:
            self.reset()
            self.finished = False

        self.click_point = self.toMapCoordinates(e.pos())

        self.rubberBand.addPoint(self.click_point, True)
        self.points.append(self.click_point)
        self.rubberBand.show()

    def finishPolygon(self):
        """Activated when by user or when the map window is closed without connecting
            the polygon. Makes the polygon valid by making first and last point
            the same. This is reflected visually. Up until now the user has been
            drawing a line: a polygon is created and shown on the map."""
        # nothing will happen if the code below has already been ran
        if self.finished:
            return
        # connecting the polygon is valid if there's already at least 3 points
        elif len(self.points) > 2:
            first_point = self.points[0]
            self.points.append(first_point)
            self.rubberBand.closePoints()
            self.rubberBand.addPoint(first_point, True)
            self.finished = True
            # a polygon is created and added to the map for visual purposes
            map_polygon = QgsGeometry.fromPolygonXY([self.points])
            self.rubberBand.setToGeometry(map_polygon)
            # get the bounding box of this new polygon
            self.poly_bbox = self.rubberBand.asGeometry().boundingBox()
        else:
            self.finished = True

    def getPoints(self):
        """Returns list of PointXY geometries, i.e. the polygon in list form"""
        self.rubberBand.reset(True)
        return self.points

    def getPolyBbox(self):
        return self.poly_bbox
Beispiel #56
0
class EventoDivision(QgsMapToolAdvancedDigitizing):
    def __init__(self, canvas, pluginM, cadDockWidget):
        QgsMapToolAdvancedDigitizing.__init__(self, canvas, cadDockWidget)
        #Asignacion inicial
        self.canvas = canvas
        self.pluginM = pluginM
        self.modoDividir = False
        self.modoEliminar = False
        self.modoEditar = False
        self.moviendoVertice = False
        self.activate()

        for x in iface.advancedDigitizeToolBar().actions():
            if x.objectName() == 'mEnableAction':
                self.botonAD = x

        self.relaciones = {}
        self.punteroRelaciones = 0
        self.relaciones[self.punteroRelaciones] = RelacionRubberGeom(
            self.crearNuevoRubberLinea(), None)

        self.rubberPunto = QgsRubberBand(self.canvas,
                                         QgsWkbTypes.PointGeometry)
        self.rubberPunto.setFillColor(QColor(0, 0, 0, 0))
        self.rubberPunto.setStrokeColor(QColor(255, 0, 0, 255))
        self.rubberPunto.setWidth(6)

        self.primerClick = False
        self.snapper = self.canvas.snappingUtils()
        self.listaPuntosLineaTemp = []
        self.cuentaClickLinea = 0
        self.relacionEnEdicion = -1

#--------------------------------------------------------------------------------------------

    def cadCanvasPressEvent(self, event):
        print('canvasPressEvent')

        x = event.pos().x()
        y = event.pos().y()
        startingPoint = QtCore.QPoint(x, y)
        trans = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
        posTemp = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)

        toAdvanced = (self.cadDockWidget().constraintAngle().isLocked()
                      or self.cadDockWidget().constraintDistance().isLocked()
                      or self.cadDockWidget().constraintX().isLocked()
                      or self.cadDockWidget().constraintY().isLocked())

        puntoSnap = self.snapCompleto(startingPoint, toAdvanced)

        if not toAdvanced:
            if puntoSnap != None:
                self.cadDockWidget().setX(str(puntoSnap.x()), 2)
                self.cadDockWidget().setY(str(puntoSnap.y()), 2)
            else:
                self.cadDockWidget().setX(str(x), 2)
                self.cadDockWidget().setY(str(y), 2)

        if self.modoDividir:  # ----- Modo Dividir ---- #
            if event.buttons() == Qt.LeftButton:

                self.puntoLineaTemp = self.toMapCoordinates(event.pos())
                geoTemp = QgsPoint(trans.x(), trans.y())
                self.cuentaClickLinea += 1

                if puntoSnap != None:  #Cuando tenemos snap ------------#

                    self.listaPuntosLineaTemp.append(puntoSnap)
                    self.isEmittingPoint = True
                    marcador = self.crearNuevoMarcaVert()
                    self.relaciones[self.punteroRelaciones].marcadores.append(
                        marcador)
                    marcador.setCenter(puntoSnap)
                else:  #Cuando no tenemos snap ------------- #

                    self.listaPuntosLineaTemp.append(self.puntoLineaTemp)
                    self.isEmittingPoint = True
                    marcador = self.crearNuevoMarcaVert()
                    self.relaciones[self.punteroRelaciones].marcadores.append(
                        marcador)
                    marcador.setCenter(self.puntoLineaTemp)

                if not self.primerClick:
                    self.primerClick = True

            if event.buttons() == Qt.RightButton:  #Click derecho
                self.primerClick = False

                print(self.relaciones)
                if self.cuentaClickLinea >= 2:  #Cuando son mas de dos puntos

                    self.isEmittingPoint = False
                    self.cuentaClickLinea = 0
                    self.primerClick = False

                    self.relaciones[self.punteroRelaciones].rubber.reset(
                        QgsWkbTypes.LineGeometry)  #Vaciamos el rubber

                    rango = len(
                        self.listaPuntosLineaTemp
                    ) - 1  #Agregamos todos los puntos al rubber excepto el ultimo
                    for x in range(0, rango):
                        punto = self.listaPuntosLineaTemp[x]
                        self.relaciones[
                            self.punteroRelaciones].rubber.addPoint(
                                punto, True)

                    geometriaR = QgsGeometry(
                        self.relaciones[self.punteroRelaciones].rubber.
                        asGeometry())  #Ponemos la geometria en la relacion
                    self.relaciones[self.punteroRelaciones].geom = geometriaR

                    vertices = self.obtenerVerticesLinea(
                        geometriaR)  #Obtenemos los vertices de la geometria

                    self.relaciones[self.punteroRelaciones].rubber.reset(
                        QgsWkbTypes.LineGeometry)  #Vaciamos el rubber

                    for vertice in vertices:  #Ponemos los vertices en el rubber
                        #self.relaciones[self.punteroRelaciones].rubber.addPoint(QgsPointXY(vertice.x(), vertice.y()), True)
                        self.relaciones[
                            self.punteroRelaciones].rubber.addPoint(
                                vertice, True)

                    self.relaciones[self.punteroRelaciones].rubber.show()
                    self.listaPuntosLineaTemp = []

                    self.punteroRelaciones += 1  #Agregamos otro Rubber
                    self.relaciones[
                        self.punteroRelaciones] = RelacionRubberGeom(
                            self.crearNuevoRubberLinea(), None)

                else:
                    self.relaciones[self.punteroRelaciones].rubber.reset(
                        QgsWkbTypes.LineGeometry)
                    self.listaPuntosLineaTemp = []
                    self.relaciones[self.punteroRelaciones].geom = None

        elif self.modoEliminar:  #-------Modo Elimina-------------#
            if event.buttons() == Qt.LeftButton:
                geomClick = QgsGeometry(QgsGeometry.fromPointXY(posTemp))
                bufferClick = geomClick.buffer(0.25, 1)

                relacion = self.obtenerRelacionCercana(bufferClick)
                if relacion != None:
                    relacion.rubber.reset(QgsWkbTypes.LineGeometry)
                    relacion.geom = None
                    relacion.vaciarMarcadores()

        elif self.modoEditar:  #--------------Modo Editar---------#
            print('un clic')
            geomClick = QgsGeometry(QgsGeometry.fromPointXY(posTemp))
            bufferClick = geomClick.buffer(0.25, 1)
            relacion = self.obtenerRelacionCercana(bufferClick)

            if event.buttons(
            ) == Qt.LeftButton:  #---------Click Izquierdo ------#

                if not self.moviendoVertice:  #Cuando NO estamos moviendo un vertice y buscamos mover uno
                    print('moviendoVertice')

                    if relacion != None:

                        print('relacion')

                        relacion.rubber.setStrokeColor(QColor(
                            255, 170, 0, 255))
                        iface.mapCanvas().refresh()
                        vertices = self.obtenerVerticesLinea(relacion.geom)
                        verticeSeleccionado = None
                        for vertice in vertices:  #Aqui buscamos el vertice cercano al click
                            geomVertice = QgsGeometry(
                                QgsGeometry.fromPointXY(vertice)).buffer(
                                    2.25, 1)
                            if geomVertice.intersects(bufferClick):
                                verticeSeleccionado = vertice
                                break

                        if verticeSeleccionado != None:  #aqui tenemos ya un vertice jalando para arrastrase

                            print('verticeSeleccionado')

                            self.listaPuntosLineaTemp = []
                            self.indiceSeleccionado = vertices.index(vertice)
                            self.moviendoVertice = True
                            for vertice in vertices:
                                self.listaPuntosLineaTemp.append(vertice)

                else:  #Cuando estamos moviendo un vertice y queremos soltarlo
                    print('moviendoVertice else')

                    self.moviendoVertice = False
                    rel = self.relaciones[self.relacionEnEdicion]
                    rel.geom = rel.rubber.asGeometry()
                    rel.rubber.setStrokeColor(QColor(0, 62, 240, 255))

                    self.punteroRelaciones = len(self.relaciones)
                    self.relaciones[
                        self.punteroRelaciones] = RelacionRubberGeom(
                            self.crearNuevoRubberLinea(), None)
                    self.listaPuntosLineaTemp = []

                    print('///////////////////////////////////')
                    print(self.pluginM.VentanaAreas,
                          type(self.pluginM.VentanaAreas))
                    print(self.pluginM, type(self.pluginM))
                    print('///////////////////////////////////')

                    #self.pluginM.VentanaAreas.close()
                    iface.mapCanvas().refresh()

            elif event.buttons(
            ) == Qt.RightButton:  #--------Click Derecho -----# Para agregar vertices personales

                if relacion != None:
                    inter = bufferClick.intersection(
                        relacion.geom.buffer(0.000004, 1)
                    )  #Checamos la interseccion con la linea a editar
                    c = inter.centroid().asPoint(
                    )  #Obtenemos el centroide, aqui se pintara el vertice

                    vertices1 = self.obtenerVerticesLinea(
                        relacion.geom)  #Obtenemos todos los vertices acutales

                    rango = len(vertices1)

                    posiblesX = []
                    for x in range(0,
                                   rango - 1):  #Recorremos todos los vertices
                        v1 = vertices1[x]  #Punto izqueirdo
                        v2 = vertices1[x + 1]  #punto derecho
                        par = (v1, v2)

                        if v1.x() <= v2.x(
                        ):  #Cuando el primer punto esta a la izquierda
                            if c.x() >= v1.x() and c.x() <= v2.x():
                                posiblesX.append(par)
                        else:  #Cuando el primer punto esta a la derecha
                            if c.x() <= v1.x() and c.x() >= v2.x():
                                posiblesX.append(par)

                    for pa in posiblesX:  #Checamos todos los posibles que se encuentren en el eje X
                        v1 = pa[0]
                        v2 = pa[1]
                        if v1.y() <= v2.y(
                        ):  #Cuando el primer punto esta abajo
                            if c.y() >= v1.y() and c.y() <= v2.y():
                                salidaY = pa
                                break
                        else:  #Cuando esta arriba
                            if c.y() <= v1.y() and c.y() >= v2.y():
                                salidaY = pa
                                break

                    indiceI = vertices1.index(salidaY[0])
                    indiceD = vertices1.index(salidaY[1])

                    vertices2 = []
                    relacion.vaciarMarcadores()
                    for x in range(
                            0, rango
                    ):  #Generamos lista d epuntos que incluyan el nuevo
                        if x == indiceD:

                            vertices2.append(c)
                            nuevo = self.crearNuevoMarcaVert()
                            centroM = QgsPointXY(c.x(), c.y())
                            nuevo.setCenter(centroM)
                            relacion.marcadores.append(nuevo)

                            vertices2.append(vertices1[x])
                            nuevo = self.crearNuevoMarcaVert()
                            centroM = QgsPointXY(vertices1[x].x(),
                                                 vertices1[x].y())
                            nuevo.setCenter(centroM)
                            relacion.marcadores.append(nuevo)

                        else:
                            vertices2.append(vertices1[x])
                            nuevo = self.crearNuevoMarcaVert()
                            centroM = QgsPointXY(vertices1[x].x(),
                                                 vertices1[x].y())
                            nuevo.setCenter(centroM)
                            relacion.marcadores.append(nuevo)

                    relacion.rubber.reset(QgsWkbTypes.LineGeometry)

                    for punto in vertices2:  #Regeneramos el rubber
                        puntoXY = QgsPointXY(punto.x(), punto.y())
                        relacion.rubber.addPoint(puntoXY, True)

                    relacion.geom = relacion.rubber.asGeometry()

#-----------------------------------------------------------------------

    def cadCanvasMoveEvent(self, event):

        x = event.pos().x()
        y = event.pos().y()
        startingPoint = QtCore.QPoint(x, y)
        posTemp = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)

        toAdvanced = (self.cadDockWidget().constraintAngle().isLocked()
                      or self.cadDockWidget().constraintDistance().isLocked()
                      or self.cadDockWidget().constraintX().isLocked()
                      or self.cadDockWidget().constraintY().isLocked())

        puntoSnap = self.snapCompleto(startingPoint, toAdvanced)

        if not toAdvanced:
            if puntoSnap != None:
                self.cadDockWidget().setX(str(puntoSnap.x()), 2)
                self.cadDockWidget().setY(str(puntoSnap.y()), 2)
            else:
                self.cadDockWidget().setX(str(x), 2)
                self.cadDockWidget().setY(str(y), 2)

        if self.modoDividir:
            self.relaciones[self.punteroRelaciones].rubber.reset(
                QgsWkbTypes.LineGeometry)
            self.rubberPunto.reset(QgsWkbTypes.PointGeometry)

            if puntoSnap != None:

                puntoSnapXY = QgsPointXY(puntoSnap.x(), puntoSnap.y())
                self.rubberPunto.addPoint(puntoSnapXY, True)
                self.rubberPunto.show()

            if self.primerClick:
                if (len(self.listaPuntosLineaTemp) > 1):

                    if puntoSnap != None:
                        self.listaPuntosLineaTemp[-1] = puntoSnapXY
                    else:
                        self.listaPuntosLineaTemp[-1] = posTemp

                    for punto in self.listaPuntosLineaTemp[:-1]:
                        self.relaciones[
                            self.punteroRelaciones].rubber.addPoint(
                                punto, False)
                    self.relaciones[self.punteroRelaciones].rubber.addPoint(
                        self.listaPuntosLineaTemp[-1], True)
                    self.relaciones[self.punteroRelaciones].rubber.show()
                else:
                    if puntoSnap != None:
                        self.listaPuntosLineaTemp.append(puntoSnapXY)
                    else:
                        self.listaPuntosLineaTemp.append(posTemp)
                    self.relaciones[self.punteroRelaciones].rubber.addPoint(
                        self.listaPuntosLineaTemp[0], True)
                    self.relaciones[self.punteroRelaciones].rubber.show()

        elif self.modoEditar:  #-modo editar

            if self.moviendoVertice:  #Arrastrando un vertice

                self.rubberPunto.reset(QgsWkbTypes.PointGeometry)

                if puntoSnap != None:

                    puntoSnapXY = QgsPointXY(puntoSnap.x(), puntoSnap.y())
                    self.rubberPunto.addPoint(puntoSnapXY, True)
                    self.rubberPunto.show()
                    self.listaPuntosLineaTemp[
                        self.indiceSeleccionado] = puntoSnapXY
                    self.relaciones[self.relacionEnEdicion].marcadores[
                        self.indiceSeleccionado].setCenter(puntoSnapXY)

                else:
                    self.listaPuntosLineaTemp[
                        self.indiceSeleccionado] = posTemp
                    self.relaciones[self.relacionEnEdicion].marcadores[
                        self.indiceSeleccionado].setCenter(posTemp)

                self.relaciones[self.relacionEnEdicion].rubber.reset(
                    QgsWkbTypes.LineGeometry)

                for punto in self.listaPuntosLineaTemp:
                    self.relaciones[self.relacionEnEdicion].rubber.addPoint(
                        punto, True)

                self.relaciones[self.relacionEnEdicion].rubber.show()

#-------------------------------------------------------------------------------------#

    def snapVertice(self, startingPoint, nombreCapa):

        layer = QgsProject.instance().mapLayer(
            self.pluginM.ACA.obtenerIdCapa(nombreCapa))

        self.snapper.setCurrentLayer(layer)
        snapMatch = self.snapper.snapToCurrentLayer(startingPoint,
                                                    QgsPointLocator.Vertex)

        if snapMatch.hasVertex():
            return snapMatch.point()

#------------------------------------------------------------------------------------#

    def snapArista(self, startingPoint, nombreCapa):

        layer = QgsProject.instance().mapLayer(
            self.pluginM.ACA.obtenerIdCapa(nombreCapa))

        self.snapper.setCurrentLayer(layer)
        snapMatch = self.snapper.snapToCurrentLayer(startingPoint,
                                                    QgsPointLocator.Edge)

        if snapMatch.hasEdge():
            return snapMatch.point()

#-----------------------------------------------------------------------------------

    def snapCompleto(self, startingPoint, toAdvanced):

        # Si obedeceremos la herramienta de digitalizacion avanzada...
        if toAdvanced:
            cadWidget = self.cadDockWidget()
            return cadWidget.currentPoint()[0]
        snap = self.snapVertice(startingPoint,
                                'predios.geom')  #----vertices -----#
        if snap != None:
            return snap
        else:
            snap = self.snapVertice(startingPoint, 'construcciones')
            if snap != None:
                return snap
            else:
                snap = self.snapVertice(startingPoint, 'horizontales.geom')
                if snap != None:
                    return snap
                else:
                    snap = self.snapVertice(
                        startingPoint,
                        'verticales')  #-----Hasta aqui son vertices -----#
                    if snap != None:
                        return snap
                    else:
                        snap = self.snapArista(startingPoint, 'predios.geom')
                        if snap != None:
                            return snap
                        else:
                            snap = self.snapArista(startingPoint,
                                                   'construcciones')
                            if snap != None:
                                return snap
                            else:
                                snap = self.snapArista(startingPoint,
                                                       'horizontales.geom')
                                if snap != None:
                                    return snap
                                else:
                                    snap = self.snapArista(
                                        startingPoint, 'verticales'
                                    )  #-------- hasta aqui aristas-----------#
                                    if snap != None:
                                        return snap
                                    else:
                                        return None

#----------------------------------------------------------------------------------------------

    def crearNuevoRubberLinea(self):
        nuevoRubber = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry)
        nuevoRubber.setFillColor(QColor(0, 0, 0, 0))
        nuevoRubber.setStrokeColor(QColor(0, 62, 240, 255))
        nuevoRubber.setWidth(2)
        #penStyle = Qt.PenStyle()
        nuevoRubber.setLineStyle(Qt.PenStyle(3))
        return nuevoRubber

#------------------------------------------------------------------------------------------

    def crearNuevoRubberPoly(self):
        nuevoRubber = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry)

        r = randint(0, 255)
        g = randint(0, 255)
        b = randint(0, 255)

        color = QColor(r, g, b, 36)
        colorAg = QColor(r, g, b, 87)
        self.pluginM.listaColores.append(colorAg)
        nuevoRubber.setFillColor(color)
        nuevoRubber.setStrokeColor(QColor(r, g, b, 255))
        nuevoRubber.setWidth(2)
        return nuevoRubber

#-------------------------------------------------------------------------------------

    def recargarRelaciones(self):
        self.relaciones = {}
        self.punteroRelaciones = 0

        self.relaciones[self.punteroRelaciones] = RelacionRubberGeom(
            self.crearNuevoRubberLinea(), None)

#-----------------------------------------------------------------------------------------

    def prueba(self, e):
        print(e)

#----------------------------------------------------------------------------------

    def obtenerRelacionCercana(self, punto):
        rango = len(self.relaciones) - 1
        for i in range(0, rango):
            relacion = self.relaciones[i]
            geom = relacion.geom
            if geom != None:
                if geom.buffer(0.000004, 1).intersects(punto):
                    self.relacionEnEdicion = i
                    return relacion


#-----------------------------------------------------------------------------------

    def obtenerVertices(self, geom):

        n = 0
        ver = geom.vertexAt(0)
        vertices = []

        while (ver != QgsPoint(0, 0)):
            n += 1
            vertices.append(ver)
            ver = geom.vertexAt(n)

        return vertices

    def obtenerVerticesLinea(self, geom):

        return geom.asPolyline()

    def crearNuevoMarcaVert(self):
        marcador = QgsVertexMarker(iface.mapCanvas())
        marcador.setColor(QColor(0, 255, 0))
        marcador.setIconSize(5)
        marcador.setIconType(QgsVertexMarker.ICON_BOX)
        marcador.setPenWidth(3)

        return marcador
Beispiel #57
0
class RectangleMapTool(QgsMapToolEmitPoint):
    rectangleCreated = pyqtSignal()

    def __init__(self, canvas):
        self.canvas = canvas
        QgsMapToolEmitPoint.__init__(self, self.canvas)

        self.rubberBand = QgsRubberBand(self.canvas,
                                        QgsWkbTypes.PolygonGeometry)
        self.rubberBand.setColor(QColor(255, 0, 0, 100))
        self.rubberBand.setWidth(2)

        self.reset()

    def reset(self):
        self.startPoint = self.endPoint = None
        self.isEmittingPoint = False
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)

    def canvasPressEvent(self, e):
        self.startPoint = self.toMapCoordinates(e.pos())
        self.endPoint = self.startPoint
        self.isEmittingPoint = True

        self.showRect(self.startPoint, self.endPoint)

    def canvasReleaseEvent(self, e):
        self.isEmittingPoint = False
        self.rectangleCreated.emit()

    def canvasMoveEvent(self, e):
        if not self.isEmittingPoint:
            return

        self.endPoint = self.toMapCoordinates(e.pos())
        self.showRect(self.startPoint, self.endPoint)

    def showRect(self, startPoint, endPoint):
        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)
        if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y():
            return

        point1 = QgsPoint(startPoint.x(), startPoint.y())
        point2 = QgsPoint(startPoint.x(), endPoint.y())
        point3 = QgsPoint(endPoint.x(), endPoint.y())
        point4 = QgsPoint(endPoint.x(), startPoint.y())

        self.rubberBand.addPoint(point1, False)
        self.rubberBand.addPoint(point2, False)
        self.rubberBand.addPoint(point3, False)
        self.rubberBand.addPoint(point4, True)  # true to update canvas
        self.rubberBand.show()

    def rectangle(self):
        if self.startPoint is None or self.endPoint is None:
            return None
        elif self.startPoint.x() == self.endPoint.x() or self.startPoint.y(
        ) == self.endPoint.y():
            return None

        return QgsRectangle(self.startPoint, self.endPoint)

    def setRectangle(self, rect):
        if rect == self.rectangle():
            return False

        if rect is None:
            self.reset()
        else:
            self.startPoint = QgsPoint(rect.xMaximum(), rect.yMaximum())
            self.endPoint = QgsPoint(rect.xMinimum(), rect.yMinimum())
            self.showRect(self.startPoint, self.endPoint)
        return True

    def deactivate(self):
        QgsMapTool.deactivate(self)
        self.deactivated.emit()
Beispiel #58
0
class EditTool(MapTool):
    """
        Inspection tool which copies the feature to a new layer
        and copies selected data from the underlying feature.
    """

    finished = pyqtSignal(QgsVectorLayer, QgsFeature)

    def __init__(self, canvas, layers, snapradius=2):
        MapTool.__init__(self, canvas, layers)
        self.canvas = canvas
        self.radius = snapradius

        self.band = QgsRubberBand(self.canvas)
        self.band.setColor(QColor.fromRgb(224, 162, 16))
        self.band.setWidth(3)

        self.cursor = QCursor(
            QPixmap([
                "16 16 3 1", "      c None", ".     c #FF0000",
                "+     c #FFFFFF", "                ", "       +.+      ",
                "      ++.++     ", "     +.....+    ", "    +.     .+   ",
                "   +.   .   .+  ", "  +.    .    .+ ", " ++.    .    .++",
                " ... ...+... ...", " ++.    .    .++", "  +.    .    .+ ",
                "   +.   .   .+  ", "   ++.     .+   ", "    ++.....+    ",
                "      ++.++     ", "       +.+      "
            ]))

    def getFeatures(self, point):
        searchRadius = (QgsTolerance.toleranceInMapUnits(
            self.radius, self.layers[0], self.canvas.mapRenderer(),
            QgsTolerance.Pixels))
        point = self.toMapCoordinates(point)

        rect = QgsRectangle()
        rect.setXMinimum(point.x() - searchRadius)
        rect.setXMaximum(point.x() + searchRadius)
        rect.setYMinimum(point.y() - searchRadius)
        rect.setYMaximum(point.y() + searchRadius)

        rq = QgsFeatureRequest().setFilterRect(rect)

        self.band.reset()
        for layer in self.layers:
            rq = QgsFeatureRequest().setFilterRect(rect)
            for feature in layer.getFeatures(rq):
                if feature.isValid():
                    yield feature, layer

    def canvasMoveEvent(self, event):
        for feature, _ in self.getFeatures(point=event.pos()):
            self.band.addGeometry(feature.geometry(), None)

    def canvasReleaseEvent(self, event):
        features = list(self.getFeatures(point=event.pos()))

        if len(features) == 1:
            feature = features[0]
            self.finished.emit(feature[1], feature[0])
        elif len(features) > 0:
            listUi = ListFeaturesForm()
            listUi.loadFeatureList(features)
            listUi.openFeatureForm.connect(self.finished)
            listUi.exec_()

    def activate(self):
        """
        Set the tool as the active tool in the canvas. 

        @note: Should be moved out into qmap.py 
               and just expose a cursor to be used
        """
        self.canvas.setCursor(self.cursor)

    def deactivate(self):
        """
        Deactive the tool.
        """
        pass

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True
Beispiel #59
0
class Dialog(QDialog, Ui_nbEditor_dialog):
    def __init__(self, iface, ml, mc):
        """Constructor for the dialog.
        
        Args:
          iface: QgsInterface instance.
        """

        QDialog.__init__(self, iface.mainWindow())

        self.setupUi(self)

        self.ml = ml
        self.mCanvas = mc
        self.mRubberBand = QgsRubberBand(self.mCanvas, True)
        self.mRubberBand.reset(QgsWkbTypes.PolygonGeometry)
        self.mRubberBand.setColor(Qt.red)
        self.mRubberBand.setWidth(2)
        self.ids = []

        self.ini(0)

        self.pushCancel.clicked.connect(self.close)
        self.pushOK.clicked.connect(self.convert)
        self.comboBox.addItems(
            ['', 'Intersections', 'Touches', 'Within distance'])

        self.comboBox.currentIndexChanged.connect(self.nbMethod)
        self.ml.selectionChanged.connect(self.map2tab)

    def ini(self, n):
        self.model = QStandardItemModel(n, 1)
        self.tableView.setModel(self.model)
        self.model.setHeaderData(0, Qt.Horizontal, 'Neighbouring IDs')
        self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.selectionModel = QItemSelectionModel(self.model)
        self.tableView.setSelectionModel(self.selectionModel)
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.selectionModel().selectionChanged.connect(self.tab2map)
        self.progressBar.setValue(0)

    def settings(self):
        self.mod = min(self.ids)
        self.p = 1
        if self.mod == 1:
            self.p = 0

    def map2tab(self):
        s = ''
        idx = self.tableView.selectionModel().selectedIndexes()[0]
        ts = str(self.model.itemData(idx)[0])

        for fid in sorted(self.ml.selectedFeatureIds()):
            s += '%s,' % str(int(fid) + self.p)

        s = s[:-1]

        if s != ts:
            self.model.setData(idx, s)

        # in order to handle the symmetry
        if len(s) > len(ts):
            iLst = s.strip().replace(' ', '').split(',')
            jLst = ts.strip().replace(' ', '').split(',')
        else:
            iLst = ts.strip().replace(' ', '').split(',')
            jLst = s.strip().replace(' ', '').split(',')

        cent = str(idx.row() + self.p)
        dLst = list(set(iLst) - set(jLst))

        for d in dLst:
            row = int(d) - self.p
            sor = str(self.model.itemData(self.model.index(row, 0))[0])
            eLst = sor.strip().replace(' ', '').split(',')
            res = ''
            if cent in set(eLst):
                ii = eLst.index(cent)
                del eLst[ii]
                eLst = sorted(map(int, eLst))
                for e in eLst:
                    res += '%s,' % e
                res = res[:-1]
            else:
                u = sor + ',%s' % cent
                eLst = sorted(map(int, u.strip().replace(' ', '').split(',')))
                for e in eLst:
                    res += '%s,' % e
                res = res[:-1]

            self.model.setData(self.model.index(row, 0, QModelIndex()), res)

    def nbWithinDist(self):
        dlg = xdist.Dialog()
        dlg.setModal(True)
        dlg.setWindowTitle("Between two objects")

        if dlg.exec_() == QDialog.Accepted:
            lDist = float(dlg.lineEdit.text())
            if lDist == 0:
                return

            feat = QgsFeature()
            provider = self.ml.dataProvider()
            e = provider.featureCount()

            self.settings()

            for ne in range(self.mod, e + self.mod):
                feat = QgsFeature()
                geom = QgsGeometry()
                fiter = self.ml.getFeatures(QgsFeatureRequest(ne))
                if fiter.nextFeature(feat):
                    geom = QgsGeometry(feat.geometry())

                neighbours = self.hdist(feat, lDist)
                row = feat.id() - self.mod
                self.model.setData(self.model.index(row, 0, QModelIndex()),
                                   neighbours)
                self.progressBar.setValue(100 * ne / e)

    def hdist(self, feata, lDist):
        geoma = QgsGeometry(feata.geometry())
        feat = QgsFeature()
        provider = self.ml.dataProvider()
        feats = provider.getFeatures()
        #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
        #self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount()))
        ne = 0
        neighbours = ""
        while feats.nextFeature(feat):
            ne += 1
            #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne)
            geomb = QgsGeometry(feat.geometry())
            if feata.id() != feat.id():
                if geoma.distance(geomb) <= lDist:
                    neighbours = neighbours + '%s,' % (feat.id() + self.p)
        return neighbours[:-1]

    def tab2map(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.ml.selectionChanged.disconnect(self.map2tab)

        idx = self.tableView.selectionModel().selectedIndexes()[0]
        featureId = idx.row() + self.p

        s = self.model.itemData(idx)
        lst = s[0].strip().replace(' ', '').split(',')

        self.ml.removeSelection()

        for sid in lst:
            self.ml.select(int(sid) - self.p)

        provider = self.ml.dataProvider()

        feat = QgsFeature()
        layer = QgsVectorLayerCache(self.ml, provider.featureCount())
        layer.featureAtId(idx.row() + self.mod, feat)
        geom = QgsGeometry(feat.geometry())

        self.mRubberBand.setToGeometry(geom, self.ml)
        self.mRubberBand.show()

        self.ml.selectionChanged.connect(self.map2tab)

        QApplication.restoreOverrideCursor()

    def closeEvent(self, event):
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.ml.selectionChanged.disconnect(self.map2tab)
        self.ml.removeSelection()
        self.mRubberBand.hide()
        self.close()

        QApplication.restoreOverrideCursor()

    def convert(self):
        dlg = editordlg()
        dlg.setModal(True)
        dlg.setWindowTitle("Neighbour list in BUGS format")
        num = ""
        adj = ""
        sumNumNeigh = 0
        for row in range(0, self.model.rowCount()):
            ts = self.model.itemData(self.model.index(row, 0))
            lst = ts[0].strip().replace(' ', '').split(',')
            num += '%s, ' % len(lst)
            sumNumNeigh += len(lst)
            lst.reverse()
            sor = ', '.join(lst) + ','
            adj = adj + str(sor) + '\n'

        num = num[:-2]
        adj = adj[:-2]

        nblist = 'list(\nnum = c(%s),\nadj = c(%s),\nsumNumNeigh=%s)' % (
            num, adj, sumNumNeigh)
        dlg.plainTextEdit.appendPlainText(nblist)

        dlg.exec_()

    def nbMethod(self):
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.ml.selectionChanged.disconnect(self.map2tab)
        self.model.removeRows(0, self.model.rowCount(QModelIndex()),
                              QModelIndex())
        n = self.ml.dataProvider().featureCount()
        self.ini(n)

        self.ids = []

        provider = self.ml.dataProvider()
        feats = provider.getFeatures()
        #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
        #self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, n))
        ne = 0
        feat = QgsFeature()
        while feats.nextFeature(feat):
            ne += 1
            #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne)
            self.ids.append(feat.id())

        if self.comboBox.currentText() == "Touches":
            if self.ml.geometryType() == 0:
                return
            else:
                self.nbTouches()
        if self.comboBox.currentText() == "Intersections":
            if self.ml.geometryType() == 0:
                return
            else:
                self.nbIntersects()
        if self.comboBox.currentText() == "Within distance":
            self.nbWithinDist()

        self.ml.selectionChanged.connect(self.map2tab)

        QApplication.restoreOverrideCursor()

    def nbTouches(self):
        feat = QgsFeature()
        provider = self.ml.dataProvider()
        e = provider.featureCount()

        self.settings()

        for ne in range(self.mod, e + self.mod):
            feat = QgsFeature()
            geom = QgsGeometry()
            fiter = self.ml.getFeatures(QgsFeatureRequest(ne))
            if fiter.nextFeature(feat):
                geom = QgsGeometry(feat.geometry())

            neighbours = self.htouch(feat)
            row = feat.id() - self.mod
            self.model.setData(self.model.index(row, 0, QModelIndex()),
                               neighbours)
            self.progressBar.setValue(100 * ne / e)

    def htouch(self, feata):
        geoma = QgsGeometry(feata.geometry())
        feat = QgsFeature()
        provider = self.ml.dataProvider()
        feats = provider.getFeatures()
        #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
        #self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount()))
        ne = 0
        neighbours = ""
        while feats.nextFeature(feat):
            ne += 1
            #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne)
            geomb = QgsGeometry(feat.geometry())
            if feata.id() != feat.id():
                if geoma.touches(geomb) == True:
                    neighbours = neighbours + '%s,' % (feat.id() + self.p)
        return neighbours[:-1]

    def nbIntersects(self):
        feat = QgsFeature()
        provider = self.ml.dataProvider()
        e = provider.featureCount()

        self.settings()

        for ne in range(self.mod, e + self.mod):
            feat = QgsFeature()
            geom = QgsGeometry()
            fiter = self.ml.getFeatures(QgsFeatureRequest(ne))
            if fiter.nextFeature(feat):
                geom = QgsGeometry(feat.geometry())

            neighbours = self.hintersect(feat)
            row = feat.id() - self.mod
            self.model.setData(self.model.index(row, 0, QModelIndex()),
                               neighbours)
            self.progressBar.setValue(100 * ne / e)

    def hintersect(self, feata):
        geoma = QgsGeometry(feata.geometry())
        feat = QgsFeature()
        provider = self.ml.dataProvider()
        feats = provider.getFeatures()
        #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
        #self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, provider.featureCount()))
        ne = 0
        neighbours = ""
        while feats.nextFeature(feat):
            ne += 1
            #self.emit(SIGNAL("runStatus(PyQt_PyObject)"), ne)
            geomb = QgsGeometry(feat.geometry())
            if feata.id() != feat.id():
                if geoma.intersects(geomb) == True:
                    neighbours = neighbours + '%s,' % (feat.id() + self.p)
        return neighbours[:-1]
class OneSideBuffer_tool(QgsMapToolIdentify):
    deact = pyqtSignal()
    def __init__(self, iface, action, plugin_dir, spinbox):
        self.canvas = iface.mapCanvas()
        self.iface = iface
        self.action = action
        self.icon_path = os.path.join(plugin_dir,"icons")
        self.spinbox = spinbox

        self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.GeometryType(3))
        self.rubberBand.setWidth(3)
        self.rubberBand.setStrokeColor(QColor(254,0,0))

        self.snap_mark = QgsVertexMarker(self.canvas)
        self.snap_mark.setColor(QColor(0, 0, 255))
        self.snap_mark.setPenWidth(2)
        self.snap_mark.setIconType(QgsVertexMarker.ICON_BOX)
        self.snap_mark.setIconSize(10)

        QgsMapToolIdentify.__init__(self, self.canvas)

        self.selectFeatureMode = True
        self.firstPointMode = False
        self.secondPointMode = False
        self.objectSizeMode = False

        self.firstPoint_locate = None
        self.linestring = None

        self.dist = self.spinbox.value()

        self.canvas.layersChanged.connect(self.setPolygonLayers)

    def activate(self):
        self.setCursor(Qt.CrossCursor)
        self.setPolygonLayers()

    def addMenu(self):
        menu = QMenu()
        self.setPolygonLayers()
        for i in self.getVisibleLayers():
            action = menu.addAction(i.name())
            action.triggered.connect(lambda ch, i=i: self.addFeature(i))
        menu.exec_(QCursor.pos())

    def addFeature(self, dest_layer):
        geometry_canvas = self.geom_poly

        for l in self.getVisibleLayers():
            geometry_canvas = self.getDifferenceGeometry(geometry_canvas, l)

        # dump geom if it s multipart
        geometry_parts = [p for p in geometry_canvas.parts()]
        for part in geometry_parts:
            part_wkt = part.asWkt()
            part_geom = QgsGeometry.fromWkt(part_wkt)

            if part_geom.isGeosValid() == False:
                part_geom = part_geom.makeValid()

            if part_geom.isGeosValid() == True and part_geom.area() > 0.1:
                self.addTopologicalPointsForActiveLayers(part_geom)

                feature = QgsVectorLayerUtils.createFeature(dest_layer)
                feature.setGeometry(part_geom)

                height_col_idx = dest_layer.fields().indexFromName('SZEROKOSC')

                if height_col_idx != -1:
                    feature.setAttribute(height_col_idx, self.dist)

                if not dest_layer.isEditable():
                    dest_layer.startEditing()

                dest_layer.addFeature(feature)

                self.iface.openFeatureForm(dest_layer, feature, False)

    def addTopologicalPointsForActiveLayers(self, geometry):
        geometry = QgsGeometry(geometry)
        layers = self.getVisibleLayers()
        for layer in layers:
            if not layer.isEditable():
                layer.startEditing()

            topology = QgsVectorLayerEditUtils(layer)
            vertices = [v for v in geometry.vertices()]

            for v in vertices:
                point = v.asWkt()
                point = QgsGeometry.fromWkt(point)
                point = point.asPoint()
                topology.addTopologicalPoints(point)  
            
        return True
    
    def calculateSide(self , linestring, point):
        segment = linestring.closestSegmentWithContext(point.asPoint())
        if segment[3] < 0:
            return 2
        else:
            return 1
     
    def canvasMoveEvent(self, e ):
        if self.firstPointMode == True or self.secondPointMode == True:
            self.snapPoint = self.checkSnapToPoint(e.pos())

            if self.snapPoint[0]:
                self.snap_mark.setCenter(self.snapPoint[1])
                self.snap_mark.show()
                self.point = QgsGeometry.fromPointXY (self.snapPoint[1])
            else:
                self.snap_mark.hide()
                self.point = QgsGeometry.fromPointXY (self.toMapCoordinates(e.pos()))

        if self.secondPointMode:
            self.secondPoint_locate = self.linestring.lineLocatePoint(self.point)
            self.output_geom = self.lineSubstring(self.linestring,self.firstPoint_locate,self.secondPoint_locate)

            if self.output_geom != None:
                self.rubberBand.setToGeometry(self.output_geom, None)
                self.rubberBand.show()

        if self.objectSizeMode:
            s_point = QgsGeometry.fromPointXY (self.toMapCoordinates(e.pos()))

            #if round(abs(self.output_geom.distance(s_point) - self.dist),1) >= self.spinbox.value():
            #self.dist = round(self.output_geom.distance(s_point)/self.spinbox.value(),1)
            self.dist = int(self.output_geom.distance(s_point)/self.spinbox.value())
            self.dist = self.dist * self.spinbox.value()
            QToolTip.showText( self.canvas.mapToGlobal( self.canvas.mouseLastXY() ), str(round(self.dist,2)), self.canvas )

            left_or_right = self.calculateSide(self.output_geom, s_point)
            self.geom_poly = self.output_geom.singleSidedBuffer(self.dist,20,left_or_right,2)
            self.rubberBand.setToGeometry(self.geom_poly, None)
            self.rubberBand.show()

    def canvasPressEvent (self, e):
        if e.button() == Qt.LeftButton:
            layerType = getattr(QgsMapToolIdentify,'VectorLayer')
            results = self.identify(e.x(), e.y(), self.TopDownStopAtFirst ,layerType)

            if self.selectFeatureMode:
                if len(results) == 0 or results[0].mLayer not in [l for l in self.polygonLayers]:
                    for l in self.polygonLayers:
                        l.removeSelection()

                elif len(results) > 0:
                    for l in self.polygonLayers:
                        try:
                            l.removeSelection()
                        except:
                            pass
                    self.current_layer = self.cur_lyr = results[0].mLayer
                    self.current_feature = QgsFeature(results[0].mFeature)
                    self.current_layer.select(self.current_feature.id())
                    self.iface.setActiveLayer(self.current_layer)

                    self.selectFeatureMode = False
                    self.firstPointMode = True

            elif self.firstPointMode:
                self.linestring = self.polygon2Linestring(self.current_feature.geometry(), e.pos())
                self.firstPoint_locate = self.linestring.lineLocatePoint(self.point)
                self.firstPointMode = False
                self.secondPointMode = True

            elif self.secondPointMode:
                self.secondPointMode = False
                self.objectSizeMode = True
                self.dist = self.spinbox.value()

            elif self.objectSizeMode:
                self.objectSizeMode = False
                self.addMenu()
                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.rubberBand.hide()
        self.deact.emit()

    def getDifferenceGeometry(self, geometry, layer):
        geometry = QgsGeometry(geometry)
        bbox = geometry.boundingBox()

        for f in layer.getFeatures(bbox):
            f_geom = f.geometry()

            if f_geom.isGeosValid() == False:
                f_geom = f_geom.makeValid()

            if f_geom.isGeosValid() == True: 
                if geometry.intersects(f_geom):
                    geometry = geometry.difference(f_geom)

        return geometry

    def getVisibleLayers(self):
        array = []
        root = QgsProject.instance().layerTreeRoot()
        for l in self.polygonLayers:
            node = root.findLayer(l.id())
            if node:
                visible = node.isVisible ()
                if visible:
                    array.append(l)
        return array

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

    def lineSubstring(self, linestring, start, end):
        array = [linestring.lineLocatePoint(QgsGeometry.fromWkt(i.asWkt())) for i in linestring.vertices()]
        one_array = []
        second_array = []
        # 1 Geom
        if start < end:
            one_array.append(start)
            for i in array:
                if i > start and i < end:
                    one_array.append(i)
            one_array.append(end)
        else:
            one_array.append(start)
            for i in array:
                if i > start:
                    one_array.append(i)
            one_array.append(0.0)
            for i in array:
                if i < end and i > 0:
                    one_array.append(i)
            one_array.append(end)

        # 2 Geom
        if start < end:
            second_array.append(end)
            for i in array:
                if i > end:
                    second_array.append(i)
            second_array.append(0.0)
            for i in array:
                if i < start and i > 0:
                    second_array.append(i)
            second_array.append(start)
        else:
            second_array.append(end)
            for i in array:
                if i > end and i < start:
                    second_array.append(i)
            second_array.append(start)

        one_geom = QgsGeometry.fromPolylineXY([linestring.interpolate(i).asPoint() for i in one_array])
        second_geom = QgsGeometry.fromPolylineXY([linestring.interpolate(i).asPoint() for i in second_array])

        if second_geom.length() < one_geom.length():
            self.linestring_rev = True
            return (second_geom)
        else:
            self.linestring_rev = False
            return(one_geom)

    def point2LayerCoordinate(self, pos, layer):
        layer_crs = layer.crs().authid()
        canvas_crs = self.canvas.mapSettings().destinationCrs().authid()

        point = self.toMapCoordinates(pos)
        point = QgsGeometry.fromPointXY(point)
        point = self.geometryCrs2Crs(point, canvas_crs, layer_crs)
        return point

    def polygon2Linestring(self, poly_geom, pos):
        geom_parts = [p for p in poly_geom.parts()]
        pos_geom = QgsGeometry.fromPointXY (self.toMapCoordinates(pos))

        cur_dist = None
        cur_geom = None
        for p in geom_parts:
            p_geom = QgsGeometry.fromWkt(p.asWkt())
            p_geom = QgsGeometry.fromPolyline([p for p in p_geom.vertices()])
            p_geom_dist = p_geom.distance(pos_geom)

            if cur_dist == None or p_geom_dist < cur_dist:
                cur_geom = p_geom
                cur_dist = p_geom_dist

        return cur_geom

    def reset(self):
        self.current_layer.removeSelection()
        self.selectFeatureMode = True
        self.firstPointMode = False
        self.secondPointMode = False
        self.firstPoint_locate = None
        self.linestring = None
        self.objectSizeMode = False
        self.snap_mark.hide()
        self.rubberBand.hide()
        self.dist = self.spinbox.value()

    def setPolygonLayers(self):
        self.polygonLayers = []
        for l in QgsProject.instance().mapLayers():
            layer = QgsProject.instance().mapLayer(l)
            if  layer.type() == 0: # 0 = Vector layer
                if layer.geometryType() == 2: # 2 = Polygon layer
                    self.polygonLayers.append(layer)