Fix and make it a tiny bit prettier

This commit is contained in:
CPD 2025-03-04 17:52:32 +01:00
parent 98f3475d97
commit e85b5bc0d4

View File

@ -1,23 +1,5 @@
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QSpacerItem, QSpinBox, QDoubleSpinBox from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QSpacerItem, QSpinBox, QDoubleSpinBox
from PyQt6.QtWidgets import QGridLayout, QMenu, QListWidget, QPushButton from PyQt6.QtWidgets import QGridLayout, QMenu, QListWidget, QPushButton, QFormLayout, QDialog, QDialogButtonBox
class MetadataInput(QWidget):
def __init__(self, elements: list[tuple[str, str]]=None):
super().__init__()
self.layout = QVBoxLayout()
self.elements = []
if elements is not None:
for (n, v) in elements:
self.addElement(n, v)
self.layout.addStretch()
self.setLayout(self.layout)
def addElement(self, name, init_val=""):
self.elements.append((name, init_val))
self.layout.addWidget(QLabel(name))
self.layout.addWidget(QLineEdit(init_val))
self.layout.addItem(QSpacerItem(0, 1))
""" """
QWidget class that contains a variable amount of key - input pairs. QWidget class that contains a variable amount of key - input pairs.
@ -25,51 +7,125 @@ One pair per line in a dense layout
pairs. The value may be text - line edit, float - qdoublespinbox and int - qspinbox. pairs. The value may be text - line edit, float - qdoublespinbox and int - qspinbox.
""" """
class MetadataInput2(QWidget): class MetadataInput(QWidget):
def __init__(self, elements: list[tuple[str, str]]=None): def __init__(self, elements: list[tuple[str, str]]=None):
super().__init__() super().__init__()
self.layout = QGridLayout() self.l_vbox = QVBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0) self.l_vbox.addWidget(QLabel("Measurement Metadata"))
self.layout.setSpacing(0) self.l_grid = QGridLayout()
self.l_grid.setContentsMargins(0, 0, 0, 0)
self.l_grid.setSpacing(0)
# first row: key value <new element button>
self.l_grid.addWidget(QLabel("Key"), 0, 0)
self.l_grid.addWidget(QLabel("Value"), 0, 1)
self.btn_new_element = QPushButton("+")
self.btn_new_element.setFixedSize(20, 20)
self.btn_new_element.clicked.connect(self.add_element_dialog)
self.l_grid.addWidget(self.btn_new_element, 0, 2)
# key-value widgets
self.ws_elements = {}
for (n, v) in elements: for (n, v) in elements:
self.add_element(n, v) self.add_element(n, v)
self.setLayout(self.layout) self.l_grid.setContentsMargins(4, 4, 4, 4)
self.l_grid.setSpacing(4)
self.l_vbox.addLayout(self.l_grid)
self.setLayout(self.l_vbox)
def add_element(self, name, init_val=""): def layout_changed(self):
row = self.layout.rowCount() # align at the top with space at the bottom
label_widget = QLabel(name) for r in range(self.l_grid.rowCount()):
self.layout.addWidget(label_widget, row, 0) self.l_grid.setRowStretch(r, 0)
self.l_grid.setRowStretch(self.l_grid.rowCount(), 1)
if isinstance(init_val, str): def add_element_dialog(self):
input_widget = QLineEdit(init_val) """
elif isinstance(init_val, int): Prompt for a new key-value pair using a Dialog having a form
input_widget = QSpinBox() """
input_widget.setValue(init_val) dialog = QDialog(self)
elif isinstance(init_val, float): dialog.setWindowTitle("Add new field")
input_widget = QDoubleSpinBox() dialog.layout = QFormLayout()
input_widget.setValue(init_val) dialog.key_input = QLineEdit()
else: dialog.value_input = QLineEdit()
input_widget = QLineEdit(str(init_val)) dialog.layout.addRow("Key", dialog.key_input)
dialog.layout.addRow("Value", dialog.value_input)
self.layout.addWidget(input_widget, row, 1) # ok and cancel
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttons.accepted.connect(dialog.accept)
buttons.rejected.connect(dialog.reject)
dialog.layout.addRow(buttons)
dialog.setLayout(dialog.layout)
ret = dialog.exec()
if ret == QDialog.DialogCode.Accepted:
self.add_element(dialog.key_input.text(), dialog.value_input.text())
def add_element(self, key, init_val=""):
if key in self.ws_elements:
raise RuntimeError(f"Can not add field '{key}', it already exists")
if key == "":
raise RuntimeError(f"Can not add field with empty key")
row = self.l_grid.rowCount()
w_label = QLabel(key)
self.l_grid.addWidget(w_label, row, 0)
w_input= QLineEdit(str(init_val))
self.l_grid.addWidget(w_input, row, 1)
# Add a small button with an X from the theme # Add a small button with an X from the theme
remove_button = QPushButton("X") btn_remove = QPushButton("X")
remove_button.setFixedSize(20, 20) btn_remove.setFixedSize(20, 20)
remove_button.clicked.connect(lambda: self.remove_element(label_widget)) btn_remove.clicked.connect(lambda: self.remove_element(key))
self.layout.addWidget(remove_button, row, 2) self.l_grid.addWidget(btn_remove, row, 2)
def remove_element(self, label_widget): self.ws_elements[key] = (w_label, w_input, btn_remove)
# get position of label widget self.layout_changed()
# TODO Fix
row = self.layout.indexOf(label_widget) def remove_element(self, name):
# remove all widgets in row if name not in self.ws_elements:
for i in range(self.layout.columnCount()): raise RuntimeError(f"Can not remove field '{name}', it does not exist")
widget = self.layout.itemAtPosition(row, i).widget() for w in self.ws_elements[name]:
print(widget) self.l_grid.removeWidget(w)
self.layout.removeWidget(widget) del self.ws_elements[name]
self.layout_changed()
def set_from_dict(self, d: dict[str, str]):
"""
Set the widgets from the dictionary
Parameters
----------
d
Dictionary of key-value pairs
Returns
-------
None
"""
# first remove widgets not in new dict
for key in self.ws_elements.keys():
if key not in d:
self.remove_element(key)
self.update_from_dict(d)
def update_from_dict(self, d: dict[str, str]):
"""
Update widgets from the dictionary.
New values will be added, no values will be removed
Parameters
----------
d
Dictionary of key-value pairs
Returns
-------
None
"""
for key, value in d.items():
if key not in self.ws_elements:
self.add_element(key, value)
else:
self.ws_elements[key][1].setText(value)
def get_dict(self): def get_dict(self):
""" """
@ -78,8 +134,8 @@ class MetadataInput2(QWidget):
Dictionary of all key-values pairs Dictionary of all key-values pairs
""" """
d = {} d = {}
for row in range(self.layout.rowCount()): for name, (w_label, w_input, _) in self.ws_elements.items():
key = self.layout.itemAtPosition(row, 0).widget().text() key = w_label.text()
value = self.layout.itemAtPosition(row, 1).widget().text() value = w_input.text()
d[key] = value d[key] = value
return d return d