NamespaceWidget.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 2
Metric Value
c 4
b 1
f 2
dl 0
loc 21
rs 9.3142
cc 1
1
import logging
2
3
from PyQt5.QtCore import pyqtSignal, Qt, QObject
4
from PyQt5.QtGui import QStandardItemModel, QStandardItem
5
from PyQt5.QtWidgets import QMenu, QAction, QStyledItemDelegate
6
7
from opcua import ua
8
9
from uawidgets.utils import trycatchslot
10
11
12
logger = logging.getLogger(__name__)
13
14
15
class NamespaceWidget(QObject):
16
17
    error = pyqtSignal(Exception)
18
19
    def __init__(self, view):
20
        QObject.__init__(self, view)
21
        self.view = view
22
        self.model = QStandardItemModel()
23
        self.view.setModel(self.model)
24
        delegate = MyDelegate(self.view, self)
25
        delegate.error.connect(self.error.emit)
26
        self.view.setItemDelegate(delegate)
27
        self.node = None
28
        self.view.header().setSectionResizeMode(1)
29
        
30
        self.addNamespaceAction = QAction("Add Namespace", self.model)
31
        self.addNamespaceAction.triggered.connect(self.add_namespace)
32
        self.removeNamespaceAction = QAction("Remove Namespace", self.model)
33
        self.removeNamespaceAction.triggered.connect(self.remove_namespace)
34
35
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
36
        self.view.customContextMenuRequested.connect(self.showContextMenu)
37
        self._contextMenu = QMenu()
38
        self._contextMenu.addAction(self.addNamespaceAction)
39
        self._contextMenu.addAction(self.removeNamespaceAction)
40
41
    @trycatchslot
42
    def add_namespace(self):
43
        uries = self.node.get_value()
44
        newidx = len(uries)
45
        it = self.model.item(0, 0)
46
        uri_it = QStandardItem("")
47
        it.appendRow([QStandardItem(), QStandardItem(str(newidx)), uri_it])
48
        idx = self.model.indexFromItem(uri_it)
49
        self.view.edit(idx)
50
51
    @trycatchslot
52
    def remove_namespace(self):
53
        idx = self.view.currentIndex()
54
        if not idx.isValid() or idx == self.model.item(0, 0):
55
            logger.warning("No valid item selected to remove")
56
        idx = idx.sibling(idx.row(), 2)
57
        item = self.model.itemFromIndex(idx)
58
        uri = item.text()
59
        uries = self.node.get_value()
60
        uries.remove(uri)
61
        logger.info("Writting namespace array: %s", uries)
62
        self.node.set_value(uries)
63
        self.reload()
64
65
    def set_node(self, node):
66
        self.model.clear()
67
        self.node = node
68
        self.show_array()
69
70
    def reload(self):
71
        self.set_node(self.node)
72
73
    def show_array(self):
74
        self.model.setHorizontalHeaderLabels(['Browse Name', 'Index', 'Value'])
75
76
        name_item = QStandardItem(self.node.get_browse_name().Name)
77
        self.model.appendRow([name_item, QStandardItem(""), QStandardItem()])
78
        it = self.model.item(0, 0)
79
        val = self.node.get_value()
80
        for idx, url in enumerate(val):
81
            it.appendRow([QStandardItem(), QStandardItem(str(idx)), QStandardItem(url)])
82
        self.view.expandAll()
83
84
    def clear(self):
85
        self.model.clear()
86
87
    def showContextMenu(self, position):
88
        self.removeNamespaceAction.setEnabled(False)
89
        idx = self.view.currentIndex()
90
        if not idx.isValid():
91
            return
92
        if idx.parent().isValid() and idx.row() >= 1:
93
            self.removeNamespaceAction.setEnabled(True)
94
        self._contextMenu.exec_(self.view.viewport().mapToGlobal(position))
95
96
97
class MyDelegate(QStyledItemDelegate):
98
99
    error = pyqtSignal(Exception)
100
    attr_written = pyqtSignal(ua.AttributeIds, ua.DataValue)
101
102
    def __init__(self, parent, widget):
103
        QStyledItemDelegate.__init__(self, parent)
104
        self.widget = widget
105
106
    @trycatchslot
107
    def createEditor(self, parent, option, idx):
108
        """
109
        Called when editing starts, here can we override default editor,
110
        disable editing for some values, etc...
111
        """
112
        if idx.column() != 2 or idx.row() == 0:
113
            return None
114
        return QStyledItemDelegate.createEditor(self, parent, option, idx)
115
116
    @trycatchslot
117
    def setModelData(self, editor, model, idx):
118
        """
119
        Called when editor has finished editing data
120
        Here we call the default implementation and save our values
121
        """
122
        QStyledItemDelegate.setModelData(self, editor, model, idx)
123
        root = model.item(0, 0)
124
        uries = []
125
        count = 0
126
        while True:
127
            child = root.child(count, 2)
128
            count += 1
129
            if not child:
130
                break
131
            uries.append(child.text())
132
        logger.info("Writting namespace array: %s", uries)
133
        self.widget.node.set_value(uries)
134
135
136