forked from ScopeFoundry/ScopeFoundry
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoperations.py
More file actions
115 lines (86 loc) · 3.55 KB
/
operations.py
File metadata and controls
115 lines (86 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from dataclasses import dataclass, field
from typing import Callable, Dict, List, Tuple
from qtpy import QtCore, QtGui, QtWidgets
from ScopeFoundry.dynamical_widgets.tools import Tools
from ScopeFoundry.helper_funcs import filter_with_patterns
class OperationsQObject(QtCore.QObject):
added = QtCore.Signal(str)
removed = QtCore.Signal(str)
@dataclass
class Operation:
name: str
func: Callable
description: str = field(default="")
icon_path: str = field(default="")
path: str = field(default="")
def new_button(self) -> QtWidgets.QPushButton:
op_button = QtWidgets.QPushButton(self.name)
op_button.setObjectName(self.name)
op_button.clicked.connect(lambda checked, f=self.func: f())
op_button.setToolTip(f"<b>{self.path}</b><p><p>{self.description}")
if isinstance(self.icon_path, QtGui.QIcon):
op_button.setIcon(self.icon_path)
elif self.icon_path:
op_button.setIcon(QtGui.QIcon(str(self.icon_path)))
return op_button
class Operations:
def __init__(self, path="") -> None:
self.q_object = OperationsQObject()
self._widgets_managers_: List[OperationWidgetsManager] = []
self._operations: Dict[str, Operation] = {}
self.path = path
def new(
self, name: str, func: Callable, description: str = "", icon_path: str = ""
) -> Operation:
return self.add(
Operation(name, func, description, icon_path, f"{self.path}/{name}")
)
def add(self, operation: Operation) -> Operation:
assert operation.name not in self._operations
self._operations[operation.name] = operation
self.q_object.added.emit(operation.name)
return operation
def remove(self, name: str) -> None:
if name not in self._operations:
return
del self._operations[name]
self.q_object.removed.emit(name)
def get(self, name: str) -> Operation:
return self._operations[name]
def new_button(self, name: str) -> QtWidgets.QPushButton:
return self._operations[name].new_button()
def keys(self) -> List[str]:
return self._operations.keys()
def __contains__(self, k: str) -> bool:
return self._operations.__contains__(k)
def __iter__(self) -> iter:
return self._operations.__iter__()
# For backwards compatbility, returning op_func rather the Operation objects.
def items(self) -> List[Tuple[str, Callable]]:
return ((k, v.func) for k, v in self._operations.items())
def __getitem__(self, key: str) -> Callable:
return self._operations[key].func
class OperationWidgetsManager:
def __init__(self, operations: Operations, tools: Tools) -> None:
self.operations = operations
self.tools = tools
operations.q_object.added.connect(self.add)
operations.q_object.removed.connect(self.remove)
self.widgets = {}
self.update()
def add(self, name: str) -> None:
self.update()
def remove(self, name: str) -> None:
widget = self.widgets.pop(name, None)
if widget is None:
return
self.tools.remove_from_layout(name, widget)
def update(self) -> None:
for op_name in filter_with_patterns(
self.operations.keys(), self.tools.include, self.tools.exclude
):
if op_name in self.widgets.keys():
continue
op_button = self.operations.new_button(op_name)
self.widgets[op_name] = op_button
self.tools.add_to_layout(None, op_button)