import re from PyQt6.QtCore import QSize, Qt, QRect from PyQt6.QtGui import QColor, QPainter, QPixmap, QIcon, QBrush, QPen, QPaintEngine from PyQt6.QtWidgets import QWidget, QHBoxLayout, QPushButton, QColorDialog, QSizePolicy, QComboBox class ColorButton(QWidget): def __init__(self, color: str): super(QWidget, self).__init__() self.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)) self.layout = QHBoxLayout(self) self.color = color colors = { # red self.tr('Strawberry Cream'): 'ff8080', self.tr('Pale Crimson'): 'e61919', # orange self.tr('Broken Buttercup'): 'ffd080', self.tr('Passion Fruit Sugar'): 'ffa200', # yellow self.tr('Sunrise Yellow'): 'fff080', self.tr('Magical Mustard'): 'ccb400', # green self.tr('Trendy Green'): 'aaff80', self.tr('Garden Of Sweden'): '44cc00', # blue self.tr('Light Sky Blue'): '80c6ff', self.tr('True Blue'): '0073d1', # purple self.tr('Fairy Topia'): 'ff80f4', self.tr('Magenta Bachiego'): 'cc00bb', # grey self.tr('Light Grey'): 'cccccc', self.tr('Grey'): '999999', # self.tr('Hot Pink'): 'ffaebc', # self.tr('Light Coral'): 'f08080', # self.tr('Red'): 'cc0000', # self.tr('Orange'): 'fcaf3e', # self.tr('Dark Orange'): 'ce5c00', # self.tr('Yellow'): 'fce94f', # self.tr('Dark Yellow'): 'c4a000', # self.tr('Mint'): 'b4f8c8', # self.tr('Green'): '8ae234', # self.tr('Dark Green'): '439a06', # self.tr('Tiffany Blue'): 'a0e7e5', # self.tr('Blue'): '729fcf', # self.tr('Dark Blue'): '3465a4', # self.tr('Purple'): 'ad7fa8', # self.tr('Dark Purple'): '5c3566', # self.tr('Brown'): 'e9b96e', # self.tr('Dark Brown'): 'c17d11', # self.tr('Grey'): 'd3d7cf', # self.tr('Dark Grey'): '888a85', # self.tr('Brewer Light Blue'): 'ece7f2', # self.tr('Brewer Blue'): 'a6bddb', # self.tr('Brewer Dark Blue'): '2b8cbe', # self.tr('Brewer Light Red'): 'fee8c8', # self.tr('Brewer Red'): 'fdbb84', # self.tr('Brewer Dark Red'): 'e34a33', } self.color_drop_down = QComboBox() self.layout.addWidget(self.color_drop_down) self.color_drop_down.addItem("transparent", "None") for color_name in colors.keys(): color_value = colors[color_name] self.color_drop_down.addItem(QIcon(self._color_pixmap(color_value)), color_name, color_value) self.color_drop_down.currentIndexChanged.connect(self._color_selected) self.btn_color_picker = QPushButton(self.tr("custom")) self.layout.addWidget(self.btn_color_picker) self.btn_color_picker.pressed.connect(self._update_color) self.btn_color_picker.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)) def _color_selected(self, index: int): self.color = self.color_drop_down.currentData() def set_color(self, color: str): self.color = color for index in range(0, self.color_drop_down.count()): item_value = self.color_drop_down.itemData(index) if item_value == color: self.color_drop_down.setCurrentIndex(index) return # color not yet present -> add it self.color_drop_down.addItem(QIcon(self._color_pixmap(color)), color, color) self.color_drop_down.setCurrentIndex(self.color_drop_down.count() - 1) def _update_color(self): new_color = QColorDialog.getColor(self._to_qcolor(self.color)) if new_color.isValid(): color = self._to_hex(new_color) self.set_color(color) @staticmethod def _is_hex_color(color: str): return re.match("[0-9a-f]{6}", color, flags=re.IGNORECASE) def _color_pixmap(self, color: str) -> QPixmap: pixmap = QPixmap(40, 40) qcolor = self._to_qcolor(color) pixmap.fill((qcolor)) return pixmap def _to_qcolor(self, color: str): if self._is_hex_color(color): red = int(color[0:2], 16) green = int(color[2:4], 16) blue = int(color[4:6], 16) return QColor(red, green, blue) elif color in QColor().colorNames(): return QColor(color) return QColor(255, 255, 255) def _to_hex(self, color: QColor) -> str: red = "{0:0{1}x}".format(color.red(), 2) green = "{0:0{1}x}".format(color.green(), 2) blue = "{0:0{1}x}".format(color.blue(), 2) return red + green + blue