class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowIcon(QIcon(":/network.svg")) # fix stuff imposible to do in qtdesigner # remove dock titlebar for addressbar w = QWidget() self.ui.addrDockWidget.setTitleBarWidget(w) # tabify some docks self.tabifyDockWidget(self.ui.evDockWidget, self.ui.subDockWidget) self.tabifyDockWidget(self.ui.subDockWidget, self.ui.refDockWidget) # we only show statusbar in case of errors self.ui.statusBar.hide() # load settings, seconds arg is default self.settings = QSettings("FreeOpcUa", "FreeOpcUaClient") self._address_list = self.settings.value("address_list", [ "opc.tcp://localhost:4840", "opc.tcp://localhost:53530/OPCUA/SimulationServer/" ]) self._address_list_max_count = int( self.settings.value("address_list_max_count", 10)) # init widgets for addr in self._address_list: self.ui.addrComboBox.insertItem(-1, addr) self.uaclient = UaClient() self.tree_ui = TreeUI(self, self.uaclient) self.refs_ui = RefsUI(self, self.uaclient) self.attrs_ui = AttrsUI(self, self.uaclient) self.datachange_ui = DataChangeUI(self, self.uaclient) self.event_ui = EventUI(self, self.uaclient) self.resize(int(self.settings.value("main_window_width", 800)), int(self.settings.value("main_window_height", 600))) self.restoreState(self.settings.value("main_window_state", b"")) self.ui.connectButton.clicked.connect(self._connect) self.ui.disconnectButton.clicked.connect(self._disconnect) # self.ui.treeView.expanded.connect(self._fit) self.ui.actionConnect.triggered.connect(self._connect) self.ui.actionDisconnect.triggered.connect(self._disconnect) def show_error(self, msg, level=1): print("showing error: ", msg, level) self.ui.statusBar.show() self.ui.statusBar.setStyleSheet( "QStatusBar { background-color : red; color : black; }") self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def get_current_node(self, idx=None): if idx is None: idx = self.ui.treeView.currentIndex() return self.tree_ui.get_current_node(idx) def get_uaclient(self): return self.uaclient def _connect(self): uri = self.ui.addrComboBox.currentText() try: self.uaclient.connect(uri) except Exception as ex: self.show_error(ex) raise self._update_address_list(uri) self.tree_ui.start() def _update_address_list(self, uri): if uri == self._address_list[0]: return if uri in self._address_list: self._address_list.remove(uri) self._address_list.insert(0, uri) if len(self._address_list) > self._address_list_max_count: self._address_list.pop(-1) def _disconnect(self): try: self.uaclient.disconnect() except Exception as ex: self.show_error(ex) raise finally: self.tree_ui.clear() self.refs_ui.clear() self.attrs_ui.clear() self.datachange_ui.clear() self.event_ui.clear() def closeEvent(self, event): self.settings.setValue("main_window_width", self.size().width()) self.settings.setValue("main_window_height", self.size().height()) self.settings.setValue("main_window_state", self.saveState()) self.settings.setValue("address_list", self._address_list) self._disconnect() event.accept()
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowIcon(QIcon(":/network.svg")) # fix stuff imposible to do in qtdesigner # remove dock titlebar for addressbar w = QWidget() self.ui.addrDockWidget.setTitleBarWidget(w) # tabify some docks self.tabifyDockWidget(self.ui.evDockWidget, self.ui.subDockWidget) self.tabifyDockWidget(self.ui.subDockWidget, self.ui.refDockWidget) # we only show statusbar in case of errors self.ui.statusBar.hide() # load settings, seconds arg is default self.settings = QSettings("FreeOpcUa", "FreeOpcUaClient") self._address_list = self.settings.value("address_list", ["opc.tcp://localhost:4840", "opc.tcp://localhost:53530/OPCUA/SimulationServer/"]) self._address_list_max_count = int(self.settings.value("address_list_max_count", 10)) # init widgets for addr in self._address_list: self.ui.addrComboBox.insertItem(-1, addr) self.uaclient = UaClient() self.tree_ui = TreeUI(self, self.uaclient) self.refs_ui = RefsUI(self, self.uaclient) self.attrs_ui = AttrsUI(self, self.uaclient) self.datachange_ui = DataChangeUI(self, self.uaclient) self.event_ui = EventUI(self, self.uaclient) self.resize(int(self.settings.value("main_window_width", 800)), int(self.settings.value("main_window_height", 600))) self.restoreState(self.settings.value("main_window_state", b"", type="QByteArray")) self.ui.connectButton.clicked.connect(self._connect) self.ui.disconnectButton.clicked.connect(self._disconnect) # self.ui.treeView.expanded.connect(self._fit) self.ui.actionConnect.triggered.connect(self._connect) self.ui.actionDisconnect.triggered.connect(self._disconnect) self.ui.modeComboBox.addItem("None") self.ui.modeComboBox.addItem("Sign") self.ui.modeComboBox.addItem("SignAndEncrypt") self.ui.policyComboBox.addItem("None") self.ui.policyComboBox.addItem("Basic128RSA15") self.ui.policyComboBox.addItem("Basic256") self.ui.policyComboBox.addItem("Basic256SHA256") def show_error(self, msg, level=1): print("showing error: ", msg, level) self.ui.statusBar.show() self.ui.statusBar.setStyleSheet("QStatusBar { background-color : red; color : black; }") self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def get_current_node(self, idx=None): return self.tree_ui.get_current_node(idx) def get_uaclient(self): return self.uaclient def _connect(self): uri = self.ui.addrComboBox.currentText() try: self.uaclient.connect(uri) except Exception as ex: self.show_error(ex) raise self._update_address_list(uri) self.tree_ui.start() def _update_address_list(self, uri): if uri == self._address_list[0]: return if uri in self._address_list: self._address_list.remove(uri) self._address_list.insert(0, uri) if len(self._address_list) > self._address_list_max_count: self._address_list.pop(-1) def _disconnect(self): try: self.uaclient.disconnect() except Exception as ex: self.show_error(ex) raise finally: self.tree_ui.clear() self.refs_ui.clear() self.attrs_ui.clear() self.datachange_ui.clear() self.event_ui.clear() def closeEvent(self, event): self.settings.setValue("main_window_width", self.size().width()) self.settings.setValue("main_window_height", self.size().height()) self.settings.setValue("main_window_state", self.saveState()) self.settings.setValue("address_list", self._address_list) self._disconnect() event.accept()
class Window(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) #fix stuff imposible to do in qtdesigner #remove dock titlebar for addressbar w = QWidget() self.ui.addrDockWidget.setTitleBarWidget(w) #tabify some docks self.tabifyDockWidget(self.ui.evDockWidget, self.ui.subDockWidget) self.tabifyDockWidget(self.ui.subDockWidget, self.ui.refDockWidget) # init widgets self.ui.statusBar.hide() self.ui.addrComboBox.insertItem(-1, "opc.tcp://localhost:4841/") self.ui.addrComboBox.insertItem( 1, "opc.tcp://localhost:53530/OPCUA/SimulationServer/") self.ui.addrComboBox.insertItem(1, "opc.tcp://10.0.5.15:49320/") self.attr_model = QStandardItemModel() self.refs_model = QStandardItemModel() self.sub_model = QStandardItemModel() self.ui.attrView.setModel(self.attr_model) self.ui.refView.setModel(self.refs_model) self.ui.subView.setModel(self.sub_model) self.model = MyModel(self) self.model.clear() self.model.error.connect(self.show_error) self.ui.treeView.setModel(self.model) self.ui.treeView.setUniformRowHeights(True) self.ui.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.uaclient = UaClient() self.ui.connectButton.clicked.connect(self._connect) self.ui.disconnectButton.clicked.connect(self._disconnect) self.ui.treeView.activated.connect(self._show_attrs_and_refs) self.ui.treeView.clicked.connect(self._show_attrs_and_refs) self.ui.treeView.expanded.connect(self._fit) self.ui.actionSubscribeDataChange.triggered.connect(self._subscribe) self.ui.actionSubscribeEvent.triggered.connect(self._subscribeEvent) self.ui.actionConnect.triggered.connect(self._connect) self.ui.actionDisconnect.triggered.connect(self._disconnect) self.ui.attrRefreshButton.clicked.connect(self.show_attrs) # context menu self.ui.treeView.addAction(self.ui.actionSubscribeDataChange) self.ui.treeView.addAction(self.ui.actionSubscribeEvent) self.ui.treeView.addAction(self.ui.actionUnsubscribe) # handle subscriptions self._subhandler = SubHandler(self.sub_model) def show_error(self, msg, level=1): print("showing error: ", msg, level) self.ui.statusBar.show() self.ui.statusBar.setStyleSheet( "QStatusBar { background-color : red; color : black; }") #self.ui.statusBar.clear() self.ui.statusBar.showMessage(str(msg)) QTimer.singleShot(1500, self.ui.statusBar.hide) def _fit(self, idx): self.ui.treeView.resizeColumnToContents(0) def _subscribeEvent(self): self.showError("Not Implemented") def _subscribe(self): idx = self.ui.treeView.currentIndex() it = self.model.itemFromIndex(idx) if not id: self.show_error("No item currently selected") node = it.data() attrs = self.uaclient.get_node_attrs(node) self.sub_model.setHorizontalHeaderLabels( ["DisplayName", "Browse Name", 'NodeId', "Value"]) item = QStandardItem(attrs[1]) self.sub_model.appendRow( [item, QStandardItem(attrs[2]), QStandardItem(attrs[3])]) try: # FIXME use handle to unsubscribe!!! handle = self.uaclient.subscribe(node, self._subhandler) except Exception as ex: self.show_error(ex) idx = self.sub_model.indexFromItem(item) self.sub_model.takeRow(idx.row()) def unsubscribe(self): idx = self.ui.treeView.currentIndex() it = self.model.itemFromIndex(idx) if not id: print("No item currently selected") node = it.data() self.uaclient.unsubscribe(node) def _show_attrs_and_refs(self, idx): node = self.get_current_node(idx) if node: self._show_attrs(node) self._show_refs(node) def get_current_node(self, idx=None): if idx is None: idx = self.ui.treeView.currentIndex() it = self.model.itemFromIndex(idx) if not it: return None node = it.data() if not node: print("No node for item:", it, it.text()) return None return node def show_attrs(self): node = self.get_current_node() if node: self._show_attrs(node) else: self.attr_model.clear() def _show_refs(self, node): self.refs_model.clear() self.refs_model.setHorizontalHeaderLabels( ['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"]) try: refs = self.uaclient.get_all_refs(node) except Exception as ex: self.show_error(ex) raise for ref in refs: self.refs_model.appendRow([ QStandardItem(str(ref.ReferenceTypeId)), QStandardItem(str(ref.NodeId)), QStandardItem(str(ref.BrowseName)), QStandardItem(str(ref.TypeDefinition)) ]) self.ui.refView.resizeColumnToContents(0) self.ui.refView.resizeColumnToContents(1) self.ui.refView.resizeColumnToContents(2) self.ui.refView.resizeColumnToContents(3) def _show_attrs(self, node): try: attrs = self.uaclient.get_all_attrs(node) except Exception as ex: self.show_error(ex) raise self.attr_model.clear() self.attr_model.setHorizontalHeaderLabels(['Attribute', 'Value']) for k, v in attrs.items(): self.attr_model.appendRow( [QStandardItem(k), QStandardItem(str(v))]) self.ui.attrView.resizeColumnToContents(0) self.ui.attrView.resizeColumnToContents(1) def _connect(self): uri = self.ui.addrComboBox.currentText() try: self.uaclient.connect(uri) except Exception as ex: self.show_error(ex) raise self.model.client = self.uaclient self.model.clear() self.model.add_item(self.uaclient.get_root_attrs()) self.ui.treeView.resizeColumnToContents(0) self.ui.treeView.resizeColumnToContents(1) self.ui.treeView.resizeColumnToContents(2) def _disconnect(self): try: self.uaclient.disconnect() except Exception as ex: self.show_error(ex) raise finally: self.model.clear() self.sub_model.clear() self.model.client = None def closeEvent(self, event): self._disconnect() event.accept()