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([])
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)
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)
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([])
def canvasPressEvent(self, event): self.pressed.emit(QPoint(event.pos().x(), event.pos().y()))
def canvasMoveEvent(self, event): self.moved.emit(QPoint(event.pos().x(), event.pos().y()))
def popup(self, pos, action=None): newPos = QPoint(pos.x() + self.offset, pos.y() + self.offset) QMenu.popup(self, newPos, action)
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)
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)