mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-04-18 06:15:37 +02:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6659c379 | ||
| 5fabd4bea9 | |||
| 4f0693cae3 | |||
|
|
ba76d6bb86 | ||
| 2304c9f849 | |||
| c6e48ec1fe | |||
|
|
f837129023 | ||
| 940ee6552c | |||
|
|
86b60b4aed | ||
| 14dd8c5b29 | |||
| b039933405 |
81
CHANGELOG.md
81
CHANGELOG.md
@@ -1,6 +1,46 @@
|
||||
# CHANGELOG
|
||||
|
||||
|
||||
## v1.3.3 (2024-11-07)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(scan_control): DeviceLineEdit kwargs readings changed to get name of the positioner ([`5fabd4b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5fabd4bea95bafd2352102686357cc1db80813fd))
|
||||
|
||||
### Documentation
|
||||
|
||||
* docs: update outdated text in docs ([`4f0693c`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4f0693cae34b391d75884837e1ae6353a0501868))
|
||||
|
||||
|
||||
## v1.3.2 (2024-11-05)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(plot_base): legend text color is changed when changing dark-light theme ([`2304c9f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2304c9f8497c1ab1492f3e6690bb79b0464c0df8))
|
||||
|
||||
### Build System
|
||||
|
||||
* build: PySide6 version fixed 6.7.2 ([`c6e48ec`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c6e48ec1fe5aaee6a7c7a6f930f1520cd439cdb2))
|
||||
|
||||
|
||||
## v1.3.1 (2024-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(ophyd_kind_util): Kind enums are imported from the bec widget util class ([`940ee65`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/940ee6552c1ee8d9b4e4a74c62351f2e133ab678))
|
||||
|
||||
|
||||
## v1.3.0 (2024-10-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix(colors): extend color map validation for matplotlib and colorcet maps (if available) ([`14dd8c5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/14dd8c5b2947c92f6643b888d71975e4e8d4ee88))
|
||||
|
||||
### Features
|
||||
|
||||
* feat(colormap_button): colormap button with menu to select colormap filtered by the colormap type ([`b039933`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b039933405e2fbe92bd81bd0748e79e8d443a741))
|
||||
|
||||
|
||||
## v1.2.0 (2024-10-25)
|
||||
|
||||
### Features
|
||||
@@ -128,44 +168,3 @@ if the widget should expand in-place ([`e4121a0`](https://gitlab.psi.ch/bec/bec_
|
||||
|
||||
|
||||
## v0.116.0 (2024-10-11)
|
||||
|
||||
### Build System
|
||||
|
||||
* build: fix PySide6 to 6.7.2 ([`908dbc1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/908dbc1760da5b323722207163f00850b84fb90b))
|
||||
|
||||
### Features
|
||||
|
||||
* feat: UI changes to have top toolbar with compact popup widgets (fix issue #360) ([`499b6b9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/499b6b9a12efd931b5728b519404c41a7e29e4d6))
|
||||
|
||||
* feat: adapt BECQueue and BECStatusBox widgets to use CompactPopupWidget ([`94ce92f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/94ce92f5b054d25ea3bb7976c1f75e14b78b9edc))
|
||||
|
||||
* feat: add 'CompactPopupWidget' container widget
|
||||
|
||||
Makes it easy to write widgets which can have a compact
|
||||
representation with LED-like global state indicator,
|
||||
with the possibility to display a popup dialog with more
|
||||
complete UI ([`49268e3`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/49268e3829406d70b09e4d88989812f5578e46f4))
|
||||
|
||||
|
||||
## v0.115.0 (2024-10-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix: make Alignment1D a MainWindow as it is an application ([`c5e9ed6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c5e9ed6e422acb908e1ada32822f5d7cc256ade7))
|
||||
|
||||
* fix: adjust bec_qthemes dependency ([`b207e45`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b207e45a67818ee061272ce00a09fe7ea31cd1ba))
|
||||
|
||||
### Features
|
||||
|
||||
* feat: add bec-app script to launch applications ([`8bf4842`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8bf48427884338672a8e3de3deb20439b0bfdf99))
|
||||
|
||||
|
||||
## v0.114.0 (2024-10-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix: prevent exception when empty string updates are coming from widget ([`04cfb1e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/04cfb1edf19437d54f07b868bcf3cfc2a35fd3bc))
|
||||
|
||||
* fix: use new 'scan_axis' signal, to set_x and select x axis on waveform
|
||||
|
||||
Fixes #361, do not try to change x axis when not permitted ([`efa2763`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/efa276358b0f5a45cce9fa84fa5f9aafaf4284f7))
|
||||
|
||||
@@ -16,6 +16,7 @@ class Widgets(str, enum.Enum):
|
||||
"""
|
||||
|
||||
AbortButton = "AbortButton"
|
||||
BECColorMapWidget = "BECColorMapWidget"
|
||||
BECDock = "BECDock"
|
||||
BECDockArea = "BECDockArea"
|
||||
BECFigure = "BECFigure"
|
||||
@@ -34,6 +35,7 @@ class Widgets(str, enum.Enum):
|
||||
PositionIndicator = "PositionIndicator"
|
||||
PositionerBox = "PositionerBox"
|
||||
PositionerControlLine = "PositionerControlLine"
|
||||
PositionerGroup = "PositionerGroup"
|
||||
ResetButton = "ResetButton"
|
||||
ResumeButton = "ResumeButton"
|
||||
RingProgressBar = "RingProgressBar"
|
||||
@@ -64,6 +66,15 @@ class AbortButton(RPCBase):
|
||||
"""
|
||||
|
||||
|
||||
class BECColorMapWidget(RPCBase):
|
||||
@property
|
||||
@rpc_call
|
||||
def colormap(self):
|
||||
"""
|
||||
Get the current colormap name.
|
||||
"""
|
||||
|
||||
|
||||
class BECCurve(RPCBase):
|
||||
@rpc_call
|
||||
def remove(self):
|
||||
@@ -2690,6 +2701,16 @@ class PositionerControlLine(RPCBase):
|
||||
"""
|
||||
|
||||
|
||||
class PositionerGroup(RPCBase):
|
||||
@rpc_call
|
||||
def set_positioners(self, device_names: "str"):
|
||||
"""
|
||||
Redraw grid with positioners from device_names string
|
||||
|
||||
Device names must be separated by space
|
||||
"""
|
||||
|
||||
|
||||
class ResetButton(RPCBase):
|
||||
@property
|
||||
@rpc_call
|
||||
|
||||
@@ -468,7 +468,7 @@ class Colors:
|
||||
return color
|
||||
|
||||
@staticmethod
|
||||
def validate_color_map(color_map: str) -> str:
|
||||
def validate_color_map(color_map: str, return_error: bool = True) -> str | bool:
|
||||
"""
|
||||
Validate the colormap input if it is supported by pyqtgraph. Can be used in any pydantic model as a field validator. If validation fails it prints all available colormaps from pyqtgraph instance.
|
||||
|
||||
@@ -476,13 +476,24 @@ class Colors:
|
||||
color_map(str): The colormap to be validated.
|
||||
|
||||
Returns:
|
||||
str: The validated colormap.
|
||||
str: The validated colormap, if colormap is valid.
|
||||
bool: False, if colormap is invalid.
|
||||
|
||||
Raises:
|
||||
PydanticCustomError: If colormap is invalid.
|
||||
"""
|
||||
available_colormaps = pg.colormap.listMaps()
|
||||
available_pg_maps = pg.colormap.listMaps()
|
||||
available_mpl_maps = pg.colormap.listMaps("matplotlib")
|
||||
available_mpl_colorcet = pg.colormap.listMaps("colorcet")
|
||||
|
||||
available_colormaps = available_pg_maps + available_mpl_maps + available_mpl_colorcet
|
||||
if color_map not in available_colormaps:
|
||||
raise PydanticCustomError(
|
||||
"unsupported colormap",
|
||||
f"Colormap '{color_map}' not found in the current installation of pyqtgraph. Choose on the following: {available_colormaps}.",
|
||||
{"wrong_value": color_map},
|
||||
)
|
||||
if return_error:
|
||||
raise PydanticCustomError(
|
||||
"unsupported colormap",
|
||||
f"Colormap '{color_map}' not found in the current installation of pyqtgraph. Choose on the following: {available_colormaps}.",
|
||||
{"wrong_value": color_map},
|
||||
)
|
||||
else:
|
||||
return False
|
||||
return color_map
|
||||
|
||||
26
bec_widgets/utils/ophyd_kind_util.py
Normal file
26
bec_widgets/utils/ophyd_kind_util.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from enum import IntFlag
|
||||
|
||||
try:
|
||||
|
||||
from enum import KEEP
|
||||
|
||||
class IFBase(IntFlag, boundary=KEEP): ...
|
||||
|
||||
except ImportError:
|
||||
|
||||
IFBase = IntFlag
|
||||
|
||||
|
||||
class Kind(IFBase):
|
||||
"""
|
||||
This is used in the .kind attribute of all OphydObj (Signals, Devices).
|
||||
|
||||
A Device examines its components' .kind atttribute to decide whether to
|
||||
traverse it in read(), read_configuration(), or neither. Additionally, if
|
||||
decides whether to include its name in `hints['fields']`.
|
||||
"""
|
||||
|
||||
omitted = 0b000
|
||||
normal = 0b001
|
||||
config = 0b010
|
||||
hinted = 0b101 # Notice that bool(hinted & normal) is True.
|
||||
@@ -1,12 +1,12 @@
|
||||
from bec_lib.callback_handler import EventType
|
||||
from bec_lib.device import Signal
|
||||
from bec_lib.logger import bec_logger
|
||||
from ophyd import Kind
|
||||
from qtpy.QtCore import Property, Slot
|
||||
|
||||
from bec_widgets.utils import ConnectionConfig
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
from bec_widgets.utils.filter_io import FilterIO
|
||||
from bec_widgets.utils.ophyd_kind_util import Kind
|
||||
from bec_widgets.utils.widget_io import WidgetIO
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
0
bec_widgets/widgets/colormap_widget/__init__.py
Normal file
0
bec_widgets/widgets/colormap_widget/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
{'files': ['colormap_widget.py']}
|
||||
@@ -0,0 +1,54 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
||||
|
||||
from bec_widgets.utils.bec_designer import designer_material_icon
|
||||
from bec_widgets.widgets.colormap_widget.colormap_widget import BECColorMapWidget
|
||||
|
||||
DOM_XML = """
|
||||
<ui language='c++'>
|
||||
<widget class='BECColorMapWidget' name='bec_color_map_widget'>
|
||||
</widget>
|
||||
</ui>
|
||||
"""
|
||||
|
||||
|
||||
class BECColorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._form_editor = None
|
||||
|
||||
def createWidget(self, parent):
|
||||
t = BECColorMapWidget(parent)
|
||||
return t
|
||||
|
||||
def domXml(self):
|
||||
return DOM_XML
|
||||
|
||||
def group(self):
|
||||
return "BEC Buttons"
|
||||
|
||||
def icon(self):
|
||||
return designer_material_icon(BECColorMapWidget.ICON_NAME)
|
||||
|
||||
def includeFile(self):
|
||||
return "bec_color_map_widget"
|
||||
|
||||
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 "BECColorMapWidget"
|
||||
|
||||
def toolTip(self):
|
||||
return "BECColorMapWidget"
|
||||
|
||||
def whatsThis(self):
|
||||
return self.toolTip()
|
||||
73
bec_widgets/widgets/colormap_widget/colormap_widget.py
Normal file
73
bec_widgets/widgets/colormap_widget/colormap_widget.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from pyqtgraph.widgets.ColorMapButton import ColorMapButton
|
||||
from qtpy.QtCore import Property, Signal, Slot
|
||||
from qtpy.QtWidgets import QSizePolicy, QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets.utils import Colors
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
|
||||
|
||||
class BECColorMapWidget(BECWidget, QWidget):
|
||||
colormap_changed_signal = Signal(str)
|
||||
ICON_NAME = "palette"
|
||||
USER_ACCESS = ["colormap"]
|
||||
|
||||
def __init__(self, parent=None, cmap: str = "magma"):
|
||||
super().__init__()
|
||||
QWidget.__init__(self, parent=parent)
|
||||
|
||||
# Create the ColorMapButton
|
||||
self.button = ColorMapButton()
|
||||
|
||||
# Set the size policy and minimum width
|
||||
size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
|
||||
self.button.setSizePolicy(size_policy)
|
||||
self.button.setMinimumWidth(100)
|
||||
self.button.setMinimumHeight(30)
|
||||
|
||||
# Create the layout
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.layout.addWidget(self.button)
|
||||
self.layout.setSpacing(0)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# Set the initial colormap
|
||||
self.button.setColorMap(cmap)
|
||||
self._cmap = cmap
|
||||
|
||||
# Connect the signal
|
||||
self.button.sigColorMapChanged.connect(self.colormap_changed)
|
||||
|
||||
@Property(str)
|
||||
def colormap(self):
|
||||
"""Get the current colormap name."""
|
||||
return self._cmap
|
||||
|
||||
@colormap.setter
|
||||
def colormap(self, name):
|
||||
"""Set the colormap by name."""
|
||||
if self._cmap != name:
|
||||
if Colors.validate_color_map(name, return_error=False) is False:
|
||||
return
|
||||
self.button.setColorMap(name)
|
||||
self._cmap = name
|
||||
self.colormap_changed_signal.emit(name)
|
||||
|
||||
@Slot()
|
||||
def colormap_changed(self):
|
||||
"""
|
||||
Emit the colormap changed signal with the current colormap selected in the button.
|
||||
"""
|
||||
cmap = self.button.colorMap().name
|
||||
self._cmap = cmap
|
||||
self.colormap_changed_signal.emit(cmap)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
import sys
|
||||
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
window = BECColorMapWidget()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
@@ -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.colormap_widget.bec_color_map_widget_plugin import (
|
||||
BECColorMapWidgetPlugin,
|
||||
)
|
||||
|
||||
QPyDesignerCustomWidgetCollection.addCustomWidget(BECColorMapWidgetPlugin())
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
main()
|
||||
@@ -147,6 +147,9 @@ class BECPlotBase(BECConnector, pg.GraphicsLayout):
|
||||
for axis in ["left", "bottom", "right", "top"]:
|
||||
self.plot_item.getAxis(axis).setPen(text_pen)
|
||||
self.plot_item.getAxis(axis).setTextPen(text_pen)
|
||||
if self.plot_item.legend is not None:
|
||||
for sample, label in self.plot_item.legend.items:
|
||||
label.setText(label.text, color=palette.text().color())
|
||||
|
||||
def set(self, **kwargs) -> None:
|
||||
"""
|
||||
|
||||
@@ -321,7 +321,7 @@ class ScanGroupBox(QGroupBox):
|
||||
for i in range(self.layout.columnCount()):
|
||||
widget = self.layout.itemAtPosition(1, i).widget()
|
||||
if isinstance(widget, DeviceLineEdit) and device_object:
|
||||
value = widget.get_device()
|
||||
value = widget.get_current_device().name
|
||||
else:
|
||||
value = WidgetIO.get_value(widget)
|
||||
kwargs[widget.arg_name] = value
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from bec_lib.device import Positioner
|
||||
from ophyd import Kind
|
||||
from qtpy.QtCore import QSize, Signal, Slot
|
||||
from qtpy.QtWidgets import QComboBox, QSizePolicy
|
||||
|
||||
from bec_widgets.utils.filter_io import ComboBoxFilterHandler, FilterIO
|
||||
from bec_widgets.utils.ophyd_kind_util import Kind
|
||||
from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from bec_lib.device import Positioner
|
||||
from ophyd import Kind
|
||||
from qtpy.QtCore import QSize, Signal, Slot
|
||||
from qtpy.QtGui import QPainter, QPaintEvent, QPen
|
||||
from qtpy.QtWidgets import QCompleter, QLineEdit, QSizePolicy
|
||||
|
||||
from bec_widgets.utils.colors import get_accent_colors
|
||||
from bec_widgets.utils.ophyd_kind_util import Kind
|
||||
from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class CurveSettings(SettingWidget):
|
||||
x_entry = self.target_widget.waveform._x_axis_mode["entry"]
|
||||
self._enable_ui_elements(x_name, x_entry)
|
||||
cm = self.target_widget.config.color_palette
|
||||
self.ui.color_map_selector_scan.combo.setCurrentText(cm)
|
||||
self.ui.color_map_selector_scan.colormap = cm
|
||||
|
||||
# Scan Curve Table
|
||||
for source in ["scan_segment", "async"]:
|
||||
@@ -115,10 +115,10 @@ class CurveSettings(SettingWidget):
|
||||
@Slot()
|
||||
def change_colormap(self, target: Literal["scan", "dap"]):
|
||||
if target == "scan":
|
||||
cm = self.ui.color_map_selector_scan.combo.currentText()
|
||||
cm = self.ui.color_map_selector_scan.colormap
|
||||
table = self.ui.scan_table
|
||||
if target == "dap":
|
||||
cm = self.ui.color_map_selector_dap.combo.currentText()
|
||||
cm = self.ui.color_map_selector_dap.colormap
|
||||
table = self.ui.dap_table
|
||||
rows = table.rowCount()
|
||||
colors = Colors.golden_angle_color(colormap=cm, num=max(10, rows + 1), format="HEX")
|
||||
|
||||
@@ -231,7 +231,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="ColormapSelector" name="color_map_selector_scan"/>
|
||||
<widget class="BECColorMapWidget" name="color_map_selector_scan">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -330,7 +337,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="ColormapSelector" name="color_map_selector_dap"/>
|
||||
<widget class="BECColorMapWidget" name="color_map_selector_dap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -348,9 +362,9 @@
|
||||
<header>device_line_edit</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ColormapSelector</class>
|
||||
<class>BECColorMapWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>colormap_selector</header>
|
||||
<header>bec_color_map_widget</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
||||
@@ -39,6 +39,17 @@ The `Colormap Selector` is a specialized combobox that allows users to select a
|
||||
**Key Features:**
|
||||
- **Colormap Selection**: Provides a dropdown to select from all available colormaps in `pyqtgraph`.
|
||||
- **Visual Preview**: Displays a small preview of the colormap next to its name, enhancing usability.
|
||||
|
||||
## Colormap Button
|
||||
|
||||
The `Colormap Button` is a custom widget that displays the current colormap and, upon clicking, shows a nested menu for selecting a different colormap. It integrates the `ColorMapMenu` from `pyqtgraph`, providing an intuitive and interactive way for users to choose colormaps within the GUI.
|
||||
|
||||
**Key Features:**
|
||||
- **Current Colormap Display**: Shows the name and a gradient icon of the current colormap directly on the button.
|
||||
- **Nested Menu Selection**: Offers a nested menu with categorized colormaps, making it easy to find and select the desired colormap.
|
||||
- **Signal Emission**: Emits a signal when the colormap changes, providing the new colormap name as a string.
|
||||
- **Qt Designer Integration**: Exposes properties and signals to be used within Qt Designer, allowing for customization within the designer interface.
|
||||
- **Resizable and Styled**: Features adjustable size policies and styles to match the look and feel of standard `QPushButton` widgets, including rounded edges.
|
||||
`````
|
||||
|
||||
````{tab} Examples
|
||||
@@ -104,6 +115,33 @@ class MyGui(QWidget):
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
## Example 4 - Adding a Colormap Button
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
from bec_widgets.widgets.buttons import ColormapButton
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setLayout(QVBoxLayout(self))
|
||||
|
||||
# Create and add the ColormapButton to the layout
|
||||
self.colormap_button = ColormapButton()
|
||||
self.layout().addWidget(self.colormap_button)
|
||||
|
||||
# Connect the signal to handle colormap changes
|
||||
self.colormap_button.colormap_changed_signal.connect(self.on_colormap_changed)
|
||||
|
||||
def on_colormap_changed(self, colormap_name):
|
||||
print(f"Selected colormap: {colormap_name}")
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
|
||||
@@ -29,16 +29,16 @@ In this example, we demonstrate how to add a `TextBox` widget to a `BECDockArea`
|
||||
text_box = gui.add_dock().add_widget("TextBox")
|
||||
|
||||
# Set the text to display
|
||||
text_box.set_text("Hello, World!")
|
||||
text_box.set_plain_text("Hello, World!")
|
||||
```
|
||||
|
||||
## Example 2 - Displaying HTML Content
|
||||
|
||||
The `TextBox` widget can automatically detect and render HTML content. This example shows how to display formatted HTML text.
|
||||
The `TextBox` widget can also render HTML content. This example shows how to display formatted HTML text.
|
||||
|
||||
```python
|
||||
# Set the text to display as HTML
|
||||
text_box.set_text("<h1>Welcome to BEC Widgets</h1><p>This is an example of displaying <strong>HTML</strong> text.</p>")
|
||||
text_box.set_html_text("<h1>Welcome to BEC Widgets</h1><p>This is an example of displaying <strong>HTML</strong> text.</p>")
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "bec_widgets"
|
||||
version = "1.2.0"
|
||||
version = "1.3.3"
|
||||
description = "BEC Widgets"
|
||||
requires-python = ">=3.10"
|
||||
classifiers = [
|
||||
@@ -38,7 +38,7 @@ dev = [
|
||||
"pytest~=8.0",
|
||||
]
|
||||
pyqt6 = ["PyQt6>=6.7", "PyQt6-WebEngine>=6.7"]
|
||||
pyside6 = ["PySide6~=6.7.2"]
|
||||
pyside6 = ["PySide6==6.7.2"]
|
||||
|
||||
[project.urls]
|
||||
"Bug Tracker" = "https://gitlab.psi.ch/bec/bec_widgets/issues"
|
||||
|
||||
69
tests/unit_tests/test_colormap_widget.py
Normal file
69
tests/unit_tests/test_colormap_widget.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import pytest
|
||||
from pyqtgraph.widgets.ColorMapButton import ColorMapButton
|
||||
|
||||
from bec_widgets.widgets.colormap_widget.colormap_widget import BECColorMapWidget
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def color_map_widget(qtbot):
|
||||
widget = BECColorMapWidget()
|
||||
qtbot.addWidget(widget)
|
||||
qtbot.waitExposed(widget)
|
||||
yield widget
|
||||
|
||||
|
||||
def test_color_map_widget_init(color_map_widget):
|
||||
"""Test that the widget initializes correctly."""
|
||||
assert color_map_widget is not None
|
||||
assert isinstance(color_map_widget, BECColorMapWidget)
|
||||
assert color_map_widget.colormap == "magma"
|
||||
assert isinstance(color_map_widget.button, ColorMapButton)
|
||||
# Check that the button has the correct initial colormap
|
||||
assert color_map_widget.button.colorMap().name == "magma"
|
||||
|
||||
|
||||
def test_color_map_widget_set_valid_colormap(color_map_widget):
|
||||
"""
|
||||
Test setting a valid colormap.
|
||||
"""
|
||||
new_cmap = "viridis"
|
||||
color_map_widget.colormap = new_cmap
|
||||
assert color_map_widget.colormap == new_cmap
|
||||
assert color_map_widget.button.colorMap().name == new_cmap
|
||||
|
||||
|
||||
def test_color_map_widget_set_invalid_colormap(color_map_widget):
|
||||
"""Test setting an invalid colormap."""
|
||||
invalid_cmap = "invalid_colormap_name"
|
||||
old_cmap = color_map_widget.colormap
|
||||
color_map_widget.colormap = invalid_cmap
|
||||
# Since invalid, the colormap should not change
|
||||
assert color_map_widget.colormap == old_cmap
|
||||
assert color_map_widget.button.colorMap().name == old_cmap
|
||||
|
||||
|
||||
def test_color_map_widget_signal_emitted(color_map_widget, qtbot):
|
||||
"""Test that the signal is emitted when the colormap changes."""
|
||||
new_cmap = "plasma"
|
||||
with qtbot.waitSignal(color_map_widget.colormap_changed_signal, timeout=1000) as blocker:
|
||||
color_map_widget.colormap = new_cmap
|
||||
assert blocker.signal_triggered
|
||||
assert blocker.args == [new_cmap]
|
||||
assert color_map_widget.colormap == new_cmap
|
||||
|
||||
|
||||
def test_color_map_widget_signal_not_emitted_for_invalid_colormap(color_map_widget, qtbot):
|
||||
"""Test that the signal is not emitted when an invalid colormap is set."""
|
||||
invalid_cmap = "invalid_colormap_name"
|
||||
with qtbot.assertNotEmitted(color_map_widget.colormap_changed_signal):
|
||||
color_map_widget.colormap = invalid_cmap
|
||||
# The colormap should remain unchanged
|
||||
assert color_map_widget.colormap == "magma"
|
||||
|
||||
|
||||
def test_color_map_widget_resize(color_map_widget):
|
||||
"""Test that the widget resizes properly."""
|
||||
width, height = 200, 50
|
||||
color_map_widget.resize(width, height)
|
||||
assert color_map_widget.width() == width
|
||||
assert color_map_widget.height() == height
|
||||
@@ -1,9 +1,9 @@
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from ophyd import Kind
|
||||
from qtpy.QtWidgets import QWidget
|
||||
|
||||
from bec_widgets.utils.ophyd_kind_util import Kind
|
||||
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
||||
from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase
|
||||
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
|
||||
|
||||
Reference in New Issue
Block a user