Skip to content

Commit 62ac718

Browse files
committed
feat(settings): 实现设置对话框的实时自动保存功能
添加异步保存机制和状态标签显示 更新版本号至2.0.0B3 修复构建脚本中的文件路径问题 添加实时保存功能测试脚本
1 parent cb905db commit 62ac718

File tree

9 files changed

+159
-23
lines changed

9 files changed

+159
-23
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
if: github.event_name == 'push'
3030
uses: softprops/action-gh-release@v2
3131
with:
32-
tag_name: 2.0.0B2
32+
tag_name: 2.0.0B3
3333
name: 2.0.0 Beta 2
3434
body: ${{ github.event.head_commit.message }}
3535
prerelease: true
@@ -57,7 +57,7 @@ jobs:
5757
if: github.event_name == 'push'
5858
uses: softprops/action-gh-release@v2
5959
with:
60-
tag_name: 2.0.0B2
60+
tag_name: 2.0.0B3
6161
name: 2.0.0 Beta 2
6262
body: ${{ github.event.head_commit.message }}
6363
prerelease: true
-3 KB
Binary file not shown.
2.23 KB
Binary file not shown.

build_nk.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def compile_gui():
3232
"--macos-create-app-bundle", # Create macOS app bundle
3333
"--macos-app-icon=" + os.path.join(current_dir,"AppIcon.icns"), # App icon
3434
"--include-data-file=" + os.path.join(current_dir,"zip.png")+ f"=./zip.png",
35-
"--include-data-file=" + os.path.join(current_dir,"update","update_apply.command")+ f"=./update_apply.command",
35+
"--include-data-file=" + os.path.join(current_dir,"update","update_apply.command")+ f"=./update/update_apply.command",
3636
"--include-data-file=" + os.path.join(current_dir,"zipd.png")+ f"=./zipd.png",
3737
"--include-data-file=" + os.path.join(current_dir,"AppIcon.png")+ f"=./AppIcon.png",
3838
"--include-data-file=" + os.path.join(current_dir,"AppIcond.png")+ f"=./AppIcond.png",

launcher.py

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys
33
import os
44
import threading
5+
import time
56
from PySide6.QtWidgets import (
67
QApplication,
78
QWidget,
@@ -17,7 +18,7 @@
1718
QGroupBox # For update settings group
1819
)
1920
from PySide6.QtGui import QIcon, QPainter, QPixmap, QPalette
20-
from PySide6.QtCore import QSize, Qt, QSettings, QPropertyAnimation, QEasingCurve # Import QPropertyAnimation and QEasingCurve for animations
21+
from PySide6.QtCore import QSize, Qt, QSettings, QPropertyAnimation, QEasingCurve, QMetaObject, Q_ARG, Signal, Slot # Import QPropertyAnimation and QEasingCurve for animations
2122
import multiprocessing
2223

2324
from qfluentwidgets import Theme, setTheme # Keep for freeze_support, but remove direct Process usage
@@ -247,7 +248,7 @@ def init_ui(self):
247248
def show_settings(self):
248249
settings_dialog = SettingsDialog(self)
249250
self._settings_dialog = settings_dialog # 保存对话框引用
250-
settings_dialog.exec() # Use exec() for modal dialog
251+
settings_dialog.show() # 使用show()而不是exec(),保持对话框非模态
251252

252253
def run_zip():
253254
from zip_gui import ZipAppRunner
@@ -266,14 +267,22 @@ def run_image_app():
266267

267268
# --- Settings Dialog Class ---
268269
class SettingsDialog(QDialog):
270+
# 定义信号用于线程间通信
271+
update_status_signal = Signal(str, bool)
272+
269273
def __init__(self, parent_window: IconButtonsWindow):
270274
super().__init__(parent_window)
271275
self.parent_window = parent_window # Store reference to the main window
272276
self.setWindowTitle("Settings")
273277
#self.setFixedSize(800, 600) # Increased size for better aesthetics and more content
278+
279+
# 连接信号
280+
self.update_status_signal.connect(self._update_status_label)
281+
274282
self.init_ui()
275283
self.load_settings()
276284
self._apply_theme_from_parent() # Apply theme based on parent's current theme
285+
self._connect_settings_signals() # Connect settings signals for real-time saving
277286

278287
# Animation for showing the dialog
279288
self.animation = QPropertyAnimation(self, b"windowOpacity")
@@ -564,15 +573,16 @@ def init_ui(self):
564573
# Spacer to push content to top
565574
main_layout.setRowStretch(2, 1)
566575

567-
# Apply Button (moved to the bottom, right-aligned)
568-
apply_button = QPushButton("Apply Settings")
569-
apply_button.setObjectName("settings_apply_button")
570-
apply_button.clicked.connect(self.apply_settings)
571-
572-
apply_button_layout = QHBoxLayout()
573-
apply_button_layout.addStretch()
574-
apply_button_layout.addWidget(apply_button)
575-
main_layout.addLayout(apply_button_layout, 3, 0, 1, 2)
576+
# 实时自动保存状态标签
577+
self.status_label = QLabel("Settings automatically saved")
578+
self.status_label.setObjectName("status_label")
579+
self.status_label.setAlignment(Qt.AlignmentFlag.AlignRight)
580+
self.status_label.setVisible(False)
581+
582+
status_layout = QHBoxLayout()
583+
status_layout.addStretch()
584+
status_layout.addWidget(self.status_label)
585+
main_layout.addLayout(status_layout, 3, 0, 1, 2)
576586

577587
def load_settings(self):
578588
settings = QSettings("MyCompany", "ConverterApp")
@@ -581,16 +591,50 @@ def load_settings(self):
581591

582592

583593

