Skip to content

Commit 3c57548

Browse files
committed
feat(gui): 全面革新GUI主题与映射编辑体验
本次提交对图形用户界面(GUI)进行了大规模的重构和美化,并显著增强了映射文件编辑器的功能性和用户体验。 主要改动包括: 1. **全新GUI主题** - 废弃了原有的 `qdarkstyle` 暗色主题。 - 引入了名为 "Otaku-Sync Soft & Fresh Theme" 的全新浅色主题,以薄荷绿为强调色,整体风格更柔和、现代化。 - 全面重写了 `gui/style.qss`,为核心组件提供了精致的样式。 2. **映射编辑器 (`MappingEditorWidget`) 重构** - **界面布局**: 采用 `QSplitter` 将布局分为左右两栏(键列表/值列表),结构更清晰。 - **用户体验**: 为键列表添加了实时搜索框;使用图标按钮替换了文本按钮;优化了“保存”按钮的视觉效果。 - **状态管理**: 实现了“未保存状态(dirty)”跟踪机制,并在主窗口标题栏中以星号(`*`)标示未保存的更改。 - **中文显示**: 将下拉框中的原始文件名替换为更易于理解的中文名称。 3. **主窗口 (`MainWindow`) 功能增强** - **安全退出**: 在关闭应用时,会检查并提示用户保存未保存的更改,有效防止数据丢失。 - **国际化**: 添加了 `QTranslator`,使得Qt内置的标准对话框能够显示为中文。 4. **其他** - 对 `update_brand_latestBeat.py` 脚本进行了初步的功能增强。 - 清理了 `mapping/tag_ggbase.json` 中的无效数据。
1 parent b7cadf4 commit 3c57548

File tree

6 files changed

+311
-111
lines changed

6 files changed

+311
-111
lines changed

gui/main_window.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
import sys
32
import asyncio
43
import threading
@@ -49,7 +48,7 @@ def __init__(self):
4948
self.keyword_input.setPlaceholderText("输入游戏名/关键词...")
5049
self.manual_mode_checkbox = QCheckBox("手动模式")
5150
self.search_button = QPushButton("🔍 开始搜索")
52-
top_layout.addWidget(QLabel("游戏名:"))
51+
top_layout.addWidget(QLabel("请输入游戏名:"))
5352
top_layout.addWidget(self.keyword_input, 1)
5453
top_layout.addWidget(self.manual_mode_checkbox)
5554
top_layout.addWidget(self.search_button)
@@ -87,7 +86,8 @@ def __init__(self):
8786
log_bridge.log_received.connect(self.log_console.appendPlainText)
8887
# Connect the mapping editor's log signal
8988
self.mapping_editor_widget.log_message.connect(self.log_console.appendPlainText)
90-
89+
self.mapping_editor_widget.dirty_status_changed.connect(self.update_window_title)
90+
9191
self.init_shared_context()
9292
self.run_background_tasks()
9393

@@ -98,6 +98,12 @@ def __init__(self):
9898
self.keyword_input.returnPressed.connect(self.start_search_process)
9999
self.batch_tools_widget.script_triggered.connect(self.start_script_execution)
100100

101+
def update_window_title(self, is_dirty):
102+
title = "Otaku Sync - 图形工具"
103+
if is_dirty:
104+
title += " *"
105+
self.setWindowTitle(title)
106+
101107
def init_shared_context(self):
102108
project_logger.system("🔧 正在初始化应用程序级共享上下文...")
103109
self.shared_context = create_shared_context()
@@ -215,10 +221,10 @@ def on_script_completed(self, script_name, success, result):
215221
f.write(name + "\n")
216222
QMessageBox.information(self, "导出成功",
217223
f"已成功导出 {len(result)} 个品牌名到项目根目录下的\n"
218-
f"{output_filename} 文件中。")
224+
f"{output_filename} 文件中。 সন")
219225
except IOError as e:
220226
project_logger.error(f"写入文件 {output_filename} 时出错: {e}")
221-
QMessageBox.critical(self, "文件写入失败", f"无法写入品牌列表到 {output_filename}")
227+
QMessageBox.critical(self, "文件写入失败", f"无法写入品牌列表到 {output_filename} সন")
222228

223229
def set_all_buttons_enabled(self, enabled):
224230
self.search_button.setEnabled(enabled)
@@ -235,7 +241,7 @@ def handle_brand_merge_requested(self, new_brand_name, suggested_brand):
235241
return
236242

