UI更新
10
.gitignore
vendored
@ -123,3 +123,13 @@ Thumbs.db
|
||||
*.temp
|
||||
*.bak
|
||||
*.backup
|
||||
BUTTON_CRASH_FIX.md
|
||||
.gitignore
|
||||
CORNER_RADIUS_FIX.md
|
||||
CORNER_RADIUS_UPDATE.md
|
||||
FIGMA_LAYOUT_IMPROVEMENTS.md
|
||||
LOGO_AREA_IMPROVEMENTS.md
|
||||
.codex/settings/kiroCodex-settings.json
|
||||
MetaCore/LOGO_AREA_REDESIGN.md
|
||||
MetaCore/LAYOUT_OPTIMIZATION_SUMMARY.md
|
||||
MetaCore/CROSS_PLATFORM_VENV.md
|
||||
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 22 KiB |
46
MetaCore/MetaCore/data/projects.json
Normal file
@ -0,0 +1,46 @@
|
||||
[
|
||||
{
|
||||
"id": 4,
|
||||
"title": "XNWX",
|
||||
"date": "2025-10-11 12:02:48",
|
||||
"type": "imported",
|
||||
"image": "C:\\Users\\29381\\Desktop\\XNWX\\XNWX.png",
|
||||
"path": "C:\\Users\\29381\\Desktop",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\XNWX",
|
||||
"description": "从文件夹 XNWX 导入",
|
||||
"status": "normal"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "示例项目1",
|
||||
"date": "2024-06-08 15:56:35",
|
||||
"type": "empty",
|
||||
"image": "📁",
|
||||
"path": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"description": "这是一个示例空白项目",
|
||||
"status": "normal"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "示例项目2",
|
||||
"date": "2023-01-10 12:09:04",
|
||||
"type": "empty",
|
||||
"image": "📁",
|
||||
"path": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"description": "这是另一个示例空白项目",
|
||||
"status": "normal"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "我的第一个项目",
|
||||
"date": "2024-06-07 06:57:46",
|
||||
"type": "empty",
|
||||
"image": "📁",
|
||||
"path": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\MetaCore",
|
||||
"description": "从这里开始您的第一个项目",
|
||||
"status": "normal"
|
||||
}
|
||||
]
|
||||
BIN
MetaCore/Resources/Icons/close_bt_icon.png
Normal file
|
After Width: | Height: | Size: 370 B |
BIN
MetaCore/Resources/Icons/delete_fail_icon.png
Normal file
|
After Width: | Height: | Size: 404 B |
BIN
MetaCore/Resources/Icons/empty_folder_icon.png
Normal file
|
After Width: | Height: | Size: 486 B |
BIN
MetaCore/Resources/Icons/file_icon.png
Normal file
|
After Width: | Height: | Size: 290 B |
BIN
MetaCore/Resources/Icons/import_file_icon.png
Normal file
|
After Width: | Height: | Size: 648 B |
BIN
MetaCore/Resources/Icons/infomation_check_icon.png
Normal file
|
After Width: | Height: | Size: 319 B |
BIN
MetaCore/Resources/Icons/infomation_hover_icon.png
Normal file
|
After Width: | Height: | Size: 345 B |
BIN
MetaCore/Resources/Icons/infomation_icon.png
Normal file
|
After Width: | Height: | Size: 332 B |
BIN
MetaCore/Resources/Icons/open_projectcard_icon.png
Normal file
|
After Width: | Height: | Size: 261 B |
BIN
MetaCore/Resources/Icons/project_empty_icon.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
MetaCore/Resources/Icons/refresh_projectcard_icon.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
MetaCore/Resources/Icons/remove_projectcard_icon.png
Normal file
|
After Width: | Height: | Size: 336 B |
BIN
MetaCore/Resources/Icons/search_icon.png
Normal file
|
After Width: | Height: | Size: 817 B |
BIN
MetaCore/Resources/Icons/solid_down_arrows.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
MetaCore/Resources/Icons/solid_right_arrows.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
MetaCore/Resources/Icons/success_icon copy.png
Normal file
|
After Width: | Height: | Size: 546 B |
BIN
MetaCore/Resources/Icons/success_icon.png
Normal file
|
After Width: | Height: | Size: 546 B |
BIN
MetaCore/Resources/Icons/warning_icon.png
Normal file
|
After Width: | Height: | Size: 482 B |
BIN
MetaCore/Resources/ProjectPreviews/default_preview_2.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
MetaCore/Resources/ProjectPreviews/default_preview_3.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
MetaCore/Resources/ProjectPreviews/preview_1_1760628516144.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
MetaCore/Resources/ProjectPreviews/preview_6_1760436321788.png
Normal file
|
After Width: | Height: | Size: 143 KiB |
@ -31,6 +31,8 @@ from pathlib import Path # 现代路径处理
|
||||
from typing import List, Dict, Optional # 类型提示
|
||||
import glob
|
||||
import subprocess
|
||||
from PyQt5.QtWidgets import QDialog
|
||||
from ui.widget import UniversalMessageDialog
|
||||
|
||||
# 第三方库导入
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QFileSystemWatcher, QTimer # Qt核心对象和信号系统
|
||||
@ -751,17 +753,21 @@ if __name__ == "__main__":
|
||||
project_names = [p.title for p in deleted_projects]
|
||||
project_list = "\n".join([f"• {name}" for name in project_names])
|
||||
|
||||
reply = QMessageBox.question(
|
||||
None,
|
||||
"多个项目目录已删除",
|
||||
f"检测到以下 {len(deleted_projects)} 个项目的目录已被删除:\n\n"
|
||||
f"{project_list}\n\n"
|
||||
f"是否要从项目列表中移除这些项目?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes
|
||||
)
|
||||
# reply = QMessageBox.question(
|
||||
# None,
|
||||
# "多个项目目录已删除",
|
||||
# f"检测到以下 {len(deleted_projects)} 个项目的目录已被删除:\n\n"
|
||||
# f"{project_list}\n\n"
|
||||
# f"是否要从项目列表中移除这些项目?",
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.Yes
|
||||
# )
|
||||
reply = UniversalMessageDialog.show_info("多个项目目录已删除", f"检测到以下 {len(deleted_projects)} 个项目的目录已被删除:\n\n"
|
||||
f"{project_list}\n\n"
|
||||
f"是否要从项目列表中移除这些项目?",
|
||||
True, "确定", "取消")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
for project in deleted_projects:
|
||||
self.remove_project_from_watcher(project)
|
||||
self.remove_project(project.id)
|
||||
@ -851,16 +857,19 @@ if __name__ == "__main__":
|
||||
if project.status != 'normal':
|
||||
return
|
||||
|
||||
reply = QMessageBox.question(
|
||||
None,
|
||||
"项目目录已删除",
|
||||
f"检测到项目 \"{project.title}\" 的目录已被删除:\n{project.project_dir}\n\n"
|
||||
f"是否要从项目列表中移除此项目?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes
|
||||
)
|
||||
# reply = QMessageBox.question(
|
||||
# None,
|
||||
# "项目目录已删除",
|
||||
# f"检测到项目 \"{project.title}\" 的目录已被删除:\n{project.project_dir}\n\n"
|
||||
# f"是否要从项目列表中移除此项目?",
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.Yes
|
||||
# )
|
||||
reply = UniversalMessageDialog.show_info("项目目录已删除", f"检测到项目 \"{project.title}\" 的目录已被删除:\n{project.project_dir}\n\n"
|
||||
f"是否要从项目列表中移除此项目?",
|
||||
True, "确定", "取消")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
self.remove_project_from_watcher(project)
|
||||
self.remove_project(project.id)
|
||||
print(f"已自动移除被删除的项目: {project.title}")
|
||||
|
||||
@ -10,6 +10,8 @@ from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager
|
||||
from ui.icon_manager import IconManager
|
||||
from ui.widget import UniversalMessageDialog
|
||||
|
||||
class CreateProjectDialog(QDialog):
|
||||
"""创建项目对话框"""
|
||||
@ -21,14 +23,28 @@ class CreateProjectDialog(QDialog):
|
||||
self.selected_template = "empty"
|
||||
self.selected_path = ""
|
||||
|
||||
# 自定义标题栏相关控件
|
||||
self.title_bar = None
|
||||
self.title_label = None
|
||||
self.close_btn = None
|
||||
self.drag_offset = None
|
||||
|
||||
# 设置对话框对象名称以应用样式
|
||||
self.setObjectName("CreateProjectDialog")
|
||||
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
|
||||
self.setAttribute(Qt.WA_StyledBackground, True)
|
||||
|
||||
self.init_ui()
|
||||
self.connect_signals()
|
||||
|
||||
# 设置对话框属性
|
||||
self.setWindowTitle("创建新的项目")
|
||||
if self.title_label is not None:
|
||||
self.title_label.setText(self.windowTitle())
|
||||
self.setModal(True)
|
||||
self.setMinimumSize(1000, 725)
|
||||
self.resize(1000, 725) # 设置默认尺寸
|
||||
self.setMinimumSize(1177, 689) # 根据Figma设计调整尺寸
|
||||
self.setMaximumSize(1177, 689)
|
||||
self.resize(1177, 689) # 设置默认尺寸
|
||||
|
||||
# 设置默认项目位置
|
||||
self.set_default_location_from_settings()
|
||||
@ -41,29 +57,59 @@ class CreateProjectDialog(QDialog):
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
# 标题栏 - 使用默认系统标题栏
|
||||
# self.create_title_bar(layout)
|
||||
|
||||
|
||||
# 自定义标题栏
|
||||
self.title_bar = self.create_title_bar()
|
||||
layout.addWidget(self.title_bar)
|
||||
|
||||
# 主要内容区域
|
||||
self.create_main_content(layout)
|
||||
|
||||
# 底部按钮
|
||||
self.create_button_area(layout)
|
||||
|
||||
|
||||
|
||||
def create_title_bar(self):
|
||||
"""创建与导入项目对话框一致的自定义标题栏"""
|
||||
title_bar = QWidget()
|
||||
title_bar.setObjectName("customTitleBar")
|
||||
|
||||
layout = QHBoxLayout(title_bar)
|
||||
layout.setContentsMargins(18, 12, 14, 12)
|
||||
layout.setSpacing(12)
|
||||
|
||||
self.title_label = QLabel(self.windowTitle())
|
||||
self.title_label.setObjectName("customTitleLabel")
|
||||
self.title_label.setAttribute(Qt.WA_TransparentForMouseEvents, True)
|
||||
layout.addWidget(self.title_label)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
if IconManager.icon_exists("close_bt_icon"):
|
||||
close_icon = IconManager.get_icon("close_bt_icon", QSize(18, 18))
|
||||
self.close_btn = QPushButton()
|
||||
self.close_btn.setIcon(close_icon)
|
||||
else:
|
||||
self.close_btn = QPushButton("X")
|
||||
self.close_btn.setObjectName("customCloseBtn")
|
||||
self.close_btn.setFixedSize(18, 18)
|
||||
self.close_btn.setCursor(Qt.PointingHandCursor)
|
||||
self.close_btn.clicked.connect(self.reject)
|
||||
layout.addWidget(self.close_btn)
|
||||
|
||||
title_bar.installEventFilter(self)
|
||||
title_bar.setCursor(Qt.ArrowCursor)
|
||||
return title_bar
|
||||
|
||||
|
||||
def create_main_content(self, layout):
|
||||
"""创建主要内容"""
|
||||
content_widget = QWidget()
|
||||
content_widget.setObjectName("createProjectContent")
|
||||
content_layout = QHBoxLayout(content_widget)
|
||||
content_layout.setContentsMargins(0, 0, 0, 0)
|
||||
content_layout.setSpacing(0)
|
||||
content_layout.setContentsMargins(10, 0, 10, 15) # 根据Figma设计调整边距
|
||||
content_layout.setSpacing(4) # 添加小间距
|
||||
|
||||
# 左侧模板选择区域 (2/3)
|
||||
# 左侧模板选择区域
|
||||
self.create_template_section(content_layout)
|
||||
|
||||
# 右侧项目信息区域 (1/3)
|
||||
# 右侧项目信息区域
|
||||
self.create_project_info_section(content_layout)
|
||||
|
||||
layout.addWidget(content_widget)
|
||||
@ -73,24 +119,28 @@ class CreateProjectDialog(QDialog):
|
||||
template_widget = QWidget()
|
||||
template_widget.setObjectName("templateSection")
|
||||
template_layout = QVBoxLayout(template_widget)
|
||||
template_layout.setContentsMargins(30, 30, 20, 30)
|
||||
|
||||
# 标题
|
||||
title_label = QLabel("选择项目模板")
|
||||
title_label.setObjectName("sectionTitle")
|
||||
template_layout.setContentsMargins(0, 0, 0, 0)
|
||||
template_layout.setSpacing(4)
|
||||
|
||||
# 标题栏
|
||||
title_label = QLabel("选择项目模版") # 与Figma设计保持一致
|
||||
title_label.setObjectName("templateHeaderLabel")
|
||||
title_label.setFixedSize(724, 33)
|
||||
template_layout.addWidget(title_label)
|
||||
template_layout.addSpacing(4)
|
||||
|
||||
# 模板网格
|
||||
self.create_template_grid(template_layout)
|
||||
|
||||
# 设置固定比例 (2/3)
|
||||
template_widget.setMinimumWidth(600)
|
||||
layout.addWidget(template_widget, 2)
|
||||
# 设置固定宽度 (根据Figma设计)
|
||||
template_widget.setFixedWidth(724)
|
||||
layout.addWidget(template_widget)
|
||||
|
||||
def create_template_grid(self, layout):
|
||||
"""创建模板网格"""
|
||||
# 滚动区域
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setFixedSize(724, 595)
|
||||
scroll_area.setObjectName("templateScrollArea")
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
@ -100,20 +150,20 @@ class CreateProjectDialog(QDialog):
|
||||
templates_widget = QWidget()
|
||||
templates_widget.setObjectName("templatesContainer")
|
||||
templates_layout = QGridLayout(templates_widget)
|
||||
templates_layout.setSpacing(20) # 增加间距,适配固定尺寸按钮
|
||||
templates_layout.setContentsMargins(10, 10, 10, 10) # 添加容器边距
|
||||
templates_layout.setSpacing(15) # 根据Figma设计调整间距
|
||||
templates_layout.setContentsMargins(15, 15, 15, 15) # 调整容器边距
|
||||
templates_layout.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 左上对齐
|
||||
|
||||
# 模板数据 - 当前只有空白项目模板,后续可以添加更多模板
|
||||
templates = [
|
||||
("empty", "📄", "空白项目模板"),
|
||||
("empty", "empty_folder_icon", "空白项目模版"), # 移除emoji图标,与Figma设计一致
|
||||
# 后续可以添加的模板示例:
|
||||
# ("web", "🌐", "Web应用模板"),
|
||||
# ("mobile", "📱", "移动应用模板"),
|
||||
# ("desktop", "🖥️", "桌面应用模板"),
|
||||
# ("api", "🔌", "API服务模板"),
|
||||
# ("data", "📊", "数据分析模板"),
|
||||
# ("game", "🎮", "游戏开发模板"),
|
||||
# ("web", "", "Web应用模板"),
|
||||
# ("mobile", "", "移动应用模板"),
|
||||
# ("desktop", "", "桌面应用模板"),
|
||||
# ("api", "", "API服务模板"),
|
||||
# ("data", "", "数据分析模板"),
|
||||
# ("game", "", "游戏开发模板"),
|
||||
]
|
||||
|
||||
# 创建模板项
|
||||
@ -133,13 +183,13 @@ class CreateProjectDialog(QDialog):
|
||||
scroll_area.setWidget(templates_widget)
|
||||
layout.addWidget(scroll_area)
|
||||
|
||||
def create_template_item(self, template_id, icon, name):
|
||||
def create_template_item(self, template_id, icon_path, name):
|
||||
"""创建模板项"""
|
||||
template_btn = QPushButton()
|
||||
template_btn.setObjectName("templateItem")
|
||||
template_btn.setCheckable(True)
|
||||
# 设置固定尺寸,确保所有模板按钮大小一致,便于后续添加多个模板
|
||||
template_btn.setFixedSize(180, 140)
|
||||
# 根据Figma设计调整尺寸 (149x127)
|
||||
template_btn.setFixedSize(149, 127)
|
||||
|
||||
# 设置默认选中
|
||||
if template_id == "empty":
|
||||
@ -148,14 +198,20 @@ class CreateProjectDialog(QDialog):
|
||||
# 布局
|
||||
btn_layout = QVBoxLayout(template_btn)
|
||||
btn_layout.setAlignment(Qt.AlignCenter)
|
||||
btn_layout.setSpacing(12)
|
||||
btn_layout.setContentsMargins(20, 24, 20, 24)
|
||||
btn_layout.setSpacing(27) # 减小间距
|
||||
btn_layout.setContentsMargins(15, 20, 15, 20)
|
||||
|
||||
# 图标
|
||||
icon_label = QLabel(icon)
|
||||
icon_label.setObjectName("templateIcon")
|
||||
icon_label.setAlignment(Qt.AlignCenter)
|
||||
btn_layout.addWidget(icon_label)
|
||||
# 图标区域 - 根据Figma设计,这里是一个空的框架
|
||||
if icon_path and IconManager.icon_exists(icon_path):
|
||||
icon = IconManager.get_icon(icon_path, QSize(40, 40))
|
||||
icon_label = QLabel() # 创建QLabel而不是QIcon
|
||||
icon_label.setObjectName("templateIcon")
|
||||
icon_label.setAlignment(Qt.AlignCenter)
|
||||
icon_label.setPixmap(icon.pixmap(QSize(40, 40))) # 设置图标
|
||||
btn_layout.addWidget(icon_label)
|
||||
else:
|
||||
# 添加空白空间以保持布局一致
|
||||
btn_layout.addStretch()
|
||||
|
||||
# 名称
|
||||
name_label = QLabel(name)
|
||||
@ -183,43 +239,54 @@ class CreateProjectDialog(QDialog):
|
||||
info_widget = QWidget()
|
||||
info_widget.setObjectName("projectInfoSection")
|
||||
info_layout = QVBoxLayout(info_widget)
|
||||
info_layout.setContentsMargins(20, 30, 30, 30)
|
||||
info_layout.setContentsMargins(15, 10, 15, 10) # 调整边距
|
||||
info_layout.setSpacing(15)
|
||||
|
||||
# 标题和描述容器
|
||||
header_widget = QWidget()
|
||||
header_widget.setObjectName("projectInfoHeader")
|
||||
header_layout = QVBoxLayout(header_widget)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.setSpacing(10)
|
||||
|
||||
# 标题
|
||||
title_label = QLabel("项目信息")
|
||||
title_label.setObjectName("sectionTitle")
|
||||
info_layout.addWidget(title_label)
|
||||
header_layout.addWidget(title_label)
|
||||
|
||||
# 模板描述
|
||||
self.description_label = QLabel("创建一个空白项目,您可以从头开始构建您的应用程序。包含基础的项目结构和配置文件,适用于任何类型的项目开发。")
|
||||
self.description_label.setObjectName("templateDescription")
|
||||
self.description_label.setWordWrap(True)
|
||||
info_layout.addWidget(self.description_label)
|
||||
header_layout.addWidget(self.description_label)
|
||||
|
||||
info_layout.addWidget(header_widget)
|
||||
|
||||
# 表单
|
||||
self.create_project_form(info_layout)
|
||||
|
||||
info_layout.addStretch()
|
||||
|
||||
# 设置固定比例 (1/3),增加最大宽度以容纳更长的错误信息
|
||||
info_widget.setMaximumWidth(350) # 从300增加到350
|
||||
layout.addWidget(info_widget, 1)
|
||||
# 设置固定宽度 (根据Figma设计)
|
||||
info_widget.setFixedWidth(427)
|
||||
layout.addWidget(info_widget)
|
||||
|
||||
def create_project_form(self, layout):
|
||||
"""创建项目表单"""
|
||||
form_layout = QVBoxLayout()
|
||||
form_layout.setSpacing(18)
|
||||
form_layout.setSpacing(15)
|
||||
|
||||
# 项目名称
|
||||
name_group = QVBoxLayout()
|
||||
name_group.setSpacing(4) # 减小间距,让错误提示更紧贴
|
||||
|
||||
name_label = QLabel("项目名称")
|
||||
name_label.setObjectName("formLabel")
|
||||
name_group.addWidget(name_label)
|
||||
name_group.setSpacing(10)
|
||||
|
||||
self.name_input = QLineEdit()
|
||||
self.name_input.setObjectName("formInput")
|
||||
self.name_input.setMinimumSize(397, 32)
|
||||
self.name_input.setPlaceholderText("输入项目名称")
|
||||
name_group.addWidget(self.name_input)
|
||||
|
||||
@ -241,11 +308,12 @@ class CreateProjectDialog(QDialog):
|
||||
desc_label = QLabel("项目描述")
|
||||
desc_label.setObjectName("formLabel")
|
||||
desc_group.addWidget(desc_label)
|
||||
desc_group.setSpacing(10)
|
||||
|
||||
self.desc_input = QTextEdit()
|
||||
self.desc_input.setObjectName("formTextArea")
|
||||
self.desc_input.setPlaceholderText("输入项目描述(可选)")
|
||||
self.desc_input.setMaximumHeight(70)
|
||||
self.desc_input.setMinimumSize(397, 96)
|
||||
desc_group.addWidget(self.desc_input)
|
||||
|
||||
form_layout.addLayout(desc_group)
|
||||
@ -255,32 +323,38 @@ class CreateProjectDialog(QDialog):
|
||||
location_label = QLabel("项目位置")
|
||||
location_label.setObjectName("formLabel")
|
||||
location_group.addWidget(location_label)
|
||||
|
||||
location_group.setSpacing(10)
|
||||
|
||||
location_layout = QHBoxLayout()
|
||||
self.location_input = QLineEdit()
|
||||
self.location_input.setObjectName("formInput")
|
||||
self.location_input.setFixedSize(280, 32)
|
||||
self.location_input.setPlaceholderText("点击浏览选择位置")
|
||||
self.location_input.setReadOnly(True)
|
||||
location_layout.addWidget(self.location_input)
|
||||
|
||||
browse_btn = QPushButton("📁")
|
||||
browse_btn = QPushButton("")
|
||||
if IconManager.icon_exists('file_icon'):
|
||||
browse_btn.setIcon(IconManager.get_icon('file_icon', QSize(20, 20)))
|
||||
browse_btn.setObjectName("browseBtn")
|
||||
browse_btn.setFixedSize(32, 32) # 减小尺寸:40x32 -> 32x32
|
||||
browse_btn.setFixedSize(103, 32) # 减小尺寸:40x32 -> 32x32
|
||||
browse_btn.setToolTip("选择项目保存位置")
|
||||
browse_btn.clicked.connect(self.browse_location)
|
||||
location_layout.addWidget(browse_btn)
|
||||
|
||||
location_group.addLayout(location_layout)
|
||||
form_layout.addLayout(location_group)
|
||||
|
||||
|
||||
form_layout.addWidget(self.create_button_area())
|
||||
|
||||
layout.addLayout(form_layout)
|
||||
|
||||
def create_button_area(self, layout):
|
||||
|
||||
def create_button_area(self):
|
||||
"""创建按钮区域"""
|
||||
button_widget = QWidget()
|
||||
button_widget.setObjectName("buttonArea")
|
||||
button_layout = QHBoxLayout(button_widget)
|
||||
button_layout.setContentsMargins(30, 20, 30, 30)
|
||||
button_layout.setContentsMargins(0, 185, 0, 10) # 根据Figma设计调整边距
|
||||
button_layout.setSpacing(10) # 设置按钮间距
|
||||
|
||||
button_layout.addStretch()
|
||||
@ -288,16 +362,18 @@ class CreateProjectDialog(QDialog):
|
||||
# 取消按钮
|
||||
cancel_btn = QPushButton("取消")
|
||||
cancel_btn.setObjectName("secondaryBtn")
|
||||
cancel_btn.setFixedSize(95, 36)
|
||||
cancel_btn.clicked.connect(self.reject)
|
||||
button_layout.addWidget(cancel_btn)
|
||||
|
||||
# 创建按钮
|
||||
self.create_btn = QPushButton("创建项目")
|
||||
self.create_btn = QPushButton("创建") # 与Figma设计保持一致
|
||||
self.create_btn.setObjectName("primaryBtn")
|
||||
self.create_btn.setFixedSize(95, 36)
|
||||
self.create_btn.clicked.connect(self.create_project)
|
||||
button_layout.addWidget(self.create_btn)
|
||||
|
||||
layout.addWidget(button_widget)
|
||||
return button_widget
|
||||
|
||||
def update_template_description(self, template_id):
|
||||
"""更新模板描述"""
|
||||
@ -328,17 +404,18 @@ class CreateProjectDialog(QDialog):
|
||||
# 验证输入
|
||||
name = self.name_input.text().strip()
|
||||
if not name:
|
||||
QMessageBox.warning(self, "输入错误", "请输入项目名称")
|
||||
# QMessageBox.warning(self, "输入错误", "请输入项目名称")
|
||||
UniversalMessageDialog.show_warning(self, "输入错误", "请输入项目名称", False, "确定")
|
||||
return
|
||||
|
||||
if not self.selected_path:
|
||||
QMessageBox.warning(self, "输入错误", "请选择项目保存位置")
|
||||
UniversalMessageDialog.show_warning(self, "输入错误", "请选择项目保存位置", False, "确定")
|
||||
return
|
||||
|
||||
# 使用项目管理器的验证方法进行全面检查
|
||||
is_valid, error_message = self.project_manager.validate_project_creation(name, self.selected_path)
|
||||
if not is_valid:
|
||||
QMessageBox.warning(self, "创建失败", error_message)
|
||||
UniversalMessageDialog.show_warning(self, "创建失败", error_message, False, "确定")
|
||||
return
|
||||
|
||||
# 创建项目
|
||||
@ -355,18 +432,18 @@ class CreateProjectDialog(QDialog):
|
||||
项目目录: {project.project_dir}
|
||||
|
||||
项目文件结构已创建完成,包含:
|
||||
• models/ - 模型文件夹
|
||||
• textures/ - 贴图文件夹
|
||||
• scenes/ - 场景文件夹
|
||||
• project.json - 项目配置文件
|
||||
? models/ - 模型文件夹
|
||||
? textures/ - 贴图文件夹
|
||||
? scenes/ - 场景文件夹
|
||||
? project.json - 项目配置文件
|
||||
|
||||
您可以开始在此基础上开发您的应用程序。"""
|
||||
|
||||
QMessageBox.information(self, "创建成功", success_msg)
|
||||
UniversalMessageDialog.show_info(self, "创建成功", success_msg, False, "确定")
|
||||
self.accept()
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "创建失败", f"项目创建失败:{str(e)}")
|
||||
UniversalMessageDialog.show_error(self, "创建失败", f"项目创建失败:{str(e)}", False, "确定")
|
||||
|
||||
def get_template_name(self, template_id):
|
||||
"""获取模板名称"""
|
||||
@ -445,6 +522,21 @@ class CreateProjectDialog(QDialog):
|
||||
|
||||
|
||||
|
||||
def eventFilter(self, watched, event):
|
||||
"""处理标题栏拖动与按钮交互"""
|
||||
if watched is self.title_bar:
|
||||
if event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton:
|
||||
self.drag_offset = event.globalPos() - self.frameGeometry().topLeft()
|
||||
return True
|
||||
if event.type() == QEvent.MouseMove and event.buttons() & Qt.LeftButton and self.drag_offset is not None:
|
||||
self.move(event.globalPos() - self.drag_offset)
|
||||
return True
|
||||
if event.type() == QEvent.MouseButtonRelease and event.button() == Qt.LeftButton:
|
||||
self.drag_offset = None
|
||||
return True
|
||||
return super().eventFilter(watched, event)
|
||||
|
||||
|
||||
def center_dialog(self):
|
||||
"""对话框居中"""
|
||||
if self.parent():
|
||||
@ -458,3 +550,18 @@ class CreateProjectDialog(QDialog):
|
||||
x = (screen.width() - self.width()) // 2
|
||||
y = (screen.height() - self.height()) // 2
|
||||
self.move(x, y)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1
MetaCore/ui/enhanced_styles.py
Normal file
@ -0,0 +1 @@
|
||||
|
||||
@ -47,8 +47,29 @@ class IconManager:
|
||||
|
||||
'search': 'search_icon.png',
|
||||
'infomation': 'infomation_icon.png',
|
||||
|
||||
'infomation_hover': 'infomation_hover_icon.png',
|
||||
'infomation_check': 'infomation_check_icon.png',
|
||||
|
||||
# 为获取项目图片
|
||||
'project_empty_icon': 'project_empty_icon.png',
|
||||
|
||||
# 卡片右键菜单
|
||||
'refresh_projectcard': 'refresh_projectcard_icon.png',
|
||||
'open_projectcard': 'open_projectcard_icon.png',
|
||||
'remove_projectcard': 'remove_projectcard_icon.png',
|
||||
|
||||
# 导入对话框
|
||||
'import_file': 'import_file_icon.png',
|
||||
|
||||
# 创建项目浏览图标
|
||||
'file_icon': 'file_icon.png',
|
||||
'empty_folder_icon': 'empty_folder_icon.png',
|
||||
'close_bt_icon': 'close_bt_icon.png',
|
||||
|
||||
# 弹窗图标
|
||||
'success_icon': 'success_icon.png',
|
||||
'warning_icon': 'warning_icon.png',
|
||||
'fail_icon': 'delete_fail_icon.png',
|
||||
}
|
||||
|
||||
# 图标缓存
|
||||
@ -202,4 +223,4 @@ class IconManager:
|
||||
for icon_name in cls.ICON_FILES:
|
||||
if not cls.icon_exists(icon_name):
|
||||
missing_icons.append(icon_name)
|
||||
return missing_icons
|
||||
return missing_icons
|
||||
|
||||
@ -15,6 +15,7 @@ from ui.import_project_dialog import ImportProjectDialog
|
||||
from ui.project_settings_page import ProjectSettingsPage
|
||||
from data.project_manager import ProjectManager
|
||||
from ui.icon_manager import IconManager
|
||||
from ui.widget import UniversalMessageDialog
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
"""主窗口类"""
|
||||
@ -282,20 +283,31 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def show_about(self):
|
||||
"""显示关于对话框"""
|
||||
QMessageBox.about(self, "关于 MetaCore",
|
||||
"MetaCore 项目管理平台\n\n"
|
||||
"版本: 1.0.0\n"
|
||||
"基于 PyQt5 开发\n\n"
|
||||
"© 2024 MetaCore Team")
|
||||
# QMessageBox.about(self, "关于 MetaCore",
|
||||
# "MetaCore 项目管理平台\n\n"
|
||||
# "版本: 1.0.0\n"
|
||||
# "基于 PyQt5 开发\n\n"
|
||||
# "© 2024 MetaCore Team")
|
||||
UniversalMessageDialog.show_info(self,
|
||||
"关于 MetaCore",
|
||||
"MetaCore 项目管理平台\n\n"
|
||||
"版本: 1.0.0\n"
|
||||
"基于 PyQt5 开发\n\n"
|
||||
"© 2024 MetaCore Team",
|
||||
False, "确定")
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""关闭事件"""
|
||||
reply = QMessageBox.question(self, '确认退出',
|
||||
'确定要退出 MetaCore 吗?',
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No)
|
||||
# reply = QMessageBox.question(self, '确认退出',
|
||||
# '确定要退出 MetaCore 吗?',
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.No)
|
||||
reply = UniversalMessageDialog.show_info(self,
|
||||
'确认退出',
|
||||
'确定要退出 MetaCore 吗?',
|
||||
True, "是", "否")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
# 保存数据
|
||||
self.project_manager.save_projects()
|
||||
event.accept()
|
||||
|
||||
@ -63,8 +63,8 @@ class ProjectArea(QWidget):
|
||||
header_widget = QWidget()
|
||||
header_widget.setObjectName("contentHeader")
|
||||
header_layout = QHBoxLayout(header_widget)
|
||||
header_layout.setContentsMargins(36, 26, 36, 28)
|
||||
header_layout.setSpacing(16)
|
||||
header_layout.setContentsMargins(36, 26, 36, 24)
|
||||
header_layout.setSpacing(0)
|
||||
|
||||
breadcrumb_container = QWidget()
|
||||
breadcrumb_container.setObjectName("breadcrumbContainer")
|
||||
@ -115,7 +115,7 @@ class ProjectArea(QWidget):
|
||||
|
||||
# 网格布局
|
||||
self.projects_layout = QGridLayout(self.projects_container)
|
||||
self.projects_layout.setContentsMargins(36, 18, 6, 18)
|
||||
self.projects_layout.setContentsMargins(36, 24, 6, 18)
|
||||
self.projects_layout.setSpacing(24)
|
||||
self.projects_layout.setAlignment(Qt.AlignTop) # 设置顶部对齐
|
||||
|
||||
|
||||
@ -15,7 +15,10 @@ from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager, Project
|
||||
from ui.icon_manager import IconManager
|
||||
from ui.styles import StyleSheet
|
||||
from ui.project_settings_page import ProjectSettingsPage
|
||||
from ui.widget import UniversalMessageDialog
|
||||
|
||||
class ImageDisplayWidget(QWidget):
|
||||
"""
|
||||
一个专门用于显示带圆角图片的控件。
|
||||
@ -310,17 +313,45 @@ class ProjectCard(QWidget):
|
||||
self.overlay_btn.setToolTip("确认删除项目")
|
||||
else:
|
||||
self.overlay_btn = QPushButton(self)
|
||||
if IconManager.icon_exists('infomation'):
|
||||
self.overlay_btn.setIcon(IconManager.get_icon('infomation', QSize(16, 16)))
|
||||
self.overlay_btn.setIconSize(QSize(16, 16))
|
||||
else:
|
||||
self.overlay_btn.setText("ⓘ")
|
||||
self.overlay_btn.setObjectName("overlayInfoBtn")
|
||||
self.overlay_btn.setCursor(Qt.PointingHandCursor)
|
||||
self.overlay_btn.setAttribute(Qt.WA_Hover, True)
|
||||
self.overlay_btn.installEventFilter(self)
|
||||
self._set_overlay_icon("infomation", fallback_text="i")
|
||||
self.overlay_btn.clicked.connect(self.show_context_menu)
|
||||
# self.overlay_btn.setToolTip("项目信息")
|
||||
|
||||
# 设置按钮位置和大小
|
||||
self.overlay_btn.setGeometry(248, 8, 20, 20)
|
||||
|
||||
def _set_overlay_icon(self, icon_name: str, fallback_text: str = ""):
|
||||
"""Set overlay button icon with fallback text."""
|
||||
if not hasattr(self, "overlay_btn"):
|
||||
return
|
||||
|
||||
if IconManager.icon_exists(icon_name):
|
||||
self.overlay_btn.setIcon(IconManager.get_icon(icon_name, QSize(16, 16)))
|
||||
self.overlay_btn.setIconSize(QSize(16, 16))
|
||||
self.overlay_btn.setText("")
|
||||
else:
|
||||
self.overlay_btn.setIcon(QIcon())
|
||||
self.overlay_btn.setText(fallback_text)
|
||||
|
||||
def eventFilter(self, watched, event):
|
||||
"""Handle hover/click states for the overlay button icon."""
|
||||
if hasattr(self, "overlay_btn") and watched is self.overlay_btn:
|
||||
if event.type() == QEvent.Enter:
|
||||
self._set_overlay_icon("infomation_hover", fallback_text="i")
|
||||
elif event.type() == QEvent.Leave:
|
||||
self._set_overlay_icon("infomation", fallback_text="i")
|
||||
elif event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton:
|
||||
self._set_overlay_icon("infomation_check", fallback_text="v")
|
||||
elif event.type() == QEvent.MouseButtonRelease and event.button() == Qt.LeftButton:
|
||||
if self.overlay_btn.rect().contains(event.pos()):
|
||||
self._set_overlay_icon("infomation_hover", fallback_text="i")
|
||||
else:
|
||||
self._set_overlay_icon("infomation", fallback_text="i")
|
||||
return super().eventFilter(watched, event)
|
||||
|
||||
def create_bottom_overlay(self):
|
||||
"""创建底部信息覆盖层"""
|
||||
@ -557,10 +588,13 @@ class ProjectCard(QWidget):
|
||||
def show_context_menu(self):
|
||||
"""显示右键菜单"""
|
||||
menu = QMenu(self)
|
||||
menu.setWindowFlags(menu.windowFlags() | Qt.FramelessWindowHint | Qt.NoDropShadowWindowHint)
|
||||
menu.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||
menu.setStyleSheet(StyleSheet.get_context_menu_style())
|
||||
|
||||
# 刷新预览图
|
||||
if IconManager.icon_exists("Refresh"):
|
||||
refresh_action = menu.addAction(IconManager.get_icon('Refresh'), "刷新预览图")
|
||||
if IconManager.icon_exists("refresh_projectcard"):
|
||||
refresh_action = menu.addAction(IconManager.get_icon('refresh_projectcard'), "刷新预览图")
|
||||
else:
|
||||
refresh_action = menu.addAction("🔄 刷新预览图")
|
||||
refresh_action.triggered.connect(self.refresh_preview_image)
|
||||
@ -568,8 +602,8 @@ class ProjectCard(QWidget):
|
||||
menu.addSeparator()
|
||||
|
||||
# 在资源管理器显示
|
||||
if IconManager.icon_exists('folder'):
|
||||
show_in_explorer_action = menu.addAction(IconManager.get_icon('folder'), "在资源管理器显示")
|
||||
if IconManager.icon_exists('open_projectcard'):
|
||||
show_in_explorer_action = menu.addAction(IconManager.get_icon('open_projectcard'), "在资源管理器显示")
|
||||
else:
|
||||
show_in_explorer_action = menu.addAction("📁 在资源管理器显示")
|
||||
show_in_explorer_action.triggered.connect(self.show_in_explorer)
|
||||
@ -577,8 +611,8 @@ class ProjectCard(QWidget):
|
||||
menu.addSeparator()
|
||||
|
||||
# 删除项目
|
||||
if IconManager.icon_exists('delete'):
|
||||
delete_action = menu.addAction(IconManager.get_icon('delete'), "移除项目")
|
||||
if IconManager.icon_exists('remove_projectcard'):
|
||||
delete_action = menu.addAction(IconManager.get_icon('remove_projectcard'), "移除项目")
|
||||
else:
|
||||
delete_action = menu.addAction("🗑️ 移除项目")
|
||||
delete_action.triggered.connect(self.delete_project)
|
||||
@ -602,18 +636,25 @@ class ProjectCard(QWidget):
|
||||
# 使用项目管理器的验证方法进行全面检查
|
||||
is_valid, error_message = self.project_manager.validate_project_open(project_path)
|
||||
if not is_valid:
|
||||
QMessageBox.warning(self, "无法打开项目", f"项目无法打开: {error_message}")
|
||||
# QMessageBox.warning(self, "无法打开项目", f"项目无法打开: {error_message}")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"无法打开项目", f"项目无法打开: {error_message}",
|
||||
False, "确定")
|
||||
return
|
||||
|
||||
# 验证通过,显示成功信息
|
||||
# QMessageBox.information(self, "打开项目", f"正在打开项目: {self.project.title}")
|
||||
# 使用question对话框提供明确的确认选项
|
||||
reply = QMessageBox.question(self, "打开项目",
|
||||
f"确定要打开项目: {self.project.title}?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes)
|
||||
# reply = QMessageBox.question(self, "打开项目",
|
||||
# f"确定要打开项目: {self.project.title}?",
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.Yes)
|
||||
reply = UniversalMessageDialog.show_info(self,
|
||||
"打开项目",
|
||||
f"确定要打开项目: {self.project.title}?",
|
||||
True, "确定", "取消")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
# 用户确认打开项目,继续执行打开逻辑
|
||||
# TODO: 在这里添加实际的项目打开逻辑
|
||||
print(f"正在打开项目路径: {project_path},正在启动应用程序: {self.project.title}")
|
||||
@ -633,11 +674,15 @@ class ProjectCard(QWidget):
|
||||
)
|
||||
|
||||
if not success:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"启动失败",
|
||||
"无法启动,请检查打开项目路径。"
|
||||
)
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"启动失败",
|
||||
"无法启动,请检查打开项目路径。",
|
||||
False, "确定")
|
||||
# QMessageBox.warning(
|
||||
# self,
|
||||
# "启动失败",
|
||||
# "无法启动,请检查打开项目路径。"
|
||||
# )
|
||||
# if success:
|
||||
# QMessageBox.information(
|
||||
# self,
|
||||
@ -678,7 +723,11 @@ class ProjectCard(QWidget):
|
||||
# except Exception as e:
|
||||
# QMessageBox.critical(self, "错误", f"打开项目时发生错误:\n{str(e)}")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", f"启动PyCharm时发生错误:\n{str(e)}")
|
||||
# QMessageBox.critical(self, "错误", f"启动PyCharm时发生错误:\n{str(e)}")
|
||||
UniversalMessageDialog.show_error(self,
|
||||
"错误",
|
||||
f"启动PyCharm时发生错误:\n{str(e)}",
|
||||
False, "确定")
|
||||
|
||||
def on_pycharm_started(self):
|
||||
"""PyCharm启动完成回调"""
|
||||
@ -686,11 +735,15 @@ class ProjectCard(QWidget):
|
||||
|
||||
def on_project_method_called(self, target_project_path):
|
||||
"""项目方法调用完成回调"""
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"操作完成",
|
||||
f"已成功在PyCharm中打开项目: {target_project_path}"
|
||||
)
|
||||
# QMessageBox.information(
|
||||
# self,
|
||||
# "操作完成",
|
||||
# f"已成功在PyCharm中打开项目: {target_project_path}"
|
||||
# )
|
||||
UniversalMessageDialog.show_info(self,
|
||||
"操作完成",
|
||||
f"已成功在PyCharm中打开项目: {target_project_path}",
|
||||
False, "确定")
|
||||
|
||||
def show_in_explorer(self):
|
||||
"""在资源管理器中显示项目目录"""
|
||||
@ -699,7 +752,11 @@ class ProjectCard(QWidget):
|
||||
project_path_str = self.project.project_dir if self.project.project_dir else self.project.path
|
||||
|
||||
if not project_path_str:
|
||||
QMessageBox.warning(self, "路径不存在", "项目路径为空,请检查项目配置。")
|
||||
# QMessageBox.warning(self, "路径不存在", "项目路径为空,请检查项目配置。")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"路径不存在",
|
||||
"项目路径为空,请检查项目配置。",
|
||||
False, "确定")
|
||||
return
|
||||
|
||||
# 使用pathlib处理路径
|
||||
@ -713,8 +770,12 @@ class ProjectCard(QWidget):
|
||||
|
||||
# 检查项目路径是否存在
|
||||
if not project_path.exists():
|
||||
QMessageBox.warning(self, "路径不存在",
|
||||
f"项目路径不存在或无效:\n{project_path}\n\n请检查项目是否已被移动或删除。")
|
||||
# QMessageBox.warning(self, "路径不存在",
|
||||
# f"项目路径不存在或无效:\n{project_path}\n\n请检查项目是否已被移动或删除。")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"路径不存在",
|
||||
f"项目路径不存在或无效:\n{project_path}\n\n请检查项目是否已被移动或删除。",
|
||||
False, "确定")
|
||||
return
|
||||
|
||||
# 获取操作系统类型
|
||||
@ -725,7 +786,12 @@ class ProjectCard(QWidget):
|
||||
# Windows使用os.startfile,会自动使用系统默认的文件管理器
|
||||
os.startfile(str(project_path))
|
||||
except OSError as e:
|
||||
QMessageBox.critical(self, "打开失败", f"无法打开资源管理器:\n{str(e)}")
|
||||
# QMessageBox.critical(self, "打开失败", f"无法打开资源管理器:\n{str(e)}")
|
||||
UniversalMessageDialog.show_error(self,
|
||||
"打开失败",
|
||||
f"无法打开资源管理器:\n{str(e)}",
|
||||
False, "确定")
|
||||
return
|
||||
|
||||
elif system == "darwin": # macOS
|
||||
if project_path.is_file():
|
||||
@ -752,39 +818,61 @@ class ProjectCard(QWidget):
|
||||
# 最后尝试使用xdg-open
|
||||
subprocess.run(['xdg-open', str(project_path)], check=True)
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
QMessageBox.warning(self, "无法打开文件管理器",
|
||||
"系统中没有找到合适的文件管理器。\n"
|
||||
f"请手动打开路径: {project_path}")
|
||||
# QMessageBox.warning(self, "无法打开文件管理器",
|
||||
# "系统中没有找到合适的文件管理器。\n"
|
||||
# f"请手动打开路径: {project_path}")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"无法打开文件管理器",
|
||||
"系统中没有找到合适的文件管理器。\n"
|
||||
f"请手动打开路径: {project_path}",
|
||||
False, "确定")
|
||||
|
||||
print(f"成功在资源管理器中打开: {project_path}")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
QMessageBox.critical(self, "打开失败",
|
||||
f"无法打开资源管理器:\n{str(e)}")
|
||||
# QMessageBox.critical(self, "打开失败",
|
||||
# f"无法打开资源管理器:\n{str(e)}")
|
||||
UniversalMessageDialog.show_error(self,
|
||||
"打开失败",
|
||||
f"无法打开资源管理器:\n{str(e)}",
|
||||
False, "确定")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误",
|
||||
f"打开资源管理器时发生错误:\n{str(e)}")
|
||||
# QMessageBox.critical(self, "错误",
|
||||
# f"打开资源管理器时发生错误:\n{str(e)}")
|
||||
UniversalMessageDialog.show_error(self,
|
||||
"错误",
|
||||
f"打开资源管理器时发生错误:\n{str(e)}",
|
||||
False, "确定")
|
||||
|
||||
def delete_project(self):
|
||||
"""删除项目"""
|
||||
reply = QMessageBox.question(self, "确认移除",
|
||||
f"确定要移除项目 \"{self.project.title}\" 吗?\n此操作不可撤销。",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No)
|
||||
# reply = QMessageBox.question(self, "确认移除",
|
||||
# f"确定要移除项目 \"{self.project.title}\" 吗?\n此操作不可撤销。",
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.No)
|
||||
reply = UniversalMessageDialog.show_info(self,
|
||||
"确认移除",
|
||||
f"确定要移除项目 \"{self.project.title}\" 吗?\n此操作不可撤销。",
|
||||
True, "确定", "取消")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
self.project_manager.remove_project(self.project.id)
|
||||
|
||||
def confirm_delete_project(self):
|
||||
"""确认删除待删除状态的项目"""
|
||||
reply = QMessageBox.question(self, "确认删除项目",
|
||||
f"确定要永久删除项目 \"{self.project.title}\" 吗?\n"
|
||||
f"此操作不可撤销。\n\n"
|
||||
f"提示:如果项目目录已恢复,您可以点击项目卡片来恢复项目。",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No)
|
||||
# reply = QMessageBox.question(self, "确认删除项目",
|
||||
# f"确定要永久删除项目 \"{self.project.title}\" 吗?\n"
|
||||
# f"此操作不可撤销。\n\n"
|
||||
# f"提示:如果项目目录已恢复,您可以点击项目卡片来恢复项目。",
|
||||
# QMessageBox.Yes | QMessageBox.No,
|
||||
# QMessageBox.No)
|
||||
reply = UniversalMessageDialog.show_info(self,
|
||||
"确认删除项目",
|
||||
f"确定要永久删除项目 \"{self.project.title}\" 吗?\n"
|
||||
f"此操作不可撤销。\n\n",
|
||||
True, "确定", "取消")
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
if reply == QDialog.Accepted:
|
||||
self.project_manager.confirm_delete_project(self.project.id)
|
||||
|
||||
def update_display(self):
|
||||
@ -852,12 +940,20 @@ class ProjectCard(QWidget):
|
||||
def try_restore_project(self):
|
||||
"""尝试恢复待删除状态的项目"""
|
||||
if self.project_manager.restore_project(self.project.id):
|
||||
QMessageBox.information(self, "项目已恢复",
|
||||
f"项目 \"{self.project.title}\" 已成功恢复!")
|
||||
# QMessageBox.information(self, "项目已恢复",
|
||||
# f"项目 \"{self.project.title}\" 已成功恢复!")
|
||||
UniversalMessageDialog.show_info(self,
|
||||
"项目已恢复",
|
||||
f"项目 \"{self.project.title}\" 已成功恢复!",
|
||||
False, "确定")
|
||||
else:
|
||||
QMessageBox.information(self, "项目目录不存在",
|
||||
f"项目 \"{self.project.title}\" 的目录仍然不存在:\n{self.project.project_dir}\n\n"
|
||||
f"提示:当您恢复项目目录后,系统会自动检测并恢复项目状态,无需手动操作。")
|
||||
# QMessageBox.information(self, "项目目录不存在",
|
||||
# f"项目 \"{self.project.title}\" 的目录仍然不存在:\n{self.project.project_dir}\n\n"
|
||||
# f"提示:当您恢复项目目录后,系统会自动检测并恢复项目状态,无需手动操作。")
|
||||
UniversalMessageDialog.show_info(self,
|
||||
"项目目录不存在",
|
||||
f"项目 \"{self.project.title}\" 的目录仍然不存在:\n{self.project.project_dir}\n\n"
|
||||
f"提示:当您恢复项目目录后,系统会自动检测并恢复项目状态,无需手动操作。")
|
||||
|
||||
def enterEvent(self, event):
|
||||
"""鼠标进入事件"""
|
||||
@ -914,7 +1010,11 @@ class ProjectCard(QWidget):
|
||||
# 获取项目路径
|
||||
project_path = self.project.project_dir if self.project.project_dir else self.project.path
|
||||
if not project_path or not Path(project_path).exists():
|
||||
QMessageBox.warning(self, "路径不存在", "项目路径不存在,无法生成预览图。")
|
||||
# QMessageBox.warning(self, "路径不存在", "项目路径不存在,无法生成预览图。")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"路径不存在",
|
||||
"项目路径不存在,无法生成预览图。",
|
||||
False, "确定")
|
||||
return
|
||||
|
||||
# 显示进度提示
|
||||
@ -958,11 +1058,18 @@ class ProjectCard(QWidget):
|
||||
# 刷新显示以显示默认图标
|
||||
self.refresh_image_display()
|
||||
|
||||
QMessageBox.warning(self, "生成失败",
|
||||
"无法生成预览图,已使用默认图标。\n\n可能原因:\n"
|
||||
"• 项目目录中没有图片文件\n"
|
||||
"• 图片文件格式不支持\n"
|
||||
"• 权限不足")
|
||||
# QMessageBox.warning(self, "生成失败",
|
||||
# "无法生成预览图,已使用默认图标。\n\n可能原因:\n"
|
||||
# "• 项目目录中没有图片文件\n"
|
||||
# "• 图片文件格式不支持\n"
|
||||
# "• 权限不足")
|
||||
UniversalMessageDialog.show_warning(self,
|
||||
"生成失败",
|
||||
"无法生成预览图,已使用默认图标。\n\n可能原因: \n"
|
||||
"• 项目目录中没有图片文件\n"
|
||||
"• 图片文件格式不支持\n"
|
||||
"• 权限不足",
|
||||
False, "确定")
|
||||
|
||||
except Exception as e:
|
||||
# 发生异常时也使用project_empty_icon作为默认图片
|
||||
@ -972,7 +1079,11 @@ class ProjectCard(QWidget):
|
||||
# 刷新显示以显示默认图标
|
||||
self.refresh_image_display()
|
||||
|
||||
QMessageBox.critical(self, "错误", f"刷新预览图时发生错误,已使用默认图标:\n{str(e)}")
|
||||
# QMessageBox.critical(self, "错误", f"刷新预览图时发生错误,已使用默认图标:\n{str(e)}")
|
||||
UniversalMessageDialog.show_error(self,
|
||||
"错误",
|
||||
f"刷新预览图时发生错误,已使用默认图标:\n{str(e)}",
|
||||
False, "确定")
|
||||
finally:
|
||||
# 恢复按钮状态
|
||||
if target_btn:
|
||||
|
||||
@ -34,131 +34,209 @@ class ProjectSettingsPage(QWidget):
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化用户界面"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(30, 30, 30, 30)
|
||||
layout.setSpacing(20)
|
||||
|
||||
# 页面标题
|
||||
self.create_page_header(layout)
|
||||
|
||||
# 默认项目位置设置
|
||||
self.create_default_location_section(layout)
|
||||
self.setObjectName("settingsPage")
|
||||
self.setAttribute(Qt.WA_StyledBackground, True)
|
||||
|
||||
self.create_open_location_section(layout)
|
||||
|
||||
# 项目创建设置
|
||||
# self.create_project_creation_section(layout)
|
||||
|
||||
# 按钮区域
|
||||
self.create_button_section(layout)
|
||||
|
||||
# 添加弹性空间
|
||||
layout.addStretch()
|
||||
|
||||
def create_page_header(self, layout):
|
||||
"""创建页面标题"""
|
||||
self.main_layout = QVBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(0, 30, 24, 30)
|
||||
self.main_layout.setSpacing(0)
|
||||
|
||||
self.content_container = QFrame()
|
||||
self.content_container.setObjectName("settingsContentArea")
|
||||
self.content_container.setFrameShape(QFrame.NoFrame)
|
||||
self.content_container.setAttribute(Qt.WA_StyledBackground, True)
|
||||
self.main_layout.addWidget(self.content_container)
|
||||
|
||||
self.content_layout = QVBoxLayout(self.content_container)
|
||||
self.content_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.content_layout.setSpacing(0)
|
||||
|
||||
header_widget = self.create_page_header()
|
||||
self.content_layout.addWidget(header_widget)
|
||||
|
||||
body_widget = self.create_settings_body()
|
||||
self.content_layout.addWidget(body_widget)
|
||||
self.content_layout.addStretch()
|
||||
|
||||
def create_page_header(self):
|
||||
"""创建面包屑与标题区域"""
|
||||
header_widget = QWidget()
|
||||
header_widget.setObjectName("contentHeader")
|
||||
header_layout = QVBoxLayout(header_widget)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.setSpacing(8)
|
||||
header_layout.setContentsMargins(36, 32, 36, 24)
|
||||
header_layout.setSpacing(0)
|
||||
|
||||
breadcrumb_widget = QWidget()
|
||||
breadcrumb_widget.setObjectName("breadcrumbContainer")
|
||||
breadcrumb_layout = QHBoxLayout(breadcrumb_widget)
|
||||
breadcrumb_layout.setContentsMargins(0, 0, 0, 0)
|
||||
breadcrumb_layout.setSpacing(8)
|
||||
|
||||
breadcrumb_base = QLabel("设置中心")
|
||||
breadcrumb_base.setObjectName("breadcrumbBase")
|
||||
breadcrumb_layout.addWidget(breadcrumb_base)
|
||||
|
||||
breadcrumb_separator = QLabel("/")
|
||||
breadcrumb_separator.setObjectName("breadcrumbSeparator")
|
||||
breadcrumb_layout.addWidget(breadcrumb_separator)
|
||||
|
||||
breadcrumb_current = QLabel("项目设置")
|
||||
breadcrumb_current.setObjectName("breadcrumbCurrent")
|
||||
breadcrumb_layout.addWidget(breadcrumb_current)
|
||||
|
||||
breadcrumb_layout.addStretch()
|
||||
header_layout.addWidget(breadcrumb_widget)
|
||||
|
||||
# title_label = QLabel("项目设置")
|
||||
# title_label.setObjectName("settingsTitle")
|
||||
# header_layout.addWidget(title_label)
|
||||
|
||||
# subtitle_label = QLabel("配置项目创建和管理的相关设置。")
|
||||
# subtitle_label.setObjectName("settingsSubtitle")
|
||||
# subtitle_label.setWordWrap(True)
|
||||
# header_layout.addWidget(subtitle_label)
|
||||
|
||||
return header_widget
|
||||
|
||||
def create_settings_body(self):
|
||||
"""创建设置内容区域,结构与项目区域组件保持一致"""
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setObjectName("projectScrollArea")
|
||||
scroll_area.setFrameShape(QFrame.NoFrame)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
|
||||
body_container = QWidget()
|
||||
body_container.setObjectName("settingsBody")
|
||||
body_layout = QVBoxLayout(body_container)
|
||||
# body_layout.setContentsMargins(36, 24, 6, 18)
|
||||
body_layout.setSpacing(24)
|
||||
|
||||
settings_card = self.create_settings_card()
|
||||
body_layout.addWidget(settings_card)
|
||||
body_layout.addStretch()
|
||||
|
||||
scroll_area.setWidget(body_container)
|
||||
|
||||
# 主标题
|
||||
title_label = QLabel("项目设置")
|
||||
title_label.setObjectName("pageTitle")
|
||||
header_layout.addWidget(title_label)
|
||||
|
||||
# 副标题
|
||||
subtitle_label = QLabel("配置项目创建和管理的相关设置")
|
||||
subtitle_label.setObjectName("pageSubtitle")
|
||||
header_layout.addWidget(subtitle_label)
|
||||
|
||||
layout.addWidget(header_widget)
|
||||
|
||||
def create_default_location_section(self, layout):
|
||||
"""创建默认项目位置设置区域"""
|
||||
# 分组框
|
||||
group_box = QGroupBox("默认项目位置")
|
||||
group_box.setObjectName("settingsGroup")
|
||||
group_layout = QVBoxLayout(group_box)
|
||||
group_layout.setSpacing(15)
|
||||
|
||||
# 说明文字
|
||||
desc_label = QLabel("设置新项目的默认创建位置。")
|
||||
desc_label.setObjectName("settingsDescription")
|
||||
return scroll_area
|
||||
|
||||
def create_settings_card(self):
|
||||
"""创建主体设置卡片内容"""
|
||||
card = QFrame()
|
||||
card.setObjectName("settingsCard")
|
||||
card.setFrameShape(QFrame.NoFrame)
|
||||
card.setAttribute(Qt.WA_StyledBackground, True)
|
||||
card_layout = QVBoxLayout(card)
|
||||
card_layout.setContentsMargins(0, 0, 0, 0)
|
||||
card_layout.setSpacing(0)
|
||||
|
||||
sections = [
|
||||
{
|
||||
"title": "默认项目位置",
|
||||
"description": "设置新项目的默认创建位置。",
|
||||
"placeholder": "选择默认项目创建位置...",
|
||||
"browse": self.browse_default_location,
|
||||
"reset": self.reset_default_location,
|
||||
"attr": "path_input",
|
||||
},
|
||||
{
|
||||
"title": "打开设置",
|
||||
"description": "设置新项目的默认打开位置。",
|
||||
"placeholder": "选择默认项目打开位置...",
|
||||
"browse": self.browse_open_location,
|
||||
"reset": self.reset_open_location,
|
||||
"attr": "open_path_input",
|
||||
},
|
||||
]
|
||||
|
||||
total = len(sections)
|
||||
for index, section_info in enumerate(sections):
|
||||
is_first = index == 0
|
||||
is_last = index == total - 1
|
||||
section_widget = self.create_path_section(
|
||||
title=section_info["title"],
|
||||
description=section_info["description"],
|
||||
placeholder=section_info["placeholder"],
|
||||
browse_handler=section_info["browse"],
|
||||
reset_handler=section_info["reset"],
|
||||
input_attr=section_info["attr"],
|
||||
is_first=is_first,
|
||||
is_last=is_last,
|
||||
)
|
||||
card_layout.addWidget(section_widget)
|
||||
|
||||
return card
|
||||
|
||||
def create_path_section(
|
||||
self,
|
||||
title,
|
||||
description,
|
||||
placeholder,
|
||||
browse_handler,
|
||||
reset_handler,
|
||||
input_attr,
|
||||
is_first=False,
|
||||
is_last=False,
|
||||
):
|
||||
"""创建路径类型设置行"""
|
||||
section = QFrame()
|
||||
section.setObjectName("settingsRow")
|
||||
section.setFrameShape(QFrame.NoFrame)
|
||||
section.setAttribute(Qt.WA_StyledBackground, True)
|
||||
section.setProperty("isFirstRow", "true" if is_first else "false")
|
||||
section.setProperty("isLastRow", "true" if is_last else "false")
|
||||
section.style().unpolish(section)
|
||||
section.style().polish(section)
|
||||
|
||||
section_layout = QVBoxLayout(section)
|
||||
bottom_margin = 24 if is_last else 0
|
||||
section_layout.setContentsMargins(32, 24, 32, bottom_margin)
|
||||
section_layout.setSpacing(0)
|
||||
|
||||
title_label = QLabel(title)
|
||||
title_label.setObjectName("settingsSectionTitle")
|
||||
section_layout.addWidget(title_label)
|
||||
section_layout.addSpacing(8)
|
||||
|
||||
desc_label = QLabel(description)
|
||||
desc_label.setObjectName("settingsSectionDesc")
|
||||
desc_label.setWordWrap(True)
|
||||
group_layout.addWidget(desc_label)
|
||||
|
||||
# 当前路径显示和选择
|
||||
path_widget = QWidget()
|
||||
path_layout = QHBoxLayout(path_widget)
|
||||
path_layout.setContentsMargins(0, 0, 0, 0)
|
||||
path_layout.setSpacing(10)
|
||||
|
||||
# 路径输入框
|
||||
self.path_input = QLineEdit()
|
||||
self.path_input.setObjectName("pathInput")
|
||||
self.path_input.setPlaceholderText("选择默认项目创建位置...")
|
||||
self.path_input.setReadOnly(True) # 只读,通过按钮选择
|
||||
path_layout.addWidget(self.path_input)
|
||||
|
||||
# 浏览按钮
|
||||
self.browse_btn = QPushButton("浏览...")
|
||||
self.browse_btn.setObjectName("browseBtn")
|
||||
self.browse_btn.clicked.connect(self.browse_default_location)
|
||||
path_layout.addWidget(self.browse_btn)
|
||||
|
||||
# 重置按钮
|
||||
self.reset_btn = QPushButton("重置")
|
||||
self.reset_btn.setObjectName("resetBtn")
|
||||
self.reset_btn.clicked.connect(self.reset_default_location)
|
||||
path_layout.addWidget(self.reset_btn)
|
||||
|
||||
group_layout.addWidget(path_widget)
|
||||
|
||||
layout.addWidget(group_box)
|
||||
section_layout.addWidget(desc_label)
|
||||
section_layout.addSpacing(15)
|
||||
|
||||
def create_open_location_section(self, layout):
|
||||
"""创建打开位置设置区域"""
|
||||
# 分组框
|
||||
group_box = QGroupBox("打开位置")
|
||||
group_box.setObjectName("settingsGroup")
|
||||
group_layout = QVBoxLayout(group_box)
|
||||
group_layout.setSpacing(15)
|
||||
field_row = QWidget()
|
||||
field_row.setObjectName("settingsFieldRow")
|
||||
field_layout = QHBoxLayout(field_row)
|
||||
field_layout.setContentsMargins(19, 0, 0, 0)
|
||||
field_layout.setSpacing(12)
|
||||
|
||||
# 说明文字
|
||||
desc_label = QLabel("设置项目文件的默认打开位置。")
|
||||
desc_label.setObjectName("settingsDescription")
|
||||
desc_label.setWordWrap(True)
|
||||
group_layout.addWidget(desc_label)
|
||||
path_input = QLineEdit()
|
||||
path_input.setObjectName("settingsPathInput")
|
||||
path_input.setPlaceholderText(placeholder)
|
||||
path_input.setReadOnly(True)
|
||||
path_input.setFixedHeight(48)
|
||||
# path_input.setMinimumWidth(1099)
|
||||
field_layout.addWidget(path_input, stretch=1)
|
||||
|
||||
# 当前路径显示和选择
|
||||
path_widget = QWidget()
|
||||
path_layout = QHBoxLayout(path_widget)
|
||||
path_layout.setContentsMargins(0, 0, 0, 0)
|
||||
path_layout.setSpacing(10)
|
||||
browse_btn = QPushButton("浏览...")
|
||||
browse_btn.setObjectName("settingsPrimaryBtn")
|
||||
browse_btn.setCursor(Qt.PointingHandCursor)
|
||||
browse_btn.setFixedSize(175, 48)
|
||||
browse_btn.clicked.connect(browse_handler)
|
||||
field_layout.addWidget(browse_btn)
|
||||
|
||||
# 路径输入框
|
||||
self.open_path_input = QLineEdit()
|
||||
self.open_path_input.setObjectName("pathInput")
|
||||
self.open_path_input.setPlaceholderText("选择默认项目打开位置...")
|
||||
self.open_path_input.setReadOnly(True) # 只读,通过按钮选择
|
||||
path_layout.addWidget(self.open_path_input)
|
||||
reset_btn = QPushButton("重置")
|
||||
reset_btn.setObjectName("settingsGhostBtn")
|
||||
reset_btn.setCursor(Qt.PointingHandCursor)
|
||||
reset_btn.setFixedSize(175, 48)
|
||||
reset_btn.clicked.connect(reset_handler)
|
||||
field_layout.addWidget(reset_btn)
|
||||
|
||||
# 浏览按钮
|
||||
self.open_browse_btn = QPushButton("浏览...")
|
||||
self.open_browse_btn.setObjectName("browseBtn")
|
||||
self.open_browse_btn.clicked.connect(self.browse_open_location)
|
||||
path_layout.addWidget(self.open_browse_btn)
|
||||
section_layout.addWidget(field_row)
|
||||
|
||||
# 重置按钮
|
||||
self.open_reset_btn = QPushButton("重置")
|
||||
self.open_reset_btn.setObjectName("resetBtn")
|
||||
self.open_reset_btn.clicked.connect(self.reset_open_location)
|
||||
path_layout.addWidget(self.open_reset_btn)
|
||||
|
||||
group_layout.addWidget(path_widget)
|
||||
|
||||
layout.addWidget(group_box)
|
||||
setattr(self, input_attr, path_input)
|
||||
return section
|
||||
|
||||
def browse_open_location(self):
|
||||
"""浏览选择打开位置"""
|
||||
@ -179,6 +257,7 @@ class ProjectSettingsPage(QWidget):
|
||||
"""重置为默认打开位置"""
|
||||
default_path = self.get_default_projects_path()
|
||||
self.open_path_input.setText(default_path)
|
||||
self.save_settings_immediately("default_open_location", self.open_path_input.text())
|
||||
|
||||
def create_project_creation_section(self, layout):
|
||||
"""创建项目创建设置区域"""
|
||||
@ -238,6 +317,7 @@ class ProjectSettingsPage(QWidget):
|
||||
"""重置为默认位置"""
|
||||
default_path = self.get_default_projects_path()
|
||||
self.path_input.setText(default_path)
|
||||
self.save_settings_immediately("default_project_location", self.path_input.text())
|
||||
|
||||
def load_settings(self):
|
||||
"""加载保存的设置"""
|
||||
|
||||
@ -140,19 +140,19 @@ class Sidebar(QWidget):
|
||||
# 我的项目分组
|
||||
self.create_nav_section(nav_layout, "我的项目", [
|
||||
("📊", "项目概述", "overview"),
|
||||
("📋", "项目管理", "management"),
|
||||
# ("📋", "项目管理", "management"),
|
||||
])
|
||||
|
||||
# 资源管理分组
|
||||
self.create_nav_section(nav_layout, "资源管理", [
|
||||
("🏷", "资源分类", "resource_category"),
|
||||
("📦", "资源管理", "resource_management"),
|
||||
])
|
||||
# self.create_nav_section(nav_layout, "资源管理", [
|
||||
# ("🏷", "资源分类", "resource_category"),
|
||||
# ("📦", "资源管理", "resource_management"),
|
||||
# ])
|
||||
|
||||
# 设置中心分组
|
||||
self.create_nav_section(nav_layout, "设置中心", [
|
||||
("📁", "项目设置", "project_settings"),
|
||||
("⚙", "系统设置", "system_settings"),
|
||||
# ("⚙", "系统设置", "system_settings"),
|
||||
])
|
||||
|
||||
nav_layout.addStretch()
|
||||
@ -184,14 +184,14 @@ class Sidebar(QWidget):
|
||||
items_widget = QWidget()
|
||||
items_widget.setObjectName("navItems")
|
||||
items_layout = QVBoxLayout(items_widget)
|
||||
items_layout.setContentsMargins(0, 10, 0, 0)
|
||||
items_layout.setContentsMargins(50, 10, 0, 0)
|
||||
items_layout.setSpacing(10)
|
||||
|
||||
# 创建导航项
|
||||
for icon, text, filter_type in items:
|
||||
nav_item = self.create_nav_item(icon, text, filter_type)
|
||||
items_layout.addWidget(nav_item)
|
||||
|
||||
items_layout.addWidget(nav_item, alignment=Qt.AlignLeft)
|
||||
|
||||
section_layout.addWidget(items_widget)
|
||||
|
||||
# 展开/收起功能
|
||||
@ -229,6 +229,8 @@ class Sidebar(QWidget):
|
||||
|
||||
item_btn.setObjectName("navItem")
|
||||
item_btn.setCheckable(True)
|
||||
item_btn.setFixedSize(QSize(186, 30))
|
||||
item_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
||||
|
||||
# 设置默认选中
|
||||
if filter_type == "overview":
|
||||
|
||||
411
MetaCore/ui/widget.py
Normal file
@ -0,0 +1,411 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
from PyQt5.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout,
|
||||
QLineEdit, QPushButton, QLabel,
|
||||
QTreeView, QTreeWidget, QTreeWidgetItem, QWidget,
|
||||
QFileDialog, QMessageBox, QAbstractItemView, QMenu, QDockWidget, QButtonGroup, QToolButton, QFrame, QSizePolicy)
|
||||
from PyQt5.QtCore import Qt, QUrl, QMimeData, QPoint, QSize
|
||||
from PyQt5.QtGui import QDrag, QPainter, QPixmap, QPen, QBrush, QFont
|
||||
from PyQt5.sip import wrapinstance
|
||||
from ui.icon_manager import IconManager
|
||||
|
||||
class UniversalMessageDialog(QDialog):
|
||||
"""通用消息对话框类 - 支持不同图标和按钮配置"""
|
||||
|
||||
# 消息类型枚举
|
||||
SUCCESS = "success_icon"
|
||||
WARNING = "warning_icon"
|
||||
ERROR = "fail_icon"
|
||||
INFO = "info"
|
||||
|
||||
def __init__(self, parent, title, message, message_type=INFO, show_cancel=True,
|
||||
confirm_text="确认", cancel_text="取消", icon_size=QSize(20, 20)):
|
||||
"""
|
||||
初始化通用消息对话框
|
||||
|
||||
Args:
|
||||
parent: 父窗口
|
||||
title: 对话框标题
|
||||
message: 消息内容
|
||||
message_type: 消息类型 (SUCCESS, WARNING, ERROR, INFO)
|
||||
show_cancel: 是否显示取消按钮
|
||||
confirm_text: 确认按钮文字
|
||||
cancel_text: 取消按钮文字
|
||||
icon_size: 图标尺寸
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle(title)
|
||||
self.setObjectName("universalMessageDialog")
|
||||
self.setModal(True)
|
||||
self.resize(508, 134)
|
||||
self.setMinimumSize(508, 134)
|
||||
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
|
||||
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||
|
||||
# 对话框配置
|
||||
self.message_type = message_type
|
||||
self.show_cancel = show_cancel
|
||||
self.confirm_text = confirm_text
|
||||
self.cancel_text = cancel_text
|
||||
self.icon_size = icon_size
|
||||
|
||||
# 拖拽相关
|
||||
self.dragging = False
|
||||
self.drag_position = QPoint()
|
||||
|
||||
# 图标管理
|
||||
self.icon_manager = IconManager()
|
||||
self._title_icon_size = QSize(18, 18)
|
||||
self._icon_close = self.icon_manager.get_icon('close_bt_icon', self._title_icon_size)
|
||||
|
||||
# 根据消息类型获取对应图标
|
||||
self._message_icon = self._get_message_icon()
|
||||
|
||||
# 设置样式
|
||||
self._setup_styles()
|
||||
|
||||
# 创建UI
|
||||
self._create_ui(message)
|
||||
|
||||
def _get_message_icon(self):
|
||||
"""根据消息类型获取对应图标"""
|
||||
icon_map = {
|
||||
self.SUCCESS: 'success_icon',
|
||||
self.WARNING: 'warning_icon',
|
||||
self.ERROR: 'fail_icon',
|
||||
self.INFO: 'success_icon' # 默认使用成功图标
|
||||
}
|
||||
|
||||
icon_name = icon_map.get(self.message_type, 'success_icon')
|
||||
return self.icon_manager.get_icon(icon_name, self.icon_size)
|
||||
|
||||
def _setup_styles(self):
|
||||
"""设置对话框样式"""
|
||||
self.setStyleSheet("""
|
||||
QDialog#universalMessageDialog {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
QFrame#baseFrame {
|
||||
background-color: #19191B;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 5px;
|
||||
}
|
||||
QWidget#titleBar {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 5px 5px 0px 0px;
|
||||
min-height: 32px;
|
||||
max-height: 32px;
|
||||
}
|
||||
QWidget#titleBar QWidget {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
QLabel#titleLabel {
|
||||
color: #FFFFFF;
|
||||
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.7px;
|
||||
}
|
||||
QWidget#controlButtons QPushButton {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #EBEBEB;
|
||||
font-size: 14px;
|
||||
min-width: 18px;
|
||||
max-width: 18px;
|
||||
min-height: 18px;
|
||||
max-height: 18px;
|
||||
padding: 0px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
QWidget#controlButtons QPushButton:hover {
|
||||
background-color: #2A2D2E;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
QPushButton#closeButton {
|
||||
border-radius: 0px 5px 0px 0px;
|
||||
}
|
||||
QPushButton#closeButton:hover {
|
||||
background-color: #2A2D2E;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
QFrame#titleSeparator {
|
||||
background-color: #3E3E42;
|
||||
border: none;
|
||||
min-height: 1px;
|
||||
max-height: 1px;
|
||||
}
|
||||
QWidget#contentWidget {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
QLabel#iconLabel {
|
||||
background-color: transparent;
|
||||
}
|
||||
QLabel#messageLabel {
|
||||
background-color: transparent;
|
||||
color: #EBEBEB;
|
||||
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.6px;
|
||||
line-height: 1.4;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
QWidget#buttonWidget {
|
||||
background-color: transparent;
|
||||
}
|
||||
QPushButton {
|
||||
background-color: rgba(89, 98, 118, 0.5);
|
||||
color: #EBEBEB;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
padding: 0px 12px;
|
||||
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 10px;
|
||||
letter-spacing: 0.5px;
|
||||
min-width: 90px;
|
||||
max-width: 90px;
|
||||
min-height: 28px;
|
||||
max-height: 28px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #3067C0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #2556A0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
QPushButton#primaryButton {
|
||||
background-color: rgba(89, 98, 118, 0.5);
|
||||
border: none;
|
||||
color: #EBEBEB;
|
||||
font-weight: 300;
|
||||
}
|
||||
QPushButton#primaryButton:hover {
|
||||
background-color: #2556A0;
|
||||
}
|
||||
QPushButton#primaryButton:pressed {
|
||||
background-color: #1E4A8C;
|
||||
}
|
||||
QPushButton#secondaryButton {
|
||||
background-color: rgba(89, 98, 118, 0.5);
|
||||
border: none;
|
||||
color: #EBEBEB;
|
||||
}
|
||||
QPushButton#secondaryButton:hover {
|
||||
background-color: #3067C0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
QPushButton#secondaryButton:pressed {
|
||||
background-color: #2556A0;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
""")
|
||||
|
||||
def _create_ui(self, message):
|
||||
"""构建用户界面"""
|
||||
main_layout = QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
main_layout.setSpacing(0)
|
||||
|
||||
base_frame = QFrame()
|
||||
base_frame.setObjectName('baseFrame')
|
||||
base_frame.setFrameShape(QFrame.NoFrame)
|
||||
base_frame.setAttribute(Qt.WA_StyledBackground, True)
|
||||
|
||||
base_layout = QVBoxLayout(base_frame)
|
||||
base_layout.setContentsMargins(25, 14, 25, 14)
|
||||
base_layout.setSpacing(0)
|
||||
|
||||
self._create_title_bar()
|
||||
base_layout.addWidget(self.title_bar)
|
||||
base_layout.addSpacing(4)
|
||||
|
||||
title_separator = QFrame()
|
||||
title_separator.setObjectName('titleSeparator')
|
||||
title_separator.setFrameShape(QFrame.HLine)
|
||||
title_separator.setFrameShadow(QFrame.Plain)
|
||||
base_layout.addWidget(title_separator)
|
||||
base_layout.addSpacing(10)
|
||||
|
||||
content_widget = QWidget()
|
||||
content_widget.setObjectName('contentWidget')
|
||||
content_layout = QVBoxLayout(content_widget)
|
||||
content_layout.setContentsMargins(0, 0, 0, 0)
|
||||
content_layout.setSpacing(10)
|
||||
|
||||
message_area = QHBoxLayout()
|
||||
message_area.setContentsMargins(0, 0, 0, 0)
|
||||
message_area.setSpacing(10)
|
||||
|
||||
# 用一个垂直布局包裹icon_label,确保顶部对齐
|
||||
icon_vbox = QVBoxLayout()
|
||||
icon_vbox.setContentsMargins(0, 0, 0, 0)
|
||||
icon_vbox.setSpacing(0)
|
||||
icon_label = QLabel()
|
||||
icon_label.setObjectName('iconLabel')
|
||||
if self._message_icon and not self._message_icon.isNull():
|
||||
icon_label.setPixmap(self._message_icon.pixmap(self.icon_size))
|
||||
icon_label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||
icon_label.setFixedSize(self.icon_size)
|
||||
icon_vbox.addWidget(icon_label, alignment=Qt.AlignTop)
|
||||
icon_vbox.addStretch()
|
||||
message_area.addLayout(icon_vbox)
|
||||
|
||||
self.message_label = QLabel(message)
|
||||
self.message_label.setObjectName('messageLabel')
|
||||
self.message_label.setWordWrap(True)
|
||||
self.message_label.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
||||
self.message_label.setMinimumHeight(self.icon_size.height())
|
||||
self.message_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
|
||||
message_area.addWidget(self.message_label, 1)
|
||||
message_area.addStretch()
|
||||
|
||||
content_layout.addLayout(message_area)
|
||||
base_layout.addWidget(content_widget)
|
||||
base_layout.addSpacing(10)
|
||||
|
||||
button_widget = QWidget()
|
||||
button_widget.setObjectName('buttonWidget')
|
||||
button_layout = QHBoxLayout(button_widget)
|
||||
button_layout.setContentsMargins(0, 0, 0, 0)
|
||||
button_layout.setSpacing(10)
|
||||
button_layout.addStretch()
|
||||
|
||||
if self.show_cancel:
|
||||
self.cancel_button = QPushButton(self.cancel_text)
|
||||
self.cancel_button.setObjectName("secondaryButton")
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
self.cancel_button.setFixedSize(90, 28)
|
||||
button_layout.addWidget(self.cancel_button)
|
||||
|
||||
self.confirm_button = QPushButton(self.confirm_text)
|
||||
self.confirm_button.setObjectName("primaryButton")
|
||||
self.confirm_button.clicked.connect(self.accept)
|
||||
self.confirm_button.setFixedSize(90, 28)
|
||||
button_layout.addWidget(self.confirm_button)
|
||||
|
||||
self.confirm_button.setDefault(True)
|
||||
self.confirm_button.setAutoDefault(True)
|
||||
if self.show_cancel:
|
||||
self.cancel_button.setAutoDefault(False)
|
||||
|
||||
base_layout.addWidget(button_widget)
|
||||
|
||||
main_layout.addWidget(base_frame)
|
||||
|
||||
def _create_title_bar(self):
|
||||
"""创建自定义标题栏"""
|
||||
self.title_bar = QFrame()
|
||||
self.title_bar.setObjectName("titleBar")
|
||||
|
||||
title_layout = QHBoxLayout(self.title_bar)
|
||||
title_layout.setContentsMargins(0, 0, 0, 0)
|
||||
title_layout.setSpacing(0)
|
||||
|
||||
self.title_label = QLabel(self.windowTitle())
|
||||
self.title_label.setObjectName("titleLabel")
|
||||
self.title_label.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)
|
||||
title_layout.addWidget(self.title_label, 1)
|
||||
|
||||
title_layout.addStretch()
|
||||
|
||||
controls = QWidget()
|
||||
controls.setObjectName("controlButtons")
|
||||
controls_layout = QHBoxLayout(controls)
|
||||
controls_layout.setContentsMargins(0, 0, 0, 0)
|
||||
controls_layout.setSpacing(0)
|
||||
|
||||
self.close_button = QPushButton()
|
||||
self.close_button.setObjectName("closeButton")
|
||||
self.close_button.clicked.connect(self.reject)
|
||||
self.close_button.setFocusPolicy(Qt.NoFocus)
|
||||
controls_layout.addWidget(self.close_button)
|
||||
|
||||
self._apply_title_bar_icons()
|
||||
|
||||
title_layout.addWidget(controls)
|
||||
|
||||
|
||||
def _apply_title_bar_icons(self):
|
||||
"""应用标题栏图标"""
|
||||
if self._icon_close:
|
||||
self.close_button.setIcon(self._icon_close)
|
||||
self.close_button.setIconSize(self._title_icon_size)
|
||||
self.close_button.setText("")
|
||||
self.close_button.setToolTip("关闭")
|
||||
|
||||
def setWindowTitle(self, title):
|
||||
"""设置窗口标题"""
|
||||
super().setWindowTitle(title)
|
||||
if hasattr(self, "title_label"):
|
||||
self.title_label.setText(title)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
"""鼠标按下事件 - 用于拖拽窗口"""
|
||||
if event.button() == Qt.LeftButton and self.title_bar.geometry().contains(event.pos()):
|
||||
self.dragging = True
|
||||
self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
|
||||
event.accept()
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""鼠标移动事件 - 用于拖拽窗口"""
|
||||
if event.buttons() == Qt.LeftButton and self.dragging:
|
||||
self.move(event.globalPos() - self.drag_position)
|
||||
event.accept()
|
||||
super().mouseMoveEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
"""鼠标释放事件 - 停止拖拽"""
|
||||
if event.button() == Qt.LeftButton:
|
||||
self.dragging = False
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
@staticmethod
|
||||
def show_success(parent, title, message, show_cancel=False, confirm_text="确认"):
|
||||
"""显示成功消息对话框"""
|
||||
dialog = UniversalMessageDialog(
|
||||
parent, title, message,
|
||||
UniversalMessageDialog.SUCCESS,
|
||||
show_cancel, confirm_text
|
||||
)
|
||||
return dialog.exec_()
|
||||
|
||||
@staticmethod
|
||||
def show_warning(parent, title, message, show_cancel=True, confirm_text="确认", cancel_text="取消"):
|
||||
"""显示警告消息对话框"""
|
||||
dialog = UniversalMessageDialog(
|
||||
parent, title, message,
|
||||
UniversalMessageDialog.WARNING,
|
||||
show_cancel, confirm_text, cancel_text
|
||||
)
|
||||
return dialog.exec_()
|
||||
|
||||
@staticmethod
|
||||
def show_error(parent, title, message, show_cancel=False, confirm_text="确认"):
|
||||
"""显示错误消息对话框"""
|
||||
dialog = UniversalMessageDialog(
|
||||
parent, title, message,
|
||||
UniversalMessageDialog.ERROR,
|
||||
show_cancel, confirm_text
|
||||
)
|
||||
return dialog.exec_()
|
||||
|
||||
@staticmethod
|
||||
def show_info(parent, title, message, show_cancel=True, confirm_text="确认", cancel_text="取消"):
|
||||
"""显示信息消息对话框"""
|
||||
dialog = UniversalMessageDialog(
|
||||
parent, title, message,
|
||||
UniversalMessageDialog.INFO,
|
||||
show_cancel, confirm_text, cancel_text
|
||||
)
|
||||
return dialog.exec_()
|
||||
@ -1,4 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": 4,
|
||||
"title": "aasd",
|
||||
"date": "2025-10-17 16:49:10",
|
||||
"type": "empty",
|
||||
"image": "C:\\Users\\29381\\Desktop\\aasd\\aasd.png",
|
||||
"path": "C:\\Users\\29381\\Desktop",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\aasd",
|
||||
"description": "asd",
|
||||
"status": "normal"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "a",
|
||||
"date": "2025-10-17 16:48:59",
|
||||
"type": "imported",
|
||||
"image": "C:\\Users\\29381\\Desktop\\a\\a.png",
|
||||
"path": "C:\\Users\\29381\\Desktop",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\a",
|
||||
"description": "从文件夹 a 导入",
|
||||
"status": "normal"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "ab",
|
||||
@ -15,7 +37,7 @@
|
||||
"title": "XNWX",
|
||||
"date": "2025-10-14 18:05:51",
|
||||
"type": "imported",
|
||||
"image": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\Resources\\ProjectPreviews\\preview_1_1760491477496.png",
|
||||
"image": "C:\\Users\\29381\\Desktop\\MetaCore-startup\\MetaCore\\Resources\\ProjectPreviews\\preview_1_1760628516144.png",
|
||||
"path": "C:\\Users\\29381\\Desktop",
|
||||
"project_dir": "C:\\Users\\29381\\Desktop\\XNWX",
|
||||
"description": "从文件夹 XNWX 导入",
|
||||
|
||||
47
scripts/example_script.py
Normal file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
示例脚本 - 演示如何编写脚本
|
||||
"""
|
||||
|
||||
from core.script_system import ScriptBase
|
||||
|
||||
class ExampleScript(ScriptBase):
|
||||
"""示例脚本类"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.counter = 0
|
||||
self.rotation_speed = 30.0 # 度/秒
|
||||
|
||||
def start(self):
|
||||
"""脚本开始时调用"""
|
||||
self.log("示例脚本开始运行!")
|
||||
self.log(f"挂载到对象: {self.gameObject.getName()}")
|
||||
|
||||
def update(self, dt):
|
||||
"""每帧更新"""
|
||||
self.counter += 1
|
||||
|
||||
# 每60帧输出一次信息
|
||||
if self.counter % 60 == 0:
|
||||
self.log(f"运行了 {self.counter} 帧")
|
||||
|
||||
# 让对象旋转
|
||||
if self.transform:
|
||||
current_h = self.transform.getH()
|
||||
new_h = current_h + self.rotation_speed * dt
|
||||
self.transform.setH(new_h)
|
||||
|
||||
def on_destroy(self):
|
||||
"""脚本销毁时调用"""
|
||||
self.log("示例脚本被销毁")
|
||||
|
||||
def on_enable(self):
|
||||
"""脚本启用时调用"""
|
||||
self.log("示例脚本被启用")
|
||||
|
||||
def on_disable(self):
|
||||
"""脚本禁用时调用"""
|
||||
self.log("示例脚本被禁用")
|
||||
133
tests/test_button_fix.py
Normal file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
测试右上角按钮点击修复
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
sys.path.insert(0, str(project_root / 'MetaCore'))
|
||||
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager, Project
|
||||
from ui.project_card import ProjectCard
|
||||
from ui.styles import StyleSheet
|
||||
|
||||
class TestButtonWindow(QWidget):
|
||||
"""测试按钮修复的窗口"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("右上角按钮修复测试")
|
||||
self.setGeometry(100, 100, 800, 600)
|
||||
self.setStyleSheet(StyleSheet.get_main_stylesheet())
|
||||
|
||||
# 设置深色背景
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #1a1a1a;
|
||||
color: #ffffff;
|
||||
}
|
||||
""" + StyleSheet.get_main_stylesheet())
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化UI"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(40, 40, 40, 40)
|
||||
layout.setSpacing(20)
|
||||
|
||||
# 标题
|
||||
title = QLabel("右上角按钮修复测试")
|
||||
title.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
|
||||
# 说明文字
|
||||
description = QLabel("""
|
||||
测试说明:
|
||||
• 点击右上角的信息按钮应该显示上下文菜单,不应该闪退
|
||||
• 菜单应该包含:刷新预览图、在资源管理器显示、移除项目
|
||||
• 所有菜单项都应该能正常工作
|
||||
""")
|
||||
description.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
layout.addWidget(description)
|
||||
|
||||
# 创建测试卡片
|
||||
self.create_test_cards(layout)
|
||||
|
||||
def create_test_cards(self, layout):
|
||||
"""创建测试卡片"""
|
||||
# 卡片容器
|
||||
cards_widget = QWidget()
|
||||
cards_layout = QHBoxLayout(cards_widget)
|
||||
cards_layout.setSpacing(24)
|
||||
cards_layout.setContentsMargins(20, 20, 20, 20)
|
||||
|
||||
# 创建项目管理器
|
||||
project_manager = ProjectManager()
|
||||
|
||||
# 创建测试项目
|
||||
test_project = Project(
|
||||
id='test_1',
|
||||
title='测试项目',
|
||||
date='2024-10-14 15:30',
|
||||
project_type='smart',
|
||||
status='active',
|
||||
path="/test/path/1",
|
||||
project_dir="/test/path/1",
|
||||
image=None
|
||||
)
|
||||
|
||||
# 创建网格视图卡片
|
||||
grid_card = ProjectCard(test_project, project_manager, view_mode="grid")
|
||||
cards_layout.addWidget(grid_card)
|
||||
|
||||
# 创建列表视图卡片
|
||||
list_card = ProjectCard(test_project, project_manager, view_mode="list")
|
||||
cards_layout.addWidget(list_card)
|
||||
|
||||
cards_layout.addStretch()
|
||||
|
||||
layout.addWidget(cards_widget)
|
||||
layout.addStretch()
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# 设置应用程序属性
|
||||
app.setApplicationName("按钮修复测试")
|
||||
app.setOrganizationName("MetaCore")
|
||||
|
||||
# 创建并显示测试窗口
|
||||
window = TestButtonWindow()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
1
tests/test_corner_debug.py
Normal file
@ -0,0 +1 @@
|
||||
|
||||
218
tests/test_corner_radius.py
Normal file
@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
测试项目卡片5px圆角效果
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
sys.path.insert(0, str(project_root / 'MetaCore'))
|
||||
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager, Project
|
||||
from ui.project_card import ProjectCard
|
||||
from ui.styles import StyleSheet
|
||||
|
||||
class CornerRadiusTestWindow(QWidget):
|
||||
"""测试5px圆角效果的窗口"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("项目卡片5px圆角测试")
|
||||
self.setGeometry(100, 100, 1000, 700)
|
||||
self.setStyleSheet(StyleSheet.get_main_stylesheet())
|
||||
|
||||
# 设置深色背景
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #1a1a1a;
|
||||
color: #ffffff;
|
||||
}
|
||||
""" + StyleSheet.get_main_stylesheet())
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化UI"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(40, 40, 40, 40)
|
||||
layout.setSpacing(20)
|
||||
|
||||
# 标题
|
||||
title = QLabel("项目卡片5px圆角效果测试")
|
||||
title.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
|
||||
# 说明文字
|
||||
description = QLabel("""
|
||||
测试说明:
|
||||
• 所有项目卡片现在都使用5px的圆角
|
||||
• 包括卡片外框、背景图片和列表视图图标
|
||||
• 圆角效果应该统一且美观
|
||||
""")
|
||||
description.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
layout.addWidget(description)
|
||||
|
||||
# 创建测试卡片网格
|
||||
self.create_test_grid(layout)
|
||||
|
||||
def create_test_grid(self, layout):
|
||||
"""创建测试卡片网格"""
|
||||
# 滚动区域
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
scroll_area.setStyleSheet("""
|
||||
QScrollArea {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
""")
|
||||
|
||||
# 网格容器
|
||||
grid_widget = QWidget()
|
||||
grid_layout = QGridLayout(grid_widget)
|
||||
grid_layout.setSpacing(24)
|
||||
grid_layout.setContentsMargins(20, 20, 20, 20)
|
||||
|
||||
# 创建项目管理器
|
||||
project_manager = ProjectManager()
|
||||
|
||||
# 创建测试项目数据
|
||||
test_projects = [
|
||||
{
|
||||
'id': '1',
|
||||
'title': '智能家居系统',
|
||||
'date': '2024-10-14 15:30',
|
||||
'type': 'smart',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
},
|
||||
{
|
||||
'id': '2',
|
||||
'title': 'VR体验项目',
|
||||
'date': '2024-10-13 09:15',
|
||||
'type': 'vr',
|
||||
'status': 'active',
|
||||
'image': str(project_root / 'MetaCore' / 'Resources' / 'ProjectPreviews' / 'preview_6_1760434704537.png') if (project_root / 'MetaCore' / 'Resources' / 'ProjectPreviews' / 'preview_6_1760434704537.png').exists() else None
|
||||
},
|
||||
{
|
||||
'id': '3',
|
||||
'title': '工业控制系统',
|
||||
'date': '2024-10-12 14:20',
|
||||
'type': 'industrial',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
},
|
||||
{
|
||||
'id': '4',
|
||||
'title': '游戏开发',
|
||||
'date': '2024-10-11 11:45',
|
||||
'type': 'game',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
}
|
||||
]
|
||||
|
||||
# 创建网格视图卡片
|
||||
row, col = 0, 0
|
||||
for project_data in test_projects:
|
||||
project = Project(
|
||||
id=project_data['id'],
|
||||
title=project_data['title'],
|
||||
date=project_data['date'],
|
||||
project_type=project_data['type'],
|
||||
status=project_data['status'],
|
||||
path=f"/test/path/{project_data['id']}",
|
||||
project_dir=f"/test/path/{project_data['id']}",
|
||||
image=project_data['image']
|
||||
)
|
||||
|
||||
# 创建项目卡片
|
||||
card = ProjectCard(project, project_manager, view_mode="grid")
|
||||
grid_layout.addWidget(card, row, col)
|
||||
|
||||
col += 1
|
||||
if col >= 3: # 每行3个卡片
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
# 添加列表视图示例
|
||||
list_title = QLabel("列表视图示例(也使用5px圆角):")
|
||||
list_title.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
""")
|
||||
|
||||
# 创建列表视图卡片
|
||||
list_widget = QWidget()
|
||||
list_layout = QVBoxLayout(list_widget)
|
||||
list_layout.setSpacing(8)
|
||||
list_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
for project_data in test_projects[:2]: # 只显示前两个
|
||||
project = Project(
|
||||
id=project_data['id'],
|
||||
title=project_data['title'],
|
||||
date=project_data['date'],
|
||||
project_type=project_data['type'],
|
||||
status=project_data['status'],
|
||||
path=f"/test/path/{project_data['id']}",
|
||||
project_dir=f"/test/path/{project_data['id']}",
|
||||
image=project_data['image']
|
||||
)
|
||||
|
||||
list_card = ProjectCard(project, project_manager, view_mode="list")
|
||||
list_layout.addWidget(list_card)
|
||||
|
||||
# 添加到主网格
|
||||
grid_layout.addWidget(list_title, row + 1, 0, 1, 3)
|
||||
grid_layout.addWidget(list_widget, row + 2, 0, 1, 3)
|
||||
|
||||
scroll_area.setWidget(grid_widget)
|
||||
layout.addWidget(scroll_area)
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# 设置应用程序属性
|
||||
app.setApplicationName("圆角测试")
|
||||
app.setOrganizationName("MetaCore")
|
||||
|
||||
# 创建并显示测试窗口
|
||||
window = CornerRadiusTestWindow()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
43
tests/test_font.py
Normal file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""快速检测Inter字体"""
|
||||
|
||||
def quick_font_check():
|
||||
try:
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtGui import QFontDatabase, QFont, QFontInfo
|
||||
import sys
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
font_db = QFontDatabase()
|
||||
families = font_db.families()
|
||||
|
||||
# 检查Inter
|
||||
inter_families = [f for f in families if 'Inter' in f]
|
||||
|
||||
if inter_families:
|
||||
print("✅ Inter字体已安装:")
|
||||
for family in inter_families:
|
||||
print(f" {family}")
|
||||
|
||||
# 测试实际使用
|
||||
test_font = QFont("Inter", 14)
|
||||
font_info = QFontInfo(test_font)
|
||||
|
||||
print(f"\n实际使用字体: {font_info.family()}")
|
||||
|
||||
if "Inter" in font_info.family():
|
||||
print("✅ Inter字体可正常使用")
|
||||
else:
|
||||
print("❌ Inter字体回退到其他字体")
|
||||
else:
|
||||
print("❌ Inter字体未安装")
|
||||
print("请从 https://fonts.google.com/specimen/Inter 下载安装")
|
||||
|
||||
app.quit()
|
||||
|
||||
except ImportError:
|
||||
print("❌ PyQt5未安装,无法检测字体")
|
||||
|
||||
if __name__ == "__main__":
|
||||
quick_font_check()
|
||||
200
tests/test_optimized_card.py
Normal file
@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
测试优化后的项目卡片组件
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
sys.path.insert(0, str(project_root / 'MetaCore'))
|
||||
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager, Project
|
||||
from ui.project_card import ProjectCard
|
||||
from ui.styles import StyleSheet
|
||||
|
||||
class TestWindow(QWidget):
|
||||
"""测试窗口"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("优化后的项目卡片测试")
|
||||
self.setGeometry(100, 100, 1200, 800)
|
||||
self.setStyleSheet(StyleSheet.get_main_stylesheet())
|
||||
|
||||
# 设置深色背景
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #1a1a1a;
|
||||
color: #ffffff;
|
||||
}
|
||||
""" + StyleSheet.get_main_stylesheet())
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化UI"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(40, 40, 40, 40)
|
||||
layout.setSpacing(20)
|
||||
|
||||
# 标题
|
||||
title = QLabel("项目卡片优化效果展示")
|
||||
title.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
|
||||
# 说明文字
|
||||
description = QLabel("""
|
||||
根据Figma设计优化的项目卡片特性:
|
||||
• 图片作为背景填充整个卡片 (276x191px)
|
||||
• 底部半透明信息覆盖层显示项目详情
|
||||
• 右上角操作按钮悬浮显示
|
||||
• 无图片时使用project_empty_icon作为默认背景
|
||||
• 完全匹配Figma设计规范的颜色和字体
|
||||
""")
|
||||
description.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
""")
|
||||
layout.addWidget(description)
|
||||
|
||||
# 创建项目卡片网格
|
||||
self.create_project_grid(layout)
|
||||
|
||||
def create_project_grid(self, layout):
|
||||
"""创建项目卡片网格"""
|
||||
# 滚动区域
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
scroll_area.setStyleSheet("""
|
||||
QScrollArea {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
""")
|
||||
|
||||
# 网格容器
|
||||
grid_widget = QWidget()
|
||||
grid_layout = QGridLayout(grid_widget)
|
||||
grid_layout.setSpacing(24)
|
||||
grid_layout.setContentsMargins(20, 20, 20, 20)
|
||||
|
||||
# 创建项目管理器
|
||||
project_manager = ProjectManager()
|
||||
|
||||
# 创建测试项目数据
|
||||
test_projects = [
|
||||
{
|
||||
'id': '1',
|
||||
'title': '智能家居控制系统',
|
||||
'date': '2024-10-14 15:30',
|
||||
'type': 'smart',
|
||||
'status': 'active',
|
||||
'image': None # 测试默认图标
|
||||
},
|
||||
{
|
||||
'id': '2',
|
||||
'title': 'VR虚拟现实项目',
|
||||
'date': '2024-10-13 09:15',
|
||||
'type': 'vr',
|
||||
'status': 'active',
|
||||
'image': str(project_root / 'MetaCore' / 'Resources' / 'ProjectPreviews' / 'preview_6_1760434704537.png')
|
||||
},
|
||||
{
|
||||
'id': '3',
|
||||
'title': '工业自动化系统',
|
||||
'date': '2024-10-12 14:20',
|
||||
'type': 'industrial',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
},
|
||||
{
|
||||
'id': '4',
|
||||
'title': '游戏开发项目',
|
||||
'date': '2024-10-11 11:45',
|
||||
'type': 'game',
|
||||
'status': 'pending_delete', # 测试待删除状态
|
||||
'image': None
|
||||
},
|
||||
{
|
||||
'id': '5',
|
||||
'title': 'UI设计项目',
|
||||
'date': '2024-10-10 16:30',
|
||||
'type': 'design',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
},
|
||||
{
|
||||
'id': '6',
|
||||
'title': '数据分析平台',
|
||||
'date': '2024-10-09 13:15',
|
||||
'type': 'smart',
|
||||
'status': 'active',
|
||||
'image': None
|
||||
}
|
||||
]
|
||||
|
||||
# 创建项目卡片
|
||||
row, col = 0, 0
|
||||
for project_data in test_projects:
|
||||
project = Project(
|
||||
id=project_data['id'],
|
||||
title=project_data['title'],
|
||||
date=project_data['date'],
|
||||
project_type=project_data['type'],
|
||||
status=project_data['status'],
|
||||
path=f"/test/path/{project_data['id']}",
|
||||
project_dir=f"/test/path/{project_data['id']}",
|
||||
image=project_data['image']
|
||||
)
|
||||
|
||||
# 创建项目卡片
|
||||
card = ProjectCard(project, project_manager, view_mode="grid")
|
||||
grid_layout.addWidget(card, row, col)
|
||||
|
||||
col += 1
|
||||
if col >= 4: # 每行4个卡片
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
scroll_area.setWidget(grid_widget)
|
||||
layout.addWidget(scroll_area)
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# 设置应用程序属性
|
||||
app.setApplicationName("项目卡片测试")
|
||||
app.setOrganizationName("MetaCore")
|
||||
|
||||
# 创建并显示测试窗口
|
||||
window = TestWindow()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
94
tests/test_simple_corner.py
Normal file
@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
简单的圆角测试
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到Python路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
sys.path.insert(0, str(project_root / 'MetaCore'))
|
||||
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
|
||||
from data.project_manager import ProjectManager, Project
|
||||
from ui.project_card import ProjectCard
|
||||
|
||||
class SimpleCornerTest(QWidget):
|
||||
"""简单圆角测试"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("简单圆角测试")
|
||||
self.setGeometry(100, 100, 600, 400)
|
||||
|
||||
# 设置深色背景
|
||||
self.setStyleSheet("""
|
||||
QWidget {
|
||||
background-color: #2a2a2a;
|
||||
}
|
||||
""")
|
||||
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
"""初始化UI"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(50, 50, 50, 50)
|
||||
layout.setSpacing(30)
|
||||
|
||||
# 标题
|
||||
title = QLabel("项目卡片5px圆角测试")
|
||||
title.setStyleSheet("""
|
||||
QLabel {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
""")
|
||||
title.setAlignment(Qt.AlignCenter)
|
||||
layout.addWidget(title)
|
||||
|
||||
# 创建项目管理器和测试项目
|
||||
project_manager = ProjectManager()
|
||||
test_project = Project(
|
||||
id='test_1',
|
||||
title='测试项目',
|
||||
date='2024-10-14',
|
||||
project_type='smart',
|
||||
status='active',
|
||||
path="/test/path",
|
||||
project_dir="/test/path",
|
||||
image=None
|
||||
)
|
||||
|
||||
# 创建项目卡片
|
||||
card = ProjectCard(test_project, project_manager, view_mode="grid")
|
||||
|
||||
# 居中显示卡片
|
||||
card_container = QWidget()
|
||||
card_layout = QHBoxLayout(card_container)
|
||||
card_layout.addStretch()
|
||||
card_layout.addWidget(card)
|
||||
card_layout.addStretch()
|
||||
|
||||
layout.addWidget(card_container)
|
||||
layout.addStretch()
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
window = SimpleCornerTest()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||