File indexing completed on 2024-05-12 05:46:37
0001 ''' 0002 Copyright (C) 2019 Tusooa Zhu <tusooa@vista.aero> 0003 0004 This file is part of Krita-docker-color-slider. 0005 0006 Krita-docker-color-slider is free software: you can redistribute it and/or modify 0007 it under the terms of the GNU General Public License as published by 0008 the Free Software Foundation, either version 3 of the License, or 0009 (at your option) any later version. 0010 0011 Krita-docker-color-slider is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with Krita-docker-color-slider. If not, see <https://www.gnu.org/licenses/>. 0018 ''' 0019 from PyQt5.QtWidgets import QWidget 0020 from PyQt5.QtGui import QPixmap, QPainter, QColor, QBrush, QPolygon 0021 from PyQt5.QtCore import QPoint 0022 from krita import ManagedColor 0023 0024 0025 class ColorSlider(QWidget): 0026 default_color = ManagedColor("", "", "") 0027 0028 def __init__(self, docker, left_color=default_color, right_color=default_color, parent=None): 0029 super(ColorSlider, self).__init__(parent) 0030 self.docker = docker 0031 self.left_color = left_color 0032 self.right_color = right_color 0033 self.slider_pixmap = None 0034 self.value_x = None 0035 self.cursor_fill_color = QColor.fromRgbF(1, 1, 1, 1) 0036 self.cursor_outline_color = QColor.fromRgbF(0, 0, 0, 1) 0037 self.need_redraw = True 0038 0039 def set_color(self, pos, color): 0040 if pos == 'left': 0041 if self.left_color is not color: 0042 self.left_color = color 0043 self.need_redraw = True 0044 else: 0045 if self.right_color is not color: 0046 self.right_color = color 0047 self.need_redraw = True 0048 0049 def update_slider(self): 0050 ''' 0051 Update the slider to a gradient between the two colors. 0052 0053 The painting of the slider comes from the program Krita. The original code can be accessed 0054 at the following URL. 0055 https://github.com/KDE/krita/blob/master/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp 0056 ''' 0057 if self.need_redraw: 0058 patch_count = self.width() 0059 base_hsva = list(self.docker.managedcolor_to_qcolor(self.left_color).getHsvF()) 0060 dest_hsva = list(self.docker.managedcolor_to_qcolor(self.right_color).getHsvF()) 0061 diff_hsva = [(dest_hsva[i] - base_hsva[i]) for i in range(4)] 0062 if dest_hsva[0] == -1.0: 0063 diff_hsva[0] = 0 0064 elif base_hsva[0] == -1.0: 0065 diff_hsva[0] = 0 0066 base_hsva[0] = dest_hsva[0] 0067 elif diff_hsva[0] > 0.5: # make sure the sliding goes through a minor arc 0068 diff_hsva[0] = diff_hsva[0] - 1.0 0069 elif diff_hsva[0] < -0.5: 0070 diff_hsva[0] = diff_hsva[0] + 1.0 0071 0072 step_hsva = [x / patch_count for x in diff_hsva] 0073 0074 self.slider_pixmap = QPixmap(self.width(), self.height()) 0075 painter = QPainter(self.slider_pixmap) 0076 0077 for i in range(patch_count): 0078 hue = base_hsva[0] + i * step_hsva[0] 0079 while hue < 0.0: 0080 hue += 1.0 0081 0082 while hue > 1.0: 0083 hue -= 1.0 0084 0085 saturation = base_hsva[1] + i * step_hsva[1] 0086 value = base_hsva[2] + i * step_hsva[2] 0087 cur_color = QColor.fromHsvF(hue, saturation, value) 0088 painter.fillRect(i, 0, 1, self.height(), cur_color) 0089 0090 painter.end() 0091 0092 self.need_redraw = False 0093 0094 widget_painter = QPainter(self) 0095 self.rendered_image = self.slider_pixmap.toImage() 0096 0097 widget_painter.drawImage(0, 0, self.rendered_image) 0098 if self.value_x is not None: 0099 start_x = self.value_x 0100 start_y = self.height() / 2 0101 delta_x = self.height() / 3 0102 delta_y = self.height() / 3 0103 points = [QPoint(start_x, start_y), 0104 QPoint(start_x - delta_x, start_y + delta_y), 0105 QPoint(start_x + delta_x, start_y + delta_y)] 0106 widget_painter.setBrush(QBrush(self.cursor_fill_color)) 0107 widget_painter.setPen(self.cursor_outline_color) 0108 widget_painter.drawPolygon(QPolygon(points)) 0109 0110 def paintEvent(self, event): 0111 self.update_slider() 0112 0113 def resizeEvent(self, event): # after resizing the widget, force-redraw the underlying slider 0114 self.need_redraw = True 0115 0116 def adjust_pos_x(self, x): # adjust the x to make it in the range of [0, width - 1] 0117 if x < 0: 0118 return 0 0119 if x >= self.width(): 0120 return self.width() - 1 0121 return x 0122 0123 def mouseMoveEvent(self, event): 0124 pos = event.pos() 0125 self.value_x = self.adjust_pos_x(pos.x()) 0126 self.update() 0127 0128 def mouseReleaseEvent(self, event): 0129 pos = event.pos() 0130 self.value_x = self.adjust_pos_x(pos.x()) 0131 y = int(self.height() / 2) 0132 fixed_pos = QPoint(self.value_x, y) 0133 color = self.rendered_image.pixelColor(fixed_pos) 0134 mc = self.docker.qcolor_to_managedcolor(color) 0135 if self.docker.canvas() is not None: 0136 if self.docker.canvas().view() is not None: 0137 self.docker.canvas().view().setForeGroundColor(mc) 0138 self.update()