237243
dialog = BrandMergeDialog(new_brand_name, suggested_brand, self)
238-
dialog.exec()
244+
dialog.exec()
239245

240246
# The dialog's result property holds the user's choice
241247
worker.set_interaction_response(dialog.result)
@@ -361,6 +367,32 @@ def cleanup_worker(self):
361367
self.script_worker = None
362368

363369
def closeEvent(self, event):
370+
# First, check for unsaved changes in the mapping editor
371+
if self.mapping_editor_widget.is_dirty:
372+
msg_box = QMessageBox(self)
373+
msg_box.setWindowTitle('未保存的更改')
374+
msg_box.setText("映射文件有未保存的更改。您想在退出前保存吗?")
375+
msg_box.setIcon(QMessageBox.Question)
376+
377+
save_button = msg_box.addButton("保存", QMessageBox.AcceptRole)
378+
discard_button = msg_box.addButton("不保存", QMessageBox.DestructiveRole)
379+
cancel_button = msg_box.addButton("取消", QMessageBox.RejectRole)
380+
381+
msg_box.setDefaultButton(cancel_button)
382+
msg_box.exec()
383+
384+
clicked_button = msg_box.clickedButton()
385+
386+
if clicked_button == save_button:
387+
if not self.mapping_editor_widget.save_current_file():
388+
event.ignore() # Ignore exit if save failed
389+
return
390+
elif clicked_button == cancel_button:
391+
event.ignore()
392+
return
393+
# If discard_button is clicked, just proceed
394+
395+
# Then, check for running workers
364396
if (self.game_sync_worker and self.game_sync_worker.isRunning()) or \
365397
(self.script_worker and self.script_worker.isRunning()):
366398
reply = QMessageBox.question(self, '任务正在进行',
@@ -380,4 +412,4 @@ def closeEvent(self, event):
380412
project_logger.error(f"关闭应用时发生错误: {e}")
381413

382414
project_logger.system("程序已安全退出。\n")
383-
event.accept()
415+
event.accept()

gui/style.qss

Lines changed: 84 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,127 @@
1-
/* Otaku-Sync Custom Stylesheet v2 */
1+
/*
2+
* Otaku-Sync Soft & Fresh Theme v6
3+
* A low-contrast, comfortable, mint-accented light theme.
4+
*/
25

36
/* --- General --- */
47
QWidget {
58
font-family: "Segoe UI", "Helvetica Neue", "Arial", sans-serif;
69
font-size: 15px;
7-
/* A slightly lighter base text color for better overall contrast */
8-
color: #E0E0E0;
10+
color: #2c3e50; /* Softer dark gray text */
11+
background-color: #F7F9FC; /* A very light, slightly blueish-gray */
912
}
1013

11-
/* --- Key Widgets --- */
12-
QPushButton, QLineEdit, QComboBox, QPlainTextEdit, QTextEdit {
13-
/* Unified padding and border-radius */
14-
padding: 9px;
15-
border-radius: 5px;
16-
/* A slightly lighter background to distinguish from the window */
17-
background-color: #333;
18-
border: 1px solid #444;
14+
/* --- Key Interactive Widgets --- */
15+
QLineEdit, QComboBox, QPlainTextEdit, QTextEdit, QListWidget {
16+
padding: 10px;
17+
border-radius: 8px;
18+
background-color: #FFFFFF;
19+
border: 1px solid #EAEAEA;
20+
selection-background-color: #1ABC9C; /* Mint Green */
21+
selection-color: #ffffff;
1922
}
2023

21-
/* Provide visual feedback on focus */
22-
QLineEdit:focus, QPlainTextEdit:focus, QTextEdit:focus, QComboBox:focus {
23-
border: 1px solid #0078d4; /* Use accent color for focus */
24+
/* Focus State */
25+
QLineEdit:focus, QPlainTextEdit:focus, QTextEdit:focus, QComboBox:focus, QListWidget:focus {
26+
border: 1px solid #1ABC9C;
2427
}
2528

29+
/* --- Buttons System --- */
30+
31+
/* Base Button Style (for Batch Tools) */
2632
QPushButton {
27-
font-weight: bold;
28-
color: #fff;
29-
background-color: #0078d4; /* Main accent color for primary actions */
33+
font-weight: 600;
34+
padding: 10px 18px;
35+
border-radius: 8px;
36+
color: #4F4F4F;
37+
background-color: #FFFFFF;
38+
border: 1px solid #EAEAEA;
3039
}
3140

3241
QPushButton:hover {
33-
background-color: #008dfa; /* Lighter blue on hover */
42+
color: #1ABC9C;
43+
border-color: #1ABC9C;
44+
}
45+
46+
QPushButton:pressed {
47+
background-color: #F0F0F0;
48+
}
49+
50+
QPushButton:disabled {
51+
color: #BDBDBD;
52+
background-color: #F5F5F5;
53+
border-color: #EAEAEA;
54+
}
55+
56+
/* Primary Action Button (Save) */
57+
QPushButton#PrimaryButton {
58+
color: #ffffff;
59+
font-weight: bold;
60+
background-color: #1ABC9C; /* Mint Green */
61+
border: none;
62+
}
63+
64+
QPushButton#PrimaryButton:hover {
65+
background-color: #1DCCAB; /* Lighter Mint */
66+
}
67+
68+
/* Tool Buttons (Add/Delete) */
69+
QPushButton#AddToolButton, QPushButton#DangerToolButton {
70+
border-radius: 14px; /* Circle */
71+
border: 1px solid #EAEAEA;
72+
background-color: #FFFFFF;
73+
}
74+
75+
QPushButton#AddToolButton:hover, QPushButton#DangerToolButton:hover {
76+
border-color: #1ABC9C;
3477
}
3578

