예제 #1
0
    def __init__(self, gui_api, TabManger, plugin_manager, parent=None):
        super(CreatePluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data
        self.TabManager = TabManger

        self.gui_api = gui_api

        self.subscriberID = None
        self.targetID = None
        self.blockName = None

        self.plugin_manager = plugin_manager

        self.pluginTree.setDragEnabled(True)
        self.pluginTree.setDropIndicatorShown(True)

        self.setWindowTitle('Available Plugins')

        model = PaPITreeModel()
        model.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(model)

        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)
        self.pluginTree.setSortingEnabled(True)
        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        self.plugin_roots = {}

        self.configuration_inputs = {}

        self.pluginTree.clicked.connect(self.pluginItemChanged)

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api,
                                                       self.TabManager)

        self.createButton.clicked.connect(self.show_create_plugin_dialog)
        self.helpButton.clicked.connect(self.help_button_triggered)
        self.finder = ModuleFinder()

        self.pluginSearchText.textChanged.connect(
            self.changed_search_plugin_text_field)

        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
        self.helpButton.setText('')
        self.helpButton.setIcon(get16Icon('help.png'))
        self.helpButton.setToolTip(
            'Opens the documentation for the currently selected plugin.')
예제 #2
0
    def __init__(self, gui_api, TabManger, plugin_manager, parent=None):
        super(CreatePluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data
        self.TabManager = TabManger

        self.gui_api = gui_api

        self.subscriberID = None
        self.targetID = None
        self.blockName = None

        self.plugin_manager = plugin_manager

        self.pluginTree.setDragEnabled(True)
        self.pluginTree.setDropIndicatorShown(True)

        self.setWindowTitle('Available Plugins')

        model = PaPITreeModel()
        model.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(model)

        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)
        self.pluginTree.setSortingEnabled(True)
        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        self.plugin_roots = {}

        self.configuration_inputs = {}

        self.pluginTree.clicked.connect(self.pluginItemChanged)

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api, self.TabManager)

        self.createButton.clicked.connect(self.show_create_plugin_dialog)
        self.helpButton.clicked.connect(self.help_button_triggered)
        self.finder = ModuleFinder()

        self.pluginSearchText.textChanged.connect(self.changed_search_plugin_text_field)

        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
        self.helpButton.setText('')
        self.helpButton.setIcon(get16Icon('help.png'))
        self.helpButton.setToolTip('Opens the documentation for the currently selected plugin.')
예제 #3
0
파일: base_visual.py 프로젝트: dlaidig/PaPI
    def _ctrlMenu_copy(self):
        """
        Callback function for context menu for copying plugins

        :return:
        """
        dplugin =  self.control_api.get_dplugin_by_uname(self._dplugin_info.uname)
        dplugin.startup_config = self.pl_get_current_config()

        plugin_create_dialog = CreatePluginDialog(self.control_api, self.TabManager, parent=self._widget)
        plugin_create_dialog.set_dplugin(dplugin, self._get_startup_configuration(), self._get_type())
        print()
        plugin_create_dialog.show()
예제 #4
0
class CreatePluginMenu(QMainWindow, Ui_PluginCreateMenu):

    def __init__(self, gui_api, TabManger, plugin_manager, parent=None):
        super(CreatePluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data
        self.TabManager = TabManger

        self.gui_api = gui_api

        self.subscriberID = None
        self.targetID = None
        self.blockName = None

        self.plugin_manager = plugin_manager

        self.pluginTree.setDragEnabled(True)
        self.pluginTree.setDropIndicatorShown(True)

        self.setWindowTitle('Available Plugins')

        model = PaPITreeModel()
        model.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(model)

        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)
        self.pluginTree.setSortingEnabled(True)
        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        self.plugin_roots = {}

        self.configuration_inputs = {}

        self.pluginTree.clicked.connect(self.pluginItemChanged)

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api, self.TabManager)

        self.createButton.clicked.connect(self.show_create_plugin_dialog)
        self.helpButton.clicked.connect(self.help_button_triggered)
        self.finder = ModuleFinder()

        self.pluginSearchText.textChanged.connect(self.changed_search_plugin_text_field)

        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
        self.helpButton.setText('')
        self.helpButton.setIcon(get16Icon('help.png'))
        self.helpButton.setToolTip('Opens the documentation for the currently selected plugin.')

    def keyPressEvent(self, event):

        if event.key() in [Qt.Key_Right, Qt.Key_Space]:
            index = self.pluginTree.currentIndex()
            self.pluginItemChanged(index)

        if event.key() == Qt.Key_Escape:
            self.close()

        # Use enter/return to bring up the dialog for a selected plugin
        if (event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter) and self.pluginTree.hasFocus():
           self.show_create_plugin_dialog()

        # if search bar has focus and user pressed enter/return,arrow up/down, change focus to the plugin tree
        if (event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter or event.key() == Qt.Key_Down \
            or event.key() == Qt.Key_Up) and self.pluginSearchText.hasFocus():
            self.pluginTree.setFocus(Qt.OtherFocusReason)

    def pluginItemChanged(self, index):
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        self.clear()

        self.scrollArea.setDisabled(True)

        if plugin_info is None:
            return

        self.scrollArea.setDisabled(False)

        self.nameEdit.setText(plugin_info.name)
        self.authorEdit.setText(plugin_info.author)
        self.descriptionText.setText(plugin_info.description)
        self.pathEdit.setText(plugin_info.path)

        self.createButton.setEnabled(plugin_info.loadable)

        lines = None
        with open(plugin_info.path + '.py') as f:
            lines = f.readlines()

        found_imports = []

        for line in lines:
            if line.startswith('import'):

                m = re.search('(import)\s+([\w.]*)(\s+as){0,1}',str.strip(line))
                if m is not None:
                    if len(m.groups()) > 2:
                        found_imports.append(m.group(2))

            if line.startswith('from'):
                m = re.search('(from)\s+([\w.]*)(\s+import)',str.strip(line))
                if m is not None:
                    if len(m.groups()) > 2:
                        found_imports.append(m.group(2))
        found_imports.sort()


        for imp in found_imports:
            item = QListWidgetItem(imp)

            spam_loader = importlib.find_loader(imp)
            found = spam_loader is not None
            if not found:
                self.modulesList.addItem(item)
                item.setBackground(QColor(255,0,0,50))

        if not plugin_info.loadable:

            self.modulesList.setEnabled(True)
            self.modulesLabel.setEnabled(True)

    def show_create_plugin_dialog(self):
        index = self.pluginTree.currentIndex()
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        if plugin_info is not None:
            if plugin_info.loadable:
                self.plugin_create_dialog.set_plugin(plugin_info)
                self.plugin_create_dialog.show()

    def showEvent(self, *args, **kwargs):

        self.plugin_manager.locatePlugins()
        candidates = self.plugin_manager.getPluginCandidates()
        all_pluginfo = {c[2].path:c[2] for c in candidates}
        loadable_pluginfo = {p.path:p for p in self.plugin_manager.getAllPlugins()}

        for pluginfo in all_pluginfo.values():

            if pluginfo.path in loadable_pluginfo.keys():
                pluginfo = loadable_pluginfo[pluginfo.path]
                pluginfo.loadable = True
            else:
                pluginfo.loadable = False
            plugin_item = PluginTreeItem(pluginfo)

            plugin_root = self.get_plugin_root(pluginfo.path)
            plugin_root.appendRow(plugin_item)

        for root in sorted(self.plugin_roots.keys()):
            self.pluginTree.model().sourceModel().appendRow(self.plugin_roots[root])
            self.plugin_roots[root].sortChildren(0)

    def help_button_triggered(self):
        index = self.pluginTree.currentIndex()
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        if plugin_info is not None:



            path = plugin_info.path
            plugin_type = path.split('/')[-3]
            suffix = "." + '.'.join(path.split('/')[-2:])
            target_url = pc.PAPI_DOC_URL + pc.PAPI_DOC_PREFIX_PLUGIN + "." + plugin_type.lower() + suffix + ".html"
            QDesktopServices.openUrl(QUrl(target_url, QUrl.TolerantMode))

    def get_plugin_root(self,path):
        parts = path.split('/');
        part = parts[-3]
        name = part
        if part not in self.plugin_roots:

            cfg_file = str.join("/", parts[0:-2]) + "/" + pc.GUI_PLUGIN_CONFIG

            if os.path.isfile(cfg_file):
                config = configparser.ConfigParser()
                config.read(cfg_file)
                if 'Config' in config.sections():
                    if 'name' in config.options('Config'):
                        name = config.get('Config', 'name')

            self.plugin_roots[part] = PaPIRootItem(name)

        return self.plugin_roots[part]

    def changed_search_plugin_text_field(self, value):

        if not len(value):
            value = "*"
            self.pluginTree.collapseAll()
        else:
            value = "*" + value + "*"
            self.pluginTree.expandAll()

        self.pluginProxyModel.sourceModel().mark_visibility_by_name(value)

        # Used to trigger filter action
        regex = QRegExp(value, Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)





    def clear(self):
        self.nameEdit.setText('')
        self.authorEdit.setText('')
        self.descriptionText.setText('')
        self.pathEdit.setText('')
        self.modulesList.clear()
        self.modulesList.setEnabled(False)
        self.modulesLabel.setEnabled(False)

    def closeEvent(self, *args, **kwargs):
        self.plugin_create_dialog.close()
예제 #5
0
    def __init__(self, gui_api, tabmanager, parent=None):
        super(OverviewPluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data

        self.gui_api = gui_api
        self.TabManager = tabmanager

        self.setWindowTitle("OverviewMenu")

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api,
                                                       self.TabManager)

        # ----------------------------------
        # Build structure of plugin tree
        # ----------------------------------

        self.dpluginModel = DPluginTreeModel()
        self.dpluginModel.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(self.dpluginModel)
        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)

        self.plugin_roots = {}

        # -----------------------------------
        # Build structure of parameter tree
        # -----------------------------------

        self.dparameterModel = DParameterTreeModel()
        self.dparameterModel.setHorizontalHeaderLabels(['Name'])
        self.parameterTree.setModel(self.dparameterModel)
        self.parameterTree.setUniformRowHeights(True)
        self.dparameterModel.dataChanged.connect(
            self.data_changed_parameter_model)

        # -----------------------------------
        # Build structure of block tree
        # -----------------------------------

        self.bModel = DBlockTreeModel(self.showInternalNameCheckBox)
        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.bModel.setColumnCount(2)
        self.blockTree.setModel(self.bModel)
        self.blockTree.setUniformRowHeights(True)
        self.bModel.dataChanged.connect(self.data_changed_block_model)

        self.showInternalNameCheckBox.clicked.connect(
            self.show_internal_name_callback)

        # -----------------------------------
        # Build structure of connection tree
        # -----------------------------------

        self.connectionModel = PaPITreeModel()
        self.connectionModel.setHorizontalHeaderLabels([''])
        self.connectionTree.setHeaderHidden(True)
        self.connectionTree.setModel(self.connectionModel)
        self.connectionTree.setUniformRowHeights(True)

        self.subscribers_root = PaPIRootItem('Subscribers')
        self.connectionModel.appendRow(self.subscribers_root)

        self.subscriptions_root = PaPIRootItem('Subscriptions')
        self.connectionModel.appendRow(self.subscriptions_root)

        # -----------------------------------
        # signal/slots
        # -----------------------------------
        self.playButton.clicked.connect(self.play_button_callback)
        self.pauseButton.clicked.connect(self.pause_button_callback)
        self.stopButton.clicked.connect(self.stop_start_button_callback)
        self.pluginTree.clicked.connect(self.plugin_item_changed)
        self.pluginTree.selectionModel().selectionChanged.connect(
            self.changed_dplugin_tree_selection)

        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        # ----------------------------------
        # Add context menu
        # ----------------------------------
        self.pluginTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.pluginTree.customContextMenuRequested.connect(
            self.open_context_menu_dplugin_tree)

        self.blockTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.blockTree.customContextMenuRequested.connect(
            self.open_context_menu_block_tree)

        self.parameterTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.parameterTree.customContextMenuRequested.connect(
            self.open_context_menu_parameter_tree)

        self.connectionTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connectionTree.customContextMenuRequested.connect(
            self.open_context_menu_connection_tree)

        # ----------------------------------
        # Add Actions
        # ----------------------------------
        self.actionRefresh.triggered.connect(self.refresh_action)
        self.pluginSearchText.textChanged.connect(
            self.changed_search_plugin_text_field)

        self.clear()

        # set focus to the search bar
        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
