|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a palette widget for the icon editor. |
|
8 """ |
|
9 |
|
10 from PyQt6.QtCore import pyqtSignal, Qt |
|
11 from PyQt6.QtGui import QColor, QPainter, QPixmap |
|
12 from PyQt6.QtWidgets import ( |
|
13 QWidget, QBoxLayout, QLabel, QFrame, QPushButton, QSpinBox, QGroupBox, |
|
14 QVBoxLayout, QRadioButton, QSpacerItem, QSizePolicy, QColorDialog |
|
15 ) |
|
16 |
|
17 |
|
18 class IconEditorPalette(QWidget): |
|
19 """ |
|
20 Class implementing a palette widget for the icon editor. |
|
21 |
|
22 @signal colorSelected(QColor) emitted after a new color has been selected |
|
23 @signal compositingChanged(QPainter.CompositionMode) emitted to signal a |
|
24 change of the compositing mode |
|
25 """ |
|
26 colorSelected = pyqtSignal(QColor) |
|
27 compositingChanged = pyqtSignal(QPainter.CompositionMode) |
|
28 |
|
29 def __init__(self, parent=None): |
|
30 """ |
|
31 Constructor |
|
32 |
|
33 @param parent reference to the parent widget (QWidget) |
|
34 """ |
|
35 super().__init__(parent) |
|
36 |
|
37 direction = ( |
|
38 QBoxLayout.Direction.LeftToRight |
|
39 if self.layoutDirection == Qt.Orientation.Horizontal else |
|
40 QBoxLayout.Direction.TopToBottom |
|
41 ) |
|
42 self.__layout = QBoxLayout(direction, self) |
|
43 self.setLayout(self.__layout) |
|
44 |
|
45 self.__preview = QLabel(self) |
|
46 self.__preview.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken) |
|
47 self.__preview.setFixedHeight(64) |
|
48 self.__preview.setAlignment( |
|
49 Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) |
|
50 self.__preview.setWhatsThis(self.tr( |
|
51 """<b>Preview</b>""" |
|
52 """<p>This is a 1:1 preview of the current icon.</p>""" |
|
53 )) |
|
54 self.__layout.addWidget(self.__preview) |
|
55 |
|
56 self.__color = QLabel(self) |
|
57 self.__color.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken) |
|
58 self.__color.setFixedHeight(24) |
|
59 self.__color.setAlignment( |
|
60 Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) |
|
61 self.__color.setWhatsThis(self.tr( |
|
62 """<b>Current Color</b>""" |
|
63 """<p>This is the currently selected color used for drawing.</p>""" |
|
64 )) |
|
65 self.__layout.addWidget(self.__color) |
|
66 |
|
67 self.__colorTxt = QLabel(self) |
|
68 self.__colorTxt.setAlignment( |
|
69 Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter) |
|
70 self.__colorTxt.setWhatsThis(self.tr( |
|
71 """<b>Current Color Value</b>""" |
|
72 """<p>This is the currently selected color value used for""" |
|
73 """ drawing.</p>""" |
|
74 )) |
|
75 self.__layout.addWidget(self.__colorTxt) |
|
76 |
|
77 self.__colorButton = QPushButton(self.tr("Select Color"), self) |
|
78 self.__colorButton.setWhatsThis(self.tr( |
|
79 """<b>Select Color</b>""" |
|
80 """<p>Select the current drawing color via a color selection""" |
|
81 """ dialog.</p>""" |
|
82 )) |
|
83 self.__colorButton.clicked.connect(self.__selectColor) |
|
84 self.__layout.addWidget(self.__colorButton) |
|
85 |
|
86 self.__colorAlpha = QSpinBox(self) |
|
87 self.__colorAlpha.setRange(0, 255) |
|
88 self.__colorAlpha.setWhatsThis(self.tr( |
|
89 """<b>Select alpha channel value</b>""" |
|
90 """<p>Select the value for the alpha channel of the current""" |
|
91 """ color.</p>""" |
|
92 )) |
|
93 self.__layout.addWidget(self.__colorAlpha) |
|
94 self.__colorAlpha.valueChanged[int].connect(self.__alphaChanged) |
|
95 |
|
96 self.__compositingGroup = QGroupBox(self.tr("Compositing"), self) |
|
97 self.__compositingGroupLayout = QVBoxLayout(self.__compositingGroup) |
|
98 self.__compositingGroup.setLayout(self.__compositingGroupLayout) |
|
99 self.__sourceButton = QRadioButton(self.tr("Replace"), |
|
100 self.__compositingGroup) |
|
101 self.__sourceButton.setWhatsThis(self.tr( |
|
102 """<b>Replace</b>""" |
|
103 """<p>Replace the existing pixel with a new color.</p>""" |
|
104 )) |
|
105 self.__sourceButton.clicked[bool].connect(self.__compositingChanged) |
|
106 self.__compositingGroupLayout.addWidget(self.__sourceButton) |
|
107 self.__sourceOverButton = QRadioButton(self.tr("Blend"), |
|
108 self.__compositingGroup) |
|
109 self.__sourceOverButton.setWhatsThis(self.tr( |
|
110 """<b>Blend</b>""" |
|
111 """<p>Blend the new color over the existing pixel.</p>""" |
|
112 )) |
|
113 self.__sourceOverButton.setChecked(True) |
|
114 self.__sourceOverButton.clicked[bool].connect( |
|
115 self.__compositingChanged) |
|
116 self.__compositingGroupLayout.addWidget(self.__sourceOverButton) |
|
117 self.__layout.addWidget(self.__compositingGroup) |
|
118 |
|
119 spacer = QSpacerItem( |
|
120 10, 10, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) |
|
121 self.__layout.addItem(spacer) |
|
122 |
|
123 def previewChanged(self, pixmap): |
|
124 """ |
|
125 Public slot to update the preview. |
|
126 |
|
127 @param pixmap new preview pixmap (QPixmap) |
|
128 """ |
|
129 self.__preview.setPixmap(pixmap) |
|
130 |
|
131 def colorChanged(self, color): |
|
132 """ |
|
133 Public slot to update the color preview. |
|
134 |
|
135 @param color new color (QColor) |
|
136 """ |
|
137 self.__currentColor = color |
|
138 self.__currentAlpha = color.alpha() |
|
139 |
|
140 pm = QPixmap(90, 18) |
|
141 pm.fill(color) |
|
142 self.__color.setPixmap(pm) |
|
143 |
|
144 self.__colorTxt.setText( |
|
145 "{0:d}, {1:d}, {2:d}, {3:d}".format( |
|
146 color.red(), color.green(), color.blue(), color.alpha())) |
|
147 |
|
148 self.__colorAlpha.setValue(self.__currentAlpha) |
|
149 |
|
150 def __selectColor(self): |
|
151 """ |
|
152 Private slot to select a new drawing color. |
|
153 """ |
|
154 col = QColorDialog.getColor(self.__currentColor) |
|
155 col.setAlpha(self.__currentAlpha) |
|
156 |
|
157 if col.isValid(): |
|
158 self.colorSelected.emit(col) |
|
159 |
|
160 def __alphaChanged(self, val): |
|
161 """ |
|
162 Private slot to track changes of the alpha channel. |
|
163 |
|
164 @param val value of the alpha channel |
|
165 """ |
|
166 if val != self.__currentAlpha: |
|
167 col = QColor(self.__currentColor) |
|
168 col.setAlpha(val) |
|
169 self.colorSelected.emit(col) |
|
170 |
|
171 def setCompositingMode(self, mode): |
|
172 """ |
|
173 Public method to set the compositing mode. |
|
174 |
|
175 @param mode compositing mode to set (QPainter.CompositionMode) |
|
176 """ |
|
177 if mode == QPainter.CompositionMode.CompositionMode_Source: |
|
178 self.__sourceButton.setChecked(True) |
|
179 elif mode == QPainter.CompositionMode.CompositionMode_SourceOver: |
|
180 self.__sourceOverButton.setChecked(True) |
|
181 |
|
182 def __compositingChanged(self, on): |
|
183 """ |
|
184 Private slot to handle a change of the compositing mode. |
|
185 |
|
186 @param on flag indicating the checked state of the compositing button |
|
187 (boolean) |
|
188 """ |
|
189 if on: |
|
190 if self.__sourceButton.isChecked(): |
|
191 self.compositingChanged.emit( |
|
192 QPainter.CompositionMode.CompositionMode_Source) |
|
193 elif self.__sourceOverButton.isChecked(): |
|
194 self.compositingChanged.emit( |
|
195 QPainter.CompositionMode.CompositionMode_SourceOver) |