Skip to content
This repository was archived by the owner on Nov 6, 2025. It is now read-only.
4 changes: 2 additions & 2 deletions src/pymodaq_gui/examples/icons.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import sys

from qtpy.QtWidgets import (QApplication, QGridLayout, QPushButton, QStyle,
from PyQt6.QtWidgets import (QApplication, QGridLayout, QPushButton, QStyle,
QWidget, QVBoxLayout)
from qtpy.QtGui import QIcon
from PyQt6.QtGui import QIcon


class Icons():
Expand Down
13 changes: 7 additions & 6 deletions src/pymodaq_gui/managers/action_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __repr__(self):

def addaction(name: str = '', icon_name: Union[str, Path, QtGui.QIcon]= '', tip='', checkable=False, checked=False,
slot: Callable = None, toolbar: QtWidgets.QToolBar = None,
menu: QtWidgets.QMenu = None, visible=True, shortcut=None,
menu: QtWidgets.QMenu = None, visible=True, shortcut: Union[str, QtCore.Qt.Key]=None,
enabled=True):
"""Create a new action and add it eventually to a toolbar and a menu

Expand All @@ -87,7 +87,7 @@ def addaction(name: str = '', icon_name: Union[str, Path, QtGui.QIcon]= '', tip=
a menu where action should be added.
visible: bool
display or not the action in the toolbar/menu
shortcut: str
shortcut: str or Qt.Key
a string defining a shortcut for this action
enabled: bool
set the enabled state
Expand Down Expand Up @@ -240,12 +240,12 @@ def __init__(self, toolbar: QtWidgets.QToolBar = None, menu: QtWidgets.QMenu = N
@property
def _menu(self) -> QtWidgets.QMenu:
"""Get the default menu (backward compatibility)"""
return self._menus.get('_default')
return self._menus.get('_default', None)

@property
def _toolbar(self) -> QtWidgets.QToolBar:
"""Get the default toolbar (backward compatibility)"""
return self._toolbars.get('_default')
return self._toolbars.get('_default', None)

def setup_actions(self):
"""Method where to create actions to be subclassed. Mandatory
Expand All @@ -266,8 +266,9 @@ def setup_actions(self):

def add_action(self, short_name: str = '', name: str = '', icon_name: Union[str, Path, QtGui.QIcon] = '', tip='',
checkable=False,
checked=False, toolbar: Union[str, QtWidgets.QToolBar, None]=None, menu: Union[str, QtWidgets.QMenu, None] = None,
visible=True, shortcut=None, auto_toolbar=True, auto_menu=True,
checked=False, toolbar: Union[str, QtWidgets.QToolBar, None]=None,
menu: Union[str, QtWidgets.QMenu, None] = None,
visible=True, shortcut: Union[str, QtCore.Qt.Key]=None, auto_toolbar=True, auto_menu=True,
enabled=True):
"""Create a new action and add it to toolbar and menu

Expand Down
5 changes: 2 additions & 3 deletions src/pymodaq_gui/managers/parameter_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ def __init__(
settings_name: Optional[str] = None,
action_list: tuple = ("search", "save", "update", "load"),
tree: ParameterTree = None

):
self._current_filter_text = ""
if settings_name is None:
Expand Down Expand Up @@ -268,12 +267,12 @@ def __init__(
)

@property
def settings_tree(self):
def settings_tree(self) -> QtWidgets.QWidget:
"""QWidget: The main widget containing the parameter tree and toolbar."""
return self._settings_tree.widget

@property
def tree(self):
def tree(self) -> ParameterTree:
"""ParameterTree: The underlying parameter tree widget."""
return self._settings_tree.tree

Expand Down
67 changes: 40 additions & 27 deletions src/pymodaq_gui/parameter/ioxml.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from typing import Union
from pathlib import Path

Expand All @@ -13,6 +15,9 @@
from pyqtgraph.parametertree.Parameter import PARAM_TYPES, PARAM_NAMES


VALID_FOR_CONFIGURATION = 'valid_for_configuration'


def walk_parameters_to_xml(parent_elt=None, param=None):
"""
To convert a parameter object (and children) to xml data tree.
Expand Down Expand Up @@ -166,6 +171,9 @@ def dict_from_param(param):
readonly = '0'
opts.update(dict(readonly=readonly))

if VALID_FOR_CONFIGURATION in param.opts:
opts.update({VALID_FOR_CONFIGURATION: '1' if param.opts[VALID_FOR_CONFIGURATION] else '0'})

# if 'limits' in param.opts:
# values = str(param.opts['limits'])
# opts.update(dict(values=values))
Expand Down Expand Up @@ -258,12 +266,22 @@ def elt_to_dict(el):
readonly = bool(int(el.get('readonly')))
param.update(dict(readonly=readonly))

if VALID_FOR_CONFIGURATION in el.attrib.keys():
valid = bool(int(el.get(VALID_FOR_CONFIGURATION)))
param.update({VALID_FOR_CONFIGURATION: valid})

if 'show_pb' in el.attrib.keys():
show_pb = bool(int(el.get('show_pb')))
else:
show_pb = False
param.update(dict(show_pb=show_pb))

if 'readonly' not in el.attrib.keys():
readonly = False
else:
readonly = bool(int(el.get('readonly')))
param.update(dict(readonly=readonly))

if 'filetype' in el.attrib.keys():
filetype = bool(int(el.get('filetype')))
param.update(dict(filetype=filetype))
Expand Down Expand Up @@ -423,6 +441,7 @@ def walk_xml_to_parameter(params=[], XML_elt=None):
raise e
return params


def set_dict_from_el(el):
"""Convert an element into a dict
----------
Expand Down Expand Up @@ -513,49 +532,43 @@ def XML_file_to_parameter(file_name: Union[str, Path]) -> list:


def XML_string_to_parameter(xml_string):
""" Convert a xml string into a list of dict for initialize pyqtgraph parameter object.
"""
Convert a xml string into a list of dict for initialize pyqtgraph parameter object.

=============== =========== ================================
**Parameters** **Type** **Description**

xml_string string the xml string to be converted
=============== =========== ================================
root = ET.fromstring(xml_string)
params = walk_xml_to_parameter(params=[], XML_elt=root)
return params

Returns
-------
params: a parameter list of dict to init a parameter

See Also
--------
walk_parameters_to_xml

Examples
--------
def xml_string_to_parameter_dict(xml_string) -> dict:
"""
Convert a xml string into a dict to initialize pyqtgraph parameter object.
"""
root = ET.fromstring(xml_string)
tree = ET.ElementTree(root)

# tree.write('test.xml')
params = walk_xml_to_parameter(params=[], XML_elt=root)
param_dict = set_dict_from_el(root)
if len(root) > 0:
param_dict['children'] = walk_xml_to_parameter(params=[], XML_elt=root)

return params
return param_dict

def xml_string_to_parameter(xml_string) -> Parameter:
return Parameter.create(**xml_string_to_parameter_dict(xml_string))


def XML_string_to_pobject(xml_string) -> Parameter:
"""
return a Parameter object from its *translated* version as a XML string
return a Parameter object from its deserialized version from a XML string

Deprecated as not symetric with parameter_to_xml_string

Parameters
----------
xml_string: (str) string representation of a Parameter Object

Returns
-------
Parameter

See Also
--------
parameter_to_xml_string
"""
return Parameter.create(name='settings', type='group',
children=XML_string_to_parameter(xml_string))



9 changes: 4 additions & 5 deletions src/pymodaq_gui/parameter/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List, Tuple, Any, Union
from dataclasses import Field, fields
from typing import List, Tuple, Union
import numpy as np
from collections import OrderedDict
from dataclasses import dataclass
from pymodaq_utils.utils import find_keys_from_val
from pymodaq_utils.serialize.factory import SerializableFactory, SerializableBase
from pymodaq_gui.parameter import ioxml
Expand Down Expand Up @@ -75,8 +73,8 @@ def deserialize(cls,
"""
path, remaining_bytes = ser_factory.get_apply_deserializer(bytes_str, False)
param_as_xml, remaining_bytes = ser_factory.get_apply_deserializer(remaining_bytes, False)
param_dict = ioxml.XML_string_to_parameter(param_as_xml)
param_obj = Parameter.create(**param_dict[0])
param_dict = ioxml.xml_string_to_parameter_dict(param_as_xml)
param_obj = Parameter.create(**param_dict)
return ParameterWithPath(param_obj, path), remaining_bytes


Expand Down Expand Up @@ -472,3 +470,4 @@ def scroll_linear(scroll_val, min_val, max_val):

d['readonly'] = False
print(parent[0]['children'][1]['children'])

18 changes: 16 additions & 2 deletions src/pymodaq_gui/utils/custom_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pymodaq_gui.utils.dock import DockArea, Dock
from pymodaq_gui.managers.action_manager import ActionManager
from pymodaq_gui.managers.parameter_manager import ParameterManager
from pymodaq_gui.parameter import ParameterTree


class CustomApp(QObject, ActionManager, ParameterManager):
Expand Down Expand Up @@ -38,10 +39,11 @@ class CustomApp(QObject, ActionManager, ParameterManager):
log_signal = QtCore.Signal(str)
params = []

def __init__(self, parent: Union[DockArea, QtWidgets.QMainWindow, QtWidgets.QWidget] = None):
def __init__(self, parent: Union[DockArea, QtWidgets.QMainWindow, QtWidgets.QWidget] = None,
tree: ParameterTree = None):
QObject.__init__(self)
ActionManager.__init__(self)
ParameterManager.__init__(self)
ParameterManager.__init__(self, tree=tree)

if not (isinstance(parent, DockArea) or
isinstance(parent, QtWidgets.QMainWindow) or
Expand Down Expand Up @@ -82,6 +84,18 @@ def setup_ui(self):

self.connect_things()

self.do_things_after_ui_setup()

def quit_fun(self):
"""Method to be subclassed in order to define a custom quit function
"""
self.mainwindow.close()

def do_things_after_ui_setup(self):
"""Non mandatory method to be subclassed in order to do things after the UI setup
"""
pass

def setup_docks(self):
"""Mandatory method to be subclassed to setup the docks layout

Expand Down
4 changes: 4 additions & 0 deletions src/pymodaq_gui/utils/widgets/qled.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ def LED_Clicked(self):
else:
self.set_as_true()
self.value_changed.emit(not self.state)

def setReadOnly(self, isreadonly: bool):
self.clickable = not isreadonly

3 changes: 2 additions & 1 deletion src/pymodaq_gui/utils/widgets/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ def insert_data(self, row, data):
def insertRows(self, row, count, parent):
self.beginInsertRows(QtCore.QModelIndex(), row, row + count - 1)
for ind in range(count):
self._data.insert(row + ind, self.data_tmp)
self._data.insert(row + ind, self.data_tmp[ind] if
(hasattr(self.data_tmp, '__len__') and len(self.data_tmp) == count) else self.data_tmp)
self._checked.insert(row + ind, False)
self.endInsertRows()
return True
Expand Down
Loading