实现层级目录窗口
This commit is contained in:
parent
c28642bdec
commit
efc37d4270
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"检查人员": "213",
|
||||
"厂家人员": "213",
|
||||
"业主人员": "213",
|
||||
"数据处理人员": "213",
|
||||
"报告编制人员": "123",
|
||||
"机组型号": "123",
|
||||
"机组厂家": "213",
|
||||
"施工日期": "开始-结束",
|
||||
"": "123",
|
||||
"外部检查": true,
|
||||
"内部检查": true,
|
||||
"防雷检查": true,
|
||||
"json路径": "/home/dtyx/桌面/yhh/ReportGenerator/config/单次检查配置信息"
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"项目名称": "123",
|
||||
"风场名": "123",
|
||||
"风场地址": "213",
|
||||
"甲方公司": "123",
|
||||
"甲方负责人": "123",
|
||||
"甲方负责人电话": "123",
|
||||
"乙方公司": "武汉迪特聚能科技有限公司",
|
||||
"乙方负责人": "123",
|
||||
"乙方负责人电话": "123",
|
||||
"项目规格": "213",
|
||||
"项目工期": "123",
|
||||
"json路径": "/home/dtyx/桌面/yhh/ReportGenerator/config/项目基本信息"
|
||||
}
|
Binary file not shown.
|
@ -1,9 +1,13 @@
|
|||
from PySide6.QtWidgets import (QGroupBox, QVBoxLayout, QHBoxLayout, QCheckBox,
|
||||
QPushButton, QDialog, QLineEdit, QFontComboBox,
|
||||
QFileDialog, QMessageBox, QLabel, QWidget,
|
||||
QTextBrowser, QApplication, QCompleter, QFrame)
|
||||
from PySide6.QtCore import QDateTime,QTimer,QDateTime,Signal,QSettings, QSortFilterProxyModel
|
||||
from PySide6.QtGui import QPixmap, QDragEnterEvent, QDropEvent, Qt, QIcon
|
||||
QTextBrowser, QApplication, QCompleter, QFrame,
|
||||
QListWidgetItem, QListWidget, QAbstractItemView,
|
||||
QStackedWidget, QStackedLayout)
|
||||
from PySide6.QtCore import (QDateTime,QTimer,QDateTime,Signal,QSettings,
|
||||
QSortFilterProxyModel, QSize)
|
||||
from PySide6.QtGui import (QPixmap, QDragEnterEvent, QDropEvent, Qt, QIcon,
|
||||
QFontMetrics)
|
||||
import json, sys, os
|
||||
|
||||
from info_core.defines import *
|
||||
|
@ -138,6 +142,10 @@ class ConfigComboBoxGroup(QGroupBox):
|
|||
QMessageBox.information(self, '信息', '删除操作已取消。')
|
||||
else:
|
||||
QMessageBox.warning(self, '警告', '没有选中任何项目。')
|
||||
def get_current_config_file(self):
|
||||
"""获取当前选中的配置文件"""
|
||||
return os.path.join(self.config_dir, self.combo_box.currentText() + ".json")
|
||||
|
||||
|
||||
class AddProjectDialog(QDialog):
|
||||
def __init__(self, dir, parent=None, path=None, combobox=None):
|
||||
|
@ -298,8 +306,9 @@ class AddPersonnelDialog(QDialog):
|
|||
{"key": "报告编制人员", "label": "报告编制人员:", "default": ""},
|
||||
{"key": "机组型号", "label": "机组型号:", "default": ""},
|
||||
{"key": "机组厂家", "label": "机组厂家:", "default": ""},
|
||||
{"key": "叶片型号", "label": "叶片型号", "default": ""},
|
||||
{"key": "叶片厂家", "label": "叶片厂家:", "default": ""},
|
||||
{"key": "施工日期", "label": "施工日期", "default": "开始-结束"},
|
||||
{"key": "", "label": "", "default": ""},
|
||||
#{"key": "", "label": "", "default": ""},
|
||||
# 可以轻松添加更多人员字段
|
||||
]
|
||||
|
@ -377,7 +386,25 @@ class AddPersonnelDialog(QDialog):
|
|||
self.save_button = QPushButton("保存")
|
||||
self.save_button.clicked.connect(self.on_save_button_clicked)
|
||||
|
||||
# 创建复选框布局
|
||||
checkbox_group = QGroupBox("检查类型")
|
||||
checkbox_layout = QHBoxLayout()
|
||||
|
||||
# 添加复选框
|
||||
self.checkboxes = {}
|
||||
for field in self.checkbox_fields:
|
||||
checkbox = QCheckBox(field["label"])
|
||||
if self.path and field["key"] in self.data:
|
||||
checkbox.setChecked(bool(self.data[field["key"]]))
|
||||
else:
|
||||
checkbox.setChecked(field["default"])
|
||||
self.checkboxes[field["key"]] = checkbox
|
||||
checkbox_layout.addWidget(checkbox)
|
||||
|
||||
checkbox_group.setLayout(checkbox_layout)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(checkbox_group)
|
||||
main_layout.addWidget(form_widget)
|
||||
main_layout.addWidget(self.save_button)
|
||||
|
||||
|
@ -390,6 +417,10 @@ class AddPersonnelDialog(QDialog):
|
|||
field["key"]: self.fields[field["key"]].text()
|
||||
for field in self.form_fields
|
||||
}
|
||||
# 添加复选框数据
|
||||
for key, checkbox in self.checkboxes.items():
|
||||
personnel_info[key] = checkbox.isChecked()
|
||||
|
||||
personnel_info["json路径"] = self.dir
|
||||
|
||||
# 验证保存目录
|
||||
|
@ -420,11 +451,7 @@ class AddPersonnelDialog(QDialog):
|
|||
QMessageBox.critical(self, "错误", f"保存文件失败: {str(e)}")
|
||||
return
|
||||
|
||||
# 更新QComboBox
|
||||
if self.combobox is None:
|
||||
self.parent().ui.personnel.addItem(os.path.basename(file_path))
|
||||
else:
|
||||
self.combobox.load_config_files(os.path.basename(self.dir))
|
||||
self.parent().load_config_files()
|
||||
|
||||
# 提示用户保存成功
|
||||
QMessageBox.information(self, "信息", f"人员信息已成功保存到 {file_path}")
|
||||
|
@ -700,386 +727,300 @@ class SmartDropdown(QWidget):
|
|||
except ValueError:
|
||||
self.messagebrowser.append(f"删除失败: 选项 {current_text} 不存在")
|
||||
|
||||
class FolderImportWidget(QGroupBox):
|
||||
"""支持双路径独立导入的组件"""
|
||||
main_folder_selected = Signal(str) # 仅总图片路径变化时发射
|
||||
selected_folder_selected = Signal(str) # 选中路径变化时发射
|
||||
get_baogao_choose_info = Signal(str) # 获取报告选择
|
||||
class FolderDropWidget(QWidget):
|
||||
selection_changed = Signal(list)
|
||||
|
||||
def __init__(self, title: str = "图片文件夹导入", parent=None):
|
||||
super().__init__(title, parent)
|
||||
self.main_folder = None
|
||||
self.selected_folder = None
|
||||
self.setup_ui()
|
||||
self.apply_styles()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
self.setMinimumSize(GROUP_BOX_MIN_WIDTH, GROUP_BOX_MIN_HEIGHT)
|
||||
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.setSpacing(GROUP_BOX_SPACING)
|
||||
main_layout.setContentsMargins(*GROUP_BOX_MARGINS)
|
||||
|
||||
# ================= 总图片路径区域 =================
|
||||
self.main_group = DropGroupBox("总图片路径(自动解析数量,生成略缩图)")
|
||||
main_group_layout = QVBoxLayout()
|
||||
|
||||
# 拖拽区域
|
||||
self.main_drag_label = QLabel("拖拽文件夹到此处或点击按钮选择")
|
||||
self.main_drag_label.setProperty("class", "waiting-label")
|
||||
|
||||
# 路径显示
|
||||
self.main_path_label = QLabel("未选择")
|
||||
self.main_path_label.setProperty("class", "info-display")
|
||||
|
||||
# 选择按钮
|
||||
self.main_select_btn = QPushButton("选择总图片文件夹")
|
||||
self.main_select_btn.setProperty("class", "normal-button")
|
||||
|
||||
main_group_layout.addWidget(self.main_drag_label)
|
||||
main_group_layout.addWidget(self.main_path_label)
|
||||
main_group_layout.addWidget(self.main_select_btn, 0, Qt.AlignmentFlag.AlignHCenter)
|
||||
self.main_group.setLayout(main_group_layout)
|
||||
self.main_group.setAcceptDrops(True)
|
||||
|
||||
# ================= 选中图片路径区域 =================
|
||||
self.selected_group = DropGroupBox("选中图片路径(获取典型部位图片,自动读取图片名做描述)")
|
||||
selected_group_layout = QVBoxLayout()
|
||||
|
||||
# 拖拽区域
|
||||
self.selected_drag_label = QLabel("拖拽文件夹到此处或点击按钮选择")
|
||||
self.selected_drag_label.setProperty("class", "waiting-label")
|
||||
|
||||
# 路径显示
|
||||
self.selected_path_label = QLabel("未选择")
|
||||
self.selected_path_label.setProperty("class", "info-display")
|
||||
|
||||
# 选择按钮
|
||||
self.selected_select_btn = QPushButton("选择图片文件夹")
|
||||
self.selected_select_btn.setProperty("class", "normal-button")
|
||||
|
||||
self.modify_layout = QHBoxLayout()
|
||||
self.modify_picture_quexian_btn = QPushButton("修改图片缺陷信息")
|
||||
self.modify_picture_quexian_btn.setProperty("class", "normal-button")
|
||||
self.modify_picture_quexian_btn.setEnabled(False)
|
||||
self.modify_picture_quexian_btn.clicked.connect(self.on_modify_picture_quexian_btn_clicked)
|
||||
self.modify_picture_huizong_btn = QPushButton("修改图片汇总信息")
|
||||
self.modify_picture_huizong_btn.setProperty("class", "normal-button")
|
||||
self.modify_picture_huizong_btn.setEnabled(False)
|
||||
self.modify_picture_huizong_btn.clicked.connect(self.on_modify_picture_huizong_btn_clicked)
|
||||
self.modify_group = QGroupBox("修改图片信息")
|
||||
self.modify_layout.addWidget(self.modify_picture_quexian_btn, 0, Qt.AlignmentFlag.AlignHCenter)
|
||||
self.modify_layout.addWidget(self.modify_picture_huizong_btn, 0, Qt.AlignmentFlag.AlignHCenter)
|
||||
self.modify_layout.addStretch(1)
|
||||
self.modify_group.setLayout(self.modify_layout)
|
||||
|
||||
|
||||
selected_group_layout.addWidget(self.selected_drag_label)
|
||||
selected_group_layout.addWidget(self.selected_path_label)
|
||||
selected_group_layout.addWidget(self.selected_select_btn, 0, Qt.AlignmentFlag.AlignHCenter)
|
||||
selected_group_layout.addWidget(self.modify_group)
|
||||
self.selected_group.setLayout(selected_group_layout)
|
||||
self.selected_group.setAcceptDrops(True)
|
||||
|
||||
# ================= 添加到主布局 =================
|
||||
main_layout.addWidget(self.main_group)
|
||||
main_layout.addWidget(self.selected_group)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
# 连接信号
|
||||
self.main_select_btn.clicked.connect(lambda: self.select_folder("main"))
|
||||
self.selected_select_btn.clicked.connect(lambda: self.select_folder("selected"))
|
||||
|
||||
self.search_file_list = []
|
||||
|
||||
def apply_styles(self):
|
||||
"""应用样式"""
|
||||
self.setStyleSheet(f"""
|
||||
{GROUP_BOX_STYLE}
|
||||
/* 内部GroupBox样式 */
|
||||
QGroupBox QGroupBox {{
|
||||
font-size: {TITLE_FONT_SIZE - 1}pt;
|
||||
border: 1px solid #ced4da;
|
||||
margin-top: 16px;
|
||||
}}
|
||||
QLabel[class="waiting-label"] {{
|
||||
{WAITING_LABEL_STYLE}
|
||||
font-size: {CONTENT_FONT_SIZE}pt;
|
||||
}}
|
||||
QLabel[class="info-display"] {{
|
||||
{INFO_DISPLAY_STYLE}
|
||||
min-height: 60px;
|
||||
}}
|
||||
QPushButton[class="normal-button"] {{
|
||||
{BUTTON_STYLE}
|
||||
min-width: 160px;
|
||||
}}
|
||||
""")
|
||||
|
||||
def select_folder(self, folder_type: str):
|
||||
"""选择文件夹"""
|
||||
dialog_title = "选择总图片文件夹" if folder_type == "main" else "选择图片文件夹"
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
dialog_title,
|
||||
os.path.expanduser("~"),
|
||||
QFileDialog.Option.ShowDirsOnly | QFileDialog.Option.DontResolveSymlinks
|
||||
)
|
||||
if folder:
|
||||
self.set_folder_path(folder, folder_type)
|
||||
|
||||
def set_folder_path(self, folder_path: str, folder_type: str):
|
||||
"""设置文件夹路径并更新UI"""
|
||||
if folder_type == "main":
|
||||
self.main_folder = folder_path
|
||||
self.main_path_label.setText(folder_path)
|
||||
self.main_drag_label.hide()
|
||||
self.main_folder_selected.emit(folder_path) # 触发解析
|
||||
else:
|
||||
self.selected_folder = folder_path
|
||||
self.selected_path_label.setText(folder_path)
|
||||
self.selected_drag_label.hide()
|
||||
self.modify_picture_quexian_btn.setEnabled(True)
|
||||
self.modify_picture_huizong_btn.setEnabled(True)
|
||||
self.selected_folder_selected.emit(folder_path)
|
||||
|
||||
def dragEnterEvent(self, event: QDragEnterEvent):
|
||||
"""总区域的拖拽事件(转发到对应子区域)"""
|
||||
source = event.source()
|
||||
if isinstance(source, QGroupBox):
|
||||
# 如果是来自子区域的拖拽,交给子区域处理
|
||||
return
|
||||
|
||||
# 否则检查是否是有效的文件夹拖拽
|
||||
if event.mimeData().hasUrls():
|
||||
urls = event.mimeData().urls()
|
||||
if len(urls) == 1 and urls[0].isLocalFile():
|
||||
file_info = urls[0].toLocalFile()
|
||||
if os.path.isdir(file_info):
|
||||
event.acceptProposedAction()
|
||||
|
||||
def dropEvent(self, event: QDropEvent):
|
||||
"""总区域的放下事件(自动分配到第一个区域)"""
|
||||
urls = event.mimeData().urls()
|
||||
if urls and urls[0].isLocalFile():
|
||||
folder_path = urls[0].toLocalFile()
|
||||
if os.path.isdir(folder_path):
|
||||
self.set_folder_path(folder_path, "main")
|
||||
|
||||
def get_paths(self) -> tuple:
|
||||
"""获取两个路径(总路径,选中路径)"""
|
||||
return self.main_folder, self.selected_folder
|
||||
|
||||
def get_baogao_choose(self):
|
||||
self.get_baogao_choose_info.emit()
|
||||
|
||||
def update_baogao_choose_info(self, info: list[str]):
|
||||
self.search_file_list = info
|
||||
|
||||
def on_modify_picture_quexian_btn_clicked(self):
|
||||
"""修改图片缺陷类型"""
|
||||
# self.get_baogao_choose()
|
||||
# if self.search_file_list:
|
||||
# Y1_num, Y1 =
|
||||
|
||||
def on_modify_picture_huizong_btn_clicked(self):
|
||||
"""修改图片汇总信息"""
|
||||
self.get_baogao_choose()
|
||||
|
||||
|
||||
# 子区域GroupBox需要单独处理拖拽事件
|
||||
class DropGroupBox(QGroupBox):
|
||||
"""支持拖拽的子区域GroupBox"""
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
def dragEnterEvent(self, event: QDragEnterEvent):
|
||||
if event.mimeData().hasUrls():
|
||||
urls = event.mimeData().urls()
|
||||
if len(urls) == 1 and urls[0].isLocalFile():
|
||||
file_info = urls[0].toLocalFile()
|
||||
if os.path.isdir(file_info):
|
||||
event.acceptProposedAction()
|
||||
return
|
||||
event.ignore()
|
||||
|
||||
def dropEvent(self, event: QDropEvent):
|
||||
urls = event.mimeData().urls()
|
||||
if urls and urls[0].isLocalFile():
|
||||
folder_path = urls[0].toLocalFile()
|
||||
if os.path.isdir(folder_path):
|
||||
# 通过parent()调用主组件的方法
|
||||
parent = self.parent()
|
||||
while parent and not isinstance(parent, FolderImportWidget):
|
||||
parent = parent.parent()
|
||||
|
||||
if parent:
|
||||
folder_type = "main" if self == parent.main_group else "selected"
|
||||
parent.set_folder_path(folder_path, folder_type)
|
||||
|
||||
class ImageAnalysisWidget(QGroupBox):
|
||||
"""完全使用宏定义样式的图片解析组件"""
|
||||
generate_path_selected = Signal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setTitle("图片解析")
|
||||
self.image_folder_path = None
|
||||
self.generate_path = None
|
||||
self.setup_ui()
|
||||
self.current_dir = None
|
||||
self.selected_folders = set()
|
||||
self.init_ui()
|
||||
self.apply_styles()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
self.setMinimumSize(GROUP_BOX_MIN_WIDTH, GROUP_BOX_MIN_HEIGHT)
|
||||
|
||||
def init_ui(self):
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.setSpacing(GROUP_BOX_SPACING)
|
||||
main_layout.setContentsMargins(*GROUP_BOX_MARGINS)
|
||||
main_layout.setSpacing(15)
|
||||
main_layout.setContentsMargins(15, 15, 15, 15)
|
||||
|
||||
# 初始状态 - 等待导入
|
||||
self.waiting_label = QLabel("请先导入图片文件夹以开始解析")
|
||||
self.waiting_label.setProperty("class", "waiting-label")
|
||||
# 顶部按钮区域
|
||||
btn_layout = QHBoxLayout()
|
||||
self.reset_btn = QPushButton("重新选择项目文件夹")
|
||||
self.reset_btn.clicked.connect(self.reset_selection)
|
||||
self.reset_btn.setFixedSize(120, 40)
|
||||
self.reset_btn.setVisible(False)
|
||||
|
||||
# 解析结果区域
|
||||
self.result_frame = QFrame()
|
||||
result_layout = QVBoxLayout()
|
||||
result_layout.setSpacing(15)
|
||||
self.clear_btn = QPushButton("清空选中机组列表")
|
||||
self.clear_btn.clicked.connect(self.clear_selected)
|
||||
self.clear_btn.setFixedSize(120, 40)
|
||||
self.clear_btn.setVisible(False)
|
||||
|
||||
# 图片文件夹信息
|
||||
folder_info_layout = QHBoxLayout()
|
||||
folder_label = QLabel("图片文件夹:")
|
||||
folder_label.setProperty("class", "info-label")
|
||||
self.folder_path_label = QLabel("未选择")
|
||||
self.folder_path_label.setProperty("class", "info-display")
|
||||
folder_info_layout.addWidget(folder_label)
|
||||
folder_info_layout.addWidget(self.folder_path_label)
|
||||
btn_layout.addWidget(self.reset_btn)
|
||||
btn_layout.addWidget(self.clear_btn)
|
||||
btn_layout.addStretch()
|
||||
main_layout.addLayout(btn_layout)
|
||||
|
||||
# 图片数量信息
|
||||
count_info_layout = QHBoxLayout()
|
||||
count_label = QLabel("图片数量:")
|
||||
count_label.setProperty("class", "info-label")
|
||||
self.image_count_label = QLabel("-")
|
||||
self.image_count_label.setProperty("class", "info-display")
|
||||
count_info_layout.addWidget(count_label)
|
||||
count_info_layout.addWidget(self.image_count_label)
|
||||
# 主内容区域 - 使用堆叠布局管理不同状态
|
||||
self.stacked_layout = QStackedLayout()
|
||||
|
||||
# 分隔线
|
||||
separator = QFrame()
|
||||
separator.setFrameShape(QFrame.Shape.HLine)
|
||||
separator.setProperty("class", "separator")
|
||||
# 状态1: 未选择文件夹时的提示
|
||||
self.prompt_container = QWidget()
|
||||
prompt_layout = QVBoxLayout()
|
||||
self.prompt_label = QLabel("拖放文件夹到此处或点击选择文件夹")
|
||||
self.prompt_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.prompt_label.mousePressEvent = self.select_folder
|
||||
prompt_layout.addWidget(self.prompt_label)
|
||||
self.prompt_container.setLayout(prompt_layout)
|
||||
self.stacked_layout.addWidget(self.prompt_container)
|
||||
|
||||
# 生成路径区域
|
||||
path_info_layout = QHBoxLayout()
|
||||
path_label = QLabel("生成路径:")
|
||||
path_label.setProperty("class", "info-label")
|
||||
self.generate_path_label = QLabel("未选择")
|
||||
self.generate_path_label.setProperty("class", "info-display")
|
||||
path_info_layout.addWidget(path_label)
|
||||
path_info_layout.addWidget(self.generate_path_label)
|
||||
# 状态2: 显示第一层文件夹 (项目选择)
|
||||
self.level1_container = QWidget()
|
||||
level1_main_layout = QVBoxLayout()
|
||||
|
||||
# 选择按钮
|
||||
self.select_path_button = QPushButton("选择生成路径")
|
||||
self.select_path_button.setProperty("class", "normal-button")
|
||||
self.select_path_button.clicked.connect(self.select_generate_path)
|
||||
self.select_path_button.setEnabled(False)
|
||||
# 添加状态标签
|
||||
self.level1_title = QLabel("项目选择")
|
||||
self.level1_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
level1_main_layout.addWidget(self.level1_title)
|
||||
|
||||
# 生成报告选项
|
||||
check_box_layout = QHBoxLayout()
|
||||
self.check_is_waibu = QCheckBox("外部")
|
||||
self.check_is_neibu = QCheckBox("内部")
|
||||
self.check_is_fanglei = QCheckBox("防雷")
|
||||
self.check_is_neibu.setStyleSheet(CHECKBOX_STYLE)
|
||||
self.check_is_waibu.setStyleSheet(CHECKBOX_STYLE)
|
||||
self.check_is_fanglei.setStyleSheet(CHECKBOX_STYLE)
|
||||
check_box_layout.addWidget(self.check_is_waibu)
|
||||
check_box_layout.addWidget(self.check_is_neibu)
|
||||
check_box_layout.addWidget(self.check_is_fanglei)
|
||||
self.level1_list = QListWidget()
|
||||
self.level1_list.setIconSize(QSize(48, 48))
|
||||
self.level1_list.setViewMode(QListWidget.ViewMode.IconMode)
|
||||
self.level1_list.setResizeMode(QListWidget.ResizeMode.Adjust)
|
||||
self.level1_list.setMovement(QListWidget.Movement.Static)
|
||||
self.level1_list.setSpacing(10)
|
||||
self.level1_list.itemDoubleClicked.connect(self.show_level2_folders)
|
||||
level1_main_layout.addWidget(self.level1_list)
|
||||
|
||||
# 添加到结果布局
|
||||
result_layout.addLayout(folder_info_layout)
|
||||
result_layout.addLayout(count_info_layout)
|
||||
result_layout.addWidget(separator)
|
||||
result_layout.addLayout(path_info_layout)
|
||||
result_layout.addWidget(self.select_path_button, 0, Qt.AlignmentFlag.AlignHCenter)
|
||||
result_layout.addLayout(check_box_layout)
|
||||
result_layout.addStretch()
|
||||
self.level1_container.setLayout(level1_main_layout)
|
||||
self.stacked_layout.addWidget(self.level1_container)
|
||||
|
||||
self.result_frame.setLayout(result_layout)
|
||||
self.result_frame.hide()
|
||||
# 状态3: 显示第二层文件夹 (机组选择)
|
||||
self.level2_container = QWidget()
|
||||
level2_main_layout = QVBoxLayout()
|
||||
|
||||
# 添加状态标签
|
||||
self.level2_title = QLabel("机组选择")
|
||||
self.level2_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
level2_main_layout.addWidget(self.level2_title)
|
||||
|
||||
self.level2_list = QListWidget()
|
||||
self.level2_list.setIconSize(QSize(48, 48))
|
||||
self.level2_list.setViewMode(QListWidget.ViewMode.IconMode)
|
||||
self.level2_list.setResizeMode(QListWidget.ResizeMode.Adjust)
|
||||
self.level2_list.setMovement(QListWidget.Movement.Static)
|
||||
self.level2_list.setSpacing(10)
|
||||
level2_main_layout.addWidget(self.level2_list)
|
||||
|
||||
# 添加返回按钮
|
||||
self.back_btn = QPushButton("返回项目选择")
|
||||
self.back_btn.clicked.connect(lambda: self.stacked_layout.setCurrentIndex(1))
|
||||
level2_main_layout.addWidget(self.back_btn)
|
||||
|
||||
self.level2_container.setLayout(level2_main_layout)
|
||||
self.stacked_layout.addWidget(self.level2_container)
|
||||
|
||||
# 将堆叠布局添加到主布局
|
||||
stack_container = QWidget()
|
||||
stack_container.setLayout(self.stacked_layout)
|
||||
main_layout.addWidget(stack_container)
|
||||
|
||||
# 已选目录列表 (始终显示在底部)
|
||||
self.selected_group = QGroupBox("已选机组")
|
||||
self.selected_group.setVisible(False)
|
||||
selected_layout = QVBoxLayout()
|
||||
self.selected_list = QListWidget()
|
||||
self.selected_list.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
||||
selected_layout.addWidget(self.selected_list)
|
||||
self.selected_group.setLayout(selected_layout)
|
||||
main_layout.addWidget(self.selected_group)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(self.waiting_label)
|
||||
main_layout.addWidget(self.result_frame)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def apply_styles(self):
|
||||
"""完全使用宏定义应用样式"""
|
||||
self.setStyleSheet(GROUP_BOX_STYLE)
|
||||
self.prompt_label.setStyleSheet(f"""
|
||||
{PATH_DISPLAY_STYLE}
|
||||
border: 2px dashed {SECONDARY_COLOR};
|
||||
min-height: 150px;
|
||||
""")
|
||||
|
||||
# 通过QSS类选择器应用样式
|
||||
self.setStyleSheet(f"""
|
||||
{self.styleSheet()}
|
||||
/* 等待提示 */
|
||||
QLabel[class="waiting-label"] {{
|
||||
{WAITING_LABEL_STYLE}
|
||||
}}
|
||||
|
||||
/* 信息标签 */
|
||||
QLabel[class="info-label"] {{
|
||||
{INFO_LABEL_STYLE}
|
||||
}}
|
||||
|
||||
/* 信息显示 */
|
||||
QLabel[class="info-display"] {{
|
||||
{INFO_DISPLAY_STYLE}
|
||||
}}
|
||||
|
||||
/* 分隔线 */
|
||||
QFrame[class="separator"] {{
|
||||
{SEPARATOR_STYLE}
|
||||
}}
|
||||
|
||||
/* 普通按钮 */
|
||||
QPushButton[class="normal-button"] {{
|
||||
{BUTTON_STYLE}
|
||||
self.level1_list.setStyleSheet(f"""
|
||||
QListWidget {{
|
||||
background-color: #f8f9fa;
|
||||
min-height: 150px;
|
||||
}}
|
||||
""")
|
||||
|
||||
def set_image_folder(self, folder_path: str):
|
||||
"""设置图片文件夹路径并开始解析"""
|
||||
self.image_folder_path = folder_path
|
||||
self.folder_path_label.setText(folder_path)
|
||||
self.start_analysis()
|
||||
self.level2_list.setStyleSheet(f"""
|
||||
QListWidget {{
|
||||
background-color: #f8f9fa;
|
||||
min-height: 150px;
|
||||
}}
|
||||
""")
|
||||
|
||||
def start_analysis(self):
|
||||
"""开始解析"""
|
||||
self.total_picture_count = 0
|
||||
for root, dirs, files in os.walk(self.image_folder_path):
|
||||
for file in files:
|
||||
# 检查文件扩展名是否为图片格式
|
||||
if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff')):
|
||||
self.total_picture_count += 1
|
||||
self.waiting_label.hide()
|
||||
self.image_count_label.setText(str(self.total_picture_count)) # 模拟解析结果
|
||||
self.select_path_button.setEnabled(True)
|
||||
self.result_frame.show()
|
||||
self.level1_title.setStyleSheet(f"""
|
||||
{LABEL_STYLE}
|
||||
font-size: {TITLE_FONT_SIZE}pt;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
""")
|
||||
|
||||
def select_generate_path(self):
|
||||
"""选择生成路径"""
|
||||
path = QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
"选择生成路径",
|
||||
os.path.expanduser("~") or self.image_folder_path,
|
||||
QFileDialog.Option.ShowDirsOnly | QFileDialog.Option.DontResolveSymlinks
|
||||
)
|
||||
if path:
|
||||
self.set_generate_path(path)
|
||||
self.level2_title.setStyleSheet(f"""
|
||||
{LABEL_STYLE}
|
||||
font-size: {TITLE_FONT_SIZE}pt;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
""")
|
||||
|
||||
def set_generate_path(self, path: str):
|
||||
"""设置并显示生成路径"""
|
||||
self.generate_path = path
|
||||
self.generate_path_label.setText(path)
|
||||
self.generate_path_selected.emit(path)
|
||||
self.selected_group.setStyleSheet(GROUP_BOX_STYLE)
|
||||
self.reset_btn.setStyleSheet(BUTTON_STYLE)
|
||||
self.clear_btn.setStyleSheet(BUTTON_STYLE)
|
||||
self.back_btn.setStyleSheet(BUTTON_STYLE)
|
||||
|
||||
def select_folder(self, event=None):
|
||||
folder = QFileDialog.getExistingDirectory(self, "选择文件夹")
|
||||
if folder:
|
||||
self.load_folder(folder)
|
||||
|
||||
def reset_selection(self):
|
||||
self.current_dir = None
|
||||
self.selected_folders.clear()
|
||||
self.level1_list.clear()
|
||||
self.level2_list.clear()
|
||||
self.selected_list.clear()
|
||||
self.stacked_layout.setCurrentIndex(0) # 显示提示
|
||||
self.reset_btn.setVisible(False)
|
||||
self.clear_btn.setVisible(False)
|
||||
self.selected_group.setVisible(False)
|
||||
self.selection_changed.emit([])
|
||||
|
||||
def clear_selected(self):
|
||||
self.selected_folders.clear()
|
||||
self.selected_list.clear()
|
||||
self.update_checkbox_states()
|
||||
self.selection_changed.emit([])
|
||||
|
||||
def load_folder(self, path):
|
||||
self.current_dir = path
|
||||
self.load_level1_folders(path)
|
||||
self.stacked_layout.setCurrentIndex(1) # 显示第一层
|
||||
self.reset_btn.setVisible(True)
|
||||
self.clear_btn.setVisible(True)
|
||||
self.selected_group.setVisible(True)
|
||||
|
||||
def dragEnterEvent(self, event: QDragEnterEvent):
|
||||
if event.mimeData().hasUrls():
|
||||
event.acceptProposedAction()
|
||||
|
||||
def dropEvent(self, event: QDropEvent):
|
||||
for url in event.mimeData().urls():
|
||||
path = url.toLocalFile()
|
||||
if os.path.isdir(path):
|
||||
self.load_folder(path)
|
||||
break
|
||||
|
||||
def load_level1_folders(self, root_path):
|
||||
self.level1_list.clear()
|
||||
self.level2_list.clear()
|
||||
|
||||
for item in os.listdir(root_path):
|
||||
item_path = os.path.join(root_path, item)
|
||||
if os.path.isdir(item_path):
|
||||
item_widget = QListWidgetItem(QIcon.fromTheme("folder"), item)
|
||||
item_widget.setData(Qt.ItemDataRole.UserRole, item_path)
|
||||
item_widget.setSizeHint(QSize(80, 80))
|
||||
item_widget.setTextAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignBottom)
|
||||
self.level1_list.addItem(item_widget)
|
||||
|
||||
def show_level2_folders(self, item):
|
||||
self.level2_list.clear()
|
||||
folder_path = item.data(Qt.ItemDataRole.UserRole)
|
||||
|
||||
for sub_item in os.listdir(folder_path):
|
||||
sub_item_path = os.path.join(folder_path, sub_item)
|
||||
if os.path.isdir(sub_item_path):
|
||||
list_item = QListWidgetItem()
|
||||
list_item.setSizeHint(QSize(100, 80))
|
||||
list_item.setData(Qt.ItemDataRole.UserRole, sub_item_path)
|
||||
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
icon_label = QLabel()
|
||||
icon_label.setPixmap(QIcon.fromTheme("folder").pixmap(48, 48))
|
||||
icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
layout.addWidget(icon_label)
|
||||
|
||||
name_check_layout = QHBoxLayout()
|
||||
checkbox = QCheckBox(sub_item)
|
||||
checkbox.setStyleSheet(f"""
|
||||
{PRIMARY_CHECKBOX_STYLE}
|
||||
QCheckBox::indicator:checked {{
|
||||
background-color: {PRIMARY_COLOR};
|
||||
border: 1px solid {PRIMARY_COLOR};
|
||||
}}
|
||||
""")
|
||||
checkbox.stateChanged.connect(lambda state, path=sub_item_path: self.toggle_folder_selection(path, state))
|
||||
checkbox.setChecked(sub_item_path in self.selected_folders)
|
||||
name_check_layout.addWidget(checkbox)
|
||||
layout.addLayout(name_check_layout)
|
||||
|
||||
widget.setLayout(layout)
|
||||
|
||||
list_item.setSizeHint(widget.sizeHint())
|
||||
self.level2_list.addItem(list_item)
|
||||
self.level2_list.setItemWidget(list_item, widget)
|
||||
|
||||
self.stacked_layout.setCurrentIndex(2) # 显示第二层
|
||||
|
||||
def toggle_folder_selection(self, folder_path, state):
|
||||
if state == Qt.CheckState.Checked.value:
|
||||
self.selected_folders.add(folder_path)
|
||||
item = QListWidgetItem(folder_path)
|
||||
self.selected_list.addItem(item)
|
||||
else:
|
||||
self.selected_folders.discard(folder_path)
|
||||
items = self.selected_list.findItems(folder_path, Qt.MatchFlag.MatchExactly)
|
||||
for item in items:
|
||||
self.selected_list.takeItem(self.selected_list.row(item))
|
||||
|
||||
self.selection_changed.emit(self.get_selected_folders())
|
||||
|
||||
def update_checkbox_states(self):
|
||||
for i in range(self.level2_list.count()):
|
||||
item = self.level2_list.item(i)
|
||||
widget = self.level2_list.itemWidget(item)
|
||||
if widget:
|
||||
checkbox = widget.findChild(QCheckBox)
|
||||
if checkbox:
|
||||
path = item.data(Qt.ItemDataRole.UserRole)
|
||||
checkbox.setChecked(path in self.selected_folders)
|
||||
|
||||
def get_selected_folders(self):
|
||||
return list(self.selected_folders)
|
||||
|
||||
class DraggableLine(QFrame):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setFrameShape(QFrame.HLine)
|
||||
self.setFrameShadow(QFrame.Sunken)
|
||||
self.setLineWidth(2)
|
||||
self.setFixedHeight(10)
|
||||
self.dragging = False
|
||||
self.setCursor(Qt.SizeVerCursor)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.dragging = True
|
||||
self.start_pos = event.globalPos()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.dragging:
|
||||
delta = event.globalPos() - self.start_pos
|
||||
self.start_pos = event.globalPos()
|
||||
# 通知父窗口调整布局
|
||||
self.parent().adjust_row_height(delta.y())
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.dragging = False
|
Binary file not shown.
Binary file not shown.
|
@ -18,8 +18,8 @@ TEXT_COLOR = "#2c3e50"
|
|||
LIGHT_TEXT_COLOR = "#ecf0f1"
|
||||
|
||||
# 按钮样式
|
||||
BUTTON_WIDTH = 100
|
||||
BUTTON_HEIGHT = 34
|
||||
BUTTON_WIDTH = 200
|
||||
BUTTON_HEIGHT = 20
|
||||
BUTTON_RADIUS = 4
|
||||
BUTTON_FONT_WEIGHT = QFont.Weight.Medium
|
||||
|
||||
|
@ -64,7 +64,7 @@ PRIMARY_BUTTON_STYLE = f"""
|
|||
"""
|
||||
|
||||
# 下拉框样式
|
||||
COMBO_BOX_HEIGHT = 34
|
||||
COMBO_BOX_HEIGHT = 10
|
||||
COMBO_BOX_STYLE = f"""
|
||||
QComboBox {{
|
||||
font-family: "{FONT_FAMILY}";
|
||||
|
@ -81,10 +81,10 @@ COMBO_BOX_STYLE = f"""
|
|||
"""
|
||||
|
||||
# 组框样式
|
||||
GROUP_BOX_MIN_WIDTH = 380
|
||||
GROUP_BOX_MIN_HEIGHT = 200
|
||||
GROUP_BOX_SPACING = 15
|
||||
GROUP_BOX_MARGINS = (15, 15, 15, 15)
|
||||
GROUP_BOX_MIN_WIDTH = 300
|
||||
GROUP_BOX_MIN_HEIGHT = 120
|
||||
GROUP_BOX_SPACING = 5
|
||||
GROUP_BOX_MARGINS = (5, 5, 5, 5)
|
||||
GROUP_BOX_STYLE = f"""
|
||||
QGroupBox {{
|
||||
font-family: "{FONT_FAMILY}";
|
||||
|
@ -127,8 +127,8 @@ PATH_DISPLAY_STYLE = f"""
|
|||
# 主窗口样式
|
||||
WINDOW_MIN_WIDTH = 1000
|
||||
WINDOW_MIN_HEIGHT = 720
|
||||
MAIN_LAYOUT_SPACING = 20
|
||||
MAIN_LAYOUT_MARGINS = (25, 25, 25, 25)
|
||||
MAIN_LAYOUT_SPACING = 10
|
||||
MAIN_LAYOUT_MARGINS = (5, 5, 5, 5)
|
||||
|
||||
# 信息标签样式 (左侧固定标签)
|
||||
INFO_LABEL_STYLE = f"""
|
||||
|
@ -167,7 +167,7 @@ WAITING_LABEL_STYLE = f"""
|
|||
"""
|
||||
|
||||
CHECKBOX_SIZE = 16 # 复选框大小
|
||||
CHECKBOX_MARGIN = 4 # 边距
|
||||
CHECKBOX_MARGIN = 1 # 边距
|
||||
|
||||
# 基础CheckBox样式
|
||||
CHECKBOX_STYLE = f"""
|
||||
|
@ -193,6 +193,15 @@ PRIMARY_CHECKBOX_STYLE = f"""
|
|||
}}
|
||||
QCheckBox::indicator:checked {{
|
||||
background-color: {PRIMARY_COLOR};
|
||||
image: url(:/icons/check_white.svg);
|
||||
}}
|
||||
"""
|
||||
|
||||
SPLITTER_STYLE = """
|
||||
QSplitter::handle {
|
||||
background: #a0a0a0; /* 分割线颜色 */
|
||||
height: 4px; /* 水平分割线高度(垂直分割线用 width) */
|
||||
}
|
||||
QSplitter::handle:hover {
|
||||
background: #808080; /* 鼠标悬停时颜色 */
|
||||
}
|
||||
"""
|
87
main.py
87
main.py
|
@ -1,10 +1,11 @@
|
|||
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout,
|
||||
QPushButton, QSizePolicy)
|
||||
QPushButton, QSizePolicy, QSplitter, QToolBar)
|
||||
from PySide6.QtGui import QFontDatabase
|
||||
from PySide6.QtCore import Signal
|
||||
from PySide6.QtCore import Signal, Qt
|
||||
|
||||
import os
|
||||
from info_core.defines import *
|
||||
from info_core.MyQtClass import ConfigComboBoxGroup, FolderImportWidget, ImageAnalysisWidget
|
||||
from info_core.MyQtClass import ConfigComboBoxGroup, FolderDropWidget, DraggableLine
|
||||
|
||||
|
||||
class ReportGeneratorUI(QMainWindow):
|
||||
|
@ -46,46 +47,66 @@ class ReportGeneratorUI(QMainWindow):
|
|||
# 第一行:项目信息和人员配置
|
||||
self.project_group = ConfigComboBoxGroup("项目基本信息")
|
||||
self.staff_group = ConfigComboBoxGroup("单次检查配置信息", is_project=False)
|
||||
self.main_layout.addWidget(self.project_group, 0, 0)
|
||||
self.main_layout.addWidget(self.staff_group, 0, 1)
|
||||
|
||||
# 第二行:导入图片路径、填写机组信息
|
||||
self.picture_group = FolderImportWidget("导入图片路径")
|
||||
self.main_layout.addWidget(self.picture_group, 1, 0)
|
||||
self.image_analysis = ImageAnalysisWidget("填写机组信息")
|
||||
self.main_layout.addWidget(self.image_analysis, 1, 1)
|
||||
# 连接信号
|
||||
self.picture_group.main_folder_selected.connect(self.image_analysis.set_image_folder)
|
||||
self.image_analysis.generate_path_selected.connect(self.on_generate_path_selected)
|
||||
|
||||
# 获取请求信号,调用获取函数,发送更新信号
|
||||
self.picture_group.get_baogao_choose_info.connect(self.get_baogao_choose_info)
|
||||
self.send_baogao_choose_info.connect(self.picture_group.update_baogao_choose_info)
|
||||
|
||||
self.picture_group = FolderDropWidget()
|
||||
# self.image_analysis =
|
||||
# self.main_layout.addWidget(self.image_analysis, 1, 1)
|
||||
# 第三行:生成报告按钮(跨两列)
|
||||
self.create_generate_button()
|
||||
self.generate_btn.setEnabled(False)
|
||||
|
||||
# 创建一个垂直分割器
|
||||
self.splitter = QSplitter(Qt.Vertical)
|
||||
self.splitter.setStyleSheet(SPLITTER_STYLE)
|
||||
# 创建顶部和底部容器
|
||||
top_container = QWidget()
|
||||
top_container.setLayout(QGridLayout())
|
||||
top_container.layout().addWidget(self.project_group, 0, 0)
|
||||
top_container.layout().addWidget(self.staff_group, 0, 1)
|
||||
|
||||
middle_container = QWidget()
|
||||
middle_container.setLayout(QGridLayout())
|
||||
middle_container.layout().addWidget(self.picture_group, 0, 0)
|
||||
|
||||
# 添加部件到分割器
|
||||
self.splitter.addWidget(top_container)
|
||||
self.splitter.addWidget(middle_container)
|
||||
|
||||
# 设置主布局
|
||||
self.main_layout.addWidget(self.splitter, 0, 0, 2, 2) # 占据前两行两列
|
||||
self.main_layout.addWidget(self.generate_btn, 2, 0, 1, 2)
|
||||
|
||||
# 设置列和行的拉伸比例
|
||||
self.main_layout.setColumnStretch(0, 1) # 第一列拉伸比例
|
||||
self.main_layout.setColumnStretch(1, 1) # 第二列拉伸比例
|
||||
self.main_layout.setRowStretch(0, 1) # 第一行拉伸比例为1
|
||||
self.main_layout.setRowStretch(1, 4) # 第二行拉伸比例为4
|
||||
self.main_layout.setRowStretch(2, 0) # 第三行不拉伸(固定高度)
|
||||
# 设置分割器初始比例
|
||||
self.splitter.setStretchFactor(0, 1)
|
||||
self.splitter.setStretchFactor(1, 4)
|
||||
|
||||
self.toolbar = QToolBar()
|
||||
self.addToolBar(self.toolbar)
|
||||
self.toolbar.setMovable(False)
|
||||
self.toolbar.setFloatable(False)
|
||||
new_action = self.toolbar.addAction("重置布局比例")
|
||||
self.toolbar.addSeparator()
|
||||
new_action.triggered.connect(self.reset_splitter)
|
||||
|
||||
def reset_splitter(self):
|
||||
"""重置分割器的比例"""
|
||||
total_size = sum(self.splitter.sizes()) # 获取当前总大小
|
||||
self.splitter.setSizes([
|
||||
int(total_size * 0.2), # 第一部分占 20%(比例 1:4)
|
||||
int(total_size * 0.8) # 第二部分占 80%
|
||||
])
|
||||
|
||||
def on_generate_path_selected(self, path):
|
||||
self.generate_btn.setEnabled(True)
|
||||
|
||||
def get_baogao_choose_info(self):
|
||||
search_file_list = []
|
||||
if self.image_analysis.check_is_waibu:
|
||||
search_file_list.append("外汇总")
|
||||
if self.image_analysis.check_is_neibu:
|
||||
search_file_list.append("内汇总")
|
||||
if self.image_analysis.check_is_fanglei:
|
||||
search_file_list.append("防汇总")
|
||||
self.send_baogao_choose_info.emit(search_file_list)
|
||||
# search_file_list = []
|
||||
# if self.image_analysis.check_is_waibu:
|
||||
# search_file_list.append("外汇总")
|
||||
# if self.image_analysis.check_is_neibu:
|
||||
# search_file_list.append("内汇总")
|
||||
# if self.image_analysis.check_is_fanglei:
|
||||
# search_file_list.append("防汇总")
|
||||
# self.send_baogao_choose_info.emit(search_file_list)
|
||||
|
||||
def create_button(self, text):
|
||||
"""创建统一风格的按钮"""
|
||||
|
|
Loading…
Reference in New Issue