|
|
|
|
@ -73,139 +73,145 @@ class WordRibbon(QFrame):
|
|
|
|
|
main_layout.addWidget(self.ribbon_area)
|
|
|
|
|
self.setLayout(main_layout)
|
|
|
|
|
|
|
|
|
|
def add_separator(self):
|
|
|
|
|
"""
|
|
|
|
|
在 Ribbon 主布局里添加一个高度自动适配的竖向分隔线
|
|
|
|
|
"""
|
|
|
|
|
line = QFrame()
|
|
|
|
|
line.setFrameShape(QFrame.VLine)
|
|
|
|
|
line.setFrameShadow(QFrame.Plain)
|
|
|
|
|
line.setStyleSheet("""
|
|
|
|
|
QFrame {
|
|
|
|
|
background-color: #d0d7de;
|
|
|
|
|
width: 1px;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
line.setFixedWidth(1)
|
|
|
|
|
|
|
|
|
|
# Ribbon 区域高度会变,这玩意就自动跟着撑满
|
|
|
|
|
line.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
|
|
|
|
|
|
|
|
|
|
self.ribbon_layout.addWidget(line)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_ribbon_group(self, title, is_special_group=False):
|
|
|
|
|
"""
|
|
|
|
|
统一的创建 group 的方法。
|
|
|
|
|
- 如果 is_special_group 为 True:返回单个 group(与原来某些位置的用法一致)。
|
|
|
|
|
- 否则:返回 (group, content_layout) 以便直接往 content_layout 塞控件(与 setup_home_tab 的用法一致)。
|
|
|
|
|
"""
|
|
|
|
|
# 对于“特殊组”(天气、每日一言)我们使用 QGroupBox 保持原样
|
|
|
|
|
if is_special_group:
|
|
|
|
|
group = QGroupBox(title)
|
|
|
|
|
# 应用主题样式 hook
|
|
|
|
|
theme_manager.theme_changed.connect(lambda: self._update_group_style(group))
|
|
|
|
|
self._update_group_style(group)
|
|
|
|
|
# 给特殊组留一些最小宽度,便于布局(可由调用方调整)
|
|
|
|
|
group.setMinimumWidth(100)
|
|
|
|
|
return group
|
|
|
|
|
|
|
|
|
|
# 常规组:使用 QFrame + 内部 content layout + 底部标题(保留标题在下的视觉)
|
|
|
|
|
group = QFrame()
|
|
|
|
|
group.setStyleSheet("""
|
|
|
|
|
QFrame { border: none; }
|
|
|
|
|
QLabel { font-size: 11px; color: #555; }
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
outer_layout = QVBoxLayout(group)
|
|
|
|
|
outer_layout.setContentsMargins(3, 3, 3, 3)
|
|
|
|
|
outer_layout.setSpacing(2)
|
|
|
|
|
|
|
|
|
|
content_widget = QWidget()
|
|
|
|
|
content_layout = QHBoxLayout(content_widget)
|
|
|
|
|
content_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
content_layout.setSpacing(5)
|
|
|
|
|
|
|
|
|
|
title_label = QLabel(title)
|
|
|
|
|
title_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
outer_layout.addWidget(content_widget)
|
|
|
|
|
outer_layout.addWidget(title_label)
|
|
|
|
|
|
|
|
|
|
group.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
|
|
|
|
return group, content_layout
|
|
|
|
|
|
|
|
|
|
def setup_home_tab(self, layout):
|
|
|
|
|
"""设置开始标签的功能区内容"""
|
|
|
|
|
|
|
|
|
|
# 字体组
|
|
|
|
|
font_group = self.create_ribbon_group("字体")
|
|
|
|
|
|
|
|
|
|
# 字体选择
|
|
|
|
|
font_layout = QHBoxLayout()
|
|
|
|
|
"""设置开始标签 Ribbon —— 保持原有变量/槽名不变,只改布局实现"""
|
|
|
|
|
|
|
|
|
|
# ---------- 字体组 ----------
|
|
|
|
|
font_group, font_layout = self.create_ribbon_group("字体")
|
|
|
|
|
|
|
|
|
|
self.font_combo = QFontComboBox()
|
|
|
|
|
self.font_combo.setFixedWidth(120)
|
|
|
|
|
self.font_combo.currentFontChanged.connect(self.on_font_changed)
|
|
|
|
|
|
|
|
|
|
self.font_size_combo = QComboBox()
|
|
|
|
|
self.font_size_combo.addItems(['8', '9', '10', '11', '12', '14', '16', '18', '20', '22', '24', '26', '28', '36', '48', '72'])
|
|
|
|
|
self.font_size_combo.addItems(
|
|
|
|
|
['8','9','10','11','12','14','16','18','20','22','24','26','28','36','48','72']
|
|
|
|
|
)
|
|
|
|
|
self.font_size_combo.setFixedWidth(70)
|
|
|
|
|
self.font_size_combo.setCurrentText('12')
|
|
|
|
|
self.font_size_combo.currentTextChanged.connect(self.on_font_size_changed)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
font_layout.addWidget(self.font_combo)
|
|
|
|
|
font_layout.addWidget(self.font_size_combo)
|
|
|
|
|
|
|
|
|
|
# 字体样式按钮
|
|
|
|
|
font_style_layout = QHBoxLayout()
|
|
|
|
|
|
|
|
|
|
self.bold_btn = self.create_toggle_button("B", "bold")
|
|
|
|
|
self.bold_btn.clicked.connect(self.on_bold_clicked)
|
|
|
|
|
self.italic_btn = self.create_toggle_button("I", "italic")
|
|
|
|
|
self.italic_btn.clicked.connect(self.on_italic_clicked)
|
|
|
|
|
self.underline_btn = self.create_toggle_button("U", "underline")
|
|
|
|
|
self.underline_btn.clicked.connect(self.on_underline_clicked)
|
|
|
|
|
|
|
|
|
|
# 字体颜色按钮
|
|
|
|
|
self.color_btn = self.create_color_button("A", "color")
|
|
|
|
|
self.color_btn.clicked.connect(self.on_color_clicked)
|
|
|
|
|
|
|
|
|
|
font_style_layout.addWidget(self.bold_btn)
|
|
|
|
|
font_style_layout.addWidget(self.italic_btn)
|
|
|
|
|
font_style_layout.addWidget(self.underline_btn)
|
|
|
|
|
font_style_layout.addWidget(self.color_btn)
|
|
|
|
|
|
|
|
|
|
font_main_layout = QVBoxLayout()
|
|
|
|
|
font_main_layout.addLayout(font_layout)
|
|
|
|
|
font_main_layout.addLayout(font_style_layout)
|
|
|
|
|
|
|
|
|
|
font_group.setLayout(font_main_layout)
|
|
|
|
|
|
|
|
|
|
font_layout.addWidget(self.bold_btn)
|
|
|
|
|
font_layout.addWidget(self.italic_btn)
|
|
|
|
|
font_layout.addWidget(self.underline_btn)
|
|
|
|
|
font_layout.addWidget(self.color_btn)
|
|
|
|
|
font_layout.addStretch()
|
|
|
|
|
layout.addWidget(font_group)
|
|
|
|
|
|
|
|
|
|
# 段落组
|
|
|
|
|
paragraph_group = self.create_ribbon_group("段落")
|
|
|
|
|
paragraph_group.setFixedWidth(320) # 增加宽度以适应更宽的按钮
|
|
|
|
|
|
|
|
|
|
# 对齐方式
|
|
|
|
|
align_layout = QHBoxLayout()
|
|
|
|
|
self.add_separator()
|
|
|
|
|
# ---------- 段落组 ----------
|
|
|
|
|
paragraph_group, paragraph_layout = self.create_ribbon_group("段落")
|
|
|
|
|
self.align_left_btn = self.create_toggle_button("左对齐", "align_left")
|
|
|
|
|
self.align_center_btn = self.create_toggle_button("居中", "align_center")
|
|
|
|
|
self.align_right_btn = self.create_toggle_button("右对齐", "align_right")
|
|
|
|
|
self.align_justify_btn = self.create_toggle_button("两端对齐", "align_justify")
|
|
|
|
|
|
|
|
|
|
align_layout.addWidget(self.align_left_btn)
|
|
|
|
|
align_layout.addWidget(self.align_center_btn)
|
|
|
|
|
align_layout.addWidget(self.align_right_btn)
|
|
|
|
|
align_layout.addWidget(self.align_justify_btn)
|
|
|
|
|
|
|
|
|
|
paragraph_layout = QVBoxLayout()
|
|
|
|
|
paragraph_layout.addLayout(align_layout)
|
|
|
|
|
|
|
|
|
|
paragraph_group.setLayout(paragraph_layout)
|
|
|
|
|
|
|
|
|
|
paragraph_layout.addWidget(self.align_left_btn)
|
|
|
|
|
paragraph_layout.addWidget(self.align_center_btn)
|
|
|
|
|
paragraph_layout.addWidget(self.align_right_btn)
|
|
|
|
|
paragraph_layout.addWidget(self.align_justify_btn)
|
|
|
|
|
paragraph_layout.addStretch()
|
|
|
|
|
layout.addWidget(paragraph_group)
|
|
|
|
|
self.add_separator()
|
|
|
|
|
|
|
|
|
|
# ---------- 样式组(单行水平排列) ----------
|
|
|
|
|
self.init_style_preview_group()
|
|
|
|
|
self.add_separator()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 样式组
|
|
|
|
|
styles_group = self.create_ribbon_group("样式")
|
|
|
|
|
styles_layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 创建标题样式按钮
|
|
|
|
|
title_buttons_layout = QHBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 一级标题按钮
|
|
|
|
|
self.heading1_btn = self.create_style_button("标题1")
|
|
|
|
|
self.heading1_btn.clicked.connect(self.on_heading1_clicked)
|
|
|
|
|
title_buttons_layout.addWidget(self.heading1_btn)
|
|
|
|
|
|
|
|
|
|
# 二级标题按钮
|
|
|
|
|
self.heading2_btn = self.create_style_button("标题2")
|
|
|
|
|
self.heading2_btn.clicked.connect(self.on_heading2_clicked)
|
|
|
|
|
title_buttons_layout.addWidget(self.heading2_btn)
|
|
|
|
|
|
|
|
|
|
# 三级标题按钮
|
|
|
|
|
self.heading3_btn = self.create_style_button("标题3")
|
|
|
|
|
self.heading3_btn.clicked.connect(self.on_heading3_clicked)
|
|
|
|
|
title_buttons_layout.addWidget(self.heading3_btn)
|
|
|
|
|
|
|
|
|
|
styles_layout.addLayout(title_buttons_layout)
|
|
|
|
|
|
|
|
|
|
# 第二行样式按钮
|
|
|
|
|
style_buttons_layout = QHBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 四级标题按钮
|
|
|
|
|
self.heading4_btn = self.create_style_button("标题4")
|
|
|
|
|
self.heading4_btn.clicked.connect(self.on_heading4_clicked)
|
|
|
|
|
style_buttons_layout.addWidget(self.heading4_btn)
|
|
|
|
|
|
|
|
|
|
# 正文按钮
|
|
|
|
|
self.body_text_btn = self.create_style_button("正文")
|
|
|
|
|
self.body_text_btn.clicked.connect(self.on_body_text_clicked)
|
|
|
|
|
style_buttons_layout.addWidget(self.body_text_btn)
|
|
|
|
|
|
|
|
|
|
style_buttons_layout.addStretch()
|
|
|
|
|
styles_layout.addLayout(style_buttons_layout)
|
|
|
|
|
|
|
|
|
|
styles_group.setLayout(styles_layout)
|
|
|
|
|
layout.addWidget(styles_group)
|
|
|
|
|
|
|
|
|
|
# 编辑组
|
|
|
|
|
editing_group = self.create_ribbon_group("编辑")
|
|
|
|
|
|
|
|
|
|
# 创建查找替换按钮,使用更适合水平排列的样式
|
|
|
|
|
|
|
|
|
|
# ---------- 编辑组 ----------
|
|
|
|
|
editing_group, editing_layout = self.create_ribbon_group("编辑")
|
|
|
|
|
self.find_btn = QToolButton()
|
|
|
|
|
self.find_btn.setText("查找")
|
|
|
|
|
self.find_btn.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
|
|
|
|
self.find_btn.setFixedSize(50, 25) # 设置适合水平排列的尺寸
|
|
|
|
|
|
|
|
|
|
self.find_btn.setFixedSize(55, 25)
|
|
|
|
|
self.replace_btn = QToolButton()
|
|
|
|
|
self.replace_btn.setText("替换")
|
|
|
|
|
self.replace_btn.setToolButtonStyle(Qt.ToolButtonTextOnly)
|
|
|
|
|
self.replace_btn.setFixedSize(50, 25) # 设置适合水平排列的尺寸
|
|
|
|
|
|
|
|
|
|
editing_layout = QHBoxLayout() # 改为水平布局
|
|
|
|
|
self.replace_btn.setFixedSize(55, 25)
|
|
|
|
|
editing_layout.addWidget(self.find_btn)
|
|
|
|
|
editing_layout.addWidget(self.replace_btn)
|
|
|
|
|
editing_layout.addStretch() # 添加弹性空间
|
|
|
|
|
editing_group.setLayout(editing_layout)
|
|
|
|
|
editing_group.setFixedWidth(120) # 设置编辑组宽度以适应查找替换按钮
|
|
|
|
|
editing_layout.addStretch()
|
|
|
|
|
layout.addWidget(editing_group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 最右侧填充空白,保证整体自适应
|
|
|
|
|
layout.addStretch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_font_changed(self, font):
|
|
|
|
|
"""字体变化处理"""
|
|
|
|
|
@ -267,6 +273,65 @@ class WordRibbon(QFrame):
|
|
|
|
|
"""两端对齐按钮点击处理"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def init_style_preview_group(self):
|
|
|
|
|
"""加入 Word 风格的样式预览区域"""
|
|
|
|
|
|
|
|
|
|
group = QFrame()
|
|
|
|
|
group.setStyleSheet("""
|
|
|
|
|
QFrame { border: none; }
|
|
|
|
|
QLabel { font-size: 11px; color: #555; }
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
outer_layout = QVBoxLayout(group)
|
|
|
|
|
outer_layout.setContentsMargins(3, 3, 3, 3)
|
|
|
|
|
outer_layout.setSpacing(2)
|
|
|
|
|
|
|
|
|
|
# 上部:样式预览按钮
|
|
|
|
|
preview_widget = QWidget()
|
|
|
|
|
preview_layout = QHBoxLayout(preview_widget)
|
|
|
|
|
preview_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
preview_layout.setSpacing(8)
|
|
|
|
|
|
|
|
|
|
style_items = [
|
|
|
|
|
("正文", "font-size:14px;"),
|
|
|
|
|
("无间隔", "font-size:14px;"),
|
|
|
|
|
("标题 1", "font-size:22px; font-weight:bold; color:#2E75B6;"),
|
|
|
|
|
("标题 2", "font-size:18px; color:#2E75B6;"),
|
|
|
|
|
("标题 3", "font-size:16px; font-weight:bold;"),
|
|
|
|
|
("副标题", "font-size:14px; font-style:italic; color:#555;"),
|
|
|
|
|
("强调", "font-size:14px; color:#C0504D;"),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for text, style in style_items:
|
|
|
|
|
btn = QPushButton(text)
|
|
|
|
|
btn.setFixedSize(95, 60)
|
|
|
|
|
btn.setStyleSheet(f"""
|
|
|
|
|
QPushButton {{
|
|
|
|
|
background: white;
|
|
|
|
|
border: 1px solid #d0d0d0;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
text-align: left;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
{style}
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:hover {{
|
|
|
|
|
border: 1px solid #4a90e2;
|
|
|
|
|
}}
|
|
|
|
|
""")
|
|
|
|
|
preview_layout.addWidget(btn)
|
|
|
|
|
|
|
|
|
|
preview_layout.addStretch()
|
|
|
|
|
|
|
|
|
|
# 下方标题
|
|
|
|
|
title_label = QLabel("样式")
|
|
|
|
|
title_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
outer_layout.addWidget(preview_widget)
|
|
|
|
|
outer_layout.addWidget(title_label)
|
|
|
|
|
|
|
|
|
|
self.ribbon_layout.addWidget(group)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_theme(self):
|
|
|
|
|
"""初始化主题"""
|
|
|
|
|
# 连接主题切换信号
|
|
|
|
|
@ -276,31 +341,19 @@ class WordRibbon(QFrame):
|
|
|
|
|
self.apply_theme()
|
|
|
|
|
|
|
|
|
|
def apply_theme(self):
|
|
|
|
|
"""应用主题样式"""
|
|
|
|
|
is_dark = theme_manager.is_dark_theme()
|
|
|
|
|
|
|
|
|
|
# 更新功能区背景
|
|
|
|
|
colors = theme_manager.get_current_theme_colors()
|
|
|
|
|
# 简化仅保留关键样式更新
|
|
|
|
|
self.ribbon_area.setStyleSheet(f"""
|
|
|
|
|
QFrame {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
border-top: none;
|
|
|
|
|
}}
|
|
|
|
|
QGroupBox {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
}}
|
|
|
|
|
QGroupBox::title {{
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
}}
|
|
|
|
|
QLabel {{
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
}}
|
|
|
|
|
""")
|
|
|
|
|
# 更新下拉框和按钮样式(调用原有 helper)
|
|
|
|
|
self.update_combo_styles(is_dark)
|
|
|
|
|
self.update_font_button_styles(is_dark)
|
|
|
|
|
|
|
|
|
|
# 更新天气组件样式
|
|
|
|
|
if hasattr(self, 'weather_icon_label') and self.weather_icon_label is not None:
|
|
|
|
|
@ -330,7 +383,10 @@ class WordRibbon(QFrame):
|
|
|
|
|
|
|
|
|
|
# 更新下拉框样式
|
|
|
|
|
self.update_combo_styles(is_dark)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_theme_changed(self, is_dark):
|
|
|
|
|
self.apply_theme()
|
|
|
|
|
|
|
|
|
|
def update_combo_styles(self, is_dark):
|
|
|
|
|
"""更新下拉框样式"""
|
|
|
|
|
colors = theme_manager.get_current_theme_colors()
|
|
|
|
|
@ -798,24 +854,6 @@ class WordRibbon(QFrame):
|
|
|
|
|
self.quote_group = None
|
|
|
|
|
self.quote_visible = False
|
|
|
|
|
|
|
|
|
|
def create_ribbon_group(self, title, is_special_group=False):
|
|
|
|
|
"""创建功能区组"""
|
|
|
|
|
group = QGroupBox(title)
|
|
|
|
|
|
|
|
|
|
# 为非特殊组设置最小宽度以确保标题完整显示
|
|
|
|
|
if not is_special_group:
|
|
|
|
|
# 根据标题长度计算合适的最小宽度
|
|
|
|
|
min_width = max(100, len(title) * 12 + 40) # 基础宽度+每个字符约12px
|
|
|
|
|
group.setMinimumWidth(min_width)
|
|
|
|
|
|
|
|
|
|
# 连接主题切换信号以动态更新样式
|
|
|
|
|
theme_manager.theme_changed.connect(lambda: self._update_group_style(group))
|
|
|
|
|
|
|
|
|
|
# 立即应用当前主题样式
|
|
|
|
|
self._update_group_style(group)
|
|
|
|
|
|
|
|
|
|
return group
|
|
|
|
|
|
|
|
|
|
def _update_group_style(self, group):
|
|
|
|
|
"""更新组样式以适配当前主题"""
|
|
|
|
|
is_dark = theme_manager.is_dark_theme()
|
|
|
|
|
|