|
|
|
|
@ -3,9 +3,10 @@ import sys
|
|
|
|
|
import os
|
|
|
|
|
from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
|
|
|
|
QTextEdit, QLabel, QSplitter, QFrame, QMenuBar,
|
|
|
|
|
QAction, QFileDialog, QMessageBox, QApplication)
|
|
|
|
|
QAction, QFileDialog, QMessageBox, QApplication,
|
|
|
|
|
QDialog, QLineEdit, QCheckBox, QPushButton)
|
|
|
|
|
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer, QRect
|
|
|
|
|
from PyQt5.QtGui import QFont, QPalette, QColor, QIcon, QPixmap, QTextCharFormat
|
|
|
|
|
from PyQt5.QtGui import QFont, QPalette, QColor, QIcon, QPixmap, QTextCharFormat, QTextCursor, QTextDocument
|
|
|
|
|
|
|
|
|
|
from ui.word_style_ui import (WordRibbon, WordStatusBar, WordTextEdit,
|
|
|
|
|
WordStyleToolBar)
|
|
|
|
|
@ -231,10 +232,106 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
|
|
|
|
|
# 打印布局
|
|
|
|
|
print_layout_action = QAction('打印布局', self)
|
|
|
|
|
print_layout_action.setCheckable(True)
|
|
|
|
|
print_layout_action.setChecked(True)
|
|
|
|
|
print_layout_action.triggered.connect(self.toggle_print_layout)
|
|
|
|
|
view_menu.addAction(print_layout_action)
|
|
|
|
|
|
|
|
|
|
view_menu.addSeparator()
|
|
|
|
|
|
|
|
|
|
# 页面布局子菜单
|
|
|
|
|
layout_menu = view_menu.addMenu('页面布局')
|
|
|
|
|
|
|
|
|
|
# 页面颜色
|
|
|
|
|
page_color_menu = layout_menu.addMenu('页面颜色')
|
|
|
|
|
white_action = QAction('白色', self)
|
|
|
|
|
white_action.triggered.connect(lambda: self.set_page_color('white'))
|
|
|
|
|
page_color_menu.addAction(white_action)
|
|
|
|
|
|
|
|
|
|
light_blue_action = QAction('浅蓝色', self)
|
|
|
|
|
light_blue_action.triggered.connect(lambda: self.set_page_color('light_blue'))
|
|
|
|
|
page_color_menu.addAction(light_blue_action)
|
|
|
|
|
|
|
|
|
|
light_yellow_action = QAction('浅黄色', self)
|
|
|
|
|
light_yellow_action.triggered.connect(lambda: self.set_page_color('light_yellow'))
|
|
|
|
|
page_color_menu.addAction(light_yellow_action)
|
|
|
|
|
|
|
|
|
|
light_green_action = QAction('浅绿色', self)
|
|
|
|
|
light_green_action.triggered.connect(lambda: self.set_page_color('light_green'))
|
|
|
|
|
page_color_menu.addAction(light_green_action)
|
|
|
|
|
|
|
|
|
|
# 页面边距
|
|
|
|
|
margin_menu = layout_menu.addMenu('页面边距')
|
|
|
|
|
normal_margin_action = QAction('普通', self)
|
|
|
|
|
normal_margin_action.triggered.connect(lambda: self.set_page_margins('normal'))
|
|
|
|
|
margin_menu.addAction(normal_margin_action)
|
|
|
|
|
|
|
|
|
|
narrow_margin_action = QAction('窄', self)
|
|
|
|
|
narrow_margin_action.triggered.connect(lambda: self.set_page_margins('narrow'))
|
|
|
|
|
margin_menu.addAction(narrow_margin_action)
|
|
|
|
|
|
|
|
|
|
wide_margin_action = QAction('宽', self)
|
|
|
|
|
wide_margin_action.triggered.connect(lambda: self.set_page_margins('wide'))
|
|
|
|
|
margin_menu.addAction(wide_margin_action)
|
|
|
|
|
|
|
|
|
|
# 缩放子菜单
|
|
|
|
|
zoom_menu = view_menu.addMenu('缩放')
|
|
|
|
|
|
|
|
|
|
zoom_in_action = QAction('放大', self)
|
|
|
|
|
zoom_in_action.setShortcut('Ctrl++')
|
|
|
|
|
zoom_in_action.triggered.connect(self.zoom_in)
|
|
|
|
|
zoom_menu.addAction(zoom_in_action)
|
|
|
|
|
|
|
|
|
|
zoom_out_action = QAction('缩小', self)
|
|
|
|
|
zoom_out_action.setShortcut('Ctrl+-')
|
|
|
|
|
zoom_out_action.triggered.connect(self.zoom_out)
|
|
|
|
|
zoom_menu.addAction(zoom_out_action)
|
|
|
|
|
|
|
|
|
|
zoom_100_action = QAction('实际大小', self)
|
|
|
|
|
zoom_100_action.setShortcut('Ctrl+0')
|
|
|
|
|
zoom_100_action.triggered.connect(self.zoom_100)
|
|
|
|
|
zoom_menu.addAction(zoom_100_action)
|
|
|
|
|
|
|
|
|
|
zoom_menu.addSeparator()
|
|
|
|
|
|
|
|
|
|
# 预设缩放选项
|
|
|
|
|
zoom_50_action = QAction('50%', self)
|
|
|
|
|
zoom_50_action.triggered.connect(lambda: self.set_zoom_level(50))
|
|
|
|
|
zoom_menu.addAction(zoom_50_action)
|
|
|
|
|
|
|
|
|
|
zoom_75_action = QAction('75%', self)
|
|
|
|
|
zoom_75_action.triggered.connect(lambda: self.set_zoom_level(75))
|
|
|
|
|
zoom_menu.addAction(zoom_75_action)
|
|
|
|
|
|
|
|
|
|
zoom_100_action2 = QAction('100%', self)
|
|
|
|
|
zoom_100_action2.triggered.connect(lambda: self.set_zoom_level(100))
|
|
|
|
|
zoom_menu.addAction(zoom_100_action2)
|
|
|
|
|
|
|
|
|
|
zoom_125_action = QAction('125%', self)
|
|
|
|
|
zoom_125_action.triggered.connect(lambda: self.set_zoom_level(125))
|
|
|
|
|
zoom_menu.addAction(zoom_125_action)
|
|
|
|
|
|
|
|
|
|
zoom_150_action = QAction('150%', self)
|
|
|
|
|
zoom_150_action.triggered.connect(lambda: self.set_zoom_level(150))
|
|
|
|
|
zoom_menu.addAction(zoom_150_action)
|
|
|
|
|
|
|
|
|
|
zoom_200_action = QAction('200%', self)
|
|
|
|
|
zoom_200_action.triggered.connect(lambda: self.set_zoom_level(200))
|
|
|
|
|
zoom_menu.addAction(zoom_200_action)
|
|
|
|
|
|
|
|
|
|
view_menu.addSeparator()
|
|
|
|
|
|
|
|
|
|
# 显示选项
|
|
|
|
|
grid_lines_action = QAction('网格线', self)
|
|
|
|
|
grid_lines_action.setCheckable(True)
|
|
|
|
|
grid_lines_action.triggered.connect(self.toggle_grid_lines)
|
|
|
|
|
view_menu.addAction(grid_lines_action)
|
|
|
|
|
|
|
|
|
|
ruler_action = QAction('标尺', self)
|
|
|
|
|
ruler_action.setCheckable(True)
|
|
|
|
|
ruler_action.triggered.connect(self.toggle_ruler)
|
|
|
|
|
view_menu.addAction(ruler_action)
|
|
|
|
|
|
|
|
|
|
# 帮助菜单
|
|
|
|
|
help_menu = menubar.addMenu('帮助(H)')
|
|
|
|
|
|
|
|
|
|
@ -318,9 +415,23 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
self.text_edit.textChanged.connect(self.on_text_changed)
|
|
|
|
|
|
|
|
|
|
# Ribbon按钮信号
|
|
|
|
|
if hasattr(self.ribbon, 'tabs'):
|
|
|
|
|
for tab_name, tab_btn in self.ribbon.tabs.items():
|
|
|
|
|
tab_btn.clicked.connect(lambda checked, name=tab_name: self.on_tab_changed(name))
|
|
|
|
|
# 标签栏已删除,相关代码已移除
|
|
|
|
|
|
|
|
|
|
# 字体设置信号
|
|
|
|
|
if hasattr(self.ribbon, 'font_combo'):
|
|
|
|
|
self.ribbon.font_combo.currentFontChanged.connect(self.on_font_changed)
|
|
|
|
|
self.ribbon.font_size_combo.currentTextChanged.connect(self.on_font_size_changed)
|
|
|
|
|
self.ribbon.bold_btn.clicked.connect(self.on_bold_clicked)
|
|
|
|
|
self.ribbon.italic_btn.clicked.connect(self.on_italic_clicked)
|
|
|
|
|
self.ribbon.underline_btn.clicked.connect(self.on_underline_clicked)
|
|
|
|
|
|
|
|
|
|
# 查找和替换按钮信号
|
|
|
|
|
if hasattr(self.ribbon, 'find_btn'):
|
|
|
|
|
self.ribbon.find_btn.clicked.connect(self.show_find_dialog)
|
|
|
|
|
if hasattr(self.ribbon, 'replace_btn'):
|
|
|
|
|
self.ribbon.replace_btn.clicked.connect(self.show_replace_dialog)
|
|
|
|
|
|
|
|
|
|
# 页面布局信号已在菜单中直接连接,无需在此重复连接
|
|
|
|
|
|
|
|
|
|
def on_text_changed(self):
|
|
|
|
|
"""文本变化处理 - 逐步显示模式"""
|
|
|
|
|
@ -389,14 +500,71 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
self.is_modified = True
|
|
|
|
|
self.update_window_title()
|
|
|
|
|
|
|
|
|
|
def on_tab_changed(self, tab_name):
|
|
|
|
|
"""标签切换处理"""
|
|
|
|
|
# 更新标签状态
|
|
|
|
|
for name, btn in self.ribbon.tabs.items():
|
|
|
|
|
btn.setChecked(name == tab_name)
|
|
|
|
|
|
|
|
|
|
# 这里可以根据不同标签切换不同的功能区内容
|
|
|
|
|
print(f"切换到标签: {tab_name}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def on_font_changed(self, font):
|
|
|
|
|
"""字体更改处理"""
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
if cursor.hasSelection():
|
|
|
|
|
# 如果有选中文本,只更改选中文本的字体
|
|
|
|
|
fmt = cursor.charFormat()
|
|
|
|
|
fmt.setFontFamily(font.family())
|
|
|
|
|
cursor.setCharFormat(fmt)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有选中文本,更改整个文档的默认字体
|
|
|
|
|
self.text_edit.setFontFamily(font.family())
|
|
|
|
|
|
|
|
|
|
def on_font_size_changed(self, size):
|
|
|
|
|
"""字体大小更改处理"""
|
|
|
|
|
try:
|
|
|
|
|
font_size = int(size)
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
if cursor.hasSelection():
|
|
|
|
|
# 如果有选中文本,只更改选中文本的字体大小
|
|
|
|
|
fmt = cursor.charFormat()
|
|
|
|
|
fmt.setFontPointSize(font_size)
|
|
|
|
|
cursor.setCharFormat(fmt)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有选中文本,更改整个文档的默认字体大小
|
|
|
|
|
self.text_edit.setFontPointSize(font_size)
|
|
|
|
|
except ValueError:
|
|
|
|
|
pass # 忽略无效的字体大小
|
|
|
|
|
|
|
|
|
|
def on_bold_clicked(self, checked):
|
|
|
|
|
"""粗体按钮点击处理"""
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
if cursor.hasSelection():
|
|
|
|
|
# 如果有选中文本,只更改选中文本的粗体样式
|
|
|
|
|
fmt = cursor.charFormat()
|
|
|
|
|
fmt.setFontWeight(QFont.Bold if checked else QFont.Normal)
|
|
|
|
|
cursor.setCharFormat(fmt)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有选中文本,更改整个文档的默认粗体样式
|
|
|
|
|
self.text_edit.setFontWeight(QFont.Bold if checked else QFont.Normal)
|
|
|
|
|
|
|
|
|
|
def on_italic_clicked(self, checked):
|
|
|
|
|
"""斜体按钮点击处理"""
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
if cursor.hasSelection():
|
|
|
|
|
# 如果有选中文本,只更改选中文本的斜体样式
|
|
|
|
|
fmt = cursor.charFormat()
|
|
|
|
|
fmt.setFontItalic(checked)
|
|
|
|
|
cursor.setCharFormat(fmt)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有选中文本,更改整个文档的默认斜体样式
|
|
|
|
|
self.text_edit.setFontItalic(checked)
|
|
|
|
|
|
|
|
|
|
def on_underline_clicked(self, checked):
|
|
|
|
|
"""下划线按钮点击处理"""
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
if cursor.hasSelection():
|
|
|
|
|
# 如果有选中文本,只更改选中文本的下划线样式
|
|
|
|
|
fmt = cursor.charFormat()
|
|
|
|
|
fmt.setFontUnderline(checked)
|
|
|
|
|
cursor.setCharFormat(fmt)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有选中文本,更改整个文档的默认下划线样式
|
|
|
|
|
self.text_edit.setFontUnderline(checked)
|
|
|
|
|
|
|
|
|
|
def update_weather_display(self, weather_data):
|
|
|
|
|
"""更新天气显示"""
|
|
|
|
|
@ -600,6 +768,319 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
# 这里可以实现打印布局的逻辑
|
|
|
|
|
self.status_bar.showMessage("打印布局功能开发中...", 3000)
|
|
|
|
|
|
|
|
|
|
def set_page_color(self, color):
|
|
|
|
|
"""设置页面颜色"""
|
|
|
|
|
color_map = {
|
|
|
|
|
'white': '#ffffff',
|
|
|
|
|
'light_blue': '#e6f3ff',
|
|
|
|
|
'light_yellow': '#fffde6',
|
|
|
|
|
'light_green': '#e6ffe6'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if color in color_map:
|
|
|
|
|
bg_color = color_map[color]
|
|
|
|
|
# 更新文本编辑区域的背景色
|
|
|
|
|
current_style = self.text_edit.styleSheet()
|
|
|
|
|
# 移除旧的背景色设置
|
|
|
|
|
import re
|
|
|
|
|
current_style = re.sub(r'background-color:\s*#[a-fA-F0-9]+;', '', current_style)
|
|
|
|
|
# 添加新的背景色设置
|
|
|
|
|
new_style = current_style + f"\nbackground-color: {bg_color};"
|
|
|
|
|
self.text_edit.setStyleSheet(new_style)
|
|
|
|
|
self.status_bar.showMessage(f"页面颜色已设置为{color}", 2000)
|
|
|
|
|
|
|
|
|
|
def set_page_margins(self, margin_type):
|
|
|
|
|
"""设置页面边距"""
|
|
|
|
|
margin_map = {
|
|
|
|
|
'normal': (50, 50, 50, 50),
|
|
|
|
|
'narrow': (20, 20, 20, 20),
|
|
|
|
|
'wide': (80, 80, 80, 80)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if margin_type in margin_map:
|
|
|
|
|
margins = margin_map[margin_type]
|
|
|
|
|
# 更新文档容器的边距
|
|
|
|
|
# text_edit的父级是document_layout,父级的父级是document_container
|
|
|
|
|
container = self.text_edit.parent().parent() # 获取文档容器
|
|
|
|
|
if container and hasattr(container, 'layout'):
|
|
|
|
|
layout = container.layout()
|
|
|
|
|
if layout:
|
|
|
|
|
layout.setContentsMargins(margins[0], margins[1], margins[2], margins[3])
|
|
|
|
|
self.status_bar.showMessage(f"页面边距已设置为{margin_type}", 2000)
|
|
|
|
|
|
|
|
|
|
def zoom_in(self):
|
|
|
|
|
"""放大"""
|
|
|
|
|
self.adjust_zoom_level(10)
|
|
|
|
|
|
|
|
|
|
def zoom_out(self):
|
|
|
|
|
"""缩小"""
|
|
|
|
|
self.adjust_zoom_level(-10)
|
|
|
|
|
|
|
|
|
|
def zoom_100(self):
|
|
|
|
|
"""实际大小"""
|
|
|
|
|
self.set_zoom_level(100)
|
|
|
|
|
|
|
|
|
|
def set_zoom_level(self, level):
|
|
|
|
|
"""设置缩放级别"""
|
|
|
|
|
if 10 <= level <= 500: # 限制缩放范围在10%到500%之间
|
|
|
|
|
# 获取当前字体大小并调整
|
|
|
|
|
current_font = self.text_edit.currentFont()
|
|
|
|
|
base_size = 12 # 基准字体大小
|
|
|
|
|
new_size = base_size * (level / 100)
|
|
|
|
|
|
|
|
|
|
# 应用新的字体大小
|
|
|
|
|
current_font.setPointSizeF(new_size)
|
|
|
|
|
self.text_edit.setFont(current_font)
|
|
|
|
|
|
|
|
|
|
self.status_bar.showMessage(f"缩放级别: {level}%", 2000)
|
|
|
|
|
|
|
|
|
|
def adjust_zoom_level(self, delta):
|
|
|
|
|
"""调整缩放级别"""
|
|
|
|
|
# 获取当前字体大小
|
|
|
|
|
current_font = self.text_edit.currentFont()
|
|
|
|
|
current_size = current_font.pointSizeF()
|
|
|
|
|
base_size = 12 # 基准字体大小
|
|
|
|
|
|
|
|
|
|
# 计算当前缩放百分比
|
|
|
|
|
current_zoom = (current_size / base_size) * 100
|
|
|
|
|
new_zoom = current_zoom + delta
|
|
|
|
|
|
|
|
|
|
# 限制缩放范围
|
|
|
|
|
if 10 <= new_zoom <= 500:
|
|
|
|
|
self.set_zoom_level(int(new_zoom))
|
|
|
|
|
|
|
|
|
|
def toggle_grid_lines(self):
|
|
|
|
|
"""切换网格线显示"""
|
|
|
|
|
self.status_bar.showMessage("网格线功能开发中...", 3000)
|
|
|
|
|
|
|
|
|
|
def toggle_ruler(self):
|
|
|
|
|
"""切换标尺显示"""
|
|
|
|
|
self.status_bar.showMessage("标尺功能开发中...", 3000)
|
|
|
|
|
|
|
|
|
|
def show_find_dialog(self):
|
|
|
|
|
"""显示查找对话框"""
|
|
|
|
|
# 创建查找对话框
|
|
|
|
|
dialog = QDialog(self)
|
|
|
|
|
dialog.setWindowTitle("查找")
|
|
|
|
|
dialog.setFixedSize(400, 150)
|
|
|
|
|
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 查找内容输入
|
|
|
|
|
find_layout = QHBoxLayout()
|
|
|
|
|
find_label = QLabel("查找内容:")
|
|
|
|
|
self.find_edit = QLineEdit()
|
|
|
|
|
find_layout.addWidget(find_label)
|
|
|
|
|
find_layout.addWidget(self.find_edit)
|
|
|
|
|
layout.addLayout(find_layout)
|
|
|
|
|
|
|
|
|
|
# 选项
|
|
|
|
|
options_layout = QHBoxLayout()
|
|
|
|
|
self.case_sensitive_checkbox = QCheckBox("区分大小写")
|
|
|
|
|
self.whole_words_checkbox = QCheckBox("全字匹配")
|
|
|
|
|
options_layout.addWidget(self.case_sensitive_checkbox)
|
|
|
|
|
options_layout.addWidget(self.whole_words_checkbox)
|
|
|
|
|
options_layout.addStretch()
|
|
|
|
|
layout.addLayout(options_layout)
|
|
|
|
|
|
|
|
|
|
# 按钮
|
|
|
|
|
buttons_layout = QHBoxLayout()
|
|
|
|
|
find_next_btn = QPushButton("查找下一个")
|
|
|
|
|
find_next_btn.clicked.connect(lambda: self.find_text(dialog))
|
|
|
|
|
cancel_btn = QPushButton("取消")
|
|
|
|
|
cancel_btn.clicked.connect(dialog.close)
|
|
|
|
|
buttons_layout.addWidget(find_next_btn)
|
|
|
|
|
buttons_layout.addWidget(cancel_btn)
|
|
|
|
|
layout.addLayout(buttons_layout)
|
|
|
|
|
|
|
|
|
|
dialog.setLayout(layout)
|
|
|
|
|
dialog.exec_()
|
|
|
|
|
|
|
|
|
|
def find_text(self, dialog):
|
|
|
|
|
"""执行查找操作"""
|
|
|
|
|
search_text = self.find_edit.text()
|
|
|
|
|
if not search_text:
|
|
|
|
|
QMessageBox.warning(self, "查找", "请输入查找内容")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 获取当前光标位置
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
start_pos = cursor.position()
|
|
|
|
|
|
|
|
|
|
# 设置查找选项
|
|
|
|
|
flags = QTextDocument.FindFlags()
|
|
|
|
|
if self.case_sensitive_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindCaseSensitively
|
|
|
|
|
if self.whole_words_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindWholeWords
|
|
|
|
|
|
|
|
|
|
# 执行查找
|
|
|
|
|
found_cursor = self.text_edit.document().find(search_text, start_pos, flags)
|
|
|
|
|
|
|
|
|
|
if found_cursor.isNull():
|
|
|
|
|
# 如果没找到,从文档开始处重新查找
|
|
|
|
|
found_cursor = self.text_edit.document().find(search_text, 0, flags)
|
|
|
|
|
|
|
|
|
|
if not found_cursor.isNull():
|
|
|
|
|
# 选中找到的文本
|
|
|
|
|
self.text_edit.setTextCursor(found_cursor)
|
|
|
|
|
self.text_edit.ensureCursorVisible()
|
|
|
|
|
else:
|
|
|
|
|
QMessageBox.information(self, "查找", f"找不到 '{search_text}'")
|
|
|
|
|
|
|
|
|
|
def show_replace_dialog(self):
|
|
|
|
|
"""显示替换对话框"""
|
|
|
|
|
# 创建替换对话框
|
|
|
|
|
dialog = QDialog(self)
|
|
|
|
|
dialog.setWindowTitle("替换")
|
|
|
|
|
dialog.setFixedSize(400, 200)
|
|
|
|
|
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 查找内容输入
|
|
|
|
|
find_layout = QHBoxLayout()
|
|
|
|
|
find_label = QLabel("查找内容:")
|
|
|
|
|
self.replace_find_edit = QLineEdit()
|
|
|
|
|
find_layout.addWidget(find_label)
|
|
|
|
|
find_layout.addWidget(self.replace_find_edit)
|
|
|
|
|
layout.addLayout(find_layout)
|
|
|
|
|
|
|
|
|
|
# 替换为输入
|
|
|
|
|
replace_layout = QHBoxLayout()
|
|
|
|
|
replace_label = QLabel("替换为:")
|
|
|
|
|
self.replace_edit = QLineEdit()
|
|
|
|
|
replace_layout.addWidget(replace_label)
|
|
|
|
|
replace_layout.addWidget(self.replace_edit)
|
|
|
|
|
layout.addLayout(replace_layout)
|
|
|
|
|
|
|
|
|
|
# 选项
|
|
|
|
|
options_layout = QHBoxLayout()
|
|
|
|
|
self.replace_case_sensitive_checkbox = QCheckBox("区分大小写")
|
|
|
|
|
self.replace_whole_words_checkbox = QCheckBox("全字匹配")
|
|
|
|
|
options_layout.addWidget(self.replace_case_sensitive_checkbox)
|
|
|
|
|
options_layout.addWidget(self.replace_whole_words_checkbox)
|
|
|
|
|
options_layout.addStretch()
|
|
|
|
|
layout.addLayout(options_layout)
|
|
|
|
|
|
|
|
|
|
# 按钮
|
|
|
|
|
buttons_layout = QHBoxLayout()
|
|
|
|
|
find_next_btn = QPushButton("查找下一个")
|
|
|
|
|
replace_btn = QPushButton("替换")
|
|
|
|
|
replace_all_btn = QPushButton("全部替换")
|
|
|
|
|
cancel_btn = QPushButton("取消")
|
|
|
|
|
|
|
|
|
|
find_next_btn.clicked.connect(lambda: self.find_text_for_replace(dialog))
|
|
|
|
|
replace_btn.clicked.connect(lambda: self.replace_text(dialog))
|
|
|
|
|
replace_all_btn.clicked.connect(lambda: self.replace_all_text(dialog))
|
|
|
|
|
cancel_btn.clicked.connect(dialog.close)
|
|
|
|
|
|
|
|
|
|
buttons_layout.addWidget(find_next_btn)
|
|
|
|
|
buttons_layout.addWidget(replace_btn)
|
|
|
|
|
buttons_layout.addWidget(replace_all_btn)
|
|
|
|
|
buttons_layout.addWidget(cancel_btn)
|
|
|
|
|
layout.addLayout(buttons_layout)
|
|
|
|
|
|
|
|
|
|
dialog.setLayout(layout)
|
|
|
|
|
dialog.exec_()
|
|
|
|
|
|
|
|
|
|
def find_text_for_replace(self, dialog):
|
|
|
|
|
"""在替换对话框中执行查找操作"""
|
|
|
|
|
search_text = self.replace_find_edit.text()
|
|
|
|
|
if not search_text:
|
|
|
|
|
QMessageBox.warning(self, "查找", "请输入查找内容")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 获取当前光标位置
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
start_pos = cursor.position()
|
|
|
|
|
|
|
|
|
|
# 设置查找选项
|
|
|
|
|
flags = QTextDocument.FindFlags()
|
|
|
|
|
if self.replace_case_sensitive_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindCaseSensitively
|
|
|
|
|
if self.replace_whole_words_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindWholeWords
|
|
|
|
|
|
|
|
|
|
# 执行查找
|
|
|
|
|
found_cursor = self.text_edit.document().find(search_text, start_pos, flags)
|
|
|
|
|
|
|
|
|
|
if found_cursor.isNull():
|
|
|
|
|
# 如果没找到,从文档开始处重新查找
|
|
|
|
|
found_cursor = self.text_edit.document().find(search_text, 0, flags)
|
|
|
|
|
|
|
|
|
|
if not found_cursor.isNull():
|
|
|
|
|
# 选中找到的文本
|
|
|
|
|
self.text_edit.setTextCursor(found_cursor)
|
|
|
|
|
self.text_edit.ensureCursorVisible()
|
|
|
|
|
else:
|
|
|
|
|
QMessageBox.information(self, "查找", f"找不到 '{search_text}'")
|
|
|
|
|
|
|
|
|
|
def replace_text(self, dialog):
|
|
|
|
|
"""替换当前选中的文本"""
|
|
|
|
|
search_text = self.replace_find_edit.text()
|
|
|
|
|
replace_text = self.replace_edit.text()
|
|
|
|
|
|
|
|
|
|
# 检查是否有选中的文本且与查找内容匹配
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
selected_text = cursor.selectedText()
|
|
|
|
|
|
|
|
|
|
# 检查是否匹配(考虑大小写敏感选项)
|
|
|
|
|
match = False
|
|
|
|
|
if self.replace_case_sensitive_checkbox.isChecked():
|
|
|
|
|
match = selected_text == search_text
|
|
|
|
|
else:
|
|
|
|
|
match = selected_text.lower() == search_text.lower()
|
|
|
|
|
|
|
|
|
|
if match:
|
|
|
|
|
# 替换选中的文本
|
|
|
|
|
cursor.insertText(replace_text)
|
|
|
|
|
# 继续查找下一个
|
|
|
|
|
self.find_text_for_replace(dialog)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有匹配的选中文本,执行查找
|
|
|
|
|
self.find_text_for_replace(dialog)
|
|
|
|
|
|
|
|
|
|
def replace_all_text(self, dialog):
|
|
|
|
|
"""替换所有匹配的文本"""
|
|
|
|
|
search_text = self.replace_find_edit.text()
|
|
|
|
|
replace_text = self.replace_edit.text()
|
|
|
|
|
|
|
|
|
|
if not search_text:
|
|
|
|
|
QMessageBox.warning(self, "替换", "请输入查找内容")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 设置查找选项
|
|
|
|
|
flags = QTextDocument.FindFlags()
|
|
|
|
|
if self.replace_case_sensitive_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindCaseSensitively
|
|
|
|
|
if self.replace_whole_words_checkbox.isChecked():
|
|
|
|
|
flags |= QTextDocument.FindWholeWords
|
|
|
|
|
|
|
|
|
|
# 保存当前光标位置
|
|
|
|
|
original_cursor = self.text_edit.textCursor()
|
|
|
|
|
|
|
|
|
|
# 从文档开始处查找并替换所有匹配项
|
|
|
|
|
count = 0
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
cursor.movePosition(QTextCursor.Start)
|
|
|
|
|
self.text_edit.setTextCursor(cursor)
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
found_cursor = self.text_edit.document().find(search_text, cursor, flags)
|
|
|
|
|
if found_cursor.isNull():
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# 替换文本
|
|
|
|
|
found_cursor.insertText(replace_text)
|
|
|
|
|
count += 1
|
|
|
|
|
cursor = found_cursor
|
|
|
|
|
|
|
|
|
|
# 恢复原始光标位置
|
|
|
|
|
self.text_edit.setTextCursor(original_cursor)
|
|
|
|
|
|
|
|
|
|
# 显示替换结果
|
|
|
|
|
QMessageBox.information(self, "替换", f"已完成 {count} 处替换。")
|
|
|
|
|
|
|
|
|
|
def show_about(self):
|
|
|
|
|
"""显示关于对话框"""
|
|
|
|
|
QMessageBox.about(
|
|
|
|
|
|