243 lines
9.4 KiB
Python
243 lines
9.4 KiB
Python
"""
|
|
样式管理GUI模块
|
|
|
|
提供样式选择、预览、编辑的图形界面。
|
|
"""
|
|
|
|
import tkinter as tk
|
|
from tkinter import ttk, filedialog, messagebox, simpledialog
|
|
from typing import Optional
|
|
|
|
from style_manager import style_manager, DocumentStyle
|
|
from config import config as config_manager
|
|
from advanced_style_editor import open_advanced_editor
|
|
|
|
|
|
def create_style_tab(parent):
|
|
"""创建样式管理选项卡"""
|
|
style_frame = ttk.Frame(parent)
|
|
|
|
# 标题
|
|
ttk.Label(style_frame, text='文章排版样式管理', font=('', 12, 'bold')).pack(anchor='w', padx=10, pady=(10, 5))
|
|
ttk.Separator(style_frame, orient='horizontal').pack(fill='x', padx=10, pady=5)
|
|
|
|
# 样式选择区域
|
|
selection_frame = ttk.LabelFrame(style_frame, text='样式选择', padding="10")
|
|
selection_frame.pack(fill='x', padx=10, pady=5)
|
|
|
|
# 当前样式
|
|
current_frame = ttk.Frame(selection_frame)
|
|
current_frame.pack(fill='x', pady=2)
|
|
ttk.Label(current_frame, text='当前样式:', width=12).pack(side='left')
|
|
|
|
style_var = tk.StringVar(value=config_manager.current_style)
|
|
style_combo = ttk.Combobox(current_frame, textvariable=style_var,
|
|
values=style_manager.get_style_names(),
|
|
state='readonly', width=25)
|
|
style_combo.pack(side='left', padx=(0, 10))
|
|
|
|
def on_style_change(*args):
|
|
config_manager.current_style = style_var.get()
|
|
from config import CONFIG_FILE_PATH
|
|
config_manager.save_to_file(CONFIG_FILE_PATH)
|
|
_update_style_info()
|
|
|
|
style_var.trace('w', on_style_change)
|
|
|
|
ttk.Button(current_frame, text='预览', command=lambda: _preview_style(style_var.get(), parent)).pack(side='left', padx=5)
|
|
|
|
# 样式信息显示
|
|
info_frame = ttk.Frame(selection_frame)
|
|
info_frame.pack(fill='x', pady=(5, 0))
|
|
|
|
info_text = tk.Text(info_frame, height=3, wrap=tk.WORD, state='disabled')
|
|
info_text.pack(fill='x')
|
|
|
|
def _update_style_info():
|
|
"""更新样式信息显示"""
|
|
style = style_manager.get_style(style_var.get())
|
|
if style:
|
|
info = f"描述: {style.description}\n作者: {style.author} 版本: {style.version}\n"
|
|
info += f"正文字体: {style.body_font.name if style.body_font else '默认'} {style.body_font.size if style.body_font else 12}pt"
|
|
|
|
info_text.config(state='normal')
|
|
info_text.delete(1.0, tk.END)
|
|
info_text.insert(1.0, info)
|
|
info_text.config(state='disabled')
|
|
|
|
# 样式管理区域
|
|
management_frame = ttk.LabelFrame(style_frame, text='样式管理', padding="10")
|
|
management_frame.pack(fill='x', padx=10, pady=5)
|
|
|
|
button_frame = ttk.Frame(management_frame)
|
|
button_frame.pack(fill='x')
|
|
|
|
def _create_new_style():
|
|
"""创建新样式"""
|
|
name = simpledialog.askstring("新建样式", "请输入样式名称:")
|
|
if name and name not in style_manager.get_style_names():
|
|
new_style = DocumentStyle(name=name, description="自定义样式", author="用户")
|
|
if style_manager.create_custom_style(new_style):
|
|
style_combo['values'] = style_manager.get_style_names()
|
|
messagebox.showinfo("成功", f"样式 '{name}' 创建成功")
|
|
else:
|
|
messagebox.showerror("错误", "创建样式失败")
|
|
elif name:
|
|
messagebox.showerror("错误", "样式名称已存在")
|
|
|
|
def _duplicate_style():
|
|
"""复制样式"""
|
|
current_name = style_var.get()
|
|
if current_name:
|
|
new_name = simpledialog.askstring("复制样式", f"基于 '{current_name}' 创建新样式,请输入新名称:")
|
|
if new_name and new_name not in style_manager.get_style_names():
|
|
if style_manager.duplicate_style(current_name, new_name):
|
|
style_combo['values'] = style_manager.get_style_names()
|
|
messagebox.showinfo("成功", f"样式 '{new_name}' 创建成功")
|
|
else:
|
|
messagebox.showerror("错误", "复制样式失败")
|
|
elif new_name:
|
|
messagebox.showerror("错误", "样式名称已存在")
|
|
|
|
def _edit_style_advanced():
|
|
"""高级样式编辑"""
|
|
current_name = style_var.get()
|
|
if not current_name:
|
|
messagebox.showwarning("警告", "请先选择一个样式")
|
|
return
|
|
|
|
# 创建高级编辑窗口
|
|
try:
|
|
edit_window = open_advanced_editor(parent, current_name)
|
|
if edit_window:
|
|
def on_window_close():
|
|
# 更新样式列表
|
|
style_combo['values'] = style_manager.get_style_names()
|
|
_update_style_info()
|
|
|
|
# 等待窗口关闭后更新
|
|
style_frame.after(1000, on_window_close)
|
|
except Exception as e:
|
|
messagebox.showerror("错误", f"打开高级编辑器失败: {str(e)}")
|
|
|
|
def _delete_style():
|
|
"""删除样式"""
|
|
current_name = style_var.get()
|
|
if current_name and current_name not in style_manager.builtin_styles:
|
|
if messagebox.askyesno("确认删除", f"确定要删除样式 '{current_name}' 吗?"):
|
|
if style_manager.delete_custom_style(current_name):
|
|
style_combo['values'] = style_manager.get_style_names()
|
|
style_var.set(style_manager.get_style_names()[0] if style_manager.get_style_names() else "")
|
|
messagebox.showinfo("成功", "样式删除成功")
|
|
else:
|
|
messagebox.showerror("错误", "删除样式失败")
|
|
else:
|
|
messagebox.showerror("错误", "无法删除内置样式")
|
|
|
|
def _export_style():
|
|
"""导出样式"""
|
|
current_name = style_var.get()
|
|
if current_name:
|
|
file_path = filedialog.asksaveasfilename(
|
|
title="导出样式",
|
|
defaultextension=".json",
|
|
filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
|
|
)
|
|
if file_path:
|
|
if style_manager.export_style(current_name, file_path):
|
|
messagebox.showinfo("成功", "样式导出成功")
|
|
else:
|
|
messagebox.showerror("错误", "导出样式失败")
|
|
|
|
def _import_style():
|
|
"""导入样式"""
|
|
file_path = filedialog.askopenfilename(
|
|
title="导入样式",
|
|
filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
|
|
)
|
|
if file_path:
|
|
style_name = style_manager.import_style(file_path)
|
|
if style_name:
|
|
style_combo['values'] = style_manager.get_style_names()
|
|
messagebox.showinfo("成功", f"样式 '{style_name}' 导入成功")
|
|
else:
|
|
messagebox.showerror("错误", "导入样式失败")
|
|
|
|
# 管理按钮
|
|
ttk.Button(button_frame, text='新建', command=_create_new_style).pack(side='left', padx=5)
|
|
ttk.Button(button_frame, text='复制', command=_duplicate_style).pack(side='left', padx=5)
|
|
ttk.Button(button_frame, text='高级编辑', command=_edit_style_advanced).pack(side='left', padx=5)
|
|
ttk.Button(button_frame, text='删除', command=_delete_style).pack(side='left', padx=5)
|
|
ttk.Button(button_frame, text='导出', command=_export_style).pack(side='left', padx=5)
|
|
ttk.Button(button_frame, text='导入', command=_import_style).pack(side='left', padx=5)
|
|
|
|
# 初始化信息显示
|
|
_update_style_info()
|
|
|
|
return style_frame
|
|
|
|
|
|
def _preview_style(style_name: str, parent):
|
|
"""预览样式"""
|
|
style = style_manager.get_style(style_name)
|
|
if not style:
|
|
return
|
|
|
|
preview_text = f"""样式预览: {style.name}
|
|
|
|
正文示例:
|
|
这是正文内容,使用 {style.body_font.name if style.body_font else '默认字体'} 字体,
|
|
大小为 {style.body_font.size if style.body_font else 12} 磅,
|
|
行距为 {style.body_paragraph.line_spacing if style.body_paragraph else 1.5} 倍。
|
|
|
|
# 一级标题示例
|
|
## 二级标题示例
|
|
### 三级标题示例
|
|
|
|
这是一个包含**粗体**和*斜体*的段落。
|
|
|
|
> 这是引用块的示例内容。
|
|
|
|
`这是行内代码`的示例。
|
|
|
|
- 无序列表项目1
|
|
- 无序列表项目2
|
|
|
|
1. 有序列表项目1
|
|
2. 有序列表项目2
|
|
"""
|
|
|
|
# 创建预览窗口
|
|
preview_window = tk.Toplevel(parent)
|
|
preview_window.title(f'样式预览 - {style_name}')
|
|
preview_window.geometry('500x400')
|
|
preview_window.transient(parent)
|
|
|
|
text_widget = tk.Text(preview_window, wrap=tk.WORD, padx=10, pady=10)
|
|
text_widget.pack(fill='both', expand=True, padx=10, pady=10)
|
|
text_widget.insert(1.0, preview_text)
|
|
text_widget.config(state='disabled')
|
|
|
|
ttk.Button(preview_window, text='关闭',
|
|
command=preview_window.destroy).pack(pady=10)
|
|
|
|
|
|
# 兼容性函数
|
|
def show_style_manager(parent=None):
|
|
"""显示样式管理器窗口"""
|
|
if parent is None:
|
|
root = tk.Tk()
|
|
root.withdraw()
|
|
parent = root
|
|
|
|
window = tk.Toplevel(parent)
|
|
window.title('样式管理器')
|
|
window.geometry('600x500')
|
|
window.transient(parent)
|
|
window.grab_set()
|
|
|
|
style_tab = create_style_tab(window)
|
|
style_tab.pack(fill='both', expand=True, padx=10, pady=10)
|
|
|
|
ttk.Button(window, text='关闭', command=window.destroy).pack(pady=10)
|