CombinedDialog.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. from PyQt5.QtGui import QTextOption
  2. from PyQt5.uic.properties import QtWidgets
  3. from qgis.PyQt.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QTableWidget, QTableWidgetItem, QGraphicsView, \
  4. QGraphicsScene, QPushButton
  5. from qgis.core import QgsProject, QgsVectorLayer
  6. from qgis.gui import QgsMapCanvas
  7. from qgis.utils import iface
  8. from qgis.PyQt.QtGui import QColor
  9. from PyQt5.QtWidgets import QSizePolicy, QStyledItemDelegate
  10. from PyQt5.QtCore import Qt, QSizeF, QRectF
  11. class WordWrapDelegate(QStyledItemDelegate):
  12. def paint(self, painter, option, index):
  13. if index.column() == 1: # Only apply word wrapping to the second column
  14. painter.save()
  15. # Create a QRectF for the bounding box (the cell's rectangle)
  16. rect = QRectF(option.rect) # Use option.rect for the cell's bounding rectangle
  17. # Define the QTextOption for word wrapping
  18. text_option = QTextOption()
  19. text_option.setWrapMode(QTextOption.WrapMode.WordWrap) # Enable word wrap
  20. # Draw the text inside the cell with word wrapping
  21. painter.setClipRect(option.rect) # Set clipping to the cell's rectangle
  22. painter.drawText(rect, index.data(), text_option) # Correct method signature here
  23. painter.restore()
  24. else:
  25. super().paint(painter, option, index)
  26. class CombinedDialog(QDialog):
  27. def __init__(self, layer, parent=None):
  28. super().__init__(parent)
  29. self.layer = layer
  30. # Set the dialog layout
  31. self.setWindowTitle('图层属性')
  32. layout = QVBoxLayout(self)
  33. # Create a QTabWidget to hold the different panels
  34. self.tabs = QTabWidget(self)
  35. # Add Metadata Panel (using QTableWidget instead of QTextEdit)
  36. metadata_table = QTableWidget(self) # Create a table widget for displaying metadata
  37. self.populate_metadata_table(metadata_table) # Populate the table with metadata
  38. self.tabs.addTab(metadata_table, '基本信息')
  39. # Add Preview Panel (using QgsMapCanvas in a QGraphicsView)
  40. preview_widget = QGraphicsView(self)
  41. preview_scene = QGraphicsScene(self)
  42. preview_widget.setScene(preview_scene)
  43. # Set up the map canvas for previewing the layer
  44. map_canvas = QgsMapCanvas()
  45. map_canvas.setCanvasColor(QColor('white')) # Set the canvas color to white
  46. map_canvas.setDestinationCrs(self.layer.crs()) # Set the CRS of the map canvas
  47. map_canvas.setExtent(self.layer.extent()) # Set the extent to match the layer's extent
  48. map_canvas.setLayers([self.layer]) # Set the layer to be previewed
  49. map_canvas.refresh() # Refresh the map canvas to show the layer
  50. # Add the map canvas to the preview scene
  51. preview_scene.addWidget(map_canvas)
  52. # Make sure the preview widget expands to fill the layout
  53. preview_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  54. # preview_scene.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  55. self.tabs.addTab(preview_widget, '预览')
  56. # Add Attribute Table Button
  57. if isinstance(layer, QgsVectorLayer):
  58. self.show_attribute_table_button = QPushButton("属性表", self)
  59. self.show_attribute_table_button.setFixedSize(60, 25)
  60. self.show_attribute_table_button.clicked.connect(self.show_attribute_table)
  61. layout.addWidget(self.show_attribute_table_button)
  62. # Add the QTabWidget to the layout
  63. layout.addWidget(self.tabs)
  64. # Set dialog size
  65. self.resize(800, 600)
  66. # Ensure the map canvas resizes to fit inside the scene
  67. map_canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  68. # Connect the resize event to adjust the canvas size
  69. preview_widget.resizeEvent = self.on_resize_event
  70. def on_resize_event(self, event):
  71. """Handles the resize event to ensure the map canvas adjusts its size."""
  72. # Resize the map canvas to the size of the QGraphicsView
  73. preview_widget = self.findChild(QGraphicsView)
  74. map_canvas = preview_widget.scene().items()[0] # Get the map canvas from the scene
  75. # Convert QSize to QSizeF (float size)
  76. new_size = QSizeF(preview_widget.size().width(), preview_widget.size().height())
  77. # Resize the canvas to match the new size
  78. map_canvas.resize(new_size) # Resize with QSizeF
  79. event.accept()
  80. def populate_metadata_table(self, table_widget):
  81. """Populate the table with metadata information of the layer."""
  82. # Get layer metadata
  83. metadata = [
  84. ("图层名称", self.layer.name()),
  85. # ("Layer Type", str(self.layer.type())),
  86. ("坐标系", self.layer.crs().authid()),
  87. ]
  88. if isinstance(self.layer, QgsVectorLayer):
  89. metadata.append(("要素数量", str(self.layer.featureCount())))
  90. metadata.append(("字段", ", ".join([field.name() for field in self.layer.fields()])))
  91. metadata.append(("数据范围", str(self.layer.extent().toString())))
  92. # Set the table dimensions
  93. table_widget.setRowCount(len(metadata))
  94. table_widget.setColumnCount(2)
  95. # Set the table headers
  96. table_widget.setHorizontalHeaderLabels(["属性名称", "属性值"])
  97. # Hide the headers
  98. table_widget.horizontalHeader().setVisible(False) # Hide horizontal (column) headers
  99. table_widget.verticalHeader().setVisible(False) # Optionally hide vertical (row) headers
  100. # Set column width
  101. table_widget.setColumnWidth(0, 200) # Set the first column (attribute) to a fixed width of 200px
  102. table_widget.setColumnWidth(1, 600)
  103. # Make the second column (value) stretchable
  104. # table_widget.horizontalHeader().setSectionResizeMode(1)
  105. # Populate the table with the metadata
  106. for row, (attribute, value) in enumerate(metadata):
  107. item_attr = QTableWidgetItem(attribute)
  108. item_value = QTableWidgetItem(value)
  109. # Enable word wrapping for both columns
  110. item_attr.setTextAlignment(Qt.AlignCenter | Qt.AlignLeft)
  111. item_value.setTextAlignment(Qt.AlignCenter | Qt.AlignLeft)
  112. # Wrap text in the second column (value)
  113. text_option = QTextOption()
  114. text_option.setWrapMode(QTextOption.WrapMode.WordWrap) # Enable word wrap for this column
  115. item_value.setText(value) # Apply value with word wrap option
  116. # Add items to the table
  117. table_widget.setItem(row, 0, item_attr)
  118. table_widget.setItem(row, 1, item_value)
  119. delegate = WordWrapDelegate()
  120. table_widget.setItemDelegateForColumn(1, delegate)
  121. table_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
  122. table_widget.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
  123. # Resize the columns to fit the content
  124. table_widget.resizeColumnsToContents()
  125. table_widget.resizeColumnToContents(1)
  126. def get_layer_metadata(self, layer):
  127. """Return basic metadata information of the layer"""
  128. metadata = []
  129. # Get layer name
  130. metadata.append(f"Layer Name: {layer.name()}")
  131. # Get layer type
  132. metadata.append(f"Layer Type: {layer.type()}")
  133. # Get CRS (Coordinate Reference System)
  134. metadata.append(f"CRS: {layer.crs().authid()}")
  135. # Get feature count
  136. if isinstance(layer, QgsVectorLayer):
  137. metadata.append(f"Feature Count: {layer.featureCount()}")
  138. # Get fields (attribute names)
  139. fields = ", ".join([field.name() for field in layer.fields()])
  140. metadata.append(f"Fields: {fields}")
  141. # Get extent
  142. metadata.append(f"Extent: {layer.extent().toString()}")
  143. return "\n".join(metadata)
  144. def show_attribute_table(self):
  145. """Show the attribute table for the current layer"""
  146. # Ensure the attribute table is brought to the front
  147. # Bring the main window and attribute table dialog to the front
  148. main_window = iface.mainWindow()
  149. main_window.raise_() # Raise the main window to the front
  150. main_window.activateWindow() # Focus the main window
  151. # Additionally, ensure the active window is focused (in case the attribute table dialog gets hidden)
  152. iface.showAttributeTable(self.layer) # Reopen if needed to ensure focus
  153. def showDialog(self):
  154. self.exec_()
  155. # Usage:
  156. # layer = iface.activeLayer() # Get the active layer
  157. # if layer:
  158. # dialog = CombinedDialog(layer)
  159. # dialog.showDialog()
  160. # else:
  161. # print("No layer selected")