from PyQt5.QtGui import QTextOption from PyQt5.uic.properties import QtWidgets from qgis.PyQt.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QTableWidget, QTableWidgetItem, QGraphicsView, \ QGraphicsScene, QPushButton from qgis.core import QgsProject, QgsVectorLayer from qgis.gui import QgsMapCanvas from qgis.utils import iface from qgis.PyQt.QtGui import QColor from PyQt5.QtWidgets import QSizePolicy, QStyledItemDelegate from PyQt5.QtCore import Qt, QSizeF, QRectF class WordWrapDelegate(QStyledItemDelegate): def paint(self, painter, option, index): if index.column() == 1: # Only apply word wrapping to the second column painter.save() # Create a QRectF for the bounding box (the cell's rectangle) rect = QRectF(option.rect) # Use option.rect for the cell's bounding rectangle # Define the QTextOption for word wrapping text_option = QTextOption() text_option.setWrapMode(QTextOption.WrapMode.WordWrap) # Enable word wrap # Draw the text inside the cell with word wrapping painter.setClipRect(option.rect) # Set clipping to the cell's rectangle painter.drawText(rect, index.data(), text_option) # Correct method signature here painter.restore() else: super().paint(painter, option, index) class CombinedDialog(QDialog): def __init__(self, layer, parent=None): super().__init__(parent) self.layer = layer # Set the dialog layout self.setWindowTitle('图层属性') layout = QVBoxLayout(self) # Create a QTabWidget to hold the different panels self.tabs = QTabWidget(self) # Add Metadata Panel (using QTableWidget instead of QTextEdit) metadata_table = QTableWidget(self) # Create a table widget for displaying metadata self.populate_metadata_table(metadata_table) # Populate the table with metadata self.tabs.addTab(metadata_table, '基本信息') # Add Preview Panel (using QgsMapCanvas in a QGraphicsView) preview_widget = QGraphicsView(self) preview_scene = QGraphicsScene(self) preview_widget.setScene(preview_scene) # Set up the map canvas for previewing the layer map_canvas = QgsMapCanvas() map_canvas.setCanvasColor(QColor('white')) # Set the canvas color to white map_canvas.setDestinationCrs(self.layer.crs()) # Set the CRS of the map canvas map_canvas.setExtent(self.layer.extent()) # Set the extent to match the layer's extent map_canvas.setLayers([self.layer]) # Set the layer to be previewed map_canvas.refresh() # Refresh the map canvas to show the layer # Add the map canvas to the preview scene preview_scene.addWidget(map_canvas) # Make sure the preview widget expands to fill the layout preview_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # preview_scene.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.tabs.addTab(preview_widget, '预览') # Add Attribute Table Button if isinstance(layer, QgsVectorLayer): self.show_attribute_table_button = QPushButton("属性表", self) self.show_attribute_table_button.setFixedSize(60, 25) self.show_attribute_table_button.clicked.connect(self.show_attribute_table) layout.addWidget(self.show_attribute_table_button) # Add the QTabWidget to the layout layout.addWidget(self.tabs) # Set dialog size self.resize(800, 600) # Ensure the map canvas resizes to fit inside the scene map_canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Connect the resize event to adjust the canvas size preview_widget.resizeEvent = self.on_resize_event def on_resize_event(self, event): """Handles the resize event to ensure the map canvas adjusts its size.""" # Resize the map canvas to the size of the QGraphicsView preview_widget = self.findChild(QGraphicsView) map_canvas = preview_widget.scene().items()[0] # Get the map canvas from the scene # Convert QSize to QSizeF (float size) new_size = QSizeF(preview_widget.size().width(), preview_widget.size().height()) # Resize the canvas to match the new size map_canvas.resize(new_size) # Resize with QSizeF event.accept() def populate_metadata_table(self, table_widget): """Populate the table with metadata information of the layer.""" # Get layer metadata metadata = [ ("图层名称", self.layer.name()), # ("Layer Type", str(self.layer.type())), ("坐标系", self.layer.crs().authid()), ] if isinstance(self.layer, QgsVectorLayer): metadata.append(("要素数量", str(self.layer.featureCount()))) metadata.append(("字段", ", ".join([field.name() for field in self.layer.fields()]))) metadata.append(("数据范围", str(self.layer.extent().toString()))) # Set the table dimensions table_widget.setRowCount(len(metadata)) table_widget.setColumnCount(2) # Set the table headers table_widget.setHorizontalHeaderLabels(["属性名称", "属性值"]) # Hide the headers table_widget.horizontalHeader().setVisible(False) # Hide horizontal (column) headers table_widget.verticalHeader().setVisible(False) # Optionally hide vertical (row) headers # Set column width table_widget.setColumnWidth(0, 200) # Set the first column (attribute) to a fixed width of 200px table_widget.setColumnWidth(1, 600) # Make the second column (value) stretchable # table_widget.horizontalHeader().setSectionResizeMode(1) # Populate the table with the metadata for row, (attribute, value) in enumerate(metadata): item_attr = QTableWidgetItem(attribute) item_value = QTableWidgetItem(value) # Enable word wrapping for both columns item_attr.setTextAlignment(Qt.AlignCenter | Qt.AlignLeft) item_value.setTextAlignment(Qt.AlignCenter | Qt.AlignLeft) # Wrap text in the second column (value) text_option = QTextOption() text_option.setWrapMode(QTextOption.WrapMode.WordWrap) # Enable word wrap for this column item_value.setText(value) # Apply value with word wrap option # Add items to the table table_widget.setItem(row, 0, item_attr) table_widget.setItem(row, 1, item_value) delegate = WordWrapDelegate() table_widget.setItemDelegateForColumn(1, delegate) table_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) table_widget.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) # Resize the columns to fit the content table_widget.resizeColumnsToContents() table_widget.resizeColumnToContents(1) def get_layer_metadata(self, layer): """Return basic metadata information of the layer""" metadata = [] # Get layer name metadata.append(f"Layer Name: {layer.name()}") # Get layer type metadata.append(f"Layer Type: {layer.type()}") # Get CRS (Coordinate Reference System) metadata.append(f"CRS: {layer.crs().authid()}") # Get feature count if isinstance(layer, QgsVectorLayer): metadata.append(f"Feature Count: {layer.featureCount()}") # Get fields (attribute names) fields = ", ".join([field.name() for field in layer.fields()]) metadata.append(f"Fields: {fields}") # Get extent metadata.append(f"Extent: {layer.extent().toString()}") return "\n".join(metadata) def show_attribute_table(self): """Show the attribute table for the current layer""" # Ensure the attribute table is brought to the front # Bring the main window and attribute table dialog to the front main_window = iface.mainWindow() main_window.raise_() # Raise the main window to the front main_window.activateWindow() # Focus the main window # Additionally, ensure the active window is focused (in case the attribute table dialog gets hidden) iface.showAttributeTable(self.layer) # Reopen if needed to ensure focus def showDialog(self): self.exec_() # Usage: # layer = iface.activeLayer() # Get the active layer # if layer: # dialog = CombinedDialog(layer) # dialog.showDialog() # else: # print("No layer selected")