#!/usr/bin/env python
'''
锐色(rycy): HSB 拾色器 14 彩。
'''

VER = r'''
rycy version: 2026.1.15.0
'''

COPR = r'''
版权所有 2025 锐码[rymaa.cn] - rybby@163.com。本软件采用 GPL v3 开源许可证。使用PyQt5库 (Riverbank Computing, GPL v3)。本程序为自由软件，在自由软件基金会发布的GNU通用公共许可证（第3版或更新版本）的条款下分发。详情请见 <https://www.gnu.org/licenses/gpl-3.0.html> 或应用目录里的 LICENSE 文件。
'''

INFO = r'''
锐色(rycy) 是一款 HSB 拾色器，由锐码工作室发行推出，锐白个人开发完成。锐色(rycy)只有14种色相(彩度)，分别是：红色(Red)，橙色(Orange)，金色(Gold)，黄色(Yellow)，黄绿(Chartreuse)，春绿(Spring-Greens)，绿色(Green)，青绿(Viridity)，青色(Cyan)，天蓝(Skyblue)，蓝色(Blue)，蓝紫(Bluish-Violet)，紫色(Violet)，紫红(Magenta)。

每种色相只有5%、10%、20%三种浓度和亮度步长，只要确定一种颜色主题，就可以轻松选择需要的颜色，不像传统的拾色器那样密密麻麻的颜色布局导致选择颜色相对困难。

PS: 5%步长按钮在点击时可以在1%、2%、5%进行切换，方便在网页样式设计时选择浅淡的背景色。若是 VI 设计从业者，使用 5%、10%、20% 三种步长足够了。另外，CMYK 的色值是根据 HSB 转换的，可能与 PS/AI 等软件的色值有出入，如果要使用精准的 CMYK 值，可以考虑将三种步长对应的所有 RGB 色块值导入到 PS/AI 软件，再从 PS/AI 软件把色板导出来提取其中的 CMYK 色值与三种步长的 HSB 色值建立映射关系。潘通色卡号目前没有对应的色值，想要潘通色卡号的可以到相关的接口进行查询并与三种步长的 HSB 色值建立映射关系。

基本操作

安装锐色(rycy): pip install rycy

安装依赖库: pip install PyQt5

PyQt5 需要图形显示相关的系统库，安装所有可能的图形依赖：apt install -y libgl1-mesa-glx libglu1-mesa libxrender1 libxext6 libx11-6 libglib2.0-0 libxcb-* libx11-xcb-dev libxkbcommon-x11-0 xvfb mesa-utils

快捷键：

A(连按3次): 切换快捷键模式

1~7,Q~U: 色相

D/F/G: 步长5/10/20

B/N: S-/B+

C/V: 复制主色/辅色

X: 切换复制格式

H: 显示帮助

M: 最小化窗口(点击右上角同效)

Esc: 退出
'''

HELP = r'''
+-------------------------------------------+
|            rycy: HSB Color 14             |
+-------------------------------------------+
|            HomePage: rymaa.cn             |
+-------------------------------------------+

Usage:
    rycy [option]

Options:
    -H, --help   Show help / 显示帮助
    -I, --info   Show info / 显示信息
    -C, --copr   Show copyright / 显示版权
    -V, --version   Show version / 显示版本
    -r, --run   run window / 启动图形窗口
'''

##############################

import os
import sys
import argparse
import subprocess
from pathlib import Path
from PyQt5.QtWidgets import QApplication, QWidget, QScrollArea, QLabel, QVBoxLayout, QDialog, QFileDialog
from PyQt5.QtGui import QPainter, QBrush, QPen, QFont, QColor, QRadialGradient, QLinearGradient, QPixmap, QImage
from PyQt5.QtCore import Qt, QRect, QTimer, QMargins

# 脚本运行模式的路径修复
if __name__ == '__main__' and __package__ is None:
    pjt_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.insert(0, pjt_root)
    __package__ = 'rycy'

##############################

class HelpDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("帮助")
        self.setFixedSize(300, 400)
        layout = QVBoxLayout()
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)

        content_label = QLabel()
        content_label.setTextFormat(Qt.PlainText)
        content_label.setWordWrap(True)
        content_label.setText(
            "锐色(rycy) 是一款 HSB 拾色器，由锐码工作室发行推出，锐白个人开发完成。锐色(rycy)只有14种色相(彩度)，分别是：红色(Red)，橙色(Orange)，金色(Gold)，黄色(Yellow)，黄绿(Chartreuse)，春绿(Spring-Greens)，绿色(Green)，青绿(Viridity)，青色(Cyan)，天蓝(Skyblue)，蓝色(Blue)，蓝紫(Bluish-Violet)，紫色(Violet)，紫红(Magenta)。\n\n每种色相只有5%、10%、20%三种浓度和亮度步长，只要确定一种颜色主题，就可以轻松选择需要的颜色，不像传统的拾色器那样密密麻麻的颜色布局导致选择颜色相对困难。PS: 5%步长按钮在点击时可以在1%、2%、5%进行切换，方便在网页样式设计时选择浅淡的背景色。若是 VI 设计从业者，使用 5%、10%、20% 三种步长足够了。另外，CMYK 的色值是根据 HSB 转换的，可能与 PS/AI 等软件的色值有出入，如果要使用精准的 CMYK 值，可以考虑将三种步长对应的所有 RGB 色块值导入到 PS/AI 软件，再从 PS/AI 软件把色板导出来提取其中的 CMYK 色值与三种步长的 HSB 色值建立映射关系。潘通色卡号目前没有对应的色值，想要潘通色卡号的可以到相关的接口进行查询并与三种步长的 HSB 色值建立映射关系。\n\n"
            "快捷键：\n"
            "A(连按3次): 切换快捷键模式\n"
            "1~7,Q~U: 色相\n"
            "D/F/G: 步长5/10/20\n"
            "B/N: S-/B+\n"
            "C/V: 复制主色/辅色\n"
            "X: 切换复制格式\n"
            "H: 显示帮助\n"
            "M: 最小化窗口(点击右上角同效)\n"
            "Esc: 退出"
        )
        content_label.setStyleSheet("padding: 10px; font-family: Verdana; font-size: 10pt;")
        scroll_area.setWidget(content_label)
        layout.addWidget(scroll_area)
        self.setLayout(layout)
        self.setStyleSheet("background-color: #ddd;")