3679
/* --- Tab Widget --- */
3780
QTabWidget::pane {
38-
/* The area where tab content is shown */
39-
border-top: 2px solid #444;
40-
margin-top: -2px; /* Align with the tab bar bottom border */
81+
border: none;
4182
}
4283

4384
QTabBar::tab {
44-
/* Style for individual tabs */
4585
padding: 10px 20px;
4686
background-color: transparent;
47-
color: #aaa; /* Dim unselected tabs */
48-
border: none; /* Remove default borders */
49-
font-weight: bold;
87+
color: #7f8c8d; /* Lighter gray for inactive tabs */
88+
border: none;
89+
font-weight: 600;
90+
border-bottom: 2px solid transparent;
91+
margin-right: 4px;
5092
}
5193

5294
QTabBar::tab:hover {
53-
color: #fff; /* Highlight on hover */
95+
color: #4F4F4F;
5496
}
5597

5698
QTabBar::tab:selected {
57-
/* Style for the active tab */
58-
color: #fff;
59-
background-color: #444; /* Lighter background for the tab itself */
60-
border-bottom: 2px solid #0078d4; /* Accent color line */
99+
color: #1ABC9C;
100+
border-bottom: 2px solid #1ABC9C;
61101
}
62102

63103

64104
/* --- GroupBox --- */
65105
QGroupBox {
66-
margin-top: 12px;
67-
border: 1px solid #444; /* Match other borders */
68-
border-radius: 8px;
69-
padding-top: 25px;
106+
margin-top: 15px;
107+
border: 1px solid #EAEAEA;
108+
border-radius: 12px;
109+
padding: 30px 15px 15px 15px;
110+
background-color: transparent; /* Inherit window background */
70111
}
71112

72113
QGroupBox::title {
73114
subcontrol-origin: margin;
74115
subcontrol-position: top left;
75-
padding: 4px 12px;
76-
margin-left: 10px;
77-
background-color: #0078d4; /* Use accent color for titles */
78-
color: #fff;
79-
border-radius: 5px;
80-
font-weight: bold;
81-
}
82-
83-
/* --- Progress Bar --- */
84-
QProgressBar {
85-
padding: 3px;
86-
border-radius: 5px;
87-
text-align: center;
88-
font-weight: bold;
89-
background-color: #333;
90-
border: 1px solid #444;
116+
padding: 0px 10px;
117+
margin-left: 15px;
118+
color: #4F4F4F;
119+
font-size: 16px;
120+
font-weight: 600;
121+
background-color: #F7F9FC; /* Match window background */
91122
}
92123

93-
QProgressBar::chunk {
94-
background-color: #0078d4;
95-
border-radius: 3px;
124+
/* --- List Widget Alternating Rows --- */
125+
QListWidget[alternatingRowColors="true"]::item:alternate {
126+
background-color: #F7F9FC;
96127
}

0 commit comments

Comments
 (0)