649 lines
24 KiB
Python
649 lines
24 KiB
Python
# dialogs_enhanced.py
|
||
"""增强型对话框 - 智能提示与确认"""
|
||
|
||
import tkinter as tk
|
||
from tkinter import ttk, messagebox
|
||
import logging
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class DependencyCheckDialog:
|
||
"""依赖检查对话框 - 显示系统依赖状态"""
|
||
|
||
def __init__(self, parent):
|
||
self.parent = parent
|
||
self.result = None
|
||
|
||
self.dialog = tk.Toplevel(parent)
|
||
self.dialog.title("系统依赖检查")
|
||
self.dialog.geometry("650x550")
|
||
self.dialog.minsize(600, 400)
|
||
self.dialog.transient(parent)
|
||
self.dialog.grab_set()
|
||
|
||
self._center_window()
|
||
self._create_widgets()
|
||
|
||
def _center_window(self):
|
||
"""居中窗口"""
|
||
self.dialog.update_idletasks()
|
||
width = 650
|
||
height = 550
|
||
x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
|
||
y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
|
||
self.dialog.geometry(f'{width}x{height}+{x}+{y}')
|
||
|
||
def _create_widgets(self):
|
||
"""创建界面"""
|
||
from dependency_checker import get_dependency_checker
|
||
|
||
checker = get_dependency_checker()
|
||
summary = checker.get_summary()
|
||
|
||
# 主框架
|
||
main_frame = ttk.Frame(self.dialog, padding="15")
|
||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 标题
|
||
ttk.Label(main_frame, text="系统依赖状态",
|
||
font=('Arial', 14, 'bold')).pack(anchor=tk.W, pady=(0, 10))
|
||
|
||
# 摘要信息
|
||
summary_frame = ttk.LabelFrame(main_frame, text="摘要", padding="10")
|
||
summary_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
ttk.Label(summary_frame,
|
||
text=f"操作系统: {summary['os_type'].upper()}").pack(anchor=tk.W)
|
||
ttk.Label(summary_frame,
|
||
text=f"总依赖项: {summary['total']} | 已安装: {summary['complete']} | 缺失: {summary['required_missing']}",
|
||
foreground='green' if summary['required_missing'] == 0 else 'red').pack(anchor=tk.W)
|
||
|
||
if summary['required_missing'] > 0:
|
||
ttk.Label(summary_frame,
|
||
text=f"⚠ 有 {summary['required_missing']} 个必需依赖未安装,部分功能可能不可用",
|
||
foreground='red').pack(anchor=tk.W, pady=(5, 0))
|
||
|
||
# 创建 notebook 标签页
|
||
notebook = ttk.Notebook(main_frame)
|
||
notebook.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
|
||
|
||
# 文件系统页
|
||
fs_frame = ttk.Frame(notebook, padding="10")
|
||
notebook.add(fs_frame, text="文件系统")
|
||
self._create_category_frame(fs_frame, summary['categories']['filesystem'])
|
||
|
||
# 分区/LVM/RAID 页
|
||
storage_frame = ttk.Frame(notebook, padding="10")
|
||
notebook.add(storage_frame, text="分区/LVM/RAID")
|
||
self._create_category_frame(storage_frame, {**summary['categories']['partition'],
|
||
**summary['categories']['lvm'],
|
||
**summary['categories']['raid']})
|
||
|
||
# 其他工具页
|
||
other_frame = ttk.Frame(notebook, padding="10")
|
||
notebook.add(other_frame, text="其他工具")
|
||
self._create_category_frame(other_frame, summary['categories']['other'])
|
||
|
||
# 安装指南页
|
||
if summary['install_commands']:
|
||
install_frame = ttk.Frame(notebook, padding="10")
|
||
notebook.add(install_frame, text="安装指南")
|
||
self._create_install_frame(install_frame, summary)
|
||
|
||
# 底部按钮
|
||
btn_frame = ttk.Frame(main_frame)
|
||
btn_frame.pack(fill=tk.X, pady=5)
|
||
|
||
ttk.Button(btn_frame, text="刷新",
|
||
command=self._refresh).pack(side=tk.LEFT, padx=5)
|
||
ttk.Button(btn_frame, text="关闭",
|
||
command=self._on_close).pack(side=tk.RIGHT, padx=5)
|
||
|
||
def _create_category_frame(self, parent, items):
|
||
"""创建分类框架"""
|
||
canvas = tk.Canvas(parent)
|
||
scrollbar = ttk.Scrollbar(parent, orient="vertical", command=canvas.yview)
|
||
scrollable_frame = ttk.Frame(canvas)
|
||
|
||
scrollable_frame.bind(
|
||
"<Configure>",
|
||
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
|
||
)
|
||
|
||
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw", width=580)
|
||
canvas.configure(yscrollcommand=scrollbar.set)
|
||
|
||
canvas.pack(side="left", fill="both", expand=True)
|
||
scrollbar.pack(side="right", fill="y")
|
||
|
||
for key, status in items.items():
|
||
self._create_item_frame(scrollable_frame, status)
|
||
|
||
def _create_item_frame(self, parent, status):
|
||
"""创建单个依赖项框架"""
|
||
frame = ttk.Frame(parent)
|
||
frame.pack(fill=tk.X, pady=3)
|
||
|
||
is_ok = status['is_complete']
|
||
is_optional = status['optional']
|
||
|
||
# 状态图标
|
||
if is_ok:
|
||
icon = "✓"
|
||
color = "green"
|
||
elif is_optional:
|
||
icon = "○"
|
||
color = "orange"
|
||
else:
|
||
icon = "✗"
|
||
color = "red"
|
||
|
||
# 标题行
|
||
header_frame = ttk.Frame(frame)
|
||
header_frame.pack(fill=tk.X)
|
||
|
||
ttk.Label(header_frame, text=icon, foreground=color,
|
||
font=('Arial', 10, 'bold')).pack(side=tk.LEFT)
|
||
ttk.Label(header_frame, text=status['name'],
|
||
font=('Arial', 9, 'bold')).pack(side=tk.LEFT, padx=5)
|
||
|
||
if is_optional:
|
||
ttk.Label(header_frame, text="(可选)",
|
||
foreground="gray").pack(side=tk.LEFT)
|
||
|
||
# 详情
|
||
detail_frame = ttk.Frame(frame)
|
||
detail_frame.pack(fill=tk.X, padx=(20, 0))
|
||
|
||
if is_ok:
|
||
ttk.Label(detail_frame, text=f"已安装命令: {', '.join(status['installed'])}",
|
||
foreground="green").pack(anchor=tk.W)
|
||
else:
|
||
if status['missing']:
|
||
ttk.Label(detail_frame, text=f"缺失命令: {', '.join(status['missing'])}",
|
||
foreground="red").pack(anchor=tk.W)
|
||
ttk.Label(detail_frame, text=f"安装包: {status['package']}",
|
||
foreground="blue").pack(anchor=tk.W)
|
||
|
||
ttk.Separator(frame, orient='horizontal').pack(fill=tk.X, pady=5)
|
||
|
||
def _create_install_frame(self, parent, summary):
|
||
"""创建安装指南框架"""
|
||
# 安装命令
|
||
cmd_frame = ttk.LabelFrame(parent, text="一键安装命令", padding="10")
|
||
cmd_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
os_type = summary['os_type']
|
||
|
||
if os_type == 'centos':
|
||
cmd = "sudo yum install -y " + " ".join(summary['install_commands'].keys())
|
||
elif os_type == 'arch':
|
||
cmd = "sudo pacman -Sy --needed " + " ".join(summary['install_commands'].keys())
|
||
elif os_type == 'ubuntu':
|
||
cmd = "sudo apt-get install -y " + " ".join(summary['install_commands'].keys())
|
||
else:
|
||
cmd = "# 请根据您的发行版安装以下包: " + ", ".join(summary['install_commands'].keys())
|
||
|
||
text_widget = tk.Text(cmd_frame, height=3, wrap=tk.WORD,
|
||
font=('Consolas', 10))
|
||
text_widget.pack(fill=tk.X)
|
||
text_widget.insert('1.0', cmd)
|
||
text_widget.config(state='disabled')
|
||
|
||
# 包详情
|
||
detail_frame = ttk.LabelFrame(parent, text="包详情", padding="10")
|
||
detail_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
canvas = tk.Canvas(detail_frame)
|
||
scrollbar = ttk.Scrollbar(detail_frame, orient="vertical", command=canvas.yview)
|
||
scrollable_frame = ttk.Frame(canvas)
|
||
|
||
scrollable_frame.bind(
|
||
"<Configure>",
|
||
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
|
||
)
|
||
|
||
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw", width=550)
|
||
canvas.configure(yscrollcommand=scrollbar.set)
|
||
|
||
canvas.pack(side="left", fill="both", expand=True)
|
||
scrollbar.pack(side="right", fill="y")
|
||
|
||
for pkg, names in summary['install_commands'].items():
|
||
ttk.Label(scrollable_frame, text=f"• {pkg}",
|
||
font=('Arial', 9, 'bold')).pack(anchor=tk.W)
|
||
ttk.Label(scrollable_frame,
|
||
text=f" 支持: {', '.join(names)}",
|
||
foreground="gray").pack(anchor=tk.W, padx=(15, 0))
|
||
|
||
def _refresh(self):
|
||
"""刷新检查"""
|
||
from dependency_checker import get_dependency_checker
|
||
|
||
# 清除缓存
|
||
checker = get_dependency_checker()
|
||
checker._cache = {}
|
||
|
||
# 重新创建界面
|
||
for widget in self.dialog.winfo_children():
|
||
widget.destroy()
|
||
self._create_widgets()
|
||
|
||
def _on_close(self):
|
||
"""关闭对话框"""
|
||
self.dialog.destroy()
|
||
|
||
def wait_for_result(self):
|
||
"""等待对话框关闭"""
|
||
self.dialog.wait_window()
|
||
|
||
|
||
class EnhancedFormatDialog:
|
||
"""增强格式化对话框 - 显示详细警告信息"""
|
||
|
||
def __init__(self, parent, device_path, device_info):
|
||
self.parent = parent
|
||
self.device_path = device_path
|
||
self.device_info = device_info
|
||
self.result = None
|
||
|
||
self.dialog = tk.Toplevel(parent)
|
||
self.dialog.title(f"格式化确认 - {device_path}")
|
||
self.dialog.geometry("500x500")
|
||
self.dialog.minsize(480, 450)
|
||
self.dialog.transient(parent)
|
||
self.dialog.grab_set()
|
||
|
||
self._center_window()
|
||
self._create_widgets()
|
||
|
||
def _center_window(self):
|
||
"""居中窗口"""
|
||
self.dialog.update_idletasks()
|
||
width = 500
|
||
height = 500
|
||
x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
|
||
y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
|
||
self.dialog.geometry(f'{width}x{height}+{x}+{y}')
|
||
|
||
def _create_widgets(self):
|
||
"""创建界面元素"""
|
||
# 主框架
|
||
main_frame = ttk.Frame(self.dialog, padding="15")
|
||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 警告标题
|
||
warning_frame = ttk.Frame(main_frame)
|
||
warning_frame.pack(fill=tk.X, pady=(0, 15))
|
||
|
||
ttk.Label(warning_frame, text="⚠️ 警告",
|
||
font=('Arial', 16, 'bold'),
|
||
foreground='red').pack(anchor=tk.W)
|
||
|
||
# 设备信息
|
||
info_frame = ttk.LabelFrame(main_frame, text="设备信息", padding="10")
|
||
info_frame.pack(fill=tk.X, pady=(0, 15))
|
||
|
||
ttk.Label(info_frame,
|
||
text=f"设备路径: {self.device_path}",
|
||
font=('Arial', 10, 'bold')).pack(anchor=tk.W, pady=2)
|
||
ttk.Label(info_frame,
|
||
text=f"设备类型: {self.device_info.get('type', 'Unknown')}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=2)
|
||
|
||
# 显示文件系统信息
|
||
fstype = self.device_info.get('fstype', '')
|
||
if fstype:
|
||
ttk.Label(info_frame,
|
||
text=f"当前文件系统: {fstype}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=2)
|
||
|
||
size = self.device_info.get('size', 'Unknown')
|
||
ttk.Label(info_frame,
|
||
text=f"设备大小: {size}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=2)
|
||
|
||
# 危险警告
|
||
danger_frame = ttk.Frame(main_frame)
|
||
danger_frame.pack(fill=tk.X, pady=(0, 15))
|
||
|
||
ttk.Label(danger_frame,
|
||
text="此操作将永久删除设备上的所有数据!",
|
||
font=('Arial', 10, 'bold'),
|
||
foreground='red').pack(anchor=tk.W, pady=5)
|
||
|
||
ttk.Label(danger_frame,
|
||
text="• 所有数据将无法恢复\n• 请确保已备份重要数据",
|
||
foreground='red').pack(anchor=tk.W, pady=5)
|
||
|
||
# 文件系统选择
|
||
fs_frame = ttk.LabelFrame(main_frame, text="选择新文件系统", padding="10")
|
||
fs_frame.pack(fill=tk.X, pady=(0, 15))
|
||
|
||
self.fs_var = tk.StringVar(value="ext4")
|
||
fs_options = ["ext4", "xfs", "fat32", "ntfs"]
|
||
|
||
for fs in fs_options:
|
||
ttk.Radiobutton(fs_frame, text=fs, variable=self.fs_var,
|
||
value=fs).pack(side=tk.LEFT, padx=10)
|
||
|
||
# 按钮
|
||
btn_frame = ttk.Frame(main_frame)
|
||
btn_frame.pack(fill=tk.X, pady=10)
|
||
|
||
ttk.Button(btn_frame, text="取消",
|
||
command=self._on_cancel).pack(side=tk.RIGHT, padx=5)
|
||
ttk.Button(btn_frame, text="确认格式化",
|
||
command=self._on_confirm).pack(side=tk.RIGHT, padx=5)
|
||
|
||
def _on_confirm(self):
|
||
self.result = self.fs_var.get()
|
||
self.dialog.destroy()
|
||
|
||
def _on_cancel(self):
|
||
self.dialog.destroy()
|
||
|
||
def wait_for_result(self):
|
||
self.dialog.wait_window()
|
||
return self.result
|
||
|
||
|
||
class EnhancedRaidDeleteDialog:
|
||
"""增强 RAID 删除对话框 - 显示阵列详情"""
|
||
|
||
def __init__(self, parent, array_path, array_data, member_devices):
|
||
self.parent = parent
|
||
self.array_path = array_path
|
||
self.array_data = array_data
|
||
self.member_devices = member_devices
|
||
self.result = False
|
||
|
||
self.dialog = tk.Toplevel(parent)
|
||
self.dialog.title(f"删除 RAID 阵列 - {array_path}")
|
||
self.dialog.geometry("500x500")
|
||
self.dialog.minsize(450, 400)
|
||
self.dialog.transient(parent)
|
||
self.dialog.grab_set()
|
||
|
||
self._center_window()
|
||
self._create_widgets()
|
||
|
||
def _center_window(self):
|
||
"""居中窗口"""
|
||
self.dialog.update_idletasks()
|
||
width = 500
|
||
height = 500
|
||
x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
|
||
y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
|
||
self.dialog.geometry(f'{width}x{height}+{x}+{y}')
|
||
|
||
def _create_widgets(self):
|
||
"""创建界面元素"""
|
||
# 主框架
|
||
main_frame = ttk.Frame(self.dialog, padding="15")
|
||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 警告标题
|
||
ttk.Label(main_frame, text="⚠️ 确认删除 RAID 阵列",
|
||
font=('Arial', 14, 'bold'),
|
||
foreground='red').pack(anchor=tk.W, pady=(0, 10))
|
||
|
||
# 阵列信息
|
||
info_frame = ttk.LabelFrame(main_frame, text="阵列信息", padding="10")
|
||
info_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
ttk.Label(info_frame, text=f"阵列名称: {self.array_path}",
|
||
font=('Arial', 10, 'bold')).pack(anchor=tk.W, pady=2)
|
||
ttk.Label(info_frame, text=f"阵列类型: RAID {self.array_data.get('level', 'Unknown')}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=2)
|
||
ttk.Label(info_frame, text=f"阵列大小: {self.array_data.get('size', 'Unknown')}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=2)
|
||
|
||
# 成员设备
|
||
member_frame = ttk.LabelFrame(main_frame, text="成员设备", padding="10")
|
||
member_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
|
||
|
||
for dev in self.member_devices:
|
||
ttk.Label(member_frame, text=f"• {dev}",
|
||
font=('Arial', 9)).pack(anchor=tk.W, pady=1)
|
||
|
||
# 危险警告
|
||
danger_frame = ttk.Frame(main_frame)
|
||
danger_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
ttk.Label(danger_frame,
|
||
text="⚠️ 删除操作将:",
|
||
font=('Arial', 10, 'bold'),
|
||
foreground='red').pack(anchor=tk.W, pady=5)
|
||
|
||
warnings = [
|
||
"• 停止并删除 RAID 阵列",
|
||
"• 清除成员设备上的 RAID 超级块",
|
||
"• 从配置文件中移除阵列配置",
|
||
"• 所有数据将永久丢失且无法恢复"
|
||
]
|
||
for warning in warnings:
|
||
ttk.Label(danger_frame, text=warning,
|
||
foreground='red').pack(anchor=tk.W, pady=2)
|
||
|
||
# 按钮
|
||
btn_frame = ttk.Frame(main_frame)
|
||
btn_frame.pack(fill=tk.X, pady=10)
|
||
|
||
ttk.Button(btn_frame, text="取消",
|
||
command=self._on_cancel).pack(side=tk.RIGHT, padx=5)
|
||
ttk.Button(btn_frame, text="确认删除",
|
||
command=self._on_confirm).pack(side=tk.RIGHT, padx=5)
|
||
|
||
def _on_confirm(self):
|
||
self.result = True
|
||
self.dialog.destroy()
|
||
|
||
def _on_cancel(self):
|
||
self.result = False
|
||
self.dialog.destroy()
|
||
|
||
def wait_for_result(self):
|
||
self.dialog.wait_window()
|
||
return self.result
|
||
|
||
|
||
class EnhancedPartitionDialog:
|
||
"""增强分区创建对话框 - 智能分区建议"""
|
||
|
||
def __init__(self, parent, disk_path, total_disk_mib, max_available_mib):
|
||
self.parent = parent
|
||
self.disk_path = disk_path
|
||
self.total_disk_mib = total_disk_mib
|
||
self.max_available_mib = max_available_mib
|
||
self.result = None
|
||
|
||
self.dialog = tk.Toplevel(parent)
|
||
self.dialog.title(f"创建分区 - {disk_path}")
|
||
self.dialog.geometry("550x550")
|
||
self.dialog.minsize(500, 500)
|
||
self.dialog.transient(parent)
|
||
self.dialog.grab_set()
|
||
|
||
self._center_window()
|
||
self._create_widgets()
|
||
|
||
def _center_window(self):
|
||
"""居中窗口"""
|
||
self.dialog.update_idletasks()
|
||
width = 550
|
||
height = 550
|
||
x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
|
||
y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
|
||
self.dialog.geometry(f'{width}x{height}+{x}+{y}')
|
||
|
||
def _create_widgets(self):
|
||
"""创建界面元素"""
|
||
# 主框架
|
||
main_frame = ttk.Frame(self.dialog, padding="15")
|
||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 标题
|
||
ttk.Label(main_frame, text=f"在 {self.disk_path} 上创建分区",
|
||
font=('Arial', 12, 'bold')).pack(anchor=tk.W, pady=(0, 10))
|
||
|
||
# 磁盘信息
|
||
info_frame = ttk.LabelFrame(main_frame, text="磁盘信息", padding="10")
|
||
info_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
total_gb = self.total_disk_mib / 1024
|
||
available_gb = self.max_available_mib / 1024
|
||
|
||
ttk.Label(info_frame,
|
||
text=f"磁盘总大小: {total_gb:.2f} GB").pack(anchor=tk.W)
|
||
ttk.Label(info_frame,
|
||
text=f"最大可用空间: {available_gb:.2f} GB",
|
||
foreground='green' if available_gb > 1 else 'red').pack(anchor=tk.W)
|
||
|
||
# 分区表类型选择
|
||
part_type_frame = ttk.LabelFrame(main_frame, text="分区表类型", padding="10")
|
||
part_type_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
self.part_type_var = tk.StringVar(value="gpt")
|
||
ttk.Radiobutton(part_type_frame, text="GPT (推荐,支持2TB以上磁盘)",
|
||
variable=self.part_type_var,
|
||
value="gpt").pack(anchor=tk.W, pady=2)
|
||
ttk.Radiobutton(part_type_frame, text="MBR (传统格式,兼容性更好)",
|
||
variable=self.part_type_var,
|
||
value="msdos").pack(anchor=tk.W, pady=2)
|
||
|
||
# 大小设置
|
||
size_frame = ttk.LabelFrame(main_frame, text="分区大小", padding="10")
|
||
size_frame.pack(fill=tk.X, pady=(0, 10))
|
||
|
||
# 使用全部空间选项
|
||
self.use_max_var = tk.BooleanVar(value=False)
|
||
ttk.Checkbutton(size_frame,
|
||
text="使用全部可用空间",
|
||
variable=self.use_max_var,
|
||
command=self._toggle_size_input).pack(anchor=tk.W, pady=5)
|
||
|
||
# 大小输入
|
||
size_input_frame = ttk.Frame(size_frame)
|
||
size_input_frame.pack(fill=tk.X, pady=5)
|
||
|
||
ttk.Label(size_input_frame, text="大小 (GB):").pack(side=tk.LEFT)
|
||
|
||
self.size_var = tk.DoubleVar(value=min(available_gb, 100))
|
||
# 使用 tk.Spinbox 兼容旧版 tkinter (Python 3.6)
|
||
try:
|
||
self.size_spin = tk.Spinbox(size_input_frame,
|
||
from_=0.1,
|
||
to=available_gb,
|
||
textvariable=self.size_var,
|
||
width=10,
|
||
increment=0.1)
|
||
except AttributeError:
|
||
# 如果 tk.Spinbox 也不可用,使用 Entry 替代
|
||
self.size_spin = tk.Entry(size_input_frame,
|
||
textvariable=self.size_var,
|
||
width=10)
|
||
self.size_spin.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 滑块
|
||
self.size_slider = ttk.Scale(size_frame,
|
||
from_=0,
|
||
to=available_gb,
|
||
orient=tk.HORIZONTAL,
|
||
length=400)
|
||
self.size_slider.set(min(available_gb, 100))
|
||
self.size_slider.pack(fill=tk.X, pady=5)
|
||
|
||
# 百分比显示
|
||
self.percent_var = tk.StringVar(value="0%")
|
||
ttk.Label(size_frame, textvariable=self.percent_var,
|
||
foreground='gray').pack(anchor=tk.E)
|
||
|
||
# 绑定更新事件
|
||
self.size_var.trace('w', self._on_size_change)
|
||
self.size_slider.configure(command=self._on_slider_change)
|
||
|
||
# 初始状态
|
||
self._toggle_size_input()
|
||
|
||
# 按钮
|
||
btn_frame = ttk.Frame(main_frame)
|
||
btn_frame.pack(fill=tk.X, pady=10)
|
||
|
||
ttk.Button(btn_frame, text="取消",
|
||
command=self._on_cancel).pack(side=tk.RIGHT, padx=5)
|
||
ttk.Button(btn_frame, text="确认创建",
|
||
command=self._on_confirm).pack(side=tk.RIGHT, padx=5)
|
||
|
||
def _on_size_change(self, *args):
|
||
"""大小输入变化时更新滑块"""
|
||
try:
|
||
value = self.size_var.get()
|
||
self.size_slider.set(value)
|
||
self._update_percent(value)
|
||
except:
|
||
pass
|
||
|
||
def _on_slider_change(self, value):
|
||
"""滑块变化时更新输入"""
|
||
try:
|
||
self.size_var.set(float(value))
|
||
self._update_percent(float(value))
|
||
except:
|
||
pass
|
||
|
||
def _update_percent(self, value):
|
||
"""更新百分比显示"""
|
||
if self.max_available_mib > 0:
|
||
percent = (value * 1024 / self.max_available_mib) * 100
|
||
self.percent_var.set(f"{percent:.1f}%")
|
||
|
||
def _toggle_size_input(self):
|
||
"""切换大小输入状态"""
|
||
if self.use_max_var.get():
|
||
# ttk.Scale 在某些旧版本 Tkinter 中不支持 state 选项
|
||
try:
|
||
self.size_slider.configure(state=tk.DISABLED)
|
||
except tk.TclError:
|
||
pass # 忽略不支持的选项
|
||
self.size_spin.configure(state=tk.DISABLED)
|
||
max_gb = self.max_available_mib / 1024
|
||
self.size_var.set(max_gb)
|
||
self._update_percent(max_gb)
|
||
else:
|
||
try:
|
||
self.size_slider.configure(state=tk.NORMAL)
|
||
except tk.TclError:
|
||
pass # 忽略不支持的选项
|
||
self.size_spin.configure(state=tk.NORMAL)
|
||
|
||
def _on_confirm(self):
|
||
size_gb = self.size_var.get()
|
||
use_max_space = self.use_max_var.get()
|
||
|
||
if not use_max_space and size_gb <= 0:
|
||
messagebox.showwarning("输入错误", "分区大小必须大于0。")
|
||
return
|
||
|
||
max_gb = self.max_available_mib / 1024
|
||
if not use_max_space and size_gb > max_gb:
|
||
messagebox.showwarning("输入错误", "分区大小不能超过最大可用空间。")
|
||
return
|
||
|
||
self.result = {
|
||
'disk_path': self.disk_path,
|
||
'partition_table_type': self.part_type_var.get(),
|
||
'size_gb': size_gb,
|
||
'use_max_space': use_max_space,
|
||
'total_disk_mib': self.total_disk_mib
|
||
}
|
||
self.dialog.destroy()
|
||
|
||
def _on_cancel(self):
|
||
self.dialog.destroy()
|
||
|
||
def wait_for_result(self):
|
||
self.dialog.wait_window()
|
||
return self.result
|