예제 #6
0
class OverviewPluginMenu(QMainWindow, Ui_PluginOverviewMenu):
    """
    This class is used to create an extra window which is used to display all created plugins.
    The information are taken by the corresponding DPlugin-Object of a plugin. By this window a user is able to
    create and cancel subscriptions.
    """
    def __init__(self, gui_api, tabmanager, parent=None):
        super(OverviewPluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data

        self.gui_api = gui_api
        self.TabManager = tabmanager

        self.setWindowTitle("OverviewMenu")

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api,
                                                       self.TabManager)

        # ----------------------------------
        # Build structure of plugin tree
        # ----------------------------------

        self.dpluginModel = DPluginTreeModel()
        self.dpluginModel.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(self.dpluginModel)
        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)

        self.plugin_roots = {}

        # -----------------------------------
        # Build structure of parameter tree
        # -----------------------------------

        self.dparameterModel = DParameterTreeModel()
        self.dparameterModel.setHorizontalHeaderLabels(['Name'])
        self.parameterTree.setModel(self.dparameterModel)
        self.parameterTree.setUniformRowHeights(True)
        self.dparameterModel.dataChanged.connect(
            self.data_changed_parameter_model)

        # -----------------------------------
        # Build structure of block tree
        # -----------------------------------

        self.bModel = DBlockTreeModel(self.showInternalNameCheckBox)
        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.bModel.setColumnCount(2)
        self.blockTree.setModel(self.bModel)
        self.blockTree.setUniformRowHeights(True)
        self.bModel.dataChanged.connect(self.data_changed_block_model)

        self.showInternalNameCheckBox.clicked.connect(
            self.show_internal_name_callback)

        # -----------------------------------
        # Build structure of connection tree
        # -----------------------------------

        self.connectionModel = PaPITreeModel()
        self.connectionModel.setHorizontalHeaderLabels([''])
        self.connectionTree.setHeaderHidden(True)
        self.connectionTree.setModel(self.connectionModel)
        self.connectionTree.setUniformRowHeights(True)

        self.subscribers_root = PaPIRootItem('Subscribers')
        self.connectionModel.appendRow(self.subscribers_root)

        self.subscriptions_root = PaPIRootItem('Subscriptions')
        self.connectionModel.appendRow(self.subscriptions_root)

        # -----------------------------------
        # signal/slots
        # -----------------------------------
        self.playButton.clicked.connect(self.play_button_callback)
        self.pauseButton.clicked.connect(self.pause_button_callback)
        self.stopButton.clicked.connect(self.stop_start_button_callback)
        self.pluginTree.clicked.connect(self.plugin_item_changed)
        self.pluginTree.selectionModel().selectionChanged.connect(
            self.changed_dplugin_tree_selection)

        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        # ----------------------------------
        # Add context menu
        # ----------------------------------
        self.pluginTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.pluginTree.customContextMenuRequested.connect(
            self.open_context_menu_dplugin_tree)

        self.blockTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.blockTree.customContextMenuRequested.connect(
            self.open_context_menu_block_tree)

        self.parameterTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.parameterTree.customContextMenuRequested.connect(
            self.open_context_menu_parameter_tree)

        self.connectionTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connectionTree.customContextMenuRequested.connect(
            self.open_context_menu_connection_tree)

        # ----------------------------------
        # Add Actions
        # ----------------------------------
        self.actionRefresh.triggered.connect(self.refresh_action)
        self.pluginSearchText.textChanged.connect(
            self.changed_search_plugin_text_field)

        self.clear()

        # set focus to the search bar
        self.pluginSearchText.setFocus(Qt.OtherFocusReason)

    def clear(self):
        """
        This function will clear this window.

        :return:
        """
        self.bModel.clear()
        self.dparameterModel.clear()

        self.subscribers_root.setRowCount(0)
        self.subscriptions_root.setRowCount(0)

        self.unameEdit.setText('')
        self.usedpluginEdit.setText('')
        self.stateEdit.setText('')
        self.typeEdit.setText('')
        self.alivestateEdit.setText('')

        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.dparameterModel.setHorizontalHeaderLabels(['Name', 'Value'])
        self.connectionModel.setHorizontalHeaderLabels([''])

    def plugin_item_changed(self, index):
        """
        Used to display all known information for a DPlugin which is
        accessible in the pluginTree by its index.

        :param index: Current selected index
        :return:
        """

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)
        self.clear()

        if dplugin is None:
            self.pluginWidget.setDisabled(True)
            return
        self.pluginWidget.setDisabled(False)

        # ------------------------------------
        # Get all needed dplugin information
        # ------------------------------------

        self.unameEdit.setText(dplugin.uname)
        self.usedpluginEdit.setText(dplugin.plugin_identifier)
        self.stateEdit.setText(dplugin.state)
        self.typeEdit.setText(dplugin.type)
        self.alivestateEdit.setText(dplugin.alive_state)

        self.pauseButton.setDisabled(False)
        self.playButton.setDisabled(False)
        self.stopButton.setDisabled(False)

        if dplugin.alive_state != PLUGIN_STATE_DEAD:
            if dplugin.state == PLUGIN_STATE_PAUSE:
                self.pauseButton.setDisabled(True)
            if dplugin.state == PLUGIN_STATE_STOPPED:
                self.pauseButton.setDisabled(True)
                self.playButton.setDisabled(True)
                self.stopButton.setText('START')
            if dplugin.state == PLUGIN_STATE_RESUMED:
                self.playButton.setDisabled(True)
            if dplugin.state == PLUGIN_STATE_START_SUCCESFUL:
                self.playButton.setDisabled(True)
                self.stopButton.setText('STOP')

        # ---------------------------
        # Add DBlocks(Also DEvent)
        # ---------------------------

        dblock_ids = dplugin.get_dblocks()

        for dblock_id in dblock_ids:
            dblock = dblock_ids[dblock_id]

            block_item = DBlockTreeItem(dblock)
            self.bModel.appendRow(block_item)

            # -------------------------
            # Add Signals of this DBlock
            # -------------------------

            for signal in dblock.get_signals():
                if signal.uname not in [pc.CORE_TIME_SIGNAL]:
                    signal_item = DSignalTreeItem(
                        signal, self.showInternalNameCheckBox)

                    block_item.appendRow(signal_item)

            block_item.sortChildren(0)

            # ----------------------------------
            # Add Subscribers of this DBlock
            # ----------------------------------

            subscriber_ids = dblock.get_subscribers()

            for subscriber_id in subscriber_ids:
                # Other plugin
                subscriber = self.dgui.get_dplugin_by_id(subscriber_id)

                if dplugin.id in subscriber.get_subscribtions():

                    for dblock_sub_id in subscriber.get_subscribtions()[
                            dplugin.id]:

                        subscriber_item = DPluginTreeItem(subscriber)
                        #                self.subscriberModel.appendRow(subscriber_item)
                        self.subscribers_root.appendRow(subscriber_item)

                        subscription = subscriber.get_subscribtions()[
                            dplugin.id][dblock_sub_id]

                        block_item = DBlockTreeItem(dblock)

                        subscriber_item.appendRow(block_item)

                        subscription_item = PaPITreeItem(
                            subscription, "Signals")
                        block_item.appendRow(subscription_item)
                        for signal_uname in sorted(subscription.get_signals()):
                            if signal_uname not in [pc.CORE_TIME_SIGNAL]:
                                signal_item = PaPITreeItem(
                                    signal_uname, signal_uname)

                                subscription_item.appendRow(signal_item)

        # -------------------------
        # Add all Subscriptions
        # for this plugin
        # -------------------------

        dplugin_sub_ids = dplugin.get_subscribtions()

        for dplugin_sub_id in dplugin_sub_ids:

            dblock_names = dplugin_sub_ids[dplugin_sub_id]

            dplugin_sub = self.gui_api.gui_data.get_dplugin_by_id(
                dplugin_sub_id)
            dplugin_sub_item = DPluginTreeItem(dplugin_sub)
            #self.subscriptionModel.appendRow(dplugin_sub_item)
            self.subscriptions_root.appendRow(dplugin_sub_item)

            for dblock_name in dblock_names:

                dblock_sub = dplugin_sub.get_dblock_by_name(dblock_name)
                dblock_sub_item = DBlockTreeItem(dblock_sub)
                dplugin_sub_item.appendRow(dblock_sub_item)

                subscription = dblock_names[dblock_name]

                subscription_item = PaPITreeItem(subscription, "Signals")

                dblock_sub_item.appendRow(subscription_item)

                for signal_uname in sorted(subscription.get_signals()):
                    if signal_uname not in [pc.CORE_TIME_SIGNAL]:
                        signal_item = PaPITreeItem(signal_uname, signal_uname)

                        subscription_item.appendRow(signal_item)

        # --------------------------
        # Add DParameters
        # --------------------------

        dparameter_names = dplugin.get_parameters()
        for dparameter_name in sorted(dparameter_names):
            dparameter = dparameter_names[dparameter_name]
            dparameter_item = DParameterTreeItem(dparameter)
            self.dparameterModel.appendRow(dparameter_item)
            self.parameterTree.resizeColumnToContents(0)
            self.parameterTree.resizeColumnToContents(1)

        self.blockTree.expandAll()
        self.parameterTree.expandAll()

        # http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html \
        # #PySide.QtGui.PySide.QtGui.QAbstractItemView.SelectionMode
        self.blockTree.setSelectionMode(QAbstractItemView.ExtendedSelection)

        # Sort Models
        self.bModel.sort(0)

    def plugin_item_refresh(self, index):
        self.parameterTree.viewport().update()
        self.blockTree.viewport().update()
        self.connectionTree.viewport().update()

    # noinspection PyUnresolvedReferences
    def open_context_menu_dplugin_tree(self, position):
        """
        This callback function is called to create a context menu
        for the dplugin tree

        :param position:
        :return:
        """
        index = self.pluginTree.indexAt(position)

        if index.parent().isValid() is False:
            return None

        if index.isValid() is False:
            return None

        if self.pluginTree.isIndexHidden(index):
            return

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        menu = QMenu('Menu')

        submenu = QMenu('Action')
        menu.addMenu(submenu)
        action = QAction('Remove plugin', self)
        submenu.addAction(action)

        action.triggered.connect(
            lambda ignore, p=dplugin.id: self.gui_api.do_delete_plugin(p))

        action = QAction('Copy plugin', self)
        submenu.addAction(action)

        action.triggered.connect(
            lambda ignore, p=dplugin: self.show_create_plugin_dialog(p))

        menu.exec_(self.pluginTree.viewport().mapToGlobal(position))

    def open_context_menu_block_tree(self, position):
        """
        This callback function is called to create a context menu
        for the block tree

        :param position:
        :return:
        """

        index = self.blockTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.blockTree.isIndexHidden(index):
            return

        item = self.blockTree.model().data(index, Qt.UserRole)

        if isinstance(item, DPlugin) or isinstance(item, DBlock):
            return

        index_sel = self.pluginTree.currentIndex()
        dplugin_sel = self.pluginTree.model().data(index_sel, Qt.UserRole)

        if dplugin_sel is not None:

            sub_menu = QMenu('Add Subscription')
            dplugin_ids = self.dgui.get_all_plugins()

            for dplugin_id in dplugin_ids:
                dplugin = dplugin_ids[dplugin_id]

                if dplugin_sel.id != dplugin_id:
                    action = QAction(self.tr(dplugin.uname), self)
                    sub_menu.addAction(action)
                    action.triggered.connect(lambda ignore, p=dplugin.uname:
                                             self.add_subscription_action(p))

            menu = QMenu()
            menu.addMenu(sub_menu)

            menu.exec_(self.blockTree.viewport().mapToGlobal(position))

    def open_context_menu_connection_tree(self, position):
        """
        This callback function is called to create a context menu
        for the subscriper tree

        :param position:
        :return:
        """
        index = self.connectionTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.connectionTree.isIndexHidden(index):
            return None

        if index.parent().isValid() is False:
            return None

        parIndex = index
        subscriberPart = False
        subscriptionPart = False
        signals = []
        isSignal = False

        while True:
            object = self.connectionTree.model().data(parIndex, Qt.DisplayRole)

            if "Subscribers" in object:
                subscriberPart = True
            if "Subscriptions" in object:
                subscriptionPart = True

            if (subscriptionPart or subscriberPart):
                break

            parIndex = parIndex.parent()

            if parIndex.isValid() is False:
                return

        if not (subscriptionPart or subscriberPart):
            return None

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole),
                      DSubscription):
            return

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole),
                      DPlugin):
            return

        # ----------------------------------
        # Open no context menu for signals
        # ----------------------------------

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole),
                      str):
            isSignal = True
        else:
            isSignal = False

        # ----------------------------------
        # Get necessary objects for this subscription/subscriber
        # ----------------------------------

        if isSignal:
            dblock = self.connectionTree.model().data(index.parent().parent(),
                                                      Qt.UserRole)
            dplugin = self.connectionTree.model().data(
                index.parent().parent().parent(), Qt.UserRole)
            signal_uname = self.connectionTree.model().data(index, Qt.UserRole)
            signals.append(signal_uname)
        else:
            dblock = self.connectionTree.model().data(index, Qt.UserRole)
            dplugin = self.connectionTree.model().data(index.parent(),
                                                       Qt.UserRole)

        if subscriberPart:
            action = QAction('Remove Subscriber', self)
            action.triggered.connect(lambda ignore, p=dblock, m=dplugin: self.
                                     remove_subscriber_action(m, p))

        if subscriptionPart:
            action = QAction('Remove Subscription', self)
            action.triggered.connect(
                lambda ignore, p=dblock, m=dplugin, s=signals: self.
                cancel_subscription_action(m, p, s))

        menu = QMenu('Remove')
        menu.addAction(action)
        menu.exec_(self.connectionTree.viewport().mapToGlobal(position))

    def open_context_menu_parameter_tree(self, position):
        """
        This callback function is called to create a context menu
        for the parameter tree

        :param position:
        :return:
        """
        index = self.parameterTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.parameterTree.isIndexHidden(index):
            return

        index_sibling = index.sibling(index.row(), index.column() - 1)

        if index_sibling.isValid():
            index = index_sibling

        dparameter = self.parameterTree.model().data(index, Qt.UserRole)
        dplugin = self.pluginTree.model().data(self.pluginTree.currentIndex(),
                                               Qt.UserRole)

        sub_menu = QMenu('Control by')

        dplugin_ids = self.dgui.get_all_plugins()

        for dplugin_id in dplugin_ids:
            dplugin_pcp = dplugin_ids[dplugin_id]

            if len(dplugin_pcp.get_devent()) > 0:
                # action = QAction(self.tr(dplugin.uname), self)
                # sub_menu.addAction(action)
                pcp_menu = QMenu(self.tr(dplugin_pcp.uname), sub_menu)
                sub_menu.addMenu(pcp_menu)

                dblock_pcp_ids = dplugin_pcp.get_dblocks()

                for dblock_pcp_id in dblock_pcp_ids:
                    dblock_pcp = dblock_pcp_ids[dblock_pcp_id]

                    count = len(dblock_pcp.get_subscribers())

                    action = QAction(
                        self.tr(dblock_pcp.name) + ' (' + str(count) + ')',
                        pcp_menu)
                    pcp_menu.addAction(action)

                    action.triggered.connect(
                        lambda ignore, p1=dplugin, p2=dparameter, p3=
                        dplugin_pcp, p4=dblock_pcp: self.
                        add_pcp_subscription_action(p1, p2, p3, p4))

        menu = QMenu()
        menu.addMenu(sub_menu)

        menu.exec_(self.parameterTree.viewport().mapToGlobal(position))

    def add_pcp_subscription_action(self, dplugin: DPlugin,
                                    dparameter: DParameter,
                                    dplugin_pcp: DPlugin, dblock_pcp: DBlock):
        """
        This function is used to create a subscription for a process control plugin.

        :param dplugin: Subscriber of a pcp plugin
        :param dparameter: Parameter of the subscriber which should be controlled by the pcp plugin.
        :param dplugin_pcp: The pcp plugin
        :param dblock_pcp: Block of the pcp plugin which is used to control the subscriber's parameter.
        :return:
        """
        self.gui_api.do_subscribe(dplugin.id, dplugin_pcp.id, dblock_pcp.name,
                                  [], dparameter.name)

    def add_subscription_action(self, dplugin_uname):
        """
        Used to add subscription for a specific dplugin

        :param dplugin_uname: Add Subscription for this DPlugin
        :return:
        """

        signals = []

        dplugin = self.gui_api.gui_data.get_dplugin_by_uname(dplugin_uname)

        indexes = self.blockTree.selectedIndexes()

        for index in indexes:
            if index.isValid():
                signal = self.blockTree.model().data(index, Qt.UserRole)
                signals.append(signal.uname)

        index_dblock = index.parent()

        dblock = self.blockTree.model().data(index_dblock, Qt.UserRole)

        index = self.pluginTree.currentIndex()

        dplugin_source = self.pluginTree.model().data(index, Qt.UserRole)

        self.gui_api.do_subscribe(dplugin.id, dplugin_source.id, dblock.name,
                                  signals)

        #self.blockTree.scrollTo(indexes[-1])

    def remove_subscriber_action(self, subscriber: DPlugin, dblock: DBlock):
        """
        Used to remove a subscriber of the dplugin selected in the DPlugin tree.

        :param subscriber: Subscriber which is effected
        :param dblock: DBlock which should be unsubscribed by Subscriber
        :return:
        """
        index = self.pluginTree.currentIndex()
        source = self.pluginTree.model().data(index, Qt.UserRole)
        self.gui_api.do_unsubscribe_uname(subscriber.uname, source.uname,
                                          dblock.name, [])

    def refresh_action(self, new_dplugin: DPlugin = None):
        """
        Used to refresh the overview menu view.

        :param new_dplugin: New dplugin which should be added in self.dpluginTreev.
        :return:
        """

        # -----------------------------------------
        # case: no DPlugin was added or removed
        #       e.g. parameter was changed
        # -----------------------------------------

        index = self.pluginTree.currentIndex()

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        if dplugin is not None:

            if dplugin.state == PLUGIN_STATE_DELETE:
                self.pluginWidget.setDisabled(True)
                self.clear()
            else:
                self.pluginWidget.setEnabled(True)
                self.plugin_item_refresh(index)

        # -----------------------------------------
        # case: remove already deleted plugins
        # -----------------------------------------
        key_copy = self.plugin_roots.copy().keys()
        for root in key_copy:

            self.plugin_roots[root].clean()

            if not self.plugin_roots[root].rowCount():
                self.dpluginModel.remove_item(self.plugin_roots[root])
                del self.plugin_roots[root]

        self.subscribers_root.clean()
        self.subscriptions_root.clean()

        #        self.subscribersTree

        # -----------------------------------------
        # case: a DPlugin was added
        # -----------------------------------------

        if new_dplugin is not None:
            plugin_item = DPluginTreeItem(new_dplugin)
            plugin_root = self.get_plugin_root(new_dplugin.path)

            if not plugin_root.hasItem(new_dplugin):
                plugin_root.appendRow(plugin_item)

            if plugin_root not in self.dpluginModel.findItems(
                    "", Qt.MatchContains):
                self.dpluginModel.appendRow(plugin_root)

    def cancel_subscription_action(self, source: DPlugin, dblock: DBlock,
                                   signals: []):
        """
        Action called to cancel a subscription of the current selected dplugin.

        :param source:
        :param dblock:
        :return:
        """
        index = self.pluginTree.currentIndex()
        subscriber = self.pluginTree.model().data(index, Qt.UserRole)
        self.gui_api.do_unsubscribe_uname(subscriber.uname, source.uname,
                                          dblock.name, signals)

    def showEvent(self, *args, **kwargs):
        """
        ShowEvent of this class.

        :param args:
        :param kwargs:
        :return:
        """
        dplugin_ids = self.dgui.get_all_plugins()

        for dplugin_id in dplugin_ids:
            dplugin = dplugin_ids[dplugin_id]
            # ------------------------------
            # Sort DPluginItem in TreeWidget
            # ------------------------------
            plugin_item = DPluginTreeItem(dplugin)

            plugin_root = self.get_plugin_root(dplugin.path)
            plugin_root.appendRow(plugin_item)

        for root in sorted(self.plugin_roots.keys()):
            self.pluginTree.model().sourceModel().appendRow(
                self.plugin_roots[root])
            self.plugin_roots[root].sortChildren(0)

    def play_button_callback(self):
        """
        Callback function for the play button.

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            self.gui_api.do_resume_plugin_by_id(item.id)
            self.playButton.setDisabled(True)
            self.pauseButton.setDisabled(False)
            self.stopButton.setDisabled(False)

    def pause_button_callback(self):
        """
        Function pause_button_callback

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            self.pauseButton.setDisabled(True)
            self.playButton.setDisabled(False)
            self.gui_api.do_pause_plugin_by_id(item.id)

    def stop_start_button_callback(self):
        """
        Function stop_start_button_callback

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            if self.stopButton.text() == 'STOP':
                self.gui_api.do_stopReset_pluign(item.id)
                self.stopButton.setText('START')
                self.pauseButton.setDisabled(True)
                self.playButton.setDisabled(True)
                self.stopButton.setDisabled(False)

            else:
                self.gui_api.do_start_plugin(item.id)
                self.stopButton.setText('STOP')
                self.pauseButton.setDisabled(False)
                self.playButton.setDisabled(False)
                self.stopButton.setDisabled(False)

    def show_internal_name_callback(self):
        """
        Callback function for 'showInternalNameCheckBox'

        :return:
        """
        self.plugin_item_changed(self.pluginTree.currentIndex())

    def data_changed_parameter_model(self, index, n):
        """
        This function is called when a dparameter value is changed by editing the 'value'-column.

        :param index: Index of current changed dparameter
        :param n: None
        :return:
        """

        dparameter = self.parameterTree.model().data(index, Qt.UserRole)
        index = self.pluginTree.currentIndex()

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        self.gui_api.do_set_parameter(dplugin.id, dparameter.name,
                                      dparameter.value)

    def data_changed_block_model(self, index, n):
        """
        This function is called when a dblock child, a disgnal, is changed.

        :param index: Index of current changed dsignal object
        :param n: None
        :return:
        """

        dsignal = self.blockTree.model().data(index, Qt.UserRole)
        dblock = self.blockTree.model().data(index.parent(), Qt.UserRole)

        dplugin = self.pluginTree.model().data(self.pluginTree.currentIndex(),
                                               Qt.UserRole)

        self.gui_api.do_edit_plugin_uname(dplugin.uname, dblock,
                                          {"edit": dsignal})

    def get_plugin_root(self, path):
        parts = path.split('/')
        part = parts[-3]
        name = part
        if part not in self.plugin_roots:

            cfg_file = str.join("/", parts[0:-2]) + "/" + pc.GUI_PLUGIN_CONFIG

            if os.path.isfile(cfg_file):
                config = configparser.ConfigParser()
                config.read(cfg_file)
                if 'Config' in config.sections():
                    if 'name' in config.options('Config'):
                        name = config.get('Config', 'name')

            self.plugin_roots[part] = PaPIRootItem(name)

        return self.plugin_roots[part]

    def changed_search_plugin_text_field(self, value):
        if not len(value):
            value = "*"
            self.pluginTree.collapseAll()
        else:
            value = "*" + value + "*"
            self.pluginTree.expandAll()

        self.pluginProxyModel.sourceModel().mark_visibility_by_name(value)

        # Used to trigger filter action
        regex = QRegExp(value, Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

    def show_create_plugin_dialog(self, dplugin):

        if dplugin.type == PLUGIN_VIP_IDENTIFIER:
            dplugin.startup_config = dplugin.plugin.pl_get_current_config()

        self.plugin_create_dialog.set_dplugin(
            dplugin, dplugin.plugin._get_startup_configuration(), dplugin.type)
        self.plugin_create_dialog.show()

    def keyPressEvent(self, event):
        """
        Used to handle key events for this gui element.

        :param event: KeyEvent
        :return:
        """
        if event.key() == Qt.Key_Escape:
            self.close()

        if self.pluginTree.hasFocus() and \
                        event.key() in [Qt.Key_Return, Qt.Key_Down, Qt.Key_Up, Qt.Key_Left, Qt.Key_Right]:
            self.plugin_item_changed(self.pluginTree.currentIndex())

        # if search bar has focus and user pressed enter/return,arrow up/down, change focus to the plugin tree
        if (event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter or event.key() == Qt.Key_Down \
            or event.key() == Qt.Key_Up) and self.pluginSearchText.hasFocus():
            self.pluginTree.setFocus(Qt.OtherFocusReason)

    def changed_dplugin_tree_selection(self, new_selection, old_selection):
        pass
예제 #7
0
파일: main.py 프로젝트: dani-l/PaPI
    def gui_graphic_init(self):
        self.setWindowTitle(pc.GUI_PAPI_WINDOW_TITLE)
        # set GUI size
        self.setGeometry(self.geometry().x(),self.geometry().y(), pc.GUI_DEFAULT_WIDTH, pc.GUI_DEFAULT_HEIGHT)

        self.count = 0

        self.log = ConsoleLog(pc.GUI_PROCESS_CONSOLE_LOG_LEVEL, pc.GUI_PROCESS_CONSOLE_IDENTIFIER)

        self.log.printText(1,pc.GUI_START_CONSOLE_MESSAGE + ' .. Process id: '+str(os.getpid()))

        self.last_config = pc.PAPI_LAST_CFG_PATH

        self.in_run_mode = False


        # -------------------------------------
        # Create placeholder
        # -------------------------------------
        self.overview_menu = None
        self.create_plugin_menu = None
        self.plugin_create_dialog = None

        # -------------------------------------
        # Create menues
        # -------------------------------------
        self.plugin_create_dialog = CreatePluginDialog(self.gui_management.gui_api, self.TabManager)


        # -------------------------------------
        # Create callback functions for buttons
        # -------------------------------------
        #self.loadButton.clicked.connect(self.load_triggered)
        #self.saveButton.clicked.connect(self.save_triggered)

        # -------------------------------------
        # Create actions
        # -------------------------------------
        _translate = QtCore.QCoreApplication.translate

        self.actionLoad.triggered.connect(self.triggered_load)
        self.actionLoad.setShortcut(_translate("DefaultMain","Ctrl+L"))



        self.actionSave.triggered.connect(self.triggered_save)
        self.actionSave.setShortcut(_translate("DefaultMain","Ctrl+S"))

        self.actionOverview.triggered.connect(self.triggered_show_overview_menu)
        self.actionOverview.setShortcut(_translate("DefaultMain","Ctrl+O"))

        self.actionCreate.triggered.connect(self.triggered_show_create_plugin_menu)
        self.actionCreate.setShortcut(_translate("DefaultMain","Ctrl+N"))

        self.actionResetPaPI.triggered.connect(self.triggered_reset_papi)
        self.actionReloadConfig.triggered.connect(self.triggered_reload_config)

        self.actionRunMode.triggered.connect(self.toggle_run_mode)

        self.actionReload_Plugin_DB.triggered.connect(self.triggered_reload_plugin_db)

        self.actionPaPI_Wiki.triggered.connect(self.triggered_papi_wiki)

        self.actionPaPI_Doc.triggered.connect(self.triggered_papi_doc)
        self.actionPaPI_Doc.setShortcut(_translate("DefaultMain","Ctrl+H"))

        self.actionAbout.triggered.connect(self.triggered_papi_about)
        self.actionAbout_Qt.triggered.connect(self.triggered_papi_about_qt)

        self.actionToolbar.triggered.connect(self.triggered_show_toolbar)

        #self.toolBar.dragEnterEvent = self.toolbarDragEnterEvent
        #self.toolBar.dropEvent = self.toolbarDropEvent

        self.toolBar.clickedFavouritePlugin.connect(self.toolbarAddFavPlugin)
        self.toolBar.removedFavouritePlugin.connect(self.favPluginWasRemoved)

        self.set_icons()
예제 #8
0
파일: main.py 프로젝트: dani-l/PaPI
class GUI(QMainWindow, Ui_DefaultMain):
    """
    Used to create the qt based PaPI gui.

    """
    def __init__(self, core_queue = None, gui_queue= None, gui_id = None, gui_data = None, is_parent = False, parent=None):
        """
        Init function

        :param core_queue: Queue used to send papi events to Core
        :param gui_queue: GUI queue which contains papi events for the gui
        :param gui_id: Unique ID for this gui
        :param gui_data: Contains all data for the current session
        :param parent: parent element
        :return:
        """
        super(GUI, self).__init__(parent)
        self.is_parent = is_parent

        self.setupUi(self)

        # Create a data structure for gui if it is missing
        # -------------------------------------------------- #
        if not isinstance(gui_data, DGui):
            self.gui_data = DGui()
        else:
            self.gui_data = gui_data


        # check if gui should be the parent process or core is the parent
        # start core if gui is parent
        # -------------------------------------------------- #
        self.core_process = None
        if is_parent:
            core_queue_ref = Queue()
            gui_queue_ref = Queue()
            gui_id_ref = 1
            self.core_process = Process(target = run_core_in_own_process,
                                        args=(gui_queue_ref,core_queue_ref, gui_id_ref ))
            self.core_process.start()
        else:
            if core_queue is None:
                raise Exception('Gui started with wrong arguments')
            if gui_queue is None:
                raise Exception('Gui started with wrong arguments')
            if not isinstance(gui_id, str):
                raise Exception('Gui started with wrong arguments')

            core_queue_ref = core_queue
            gui_queue_ref = gui_queue
            gui_id_ref = gui_id


        # Create the Tab Manager and the gui management unit #
        # connect some signals of management to gui          #
        # -------------------------------------------------- #
        self.TabManager = PapiTabManger(tabWigdet=self.widgetTabs, centralWidget=self.centralwidget)

        self.gui_management = GuiManagement(core_queue_ref,
                                    gui_queue_ref,
                                    gui_id_ref,
                                    self.TabManager,
                                    self.get_gui_config,
                                    self.set_gui_config)

        self.TabManager.gui_api = self.gui_management.gui_api
        self.TabManager.dGui    = self.gui_management.gui_data

        self.gui_management.gui_event_processing.added_dplugin.connect(self.add_dplugin)
        self.gui_management.gui_event_processing.removed_dplugin.connect(self.remove_dplugin)
        self.gui_management.gui_event_processing.dgui_changed.connect(self.changed_dgui)
        self.gui_management.gui_event_processing.plugin_died.connect(self.plugin_died)

        self.gui_management.gui_api.error_occured.connect(self.error_occured)

        # initialize the graphic of the gui
        # -------------------------------------------------- #
        self.gui_graphic_init()

        signal.signal(signal.SIGINT, lambda a,b: self.signal_handler(a,b))

        # List for keys that are active
        self.keysActiveList = [];


    def signal_handler(self,signal, frame):
        """
        This handler will be called, when CTRL+C is used in the console
        It will react to SIGINT Signal
        As an reaction it will close the gui by first telling the core to close and then closing the gui
        :return:
        """
        self.gui_management.gui_api.do_close_program()
        sys.exit(0)


    def gui_graphic_init(self):
        self.setWindowTitle(pc.GUI_PAPI_WINDOW_TITLE)
        # set GUI size
        self.setGeometry(self.geometry().x(),self.geometry().y(), pc.GUI_DEFAULT_WIDTH, pc.GUI_DEFAULT_HEIGHT)

        self.count = 0

        self.log = ConsoleLog(pc.GUI_PROCESS_CONSOLE_LOG_LEVEL, pc.GUI_PROCESS_CONSOLE_IDENTIFIER)

        self.log.printText(1,pc.GUI_START_CONSOLE_MESSAGE + ' .. Process id: '+str(os.getpid()))

        self.last_config = pc.PAPI_LAST_CFG_PATH

        self.in_run_mode = False


        # -------------------------------------
        # Create placeholder
        # -------------------------------------
        self.overview_menu = None
        self.create_plugin_menu = None
        self.plugin_create_dialog = None

        # -------------------------------------
        # Create menues
        # -------------------------------------
        self.plugin_create_dialog = CreatePluginDialog(self.gui_management.gui_api, self.TabManager)


        # -------------------------------------
        # Create callback functions for buttons
        # -------------------------------------
        #self.loadButton.clicked.connect(self.load_triggered)
        #self.saveButton.clicked.connect(self.save_triggered)

        # -------------------------------------
        # Create actions
        # -------------------------------------
        _translate = QtCore.QCoreApplication.translate

        self.actionLoad.triggered.connect(self.triggered_load)
        self.actionLoad.setShortcut(_translate("DefaultMain","Ctrl+L"))



        self.actionSave.triggered.connect(self.triggered_save)
        self.actionSave.setShortcut(_translate("DefaultMain","Ctrl+S"))

        self.actionOverview.triggered.connect(self.triggered_show_overview_menu)
        self.actionOverview.setShortcut(_translate("DefaultMain","Ctrl+O"))

        self.actionCreate.triggered.connect(self.triggered_show_create_plugin_menu)
        self.actionCreate.setShortcut(_translate("DefaultMain","Ctrl+N"))

        self.actionResetPaPI.triggered.connect(self.triggered_reset_papi)
        self.actionReloadConfig.triggered.connect(self.triggered_reload_config)

        self.actionRunMode.triggered.connect(self.toggle_run_mode)

        self.actionReload_Plugin_DB.triggered.connect(self.triggered_reload_plugin_db)

        self.actionPaPI_Wiki.triggered.connect(self.triggered_papi_wiki)

        self.actionPaPI_Doc.triggered.connect(self.triggered_papi_doc)
        self.actionPaPI_Doc.setShortcut(_translate("DefaultMain","Ctrl+H"))

        self.actionAbout.triggered.connect(self.triggered_papi_about)
        self.actionAbout_Qt.triggered.connect(self.triggered_papi_about_qt)

        self.actionToolbar.triggered.connect(self.triggered_show_toolbar)

        #self.toolBar.dragEnterEvent = self.toolbarDragEnterEvent
        #self.toolBar.dropEvent = self.toolbarDropEvent

        self.toolBar.clickedFavouritePlugin.connect(self.toolbarAddFavPlugin)
        self.toolBar.removedFavouritePlugin.connect(self.favPluginWasRemoved)

        self.set_icons()

    def addFavPlugin(self, fav_plugin):
        plugin_manager = self.gui_management.plugin_manager;

        plugin_manager.locatePlugins()

        candidates = plugin_manager.getPluginCandidates()
        all_pluginfo = {c[2].path:c[2] for c in candidates}
        loadable_pluginfo = {p.path:p for p in plugin_manager.getAllPlugins()}

        for plugin_info in all_pluginfo.values():
            if plugin_info.name == fav_plugin:

                if plugin_info.path in loadable_pluginfo.keys():
                    plugin_info = loadable_pluginfo[plugin_info.path]
                    plugin_info.loadable = True
                else:
                    plugin_info.loadable = False

                self.toolbarAddFavPlugin(plugin_info)

    def favPluginWasRemoved(self):
        self.gui_management.gui_api.do_save_xml_config_reloaded(
            pc.PAPI_USER_CFG, plToSave=[], sToSave=[], saveUserSettings=True)

    def set_icons(self):
        # -------------------------------------
        # Create Icons for buttons
        # -------------------------------------
        load_icon = get32Icon('folder')
        save_icon = get32Icon('file_save_as')
        # -------------------------------------
        # Set Icons for buttons
        # -------------------------------------
        #self.loadButton.setIconSize(QSize(32, 32))
        #self.loadButton.setIcon(load_icon)

        #self.saveButton.setIconSize(QSize(32, 32))
        #self.saveButton.setIcon(save_icon)

        # -------------------------------------
        # Create Icons for actions
        # -------------------------------------
        load_icon = get16Icon('folder')
        save_icon = get16Icon('file_save_as')
        exit_icon = get16Icon('cancel')
        overview_icon = get16Icon('tree_list')
        create_icon = get16Icon('application_add')
        reload_icon = get16Icon('arrow_rotate_clockwise')
        help_icon = get16Icon('help')
        info_icon = get16Icon('information')
        refresh_icon = get16Icon('arrow_refresh')
        delete_icon = get16Icon('delete')
        view_icon = get16Icon('reviewing_pane')

        # -------------------------------------
        # Set Icons for actions
        # -------------------------------------
        self.actionLoad.setIcon(load_icon)
        self.actionSave.setIcon(save_icon)
        self.actionExit.setIcon(exit_icon)
        self.actionOverview.setIcon(overview_icon)
        self.actionCreate.setIcon(create_icon)
        self.actionReload_Plugin_DB.setIcon(reload_icon)
        self.actionReloadConfig.setIcon(reload_icon)
        self.actionPaPI_Wiki.setIcon(help_icon)
        self.actionPaPI_Doc.setIcon(help_icon)
        self.actionAbout.setIcon(info_icon)
        self.actionAbout_Qt.setIcon(info_icon)
        self.actionAbout_PySide.setIcon(info_icon)
        self.actionResetPaPI.setIcon(delete_icon)
        self.actionRunMode.setIcon(view_icon)

        # -------------------------------------
        # Set Icons visible in menu
        # -------------------------------------
        self.actionLoad.setIconVisibleInMenu(True)
        self.actionSave.setIconVisibleInMenu(True)
        self.actionExit.setIconVisibleInMenu(True)
        self.actionOverview.setIconVisibleInMenu(True)
        self.actionCreate.setIconVisibleInMenu(True)
        self.actionReload_Plugin_DB.setIconVisibleInMenu(True)
        self.actionReloadConfig.setIconVisibleInMenu(True)
        self.actionPaPI_Wiki.setIconVisibleInMenu(True)
        self.actionPaPI_Doc.setIconVisibleInMenu(True)
        self.actionAbout.setIconVisibleInMenu(True)
        self.actionAbout_Qt.setIconVisibleInMenu(True)
        self.actionAbout_PySide.setIconVisibleInMenu(True)
        self.actionResetPaPI.setIconVisibleInMenu(True)
        self.actionRunMode.setIconVisibleInMenu(True)

    def get_gui_config(self, saveUserSettings=False):

        actTab = {}
        actTab['Active'] = str(self.TabManager.get_currently_active_tab())

        tabs = {}
        tab_dict = self.TabManager.get_tabs_by_uname()
        for tab in tab_dict:
            tabOb = tab_dict[tab]
            tabs[tab]= {}
            tabs[tab]['Background'] = tabOb.background
            tabs[tab]['Position'] = str(self.TabManager.getTabPosition_by_name(tab))

        size = {}

        size['X']= str(self.size().width())

        size['Y']= str(self.size().height())


        cfg = {}
        cfg['ActiveTab'] = actTab
        cfg['Tabs'] = tabs
        cfg['Size'] = size

        # ----------------------
        # Set favourite plugins
        # ----------------------
        if saveUserSettings:
            favourites = {}
            actions = self.toolBar.actions()
            for i in range(len(actions)):
                action = actions[i]
                if isinstance(action, PaPIFavAction):
                    favourites[action.text()] = {}
                    favourites[action.text()]['position'] = str(i)

            cfg['Favourites'] = favourites

        return cfg

    def set_gui_config(self, cfg):
        #print(cfg)
        # #################
        # # Cfgs for Tabs #
        # #################
        # if 'tabs' in cfg:
        #     tabList = {}
        #     for tab in cfg['tabs']:
        #         # Tab Name
        #         name = tab
        #
        #         # Tab details
        #         tabDetails = cfg['tabs'][tab]
        #
        #         # check for background
        #         if 'background' in tabDetails:
        #             bg = tabDetails['background']
        #             if bg != 'default':
        #                 self.TabManager.set_background_for_tab_with_name(name,bg)
        #         else:
        #             bg = None
        #
        #         # check for position
        #         if 'position' in tabDetails:
        #             pos = int(tabDetails['position'])
        #         else:
        #             if len(list(tabList.keys())) > 1:
        #                 pos = max(list(tabList.keys()))+1
        #             else:
        #                 pos = 0
        #
        #         tabList[pos] = [name, bg]
        #
        #     # sort tabs acoriding to positions
        #     keys = list(tabList.keys())
        #     keys.sort()
        #     for position in keys:
        #         name = tabList[position][0]
        #         bg = tabList[position][1]
        #         tabOb = self.TabManager.add_tab(name)
        #         self.TabManager.set_background_for_tab_with_name(name,bg)
        #
        # if 'activeTab' in cfg:
        #     if 'value' in cfg['activeTab']['active']:
        #         self.TabManager.set_tab_active_by_index(int( cfg['activeTab']['active']['value'] ))
        #
        #################
        # windows size: #
        #################
        if 'Size' in cfg:
            w = int(cfg['Size']['X'])
            h = int(cfg['Size']['Y'])
            self.resize_gui_window(w,h)

        # ------------------------
        # Restore favourite icons
        # ------------------------
        if 'Favourites' in cfg:
            sorted_positions = {}

            for plugin in cfg['Favourites']:
                sorted_positions[int(cfg['Favourites'][plugin]['position'])] = plugin

            for position in sorted(sorted_positions.keys()):
                plugin = sorted_positions[position]
                self.addFavPlugin(plugin)

        # -----------------------
        # Restore Tabs
        # -----------------------
        if 'Tabs' in cfg:
            for tabName in cfg['Tabs']:
                tab = cfg['Tabs'][tabName]
                self.TabManager.add_tab(tabName)
                if 'Background' in tab:
                    self.TabManager.set_background_for_tab_with_name(tabName, tab['Background'])

                


    def triggered_reload_plugin_db(self):
        """
        This Callback function will reload the plugin list of the plugin manager

        :return:
        """
        self.gui_management.plugin_manager.collectPlugins()

    def run(self):
        """


        :return:
        """
        # create a timer and set interval for processing events with working loop

        #QtCore.QTimer.singleShot(GUI_WOKRING_INTERVAL, lambda: self.gui_event_processing.gui_working(self.closeEvent))
        self.workingTimer = QtCore.QTimer(self)
        self.workingTimer.timeout.connect(lambda: self.gui_management.gui_event_processing.gui_working(self.closeEvent, self.workingTimer))
        self.workingTimer.start(pc.GUI_WOKRING_INTERVAL)




    def triggered_show_create_plugin_menu(self):
        """


        :return:
        """
        self.create_plugin_menu = CreatePluginMenu(self.gui_management.gui_api,
                                                   self.TabManager,
                                                   self.gui_management.plugin_manager )

        self.create_plugin_menu.show()

    def triggered_show_overview_menu(self):
        """
        Used to show the overview menu.

        :return:
        """
        self.overview_menu = OverviewPluginMenu(self.gui_management.gui_api, self.gui_management.tab_manager)
        self.overview_menu.show()

    def triggered_show_toolbar(self):
        """
        Used to hide and unhide the toolbar
        :return:
        """

        self.toolBar.setHidden(not self.toolBar.isHidden())

        self.actionToolbar.setChecked(not self.toolBar.isHidden())

    def triggered_load(self):
        """
        Used to start the 'load config' dialog.

        :return:
        """
        fileNames = ''

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setNameFilter( self.tr("PaPI-Cfg (*.xml)"))
        dialog.setDirectory(pc.CONFIG_DEFAULT_DIRECTORY)
        dialog.setWindowTitle("Load Configuration")

        if dialog.exec_():
            fileNames = dialog.selectedFiles()

        if len(fileNames):
            if fileNames[0] != '':
                self.last_config = fileNames[0]
                self.load_config(fileNames[0])

    def load_config(self, file_name):
        self.gui_management.gui_api.do_load_xml(file_name)

    def triggered_save(self):
        """
        Used to start the 'save config' dialog.

        :return:
        """
        fileNames = ''

        dialog = PaPIConfigSaveDialog(self, self.gui_management.gui_api)

        dialog.fill_with()

        if dialog.exec_():
            fileNames = dialog.selectedFiles()

        plugin_list, subscription_list = dialog.get_create_lists()

        if len(fileNames):



            if fileNames[0] != '':
                if "json" in dialog.selectedNameFilter():
                    self.gui_management.gui_api.do_save_json_config_reloaded(fileNames[0], plToSave=plugin_list, sToSave=subscription_list)

                if "xml" in dialog.selectedNameFilter():
                    self.gui_management.gui_api.do_save_xml_config_reloaded(fileNames[0], plToSave=plugin_list, sToSave=subscription_list)

    def closeEvent(self, *args, **kwargs):
        """
        Handle close event.
        Saves current session as 'papi/last_active_papi.xml'
        Closes all opened windows.

        :param args:
        :param kwargs:
        :return:
        """
        try:
            self.gui_management.gui_api.do_save_xml_config('papi/last_active_papi.xml')
        except Exception as E:
            tb = traceback.format_exc()

        self.gui_management.gui_api.do_close_program()
        if self.create_plugin_menu is not None:
            self.create_plugin_menu.close()

        if self.overview_menu is not None:
            self.overview_menu.close()

        self.close()

    def add_dplugin(self, dplugin):
        """
        Callback function called by 'DPlugin added signal'
        Used to add a DPlugin SubWindow on the GUI if possible.

        :param dplugin:
        :return:
        """
        if dplugin.type == pc.PLUGIN_VIP_IDENTIFIER:

            # sub_window_ori = dplugin.plugin.get_sub_window()
            #
            # dplugin.plugin.set_window_for_internal_usage(PaPIMDISubWindow())
            # dplugin.plugin.pl_set_widget_for_internal_usage(sub_window_ori.widget())

            sub_window = dplugin.plugin._get_sub_window()

            config = dplugin.startup_config
            tab_name = config['tab']['value']
            if tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]
            else:
                self.log.printText(1,'add dplugin: no tab with tab_id of dplugin')
                area = self.TabManager.add_tab(tab_name)

            area.addSubWindow(sub_window)

            isMaximized = config['maximized']['value'] == '1'


            size_re = re.compile(r'([0-9]+)')

            pos = config['position']['value']
            window_pos = size_re.findall(pos)
            sub_window.move(int(window_pos[0]), int(window_pos[1]))

            if not isMaximized:
                sub_window.show()
            else:
                sub_window.showMaximized()

            # see http://qt-project.org/doc/qt-4.8/qt.html#WindowType-enum

            sub_window.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowMinMaxButtonsHint | Qt.WindowTitleHint )

        if self.overview_menu is not None:
            self.overview_menu.refresh_action(dplugin)

    def remove_dplugin(self, dplugin):
        """
        Callback function called by 'DPlugin removed signal'
        Used to removed a DPlugin SubWindow from the GUI if possible.

        :param dplugin:
        :return:
        """
        if dplugin.type == pc.PLUGIN_VIP_IDENTIFIER:
            config = dplugin.plugin.pl_get_current_config()
            tab_name = config['tab']['value']
            if tab_name in self.TabManager.get_tabs_by_uname():
                tabOb = self.TabManager.get_tabs_by_uname()[tab_name]
                tabOb.removeSubWindow(dplugin.plugin._get_sub_window())
                if tabOb.closeIfempty is True:
                    if len(tabOb.subWindowList()) == 0:
                        if isinstance(tabOb, TabObject):
                            self.TabManager.closeTab_by_name(tabOb.name)
                        else:
                            self.TabManager.remove_window(tabOb)


    def changed_dgui(self):
        if self.overview_menu is not None:
            self.overview_menu.refresh_action()

    def plugin_died(self, dplugin, e, msg):
        dplugin.state = pc.PLUGIN_STATE_STOPPED

        self.gui_management.gui_api.do_stopReset_plugin_uname(dplugin.uname)

        errMsg = QtGui.QMessageBox(self)
        errMsg.setFixedWidth(650)

        # layout = errMsg.layout();
        # spacer = QtGui.QSpacerItem(1000, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        # layout.addItem(spacer, layout.rowCount(), 0,1, layout.columnCount())

        errMsg.setIcon(QtGui.QMessageBox.Critical)
        errMsg.setSizeGripEnabled(True)
        errMsg.setWindowTitle("Plugin: " + dplugin.uname + " // " + str(e))
        errMsg.setText("Error in plugin" + dplugin.uname + " // " + str(e))
        errMsg.setDetailedText(str(msg))
        errMsg.setWindowModality(Qt.NonModal)
        errMsg.show()

    def error_occured(self, title, msg, detailed_msg):

        errMsg = QtGui.QMessageBox(self)
        errMsg.setFixedWidth(650)

        errMsg.setWindowTitle(title)
        errMsg.setText(str(msg))
        errMsg.setDetailedText(str(detailed_msg))
        errMsg.setWindowModality(Qt.NonModal)
        errMsg.show()

    def toggle_run_mode(self):
        if self.in_run_mode is False:
            # hide toolbar
            self.toolBar.setHidden(True)
            self.actionToolbar.setChecked(False)
            # disable context menu of tabmanger
            self.TabManager.disableContextMenus()

            # lock subwindows in tabs
            for tabName in self.TabManager.tab_dict_uname:
                tabObject = self.TabManager.tab_dict_uname[tabName]

                for subWindow in tabObject.subWindowList():
                    subWindow.disableInteraction()
            self.in_run_mode = True
        else:
            # show toolbar
            self.toolBar.setHidden(False)
            self.actionToolbar.setChecked(True)
            # disable context menu of tabmanger
            self.TabManager.enableContextMenus()

            # unlock subwindows in tabs
            for tabName in self.TabManager.tab_dict_uname:
                tabObject = self.TabManager.tab_dict_uname[tabName]

                for subWindow in tabObject.subWindowList():
                    subWindow.enableInteraction()
            self.in_run_mode = False

    def toogle_lock(self):
        raise Exception("PLEASE REPORT THIS BUG!!")
        if self.in_run_mode:
            for tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]

                windowsList = area.subWindowList()

                for window in windowsList:

                    #window.setAttribute(Qt.WA_NoBackground)

                    #window.setAttribute(Qt.WA_NoSystemBackground)
                    #window.setAttribute(Qt.WA_TranslucentBackground)
                    #window.set_movable(False)
                    window.setMouseTracking(False)
                    window.setWindowFlags(~Qt.WindowMinMaxButtonsHint & (Qt.CustomizeWindowHint | Qt.WindowTitleHint))

        if not self.in_run_mode:
            for tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]

                windowsList = area.subWindowList()

                for window in windowsList:
                    #window.set_movable(True)
                    window.setMouseTracking(True)
                    window.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowMinMaxButtonsHint | Qt.WindowTitleHint )

    def keyPressEvent(self, event):
        if event.key() not in self.keysActiveList:
            self.keysActiveList.append(event.key())

        if  QtCore.Qt.Key_Escape in self.keysActiveList:
            if self.in_run_mode:
                self.toggle_run_mode()

        if QtCore.Qt.Key_D in self.keysActiveList and QtCore.Qt.Key_Control in self.keysActiveList:
            self.gui_management.tab_manager.select_next_tab()
            self.keysActiveList.remove(QtCore.Qt.Key_D)
            #self.keysActiveList.remove(QtCore.Qt.Key_Control)

        if QtCore.Qt.Key_A in self.keysActiveList and QtCore.Qt.Key_Control in self.keysActiveList:
            self.gui_management.tab_manager.select_prev_tab()
            self.keysActiveList.remove(QtCore.Qt.Key_A)
            #self.keysActiveList.remove(QtCore.Qt.Key_Control)


    def keyReleaseEvent(self, event):
        if event.key() in self.keysActiveList:
            self.keysActiveList.remove(event.key())


    def resize_gui_window(self, w, h):
        self.setGeometry(self.geometry().x(),self.geometry().y(),w,h)


    def triggered_reload_config(self):
        """
        This function is used to reset PaPI and to reload the last loaded configuration file.
        :return:
        """
        if self.last_config is not None:
            self.triggered_reset_papi()
            QtCore.QTimer.singleShot(pc.GUI_WAIT_TILL_RELOAD, lambda: self.gui_management.gui_api.do_load_xml(self.last_config))

    def triggered_reset_papi(self):
        """
        This function is called to reset PaPI. That means all subscriptions were canceled and all plugins were removed.
        :return:
        """
        h = pc.GUI_DEFAULT_HEIGHT
        w = pc.GUI_DEFAULT_WIDTH
        self.setGeometry(self.geometry().x(),self.geometry().y(),w,h)

        self.TabManager.set_all_tabs_to_close_when_empty(True)
        self.TabManager.close_all_empty_tabs()

        self.gui_management.gui_api.do_reset_papi()



    def triggered_papi_wiki(self):
        QDesktopServices.openUrl(QUrl(pc.PAPI_WIKI_URL, QUrl.TolerantMode))

    def triggered_papi_doc(self):
        QDesktopServices.openUrl(QUrl(pc.PAPI_DOC_URL, QUrl.TolerantMode))

    def triggered_papi_about(self):
        QMessageBox.about(self, pc.PAPI_ABOUT_TITLE, pc.PAPI_ABOUT_TEXT)

    def triggered_papi_about_qt(self):
        QMessageBox.aboutQt(self)

    def toolbarAddFavPlugin(self, plugin_info):

        l = len(plugin_info.name)
        path = plugin_info.path[:-l]
        path += 'box.png'
        px = QPixmap(path)

        icon = QIcon(px)

        for action in self.toolBar.actions():
            if action.text() == plugin_info.name:
                return

        plugin_action = PaPIFavAction(icon, plugin_info.name, self)
        plugin_action.triggered.connect(lambda ignore, p1=plugin_info : self.show_create_plugin_dialog(p1))

        self.toolBar.addAction(plugin_action)

        self.gui_management.gui_api.do_save_xml_config_reloaded(
            pc.PAPI_USER_CFG, plToSave=[], sToSave=[], saveUserSettings=True)

    def show_create_plugin_dialog(self, plugin_info):
        if plugin_info is not None:
            if plugin_info.loadable:
                self.plugin_create_dialog.set_plugin(plugin_info)
                self.plugin_create_dialog.show()

    def dropEvent(self, event:QDropEvent):
        source = event.source()
예제 #9
0
    def __init__(self, gui_api, tabmanager, parent=None):
        super(OverviewPluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data

        self.gui_api = gui_api
        self.TabManager = tabmanager;

        self.setWindowTitle("OverviewMenu")

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api, self.TabManager)

        # ----------------------------------
        # Build structure of plugin tree
        # ----------------------------------

        self.dpluginModel = DPluginTreeModel()
        self.dpluginModel.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(self.dpluginModel)
        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)

        self.plugin_roots = {}

        # -----------------------------------
        # Build structure of parameter tree
        # -----------------------------------

        self.dparameterModel = DParameterTreeModel()
        self.dparameterModel.setHorizontalHeaderLabels(['Name'])
        self.parameterTree.setModel(self.dparameterModel)
        self.parameterTree.setUniformRowHeights(True)
        self.dparameterModel.dataChanged.connect(self.data_changed_parameter_model)

        # -----------------------------------
        # Build structure of block tree
        # -----------------------------------

        self.bModel = DBlockTreeModel(self.showInternalNameCheckBox)
        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.bModel.setColumnCount(2)
        self.blockTree.setModel(self.bModel)
        self.blockTree.setUniformRowHeights(True)
        self.bModel.dataChanged.connect(self.data_changed_block_model)

        self.showInternalNameCheckBox.clicked.connect(self.show_internal_name_callback)

        # -----------------------------------
        # Build structure of connection tree
        # -----------------------------------

        self.connectionModel = PaPITreeModel()
        self.connectionModel.setHorizontalHeaderLabels([''])
        self.connectionTree.setHeaderHidden(True)
        self.connectionTree.setModel(self.connectionModel)
        self.connectionTree.setUniformRowHeights(True)

        self.subscribers_root = PaPIRootItem('Subscribers')
        self.connectionModel.appendRow(self.subscribers_root)

        self.subscriptions_root = PaPIRootItem('Subscriptions')
        self.connectionModel.appendRow(self.subscriptions_root)

        # -----------------------------------
        # signal/slots
        # -----------------------------------
        self.playButton.clicked.connect(self.play_button_callback)
        self.pauseButton.clicked.connect(self.pause_button_callback)
        self.stopButton.clicked.connect(self.stop_start_button_callback)
        self.pluginTree.clicked.connect(self.plugin_item_changed)
        self.pluginTree.selectionModel().selectionChanged.connect(self.changed_dplugin_tree_selection)

        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        # ----------------------------------
        # Add context menu
        # ----------------------------------
        self.pluginTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.pluginTree.customContextMenuRequested.connect(self.open_context_menu_dplugin_tree)

        self.blockTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.blockTree.customContextMenuRequested.connect(self.open_context_menu_block_tree)

        self.parameterTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.parameterTree.customContextMenuRequested.connect(self.open_context_menu_parameter_tree)

        self.connectionTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connectionTree.customContextMenuRequested.connect(self.open_context_menu_connection_tree)

        # ----------------------------------
        # Add Actions
        # ----------------------------------
        self.actionRefresh.triggered.connect(self.refresh_action)
        self.pluginSearchText.textChanged.connect(self.changed_search_plugin_text_field)

        self.clear()

        # set focus to the search bar
        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
예제 #10
0
class OverviewPluginMenu(QMainWindow, Ui_PluginOverviewMenu):
    """
    This class is used to create an extra window which is used to display all created plugins.
    The information are taken by the corresponding DPlugin-Object of a plugin. By this window a user is able to
    create and cancel subscriptions.
    """

    def __init__(self, gui_api, tabmanager, parent=None):
        super(OverviewPluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data

        self.gui_api = gui_api
        self.TabManager = tabmanager;

        self.setWindowTitle("OverviewMenu")

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api, self.TabManager)

        # ----------------------------------
        # Build structure of plugin tree
        # ----------------------------------

        self.dpluginModel = DPluginTreeModel()
        self.dpluginModel.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(self.dpluginModel)
        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)

        self.plugin_roots = {}

        # -----------------------------------
        # Build structure of parameter tree
        # -----------------------------------

        self.dparameterModel = DParameterTreeModel()
        self.dparameterModel.setHorizontalHeaderLabels(['Name'])
        self.parameterTree.setModel(self.dparameterModel)
        self.parameterTree.setUniformRowHeights(True)
        self.dparameterModel.dataChanged.connect(self.data_changed_parameter_model)

        # -----------------------------------
        # Build structure of block tree
        # -----------------------------------

        self.bModel = DBlockTreeModel(self.showInternalNameCheckBox)
        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.bModel.setColumnCount(2)
        self.blockTree.setModel(self.bModel)
        self.blockTree.setUniformRowHeights(True)
        self.bModel.dataChanged.connect(self.data_changed_block_model)

        self.showInternalNameCheckBox.clicked.connect(self.show_internal_name_callback)

        # -----------------------------------
        # Build structure of connection tree
        # -----------------------------------

        self.connectionModel = PaPITreeModel()
        self.connectionModel.setHorizontalHeaderLabels([''])
        self.connectionTree.setHeaderHidden(True)
        self.connectionTree.setModel(self.connectionModel)
        self.connectionTree.setUniformRowHeights(True)

        self.subscribers_root = PaPIRootItem('Subscribers')
        self.connectionModel.appendRow(self.subscribers_root)

        self.subscriptions_root = PaPIRootItem('Subscriptions')
        self.connectionModel.appendRow(self.subscriptions_root)

        # -----------------------------------
        # signal/slots
        # -----------------------------------
        self.playButton.clicked.connect(self.play_button_callback)
        self.pauseButton.clicked.connect(self.pause_button_callback)
        self.stopButton.clicked.connect(self.stop_start_button_callback)
        self.pluginTree.clicked.connect(self.plugin_item_changed)
        self.pluginTree.selectionModel().selectionChanged.connect(self.changed_dplugin_tree_selection)

        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        # ----------------------------------
        # Add context menu
        # ----------------------------------
        self.pluginTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.pluginTree.customContextMenuRequested.connect(self.open_context_menu_dplugin_tree)

        self.blockTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.blockTree.customContextMenuRequested.connect(self.open_context_menu_block_tree)

        self.parameterTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.parameterTree.customContextMenuRequested.connect(self.open_context_menu_parameter_tree)

        self.connectionTree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connectionTree.customContextMenuRequested.connect(self.open_context_menu_connection_tree)

        # ----------------------------------
        # Add Actions
        # ----------------------------------
        self.actionRefresh.triggered.connect(self.refresh_action)
        self.pluginSearchText.textChanged.connect(self.changed_search_plugin_text_field)

        self.clear()

        # set focus to the search bar
        self.pluginSearchText.setFocus(Qt.OtherFocusReason)


    def clear(self):
        """
        This function will clear this window.

        :return:
        """
        self.bModel.clear()
        self.dparameterModel.clear()

        self.subscribers_root.setRowCount(0)
        self.subscriptions_root.setRowCount(0)

        self.unameEdit.setText('')
        self.usedpluginEdit.setText('')
        self.stateEdit.setText('')
        self.typeEdit.setText('')
        self.alivestateEdit.setText('')

        self.bModel.setHorizontalHeaderLabels(['Name'])
        self.dparameterModel.setHorizontalHeaderLabels(['Name', 'Value'])
        self.connectionModel.setHorizontalHeaderLabels([''])

    def plugin_item_changed(self, index):
        """
        Used to display all known information for a DPlugin which is
        accessible in the pluginTree by its index.

        :param index: Current selected index
        :return:
        """

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)
        self.clear()

        if dplugin is None:
            self.pluginWidget.setDisabled(True)
            return
        self.pluginWidget.setDisabled(False)

        # ------------------------------------
        # Get all needed dplugin information
        # ------------------------------------

        self.unameEdit.setText(dplugin.uname)
        self.usedpluginEdit.setText(dplugin.plugin_identifier)
        self.stateEdit.setText(dplugin.state)
        self.typeEdit.setText(dplugin.type)
        self.alivestateEdit.setText(dplugin.alive_state)

        self.pauseButton.setDisabled(False)
        self.playButton.setDisabled(False)
        self.stopButton.setDisabled(False)

        if dplugin.alive_state != PLUGIN_STATE_DEAD:
            if dplugin.state == PLUGIN_STATE_PAUSE:
                self.pauseButton.setDisabled(True)
            if dplugin.state == PLUGIN_STATE_STOPPED:
                self.pauseButton.setDisabled(True)
                self.playButton.setDisabled(True)
                self.stopButton.setText('START')
            if dplugin.state == PLUGIN_STATE_RESUMED:
                self.playButton.setDisabled(True)
            if dplugin.state == PLUGIN_STATE_START_SUCCESFUL:
                self.playButton.setDisabled(True)
                self.stopButton.setText('STOP')

        # ---------------------------
        # Add DBlocks(Also DEvent)
        # ---------------------------

        dblock_ids = dplugin.get_dblocks()

        for dblock_id in dblock_ids:
            dblock = dblock_ids[dblock_id]

            block_item = DBlockTreeItem(dblock)
            self.bModel.appendRow(block_item)

            # -------------------------
            # Add Signals of this DBlock
            # -------------------------

            for signal in dblock.get_signals():
                if signal.uname not in [pc.CORE_TIME_SIGNAL]:
                    signal_item = DSignalTreeItem(signal, self.showInternalNameCheckBox)

                    block_item.appendRow(signal_item)

            block_item.sortChildren(0)

            # ----------------------------------
            # Add Subscribers of this DBlock
            # ----------------------------------

            subscriber_ids = dblock.get_subscribers()

            for subscriber_id in subscriber_ids:
                # Other plugin
                subscriber = self.dgui.get_dplugin_by_id(subscriber_id)

                if dplugin.id in subscriber.get_subscribtions():

                    for dblock_sub_id in subscriber.get_subscribtions()[dplugin.id]:


                        subscriber_item = DPluginTreeItem(subscriber)
                        #                self.subscriberModel.appendRow(subscriber_item)
                        self.subscribers_root.appendRow(subscriber_item)

                        subscription = subscriber.get_subscribtions()[dplugin.id][dblock_sub_id]

                        block_item = DBlockTreeItem(dblock)

                        subscriber_item.appendRow(block_item)

                        subscription_item = PaPITreeItem(subscription, "Signals")
                        block_item.appendRow(subscription_item)
                        for signal_uname in sorted(subscription.get_signals()):
                            if signal_uname not in [pc.CORE_TIME_SIGNAL]:
                                signal_item = PaPITreeItem(signal_uname, signal_uname)

                                subscription_item.appendRow(signal_item)


        # -------------------------
        # Add all Subscriptions
        # for this plugin
        # -------------------------

        dplugin_sub_ids = dplugin.get_subscribtions()

        for dplugin_sub_id in dplugin_sub_ids:


            dblock_names = dplugin_sub_ids[dplugin_sub_id]

            dplugin_sub = self.gui_api.gui_data.get_dplugin_by_id(dplugin_sub_id)
            dplugin_sub_item = DPluginTreeItem(dplugin_sub)
            #self.subscriptionModel.appendRow(dplugin_sub_item)
            self.subscriptions_root.appendRow(dplugin_sub_item)

            for dblock_name in dblock_names:

                dblock_sub = dplugin_sub.get_dblock_by_name(dblock_name)
                dblock_sub_item = DBlockTreeItem(dblock_sub)
                dplugin_sub_item.appendRow(dblock_sub_item)

                subscription = dblock_names[dblock_name]

                subscription_item = PaPITreeItem(subscription, "Signals")

                dblock_sub_item.appendRow(subscription_item)

                for signal_uname in sorted(subscription.get_signals()):
                    if signal_uname not in [pc.CORE_TIME_SIGNAL]:
                        signal_item = PaPITreeItem(signal_uname, signal_uname)

                        subscription_item.appendRow(signal_item)

        # --------------------------
        # Add DParameters
        # --------------------------

        dparameter_names = dplugin.get_parameters()
        for dparameter_name in sorted(dparameter_names):
            dparameter = dparameter_names[dparameter_name]
            dparameter_item = DParameterTreeItem(dparameter)
            self.dparameterModel.appendRow(dparameter_item)
            self.parameterTree.resizeColumnToContents(0)
            self.parameterTree.resizeColumnToContents(1)

        self.blockTree.expandAll()
        self.parameterTree.expandAll()

        # http://srinikom.github.io/pyside-docs/PySide/QtGui/QAbstractItemView.html \
        # #PySide.QtGui.PySide.QtGui.QAbstractItemView.SelectionMode
        self.blockTree.setSelectionMode(QAbstractItemView.ExtendedSelection)

        # Sort Models
        self.bModel.sort(0)

    def plugin_item_refresh(self, index):
        self.parameterTree.viewport().update()
        self.blockTree.viewport().update()
        self.connectionTree.viewport().update()

    # noinspection PyUnresolvedReferences
    def open_context_menu_dplugin_tree(self, position):
        """
        This callback function is called to create a context menu
        for the dplugin tree

        :param position:
        :return:
        """
        index = self.pluginTree.indexAt(position)

        if index.parent().isValid() is False:
            return None

        if index.isValid() is False:
            return None

        if self.pluginTree.isIndexHidden(index):
            return

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        menu = QMenu('Menu')

        submenu = QMenu('Action')
        menu.addMenu(submenu)
        action = QAction('Remove plugin', self)
        submenu.addAction(action)

        action.triggered.connect(lambda ignore, p=dplugin.id: self.gui_api.do_delete_plugin(p))

        action = QAction('Copy plugin', self)
        submenu.addAction(action)

        action.triggered.connect(lambda ignore, p=dplugin: self.show_create_plugin_dialog(p))

        menu.exec_(self.pluginTree.viewport().mapToGlobal(position))

    def open_context_menu_block_tree(self, position):
        """
        This callback function is called to create a context menu
        for the block tree

        :param position:
        :return:
        """

        index = self.blockTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.blockTree.isIndexHidden(index):
            return

        item = self.blockTree.model().data(index, Qt.UserRole)

        if isinstance(item, DPlugin) or isinstance(item, DBlock):
            return

        index_sel = self.pluginTree.currentIndex()
        dplugin_sel = self.pluginTree.model().data(index_sel, Qt.UserRole)

        if dplugin_sel is not None:

            sub_menu = QMenu('Add Subscription')
            dplugin_ids = self.dgui.get_all_plugins()

            for dplugin_id in dplugin_ids:
                dplugin = dplugin_ids[dplugin_id]

                if dplugin_sel.id != dplugin_id:
                    action = QAction(self.tr(dplugin.uname), self)
                    sub_menu.addAction(action)
                    action.triggered.connect(lambda ignore, p=dplugin.uname: self.add_subscription_action(p))

            menu = QMenu()
            menu.addMenu(sub_menu)

            menu.exec_(self.blockTree.viewport().mapToGlobal(position))

    def open_context_menu_connection_tree(self, position):
        """
        This callback function is called to create a context menu
        for the subscriper tree

        :param position:
        :return:
        """
        index = self.connectionTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.connectionTree.isIndexHidden(index):
            return None

        if index.parent().isValid() is False:
            return None

        parIndex = index
        subscriberPart = False
        subscriptionPart = False
        signals = []
        isSignal = False

        while True:
            object = self.connectionTree.model().data(parIndex, Qt.DisplayRole)

            if "Subscribers" in object:
                subscriberPart = True
            if "Subscriptions" in object:
                subscriptionPart = True

            if ( subscriptionPart or subscriberPart ):
                break

            parIndex = parIndex.parent()

            if parIndex.isValid() is False:
                return

        if not (subscriptionPart or subscriberPart):
            return None

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole), DSubscription):
            return

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole), DPlugin):
            return

        # ----------------------------------
        # Open no context menu for signals
        # ----------------------------------

        if isinstance(self.connectionTree.model().data(index, Qt.UserRole), str):
            isSignal = True
        else:
            isSignal = False



        # ----------------------------------
        # Get necessary objects for this subscription/subscriber
        # ----------------------------------

        if isSignal:
            dblock = self.connectionTree.model().data(index.parent().parent(), Qt.UserRole)
            dplugin = self.connectionTree.model().data(index.parent().parent().parent(), Qt.UserRole)
            signal_uname = self.connectionTree.model().data(index, Qt.UserRole)
            signals.append(signal_uname)
        else:
            dblock = self.connectionTree.model().data(index, Qt.UserRole)
            dplugin = self.connectionTree.model().data(index.parent(), Qt.UserRole)

        if subscriberPart:
            action = QAction('Remove Subscriber', self)
            action.triggered.connect(lambda ignore, p=dblock, m=dplugin: self.remove_subscriber_action(m, p))

        if subscriptionPart:
            action = QAction('Remove Subscription', self)
            action.triggered.connect(lambda ignore, p=dblock, m=dplugin, s=signals: self.cancel_subscription_action(m, p, s))

        menu = QMenu('Remove')
        menu.addAction(action)
        menu.exec_(self.connectionTree.viewport().mapToGlobal(position))

    def open_context_menu_parameter_tree(self, position):
        """
        This callback function is called to create a context menu
        for the parameter tree

        :param position:
        :return:
        """
        index = self.parameterTree.indexAt(position)

        if index.isValid() is False:
            return None

        if self.parameterTree.isIndexHidden(index):
            return

        index_sibling = index.sibling(index.row(), index.column()-1)

        if index_sibling.isValid():
            index = index_sibling

        dparameter = self.parameterTree.model().data(index, Qt.UserRole)
        dplugin = self.pluginTree.model().data(self.pluginTree.currentIndex(), Qt.UserRole)

        sub_menu = QMenu('Control by')

        dplugin_ids = self.dgui.get_all_plugins()

        for dplugin_id in dplugin_ids:
            dplugin_pcp = dplugin_ids[dplugin_id]

            if len(dplugin_pcp.get_devent()) > 0:
                # action = QAction(self.tr(dplugin.uname), self)
                # sub_menu.addAction(action)
                pcp_menu = QMenu(self.tr(dplugin_pcp.uname), sub_menu)
                sub_menu.addMenu(pcp_menu)

                dblock_pcp_ids = dplugin_pcp.get_dblocks()

                for dblock_pcp_id in dblock_pcp_ids:
                    dblock_pcp = dblock_pcp_ids[dblock_pcp_id]

                    count = len(dblock_pcp.get_subscribers())

                    action = QAction(self.tr(dblock_pcp.name)+' ('+str(count)+')', pcp_menu)
                    pcp_menu.addAction(action)

                    action.triggered.connect(lambda ignore, p1=dplugin, p2=dparameter, p3=dplugin_pcp, p4=dblock_pcp:
                                             self.add_pcp_subscription_action(p1, p2, p3, p4))

        menu = QMenu()
        menu.addMenu(sub_menu)

        menu.exec_(self.parameterTree.viewport().mapToGlobal(position))

    def add_pcp_subscription_action(self, dplugin: DPlugin, dparameter: DParameter, dplugin_pcp: DPlugin,
                                    dblock_pcp: DBlock):
        """
        This function is used to create a subscription for a process control plugin.

        :param dplugin: Subscriber of a pcp plugin
        :param dparameter: Parameter of the subscriber which should be controlled by the pcp plugin.
        :param dplugin_pcp: The pcp plugin
        :param dblock_pcp: Block of the pcp plugin which is used to control the subscriber's parameter.
        :return:
        """
        self.gui_api.do_subscribe(dplugin.id, dplugin_pcp.id, dblock_pcp.name, [], dparameter.name)


    def add_subscription_action(self, dplugin_uname):
        """
        Used to add subscription for a specific dplugin

        :param dplugin_uname: Add Subscription for this DPlugin
        :return:
        """

        signals = []

        dplugin = self.gui_api.gui_data.get_dplugin_by_uname(dplugin_uname)

        indexes = self.blockTree.selectedIndexes()


        for index in indexes:
            if index.isValid():
                signal = self.blockTree.model().data(index, Qt.UserRole)
                signals.append(signal.uname)

        index_dblock = index.parent()

        dblock = self.blockTree.model().data(index_dblock, Qt.UserRole)

        index = self.pluginTree.currentIndex()

        dplugin_source = self.pluginTree.model().data(index, Qt.UserRole)


        self.gui_api.do_subscribe(dplugin.id, dplugin_source.id, dblock.name, signals)

        #self.blockTree.scrollTo(indexes[-1])

    def remove_subscriber_action(self, subscriber: DPlugin, dblock: DBlock):
        """
        Used to remove a subscriber of the dplugin selected in the DPlugin tree.

        :param subscriber: Subscriber which is effected
        :param dblock: DBlock which should be unsubscribed by Subscriber
        :return:
        """
        index = self.pluginTree.currentIndex()
        source = self.pluginTree.model().data(index, Qt.UserRole)
        self.gui_api.do_unsubscribe_uname(subscriber.uname, source.uname, dblock.name, [])

    def refresh_action(self, new_dplugin: DPlugin=None):
        """
        Used to refresh the overview menu view.

        :param new_dplugin: New dplugin which should be added in self.dpluginTreev.
        :return:
        """

        # -----------------------------------------
        # case: no DPlugin was added or removed
        #       e.g. parameter was changed
        # -----------------------------------------

        index = self.pluginTree.currentIndex()

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        if dplugin is not None:

            if dplugin.state == PLUGIN_STATE_DELETE:
                self.pluginWidget.setDisabled(True)
                self.clear()
            else:
                self.pluginWidget.setEnabled(True)
                self.plugin_item_refresh(index)

        # -----------------------------------------
        # case: remove already deleted plugins
        # -----------------------------------------
        key_copy = self.plugin_roots.copy().keys()
        for root in key_copy:

            self.plugin_roots[root].clean()

            if not self.plugin_roots[root].rowCount():
                self.dpluginModel.remove_item(self.plugin_roots[root])
                del self.plugin_roots[root]

        self.subscribers_root.clean()
        self.subscriptions_root.clean()

        #        self.subscribersTree

        # -----------------------------------------
        # case: a DPlugin was added
        # -----------------------------------------

        if new_dplugin is not None:
            plugin_item = DPluginTreeItem(new_dplugin)
            plugin_root = self.get_plugin_root(new_dplugin.path)

            if not plugin_root.hasItem(new_dplugin):
                plugin_root.appendRow(plugin_item)

            if plugin_root not in self.dpluginModel.findItems("", Qt.MatchContains):
                self.dpluginModel.appendRow(plugin_root)


    def cancel_subscription_action(self, source: DPlugin, dblock: DBlock, signals: []):
        """
        Action called to cancel a subscription of the current selected dplugin.

        :param source:
        :param dblock:
        :return:
        """
        index = self.pluginTree.currentIndex()
        subscriber = self.pluginTree.model().data(index, Qt.UserRole)
        self.gui_api.do_unsubscribe_uname(subscriber.uname, source.uname, dblock.name, signals)

    def showEvent(self, *args, **kwargs):
        """
        ShowEvent of this class.

        :param args:
        :param kwargs:
        :return:
        """
        dplugin_ids = self.dgui.get_all_plugins()

        for dplugin_id in dplugin_ids:
            dplugin = dplugin_ids[dplugin_id]
            # ------------------------------
            # Sort DPluginItem in TreeWidget
            # ------------------------------
            plugin_item = DPluginTreeItem(dplugin)

            plugin_root = self.get_plugin_root(dplugin.path)
            plugin_root.appendRow(plugin_item)

        for root in sorted(self.plugin_roots.keys()):
            self.pluginTree.model().sourceModel().appendRow(self.plugin_roots[root])
            self.plugin_roots[root].sortChildren(0)

    def play_button_callback(self):
        """
        Callback function for the play button.

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            self.gui_api.do_resume_plugin_by_id(item.id)
            self.playButton.setDisabled(True)
            self.pauseButton.setDisabled(False)
            self.stopButton.setDisabled(False)

    def pause_button_callback(self):
        """
        Function pause_button_callback

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            self.pauseButton.setDisabled(True)
            self.playButton.setDisabled(False)
            self.gui_api.do_pause_plugin_by_id(item.id)

    def stop_start_button_callback(self):
        """
        Function stop_start_button_callback

        :return:
        """
        index = self.pluginTree.currentIndex()
        item = self.pluginTree.model().data(index, Qt.UserRole)
        if item is not None:
            if self.stopButton.text() == 'STOP':
                self.gui_api.do_stopReset_pluign(item.id)
                self.stopButton.setText('START')
                self.pauseButton.setDisabled(True)
                self.playButton.setDisabled(True)
                self.stopButton.setDisabled(False)

            else:
                self.gui_api.do_start_plugin(item.id)
                self.stopButton.setText('STOP')
                self.pauseButton.setDisabled(False)
                self.playButton.setDisabled(False)
                self.stopButton.setDisabled(False)

    def show_internal_name_callback(self):
        """
        Callback function for 'showInternalNameCheckBox'

        :return:
        """
        self.plugin_item_changed(self.pluginTree.currentIndex())

    def data_changed_parameter_model(self, index, n):
        """
        This function is called when a dparameter value is changed by editing the 'value'-column.

        :param index: Index of current changed dparameter
        :param n: None
        :return:
        """

        dparameter = self.parameterTree.model().data(index, Qt.UserRole)
        index = self.pluginTree.currentIndex()

        dplugin = self.pluginTree.model().data(index, Qt.UserRole)

        self.gui_api.do_set_parameter(dplugin.id, dparameter.name, dparameter.value)

    def data_changed_block_model(self, index, n):
        """
        This function is called when a dblock child, a disgnal, is changed.

        :param index: Index of current changed dsignal object
        :param n: None
        :return:
        """

        dsignal = self.blockTree.model().data(index, Qt.UserRole)
        dblock  = self.blockTree.model().data(index.parent(), Qt.UserRole)

        dplugin = self.pluginTree.model().data(self.pluginTree.currentIndex(), Qt.UserRole)

        self.gui_api.do_edit_plugin_uname(dplugin.uname, dblock, {"edit" : dsignal})

    def get_plugin_root(self,path):
        parts = path.split('/');
        part = parts[-3]
        name = part
        if part not in self.plugin_roots:

            cfg_file = str.join("/", parts[0:-2]) + "/" + pc.GUI_PLUGIN_CONFIG



            if os.path.isfile(cfg_file):
                config = configparser.ConfigParser()
                config.read(cfg_file)
                if 'Config' in config.sections():
                    if 'name' in config.options('Config'):
                        name = config.get('Config', 'name')

            self.plugin_roots[part] = PaPIRootItem(name)

        return self.plugin_roots[part]

    def changed_search_plugin_text_field(self, value):
        if not len(value):
            value = "*"
            self.pluginTree.collapseAll()
        else:
            value = "*" + value + "*"
            self.pluginTree.expandAll()

        self.pluginProxyModel.sourceModel().mark_visibility_by_name(value)

        # Used to trigger filter action
        regex = QRegExp(value, Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

    def show_create_plugin_dialog(self, dplugin):

        if dplugin.type == PLUGIN_VIP_IDENTIFIER:
            dplugin.startup_config = dplugin.plugin.pl_get_current_config()

        self.plugin_create_dialog.set_dplugin(dplugin, dplugin.plugin._get_startup_configuration(), dplugin.type)
        self.plugin_create_dialog.show()

    def keyPressEvent(self, event):
        """
        Used to handle key events for this gui element.

        :param event: KeyEvent
        :return:
        """
        if event.key() == Qt.Key_Escape:
            self.close()

        if self.pluginTree.hasFocus() and \
                        event.key() in [Qt.Key_Return, Qt.Key_Down, Qt.Key_Up, Qt.Key_Left, Qt.Key_Right]:
            self.plugin_item_changed(self.pluginTree.currentIndex())

        # if search bar has focus and user pressed enter/return,arrow up/down, change focus to the plugin tree
        if (event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter or event.key() == Qt.Key_Down \
            or event.key() == Qt.Key_Up) and self.pluginSearchText.hasFocus():
            self.pluginTree.setFocus(Qt.OtherFocusReason)

    def changed_dplugin_tree_selection(self, new_selection, old_selection):
        pass
예제 #11
0
    def gui_graphic_init(self):
        self.setWindowTitle(pc.GUI_PAPI_WINDOW_TITLE)
        # set GUI size
        self.setGeometry(self.geometry().x(),
                         self.geometry().y(), pc.GUI_DEFAULT_WIDTH,
                         pc.GUI_DEFAULT_HEIGHT)

        self.count = 0

        self.log = ConsoleLog(pc.GUI_PROCESS_CONSOLE_LOG_LEVEL,
                              pc.GUI_PROCESS_CONSOLE_IDENTIFIER)

        self.log.printText(
            1, pc.GUI_START_CONSOLE_MESSAGE + ' .. Process id: ' +
            str(os.getpid()))

        self.last_config = pc.PAPI_LAST_CFG_PATH

        self.in_run_mode = False

        # -------------------------------------
        # Create placeholder
        # -------------------------------------
        self.overview_menu = None
        self.create_plugin_menu = None
        self.plugin_create_dialog = None

        # -------------------------------------
        # Create menues
        # -------------------------------------
        self.plugin_create_dialog = CreatePluginDialog(
            self.gui_management.gui_api, self.TabManager)

        # -------------------------------------
        # Create callback functions for buttons
        # -------------------------------------
        #self.loadButton.clicked.connect(self.load_triggered)
        #self.saveButton.clicked.connect(self.save_triggered)

        # -------------------------------------
        # Create actions
        # -------------------------------------
        _translate = QtCore.QCoreApplication.translate

        self.actionLoad.triggered.connect(self.triggered_load)
        self.actionLoad.setShortcut(_translate("DefaultMain", "Ctrl+L"))

        self.actionSave.triggered.connect(self.triggered_save)
        self.actionSave.setShortcut(_translate("DefaultMain", "Ctrl+S"))

        self.actionOverview.triggered.connect(
            self.triggered_show_overview_menu)
        self.actionOverview.setShortcut(_translate("DefaultMain", "Ctrl+O"))

        self.actionCreate.triggered.connect(
            self.triggered_show_create_plugin_menu)
        self.actionCreate.setShortcut(_translate("DefaultMain", "Ctrl+N"))

        self.actionResetPaPI.triggered.connect(self.triggered_reset_papi)
        self.actionReloadConfig.triggered.connect(self.triggered_reload_config)

        self.actionRunMode.triggered.connect(self.toggle_run_mode)

        self.actionReload_Plugin_DB.triggered.connect(
            self.triggered_reload_plugin_db)

        self.actionPaPI_Wiki.triggered.connect(self.triggered_papi_wiki)

        self.actionPaPI_Doc.triggered.connect(self.triggered_papi_doc)
        self.actionPaPI_Doc.setShortcut(_translate("DefaultMain", "Ctrl+H"))

        self.actionAbout.triggered.connect(self.triggered_papi_about)
        self.actionAbout_Qt.triggered.connect(self.triggered_papi_about_qt)

        self.actionToolbar.triggered.connect(self.triggered_show_toolbar)

        #self.toolBar.dragEnterEvent = self.toolbarDragEnterEvent
        #self.toolBar.dropEvent = self.toolbarDropEvent

        self.toolBar.clickedFavouritePlugin.connect(self.toolbarAddFavPlugin)
        self.toolBar.removedFavouritePlugin.connect(self.favPluginWasRemoved)

        self.set_icons()
예제 #12
0
class GUI(QMainWindow, Ui_DefaultMain):
    """
    Used to create the qt based PaPI gui.

    """
    def __init__(self,
                 core_queue=None,
                 gui_queue=None,
                 gui_id=None,
                 gui_data=None,
                 is_parent=False,
                 parent=None):
        """
        Init function

        :param core_queue: Queue used to send papi events to Core
        :param gui_queue: GUI queue which contains papi events for the gui
        :param gui_id: Unique ID for this gui
        :param gui_data: Contains all data for the current session
        :param parent: parent element
        :return:
        """
        super(GUI, self).__init__(parent)
        self.is_parent = is_parent

        self.setupUi(self)

        # Create a data structure for gui if it is missing
        # -------------------------------------------------- #
        if not isinstance(gui_data, DGui):
            self.gui_data = DGui()
        else:
            self.gui_data = gui_data

        # check if gui should be the parent process or core is the parent
        # start core if gui is parent
        # -------------------------------------------------- #
        self.core_process = None
        if is_parent:
            core_queue_ref = Queue()
            gui_queue_ref = Queue()
            gui_id_ref = 1
            self.core_process = Process(target=run_core_in_own_process,
                                        args=(gui_queue_ref, core_queue_ref,
                                              gui_id_ref))
            self.core_process.start()
        else:
            if core_queue is None:
                raise Exception('Gui started with wrong arguments')
            if gui_queue is None:
                raise Exception('Gui started with wrong arguments')
            if not isinstance(gui_id, str):
                raise Exception('Gui started with wrong arguments')

            core_queue_ref = core_queue
            gui_queue_ref = gui_queue
            gui_id_ref = gui_id

        # Create the Tab Manager and the gui management unit #
        # connect some signals of management to gui          #
        # -------------------------------------------------- #
        self.TabManager = PapiTabManger(tabWigdet=self.widgetTabs,
                                        centralWidget=self.centralwidget)

        self.gui_management = GuiManagement(core_queue_ref, gui_queue_ref,
                                            gui_id_ref, self.TabManager,
                                            self.get_gui_config,
                                            self.set_gui_config)

        self.TabManager.gui_api = self.gui_management.gui_api
        self.TabManager.dGui = self.gui_management.gui_data

        self.gui_management.gui_event_processing.added_dplugin.connect(
            self.add_dplugin)
        self.gui_management.gui_event_processing.removed_dplugin.connect(
            self.remove_dplugin)
        self.gui_management.gui_event_processing.dgui_changed.connect(
            self.changed_dgui)
        self.gui_management.gui_event_processing.plugin_died.connect(
            self.plugin_died)

        self.gui_management.gui_api.error_occured.connect(self.error_occured)

        # initialize the graphic of the gui
        # -------------------------------------------------- #
        self.gui_graphic_init()

        signal.signal(signal.SIGINT, lambda a, b: self.signal_handler(a, b))

        # List for keys that are active
        self.keysActiveList = []

    def signal_handler(self, signal, frame):
        """
        This handler will be called, when CTRL+C is used in the console
        It will react to SIGINT Signal
        As an reaction it will close the gui by first telling the core to close and then closing the gui
        :return:
        """
        self.gui_management.gui_api.do_close_program()
        sys.exit(0)

    def gui_graphic_init(self):
        self.setWindowTitle(pc.GUI_PAPI_WINDOW_TITLE)
        # set GUI size
        self.setGeometry(self.geometry().x(),
                         self.geometry().y(), pc.GUI_DEFAULT_WIDTH,
                         pc.GUI_DEFAULT_HEIGHT)

        self.count = 0

        self.log = ConsoleLog(pc.GUI_PROCESS_CONSOLE_LOG_LEVEL,
                              pc.GUI_PROCESS_CONSOLE_IDENTIFIER)

        self.log.printText(
            1, pc.GUI_START_CONSOLE_MESSAGE + ' .. Process id: ' +
            str(os.getpid()))

        self.last_config = pc.PAPI_LAST_CFG_PATH

        self.in_run_mode = False

        # -------------------------------------
        # Create placeholder
        # -------------------------------------
        self.overview_menu = None
        self.create_plugin_menu = None
        self.plugin_create_dialog = None

        # -------------------------------------
        # Create menues
        # -------------------------------------
        self.plugin_create_dialog = CreatePluginDialog(
            self.gui_management.gui_api, self.TabManager)

        # -------------------------------------
        # Create callback functions for buttons
        # -------------------------------------
        #self.loadButton.clicked.connect(self.load_triggered)
        #self.saveButton.clicked.connect(self.save_triggered)

        # -------------------------------------
        # Create actions
        # -------------------------------------
        _translate = QtCore.QCoreApplication.translate

        self.actionLoad.triggered.connect(self.triggered_load)
        self.actionLoad.setShortcut(_translate("DefaultMain", "Ctrl+L"))

        self.actionSave.triggered.connect(self.triggered_save)
        self.actionSave.setShortcut(_translate("DefaultMain", "Ctrl+S"))

        self.actionOverview.triggered.connect(
            self.triggered_show_overview_menu)
        self.actionOverview.setShortcut(_translate("DefaultMain", "Ctrl+O"))

        self.actionCreate.triggered.connect(
            self.triggered_show_create_plugin_menu)
        self.actionCreate.setShortcut(_translate("DefaultMain", "Ctrl+N"))

        self.actionResetPaPI.triggered.connect(self.triggered_reset_papi)
        self.actionReloadConfig.triggered.connect(self.triggered_reload_config)

        self.actionRunMode.triggered.connect(self.toggle_run_mode)

        self.actionReload_Plugin_DB.triggered.connect(
            self.triggered_reload_plugin_db)

        self.actionPaPI_Wiki.triggered.connect(self.triggered_papi_wiki)

        self.actionPaPI_Doc.triggered.connect(self.triggered_papi_doc)
        self.actionPaPI_Doc.setShortcut(_translate("DefaultMain", "Ctrl+H"))

        self.actionAbout.triggered.connect(self.triggered_papi_about)
        self.actionAbout_Qt.triggered.connect(self.triggered_papi_about_qt)

        self.actionToolbar.triggered.connect(self.triggered_show_toolbar)

        #self.toolBar.dragEnterEvent = self.toolbarDragEnterEvent
        #self.toolBar.dropEvent = self.toolbarDropEvent

        self.toolBar.clickedFavouritePlugin.connect(self.toolbarAddFavPlugin)
        self.toolBar.removedFavouritePlugin.connect(self.favPluginWasRemoved)

        self.set_icons()

    def addFavPlugin(self, fav_plugin):
        plugin_manager = self.gui_management.plugin_manager

        plugin_manager.locatePlugins()

        candidates = plugin_manager.getPluginCandidates()
        all_pluginfo = {c[2].path: c[2] for c in candidates}
        loadable_pluginfo = {p.path: p for p in plugin_manager.getAllPlugins()}

        for plugin_info in all_pluginfo.values():
            if plugin_info.name == fav_plugin:

                if plugin_info.path in loadable_pluginfo.keys():
                    plugin_info = loadable_pluginfo[plugin_info.path]
                    plugin_info.loadable = True
                else:
                    plugin_info.loadable = False

                self.toolbarAddFavPlugin(plugin_info)

    def favPluginWasRemoved(self):
        self.gui_management.gui_api.do_save_xml_config_reloaded(
            pc.PAPI_USER_CFG, plToSave=[], sToSave=[], saveUserSettings=True)

    def set_icons(self):
        # -------------------------------------
        # Create Icons for buttons
        # -------------------------------------
        load_icon = get32Icon('folder')
        save_icon = get32Icon('file_save_as')
        # -------------------------------------
        # Set Icons for buttons
        # -------------------------------------
        #self.loadButton.setIconSize(QSize(32, 32))
        #self.loadButton.setIcon(load_icon)

        #self.saveButton.setIconSize(QSize(32, 32))
        #self.saveButton.setIcon(save_icon)

        # -------------------------------------
        # Create Icons for actions
        # -------------------------------------
        load_icon = get16Icon('folder')
        save_icon = get16Icon('file_save_as')
        exit_icon = get16Icon('cancel')
        overview_icon = get16Icon('tree_list')
        create_icon = get16Icon('application_add')
        reload_icon = get16Icon('arrow_rotate_clockwise')
        help_icon = get16Icon('help')
        info_icon = get16Icon('information')
        refresh_icon = get16Icon('arrow_refresh')
        delete_icon = get16Icon('delete')
        view_icon = get16Icon('reviewing_pane')

        # -------------------------------------
        # Set Icons for actions
        # -------------------------------------
        self.actionLoad.setIcon(load_icon)
        self.actionSave.setIcon(save_icon)
        self.actionExit.setIcon(exit_icon)
        self.actionOverview.setIcon(overview_icon)
        self.actionCreate.setIcon(create_icon)
        self.actionReload_Plugin_DB.setIcon(reload_icon)
        self.actionReloadConfig.setIcon(reload_icon)
        self.actionPaPI_Wiki.setIcon(help_icon)
        self.actionPaPI_Doc.setIcon(help_icon)
        self.actionAbout.setIcon(info_icon)
        self.actionAbout_Qt.setIcon(info_icon)
        self.actionAbout_PySide.setIcon(info_icon)
        self.actionResetPaPI.setIcon(delete_icon)
        self.actionRunMode.setIcon(view_icon)

        # -------------------------------------
        # Set Icons visible in menu
        # -------------------------------------
        self.actionLoad.setIconVisibleInMenu(True)
        self.actionSave.setIconVisibleInMenu(True)
        self.actionExit.setIconVisibleInMenu(True)
        self.actionOverview.setIconVisibleInMenu(True)
        self.actionCreate.setIconVisibleInMenu(True)
        self.actionReload_Plugin_DB.setIconVisibleInMenu(True)
        self.actionReloadConfig.setIconVisibleInMenu(True)
        self.actionPaPI_Wiki.setIconVisibleInMenu(True)
        self.actionPaPI_Doc.setIconVisibleInMenu(True)
        self.actionAbout.setIconVisibleInMenu(True)
        self.actionAbout_Qt.setIconVisibleInMenu(True)
        self.actionAbout_PySide.setIconVisibleInMenu(True)
        self.actionResetPaPI.setIconVisibleInMenu(True)
        self.actionRunMode.setIconVisibleInMenu(True)

    def get_gui_config(self, saveUserSettings=False):

        actTab = {}
        actTab['Active'] = str(self.TabManager.get_currently_active_tab())

        tabs = {}
        tab_dict = self.TabManager.get_tabs_by_uname()
        for tab in tab_dict:
            tabOb = tab_dict[tab]
            tabs[tab] = {}
            tabs[tab]['Background'] = tabOb.background
            tabs[tab]['Position'] = str(
                self.TabManager.getTabPosition_by_name(tab))

        size = {}

        size['X'] = str(self.size().width())

        size['Y'] = str(self.size().height())

        cfg = {}
        cfg['ActiveTab'] = actTab
        cfg['Tabs'] = tabs
        cfg['Size'] = size

        # ----------------------
        # Set favourite plugins
        # ----------------------
        if saveUserSettings:
            favourites = {}
            actions = self.toolBar.actions()
            for i in range(len(actions)):
                action = actions[i]
                if isinstance(action, PaPIFavAction):
                    favourites[action.text()] = {}
                    favourites[action.text()]['position'] = str(i)

            cfg['Favourites'] = favourites

        return cfg

    def set_gui_config(self, cfg):
        #print(cfg)
        # #################
        # # Cfgs for Tabs #
        # #################
        # if 'tabs' in cfg:
        #     tabList = {}
        #     for tab in cfg['tabs']:
        #         # Tab Name
        #         name = tab
        #
        #         # Tab details
        #         tabDetails = cfg['tabs'][tab]
        #
        #         # check for background
        #         if 'background' in tabDetails:
        #             bg = tabDetails['background']
        #             if bg != 'default':
        #                 self.TabManager.set_background_for_tab_with_name(name,bg)
        #         else:
        #             bg = None
        #
        #         # check for position
        #         if 'position' in tabDetails:
        #             pos = int(tabDetails['position'])
        #         else:
        #             if len(list(tabList.keys())) > 1:
        #                 pos = max(list(tabList.keys()))+1
        #             else:
        #                 pos = 0
        #
        #         tabList[pos] = [name, bg]
        #
        #     # sort tabs acoriding to positions
        #     keys = list(tabList.keys())
        #     keys.sort()
        #     for position in keys:
        #         name = tabList[position][0]
        #         bg = tabList[position][1]
        #         tabOb = self.TabManager.add_tab(name)
        #         self.TabManager.set_background_for_tab_with_name(name,bg)
        #
        # if 'activeTab' in cfg:
        #     if 'value' in cfg['activeTab']['active']:
        #         self.TabManager.set_tab_active_by_index(int( cfg['activeTab']['active']['value'] ))
        #
        #################
        # windows size: #
        #################
        if 'Size' in cfg:
            w = int(cfg['Size']['X'])
            h = int(cfg['Size']['Y'])
            self.resize_gui_window(w, h)

        # ------------------------
        # Restore favourite icons
        # ------------------------
        if 'Favourites' in cfg:
            sorted_positions = {}

            for plugin in cfg['Favourites']:
                sorted_positions[int(
                    cfg['Favourites'][plugin]['position'])] = plugin

            for position in sorted(sorted_positions.keys()):
                plugin = sorted_positions[position]
                self.addFavPlugin(plugin)

        # -----------------------
        # Restore Tabs
        # -----------------------
        if 'Tabs' in cfg:
            for tabName in cfg['Tabs']:
                tab = cfg['Tabs'][tabName]
                self.TabManager.add_tab(tabName)
                if 'Background' in tab:
                    self.TabManager.set_background_for_tab_with_name(
                        tabName, tab['Background'])

    def triggered_reload_plugin_db(self):
        """
        This Callback function will reload the plugin list of the plugin manager

        :return:
        """
        self.gui_management.plugin_manager.collectPlugins()

    def run(self):
        """


        :return:
        """
        # create a timer and set interval for processing events with working loop

        #QtCore.QTimer.singleShot(GUI_WOKRING_INTERVAL, lambda: self.gui_event_processing.gui_working(self.closeEvent))
        self.workingTimer = QtCore.QTimer(self)
        self.workingTimer.timeout.connect(
            lambda: self.gui_management.gui_event_processing.gui_working(
                self.closeEvent, self.workingTimer))
        self.workingTimer.start(pc.GUI_WOKRING_INTERVAL)

    def triggered_show_create_plugin_menu(self):
        """


        :return:
        """
        self.create_plugin_menu = CreatePluginMenu(
            self.gui_management.gui_api, self.TabManager,
            self.gui_management.plugin_manager)

        self.create_plugin_menu.show()

    def triggered_show_overview_menu(self):
        """
        Used to show the overview menu.

        :return:
        """
        self.overview_menu = OverviewPluginMenu(
            self.gui_management.gui_api, self.gui_management.tab_manager)
        self.overview_menu.show()

    def triggered_show_toolbar(self):
        """
        Used to hide and unhide the toolbar
        :return:
        """

        self.toolBar.setHidden(not self.toolBar.isHidden())

        self.actionToolbar.setChecked(not self.toolBar.isHidden())

    def triggered_load(self):
        """
        Used to start the 'load config' dialog.

        :return:
        """
        fileNames = ''

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setNameFilter(self.tr("PaPI-Cfg (*.xml)"))
        dialog.setDirectory(pc.CONFIG_DEFAULT_DIRECTORY)
        dialog.setWindowTitle("Load Configuration")

        if dialog.exec_():
            fileNames = dialog.selectedFiles()

        if len(fileNames):
            if fileNames[0] != '':
                self.last_config = fileNames[0]
                self.load_config(fileNames[0])

    def load_config(self, file_name):
        self.gui_management.gui_api.do_load_xml(file_name)

    def triggered_save(self):
        """
        Used to start the 'save config' dialog.

        :return:
        """
        fileNames = ''

        dialog = PaPIConfigSaveDialog(self, self.gui_management.gui_api)

        dialog.fill_with()

        if dialog.exec_():
            fileNames = dialog.selectedFiles()

        plugin_list, subscription_list = dialog.get_create_lists()

        if len(fileNames):

            if fileNames[0] != '':
                if "json" in dialog.selectedNameFilter():
                    self.gui_management.gui_api.do_save_json_config_reloaded(
                        fileNames[0],
                        plToSave=plugin_list,
                        sToSave=subscription_list)

                if "xml" in dialog.selectedNameFilter():
                    self.gui_management.gui_api.do_save_xml_config_reloaded(
                        fileNames[0],
                        plToSave=plugin_list,
                        sToSave=subscription_list)

    def closeEvent(self, *args, **kwargs):
        """
        Handle close event.
        Saves current session as 'papi/last_active_papi.xml'
        Closes all opened windows.

        :param args:
        :param kwargs:
        :return:
        """
        try:
            self.gui_management.gui_api.do_save_xml_config(
                'papi/last_active_papi.xml')
        except Exception as E:
            tb = traceback.format_exc()

        self.gui_management.gui_api.do_close_program()
        if self.create_plugin_menu is not None:
            self.create_plugin_menu.close()

        if self.overview_menu is not None:
            self.overview_menu.close()

        self.close()

    def add_dplugin(self, dplugin):
        """
        Callback function called by 'DPlugin added signal'
        Used to add a DPlugin SubWindow on the GUI if possible.

        :param dplugin:
        :return:
        """
        if dplugin.type == pc.PLUGIN_VIP_IDENTIFIER:

            # sub_window_ori = dplugin.plugin.get_sub_window()
            #
            # dplugin.plugin.set_window_for_internal_usage(PaPIMDISubWindow())
            # dplugin.plugin.pl_set_widget_for_internal_usage(sub_window_ori.widget())

            sub_window = dplugin.plugin._get_sub_window()

            config = dplugin.startup_config
            tab_name = config['tab']['value']
            if tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]
            else:
                self.log.printText(
                    1, 'add dplugin: no tab with tab_id of dplugin')
                area = self.TabManager.add_tab(tab_name)

            area.addSubWindow(sub_window)

            isMaximized = config['maximized']['value'] == '1'

            size_re = re.compile(r'([0-9]+)')

            pos = config['position']['value']
            window_pos = size_re.findall(pos)
            sub_window.move(int(window_pos[0]), int(window_pos[1]))

            if not isMaximized:
                sub_window.show()
            else:
                sub_window.showMaximized()

            # see http://qt-project.org/doc/qt-4.8/qt.html#WindowType-enum

            sub_window.setWindowFlags(Qt.CustomizeWindowHint
                                      | Qt.WindowMinMaxButtonsHint
                                      | Qt.WindowTitleHint)

        if self.overview_menu is not None:
            self.overview_menu.refresh_action(dplugin)

    def remove_dplugin(self, dplugin):
        """
        Callback function called by 'DPlugin removed signal'
        Used to removed a DPlugin SubWindow from the GUI if possible.

        :param dplugin:
        :return:
        """
        if dplugin.type == pc.PLUGIN_VIP_IDENTIFIER:
            config = dplugin.plugin.pl_get_current_config()
            tab_name = config['tab']['value']
            if tab_name in self.TabManager.get_tabs_by_uname():
                tabOb = self.TabManager.get_tabs_by_uname()[tab_name]
                tabOb.removeSubWindow(dplugin.plugin._get_sub_window())
                if tabOb.closeIfempty is True:
                    if len(tabOb.subWindowList()) == 0:
                        if isinstance(tabOb, TabObject):
                            self.TabManager.closeTab_by_name(tabOb.name)
                        else:
                            self.TabManager.remove_window(tabOb)

    def changed_dgui(self):
        if self.overview_menu is not None:
            self.overview_menu.refresh_action()

    def plugin_died(self, dplugin, e, msg):
        dplugin.state = pc.PLUGIN_STATE_STOPPED

        self.gui_management.gui_api.do_stopReset_plugin_uname(dplugin.uname)

        errMsg = QtGui.QMessageBox(self)
        errMsg.setFixedWidth(650)

        # layout = errMsg.layout();
        # spacer = QtGui.QSpacerItem(1000, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        # layout.addItem(spacer, layout.rowCount(), 0,1, layout.columnCount())

        errMsg.setIcon(QtGui.QMessageBox.Critical)
        errMsg.setSizeGripEnabled(True)
        errMsg.setWindowTitle("Plugin: " + dplugin.uname + " // " + str(e))
        errMsg.setText("Error in plugin" + dplugin.uname + " // " + str(e))
        errMsg.setDetailedText(str(msg))
        errMsg.setWindowModality(Qt.NonModal)
        errMsg.show()

    def error_occured(self, title, msg, detailed_msg):

        errMsg = QtGui.QMessageBox(self)
        errMsg.setFixedWidth(650)

        errMsg.setWindowTitle(title)
        errMsg.setText(str(msg))
        errMsg.setDetailedText(str(detailed_msg))
        errMsg.setWindowModality(Qt.NonModal)
        errMsg.show()

    def toggle_run_mode(self):
        if self.in_run_mode is False:
            # hide toolbar
            self.toolBar.setHidden(True)
            self.actionToolbar.setChecked(False)
            # disable context menu of tabmanger
            self.TabManager.disableContextMenus()

            # lock subwindows in tabs
            for tabName in self.TabManager.tab_dict_uname:
                tabObject = self.TabManager.tab_dict_uname[tabName]

                for subWindow in tabObject.subWindowList():
                    subWindow.disableInteraction()
            self.in_run_mode = True
        else:
            # show toolbar
            self.toolBar.setHidden(False)
            self.actionToolbar.setChecked(True)
            # disable context menu of tabmanger
            self.TabManager.enableContextMenus()

            # unlock subwindows in tabs
            for tabName in self.TabManager.tab_dict_uname:
                tabObject = self.TabManager.tab_dict_uname[tabName]

                for subWindow in tabObject.subWindowList():
                    subWindow.enableInteraction()
            self.in_run_mode = False

    def toogle_lock(self):
        raise Exception("PLEASE REPORT THIS BUG!!")
        if self.in_run_mode:
            for tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]

                windowsList = area.subWindowList()

                for window in windowsList:

                    #window.setAttribute(Qt.WA_NoBackground)

                    #window.setAttribute(Qt.WA_NoSystemBackground)
                    #window.setAttribute(Qt.WA_TranslucentBackground)
                    #window.set_movable(False)
                    window.setMouseTracking(False)
                    window.setWindowFlags(~Qt.WindowMinMaxButtonsHint
                                          & (Qt.CustomizeWindowHint
                                             | Qt.WindowTitleHint))

        if not self.in_run_mode:
            for tab_name in self.TabManager.get_tabs_by_uname():
                area = self.TabManager.get_tabs_by_uname()[tab_name]

                windowsList = area.subWindowList()

                for window in windowsList:
                    #window.set_movable(True)
                    window.setMouseTracking(True)
                    window.setWindowFlags(Qt.CustomizeWindowHint
                                          | Qt.WindowMinMaxButtonsHint
                                          | Qt.WindowTitleHint)

    def keyPressEvent(self, event):
        if event.key() not in self.keysActiveList:
            self.keysActiveList.append(event.key())

        if QtCore.Qt.Key_Escape in self.keysActiveList:
            if self.in_run_mode:
                self.toggle_run_mode()

        if QtCore.Qt.Key_D in self.keysActiveList and QtCore.Qt.Key_Control in self.keysActiveList:
            self.gui_management.tab_manager.select_next_tab()
            self.keysActiveList.remove(QtCore.Qt.Key_D)
            #self.keysActiveList.remove(QtCore.Qt.Key_Control)

        if QtCore.Qt.Key_A in self.keysActiveList and QtCore.Qt.Key_Control in self.keysActiveList:
            self.gui_management.tab_manager.select_prev_tab()
            self.keysActiveList.remove(QtCore.Qt.Key_A)
            #self.keysActiveList.remove(QtCore.Qt.Key_Control)

    def keyReleaseEvent(self, event):
        if event.key() in self.keysActiveList:
            self.keysActiveList.remove(event.key())

    def resize_gui_window(self, w, h):
        self.setGeometry(self.geometry().x(), self.geometry().y(), w, h)

    def triggered_reload_config(self):
        """
        This function is used to reset PaPI and to reload the last loaded configuration file.
        :return:
        """
        if self.last_config is not None:
            self.triggered_reset_papi()
            QtCore.QTimer.singleShot(
                pc.GUI_WAIT_TILL_RELOAD, lambda: self.gui_management.gui_api.
                do_load_xml(self.last_config))

    def triggered_reset_papi(self):
        """
        This function is called to reset PaPI. That means all subscriptions were canceled and all plugins were removed.
        :return:
        """
        h = pc.GUI_DEFAULT_HEIGHT
        w = pc.GUI_DEFAULT_WIDTH
        self.setGeometry(self.geometry().x(), self.geometry().y(), w, h)

        self.TabManager.set_all_tabs_to_close_when_empty(True)
        self.TabManager.close_all_empty_tabs()

        self.gui_management.gui_api.do_reset_papi()

    def triggered_papi_wiki(self):
        QDesktopServices.openUrl(QUrl(pc.PAPI_WIKI_URL, QUrl.TolerantMode))

    def triggered_papi_doc(self):
        QDesktopServices.openUrl(QUrl(pc.PAPI_DOC_URL, QUrl.TolerantMode))

    def triggered_papi_about(self):
        QMessageBox.about(self, pc.PAPI_ABOUT_TITLE, pc.PAPI_ABOUT_TEXT)

    def triggered_papi_about_qt(self):
        QMessageBox.aboutQt(self)

    def toolbarAddFavPlugin(self, plugin_info):

        l = len(plugin_info.name)
        path = plugin_info.path[:-l]
        path += 'box.png'
        px = QPixmap(path)

        icon = QIcon(px)

        for action in self.toolBar.actions():
            if action.text() == plugin_info.name:
                return

        plugin_action = PaPIFavAction(icon, plugin_info.name, self)
        plugin_action.triggered.connect(
            lambda ignore, p1=plugin_info: self.show_create_plugin_dialog(p1))

        self.toolBar.addAction(plugin_action)

        self.gui_management.gui_api.do_save_xml_config_reloaded(
            pc.PAPI_USER_CFG, plToSave=[], sToSave=[], saveUserSettings=True)

    def show_create_plugin_dialog(self, plugin_info):
        if plugin_info is not None:
            if plugin_info.loadable:
                self.plugin_create_dialog.set_plugin(plugin_info)
                self.plugin_create_dialog.show()

    def dropEvent(self, event: QDropEvent):
        source = event.source()
예제 #13
0
class CreatePluginMenu(QMainWindow, Ui_PluginCreateMenu):
    def __init__(self, gui_api, TabManger, plugin_manager, parent=None):
        super(CreatePluginMenu, self).__init__(parent)
        self.setupUi(self)
        self.dgui = gui_api.gui_data
        self.TabManager = TabManger

        self.gui_api = gui_api

        self.subscriberID = None
        self.targetID = None
        self.blockName = None

        self.plugin_manager = plugin_manager

        self.pluginTree.setDragEnabled(True)
        self.pluginTree.setDropIndicatorShown(True)

        self.setWindowTitle('Available Plugins')

        model = PaPITreeModel()
        model.setHorizontalHeaderLabels(['Name'])

        self.pluginProxyModel = PaPITreeProxyModel(self)
        self.pluginProxyModel.setSourceModel(model)

        regex = QRegExp("*", Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

        self.pluginTree.setModel(self.pluginProxyModel)
        self.pluginTree.setUniformRowHeights(True)
        self.pluginTree.setSortingEnabled(True)
        self.pluginTree.setStyleSheet(pc.TREE_CSS)

        self.plugin_roots = {}

        self.configuration_inputs = {}

        self.pluginTree.clicked.connect(self.pluginItemChanged)

        self.plugin_create_dialog = CreatePluginDialog(self.gui_api,
                                                       self.TabManager)

        self.createButton.clicked.connect(self.show_create_plugin_dialog)
        self.helpButton.clicked.connect(self.help_button_triggered)
        self.finder = ModuleFinder()

        self.pluginSearchText.textChanged.connect(
            self.changed_search_plugin_text_field)

        self.pluginSearchText.setFocus(Qt.OtherFocusReason)
        self.helpButton.setText('')
        self.helpButton.setIcon(get16Icon('help.png'))
        self.helpButton.setToolTip(
            'Opens the documentation for the currently selected plugin.')

    def keyPressEvent(self, event):

        if event.key() in [Qt.Key_Right, Qt.Key_Space]:
            index = self.pluginTree.currentIndex()
            self.pluginItemChanged(index)

        if event.key() == Qt.Key_Escape:
            self.close()

        # Use enter/return to bring up the dialog for a selected plugin
        if (event.key() == Qt.Key_Return
                or event.key() == Qt.Key_Enter) and self.pluginTree.hasFocus():
            self.show_create_plugin_dialog()

        # if search bar has focus and user pressed enter/return,arrow up/down, change focus to the plugin tree
        if (event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter or event.key() == Qt.Key_Down \
            or event.key() == Qt.Key_Up) and self.pluginSearchText.hasFocus():
            self.pluginTree.setFocus(Qt.OtherFocusReason)

    def pluginItemChanged(self, index):
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        self.clear()

        self.scrollArea.setDisabled(True)

        if plugin_info is None:
            return

        self.scrollArea.setDisabled(False)

        self.nameEdit.setText(plugin_info.name)
        self.authorEdit.setText(plugin_info.author)
        self.descriptionText.setText(plugin_info.description)
        self.pathEdit.setText(plugin_info.path)

        self.createButton.setEnabled(plugin_info.loadable)

        lines = None
        with open(plugin_info.path + '.py') as f:
            lines = f.readlines()

        found_imports = []

        for line in lines:
            if line.startswith('import'):

                m = re.search('(import)\s+([\w.]*)(\s+as){0,1}',
                              str.strip(line))
                if m is not None:
                    if len(m.groups()) > 2:
                        found_imports.append(m.group(2))

            if line.startswith('from'):
                m = re.search('(from)\s+([\w.]*)(\s+import)', str.strip(line))
                if m is not None:
                    if len(m.groups()) > 2:
                        found_imports.append(m.group(2))
        found_imports.sort()

        for imp in found_imports:
            item = QListWidgetItem(imp)

            spam_loader = importlib.find_loader(imp)
            found = spam_loader is not None
            if not found:
                self.modulesList.addItem(item)
                item.setBackground(QColor(255, 0, 0, 50))

        if not plugin_info.loadable:

            self.modulesList.setEnabled(True)
            self.modulesLabel.setEnabled(True)

    def show_create_plugin_dialog(self):
        index = self.pluginTree.currentIndex()
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        if plugin_info is not None:
            if plugin_info.loadable:
                self.plugin_create_dialog.set_plugin(plugin_info)
                self.plugin_create_dialog.show()

    def showEvent(self, *args, **kwargs):

        self.plugin_manager.locatePlugins()
        candidates = self.plugin_manager.getPluginCandidates()
        all_pluginfo = {c[2].path: c[2] for c in candidates}
        loadable_pluginfo = {
            p.path: p
            for p in self.plugin_manager.getAllPlugins()
        }

        for pluginfo in all_pluginfo.values():

            if pluginfo.path in loadable_pluginfo.keys():
                pluginfo = loadable_pluginfo[pluginfo.path]
                pluginfo.loadable = True
            else:
                pluginfo.loadable = False
            plugin_item = PluginTreeItem(pluginfo)

            plugin_root = self.get_plugin_root(pluginfo.path)
            plugin_root.appendRow(plugin_item)

        for root in sorted(self.plugin_roots.keys()):
            self.pluginTree.model().sourceModel().appendRow(
                self.plugin_roots[root])
            self.plugin_roots[root].sortChildren(0)

    def help_button_triggered(self):
        index = self.pluginTree.currentIndex()
        plugin_info = self.pluginTree.model().data(index, Qt.UserRole)

        if plugin_info is not None:

            path = plugin_info.path
            plugin_type = path.split('/')[-3]
            suffix = "." + '.'.join(path.split('/')[-2:])
            target_url = pc.PAPI_DOC_URL + pc.PAPI_DOC_PREFIX_PLUGIN + "." + plugin_type.lower(
            ) + suffix + ".html"
            QDesktopServices.openUrl(QUrl(target_url, QUrl.TolerantMode))

    def get_plugin_root(self, path):
        parts = path.split('/')
        part = parts[-3]
        name = part
        if part not in self.plugin_roots:

            cfg_file = str.join("/", parts[0:-2]) + "/" + pc.GUI_PLUGIN_CONFIG

            if os.path.isfile(cfg_file):
                config = configparser.ConfigParser()
                config.read(cfg_file)
                if 'Config' in config.sections():
                    if 'name' in config.options('Config'):
                        name = config.get('Config', 'name')

            self.plugin_roots[part] = PaPIRootItem(name)

        return self.plugin_roots[part]

    def changed_search_plugin_text_field(self, value):

        if not len(value):
            value = "*"
            self.pluginTree.collapseAll()
        else:
            value = "*" + value + "*"
            self.pluginTree.expandAll()

        self.pluginProxyModel.sourceModel().mark_visibility_by_name(value)

        # Used to trigger filter action
        regex = QRegExp(value, Qt.CaseInsensitive, QRegExp.Wildcard)
        self.pluginProxyModel.setFilterRegExp(regex)

    def clear(self):
        self.nameEdit.setText('')
        self.authorEdit.setText('')
        self.descriptionText.setText('')
        self.pathEdit.setText('')
        self.modulesList.clear()
        self.modulesList.setEnabled(False)
        self.modulesLabel.setEnabled(False)

    def closeEvent(self, *args, **kwargs):
        self.plugin_create_dialog.close()