Ejemplo n.º 1
0
    def _get_layers_from_coordinates(self, point, rb_list, tab_type=None):

        cursor = QCursor()
        x = cursor.pos().x()
        y = cursor.pos().y()
        click_point = QPoint(x + 5, y + 5)

        visible_layers = tools_qgis.get_visible_layers(as_str_list=True)
        scale_zoom = self.iface.mapCanvas().scale()

        # Get layers under mouse clicked
        extras = f'"pointClickCoords":{{"xcoord":{point.x()}, "ycoord":{point.y()}}}, '
        extras += f'"visibleLayers":{visible_layers}, '
        extras += f'"zoomScale":{scale_zoom} '
        body = tools_gw.create_body(extras=extras)
        json_result = tools_gw.execute_procedure(
            'gw_fct_getlayersfromcoordinates',
            body,
            rubber_band=self.rubber_band)
        if not json_result or json_result['status'] == 'Failed':
            return False

        # hide QMenu identify if no feature under mouse
        len_layers = len(json_result['body']['data']['layersNames'])
        if len_layers == 0:
            return False

        self.icon_folder = self.plugin_dir + '/icons/'

        # Right click main QMenu
        main_menu = QMenu()

        # Create one menu for each layer
        for layer in json_result['body']['data']['layersNames']:
            layer_name = tools_qgis.get_layer_by_tablename(layer['layerName'])
            icon_path = self.icon_folder + layer['icon'] + '.png'
            if os.path.exists(str(icon_path)):
                icon = QIcon(icon_path)
                sub_menu = main_menu.addMenu(icon, layer_name.name())
            else:
                sub_menu = main_menu.addMenu(layer_name.name())
            # Create one QAction for each id
            for feature in layer['ids']:
                if 'label' in feature:
                    label = str(feature['label'])
                else:
                    label = str(feature['id'])
                action = QAction(label, None)
                action.setProperty('feature_id', str(feature['id']))
                sub_menu.addAction(action)
                action.triggered.connect(
                    partial(self._get_info_from_selected_id, action, tab_type))
                action.hovered.connect(
                    partial(self._draw_by_action, feature, rb_list))

        main_menu.addSeparator()
        # Identify all
        cont = 0
        for layer in json_result['body']['data']['layersNames']:
            cont += len(layer['ids'])
        action = QAction(f'Identify all ({cont})', None)
        action.hovered.connect(
            partial(self._identify_all, json_result, rb_list))
        main_menu.addAction(action)
        main_menu.addSeparator()
        main_menu.exec_(click_point)
