Skip to content

Commit

Permalink
Refactor config group widget to config groups editor
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 committed Oct 14, 2024
1 parent ade5f2f commit 9058d63
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 48 deletions.
15 changes: 0 additions & 15 deletions examples/config_group_widget.py

This file was deleted.

21 changes: 21 additions & 0 deletions examples/config_groups_editor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pymmcore_plus import CMMCorePlus
from qtpy.QtWidgets import QApplication, QPushButton
from rich import print

from pymmcore_widgets import ConfigGroupsEditor

core = CMMCorePlus().instance()
core.loadSystemConfiguration()

app = QApplication([])

ocd = ConfigGroupsEditor.create_from_core(core)
ocd.resize(1080, 860)
ocd.setCurrentGroup("Channel")
ocd.show()

btn = QPushButton("Print Current Data")
btn.clicked.connect(lambda: print(ocd.data()))
ocd.layout().children()[0].addWidget(btn) # Add button to the layout

app.exec()
4 changes: 2 additions & 2 deletions src/pymmcore_widgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"MDAWidget",
"ObjectivesPixelConfigurationWidget",
"ObjectivesWidget",
"ConfigGroupWidget",
"ConfigGroupsEditor",
"PixelConfigurationWidget",
"PositionTable",
"PresetsWidget",
Expand All @@ -46,7 +46,7 @@

