From c9e5dd542c9eb7c9069d1c0f1256a634a166eb40 Mon Sep 17 00:00:00 2001
From: wyzula-jan <133381102+wyzula-jan@users.noreply.github.com>
Date: Sat, 14 Oct 2023 17:07:44 +0200
Subject: [PATCH] feat: config_dialog.py interactive editor of plot settings
---
bec_widgets/examples/modular_app/___init__.py | 85 +++++++++
.../examples/modular_app/modular_app.py | 4 +-
bec_widgets/widgets/monitor/__init__.py | 0
bec_widgets/widgets/monitor/config_dialog.py | 108 +++++++++++
bec_widgets/widgets/monitor/config_dialog.ui | 160 +++++++++++++++++
.../widgets/{ => monitor}/device_monitor.py | 0
bec_widgets/widgets/monitor/tab_template.ui | 169 ++++++++++++++++++
7 files changed, 525 insertions(+), 1 deletion(-)
create mode 100644 bec_widgets/examples/modular_app/___init__.py
create mode 100644 bec_widgets/widgets/monitor/__init__.py
create mode 100644 bec_widgets/widgets/monitor/config_dialog.py
create mode 100644 bec_widgets/widgets/monitor/config_dialog.ui
rename bec_widgets/widgets/{ => monitor}/device_monitor.py (100%)
create mode 100644 bec_widgets/widgets/monitor/tab_template.ui
diff --git a/bec_widgets/examples/modular_app/___init__.py b/bec_widgets/examples/modular_app/___init__.py
new file mode 100644
index 00000000..68ba0263
--- /dev/null
+++ b/bec_widgets/examples/modular_app/___init__.py
@@ -0,0 +1,85 @@
+from PyQt5.QtWidgets import (
+ QApplication,
+ QMainWindow,
+ QVBoxLayout,
+ QWidget,
+ QTabWidget,
+ QPushButton,
+ QDialog,
+ QListView,
+ QStandardItemModel,
+ QStandardItem,
+)
+from bec_widgets.widgets.device_monitor import BECDeviceMonitor
+from bec_widgets.bec_dispatcher import bec_dispatcher
+
+
+class ConfigDialog(QDialog):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setWindowTitle("Configuration")
+ self.layout = QVBoxLayout(self)
+ self.listView = QListView(self)
+ self.layout.addWidget(self.listView)
+ self.okButton = QPushButton("OK", self)
+ self.layout.addWidget(self.okButton)
+ self.okButton.clicked.connect(self.accept)
+
+ def populate_device_list(self, device_names):
+ model = QStandardItemModel()
+ for device_name in device_names:
+ item = QStandardItem(device_name)
+ item.setCheckable(True)
+ model.appendRow(item)
+ self.listView.setModel(model)
+
+
+class PlotTabWidget(QTabWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.addTabButton = QPushButton("Add Tab", self)
+ self.addTabButton.clicked.connect(self.add_new_tab)
+ self.setCornerWidget(self.addTabButton)
+
+ def add_new_tab(self):
+ config_dialog = ConfigDialog(self)
+ config_dialog.populate_device_list(bec_dispatcher.client.device_manager.devices.keys())
+ if config_dialog.exec_():
+ selected_devices = [
+ config_dialog.listView.model().item(i).text()
+ for i in range(config_dialog.listView.model().rowCount())
+ if config_dialog.listView.model().item(i).checkState()
+ ]
+ # Assuming device_config is a function that generates a config based on selected devices
+ config = device_config(selected_devices)
+ bec_device_monitor = BECDeviceMonitor(parent=self, config=config)
+ self.addTab(bec_device_monitor, f"Tab {self.count() + 1}")
+
+
+class ModularApp(QMainWindow):
+ def __init__(self, client=None, parent=None):
+ super(ModularApp, self).__init__(parent)
+ self.client = bec_dispatcher.client if client is None else client
+ self.init_ui()
+
+ def init_ui(self):
+ self.tabWidget = PlotTabWidget(self)
+ self.setCentralWidget(self.tabWidget)
+
+
+def device_config(selected_devices):
+ # Generate a configuration based on the selected devices
+ # This is a placeholder and should be replaced with your actual logic
+ pass
+
+
+if __name__ == "__main__":
+ client = bec_dispatcher.client
+ client.start()
+
+ app = QApplication([])
+ modularApp = ModularApp(client=client)
+
+ window = modularApp
+ window.show()
+ app.exec_()
diff --git a/bec_widgets/examples/modular_app/modular_app.py b/bec_widgets/examples/modular_app/modular_app.py
index f2353ba5..e933b4d0 100644
--- a/bec_widgets/examples/modular_app/modular_app.py
+++ b/bec_widgets/examples/modular_app/modular_app.py
@@ -1,7 +1,9 @@
import os
+
from PyQt5 import uic
from PyQt5.QtWidgets import QMainWindow, QApplication, QVBoxLayout
-from bec_widgets.widgets.device_monitor import BECDeviceMonitor
+
+from bec_widgets.widgets.monitor.device_monitor import BECDeviceMonitor
config_1 = {
"plot_settings": {
diff --git a/bec_widgets/widgets/monitor/__init__.py b/bec_widgets/widgets/monitor/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/bec_widgets/widgets/monitor/config_dialog.py b/bec_widgets/widgets/monitor/config_dialog.py
new file mode 100644
index 00000000..8b8e732f
--- /dev/null
+++ b/bec_widgets/widgets/monitor/config_dialog.py
@@ -0,0 +1,108 @@
+from PyQt5 import uic
+from PyQt5.QtWidgets import (
+ QApplication,
+ QWidget,
+ QVBoxLayout,
+ QLineEdit,
+ QLabel,
+ QGroupBox,
+ QHBoxLayout,
+ QPushButton,
+ QTableWidgetItem,
+)
+
+Ui_Form, BaseClass = uic.loadUiType("config_dialog.ui")
+Tab_Ui_Form, Tab_BaseClass = uic.loadUiType("tab_template.ui")
+
+
+class MainApp(QWidget, Ui_Form):
+ def __init__(self):
+ super().__init__()
+ self.setupUi(self)
+
+ self.signal_count = 1 # TODO decide if useful
+
+ self.tab_ui_objects = [] # Create a list to hold the Tab_Ui_Form objects
+
+ # Connect the buttons
+ self.pushButton_add_new_plot.clicked.connect(self.add_new_plot)
+ self.pushButton_ok.clicked.connect(self.get_configuration)
+
+ self.add_new_plot() # add initial first plot tab
+
+ def add_new_plot(self):
+ # Set tabs
+ new_tab_widget = QWidget()
+ new_tab = Tab_Ui_Form()
+ new_tab.setupUi(new_tab_widget)
+
+ # Tab Signals
+ new_tab.pushButton_y_new.clicked.connect(
+ lambda: self.add_new_signal(new_tab.tableWidget_y_signals)
+ )
+ new_tab_name = f"Plot {self.tabWidget_plots.count() + 1}"
+ self.tabWidget_plots.addTab(
+ new_tab_widget, new_tab_name
+ ) # Add the new QWidget as a new tab
+ self.tab_ui_objects.append(new_tab) # Append the Tab_Ui_Form object to the list
+
+ def add_new_signal(self, tableWidget_y_signals):
+ row_position = tableWidget_y_signals.rowCount()
+ tableWidget_y_signals.insertRow(row_position)
+ tableWidget_y_signals.setItem(row_position, 0, QTableWidgetItem(""))
+ tableWidget_y_signals.setItem(row_position, 1, QTableWidgetItem(""))
+
+ def get_configuration(self):
+ config = {
+ "plot_settings": {
+ "background_color": "black",
+ "num_columns": self.spinBox.value(),
+ "colormap": self.comboBox_2.currentText(),
+ "scan_types": self.comboBox.currentText() == "Enabled",
+ },
+ "plot_data": [],
+ }
+
+ for index in range(self.tabWidget_plots.count()):
+ tab = self.tabWidget_plots.widget(index)
+ ui_object = self.tab_ui_objects[index]
+ table = ui_object.tableWidget_y_signals
+ signals = [
+ {
+ "name": self.safe_text(table.item(row, 0)),
+ "entry": self.safe_text(table.item(row, 1)),
+ }
+ for row in range(table.rowCount())
+ ]
+
+ plot_config = {
+ "plot_name": self.safe_text(ui_object.lineEdit_plot_title),
+ "x": {
+ "label": self.safe_text(ui_object.lineEdit_x_label),
+ "signals": [
+ {
+ "name": self.safe_text(ui_object.lineEdit_x_name),
+ "entry": self.safe_text(ui_object.lineEdit_x_entry),
+ }
+ ],
+ },
+ "y": {
+ "label": self.safe_text(ui_object.lineEdit_y_label),
+ "signals": signals,
+ },
+ }
+ config["plot_data"].append(plot_config)
+
+ print(config)
+ return config
+
+ @staticmethod
+ def safe_text(line_edit):
+ return "" if line_edit is None else line_edit.text()
+
+
+if __name__ == "__main__":
+ app = QApplication([])
+ main_app = MainApp()
+ main_app.show()
+ app.exec_()
diff --git a/bec_widgets/widgets/monitor/config_dialog.ui b/bec_widgets/widgets/monitor/config_dialog.ui
new file mode 100644
index 00000000..b7fc6f59
--- /dev/null
+++ b/bec_widgets/widgets/monitor/config_dialog.ui
@@ -0,0 +1,160 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 558
+ 769
+
+
+
+ Plot Configuration
+
+
+ -
+
+
-
+
+
+ Plot Layout Settings
+
+
+
-
+
+
+ -
+
+
+ Scan Types
+
+
+
+ -
+
+
+ Default Color Palette
+
+
+
+ -
+
+
-
+
+ magma
+
+
+ -
+
+ viridis
+
+
+ -
+
+ reds
+
+
+
+
+ -
+
+
+ Number of Columns
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
-
+
+ Disabled
+
+
+ -
+
+ Enabled
+
+
+
+
+ -
+
+
+ Add New Plot
+
+
+
+
+
+
+ -
+
+
+ Configuration
+
+
+
-
+
+
+ Import
+
+
+
+ -
+
+
+ Export
+
+
+
+
+
+
+
+
+ -
+
+
+ -1
+
+
+
+ -
+
+
-
+
+
+ Cancel
+
+
+
+ -
+
+
+ Apply
+
+
+
+ -
+
+
+ OK
+
+
+
+
+
+
+
+
+
+
diff --git a/bec_widgets/widgets/device_monitor.py b/bec_widgets/widgets/monitor/device_monitor.py
similarity index 100%
rename from bec_widgets/widgets/device_monitor.py
rename to bec_widgets/widgets/monitor/device_monitor.py
diff --git a/bec_widgets/widgets/monitor/tab_template.ui b/bec_widgets/widgets/monitor/tab_template.ui
new file mode 100644
index 00000000..498febce
--- /dev/null
+++ b/bec_widgets/widgets/monitor/tab_template.ui
@@ -0,0 +1,169 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 506
+ 592
+
+
+
+ Form
+
+
+ -
+
+
+ General
+
+
+
-
+
+
+ X Label
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ -
+
+
+ Y Label
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ Plot Title
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+
+
+
+ -
+
+
-
+
+
+ X Axis
+
+
+
-
+
+
+ Name:
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+ Entry:
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+ 1
+
+
+
+
+ Name
+
+
+
+
+ Entries
+
+
+
+
+ Color
+
+
+
+
+ -
+
+
-
+
+
+ Remove Current Plot
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Add New Signal
+
+
+
+
+
+
+
+
+
+
+
+