""" the plugin loader class """ # PySide2 import from PySide2 import QtWidgets from PySide2.QtCore import Qt # simulator imports from engine.dynamicloader import DynamicLoader # it loads all the classes in plugin folder dynamically # so used * in here to load all from plugins import * class Engine(DynamicLoader): """ The simulator class which loads the ui file dynamically and initializes the objects and can be eventually shown. Note: this class is growing fast and seems like needs to be multiple classes """ mdiArea: QtWidgets.QMdiArea menuBar: QtWidgets.QMenuBar menuWindows: QtWidgets.QMenu lblStatusCANBus: QtWidgets.QLabel lblStatusMessages: QtWidgets.QLabel plugins = [] def __init__(self): super().__init__(os.path.dirname(__file__)) self.__init_plugins() self.__init_actions() def _init_loader(self): """ initializes the class by calling it's initializer methods to make objects ready :return: none """ self.lblStatusCANBus = self.find_label('lblStatusCANBus') self.lblStatusMessages = self.find_label('lblStatusMessages') self.mdiArea = self.find_widget(QtWidgets.QMdiArea, 'mdiArea') self.menuBar = self.find_widget(QtWidgets.QMenuBar, 'menuBar') self.menuWindows = self.find_widget(QtWidgets.QMenu, 'menuWindows') self.action_show_all = self.find_action('actionShowAll') def _init_widgets(self): pass def _init_connections(self): pass def __init_plugins(self): """ initializes the widgets' properties :return: none """ # loading/registering plugins # the loaded_plugins has been filled and exposed # from within the __init__.py in the plugins folder # folders with '__' and '.' have been ignored. for plugin in available_plugins: self.plugins.append(eval(plugin)()) self.__register_plugin() def __init_actions(self): """ initializes the widgets connections :return: none """ self.action_show_all.toggled.connect(self.set_all_windows_visible) def __create_actions(self, name: str, window: QtWidgets.QWidget): """ creates a menu action item with the name/title name and set to show/hide the plugin form object :param name: the action menu title :param window: the object to show/hide :return: false if the object is None """ if window is None: return False top_menu_name = "View" sub_menu_name = name names = name.split("/") if len(names) > 1: top_menu_name = names[0] sub_menu_name = names[1] menu = None if top_menu_name != "": found = False for item in self.menuBar.actions(): if item.text().replace('&', '').strip().lower() == top_menu_name.replace('&', '').strip().lower(): menu = item.menu() found = True break if not found: menu = self.menuBar.addMenu(top_menu_name) action = menu.addAction(sub_menu_name) action.triggered.connect(lambda: self.__action_triggered(window)) self.action_show_all.toggled.connect(action.setChecked) def __action_triggered(self, window): if window.isVisible(): if self.mdiArea.activeSubWindow() == window: window.setVisible(False) else: self.mdiArea.setActiveSubWindow(window) else: window.setVisible(True) def __register_plugin(self): """ creates the plugin object and adds it to the mdi and creates an action menu for it :param obj: the plugin object :return: False if the passed obj is None """ titles = {} for obj in self.plugins: titles[obj.window.windowTitle()] = obj for title in sorted(titles): wgt = titles[title].window sub = self.mdiArea.addSubWindow(wgt) sub.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowTitleHint) sub.setWindowFlag(Qt.WindowMaximizeButtonHint, obj.canMaximize) sub.setVisible(obj.isVisible) self.__create_actions(title, sub) wgt.setWindowTitle(wgt.setWindowTitle(title.replace('&', ''))) def set_all_windows_visible(self, visible: bool): """ sets all the windows (in)visible :param visible: if true the windows are set to visible :return: None """ for sub in self.mdiArea.subWindowList(): sub.setVisible(visible) self.mdiArea.cascadeSubWindows()