From 1154098ad10dadd2659c00420c6683898bce7413 Mon Sep 17 00:00:00 2001 From: Horse861 <929110464@qq.com> Date: Mon, 3 Nov 2025 10:39:08 +0800 Subject: [PATCH] =?UTF-8?q?1.0-win=E6=89=93=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build_v1.0.py | 331 +++++++++++++++++++++++++++++++++++ package_v1.0.py | 251 ++++++++++++++++++++++++++ resources/icons/app_icon.ico | Bin 0 -> 9142 bytes setup.py | 18 +- src/main.py | 2 +- src/ui/ui.txt | 0 字体颜色功能说明.md | 88 ---------- 7 files changed, 600 insertions(+), 90 deletions(-) create mode 100644 build_v1.0.py create mode 100644 package_v1.0.py create mode 100644 resources/icons/app_icon.ico delete mode 100644 src/ui/ui.txt delete mode 100644 字体颜色功能说明.md diff --git a/build_v1.0.py b/build_v1.0.py new file mode 100644 index 0000000..9689a80 --- /dev/null +++ b/build_v1.0.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +MagicWord 1.0.0 版本发布脚本 +用于构建和打包应用程序,包含所有图片和图标资源 +""" + +import os +import sys +import subprocess +import platform +import shutil +import zipfile +from datetime import datetime +from PIL import Image + +def run_command(command, shell=False, cwd=None): + """运行命令并返回结果""" + try: + result = subprocess.run(command, shell=shell, capture_output=True, text=True, encoding='utf-8', cwd=cwd) + return result.returncode, result.stdout, result.stderr + except Exception as e: + return -1, "", str(e) + +def create_ico_from_png(): + """从PNG图标创建ICO文件""" + print("创建ICO图标文件...") + + # 检查是否存在256x256的PNG图标 + png_path = "resources/icons/app_icon_256X256.png" + ico_path = "resources/icons/app_icon.ico" + + if os.path.exists(png_path): + try: + # 打开PNG图像 + img = Image.open(png_path) + + # 创建不同尺寸的图标 + icon_sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)] + + # 保存为ICO格式 + img.save(ico_path, format='ICO', sizes=icon_sizes) + print(f"ICO图标创建成功: {ico_path}") + return True + except Exception as e: + print(f"创建ICO图标失败: {e}") + return False + else: + print(f"找不到PNG图标文件: {png_path}") + return False + +def clean_build_dirs(): + """清理构建目录""" + print("清理构建目录...") + dirs_to_clean = ['build', 'dist', '__pycache__', '*.egg-info'] + + for dir_name in dirs_to_clean: + if '*' in dir_name: + # 处理通配符 + import glob + for path in glob.glob(dir_name): + if os.path.isdir(path): + shutil.rmtree(path, ignore_errors=True) + elif os.path.exists(dir_name): + if os.path.isdir(dir_name): + shutil.rmtree(dir_name, ignore_errors=True) + else: + os.remove(dir_name) + + # 清理src目录下的__pycache__ + for root, dirs, files in os.walk('src'): + for dir_name in dirs: + if dir_name == '__pycache__': + cache_path = os.path.join(root, dir_name) + shutil.rmtree(cache_path, ignore_errors=True) + print(f"清理缓存: {cache_path}") + +def install_dependencies(): + """安装依赖""" + print("安装项目依赖...") + + # 首先安装PIL(用于图标转换) + code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "Pillow"]) + if code != 0: + print(f"Pillow安装失败: {stderr}") + return False + + # 安装其他依赖 + code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"]) + if code != 0: + print(f"依赖安装失败: {stderr}") + return False + print("依赖安装成功") + return True + +def build_executable(): + """构建可执行文件""" + print("构建可执行文件...") + + # 安装pyinstaller + print("安装PyInstaller...") + code, stdout, stderr = run_command([sys.executable, "-m", "pip", "install", "pyinstaller"]) + if code != 0: + print(f"PyInstaller安装失败: {stderr}") + return False + + # 创建ICO图标 + create_ico_from_png() + + # PyInstaller命令 - 完整版本 + pyinstaller_cmd = [ + "pyinstaller", + "--name", "MagicWord", + "--version", "1.0.0", # 设置版本号为1.0.0 + "--distpath", "dist", + "--workpath", "build", + "--specpath", ".", + # 添加资源文件 + "--add-data", "resources;resources", + "--add-data", "resources/icons;resources/icons", + "--add-data", "resources/config;resources/config", + "--add-data", "resources/qss;resources/qss", + "--add-data", "src;src", + "--add-data", "src/ui;src/ui", + "--add-data", "src/demo;src/demo", + # 隐藏导入 + "--hidden-import", "PyQt5", + "--hidden-import", "PyQt5.QtCore", + "--hidden-import", "PyQt5.QtGui", + "--hidden-import", "PyQt5.QtWidgets", + "--hidden-import", "requests", + "--hidden-import", "beautifulsoup4", + "--hidden-import", "python-docx", + "--hidden-import", "PyPDF2", + "--hidden-import", "ebooklib", + "--hidden-import", "chardet", + "--hidden-import", "PIL", + "--hidden-import", "pillow", + # 图标设置 + "--icon", "resources/icons/app_icon.ico" if os.path.exists("resources/icons/app_icon.ico") else "resources/icons/app_icon_256X256.png", + "--windowed", # 无控制台窗口 + "--noconfirm", + "--clean", # 清理临时文件 + "src/main.py" + ] + + print("运行PyInstaller...") + code, stdout, stderr = run_command(pyinstaller_cmd) + + if code != 0: + print(f"完整构建失败,尝试简化构建: {stderr}") + # 简化版本 + simple_cmd = [ + "pyinstaller", + "--onefile", + "--windowed", + "--icon=resources/icons/app_icon.ico" if os.path.exists("resources/icons/app_icon.ico") else "resources/icons/app_icon_256X256.png", + "--add-data=resources;resources", + "--add-data=resources/icons;resources/icons", + "--add-data=src;src", + "--name=MagicWord", + "--version=1.0.0", + "--clean", + "src/main.py" + ] + code, stdout, stderr = run_command(simple_cmd) + if code != 0: + print(f"简化构建也失败: {stderr}") + return False + + print("可执行文件构建成功") + return True + +def create_package(): + """创建发布包""" + print("创建发布包...") + + # 检查构建结果 + if platform.system() == "Windows": + exe_path = "dist/MagicWord.exe" + else: + exe_path = "dist/MagicWord" + + if not os.path.exists(exe_path): + print(f"错误: 找不到可执行文件 {exe_path}") + return False + + # 创建发布目录 + release_dir = "dist_package_v1.0" + if os.path.exists(release_dir): + shutil.rmtree(release_dir) + os.makedirs(release_dir) + + # 复制文件到发布目录 + files_to_copy = [ + (exe_path, "MagicWord.exe" if platform.system() == "Windows" else "MagicWord"), + ("README.md", "README.md"), + ("CHANGELOG.md", "CHANGELOG.md"), + ("requirements.txt", "requirements.txt"), + ("install_and_fix.py", "install_and_fix.py"), + ] + + for src, dst in files_to_copy: + if os.path.exists(src): + shutil.copy2(src, os.path.join(release_dir, dst)) + print(f"复制: {src} -> {dst}") + + # 复制图标文件到发布包 + icons_dir = os.path.join(release_dir, "icons") + if os.path.exists("resources/icons"): + shutil.copytree("resources/icons", icons_dir) + print("复制图标文件到发布包") + + # 创建运行脚本 + if platform.system() == "Windows": + run_script = """@echo off +echo MagicWord 1.0.0 启动中... +cd /d "%~dp0" +start MagicWord.exe +""" + with open(os.path.join(release_dir, "run.bat"), "w") as f: + f.write(run_script) + + # 创建桌面快捷方式脚本 + desktop_shortcut_script = """@echo off +echo 创建桌面快捷方式... +set SCRIPT_DIR=%~dp0 +set DESKTOP=%USERPROFILE%\Desktop +set SHORTCUT=%DESKTOP%\MagicWord.lnk +powershell -Command "$WshShell = New-Object -comObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut('%SHORTCUT%'); $Shortcut.TargetPath = '%SCRIPT_DIR%MagicWord.exe'; $Shortcut.WorkingDirectory = '%SCRIPT_DIR%'; $Shortcut.IconLocation = '%SCRIPT_DIR%icons\\app_icon_256X256.png'; $Shortcut.Save()" +echo 桌面快捷方式创建完成! +pause +""" + with open(os.path.join(release_dir, "create_desktop_shortcut.bat"), "w") as f: + f.write(desktop_shortcut_script) + + else: + run_script = """#!/bin/bash +echo "MagicWord 1.0.0 启动中..." +cd "$(dirname "$0")" +./MagicWord & +""" + with open(os.path.join(release_dir, "run.sh"), "w") as f: + f.write(run_script) + os.chmod(os.path.join(release_dir, "run.sh"), 0o755) + + # 创建发布说明 + release_info = f"""MagicWord 1.0.0 发布包 +构建时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} +平台: {platform.system()} {platform.machine()} +Python版本: {platform.python_version()} + +快速开始: +1. 运行 install_and_fix.py 安装依赖(如果需要) +2. 运行 run.bat (Windows) 或 run.sh (Linux/Mac) +3. 或直接运行 MagicWord.exe + +功能特性: +- 完整的文档处理功能 +- 打字练习模式 +- 学习模式 +- 多种文档格式支持(Word, PDF, TXT等) +- 美观的Word风格界面 +- 完整的图标和界面资源 + +图标说明: +- 包含完整的图标资源文件 +- 支持多种尺寸的图标(32x32, 64x64, 128x128, 256x256) +- Windows版本包含ICO格式图标 +- 可创建桌面快捷方式 + +详细更新请查看 CHANGELOG.md +""" + + with open(os.path.join(release_dir, "发布说明.txt"), "w", encoding='utf-8') as f: + f.write(release_info) + + # 创建ZIP压缩包 + print("创建ZIP压缩包...") + zip_filename = f"MagicWord_v1.0.0_{platform.system()}_{platform.machine()}" + with zipfile.ZipFile(f"{zip_filename}.zip", 'w', zipfile.ZIP_DEFLATED) as zipf: + for root, dirs, files in os.walk(release_dir): + for file in files: + file_path = os.path.join(root, file) + arc_path = os.path.relpath(file_path, release_dir) + zipf.write(file_path, arc_path) + print(f"添加到压缩包: {arc_path}") + + print(f"发布包创建成功: {zip_filename}.zip") + return True + +def main(): + """主函数""" + print("=" * 50) + print("MagicWord 1.0.0 构建脚本") + print("=" * 50) + + # 检查Python版本 + if sys.version_info < (3, 6): + print("错误: 需要Python 3.6或更高版本") + return False + + # 清理构建目录 + clean_build_dirs() + + # 安装依赖 + if not install_dependencies(): + print("依赖安装失败") + return False + + # 构建可执行文件 + if not build_executable(): + print("可执行文件构建失败") + return False + + # 创建发布包 + if not create_package(): + print("发布包创建失败") + return False + + print("=" * 50) + print("构建完成!") + print("发布包位于: dist_package_v1.0/") + print("ZIP压缩包已创建") + print("=" * 50) + + return True + +if __name__ == "__main__": + success = main() + sys.exit(0 if success else 1) \ No newline at end of file diff --git a/package_v1.0.py b/package_v1.0.py new file mode 100644 index 0000000..9ba4472 --- /dev/null +++ b/package_v1.0.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +MagicWord 1.0.0 完整打包脚本 +创建包含所有资源的发布包 +""" + +import os +import sys +import shutil +import zipfile +from datetime import datetime + +def create_package(): + """创建完整的发布包""" + print("=" * 60) + print("MagicWord 1.0.0 完整打包程序") + print("=" * 60) + + # 检查可执行文件是否存在 + exe_path = "dist/MagicWord.exe" + if not os.path.exists(exe_path): + print(f"错误: 找不到可执行文件 {exe_path}") + print("请先运行PyInstaller构建可执行文件") + return False + + # 创建发布目录 + release_dir = "MagicWord_v1.0.0_Windows" + if os.path.exists(release_dir): + shutil.rmtree(release_dir) + os.makedirs(release_dir) + + print("创建发布包目录...") + + # 复制主要文件 + files_to_copy = [ + (exe_path, "MagicWord.exe"), + ("README.md", "README.md"), + ("CHANGELOG.md", "CHANGELOG.md"), + ("requirements.txt", "requirements.txt"), + ("install_and_fix.py", "install_and_fix.py"), + ] + + for src, dst in files_to_copy: + if os.path.exists(src): + shutil.copy2(src, os.path.join(release_dir, dst)) + print(f"✓ 复制: {src} -> {dst}") + else: + print(f"⚠ 跳过: {src} (文件不存在)") + + # 复制图标文件 + icons_dir = os.path.join(release_dir, "icons") + if os.path.exists("resources/icons"): + shutil.copytree("resources/icons", icons_dir) + print("✓ 复制图标文件到发布包") + + # 复制配置文件 + config_dir = os.path.join(release_dir, "config") + if os.path.exists("resources/config"): + shutil.copytree("resources/config", config_dir) + print("✓ 复制配置文件到发布包") + + # 复制样式文件 + qss_dir = os.path.join(release_dir, "qss") + if os.path.exists("resources/qss") and os.listdir("resources/qss"): + shutil.copytree("resources/qss", qss_dir) + print("✓ 复制样式文件到发布包") + + # 注意: UI图像文件已通过PyInstaller打包到可执行文件中 + # 程序会在运行时从打包的资源中加载 114514.png 和 UI.png + + # 创建运行脚本 + print("创建运行脚本...") + + # Windows运行脚本 + run_script = """@echo off +echo ======================================== +echo MagicWord 1.0.0 启动中... +echo ======================================== +cd /d "%~dp0" +start "" "MagicWord.exe" +echo 程序已启动! +timeout /t 3 /nobreak > nul +""" + + with open(os.path.join(release_dir, "运行程序.bat"), "w", encoding='utf-8') as f: + f.write(run_script) + + # 创建桌面快捷方式脚本 + desktop_shortcut_script = """@echo off +echo 正在创建桌面快捷方式... +cd /d "%~dp0" +set SCRIPT_DIR=%CD% +set DESKTOP=%USERPROFILE%\Desktop +set SHORTCUT=%DESKTOP%\MagicWord.lnk + +echo 脚本目录: %SCRIPT_DIR% +echo 桌面路径: %DESKTOP% + +powershell -Command " + $WshShell = New-Object -comObject WScript.Shell + $Shortcut = $WshShell.CreateShortcut('%SHORTCUT%') + $Shortcut.TargetPath = '%SCRIPT_DIR%\MagicWord.exe' + $Shortcut.WorkingDirectory = '%SCRIPT_DIR%' + $Shortcut.IconLocation = '%SCRIPT_DIR%\icons\app_icon_256X256.png' + $Shortcut.Description = 'MagicWord 1.0.0 - 隐私学习软件' + $Shortcut.Save() + Write-Host '桌面快捷方式创建成功!' -ForegroundColor Green +" + +if exist "%SHORTCUT%" ( + echo 桌面快捷方式创建成功! +) else ( + echo 桌面快捷方式创建失败! +) +echo. +echo 按任意键退出... +pause > nul +""" + + with open(os.path.join(release_dir, "创建桌面快捷方式.bat"), "w", encoding='utf-8') as f: + f.write(desktop_shortcut_script) + + # 创建安装说明 + install_guide = """MagicWord 1.0.0 安装使用说明 + +======================================== +系统要求 +======================================== +- Windows 7/8/10/11 (64位) +- 至少 100MB 可用磁盘空间 +- 建议内存: 4GB 以上 + +======================================== +快速开始 +======================================== +方法1: 直接运行 +1. 双击 "MagicWord.exe" 即可运行程序 + +方法2: 使用运行脚本 +1. 双击 "运行程序.bat" 自动启动程序 + +方法3: 创建桌面快捷方式 +1. 双击 "创建桌面快捷方式.bat" +2. 桌面上会出现 MagicWord 快捷方式 +3. 双击桌面快捷方式即可运行 + +======================================== +文件说明 +======================================== +MagicWord.exe - 主程序文件 +icons/ - 图标文件夹 + app_icon.ico - 应用程序图标 + app_icon_256X256.png - 256x256图标 + app_icon_128X128.png - 128x128图标 + app_icon_64X64.png - 64x64图标 + app_icon_32X32.png - 32x32图标 + +config/ - 配置文件 +README.md - 项目说明文档 +CHANGELOG.md - 更新日志 + +======================================== +卸载方法 +======================================== +直接删除整个 MagicWord 文件夹即可完全卸载 + +======================================== +技术支持 +======================================== +如有问题,请查看 README.md 文件或联系开发者 + +======================================== +版本信息 +======================================== +版本: 1.0.0 +构建时间: {build_time} +平台: Windows +架构: {architecture} + +祝您使用愉快! +""".format( + build_time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + architecture="64位" + ) + + with open(os.path.join(release_dir, "安装说明.txt"), "w", encoding='utf-8') as f: + f.write(install_guide) + + # 创建版本信息文件 + version_info = f"""MagicWord Version 1.0.0 +Build Date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} +Platform: Windows +Architecture: 64-bit +Python Version: 3.13 +Qt Version: PyQt5 + +This is a standalone executable package containing all necessary dependencies. +""" + + with open(os.path.join(release_dir, "version.txt"), "w", encoding='utf-8') as f: + f.write(version_info) + + print("创建ZIP压缩包...") + + # 创建ZIP压缩包 + zip_filename = f"MagicWord_v1.0.0_Windows_64bit" + with zipfile.ZipFile(f"{zip_filename}.zip", 'w', zipfile.ZIP_DEFLATED) as zipf: + for root, dirs, files in os.walk(release_dir): + for file in files: + file_path = os.path.join(root, file) + arc_path = os.path.relpath(file_path, release_dir) + zipf.write(file_path, arc_path) + print(f"添加到压缩包: {arc_path}") + + print("=" * 60) + print("✅ 打包完成!") + print(f"📁 发布包目录: {release_dir}/") + print(f"📦 ZIP压缩包: {zip_filename}.zip") + print("=" * 60) + + # 显示发布包内容 + print("\n发布包内容:") + for root, dirs, files in os.walk(release_dir): + level = root.replace(release_dir, '').count(os.sep) + indent = ' ' * 2 * level + print(f"{indent}{os.path.basename(root)}/") + subindent = ' ' * 2 * (level + 1) + for file in files: + print(f"{subindent}{file}") + + return True + +def main(): + """主函数""" + try: + success = create_package() + if success: + print("\n🎉 所有文件已成功打包!") + print("您可以分发 ZIP 文件给用户。") + else: + print("\n❌ 打包过程中出现错误。") + return 1 + except Exception as e: + print(f"\n❌ 发生错误: {e}") + return 1 + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file diff --git a/resources/icons/app_icon.ico b/resources/icons/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9a97f720c9e1ba46ad6ab16e2ea2d7b6a9c472b7 GIT binary patch literal 9142 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.8.10", "PyPDF2>=1.26.0", @@ -24,4 +27,17 @@ setup( ], }, python_requires=">=3.6", + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Education", + "Topic :: Office/Business", + ], ) \ No newline at end of file diff --git a/src/main.py b/src/main.py index b119247..de007be 100644 --- a/src/main.py +++ b/src/main.py @@ -85,7 +85,7 @@ def main(): # 设置应用程序属性 app.setApplicationName("MagicWord") - app.setApplicationVersion("0.2.2") + app.setApplicationVersion("1.0.0") app.setOrganizationName("MagicWord") # 设置窗口图标(如果存在) diff --git a/src/ui/ui.txt b/src/ui/ui.txt deleted file mode 100644 index e69de29..0000000 diff --git a/字体颜色功能说明.md b/字体颜色功能说明.md deleted file mode 100644 index 5f2b43e..0000000 --- a/字体颜色功能说明.md +++ /dev/null @@ -1,88 +0,0 @@ -# 字体颜色功能说明 - -我已经成功为你的MagicWord应用添加了字体颜色工具!以下是添加的功能: - -## 🎯 重要更新:保留之前内容的颜色 - -**根据你的需求,字体颜色功能已修改为保留原有内容的颜色!** - -### 修改后的功能特性 -- ✅ **保留原有内容颜色**:已有文本的颜色完全保持不变 -- ✅ **只影响新输入**:新输入的文本将使用选定的颜色 -- ✅ **智能提示**:选择文本时会提示颜色只对新输入生效 -- ✅ **向后兼容**:不会影响现有的粗体、斜体、下划线等格式 - -## 新增功能 - -### 1. 字体颜色按钮 -- 在"开始"标签页的"字体"组中,添加了一个新的颜色按钮(显示为"A") -- 该按钮位于加粗(B)、斜体(I)、下划线(U)按钮的右侧 - -### 2. 颜色选择功能 -- 点击颜色按钮会弹出颜色选择对话框 -- 用户可以选择任意颜色 -- **重要**:只影响后续输入的文本,不会改变已有内容的颜色 - -## 技术实现 - -### UI界面修改 -1. **word_style_ui.py** 中添加了: - - `color_btn` 按钮创建 - - `create_color_button()` 方法用于创建颜色按钮 - - `on_color_clicked()` 方法作为按钮点击事件的处理函数 - -2. **word_main_window.py** 中修改了: - - 颜色按钮的信号连接 - - `on_color_clicked()` 方法:简化为只设置默认颜色,不影响已有内容 - -### 功能特性 -- 使用 PyQt5 的 `QColorDialog` 提供颜色选择界面 -- **只设置默认文本颜色**,不修改已有内容的格式 -- 智能状态栏提示,告知用户颜色的应用范围 -- 保持与现有字体样式(粗体、斜体、下划线)的一致性 - -## 使用方法 - -### 设置新文本颜色 -1. 点击颜色按钮(A) -2. 在弹出的颜色对话框中选择所需颜色 -3. 点击"确定" -4. **后续输入的所有文本都将使用该颜色** -5. **已有文本的颜色完全保持不变** - -### 颜色选择提示 -- 如果选择了文本,会提示:"字体颜色已设置,新输入的文本将使用该颜色" -- 如果没有选择文本,会显示新颜色的具体信息 - -## 界面位置 - -字体颜色工具位于: -开始标签页 → 字体组 → 样式按钮区域(B、I、U按钮右侧) - -## 🔧 技术实现细节 - -### 修改后的核心逻辑 -```python -def on_color_clicked(self): - """字体颜色按钮点击处理 - 保留之前内容的颜色""" - # 只设置后续输入的默认颜色,不影响已有内容 - self.text_edit.setTextColor(color) - - # 友好的用户提示 - if cursor.hasSelection(): - self.status_bar.showMessage("字体颜色已设置,新输入的文本将使用该颜色", 2000) -``` - -这个实现确保: -- ✅ 用户可以自由设置新文本的颜色 -- ✅ 所有已有内容的颜色完全保留 -- ✅ 用户体验友好,有明确的操作反馈 - -## 🚀 优势 - -1. **非破坏性**:不会意外改变已有内容的格式 -2. **直观易用**:用户明确知道颜色设置的影响范围 -3. **灵活性高**:可以随时更改新文本的颜色而不影响历史内容 -4. **兼容性好**:与所有现有功能完美配合 - -这个新增功能与现有的字体样式工具完美集成,提供了完整且安全的文本格式化能力! \ No newline at end of file -- 2.34.1