testexecutor-ui 0.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. testexecutor/VERSION +1 -0
  2. testexecutor/__init__.py +6 -0
  3. testexecutor/control/TestListenerApi.py +56 -0
  4. testexecutor/control/TestSuiteListener.py +249 -0
  5. testexecutor/control/__init__.py +0 -0
  6. testexecutor/model/GenericListModel.py +63 -0
  7. testexecutor/model/InstructionsModel.py +351 -0
  8. testexecutor/model/KeyValueModel.py +177 -0
  9. testexecutor/model/MultiTestWindowModel.py +184 -0
  10. testexecutor/model/ResultModel.py +314 -0
  11. testexecutor/model/TestSuiteControlModel.py +139 -0
  12. testexecutor/model/TestSuiteGroup.py +105 -0
  13. testexecutor/model/TestSuiteModel.py +301 -0
  14. testexecutor/model/__init__.py +0 -0
  15. testexecutor/model/selector/FilterGroupModel.py +90 -0
  16. testexecutor/model/selector/FilterModel.py +251 -0
  17. testexecutor/model/selector/MultiSelectDetails.py +106 -0
  18. testexecutor/model/selector/MultiSelectListModel.py +48 -0
  19. testexecutor/model/selector/__init__.py +0 -0
  20. testexecutor/ui/IdentificationWidget.qml +40 -0
  21. testexecutor/ui/InputWidget.qml +74 -0
  22. testexecutor/ui/InstructionWidget.qml +185 -0
  23. testexecutor/ui/KeyValueItem.qml +194 -0
  24. testexecutor/ui/KeyValueItemConfig.qml +41 -0
  25. testexecutor/ui/KeyValueList.qml +49 -0
  26. testexecutor/ui/MultiTestWidget.qml +48 -0
  27. testexecutor/ui/MultiTestWindow.qml +88 -0
  28. testexecutor/ui/ResultItem.qml +199 -0
  29. testexecutor/ui/ResultItemConfig.qml +46 -0
  30. testexecutor/ui/ResultList.qml +58 -0
  31. testexecutor/ui/TestSuiteConfig.qml +95 -0
  32. testexecutor/ui/TestSuiteController.qml +54 -0
  33. testexecutor/ui/TestSuiteWidget.qml +350 -0
  34. testexecutor/ui/selector/FilterItem.qml +75 -0
  35. testexecutor/ui/selector/FilterItemConfig.qml +24 -0
  36. testexecutor/ui/selector/FilterMultiSelectorItem.qml +169 -0
  37. testexecutor/ui/selector/FilterMultiSelectorItemConfig.qml +22 -0
  38. testexecutor/ui/selector/FilterMultiSelectorList.qml +50 -0
  39. testexecutor/ui/selector/HeaderConfig.qml +24 -0
  40. testexecutor/ui/selector/SectionConfig.qml +24 -0
  41. testexecutor/ui/selector/SectionDelegate.qml +85 -0
  42. testexecutor/ui/selector/SelectorHeader.qml +43 -0
  43. testexecutor/ui/selector/SuiteList.qml +150 -0
  44. testexecutor/ui/selector/SuiteSelector.qml +71 -0
  45. testexecutor/ui/selector/SuiteSelectorConfig.qml +38 -0
  46. testexecutor/ui/selector/TestConfig.qml +22 -0
  47. testexecutor/ui/selector/TestDelegate.qml +75 -0
  48. testexecutor/ui/te-64x64.ico +0 -0
  49. testexecutor_ui-0.6.1.dist-info/LICENSE +204 -0
  50. testexecutor_ui-0.6.1.dist-info/METADATA +27 -0
  51. testexecutor_ui-0.6.1.dist-info/NOTICE +3 -0
  52. testexecutor_ui-0.6.1.dist-info/RECORD +54 -0
  53. testexecutor_ui-0.6.1.dist-info/WHEEL +5 -0
  54. testexecutor_ui-0.6.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,251 @@