Ejemplo n.º 2
0
    def mouseMoveEvent(self, event, useLast=False):
        """
        @type event: QMouseEvent
        @param event:
        @return:
        """
        if event is not None:
            self.lastMouseX = event.x()
            self.lastMouseY = event.y()

        if useLast is False and self.lastMouseX != -1 and self.lastMouseY != -1:
            # generates an event that simulates a mouse move, because even if
            # mouse is still, video is running and mouse lat/lon must be
            # updated.
            event = QMouseEvent(
                QEvent.MouseMove,
                QPoint(
                    self.lastMouseX,
                    self.lastMouseY),
                Qt.NoButton,
                Qt.NoButton,
                Qt.NoModifier)
        else:
            return

        # Magnifier can move on black screen for show image borders
        if self._interaction.magnifier:
            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))
            self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry)
            return

        # Prevent draw on video if not started or finished
        # if self.parent.player.position() == 0:
        #    return

        # Mouse 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 GetGCPGeoTransform() is not None:
            Longitude, Latitude, Altitude = vut.GetPointCommonCoords(
                event, self.surface)

            tr = QgsCoordinateTransform(
                QgsCoordinateReferenceSystem('EPSG:4326'),
                iface.mapCanvas().mapSettings().destinationCrs(),
                QgsProject.instance().transformContext())
            mapPt = tr.transform(QgsPointXY(Longitude, Latitude))

            vertices = self.Cursor_Canvas_RubberBand.numberOfVertices()
            if vertices > 0:
                self.Cursor_Canvas_RubberBand.removePoint(0, True, 0)
                self.Cursor_Canvas_RubberBand.movePoint(mapPt, 0)
            else:
                self.Cursor_Canvas_RubberBand.addPoint(mapPt)

            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;'>" + \
                    ("%.5f" % Longitude) + "</span>"
                txt += "<span style='font-size:10pt; font-weight:bold;'> Lat : </span>"
                txt += "<span style='font-size:9pt; font-weight:normal;'>" + \
                    ("%.5f" % 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>")

        # 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 drawHistogram(self):
        #if self.inputlayer is None:
        #    return
        self.showInfo("Drawing histogram...")
        viewprect = QRectF(self.histoGraphicsView.viewport().rect())
        self.histoGraphicsView.setSceneRect(viewprect)
        self.setupScene.clear()
        self.setupScene.update()
        histbottom = self.histoGraphicsView.sceneRect().bottom()
        histtop = self.histoGraphicsView.sceneRect().top()
        left = self.histoGraphicsView.sceneRect().left() + self.histopadding
        right = self.histoGraphicsView.sceneRect().right() - self.histopadding
        histheight = histbottom - histtop
        histwidth = right - left
        step = 1.0 * histwidth / self.histobins
        maxlength = histheight
        padding = 1
        ll = QPoint(self.histopadding - 1, histheight - padding)
        start = QPointF(self.histoGraphicsView.mapToScene(ll))

        # Check if there is only one value
        #myrange = (self.minValueSpinBox.value(),self.maxValueSpinBox.value())
        if self.histogramAvailable:
            maxvalue = 0.0
            for i in range(len(self.histo[0])):
                if self.histo[0][i] > maxvalue:
                    maxvalue = self.histo[0][i]
            if maxvalue == 0:
                return
            self.maxBinNumber.setText(str(maxvalue))
            # Create the histogram:
            #self.showInfo("maxvalue: " + str(maxvalue))
            #self.showInfo("maxlength: " + str(maxlength))
            #self.showInfo("step: " + str(step))
            for i in range(self.histobins):
                binnumber = self.histo[0][i]
                if binnumber == 0:
                    continue
                height = (1.0 * self.histo[0][i] / maxvalue *
                          (maxlength - padding))
                rectangle = QGraphicsRectItem(start.x() + step * i, start.y(),
                                              step, -height)
                rectangle.setPen(QPen(QColor(102, 102, 102)))
                rectangle.setBrush(QBrush(QColor(240, 240, 240)))
                self.setupScene.addItem(rectangle)
                #self.showInfo(str(i) + ": " + str(height))
            #if self.levelsListView.model().rowCount() > 0:
        # Add lines for the levels
        minvalue = float(self.histMinValue.text())
        maxvalue = float(self.histMaxValue.text())
        datarange = maxvalue - minvalue
        if datarange == 0:
            return
        i = 0
        while self.levelsListView.model().item(i):
            #self.showInfo("Element: " +
            #       str(self.levelsListView.model().item(i).text()))
            #continue
            value = float(self.levelsListView.model().item(i).text())
            xvalue = start.x() + histwidth * (value - minvalue) / datarange
            line = QGraphicsLineItem(xvalue, 0, xvalue, histheight)
            if i == 0 or i == (self.levelsListView.model().rowCount() - 1):
                line.setPen(QPen(QColor(204, 0, 0)))
            else:
                line.setPen(QPen(QColor(0, 204, 0)))
            self.setupScene.addItem(line)
            i = i + 1
Ejemplo n.º 4
0
 def canvasMoveEvent(self, event):
     self.moved.emit(QPoint(event.pos().x(), event.pos().y()))
Ejemplo n.º 5
0
    def paintEvent(self, event):
        """
        @type event: QPaintEvent
        @param event:
        @return:
        """

        if not self.surface.isActive():
            return

        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

        # Draw On Video
        draw.drawOnVideo(
            self.drawPtPos,
            self.drawLines,
            self.drawPolygon,
            self.drawMeasureDistance,
            self.drawMeasureArea,
            self.drawCesure,
            self.painter,
            self.surface,
            GetGCPGeoTransform())

        # Draw On Video Object tracking Object
        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.setBrush(Qt.transparent)
                    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
Ejemplo n.º 6
0
    def __init__(self, iface: QgisInterface, version: str, plugin_dir: str, isBatch: bool, isHUC: bool=False, logFile: Optional[str]=None) -> None:
        """Initialise class variables."""
        settings = QSettings()
        if settings.contains('/QSWATPlus/SWATPlusDir'):
            SWATPlusDir = settings.value('/QSWATPlus/SWATPlusDir')
            if not os.path.isdir(SWATPlusDir):
                SWATPlusDir = Parameters._SWATPLUSDEFAULTDIR 
        else:
            SWATPlusDir = Parameters._SWATPLUSDEFAULTDIR
        if not os.path.isdir(SWATPlusDir):
            QSWATUtils.error('''Cannot find SWATPlus directory, expected to be {0}.
Please use the Parameters form to set its location.'''.format(SWATPlusDir), isBatch)
        else:
            settings.setValue('/QSWATPlus/SWATPlusDir', SWATPlusDir)
        ## SWATPlus directory
        self.SWATPlusDir = SWATPlusDir
        ## Directory containing QSWAT plugin
        self.plugin_dir = plugin_dir
        ## Databases directory: part of plugin
        # containing template project and reference databases, plus soil database for STATSGO and SSURGO
        self.dbPath = QSWATUtils.join(self.SWATPlusDir, Parameters._DBDIR)
        ## Path of template project database
        self.dbProjTemplate =  QSWATUtils.join(self.dbPath, Parameters._DBPROJ)
        ## Path of template reference database
        self.dbRefTemplate = QSWATUtils.join(self.dbPath, Parameters._DBREF)
        ## Directory of TauDEM executables
        self.TauDEMDir = TauDEMUtils.findTauDEMDir(settings, not isBatch)[0]
        ## Path of mpiexec
        self.mpiexecPath = TauDEMUtils.findMPIExecPath(settings)
        proj: QgsProject = QgsProject.instance()
        title = proj.title()
        ## QGIS interface
        self.iface = iface
        ## project projection (set from DEM)
        self.crsProject: Optional[QgsCoordinateReferenceSystem] = None
        ## Stream burn-in depth
        self.burninDepth: int = proj.readNumEntry(title, 'params/burninDepth', Parameters._BURNINDEPTH)[0]
        ## Channel width multiplier
        self.channelWidthMultiplier: float = proj.readDoubleEntry(title, 'params/channelWidthMultiplier', Parameters._CHANNELWIDTHMULTIPLIER)[0]
        ## Channel width exponent
        self.channelWidthExponent: float = proj.readDoubleEntry(title, 'params/channelWidthExponent', Parameters._CHANNELWIDTHEXPONENT)[0]
        ## Channel depth multiplier
        self.channelDepthMultiplier: float = proj.readDoubleEntry(title, 'params/channelDepthMultiplier', Parameters._CHANNELDEPTHMULTIPLIER)[0]
        ## Channel depth exponent
        self.channelDepthExponent: float = proj.readDoubleEntry(title, 'params/channelDepthExponent', Parameters._CHANNELDEPTHEXPONENT)[0]
        ## reach slope multiplier
        self.reachSlopeMultiplier: float = proj.readDoubleEntry(title, 'params/reachSlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## tributary slope multiplier
        self.tributarySlopeMultiplier: float = proj.readDoubleEntry(title, 'params/tributarySlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## mean slope multiplier
        self.meanSlopeMultiplier: float = proj.readDoubleEntry(title, 'params/meanSlopeMultiplier', Parameters._MULTIPLIER)[0]
        ## main length multiplier
        self.mainLengthMultiplier: float = proj.readDoubleEntry(title, 'params/mainLengthMultiplier', Parameters._MULTIPLIER)[0]
        ## tributary length multiplier
        self.tributaryLengthMultiplier: float = proj.readDoubleEntry(title, 'params/tributaryLengthMultiplier', Parameters._MULTIPLIER)[0]
        ## upslope HRU drain percent
        self.upslopeHRUDrain: int = proj.readNumEntry(title, 'params/upslopeHRUDrain', Parameters._UPSLOPEHRUDRAIN)[0]
        ## Index of slope group in Layers panel
        self.slopeGroupIndex = -1
        ## Index of landuse group in Layers panel
        self.landuseGroupIndex = -1
        ## Index of soil group in Layers panel
        self.soilGroupIndex = -1
        ## Index of watershed group in Layers panel
        self.watershedGroupIndex = -1
        ## Index of results group in Layers panel
        self.resultsGroupIndex = -1
        ## Index of animation group in Layers panel
        self.animationGroupIndex = -1
        ## Flag showing if using existing watershed
        self.existingWshed = False
        ## Flag showing if using grid model
        self.useGridModel = False
        ## flag to show if using landscape units
        self.useLandscapes = False
        ## flag to show if dividing into left/right/headwater landscape units
        self.useLeftRight = False
        ## Path of DEM raster
        self.demFile = ''
        ## Path of filled DEM raster
        self.felFile = ''
        ## Path of stream burn-in shapefile
        self.burnFile = ''
        ## Path of DEM after burning-in
        self.burnedDemFile = ''
        ## Path of D8 flow direction raster
        self.pFile = ''
        ## Path of D8 flow accumulation raster
        self.ad8File = ''
        ## Path of subbasins raster
        self.basinFile = ''
        ## path of channel basins raster
        self.channelBasinFile = ''
        ## path of channel basins file with lakes masked out
        self.chBasinNoLakeFile = ''
        ## Path of channel raster
        self.srcChannelFile = ''
        ## Path of valleyDepthsFile
        # value at each point in this raster is the drop in metres
        # from the point to where its D8 flow path meets a channel
        # Channel elevations are measured at points adjacent to the channel
        # to avoid problems caused by burning-in
        self.valleyDepthsFile = ''
        ## Path of outlets shapefile
        self.outletFile = ''
        ## path of snapped outlets file
        self.snapFile = ''
        ## Path of outlets shapefile for extra reservoirs and point sources
        self.extraOutletFile = ''
        ## Path of stream shapefile
        self.streamFile = ''
        ## Path of stream shapefile calculated by delineation
        # since streamFile is set to streams from grid when using a grid model
        self.delinStreamFile = ''
        ## Path of channel shapefile
        self.channelFile = ''
        ## Path of subbasins shapefile or grid file when using grids
        self.subbasinsFile = ''
        ## Path of subbasins shapefile before lakes removed.  Not used with grid models.
        self.subsNoLakesFile = ''
        ## Path of watershed shapefile: shows channel basins.  Not used with grid models.
        self.wshedFile = ''
        ## Path of file like D8 contributing area but with heightened values at subbasin outlets
        self.hd8File = ''
        ## Path of distance to stream outlets raster
        self.distStFile = ''
        ## Path of distance to channel raster
        self.distChFile = ''
        ## Path of slope raster
        self.slopeFile = ''
        ## path of lakes shapefile
        self.lakeFile = ''
        ## Path of slope bands raster
        self.slopeBandsFile = ''
        ## Path of landuse raster
        self.landuseFile = ''
        ## Path of soil raster
        self.soilFile = ''
        ## path of floodplain raster
        self.floodFile = ''
        ## path of raster generated from playa lakes
        self.playaFile = ''
        ## Nodata value for DEM
        self.elevationNoData = 0.0
        ## DEM horizontal block size
        self.xBlockSize = 0
        ## DEM vertical block size
        self.yBlockSize = 0
        ## Nodata value for basins raster
        self.basinNoData = 0
        ## Nodata value for distance to outlets raster
        self.distStNoData = 0.0
        ## Nodata value for distance to channel raster
        self.distChNoData = 0.0
        ## Nodata value for slope raster
        self.slopeNoData = 0
        ## Nodata value for landuse raster
        self.cropNoData = 0
        ## Nodata value for soil raster
        self.soilNoData = 0
        ## Nodata value for floodplain raster
        self.floodNoData = -1 
        ## Area of DEM cell in square metres
        self.cellArea = 0.0
        ## channel threshold in square metres
        self.channelThresholdArea = 10000000.0 # 1000 hectares default
        ## gridSize as count of DEM cells per side (grid model only)
        self.gridSize = 0
        ## list of landuses exempt from HRU removal
        self.exemptLanduses: List[str] = []
        ## table of landuses being split
        self.splitLanduses: Dict[str, Dict[str, float]] = dict()
        ## Elevation bands threshold in metres
        self.elevBandsThreshold = 0
        ## Number of elevation bands
        self.numElevBands = 0
        ## Topology object
        self.topo: QSWATTopology = QSWATTopology(isBatch, isHUC)
        projFile: str = proj.fileName()
        projPath: str = QFileInfo(projFile).canonicalFilePath()
        pdir, base = os.path.split(projPath)
        ## Project name
        self.projName = os.path.splitext(base)[0]
        ## Project directory
        self.projDir = pdir
        ## QSWAT+ version
        self.version = version
        ## DEM directory
        self.demDir = ''
        ## Landuse directory
        self.landuseDir = ''
        ## Soil directory
        self.soilDir = ''
        ## Landscape directory
        self.landscapeDir = ''
        ## Floodplain directory
        self.floodDir = ''
        ## text directory
        self.textDir = ''
        ## Rasters directory
        self.rastersDir = ''
        ## Shapes directory
        self.shapesDir = ''
        ## Scenarios directory
        self.scenariosDir = ''
        ## Results directory
        self.resultsDir = ''
        ## Plots directory
        self.plotsDir = ''
        ## png directory for storing png images used to create animation videos
        self.pngDir = ''
        ## animation directory for storing animation files
        self.animationDir = ''
        self.createSubDirectories()
        ## path of full lsus shapefile
        self.fullLSUsFile = QSWATUtils.join(self.shapesDir, Parameters._LSUS1 + '.shp')
        ## path of actual lsus shapefile (after channel mergers
        self.actLSUsFile = QSWATUtils.join(self.shapesDir, Parameters._LSUS2 + '.shp')
        ## Path of FullHRUs shapefile
        self.fullHRUsFile = QSWATUtils.join(self.shapesDir, Parameters._HRUS1 + '.shp')
        ## Path of ActHRUs shapefile
        self.actHRUsFile = QSWATUtils.join(self.shapesDir, Parameters._HRUS2 + '.shp')
        ## Flag to show if running in batch mode
        self.isBatch = isBatch
        ## flag for HUC projects
        self.isHUC = isHUC
        ## log file for message output for HUC projects
        self.logFile = logFile
        ## Path of project database
        self.db: DBUtils = DBUtils(self.projDir, self.projName, self.dbProjTemplate, self.dbRefTemplate, self.isHUC, self.logFile, self.isBatch)
        ## multiplier to turn DEM distances to metres
        self.horizontalFactor = 1
        ## multiplier to turn elevations to metres
        self.verticalFactor = 1
        ## vertical units
        self.verticalUnits = Parameters._METRES
        # positions of sub windows
        ## Position of delineation form
        self.delineatePos = QPoint(0, 100)
        ## Position of HRUs form
        self.hrusPos = QPoint(0, 100)
        ## Position of parameters form
        self.parametersPos = QPoint(50, 100)
        ## Position of landscape form
        self.landscapePos = QPoint(50, 80)
        ## Position of select subbasins form
        self.selectSubsPos = QPoint(50, 100)
        ## Position of select reservoirs form
        self.selectResPos = QPoint(50, 100)
        ## Position of about form
        self.aboutPos = QPoint(50, 100)
        ## Position of elevation bands form
        self.elevationBandsPos = QPoint(50, 100)
        ## Position of split landuses form
        self.splitPos = QPoint(50, 100)
        ## Position of select landuses form
        self.selectLuPos = QPoint(50, 100)
        ## Position of exempt landuses form
        self.exemptPos = QPoint(50, 100)
        ## Position of outlets form
        self.outletsPos = QPoint(50, 100)
        ## Position of select outlets file form
        self.selectOutletFilePos = QPoint(50, 100)
        ## Position of select outlets form
        self.selectOutletPos = QPoint(50, 100)
        ## Position of visualise form
        self.visualisePos = QPoint(0, 100)
        ## rasters open that need to be closed if memory exception occurs
        self.openRasters: Set[Raster] = set()
        ## options for creating shapefiles
        self.vectorFileWriterOptions = QgsVectorFileWriter.SaveVectorOptions()
        self.vectorFileWriterOptions.ActionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
        self.vectorFileWriterOptions.driverName = "ESRI Shapefile"
        self.vectorFileWriterOptions.fileEncoding = "UTF-8"
        ## will set to choice made when converting from ArcSWAT, if that was how the project file was created
        # 0: Full
        # 1: Existing
        # 2: No GIS
        # NB These values are defined in convertFromArc.py
        self.fromArcChoice = -1
Ejemplo n.º 7
0
    def test_signalConnection(self):
        # remove all layers
        QgsProject.instance().removeAllMapLayers()
        # set dependencies and add back layers
        self.pointsLayer = QgsVectorLayer(
            "dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points",
            "spatialite")
        assert (self.pointsLayer.isValid())
        self.linesLayer = QgsVectorLayer(
            "dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines",
            "spatialite")
        assert (self.linesLayer.isValid())
        self.pointsLayer2 = QgsVectorLayer(
            "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2",
            "spatialite")
        assert (self.pointsLayer2.isValid())
        self.pointsLayer.setDependencies(
            [QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies(
            [QgsMapLayerDependency(self.pointsLayer.id())])
        # this should update connections between layers
        QgsProject.instance().addMapLayers([self.pointsLayer])
        QgsProject.instance().addMapLayers([self.linesLayer])
        QgsProject.instance().addMapLayers([self.pointsLayer2])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(
            self.pointsLayer,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        cfg.setIndividualLayerSettings(
            self.pointsLayer2,
            QgsSnappingConfig.IndividualLayerSettings(True,
                                                      QgsSnappingConfig.Vertex,
                                                      20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(4)
        geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is OK
        m = u.snapToMap(QPoint(75, 100 - 0))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.8, 0.0))

        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Ejemplo n.º 8
0
    def canvasReleaseEvent(self, event):

        if not self.mouse_clicked:
            return

        if event.button() == Qt.LeftButton:

            self.mouse_clicked = False

            # No pipe snapped: notify user
            if self.snapped_pipe_id is None:

                self.iface.messageBar().pushMessage(Parameters.plug_in_name, 'You need to snap the cursor to a pipe to add a valve.', Qgis.Info, 5)

            # A pipe has been snapped
            else:

                request = QgsFeatureRequest().setFilterFid(self.snapped_pipe_id)
                feats = self.params.pipes_vlay.getFeatures(request)
                features = [feat for feat in feats]
                if len(features) == 1:

                    # Check whether the pipe has a start and an end node
                    (start_node, end_node) = NetworkUtils.find_start_end_nodes(self.params, features[0].geometry())

                    if not start_node or not end_node:
                        self.iface.messageBar().pushMessage(Parameters.plug_in_name, 'The pipe is missing the start or end nodes.', Qgis.Warning, 5)      # TODO: softcode
                        return

                    # Find endnode closest to valve position
                    dist_1 = start_node.geometry().distance(QgsGeometry.fromPointXY(self.snapped_vertex))
                    dist_2 = end_node.geometry().distance(QgsGeometry.fromPointXY(self.snapped_vertex))

                    # Get the attributes of the closest junction
                    (start_node, end_node) = NetworkUtils.find_start_end_nodes(self.params, features[0].geometry(), False, True, True)
                    if dist_1 < dist_2:
                        closest_junction_ft = start_node
                    else:
                        closest_junction_ft = end_node

                    # Create the valve
                    diameter = features[0].attribute(Pipe.field_name_diameter)
                    # diameter = self.data_dock.txt_valve_diameter.text()
                    minor_loss = self.data_dock.txt_valve_minor_loss.text()
                    selected_type = self.data_dock.cbo_valve_type.itemData(self.data_dock.cbo_valve_type.currentIndex())
                    if selected_type != Valve.type_gpv:
                        setting = self.data_dock.txt_valve_setting.text()
                    else:
                        valve_curve = self.data_dock.cbo_valve_curve.itemData(self.data_dock.cbo_valve_curve.currentIndex())
                        if valve_curve is not None:
                            setting = valve_curve.id
                        else:
                            setting = None

                    # Pump status
                    valve_status = self.data_dock.cbo_valve_status.itemData(
                        self.data_dock.cbo_valve_status.currentIndex())

                    # Valve description
                    valve_desc = self.data_dock.txt_valve_desc.text()

                    # Valve tag
                    valve_tag = self.data_dock.cbo_valve_tag.currentText()

                    try:
                        LinkHandler.create_new_pumpvalve(
                            self.params,
                            self.data_dock,
                            features[0],
                            closest_junction_ft,
                            self.snapped_vertex,
                            self.params.valves_vlay,
                            {Valve.field_name_diameter: diameter,
                             Valve.field_name_minor_loss: minor_loss,
                             Valve.field_name_setting: setting,
                             Valve.field_name_type: selected_type,
                             Valve.field_name_status: valve_status,
                             Valve.field_name_description: valve_desc,
                             Valve.field_name_tag: valve_tag})

                    except PumpValveCreationException as ex:
                        self.iface.messageBar().pushMessage(
                            Parameters.plug_in_name,
                            ', '.join(ex.args),
                            Qgis.Info,
                            5)

        elif event.button() == Qt.RightButton:

            self.mouse_clicked = False

            # Check whether it clicked on a valve vertex
            if len(NetworkUtils.find_adjacent_links(self.params, self.snapped_vertex)['valves']) == 0 or self.snapped_pipe_id is None:
                return

            menu = QMenu()
            diameter_action = menu.addAction('Change diameter...')  # TODO: softcode
            invert_action = menu.addAction('Flip orientation')  # TODO: softcode
            action = menu.exec_(self.iface.mapCanvas().mapToGlobal(QPoint(event.pos().x(), event.pos().y())))

            request = QgsFeatureRequest().setFilterFid(self.snapped_pipe_id)
            feats = self.params.pipes_vlay.getFeatures(request)
            features = [feat for feat in feats]
            if len(features) == 1:
                adj_links = NetworkUtils.find_links_adjacent_to_link(
                    self.params, self.params.pipes_vlay, features[0], True, True, False)

                for valve_ft in adj_links['valves']:

                    if action == diameter_action:
                        old_diam = valve_ft.attribute(Valve.field_name_diameter)
                        self.diameter_dialog = DiameterDialog(self.iface.mainWindow(), self.params, old_diam)
                        self.diameter_dialog.exec_()  # Exec creates modal dialog
                        new_diameter = self.diameter_dialog.get_diameter()
                        if new_diameter is None:
                            return

                        # Update valve diameter
                        vector_utils.update_attribute(self.params.valves_vlay, valve_ft, Valve.field_name_diameter, new_diameter)

                        # Modify pipes diameters
                        adj_pipes_fts = NetworkUtils.find_links_adjacent_to_link(
                            self.params, self.params.valves_vlay, valve_ft, False, True, True)

                        if adj_pipes_fts:

                            for adj_pipe_ft in adj_pipes_fts['pipes']:

                                vector_utils.update_attribute(self.params.pipes_vlay,
                                                              adj_pipe_ft,
                                                              Pipe.field_name_diameter,
                                                              new_diameter)

                            self.iface.messageBar().pushMessage(
                                Parameters.plug_in_name,
                                'Diameters of pipes adjacent to valve updated.',
                                Qgis.Info,
                                5)  # TODO: softcode

                    elif action == invert_action:

                        request = QgsFeatureRequest().setFilterFid(self.snapped_pipe_id)
                        feats = self.params.pipes_vlay.getFeatures(request)
                        features = [feat for feat in feats]
                        if len(features) == 1:
                            adj_links = NetworkUtils.find_links_adjacent_to_link(
                                self.params, self.params.pipes_vlay, features[0], True, True, False)

                            for adj_link in adj_links['valves']:
                                adj_link_pts = adj_link.geometry().asPolyline()
                                for adj_link_pt in adj_link_pts:
                                    if NetworkUtils.points_overlap(adj_link_pt, self.snapped_vertex,
                                                                   self.params.tolerance):

                                        geom = adj_link.geometry()

                                        if geom.wkbType() == QgsWkbTypes.MultiLineString:
                                            nodes = geom.asMultiPolyline()
                                            for line in nodes:
                                                line.reverse()
                                            newgeom = QgsGeometry.fromMultiPolylineXY(nodes)
                                            self.params.valves_vlay.changeGeometry(adj_link.id(), newgeom)

                                        if geom.wkbType() == QgsWkbTypes.LineString:
                                            nodes = geom.asPolyline()
                                            nodes.reverse()
                                            newgeom = QgsGeometry.fromPolylineXY(nodes)
                                            self.params.valves_vlay.changeGeometry(adj_link.id(), newgeom)

                                        self.iface.mapCanvas().refresh()

                                        break

            self.iface.mapCanvas().refresh()
Ejemplo n.º 9
0
    def testInteraction(self):  # pylint: disable=too-many-statements
        """
        Test tool interaction
        """
        canvas = QgsMapCanvas()
        canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326))
        canvas.setFrameStyle(0)
        canvas.resize(600, 400)
        self.assertEqual(canvas.width(), 600)
        self.assertEqual(canvas.height(), 400)

        layer = QgsVectorLayer("Polygon?crs=epsg:4326&field=fldtxt:string",
                               "layer", "memory")
        f = QgsFeature()
        f.setAttributes(['a'])
        f.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 32, 15, 45)))
        f2 = QgsFeature()
        f2.setAttributes(['b'])
        f2.setGeometry(QgsGeometry.fromRect(QgsRectangle(15, 25, 18, 45)))
        success, (f, f2) = layer.dataProvider().addFeatures([f, f2])
        self.assertTrue(success)

        canvas.setLayers([layer])
        canvas.setExtent(QgsRectangle(10, 30, 20, 35))
        canvas.show()

        handler = RedistrictHandler(layer, 'fldtxt')
        factory = DecoratorFactory()
        registry = DistrictRegistry(districts=['a', 'b'])
        tool = InteractiveRedistrictingTool(canvas,
                                            handler,
                                            district_registry=registry,
                                            decorator_factory=factory)

        # mouse over a feature's interior
        point = canvas.mapSettings().mapToPixel().transform(20, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertFalse(tool.is_active)
        self.assertFalse(tool.snap_indicator.match().isValid())
        # mouse over a single feature's boundary (not valid district boundary)
        point = canvas.mapSettings().mapToPixel().transform(5, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertFalse(tool.is_active)
        self.assertFalse(tool.snap_indicator.match().isValid())
        # mouse over a two feature's boundary (valid district boundary)
        point = canvas.mapSettings().mapToPixel().transform(15, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertFalse(tool.is_active)
        self.assertTrue(tool.snap_indicator.match().isValid())

        # avoid segfault
        tool.snap_indicator.setMatch(QgsPointLocator.Match())

        # clicks to ignore
        point = canvas.mapSettings().mapToPixel().transform(10, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.MidButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.RightButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)

        # click over bad area
        point = canvas.mapSettings().mapToPixel().transform(10, 30)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.LeftButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)

        # click over feature area
        layer.startEditing()
        point = canvas.mapSettings().mapToPixel().transform(10, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.LeftButton)
        tool.canvasPressEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.click_point.x(), 10)
        self.assertEqual(tool.click_point.y(), 33)
        self.assertEqual(tool.districts, {'a'})
        self.assertFalse(tool.modified)

        # now move over current feature - should do nothing!
        point = canvas.mapSettings().mapToPixel().transform(10, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertFalse(tool.modified)

        # move over other feature
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')
        point = canvas.mapSettings().mapToPixel().transform(16, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.modified, {f2.id()})
        self.assertEqual(tool.current_district, 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'a')

        # move over nothing
        point = canvas.mapSettings().mapToPixel().transform(26, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.modified, {f2.id()})

        # left click - commit changes
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.LeftButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)

        layer.rollBack()
        layer.startEditing()

        # add a decorator
        tool.decorator_factory = TestDecoratorFactory()

        # now try with clicks over boundary
        point = canvas.mapSettings().mapToPixel().transform(15, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.LeftButton)
        tool.canvasPressEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.click_point.x(), 15)
        self.assertEqual(tool.click_point.y(), 33)
        self.assertEqual(tool.districts, {'a', 'b'})
        self.assertFalse(tool.modified)

        # move left
        self.assertEqual(layer.getFeature(f.id())[0], 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')
        point = canvas.mapSettings().mapToPixel().transform(10, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.modified, {f.id()})
        self.assertEqual(tool.current_district, 'b')
        self.assertEqual(layer.getFeature(f.id())[0], 'b')
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')

        # move over nothing
        point = canvas.mapSettings().mapToPixel().transform(26, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.modified, {f.id()})

        # right click - discard changes
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.RightButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)
        self.assertEqual(layer.getFeature(f.id())[0], 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')

        # try again, move right
        point = canvas.mapSettings().mapToPixel().transform(15, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.LeftButton)
        tool.canvasPressEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.click_point.x(), 15)
        self.assertEqual(tool.click_point.y(), 33)
        self.assertEqual(tool.districts, {'a', 'b'})
        self.assertFalse(tool.modified)
        # move right
        self.assertEqual(layer.getFeature(f.id())[0], 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')
        point = canvas.mapSettings().mapToPixel().transform(17, 33)
        event = QgsMapMouseEvent(canvas, QEvent.MouseMove,
                                 QPoint(point.x(), point.y()))
        tool.canvasMoveEvent(event)
        self.assertTrue(tool.is_active)
        self.assertEqual(tool.modified, {f2.id()})
        self.assertEqual(tool.current_district, 'a')
        self.assertEqual(layer.getFeature(f.id())[0], 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'a')
        event = QgsMapMouseEvent(canvas, QEvent.MouseButtonPress,
                                 QPoint(point.x(), point.y()), Qt.RightButton)
        tool.canvasPressEvent(event)
        self.assertFalse(tool.is_active)
        self.assertEqual(layer.getFeature(f.id())[0], 'a')
        self.assertEqual(layer.getFeature(f2.id())[0], 'b')

        layer.rollBack()
Ejemplo n.º 10
0
 def zoomActual(self):
     point = self.view.mapToScene(QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2))
     self.view.resetTransform()
     self.view.scale(QgsApplication.desktop().logicalDpiX() / 96, QgsApplication.desktop().logicalDpiX() / 96)
     self.view.centerOn(point)
Ejemplo n.º 11
0
 def popup(self, pos, action = None):
    newPos = QPoint(pos.x() + self.offset, pos.y() + self.offset)
    QMenu.popup(self, newPos, action)
Ejemplo n.º 12
0
 def canvasPressEvent(self, e):
     self.drugging = True
     point = QPoint(e.pos().x(), e.pos().y())
     self.callback(point)
     return None
    def search_data(self, **kwargs):
        """
        Get plot geometries associated with parcels, both collected and official, zoom to them, activate map swipe tool
            and fill comparison table.

        :param kwargs: key-value (field name-field value) to search in parcel tables, both collected and official
                       Normally, keys are parcel_number, old_parcel_number or FMI, but if duplicates are found, an
                       additional t_id disambiguates only for the collected source. In the Official source we assume
                       we will not find duplicates, if there are, we will choose the first record found an will not deal
                       with letting the user choose one of the duplicates by hand (as we do for the collected source).
        """
        self.chk_show_all_plots.setEnabled(False)
        self.chk_show_all_plots.setChecked(True)
        self.initialize_tools_and_layers()  # Reset any filter on layers
        already_zoomed_in = False

        self.clear_result_table()

        search_field = self.cbo_parcel_fields.currentData()
        search_value = list(kwargs.values())[0]

        # Get OFFICIAL parcel's t_id and get related plot(s)
        expression = QgsExpression("{}='{}'".format(search_field,
                                                    search_value))
        request = QgsFeatureRequest(expression)
        field_idx = self.utils._official_layers[PARCEL_TABLE][LAYER].fields(
        ).indexFromName(ID_FIELD)
        request.setFlags(QgsFeatureRequest.NoGeometry)
        request.setSubsetOfAttributes([field_idx
                                       ])  # Note: this adds a new flag
        official_parcels = [
            feature for feature in self.utils._official_layers[PARCEL_TABLE]
            [LAYER].getFeatures(request)
        ]

        if len(official_parcels) > 1:
            # We do not expect duplicates in the official source!
            pass  # We'll choose the first one anyways
        elif len(official_parcels) == 0:
            print("No parcel found!", search_field, search_value)

        official_plot_t_ids = []
        if official_parcels:
            official_plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels(
                self.utils._official_db, [official_parcels[0][ID_FIELD]],
                field_name=ID_FIELD,
                plot_layer=self.utils._official_layers[PLOT_TABLE][LAYER],
                uebaunit_table=self.utils._official_layers[UEBAUNIT_TABLE]
                [LAYER])

            if official_plot_t_ids:
                self._current_official_substring = "\"{}\" IN ('{}')".format(
                    ID_FIELD,
                    "','".join([str(t_id) for t_id in official_plot_t_ids]))
                self.parent.request_zoom_to_features(
                    self.utils._official_layers[PLOT_TABLE][LAYER], list(),
                    official_plot_t_ids)
                already_zoomed_in = True

        # Now get COLLECTED parcel's t_id and get related plot(s)
        collected_parcel_t_id = None
        if 'collected_parcel_t_id' in kwargs:
            # This is the case when this panel is called and we already know the parcel number is duplicated
            collected_parcel_t_id = kwargs['collected_parcel_t_id']
            search_criterion_collected = {
                ID_FIELD: collected_parcel_t_id
            }  # As there are duplicates, we need to use t_ids
        else:
            # This is the case when:
            #   + Either this panel was called and we know the parcel number is not duplicated, or
            #   + This panel was shown without knowing about duplicates (e.g., individual parcel search) and we still
            #     need to discover whether we have duplicates for this search criterion
            search_criterion_collected = {search_field: search_value}

            request = QgsFeatureRequest(expression)
            request.setFlags(QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes(
                [ID_FIELD], self.utils._layers[PARCEL_TABLE]
                [LAYER].fields())  # Note this adds a new flag
            collected_parcels = self.utils._layers[PARCEL_TABLE][
                LAYER].getFeatures(request)
            collected_parcels_t_ids = [
                feature[ID_FIELD] for feature in collected_parcels
            ]

            if collected_parcels_t_ids:
                collected_parcel_t_id = collected_parcels_t_ids[0]
                if len(collected_parcels_t_ids
                       ) > 1:  # Duplicates in collected source after a search
                    QApplication.restoreOverrideCursor(
                    )  # Make sure cursor is not waiting (it is if on an identify)
                    QCoreApplication.processEvents()
                    dlg_select_parcel = SelectDuplicateParcelDialog(
                        self.utils, collected_parcels_t_ids, self.parent)
                    dlg_select_parcel.exec_()

                    if dlg_select_parcel.parcel_t_id:  # User selected one of the duplicated parcels
                        collected_parcel_t_id = dlg_select_parcel.parcel_t_id
                        search_criterion_collected = {
                            ID_FIELD: collected_parcel_t_id
                        }
                    else:
                        return  # User just cancelled the dialog, there is nothing more to do

        search_criterion_official = {search_field: search_value}

        self.fill_table(search_criterion_official, search_criterion_collected)

        if collected_parcel_t_id is not None:
            plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels(
                self.utils._db, [collected_parcel_t_id],
                field_name=ID_FIELD,
                plot_layer=self.utils._layers[PLOT_TABLE][LAYER],
                uebaunit_table=self.utils._layers[UEBAUNIT_TABLE][LAYER])
            if plot_t_ids:
                self._current_substring = "{} IN ('{}')".format(
                    ID_FIELD, "','".join([str(t_id) for t_id in plot_t_ids]))
                if not already_zoomed_in:
                    self.parent.request_zoom_to_features(
                        self.utils._layers[PLOT_TABLE][LAYER], list(),
                        plot_t_ids)

                # Send a custom mouse move on the map to make the map swipe tool's limit appear on the canvas

                # Activate Swipe Tool
                self.utils.qgis_utils.activate_layer_requested.emit(
                    self.utils._official_layers[PLOT_TABLE][LAYER])
                if official_plot_t_ids:  # Otherwise the map swipe tool doesn't add any value :)
                    self.parent.activate_map_swipe_tool()

                    plots = self.utils.ladm_data.get_features_from_t_ids(
                        self.utils._layers[PLOT_TABLE][LAYER], plot_t_ids,
                        True)
                    plots_extent = QgsRectangle()
                    for plot in plots:
                        plots_extent.combineExtentWith(
                            plot.geometry().boundingBox())

                    coord_x = plots_extent.xMaximum() - (plots_extent.xMaximum(
                    ) - plots_extent.xMinimum()) / 9  # 90%
                    coord_y = plots_extent.yMaximum() - (plots_extent.yMaximum(
                    ) - plots_extent.yMinimum()) / 2  # 50%

                    coord_transform = self.utils.iface.mapCanvas(
                    ).getCoordinateTransform()
                    map_point = coord_transform.transform(coord_x, coord_y)
                    widget_point = map_point.toQPointF().toPoint()
                    global_point = self.utils.canvas.mapToGlobal(widget_point)

                    self.utils.canvas.mousePressEvent(
                        QMouseEvent(QEvent.MouseButtonPress, global_point,
                                    Qt.LeftButton, Qt.LeftButton,
                                    Qt.NoModifier))
                    self.utils.canvas.mouseMoveEvent(
                        QMouseEvent(QEvent.MouseMove,
                                    widget_point + QPoint(1, 0), Qt.NoButton,
                                    Qt.LeftButton, Qt.NoModifier))
                    self.utils.canvas.mouseReleaseEvent(
                        QMouseEvent(QEvent.MouseButtonRelease,
                                    widget_point + QPoint(1, 0), Qt.LeftButton,
                                    Qt.LeftButton, Qt.NoModifier))

        # Once the query is done, activate the checkbox to alternate all plots/only selected plot
        self.chk_show_all_plots.setEnabled(True)
Ejemplo n.º 14
0
 def canvasPressEvent(self, event):
     self.pressed.emit(QPoint(event.pos().x(), event.pos().y()))
Ejemplo n.º 15
0
 def dock_pos(cls):
     settings = cls.get_settings()
     return settings.value('/ui/dockWidgetPos',
                           QPoint(500, 500),
                           type=QPoint)
Ejemplo n.º 16
0
 def updateVideoRect(self):
     ''' Update video rectangle '''
     size = self.surfaceFormat().sizeHint()
     size.scale(self.widget.size().boundedTo(size), Qt.KeepAspectRatio)
     self._targetRect = QRect(QPoint(0, 0), size)
     self._targetRect.moveCenter(self.widget.rect().center())
Ejemplo n.º 17
0
    def search_data(self, **kwargs):
        """
        Get plot geometries associated with parcels, both collected and supplies, zoom to them, fill comparison table
        and activate map swipe tool.

        To fill the comparison table we build two search dicts, one for supplies (already given because the alphanumeric
        search is on supplies db source), and another one for collected. For the latter, we have 3 cases. We specify
        them below (inline).

        :param kwargs: key-value (field name-field value) to search in parcel tables, both collected and supplies
                       Normally, keys are parcel_number, old_parcel_number or FMI, but if duplicates are found, an
                       additional t_id disambiguates only for the collected source. In the supplies source we assume
                       we will not find duplicates, if there are, we will choose the first record found an will not deal
                       with letting the user choose one of the duplicates by hand (as we do for the collected source).
        """
        self.chk_show_all_plots.setEnabled(False)
        self.chk_show_all_plots.setChecked(True)
        self.initialize_tools_and_layers()  # Reset any filter on layers

        plots_supplies = list()
        plots_collected = list()
        self.clear_result_table()

        search_option = self.cbo_parcel_fields.currentData()
        search_field_supplies = get_supplies_search_options(self.utils._supplies_db.names)[search_option]
        search_field_collected = get_collected_search_options(self.utils._db.names)[search_option]
        search_value = list(kwargs.values())[0]


        # Build search criterion for both supplies and collected
        search_criterion_supplies = {search_field_supplies: search_value}

        # Get supplies parcel's t_id and get related plot(s)
        expression_supplies = QgsExpression("{}='{}'".format(search_field_supplies, search_value))
        request = QgsFeatureRequest(expression_supplies)
        field_idx = self.utils._supplies_layers[self.utils._supplies_db.names.GC_PARCEL_T][LAYER].fields().indexFromName(self.utils._supplies_db.names.T_ID_F)
        request.setFlags(QgsFeatureRequest.NoGeometry)
        request.setSubsetOfAttributes([field_idx])  # Note: this adds a new flag
        supplies_parcels = [feature for feature in self.utils._supplies_layers[self.utils._supplies_db.names.GC_PARCEL_T][LAYER].getFeatures(request)]

        if len(supplies_parcels) > 1:
            # We do not expect duplicates in the supplies source!
            pass  # We'll choose the first one anyways
        elif len(supplies_parcels) == 0:
            self.logger.info(__name__, "No supplies parcel found! Search: {}={}".format(search_field_supplies, search_value))

        supplies_plot_t_ids = []
        if supplies_parcels:
            supplies_plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels_supplies(self.utils._supplies_db,
                                              [supplies_parcels[0][self.utils._supplies_db.names.T_ID_F]],
                                              self.utils._supplies_db.names.T_ID_F,
                                              self.utils._supplies_layers[self.utils._supplies_db.names.GC_PLOT_T][LAYER])

            if supplies_plot_t_ids:
                self._current_supplies_substring = "\"{}\" IN ('{}')".format(self.utils._supplies_db.names.T_ID_F, "','".join([str(t_id) for t_id in supplies_plot_t_ids]))
                plots_supplies = self.utils.ladm_data.get_features_from_t_ids(
                    self.utils._supplies_layers[self.utils._supplies_db.names.GC_PLOT_T][LAYER],
                    self.utils._supplies_db.names.T_ID_F, supplies_plot_t_ids, True)


        # Now get COLLECTED parcel's t_id to build the search dict for collected
        collected_parcel_t_id = None
        if 'collected_parcel_t_id' in kwargs:
            # This is the case when this panel is called and we already know the parcel number is duplicated
            collected_parcel_t_id = kwargs['collected_parcel_t_id']
            search_criterion_collected = {self.utils._db.names.T_ID_F: collected_parcel_t_id}  # As there are duplicates, we need to use t_ids
        else:
            # This is the case when:
            #   + Either this panel was called and we know the parcel number is not duplicated, or
            #   + This panel was shown without knowing about duplicates (e.g., individual parcel search) and we still
            #     need to discover whether we have duplicates for this search criterion
            search_criterion_collected = {search_field_collected: search_value}

            expression_collected = QgsExpression("{}='{}'".format(search_field_collected, search_value))
            request = QgsFeatureRequest(expression_collected)
            request.setFlags(QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes([self.utils._db.names.T_ID_F],
                                          self.utils._layers[self.utils._db.names.OP_PARCEL_T][LAYER].fields())  # Note this adds a new flag
            collected_parcels = self.utils._layers[self.utils._db.names.OP_PARCEL_T][LAYER].getFeatures(request)
            collected_parcels_t_ids = [feature[self.utils._db.names.T_ID_F] for feature in collected_parcels]

            if collected_parcels_t_ids:
                collected_parcel_t_id = collected_parcels_t_ids[0]
                if len(collected_parcels_t_ids) > 1:  # Duplicates in collected source after a search
                    QApplication.restoreOverrideCursor()  # Make sure cursor is not waiting (it is if on an identify)
                    QCoreApplication.processEvents()
                    dlg_select_parcel = SelectDuplicateParcelDialog(self.utils, collected_parcels_t_ids, self.parent)
                    dlg_select_parcel.exec_()

                    if dlg_select_parcel.parcel_t_id:  # User selected one of the duplicated parcels
                        collected_parcel_t_id = dlg_select_parcel.parcel_t_id
                        search_criterion_collected = {self.utils._db.names.T_ID_F: collected_parcel_t_id}
                    else:
                        return  # User just cancelled the dialog, there is nothing more to do


        self.fill_table(search_criterion_supplies, search_criterion_collected)

        # Now get related plot(s) for both collected and supplies,
        if collected_parcel_t_id is not None:
            plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels(self.utils._db,
                                                                           [collected_parcel_t_id],
                                                                           self.utils._db.names.T_ID_F,
                                                                           plot_layer=self.utils._layers[self.utils._db.names.OP_PLOT_T][LAYER],
                                                                           uebaunit_table=self.utils._layers[self.utils._db.names.COL_UE_BAUNIT_T][LAYER])

            if plot_t_ids:
                self._current_substring = "{} IN ('{}')".format(self.utils._db.names.T_ID_F, "','".join([str(t_id) for t_id in plot_t_ids]))
                plots_collected = self.utils.ladm_data.get_features_from_t_ids(self.utils._layers[self.utils._db.names.OP_PLOT_T][LAYER],
                                                                               self.utils._db.names.T_ID_F,
                                                                               plot_t_ids,
                                                                               True)

        # Zoom to combined extent
        plot_features = plots_supplies + plots_collected  # Feature list
        plots_extent = QgsRectangle()
        for plot in plot_features:
            plots_extent.combineExtentWith(plot.geometry().boundingBox())

        if not plots_extent.isEmpty():
            self.utils.iface.mapCanvas().zoomToFeatureExtent(plots_extent)

            if plots_supplies and plots_collected:  # Otherwise the map swipe tool doesn't add any value :)
                # Activate Swipe Tool
                self.utils.qgis_utils.activate_layer_requested.emit(self.utils._supplies_layers[self.utils._supplies_db.names.GC_PLOT_T][LAYER])
                self.parent.activate_map_swipe_tool()

                # Send a custom mouse move on the map to make the map swipe tool's limit appear on the canvas
                coord_x = plots_extent.xMaximum() - (plots_extent.xMaximum() - plots_extent.xMinimum()) / 9  # 90%
                coord_y = plots_extent.yMaximum() - (plots_extent.yMaximum() - plots_extent.yMinimum()) / 2  # 50%

                coord_transform = self.utils.iface.mapCanvas().getCoordinateTransform()
                map_point = coord_transform.transform(coord_x, coord_y)
                widget_point = map_point.toQPointF().toPoint()
                global_point = self.utils.canvas.mapToGlobal(widget_point)

                self.utils.canvas.mousePressEvent(QMouseEvent(QEvent.MouseButtonPress, global_point, Qt.LeftButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseMoveEvent(QMouseEvent(QEvent.MouseMove, widget_point + QPoint(1,0), Qt.NoButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseReleaseEvent(QMouseEvent(QEvent.MouseButtonRelease, widget_point + QPoint(1,0), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier))

        # Once the query is done, activate the checkbox to alternate all plots/only selected plot
        self.chk_show_all_plots.setEnabled(True)
Ejemplo n.º 18
0
    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.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)

        # Cursor Canvas Rubberband
        self.Cursor_Canvas_RubberBand = QgsRubberBand(
            iface.mapCanvas(), QgsWkbTypes.PointGeometry)
        self.Cursor_Canvas_RubberBand.setWidth(4)
        self.Cursor_Canvas_RubberBand.setColor(QColor(255, 100, 100, 250))
        self.Cursor_Canvas_RubberBand.setIcon(QgsRubberBand.ICON_FULL_DIAMOND)

        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)

        self.lastMouseX = -1
        self.lastMouseY = -1
Ejemplo n.º 19
0
 def zoomActual(self):
     point = self.view.mapToScene(QPoint(self.view.viewport().width() / 2, self.view.viewport().height() / 2))
     self.view.resetTransform()
     self.view.centerOn(point)
Ejemplo n.º 20
0
 def RestoreDrawer(self):
     ''' Remove and restore all Drawer Options '''
     self._interaction.clear()
     # Magnifier Glass
     self.dragPos = QPoint()
     self.tapTimer.stop()
Ejemplo n.º 21
0
    def test_resetSnappingIndex(self):
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(self.pointsLayer,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)

        m = u.snapToMap(QPoint(95, 100))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(1, 0))

        f = QgsFeature(self.linesLayer.fields())
        f.setId(1)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()

        l1 = len([f for f in self.pointsLayer.getFeatures()])
        self.assertEqual(l1, 4)
        m = u.snapToMap(QPoint(95, 0))
        # snapping not updated
        self.pointsLayer.setDependencies([])
        self.assertEqual(m.isValid(), False)

        # set layer dependencies
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(2)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the snapped point is OK
        m = u.snapToMap(QPoint(45, 50))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.5, 0.5))
        self.pointsLayer.setDependencies([])

        # test chained layer dependencies A -> B -> C
        cfg.setIndividualLayerSettings(self.pointsLayer2,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(3)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is OK
        m = u.snapToMap(QPoint(75, 100 - 80))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.7, 0.8))
        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Ejemplo n.º 22
0
    def test_tool(self):
        """
        Test some plot tool logic
        """
        canvas = QgsElevationProfileCanvas()
        canvas.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
        canvas.setFrameStyle(0)
        canvas.resize(600, 400)
        canvas.setProject(QgsProject.instance())
        canvas.show()
        self.assertEqual(canvas.width(), 600)
        self.assertEqual(canvas.height(), 400)
        ls = QgsLineString()
        ls.fromWkt('LineString(0 2, 10 2, 10 4)')
        canvas.setProfileCurve(ls)
        canvas.setVisiblePlotRange(0, ls.length(), 0, 100)

        self.assertFalse(canvas.tool())
        tool = TestTool(canvas)
        self.assertFalse(tool.isActive())
        canvas.setTool(tool)
        self.assertEqual(canvas.tool(), tool)

        key_press_event = QKeyEvent(QEvent.KeyPress, 54, Qt.ShiftModifier)
        canvas.keyPressEvent(key_press_event)
        self.assertEqual(tool.events[-1].type(), QEvent.KeyPress)

        key_release_event = QKeyEvent(QEvent.KeyRelease, 54, Qt.ShiftModifier)
        canvas.keyReleaseEvent(key_release_event)
        self.assertEqual(tool.events[-1].type(), QEvent.KeyRelease)

        mouse_dbl_click_event = QMouseEvent(QEvent.MouseButtonDblClick,
                                            QPointF(300, 200), Qt.LeftButton,
                                            Qt.MouseButtons(),
                                            Qt.ShiftModifier)
        canvas.mouseDoubleClickEvent(mouse_dbl_click_event)
        self.assertEqual(tool.events[-1].type(), QEvent.MouseButtonDblClick)
        self.assertIsInstance(tool.events[-1], QgsPlotMouseEvent)
        self.assertAlmostEqual(tool.events[-1].mapPoint().x(), 5.92, 1)
        self.assertAlmostEqual(tool.events[-1].mapPoint().y(), 2, 4)
        self.assertAlmostEqual(tool.events[-1].mapPoint().z(), 49.165, 0)

        mouse_move_event = QMouseEvent(QEvent.MouseMove,
                                       QPointF(300, 200), Qt.LeftButton,
                                       Qt.MouseButtons(), Qt.ShiftModifier)
        canvas.mouseMoveEvent(mouse_move_event)
        self.assertEqual(tool.events[-1].type(), QEvent.MouseMove)
        self.assertIsInstance(tool.events[-1], QgsPlotMouseEvent)
        self.assertAlmostEqual(tool.events[-1].mapPoint().x(), 5.92, 1)
        self.assertAlmostEqual(tool.events[-1].mapPoint().y(), 2, 4)
        self.assertAlmostEqual(tool.events[-1].mapPoint().z(), 49.165, 0)

        mouse_press_event = QMouseEvent(QEvent.MouseButtonPress,
                                        QPointF(300, 200), Qt.LeftButton,
                                        Qt.MouseButtons(), Qt.ShiftModifier)
        canvas.mousePressEvent(mouse_press_event)
        self.assertEqual(tool.events[-1].type(), QEvent.MouseButtonPress)
        self.assertIsInstance(tool.events[-1], QgsPlotMouseEvent)
        self.assertAlmostEqual(tool.events[-1].mapPoint().x(), 5.927, 1)
        self.assertAlmostEqual(tool.events[-1].mapPoint().y(), 2, 4)
        self.assertAlmostEqual(tool.events[-1].mapPoint().z(), 49.165, 0)

        mouse_release_event = QMouseEvent(QEvent.MouseButtonRelease,
                                          QPointF(300, 200), Qt.LeftButton,
                                          Qt.MouseButtons(), Qt.ShiftModifier)
        canvas.mouseReleaseEvent(mouse_release_event)
        self.assertEqual(tool.events[-1].type(), QEvent.MouseButtonRelease)
        self.assertIsInstance(tool.events[-1], QgsPlotMouseEvent)
        self.assertAlmostEqual(tool.events[-1].mapPoint().x(), 5.927, 1)
        self.assertAlmostEqual(tool.events[-1].mapPoint().y(), 2, 4)
        self.assertAlmostEqual(tool.events[-1].mapPoint().z(), 49.165, 0)

        wheel_event = QWheelEvent(QPointF(300, 200), QPointF(300, 200),
                                  QPoint(1, 2), QPoint(3, 4), Qt.NoButton,
                                  Qt.NoModifier, Qt.ScrollBegin, False)
        canvas.wheelEvent(wheel_event)
        self.assertEqual(tool.events[-1].type(), QEvent.Wheel)