1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-04-15 21:20:55 +02:00

Compare commits

...

4 Commits

11 changed files with 257 additions and 43 deletions

View File

@@ -22,6 +22,13 @@ workflow:
include:
- template: Security/Secret-Detection.gitlab-ci.yml
- project: "bec/awi_utils"
file: "/templates/check-packages-job.yml"
inputs:
stage: test
path: "."
pytest_args: "-v --random-order tests/"
exclude_packages: ""
# different stages in the pipeline
stages:
@@ -32,21 +39,21 @@ stages:
- Deploy
.install-qt-webengine-deps: &install-qt-webengine-deps
- apt-get -y install libnss3 libxdamage1 libasound2 libatomic1 libxcursor1
- export QTWEBENGINE_DISABLE_SANDBOX=1
- apt-get -y install libnss3 libxdamage1 libasound2 libatomic1 libxcursor1
- export QTWEBENGINE_DISABLE_SANDBOX=1
.clone-repos: &clone-repos
- git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
- git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
- export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
- git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
- git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
- export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
.install-os-packages: &install-os-packages
- apt-get update
- apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
- *install-qt-webengine-deps
- apt-get update
- apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
- *install-qt-webengine-deps
before_script:
- if [[ "$CI_PROJECT_PATH" != "bec/bec_widgets" ]]; then
- if [[ "$CI_PROJECT_PATH" != "bec/bec_widgets" ]]; then
echo -e "\033[35;1m Using branch $CHILD_PIPELINE_BRANCH of BEC Widgets \033[0;m";
test -d bec_widgets || git clone --branch $CHILD_PIPELINE_BRANCH https://gitlab.psi.ch/bec/bec_widgets.git; cd bec_widgets;
fi
@@ -92,10 +99,10 @@ pylint-check:
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
# Identify changed Python files
- if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
TARGET_BRANCH_COMMIT_SHA=$(git rev-parse origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME);
CHANGED_FILES=$(git diff --name-only $TARGET_BRANCH_COMMIT_SHA HEAD | grep '\.py$' || true);
TARGET_BRANCH_COMMIT_SHA=$(git rev-parse origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME);
CHANGED_FILES=$(git diff --name-only $TARGET_BRANCH_COMMIT_SHA HEAD | grep '\.py$' || true);
else
CHANGED_FILES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep '\.py$' || true);
CHANGED_FILES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep '\.py$' || true);
fi
- if [ -z "$CHANGED_FILES" ]; then echo "No Python files changed."; exit 0; fi
@@ -120,7 +127,7 @@ tests:
stage: test
needs: []
variables:
QT_QPA_PLATFORM: "offscreen"
QT_QPA_PLATFORM: "offscreen"
script:
- *clone-repos
- *install-os-packages
@@ -141,21 +148,21 @@ tests:
test-matrix:
parallel:
matrix:
- PYTHON_VERSION:
- "3.10"
- "3.11"
- "3.12"
QT_PCKG:
- "pyside6"
- "pyqt5"
- "pyqt6"
- PYTHON_VERSION:
- "3.10"
- "3.11"
- "3.12"
QT_PCKG:
- "pyside6"
- "pyqt5"
- "pyqt6"
stage: AdditionalTests
needs: []
variables:
QT_QPA_PLATFORM: "offscreen"
PYTHON_VERSION: ""
QT_PCKG: ""
QT_QPA_PLATFORM: "offscreen"
PYTHON_VERSION: ""
QT_PCKG: ""
image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:$PYTHON_VERSION
script:
- *clone-repos
@@ -226,7 +233,7 @@ semver:
- pip install python-semantic-release==9.* wheel build twine
- export GL_TOKEN=$CI_UPDATES
- semantic-release -vv version
# check if any artifacts were created
- if [ ! -d dist ]; then echo No release will be made; exit 0; fi
- twine upload dist/* -u __token__ -p $CI_PYPI_TOKEN --skip-existing
@@ -242,7 +249,7 @@ pages:
variables:
TARGET_BRANCH: $CI_COMMIT_REF_NAME
rules:
- if: '$CI_COMMIT_TAG != null'
- if: "$CI_COMMIT_TAG != null"
variables:
TARGET_BRANCH: $CI_COMMIT_TAG
- if: '$CI_COMMIT_REF_NAME == "main" && $CI_PROJECT_PATH == "bec/bec_widgets"'

View File

@@ -16,6 +16,7 @@ class Widgets(str, enum.Enum):
BECDock = "BECDock"
BECDockArea = "BECDockArea"
BECFigure = "BECFigure"
RoundStatusIndicator = "RoundStatusIndicator"
SpiralProgressBar = "SpiralProgressBar"
TextBox = "TextBox"
WebsiteWidget = "WebsiteWidget"
@@ -1719,6 +1720,17 @@ class Ring(RPCBase):
"""
class RoundStatusIndicator(RPCBase):
@rpc_call
def set_state(self, state: Literal["success", "failure", "warning"]) -> None:
"""
Set the state of the indicator.
Args:
state (str): The state of the indicator. Can be "success", "failure", or "warning"
"""
class SpiralProgressBar(RPCBase):
@rpc_call
def get_all_rpc(self) -> "dict":
@@ -1920,7 +1932,7 @@ class TextBox(RPCBase):
@rpc_call
def set_color(self, background_color: str, font_color: str) -> None:
"""
Set the background color of the Widget.
Set the background color of the widget.
Args:
background_color (str): The color to set the background in HEX.
@@ -1930,13 +1942,19 @@ class TextBox(RPCBase):
@rpc_call
def set_text(self, text: str) -> None:
"""
Set the text of the Widget
Set the text of the widget.
Args:
text (str): The text to set.
"""
@rpc_call
def set_font_size(self, size: int) -> None:
"""
Set the font size of the text in the Widget.
Set the font size of the text in the widget.
Args:
size (int): The font size to set.
"""

View File

@@ -1,5 +1,6 @@
from bec_widgets.utils import BECConnector
from bec_widgets.widgets.figure import BECFigure
from bec_widgets.widgets.round_status_indicator.round_status_indicator import RoundStatusIndicator
from bec_widgets.widgets.spiral_progress_bar.spiral_progress_bar import SpiralProgressBar
from bec_widgets.widgets.text_box.text_box import TextBox
from bec_widgets.widgets.website.website import WebsiteWidget
@@ -13,6 +14,7 @@ class RPCWidgetHandler:
"SpiralProgressBar": SpiralProgressBar,
"Website": WebsiteWidget,
"TextBox": TextBox,
"RoundStatusIndicator": RoundStatusIndicator,
}
@staticmethod

View File

@@ -0,0 +1,108 @@
from enum import Enum
from typing import Literal
from PyQt6.QtGui import QPaintEvent
from qtpy import QtGui
from qtpy.QtCore import QRect, Qt
from qtpy.QtWidgets import QApplication, QMainWindow, QWidget
from bec_widgets.utils.bec_connector import BECConnector, ConnectionConfig
class RoundStatusIndicatorConfig(ConnectionConfig):
"""
Configuration for the RoundStatusIndicator
"""
state: Literal["success", "failure", "warning"] = "success"
class RoundStatusIndicator(BECConnector, QWidget):
indicator_config = {
"success": {"color": "#24a148", "text": "", "offset": 0.25},
"failure": {"color": "#da1e28", "text": "", "offset": 0.28},
"warning": {"color": "#ffcc00", "text": "!", "offset": 0.28},
}
USER_ACCESS = ["set_state"]
def __init__(
self,
client=None,
config: RoundStatusIndicatorConfig | dict | None = None,
gui_id=None,
parent=None,
):
super().__init__(client=client, config=config, gui_id=gui_id)
QWidget.__init__(self, parent=parent)
self.config = config or RoundStatusIndicatorConfig(widget_class=self.__class__.__name__)
self.active_state_config = self.indicator_config[self.config.state]
def paintEvent(self, _event: QPaintEvent) -> None:
"""
Paint the widget.
Args:
_event (QPaintEvent): The paint event
"""
color = QtGui.QColor(self.active_state_config["color"]) # Red color as default
text_color = QtGui.QColor("#ffffff") # White color for text
text = self.active_state_config["text"]
offset = self.active_state_config["offset"]
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.RenderHint.Antialiasing)
# Determine the size of the widget
size = min(self.width(), self.height())
rect = QRect(0, 0, size, size)
# Set the color and draw the disk
painter.setBrush(color)
painter.setPen(Qt.PenStyle.NoPen)
painter.drawEllipse(rect)
# Draw the exclamation mark "!"
painter.setPen(text_color)
font = painter.font()
font.setPixelSize(int(size * 0.9)) # Adjust font size based on widget size
painter.setFont(font)
# text_rect = painter.boundingRect(rect, Qt.AlignmentFlag.AlignCenter, text)
font_metrics = QtGui.QFontMetrics(font)
text_width = font_metrics.horizontalAdvance(text)
text_height = font_metrics.height()
text_x = int(rect.center().x() - text_width / 2)
text_y = int(rect.center().y() + text_height * offset)
painter.drawText(text_x, text_y, text)
def set_state(self, state: Literal["success", "failure", "warning"]) -> None:
"""
Set the state of the indicator.
Args:
state (str): The state of the indicator. Can be "success", "failure", or "warning"
"""
self.config.state = state
self.active_state_config = self.indicator_config[state]
self.update()
if __name__ == "__main__":
app = QApplication([])
window = QMainWindow()
status_indicator = RoundStatusIndicator()
window.setCentralWidget(status_indicator)
window.resize(200, 200)
window.show()
# Example of changing the color
status_indicator.set_state("warning") # Change to a different color
app.exec()

View File

@@ -1,18 +1,46 @@
(developer)=
# Development
# Developer
To contribute to the development of BEC Widgets, start by setting up the development environment:
Welcome to the BEC Widgets developer guide! This section is intended for developers who want to contribute to the development of BEC Widgets.
1. **Clone the Repository**:
```bash
git clone https://gitlab.psi.ch/bec/bec_widgets
cd bec_widgets
```
2. **Install in Editable Mode**:
```{toctree}
---
maxdepth: 2
hidden: true
---
Installing the package in editable mode allows you to make changes to the code and test them in real-time.
```bash
pip install -e .[dev,pyqt6]
getting_started/getting_started.md
widgets/widgets.md
api_reference/api_reference.md
```
***
````{grid} 2
:gutter: 5
```{grid-item-card}
:link: developer.getting_started
:link-type: ref
:img-top: /assets/rocket_launch_48dp.svg
:text-align: center
## Getting Started
Learn how to install BEC Widgets and get started with the framework.
```
```{grid-item-card}
:link: developer.widgets
:link-type: ref
:img-top: /assets/apps_48dp.svg
:text-align: center
## Widgets
Learn about the building blocks of larger applications: widgets.
```
````

View File

@@ -0,0 +1,27 @@
(developer.development)=
# Development
If you like to contribute to the development of BEC Widgets, you can follow the steps below to set up your development environment.
BEC Widgets works in conjunction with [BEC](https://bec.readthedocs.io/en/latest/).
Therefore, we recommend that you install BEC first following the [developer instructions](https://bec.readthedocs.io/en/latest/developer/getting_started/install_developer_env.html) and include BEC Widgets.
If you already have a BEC environment set up, you can install BEC Widgets in editable mode into your BEC Python environment.
**Prerequisites**
1. **Python Version:** BEC Widgets requires Python version 3.10 or higher. Verify your Python version to ensure compatibility.
2. **BEC Installation:** BEC Widgets works in conjunction with BEC. While BEC is a dependency and will be installed automatically, you can find more information about BEC and its installation process in the [BEC documentation](https://beamline-experiment-control.readthedocs.io/en/latest/).
**Clone the Repository**:
```bash
git clone https://gitlab.psi.ch/bec/bec_widgets
cd bec_widgets
```
**Install in Editable Mode**:
Please install the package in editable mode into your BEC Python environemnt.
```bash
pip install -e '.[dev,pyqt6]'
```
This installs the package together with [PyQT6](https://www.riverbankcomputing.com/static/Docs/PyQt6/introduction.html).

View File

@@ -0,0 +1,12 @@
(developer.getting_started)=
# Getting Started
This section provides valuable information for developers who want to contribute to the development of BEC Widgets. The guide will help you set up the development environment, understand the modular development concept of BEC Widgets, and contribute to the project.
```{toctree}
---
maxdepth: 2
hidden: false
---
development/
```

View File

@@ -0,0 +1,12 @@
(developer.widgets)=
# Widgets
This section provides an introduction to the building blocks of BEC Widgets: widgets. Widgets are the basic components of the graphical user interface (GUI) and are used to create larger applications. We will cover key topics such as how to develop new widgets or how to customise existing widgets. For details on the already available widgets and their usage, please refer to user section about [widgets](#user.widgets)
```{toctree}
---
maxdepth: 2
hidden: false
---
how_to_develop_a_widget/
```

View File

@@ -9,7 +9,7 @@ Before installing BEC Widgets, please ensure the following requirements are met:
**Standard Installation**
To install BEC Widgets using the pip package manager, execute the following command in your terminal for getting the default PyQT6 version in your python environment:
To install BEC Widgets using the pip package manager, execute the following command in your terminal for getting the default PyQT6 version into your python environment for BEC:
```bash

View File

@@ -1,5 +1,5 @@
(user.widgets.text_box)=
# [Text Box Widget](/api_reference/_autosummary/bec_widgets.cli.client.TextBoxWidget)
# [Text Box Widget](/api_reference/_autosummary/bec_widgets.cli.client.TextBox)
**Purpose:**
The Text Box Widget is a widget that allows you to display text within the BEC GUI. The widget can be used to display plain text or HTML text.