Files
playwrite/gui/base_tab.py
Misaka 3b7c00377f style: format all Python files with Black
Apply Black formatter to the entire codebase for consistent code style.

Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
2026-02-26 22:44:03 +08:00

133 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
BaseTab - 标签页基类
提供所有标签页共享的通用功能,包括:
- 统一的日志更新方法
- 线程安全的 GUI 操作
- 通用工具方法
"""
import logging
import tkinter as tk
from tkinter import ttk
class BaseTab(ttk.Frame):
"""标签页基类
提供所有标签页共享的通用功能。
子类应继承此类并实现 create_widgets 方法。
"""
def __init__(self, parent, config=None, main_window=None):
"""初始化基类
Args:
parent: 父容器
config: 配置管理器(可选)
main_window: 主窗口引用(可选)
"""
super().__init__(parent)
self.config = config
self.main_window = main_window
def _update_log(self, message: str, level: str = "INFO"):
"""
线程安全的日志更新方法
通过统一的 logging 系统输出日志,自动同时输出到控制台和 GUI。
Args:
message: 日志消息
level: 日志级别 (INFO, SUCCESS, WARNING, ERROR, DEBUG)
Note:
子类需要设置 self.logger 和 self._gui_handler 才能使用此方法。
如果 self.logger 未设置,将使用 logging.getLogger(__name__) 作为后备。
"""
# 获取 logger优先使用实例的 logger否则使用模块 logger
logger = getattr(self, "logger", None) or logging.getLogger(__name__)
# 将自定义级别映射到 logging 级别
level_upper = level.upper()
if level_upper == "SUCCESS":
# SUCCESS 映射到 INFO但在 UI 中仍显示为 SUCCESS
logger.info(message)
else:
# 其他级别直接映射
log_level = getattr(logging, level_upper, logging.INFO)
logger.log(log_level, message)
def _run_on_main_thread(self, callback, *args, **kwargs):
"""在主线程中执行回调函数(线程安全)
Args:
callback: 要执行的回调函数
*args: 位置参数
**kwargs: 关键字参数
Note:
使用 after(0, ...) 确保在主线程中执行。
"""
self.after(0, lambda: callback(*args, **kwargs))
def _is_admin(self) -> bool:
"""检查当前用户是否为管理员
Returns:
bool: 如果是管理员返回 True否则返回 False
Note:
需要 main_window 或 session_manager 支持。
"""
# 尝试从 session_manager 获取
if hasattr(self, "session_manager") and self.session_manager:
return self.session_manager.is_admin()
# 尝试从 main_window 获取
if self.main_window and hasattr(self.main_window, "session_manager"):
return self.main_window.session_manager.is_admin()
return False
def _get_username(self) -> str:
"""获取当前用户名
Returns:
str: 当前用户名,如果无法获取则返回空字符串
Note:
需要 session_manager 支持。
"""
if hasattr(self, "session_manager") and self.session_manager:
return self.session_manager.get_username() or ""
if self.main_window and hasattr(self.main_window, "session_manager"):
return self.main_window.session_manager.get_username() or ""
return ""
def set_busy(self, busy: bool):
"""设置窗口忙碌状态(显示等待光标)
Args:
busy: True 显示等待光标False 恢复正常光标
"""
try:
cursor = "watch" if busy else "arrow"
# 获取顶层窗口
toplevel = self.winfo_toplevel()
if toplevel:
toplevel.config(cursor=cursor)
toplevel.update()
except tk.TclError:
# 窗口可能已被销毁
pass
def reload_config(self):
"""重新加载配置(子类可覆盖此方法)"""
if self.config and hasattr(self.config, "reload"):
self.config.reload()