class rycyColorPicker(QWidget):
    def __init__(self):
        super().__init__()
        # 窗口设置
        self.setFixedSize(260, 335)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground, False)

        # 初始状态
        self.hue = 0
        self.sat = 100
        self.bri = 100
        self.step = 10
        self.step2 = 5  # 新增：用于 1/2/5 循环
        self.sl = 2  # 饱和度等级
        self.bl = 1  # 亮度等级
        self.cn = 0  # 复制格式索引
        self.cnl = ['all', 'hex', '#hex', 'rgb', 'rgba', 'hsv', 'hsb', 'cmyk', 'pan']
        self.mns = 0  # 是否显示菜单
        self.cps = 0  # 是否显示复制提示
        self.cpv = ""  # 复制内容
        self.cx = self.cy = 0  # 当前选中色块坐标（绘制游标用）

        # 色相按钮定义
        self.hue_buttons = [
            (0, "0"), (30, "30"), (45, "45"), (60, "60"), (75, "75"), (90, "90"),
            (120, "120"), (150, "150"), (180, "180"), (210, "210"), (240, "240"),
            (270, "270"), (300, "300"), (330, "330")
        ]

        # 主色、辅色
        self.mc = "#FF0000"
        self.ac = "#FF3232"

        # 启动定时器隐藏复制提示
        self.copy_timer = self.new_timer()

        self.help_dialog = HelpDialog(self)

        # 快捷键模式控制
        self.feature_mode = False  # 功能键模式（三连 A 激活）
        self.f_press_count = 0
        self.f_timer = QTimer()
        self.f_timer.setSingleShot(True)
        self.f_timer.timeout.connect(self.reset_f_count)

        # 窗口状态
        self.last_mouse_pos = None

        self.setWindowTitle("锐色rycy HSB 14")
        self.show()

    def new_timer(self):
        timer = self.startTimer(3000)  # 3秒后触发
        return timer

    def timerEvent(self, event):
        if event.timerId() == self.copy_timer:
            self.killTimer(self.copy_timer)
            self.cps = 0
            self.update()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.last_mouse_pos = event.globalPos() - self.pos()

        # 点击右上角 20px 区域最小化
        pos = event.pos()
        if pos.x() >= self.width() - 20 and pos.y() <= 20:
            self.showMinimized()

    def mouseMoveEvent(self, event):
        if hasattr(self, 'last_mouse_pos') and self.last_mouse_pos is not None:
            self.move(event.globalPos() - self.last_mouse_pos)

    def mouseReleaseEvent(self, event):
        if hasattr(self, 'last_mouse_pos'):
            self.last_mouse_pos = None

    def keyPressEvent(self, event):
        # 处理三连 A 激活功能键模式
        if event.key() == Qt.Key_A:
            self.f_press_count += 1
            if self.f_press_count >= 3:
                self.feature_mode = not self.feature_mode
                self.f_press_count = 0
                self.update()
            else:
                self.f_timer.start(300)  # 300ms内再按有效
            return

        # 只有在功能键模式下才执行快捷键操作
        if self.feature_mode:
            self.handle_key_action(event)
        
    def reset_f_count(self):
        self.f_press_count = 0

    def handle_key_action(self, event):
        key_map = {
            Qt.Key_1: 0, Qt.Key_2: 30, Qt.Key_3: 45, Qt.Key_4: 60,
            Qt.Key_5: 75, Qt.Key_6: 90, Qt.Key_7: 120,
            Qt.Key_Q: 150, Qt.Key_W: 180, Qt.Key_E: 210,
            Qt.Key_R: 240, Qt.Key_T: 270, Qt.Key_Y: 300, Qt.Key_U: 330,
            Qt.Key_D: 'step5', Qt.Key_F: 10, Qt.Key_G: 20,  # D 键改为触发 step5 循环
            Qt.Key_B: 'sl', Qt.Key_N: 'bl',
            Qt.Key_X: 'cpn', Qt.Key_C: 'mc', Qt.Key_V: 'ac',
            Qt.Key_H: 'help', Qt.Key_M: 'mini', Qt.Key_Escape: 'esc'
        }
        if event.key() in key_map:
            val = key_map[event.key()]
            if isinstance(val, int):
                self.hue = val
                self.update_colors()
            elif val == 'step5':
                # 循环切换 5 → 2 → 1 → 5...
                if self.step2 == 5:
                    self.step = self.step2 = 2
                elif self.step2 == 2:
                    self.step = self.step2 = 1
                else:  # self.step2 == 1
                    self.step = self.step2 = 5
                self.update_colors()
            elif val == 10 or val == 20:
                self.step = val
                self.update_colors()
            elif val == 'sl':
                self.sl = (self.sl + 1) % 6
                self.update_colors()
            elif val == 'bl':
                self.bl = (self.bl + 1) % 6
                self.update_colors()
            elif val == 'cpn':
                self.cn = (self.cn + 1) % len(self.cnl)
                self.update()
            elif val == 'mc':
                self.copy_color('mc')
            elif val == 'ac':
                self.copy_color('ac')
            elif val == 'help':
                self.toggle_help()
            elif val == 'mini':
                self.showMinimized()
            elif val == 'esc':
                self.close()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # 背景
        painter.fillRect(self.rect(), QBrush(QColor("#eee")))

        # 计算主色和辅色
        self.mc = self.hsv_to_rgb(self.hue, self.sat, self.bri)
        if self.sl != 0 or self.bl != 0:
            s = max(0, self.sat - self.step * self.sl)
            b = min(100, self.bri + self.step * self.bl)
            self.ac = self.hsv_to_rgb(self.hue, s, b)
        else:
            self.ac = self.mc

        # 计算文字颜色（根据亮度决定黑白）
        r = int(self.mc[1:3], 16)
        g = int(self.mc[3:5], 16)
        b = int(self.mc[5:7], 16)
        brightness = (r * 299 + g * 587 + b * 114) / 1000
        fg_color = QColor("#fff") if brightness < 128 else QColor("#000")

        # 绘制色相按钮 (30x25)
        x, y = 0, 0
        for i, (h, label) in enumerate(self.hue_buttons):
            rect = QRect(x, y, 30, 25)
            color = self.hsv_to_rgb(h, 100, 100)
            painter.setBrush(QBrush(QColor(color)))
            painter.setPen(QPen(QColor("#ccc"), 0.5))
            painter.drawRect(rect)
            if h == self.hue:
                painter.setPen(QPen(QColor("#fff")))
            else:
                painter.setPen(QPen(QColor("#000")))
            painter.setFont(QFont("Verdana", 10))
            painter.drawText(rect, Qt.AlignCenter, label)
            x += 30
            if i == 6:
                x = 0
                y = 25

        # 右上角大方框使用方框径向渐变
        rect = QRect(210, 0, 50, 50)
        center_x = rect.center().x()
        center_y = rect.center().y()
        max_radius = max(rect.width(), rect.height()) * 0.7
        grad = QRadialGradient(center_x, center_y, max_radius, center_x, center_y)
        grad.setColorAt(0, QColor(self.ac))
        grad.setColorAt(1, QColor(self.mc))
        painter.setBrush(QBrush(grad))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)

        # 绘制底部按钮
        btn_y = 50
        btn_w, btn_h = 25, 25

        # 步长按钮：第一个按钮现在显示 step2 的值（1/2/5）
        steps_display = [str(self.step2), '10', '20']  # 第一个动态
        for i in range(3):
            rect = QRect(i * btn_w, btn_y, btn_w, btn_h)
            is_active = (i == 0 and self.step in [1,2,5]) or (i == 1 and self.step == 10) or (i == 2 and self.step == 20)
            if is_active:
                painter.setBrush(QBrush(QColor("#bbf")))
            else:
                painter.setBrush(QBrush(QColor("#ddf")))
            painter.setPen(QPen(QColor("#ccc"), 0.5))
            painter.drawRect(rect)
            painter.setPen(QPen(QColor("#000")))
            font_size = 8
            if self.step in (1, 2, 5):
                font_size = 7
            painter.setFont(QFont("Verdana", font_size))
            painter.drawText(rect, Qt.AlignCenter, steps_display[i])

        # S-
        rect = QRect(75, btn_y, btn_w, btn_h)
        painter.setBrush(QBrush(QColor("#ddf")))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)
        painter.setPen(QPen(QColor("#000")))
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(rect, Qt.AlignCenter, f"S-{self.sl}")

        # B+
        rect = QRect(100, btn_y, btn_w, btn_h)
        painter.setBrush(QBrush(QColor("#ddf")))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)
        painter.setPen(QPen(QColor("#000")))
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(rect, Qt.AlignCenter, f"B+{self.bl}")

        # CP
        rect = QRect(125, btn_y, btn_w, btn_h)
        painter.setBrush(QBrush(QColor("#ddf")))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)
        painter.setPen(QPen(QColor("#000")))
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(rect, Qt.AlignCenter, self.cnl[self.cn])

        # MC
        rect = QRect(150, btn_y, btn_w, btn_h)
        painter.setBrush(QBrush(QColor(self.mc)))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)
        painter.setPen(fg_color)
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(rect, Qt.AlignCenter, "MC")

        # AC
        rect = QRect(175, btn_y, btn_w, btn_h)
        painter.setBrush(QBrush(QColor(self.ac)))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(rect)
        painter.setPen(fg_color)
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(rect, Qt.AlignCenter, "AC")

        # Help 按钮使用从左到右的线性渐变
        help_rect = QRect(200, btn_y, 60, btn_h)
        if self.mc != self.ac:
            grad = QLinearGradient(help_rect.left(), help_rect.center().y(),
                                   help_rect.right(), help_rect.center().y())
            grad.setColorAt(0, QColor(self.mc))
            grad.setColorAt(1, QColor(self.ac))
            painter.setBrush(QBrush(grad))
        else:
            painter.setBrush(QBrush(QColor(self.mc)))
        painter.setPen(QPen(QColor("#ccc"), 0.5))
        painter.drawRect(help_rect)
        painter.setPen(fg_color)
        painter.setFont(QFont("Verdana", font_size))
        painter.drawText(help_rect, Qt.AlignCenter, "Help")

        # === 色板绘制逻辑 ===
        if self.step == 1:
            sp, vp = 20, 80
        elif self.step == 2:
            sp, vp = 40, 60
        else:  # 5, 10, 20
            sp, vp = 100, 0

        # 确定起始位置和块大小
        if self.step in (1, 2, 5):
            block_w = block_h = 10
            start_x, start_y = 30, 105
            font_size_label = 6
        elif self.step == 10:
            block_w = block_h = 20
            start_x, start_y = 30, 105
            font_size_label = 8
        else:  # step == 20
            block_w = block_h = 40
            start_x, start_y = 10, 85
            font_size_label = None  # 不显示标签

        # 绘制色板
        for i, v in enumerate(range(100, vp - 1, -self.step)):
            for j, s in enumerate(range(0, sp + 1, self.step)):
                x = start_x + j * block_w
                y = start_y + i * block_h
                color = self.hsv_to_rgb(self.hue, s, v)
                painter.setBrush(QBrush(QColor(color)))
                painter.setPen(QPen(QColor("#ccc"), 0.5))
                painter.drawRect(x, y, block_w, block_h)
                if s == self.sat and v == self.bri:
                    self.cx, self.cy = x, y

        # 绘制 S/B 标签（仅当 step <=10）
        if self.step in (1, 2, 5, 10):
            border_pen = QPen(QColor("#ccc"), 0.5)
            painter.setFont(QFont("Verdana", font_size_label))

            # S/B 标识
            label_rect = QRect(start_x - 20, start_y - 20, 20, 20)
            painter.setPen(border_pen)
            painter.setBrush(QBrush(Qt.NoBrush))
            painter.drawRect(label_rect)
            painter.setPen(QPen(QColor("#000")))
            painter.drawText(label_rect, Qt.AlignCenter, "S/B")

            # 左侧 B 值
            for i, v in enumerate(range(100, vp - 1, -self.step)):
                y = start_y + i * block_h
                text_rect = QRect(start_x - 20, y, 20, block_h)
                painter.setPen(border_pen)
                painter.setBrush(QBrush(Qt.NoBrush))
                painter.drawRect(text_rect)
                painter.setPen(QPen(QColor("#000")))
                painter.drawText(text_rect, Qt.AlignCenter, str(v))

            # 顶部 S 值
            for j, s in enumerate(range(0, sp + 1, self.step)):
                x = start_x + j * block_w
                text_rect = QRect(x, start_y - 20, block_w, 20)
                painter.setPen(border_pen)
                painter.setBrush(QBrush(Qt.NoBrush))
                painter.drawRect(text_rect)
                painter.setPen(QPen(QColor("#000")))
                painter.drawText(text_rect, Qt.AlignCenter, str(s))

        # 画十字游标
        if self.cx and self.cy:
            painter.setPen(QPen(fg_color, 1))
            cx_center = self.cx + block_w // 2
            cy_center = self.cy + block_h // 2
            painter.drawLine(cx_center, self.cy, cx_center, self.cy + block_h)
            painter.drawLine(self.cx, cy_center, self.cx + block_w, cy_center)

        # 复制提示
        if self.cps:
            total_width = ((sp // self.step) + 1) * block_w
            total_height = ((100 - vp) // self.step + 1) * block_h
            text_rect = QRect(start_x, start_y, total_width, total_height)
            painter.setPen(QPen(QColor("#fff")))
            painter.setFont(QFont("Verdana", 10, QFont.Bold))
            painter.drawText(text_rect, Qt.AlignCenter, self.cpv)

        # 右下角绿色小方块（功能键模式指示）
        if self.feature_mode:
            painter.setBrush(QBrush(QColor("#080")))
            painter.setPen(Qt.NoPen)
            painter.drawRect(self.width() - 10, self.height() - 10, 10, 10)

    def mouseReleaseEvent(self, event):
        pos = event.pos()
        x, y = pos.x(), pos.y()

        # 检查色相按钮
        for i, (h, label) in enumerate(self.hue_buttons):
            row = i // 7
            col = i % 7
            bx = col * 30
            by = row * 25
            if bx <= x < bx + 30 and by <= y < by + 25:
                self.hue = h
                self.update_colors()
                return

        # 检查底部按钮
        if 50 <= y < 75:
            if x < 75:
                step_idx = x // 25
                if step_idx == 0:
                    # 点击第一个按钮：循环 5→2→1
                    if self.step2 == 5:
                        self.step = self.step2 = 2
                    elif self.step2 == 2:
                        self.step = self.step2 = 1
                    else:
                        self.step = self.step2 = 5
                    self.update_colors()
                elif step_idx == 1:
                    self.step = 10
                    self.update_colors()
                elif step_idx == 2:
                    self.step = 20
                    self.update_colors()
            elif 75 <= x < 100:
                self.sl = (self.sl + 1) % 6
                self.update_colors()
            elif 100 <= x < 125:
                self.bl = (self.bl + 1) % 6
                self.update_colors()
            elif 125 <= x < 150:
                self.cn = (self.cn + 1) % len(self.cnl)
                self.update()
            elif 150 <= x < 175:
                self.copy_color('mc')
            elif 175 <= x < 200:
                self.copy_color('ac')
            elif 200 <= x < 260:
                self.toggle_help()

        # 色板区域点击
        if self.step == 1:
            sp, vp = 20, 80
            start_x, start_y = 30, 105
            block_w = block_h = 10
        elif self.step == 2:
            sp, vp = 40, 60
            start_x, start_y = 30, 105
            block_w = block_h = 10
        elif self.step == 5:
            sp, vp = 100, 0
            start_x, start_y = 30, 105
            block_w = block_h = 10
        elif self.step == 10:
            sp, vp = 100, 0
            start_x, start_y = 30, 105
            block_w = block_h = 20
        else:  # step == 20
            sp, vp = 100, 0
            start_x, start_y = 10, 85
            block_w = block_h = 40

        if x >= start_x and y >= start_y:
            j = (x - start_x) // block_w
            i = (y - start_y) // block_h
            s = j * self.step
            v = 100 - i * self.step
            if 0 <= s <= sp and vp <= v <= 100:
                self.sat = s
                self.bri = v
                self.update_colors()

    def update_colors(self):
        self.update()

    def hsv_to_rgb(self, h, s, v):
        h = h % 360
        s /= 100
        v /= 100
        c = v * s
        x = c * (1 - abs((h / 60) % 2 - 1))
        m = v - c
        if 0 <= h < 60:
            r, g, b = c, x, 0
        elif 60 <= h < 120:
            r, g, b = x, c, 0
        elif 120 <= h < 180:
            r, g, b = 0, c, x
        elif 180 <= h < 240:
            r, g, b = 0, x, c
        elif 240 <= h < 300:
            r, g, b = x, 0, c
        else:
            r, g, b = c, 0, x
        r, g, b = (r + m), (g + m), (b + m)
        return f"#{int(r*255):02X}{int(g*255):02X}{int(b*255):02X}"

    def rgb_to_hsv(self, r, g, b):
        r, g, b = r / 255.0, g / 255.0, b / 255.0
        mx = max(r, g, b)
        mn = min(r, g, b)
        df = mx - mn
        if mx == mn:
            h = 0
        elif mx == r:
            h = (60 * ((g - b) / df) + 360) % 360
        elif mx == g:
            h = (60 * ((b - r) / df) + 120) % 360
        else:
            h = (60 * ((r - g) / df) + 240) % 360
        s = 0 if mx == 0 else (df / mx)
        v = mx
        return {'h': round(h), 's': round(s * 100), 'v': round(v * 100)}

    def copy_color(self, mode):
        clipboard = QApplication.clipboard()
        if mode == 'mc':
            color = self.mc
        else:
            color = self.ac

        r = int(color[1:3], 16)
        g = int(color[3:5], 16)
        b = int(color[5:7], 16)

        hsv = self.rgb_to_hsv(r, g, b)
        h, s, v = hsv['h'], hsv['s'], hsv['v']

        c = 1 - r / 255
        m = 1 - g / 255
        y = 1 - b / 255
        k = min(c, m, y)
        if k == 1:
            c = m = y = 0
        else:
            c = (c - k) / (1 - k)
            m = (m - k) / (1 - k)
            y = (y - k) / (1 - k)
        cmyk = f"CMYK: {int(c*100)} {int(m*100)} {int(y*100)} {int(k*100)}"

        hex_val = color[1:].upper()
        hash_hex = color.upper()

        formats = [
            f"{hash_hex}\nrgb({r}, {g}, {b})\nrgba({r}, {g}, {b}, 1)\nhsv({h}, {s}, {v})\n{cmyk}\nPANTONE 185 C",
            hex_val,
            hash_hex,
            f"rgb({r}, {g}, {b})",
            f"rgba({r}, {g}, {b}, 1)",
            f"hsv({h}, {s}, {v})",
            f"HSB: {h} {s} {v}",
            cmyk,
            "PANTONE 185 C"
        ]

        text = formats[self.cn]
        clipboard.setText(text)
        self.cpv = text
        self.cps = 1
        if hasattr(self, 'copy_timer'):
            self.killTimer(self.copy_timer)
        self.copy_timer = self.new_timer()
        self.update()

    def toggle_help(self):
        if self.help_dialog.isVisible():
            self.help_dialog.hide()
        else:
            self.help_dialog.show()


def run_win(run):
    '''
    启动图形窗口。
    '''
    if run:
        app = QApplication(sys.argv)
        picker = rycyColorPicker()
        sys.exit(app.exec_())
    else:
        if sys.platform == "win32":
            pythonw_path = sys.executable.replace('python.exe', 'pythonw.exe')
            script_path = Path(__file__).resolve()
            cmd = f'start "" "{pythonw_path}" "{script_path}" -r --win'
            subprocess.Popen(cmd, shell=True, start_new_session=True)
        else:
            # Linux/macOS
            script_path = Path(__file__).resolve()
            cmd = [sys.executable, str(script_path), "-r", "--win"]
            subprocess.Popen(cmd, start_new_session=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

        print("\nGUI 已在后台启动，当前命令行可安全关闭。")
        sys.exit(0)

def main(args=None):
    '''
    入口主函数。
    返回: void
    参数列表：
        args (str): 参数列表，通过命令行传入或调用者传入。
    '''

    # 全局选项
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('-H', '--help', action='store_true')
    parser.add_argument('-I', '--info', action='store_true')
    parser.add_argument('-C', '--copr', action='store_true')
    parser.add_argument('-V', '--version', action='store_true')
    parser.add_argument('-r', '--run', action='store_true')
    parser.add_argument('--win', action='store_true')

    args = parser.parse_args(args)

    if args.version:
        print(VER)
    elif args.copr:
        print(COPR)
    elif args.info:
        print(INFO)
    elif args.help:
        print(HELP)
    elif args.run:
        run_win(args.win)
    else:
        print(HELP)

if __name__ == '__main__':
    main()