class ModelManagerUI(QObject): """ Interface to ModelMgr that displays dialogs to interact with users. Logic is inside ModelManager, this class only handle the UI and dialogs """ error = pyqtSignal(Exception) def __init__(self, modeler): QObject.__init__(self) self.modeler = modeler self._model_mgr = ModelManager(modeler) self._model_mgr.error.connect(self.error) self.settings = QSettings() self._last_model_dir = self.settings.value("last_model_dir", ".") self._copy_clipboard = None def get_current_server(self): return self._model_mgr.server_mgr def get_new_nodes(self): return self._model_mgr.new_nodes @trycatchslot def new(self): if not self.try_close_model(): return self._model_mgr.new_model() @trycatchslot def delete(self): node = self.modeler.get_current_node() self._model_mgr.delete_node(node) @trycatchslot def copy(self): node = self.modeler.get_current_node() if node: self._copy_clipboard = node @trycatchslot def paste(self): if self._copy_clipboard: self._model_mgr.paste_node(self._copy_clipboard) @trycatchslot def close_model(self): self.try_close_model() def try_close_model(self): if self._model_mgr.modified: reply = QMessageBox.question( self.modeler, "OPC UA Modeler", "Model is modified, do you really want to close model?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply != QMessageBox.Yes: return False self._model_mgr.close_model(force=True) return True @trycatchslot def open(self): if not self.try_close_model(): return path, ok = QFileDialog.getOpenFileName( self.modeler, caption="Open OPC UA XML", filter="XML Files (*.xml *.XML)", directory=self._last_model_dir) if not ok: return if self._last_model_dir != os.path.dirname(path): self._last_model_dir = os.path.dirname(path) self.settings.setValue("last_model_dir", self._last_model_dir) self._model_mgr.open_model(path) @trycatchslot def import_xml(self): last_import_dir = self.settings.value("last_import_dir", ".") path, ok = QFileDialog.getOpenFileName( self.modeler, caption="Import reference OPC UA XML", filter="XML Files (*.xml *.XML)", directory=last_import_dir) if not ok: return None self.settings.setValue("last_import_dir", last_import_dir) self._model_mgr.import_xml(path) @trycatchslot def save_as(self): self._save_as() def _save_as(self): path, ok = QFileDialog.getSaveFileName( self.modeler, caption="Save OPC UA XML", filter="XML Files (*.xml *.XML)") if ok: if os.path.isfile(path): reply = QMessageBox.question( self.modeler, "OPC UA Modeler", "File already exit, do you really want to save to this file?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply != QMessageBox.Yes: return if self._last_model_dir != os.path.dirname(path): self._last_model_dir = os.path.dirname(path) self.settings.setValue("last_model_dir", self._last_model_dir) self._model_mgr.save_model(path) @trycatchslot def save(self): if not self._model_mgr.current_path: self.save_as() else: self._model_mgr.save_model() @trycatchslot def add_method(self): args, ok = NewUaMethodDialog.getArgs(self.modeler, "Add Method", self._model_mgr.server_mgr) if ok: self._model_mgr.add_method(*args) @trycatchslot def add_object_type(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Object Type", self._model_mgr.server_mgr) if ok: self._model_mgr.add_object_type(*args) @trycatchslot def add_folder(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Folder", self._model_mgr.server_mgr) if ok: self._model_mgr.add_folder(*args) @trycatchslot def add_object(self): args, ok = NewUaObjectDialog.getArgs( self.modeler, "Add Object", self._model_mgr.server_mgr, base_node_type=self._model_mgr.server_mgr.nodes.base_object_type) if ok: self._model_mgr.add_object(*args) @trycatchslot def add_data_type(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Data Type", self._model_mgr.server_mgr) if ok: self._model_mgr.add_data_type(*args) @trycatchslot def add_variable(self): dtype = self.settings.value("last_datatype", None) args, ok = NewUaVariableDialog.getArgs(self.modeler, "Add Variable", self._model_mgr.server_mgr, default_value=9.99, dtype=dtype) if ok: self._model_mgr.add_variable(*args) self.settings.setValue("last_datatype", args[4]) @trycatchslot def add_property(self): dtype = self.settings.value("last_datatype", None) args, ok = NewUaVariableDialog.getArgs(self.modeler, "Add Property", self._model_mgr.server_mgr, default_value=9.99, dtype=dtype) if ok: self._model_mgr.add_property(*args) @trycatchslot def add_variable_type(self): args, ok = NewUaObjectDialog.getArgs( self.modeler, "Add Variable Type", self._model_mgr.server_mgr, base_node_type=self._model_mgr.server_mgr.get_node( ua.ObjectIds.BaseVariableType)) if ok: self._model_mgr.add_variable_type(*args)
class ModelManagerUI(QObject): """ Interface to ModelMgr that displays dialogs to interact with users. Logic is inside ModelManager, this class only handle the UI and dialogs """ error = pyqtSignal(Exception) titleChanged = pyqtSignal(str) def __init__(self, modeler): QObject.__init__(self) self.modeler = modeler self._model_mgr = ModelManager(modeler) self._model_mgr.error.connect(self.error) self._model_mgr.titleChanged.connect(self.titleChanged) self.settings = QSettings() self._last_model_dir = self.settings.value("last_model_dir", ".") self._copy_clipboard = None def get_current_server(self): return self._model_mgr.server_mgr def get_new_nodes(self): return self._model_mgr.new_nodes def setModified(self, val=True): self._model_mgr.modified = val @trycatchslot def new(self): if not self.try_close_model(): return self._model_mgr.new_model() @trycatchslot def delete(self): node = self.modeler.get_current_node() self._model_mgr.delete_node(node) @trycatchslot def copy(self): node = self.modeler.get_current_node() if node: self._copy_clipboard = node @trycatchslot def paste(self): if self._copy_clipboard: self._model_mgr.paste_node(self._copy_clipboard) @trycatchslot def close_model(self): self.try_close_model() def try_close_model(self): if self._model_mgr.modified: reply = QMessageBox.question( self.modeler, "OPC UA Modeler", "Model is modified, do you really want to close model?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel ) if reply != QMessageBox.Yes: return False self._model_mgr.close_model(force=True) return True @trycatchslot def open(self): if not self.try_close_model(): return path, ok = QFileDialog.getOpenFileName(self.modeler, caption="Open OPC UA XML", filter="XML Files (*.xml *.XML *.uamodel)", directory=self._last_model_dir) if not ok: return if self._last_model_dir != os.path.dirname(path): self._last_model_dir = os.path.dirname(path) self.settings.setValue("last_model_dir", self._last_model_dir) self._model_mgr.open(path) self.modeler.update_recent_files(path) def open_file(self, path): self._model_mgr.open(path) @trycatchslot def import_xml(self): last_import_dir = self.settings.value("last_import_dir", ".") path, ok = QFileDialog.getOpenFileName(self.modeler, caption="Import reference OPC UA XML", filter="XML Files (*.xml *.XML)", directory=last_import_dir) if not ok: return self.settings.setValue("last_import_dir", last_import_dir) self._model_mgr.import_xml(path) @trycatchslot def save_as(self): self._save_as() def _save_as(self): path, ok = QFileDialog.getSaveFileName(self.modeler, caption="Save OPC UA XML", filter="XML Files (*.xml *.XML)") if ok: print("PATH", path) if self._last_model_dir != os.path.dirname(path): self._last_model_dir = os.path.dirname(path) self.settings.setValue("last_model_dir", self._last_model_dir) self._model_mgr.save_xml(path) path = self._model_mgr.save_ua_model(path) self.modeler.update_recent_files(path) @trycatchslot def save(self): if not self._model_mgr.current_path: self.save_as() else: self._model_mgr.save_xml() self._model_mgr.save_ua_model() @trycatchslot def add_method(self): args, ok = NewUaMethodDialog.getArgs(self.modeler, "Add Method", self._model_mgr.server_mgr) if ok: nodes = self._model_mgr.add_method(*args) print("ADDED", [c.get_browse_name() for c in nodes]) self._add_modelling_rule(nodes) @trycatchslot def add_object_type(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Object Type", self._model_mgr.server_mgr) if ok: self._model_mgr.add_object_type(*args) @trycatchslot def add_folder(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Folder", self._model_mgr.server_mgr) if ok: node = self._model_mgr.add_folder(*args) self._add_modelling_rule(node) @trycatchslot def add_object(self): args, ok = NewUaObjectDialog.getArgs(self.modeler, "Add Object", self._model_mgr.server_mgr, base_node_type=self._model_mgr.server_mgr.nodes.base_object_type) if ok: nodes = self._model_mgr.add_object(*args) # FIXME: in this particular case we may want to navigate recursively to add ref self._add_modelling_rule(nodes) def _add_modelling_rule(self, nodes): if not isinstance(nodes, (list, tuple)): nodes = [nodes] for node in nodes: path = node.get_path() if self._model_mgr.server_mgr.nodes.base_object_type in path: # we are creating a new type, add modeling rule node.set_modelling_rule(True) @trycatchslot def add_data_type(self): args, ok = NewNodeBaseDialog.getArgs(self.modeler, "Add Data Type", self._model_mgr.server_mgr) if ok: self._model_mgr.add_data_type(*args) @trycatchslot def add_variable(self): args, ok = NewUaVariableDialog.getArgs(self.modeler, "Add Variable", self._model_mgr.server_mgr) if ok: node = self._model_mgr.add_variable(*args) self._add_modelling_rule(node) @trycatchslot def add_property(self): args, ok = NewUaVariableDialog.getArgs(self.modeler, "Add Property", self._model_mgr.server_mgr) if ok: node = self._model_mgr.add_property(*args) self._add_modelling_rule(node) @trycatchslot def add_variable_type(self): args, ok = NewUaObjectDialog.getArgs(self.modeler, "Add Variable Type", self._model_mgr.server_mgr, base_node_type=self._model_mgr.server_mgr.get_node(ua.ObjectIds.BaseVariableType)) if ok: self._model_mgr.add_variable_type(*args)