Source code for qudi.tools.config_editor.tree_widgets

# -*- coding: utf-8 -*-
"""

"""

__all__ = [
    'AvailableModulesTreeWidget',
    'SelectedModulesTreeWidget',
    'ConfigModulesTreeWidget',
]

from re import compile
from PySide2 import QtCore, QtWidgets, QtGui
from typing import Optional, Iterable, Mapping, Tuple, Dict, List, Sequence


[docs] class AvailableModulesTreeWidget(QtWidgets.QTreeWidget): """ """
[docs] def __init__( self, modules: Optional[Iterable[str]] = None, parent: Optional[QtWidgets.QWidget] = None, ) -> None: super().__init__(parent=parent) self.setColumnCount(2) self.setHeaderLabels(('Base', 'module.Class')) self.setSelectionMode(self.ExtendedSelection) self.setEditTriggers(self.EditTrigger.NoEditTriggers) self.setDragEnabled(True) self.top_level_items = dict() self.clear_modules() if modules is not None: self.set_modules(sorted(modules))
@property def modules(self) -> List[str]: modules = list() for base, top_item in self.top_level_items.items(): items = [top_item.child(index) for index in range(top_item.childCount())] modules.extend(f'{base}.{it.text(1)}' for it in items) return modules
[docs] def set_modules(self, modules: Iterable[str]) -> None: # Clear all modules self._clear_modules() # Add new modules for module in modules: self._add_module(module) # Resize columns self.resize_columns_to_content()
[docs] def add_module(self, module: str) -> None: self._add_module(module) self.resize_columns_to_content()
def _add_module(self, module: str) -> None: base, module_class = module.split('.', 1) item = QtWidgets.QTreeWidgetItem() item.setText(1, module_class) item.setFlags( QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled ) self.top_level_items[base].addChild(item)
[docs] def remove_module(self, module: str) -> None: self._remove_module(module) self.resize_columns_to_content()
def _remove_module(self, module: str) -> None: base, module_class = module.split('.', 1) top_level_item = self.top_level_items[base] for index in range(top_level_item.childCount()): child = top_level_item.child(index) if child.text(1) == module_class: top_level_item.removeChild(child) break
[docs] def clear_modules(self) -> None: self._clear_modules() self.resize_columns_to_content()
def _clear_modules(self) -> None: self.clear() for disp_base in ('GUI', 'Logic', 'Hardware'): item = QtWidgets.QTreeWidgetItem() item.setFlags(QtCore.Qt.ItemIsEnabled) item.setText(0, disp_base) self.addTopLevelItem(item) item.setExpanded(True) self.top_level_items[disp_base.lower()] = item
[docs] def resize_columns_to_content(self) -> None: for i in range(self.columnCount()): self.resizeColumnToContents(i)
[docs] def mimeData(self, items: Sequence) -> QtCore.QMimeData: """Add text to mime data. This is the quick (but not necessarily dirty) way.""" texts = tuple(f'{it.parent().text(0).lower()}.{it.text(1)}' for it in items) mime = super().mimeData(items) mime.setText(';'.join(texts)) return mime
[docs] class ConfigModulesTreeWidget(QtWidgets.QTreeWidget): """ """
[docs] def __init__( self, named_modules: Optional[Mapping[str, str]] = None, unnamed_modules: Optional[Iterable[str]] = None, parent: Optional[QtWidgets.QWidget] = None, ) -> None: super().__init__(parent=parent) self.setDragEnabled(False) self.setDropIndicatorShown(False) self.setAcceptDrops(True) self.setColumnCount(3) self.setHeaderLabels(['Base', 'Name', 'module.Class']) self.setSelectionMode(self.SingleSelection) self.setEditTriggers(self.EditTrigger.NoEditTriggers) self.itemDoubleClicked.connect(self._edit_item_column) self.top_level_items = dict() self.set_modules(named_modules, unnamed_modules) self._valid_foreground = next(iter(self.top_level_items.values())).foreground(0) self._name_regex = compile(r'^[a-zA-Z_]+[a-zA-Z0-9_]*$')
@property def modules(self) -> Tuple[Dict[str, str], List[str]]: named_modules = dict() unnamed_modules = list() for base, top_item in self.top_level_items.items(): items = [top_item.child(index) for index in range(top_item.childCount())] for it in items: name = it.text(1) module = f'{base}.{it.text(2)}' if self.is_valid_name(name) and name not in named_modules: named_modules[name] = module else: unnamed_modules.append(module) return named_modules, unnamed_modules
[docs] def set_modules( self, named_modules: Optional[Mapping[str, str]] = None, unnamed_modules: Optional[Iterable[str]] = None, ) -> None: if named_modules is None: named_modules = dict() if unnamed_modules is None: unnamed_modules = list() # Clear all modules self._clear_modules() # Add new modules for name, module in named_modules.items(): self._add_module(module, name) for module in unnamed_modules: self._add_module(module) # Resize columns self.resize_columns_to_content()
[docs] def add_module(self, module: str, name: Optional[str] = None) -> None: self._add_module(module, name) self.resize_columns_to_content()
def _add_module(self, module: str, name: Optional[str] = None) -> None: base, module_class = module.split('.', 1) item = QtWidgets.QTreeWidgetItem() item.setText(1, '<enter unique name>' if name is None else name) item.setText(2, module_class) item.setFlags( QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable ) self.top_level_items[base].addChild(item)
[docs] def remove_module(self, name: str) -> None: self._remove_module(name) self.resize_columns_to_content()
def _remove_module(self, name: str) -> None: found = False for base, top_item in self.top_level_items.items(): for index in range(top_item.childCount()): child = top_item.child(index) if child.text(1) == name: top_item.removeChild(child) found = True break if found: break
[docs] def clear_modules(self) -> None: self._clear_modules() self.resize_columns_to_content()
def _clear_modules(self) -> None: self.clear() for disp_base in ['GUI', 'Logic', 'Hardware']: item = QtWidgets.QTreeWidgetItem() item.setFlags(QtCore.Qt.ItemIsEnabled) item.setText(0, disp_base) self.addTopLevelItem(item) item.setExpanded(True) self.top_level_items[disp_base.lower()] = item
[docs] def resize_columns_to_content(self) -> None: for i in range(self.columnCount()): self.resizeColumnToContents(i)
[docs] def is_valid_name(self, name: str) -> bool: set_names = list() for base, top_item in self.top_level_items.items(): items = [top_item.child(index) for index in range(top_item.childCount())] set_names.extend(it.text(1) for it in items) return self._name_regex.match(name) is not None and set_names.count(name) <= 1
@QtCore.Slot(QtWidgets.QTreeWidgetItem, int) def _edit_item_column(self, item: QtWidgets.QTreeWidgetItem, column: int) -> None: if item and column == 1 and item.parent() is not None: self.editItem(item, column)
[docs] class SelectedModulesTreeWidget(ConfigModulesTreeWidget): """ """
[docs] def dropEvent(self, event: QtGui.QDropEvent) -> None: if isinstance(event.source(), AvailableModulesTreeWidget): full_text = event.mimeData().text() for module in full_text.split(';'): self._add_module(module) self.resize_columns_to_content() event.accept() else: event.ignore()
[docs] def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: if event.key() == QtCore.Qt.Key_Delete: for item in self.selectedItems(): if item.parent() is not None: item.parent().removeChild(item) event.accept() else: super().keyPressEvent(event)