Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 101 additions & 1 deletion glue_qt/utils/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

__all__ = ['mpl_to_qt_color', 'qt_to_mpl_color', 'cmap2pixmap',
'tint_pixmap', 'QColorBox', 'ColorProperty', 'connect_color',
'QColormapCombo']
'QColormapCombo', 'connect_colormap_widget', 'QColormapWidget']


def mpl_to_qt_color(color, alpha=None):
Expand Down Expand Up @@ -219,6 +219,106 @@ def resizeEvent(self, *args, **kwargs):
self._update_icons()


class QColormapWidget(QtWidgets.QWidget):

changed = QtCore.Signal()

def __init__(self, *args, **kwargs):
super(QColormapWidget, self).__init__(*args, **kwargs)
layout = QtWidgets.QHBoxLayout()
self.cmap_combo = QColormapCombo()
self.cmap_combo.setMinimumWidth(100)
self.cmap_button = QtWidgets.QPushButton(text="⇄")
self.cmap_button.setCheckable(True)
self.cmap_button.setMaximumWidth(25)
layout.addWidget(self.cmap_combo, stretch=1)
layout.addWidget(self.cmap_button)
layout.setSpacing(3)
self.setLayout(layout)

self.cmap_button.toggled.connect(self._update_from_widget)
self.cmap_combo.currentIndexChanged.connect(self._update_from_widget)

def value(self):
wrapper = self.itemData(self.cmap_combo.currentIndex(), reverse=self.cmap_button.isChecked())
return wrapper.data if wrapper is not None else None

def isChecked(self):
return self.cmap_button.isChecked()

def _update_from_widget(self, value):
self.changed.emit()

def set(self, index, reverse):
with QtCore.QSignalBlocker(self.cmap_combo), QtCore.QSignalBlocker(self.cmap_button):
self.cmap_combo.setCurrentIndex(index)
self.cmap_button.setChecked(reverse)
reversible = callable(getattr(self.value(), 'reversed', None))
self.cmap_button.setEnabled(reversible)
self.changed.emit()

def count(self):
return self.cmap_combo.count()

def refresh_options(self):
self.cmap_combo.refresh_options()

def itemData(self, index, reverse=False):
wrapper = self.cmap_combo.itemData(index)
if wrapper is None:
return None
data = wrapper.data
if reverse:
data = data.reversed()
return UserDataWrapper(data=data)


def _find_cmap_combo_data(widget, value):
"""
Returns the index in a combo box where the colormap or its reverse equals the value

Raises a ValueError if data is not found
"""
# Here we check that the result is True, because some classes may overload
# == and return other kinds of objects whether true or false.
for idx in range(widget.count()):
if (item_data := widget.itemData(idx)) is not None:
if isinstance(item_data, UserDataWrapper):
data = item_data.data
else:
data = item_data
if data is value or (data == value) is True:
return idx, False
if callable(getattr(data, 'reversed', None)):
data = data.reversed()
if data is value or (data == value) is True:
return idx, True
return -1, False
raise ValueError("%s not found in combo box" % (value,))


def connect_colormap_widget(client, prop, widget):

def update_widget(item):
try:
idx, reverse = _find_cmap_combo_data(widget, item)
except ValueError:
if item is None:
idx, reverse = -1, False
else:
raise
widget.set(idx, reverse)

def update_prop():
setattr(client, prop, widget.value())

add_callback(client, prop, update_widget)
widget.changed.connect(nonpartial(update_prop))
update_widget(getattr(client, prop))


HANDLERS['cmap'] = connect_colormap_widget

if __name__ == "__main__":

from glue_qt.utils import get_qapp
Expand Down
41 changes: 40 additions & 1 deletion glue_qt/utils/tests/test_colors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from unittest.mock import MagicMock

from echo import CallbackProperty
from glue.config import colormaps
from qtpy import QtGui

from ..colors import qt_to_mpl_color, QColorBox, connect_color, QColormapCombo
from ..colors import qt_to_mpl_color, QColorBox, connect_color, QColormapCombo, connect_colormap_widget, QColormapWidget


