def prepare_identify_plot(self): """ Custom Identify tool was activated, prepare everything for identifying plots """ self.active_map_tool_before_custom = self.utils.canvas.mapTool() self.btn_identify_plot.setChecked(True) self.utils.canvas.mapToolSet.connect(self.initialize_maptool) if self.utils._supplies_layers[ self.utils._supplies_db.names.GC_PLOT_T] is None: self.utils.add_layers() self.maptool_identify.setLayer(self.utils._supplies_layers[ self.utils._supplies_db.names.GC_PLOT_T]) cursor = QCursor() cursor.setShape(Qt.PointingHandCursor) self.maptool_identify.setCursor(cursor) self.utils.canvas.setMapTool(self.maptool_identify) try: self.maptool_identify.featureIdentified.disconnect() except TypeError as e: pass self.maptool_identify.featureIdentified.connect(self.get_info_by_plot)
def activate(self): cursor = QCursor() cursor.setShape(Qt.ArrowCursor) self.iface.mapCanvas().setCursor(cursor) layers = { self.params.junctions_vlay: QgsSnappingConfig.Vertex, self.params.reservoirs_vlay: QgsSnappingConfig.Vertex, self.params.tanks_vlay: QgsSnappingConfig.Vertex, self.params.pipes_vlay: QgsSnappingConfig.VertexAndSegment } self.snapper = NetworkUtils.set_up_snapper(layers, self.iface.mapCanvas(), self.params.snap_tolerance) self.snapper.toggleEnabled() # Editing if not self.params.junctions_vlay.isEditable(): self.params.junctions_vlay.startEditing() if not self.params.reservoirs_vlay.isEditable(): self.params.reservoirs_vlay.startEditing() if not self.params.tanks_vlay.isEditable(): self.params.tanks_vlay.startEditing() if not self.params.pipes_vlay.isEditable(): self.params.pipes_vlay.startEditing() if not self.params.pumps_vlay.isEditable(): self.params.pumps_vlay.startEditing() if not self.params.valves_vlay.isEditable(): self.params.valves_vlay.startEditing()
def select_feature(self): self.setVisible(False) # Make wizard disappear # Create maptool self.maptool_identify = QgsMapToolIdentifyFeature(self.canvas) self.maptool_identify.setLayer(self._current_layer) cursor = QCursor() cursor.setShape(Qt.CrossCursor) self.maptool_identify.setCursor(cursor) self.canvas.setMapTool(self.maptool_identify) self.maptool_identify.featureIdentified.connect(self.get_feature_id)
def btn_sel_element_clicked(self): if self.output_reader is None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Please select the simulation out file.', Qgis.Warning, 5) # TODO: softcode return self.tool = SelectTool(self, self.params) self.iface.mapCanvas().setMapTool(self.tool) cursor = QCursor() cursor.setShape(Qt.ArrowCursor) self.iface.mapCanvas().setCursor(cursor)
def __init__(self, canvas, layer, multi=True): self.canvas = canvas QgsMapToolEmitPoint.__init__(self, self.canvas) self._multi = multi self._layer = layer # Cursor cursor = QCursor() cursor.setShape(Qt.CrossCursor) self.setCursor(cursor) # RubberBand Style self.rubberBand = QgsRubberBand(self.canvas, True) self.rubberBand.setBrushStyle(Qt.Dense4Pattern) self.rubberBand.setColor(QColor(255, 181, 92)) self.rubberBand.setStrokeColor(QColor(232, 137, 72)) self.rubberBand.setWidth(0.2) self.reset()
class TidalPredictionTool(QgsMapToolIdentify): def __init__(self, canvas, dock): super(QgsMapToolIdentify, self).__init__(canvas) self.canvas = canvas self.dock = dock self.selectionMode = self.AllLayers self.cursor = QCursor() self.cursor.setShape(Qt.ArrowCursor) self.setCursor(self.cursor) def canvasPressEvent(self, mouseEvent): return def canvasMoveEvent(self, mouseEvent): return def canvasReleaseEvent(self, mouseEvent): self.currentMoveAction = QgsMapCanvasAnnotationItem.NoAction self.setCursor(self.cursor) layers = [] currentStations = currentStationsLayer() if currentStations is not None: layers.append(currentStations) results = self.identify(mouseEvent.x(), mouseEvent.y(), layers) for r in results: layer = r.mLayer if layer == currentStations: feature = r.mFeature if feature['surface'] > 0: self.dock.activate() self.dock.setCurrentStation(feature) break def activate(self): self.dock.activate() def deactivate(self): self.dock.deactivate()
def _prepare_identify_plot(self): """ Custom Identify tool was activated, prepare everything for identifying plots """ self.active_map_tool_before_custom = self.canvas.mapTool() self.btn_identify_plot.setChecked(True) self.canvas.mapToolSet.connect(self._initialize_tools) self.maptool_identify.setLayer(self._controller.plot_layer()) cursor = QCursor() cursor.setShape(Qt.PointingHandCursor) self.maptool_identify.setCursor(cursor) self.canvas.setMapTool(self.maptool_identify) try: self.maptool_identify.featureIdentified.disconnect() except TypeError as e: pass self.maptool_identify.featureIdentified.connect( self._search_data_by_plot)
class ParentMapTool(QgsMapTool): def __init__(self, iface, settings, action, index_action): """ Class constructor """ self.iface = iface self.canvas = self.iface.mapCanvas() self.settings = settings self.show_help = bool(int(self.settings.value('status/show_help', 1))) self.index_action = index_action self.layer_arc = None self.layer_connec = None self.layer_gully = None self.layer_node = None self.schema_name = None self.controller = None self.dao = None self.snapper_manager = None # Call superclass constructor and set current action QgsMapTool.__init__(self, self.canvas) self.setAction(action) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.CrossCursor) # Get default cursor # noinspection PyCallingNonCallable self.std_cursor = self.parent().cursor() # Set default vertex marker color = QColor(255, 100, 255) self.vertex_marker = QgsVertexMarker(self.canvas) self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.vertex_marker.setColor(color) self.vertex_marker.setIconSize(15) self.vertex_marker.setPenWidth(3) # Set default rubber band color_selection = QColor(254, 178, 76, 63) self.rubber_band = QgsRubberBand(self.canvas, 2) self.rubber_band.setColor(color) self.rubber_band.setFillColor(color_selection) self.rubber_band.setWidth(1) self.reset() self.force_active_layer = True def get_cursor_multiple_selection(self): """ Set cursor for multiple selection """ path_folder = os.path.join(os.path.dirname(__file__), os.pardir) path_cursor = os.path.join(path_folder, 'icons', '201.png') if os.path.exists(path_cursor): cursor = QCursor(QPixmap(path_cursor)) else: cursor = QCursor(Qt.ArrowCursor) return cursor def set_controller(self, controller): self.controller = controller self.schema_name = controller.schema_name self.plugin_dir = self.controller.plugin_dir if self.snapper_manager is None: self.snapper_manager = SnappingConfigManager(self.iface) self.snapper_manager.controller = controller def deactivate(self): # Uncheck button self.action().setChecked(False) # Restore previous snapping self.snapper_manager.recover_snapping_options() # Enable snapping self.snapper_manager.enable_snapping(True) # Recover cursor self.canvas.setCursor(self.std_cursor) # Remove highlight self.vertex_marker.hide() def recover_previus_maptool(self): if self.controller.prev_maptool: self.iface.mapCanvas().setMapTool(self.controller.prev_maptool) self.controller.prev_maptool = None def remove_vertex(self): """ Remove vertex_marker from canvas""" vertex_items = [ i for i in self.iface.mapCanvas().scene().items() if issubclass(type(i), QgsVertexMarker) ] for ver in vertex_items: if ver in self.iface.mapCanvas().scene().items(): if self.vertex_marker == ver: self.iface.mapCanvas().scene().removeItem(ver) def set_icon(self, widget, icon): """ Set @icon to selected @widget """ # Get icons folder icons_folder = os.path.join(self.plugin_dir, 'icons') icon_path = os.path.join(icons_folder, str(icon) + ".png") if os.path.exists(icon_path): widget.setIcon(QIcon(icon_path)) else: self.controller.log_info("File not found", parameter=icon_path) def set_action_pan(self): """ Set action 'Pan' """ try: self.iface.actionPan().trigger() except Exception: pass def reset_rubber_band(self, geom_type="polygon"): try: if geom_type == "polygon": geom_type = QgsWkbTypes.PolygonGeometry elif geom_type == "line": geom_type = QgsWkbTypes.LineString self.rubber_band.reset(geom_type) except: pass def reset(self): self.reset_rubber_band() self.snapped_feat = None def cancel_map_tool(self): """ Executed if user press right button or escape key """ # Reset rubber band self.reset() # Deactivate map tool self.deactivate() self.set_action_pan() def remove_markers(self): """ Remove previous markers """ vertex_items = [ i for i in list(self.canvas.scene().items()) if issubclass(type(i), QgsVertexMarker) ] for ver in vertex_items: if ver in list(self.canvas.scene().items()): self.canvas.scene().removeItem(ver) def refresh_map_canvas(self): """ Refresh all layers present in map canvas """ self.canvas.refreshAllLayers() for layer_refresh in self.canvas.layers(): layer_refresh.triggerRepaint() def open_dialog(self, dlg=None, dlg_name=None, info=True, maximize_button=True, stay_on_top=True): """ Open dialog """ # Check database connection before opening dialog if not self.controller.check_db_connection(): return if dlg is None or type(dlg) is bool: dlg = self.dlg # Manage i18n of the dialog if dlg_name: self.controller.manage_translation(dlg_name, dlg) # Manage stay on top, maximize/minimize button and information button # if info is True maximize flag will be ignored # To enable maximize button you must set info to False flags = Qt.WindowCloseButtonHint if info: flags |= Qt.WindowSystemMenuHint | Qt.WindowContextHelpButtonHint else: if maximize_button: flags |= Qt.WindowMinMaxButtonsHint if stay_on_top: flags |= Qt.WindowStaysOnTopHint dlg.setWindowFlags(flags) # Open dialog if issubclass(type(dlg), GwDialog): dlg.open() elif issubclass(type(dlg), GwMainWindow): dlg.show() else: dlg.show() def close_dialog(self, dlg=None, set_action_pan=True): """ Close dialog """ if dlg is None or type(dlg) is bool: dlg = self.dlg try: self.save_settings(dlg) dlg.close() if set_action_pan: map_tool = self.canvas.mapTool() # If selected map tool is from the plugin, set 'Pan' as current one if map_tool.toolName() == '': self.set_action_pan() except AttributeError: pass def load_settings(self, dialog=None): """ Load QGIS settings related with dialog position and size """ if dialog is None: dialog = self.dlg try: x = self.controller.plugin_settings_value(dialog.objectName() + "_x") y = self.controller.plugin_settings_value(dialog.objectName() + "_y") width = self.controller.plugin_settings_value( dialog.objectName() + "_width", dialog.property('width')) height = self.controller.plugin_settings_value( dialog.objectName() + "_height", dialog.property('height')) if int(x) < 0 or int(y) < 0: dialog.resize(int(width), int(height)) else: screens = ctypes.windll.user32 screen_x = screens.GetSystemMetrics(78) screen_y = screens.GetSystemMetrics(79) if int(x) > screen_x: x = int(screen_x) - int(width) if int(y) > screen_y: y = int(screen_y) dialog.setGeometry(int(x), int(y), int(width), int(height)) except: pass def save_settings(self, dialog=None): """ Save QGIS settings related with dialog position and size """ if dialog is None: dialog = self.dlg try: self.controller.plugin_settings_set_value( dialog.objectName() + "_width", dialog.property('width')) self.controller.plugin_settings_set_value( dialog.objectName() + "_height", dialog.property('height')) self.controller.plugin_settings_set_value( dialog.objectName() + "_x", dialog.pos().x()) self.controller.plugin_settings_set_value( dialog.objectName() + "_y", dialog.pos().y()) except: pass def check_expression(self, expr_filter, log_info=False): """ Check if expression filter @expr is valid """ if log_info: self.controller.log_info(expr_filter) expr = QgsExpression(expr_filter) if expr.hasParserError(): message = "Expression Error" self.controller.log_warning(message, parameter=expr_filter) return False, expr return True, expr def get_composers_list(self): layour_manager = QgsProject.instance().layoutManager().layouts() active_composers = [layout for layout in layour_manager] return active_composers def get_composer_index(self, name): index = 0 composers = self.get_composers_list() for comp_view in composers: composer_name = comp_view.name() if composer_name == name: break index += 1 return index def canvasMoveEvent(self, event): # Make sure active layer is always 'v_edit_node' cur_layer = self.iface.activeLayer() if cur_layer != self.layer_node and self.force_active_layer: self.iface.setActiveLayer(self.layer_node) # Hide highlight and get coordinates self.vertex_marker.hide() event_point = self.snapper_manager.get_event_point(event) # Snapping result = self.snapper_manager.snap_to_current_layer(event_point) if self.snapper_manager.result_is_valid(): self.snapper_manager.add_marker(result, self.vertex_marker) def create_body(self, form='', feature='', filter_fields='', extras=None): """ Create and return parameters as body to functions""" client = f'$${{"client":{{"device":4, "infoType":1, "lang":"ES"}}, ' form = f'"form":{{{form}}}, ' feature = '"feature":{' + feature + '}, ' filter_fields = '"filterFields":{' + filter_fields + '}' page_info = '"pageInfo":{}' data = '"data":{' + filter_fields + ', ' + page_info if extras: data += ', ' + extras data += f'}}}}$$' body = "" + client + form + feature + data return body def refresh_legend(self): """ This function solves the bug generated by changing the type of feature. Mysteriously this bug is solved by checking and unchecking the categorization of the tables. # TODO solve this bug """ layers = [ self.controller.get_layer_by_tablename('v_edit_node'), self.controller.get_layer_by_tablename('v_edit_connec'), self.controller.get_layer_by_tablename('v_edit_gully') ] for layer in layers: if layer: ltl = QgsProject.instance().layerTreeRoot().findLayer( layer.id()) ltm = self.iface.layerTreeView().model() legendNodes = ltm.layerLegendNodes(ltl) for ln in legendNodes: current_state = ln.data(Qt.CheckStateRole) ln.setData(Qt.Unchecked, Qt.CheckStateRole) ln.setData(Qt.Checked, Qt.CheckStateRole) ln.setData(current_state, Qt.CheckStateRole) def put_layer_into_toc(self, tablename=None, the_geom="the_geom", field_id="id", group='GW Layers'): """ Put layer from postgres DB into TOC""" schema_name = self.controller.credentials['schema'].replace('"', '') uri = QgsDataSourceUri() uri.setConnection(self.controller.credentials['host'], self.controller.credentials['port'], self.controller.credentials['db'], self.controller.credentials['user'], self.controller.credentials['password']) if not field_id: field_id = self.controller.get_pk(tablename) if not field_id: field_id = "id" uri.setDataSource(schema_name, f'{tablename}', the_geom, None, field_id) layer = QgsVectorLayer(uri.uri(), f'{tablename}', "postgres") root = QgsProject.instance().layerTreeRoot() my_group = root.findGroup(group) if my_group is None: my_group = root.insertGroup(0, group) my_group.insertLayer(0, layer) self.iface.mapCanvas().refresh() return layer def populate_info_text(self, dialog, data, force_tab=True, reset_text=True, tab_idx=1): change_tab = False text = qt_tools.getWidgetText(dialog, 'txt_infolog', return_string_null=False) if reset_text: text = "" for item in data['info']['values']: if 'message' in item: if item['message'] is not None: text += str(item['message']) + "\n" if force_tab: change_tab = True else: text += "\n" qt_tools.setWidgetText(dialog, 'txt_infolog', text + "\n") qtabwidget = dialog.findChild(QTabWidget, 'mainTab') if change_tab and qtabwidget is not None: qtabwidget.setCurrentIndex(tab_idx) return change_tab
class CadApiInfo(ParentMapTool): """ Button 37: Info """ def __init__(self, iface, settings, action, index_action): """ Class constructor """ super(CadApiInfo, self).__init__(iface, settings, action, index_action) self.index_action = index_action self.tab_type = None # Used when the signal 'signal_activate' is emitted from the info, do not open another form self.block_signal = False self.previous_api_cf = None def create_point(self, event): x = event.pos().x() y = event.pos().y() try: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) except (TypeError, KeyError): self.iface.actionPan().trigger() return False return point """ QgsMapTools inherited event functions """ def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: for rb in self.rubberband_list: rb.reset() self.api_cf.resetRubberbands() self.action().trigger() return def canvasMoveEvent(self, event): pass def canvasReleaseEvent(self, event): for rb in self.rubberband_list: rb.reset() if self.block_signal: self.block_signal = False return self.controller.init_docker() if event.button() == Qt.LeftButton: point = self.create_point(event) if point is False: return api_cf = ApiCF(self.iface, self.settings, self.controller, self.controller.plugin_dir, self.tab_type) api_cf.signal_activate.connect(self.reactivate_map_tool) api_cf.open_form(point, tab_type=self.tab_type) # Remove previous rubberband when open new docker if isinstance(self.previous_api_cf, ApiCF) and self.controller.dlg_docker is not None: self.previous_api_cf.resetRubberbands() self.previous_api_cf = api_cf elif event.button() == Qt.RightButton: point = self.create_point(event) if point is False: return api_cf = ApiCF(self.iface, self.settings, self.controller, self.controller.plugin_dir, self.tab_type) api_cf.hilight_feature(point, self.rubberband_list, self.tab_type) def reactivate_map_tool(self): """ Reactivate tool """ self.block_signal = True info_action = self.iface.mainWindow().findChild( QAction, 'map_tool_api_info_data') info_action.trigger() def activate(self): # Check button self.action().setChecked(True) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.WhatsThisCursor) self.canvas.setCursor(self.cursor) self.rubberband_list = [] if self.index_action == '37': self.tab_type = 'data' elif self.index_action == '199': self.tab_type = 'inp' def deactivate(self): for rb in self.rubberband_list: rb.reset() if hasattr(self, 'api_cf'): self.api_cf.resetRubberbands() ParentMapTool.deactivate(self)
class GwInfoButton(GwParentMapTool): def __init__(self, icon_path, text, toolbar, action_group): super().__init__(icon_path, text, toolbar, action_group) self.rubber_band = QgsRubberBand(global_vars.canvas) self.tab_type = None # Used when the signal 'signal_activate' is emitted from the info, do not open another form self.block_signal = False def create_point(self, event): x = event.pos().x() y = event.pos().y() try: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) except (TypeError, KeyError): self.iface.actionPan().trigger() return False return point """ QgsMapTools inherited event functions """ def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: for rb in self.rubberband_list: rb.reset() self.rubber_band.reset() self.action.trigger() return def canvasMoveEvent(self, event): pass def canvasReleaseEvent(self, event): for rb in self.rubberband_list: rb.reset() if self.block_signal: self.block_signal = False return self.controller.init_docker() if event.button() == Qt.LeftButton: point = self.create_point(event) if point is False: return self.api_cf.get_info_from_coordinates(point, tab_type=self.tab_type) elif event.button() == Qt.RightButton: point = self.create_point(event) if point is False: return self.get_layers_from_coordinates(point, self.rubberband_list, self.tab_type) def reactivate_map_tool(self): """ Reactivate tool """ self.block_signal = True info_action = self.iface.mainWindow().findChild( QAction, 'map_tool_api_info_data') info_action.trigger() def activate(self): # Check button self.action.setChecked(True) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.WhatsThisCursor) self.canvas.setCursor(self.cursor) self.rubberband_list = [] # if self.index_action == '37': self.tab_type = 'data' # elif self.index_action == '199': # self.tab_type = 'inp' self.api_cf = GwInfo(self.tab_type) self.api_cf.signal_activate.connect(self.reactivate_map_tool) def deactivate(self): for rb in self.rubberband_list: rb.reset() if hasattr(self, 'api_cf'): self.rubber_band.reset() super().deactivate() 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 = get_visible_layers(as_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 = create_body(extras=extras) json_result = self.controller.get_json( 'gw_fct_getlayersfromcoordinates', body, rubber_band=self.rubber_band) if not json_result: 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 = self.controller.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']: action = QAction(str(feature['id']), None) 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) def identify_all(self, complet_list, rb_list): self.rubber_band.reset() for rb in rb_list: rb.reset() for layer in complet_list['body']['data']['layersNames']: for feature in layer['ids']: points = [] list_coord = re.search('\((.*)\)', str(feature['geometry'])) coords = list_coord.group(1) polygon = coords.split(',') for i in range(0, len(polygon)): x, y = polygon[i].split(' ') point = QgsPointXY(float(x), float(y)) points.append(point) rb = QgsRubberBand(self.canvas) polyline = QgsGeometry.fromPolylineXY(points) rb.setToGeometry(polyline, None) rb.setColor(QColor(255, 0, 0, 100)) rb.setWidth(5) rb.show() rb_list.append(rb) def draw_by_action(self, feature, rb_list, reset_rb=True): """ Draw lines based on geometry """ for rb in rb_list: rb.reset() if feature['geometry'] is None: return list_coord = re.search('\((.*)\)', str(feature['geometry'])) max_x, max_y, min_x, min_y = get_max_rectangle_from_coords(list_coord) if reset_rb is True: self.rubber_band.reset() if str(max_x) == str(min_x) and str(max_y) == str(min_y): point = QgsPointXY(float(max_x), float(max_y)) draw_point(point, self.rubber_band) else: points = get_points(list_coord) draw_polyline(points, self.rubber_band) def get_info_from_selected_id(self, action, tab_type): """ Set active selected layer """ self.rubber_band.reset() parent_menu = action.associatedWidgets()[0] layer = self.controller.get_layer_by_layername(parent_menu.title()) if layer: layer_source = self.controller.get_layer_source(layer) self.iface.setActiveLayer(layer) complet_result, dialog = self.api_cf.get_info_from_id( table_name=layer_source['table'], feature_id=action.text(), tab_type=tab_type)
def canvasMoveEvent(self, mouseEvent): item = self.selectedItem() if not item: return annotation = item.annotation() if not annotation: return pixelToMmScale = 25.4 / self.canvas.logicalDpiX() if self.currentMoveAction == QgsMapCanvasAnnotationItem.MoveFramePosition: # move the entire frame newCanvasPos = item.pos() + (mouseEvent.pos() - self.lastMousePosition) if annotation.hasFixedMapPosition(): deltaX = pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) deltaY = pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) annotation.setFrameOffsetFromReferencePointMm( QPointF( annotation.frameOffsetFromReferencePointMm().x() + deltaX, annotation.frameOffsetFromReferencePointMm().y() + deltaY)) annotation.setRelativePosition( QPointF(newCanvasPos.x() / self.canvas.width(), newCanvasPos.y() / self.canvas.height())) item.update() QgsProject.instance().setDirty(True) elif self.currentMoveAction != QgsMapCanvasAnnotationItem.NoAction: # handle vertical frame resize actions only size = annotation.frameSizeMm() xmin = annotation.frameOffsetFromReferencePointMm().x() ymin = annotation.frameOffsetFromReferencePointMm().y() xmax = xmin + size.width() ymax = ymin + size.height() relPosX = annotation.relativePosition().x() relPosY = annotation.relativePosition().y() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightUp): ymin += pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) relPosY = (relPosY * self.canvas.height() + mouseEvent.pos().y() - self.lastMousePosition.y()) / self.canvas.height() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameDown or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftDown or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightDown): ymax += pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeft or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftDown): xmin += pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) relPosX = (relPosX * self.canvas.width() + mouseEvent.pos().x() - self.lastMousePosition.x()) / self.canvas.width() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRight or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightDown): xmax += pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) # switch min / max if necessary if xmax < xmin: tmp = xmax xmax = xmin xmin = tmp if ymax < ymin: tmp = ymax ymax = ymin ymin = tmp annotation.setFrameOffsetFromReferencePointMm(QPointF(xmin, ymin)) annotation.setFrameSizeMm(QSizeF(xmax - xmin, ymax - ymin)) annotation.setRelativePosition(QPointF(relPosX, relPosY)) item.update() QgsProject.instance().setDirty(True) moveAction = item.moveActionForPosition(mouseEvent.pos()) cursor = QCursor() cursor.setShape(item.cursorShapeForAction(moveAction)) self.setCursor(cursor) self.lastMousePosition = mouseEvent.pos()
class GwInfoButton(GwMaptool): """ Button 37: Info """ def __init__(self, icon_path, action_name, text, toolbar, action_group): super().__init__(icon_path, action_name, text, toolbar, action_group) self.rubber_band = tools_gw.create_rubberband(global_vars.canvas) self.tab_type = None # Used when the signal 'signal_activate' is emitted from the info, do not open another form self.block_signal = False self.previous_info_feature = None self.action_name = action_name # region QgsMapTools inherited """ QgsMapTools inherited event functions """ def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: for rb in self.rubberband_list: tools_gw.reset_rubberband(rb) tools_gw.reset_rubberband(self.rubber_band) self.action.trigger() return def canvasMoveEvent(self, event): pass def canvasReleaseEvent(self, event): self._get_info(event) def activate(self): if info.is_inserting: msg = "You cannot insert more than one feature at the same time, finish editing the previous feature" tools_qgis.show_message(msg) super().deactivate() return # Check action. It works if is selected from toolbar. Not working if is selected from menu or shortcut keys if hasattr(self.action, "setChecked"): self.action.setChecked(True) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.WhatsThisCursor) self.canvas.setCursor(self.cursor) self.rubberband_list = [] self.tab_type = 'data' def deactivate(self): if hasattr(self, 'rubberband_list'): for rb in self.rubberband_list: tools_gw.reset_rubberband(rb) if hasattr(self, 'dlg_info_feature'): tools_gw.reset_rubberband(self.rubber_band) super().deactivate() # endregion # region private functions def _create_point(self, event): x = event.pos().x() y = event.pos().y() try: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) except (TypeError, KeyError): self.iface.actionPan().trigger() return False return point def _reactivate_map_tool(self): """ Reactivate tool """ self.block_signal = True info_action = self.iface.mainWindow().findChildren( QAction, self.action_name)[-1] info_action.trigger() 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) def _identify_all(self, complet_list, rb_list): tools_gw.reset_rubberband(self.rubber_band) for rb in rb_list: tools_gw.reset_rubberband(rb) for layer in complet_list['body']['data']['layersNames']: for feature in layer['ids']: points = [] list_coord = re.search('\((.*)\)', str(feature['geometry'])) coords = list_coord.group(1) polygon = coords.split(',') for i in range(0, len(polygon)): x, y = polygon[i].split(' ') point = QgsPointXY(float(x), float(y)) points.append(point) rb = tools_gw.create_rubberband(self.canvas) polyline = QgsGeometry.fromPolylineXY(points) rb.setToGeometry(polyline, None) rb.setColor(QColor(255, 0, 0, 100)) rb.setWidth(5) rb.show() rb_list.append(rb) def _draw_by_action(self, feature, rb_list, reset_rb=True): """ Draw lines based on geometry """ for rb in rb_list: tools_gw.reset_rubberband(rb) if feature['geometry'] is None: return list_coord = re.search('\((.*)\)', str(feature['geometry'])) max_x, max_y, min_x, min_y = tools_qgis.get_max_rectangle_from_coords( list_coord) if reset_rb: tools_gw.reset_rubberband(self.rubber_band) if str(max_x) == str(min_x) and str(max_y) == str(min_y): point = QgsPointXY(float(max_x), float(max_y)) tools_qgis.draw_point(point, self.rubber_band) else: points = tools_qgis.get_geometry_vertex(list_coord) tools_qgis.draw_polyline(points, self.rubber_band) def _get_info_from_selected_id(self, action, tab_type): """ Set active selected layer """ tools_gw.reset_rubberband(self.rubber_band) parent_menu = action.associatedWidgets()[0] layer = tools_qgis.get_layer_by_layername(parent_menu.title()) if layer: layer_source = tools_qgis.get_layer_source(layer) self.iface.setActiveLayer(layer) tools_gw.init_docker() info_feature = GwInfo(self.tab_type) info_feature.signal_activate.connect(self._reactivate_map_tool) info_feature.get_info_from_id( table_name=layer_source['table'], feature_id=action.property('feature_id'), tab_type=tab_type) # Remove previous rubberband when open new docker if isinstance( self.previous_info_feature, GwInfo ) and global_vars.session_vars['dialog_docker'] is not None: tools_gw.reset_rubberband( self.previous_info_feature.rubber_band) self.previous_info_feature = info_feature def _get_info(self, event): for rb in self.rubberband_list: tools_gw.reset_rubberband(rb) if self.block_signal: self.block_signal = False return if event.button() == Qt.LeftButton: point = self._create_point(event) if point is False: return tools_gw.init_docker() info_feature = GwInfo(self.tab_type) info_feature.signal_activate.connect(self._reactivate_map_tool) info_feature.get_info_from_coordinates(point, tab_type=self.tab_type) # Remove previous rubberband when open new docker if isinstance( self.previous_info_feature, GwInfo ) and global_vars.session_vars['dialog_docker'] is not None: tools_gw.reset_rubberband( self.previous_info_feature.rubber_band) self.previous_info_feature = info_feature elif event.button() == Qt.RightButton: point = self._create_point(event) if point is False: return self._get_layers_from_coordinates(point, self.rubberband_list, self.tab_type)
class GwInfoButton(GwParentMapTool): def __init__(self, icon_path, text, toolbar, action_group, iface, settings, controller, plugin_dir): super().__init__(icon_path, text, toolbar, action_group, iface, settings, controller, plugin_dir) self.tab_type = None # Used when the signal 'signal_activate' is emitted from the info, do not open another form self.block_signal = False def create_point(self, event): x = event.pos().x() y = event.pos().y() try: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) except (TypeError, KeyError): self.iface.actionPan().trigger() return False return point """ QgsMapTools inherited event functions """ def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: for rb in self.rubberband_list: rb.reset() self.api_cf.resetRubberbands() self.action.trigger() return def canvasMoveEvent(self, event): pass def canvasReleaseEvent(self, event): for rb in self.rubberband_list: rb.reset() if self.block_signal: self.block_signal = False return self.controller.init_docker() if event.button() == Qt.LeftButton: point = self.create_point(event) if point is False: return self.api_cf.open_form(point, tab_type=self.tab_type) elif event.button() == Qt.RightButton: point = self.create_point(event) if point is False: return self.api_cf.hilight_feature(point, self.rubberband_list, self.tab_type) def reactivate_map_tool(self): """ Reactivate tool """ self.block_signal = True info_action = self.iface.mainWindow().findChild( QAction, 'map_tool_api_info_data') info_action.trigger() def activate(self): # Check button self.action.setChecked(True) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.WhatsThisCursor) self.canvas.setCursor(self.cursor) self.rubberband_list = [] # if self.index_action == '37': self.tab_type = 'data' # elif self.index_action == '199': # self.tab_type = 'inp' self.api_cf = GwInfo(self.iface, self.settings, self.controller, self.controller.plugin_dir, self.tab_type) self.api_cf.signal_activate.connect(self.reactivate_map_tool) def deactivate(self): for rb in self.rubberband_list: rb.reset() if hasattr(self, 'api_cf'): self.api_cf.resetRubberbands() super().deactivate()
def activate(self): self.layer_selft.clear() cursor = QCursor() cursor.setShape(Qt.ArrowCursor) self.iface.mapCanvas().setCursor(cursor) # Snapping # QgsProject.instance().setSnapSettingsForLayer(self.params.junctions_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.reservoirs_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.tanks_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.pipes_vlay.id(), # True, # QgsSnapper.SnapToSegment, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # snap_layer_junctions = NetworkUtils.set_up_snap_layer(self.params.junctions_vlay) # snap_layer_reservoirs = NetworkUtils.set_up_snap_layer(self.params.reservoirs_vlay) # snap_layer_tanks = NetworkUtils.set_up_snap_layer(self.params.tanks_vlay) # snap_layer_pipes = NetworkUtils.set_up_snap_layer(self.params.pipes_vlay, snapping_type=QgsSnapper.SnapToSegment) layers = { self.params.junctions_vlay: QgsSnappingConfig.Vertex, self.params.reservoirs_vlay: QgsSnappingConfig.Vertex, self.params.tanks_vlay: QgsSnappingConfig.Vertex, self.params.pipes_vlay: QgsSnappingConfig.VertexAndSegment } self.snapper = NetworkUtils.set_up_snapper(layers, self.iface.mapCanvas(), self.params.snap_tolerance) self.snapper.toggleEnabled() # Editing if not self.params.junctions_vlay.isEditable(): self.params.junctions_vlay.startEditing() if not self.params.reservoirs_vlay.isEditable(): self.params.reservoirs_vlay.startEditing() if not self.params.tanks_vlay.isEditable(): self.params.tanks_vlay.startEditing() if not self.params.pipes_vlay.isEditable(): self.params.pipes_vlay.startEditing() if not self.params.pumps_vlay.isEditable(): self.params.pumps_vlay.startEditing() if not self.params.valves_vlay.isEditable(): self.params.valves_vlay.startEditing()
class CreatePredictionAnnotationsTool(QgsMapToolIdentify): def __init__(self, canvas): super(QgsMapToolIdentify, self).__init__(canvas) self.canvas = canvas self.selectionMode = self.ActiveLayer # TODO: maybe this can use all layers self.currentMoveAction = QgsMapCanvasAnnotationItem.NoAction self.cursor = QCursor() self.cursor.setShape(Qt.ArrowCursor) self.setCursor(self.cursor) def canvasPressEvent(self, mouseEvent): self.lastMousePosition = mouseEvent.pos() item = self.selectedItem() if item: self.currentMoveAction = item.moveActionForPosition( mouseEvent.pos()) if self.currentMoveAction != QgsMapCanvasAnnotationItem.NoAction: return # select a new item if there is one at this position if (not item ) or self.currentMoveAction == QgsMapCanvasAnnotationItem.NoAction: self.canvas.scene().clearSelection() existingItem = self.itemAtPos(mouseEvent.pos()) if existingItem: existingItem.setSelected(True) def canvasMoveEvent(self, mouseEvent): item = self.selectedItem() if not item: return annotation = item.annotation() if not annotation: return pixelToMmScale = 25.4 / self.canvas.logicalDpiX() if self.currentMoveAction == QgsMapCanvasAnnotationItem.MoveFramePosition: # move the entire frame newCanvasPos = item.pos() + (mouseEvent.pos() - self.lastMousePosition) if annotation.hasFixedMapPosition(): deltaX = pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) deltaY = pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) annotation.setFrameOffsetFromReferencePointMm( QPointF( annotation.frameOffsetFromReferencePointMm().x() + deltaX, annotation.frameOffsetFromReferencePointMm().y() + deltaY)) annotation.setRelativePosition( QPointF(newCanvasPos.x() / self.canvas.width(), newCanvasPos.y() / self.canvas.height())) item.update() QgsProject.instance().setDirty(True) elif self.currentMoveAction != QgsMapCanvasAnnotationItem.NoAction: # handle vertical frame resize actions only size = annotation.frameSizeMm() xmin = annotation.frameOffsetFromReferencePointMm().x() ymin = annotation.frameOffsetFromReferencePointMm().y() xmax = xmin + size.width() ymax = ymin + size.height() relPosX = annotation.relativePosition().x() relPosY = annotation.relativePosition().y() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightUp): ymin += pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) relPosY = (relPosY * self.canvas.height() + mouseEvent.pos().y() - self.lastMousePosition.y()) / self.canvas.height() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameDown or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftDown or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightDown): ymax += pixelToMmScale * (mouseEvent.pos().y() - self.lastMousePosition.y()) if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeft or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameLeftDown): xmin += pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) relPosX = (relPosX * self.canvas.width() + mouseEvent.pos().x() - self.lastMousePosition.x()) / self.canvas.width() if (self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRight or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightUp or self.currentMoveAction == QgsMapCanvasAnnotationItem.ResizeFrameRightDown): xmax += pixelToMmScale * (mouseEvent.pos().x() - self.lastMousePosition.x()) # switch min / max if necessary if xmax < xmin: tmp = xmax xmax = xmin xmin = tmp if ymax < ymin: tmp = ymax ymax = ymin ymin = tmp annotation.setFrameOffsetFromReferencePointMm(QPointF(xmin, ymin)) annotation.setFrameSizeMm(QSizeF(xmax - xmin, ymax - ymin)) annotation.setRelativePosition(QPointF(relPosX, relPosY)) item.update() QgsProject.instance().setDirty(True) moveAction = item.moveActionForPosition(mouseEvent.pos()) cursor = QCursor() cursor.setShape(item.cursorShapeForAction(moveAction)) self.setCursor(cursor) self.lastMousePosition = mouseEvent.pos() def canvasReleaseEvent(self, mouseEvent): self.currentMoveAction = QgsMapCanvasAnnotationItem.NoAction self.setCursor(self.cursor) results = self.identify(mouseEvent.x(), mouseEvent.y(), self.selectionMode, self.VectorLayer) for r in results: # TODO: filter out features in layers that aren't relevant if False: continue layer = r.mLayer feature = r.mFeature a = QgsHtmlAnnotation() a.setMapLayer(layer) html = os.path.join(os.path.dirname(__file__), 'html', 'current_predictions_annotation.html') a.setSourceFile(html) a.setAssociatedFeature(feature) # TODO: this size and offset are wack. Can we dynamically calculate from the content somehow? a.setFrameSize(QSizeF(270, 160)) a.setFrameOffsetFromReferencePoint(QPointF(-300, -200)) a.setMapPosition(feature.geometry().asPoint()) a.setMapPositionCrs(QgsCoordinateReferenceSystem(layer.crs())) # disable its symbol for symbol in a.markerSymbol().symbolLayers(): symbol.setEnabled(False) QgsProject.instance().annotationManager().addAnnotation(a) # select the just-created annotation to make it easy to move or resize item = self.itemForAnnotation(a) if item: self.canvas.scene().clearSelection() item.setSelected(True) break def keyPressEvent(self, keyEvent): item = self.selectedItem() if item: if keyEvent.key() == Qt.Key_Backspace or keyEvent.key( ) == Qt.Key_Delete: QgsProject.instance().annotationManager().removeAnnotation( item.annotation()) self.setCursor(self.cursor) keyEvent.ignore() def selectedItem(self): for item in self.canvas.annotationItems(): if item.isSelected(): return item return None def itemAtPos(self, point): for item in self.canvas.annotationItems(): if item.moveActionForPosition( point) == QgsMapCanvasAnnotationItem.MoveFramePosition: return item return None def itemForAnnotation(self, annotation): for item in self.canvas.annotationItems(): if item.annotation() == annotation: return item return None
class GwParentMapTool(QgsMapTool): def __init__(self, icon_path, text, toolbar, action_group, iface, settings, controller, plugin_dir): self.iface = iface self.settings = settings self.controller = controller self.plugin_dir = plugin_dir self.show_help = bool(int(self.settings.value('status/show_help', 1))) self.layer_arc = None self.layer_connec = None self.layer_gully = None self.layer_node = None self.snapper_manager = SnappingConfigManager(self.iface) self.snapper_manager.controller = controller self.canvas = iface.mapCanvas() super().__init__(self.canvas) icon = None if os.path.exists(icon_path): icon = QIcon(icon_path) self.action = None if icon is None: self.action = QAction(text, action_group) else: self.action = QAction(icon, text, action_group) self.action.setObjectName(text) self.action.setCheckable(True) self.action.triggered.connect(self.clicked_event) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.CrossCursor) # Get default cursor # noinspection PyCallingNonCallable self.std_cursor = self.parent().cursor() # Set default vertex marker color = QColor(255, 100, 255) self.vertex_marker = QgsVertexMarker(self.canvas) self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.vertex_marker.setColor(color) self.vertex_marker.setIconSize(15) self.vertex_marker.setPenWidth(3) # Set default rubber band color_selection = QColor(254, 178, 76, 63) self.rubber_band = QgsRubberBand(self.canvas, 2) self.rubber_band.setColor(color) self.rubber_band.setFillColor(color_selection) self.rubber_band.setWidth(1) self.reset() self.force_active_layer = True toolbar.addAction(self.action) self.setAction(self.action) def clicked_event(self): self.controller.prev_maptool = self.iface.mapCanvas().mapTool() if not (self == self.iface.mapCanvas().mapTool()): self.iface.mapCanvas().setMapTool(self) else: self.iface.mapCanvas().unsetMapTool(self) def deactivate(self): # Uncheck button self.action.setChecked(False) # Restore previous snapping self.snapper_manager.recover_snapping_options() # Enable snapping self.snapper_manager.enable_snapping(True) # Recover cursor self.canvas.setCursor(self.std_cursor) # Remove highlight self.vertex_marker.hide() def canvasMoveEvent(self, event): # Make sure active layer is always 'v_edit_node' cur_layer = self.iface.activeLayer() if cur_layer != self.layer_node and self.force_active_layer: self.iface.setActiveLayer(self.layer_node) # Hide highlight and get coordinates self.vertex_marker.hide() event_point = self.snapper_manager.get_event_point(event) # Snapping result = self.snapper_manager.snap_to_current_layer(event_point) if self.snapper_manager.result_is_valid(): self.snapper_manager.add_marker(result, self.vertex_marker) def recover_previus_maptool(self): if self.controller.prev_maptool: self.iface.mapCanvas().setMapTool(self.controller.prev_maptool) self.controller.prev_maptool = None def remove_vertex(self): """ Remove vertex_marker from canvas""" vertex_items = [i for i in self.iface.mapCanvas().scene().items() if issubclass(type(i), QgsVertexMarker)] for ver in vertex_items: if ver in self.iface.mapCanvas().scene().items(): if self.vertex_marker == ver: self.iface.mapCanvas().scene().removeItem(ver) def set_action_pan(self): """ Set action 'Pan' """ try: self.iface.actionPan().trigger() except Exception: pass def reset_rubber_band(self, geom_type="polygon"): try: if geom_type == "polygon": geom_type = QgsWkbTypes.PolygonGeometry elif geom_type == "line": geom_type = QgsWkbTypes.LineString self.rubber_band.reset(geom_type) except: pass def reset(self): self.reset_rubber_band() self.snapped_feat = None def cancel_map_tool(self): """ Executed if user press right button or escape key """ # Reset rubber band self.reset() # Deactivate map tool self.deactivate() self.set_action_pan() def remove_markers(self): """ Remove previous markers """ vertex_items = [i for i in list(self.canvas.scene().items()) if issubclass(type(i), QgsVertexMarker)] for ver in vertex_items: if ver in list(self.canvas.scene().items()): self.canvas.scene().removeItem(ver) def refresh_map_canvas(self): """ Refresh all layers present in map canvas """ self.canvas.refreshAllLayers() for layer_refresh in self.canvas.layers(): layer_refresh.triggerRepaint()
class GwMaptool(QgsMapTool): def __init__(self, icon_path, action_name, text, toolbar, action_group, icon_type=4): self.iface = global_vars.iface self.canvas = global_vars.canvas self.schema_name = global_vars.schema_name self.settings = global_vars.giswater_settings self.plugin_dir = global_vars.plugin_dir self.project_type = global_vars.project_type self.show_help = tools_gw.get_config_parser('system', 'show_help', "project", "giswater") self.layer_arc = None self.layer_connec = None self.layer_gully = None self.layer_node = None self.snapper_manager = GwSnapManager(self.iface) self.previous_snapping = self.snapper_manager.get_snapping_options() super().__init__(self.canvas) # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.CrossCursor) # Get default cursor # noinspection PyCallingNonCallable self.std_cursor = self.parent().cursor() # Set default vertex marker self.vertex_marker = self.snapper_manager.vertex_marker self.snapper_manager.set_vertex_marker(self.vertex_marker, icon_type=icon_type) # Set default rubber band color = QColor(255, 100, 255) color_selection = QColor(254, 178, 76, 63) self.rubber_band = tools_gw.create_rubberband(self.canvas, 2) self.rubber_band.setColor(color) self.rubber_band.setFillColor(color_selection) self.rubber_band.setWidth(1) self.reset() self.force_active_layer = True if toolbar is None: return self.action = None icon = None if os.path.exists(icon_path): icon = QIcon(icon_path) if icon is None: self.action = QAction(text, action_group) else: self.action = QAction(icon, text, action_group) self.action.setObjectName(action_name) self.action.setCheckable(True) self.action.triggered.connect(self.clicked_event) toolbar.addAction(self.action) self.setAction(self.action) def clicked_event(self): selected_maptool = self.iface.mapCanvas().mapTool() self.prev_maptool = selected_maptool if not self == selected_maptool: self.iface.mapCanvas().setMapTool(self) def deactivate(self): # Uncheck button if hasattr( self.action, "setChecked" ): # If the maptool is activated through the giswater menu, it breaks self.action.setChecked(False) # Restore previous snapping self.snapper_manager.restore_snap_options(self.previous_snapping) # Enable snapping self.snapper_manager.set_snapping_status(True) # Recover cursor self.canvas.setCursor(self.std_cursor) # Remove highlight self.vertex_marker.hide() def canvasMoveEvent(self, event): # Make sure active layer is always 'v_edit_node' cur_layer = self.iface.activeLayer() if cur_layer != self.layer_node and self.force_active_layer: self.iface.setActiveLayer(self.layer_node) # Hide highlight and get coordinates self.vertex_marker.hide() event_point = self.snapper_manager.get_event_point(event) # Snapping result = self.snapper_manager.snap_to_current_layer(event_point) if result.isValid(): self.snapper_manager.add_marker(result, self.vertex_marker) def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.cancel_map_tool() return def canvasReleaseEvent(self, event): if event.button() == Qt.RightButton: self.cancel_map_tool() def recover_previus_maptool(self): if self.prev_maptool: self.iface.mapCanvas().setMapTool(self.prev_maptool) self.prev_maptool = None def set_action_pan(self): """ Set action 'Pan' """ try: self.iface.actionPan().trigger() except Exception: pass def reset_rubber_band(self, geom_type="polygon"): if geom_type == "polygon": geom_type = QgsWkbTypes.PolygonGeometry elif geom_type == "line": geom_type = QgsWkbTypes.LineGeometry self.rubber_band.reset(geom_type) def reset(self): self.reset_rubber_band() self.snapped_feat = None def cancel_map_tool(self): """ Executed if user press right button or escape key """ # Reset rubber band self.reset() # Deactivate map tool self.deactivate() # Set action pan self.set_action_pan() def refresh_map_canvas(self): """ Refresh all layers present in map canvas """ self.canvas.refreshAllLayers() for layer_refresh in self.canvas.layers(): layer_refresh.triggerRepaint() def manage_active_maptool(self): """ Check in init config file if user wants to keep map tool active or not """ value = tools_gw.get_config_parser('user_edit_tricks', 'keep_maptool_active', "user", "init", prefix=True) keep_maptool_active = tools_os.set_boolean(value, False) if not keep_maptool_active: self.cancel_map_tool()