File indexing completed on 2024-05-26 04:34:17
0001 ''' 0002 SPDX-FileCopyrightText: 2019 Tusooa Zhu <tusooa@vista.aero> 0003 0004 This file is part of Krita-docker-color-slider. 0005 0006 SPDX-License-Identifier: GPL-3.0-or-later 0007 ''' 0008 from PyQt5.QtWidgets import QWidget 0009 from PyQt5.QtGui import QPixmap, QPainter, QColor, QBrush, QPolygon 0010 from PyQt5.QtCore import QPoint 0011 from krita import ManagedColor 0012 0013 0014 class ColorSlider(QWidget): 0015 default_color = ManagedColor("", "", "") 0016 0017 def __init__(self, docker, left_color=default_color, right_color=default_color, parent=None): 0018 super(ColorSlider, self).__init__(parent) 0019 self.docker = docker 0020 self.left_color = left_color 0021 self.right_color = right_color 0022 self.slider_pixmap = None 0023 self.value_x = None 0024 self.cursor_fill_color = QColor.fromRgbF(1, 1, 1, 1) 0025 self.cursor_outline_color = QColor.fromRgbF(0, 0, 0, 1) 0026 self.need_redraw = True 0027 0028 def set_color(self, pos, color): 0029 if pos == 'left': 0030 if self.left_color is not color: 0031 self.left_color = color 0032 self.need_redraw = True 0033 else: 0034 if self.right_color is not color: 0035 self.right_color = color 0036 self.need_redraw = True 0037 0038 def update_slider(self): 0039 ''' 0040 Update the slider to a gradient between the two colors. 0041 0042 The painting of the slider comes from the program Krita. The original code can be accessed 0043 at the following URL. 0044 https://github.com/KDE/krita/blob/master/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp 0045 ''' 0046 if self.need_redraw: 0047 patch_count = self.width() 0048 base_hsva = list(self.docker.managedcolor_to_qcolor(self.left_color).getHsvF()) 0049 dest_hsva = list(self.docker.managedcolor_to_qcolor(self.right_color).getHsvF()) 0050 diff_hsva = [(dest_hsva[i] - base_hsva[i]) for i in range(4)] 0051 if dest_hsva[0] == -1.0: 0052 diff_hsva[0] = 0 0053 elif base_hsva[0] == -1.0: 0054 diff_hsva[0] = 0 0055 base_hsva[0] = dest_hsva[0] 0056 elif diff_hsva[0] > 0.5: # make sure the sliding goes through a minor arc 0057 diff_hsva[0] = diff_hsva[0] - 1.0 0058 elif diff_hsva[0] < -0.5: 0059 diff_hsva[0] = diff_hsva[0] + 1.0 0060 0061 step_hsva = [x / patch_count for x in diff_hsva] 0062 0063 self.slider_pixmap = QPixmap(self.width(), self.height()) 0064 painter = QPainter(self.slider_pixmap) 0065 0066 for i in range(patch_count): 0067 hue = base_hsva[0] + i * step_hsva[0] 0068 while hue < 0.0: 0069 hue += 1.0 0070 0071 while hue > 1.0: 0072 hue -= 1.0 0073 0074 saturation = base_hsva[1] + i * step_hsva[1] 0075 value = base_hsva[2] + i * step_hsva[2] 0076 cur_color = QColor.fromHsvF(hue, saturation, value) 0077 painter.fillRect(i, 0, 1, self.height(), cur_color) 0078 0079 painter.end() 0080 0081 self.need_redraw = False 0082 0083 widget_painter = QPainter(self) 0084 self.rendered_image = self.slider_pixmap.toImage() 0085 0086 widget_painter.drawImage(0, 0, self.rendered_image) 0087 if self.value_x is not None: 0088 start_x = int(self.value_x) 0089 start_y = int(self.height() / 2) 0090 delta_x = int(self.height() / 3) 0091 delta_y = int(self.height() / 3) 0092 points = [QPoint(start_x, start_y), 0093 QPoint(start_x - delta_x, start_y + delta_y), 0094 QPoint(start_x + delta_x, start_y + delta_y)] 0095 widget_painter.setBrush(QBrush(self.cursor_fill_color)) 0096 widget_painter.setPen(self.cursor_outline_color) 0097 widget_painter.drawPolygon(QPolygon(points)) 0098 0099 def paintEvent(self, event): 0100 self.update_slider() 0101 0102 def resizeEvent(self, event): # after resizing the widget, force-redraw the underlying slider 0103 self.need_redraw = True 0104 0105 def adjust_pos_x(self, x): # adjust the x to make it in the range of [0, width - 1] 0106 if x < 0: 0107 return 0 0108 if x >= self.width(): 0109 return self.width() - 1 0110 return x 0111 0112 def mouseMoveEvent(self, event): 0113 pos = event.pos() 0114 self.value_x = self.adjust_pos_x(pos.x()) 0115 self.update() 0116 0117 def mouseReleaseEvent(self, event): 0118 pos = event.pos() 0119 self.value_x = self.adjust_pos_x(pos.x()) 0120 y = int(self.height() / 2) 0121 fixed_pos = QPoint(self.value_x, y) 0122 color = self.rendered_image.pixelColor(fixed_pos) 0123 mc = self.docker.qcolor_to_managedcolor(color) 0124 if self.docker.canvas() is not None: 0125 if self.docker.canvas().view() is not None: 0126 self.docker.canvas().view().setForeGroundColor(mc) 0127 self.update()