Completed
Push — master ( 8ef529...d1d067 )
by Olivier
01:10
created

AttrsWidget.__init__()   A

Complexity

Conditions 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 17
rs 9.4285
1
from PyQt5.QtCore import pyqtSignal, Qt, QObject
2
from PyQt5.QtGui import QStandardItemModel, QStandardItem
3
from PyQt5.QtWidgets import QApplication, QMenu, QAction
4
5
from opcua import ua
6
from opcua.common.ua_utils import string_to_variant, variant_to_string, val_to_string
7
8
9
class AttrsWidget(QObject):
10
11
    error = pyqtSignal(str)
12
13
    def __init__(self, view):
14
        QObject.__init__(self, view)
15
        self.view = view
16
        self.model = QStandardItemModel()
17
        self.view.setModel(self.model)
18
        self.current_node = None
19
        self.view.doubleClicked.connect(self.edit_attr)
20
        self.model.itemChanged.connect(self.edit_attr_finished)
21
        self.view.header().setSectionResizeMode(1)
22
23
        # Context menu
24
        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
25
        self.view.customContextMenuRequested.connect(self.showContextMenu)
26
        copyaction = QAction("&Copy Value", self.model)
27
        copyaction.triggered.connect(self._copy_value)
28
        self._contextMenu = QMenu()
29
        self._contextMenu.addAction(copyaction)
30
31
    def _check_edit(self, item):
32
        """
33
        filter only element we want to edit.
34
        take either idx eller item as argument
35
        """
36
        if item.column() != 1:
37
            return False
38
        name_item = self.model.item(item.row(), 0)
39
        if name_item.text() != "Value":
40
            return False
41
        return True
42
43
    def edit_attr(self, idx):
44
        if not self._check_edit(idx):
45
            return
46
        attritem = self.model.item(idx.row(), 0)
47
        if attritem.text() == "Value":
48
            self.view.edit(idx)
49
50
    def edit_attr_finished(self, item):
51
        if not self._check_edit(item):
52
            return
53
        try:
54
            var = item.data()
55
            val = item.text()
56
            var = string_to_variant(val, var.VariantType)
57
            self.current_node.set_value(var)
58
        except Exception as ex:
59
            self.error.emit(ex)
60
            raise
61
        finally:
62
            dv = self.current_node.get_data_value()
63
            item.setText(variant_to_string(dv.Value))
64
            name_item = self.model.item(item.row(), 0)
65
            name_item.child(0, 1).setText(val_to_string(dv.ServerTimestamp))
66
            name_item.child(1, 1).setText(val_to_string(dv.SourceTimestamp))
67
68
    def showContextMenu(self, position):
69
        item = self.get_current_item()
70
        if item:
71
            self._contextMenu.exec_(self.view.mapToGlobal(position))
72
73
    def get_current_item(self, col_idx=0):
74
        idx = self.view.currentIndex()
75
        return self.model.item(idx.row(), col_idx)
76
77
    def _copy_value(self, position):
78
        it = self.get_current_item(1)
79
        if it:
80
            QApplication.clipboard().setText(it.text())
81
82
    def clear(self):
83
        self.model.clear()
84
85
    def show_attrs(self, node):
86
        self.current_node = node
87
        self.model.clear()
88
        if self.current_node:
89
            self._show_attrs()
90
        self.view.expandAll()
91
92
    def _show_attrs(self):
93
        attrs = self.get_all_attrs()
94
        self.model.setHorizontalHeaderLabels(['Attribute', 'Value', 'DataType'])
95
        for name, dv in attrs:
96
            if name == "DataType":
97
                if isinstance(dv.Value.Value.Identifier, int) and dv.Value.Value.Identifier < 63:
98
                    string = ua.DataType_to_VariantType(dv.Value.Value).name
99
                elif dv.Value.Value.Identifier in ua.ObjectIdNames:
100
                    string = ua.ObjectIdNames[dv.Value.Value.Identifier]
101
                else:
102
                    string = dv.Value.Value.to_string()
103
            elif name in ("AccessLevel", "UserAccessLevel"):
104
                string = ",".join([e.name for e in ua.int_to_AccessLevel(dv.Value.Value)])
105
            elif name in ("WriteMask", "UserWriteMask"):
106
                string = ",".join([e.name for e in ua.int_to_WriteMask(dv.Value.Value)])
107
            elif name in ("EventNotifier"):
108
                string = ",".join([e.name for e in ua.int_to_EventNotifier(dv.Value.Value)])
109
            else:
110
                string = variant_to_string(dv.Value)
111
            name_item = QStandardItem(name)
112
            vitem = QStandardItem(string)
113
            vitem.setData(dv.Value)
114
            self.model.appendRow([name_item, vitem, QStandardItem(dv.Value.VariantType.name)])
115
            if name == "Value":
116
                string = val_to_string(dv.ServerTimestamp)
117
                name_item.appendRow([QStandardItem("Server Timestamp"), QStandardItem(string), QStandardItem(ua.VariantType.DateTime.name)])
118
                string = val_to_string(dv.SourceTimestamp)
119
                name_item.appendRow([QStandardItem("Source Timestamp"), QStandardItem(string), QStandardItem(ua.VariantType.DateTime.name)])
120
121
    def get_all_attrs(self):
122
        names = []
123
        vals = []
124
        for name, val in ua.AttributeIds.__dict__.items():
125
            if not name.startswith("_"):
126
                names.append(name)
127
                vals.append(val)
128
        try:
129
            attrs = self.current_node.get_attributes(vals)
130
        except Exception as ex:
131
            self.error.emit(ex)
132
            raise
133
        res = []
134
        for idx, name in enumerate(names):
135
            if attrs[idx].StatusCode.is_good():
136
                res.append((name, attrs[idx]))
137
        res.sort()
138
        return res
139
140
141
142