from ._install_widget import InstallWidget
from .config_presets import (
ConfigGroupWidget,
ConfigGroupsEditor,
GroupPresetTableWidget,
ObjectivesPixelConfigurationWidget,
PixelConfigurationWidget,
Expand Down
4 changes: 2 additions & 2 deletions src/pymmcore_widgets/config_presets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Widgets related to configuration groups and presets."""

from ._config_group_widget import ConfigGroupWidget
from ._config_groups_editor import ConfigGroupsEditor
from ._group_preset_widget._group_preset_table_widget import GroupPresetTableWidget
from ._objectives_pixel_configuration_widget import ObjectivesPixelConfigurationWidget
from ._pixel_configuration_widget import PixelConfigurationWidget
Expand All @@ -9,5 +9,5 @@
"GroupPresetTableWidget",
"ObjectivesPixelConfigurationWidget",
"PixelConfigurationWidget",
"ConfigGroupWidget",
"ConfigGroupsEditor",
]
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
QGroupBox,
QHBoxLayout,
QLabel,
QPushButton,
QSpacerItem,
QSplitter,
QVBoxLayout,
Expand Down Expand Up @@ -43,7 +42,7 @@ def _copy_named_obj(obj: T, new_name: str) -> T:
return obj

Check warning on line 42 in src/pymmcore_widgets/config_presets/_config_groups_editor.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_config_groups_editor.py#L40-L42

Added lines #L40 - L42 were not covered by tests


class ConfigGroupWidget(QWidget):
class ConfigGroupsEditor(QWidget):
"""Widget for managing configuration groups and presets.
This is a high level widget that allows the user to manage all of the configuration
Expand Down Expand Up @@ -71,9 +70,6 @@ def __init__(
ConfigPreset, clone_function=_copy_named_obj, parent=self, base_key="Config"
)

self.btn_activate = QPushButton("Set Active")
self.presets.btn_layout.insertWidget(3, self.btn_activate)

# Groups -----------------------------------------------------
self._light_path_group = _LightPathGroupBox(self)
self._cam_group = _CameraGroupBox(self)
Expand Down Expand Up @@ -116,13 +112,21 @@ def __init__(

self.groups.currentKeyChanged.connect(self._on_current_group_changed)
if data is not None:
self.groups.setRoot({group.name: group for group in data})
self.setData(data)

Check warning on line 115 in src/pymmcore_widgets/config_presets/_config_groups_editor.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_config_groups_editor.py#L113-L115

Added lines #L113 - L115 were not covered by tests

# after groups.setRoot to prevent a bunch of stuff when setting initial data
self.presets.currentKeyChanged.connect(self._update_gui_from_model)

Check warning on line 118 in src/pymmcore_widgets/config_presets/_config_groups_editor.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_config_groups_editor.py#L118

Added line #L118 was not covered by tests

# Public API -------------------------------------------------------

def setData(self, data: Iterable[ConfigGroup]) -> None:
"""Replace all data with the given collection of ConfigGroup objects."""
self.groups.setRoot({group.name: group for group in data})

Check warning on line 124 in src/pymmcore_widgets/config_presets/_config_groups_editor.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_config_groups_editor.py#L124

Added line #L124 was not covered by tests

def data(self) -> Collection[ConfigGroup]:
"""Return the current data as a collection of ConfigGroup objects."""
return deepcopy(list(self.groups.root().values()))

Check warning on line 128 in src/pymmcore_widgets/config_presets/_config_groups_editor.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_config_groups_editor.py#L128

Added line #L128 was not covered by tests

def setCurrentGroup(self, group: str) -> None:
"""Set the current group by name.
Expand Down Expand Up @@ -179,7 +183,7 @@ def setCurrentSettings(self, settings: Iterable[Setting]) -> None:
@classmethod
def create_from_core(
cls, core: CMMCorePlus, parent: QWidget | None = None
) -> ConfigGroupWidget:
) -> ConfigGroupsEditor:
"""Create a new instance and update it with the given core instance."""
groups = ConfigGroup.all_config_groups(core)
self = cls(data=groups.values(), parent=parent)
Expand Down
42 changes: 20 additions & 22 deletions src/pymmcore_widgets/config_presets/_unique_name_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import warnings
from copy import deepcopy
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, overload
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar

from qtpy.QtCore import Qt, Signal
from qtpy.QtWidgets import (
Expand All @@ -19,29 +19,10 @@
if TYPE_CHECKING:
from collections.abc import Iterable, Mapping, MutableMapping

from PyQt6.QtGui import QKeyEvent

class UniqueListWidget(QListWidget):
@overload
def addItem(self, item: QListWidgetItem | None, /) -> None: ...
@overload
def addItem(self, label: str | None, /) -> None: ...
def addItem(self, item: QListWidgetItem | str | None) -> None:
if item is None:
item = QListWidgetItem()
txt = item.text() if isinstance(item, QListWidgetItem) else item
for i in self._iter_texts():
if i == txt:
raise ValueError(f"Item with text {txt!r} already exists.")
super().addItem(item)

def addItems(self, labels: Iterable[str | None]) -> None:
for label in labels:
self.addItem(label)

def _iter_texts(self) -> Iterable[str]:
for i in range(self.count()):
if item := self.item(i):
yield item.text()
class UniqueListWidget(QListWidget): ...


class UniqueKeyList(QWidget):
Expand Down Expand Up @@ -112,6 +93,7 @@ def __init__(
self._list_widget.setEditTriggers(

Check warning on line 93 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L92-L93

Added lines #L92 - L93 were not covered by tests
QListWidget.EditTrigger.DoubleClicked
| QListWidget.EditTrigger.SelectedClicked
| QListWidget.EditTrigger.EditKeyPressed
)

self.btn_new = QPushButton("New")
Expand Down Expand Up @@ -269,6 +251,22 @@ def setBaseKey(self, base_key: str) -> None:
"""
self._base_key = base_key

Check warning on line 252 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L252

Added line #L252 was not covered by tests

# Overrides ---------------------------------------------------

def keyPressEvent(self, a0: QKeyEvent | None) -> None:
if a0 is None:
return
key = a0.key()
if key in (Qt.Key.Key_Delete, Qt.Key.Key_Backspace):
self._remove_current()

Check warning on line 261 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L257-L261

Added lines #L257 - L261 were not covered by tests
# command-D or control-D should duplicate the current item
elif (

Check warning on line 263 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L263

Added line #L263 was not covered by tests
key == Qt.Key.Key_D and a0.modifiers() & Qt.KeyboardModifier.ControlModifier
):
self._duplicate_current()

Check warning on line 266 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L266

Added line #L266 was not covered by tests
else:
super().keyPressEvent(a0)

Check warning on line 268 in src/pymmcore_widgets/config_presets/_unique_name_list.py

View check run for this annotation

Codecov / codecov/patch

src/pymmcore_widgets/config_presets/_unique_name_list.py#L268

Added line #L268 was not covered by tests

# PRIVATE ---------------------------------------------------

def _iter_texts(self) -> Iterable[str]:
Expand Down

0 comments on commit 9058d63

Please sign in to comment.