|
|
|
|
@ -12,6 +12,7 @@ from ui.word_style_ui import (WordRibbon, WordStatusBar, WordTextEdit,
|
|
|
|
|
WordStyleToolBar)
|
|
|
|
|
from services.network_service import NetworkService
|
|
|
|
|
from typing_logic import TypingLogic
|
|
|
|
|
from ui.word_style_ui import WeatherAPI
|
|
|
|
|
from file_parser import FileParser
|
|
|
|
|
|
|
|
|
|
class WeatherFetchThread(QThread):
|
|
|
|
|
@ -19,12 +20,25 @@ class WeatherFetchThread(QThread):
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.network_service = NetworkService()
|
|
|
|
|
self.weather_api = WeatherAPI()
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
try:
|
|
|
|
|
weather_data = self.network_service.get_weather()
|
|
|
|
|
self.weather_fetched.emit(weather_data)
|
|
|
|
|
# 使用WeatherAPI获取天气数据
|
|
|
|
|
weather_data = self.weather_api.get_weather_data("北京")
|
|
|
|
|
if weather_data:
|
|
|
|
|
# 格式化天气数据
|
|
|
|
|
formatted_data = {
|
|
|
|
|
'city': weather_data['city'],
|
|
|
|
|
'temperature': weather_data['current']['temp'],
|
|
|
|
|
'description': weather_data['current']['weather'],
|
|
|
|
|
'humidity': weather_data['current']['humidity'],
|
|
|
|
|
'wind_scale': weather_data['current']['wind_scale'],
|
|
|
|
|
'forecast': weather_data['forecast']
|
|
|
|
|
}
|
|
|
|
|
self.weather_fetched.emit(formatted_data)
|
|
|
|
|
else:
|
|
|
|
|
self.weather_fetched.emit({'error': '无法获取天气数据,请检查API密钥'})
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.weather_fetched.emit({'error': str(e)})
|
|
|
|
|
|
|
|
|
|
@ -51,8 +65,10 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
self.is_loading_file = False # 添加文件加载标志
|
|
|
|
|
self.imported_content = "" # 存储导入的完整内容
|
|
|
|
|
self.displayed_chars = 0 # 已显示的字符数
|
|
|
|
|
self.setup_ui()
|
|
|
|
|
|
|
|
|
|
# 初始化网络服务和WeatherAPI
|
|
|
|
|
self.network_service = NetworkService()
|
|
|
|
|
self.weather_api = WeatherAPI()
|
|
|
|
|
|
|
|
|
|
# 设置窗口属性
|
|
|
|
|
self.setWindowTitle("文档1 - MagicWord")
|
|
|
|
|
@ -239,98 +255,19 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
# 天气功能
|
|
|
|
|
weather_menu = view_menu.addMenu('天气信息')
|
|
|
|
|
|
|
|
|
|
# 显示选项
|
|
|
|
|
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)
|
|
|
|
|
# 刷新天气
|
|
|
|
|
refresh_weather_action = QAction('刷新天气', self)
|
|
|
|
|
refresh_weather_action.setShortcut('F5')
|
|
|
|
|
refresh_weather_action.triggered.connect(self.refresh_weather)
|
|
|
|
|
weather_menu.addAction(refresh_weather_action)
|
|
|
|
|
|
|
|
|
|
ruler_action = QAction('标尺', self)
|
|
|
|
|
ruler_action.setCheckable(True)
|
|
|
|
|
ruler_action.triggered.connect(self.toggle_ruler)
|
|
|
|
|
view_menu.addAction(ruler_action)
|
|
|
|
|
# 显示详细天气
|
|
|
|
|
show_weather_action = QAction('显示详细天气', self)
|
|
|
|
|
show_weather_action.triggered.connect(self.show_detailed_weather)
|
|
|
|
|
weather_menu.addAction(show_weather_action)
|
|
|
|
|
|
|
|
|
|
# 帮助菜单
|
|
|
|
|
help_menu = menubar.addMenu('帮助(H)')
|
|
|
|
|
@ -571,9 +508,114 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
if 'error' in weather_data:
|
|
|
|
|
self.status_bar.showMessage(f"天气信息获取失败: {weather_data['error']}", 3000)
|
|
|
|
|
else:
|
|
|
|
|
city = weather_data.get('city', '未知城市')
|
|
|
|
|
temp = weather_data.get('temperature', 'N/A')
|
|
|
|
|
desc = weather_data.get('description', 'N/A')
|
|
|
|
|
self.status_bar.showMessage(f"天气: {desc}, {temp}°C", 5000)
|
|
|
|
|
humidity = weather_data.get('humidity', 'N/A')
|
|
|
|
|
wind_scale = weather_data.get('wind_scale', 'N/A')
|
|
|
|
|
|
|
|
|
|
# 在状态栏显示简要天气信息
|
|
|
|
|
self.status_bar.showMessage(f"{city}: {desc}, {temp}°C, 湿度{humidity}%, 风力{wind_scale}级", 5000)
|
|
|
|
|
|
|
|
|
|
# 存储天气数据供其他功能使用
|
|
|
|
|
self.current_weather_data = weather_data
|
|
|
|
|
|
|
|
|
|
def refresh_weather(self):
|
|
|
|
|
"""手动刷新天气信息"""
|
|
|
|
|
try:
|
|
|
|
|
# 使用WeatherAPI获取天气数据
|
|
|
|
|
weather_data = self.weather_api.get_weather_data("北京")
|
|
|
|
|
if weather_data:
|
|
|
|
|
# 格式化天气数据
|
|
|
|
|
formatted_data = {
|
|
|
|
|
'city': weather_data['city'],
|
|
|
|
|
'temperature': weather_data['current']['temp'],
|
|
|
|
|
'description': weather_data['current']['weather'],
|
|
|
|
|
'humidity': weather_data['current']['humidity'],
|
|
|
|
|
'wind_scale': weather_data['current']['wind_scale'],
|
|
|
|
|
'forecast': weather_data['forecast']
|
|
|
|
|
}
|
|
|
|
|
self.update_weather_display(formatted_data)
|
|
|
|
|
self.status_bar.showMessage("天气信息已刷新", 2000)
|
|
|
|
|
else:
|
|
|
|
|
self.status_bar.showMessage("天气信息刷新失败,请检查API密钥", 3000)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.status_bar.showMessage(f"天气刷新失败: {str(e)}", 3000)
|
|
|
|
|
|
|
|
|
|
def show_detailed_weather(self):
|
|
|
|
|
"""显示详细天气信息对话框"""
|
|
|
|
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit
|
|
|
|
|
|
|
|
|
|
# 检查是否有天气数据
|
|
|
|
|
if not hasattr(self, 'current_weather_data') or not self.current_weather_data:
|
|
|
|
|
QMessageBox.information(self, "天气信息", "暂无天气数据,请先刷新天气信息")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
weather_data = self.current_weather_data
|
|
|
|
|
|
|
|
|
|
# 创建对话框
|
|
|
|
|
dialog = QDialog(self)
|
|
|
|
|
dialog.setWindowTitle("详细天气信息")
|
|
|
|
|
dialog.setMinimumWidth(400)
|
|
|
|
|
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 城市信息
|
|
|
|
|
city_label = QLabel(f"<h2>{weather_data.get('city', '未知城市')}</h2>")
|
|
|
|
|
layout.addWidget(city_label)
|
|
|
|
|
|
|
|
|
|
# 当前天气信息
|
|
|
|
|
current_layout = QVBoxLayout()
|
|
|
|
|
current_layout.addWidget(QLabel("<b>当前天气:</b>"))
|
|
|
|
|
|
|
|
|
|
current_info = f"""
|
|
|
|
|
温度: {weather_data.get('temperature', 'N/A')}°C
|
|
|
|
|
天气状况: {weather_data.get('description', 'N/A')}
|
|
|
|
|
湿度: {weather_data.get('humidity', 'N/A')}%
|
|
|
|
|
风力: {weather_data.get('wind_scale', 'N/A')}级
|
|
|
|
|
"""
|
|
|
|
|
current_text = QTextEdit()
|
|
|
|
|
current_text.setPlainText(current_info.strip())
|
|
|
|
|
current_text.setReadOnly(True)
|
|
|
|
|
current_layout.addWidget(current_text)
|
|
|
|
|
|
|
|
|
|
layout.addLayout(current_layout)
|
|
|
|
|
|
|
|
|
|
# 天气预报信息
|
|
|
|
|
if 'forecast' in weather_data and weather_data['forecast']:
|
|
|
|
|
forecast_layout = QVBoxLayout()
|
|
|
|
|
forecast_layout.addWidget(QLabel("<b>天气预报:</b>"))
|
|
|
|
|
|
|
|
|
|
forecast_text = QTextEdit()
|
|
|
|
|
forecast_info = ""
|
|
|
|
|
for i, day in enumerate(weather_data['forecast'][:3]): # 显示最近3天的预报
|
|
|
|
|
if i < len(weather_data['forecast']):
|
|
|
|
|
day_data = weather_data['forecast'][i]
|
|
|
|
|
forecast_info += f"第{i+1}天: {day_data.get('fxDate', 'N/A')} - {day_data.get('textDay', 'N/A')}, {day_data.get('tempMin', 'N/A')}~{day_data.get('tempMax', 'N/A')}°C\n"
|
|
|
|
|
|
|
|
|
|
forecast_text.setPlainText(forecast_info.strip())
|
|
|
|
|
forecast_text.setReadOnly(True)
|
|
|
|
|
forecast_layout.addWidget(forecast_text)
|
|
|
|
|
layout.addLayout(forecast_layout)
|
|
|
|
|
|
|
|
|
|
# 按钮
|
|
|
|
|
button_layout = QHBoxLayout()
|
|
|
|
|
refresh_button = QPushButton("刷新")
|
|
|
|
|
refresh_button.clicked.connect(lambda: self.refresh_weather_and_close(dialog))
|
|
|
|
|
close_button = QPushButton("关闭")
|
|
|
|
|
close_button.clicked.connect(dialog.close)
|
|
|
|
|
|
|
|
|
|
button_layout.addWidget(refresh_button)
|
|
|
|
|
button_layout.addWidget(close_button)
|
|
|
|
|
layout.addLayout(button_layout)
|
|
|
|
|
|
|
|
|
|
dialog.setLayout(layout)
|
|
|
|
|
dialog.exec_()
|
|
|
|
|
|
|
|
|
|
def refresh_weather_and_close(self, dialog):
|
|
|
|
|
"""刷新天气并关闭对话框"""
|
|
|
|
|
self.refresh_weather()
|
|
|
|
|
dialog.close()
|
|
|
|
|
|
|
|
|
|
def update_quote_display(self, quote_data):
|
|
|
|
|
"""更新名言显示"""
|
|
|
|
|
|