You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
Tkinter 图形界面模块(白板 GUI
为各模块提供可视化的测试入口:密钥/证书、加密/解密、数字信封、P2P 传输、日志。
仅提供界面与事件占位,核心逻辑由 core/* 实现后接入。
"""
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from typing import Optional
from ui.about_tab import create_about_tab
from ui.context import UIContext
from ui.crypto_tab import create_crypto_tab
from ui.envelope_tab import create_envelope_tab
from ui.keys_tab import create_keys_tab
from ui.p2p_tab import create_p2p_tab
# 尝试懒加载核心模块,未安装依赖时不抛出异常,界面仍可运行
try:
from core import crypto as crypto_mod
except Exception:
crypto_mod = None
try:
from core import protocol as protocol_mod
except Exception:
protocol_mod = None
try:
from core import transfer as transfer_mod
except Exception:
transfer_mod = None
try:
from core import signaling_client as signaling_mod
except Exception:
signaling_mod = None
class MainWindow:
"""主窗口:提供标签页白板 GUI 以便功能联调与演示"""
def __init__(
self,
root: tk.Tk,
*,
default_sig_host: str = "127.0.0.1",
default_sig_port: int = 9999,
default_user: str = "alice",
default_listen_port: int = 8001,
):
self.root = root
self.root.title("SecureFileProject - 白板测试 GUI")
self.root.geometry("900x600")
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(fill=tk.BOTH, expand=True)
self.log_text = tk.Text(self.root, height=6, state=tk.DISABLED)
self.log_text.pack(fill=tk.X, side=tk.BOTTOM)
self.status_var = tk.StringVar(value="就绪")
status_bar = ttk.Label(self.root, textvariable=self.status_var, anchor=tk.W)
status_bar.pack(fill=tk.X, side=tk.BOTTOM)
self.selected_file: Optional[str] = None
self.ctx = UIContext(
log=self._log,
set_status=self._set_status,
choose_file=self._choose_file,
ensure_impl=self._ensure_impl,
get_selected_file=self._get_selected_file,
set_selected_file=self._set_selected_file,
)
create_keys_tab(self.notebook, self.ctx, crypto_mod)
create_crypto_tab(self.notebook, self.ctx, crypto_mod)
create_envelope_tab(self.notebook, self.ctx, protocol_mod)
create_p2p_tab(
self.notebook,
self.ctx,
signaling_mod,
transfer_mod,
default_sig_host=default_sig_host,
default_sig_port=default_sig_port,
default_user=default_user,
default_listen_port=default_listen_port,
)
create_about_tab(self.notebook, self.ctx)
self._log("GUI 初始化完成。若功能未实现,将提示 TODO。")
def _log(self, msg: str):
self.log_text.configure(state=tk.NORMAL)
self.log_text.insert(tk.END, f"[LOG] {msg}\n")
self.log_text.see(tk.END)
self.log_text.configure(state=tk.DISABLED)
def _set_status(self, msg: str):
self.status_var.set(msg)
def _get_selected_file(self) -> Optional[str]:
return self.selected_file
def _set_selected_file(self, path: str):
self.selected_file = path
self._set_status(f"已选择文件:{os.path.basename(path)}")
self._log(f"选择文件: {path}")
def _choose_file(self) -> Optional[str]:
path = filedialog.askopenfilename()
if path:
self._set_selected_file(path)
return path
return None
def _ensure_impl(self, module, feature_name: str) -> bool:
if module is None:
messagebox.showwarning("功能未就绪", f"{feature_name} 依赖模块尚未可用或依赖未安装。请先完成核心实现或安装依赖。")
self._log(f"{feature_name} 未就绪:模块或依赖缺失")
return False
return True
def run_app(
*,
default_sig_host: str = "127.0.0.1",
default_sig_port: int = 9999,
default_user: str = "alice",
default_listen_port: int = 8001,
):
root = tk.Tk()
MainWindow(
root,
default_sig_host=default_sig_host,
default_sig_port=default_sig_port,
default_user=default_user,
default_listen_port=default_listen_port,
)
root.mainloop()