1
+ """
2
+
3
+ An object which provides filtering information.
4
+ Each filter has
5
+ - a list of allowable filter items
6
+ - a list of active filter items
7
+
8
+ Copyright (c) 2020- Sipke Vriend
9
+ Licensed under BSD-3-Clause, refer LICENSE
10
+ """
11
+
12
+ import threading
13
+ from PySide6.QtCore import QObject
14
+ from PySide6.QtCore import QStringListModel, QAbstractListModel, Qt, QModelIndex
15
+ from PySide6.QtCore import Signal, Property, Slot
16
+
17
+ """
18
+ class SelectionList(QStringListModel):
19
+ def __init__(self):
20
+ QStringListModel.__init__(self)
21
+
22
+ @Slot(str)
23
+ def prepend(self, data):
24
+ print("prepend", data)
25
+ if self.insertRow(0):
26
+ index = self.index(0)
27
+ self.setData(index, data)
28
+ """
29
+
30
+ class ItemList(QAbstractListModel):
31
+
32
+ ItemRole = Qt.UserRole
33
+ ItemKey = b"item"
34
+
35
+ _roles = {
36
+ ItemRole: ItemKey
37
+ }
38
+
39
+ def __init__(self, parent=None):
40
+ QAbstractListModel.__init__(self, parent)
41
+ self._datas = []
42
+
43
+ def addData(self, data):
44
+ index = QModelIndex()
45
+ row = self.rowCount()
46
+ self.beginInsertRows(index, row, row)
47
+ self._datas.append(data)
48
+ self.endInsertRows()
49
+ self.dataChanged.emit(row, row, self._roles)
50
+ self.changed.emit()
51
+
52
+ def setData(self, index, value, role):
53
+ ret = False
54
+ try:
55
+ data = self._datas[index.row()]
56
+ except IndexError:
57
+ return ret
58
+ if role == self.ItemRole:
59
+ self._datas[index.row()] = value
60
+ self.dataChanged.emit(index, index, {self.ItemRole: self.ItemKey})
61
+ self.changed.emit()
62
+ ret = True
63
+ return ret
64
+
65
+ def rowCount(self, parent=QModelIndex()):
66
+ return len(self._datas)
67
+
68
+ def data(self, index, role=Qt.DisplayRole):
69
+ try:
70
+ data = self._datas[index.row()]
71
+ except IndexError:
72
+ return None
73
+
74
+ if role == self.ItemRole:
75
+ return data
76
+
77
+ return None
78
+
79
+ def roleNames(self):
80
+ return self._roles
81
+
82
+ def removeRows(self, position, rows, parent=QModelIndex()):
83
+ self.beginRemoveRows(parent, position, position + rows - 1)
84
+ del self._datas[position:position + rows]
85
+ self.endRemoveRows()
86
+ self.dataChanged.emit(0, self.rowCount(), self._roles)
87
+ self.changed.emit()
88
+ #self.dataChanged.emit(0, self.rowCount(), self._roles)
89
+ return True
90
+
91
+ def getItems(self):
92
+ """
93
+ Returns dictionary with key:value pairs as string:string. Note the label is not included.
94
+ :return: Returns dictionary with key:value pairs
95
+ """
96
+ values = []
97
+ for row in range(len(self._datas)):
98
+ item = self._datas[row]
99
+ values.append(item)
100
+ return values
101
+
102
+ def updateItems(self, content_list):
103
+ """
104
+ Update the items to match data, ensuring we remove and add rather than dump the whole set and replace.
105
+ :param content_list: the new content to be added
106
+ :return:
107
+ """
108
+ rowCount = self.rowCount()
109
+ alreadyPresent = []
110
+ indexes_to_remove = []
111
+ for i in range(rowCount):
112
+ existing_index = self.index(i, 0)
113
+ existingItem = existing_index.data(self.ItemRole)
114
+ if existingItem not in content_list:
115
+ indexes_to_remove.insert(0, existing_index)
116
+ elif existingItem in content_list:
117
+ alreadyPresent.append(existingItem)
118
+ for index in indexes_to_remove:
119
+ self.removeRows(index.row(), 1)
120
+ for item in content_list:
121
+ if item not in alreadyPresent:
122
+ row = self.rowCount()
123
+ self.beginInsertRows(QModelIndex(), row, row)
124
+ self.addData(item)
125
+ self.endInsertRows()
126
+ #self.dataChanged.emit(0, self.rowCount(), self._roles)
127
+ self.dataChanged.emit(0, self.rowCount(), self._roles)
128
+ self.changed.emit()
129
+
130
+ @Slot()
131
+ def clear(self):
132
+ rowCount = self.rowCount(QModelIndex())
133
+ if rowCount:
134
+ self.beginRemoveRows(QModelIndex(), 0, rowCount - 1)
135
+ self._datas.clear()
136
+ self.endRemoveRows()
137
+ self.dataChanged.emit(0, self.rowCount(), self._roles)
138
+ self.changed.emit()
139
+
140
+ @Slot(str)
141
+ def prepend(self, data):
142
+ index = QModelIndex()
143
+ self.beginInsertRows(index, 0, 0)
144
+ self._datas.insert(0, data)
145
+ self.endInsertRows()
146
+ self.changed.emit()
147
+
148
+ @Slot(int)
149
+ def remove(self, i):
150
+ index = QModelIndex()
151
+ self.beginRemoveRows(index, i, i)
152
+ del self._datas[i]
153
+ self.endRemoveRows()
154
+ self.changed.emit()
155
+
156
+ changed = Signal()
157
+
158
+
159
+ class FilterModel(QObject):
160
+
161
+ def __init__(self, name=None, allowable=None):
162
+ QObject.__init__(self)
163
+ if not allowable:
164
+ allowable = []
165
+ self._proposed = QStringListModel()
166
+ self._proposed.setStringList(allowable)
167
+ self._selected = ItemList()
168
+ self._selected.changed.connect(self._onSelectedChanged, Qt.QueuedConnection)
169
+ self._name = name
170
+ self.lock = threading.RLock()
171
+
172
+ def _setproposed(self, proposed):
173
+ """ Setter for proposed Property """
174
+ changed = False
175
+ with self.lock:
176
+ if self._proposed != proposed:
177
+ self._proposed = proposed
178
+ changed = True
179
+ if changed:
180
+ self.proposed_changed.emit()
181
+
182
+ def _getproposed(self):
183
+ """
184
+ Getter for proposed Property
185
+ """
186
+ proposed = None
187
+ with self.lock:
188
+ proposed = self._proposed
189
+ return proposed
190
+
191
+ """
192
+ proposed is a list of possible filter values that can be used to control the suite filtering.
193
+ """
194
+ proposed_changed = Signal()
195
+ proposed = Property(QObject, _getproposed, _setproposed, notify=proposed_changed)
196
+
197
+ def _setselected(self, selected):
198
+ """ Setter for selected Property """
199
+ changed = False
200
+ with self.lock:
201
+ if self._selected != selected:
202
+ self._selected = selected
203
+ changed = True
204
+ if changed:
205
+ self.selected_changed.emit()
206
+
207
+ def _getselected(self):
208
+ """
209
+ Getter for selected Property
210
+ """
211
+ selected = None
212
+ with self.lock:
213
+ selected = self._selected
214
+ return selected
215
+
216
+ """
217
+ selected is a list of chosen filter values
218
+ """
219
+ selected_changed = Signal()
220
+ selected = Property(QObject, _getselected, _setselected, notify=selected_changed)
221
+
222
+ @Slot(str, object)
223
+ def _onSelectedChanged(self):
224
+ self.updated_selected.emit(self.name, self.selected)
225
+
226
+ updated_selected = Signal(str, QObject)
227
+
228
+ def _setname(self, name):
229
+ """ Setter for name Property """
230
+ changed = False
231
+ with self.lock:
232
+ if self._name != name:
233
+ self._name = name
234
+ changed = True
235
+ if changed:
236
+ self.name_changed.emit()
237
+
238
+ def _getname(self):
239
+ """
240
+ Getter for name Property
241
+ """
242
+ name = None
243
+ with self.lock:
244
+ name = self._name
245
+ return name
246
+
247
+ """
248
+ name is a list of chosen filter values
249
+ """
250
+ name_changed = Signal()
251
+ name = Property(str, _getname, _setname, notify=name_changed)
@@ -0,0 +1,106 @@
1
+ # Copyright 2021 Direkt Embedded Pty Ltd
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ import threading
17
+ from PySide6.QtCore import Signal
18
+ from PySide6.QtCore import Property
19
+ from PySide6.QtCore import QObject
20
+
21
+
22
+ class MultiSelectDetails(QObject):
23
+
24
+ def __init__(self, name, description, owner="default"):
25
+ QObject.__init__(self)
26
+ self.lock = threading.RLock()
27
+ self._name = name
28
+ self._owner = owner
29
+ self._selected = False
30
+ self._description = description
31
+
32
+ def _set_name(self, name):
33
+ """ Setter for name Property """
34
+ changed = False
35
+ with self.lock:
36
+ if self._name != name:
37
+ self._name = name
38
+ changed = True
39
+ if changed:
40
+ self.name_changed.emit()
41
+
42
+ def _get_name(self):
43
+ """ Getter for name Property """
44
+ with self.lock:
45
+ v = self._name
46
+ return v
47
+
48
+ name_changed = Signal()
49
+ name = Property(str, _get_name, _set_name, notify=name_changed)
50
+
51
+ def _set_owner(self, owner):
52
+ """ Setter for owner Property """
53
+ changed = False
54
+ with self.lock:
55
+ if self._owner != owner:
56
+ self._owner = owner
57
+ changed = True
58
+ if changed:
59
+ self.owner_changed.emit()
60
+
61
+ def _get_owner(self):
62
+ """ Getter for owner Property """
63
+ with self.lock:
64
+ v = self._owner
65
+ return v
66
+
67
+ owner_changed = Signal()
68
+ owner = Property(str, _get_owner, _set_owner, notify=owner_changed)
69
+
70
+ def _set_description(self, description):
71
+ """ Setter for description Property """
72
+ changed = False
73
+ with self.lock:
74
+ if self._description != description:
75
+ self._description = description
76
+ changed = True
77
+ if changed:
78
+ self.description_changed.emit()
79
+
80
+ def _get_description(self):
81
+ """ Getter for description Property """
82
+ with self.lock:
83
+ v = self._description
84
+ return v
85
+
86
+ description_changed = Signal()
87
+ description = Property(str, _get_description, _set_description, notify=description_changed)
88
+
89
+ def _set_selected(self, selected):
90
+ """ Setter for selected Property """
91
+ changed = False
92
+ with self.lock:
93
+ if self._selected != selected:
94
+ self._selected = selected
95
+ changed = True
96
+ if changed:
97
+ self.selected_changed.emit()
98
+
99
+ def _get_selected(self):
100
+ """ Getter for selected Property """
101
+ with self.lock:
102
+ v = self._selected
103
+ return v
104
+
105
+ selected_changed = Signal()
106
+ selected = Property(bool, _get_selected, _set_selected, notify=selected_changed)
@@ -0,0 +1,48 @@
1
+ # Copyright 2021 Direkt Embedded Pty Ltd
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ A class based on GenericListModel for use in a list with selected and owner as a properties.
17
+ Where owner can be used as the listview section and selected used to define an item is selected or not.
18
+ These properties can be accessed within qml models through model.item.<property_name>
19
+ """
20
+
21
+ from PySide6.QtCore import Slot
22
+ from ..GenericListModel import GenericListModel
23
+ from .MultiSelectDetails import MultiSelectDetails
24
+
25
+
26
+ class MultiSelectListModel(GenericListModel):
27
+
28
+ def __init__(self, parent=None):
29
+ GenericListModel.__init__(self, parent)
30
+
31
+ @Slot(str, result=int)
32
+ def selected_count(self, owner):
33
+ count = 0
34
+ for item in self._data:
35
+ if item.selected and item.owner == owner:
36
+ count = count + 1
37
+ return count
38
+
39
+ def appendChild(self, name, description, owner):
40
+ child = MultiSelectDetails(name, description, owner)
41
+ self.add(child)
42
+
43
+ def selectedItems(self):
44
+ selected_items = []
45
+ for item in self._data:
46
+ if item.selected:
47
+ selected_items.append(item)
48
+ return selected_items
File without changes
@@ -0,0 +1,40 @@
1
+ /*
2
+ * Copyright 2020 Direkt, Australia
3
+ * Copyright 2021 Direkt Embedded Pty Ltd
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ import QtQuick
19
+ import QtQuick.Layouts
20
+ import QtQuick.Controls
21
+
22
+ Item {
23
+ id: identificationWidget
24
+ property var identifiers
25
+ property var color: "#e5e2e2"
26
+ property alias itemConfig: identificationList.itemConfig
27
+
28
+ ColumnLayout {
29
+ id: identificationWidgetLayout
30
+ anchors.fill: parent
31
+
32
+ KeyValueList {
33
+ id: identificationList
34
+ keyvalues: identifiers
35
+ Layout.fillHeight: true
36
+ Layout.fillWidth: true
37
+ }
38
+ }
39
+ }
40
+
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright 2022 Direkt Embedded Pty Ltd
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import QtQuick
18
+ import QtQuick.Layouts
19
+ import QtQuick.Controls
20
+
21
+ Item {
22
+ id: inputWidget
23
+ property var color: "#e5e2e2"
24
+ property string inputid
25
+ property bool hidden: false
26
+
27
+ ColumnLayout {
28
+ id: inputWidgetLayout
29
+ anchors.fill: parent
30
+
31
+ Item {
32
+ // The Item wrapper is to allow TextField pixelSize to reference the parents height.
33
+ Layout.preferredHeight: parent.height
34
+ Layout.minimumHeight: parent.height * 0.15
35
+ Layout.maximumHeight: parent.height
36
+ Layout.fillWidth: true
37
+
38
+ TextField {
39
+ id: singleInputField
40
+ text: ""
41
+ topPadding: 0
42
+ bottomPadding: 0
43
+ anchors.fill: parent
44
+ horizontalAlignment: Text.AlignHCenter
45
+ placeholderText: "Input"
46
+ font.pixelSize: parent.height * 0.7
47
+ echoMode: inputWidget.hidden ? TextInput.Password : TextInput.Normal
48
+ // onAccepted is called when 'return' is entered.
49
+ onAccepted: {
50
+ if (inputWidget.inputid === singleInputField.text) {
51
+ inputWidget.inputid = ""
52
+ }
53
+ inputWidget.inputid = singleInputField.text
54
+ singleInputField.text = ""
55
+ }
56
+ // Whenever a new line is detected we want to update input it also so the caller gets the scanned input
57
+ onTextEdited: {
58
+ var str = singleInputField.text
59
+ if (str.charAt(str.length - 1) === '\n') {
60
+ if (inputWidget.inputid === singleInputField.text) {
61
+ inputWidget.inputid = ""
62
+ }
63
+ inputWidget.inputid = singleInputField.text
64
+ singleInputField.text = ""
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ function inputFocus() {
71
+ singleInputField.forceActiveFocus();
72
+ }
73
+ }
74
+