#!/usr/bin/env python # -*- coding: utf-8 -*- """ 导出地图选项卡模块 """ import os import arcpy import traceback from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLabel, QLineEdit, QPushButton, QCheckBox, QFileDialog, QMessageBox) from PyQt6.QtCore import pyqtSignal from ..components.file_list_group import FileListGroup from ..runners.script_runner import ScriptRunner class ExportMapTab(QWidget): """导出地图选项卡""" # 定义日志信号,用于将日志消息传递给主窗口 log_signal = pyqtSignal(str) def __init__(self, parent=None): super().__init__(parent) self.main_window = parent self.setupUi() self.load_settings() def setupUi(self): """设置界面""" # 主布局 self.main_layout = QVBoxLayout(self) # 参数区域 self.form_layout = QFormLayout() # 区县名称 self.county_name_edit = QLineEdit() self.form_layout.addRow("区县名称:", self.county_name_edit) # 配置文件 config_layout = QHBoxLayout() self.config_file_edit = QLineEdit() self.config_file_edit.setEnabled(False) config_layout.addWidget(self.config_file_edit) # self.config_file_browse = QPushButton("浏览...") # self.config_file_browse.clicked.connect(self.on_browse_config_file) # config_layout.addWidget(self.config_file_browse) self.form_layout.addRow("配置文件:", config_layout) # 模板文件 self.template_aprx_file_edit = QLineEdit() self.template_path_browse = QPushButton("浏览...") self.template_path_browse.clicked.connect(self.on_browse_template_path) template_layout = QHBoxLayout() template_layout.addWidget(self.template_aprx_file_edit) template_layout.addWidget(self.template_path_browse) self.form_layout.addRow("模板文件:", template_layout) # 数据源路径 self.data_source_path_edit = QLineEdit() self.data_source_path_browse = QPushButton("浏览...") self.data_source_path_browse.clicked.connect(self.on_browse_data_source_path) data_source_layout = QHBoxLayout() data_source_layout.addWidget(self.data_source_path_edit) data_source_layout.addWidget(self.data_source_path_browse) self.form_layout.addRow("数据源路径:", data_source_layout) # 符号系统路径 self.symbol_path_edit = QLineEdit() self.symbol_path_browse = QPushButton("浏览...") self.symbol_path_browse.clicked.connect(self.on_browse_symbol_path) symbol_layout = QHBoxLayout() symbol_layout.addWidget(self.symbol_path_edit) symbol_layout.addWidget(self.symbol_path_browse) self.form_layout.addRow("符号系统路径:", symbol_layout) # 统计表格图片路径 self.pic_path_edit = QLineEdit() self.pic_path_browse = QPushButton("浏览...") self.pic_path_browse.clicked.connect(self.on_browse_pic_path) pic_layout = QHBoxLayout() pic_layout.addWidget(self.pic_path_edit) pic_layout.addWidget(self.pic_path_browse) self.form_layout.addRow("面积统计图片路径:", pic_layout) # 输出路径 self.output_path_edit = QLineEdit() self.output_path_browse = QPushButton("浏览...") self.output_path_browse.clicked.connect(self.on_browse_output_path) output_layout = QHBoxLayout() output_layout.addWidget(self.output_path_edit) output_layout.addWidget(self.output_path_browse) self.form_layout.addRow("输出路径:", output_layout) # 文件列表布局 self.file_list_group = FileListGroup(self, "选择要导出的要素类:") self.file_list_group.load_files.connect(self.on_load_polygon) # 选项区域 options_layout = QVBoxLayout() # 强制重新生成选项 self.force_regenerate_check = QCheckBox("强制重新生成工程文件") options_layout.addWidget(self.force_regenerate_check) # 添加到主布局 self.main_layout.addLayout(self.form_layout) self.main_layout.addWidget(self.file_list_group) self.main_layout.addLayout(options_layout) # 导出按钮 self.export_button = QPushButton("导出地图") self.export_button.clicked.connect(self.on_export_map) self.main_layout.addWidget(self.export_button) # 状态标签 self.status_label = QLabel("状态: 就绪") self.main_layout.addWidget(self.status_label) def on_browse_config_file(self): """浏览配置文件""" initial_dir = "" if os.path.exists(self.config_file_edit.text()): initial_dir = self.config_file_edit.text() file_path, _ = QFileDialog.getOpenFileName(self, "选择配置文件", initial_dir, "JSON文件 (*.json);;所有文件 (*.*)") if file_path: self.config_file_edit.setText(file_path) def on_browse_template_path(self): """浏览模板文件""" initial_dir = "" if os.path.exists(self.template_aprx_file_edit.text()): initial_dir = self.template_aprx_file_edit.text() file_path, _ = QFileDialog.getOpenFileName(self, "选择模板文件", initial_dir, "ArcGIS Pro工程文件 (*.aprx)") if file_path: self.template_aprx_file_edit.setText(file_path) def on_browse_data_source_path(self): """浏览数据源路径""" initial_dir = "" if os.path.exists(self.data_source_path_edit.text()): initial_dir = os.path.dirname(self.data_source_path_edit.text()) folder_path = QFileDialog.getExistingDirectory(self, "选择数据源文件夹", initial_dir) if folder_path and folder_path.endswith(".gdb"): self.data_source_path_edit.setText(folder_path) # 自动加载图层列表 self.on_load_polygon() else: QMessageBox.warning(self, "错误", "请选择GDB的数据源。") def on_browse_symbol_path(self): """浏览符号系统路径""" initial_dir = "" if os.path.exists(self.symbol_path_edit.text()): initial_dir = os.path.dirname(self.symbol_path_edit.text()) folder_path = QFileDialog.getExistingDirectory(self, "选择符号系统文件夹", initial_dir) if folder_path: self.symbol_path_edit.setText(folder_path) def on_browse_pic_path(self): """浏览符号系统路径""" initial_dir = "" if os.path.exists(self.pic_path_edit.text()): initial_dir = os.path.dirname(self.pic_path_edit.text()) folder_path = QFileDialog.getExistingDirectory(self, "选择符号系统文件夹", initial_dir) if folder_path: self.pic_path_edit.setText(folder_path) def on_browse_output_path(self): """浏览输出路径""" initial_dir = "" if os.path.exists(self.output_path_edit.text()): initial_dir = os.path.dirname(self.output_path_edit.text()) folder_path = QFileDialog.getExistingDirectory(self, "选择输出文件夹", initial_dir) if folder_path.endswith(".gdb"): QMessageBox.warning(self, "警告", "请选择有效的输出路径") return self.output_path_edit.setText(folder_path) def on_load_polygon(self): """加载图层列表""" try: data_source_paths = self.data_source_path_edit.text() # 清空列表 self.file_list_group.file_list.clear() # 添加图层 if arcpy.Exists(data_source_paths): arcpy.env.workspace = data_source_paths for polygon in arcpy.ListFeatureClasses(feature_type="Polygon"): self.file_list_group.file_list.addItem(polygon) self.log_message(f"已加载 {self.file_list_group.file_list.count()} 个图层") except Exception as e: self.log_error(f"加载图层列表失败: {str(e)}") traceback.print_exc() def get_selected_polygon(self): """获取选中的图层列表""" selected_items = self.file_list_group.file_list.selectedItems() return [item.text() for item in selected_items] def on_export_map(self): """导出地图按钮点击事件""" try: # 验证并获取参数 params = self.validate_and_params() if not params: return polygon_list = params.get('polygon_list') # 清空日志 self.log_message("开始导出工程文件...") self.log_message(f"选中的图层: {polygon_list}") # 创建导出线程 self.runner = ScriptRunner() self.runner.task_log.connect(self.on_script_log) self.runner.task_error.connect(self.log_error) self.runner.task_finished.connect(self.on_script_finished) # 禁用导出按钮 self.export_button.setEnabled(False) self.status_label.setText("状态: 正在导出...") # 运行导出脚本(使用外部窗口) # print(params) self.runner.run_export_map(params) except Exception as e: self.log_error(f"导出准备过程出错: {str(e)}") traceback.print_exc() def log_message(self, message): """添加日志消息""" # 如果父窗口存在,使用父窗口的日志功能 if self.main_window and hasattr(self.main_window, 'log_signal'): self.main_window.log_signal.emit(message) else: # 否则发射自己的信号 self.log_signal.emit(message) def log_error(self, message): """添加错误日志""" self.log_message(f"错误: {message}") def on_script_log(self, task_id, message): """脚本输出日志""" self.log_message(f"{task_id}: {message}") def on_script_finished(self, task_id:str, success:bool, message:str): """导出完成事件处理""" # 恢复导出按钮 self.export_button.setEnabled(True) if success: self.status_label.setText("状态: 导出完成") QMessageBox.information(self, "成功", "地图导出完成!") else: self.status_label.setText("状态: 导出失败") QMessageBox.warning(self, "失败", "地图导出过程中出现错误,请查看日志详情") def validate_and_params(self): # 获取输入参数 county_name = self.county_name_edit.text().strip() if not county_name: QMessageBox.warning(self, "错误", "请输入区县名称") return # 获取面要素列表 polygon_list = self.get_selected_polygon() if not polygon_list: QMessageBox.warning(self, "错误", "请选择至少一个要素") return # 获取配置文件 config_file = self.config_file_edit.text() if not os.path.exists(config_file): QMessageBox.warning(self, "错误", "配置文件不存在") return # 获取模板文件 template_aprx_file = self.template_aprx_file_edit.text() if not os.path.exists(template_aprx_file): QMessageBox.warning(self, "错误", "模板文件不存在") return # 获取输出路径 output_path = self.output_path_edit.text() if not output_path: QMessageBox.warning(self, "错误", "请选择输出路径") return # 获取数据源路径 data_source_path = self.data_source_path_edit.text() if not os.path.exists(data_source_path) and not data_source_path.endswith(".gdb"): QMessageBox.warning(self, "错误", "请确认是否是有效数据源") return # 获取符号系统路径 symbol_path = self.symbol_path_edit.text() if not os.path.exists(symbol_path): QMessageBox.warning(self, "错误", "符号系统路径不存在") return # 获取图片源路径 pic_path = self.pic_path_edit.text() if not os.path.exists(pic_path): QMessageBox.warning(self, "错误", "符号系统路径不存在") return # 是否强制重新生成 force_regenerate = self.force_regenerate_check.isChecked() # 准备参数 return { 'config_file': config_file, 'county_name': county_name, 'polygon_list': polygon_list, 'template_aprx_file': template_aprx_file, 'output_path': output_path, 'data_source_path': data_source_path, 'symbol_path': symbol_path, 'force_regenerate': force_regenerate, 'pic_path': pic_path } def load_settings(self): """从主窗口加载设置""" try: if not self.main_window or not hasattr(self.main_window, 'settings'): return settings = self.main_window.settings if 'export_map_settings' in settings: paths = settings['export_map_settings'] # 直接使用get方法设置默认值 self.config_file_edit.setText(paths.get("config_file", "")) self.county_name_edit.setText(paths.get("county_name", "")) self.template_aprx_file_edit.setText(paths.get("template_aprx_file", "")) self.output_path_edit.setText(paths.get("output_path", "")) self.data_source_path_edit.setText(paths.get("data_source_path", "")) self.symbol_path_edit.setText(paths.get("symbol_path", "")) self.pic_path_edit.setText(paths.get("pic_path", "")) except Exception as e: self.log_error(f"加载设置失败: {str(e)}") def get_settings(self): """获取当前设置,供主窗口保存使用""" return { 'config_file': self.config_file_edit.text(), 'county_name': self.county_name_edit.text(), 'template_aprx_file': self.template_aprx_file_edit.text(), 'output_path': self.output_path_edit.text(), 'data_source_path': self.data_source_path_edit.text(), 'symbol_path': self.symbol_path_edit.text(), 'pic_path': self.pic_path_edit.text() } def update_config_file(self, config_file): self.config_file_edit.setText(config_file)