1-
21import sys
32import asyncio
43import 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 ()
0 commit comments