292 lines
12 KiB
Python
292 lines
12 KiB
Python
import multiprocessing
|
|
import os
|
|
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
|
|
QLineEdit, QFileDialog, QMessageBox, QListWidget,
|
|
QComboBox, QSpinBox, QGroupBox, QFormLayout, QCheckBox)
|
|
from ..runners.script_runner import ScriptRunner
|
|
from ..components.file_list_group import FileListGroup
|
|
|
|
|
|
class ExportImageTab(QWidget):
|
|
"""导出成果图标签页"""
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.main_window = parent
|
|
self.runner = ScriptRunner(self)
|
|
self.connect_signals()
|
|
self.init_ui()
|
|
self.load_settings()
|
|
self.on_load_files()
|
|
|
|
def connect_signals(self):
|
|
"""连接脚本运行器信号"""
|
|
# 连接ScriptRunner的信号
|
|
self.runner.task_started.connect(self.on_script_started)
|
|
self.runner.task_finished.connect(self.on_script_finished)
|
|
self.runner.task_error.connect(self.on_script_error)
|
|
self.runner.task_log.connect(self.on_script_log)
|
|
|
|
def init_ui(self):
|
|
main_layout = QVBoxLayout(self)
|
|
|
|
# 输入输出设置组
|
|
io_group = QGroupBox("输入输出设置")
|
|
io_layout = QFormLayout()
|
|
|
|
# 地图文档文件夹选择
|
|
data_layout = QHBoxLayout()
|
|
self.input_aprx_path_edit = QLineEdit()
|
|
data_layout.addWidget(self.input_aprx_path_edit)
|
|
browse_data_btn = QPushButton("浏览...")
|
|
browse_data_btn.clicked.connect(self.browse_data_source)
|
|
data_layout.addWidget(browse_data_btn)
|
|
io_layout.addRow("工程文件夹:", data_layout)
|
|
|
|
# 输出路径选择
|
|
output_layout = QHBoxLayout()
|
|
self.output_image_path_edit = QLineEdit()
|
|
output_layout.addWidget(self.output_image_path_edit)
|
|
browse_output_btn = QPushButton("浏览...")
|
|
browse_output_btn.clicked.connect(self.browse_output)
|
|
output_layout.addWidget(browse_output_btn)
|
|
io_layout.addRow("输出文件夹:", output_layout)
|
|
|
|
io_group.setLayout(io_layout)
|
|
main_layout.addWidget(io_group)
|
|
|
|
# 添加文件列表布局
|
|
self.file_list_group = FileListGroup(self, "选择要导出的文件")
|
|
self.file_list_group.load_files.connect(self.on_load_files)
|
|
main_layout.addWidget(self.file_list_group)
|
|
|
|
# 导出设置组
|
|
export_group = QGroupBox("导出设置")
|
|
export_layout = QFormLayout()
|
|
|
|
# 格式选择
|
|
self.format_combo = QComboBox()
|
|
self.format_combo.addItems(["PDF", "PNG", "JPG", "TIFF", "EPS", "SVG", "AI"])
|
|
export_layout.addRow("导出格式:", self.format_combo)
|
|
|
|
# 分辨率设置
|
|
self.resolution_spinbox = QSpinBox()
|
|
self.resolution_spinbox.setRange(72, 1200)
|
|
self.resolution_spinbox.setSingleStep(12)
|
|
self.resolution_spinbox.setValue(300)
|
|
self.resolution_spinbox.setSuffix(" DPI")
|
|
export_layout.addRow("分辨率:", self.resolution_spinbox)
|
|
|
|
# 强制重新生成选项
|
|
self.image_force_regenerate_check = QCheckBox("强制重新生成工程文件")
|
|
self.image_force_regenerate_check.setChecked(False)
|
|
self.image_force_regenerate_check.setToolTip("勾选后将忽略已存在的工程文件,重新生成")
|
|
export_layout.addRow("处理选项:", self.image_force_regenerate_check)
|
|
|
|
# 多进程设置
|
|
self.use_multiprocessing = QCheckBox("使用多进程导出")
|
|
self.use_multiprocessing.setChecked(True)
|
|
export_layout.addRow("批量模式:", self.use_multiprocessing)
|
|
|
|
# 进程数量设置
|
|
self.process_count = QSpinBox()
|
|
self.process_count.setRange(1, multiprocessing.cpu_count())
|
|
self.process_count.setValue(max(1, multiprocessing.cpu_count() - 1)) # 默认使用CPU核心数-1
|
|
export_layout.addRow("进程数量:", self.process_count)
|
|
|
|
export_group.setLayout(export_layout)
|
|
main_layout.addWidget(export_group)
|
|
|
|
# 操作按钮
|
|
self.export_existing_btn = QPushButton("导出成果图")
|
|
self.export_existing_btn.setToolTip("仅导出输出文件夹中已存在的工程文件")
|
|
self.export_existing_btn.clicked.connect(self.on_export_existing)
|
|
|
|
main_layout.addWidget(self.export_existing_btn)
|
|
# main_layout.addStretch()
|
|
def browse_data_source(self):
|
|
"""浏览工程目录"""
|
|
initial_dir = ""
|
|
if os.path.exists(self.input_aprx_path_edit.text()):
|
|
initial_dir = os.path.dirname(self.input_aprx_path_edit.text())
|
|
|
|
dir_path = QFileDialog.getExistingDirectory(self, "选择工程目录", initial_dir)
|
|
if dir_path:
|
|
self.input_aprx_path_edit.setText(dir_path)
|
|
self.on_load_files()
|
|
|
|
def browse_output(self):
|
|
"""选择输出路径"""
|
|
initial_dir = ""
|
|
if os.path.exists(self.output_image_path_edit.text()):
|
|
initial_dir = os.path.dirname(self.output_image_path_edit.text())
|
|
|
|
dir_path = QFileDialog.getExistingDirectory(self, "选择输出路径", initial_dir)
|
|
if dir_path:
|
|
self.output_image_path_edit.setText(dir_path)
|
|
|
|
def on_load_files(self):
|
|
"""加载图层列表"""
|
|
try:
|
|
input_aprx_path = self.input_aprx_path_edit.text()
|
|
if not os.path.exists(input_aprx_path):
|
|
QMessageBox.warning(self, "错误", "请先选择输入文件夹")
|
|
return
|
|
|
|
# 清空列表
|
|
self.file_list_group.file_list.clear()
|
|
|
|
# 添加文件
|
|
for file_name in os.listdir(input_aprx_path):
|
|
file_path = os.path.join(input_aprx_path, file_name)
|
|
if file_name.endswith(".aprx") and os.path.isfile(file_path):
|
|
self.file_list_group.file_list.addItem(file_path)
|
|
|
|
self.log_message(f"已加载 {self.file_list_group.file_list.count()} 个文件")
|
|
|
|
except Exception as e:
|
|
self.log_message(f"加载文件失败: {str(e)}")
|
|
|
|
def on_script_started(self, task_id, task_description):
|
|
"""脚本开始执行回调"""
|
|
self.set_buttons_enabled(False)
|
|
self.log_message(f"{task_id}: 正在运行 - {task_description}")
|
|
|
|
def on_script_finished(self, task_id:str, success:bool, message:str):
|
|
"""脚本执行完成回调"""
|
|
self.set_buttons_enabled(True)
|
|
if success:
|
|
QMessageBox.information(self, "成功", "成果图导出完成!")
|
|
else:
|
|
QMessageBox.warning(self, "失败", "导出过程中出现错,请查看日志详情")
|
|
|
|
def on_script_error(self, error_msg):
|
|
"""脚本执行错误回调"""
|
|
self.set_buttons_enabled(True)
|
|
self.log_message(f"错误: {error_msg}")
|
|
QMessageBox.critical(self, "错误", error_msg)
|
|
|
|
def on_script_log(self, task_id, message):
|
|
"""脚本输出日志"""
|
|
self.log_message(f"{task_id}: {message}")
|
|
def log_message(self, message):
|
|
"""日志输出"""
|
|
if self.main_window and hasattr(self.main_window, 'log_signal'):
|
|
self.main_window.log_signal.emit(message)
|
|
else:
|
|
print(message)
|
|
def set_buttons_enabled(self, enabled):
|
|
"""设置按钮启用状态"""
|
|
self.export_existing_btn.setEnabled(enabled)
|
|
|
|
def validate_and_params(self):
|
|
"""验证输入参数并返回参数"""
|
|
# 验证工程文件
|
|
aprx_files = self.file_list_group.file_list.selectedItems()
|
|
if not aprx_files or len(aprx_files) == 0:
|
|
QMessageBox.warning(self, "警告", "请选择要导出的文件")
|
|
return None
|
|
|
|
# 验证工程目录
|
|
input_aprx_folder = self.input_aprx_path_edit.text()
|
|
if not os.path.exists(input_aprx_folder):
|
|
QMessageBox.warning(self, "警告", "请选择有效的工程文件目录")
|
|
return None
|
|
|
|
# 验证输出路径
|
|
output_image_path = self.output_image_path_edit.text()
|
|
if not os.path.exists(output_image_path):
|
|
QMessageBox.warning(self, "警告", "请选择输出路径")
|
|
return None
|
|
|
|
aprx_file_list = [file.text() for file in aprx_files]
|
|
output_image_path = os.path.join(output_image_path, self.format_combo.currentText().lower())
|
|
|
|
return {
|
|
'input_aprx_folder': input_aprx_folder,
|
|
'aprx_file_list': aprx_file_list,
|
|
'output_image_path': output_image_path
|
|
}
|
|
|
|
def get_layout_settings(self):
|
|
""" 获取布局设置 """
|
|
config = {
|
|
'input_aprx_path': self.input_aprx_path_edit.text(),
|
|
'output_image_path': self.output_image_path_edit.text(),
|
|
'default_format': self.format_combo.currentText(),
|
|
'resolution': self.resolution_spinbox.value(),
|
|
'force_regenerate': self.image_force_regenerate_check.isChecked(),
|
|
'use_multiprocessing': self.use_multiprocessing.isChecked(),
|
|
'process_count': self.process_count.value()
|
|
}
|
|
|
|
return config
|
|
|
|
def load_settings(self):
|
|
"""加载设置"""
|
|
if not self.main_window:
|
|
return
|
|
|
|
try:
|
|
settings = self.main_window.settings
|
|
export_image_settings = settings.get('export_image_settings', {})
|
|
|
|
self.input_aprx_path_edit.setText(export_image_settings.get('input_aprx_path', ''))
|
|
self.output_image_path_edit.setText(export_image_settings.get('output_image_path', ''))
|
|
# 设置导出格式
|
|
format_index = self.format_combo.findText(export_image_settings.get('default_format', 'PDF'))
|
|
if format_index >= 0:
|
|
self.format_combo.setCurrentIndex(format_index)
|
|
|
|
# 设置分辨率
|
|
self.resolution_spinbox.setValue(export_image_settings.get('resolution', 300))
|
|
|
|
except Exception as e:
|
|
self.log_message(f"加载设置失败: {str(e)}")
|
|
|
|
def on_export_layout(self):
|
|
"""仅导出布局按钮点击事件"""
|
|
# 验证并获取参数
|
|
layout_params = self.validate_and_params()
|
|
if not layout_params:
|
|
return
|
|
|
|
# 准备导出布局参数
|
|
|
|
layout_params['export_format'] = self.format_combo.currentText()
|
|
layout_params['resolution'] = self.resolution_spinbox.value()
|
|
layout_params['image_force_regenerate'] = self.image_force_regenerate_check.isChecked()
|
|
print(layout_params)
|
|
|
|
# 调用导出布局脚本
|
|
# self.runner.run_export_layout(layout_params)
|
|
|
|
def on_export_existing(self):
|
|
"""导出已有工程按钮点击事件"""
|
|
# 验证并获取参数
|
|
layout_params = self.validate_and_params()
|
|
if not layout_params:
|
|
return
|
|
|
|
# 确认是否导出所有工程文件
|
|
result = QMessageBox.question(
|
|
self,
|
|
"确认",
|
|
f"将导出 {len(layout_params['aprx_file_list'])} 个工程文件的布局,是否继续?",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if result == QMessageBox.StandardButton.No:
|
|
return
|
|
|
|
# 准备批量导出布局参数
|
|
layout_params['export_format'] = self.format_combo.currentText()
|
|
layout_params['resolution'] = self.resolution_spinbox.value()
|
|
layout_params['image_force_regenerate'] = self.image_force_regenerate_check.isChecked()
|
|
layout_params['use_multiprocessing'] = self.use_multiprocessing.isChecked()
|
|
layout_params['process_count'] = self.process_count.value()
|
|
|
|
# 调用批量导出布局脚本
|
|
# print(layout_params)
|
|
self.runner.run_export_layout(layout_params)
|