feat: 实现CutThenThink P0阶段核心功能
项目初始化 - 创建完整项目结构(src/, data/, docs/, examples/, tests/) - 配置requirements.txt依赖 - 创建.gitignore P0基础框架 - 数据库模型:Record模型,6种分类类型 - 配置管理:YAML配置,支持AI/OCR/云存储/UI配置 - OCR模块:PaddleOCR本地识别,支持云端扩展 - AI模块:支持OpenAI/Claude/通义/Ollama,6种分类 - 存储模块:完整CRUD,搜索,统计,导入导出 - 主窗口框架:侧边栏导航,米白配色方案 - 图片处理:截图/剪贴板/文件选择/图片预览 - 处理流程整合:OCR→AI→存储串联,Markdown展示,剪贴板复制 - 分类浏览:卡片网格展示,分类筛选,搜索,详情查看 技术栈 - PyQt6 + SQLAlchemy + PaddleOCR + OpenAI/Claude SDK - 共47个Python文件,4000+行代码 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
36
src/gui/styles/__init__.py
Normal file
36
src/gui/styles/__init__.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""
|
||||
GUI样式和主题模块
|
||||
|
||||
提供颜色方案和主题样式表
|
||||
"""
|
||||
|
||||
from src.gui.styles.colors import ColorScheme, COLORS, get_color
|
||||
from src.gui.styles.theme import ThemeStyles
|
||||
|
||||
# 浏览视图样式(如果存在)
|
||||
try:
|
||||
from src.gui.styles.browse_style import (
|
||||
get_style, get_category_color, get_category_name,
|
||||
CATEGORY_COLORS, CATEGORY_NAMES
|
||||
)
|
||||
_has_browse_style = True
|
||||
except ImportError:
|
||||
_has_browse_style = False
|
||||
|
||||
__all__ = [
|
||||
# 颜色和主题
|
||||
'ColorScheme',
|
||||
'COLORS',
|
||||
'get_color',
|
||||
'ThemeStyles',
|
||||
]
|
||||
|
||||
# 如果浏览样式存在,添加到导出
|
||||
if _has_browse_style:
|
||||
__all__.extend([
|
||||
'get_style',
|
||||
'get_category_color',
|
||||
'get_category_name',
|
||||
'CATEGORY_COLORS',
|
||||
'CATEGORY_NAMES',
|
||||
])
|
||||
341
src/gui/styles/browse_style.py
Normal file
341
src/gui/styles/browse_style.py
Normal file
@@ -0,0 +1,341 @@
|
||||
"""
|
||||
浏览视图样式定义
|
||||
|
||||
包含卡片、按钮、对话框等组件的样式
|
||||
"""
|
||||
|
||||
# 通用样式
|
||||
COMMON_STYLES = """
|
||||
QWidget {
|
||||
font-family: "Microsoft YaHei", "PingFang SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
|
||||
}
|
||||
"""
|
||||
|
||||
# 卡片样式
|
||||
CARD_STYLES = """
|
||||
RecordCard {
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #E8E8E8;
|
||||
}
|
||||
RecordCard:hover {
|
||||
background-color: #FAFAFA;
|
||||
border: 1px solid #4A90E2;
|
||||
}
|
||||
"""
|
||||
|
||||
# 按钮样式
|
||||
BUTTON_STYLES = {
|
||||
'primary': """
|
||||
QPushButton {
|
||||
background-color: #4A90E2;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #357ABD;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #2E6FA8;
|
||||
}
|
||||
QPushButton:disabled {
|
||||
background-color: #BDC3C7;
|
||||
color: #ECF0F1;
|
||||
}
|
||||
""",
|
||||
'success': """
|
||||
QPushButton {
|
||||
background-color: #58D68D;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #48C9B0;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #45B39D;
|
||||
}
|
||||
""",
|
||||
'danger': """
|
||||
QPushButton {
|
||||
background-color: #EC7063;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #E74C3C;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #C0392B;
|
||||
}
|
||||
""",
|
||||
'secondary': """
|
||||
QPushButton {
|
||||
background-color: #95A5A6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #7F8C8D;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #6C7A7D;
|
||||
}
|
||||
""",
|
||||
}
|
||||
|
||||
# 分类按钮颜色
|
||||
CATEGORY_COLORS = {
|
||||
"TODO": "#5DADE2",
|
||||
"NOTE": "#58D68D",
|
||||
"IDEA": "#F5B041",
|
||||
"REF": "#AF7AC5",
|
||||
"FUNNY": "#EC7063",
|
||||
"TEXT": "#95A5A6",
|
||||
}
|
||||
|
||||
# 分类名称
|
||||
CATEGORY_NAMES = {
|
||||
"TODO": "待办",
|
||||
"NOTE": "笔记",
|
||||
"IDEA": "灵感",
|
||||
"REF": "参考",
|
||||
"FUNNY": "趣味",
|
||||
"TEXT": "文本",
|
||||
}
|
||||
|
||||
# 输入框样式
|
||||
INPUT_STYLES = """
|
||||
QLineEdit {
|
||||
padding: 10px 15px;
|
||||
border: 2px solid #E0E0E0;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
background-color: #FAFAFA;
|
||||
color: #333;
|
||||
}
|
||||
QLineEdit:focus {
|
||||
border: 2px solid #4A90E2;
|
||||
background-color: white;
|
||||
}
|
||||
QLineEdit:disabled {
|
||||
background-color: #ECF0F1;
|
||||
color: #95A5A6;
|
||||
}
|
||||
"""
|
||||
|
||||
# 文本编辑框样式
|
||||
TEXTEDIT_STYLES = """
|
||||
QTextEdit {
|
||||
border: 1px solid #E0E0E0;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
background-color: #FAFAFA;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}
|
||||
QTextEdit:focus {
|
||||
border: 1px solid #4A90E2;
|
||||
background-color: white;
|
||||
}
|
||||
"""
|
||||
|
||||
# 下拉框样式
|
||||
COMBOBOX_STYLES = """
|
||||
QComboBox {
|
||||
padding: 8px 15px;
|
||||
border: 2px solid #E0E0E0;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
background-color: white;
|
||||
color: #333;
|
||||
}
|
||||
QComboBox:hover {
|
||||
border: 2px solid #4A90E2;
|
||||
}
|
||||
QComboBox::drop-down {
|
||||
border: none;
|
||||
width: 30px;
|
||||
}
|
||||
QComboBox::down-arrow {
|
||||
image: none;
|
||||
border: 5px solid transparent;
|
||||
border-top-color: #333;
|
||||
margin-right: 10px;
|
||||
}
|
||||
QComboBox QAbstractItemView {
|
||||
border: 1px solid #E0E0E0;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
selection-background-color: #4A90E2;
|
||||
selection-color: white;
|
||||
padding: 5px;
|
||||
}
|
||||
"""
|
||||
|
||||
# 滚动区域样式
|
||||
SCROLLAREA_STYLES = """
|
||||
QScrollArea {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
QScrollBar:vertical {
|
||||
border: none;
|
||||
background-color: #F5F5F5;
|
||||
width: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #BDC3C7;
|
||||
border-radius: 6px;
|
||||
min-height: 30px;
|
||||
}
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background-color: #95A5A6;
|
||||
}
|
||||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
QScrollBar:horizontal {
|
||||
border: none;
|
||||
background-color: #F5F5F5;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #BDC3C7;
|
||||
border-radius: 6px;
|
||||
min-width: 30px;
|
||||
}
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background-color: #95A5A6;
|
||||
}
|
||||
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
"""
|
||||
|
||||
# 框架样式
|
||||
FRAME_STYLES = """
|
||||
QFrame {
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #E0E0E0;
|
||||
}
|
||||
"""
|
||||
|
||||
# 标签样式
|
||||
LABEL_STYLES = {
|
||||
'title': """
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #2C3E50;
|
||||
}
|
||||
""",
|
||||
'subtitle': """
|
||||
QLabel {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #34495E;
|
||||
}
|
||||
""",
|
||||
'body': """
|
||||
QLabel {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
""",
|
||||
'caption': """
|
||||
QLabel {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
""",
|
||||
}
|
||||
|
||||
# 对话框样式
|
||||
DIALOG_STYLES = """
|
||||
QDialog {
|
||||
background-color: #F5F7FA;
|
||||
}
|
||||
"""
|
||||
|
||||
# 工具栏样式
|
||||
TOOLBAR_STYLES = """
|
||||
QFrame {
|
||||
background-color: white;
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def get_style(style_type: str, *args) -> str:
|
||||
"""
|
||||
获取样式字符串
|
||||
|
||||
Args:
|
||||
style_type: 样式类型 (button, input, label等)
|
||||
*args: 额外参数 (如button类型: primary, secondary等)
|
||||
|
||||
Returns:
|
||||
样式字符串
|
||||
"""
|
||||
styles = {
|
||||
'button': BUTTON_STYLES.get(args[0] if args else 'primary', ''),
|
||||
'input': INPUT_STYLES,
|
||||
'textedit': TEXTEDIT_STYLES,
|
||||
'combobox': COMBOBOX_STYLES,
|
||||
'scrollarea': SCROLLAREA_STYLES,
|
||||
'frame': FRAME_STYLES,
|
||||
'label': LABEL_STYLES.get(args[0] if args else 'body', ''),
|
||||
'dialog': DIALOG_STYLES,
|
||||
'toolbar': TOOLBAR_STYLES,
|
||||
}
|
||||
|
||||
return styles.get(style_type, '')
|
||||
|
||||
|
||||
def get_category_color(category: str) -> str:
|
||||
"""
|
||||
获取分类颜色
|
||||
|
||||
Args:
|
||||
category: 分类代码
|
||||
|
||||
Returns:
|
||||
颜色代码
|
||||
"""
|
||||
return CATEGORY_COLORS.get(category, "#95A5A6")
|
||||
|
||||
|
||||
def get_category_name(category: str) -> str:
|
||||
"""
|
||||
获取分类中文名
|
||||
|
||||
Args:
|
||||
category: 分类代码
|
||||
|
||||
Returns:
|
||||
中文名
|
||||
"""
|
||||
return CATEGORY_NAMES.get(category, category)
|
||||
122
src/gui/styles/colors.py
Normal file
122
src/gui/styles/colors.py
Normal file
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
颜色定义模块
|
||||
|
||||
定义应用程序使用的颜色方案,采用米白色系
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict
|
||||
|
||||
|
||||
@dataclass
|
||||
class ColorScheme:
|
||||
"""颜色方案类 - 米白色主题"""
|
||||
|
||||
# 主色调 - 米白色系
|
||||
background_primary: str = "#FAF8F5" # 主背景色 - 米白色
|
||||
background_secondary: str = "#F0ECE8" # 次要背景色 - 浅米色
|
||||
background_card: str = "#FFFFFF" # 卡片背景色 - 纯白
|
||||
|
||||
# 文字颜色
|
||||
text_primary: str = "#2C2C2C" # 主要文字 - 深灰
|
||||
text_secondary: str = "#666666" # 次要文字 - 中灰
|
||||
text_disabled: str = "#999999" # 禁用文字 - 浅灰
|
||||
text_hint: str = "#B8B8B8" # 提示文字 - 更浅灰
|
||||
|
||||
# 强调色 - 温暖的棕色系
|
||||
accent_primary: str = "#8B6914" # 主要强调色 - 金棕
|
||||
accent_secondary: str = "#A67C52" # 次要强调色 - 驼色
|
||||
accent_hover: str = "#D4A574" # 悬停色 - 浅驼
|
||||
|
||||
# 边框和分割线
|
||||
border_light: str = "#E8E4E0" # 浅边框
|
||||
border_medium: str = "#D0CCC6" # 中边框
|
||||
border_dark: str = "#B0ABA5" # 深边框
|
||||
|
||||
# 功能色
|
||||
success: str = "#6B9B3A" # 成功 - 橄榄绿
|
||||
warning: str = "#D9A518" # 警告 - 金黄
|
||||
error: str = "#C94B38" # 错误 - 铁锈红
|
||||
info: str = "#5B8FB9" # 信息 - 钢蓝
|
||||
|
||||
# 阴影
|
||||
shadow_light: str = "rgba(0, 0, 0, 0.05)" # 浅阴影
|
||||
shadow_medium: str = "rgba(0, 0, 0, 0.1)" # 中阴影
|
||||
shadow_dark: str = "rgba(0, 0, 0, 0.15)" # 深阴影
|
||||
|
||||
# 侧边栏
|
||||
sidebar_background: str = "#F5F1EC" # 侧边栏背景
|
||||
sidebar_item_hover: str = "#EBE7E2" # 侧边栏项悬停
|
||||
sidebar_item_active: str = "#E0DCD6" # 侧边栏项激活
|
||||
sidebar_text: str = "#4A4642" # 侧边栏文字
|
||||
|
||||
# 按钮
|
||||
button_primary_bg: str = "#8B6914" # 主按钮背景
|
||||
button_primary_hover: str = "#A67C52" # 主按钮悬停
|
||||
button_primary_text: str = "#FFFFFF" # 主按钮文字
|
||||
|
||||
button_secondary_bg: str = "#E8E4E0" # 次要按钮背景
|
||||
button_secondary_hover: str = "#D0CCC6" # 次要按钮悬停
|
||||
button_secondary_text: str = "#2C2C2C" # 次要按钮文字
|
||||
|
||||
# 输入框
|
||||
input_background: str = "#FFFFFF" # 输入框背景
|
||||
input_border: str = "#D0CCC6" # 输入框边框
|
||||
input_focus_border: str = "#8B6914" # 输入框聚焦边框
|
||||
input_placeholder: str = "#B8B8B8" # 输入框占位符
|
||||
|
||||
def to_dict(self) -> Dict[str, str]:
|
||||
"""转换为字典"""
|
||||
return {
|
||||
'background_primary': self.background_primary,
|
||||
'background_secondary': self.background_secondary,
|
||||
'background_card': self.background_card,
|
||||
'text_primary': self.text_primary,
|
||||
'text_secondary': self.text_secondary,
|
||||
'text_disabled': self.text_disabled,
|
||||
'text_hint': self.text_hint,
|
||||
'accent_primary': self.accent_primary,
|
||||
'accent_secondary': self.accent_secondary,
|
||||
'accent_hover': self.accent_hover,
|
||||
'border_light': self.border_light,
|
||||
'border_medium': self.border_medium,
|
||||
'border_dark': self.border_dark,
|
||||
'success': self.success,
|
||||
'warning': self.warning,
|
||||
'error': self.error,
|
||||
'info': self.info,
|
||||
'shadow_light': self.shadow_light,
|
||||
'shadow_medium': self.shadow_medium,
|
||||
'shadow_dark': self.shadow_dark,
|
||||
'sidebar_background': self.sidebar_background,
|
||||
'sidebar_item_hover': self.sidebar_item_hover,
|
||||
'sidebar_item_active': self.sidebar_item_active,
|
||||
'sidebar_text': self.sidebar_text,
|
||||
'button_primary_bg': self.button_primary_bg,
|
||||
'button_primary_hover': self.button_primary_hover,
|
||||
'button_primary_text': self.button_primary_text,
|
||||
'button_secondary_bg': self.button_secondary_bg,
|
||||
'button_secondary_hover': self.button_secondary_hover,
|
||||
'button_secondary_text': self.button_secondary_text,
|
||||
'input_background': self.input_background,
|
||||
'input_border': self.input_border,
|
||||
'input_focus_border': self.input_focus_border,
|
||||
'input_placeholder': self.input_placeholder,
|
||||
}
|
||||
|
||||
|
||||
# 全局颜色方案实例
|
||||
COLORS = ColorScheme()
|
||||
|
||||
|
||||
def get_color(name: str) -> str:
|
||||
"""
|
||||
获取颜色值
|
||||
|
||||
Args:
|
||||
name: 颜色名称
|
||||
|
||||
Returns:
|
||||
颜色值(十六进制字符串)
|
||||
"""
|
||||
return getattr(COLORS, name, "#000000")
|
||||
437
src/gui/styles/theme.py
Normal file
437
src/gui/styles/theme.py
Normal file
@@ -0,0 +1,437 @@
|
||||
"""
|
||||
主题样式表模块
|
||||
|
||||
定义 Qt 样式表(QSS),实现米白色主题
|
||||
"""
|
||||
|
||||
from .colors import COLORS
|
||||
|
||||
|
||||
class ThemeStyles:
|
||||
"""主题样式表类"""
|
||||
|
||||
@staticmethod
|
||||
def get_main_window_stylesheet() -> str:
|
||||
"""
|
||||
获取主窗口样式表
|
||||
|
||||
Returns:
|
||||
QSS 样式表字符串
|
||||
"""
|
||||
return f"""
|
||||
/* ========== 主窗口 ========== */
|
||||
QMainWindow {{
|
||||
background-color: {COLORS.background_primary};
|
||||
}}
|
||||
|
||||
/* ========== 侧边栏 ========== */
|
||||
QWidget#sidebar {{
|
||||
background-color: {COLORS.sidebar_background};
|
||||
border-right: 1px solid {COLORS.border_light};
|
||||
}}
|
||||
|
||||
QPushButton#navButton {{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 12px 16px;
|
||||
text-align: left;
|
||||
color: {COLORS.sidebar_text};
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}}
|
||||
|
||||
QPushButton#navButton:hover {{
|
||||
background-color: {COLORS.sidebar_item_hover};
|
||||
}}
|
||||
|
||||
QPushButton#navButton:checked {{
|
||||
background-color: {COLORS.sidebar_item_active};
|
||||
color: {COLORS.accent_primary};
|
||||
font-weight: 600;
|
||||
}}
|
||||
|
||||
QWidget#navSeparator {{
|
||||
background-color: {COLORS.border_light};
|
||||
max-height: 1px;
|
||||
min-height: 1px;
|
||||
margin: 8px 16px;
|
||||
}}
|
||||
|
||||
/* ========== 主内容区域 ========== */
|
||||
QWidget#contentArea {{
|
||||
background-color: {COLORS.background_primary};
|
||||
}}
|
||||
|
||||
QStackedWidget#contentStack {{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}}
|
||||
|
||||
/* ========== 标题 ========== */
|
||||
QLabel#pageTitle {{
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
padding: 8px 0;
|
||||
}}
|
||||
|
||||
QLabel#sectionTitle {{
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding: 4px 0;
|
||||
}}
|
||||
|
||||
/* ========== 卡片 ========== */
|
||||
QWidget#card {{
|
||||
background-color: {COLORS.background_card};
|
||||
border-radius: 12px;
|
||||
border: 1px solid {COLORS.border_light};
|
||||
padding: 16px;
|
||||
}}
|
||||
|
||||
/* ========== 按钮 ========== */
|
||||
QPushButton {{
|
||||
background-color: {COLORS.button_secondary_bg};
|
||||
color: {COLORS.button_secondary_text};
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}}
|
||||
|
||||
QPushButton:hover {{
|
||||
background-color: {COLORS.button_secondary_hover};
|
||||
}}
|
||||
|
||||
QPushButton:pressed {{
|
||||
background-color: {COLORS.border_medium};
|
||||
}}
|
||||
|
||||
QPushButton:disabled {{
|
||||
background-color: {COLORS.background_secondary};
|
||||
color: {COLORS.text_disabled};
|
||||
}}
|
||||
|
||||
QPushButton#primaryButton {{
|
||||
background-color: {COLORS.button_primary_bg};
|
||||
color: {COLORS.button_primary_text};
|
||||
}}
|
||||
|
||||
QPushButton#primaryButton:hover {{
|
||||
background-color: {COLORS.button_primary_hover};
|
||||
}}
|
||||
|
||||
/* ========== 输入框 ========== */
|
||||
QLineEdit, QTextEdit, QPlainTextEdit {{
|
||||
background-color: {COLORS.input_background};
|
||||
border: 1px solid {COLORS.input_border};
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
selection-background-color: {COLORS.accent_secondary};
|
||||
}}
|
||||
|
||||
QLineEdit:hover, QTextEdit:hover, QPlainTextEdit:hover {{
|
||||
border-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {{
|
||||
border: 2px solid {COLORS.input_focus_border};
|
||||
padding: 7px 11px;
|
||||
}}
|
||||
|
||||
QLineEdit:disabled, QTextEdit:disabled, QPlainTextEdit:disabled {{
|
||||
background-color: {COLORS.background_secondary};
|
||||
color: {COLORS.text_disabled};
|
||||
}}
|
||||
|
||||
/* ========== 下拉框 ========== */
|
||||
QComboBox {{
|
||||
background-color: {COLORS.input_background};
|
||||
border: 1px solid {COLORS.input_border};
|
||||
border-radius: 6px;
|
||||
padding: 8px 12px;
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
}}
|
||||
|
||||
QComboBox:hover {{
|
||||
border-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QComboBox:focus {{
|
||||
border: 2px solid {COLORS.input_focus_border};
|
||||
}}
|
||||
|
||||
QComboBox::drop-down {{
|
||||
border: none;
|
||||
width: 20px;
|
||||
}}
|
||||
|
||||
QComboBox::down-arrow {{
|
||||
image: none;
|
||||
border: 5px solid transparent;
|
||||
border-top-color: {COLORS.text_secondary};
|
||||
margin-right: 5px;
|
||||
}}
|
||||
|
||||
QComboBox QAbstractItemView {{
|
||||
background-color: {COLORS.background_card};
|
||||
border: 1px solid {COLORS.border_light};
|
||||
selection-background-color: {COLORS.sidebar_item_active};
|
||||
selection-color: {COLORS.text_primary};
|
||||
padding: 4px;
|
||||
}}
|
||||
|
||||
/* ========== 滚动条 ========== */
|
||||
QScrollBar:vertical {{
|
||||
background-color: transparent;
|
||||
width: 10px;
|
||||
margin: 0px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:vertical {{
|
||||
background-color: {COLORS.border_medium};
|
||||
border-radius: 5px;
|
||||
min-height: 30px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:vertical:hover {{
|
||||
background-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{
|
||||
height: 0px;
|
||||
}}
|
||||
|
||||
QScrollBar:horizontal {{
|
||||
background-color: transparent;
|
||||
height: 10px;
|
||||
margin: 0px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:horizontal {{
|
||||
background-color: {COLORS.border_medium};
|
||||
border-radius: 5px;
|
||||
min-width: 30px;
|
||||
}}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {{
|
||||
background-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {{
|
||||
width: 0px;
|
||||
}}
|
||||
|
||||
/* ========== 分组框 ========== */
|
||||
QGroupBox {{
|
||||
background-color: {COLORS.background_card};
|
||||
border: 1px solid {COLORS.border_light};
|
||||
border-radius: 8px;
|
||||
margin-top: 12px;
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: {COLORS.text_primary};
|
||||
}}
|
||||
|
||||
QGroupBox::title {{
|
||||
subcontrol-origin: margin;
|
||||
left: 16px;
|
||||
padding: 0 8px;
|
||||
}}
|
||||
|
||||
/* ========== 标签页 ========== */
|
||||
QTabWidget::pane {{
|
||||
background-color: {COLORS.background_card};
|
||||
border: 1px solid {COLORS.border_light};
|
||||
border-radius: 8px;
|
||||
top: -1px;
|
||||
}}
|
||||
|
||||
QTabBar::tab {{
|
||||
background-color: {COLORS.background_secondary};
|
||||
color: {COLORS.text_secondary};
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
margin-right: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}}
|
||||
|
||||
QTabBar::tab:selected {{
|
||||
background-color: {COLORS.background_card};
|
||||
color: {COLORS.text_primary};
|
||||
font-weight: 600;
|
||||
}}
|
||||
|
||||
QTabBar::tab:hover:!selected {{
|
||||
background-color: {COLORS.sidebar_item_hover};
|
||||
}}
|
||||
|
||||
/* ========== 复选框 ========== */
|
||||
QCheckBox {{
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
spacing: 8px;
|
||||
}}
|
||||
|
||||
QCheckBox::indicator {{
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid {COLORS.input_border};
|
||||
border-radius: 4px;
|
||||
background-color: {COLORS.input_background};
|
||||
}}
|
||||
|
||||
QCheckBox::indicator:hover {{
|
||||
border-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QCheckBox::indicator:checked {{
|
||||
background-color: {COLORS.accent_primary};
|
||||
border-color: {COLORS.accent_primary};
|
||||
image: none;
|
||||
}}
|
||||
|
||||
QCheckBox::indicator:checked::after {{
|
||||
content: "✓";
|
||||
color: {COLORS.button_primary_text};
|
||||
}}
|
||||
|
||||
/* ========== 单选框 ========== */
|
||||
QRadioButton {{
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
spacing: 8px;
|
||||
}}
|
||||
|
||||
QRadioButton::indicator {{
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid {COLORS.input_border};
|
||||
border-radius: 9px;
|
||||
background-color: {COLORS.input_background};
|
||||
}}
|
||||
|
||||
QRadioButton::indicator:hover {{
|
||||
border-color: {COLORS.border_dark};
|
||||
}}
|
||||
|
||||
QRadioButton::indicator:checked {{
|
||||
background-color: {COLORS.input_background};
|
||||
border-color: {COLORS.accent_primary};
|
||||
}}
|
||||
|
||||
QRadioButton::indicator:checked::after {{
|
||||
content: "";
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: {COLORS.accent_primary};
|
||||
}}
|
||||
|
||||
/* ========== 进度条 ========== */
|
||||
QProgressBar {{
|
||||
background-color: {COLORS.background_secondary};
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
height: 8px;
|
||||
text-align: center;
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 12px;
|
||||
}}
|
||||
|
||||
QProgressBar::chunk {{
|
||||
background-color: {COLORS.accent_primary};
|
||||
border-radius: 6px;
|
||||
}}
|
||||
|
||||
/* ========== 分隔线 ========== */
|
||||
QFrame[frameShape="4"], QFrame[frameShape="5"] {{
|
||||
color: {COLORS.border_light};
|
||||
}}
|
||||
|
||||
/* ========== 工具提示 ========== */
|
||||
QToolTip {{
|
||||
background-color: {COLORS.text_primary};
|
||||
color: {COLORS.background_primary};
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
}}
|
||||
|
||||
/* ========== 菜单 ========== */
|
||||
QMenu {{
|
||||
background-color: {COLORS.background_card};
|
||||
border: 1px solid {COLORS.border_light};
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
}}
|
||||
|
||||
QMenu::item {{
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
}}
|
||||
|
||||
QMenu::item:selected {{
|
||||
background-color: {COLORS.sidebar_item_active};
|
||||
color: {COLORS.accent_primary};
|
||||
}}
|
||||
|
||||
QMenu::separator {{
|
||||
height: 1px;
|
||||
background-color: {COLORS.border_light};
|
||||
margin: 4px 8px;
|
||||
}}
|
||||
|
||||
/* ========== 列表 ========== */
|
||||
QListWidget {{
|
||||
background-color: {COLORS.background_card};
|
||||
border: 1px solid {COLORS.border_light};
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
}}
|
||||
|
||||
QListWidget::item {{
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
color: {COLORS.text_primary};
|
||||
font-size: 14px;
|
||||
}}
|
||||
|
||||
QListWidget::item:hover {{
|
||||
background-color: {COLORS.sidebar_item_hover};
|
||||
}}
|
||||
|
||||
QListWidget::item:selected {{
|
||||
background-color: {COLORS.sidebar_item_active};
|
||||
color: {COLORS.accent_primary};
|
||||
}}
|
||||
|
||||
/* ========== 状态栏 ========== */
|
||||
QStatusBar {{
|
||||
background-color: {COLORS.background_secondary};
|
||||
color: {COLORS.text_secondary};
|
||||
border-top: 1px solid {COLORS.border_light};
|
||||
font-size: 12px;
|
||||
}}
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def apply_style(widget) -> None:
|
||||
"""
|
||||
应用样式到部件
|
||||
|
||||
Args:
|
||||
widget: Qt 部件
|
||||
"""
|
||||
widget.setStyleSheet(ThemeStyles.get_main_window_stylesheet())
|
||||
Reference in New Issue
Block a user