def test_colors():
Expand Down Expand Up @@ -52,3 +53,41 @@ class FakeClass(object):
def test_colormap_combo():

combo = QColormapCombo()


def test_colormap_widget():

widget = QColormapWidget()


def test_colormap_widget_value():

class FakeClass(object):
cmap = CallbackProperty()

c = FakeClass()
widget = QColormapWidget()

connect_colormap_widget(c, 'cmap', widget)

cmap0 = colormaps.members[0][1]

widget.set(0, True)
assert c.cmap == cmap0.reversed()

cmap1 = colormaps.members[1][1]
widget.set(1, True)
assert c.cmap == cmap1.reversed()

widget.set(1, False)
assert c.cmap == cmap1

c.cmap = cmap0
assert widget.cmap_combo.currentIndex() == 0
assert not widget.cmap_button.isChecked()
assert widget.value() == cmap0

c.cmap = cmap1.reversed()
assert widget.cmap_combo.currentIndex() == 1
assert widget.cmap_button.isChecked()
assert widget.value() == cmap1.reversed()
4 changes: 2 additions & 2 deletions glue_qt/viewers/image/layer_style_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(self, layer, parent=None):
def _update_color_mode(self, color_mode):
if color_mode == 'Colormaps':
self.ui.color_color.hide()
self.ui.combodata_cmap.show()
self.ui.cmap_cmap.show()
else:
self.ui.color_color.show()
self.ui.combodata_cmap.hide()
self.ui.cmap_cmap.hide()
26 changes: 5 additions & 21 deletions glue_qt/viewers/image/layer_style_editor.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>292</width>
<height>197</height>
<height>204</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -43,7 +43,6 @@
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
Expand All @@ -59,7 +58,6 @@
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
Expand Down Expand Up @@ -92,20 +90,7 @@
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QColormapCombo" name="combodata_cmap">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="frame">
<bool>false</bool>
</property>
</widget>
<widget class="QColormapWidget" name="cmap_cmap" native="true"/>
</item>
<item>
<widget class="QColorBox" name="color_color">
Expand Down Expand Up @@ -249,7 +234,6 @@
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
Expand All @@ -265,7 +249,6 @@
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
Expand Down Expand Up @@ -299,9 +282,10 @@
<header>glue_qt.utils.colors</header>
</customwidget>
<customwidget>
<class>QColormapCombo</class>
<extends>QComboBox</extends>
<class>QColormapWidget</class>
<extends>QWidget</extends>
<header>glue_qt.utils.colors</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
Expand Down
8 changes: 4 additions & 4 deletions glue_qt/viewers/scatter/layer_style_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def _update_cmap_mode(self, cmap_mode=None):
self.ui.valuetext_cmap_vmin.hide()
self.ui.valuetext_cmap_vmax.hide()
self.ui.button_flip_cmap.hide()
self.ui.combodata_cmap.hide()
self.ui.cmap_cmap.hide()
self.ui.label_colormap.hide()
self.ui.color_color.show()
else:
Expand All @@ -226,7 +226,7 @@ def _update_cmap_mode(self, cmap_mode=None):
self.ui.valuetext_cmap_vmin.show()
self.ui.valuetext_cmap_vmax.show()
self.ui.button_flip_cmap.show()
self.ui.combodata_cmap.show()
self.ui.cmap_cmap.show()
self.ui.label_colormap.show()
self.ui.color_color.hide()

Expand All @@ -242,9 +242,9 @@ def _update_cmaps(self, *args):
if getattr(actual_component, 'preferred_cmap', False):
cmap = actual_component.preferred_cmap
name = actual_component.cmap_name
self.ui.combodata_cmap.refresh_options(colormaps=[(name, cmap)])
self.ui.cmap_cmap.refresh_options(colormaps=[(name, cmap)])
else:
self.ui.combodata_cmap.refresh_options()
self.ui.cmap_cmap.refresh_options()


class ScatterRegionLayerStyleEditor(QtWidgets.QWidget):
Expand Down
Loading
Loading