From aa40d44635789fe64f0c472c7912e919522d14c6 Mon Sep 17 00:00:00 2001 From: Maciej Chmielewski Date: Wed, 27 Aug 2025 13:12:22 +0200 Subject: [PATCH] PolaMap Lite - Karta informacyjna - generowanie karty informacyjnej --- InfoTools.py | 575 +++++++++++++++++++++++++++++ InfoToolsDialog.py | 180 +++++++++ giap_dynamic_layout.py | 5 + giap_dynamic_layout.ui | 13 + giap_layout.py | 8 +- icons/karta_info.png | Bin 0 -> 889 bytes karta_informacjna_dialog.ui | 318 ++++++++++++++++ karta_informacyjna_docker_test2.ui | 205 ++++++++++ karta_informacyjna_test.ui | 333 +++++++++++++++++ ribbon_config.py | 1 + utils.py | 5 +- 11 files changed, 1641 insertions(+), 2 deletions(-) create mode 100644 InfoTools.py create mode 100644 InfoToolsDialog.py create mode 100644 icons/karta_info.png create mode 100644 karta_informacjna_dialog.ui create mode 100644 karta_informacyjna_docker_test2.ui create mode 100644 karta_informacyjna_test.ui diff --git a/InfoTools.py b/InfoTools.py new file mode 100644 index 0000000..83b3e01 --- /dev/null +++ b/InfoTools.py @@ -0,0 +1,575 @@ +# -*- coding: utf-8 -*- + +import requests +from lxml import html, etree + +from qgis.PyQt.QtGui import QColor +from qgis.PyQt.QtCore import QTimer, Qt +from qgis.PyQt.QtWidgets import QLabel +from qgis.gui import QgisInterface, QgsMapToolIdentify, QgsMapCanvas, QgsRubberBand, QgsHighlight +from qgis.core import (QgsGeometry, QgsWkbTypes, QgsRectangle, QgsFeature, QgsVectorLayer, QgsRasterLayer, QgsRaster, + QgsDistanceArea, QgsProject, QgsMapLayer) + +from .InfoToolsDialog import InfoToolsDialog + + +params_feature_info = { + "REQUEST": "GetFeatureInfo", + "SERVICE": "WMS", + "VERSION": "1.1.1", + "LAYERS": "integracja", + "QUERY_LAYERS": "", + "SRS": "", + "FORMAT": "image/png", + "INFO_FORMAT": "application/vnd.ogc.gml", + "BBOX": "", + "WIDTH": "", + "HEIGHT": "", + "I": "", + "J": "", +} + + +class InfoTool: + def __init__(self, iface: QgisInterface) -> None: + self.iface = iface + self.dialog = InfoToolsDialog(iface.mainWindow()) + self.canvas = self.iface.mapCanvas() + self.features_dict = {} + self.tool = None + self.default_map_tool = None + self.highlighter = HighlightFeatures(self.canvas, parent_tool=self) + self.highlighter.clear() + self.current_crs = QgsProject.instance().crs() + + QgsProject.instance().crsChanged.connect(self.update_crs) + self.dialog.rejected.connect(self.sample) + self.dialog.identify_feature.triggered.connect(self.activate_identify_tool) + self.dialog.identify_feature_hover.triggered.connect(self.activate_identify_hover_tool) + self.dialog.identify_feature_polygon.triggered.connect(self.activate_identify_polygon_tool) + self.dialog.identify_feature_freehand.triggered.connect(self.activate_identify_freehand_tool) + self.dialog.identify_feature_radius.triggered.connect(self.activate_identify_radius_tool) + + def get_layer(self) -> QgsMapLayer | None: + return self.iface.activeLayer() + + def run(self) -> None: + self.default_map_tool = self.canvas.mapTool() + self.dialog.show() + self.dialog.raise_() + + def sample(self) -> None: + if self.tool: + self.canvas.unsetMapTool(self.tool) + self.tool = None + if self.default_map_tool: + self.canvas.setMapTool(self.default_map_tool) + self.highlighter.clear() + + def update_crs(self) -> None: + self.current_crs = QgsProject.instance().crs() + self.highlighter.clear() + self.dialog.get_data(None, None, None, None) + self.canvas.refresh() + + def activate_identify_tool(self) -> None: + if not self.iface.activeLayer(): + return + self.highlighter.clear() + self.tool = IdentifyFeatureTool( + self.iface, self.canvas, + lambda data, click_point, layer_type: self.dialog.get_data(data, click_point, layer_type, self.iface.activeLayer().name()), + self.features_dict, self + ) + self.canvas.unsetMapTool(self.tool) + self.canvas.setMapTool(self.tool) + + def activate_identify_hover_tool(self) -> None: + if not self.iface.activeLayer(): + return + self.highlighter.clear() + self.tool = IdentifyFeatureHoverTool( + self.iface, self.canvas, + lambda data, click_point, layer_type: self.dialog.get_data(data, None, layer_type, self.iface.activeLayer().name()), + self.features_dict, self + ) + self.canvas.unsetMapTool(self.tool) + self.canvas.setMapTool(self.tool) + + def activate_identify_polygon_tool(self) -> None: + if not self.iface.activeLayer(): + return + self.highlighter.clear() + self.tool = IdentifyFeaturePolygonTool( + self.iface, self.canvas, + lambda data, click_point, layer_type: self.dialog.get_data(data, None, layer_type, self.iface.activeLayer().name()), + self.features_dict, self + ) + self.canvas.unsetMapTool(self.tool) + self.canvas.setMapTool(self.tool) + + def activate_identify_freehand_tool(self) -> None: + if not self.iface.activeLayer(): + return + self.highlighter.clear() + self.tool = IdentifyFeatureFreehandTool( + self.iface, self.canvas, + lambda data, click_point, layer_type: self.dialog.get_data(data, None, layer_type, self.iface.activeLayer().name()), + self.features_dict, self + ) + self.canvas.unsetMapTool(self.tool) + self.canvas.setMapTool(self.tool) + + def activate_identify_radius_tool(self) -> None: + if not self.iface.activeLayer(): + return + self.highlighter.clear() + self.tool = IdentifyFeatureRadiusTool( + self.iface, self.canvas, + lambda data, click_point, layer_type: self.dialog.get_data(data, None, layer_type, self.iface.activeLayer().name()), + self.features_dict, self + ) + self.canvas.unsetMapTool(self.tool) + self.canvas.setMapTool(self.tool) + + +class HighlightFeatures: + def __init__(self, canvas: QgsMapCanvas, parent_tool: InfoTool) -> None: + """Uwydatnia zaznaczone obiekty wektorowe na mapie""" + self.canvas = canvas + self.parent_tool = parent_tool + self.highlight = None + + def clear(self) -> None: + if self.highlight: + self.highlight.hide() + if self.canvas and self.highlight.scene(): + self.canvas.scene().removeItem(self.highlight) + self.highlight = None + + if self.parent_tool: + if hasattr(self.parent_tool, "highlight") and self.parent_tool.highlight: + self.parent_tool.highlight.hide() + if self.canvas and self.parent_tool.highlight.scene(): + self.canvas.scene().removeItem(self.parent_tool.highlight) + self.parent_tool.highlight = None + + def highlight_features(self, features) -> None: + self.clear() + if isinstance(features, QgsFeature): + features = [features] + if not features: + return + multi_geom = QgsGeometry.unaryUnion([f.geometry() for f in features]) + self.highlight = QgsHighlight(self.canvas, multi_geom, self.parent_tool.get_layer()) + self.highlight.setColor(QColor(255,0,0)) + self.highlight.setFillColor(QColor(255,0,0)) + self.highlight.setWidth(1) + self.highlight.show() + if self.parent_tool: + self.parent_tool.highlight = self.highlight + + +class IdentifyFeatureTool(QgsMapToolIdentify): + def __init__(self, iface: QgisInterface, canvas: QgsMapCanvas, callback, features_dict, parent_tool: InfoTool) -> None: + super().__init__(canvas) + self.iface = iface + self.canvas = canvas + self.callback = callback + self.features_dict = features_dict + self.parent_tool = parent_tool + self.highlighter = HighlightFeatures(self.canvas, self.parent_tool) + self.highlighter.clear() + self.start_point = None + self.end_point = None + self.dragging = False + self.rubber_band = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) + self.rubber_band.setColor(QColor(0,0,255,50)) + self.rubber_band.setFillColor(QColor(0,0,255,50)) + self.rubber_band.setWidth(2) + + def deactivate(self) -> None: + super().deactivate() + if not hasattr(self.parent_tool.dialog, 'is_closing') or not self.parent_tool.dialog.is_closing: + self.highlighter.clear() + + def canvasPressEvent(self, event) -> None: + self.start_point = self.toMapCoordinates(event.pos()) + self.dragging = False + + def canvasMoveEvent(self, event) -> None: + layer = self.parent_tool.get_layer() + if not self.start_point: + return + self.end_point = self.toMapCoordinates(event.pos()) + if isinstance(layer, QgsVectorLayer): + self.dragging = True + else: + return + rect = QgsRectangle(self.start_point, self.end_point) + self.rubber_band.setToGeometry(QgsGeometry.fromRect(rect), None) + self.rubber_band.show() + + def canvasReleaseEvent(self, event) -> None: + layer = self.parent_tool.get_layer() + if not self.start_point: + return + self.rubber_band.hide() + self.highlighter.clear() + if self.dragging: + self.end_point = self.toMapCoordinates(event.pos()) + rect = QgsRectangle(self.start_point, self.end_point) + rect_geom = QgsGeometry.fromRect(rect) + features = [f for f in layer.getFeatures() if f.geometry().intersects(rect_geom)] + if features: + self.features_dict.clear() + for f in features: + self.features_dict[f.id()] = f + self.callback(features, None, layer.dataProvider().name()) + self.highlighter.highlight_features(features) + else: + self.highlighter.clear() + self.callback(None, None, None) + else: + if isinstance(layer, QgsVectorLayer): + result = self.identify(event.pos().x(), event.pos().y(), [layer], self.TopDownStopAtFirst) + if result: + feature = result[0].mFeature + if feature.isValid(): + self.features_dict[feature.id()] = feature + self.highlighter.highlight_features([feature]) + self.callback([feature], self.start_point, layer.dataProvider().name()) + else: + self.highlighter.clear() + self.callback(None, None, None) + + elif isinstance(layer, QgsRasterLayer): + if not layer.extent().contains(self.start_point): + self.highlighter.clear() + self.start_point = None + self.callback(None, None, None) + return + + if layer.dataProvider().name() == 'wms': + layer_metadata = layer.htmlMetadata() + metadata_tree = html.fromstring(layer_metadata) + url = metadata_tree.xpath("//a/@href")[0] + params_feature_info["SRS"] = layer.crs().authid() + params_feature_info["BBOX"] = ( + f"{self.canvas.extent().xMinimum()},{self.canvas.extent().yMinimum()}," + f"{self.canvas.extent().xMaximum()},{self.canvas.extent().yMaximum()}" + ) + params_feature_info["WIDTH"] = self.canvas.width() + params_feature_info["HEIGHT"] = self.canvas.height() + params_feature_info["I"] = event.pos().x() + params_feature_info["J"] = event.pos().y() + response = requests.get(url, params=params_feature_info) + response.encoding = "utf-8" + response = response.text + response = response.split(">", 1)[1].strip() + xml_file = etree.fromstring(response) + xml_attributes = xml_file.findall(".//{http://www.intergraph.com/geomedia/gml}Attribute") + attributes_dict = {} + for attr in xml_attributes: + attributes_dict[attr.get("Name")] = attr.text.strip() if attr.text else '' + self.callback(attributes_dict, None, layer.dataProvider().name()) if attributes_dict else self.callback(None, None, None) + + elif layer.dataProvider().name() == 'gdal': + ident = layer.dataProvider().identify(self.start_point, QgsRaster.IdentifyFormatValue) + values = ident.results() + no_data_pxl = layer.dataProvider().sourceNoDataValue(1) + pxl_value = values.get(1, None) + if pxl_value is None or pxl_value == no_data_pxl: + self.callback(None, None, None) + else: + col = int((self.start_point[0] - layer.extent().xMinimum()) / layer.rasterUnitsPerPixelX()) + row = int((layer.extent().yMaximum() - self.start_point[1]) / layer.rasterUnitsPerPixelY()) + self.callback([values, self.start_point, col, row], None, layer.dataProvider().name()) + self.start_point = None + self.end_point = None + self.dragging = False + + +class IdentifyFeatureHoverTool(QgsMapToolIdentify): + def __init__(self, iface: QgisInterface, canvas: QgsMapCanvas, callback, features_dict, parent_tool: InfoTool) -> None: + super().__init__(canvas) + self.iface = iface + self.canvas = canvas + self.callback = callback + self.features_dict = features_dict + self.parent_tool = parent_tool + self.highlighter = HighlightFeatures(self.canvas, self.parent_tool) + self.highlighter.clear() + self.start_point = None + self.last_mouse_event = None + self.throttle_timer = QTimer() + self.throttle_timer.setInterval(200) + self.throttle_timer.setSingleShot(True) + self.throttle_timer.timeout.connect(self.do_identify) + + def deactivate(self) -> None: + super().deactivate() + if not hasattr(self.parent_tool.dialog, 'is_closing') or not self.parent_tool.dialog.is_closing: + self.highlighter.clear() + + def canvasMoveEvent(self, event) -> None: + self.last_mouse_event = event + self.start_point = event + if not self.throttle_timer.isActive(): + self.throttle_timer.start() + + def do_identify(self) -> None: + layer = self.iface.activeLayer() + if not self.last_mouse_event: + return + if isinstance(layer, QgsVectorLayer): + result = self.identify(self.last_mouse_event.pos().x(), self.last_mouse_event.pos().y(), [layer], self.TopDownStopAtFirst) + if result: + feature = result[0].mFeature + if feature.isValid(): + self.features_dict[feature.id()] = feature + self.highlighter.highlight_features([feature]) + # self.callback([feature]) + self.callback([feature], None, layer.dataProvider().name()) + else: + self.highlighter.clear() + self.callback(None, None, None) + + elif isinstance(layer, QgsRasterLayer): + self.start_point = self.toMapCoordinates(self.last_mouse_event.pos()) + if not layer.extent().contains(self.start_point): + self.callback(None, None, None) + return + ident = layer.dataProvider().identify(self.start_point, QgsRaster.IdentifyFormatValue) + if ident.isValid(): + values = ident.results() + no_data_pxl = layer.dataProvider().sourceNoDataValue(1) + pxl_value = values.get(1, None) + if pxl_value is None or pxl_value == no_data_pxl: + self.callback(None, None, None) + else: + col = int((self.start_point[0] - layer.extent().xMinimum()) / layer.rasterUnitsPerPixelX()) + row = int((layer.extent().yMaximum() - self.start_point[1]) / layer.rasterUnitsPerPixelY()) + self.callback([values, self.start_point, col, row], None, layer.dataProvider().name()) + self.highlighter.clear() + + +class IdentifyFeaturePolygonTool(QgsMapToolIdentify): + def __init__(self, iface: QgisInterface, canvas: QgsMapCanvas, callback, features_dict, parent_tool: InfoTool) -> None: + super().__init__(canvas) + self.iface = iface + self.canvas = canvas + self.callback = callback + self.features_dict = features_dict + self.parent_tool = parent_tool + self.highlighter = HighlightFeatures(self.canvas, self.parent_tool) + self.highlighter.clear() + self.point = None + self.points = [] + self.is_drawing = False + self.rubberBand = None + + def deactivate(self) -> None: + super().deactivate() + if not hasattr(self.parent_tool.dialog, 'is_closing') or not self.parent_tool.dialog.is_closing: + self.highlighter.clear() + + def canvasPressEvent(self, event) -> None: + layer = self.iface.activeLayer() + if not layer: + return + self.highlighter.clear() + if self.rubberBand is None: + self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) + self.rubberBand.setColor(QColor(0, 0, 255, 50)) + self.rubberBand.setFillColor(QColor(0, 0, 255, 50)) + self.rubberBand.setWidth(2) + if isinstance(layer, QgsVectorLayer): + if event.button() == Qt.LeftButton: + self.point = self.toMapCoordinates(event.pos()) + self.points.append(self.point) + self.is_drawing = True + self.rubberBand.setToGeometry(QgsGeometry.fromPolygonXY([self.points]), None) + self.rubberBand.show() + elif event.button() == Qt.RightButton: + if len(self.points) < 3: + self.points.clear() + self.rubberBand.hide() + self.rubberBand = None + self.is_drawing = False + return + else: + polygon = self.rubberBand.asGeometry() + features = [f for f in layer.getFeatures() if f.geometry().intersects(polygon)] + if features: + self.features_dict.clear() + for f in features: + self.features_dict[f.id()] = f + self.callback(features, None, layer.dataProvider().name()) + self.highlighter.highlight_features(features) + else: + self.highlighter.clear() + self.callback(None, None, None) + self.is_drawing = False + self.points.clear() + self.rubberBand.hide() + self.rubberBand = None + return + + def canvasMoveEvent(self, event) -> None: + if not self.is_drawing or not self.points: + return + temp_points = self.points + [self.toMapCoordinates(event.pos())] + self.rubberBand.setToGeometry(QgsGeometry.fromPolygonXY([temp_points]), None) + + +class IdentifyFeatureFreehandTool(QgsMapToolIdentify): + def __init__(self, iface: QgisInterface, canvas: QgsMapCanvas, callback, features_dict, parent_tool: InfoTool) -> None: + super().__init__(canvas) + self.iface = iface + self.canvas = canvas + self.callback = callback + self.features_dict = features_dict + self.parent_tool = parent_tool + self.highlighter = HighlightFeatures(self.canvas, self.parent_tool) + self.highlighter.clear() + self.start_point = None + self.end_point = None + self.points = [] + self.rubberBand = None + self.is_drawing = False + self.wait_for_second_click = False + self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) + self.rubberBand.setColor(QColor(0, 0, 255, 50)) + self.rubberBand.setFillColor(QColor(0, 0, 255, 50)) + self.rubberBand.setWidth(2) + + def deactivate(self) -> None: + super().deactivate() + if not hasattr(self.parent_tool.dialog, 'is_closing') or not self.parent_tool.dialog.is_closing: + self.highlighter.clear() + + def canvasPressEvent(self, event): + layer = self.iface.activeLayer() + if not layer: + return + self.highlighter.clear() + if isinstance(layer, QgsVectorLayer): + self.rubberBand.setToGeometry(QgsGeometry.fromPolygonXY([self.points]), None) + self.rubberBand.show() + if event.button() == Qt.LeftButton and not self.wait_for_second_click: + if not self.wait_for_second_click: + self.is_drawing = True + self.wait_for_second_click = True + elif event.button() == Qt.LeftButton and self.wait_for_second_click: + self.wait_for_second_click = False + polygon = self.rubberBand.asGeometry() + features = [f for f in layer.getFeatures() if f.geometry().intersects(polygon)] + if features: + self.features_dict.clear() + for f in features: + self.features_dict[f.id()] = f + self.callback(features, None, layer.dataProvider().name()) + self.highlighter.highlight_features(features) + else: + self.highlighter.clear() + self.callback(None, None, None) + self.points.clear() + self.rubberBand.hide() + self.is_drawing = False + if event.button() == Qt.RightButton: + self.highlighter.clear() + self.callback(None, None, None) + self.points.clear() + self.rubberBand.hide() + self.is_drawing = False + self.wait_for_second_click = False + + def canvasMoveEvent(self, event) -> None: + if self.is_drawing: + point = self.toMapCoordinates(event.pos()) + self.points.append(point) + self.rubberBand.addPoint(point) + + +class IdentifyFeatureRadiusTool(QgsMapToolIdentify): + def __init__(self, iface: QgisInterface, canvas: QgsMapCanvas, callback, features_dict, parent_tool: InfoTool) -> None: + super().__init__(canvas) + self.iface = iface + self.canvas = canvas + self.callback = callback + self.features_dict = features_dict + self.parent_tool = parent_tool + self.highlighter = HighlightFeatures(self.canvas, self.parent_tool) + self.highlighter.clear() + self.center_point = None + self.wait_for_second_click = False + self.label = QLabel(self.canvas) + self.label.setStyleSheet( + """ + padding: 4px; + border-radius: 6px; + """ + ) + self.label.setAlignment(Qt.AlignCenter) + self.label.adjustSize() + self.label.move(10, 10) + self.distance_calc = QgsDistanceArea() + self.distance_calc.setSourceCrs(canvas.mapSettings().destinationCrs(), QgsProject.instance().transformContext()) + self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) + self.rubberBand.setColor(QColor(0, 0, 255, 50)) + self.rubberBand.setFillColor(QColor(0, 0, 255, 50)) + self.rubberBand.setWidth(2) + + def deactivate(self) -> None: + super().deactivate() + if not hasattr(self.parent_tool.dialog, 'is_closing') or not self.parent_tool.dialog.is_closing: + self.highlighter.clear() + if self.label: + self.label.hide() + + def canvasPressEvent(self, event) -> None: + layer = self.iface.activeLayer() + if not layer: + return + self.highlighter.clear() + if isinstance(layer, QgsVectorLayer): + if event.button() == Qt.LeftButton and not self.wait_for_second_click: + self.center_point = self.toMapCoordinates(event.pos()) + self.wait_for_second_click = True + elif event.button() == Qt.LeftButton and self.wait_for_second_click: + polygon = self.rubberBand.asGeometry() + features = [f for f in layer.getFeatures() if f.geometry().intersects(polygon)] + self.label.hide() + if features: + self.features_dict.clear() + for f in features: + self.features_dict[f.id()] = f + self.callback(features, None, layer.dataProvider().name()) + self.highlighter.highlight_features(features) + else: + self.highlighter.clear() + self.callback(None, None, None) + self.center_point = None + self.rubberBand.hide() + self.wait_for_second_click = False + if event.button() == Qt.RightButton: + self.highlighter.clear() + self.callback(None, None, None) + self.center_point = None + self.rubberBand.hide() + self.wait_for_second_click = False + self.label.hide() + + def canvasMoveEvent(self, event) -> None: + if self.center_point: + current_point = self.toMapCoordinates(event.pos()) + radius = self.center_point.distance(current_point) + radius_length = self.distance_calc.measureLine(self.center_point, current_point) + buffer_geom = QgsGeometry.fromPointXY(self.center_point).buffer(radius, 50) + self.rubberBand.setToGeometry(buffer_geom, None) + self.rubberBand.show() + self.label.setText(f"Promień zaznaczenia: {radius_length:.5f}") + self.label.adjustSize() + self.label.show() + diff --git a/InfoToolsDialog.py b/InfoToolsDialog.py new file mode 100644 index 0000000..c73212b --- /dev/null +++ b/InfoToolsDialog.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- + +import os + +import requests +from lxml import etree +from io import BytesIO + +from qgis.PyQt import QtWidgets, uic +from qgis.PyQt.QtWidgets import QMenu, QTreeWidgetItem, QLabel +from qgis.PyQt.QtCore import Qt, pyqtSignal +from qgis.PyQt.QtGui import QPixmap +from qgis.core import QgsWkbTypes + + +FORM_CLASS, _ = uic.loadUiType(os.path.join( + os.path.dirname(__file__), 'karta_informacyjna_test.ui')) + + +class InfoToolsDialog(QtWidgets.QDialog, FORM_CLASS): + dialog_closed = pyqtSignal() + def __init__(self, parent: QtWidgets=None) -> None: + super(InfoToolsDialog, self).__init__(parent) + self.setupUi(self) + self.setWindowFlag(Qt.Window) + self.menu = QMenu(self) + self.is_closing = False + self.identify_feature = self.menu.addAction("Identyfikuj obiekt(y)") + self.identify_feature_hover = self.menu.addAction("Identyfikuj obiekty pod kursorem myszy") + self.identify_feature_polygon = self.menu.addAction("Identyfikuj obiekty wielobokiem") + self.identify_feature_freehand = self.menu.addAction("Identyfikuj obiekty swobodnie") + self.identify_feature_radius = self.menu.addAction("Identyfikuj obiekty promieniem") + self.selectObjectPushButton.setMenu(self.menu) + + def get_data(self, data=None, click_point=None, layer_type=None, layer_name=None) -> None: + self.treeWidget.clear() + if data is None: + return + if layer_type == 'ogr': + self.show_ogr_data(data, click_point, layer_name) + elif layer_type == 'gdal': + self.show_gdal_data(data, layer_name) + elif layer_type == 'wms': + self.show_wms_data(data, layer_name) + + def show_ogr_data(self, data=None, click_point=None, layer_name=None) -> None: + title = f"{layer_name} [{len(data)}]" + root_item = QTreeWidgetItem([title]) + self.treeWidget.addTopLevelItem(root_item) + for d in data: + fields = d.fields() + geom = d.geometry() + attributes = d.attributes() + for i, field_primary in enumerate(fields): + item_primary = QTreeWidgetItem([str(field_primary.name()), str(attributes[i])]) + root_item.addChild(item_primary) + sub_item = QTreeWidgetItem(["(pochodne)", ""]) + item_primary.addChild(sub_item) + sub_item.addChild(QTreeWidgetItem(["ID obiektu", str(d.id())])) + if click_point: + sub_item.addChild(QTreeWidgetItem(["(wskazana współrzędna X)", f"{click_point[0]:.6f}"])) + sub_item.addChild(QTreeWidgetItem(["(wskazana współrzędna Y)", f"{click_point[1]:.6f}"])) + if geom.type() == QgsWkbTypes.PointGeometry: + if geom.isMultipart(): + multi_points = d.geometry().asMultiPoint() + sub_item.addChild(QTreeWidgetItem(["X obiektu", f"{multi_points.x():.6f}"])) + sub_item.addChild(QTreeWidgetItem(["Y obiektu", f"{multi_points.y():.6f}"])) + elif geom.asPoint(): + points = geom.asPoint() + sub_item.addChild(QTreeWidgetItem(["X obiektu", f"{points.x():.6f}"])) + sub_item.addChild(QTreeWidgetItem(["Y obiektu", f"{points.y():.6f}"])) + elif geom.type() == QgsWkbTypes.LineGeometry: + if geom.isMultipart(): + multi_polylines = geom.asMultiPolyline() + sub_item.addChild(QTreeWidgetItem([ + "X najbliższego wierzchołka", f"{geom.closestVertex(click_point)[0][0]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem([ + "Y najbliższego wierzchołka", f"{geom.closestVertex(click_point)[0][1]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem([ + "Odległość między wskazanym punktem a najbliższym wierzchołkiem", + f"{geom.closestVertex(click_point)[4]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem(["Części", str(len(multi_polylines))])) + sub_item.addChild(QTreeWidgetItem(["Długość (kartezjańska)", f"{geom.length():.6f} m"])) + # Długość elipsoidalna EPSG:7019 + sub_item.addChild(QTreeWidgetItem(["Wierzchołki", str(len(list(geom.vertices())))])) + sub_item.addChild(QTreeWidgetItem([ + "Numer najbliższego wierzchołka", str(geom.closestVertex(click_point)[1]) + ])) + elif geom.asPolyline(): + polylines = geom.asPolyline() + sub_item.addChild(QTreeWidgetItem(["Części", str(len(polylines))])) + # Długość elipsoidalna EPSG:7019 + sub_item.addChild(QTreeWidgetItem(["Długość (kartezjańska)", f"{geom.length():.6f} m"])) + sub_item.addChild(QTreeWidgetItem(["Wierzchołki", str(len(list(geom.vertices())))])) + elif geom.type() == QgsWkbTypes.PolygonGeometry: + if geom.isMultipart(): + multi_polygons = geom.asMultiPolygon() + sub_item.addChild(QTreeWidgetItem([ + "X najbliższego wierzchołka", f"{geom.closestVertex(click_point)[0][0]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem([ + "Y najbliższego wierzchołka", f"{geom.closestVertex(click_point)[0][1]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem([ + "Odległość między wskazanym punktem a najbliższym wierzchołkiem", + f"{geom.closestVertex(click_point)[4]:.6f}" + ])) + sub_item.addChild(QTreeWidgetItem(["Części", str(len(multi_polygons))])) + sub_item.addChild(QTreeWidgetItem(["Obwód (kartezjański)"])) + sub_item.addChild(QTreeWidgetItem(["Powierzchnia (kartezjańska)", f"{geom.area():.6f}"])) + sub_item.addChild(QTreeWidgetItem(["Wierzchołki", str(len(list(geom.vertices())))])) + sub_item.addChild(QTreeWidgetItem([ + "Numer najbliższego wierzchołka", str(geom.closestVertex(click_point)[1]) + ])) + elif geom.asPolyline(): + polygons = geom.asPolygon() + sub_item.addChild(QTreeWidgetItem(["Części", str(len(polygons))])) + #obwod elipsoidalny + sub_item.addChild(QTreeWidgetItem(["Obwód (kartezjański)"])) + #powierzchnia elipsoidalna + sub_item.addChild(QTreeWidgetItem(["Powierzchnia (kartezjańska)", f"{geom.area():.6f}"])) + sub_item.addChild(QTreeWidgetItem(["Wierzchołki", str(len(list(geom.vertices())))])) + sub_item.setExpanded(True) + for j, field_secondary in enumerate(fields): + item_secondary = QTreeWidgetItem([str(field_secondary.name()), str(attributes[j])]) + item_primary.addChild(item_secondary) + item_primary.setExpanded(True) + break + root_item.setExpanded(True) + + def show_gdal_data(self, data=None, layer_name=None) -> None: + title = f"{layer_name}" + root_item = QTreeWidgetItem([title]) + self.treeWidget.addTopLevelItem(root_item) + item = QTreeWidgetItem([str(f"Kanał: {next(iter(data[0]))}"), str(next(iter(data[0].values())))]) + root_item.addChild(item) + sub_item = QTreeWidgetItem(["(pochodne)", ""]) + item.addChild(sub_item) + sub_item.addChild(QTreeWidgetItem(["(wskazana współrzędna X)", str(data[1][0])])) + sub_item.addChild(QTreeWidgetItem(["(wskazana współrzędna Y)", str(data[1][1])])) + sub_item.addChild(QTreeWidgetItem(["Kolumna (numeracja od 0)", str(data[2])])) + sub_item.addChild(QTreeWidgetItem(["Wiersz (numeracja od 0)", str(data[3])])) + root_item.setExpanded(True) + item.setExpanded(True) + + def show_wms_data(self, data=None, layer_name=None) -> None: + title = f"{layer_name}" + root_item = QTreeWidgetItem([title]) + self.treeWidget.addTopLevelItem(root_item) + for k, v in data.items(): + if k != "Kod QR": + root_item.addChild(QTreeWidgetItem([k, v])) + else: + qr_link = etree.XML(data.get("Kod QR")).xpath("//img/@src") + qr_item = QTreeWidgetItem() + root_item.addChild(qr_item) + try: + response_qr_link = requests.get(qr_link[0]) + response_qr_link.raise_for_status() + qr_item.setText(0, "Kod QR") + pixmap = QPixmap() + pixmap.loadFromData(BytesIO(response_qr_link.content).read()) + label = QLabel() + label.setPixmap(pixmap.scaledToHeight(128)) #tu na sztywno poprawić potem + self.treeWidget.setItemWidget(qr_item, 1, label) + except Exception as e: + qr_item.setText(0, "Kod QR") + qr_item.setText(1, f"Błąd ładowania: {e}") + root_item.setExpanded(True) + + def closeEvent(self, event) -> None: + self.treeWidget.clear() + self.is_closing = True + super().closeEvent(event) + if hasattr(self, 'dialog_closed'): + self.dialog_closed.emit() + diff --git a/giap_dynamic_layout.py b/giap_dynamic_layout.py index 3c2881e..28a521b 100644 --- a/giap_dynamic_layout.py +++ b/giap_dynamic_layout.py @@ -18,6 +18,7 @@ from qgis.utils import iface from qgis.gui import QgsMapTool +from .InfoTools import InfoTool from .geocoding_tool import Geocoding from .prng_tool import PRNGTool from .OrtoTools import OrtoAddingTool @@ -879,6 +880,10 @@ def set_custom_action(self) -> None: self.add_wfs = AddWfsTool() self.tbut.clicked.connect(self.add_wfs.run) self.tbut.setToolTip(tr("Download data from WFS")) + if oname == 'giapInfoCard': + self.info_card = InfoTool(iface) + self.tbut.clicked.connect(self.info_card.run) + self.tbut.setToolTip(tr("Info card")) if oname == "giapMyPrints": self.tbut.setToolTip(tr("My Prints")) if oname == "giapAreaLength": diff --git a/giap_dynamic_layout.ui b/giap_dynamic_layout.ui index 830c3ea..42bb504 100644 --- a/giap_dynamic_layout.ui +++ b/giap_dynamic_layout.ui @@ -505,6 +505,19 @@ for the street: Warszawa, Pasaż Ursynowski + + + + + 0 + 30 + + + + ... + + + diff --git a/giap_layout.py b/giap_layout.py index 991baf7..5b57c6d 100644 --- a/giap_layout.py +++ b/giap_layout.py @@ -222,11 +222,17 @@ def initGui(self) -> None: area_length_tool = QgsMapTool(self.iface.mapCanvas()) area_length_tool.setAction(self.main_widget.area_length_action) self.main_widget.runArea.setDefaultAction(self.main_widget.area_length_action) - + info_card_tool = QgsMapTool(self.iface.mapCanvas()) + info_card_tool.setAction(self.main_widget.area_length_action) + self.main_widget.runArea.setDefaultAction(self.main_widget.area_length_action) orto_button = self.main_widget.runOrtoTool orto_button.setIcon(QIcon(os.path.join(self.plugin_dir, 'icons', 'orto_icon2.png'))) self.orto_add = OrtoAddingTool(self.main_widget, orto_button, self.iface) + # self.main_widget.infoCardButton.clicked.connect(self.info_card.run) + self.main_widget.infoCardButton.setIcon( + QIcon(os.path.join(self.plugin_dir, 'icons', 'karta_info.png'))) + self.visibility_search_tool = False self.main_widget.offOnSearchButton.clicked.connect( lambda: self.off_on_search_tool(self.visibility_search_tool)) diff --git a/icons/karta_info.png b/icons/karta_info.png new file mode 100644 index 0000000000000000000000000000000000000000..05e6c11e1b986842fc0ccc674f0351493bcd3c7f GIT binary patch literal 889 zcmeAS@N?(olHy`uVBq!ia0vp^DIm``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di3`}1b- zBG=10@rR$^u89-4rB*Ou-_GYd_ZWo+wIFsHuy7e_pFr4k2wKYrgO059%XM;=k?&!U>t*hg0D=NPJ`e?Ox>5Y}g zd2Qyb36V0G&^l4$*ldBrU#3sje3GC$OJj=Q^5V&N&AeZJ6H7Rda$?onkmrdqho?$> zPHZu#{6EWiO-XJa+u61?{}bOFsuT&Io~S9k?PQOYN5~0fbL-x~MT*@$O%nnIjJTZK z98YL)NU|y}R!9+PfeE(#dh$qN?|a@i`(xa{f7W~SS8UUCeWmRN%^zQCRy;NH5PE!k zar(>a%6I49{cr}J7V$Y7q8q- zUZV{Dj@j%VPUKEVVX{9d@pFIH??UM%1=Z``XP=xH_H52et}6=*_qO}2(Niw|c4p)A z$r49*cYiqb^}gcc&6i&)TVAo{agTW%zFa``^M^B~6O>QhGs^J$=(OAq;(^C?d@pmZ zU%YvXPhEWWi8#&O@h@Lkd05Y}yIK9|(f9N6+b$`u<9z(}z~LuVC$iS9{r@%Q_g}SL ziR(X}%AN4UCx8Fuy>mBAuUP6i7ZwOuLk6qhvD^uh#X|cn_lhV!H23)QvHtaPfd z4t_qAeVzMhmv;Aw76bP8cFU%3P!0E8dcDWup7R}j)wB0^O| literal 0 HcmV?d00001 diff --git a/karta_informacjna_dialog.ui b/karta_informacjna_dialog.ui new file mode 100644 index 0000000..96a8e0a --- /dev/null +++ b/karta_informacjna_dialog.ui @@ -0,0 +1,318 @@ + + + KompozycjeDialog + + + Qt::NonModal + + + true + + + + 0 + 0 + 521 + 734 + + + + + 1 + 1 + + + + + 521 + 734 + + + + + Segoe UI + 10 + 50 + false + false + + + + Karta informacyjna + + + + :/plugins/GIAP-giap_layout/icons/giap_logo.png:/plugins/GIAP-giap_layout/icons/giap_logo.png + + + +QAbstractItemView +{ + alternate-background-color: #e6e6e6; +} +QComboBox +{ + selection-background-color: #b7d3e8; + background-color: #4f5a63; + border-style: solid; + border: 1px solid #5689b0; + border-radius: 3px; + padding: 2px; + font: 9pt "Segoe UI"; + height: 20px; +} + +QComboBox:on +{ + background-color: #4f5a63; + padding-top: 3px; + padding-left: 1px; + selection-background-color: #4a4a4a; +} + +QComboBox QAbstractItemView +{ + background-color: #4f5a63; + border-radius: 4px; + border: 1px solid #6fb1e3; + selection-background-color: #4f5a63; + padding: 4px 10px 4px 10px; + width: 1.9em; +} + +QComboBox::drop-down +{ + subcontrol-origin: padding; + subcontrol-position: top right; + width: 15px; + background-color: #5689b0; + border-left-width: 0; + border-left-color: #1a2936; + border-left-style: solid; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +QComboBox::down-arrow +{ + image: url(icons/down_arrow_disabled.png); +} + +QComboBox::down-arrow:on, +QComboBox::down-arrow:hover, +QComboBox::down-arrow:focus +{ + image: url(icons/down_arrow.png); +} + +QLineEdit +{ + border: 1px solid #5689b0; + border-radius: 3px; + background-color: #4f5a63; +} + +QGroupBox { +border: 1px solid #5689b0; +} + +QToolButton { + border: 0px solid transparent; + color: #EDF6FC; + +} + +QToolButton:hover { + background-color: #b7d3e8; + border: 1px solid #0A0C0D; +} + +QToolButton:pressed { + background-color: #b7d3e8; + border: 1px solid #0A0C0D; +} + +QTableView:item:selected { + background-color: #6fb1e3; +} + +QTableView:item:hover { + background-color: #6fb1e3; +} + + + + + + + false + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Identyfikuj obiekt + + + + + + + + + + Wskaż z mapy + + + + + + + Tryb + + + + + + + + Identyfikuj obiekty + + + + + 2 + + + + + 3 + + + + + + + + + Obiekt + + + + + Wartość + + + + + + + + Dodaj załącznik graficzny + + + + + + + Wybór formatu + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + PDF + + + + + + + XLS + + + + + + + CSV + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Podgląd karty + + + + + + + Zapisz... + + + + + + + + + + + diff --git a/karta_informacyjna_docker_test2.ui b/karta_informacyjna_docker_test2.ui new file mode 100644 index 0000000..ac47f76 --- /dev/null +++ b/karta_informacyjna_docker_test2.ui @@ -0,0 +1,205 @@ + + + KompozycjeDialog + + + + 0 + 0 + 521 + 734 + + + + Dialog + + + + + 0 + 0 + 521 + 741 + + + + + + + + + + + + + + 0 + 20 + 521 + 711 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + true + + + + Identyfikuj obiekty + + + + + + + + Zapisz... + + + + + + + + 8 + + + + Tryb + + + + + + + + + + Wskaż z mapy + + + + + + + Dodaj załącznik graficzny + + + + + + + true + + + Wybór formatu + + + + + + + + 8 + + + + Identyfikuj obiekt + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + PDF + + + + + + + XLS + + + + + + + CSV + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Podgląd karty + + + + + + + 200 + + + + Obiekt + + + AlignCenter + + + + + Wartość + + + AlignCenter + + + + + + + + + + diff --git a/karta_informacyjna_test.ui b/karta_informacyjna_test.ui new file mode 100644 index 0000000..a4d3d7e --- /dev/null +++ b/karta_informacyjna_test.ui @@ -0,0 +1,333 @@ + + + KompozycjeDialog + + + Qt::NonModal + + + true + + + + 0 + 0 + 521 + 734 + + + + + 1 + 1 + + + + + 521 + 734 + + + + + Segoe UI + 10 + 50 + false + false + + + + Karta informacyjna + + + + :/plugins/GIAP-giap_layout/icons/giap_logo.png:/plugins/GIAP-giap_layout/icons/giap_logo.png + + + +QAbstractItemView +{ + alternate-background-color: #e6e6e6; +} +QComboBox +{ + selection-background-color: #b7d3e8; + background-color: #4f5a63; + border-style: solid; + border: 1px solid #5689b0; + border-radius: 3px; + padding: 2px; + font: 9pt "Segoe UI"; + height: 20px; +} + +QComboBox:on +{ + background-color: #4f5a63; + padding-top: 3px; + padding-left: 1px; + selection-background-color: #4a4a4a; +} + +QComboBox QAbstractItemView +{ + background-color: #4f5a63; + border-radius: 4px; + border: 1px solid #6fb1e3; + selection-background-color: #4f5a63; + padding: 4px 10px 4px 10px; + width: 1.9em; +} + +QComboBox::drop-down +{ + subcontrol-origin: padding; + subcontrol-position: top right; + width: 15px; + background-color: #5689b0; + border-left-width: 0; + border-left-color: #1a2936; + border-left-style: solid; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +QComboBox::down-arrow +{ + image: url(icons/down_arrow_disabled.png); +} + +QComboBox::down-arrow:on, +QComboBox::down-arrow:hover, +QComboBox::down-arrow:focus +{ + image: url(icons/down_arrow.png); +} + +QLineEdit +{ + border: 1px solid #5689b0; + border-radius: 3px; + background-color: #4f5a63; +} + +QGroupBox { +border: 1px solid #5689b0; +} + +QToolButton { + border: 0px solid transparent; + color: #EDF6FC; + +} + +QToolButton:hover { + background-color: #b7d3e8; + border: 1px solid #0A0C0D; +} + +QToolButton:pressed { + background-color: #b7d3e8; + border: 1px solid #0A0C0D; +} + +QTableView:item:selected { + background-color: #6fb1e3; +} + +QTableView:item:hover { + background-color: #6fb1e3; +} + + + + + + + false + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + true + + + + Identyfikuj obiekty + + + + + + + + Zapisz... + + + + + + + + 8 + + + + Tryb + + + + + + + + + + Wskaż z mapy + + + + + + + Dodaj załącznik graficzny + + + + + + + true + + + Wybór formatu + + + + + + + + 8 + + + + Identyfikuj obiekt + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + PDF + + + + + + + XLS + + + + + + + CSV + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Podgląd karty + + + + + + + 200 + + + + Obiekt + + + AlignCenter + + + + + Wartość + + + AlignCenter + + + + + + + + + + + + diff --git a/ribbon_config.py b/ribbon_config.py index a332656..581c456 100644 --- a/ribbon_config.py +++ b/ribbon_config.py @@ -123,6 +123,7 @@ ['giapQuickPrint', 0, 2], ['giapAreaLength', 0, 3], ['giapAddWfsLayer', 0, 4], + ['giapInfoCard', 0, 5], ] }, diff --git a/utils.py b/utils.py index 1e02bd2..148abf4 100644 --- a/utils.py +++ b/utils.py @@ -710,6 +710,7 @@ def paint(self, painter, option, index): ['giapgeokodowanie', 1, 0], ['giapGeoportal', 0, 1], ['giapOrtoContr', 1, 1], + ['giapInfoCard', 0, 2], ] }, { @@ -1411,6 +1412,7 @@ def paint(self, painter, option, index): "giapQuickPrint": 'quick_print.png', "giapMyPrints": 'my_prints.png', "giapAreaLength": 'measuring.png', + "giapInfoCard": 'karta_info.png', 'mActionShowAlignRasterTool': 'mActionShowAlignRasterTool.png', 'mActionNewMemoryLayer': 'mActionNewMemoryLayer.png', 'mActionSaveProjectAs': 'mActionSaveProjectAs.png', @@ -1432,9 +1434,10 @@ def paint(self, painter, option, index): 'giapGeoportal': 'Geoportal', 'giapOrtoContr': 'Ortofotomapa archiwalna', "giapgeokodowanie": 'geokodowanie', + "giapInfoCard": 'Info card', } -max_ele_nazwy = 4 +max_ele_nazwy = 5 def icon_manager(tool_list: List[str], main_qgs_widget: QObject = None) -> \