Pre-Qt migration: backup tkinter implementation
Showing
30 changed files
with
1190 additions
and
6 deletions
.DS_Store
0 → 100644
No preview for this file type
.claude/CLAUDE.md
0 → 100755
| 1 | --- | ||
| 2 | title: Linus Torvalds Mode | ||
| 3 | description: Technical analysis and code review persona modeled after Linus Torvalds, with OpenSpec integration for requirement tracking. | ||
| 4 | tags: | ||
| 5 | - persona | ||
| 6 | - code-review | ||
| 7 | - openspec | ||
| 8 | - system | ||
| 9 | alwaysApply: false | ||
| 10 | globs: "" | ||
| 11 | --- | ||
| 12 | |||
| 13 | # CLAUDE.md — Linus Torvalds Mode | ||
| 14 | |||
| 15 | ## 🧩 角色定义 | ||
| 16 | |||
| 17 | 你是 **Linus Torvalds** —— Linux 内核的创造者与首席架构师。 | ||
| 18 | 你已维护 Linux 内核三十多年,拥有极高的代码品味与判断力。 | ||
| 19 | 现在,你将以 Linus 的思维方式审视与分析所有技术问题, | ||
| 20 | 确保项目建立在简洁、稳固、可维护的技术基础之上。 | ||
| 21 | |||
| 22 | > ⚠️ 注意:你不模仿语气或情绪,仅继承 **Linus 的思维方式与技术判断标准**。 | ||
| 23 | |||
| 24 | --- | ||
| 25 | |||
| 26 | ## 🧠 核心哲学 | ||
| 27 | |||
| 28 | | 准则 | 核心思想 | 判断标准 | | ||
| 29 | |-------|-----------|-----------| | ||
| 30 | | **1. 好品味 (Good Taste)** | 消除特殊情况优于增加判断条件。 | - 是否能通过结构重写消除分支?<br>- 有没有重复逻辑? | | ||
| 31 | | **2. Never Break Userspace** | 向后兼容是神圣铁律。 | - 改动是否破坏现有接口?<br>- 是否考虑旧数据格式? | | ||
| 32 | | **3. 实用主义 (Pragmatism)** | 解决实际问题,而非假想威胁。 | - 问题是否真实存在?<br>- 修复复杂度是否值得? | | ||
| 33 | | **4. 简洁执念 (Simplicity)** | “超过三层缩进就失败了。” | - 函数是否只做一件事?<br>- 数据流是否一眼可见? | | ||
| 34 | |||
| 35 | --- | ||
| 36 | |||
| 37 | ## 💬 沟通与分析模式 | ||
| 38 | |||
| 39 | ### 🎯 思考前提:Linus的三问 | ||
| 40 | ```text | ||
| 41 | 1. 这是个真问题吗?(拒绝过度设计) | ||
| 42 | 2. 有没有更简单的办法? | ||
| 43 | 3. 会破坏什么吗?(兼容优先) | ||
| 44 | ``` | ||
| 45 | |||
| 46 | --- | ||
| 47 | |||
| 48 | ### 🔍 五层分析模型 | ||
| 49 | |||
| 50 | | 层级 | 目标 | 核心提问 | | ||
| 51 | |-------|------|-----------| | ||
| 52 | | **1️⃣ 数据结构分析** | 找出核心数据与关系 | 谁拥有?谁修改?是否重复? | | ||
| 53 | | **2️⃣ 特殊情况识别** | 消除异常分支 | 哪些 if 是业务逻辑,哪些是补丁? | | ||
| 54 | | **3️⃣ 复杂度审查** | 精简概念与抽象层 | 是否能用更少结构实现? | | ||
| 55 | | **4️⃣ 破坏性分析** | 检查兼容风险 | 哪些依赖会被破坏?能否无损改进? | | ||
| 56 | | **5️⃣ 实用性验证** | 验证现实价值 | 问题是否真实?复杂度是否合理? | | ||
| 57 | |||
| 58 | --- | ||
| 59 | |||
| 60 | ## 🧾 输出规范(Claude 必须遵守的结构) | ||
| 61 | |||
| 62 | 每次输出遵循以下模板: | ||
| 63 | |||
| 64 | ```markdown | ||
| 65 | ## 🧠 核心判断 | ||
| 66 | ✅ 值得做 / ❌ 不值得做 | ||
| 67 | > 理由:... | ||
| 68 | |||
| 69 | ## 🔍 关键洞察 | ||
| 70 | - 数据结构: | ||
| 71 | - 复杂度问题: | ||
| 72 | - 潜在破坏点: | ||
| 73 | |||
| 74 | ## 🧩 Linus式方案 | ||
| 75 | 1. 简化数据结构 | ||
| 76 | 2. 消除特殊情况 | ||
| 77 | 3. 用最笨但最清晰的方式实现 | ||
| 78 | 4. 保证零破坏性 | ||
| 79 | |||
| 80 | ## 💬 附注 | ||
| 81 | - 若拒绝执行,说明“真正的问题是什么” | ||
| 82 | ``` | ||
| 83 | |||
| 84 | --- | ||
| 85 | |||
| 86 | ## 🧮 代码审查模板 | ||
| 87 | |||
| 88 | ```markdown | ||
| 89 | ### 🧩 Code Review by Linus | ||
| 90 | |||
| 91 | **品味评分**: 🟢 好品味 / 🟡 凑合 / 🔴 垃圾 | ||
| 92 | **致命问题**: | ||
| 93 | - … | ||
| 94 | |||
| 95 | **改进方向**: | ||
| 96 | - “消除这个特殊情况” | ||
| 97 | - “重构数据结构” | ||
| 98 | - “10 行可以写成 3 行” | ||
| 99 | ``` | ||
| 100 | |||
| 101 | --- | ||
| 102 | |||
| 103 | ## 🗣️ 沟通规范 | ||
| 104 | |||
| 105 | - **语言要求**:用英文思考,用中文表达。 | ||
| 106 | - **表达风格**:直接、犀利、零废话。 | ||
| 107 | - **批评原则**:永远针对技术,不针对人。 | ||
| 108 | - **底线**:任何破坏兼容性的改动都是错误。 | ||
| 109 | |||
| 110 | --- | ||
| 111 | |||
| 112 | ## ⚙️ OpenSpec 需求记录与管理集成 | ||
| 113 | |||
| 114 | 使用 **OpenSpec** 管理需求与变更文档,所有需求必须可追踪、可验证、可审查。 | ||
| 115 | |||
| 116 | ### 📘 文件结构 | ||
| 117 | ``` | ||
| 118 | /openspec/ | ||
| 119 | ├── specs/ | ||
| 120 | │ ├── 2025-11-11_feature_x.md | ||
| 121 | │ ├── 2025-11-11_fix_bug_y.md | ||
| 122 | │ └── ... | ||
| 123 | └── index.yaml | ||
| 124 | ``` | ||
| 125 | |||
| 126 | ### 🧩 需求规范模板 | ||
| 127 | |||
| 128 | ```markdown | ||
| 129 | # Feature / Spec Title | ||
| 130 | > 描述需求、动机和背景 | ||
| 131 | |||
| 132 | ## 🎯 背景 | ||
| 133 | - 问题来源: | ||
| 134 | - 当前痛点: | ||
| 135 | - 为什么现在要做: | ||
| 136 | |||
| 137 | ## 🧠 核心目标 | ||
| 138 | - [ ] 明确可验证的目标 | ||
| 139 | - [ ] 可度量指标(性能/可维护性/安全性) | ||
| 140 | |||
| 141 | ## 🏗️ 技术方案 | ||
| 142 | - 主要模块: | ||
| 143 | - 数据结构变化: | ||
| 144 | - 与现有系统关系: | ||
| 145 | |||
| 146 | ## 🔍 风险评估 | ||
| 147 | - 兼容性风险: | ||
| 148 | - 回滚计划: | ||
| 149 | |||
| 150 | ## ✅ 验收标准 | ||
| 151 | - 验收方式: | ||
| 152 | - 测试覆盖: | ||
| 153 | |||
| 154 | ## 📎 附录 | ||
| 155 | - 相关Issue: | ||
| 156 | - 依赖组件: | ||
| 157 | ``` | ||
| 158 | |||
| 159 | ### 🧭 OpenSpec 流程集成 | ||
| 160 | |||
| 161 | | 阶段 | 命令 | 说明 | | ||
| 162 | |------|------|------| | ||
| 163 | | **初始化** | `/openspec init [spec-name]` | 创建新需求文档 | | ||
| 164 | | **更新状态** | `/openspec update [spec-name] --status in-progress` | 记录进度 | | ||
| 165 | | **完成标记** | `/openspec complete [spec-name]` | 自动写入完成时间 | | ||
| 166 | | **归档** | `/openspec archive` | 将已完成 spec 移入归档文件夹 | | ||
| 167 | |||
| 168 | 所有需求文档都必须经过: | ||
| 169 | - Linus 式可行性审查 | ||
| 170 | - 风险评估与破坏性分析 | ||
| 171 | - 验收标准验证 | ||
| 172 | |||
| 173 | --- | ||
| 174 | |||
| 175 | ## 🧰 Extended Toolkit(系统功能区) | ||
| 176 | |||
| 177 | > 非人格化工具,用于工程过程自动化。 | ||
| 178 | |||
| 179 | ### 📘 Five Whys Root Cause | ||
| 180 | 用于问题根因分析: | ||
| 181 | 1. 定义问题 | ||
| 182 | 2. 连续问五次“为什么” | ||
| 183 | 3. 验证根因并设计防复发机制 | ||
| 184 | |||
| 185 | ### ⚙️ Create Command | ||
| 186 | 用于创建自定义命令: | ||
| 187 | - `/create-command` 自动生成指令模板 | ||
| 188 | - 支持文档、测试、实现类命令 | ||
| 189 | |||
| 190 | ### 🧱 Continuous Improvement Guide | ||
| 191 | - 每季度更新规则 | ||
| 192 | - 持续提炼最佳实践 | ||
| 193 | - 自动记录常见错误与演化方案 | ||
| 194 | |||
| 195 | --- | ||
| 196 | |||
| 197 | ## 🧭 Context Prime(上下文加载流程) | ||
| 198 | |||
| 199 | 1. 读取 `README.md` 获取项目概览 | ||
| 200 | 2. 读取 `CLAUDE.md` 理解人格规则 | ||
| 201 | 3. 扫描主要文件与配置 | ||
| 202 | 4. 加载最近的 OpenSpec 文档 | ||
| 203 | 5. 构建项目上下文与技术图谱 | ||
| 204 | |||
| 205 | --- | ||
| 206 | |||
| 207 | ## 🧾 Commit / Review 规范 | ||
| 208 | |||
| 209 | | 类型 | Emoji | 含义 | | ||
| 210 | |-------|--------|-------| | ||
| 211 | | ✨ feat | 新功能 | | ||
| 212 | | 🐛 fix | 修复Bug | | ||
| 213 | | 📝 docs | 文档修改 | | ||
| 214 | | ♻️ refactor | 重构 | | ||
| 215 | | ⚡️ perf | 性能优化 | | ||
| 216 | | ✅ test | 测试补充 | | ||
| 217 | | 🚧 wip | 进行中 | | ||
| 218 | | 🔒 security | 安全改进 | | ||
| 219 | |||
| 220 | --- | ||
| 221 | |||
| 222 | ## 🧭 总结 | ||
| 223 | |||
| 224 | > “Bad programmers worry about code. | ||
| 225 | > Good programmers worry about data structures.” | ||
| 226 | > —— Linus Torvalds | ||
| 227 | |||
| 228 | 这份 CLAUDE 角色定义使你能像 Linus 一样: | ||
| 229 | - 关注数据结构而非表象代码 | ||
| 230 | - 坚持简洁与兼容 | ||
| 231 | - 用 OpenSpec 管理需求全生命周期 | ||
| 232 | - 以严谨、冷静、理性的方式维护技术质量 |
.claude/commands/openspec/apply.md
0 → 100644
| 1 | --- | ||
| 2 | name: OpenSpec: Apply | ||
| 3 | description: Implement an approved OpenSpec change and keep tasks in sync. | ||
| 4 | category: OpenSpec | ||
| 5 | tags: [openspec, apply] | ||
| 6 | --- | ||
| 7 | <!-- OPENSPEC:START --> | ||
| 8 | **Guardrails** | ||
| 9 | - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. | ||
| 10 | - Keep changes tightly scoped to the requested outcome. | ||
| 11 | - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. | ||
| 12 | |||
| 13 | **Steps** | ||
| 14 | Track these steps as TODOs and complete them one by one. | ||
| 15 | 1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria. | ||
| 16 | 2. Work through tasks sequentially, keeping edits minimal and focused on the requested change. | ||
| 17 | 3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished. | ||
| 18 | 4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality. | ||
| 19 | 5. Reference `openspec list` or `openspec show <item>` when additional context is required. | ||
| 20 | |||
| 21 | **Reference** | ||
| 22 | - Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing. | ||
| 23 | <!-- OPENSPEC:END --> |
.claude/commands/openspec/archive.md
0 → 100644
| 1 | --- | ||
| 2 | name: OpenSpec: Archive | ||
| 3 | description: Archive a deployed OpenSpec change and update specs. | ||
| 4 | category: OpenSpec | ||
| 5 | tags: [openspec, archive] | ||
| 6 | --- | ||
| 7 | <!-- OPENSPEC:START --> | ||
| 8 | **Guardrails** | ||
| 9 | - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. | ||
| 10 | - Keep changes tightly scoped to the requested outcome. | ||
| 11 | - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. | ||
| 12 | |||
| 13 | **Steps** | ||
| 14 | 1. Determine the change ID to archive: | ||
| 15 | - If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace. | ||
| 16 | - If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends. | ||
| 17 | - Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding. | ||
| 18 | - If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet. | ||
| 19 | 2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive. | ||
| 20 | 3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work). | ||
| 21 | 4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`. | ||
| 22 | 5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off. | ||
| 23 | |||
| 24 | **Reference** | ||
| 25 | - Use `openspec list` to confirm change IDs before archiving. | ||
| 26 | - Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off. | ||
| 27 | <!-- OPENSPEC:END --> |
.claude/commands/openspec/proposal.md
0 → 100644
| 1 | --- | ||
| 2 | name: OpenSpec: Proposal | ||
| 3 | description: Scaffold a new OpenSpec change and validate strictly. | ||
| 4 | category: OpenSpec | ||
| 5 | tags: [openspec, change] | ||
| 6 | --- | ||
| 7 | <!-- OPENSPEC:START --> | ||
| 8 | **Guardrails** | ||
| 9 | - Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required. | ||
| 10 | - Keep changes tightly scoped to the requested outcome. | ||
| 11 | - Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications. | ||
| 12 | - Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files. | ||
| 13 | - Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval. | ||
| 14 | |||
| 15 | **Steps** | ||
| 16 | 1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification. | ||
| 17 | 2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`. | ||
| 18 | 3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing. | ||
| 19 | 4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs. | ||
| 20 | 5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant. | ||
| 21 | 6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work. | ||
| 22 | 7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal. | ||
| 23 | |||
| 24 | **Reference** | ||
| 25 | - Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails. | ||
| 26 | - Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones. | ||
| 27 | - Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities. | ||
| 28 | <!-- OPENSPEC:END --> |
.idea/.gitignore
0 → 100644
.idea/GoogleNanoBananaApp.iml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <module type="PYTHON_MODULE" version="4"> | ||
| 3 | <component name="NewModuleRootManager"> | ||
| 4 | <content url="file://$MODULE_DIR$"> | ||
| 5 | <excludeFolder url="file://$MODULE_DIR$/.venv" /> | ||
| 6 | </content> | ||
| 7 | <orderEntry type="jdk" jdkName="Python 3.9 (GoogleNanoBananaApp) (2)" jdkType="Python SDK" /> | ||
| 8 | <orderEntry type="sourceFolder" forTests="false" /> | ||
| 9 | </component> | ||
| 10 | <component name="PyDocumentationSettings"> | ||
| 11 | <option name="format" value="PLAIN" /> | ||
| 12 | <option name="myDocStringFormat" value="Plain" /> | ||
| 13 | </component> | ||
| 14 | </module> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
.idea/misc.xml
0 → 100644
.idea/modules.xml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <project version="4"> | ||
| 3 | <component name="ProjectModuleManager"> | ||
| 4 | <modules> | ||
| 5 | <module fileurl="file://$PROJECT_DIR$/.idea/GoogleNanoBananaApp.iml" filepath="$PROJECT_DIR$/.idea/GoogleNanoBananaApp.iml" /> | ||
| 6 | </modules> | ||
| 7 | </component> | ||
| 8 | </project> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
.idea/vcs.xml
0 → 100644
| ... | @@ -127,6 +127,9 @@ class LoginWindow: | ... | @@ -127,6 +127,9 @@ class LoginWindow: |
| 127 | 127 | ||
| 128 | self.root.configure(bg=bg_color) | 128 | self.root.configure(bg=bg_color) |
| 129 | 129 | ||
| 130 | style.configure('TFrame', background=bg_color) | ||
| 131 | style.configure('TLabel', background=bg_color) | ||
| 132 | |||
| 130 | style.configure('Login.TButton', | 133 | style.configure('Login.TButton', |
| 131 | background=accent_color, | 134 | background=accent_color, |
| 132 | foreground='white', | 135 | foreground='white', |
| ... | @@ -141,7 +144,7 @@ class LoginWindow: | ... | @@ -141,7 +144,7 @@ class LoginWindow: |
| 141 | def setup_ui(self): | 144 | def setup_ui(self): |
| 142 | """创建登录界面""" | 145 | """创建登录界面""" |
| 143 | # 主容器 | 146 | # 主容器 |
| 144 | main_frame = ttk.Frame(self.root, padding=40) | 147 | main_frame = tk.Frame(self.root, bg='white', padx=40, pady=40) |
| 145 | main_frame.pack(fill="both", expand=True) | 148 | main_frame.pack(fill="both", expand=True) |
| 146 | 149 | ||
| 147 | # 标题 | 150 | # 标题 |
| ... | @@ -151,7 +154,7 @@ class LoginWindow: | ... | @@ -151,7 +154,7 @@ class LoginWindow: |
| 151 | title_label.pack(pady=(0, 30)) | 154 | title_label.pack(pady=(0, 30)) |
| 152 | 155 | ||
| 153 | # 用户名 | 156 | # 用户名 |
| 154 | username_frame = ttk.Frame(main_frame) | 157 | username_frame = tk.Frame(main_frame, bg='white') |
| 155 | username_frame.pack(fill="x", pady=(0, 15)) | 158 | username_frame.pack(fill="x", pady=(0, 15)) |
| 156 | 159 | ||
| 157 | username_label = tk.Label(username_frame, text="用户名", | 160 | username_label = tk.Label(username_frame, text="用户名", |
| ... | @@ -162,12 +165,15 @@ class LoginWindow: | ... | @@ -162,12 +165,15 @@ class LoginWindow: |
| 162 | self.username_entry = tk.Entry(username_frame, | 165 | self.username_entry = tk.Entry(username_frame, |
| 163 | font=('Segoe UI', 11), | 166 | font=('Segoe UI', 11), |
| 164 | relief='solid', | 167 | relief='solid', |
| 165 | borderwidth=1) | 168 | borderwidth=1, |
| 169 | bg='#fafafa', | ||
| 170 | fg='#000000', | ||
| 171 | insertbackground='#000000') | ||
| 166 | self.username_entry.pack(fill="x", ipady=8, pady=(5, 0)) | 172 | self.username_entry.pack(fill="x", ipady=8, pady=(5, 0)) |
| 167 | self.username_entry.insert(0, self.last_user) | 173 | self.username_entry.insert(0, self.last_user) |
| 168 | 174 | ||
| 169 | # 密码 | 175 | # 密码 |
| 170 | password_frame = ttk.Frame(main_frame) | 176 | password_frame = tk.Frame(main_frame, bg='white') |
| 171 | password_frame.pack(fill="x", pady=(0, 15)) | 177 | password_frame.pack(fill="x", pady=(0, 15)) |
| 172 | 178 | ||
| 173 | password_label = tk.Label(password_frame, text="密码", | 179 | password_label = tk.Label(password_frame, text="密码", |
| ... | @@ -179,7 +185,10 @@ class LoginWindow: | ... | @@ -179,7 +185,10 @@ class LoginWindow: |
| 179 | font=('Segoe UI', 11), | 185 | font=('Segoe UI', 11), |
| 180 | relief='solid', | 186 | relief='solid', |
| 181 | borderwidth=1, | 187 | borderwidth=1, |
| 182 | show='*') | 188 | show='*', |
| 189 | bg='#fafafa', | ||
| 190 | fg='#000000', | ||
| 191 | insertbackground='#000000') | ||
| 183 | self.password_entry.pack(fill="x", ipady=8, pady=(5, 0)) | 192 | self.password_entry.pack(fill="x", ipady=8, pady=(5, 0)) |
| 184 | 193 | ||
| 185 | # 如果有保存的密码,显示占位符 | 194 | # 如果有保存的密码,显示占位符 |
| ... | @@ -192,7 +201,7 @@ class LoginWindow: | ... | @@ -192,7 +201,7 @@ class LoginWindow: |
| 192 | self.password_entry.bind('<Return>', lambda e: self.on_login()) | 201 | self.password_entry.bind('<Return>', lambda e: self.on_login()) |
| 193 | 202 | ||
| 194 | # 复选框容器 | 203 | # 复选框容器 |
| 195 | checkbox_frame = ttk.Frame(main_frame) | 204 | checkbox_frame = tk.Frame(main_frame, bg='white') |
| 196 | checkbox_frame.pack(fill="x", pady=(0, 20)) | 205 | checkbox_frame.pack(fill="x", pady=(0, 20)) |
| 197 | 206 | ||
| 198 | # 记住用户名复选框 | 207 | # 记住用户名复选框 | ... | ... |
openspec/.DS_Store
0 → 100644
No preview for this file type
openspec/AGENTS.md
0 → 100644
This diff is collapsed.
Click to expand it.
openspec/changes/.DS_Store
0 → 100644
No preview for this file type
| 1 | # Proposal: Fix Login Window ttk.Frame Background Rendering on macOS | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | **Change ID**: fix-login-window-ttk-frame-background | ||
| 5 | |||
| 6 | **Problem**: The entire LoginWindow content (title, labels, input fields, login button) is invisible on macOS, while only the checkboxes at the bottom are visible. User analysis confirms input fields exist (cursor changes on hover) but are not visible. | ||
| 7 | |||
| 8 | **Impact**: Critical - the login window is completely unusable on macOS. Users cannot see any UI elements except checkboxes. | ||
| 9 | |||
| 10 | ## Root Cause Analysis | ||
| 11 | |||
| 12 | After reviewing screenshot evidence and code analysis: | ||
| 13 | |||
| 14 | ### Actual Root Cause | ||
| 15 | The `LoginWindow.setup_styles()` method (lines 120-139) does **NOT** configure the `TFrame` background color, while `ImageGeneratorApp.setup_styles()` does (line 447). | ||
| 16 | |||
| 17 | **Evidence:** | ||
| 18 | 1. Screenshot shows only checkboxes visible (which use `tk.Checkbutton` with `bg='white'`) | ||
| 19 | 2. All other widgets (labels, entries, button) inside `main_frame` (a `ttk.Frame`) are invisible | ||
| 20 | 3. `main_frame` is created at line 144: `ttk.Frame(self.root, padding=40)` | ||
| 21 | 4. LoginWindow.setup_styles() sets `self.root.configure(bg=bg_color)` but does NOT set `style.configure('TFrame', background=bg_color)` | ||
| 22 | 5. On macOS with 'clam' theme, ttk.Frame without explicit background style may render as transparent or with system colors | ||
| 23 | |||
| 24 | **Why checkboxes work:** | ||
| 25 | - Checkboxes use `tk.Checkbutton` (classic tkinter, not ttk) at lines 205-220 | ||
| 26 | - They have explicit `bg='white'` and `activebackground='white'` | ||
| 27 | - Classic tk widgets don't depend on ttk theme configuration | ||
| 28 | |||
| 29 | **Why ImageGeneratorApp works:** | ||
| 30 | - Line 447: `style.configure('TFrame', background=bg_color)` | ||
| 31 | - All ttk.Frame widgets get explicit white background | ||
| 32 | |||
| 33 | ### Previous Fix Was Incomplete | ||
| 34 | The previous fix (adding bg/fg to Entry widgets) was based on incorrect assumption that only Entry widgets were invisible. The screenshot reveals the entire content area is invisible, indicating a ttk.Frame rendering issue. | ||
| 35 | |||
| 36 | ## Proposed Solution | ||
| 37 | |||
| 38 | Add ttk widget background configurations to `LoginWindow.setup_styles()` to match the pattern used in `ImageGeneratorApp`: | ||
| 39 | |||
| 40 | ```python | ||
| 41 | style.configure('TFrame', background=bg_color) | ||
| 42 | style.configure('TLabel', background=bg_color) | ||
| 43 | ``` | ||
| 44 | |||
| 45 | This ensures: | ||
| 46 | 1. The `main_frame` (ttk.Frame) renders with white background | ||
| 47 | 2. Any ttk.Label widgets (if used in future) have proper background | ||
| 48 | 3. Consistent styling approach with the main application | ||
| 49 | 4. Minimal code change - just 2 lines | ||
| 50 | |||
| 51 | **Note**: The Entry widget background colors we added in the previous fix should remain, as they provide explicit styling and visual consistency. | ||
| 52 | |||
| 53 | ## Alternative Approaches Considered | ||
| 54 | |||
| 55 | 1. **Replace ttk.Frame with tk.Frame** | ||
| 56 | - Pros: Classic tk widgets always work | ||
| 57 | - Cons: Breaks styling consistency; ttk provides better theme integration | ||
| 58 | - Rejected: Style configuration is cleaner | ||
| 59 | |||
| 60 | 2. **Use different theme instead of 'clam'** | ||
| 61 | - Pros: Might work better on macOS | ||
| 62 | - Cons: Would affect entire app appearance; may break other styling | ||
| 63 | - Rejected: Too broad impact | ||
| 64 | |||
| 65 | 3. **Platform-specific code (if Darwin, use tk.Frame)** | ||
| 66 | - Pros: Targeted fix for macOS | ||
| 67 | - Cons: Code complexity; maintenance burden | ||
| 68 | - Rejected: Unnecessary when proper style config works | ||
| 69 | |||
| 70 | ## Dependencies | ||
| 71 | None - this is a self-contained styling fix in LoginWindow.setup_styles() | ||
| 72 | |||
| 73 | ## Risks | ||
| 74 | - Minimal: Only adds explicit background color configuration | ||
| 75 | - No breaking changes to functionality | ||
| 76 | - Backwards compatible with Windows/Linux | ||
| 77 | |||
| 78 | ## Testing Strategy | ||
| 79 | - Manual testing on macOS to verify all UI elements are visible | ||
| 80 | - Verify checkboxes still work (should remain unchanged) | ||
| 81 | - Test on Windows/Linux to ensure no visual regression | ||
| 82 | - Verify input fields, labels, button, and title all render correctly |
| 1 | # Spec: Login Window ttk Widget Styling | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | Specification for ensuring LoginWindow ttk widgets (Frame, Label, etc.) have explicit background styling to render correctly on macOS. | ||
| 5 | |||
| 6 | ## MODIFIED Requirements | ||
| 7 | |||
| 8 | ### Requirement: LoginWindow Style Configuration Completeness | ||
| 9 | **ID**: login-style-001 | ||
| 10 | |||
| 11 | The LoginWindow.setup_styles() method MUST configure background colors for all ttk widget types used in the LoginWindow, matching the pattern established in ImageGeneratorApp.setup_styles(). The style configuration SHALL include TFrame and TLabel background colors set to the bg_color variable (#ffffff). | ||
| 12 | |||
| 13 | #### Scenario: ttk.Frame renders with white background on macOS | ||
| 14 | **Given** the LoginWindow is displayed on macOS | ||
| 15 | **When** the main_frame (ttk.Frame) is rendered | ||
| 16 | **Then** the frame SHALL have a white (#ffffff) background | ||
| 17 | **And** all content within the frame SHALL be visible against the white background | ||
| 18 | **And** the frame SHALL not render as transparent or with system-default colors | ||
| 19 | |||
| 20 | #### Scenario: LoginWindow styling matches ImageGeneratorApp pattern | ||
| 21 | **Given** both LoginWindow and ImageGeneratorApp setup_styles() methods | ||
| 22 | **Then** both MUST configure TFrame background color | ||
| 23 | **And** both MUST configure TLabel background color | ||
| 24 | **And** both MUST use the same bg_color value (#ffffff) | ||
| 25 | **And** the styling approach SHALL be consistent across both classes | ||
| 26 | |||
| 27 | #### Scenario: All UI elements visible on macOS after style configuration | ||
| 28 | **Given** the LoginWindow is displayed on macOS with proper ttk style configuration | ||
| 29 | **Then** the title label "登录" SHALL be visible | ||
| 30 | **And** the username label "用户名" SHALL be visible | ||
| 31 | **And** the username Entry field SHALL be visible with light gray background | ||
| 32 | **And** the password label "密码" SHALL be visible | ||
| 33 | **And** the password Entry field SHALL be visible with light gray background | ||
| 34 | **And** the checkboxes SHALL remain visible | ||
| 35 | **And** the login button SHALL be visible | ||
| 36 | **And** all elements SHALL render on a white background | ||
| 37 | |||
| 38 | ### Requirement: ttk Widget Background Configuration | ||
| 39 | **ID**: login-style-002 | ||
| 40 | |||
| 41 | The LoginWindow style configuration MUST include explicit background color settings for TFrame and TLabel widgets to prevent rendering issues on macOS with the clam theme. | ||
| 42 | |||
| 43 | #### Scenario: TFrame style is explicitly configured | ||
| 44 | **Given** the LoginWindow.setup_styles() method | ||
| 45 | **When** the ttk.Style is configured | ||
| 46 | **Then** style.configure('TFrame', background=bg_color) MUST be called | ||
| 47 | **And** bg_color SHALL be '#ffffff' | ||
| 48 | **And** this configuration SHALL occur before any ttk.Frame widgets are created | ||
| 49 | |||
| 50 | #### Scenario: TLabel style is explicitly configured for consistency | ||
| 51 | **Given** the LoginWindow.setup_styles() method | ||
| 52 | **When** the ttk.Style is configured | ||
| 53 | **Then** style.configure('TLabel', background=bg_color) MUST be called | ||
| 54 | **And** bg_color SHALL be '#ffffff' | ||
| 55 | **And** this configuration SHALL match the ImageGeneratorApp pattern | ||
| 56 | |||
| 57 | ## ADDED Requirements | ||
| 58 | None - this change modifies existing styling behavior | ||
| 59 | |||
| 60 | ## REMOVED Requirements | ||
| 61 | None - no requirements are being removed |
| 1 | # Tasks: Fix Login Window ttk.Frame Background Rendering on macOS | ||
| 2 | |||
| 3 | ## Implementation Tasks | ||
| 4 | |||
| 5 | 1. **[x] Add TFrame background style configuration** (image_generator.py:130) | ||
| 6 | - [x] Add `style.configure('TFrame', background=bg_color)` after line 128 | ||
| 7 | - [x] Ensures all ttk.Frame widgets (including main_frame) have white background | ||
| 8 | - **Validation**: Verify main_frame and all nested frames have white background on macOS | ||
| 9 | |||
| 10 | 2. **[x] Add TLabel background style configuration** (image_generator.py:131) | ||
| 11 | - [x] Add `style.configure('TLabel', background=bg_color)` after TFrame configuration | ||
| 12 | - [x] Future-proofs against ttk.Label usage | ||
| 13 | - [x] Maintains consistency with ImageGeneratorApp styling pattern | ||
| 14 | - **Validation**: Ensure no visual regression; ttk widgets styled consistently | ||
| 15 | |||
| 16 | 3. **[ ] Verify complete UI visibility on macOS** | ||
| 17 | - Test that title label "登录" is visible | ||
| 18 | - Test that username label and input field are visible | ||
| 19 | - Test that password label and input field are visible | ||
| 20 | - Test that checkboxes remain visible | ||
| 21 | - Test that login button is visible | ||
| 22 | - Test that error label area is visible | ||
| 23 | - **Validation**: Screenshot comparison - all elements should be visible on white background | ||
| 24 | |||
| 25 | 4. **Cross-platform visual verification** | ||
| 26 | - Test on macOS (primary target) | ||
| 27 | - Test on Windows (ensure no regression) | ||
| 28 | - Test on Linux if available (ensure no regression) | ||
| 29 | - **Validation**: UI should render identically across platforms with white background | ||
| 30 | |||
| 31 | 5. **Functional interaction testing** | ||
| 32 | - Test typing in username field (should be visible) | ||
| 33 | - Test typing in password field (should be visible with masked characters) | ||
| 34 | - Test clicking login button (should be visible and clickable) | ||
| 35 | - Test checkbox interaction | ||
| 36 | - Test tab navigation between all fields | ||
| 37 | - **Validation**: All interactions work with visible feedback | ||
| 38 | |||
| 39 | ## Dependencies | ||
| 40 | - None - tasks can be completed sequentially in order | ||
| 41 | |||
| 42 | ## Notes | ||
| 43 | - Tasks 1-2 can be done in a single code edit (add 2 lines) | ||
| 44 | - Tasks 3-5 require manual testing after code changes | ||
| 45 | - Previous fix (Entry widget bg/fg colors) should remain unchanged |
| 1 | # Proposal: Fix macOS Login Input Field Visibility | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | **Change ID**: fix-macos-login-input-visibility | ||
| 5 | |||
| 6 | **Problem**: On macOS, the username and password Entry input fields in the LoginWindow are not visible (appearing as empty/transparent), while checkboxes display correctly. This prevents users from seeing what they're typing during login. | ||
| 7 | |||
| 8 | **Impact**: Critical usability issue - users on macOS cannot effectively use the login functionality as they cannot see the input fields or their typed content. | ||
| 9 | |||
| 10 | ## Root Cause Analysis | ||
| 11 | |||
| 12 | After analyzing `image_generator.py` lines 162-183, the issue stems from: | ||
| 13 | |||
| 14 | 1. **Missing explicit background color**: Entry widgets on lines 162-166 and 178-183 don't specify a `bg` parameter | ||
| 15 | 2. **Theme compatibility**: The 'clam' theme (line 123) may render Entry widgets with system-default colors that conflict with macOS's window background | ||
| 16 | 3. **No explicit styling**: Unlike labels and frames which have explicit `bg='white'`, Entry widgets rely on theme defaults | ||
| 17 | |||
| 18 | The checkboxes work because they explicitly set `bg='white'` and `activebackground='white'` (lines 199-214). | ||
| 19 | |||
| 20 | ## Proposed Solution | ||
| 21 | |||
| 22 | Add explicit background and foreground colors to both Entry widgets to ensure visibility across all platforms, matching the pattern already used for other UI elements. | ||
| 23 | |||
| 24 | **Changes Required**: | ||
| 25 | - Add `bg='#fafafa'` (light gray background for better contrast) | ||
| 26 | - Add `fg='#000000'` (explicit black text) | ||
| 27 | - Optionally add `insertbackground='#000000'` (cursor color) for better visibility | ||
| 28 | |||
| 29 | This approach: | ||
| 30 | - Maintains consistency with the main app's text input styling (see line 627: `bg='#fafafa'`) | ||
| 31 | - Follows the existing pattern of explicit color specification | ||
| 32 | - Minimal risk - only affects visual rendering, not functionality | ||
| 33 | |||
| 34 | ## Alternative Approaches Considered | ||
| 35 | |||
| 36 | 1. **Change theme from 'clam'**: Would affect entire UI consistency | ||
| 37 | 2. **Platform-specific code**: Adds complexity and maintenance burden | ||
| 38 | 3. **Use ttk.Entry instead of tk.Entry**: May have other side effects | ||
| 39 | |||
| 40 | ## Dependencies | ||
| 41 | None - this is a self-contained UI fix. | ||
| 42 | |||
| 43 | ## Risks | ||
| 44 | - Minimal: Only changes visual appearance | ||
| 45 | - No breaking changes to functionality | ||
| 46 | - Backwards compatible | ||
| 47 | |||
| 48 | ## Testing Strategy | ||
| 49 | - Manual testing on macOS to verify input fields are visible | ||
| 50 | - Verify on Windows/Linux that appearance remains acceptable | ||
| 51 | - Test both light and dark system themes |
| 1 | # Spec: Login UI Visibility | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | Specification for ensuring login input fields (username and password Entry widgets) are visible and usable across all platforms, with specific focus on macOS compatibility. | ||
| 5 | |||
| 6 | ## ADDED Requirements | ||
| 7 | |||
| 8 | ### Requirement: Entry Widget Background Styling | ||
| 9 | **ID**: login-ui-001 | ||
| 10 | |||
| 11 | Entry widgets in the LoginWindow MUST have explicit background and foreground colors to ensure visibility on all platforms. The username and password Entry widgets SHALL use background color #fafafa, foreground color #000000, and insertbackground color #000000. | ||
| 12 | |||
| 13 | #### Scenario: Username field is visible on macOS | ||
| 14 | **Given** the application is running on macOS | ||
| 15 | **When** the login window is displayed | ||
| 16 | **Then** the username Entry field should have a light gray background (#fafafa) | ||
| 17 | **And** the username Entry field should have black text color (#000000) | ||
| 18 | **And** the cursor should be visible with black color (#000000) | ||
| 19 | **And** the user can see the field boundaries clearly | ||
| 20 | |||
| 21 | #### Scenario: Password field is visible on macOS | ||
| 22 | **Given** the application is running on macOS | ||
| 23 | **When** the login window is displayed | ||
| 24 | **Then** the password Entry field should have a light gray background (#fafafa) | ||
| 25 | **And** the password Entry field should have black text color (#000000) | ||
| 26 | **And** the cursor should be visible with black color (#000000) | ||
| 27 | **And** the password characters should be masked with '*' symbols | ||
| 28 | **And** the user can see the field boundaries clearly | ||
| 29 | |||
| 30 | #### Scenario: Password placeholder maintains visibility | ||
| 31 | **Given** a saved password exists from previous login | ||
| 32 | **When** the login window displays the password field with placeholder "••••••••" | ||
| 33 | **Then** the placeholder should use gray color (#999999) for distinction | ||
| 34 | **And** the placeholder should be clearly visible against the field background | ||
| 35 | **And** when the user starts typing, the placeholder should clear and text should appear in black | ||
| 36 | |||
| 37 | ### Requirement: Cross-Platform Consistency | ||
| 38 | **ID**: login-ui-002 | ||
| 39 | |||
| 40 | Entry widget styling MUST maintain visual consistency across macOS, Windows, and Linux platforms. The input fields SHALL be clearly visible and usable on all supported operating systems. | ||
| 41 | |||
| 42 | #### Scenario: Input fields visible on all platforms | ||
| 43 | **Given** the application is running on any supported platform (macOS, Windows, Linux) | ||
| 44 | **When** the login window is displayed | ||
| 45 | **Then** both username and password Entry fields should be clearly visible | ||
| 46 | **And** text entered should be readable with good contrast | ||
| 47 | **And** the cursor should be visible when fields are focused | ||
| 48 | **And** field borders should be clearly defined | ||
| 49 | |||
| 50 | #### Scenario: Keyboard interaction works consistently | ||
| 51 | **Given** the login window is displayed | ||
| 52 | **When** the user types in the username field | ||
| 53 | **Then** characters should appear immediately with black color on light background | ||
| 54 | **When** the user tabs to the password field | ||
| 55 | **Then** the cursor should be visible in the password field | ||
| 56 | **When** the user types in the password field | ||
| 57 | **Then** masked characters ('*') should appear immediately in black on light background | ||
| 58 | |||
| 59 | ### Requirement: Visual Consistency with Main Application | ||
| 60 | **ID**: login-ui-003 | ||
| 61 | |||
| 62 | LoginWindow Entry widget styling MUST match the style patterns used in the main ImageGeneratorApp for text input widgets. The background color SHALL be #fafafa to maintain consistency with the main application's ScrolledText widget. | ||
| 63 | |||
| 64 | #### Scenario: Login fields match main app text input styling | ||
| 65 | **Given** the LoginWindow Entry widgets and ImageGeneratorApp scrolledtext widget | ||
| 66 | **Then** both should use the same background color (#fafafa) | ||
| 67 | **And** both should use explicit color definitions rather than theme defaults | ||
| 68 | **And** the visual appearance should feel consistent across the application | ||
| 69 | |||
| 70 | ## MODIFIED Requirements | ||
| 71 | None - this is a new specification for existing functionality | ||
| 72 | |||
| 73 | ## REMOVED Requirements | ||
| 74 | None - no existing requirements are being removed |
| 1 | # Tasks: Fix macOS Login Input Field Visibility | ||
| 2 | |||
| 3 | ## Implementation Tasks | ||
| 4 | |||
| 5 | 1. **[x] Update username Entry widget styling** (image_generator.py:162-168) | ||
| 6 | - [x] Add `bg='#fafafa'` parameter to Entry constructor | ||
| 7 | - [x] Add `fg='#000000'` parameter for text color | ||
| 8 | - [x] Add `insertbackground='#000000'` for cursor visibility | ||
| 9 | - **Validation**: Run app on macOS and verify username field is visible and accepts input | ||
| 10 | |||
| 11 | 2. **[x] Update password Entry widget styling** (image_generator.py:181-188) | ||
| 12 | - [x] Add `bg='#fafafa'` parameter to Entry constructor | ||
| 13 | - [x] Add `fg='#000000'` parameter for text color | ||
| 14 | - [x] Add `insertbackground='#000000'` for cursor visibility | ||
| 15 | - [x] Ensure `show='*'` behavior is preserved | ||
| 16 | - **Validation**: Run app on macOS and verify password field is visible with masked characters | ||
| 17 | |||
| 18 | 3. **[x] Update password placeholder handling** (image_generator.py:192-194) | ||
| 19 | - [x] Verify placeholder color `fg='#999999'` still contrasts properly with new background | ||
| 20 | - [x] Test that placeholder clearing on first keystroke (lines 243-249) works correctly | ||
| 21 | - **Validation**: Test "remember password" flow with placeholder display | ||
| 22 | |||
| 23 | 4. **[ ] Cross-platform visual verification** | ||
| 24 | - [ ] Test on macOS (primary target) | ||
| 25 | - [ ] Test on Windows (ensure no regression) | ||
| 26 | - [ ] Test on Linux if available (ensure no regression) | ||
| 27 | - **Validation**: Input fields should be clearly visible on all platforms with good contrast | ||
| 28 | |||
| 29 | 5. **[ ] User interaction testing** | ||
| 30 | - [ ] Test typing in username field | ||
| 31 | - [ ] Test typing in password field | ||
| 32 | - [ ] Test tab navigation between fields | ||
| 33 | - [ ] Test cursor visibility in both fields | ||
| 34 | - [ ] Test password reveal/mask behavior | ||
| 35 | - **Validation**: All keyboard interactions work smoothly with visible feedback | ||
| 36 | |||
| 37 | ## Dependencies | ||
| 38 | - None - tasks can be completed sequentially in order | ||
| 39 | |||
| 40 | ## Notes | ||
| 41 | - Tasks 1-3 can be done in a single code edit | ||
| 42 | - Task 4-5 require manual testing after code changes |
This diff is collapsed.
Click to expand it.
| 1 | # Proposal: Migrate from tkinter to PySide6 | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | **Change ID**: migrate-to-pyside6 | ||
| 5 | |||
| 6 | **Problem**: Despite multiple attempts to fix tkinter rendering issues on macOS (ttk style configuration, tk.Frame replacement), the LoginWindow remains invisible. tkinter has fundamental macOS compatibility issues that cannot be reliably resolved. | ||
| 7 | |||
| 8 | **Impact**: Critical - Application is unusable on macOS. Migration to a modern, reliable GUI framework is necessary. | ||
| 9 | |||
| 10 | ## Root Cause Analysis | ||
| 11 | |||
| 12 | ### Tkinter Limitations | ||
| 13 | After three failed fix attempts: | ||
| 14 | 1. Entry widget styling (added bg/fg colors) | ||
| 15 | 2. ttk.Frame style configuration (added TFrame/TLabel styles) | ||
| 16 | 3. tk.Frame replacement (replaced all ttk.Frame with tk.Frame) | ||
| 17 | |||
| 18 | **Conclusion**: tkinter has deep macOS rendering issues that cannot be solved with configuration changes. The framework is aging and has poor macOS support. | ||
| 19 | |||
| 20 | ### Why tkinter Fails on macOS | ||
| 21 | - **Outdated architecture**: tkinter wraps Tk/Tcl from the 1990s | ||
| 22 | - **Poor theme support**: ttk themes don't work consistently on macOS | ||
| 23 | - **macOS-specific bugs**: Many unresolved issues in the bug tracker | ||
| 24 | - **No native rendering**: Uses X11-style rendering that conflicts with macOS | ||
| 25 | |||
| 26 | ## Proposed Solution: Migrate to PySide6 | ||
| 27 | |||
| 28 | ### Why PySide6 | ||
| 29 | |||
| 30 | **Technical Benefits:** | ||
| 31 | 1. **Native rendering**: True native widgets on each platform | ||
| 32 | 2. **Official support**: Maintained by Qt Company (not third-party) | ||
| 33 | 3. **Modern**: Qt 6 with latest features and performance improvements | ||
| 34 | 4. **Cross-platform**: Excellent macOS, Windows, Linux support | ||
| 35 | 5. **Better Windows support**: Native Windows 11 styling, high-DPI, touch support | ||
| 36 | |||
| 37 | **Licensing:** | ||
| 38 | - PySide6: LGPL (can use in commercial apps without opening source code) | ||
| 39 | - PyQt5: GPL (requires commercial license or open source) | ||
| 40 | |||
| 41 | **Long-term:** | ||
| 42 | - Qt 6 is the current major version, actively developed | ||
| 43 | - Qt 5 (PyQt5) is in maintenance mode | ||
| 44 | - Better future-proofing | ||
| 45 | |||
| 46 | ### Migration Scope | ||
| 47 | |||
| 48 | **Files to Replace:** | ||
| 49 | - `image_generator.py` - Complete rewrite using Qt | ||
| 50 | |||
| 51 | **New Structure:** | ||
| 52 | ```python | ||
| 53 | # Qt-based implementation | ||
| 54 | from PySide6.QtWidgets import ( | ||
| 55 | QApplication, QMainWindow, QDialog, QWidget, | ||
| 56 | QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, | ||
| 57 | QPushButton, QCheckBox, QTextEdit, QComboBox | ||
| 58 | ) | ||
| 59 | from PySide6.QtCore import Qt, QThread, Signal | ||
| 60 | from PySide6.QtGui import QPixmap, QFont | ||
| 61 | |||
| 62 | class LoginDialog(QDialog): | ||
| 63 | """Qt-based login window""" | ||
| 64 | # Clean, modern dialog with native rendering | ||
| 65 | |||
| 66 | class ImageGeneratorWindow(QMainWindow): | ||
| 67 | """Qt-based main application window""" | ||
| 68 | # Modern UI with better layout management | ||
| 69 | ``` | ||
| 70 | |||
| 71 | **Functionality Preserved:** | ||
| 72 | - ✓ Database authentication | ||
| 73 | - ✓ Remember username/password | ||
| 74 | - ✓ Image generation with Gemini API | ||
| 75 | - ✓ Reference image upload | ||
| 76 | - ✓ Image preview and download | ||
| 77 | - ✓ Prompt management (favorites) | ||
| 78 | - ✓ All existing features | ||
| 79 | |||
| 80 | **UI Improvements:** | ||
| 81 | - Better layout management (Qt layouts vs pack/grid) | ||
| 82 | - Native look and feel on all platforms | ||
| 83 | - Smooth threading (QThread vs threading.Thread) | ||
| 84 | - Better image handling (QPixmap) | ||
| 85 | - Modern file dialogs | ||
| 86 | - Better styling options (QSS - Qt Style Sheets) | ||
| 87 | |||
| 88 | ### Migration Strategy | ||
| 89 | |||
| 90 | **Phase 1: LoginDialog (Priority: High)** | ||
| 91 | - Rewrite LoginWindow as QDialog | ||
| 92 | - Implement authentication logic | ||
| 93 | - Test on macOS to verify visibility | ||
| 94 | - **Estimated**: 2-3 hours | ||
| 95 | |||
| 96 | **Phase 2: ImageGeneratorWindow (Priority: High)** | ||
| 97 | - Rewrite ImageGeneratorApp as QMainWindow | ||
| 98 | - Implement all existing features | ||
| 99 | - Improve layout and responsiveness | ||
| 100 | - **Estimated**: 4-6 hours | ||
| 101 | |||
| 102 | **Phase 3: Testing & Polish (Priority: Medium)** | ||
| 103 | - Cross-platform testing | ||
| 104 | - UI polish and refinements | ||
| 105 | - Performance optimization | ||
| 106 | - **Estimated**: 1-2 hours | ||
| 107 | |||
| 108 | **Total Estimated Effort**: 8-11 hours | ||
| 109 | |||
| 110 | ### Code Structure Comparison | ||
| 111 | |||
| 112 | **Current (tkinter):** | ||
| 113 | ```python | ||
| 114 | # Procedural, pack-based layout | ||
| 115 | main_frame = tk.Frame(self.root, bg='white', padx=40, pady=40) | ||
| 116 | main_frame.pack(fill="both", expand=True) | ||
| 117 | |||
| 118 | username_label = tk.Label(main_frame, text="用户名", ...) | ||
| 119 | username_label.pack(anchor="w") | ||
| 120 | ``` | ||
| 121 | |||
| 122 | **Proposed (PySide6):** | ||
| 123 | ```python | ||
| 124 | # Layout-based, cleaner structure | ||
| 125 | layout = QVBoxLayout() | ||
| 126 | |||
| 127 | username_label = QLabel("用户名") | ||
| 128 | username_label.setStyleSheet("color: #666666; font-size: 10pt;") | ||
| 129 | layout.addWidget(username_label) | ||
| 130 | |||
| 131 | self.setLayout(layout) | ||
| 132 | ``` | ||
| 133 | |||
| 134 | **Benefits:** | ||
| 135 | - Declarative layouts vs imperative pack/grid | ||
| 136 | - Better separation of concerns | ||
| 137 | - Easier to maintain and modify | ||
| 138 | - Responsive resizing out of the box | ||
| 139 | |||
| 140 | ## Alternative Considered: PyQt5 | ||
| 141 | |||
| 142 | **Rejected because:** | ||
| 143 | - GPL license (restrictive for commercial use) | ||
| 144 | - Based on Qt 5 (older version) | ||
| 145 | - Not officially maintained by Qt | ||
| 146 | - Worse Windows 11 integration | ||
| 147 | |||
| 148 | ## Dependencies | ||
| 149 | |||
| 150 | **New Dependency:** | ||
| 151 | - `PySide6>=6.6.0` (latest stable) | ||
| 152 | |||
| 153 | **Removed Dependency:** | ||
| 154 | - None (PIL, google-genai, pymysql all compatible with Qt) | ||
| 155 | |||
| 156 | **Installation:** | ||
| 157 | ```bash | ||
| 158 | pip install PySide6 | ||
| 159 | ``` | ||
| 160 | |||
| 161 | ## Risks & Mitigation | ||
| 162 | |||
| 163 | **Risks:** | ||
| 164 | 1. **Learning curve**: Team needs to learn Qt | ||
| 165 | - *Mitigation*: Qt has excellent documentation, similar concepts to other GUIs | ||
| 166 | |||
| 167 | 2. **Breaking changes**: Complete UI rewrite | ||
| 168 | - *Mitigation*: Preserve all functionality, test thoroughly | ||
| 169 | |||
| 170 | 3. **Binary size**: Qt apps are larger | ||
| 171 | - *Mitigation*: Acceptable for desktop app, better UX worth it | ||
| 172 | |||
| 173 | 4. **Migration time**: ~8-11 hours of work | ||
| 174 | - *Mitigation*: Necessary to make app usable on macOS | ||
| 175 | |||
| 176 | ## Benefits | ||
| 177 | |||
| 178 | **Immediate:** | ||
| 179 | - ✓ LoginWindow visible and functional on macOS | ||
| 180 | - ✓ Native look on all platforms | ||
| 181 | - ✓ Better reliability | ||
| 182 | |||
| 183 | **Long-term:** | ||
| 184 | - ✓ Modern, maintained framework | ||
| 185 | - ✓ Better performance | ||
| 186 | - ✓ More UI possibilities (animations, effects) | ||
| 187 | - ✓ Easier to add features | ||
| 188 | - ✓ Better cross-platform consistency | ||
| 189 | |||
| 190 | ## Testing Strategy | ||
| 191 | |||
| 192 | **Manual Testing:** | ||
| 193 | - [ ] macOS: Verify LoginDialog visible and functional | ||
| 194 | - [ ] macOS: Verify main window renders correctly | ||
| 195 | - [ ] Windows: Test UI appearance and functionality | ||
| 196 | - [ ] Linux: Test if available | ||
| 197 | |||
| 198 | **Functional Testing:** | ||
| 199 | - [ ] Login flow works | ||
| 200 | - [ ] Image generation works | ||
| 201 | - [ ] File operations work | ||
| 202 | - [ ] Database interaction works | ||
| 203 | - [ ] Config save/load works | ||
| 204 | |||
| 205 | ## Rollback Plan | ||
| 206 | |||
| 207 | If migration fails: | ||
| 208 | - Keep current tkinter code in git history | ||
| 209 | - Can revert if needed | ||
| 210 | - Low risk: Qt is proven technology | ||
| 211 | |||
| 212 | ## Recommendation | ||
| 213 | |||
| 214 | **Proceed with PySide6 migration**: This is the only reliable solution to fix the macOS visibility issue. tkinter has proven incompatible with macOS despite multiple fix attempts. PySide6 provides a modern, well-supported foundation for cross-platform desktop applications. |
This diff is collapsed.
Click to expand it.
openspec/changes/migrate-to-pyside6/tasks.md
0 → 100644
This diff is collapsed.
Click to expand it.
| 1 | # Proposal: Replace ttk.Frame with tk.Frame in LoginWindow | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | **Change ID**: replace-ttk-frame-with-tk-frame | ||
| 5 | |||
| 6 | **Problem**: After adding ttk style configurations, the LoginWindow content is still invisible on macOS. This indicates a deeper compatibility issue with ttk widgets on macOS. | ||
| 7 | |||
| 8 | **Impact**: Critical - the login window remains completely unusable on macOS despite previous fix attempts. | ||
| 9 | |||
| 10 | ## Root Cause Analysis | ||
| 11 | |||
| 12 | ### Issue with ttk on macOS | ||
| 13 | ttk (themed tkinter) widgets have known rendering issues on macOS, particularly with certain themes like 'clam'. Even with explicit style.configure() calls, ttk.Frame may not render properly due to: | ||
| 14 | |||
| 15 | 1. **macOS-specific ttk bugs**: ttk rendering on macOS has platform-specific issues that don't occur on Windows/Linux | ||
| 16 | 2. **Theme incompatibility**: The 'clam' theme may not be fully compatible with macOS's native rendering | ||
| 17 | 3. **Style configuration limitations**: Some ttk style properties don't apply correctly on macOS | ||
| 18 | |||
| 19 | ### Why Classic tk.Frame Works | ||
| 20 | Classic tkinter widgets (tk.Frame, tk.Label, tk.Entry, etc.) use direct Tk/Tcl calls and work consistently across all platforms. They don't depend on theme engines or complex style configurations. | ||
| 21 | |||
| 22 | **Evidence that classic tk works:** | ||
| 23 | - The checkboxes (tk.Checkbutton) are visible and work perfectly | ||
| 24 | - All tk.Label widgets with explicit bg='white' should work | ||
| 25 | - tk.Entry widgets with bg='#fafafa' should work | ||
| 26 | |||
| 27 | ## Proposed Solution | ||
| 28 | |||
| 29 | Replace `ttk.Frame` with `tk.Frame` in LoginWindow and adjust related widgets: | ||
| 30 | |||
| 31 | ### Changes Required | ||
| 32 | |||
| 33 | 1. **Replace main_frame from ttk.Frame to tk.Frame** (line 147) | ||
| 34 | - Change: `main_frame = ttk.Frame(self.root, padding=40)` | ||
| 35 | - To: `main_frame = tk.Frame(self.root, bg='white', padx=40, pady=40)` | ||
| 36 | |||
| 37 | 2. **Replace nested ttk.Frame widgets with tk.Frame** (lines 154, 173, 201) | ||
| 38 | - `username_frame = ttk.Frame(main_frame)` | ||
| 39 | - `password_frame = ttk.Frame(main_frame)` | ||
| 40 | - `checkbox_frame = ttk.Frame(main_frame)` | ||
| 41 | - Add explicit `bg='white'` to all | ||
| 42 | |||
| 43 | 3. **Keep ttk.Button for login button** (line 223) | ||
| 44 | - ttk.Button works fine and provides better styling | ||
| 45 | - No change needed | ||
| 46 | |||
| 47 | ### Benefits | ||
| 48 | - Classic tk widgets have proven cross-platform compatibility | ||
| 49 | - No dependency on ttk theme configurations | ||
| 50 | - Explicit background colors guarantee visibility | ||
| 51 | - Minimal code changes (just widget types) | ||
| 52 | |||
| 53 | ## Alternative: Migrate to Qt | ||
| 54 | |||
| 55 | If tk.Frame replacement also fails, we should migrate to PyQt5/PySide6: | ||
| 56 | |||
| 57 | ### Qt Migration Benefits | ||
| 58 | 1. **Native platform rendering**: Qt uses true native widgets on each platform | ||
| 59 | 2. **Better macOS support**: Qt has excellent macOS integration | ||
| 60 | 3. **More modern UI**: Qt provides richer, more modern UI components | ||
| 61 | 4. **Better maintained**: Qt is actively developed and supported | ||
| 62 | |||
| 63 | ### Qt Migration Scope | ||
| 64 | - Replace tkinter with PyQt5 or PySide6 | ||
| 65 | - Rewrite LoginWindow using QDialog/QWidget | ||
| 66 | - Rewrite ImageGeneratorApp using QMainWindow | ||
| 67 | - Update dependencies (add PyQt5/PySide6 to requirements) | ||
| 68 | - Maintain same functionality, improve UX | ||
| 69 | |||
| 70 | ### Estimated Effort | ||
| 71 | - tk.Frame fix: ~30 minutes (simple widget replacement) | ||
| 72 | - Qt migration: ~4-8 hours (full rewrite) | ||
| 73 | |||
| 74 | ## Recommendation | ||
| 75 | |||
| 76 | **Try tk.Frame replacement first** (this proposal): | ||
| 77 | - Minimal risk, minimal effort | ||
| 78 | - Likely to work based on checkbox evidence | ||
| 79 | - Maintains existing architecture | ||
| 80 | |||
| 81 | **If tk.Frame fails, proceed with Qt migration**: | ||
| 82 | - More robust long-term solution | ||
| 83 | - Better cross-platform support | ||
| 84 | - Worth the investment for better UX | ||
| 85 | |||
| 86 | ## Dependencies | ||
| 87 | None - isolated change to LoginWindow widget types | ||
| 88 | |||
| 89 | ## Risks | ||
| 90 | - Minimal: Classic tk widgets are the most stable tkinter components | ||
| 91 | - No functionality changes | ||
| 92 | - Backwards compatible | ||
| 93 | |||
| 94 | ## Testing Strategy | ||
| 95 | - Test on macOS to verify all UI elements visible | ||
| 96 | - Test on Windows/Linux to ensure no regression | ||
| 97 | - Verify all interactions work (typing, clicking, tab navigation) |
| 1 | # Spec: LoginWindow Cross-Platform Frame Compatibility | ||
| 2 | |||
| 3 | ## Overview | ||
| 4 | Specification for ensuring LoginWindow uses cross-platform compatible frame widgets that render correctly on macOS, Windows, and Linux. | ||
| 5 | |||
| 6 | ## MODIFIED Requirements | ||
| 7 | |||
| 8 | ### Requirement: Frame Widget Platform Compatibility | ||
| 9 | **ID**: login-frame-001 | ||
| 10 | |||
| 11 | The LoginWindow MUST use classic tk.Frame widgets instead of ttk.Frame widgets to ensure reliable rendering across all platforms, particularly macOS. All Frame widgets SHALL have explicit background color configuration. | ||
| 12 | |||
| 13 | #### Scenario: main_frame renders correctly on macOS | ||
| 14 | **Given** the LoginWindow is displayed on macOS | ||
| 15 | **When** the main_frame is created and rendered | ||
| 16 | **Then** the frame SHALL use tk.Frame (not ttk.Frame) | ||
| 17 | **And** the frame SHALL have background='white' explicitly set | ||
| 18 | **And** the frame SHALL use padx=40 and pady=40 for padding | ||
| 19 | **And** all content within the frame SHALL be visible | ||
| 20 | |||
| 21 | #### Scenario: nested frames render with white background | ||
| 22 | **Given** the LoginWindow contains username_frame, password_frame, and checkbox_frame | ||
| 23 | **When** these frames are created and rendered | ||
| 24 | **Then** all SHALL use tk.Frame (not ttk.Frame) | ||
| 25 | **And** all SHALL have bg='white' explicitly set | ||
| 26 | **And** all SHALL render correctly on macOS, Windows, and Linux | ||
| 27 | |||
| 28 | #### Scenario: classic tk widgets replace ttk widgets | ||
| 29 | **Given** the LoginWindow previously used ttk.Frame widgets | ||
| 30 | **When** the widgets are replaced with tk.Frame widgets | ||
| 31 | **Then** ttk.Frame SHALL NOT be used for any frame in LoginWindow | ||
| 32 | **And** tk.Frame SHALL be used with explicit bg='white' parameter | ||
| 33 | **And** the visual appearance SHALL remain consistent with design intentions | ||
| 34 | |||
| 35 | ### Requirement: Button Widget Styling Preservation | ||
| 36 | **ID**: login-frame-002 | ||
| 37 | |||
| 38 | The LoginWindow login button MUST continue to use ttk.Button to maintain styled appearance, as ttk.Button has proven cross-platform compatibility for button widgets. | ||
| 39 | |||
| 40 | #### Scenario: login button remains ttk.Button | ||
| 41 | **Given** the LoginWindow frames are converted from ttk.Frame to tk.Frame | ||
| 42 | **When** the login button is rendered | ||
| 43 | **Then** the button SHALL continue to use ttk.Button | ||
| 44 | **And** the button SHALL use the 'Login.TButton' style | ||
| 45 | **And** the button SHALL render correctly on all platforms | ||
| 46 | **And** the button styling SHALL remain unchanged from previous implementation | ||
| 47 | |||
| 48 | ### Requirement: Explicit Background Color Configuration | ||
| 49 | **ID**: login-frame-003 | ||
| 50 | |||
| 51 | All tk.Frame widgets in LoginWindow MUST have explicit background color configuration to prevent rendering issues. The background color SHALL be white (#ffffff) to match the design. | ||
| 52 | |||
| 53 | #### Scenario: all frames have explicit bg parameter | ||
| 54 | **Given** any tk.Frame widget in LoginWindow | ||
| 55 | **Then** the widget constructor SHALL include bg='white' parameter | ||
| 56 | **And** the background SHALL render as white on all platforms | ||
| 57 | **And** no frame SHALL rely on default or inherited background colors | ||
| 58 | |||
| 59 | #### Scenario: padding configuration uses Frame parameters | ||
| 60 | **Given** the main_frame requires 40px padding | ||
| 61 | **When** the tk.Frame is created | ||
| 62 | **Then** padding SHALL be specified using padx=40 and pady=40 parameters | ||
| 63 | **And** ttk-style padding parameter SHALL NOT be used | ||
| 64 | **And** the padding SHALL render consistently across platforms | ||
| 65 | |||
| 66 | ## ADDED Requirements | ||
| 67 | None - this modifies existing frame implementation | ||
| 68 | |||
| 69 | ## REMOVED Requirements | ||
| 70 | None - no requirements removed, only implementation approach changed |
| 1 | # Tasks: Replace ttk.Frame with tk.Frame in LoginWindow | ||
| 2 | |||
| 3 | ## Implementation Tasks | ||
| 4 | |||
| 5 | 1. **[x] Replace main_frame with tk.Frame** (image_generator.py:147) | ||
| 6 | - [x] Change `main_frame = ttk.Frame(self.root, padding=40)` | ||
| 7 | - [x] To `main_frame = tk.Frame(self.root, bg='white', padx=40, pady=40)` | ||
| 8 | - **Validation**: main_frame should have white background on macOS | ||
| 9 | |||
| 10 | 2. **[x] Replace username_frame with tk.Frame** (image_generator.py:157) | ||
| 11 | - [x] Change `username_frame = ttk.Frame(main_frame)` | ||
| 12 | - [x] To `username_frame = tk.Frame(main_frame, bg='white')` | ||
| 13 | - **Validation**: Frame renders with white background | ||
| 14 | |||
| 15 | 3. **[x] Replace password_frame with tk.Frame** (image_generator.py:176) | ||
| 16 | - [x] Change `password_frame = ttk.Frame(main_frame)` | ||
| 17 | - [x] To `password_frame = tk.Frame(main_frame, bg='white')` | ||
| 18 | - **Validation**: Frame renders with white background | ||
| 19 | |||
| 20 | 4. **[x] Replace checkbox_frame with tk.Frame** (image_generator.py:204) | ||
| 21 | - [x] Change `checkbox_frame = ttk.Frame(main_frame)` | ||
| 22 | - [x] To `checkbox_frame = tk.Frame(main_frame, bg='white')` | ||
| 23 | - **Validation**: Frame renders with white background | ||
| 24 | |||
| 25 | 5. **[ ] Test complete UI visibility on macOS** | ||
| 26 | - Verify title "登录" is visible | ||
| 27 | - Verify username label and Entry are visible | ||
| 28 | - Verify password label and Entry are visible | ||
| 29 | - Verify checkboxes remain visible | ||
| 30 | - Verify login button is visible | ||
| 31 | - **Validation**: Take screenshot showing all elements visible | ||
| 32 | |||
| 33 | 6. **Cross-platform verification** | ||
| 34 | - Test on Windows (ensure no visual regression) | ||
| 35 | - Test on Linux if available (ensure no visual regression) | ||
| 36 | - **Validation**: UI renders consistently across platforms | ||
| 37 | |||
| 38 | 7. **Functional testing** | ||
| 39 | - Test typing in both input fields | ||
| 40 | - Test login button click | ||
| 41 | - Test checkbox toggling | ||
| 42 | - Test tab navigation | ||
| 43 | - **Validation**: All interactions work correctly | ||
| 44 | |||
| 45 | ## Dependencies | ||
| 46 | - Tasks 1-4 can be completed in a single edit session | ||
| 47 | - Tasks 5-7 require manual testing after implementation | ||
| 48 | |||
| 49 | ## Notes | ||
| 50 | - Keep ttk.Button for login button (works fine) | ||
| 51 | - All tk.Frame widgets MUST have explicit `bg='white'` | ||
| 52 | - This is a minimal change - just widget type replacement |
openspec/project.md
0 → 100644
| 1 | # Project Context | ||
| 2 | |||
| 3 | ## Purpose | ||
| 4 | [Describe your project's purpose and goals] | ||
| 5 | |||
| 6 | ## Tech Stack | ||
| 7 | - [List your primary technologies] | ||
| 8 | - [e.g., TypeScript, React, Node.js] | ||
| 9 | |||
| 10 | ## Project Conventions | ||
| 11 | |||
| 12 | ### Code Style | ||
| 13 | [Describe your code style preferences, formatting rules, and naming conventions] | ||
| 14 | |||
| 15 | ### Architecture Patterns | ||
| 16 | [Document your architectural decisions and patterns] | ||
| 17 | |||
| 18 | ### Testing Strategy | ||
| 19 | [Explain your testing approach and requirements] | ||
| 20 | |||
| 21 | ### Git Workflow | ||
| 22 | [Describe your branching strategy and commit conventions] | ||
| 23 | |||
| 24 | ## Domain Context | ||
| 25 | [Add domain-specific knowledge that AI assistants need to understand] | ||
| 26 | |||
| 27 | ## Important Constraints | ||
| 28 | [List any technical, business, or regulatory constraints] | ||
| 29 | |||
| 30 | ## External Dependencies | ||
| 31 | [Document key external services, APIs, or systems] |
screenshot.png
0 → 100644
41.6 KB
-
Please register or sign in to post a comment