@@ -25,16 +25,49 @@ def __new__(cls, content_widget_class=None, parent: QFrame = None, **kwargs):
2525 # 直接创建新实例,不使用缓存
2626 return super (PageTemplate , cls ).__new__ (cls )
2727
28- def __init__ (self , content_widget_class = None , parent : QFrame = None , ** kwargs ):
28+ def __init__ (
29+ self ,
30+ content_widget_class = None ,
31+ parent : QFrame = None ,
32+ is_preview_mode = False ,
33+ ** kwargs ,
34+ ):
2935 super ().__init__ (parent = parent )
3036
3137 self .ui_created = False
3238 self .content_created = False
3339 self .content_widget_class = content_widget_class
40+ self ._is_preview_mode = is_preview_mode
3441
3542 self .__connectSignalToSlot ()
3643 self .create_ui_components ()
3744
45+ @property
46+ def is_preview_mode (self ):
47+ """获取是否为预览模式"""
48+ return self ._is_preview_mode
49+
50+ @is_preview_mode .setter
51+ def is_preview_mode (self , value ):
52+ """设置是否为预览模式,并在值改变时触发锁定逻辑
53+
54+ Args:
55+ value: 是否为预览模式
56+ """
57+ self ._is_preview_mode = value
58+ # 如果内容组件已经创建完成,立即执行锁定逻辑
59+ if (
60+ self .content_created
61+ and hasattr (self , "contentWidget" )
62+ and self .contentWidget
63+ ):
64+ if value :
65+ self ._lock_all_widgets (self .contentWidget )
66+ else :
67+ # 如果不是预览模式,可以选择解锁所有组件
68+ # 但通常情况下,预览模式是一次性的,所以这里可以不处理
69+ pass
70+
3871 def __connectSignalToSlot (self ):
3972 qconfig .themeChanged .connect (setTheme )
4073
@@ -86,7 +119,7 @@ def _ensure_scroll_area(self):
86119
87120 def create_content (self ):
88121 """后台创建内容组件,避免堵塞进程 - 使用延迟创建的布局"""
89- if not self .ui_created or self . content_created or not self .content_widget_class :
122+ if not self .ui_created or not self .content_widget_class :
90123 return
91124
92125 # 确保滚动区域已创建
@@ -113,10 +146,25 @@ def create_content(self):
113146 content_cls = self .content_widget_class
114147 content_name = getattr (content_cls , "__name__" , str (content_cls ))
115148
116- # 实例化并添加到延迟创建的布局
117- self .contentWidget = content_cls (self )
118- self ._inner_layout_lazy .addWidget (self .contentWidget )
119- self .content_created = True
149+ # 如果内容组件尚未创建,创建并添加到布局
150+ if not self .content_created :
151+ # 实例化并添加到延迟创建的布局
152+ self .contentWidget = content_cls (self )
153+ self ._inner_layout_lazy .addWidget (self .contentWidget )
154+ self .content_created = True
155+
156+ # 如果是预览模式,立即锁定所有组件
157+ if self .is_preview_mode :
158+ self ._lock_all_widgets (self .contentWidget )
159+ else :
160+ # 如果内容组件已经创建,检查是否需要更新锁定状态
161+ if hasattr (self , "contentWidget" ) and self .contentWidget :
162+ if self .is_preview_mode :
163+ self ._lock_all_widgets (self .contentWidget )
164+ else :
165+ # 如果不是预览模式,可以选择解锁所有组件
166+ # 但通常情况下,预览模式是一次性的,所以这里可以不处理
167+ pass
120168
121169 elapsed = time .perf_counter () - start
122170 loguru .logger .debug (f"创建内容组件 { content_name } 耗时: { elapsed :.3f} s" )
@@ -154,7 +202,51 @@ def create_empty_content(self, message="该页面正在开发中,敬请期待
154202 self .inner_layout_personal .addWidget (self .contentWidget )
155203 self .content_created = True
156204
157- @classmethod
205+ def _lock_all_widgets (self , widget ):
206+ """递归锁定所有子组件,包括嵌套的组件和GroupHeaderCardWidget内部的控件
207+
208+ Args:
209+ widget: 要锁定的根组件
210+ """
211+ if widget is None :
212+ return
213+
214+ # 首先锁定当前组件
215+ if hasattr (widget , "setEnabled" ):
216+ widget .setEnabled (False )
217+
218+ # 特殊处理GroupHeaderCardWidget,确保锁定所有addItem或addGroup添加的控件
219+ try :
220+ if hasattr (widget , "widgets" ):
221+ # 如果GroupHeaderCardWidget有widgets属性,锁定所有widgets
222+ for w in widget .widgets :
223+ if isinstance (w , QWidget ):
224+ self ._lock_all_widgets (w )
225+ elif hasattr (widget , "items" ):
226+ # 如果有items属性,锁定所有items
227+ for item in widget .items :
228+ if hasattr (item , "widget" ) and isinstance (item .widget , QWidget ):
229+ self ._lock_all_widgets (item .widget )
230+ elif isinstance (item , QWidget ):
231+ self ._lock_all_widgets (item )
232+ except Exception as e :
233+ logger .debug (f"处理特殊组件时出错: { e } " )
234+
235+ # 然后递归锁定所有直接子组件
236+ for child in widget .children ():
237+ if isinstance (child , QWidget ):
238+ self ._lock_all_widgets (child )
239+
240+ # 最后,检查是否有contentWidget或其他可能包含控件的属性
241+ if hasattr (widget , "contentWidget" ) and isinstance (
242+ widget .contentWidget , QWidget
243+ ):
244+ self ._lock_all_widgets (widget .contentWidget )
245+ if hasattr (widget , "centralWidget" ) and isinstance (
246+ widget .centralWidget , QWidget
247+ ):
248+ self ._lock_all_widgets (widget .centralWidget )
249+
158250 def clear_instance_cache (cls ):
159251 """清除实例缓存,用于强制重新创建页面"""
160252 cls ._instances .clear ()
@@ -186,13 +278,14 @@ class PivotPageTemplate(QFrame):
186278 - 支持按需重新加载
187279 """
188280
189- def __init__ (self , page_config : dict , parent : QFrame = None ):
281+ def __init__ (self , page_config : dict , parent : QFrame = None , is_preview_mode = False ):
190282 """
191283 初始化 Pivot 页面模板
192284
193285 Args:
194286 page_config: 页面配置字典,格式为 {"page_name": "display_name", ...}
195287 parent: 父窗口
288+ is_preview_mode: 是否为预览模式
196289 """
197290 super ().__init__ (parent = parent )
198291
@@ -204,11 +297,33 @@ def __init__(self, page_config: dict, parent: QFrame = None):
204297 self .base_path = "app.view.settings.list_management" # 默认基础路径
205298 self ._page_load_order = [] # 页面加载顺序,用于LRU卸载
206299 self .MAX_CACHED_PAGES = MAX_CACHED_PAGES # 最大同时保留在内存中的页面数量
300+ self ._is_preview_mode = is_preview_mode
207301
208302 self .__connectSignalToSlot ()
209303
210304 QTimer .singleShot (0 , self .create_ui_components )
211305
306+ @property
307+ def is_preview_mode (self ):
308+ """获取是否为预览模式"""
309+ return self ._is_preview_mode
310+
311+ @is_preview_mode .setter
312+ def is_preview_mode (self , value ):
313+ """设置是否为预览模式,并在值改变时触发锁定逻辑
314+
315+ Args:
316+ value: 是否为预览模式
317+ """
318+ self ._is_preview_mode = value
319+ # 如果已经有加载的页面,立即执行锁定逻辑
320+ if hasattr (self , "page_infos" ):
321+ for page_name , info in self .page_infos .items ():
322+ if info .get ("loaded" ) and info .get ("widget" ):
323+ widget = info .get ("widget" )
324+ if widget :
325+ self ._lock_all_widgets (widget )
326+
212327 def __connectSignalToSlot (self ):
213328 """连接信号与槽"""
214329 qconfig .themeChanged .connect (setTheme )
@@ -348,6 +463,10 @@ def _load_page_content(
348463 widget = content_widget_class (self )
349464 widget .setObjectName (page_name )
350465
466+ # 如果是预览模式,锁定所有组件
467+ if self .is_preview_mode :
468+ self ._lock_all_widgets (widget )
469+
351470 # 清除加载提示(使用安全的 takeAt 循环以避免 Qt C++ 对象提前删除问题)
352471 try :
353472 while inner_layout .count () > 0 :
@@ -534,6 +653,51 @@ def get_current_page(self) -> str:
534653 """获取当前页面名称"""
535654 return self .current_page
536655
656+ def _lock_all_widgets (self , widget ):
657+ """递归锁定所有子组件,包括嵌套的组件和GroupHeaderCardWidget内部的控件
658+
659+ Args:
660+ widget: 要锁定的根组件
661+ """
662+ if widget is None :
663+ return
664+
665+ # 首先锁定当前组件
666+ if hasattr (widget , "setEnabled" ):
667+ widget .setEnabled (False )
668+
669+ # 特殊处理GroupHeaderCardWidget,确保锁定所有addItem或addGroup添加的控件
670+ try :
671+ if hasattr (widget , "widgets" ):
672+ # 如果GroupHeaderCardWidget有widgets属性,锁定所有widgets
673+ for w in widget .widgets :
674+ if isinstance (w , QWidget ):
675+ self ._lock_all_widgets (w )
676+ elif hasattr (widget , "items" ):
677+ # 如果有items属性,锁定所有items
678+ for item in widget .items :
679+ if hasattr (item , "widget" ) and isinstance (item .widget , QWidget ):
680+ self ._lock_all_widgets (item .widget )
681+ elif isinstance (item , QWidget ):
682+ self ._lock_all_widgets (item )
683+ except Exception as e :
684+ logger .debug (f"处理特殊组件时出错: { e } " )
685+
686+ # 然后递归锁定所有直接子组件
687+ for child in widget .children ():
688+ if isinstance (child , QWidget ):
689+ self ._lock_all_widgets (child )
690+
691+ # 最后,检查是否有contentWidget或其他可能包含控件的属性
692+ if hasattr (widget , "contentWidget" ) and isinstance (
693+ widget .contentWidget , QWidget
694+ ):
695+ self ._lock_all_widgets (widget .contentWidget )
696+ if hasattr (widget , "centralWidget" ) and isinstance (
697+ widget .centralWidget , QWidget
698+ ):
699+ self ._lock_all_widgets (widget .centralWidget )
700+
537701 def get_page (self , page_name : str ):
538702 """根据页面名称获取页面组件"""
539703 return self .pages .get (page_name , None )
0 commit comments