feat(ui): 迁移 StyleDesignerTab + TaskQueueWidget 样式
- StyleDesignerTab 删 8 处 inline setStyleSheet:
- 主按钮"生成珠宝图片" variant=primary(统一两个 tab 的视觉权重)
- 随机/恢复按钮去硬编码颜色,恢复按钮 variant=ghost
- 各 caption label 用 role=caption(统一字号)
- prompt_group 的 font-size:16px inline 删除
- result_label 用 #previewImage objectName + has_image property 切换
- 类内补 _set_status helper(之前批量替换时漏了)
- task_queue.py:
- TaskQueueWidget 用 #taskQueueSidebar objectName,
顶部新增 #sidebarHeader 40px header bar,
与主区 TabBar 视觉同高 — 修复"任务队列"标题飘到 tab 旁边的视觉断层
- 删除 list/widget 内嵌 stylesheet,全部走全局主题
- QListWidgetItem 状态色(橙/蓝/绿/红/灰)改用 theme.get_color() 读当前
主题 token,浅深模式都对
- theme.py 新增 get_color(token, fallback) 公共函数:
用于 widget 内嵌颜色调用(如 setForeground 等 QSS 命中不到的渲染层 API)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Showing
3 changed files
with
86 additions
and
120 deletions
| ... | @@ -4007,6 +4007,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4007,6 +4007,7 @@ class StyleDesignerTab(QWidget): |
| 4007 | self.logger = logging.getLogger(__name__) | 4007 | self.logger = logging.getLogger(__name__) |
| 4008 | self.library_manager = library_manager | 4008 | self.library_manager = library_manager |
| 4009 | self.parent_window = parent | 4009 | self.parent_window = parent |
| 4010 | self.setObjectName("styleDesignerTab") | ||
| 4010 | 4011 | ||
| 4011 | # 字段顺序 | 4012 | # 字段顺序 |
| 4012 | self.categories = ["主石形状", "主石材质", "金属", "花头形式", "戒臂结构", "戒臂处理", "特殊元素", "辅石镶嵌"] | 4013 | self.categories = ["主石形状", "主石材质", "金属", "花头形式", "戒臂结构", "戒臂处理", "特殊元素", "辅石镶嵌"] |
| ... | @@ -4051,38 +4052,15 @@ class StyleDesignerTab(QWidget): | ... | @@ -4051,38 +4052,15 @@ class StyleDesignerTab(QWidget): |
| 4051 | # 全局按钮区域 | 4052 | # 全局按钮区域 |
| 4052 | buttons_layout = QHBoxLayout() | 4053 | buttons_layout = QHBoxLayout() |
| 4053 | 4054 | ||
| 4054 | # 随机生成按钮 | 4055 | # 随机生成按钮(次要操作,无 variant 走默认) |
| 4055 | random_btn = QPushButton("🎲 随机生成参数") | 4056 | random_btn = QPushButton("🎲 随机生成参数") |
| 4056 | random_btn.clicked.connect(self.randomize_parameters) | 4057 | random_btn.clicked.connect(self.randomize_parameters) |
| 4057 | random_btn.setStyleSheet(""" | ||
| 4058 | QPushButton { | ||
| 4059 | background-color: #4CAF50; | ||
| 4060 | color: white; | ||
| 4061 | padding: 8px; | ||
| 4062 | border-radius: 4px; | ||
| 4063 | font-weight: bold; | ||
| 4064 | } | ||
| 4065 | QPushButton:hover { | ||
| 4066 | background-color: #45a049; | ||
| 4067 | } | ||
| 4068 | """) | ||
| 4069 | buttons_layout.addWidget(random_btn) | 4058 | buttons_layout.addWidget(random_btn) |
| 4070 | 4059 | ||
| 4071 | # 全局恢复按钮 | 4060 | # 全局恢复按钮(轻量警告 - 用 ghost) |
| 4072 | reset_all_btn = QPushButton("🔄 恢复所有默认词库") | 4061 | reset_all_btn = QPushButton("🔄 恢复所有默认词库") |
| 4062 | reset_all_btn.setProperty("variant", "ghost") | ||
| 4073 | reset_all_btn.clicked.connect(self.reset_all_library) | 4063 | reset_all_btn.clicked.connect(self.reset_all_library) |
| 4074 | reset_all_btn.setStyleSheet(""" | ||
| 4075 | QPushButton { | ||
| 4076 | background-color: #ff9800; | ||
| 4077 | color: white; | ||
| 4078 | padding: 8px; | ||
| 4079 | border-radius: 4px; | ||
| 4080 | font-weight: bold; | ||
| 4081 | } | ||
| 4082 | QPushButton:hover { | ||
| 4083 | background-color: #f57c00; | ||
| 4084 | } | ||
| 4085 | """) | ||
| 4086 | buttons_layout.addWidget(reset_all_btn) | 4064 | buttons_layout.addWidget(reset_all_btn) |
| 4087 | 4065 | ||
| 4088 | buttons_layout.addStretch() | 4066 | buttons_layout.addStretch() |
| ... | @@ -4101,7 +4079,6 @@ class StyleDesignerTab(QWidget): | ... | @@ -4101,7 +4079,6 @@ class StyleDesignerTab(QWidget): |
| 4101 | self.prompt_preview.setReadOnly(True) | 4079 | self.prompt_preview.setReadOnly(True) |
| 4102 | prompt_layout.addWidget(self.prompt_preview) | 4080 | prompt_layout.addWidget(self.prompt_preview) |
| 4103 | prompt_group.setLayout(prompt_layout) | 4081 | prompt_group.setLayout(prompt_layout) |
| 4104 | prompt_group.setStyleSheet("font-size: 16px;") | ||
| 4105 | 4082 | ||
| 4106 | content_row.addWidget(prompt_group, 2) | 4083 | content_row.addWidget(prompt_group, 2) |
| 4107 | 4084 | ||
| ... | @@ -4111,7 +4088,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4111,7 +4088,7 @@ class StyleDesignerTab(QWidget): |
| 4111 | 4088 | ||
| 4112 | # 生成模式(放在最前面) | 4089 | # 生成模式(放在最前面) |
| 4113 | mode_label = QLabel("生成模式") | 4090 | mode_label = QLabel("生成模式") |
| 4114 | mode_label.setStyleSheet("QLabel { font-size: 14px; line-height: 18px; }") | 4091 | mode_label.setProperty("role", "caption") |
| 4115 | settings_layout.addWidget(mode_label) | 4092 | settings_layout.addWidget(mode_label) |
| 4116 | self.generation_mode = QComboBox() | 4093 | self.generation_mode = QComboBox() |
| 4117 | self.generation_mode.addItems(["极速模式", "慢速模式"]) | 4094 | self.generation_mode.addItems(["极速模式", "慢速模式"]) |
| ... | @@ -4123,7 +4100,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4123,7 +4100,7 @@ class StyleDesignerTab(QWidget): |
| 4123 | 4100 | ||
| 4124 | # 宽高比 | 4101 | # 宽高比 |
| 4125 | aspect_label = QLabel("宽高比") | 4102 | aspect_label = QLabel("宽高比") |
| 4126 | aspect_label.setStyleSheet("QLabel { font-size: 14px; line-height: 18px; }") | 4103 | aspect_label.setProperty("role", "caption") |
| 4127 | settings_layout.addWidget(aspect_label) | 4104 | settings_layout.addWidget(aspect_label) |
| 4128 | self.aspect_ratio = QComboBox() | 4105 | self.aspect_ratio = QComboBox() |
| 4129 | self.aspect_ratio.addItems([ | 4106 | self.aspect_ratio.addItems([ |
| ... | @@ -4140,7 +4117,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4140,7 +4117,7 @@ class StyleDesignerTab(QWidget): |
| 4140 | 4117 | ||
| 4141 | # 图片尺寸 | 4118 | # 图片尺寸 |
| 4142 | size_label = QLabel("图片尺寸") | 4119 | size_label = QLabel("图片尺寸") |
| 4143 | size_label.setStyleSheet("QLabel { font-size: 14px; line-height: 18px; }") | 4120 | size_label.setProperty("role", "caption") |
| 4144 | settings_layout.addWidget(size_label) | 4121 | settings_layout.addWidget(size_label) |
| 4145 | self.image_size = QComboBox() | 4122 | self.image_size = QComboBox() |
| 4146 | self.image_size.addItems(["1K", "2K", "4K"]) | 4123 | self.image_size.addItems(["1K", "2K", "4K"]) |
| ... | @@ -4159,20 +4136,8 @@ class StyleDesignerTab(QWidget): | ... | @@ -4159,20 +4136,8 @@ class StyleDesignerTab(QWidget): |
| 4159 | # Action buttons - 与图片生成页面保持一致 | 4136 | # Action buttons - 与图片生成页面保持一致 |
| 4160 | action_layout = QHBoxLayout() | 4137 | action_layout = QHBoxLayout() |
| 4161 | self.generate_btn = QPushButton("🎨 生成珠宝图片") | 4138 | self.generate_btn = QPushButton("🎨 生成珠宝图片") |
| 4139 | self.generate_btn.setProperty("variant", "primary") | ||
| 4162 | self.generate_btn.clicked.connect(self.generate_image) | 4140 | self.generate_btn.clicked.connect(self.generate_image) |
| 4163 | self.generate_btn.setStyleSheet(""" | ||
| 4164 | QPushButton { | ||
| 4165 | background-color: #007AFF; | ||
| 4166 | color: white; | ||
| 4167 | padding: 12px; | ||
| 4168 | border-radius: 4px; | ||
| 4169 | font-size: 14px; | ||
| 4170 | font-weight: bold; | ||
| 4171 | } | ||
| 4172 | QPushButton:hover { | ||
| 4173 | background-color: #0051D5; | ||
| 4174 | } | ||
| 4175 | """) | ||
| 4176 | action_layout.addWidget(self.generate_btn) | 4141 | action_layout.addWidget(self.generate_btn) |
| 4177 | 4142 | ||
| 4178 | self.download_btn = QPushButton("💾 下载图片") | 4143 | self.download_btn = QPushButton("💾 下载图片") |
| ... | @@ -4181,7 +4146,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4181,7 +4146,7 @@ class StyleDesignerTab(QWidget): |
| 4181 | action_layout.addWidget(self.download_btn) | 4146 | action_layout.addWidget(self.download_btn) |
| 4182 | 4147 | ||
| 4183 | self.status_label = QLabel("● 就绪") | 4148 | self.status_label = QLabel("● 就绪") |
| 4184 | self.status_label.setStyleSheet("QLabel { font-size: 14px; line-height: 18px; }") | 4149 | self.status_label.setProperty("status", "muted") |
| 4185 | action_layout.addWidget(self.status_label) | 4150 | action_layout.addWidget(self.status_label) |
| 4186 | action_layout.addStretch() | 4151 | action_layout.addStretch() |
| 4187 | 4152 | ||
| ... | @@ -4192,19 +4157,11 @@ class StyleDesignerTab(QWidget): | ... | @@ -4192,19 +4157,11 @@ class StyleDesignerTab(QWidget): |
| 4192 | preview_layout = QVBoxLayout() | 4157 | preview_layout = QVBoxLayout() |
| 4193 | 4158 | ||
| 4194 | self.result_label = QLabel("生成的图片将在这里显示\n双击用系统查看器打开") | 4159 | self.result_label = QLabel("生成的图片将在这里显示\n双击用系统查看器打开") |
| 4160 | self.result_label.setObjectName("previewImage") | ||
| 4161 | self.result_label.setProperty("has_image", "false") | ||
| 4195 | self.result_label.setAlignment(Qt.AlignCenter) | 4162 | self.result_label.setAlignment(Qt.AlignCenter) |
| 4196 | self.result_label.setMinimumHeight(300) | 4163 | self.result_label.setMinimumHeight(300) |
| 4197 | self.result_label.setMinimumWidth(400) | 4164 | self.result_label.setMinimumWidth(400) |
| 4198 | self.result_label.setStyleSheet(""" | ||
| 4199 | QLabel { | ||
| 4200 | color: #999999; | ||
| 4201 | font-size: 14px; | ||
| 4202 | line-height: 18px; | ||
| 4203 | border: 1px solid #ddd; | ||
| 4204 | border-radius: 4px; | ||
| 4205 | background-color: #f9f9f9; | ||
| 4206 | } | ||
| 4207 | """) | ||
| 4208 | self.result_label.setScaledContents(False) | 4165 | self.result_label.setScaledContents(False) |
| 4209 | # 保存原始的双击处理方法引用 | 4166 | # 保存原始的双击处理方法引用 |
| 4210 | self.original_mouseDoubleClickEvent = self.result_label.mouseDoubleClickEvent | 4167 | self.original_mouseDoubleClickEvent = self.result_label.mouseDoubleClickEvent |
| ... | @@ -4221,6 +4178,14 @@ class StyleDesignerTab(QWidget): | ... | @@ -4221,6 +4178,14 @@ class StyleDesignerTab(QWidget): |
| 4221 | # 初始化 prompt 预览 | 4178 | # 初始化 prompt 预览 |
| 4222 | self.update_prompt_preview() | 4179 | self.update_prompt_preview() |
| 4223 | 4180 | ||
| 4181 | def _set_status(self, status: str, text: str | None = None) -> None: | ||
| 4182 | """统一状态标签视觉。status: success|warning|danger|info|muted""" | ||
| 4183 | if text is not None: | ||
| 4184 | self.status_label.setText(text) | ||
| 4185 | self.status_label.setProperty("status", status) | ||
| 4186 | self.status_label.style().unpolish(self.status_label) | ||
| 4187 | self.status_label.style().polish(self.status_label) | ||
| 4188 | |||
| 4224 | def randomize_parameters(self): | 4189 | def randomize_parameters(self): |
| 4225 | """随机生成一套参数(跳过锁定的字段)""" | 4190 | """随机生成一套参数(跳过锁定的字段)""" |
| 4226 | for category, combo in self.combo_boxes.items(): | 4191 | for category, combo in self.combo_boxes.items(): |
| ... | @@ -4239,7 +4204,7 @@ class StyleDesignerTab(QWidget): | ... | @@ -4239,7 +4204,7 @@ class StyleDesignerTab(QWidget): |
| 4239 | # 标签 | 4204 | # 标签 |
| 4240 | label = QLabel(f"{category}:") | 4205 | label = QLabel(f"{category}:") |
| 4241 | label.setMinimumWidth(70) # 减小标签宽度以适应两列布局 | 4206 | label.setMinimumWidth(70) # 减小标签宽度以适应两列布局 |
| 4242 | label.setStyleSheet("QLabel { font-size: 14px; line-height: 18px; }") | 4207 | label.setProperty("role", "caption") |
| 4243 | layout.addWidget(label) | 4208 | layout.addWidget(label) |
| 4244 | 4209 | ||
| 4245 | # 下拉框 | 4210 | # 下拉框 |
| ... | @@ -4671,12 +4636,9 @@ class StyleDesignerTab(QWidget): | ... | @@ -4671,12 +4636,9 @@ class StyleDesignerTab(QWidget): |
| 4671 | Qt.SmoothTransformation | 4636 | Qt.SmoothTransformation |
| 4672 | ) | 4637 | ) |
| 4673 | self.result_label.setPixmap(scaled_pixmap) | 4638 | self.result_label.setPixmap(scaled_pixmap) |
| 4674 | self.result_label.setStyleSheet(""" | 4639 | self.result_label.setProperty("has_image", "true") |
| 4675 | QLabel { | 4640 | self.result_label.style().unpolish(self.result_label) |
| 4676 | border: 1px solid #ddd; | 4641 | self.result_label.style().polish(self.result_label) |
| 4677 | background-color: white; | ||
| 4678 | } | ||
| 4679 | """) | ||
| 4680 | # 启用下载按钮 | 4642 | # 启用下载按钮 |
| 4681 | self.download_btn.setEnabled(True) | 4643 | self.download_btn.setEnabled(True) |
| 4682 | except Exception as e: | 4644 | except Exception as e: | ... | ... |
| ... | @@ -447,66 +447,49 @@ class TaskQueueWidget(QWidget): | ... | @@ -447,66 +447,49 @@ class TaskQueueWidget(QWidget): |
| 447 | self._update_summary() | 447 | self._update_summary() |
| 448 | 448 | ||
| 449 | def _setup_ui(self): | 449 | def _setup_ui(self): |
| 450 | """构建右侧任务列表 UI""" | 450 | """构建右侧任务列表 UI(视觉走全局主题)""" |
| 451 | self.setObjectName("taskQueueSidebar") | ||
| 452 | |||
| 451 | layout = QVBoxLayout() | 453 | layout = QVBoxLayout() |
| 452 | layout.setContentsMargins(8, 8, 8, 8) | 454 | layout.setContentsMargins(0, 0, 0, 0) |
| 453 | layout.setSpacing(2) | 455 | layout.setSpacing(0) |
| 456 | |||
| 457 | # Header bar — 与主区 TabBar 同高(40px),消除"任务队列"飘上去的视觉 | ||
| 458 | header = QWidget() | ||
| 459 | header.setObjectName("sidebarHeader") | ||
| 460 | header_layout = QHBoxLayout() | ||
| 461 | header_layout.setContentsMargins(0, 0, 0, 0) | ||
| 462 | header_layout.setSpacing(0) | ||
| 454 | 463 | ||
| 455 | # 标题 | ||
| 456 | title = QLabel("任务队列") | 464 | title = QLabel("任务队列") |
| 457 | title.setStyleSheet("QLabel { font-weight: bold; font-size: 10px; color: #666; }") | 465 | title.setAlignment(Qt.AlignVCenter) |
| 458 | title.setAlignment(Qt.AlignCenter) | ||
| 459 | title.setToolTip("鼠标悬停查看详情\n右键等待中或运行中的任务可取消") | 466 | title.setToolTip("鼠标悬停查看详情\n右键等待中或运行中的任务可取消") |
| 460 | layout.addWidget(title) | 467 | header_layout.addWidget(title) |
| 461 | 468 | header_layout.addStretch() | |
| 462 | # 分隔线 | 469 | header.setLayout(header_layout) |
| 463 | line = QLabel() | 470 | layout.addWidget(header) |
| 464 | line.setFrameStyle(QFrame.HLine | QFrame.Sunken) | ||
| 465 | layout.addWidget(line) | ||
| 466 | 471 | ||
| 467 | # 任务状态列表 - 可点击的列表项 | 472 | # 任务状态列表 - 可点击的列表项(样式由全局 QSS 提供) |
| 468 | self.task_list = QListWidget() | 473 | self.task_list = QListWidget() |
| 469 | self.task_list.setStyleSheet(""" | 474 | self.task_list.setObjectName("taskList") |
| 470 | QListWidget { | 475 | self.task_list.setFrameShape(QFrame.NoFrame) |
| 471 | border: none; | ||
| 472 | font-size: 11px; | ||
| 473 | padding: 2px; | ||
| 474 | } | ||
| 475 | QListWidget::item { | ||
| 476 | padding: 4px 2px; | ||
| 477 | border-bottom: 1px solid #eee; | ||
| 478 | min-height: 20px; | ||
| 479 | } | ||
| 480 | QListWidget::item:hover { | ||
| 481 | background-color: #e3f2fd; | ||
| 482 | cursor: pointer; | ||
| 483 | } | ||
| 484 | QListWidget::item:selected { | ||
| 485 | background-color: #bbdefb; | ||
| 486 | } | ||
| 487 | """) | ||
| 488 | self.task_list.itemClicked.connect(self._on_task_item_clicked) | 476 | self.task_list.itemClicked.connect(self._on_task_item_clicked) |
| 489 | 477 | ||
| 490 | # 启用右键菜单 | 478 | # 启用右键菜单 |
| 491 | self.task_list.setContextMenuPolicy(Qt.CustomContextMenu) | 479 | self.task_list.setContextMenuPolicy(Qt.CustomContextMenu) |
| 492 | self.task_list.customContextMenuRequested.connect(self._show_context_menu) | 480 | self.task_list.customContextMenuRequested.connect(self._show_context_menu) |
| 493 | 481 | ||
| 494 | layout.addWidget(self.task_list) | 482 | # 加 padding 让列表脱离边缘 |
| 483 | list_wrap = QVBoxLayout() | ||
| 484 | list_wrap.setContentsMargins(8, 8, 8, 8) | ||
| 485 | list_wrap.addWidget(self.task_list) | ||
| 486 | layout.addLayout(list_wrap) | ||
| 495 | 487 | ||
| 496 | layout.addStretch() | ||
| 497 | self.setLayout(layout) | 488 | self.setLayout(layout) |
| 498 | 489 | ||
| 499 | # 设置极窄宽度 | 490 | # 设置极窄宽度 |
| 500 | self.setMaximumWidth(120) | 491 | self.setMaximumWidth(140) |
| 501 | self.setMinimumWidth(80) | 492 | self.setMinimumWidth(100) |
| 502 | |||
| 503 | # 样式 | ||
| 504 | self.setStyleSheet(""" | ||
| 505 | TaskQueueWidget { | ||
| 506 | background-color: #f5f5f5; | ||
| 507 | border-left: 1px solid #ddd; | ||
| 508 | } | ||
| 509 | """) | ||
| 510 | 493 | ||
| 511 | def _connect_signals(self): | 494 | def _connect_signals(self): |
| 512 | """绑定信号""" | 495 | """绑定信号""" |
| ... | @@ -519,30 +502,30 @@ class TaskQueueWidget(QWidget): | ... | @@ -519,30 +502,30 @@ class TaskQueueWidget(QWidget): |
| 519 | 502 | ||
| 520 | def _update_summary(self): | 503 | def _update_summary(self): |
| 521 | """更新任务列表 - 显示可点击的状态项""" | 504 | """更新任务列表 - 显示可点击的状态项""" |
| 505 | from theme import get_color | ||
| 522 | self.task_list.clear() | 506 | self.task_list.clear() |
| 523 | tasks = self.manager.get_all_tasks() | 507 | tasks = self.manager.get_all_tasks() |
| 524 | 508 | ||
| 525 | # 按状态分类并转换为文字 | 509 | # 按状态分类并转换为文字(颜色读自当前主题,浅深都对) |
| 526 | for task in tasks: | 510 | for task in tasks: |
| 527 | # 状态文字和颜色 | ||
| 528 | if task.status == TaskStatus.RUNNING: | 511 | if task.status == TaskStatus.RUNNING: |
| 529 | status_text = "执行中" | 512 | status_text = "执行中" |
| 530 | color = "#FF9500" # 橙色 | 513 | color = get_color("warning", "#FF9500") |
| 531 | elif task.status == TaskStatus.PENDING: | 514 | elif task.status == TaskStatus.PENDING: |
| 532 | status_text = "等待中" | 515 | status_text = "等待中" |
| 533 | color = "#007AFF" # 蓝色 | 516 | color = get_color("accent", "#007AFF") |
| 534 | elif task.status == TaskStatus.COMPLETED: | 517 | elif task.status == TaskStatus.COMPLETED: |
| 535 | status_text = "已完成" | 518 | status_text = "已完成" |
| 536 | color = "#34C759" # 绿色 | 519 | color = get_color("success", "#34C759") |
| 537 | elif task.status == TaskStatus.FAILED: | 520 | elif task.status == TaskStatus.FAILED: |
| 538 | status_text = "失败" | 521 | status_text = "失败" |
| 539 | color = "#FF3B30" # 红色 | 522 | color = get_color("danger", "#FF3B30") |
| 540 | elif task.status == TaskStatus.CANCELLED: | 523 | elif task.status == TaskStatus.CANCELLED: |
| 541 | status_text = "已取消" | 524 | status_text = "已取消" |
| 542 | color = "#8E8E93" # 中性灰 | 525 | color = get_color("text_tertiary", "#8E8E93") |
| 543 | else: | 526 | else: |
| 544 | status_text = "未知" | 527 | status_text = "未知" |
| 545 | color = "#666666" # 灰色 | 528 | color = get_color("text_secondary", "#666666") |
| 546 | 529 | ||
| 547 | # 创建列表项 | 530 | # 创建列表项 |
| 548 | item = QListWidgetItem(status_text) | 531 | item = QListWidgetItem(status_text) |
| ... | @@ -717,7 +700,7 @@ class TaskQueueWidget(QWidget): | ... | @@ -717,7 +700,7 @@ class TaskQueueWidget(QWidget): |
| 717 | 700 | ||
| 718 | # 标题 | 701 | # 标题 |
| 719 | title = QLabel("📋 任务队列") | 702 | title = QLabel("📋 任务队列") |
| 720 | title.setStyleSheet("QLabel { font-weight: bold; font-size: 14px; }") | 703 | title.setProperty("role", "title") |
| 721 | layout.addWidget(title) | 704 | layout.addWidget(title) |
| 722 | 705 | ||
| 723 | # 任务列表 | 706 | # 任务列表 |
| ... | @@ -729,13 +712,14 @@ class TaskQueueWidget(QWidget): | ... | @@ -729,13 +712,14 @@ class TaskQueueWidget(QWidget): |
| 729 | item = QListWidgetItem() | 712 | item = QListWidgetItem() |
| 730 | item.setData(Qt.UserRole, task.id) | 713 | item.setData(Qt.UserRole, task.id) |
| 731 | 714 | ||
| 715 | from theme import get_color | ||
| 732 | status_map = { | 716 | status_map = { |
| 733 | TaskStatus.RUNNING: ("●", "#FF9500"), | 717 | TaskStatus.RUNNING: ("●", get_color("warning", "#FF9500")), |
| 734 | TaskStatus.PENDING: ("○", "#8E8E93"), | 718 | TaskStatus.PENDING: ("○", get_color("text_tertiary", "#8E8E93")), |
| 735 | TaskStatus.COMPLETED: ("✓", "#34C759"), | 719 | TaskStatus.COMPLETED: ("✓", get_color("success", "#34C759")), |
| 736 | TaskStatus.FAILED: ("✗", "#FF3B30"), | 720 | TaskStatus.FAILED: ("✗", get_color("danger", "#FF3B30")), |
| 737 | } | 721 | } |
| 738 | icon, color = status_map.get(task.status, ("?", "#000")) | 722 | icon, color = status_map.get(task.status, ("?", get_color("text_primary", "#000"))) |
| 739 | 723 | ||
| 740 | prompt_preview = task.prompt[:30] + "..." if len(task.prompt) > 30 else task.prompt | 724 | prompt_preview = task.prompt[:30] + "..." if len(task.prompt) > 30 else task.prompt |
| 741 | display_text = f"{icon} {prompt_preview}" | 725 | display_text = f"{icon} {prompt_preview}" | ... | ... |
| ... | @@ -748,4 +748,24 @@ def apply_theme(app: QApplication) -> ThemeManager: | ... | @@ -748,4 +748,24 @@ def apply_theme(app: QApplication) -> ThemeManager: |
| 748 | 返回 ThemeManager 实例,调用方应持有引用以保持信号连接(否则会被 | 748 | 返回 ThemeManager 实例,调用方应持有引用以保持信号连接(否则会被 |
| 749 | Python GC 当作未引用的 QObject 回收,导致系统切换失效)。 | 749 | Python GC 当作未引用的 QObject 回收,导致系统切换失效)。 |
| 750 | """ | 750 | """ |
| 751 | return ThemeManager(app) | 751 | mgr = ThemeManager(app) |
| 752 | # 全局可访问点,方便 get_color() 等无 widget 引用的场景 | ||
| 753 | app.theme_manager = mgr | ||
| 754 | return mgr | ||
| 755 | |||
| 756 | |||
| 757 | def get_color(token: str, fallback: str = "#000000") -> str: | ||
| 758 | """读取当前主题下的颜色 token。 | ||
| 759 | |||
| 760 | 用于 widget 内嵌颜色调用(如 QListWidgetItem.setForeground 等), | ||
| 761 | QSS 命中不到的渲染层 API。注意:返回的是当前快照,主题切换后需要 | ||
| 762 | 在下一次重绘时重新读取。 | ||
| 763 | """ | ||
| 764 | try: | ||
| 765 | app = QApplication.instance() | ||
| 766 | mgr = getattr(app, "theme_manager", None) | ||
| 767 | mode = mgr.current_mode() if mgr else "light" | ||
| 768 | except Exception: | ||
| 769 | mode = "light" | ||
| 770 | table = TOKENS_DARK if mode == "dark" else TOKENS_LIGHT | ||
| 771 | return table.get(token, fallback) | ... | ... |
-
Please register or sign in to post a comment