Professional Documents
Culture Documents
@file
@brief A non-modal Qt color picker dialog launcher
@author FeRD (Frank Dana) <ferdnyc@gmail.com>
@section LICENSE
OpenShot Video Editor is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
"""
class ColorPicker(QWidget):
"""Show a non-modal color picker.
QColorDialog.colorSelected(QColor) is emitted when the user picks a color"""
class CPDialog(QColorDialog):
"""Show a modified QColorDialog which supports checkerboard alpha"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
log.debug("CPDialog initialized")
self.alpha_label = CPAlphaShowLabel(self)
self.alpha_label.setObjectName("alpha_label")
self.currentColorChanged.connect(self.alpha_label.updateColor)
def replace_label(self):
log.debug("Beginning discovery for QColorShowLabel widget")
# Find the dialog widget used to display the current
# color, so we can replace it with our implementation
try:
qcs = [
a for a in self.children()
if hasattr(a, "metaObject")
and a.metaObject().className() == 'QColorShower'
][0]
log.debug("Found QColorShower: %s", qcs)
qcsl = [
b for b in qcs.children()
if hasattr(b, "metaObject")
and b.metaObject().className() == 'QColorShowLabel'
][0]
log.debug("Found QColorShowLabel: %s", qcsl)
except IndexError as ex:
child_list = [
a.metaObject().className()
for a in self.children()
if hasattr(a, "metaObject")
]
log.debug("%d children of CPDialog %s", len(child_list), child_list)
raise RuntimeError("Could not find label to replace!") from ex
qcslay = qcs.layout()
log.debug(
"QColorShowLabel found at layout index %d", qcslay.indexOf(qcsl))
qcs.layout().replaceWidget(qcsl, self.alpha_label)
log.debug("Replaced QColorShowLabel widget, hiding original")
# Make sure it doesn't receive signals while hidden
qcsl.blockSignals(True)
qcsl.hide()
self.alpha_label.show()
class CPAlphaShowLabel(QLabel):
"""A replacement for QColorDialog's QColorShowLabel which
displays the currently-active color using checkerboard alpha"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Length in pixels of a side of the checkerboard squares
# (Pattern is made up of 2x2 squares, total size 2n x 2n)
self.checkerboard_size = 8
# Start out transparent by default
self.color = super().parent().currentColor()
self.build_pattern()
log.debug("CPAlphaShowLabel initialized, creating brush")
def updateColor(self, color: QColor):
self.color = color
log.debug("Label color set to %s", str(color.getRgb()))
self.repaint()
def build_pattern(self) -> QPixmap:
"""Construct tileable checkerboard pattern for paint events"""
# Brush will be an nxn checkerboard pattern
n = self.checkerboard_size
pat = QPixmap(2 * n, 2 * n)
p = QPainter(pat)
p.setPen(Qt.NoPen)
# Paint a checkerboard pattern for the color to be overlaid on
self.bg0 = QColor("#aaa")
self.bg1 = QColor("#ccc")
p.fillRect(pat.rect(), self.bg0)
p.fillRect(QRect(0, 0, n, n), self.bg1)
p.fillRect(QRect(n, n, 2 * n, 2 * n), self.bg1)
p.end()
log.debug("Constructed %s checkerboard brush", pat.size())
self.pattern = pat
def paintEvent(self, event):
"""Show the current color, with checkerboard alpha"""
event.accept()
p = QPainter(self)
p.setPen(Qt.NoPen)
if self.color.alphaF() < 1.0:
# Draw a checkerboard pattern under the color
p.drawTiledPixmap(event.rect(), self.pattern, QPoint(4,4))
p.fillRect(event.rect(), self.color)
p.end()