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 0000000..05e6c11
Binary files /dev/null and b/icons/karta_info.png differ
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) -> \