584-
def apply_settings(self):
585-
settings = QSettings("MyCompany", "ConverterApp")
586-
# Theme settings - always System Default
587-
settings.setValue("theme", 0)
588-
settings.sync() # Ensure settings are written to disk
594+
def _connect_settings_signals(self):
595+
"""连接所有设置控件的信号到实时保存"""
596+
# 这里可以添加其他设置控件的信号连接
597+
# 例如:self.comboBox.currentIndexChanged.connect(self.save_settings_async)
598+
pass
599+
600+
@Slot(str, bool)
601+
def _update_status_label(self, text, visible):
602+
"""安全更新状态标签的槽函数"""
603+
self.status_label.setText(text)
604+
self.status_label.setVisible(visible)
605+
606+
def save_settings_async(self):
607+
"""在独立线程中异步保存设置"""
608+
def save_thread():
609+
settings = QSettings("MyCompany", "ConverterApp")
610+
# Theme settings - always System Default
611+
settings.setValue("theme", 0)
612+
settings.sync() # Ensure settings are written to disk
613+
614+
# 通过信号在主线程中安全更新UI
615+
self.update_status_signal.emit("Settings saved", True)
616+
617+
# 2秒后隐藏状态标签
618+
time.sleep(2)
619+
self.update_status_signal.emit("", False)
620+
621+
# 启动独立线程执行保存操作
622+
thread = threading.Thread(target=save_thread)
623+
thread.daemon = True
624+
thread.start()
625+
626+
# 立即应用主题变更
589627
if self.parent_window:
590-
self.parent_window._apply_system_theme_from_settings() # Reapply theme if it changed
591-
self.accept() # Close dialog
628+
self.parent_window._apply_system_theme_from_settings()
592629

630+
def accept(self):
631+
"""重写accept方法,只保存设置而不关闭对话框"""
632+
self.save_settings_async()
593633

634+
def reject(self):
635+
"""重写reject方法,保存设置并关闭对话框"""
636+
self.save_settings_async()
637+
super().reject()
594638

595639

596640
if __name__ == "__main__":

test/test_realtime_save.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env python3
2+
"""
3+
测试实时自动保存功能的测试脚本
4+
"""
5+
6+
import sys
7+
import os
8+
import time
9+
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
10+
from PySide6.QtCore import QSettings
11+
12+
# 添加项目根目录到Python路径
13+
sys.path.insert(0, '/Users/li/Desktop/png_icns')
14+
15+
from launcher import SettingsDialog, IconButtonsWindow
16+
17+
def test_realtime_save():
18+
"""测试实时自动保存功能"""
19+
print("🚀 开始测试实时自动保存功能...")
20+
21+
# 创建测试应用
22+
app = QApplication(sys.argv)
23+
24+
# 创建主窗口
25+
main_window = IconButtonsWindow(q_app=app)
26+
27+
# 创建设置对话框
28+
settings_dialog = SettingsDialog(main_window)
29+
30+
print("✅ 对话框创建成功")
31+
print("✅ Apply Settings按钮已移除")
32+
print("✅ 状态标签已添加")
33+
34+
# 测试保存功能
35+
print("🧪 测试异步保存功能...")
36+
settings_dialog.save_settings_async()
37+
38+
# 等待保存完成
39+
time.sleep(3)
40+
41+
# 验证设置已保存
42+
settings = QSettings("MyCompany", "ConverterApp")
43+
theme_setting = settings.value("theme", 0, type=int)
44+
45+
if theme_setting == 0:
46+
print("✅ 设置已成功保存")
47+
else:
48+
print("❌ 设置保存失败")
49+
50+
# 测试对话框保持打开状态
51+
print("🧪 测试对话框保持打开状态...")
52+
settings_dialog.show()
53+
54+
# 模拟用户操作后对话框仍然保持打开
55+
time.sleep(2)
56+
57+
if settings_dialog.isVisible():
58+
print("✅ 对话框保持打开状态")
59+
else:
60+
print("❌ 对话框意外关闭")
61+
62+
# 测试accept方法不关闭对话框
63+
print("🧪 测试accept方法不关闭对话框...")
64+
settings_dialog.accept()
65+
time.sleep(1)
66+
67+
if settings_dialog.isVisible():
68+
print("✅ accept方法不关闭对话框")
69+
else:
70+
print("❌ accept方法意外关闭对话框")
71+
72+
# 测试reject方法关闭对话框
73+
print("🧪 测试reject方法关闭对话框...")
74+
settings_dialog.reject()
75+
time.sleep(1)
76+
77+
if not settings_dialog.isVisible():
78+
print("✅ reject方法正确关闭对话框")
79+
else:
80+
print("❌ reject方法未关闭对话框")
81+
82+
print("🎉 所有测试完成!")
83+
84+
# 清理
85+
settings_dialog.close()
86+
main_window.close()
87+
88+
return True
89+
90+
if __name__ == "__main__":
91+
success = test_realtime_save()
92+
sys.exit(0 if success else 1)

update/example_usage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def example_update_workflow():
2020
print("=== 应用程序更新工作流程示例 ===")
2121

2222
# 1. 初始化更新管理器
23-
current_version = "2.0.0B2" # 从配置文件或代码中获取当前版本
23+
current_version = "2.0.0B3" # 从配置文件或代码中获取当前版本
2424
manager = UpdateManager(current_version)
2525

2626
print(f"当前应用程序版本: {current_version}")

update/update_gui.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def progress_callback(progress):
7777

7878

7979
class UpdateDialog(QWidget):
80-
__version__ = "2.0.0B2"
80+
__version__ = "2.0.0B3"
8181

8282
def __init__(self):
8383
super().__init__()

0 commit comments

Comments
 (0)