mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 03:31:50 +02:00
feat(color_map_selector): added colormap selector with plugin
This commit is contained in:
0
bec_widgets/widgets/color_map_selector/__init__.py
Normal file
0
bec_widgets/widgets/color_map_selector/__init__.py
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
111
bec_widgets/widgets/color_map_selector/color_map_selector.py
Normal file
111
bec_widgets/widgets/color_map_selector/color_map_selector.py
Normal file
@ -0,0 +1,111 @@
|
||||
import pyqtgraph as pg
|
||||
from qtpy.QtCore import Property, Signal, Slot
|
||||
from qtpy.QtGui import QColor, QFontMetrics, QImage
|
||||
from qtpy.QtWidgets import QApplication, QComboBox, QStyledItemDelegate, QVBoxLayout, QWidget
|
||||
|
||||
|
||||
class ColormapDelegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None):
|
||||
super(ColormapDelegate, self).__init__(parent)
|
||||
self.image_width = 25
|
||||
self.image_height = 10
|
||||
self.gap = 10
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
text = index.data()
|
||||
colormap = pg.colormap.get(text)
|
||||
colors = colormap.getLookupTable(start=0.0, stop=1.0, alpha=False)
|
||||
|
||||
font_metrics = QFontMetrics(painter.font())
|
||||
text_width = font_metrics.width(text)
|
||||
text_height = font_metrics.height()
|
||||
|
||||
total_height = max(text_height, self.image_height)
|
||||
|
||||
image = QImage(self.image_width, self.image_height, QImage.Format_RGB32)
|
||||
for i in range(self.image_width):
|
||||
color = QColor(*colors[int(i * (len(colors) - 1) / (self.image_width - 1))])
|
||||
for j in range(self.image_height):
|
||||
image.setPixel(i, j, color.rgb())
|
||||
|
||||
painter.drawImage(
|
||||
option.rect.x(), option.rect.y() + (total_height - self.image_height) // 2, image
|
||||
)
|
||||
painter.drawText(
|
||||
option.rect.x() + self.image_width + self.gap,
|
||||
option.rect.y() + (total_height - text_height) // 2 + font_metrics.ascent(),
|
||||
text,
|
||||
)
|
||||
|
||||
|
||||
class ColormapSelector(QWidget):
|
||||
"""
|
||||
Simple colormap combobox widget. By default it loads all the available colormaps in pyqtgraph.
|
||||
"""
|
||||
|
||||
colormap_changed_signal = Signal(str)
|
||||
|
||||
def __init__(self, parent=None, default_colormaps=None):
|
||||
super().__init__(parent)
|
||||
self._colormaps = []
|
||||
self.initUI(default_colormaps)
|
||||
|
||||
def initUI(self, default_colormaps=None):
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.combo = QComboBox()
|
||||
self.combo.setItemDelegate(ColormapDelegate())
|
||||
self.combo.currentTextChanged.connect(self.colormap_changed)
|
||||
self.available_colormaps = pg.colormap.listMaps()
|
||||
if default_colormaps is None:
|
||||
default_colormaps = self.available_colormaps
|
||||
self.add_color_maps(default_colormaps)
|
||||
self.layout.addWidget(self.combo)
|
||||
|
||||
@Slot()
|
||||
def colormap_changed(self):
|
||||
"""
|
||||
Emit the colormap changed signal with the current colormap selected in the combobox.
|
||||
"""
|
||||
self.colormap_changed_signal.emit(self.combo.currentText())
|
||||
|
||||
def add_color_maps(self, colormaps=None):
|
||||
"""
|
||||
Add colormaps to the combobox.
|
||||
|
||||
Args:
|
||||
colormaps(list): List of colormaps to add to the combobox. If None, all available colormaps are added.
|
||||
"""
|
||||
self.combo.clear()
|
||||
if colormaps is not None:
|
||||
for name in colormaps:
|
||||
if name in self.available_colormaps:
|
||||
self.combo.addItem(name)
|
||||
else:
|
||||
for name in self.available_colormaps:
|
||||
self.combo.addItem(name)
|
||||
self._colormaps = colormaps if colormaps is not None else self.available_colormaps
|
||||
|
||||
@Property("QStringList")
|
||||
def colormaps(self):
|
||||
"""
|
||||
Property to get and set the colormaps in the combobox.
|
||||
"""
|
||||
return self._colormaps
|
||||
|
||||
@colormaps.setter
|
||||
def colormaps(self, value):
|
||||
"""
|
||||
Set the colormaps in the combobox.
|
||||
"""
|
||||
if self._colormaps != value:
|
||||
self._colormaps = value
|
||||
self.add_color_maps(value)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
import sys
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
ex = ColormapSelector()
|
||||
ex.show()
|
||||
sys.exit(app.exec_())
|
@ -0,0 +1 @@
|
||||
{'files': ['color_map_selector.py']}
|
@ -0,0 +1,57 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
import os
|
||||
|
||||
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
||||
from qtpy.QtGui import QIcon
|
||||
|
||||
from bec_widgets.widgets.color_map_selector.color_map_selector import ColormapSelector
|
||||
|
||||
DOM_XML = """
|
||||
<ui language='c++'>
|
||||
<widget class='ColormapSelector' name='color_map_selector'>
|
||||
</widget>
|
||||
</ui>
|
||||
"""
|
||||
|
||||
|
||||
class ColormapSelectorPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._form_editor = None
|
||||
|
||||
def createWidget(self, parent):
|
||||
t = ColormapSelector(parent)
|
||||
return t
|
||||
|
||||
def domXml(self):
|
||||
return DOM_XML
|
||||
|
||||
def group(self):
|
||||
return "BEC Buttons"
|
||||
|
||||
def icon(self):
|
||||
current_path = os.path.dirname(__file__)
|
||||
icon_path = os.path.join(current_path, "assets", "color_map_selector_icon.png")
|
||||
return QIcon(icon_path)
|
||||
|
||||
def includeFile(self):
|
||||
return "color_map_selector"
|
||||
|
||||
def initialize(self, form_editor):
|
||||
self._form_editor = form_editor
|
||||
|
||||
def isContainer(self):
|
||||
return False
|
||||
|
||||
def isInitialized(self):
|
||||
return self._form_editor is not None
|
||||
|
||||
def name(self):
|
||||
return "ColormapSelector"
|
||||
|
||||
def toolTip(self):
|
||||
return "A custom QComboBox widget for selecting colormaps."
|
||||
|
||||
def whatsThis(self):
|
||||
return self.toolTip()
|
@ -0,0 +1,17 @@
|
||||
def main(): # pragma: no cover
|
||||
from qtpy import PYSIDE6
|
||||
|
||||
if not PYSIDE6:
|
||||
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
||||
return
|
||||
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
||||
|
||||
from bec_widgets.widgets.color_map_selector.color_map_selector_plugin import (
|
||||
ColormapSelectorPlugin,
|
||||
)
|
||||
|
||||
QPyDesignerCustomWidgetCollection.addCustomWidget(ColormapSelectorPlugin())
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
main()
|
43
tests/unit_tests/test_color_map_selector.py
Normal file
43
tests/unit_tests/test_color_map_selector.py
Normal file
@ -0,0 +1,43 @@
|
||||
import pyqtgraph as pg
|
||||
import pytest
|
||||
|
||||
from bec_widgets.widgets.color_map_selector.color_map_selector import ColormapSelector
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def color_map_selector(qtbot):
|
||||
widget = ColormapSelector()
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
widget.close()
|
||||
|
||||
|
||||
def test_color_map_selector_init(color_map_selector):
|
||||
assert color_map_selector is not None
|
||||
assert isinstance(color_map_selector, ColormapSelector)
|
||||
|
||||
all_maps = pg.colormap.listMaps()
|
||||
loaded_maps = [
|
||||
color_map_selector.combo.itemText(i) for i in range(color_map_selector.combo.count())
|
||||
]
|
||||
assert len(loaded_maps) > 0
|
||||
assert all_maps == loaded_maps
|
||||
|
||||
|
||||
def test_color_map_selector_add_color_maps(color_map_selector):
|
||||
color_map_selector.add_color_maps(["cividis", "viridis"])
|
||||
assert color_map_selector.combo.count() == 2
|
||||
assert color_map_selector.combo.itemText(0) == "cividis"
|
||||
assert color_map_selector.combo.itemText(1) == "viridis"
|
||||
assert color_map_selector.combo.itemText(2) != "cividis"
|
||||
assert color_map_selector.combo.itemText(2) != "viridis"
|
||||
|
||||
|
||||
def test_colormap_add_maps_by_property(color_map_selector):
|
||||
color_map_selector.colormaps = ["cividis", "viridis"]
|
||||
assert color_map_selector.combo.count() == 2
|
||||
assert color_map_selector.combo.itemText(0) == "cividis"
|
||||
assert color_map_selector.combo.itemText(1) == "viridis"
|
||||
assert color_map_selector.combo.itemText(2) != "cividis"
|
||||
assert color_map_selector.combo.itemText(2) != "viridis"
|
Reference in New Issue
Block a user