Esempio n. 1
0
    def add_to_persistent_pipeline(self, pipeline):
        """add_to_persistent_pipeline(pipeline):
        (module_id_map, connection_id_map, modules_added)
        Adds a pipeline to the persistent pipeline of the cached interpreter
        and adds current logging object to each existing module.

        Returns four things: two dictionaries describing the mapping
        of ids from the passed pipeline to the persistent one (the
        first one has the module id mapping, the second one has the
        connection id mapping), a set of all module ids added to the
        persistent pipeline, and a set of all connection ids added to
        the persistent pipeline."""
        module_id_map = Bidict()
        connection_id_map = Bidict()
        modules_added = set()
        connections_added = set()
        pipeline.refresh_signatures()
        # we must traverse vertices in topological sort order
        verts = pipeline.graph.vertices_topological_sort()
        for new_module_id in verts:
            new_sig = pipeline.subpipeline_signature(new_module_id)
            if not self._persistent_pipeline.has_subpipeline_signature(
                    new_sig):
                # Must add module to persistent pipeline
                persistent_module = copy.copy(pipeline.modules[new_module_id])
                persistent_id = self._persistent_pipeline.fresh_module_id()
                persistent_module.id = persistent_id
                self._persistent_pipeline.add_module(persistent_module)
                self._persistent_pipeline.modules[persistent_id]._signature = \
                    base64.b16encode(new_sig).lower()
                module_id_map[new_module_id] = persistent_id
                modules_added.add(new_module_id)
            else:
                i = self._persistent_pipeline \
                        .subpipeline_id_from_signature(new_sig)
                module_id_map[new_module_id] = i
        for connection in pipeline.connections.itervalues():
            new_sig = pipeline.connection_signature(connection.id)
            if not self._persistent_pipeline.has_connection_signature(new_sig):
                # Must add connection to persistent pipeline
                persistent_connection = copy.copy(connection)
                persistent_id = self._persistent_pipeline.fresh_connection_id()
                persistent_connection.id = persistent_id
                persistent_connection.sourceId = module_id_map[
                    connection.sourceId]
                persistent_connection.destinationId = module_id_map[
                    connection.destinationId]
                self._persistent_pipeline.add_connection(persistent_connection)
                connection_id_map[connection.id] = persistent_id
                connections_added.add(connection.id)
            else:
                i = self._persistent_pipeline \
                        .connection_id_from_signature(new_sig)
                connection_id_map[connection.id] = i
        # update persistent signatures
        self._persistent_pipeline.compute_signatures()
        return (module_id_map, connection_id_map, modules_added,
                connections_added)
Esempio n. 2
0
    def __init__(self, controller, panel, parent=None):
        """ QAliasList(parent: QWidget) -> QAliasTable

        """
        QtGui.QTreeWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
                           QtGui.QSizePolicy.Expanding)
        self.setRootIsDecorated(False)
        self.panel = panel
        self.aliases = Bidict()
        self.alias_widgets = {}
        self.controller = controller
        self.header().setStretchLastSection(True)
        self.setHeaderLabels(["Position", "Name", "Type"])
        self.itemSelectionChanged.connect(self.setPreviousSelected)
        self.connect(self,
                     QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"),
                     self.currentAliasChanged)
        self.previousSelected = -1
Esempio n. 3
0
    def build_widget(self):
        layout = QtGui.QVBoxLayout()
        layout.setMargin(4)
        layout.setSpacing(2)
        self.searchBox = QSearchBox(True, False, self)
        layout.addWidget(self.searchBox)
        options_layout = QtGui.QHBoxLayout()
        options_layout.setSpacing(5)
        options_layout.setAlignment(QtCore.Qt.AlignLeft)
        options_layout.addWidget(QtGui.QLabel("Search:"))
        searchAll = QtGui.QRadioButton("Open Vistrails")
        searchCurrent = QtGui.QRadioButton("Current Vistrail")
        searchWorkflow = QtGui.QRadioButton("Current Workflow")
        useRegex = QtGui.QCheckBox("Regular expression")
        self.level_group = QtGui.QButtonGroup()
        self.level_group.addButton(searchAll)
        self.level_group.addButton(searchCurrent)
        self.level_group.addButton(searchWorkflow)
        self.level_map = \
            Bidict([(QueryController.LEVEL_ALL, searchAll),
                    (QueryController.LEVEL_VISTRAIL, searchCurrent),
                    (QueryController.LEVEL_WORKFLOW, searchWorkflow)])
        options_layout.addWidget(searchAll)
        options_layout.addWidget(searchCurrent)
        options_layout.addWidget(searchWorkflow)
        options_layout.addWidget(useRegex)
        searchCurrent.setChecked(True)
        
        self.editButton = QtGui.QPushButton("Edit")
        self.editButton.setEnabled(False)
        self.backButton = QtGui.QPushButton("Back to Search")
        self.backButton.setEnabled(False)
        options_layout.addStretch(1)
        options_layout.addWidget(self.editButton, 0, QtCore.Qt.AlignRight)
        options_layout.addWidget(self.backButton, 0, QtCore.Qt.AlignRight)
        layout.addLayout(options_layout)
        self.setLayout(layout)

        self.connect(self.searchBox, QtCore.SIGNAL('resetSearch()'),
                     self.resetSearch)
        self.connect(self.searchBox, QtCore.SIGNAL('executeSearch(QString)'),
                     self.executeSearch)
        self.connect(self.searchBox, QtCore.SIGNAL('refineMode(bool)'),
                     self.refineMode)
        self.connect(self.backButton, QtCore.SIGNAL('clicked()'),
                     self.backToSearch)
        self.connect(self.editButton, QtCore.SIGNAL('clicked()'),
                     self.doEdit)
        self.connect(self.level_group, 
                     QtCore.SIGNAL('buttonClicked(QAbstractButton*)'),
                     self.levelChanged)
        self.connect(useRegex, QtCore.SIGNAL('stateChanged(int)'),
                     self.useRegexChanged)
Esempio n. 4
0
    def __init__(self, controller, panel, parent=None):
        """ QAliasList(parent: QWidget) -> QAliasTable

        """
        QtGui.QTreeWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
                           QtGui.QSizePolicy.Expanding)
        self.setRootIsDecorated(False)
        self.panel = panel
        self.aliases = Bidict()
        self.alias_widgets = {}
        self.controller = controller
        self.header().setStretchLastSection(True)
        self.setHeaderLabels(["Position", "Name", "Type"])
        self.itemSelectionChanged.connect(self.setPreviousSelected)
        self.connect(self,
                     QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"),
                     self.currentAliasChanged)
        self.previousSelected = -1
Esempio n. 5
0
class QQueryView(QtGui.QWidget, BaseView):
    VISUAL_SEARCH_VIEW = 0
    GLOBAL_RESULT_VIEW = 1
    VERSION_RESULT_VIEW = 2
    WORKFLOW_RESULT_VIEW = 3

    RESULT_LEVEL_MAP = \
        Bidict([(QueryController.LEVEL_ALL, GLOBAL_RESULT_VIEW),
                (QueryController.LEVEL_VISTRAIL, VERSION_RESULT_VIEW),
                (QueryController.LEVEL_WORKFLOW, WORKFLOW_RESULT_VIEW)])

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        BaseView.__init__(self)
        self.build_widget()
        self.set_title("Search")

    def set_controller(self, controller=None):
        if self.controller:
            self.disconnect(self.controller, QtCore.SIGNAL('stateChanged'),
                            self.update_controller)
        self.controller = controller
        if controller:
            self.connect(self.controller, QtCore.SIGNAL('stateChanged'),
                         self.update_controller)
        self.vt_controller.vistrail_view = self.version_result_view
        self.vt_controller.current_pipeline_view = \
            self.workflow_result_view
        # self.vt_controller.vistrail_view.set_controller(self.vt_controller)
        # FIXME Need to figure out how to deal with this !!!
        self.vt_controller.set_vistrail(controller.vistrail,
                                        None,
                                        set_log_on_vt=False)
        hide_upgrades = not getattr(get_vistrails_configuration(),
                                    'hideUpgrades', True)
        self.vt_controller.change_selected_version(controller.current_version,
                                                   hide_upgrades,
                                                   hide_upgrades)
        self.version_result_view.set_controller(self.vt_controller)
        self.workflow_result_view.set_controller(self.vt_controller)
        self.query_controller.set_vistrail_controller(controller)

    def update_controller(self):
        # FIXME Need to figure out how to deal with this !!!
        self.vt_controller.set_vistrail(self.controller.vistrail,
                                        None,
                                        set_log_on_vt=False)
        hide_upgrades = getattr(get_vistrails_configuration(), 'hideUpgrades',
                                True)
        self.vt_controller.change_selected_version(
            self.controller.current_version, hide_upgrades, hide_upgrades)

    def build_widget(self):
        layout = QtGui.QVBoxLayout()
        layout.setMargin(0)
        layout.setSpacing(0)

        self.query_controller = QueryController(self)
        self.vt_controller = VistrailController(auto_save=False)
        self.p_controller = VistrailController(Vistrail(), auto_save=False)

        self.connect(self.p_controller, QtCore.SIGNAL('vistrailChanged()'),
                     self.vistrailChanged)

        self.query_box = QQueryBox()
        self.query_box.set_controller(self.query_controller)
        layout.addWidget(self.query_box)

        self.stacked_widget = QtGui.QStackedWidget()
        self.pipeline_view = QQueryPipelineView()
        self.p_controller.current_pipeline_view = self.pipeline_view
        self.pipeline_view.set_controller(self.p_controller)
        self.pipeline_view.set_query_controller(self.query_controller)
        QQueryView.VISUAL_SEARCH_VIEW = \
            self.stacked_widget.addWidget(self.pipeline_view)
        self.global_result_view = QQueryResultGlobalView()
        QQueryView.GLOBAL_RESULT_VIEW = \
            self.stacked_widget.addWidget(self.global_result_view)
        self.version_result_view = QQueryResultVersionView()
        self.connect(self.version_result_view.scene(),
                     QtCore.SIGNAL('versionSelected(int,bool,bool,bool,bool)'),
                     self.result_version_selected)
        # self.version_result_view.set_controller(self.vt_controller)
        QQueryView.VERSION_RESULT_VIEW = \
            self.stacked_widget.addWidget(self.version_result_view)
        self.workflow_result_view = QQueryResultWorkflowView()
        # self.workflow_result_view.set_controller(self.vt_controller)
        QQueryView.WORKFLOW_RESULT_VIEW = \
            self.stacked_widget.addWidget(self.workflow_result_view)
        self.stacked_widget.setCurrentWidget(self.pipeline_view)
        layout.addWidget(self.stacked_widget)

        self.setLayout(layout)
        self.current_display = QQueryView.VISUAL_SEARCH_VIEW
        self.current_result_view = QQueryView.VERSION_RESULT_VIEW

    def set_default_layout(self):
        from vistrails.gui.module_palette import QModulePalette
        from vistrails.gui.module_info import QModuleInfo
        self.set_palette_layout({
            QtCore.Qt.LeftDockWidgetArea: QModulePalette,
            QtCore.Qt.RightDockWidgetArea: QModuleInfo,
        })

    def set_action_links(self):
        self.action_links = \
            { 'execute': ('query_pipeline_changed', self.set_execute_action) }

        # also add other notification here...
        from vistrails.gui.vistrails_window import _app
        _app.register_notification('query_pipeline_changed',
                                   self.set_reset_button)

    def set_reset_button(self, pipeline):
        self.query_box.setManualResetEnabled(self.pipeline_non_empty(pipeline))

    def set_result_level(self, level):
        view_idx = QQueryView.RESULT_LEVEL_MAP[level]
        if self.current_display != QQueryView.VISUAL_SEARCH_VIEW:
            self.set_display_view(view_idx)
        self.current_result_view = view_idx
        self.query_controller.update_results()

    def set_to_search_mode(self):
        self.set_display_view(QQueryView.VISUAL_SEARCH_VIEW)
        self.query_box.backButton.setEnabled(False)
        self.query_box.editButton.setEnabled(False)
        self.set_reset_button(self.p_controller.current_pipeline)

        from vistrails.gui.vistrails_window import _app
        _app.notify('query_pipeline_changed',
                    self.p_controller.current_pipeline)

    def set_to_result_mode(self):
        self.set_display_view(self.current_result_view)
        self.query_box.backButton.setEnabled(True)
        if self.query_controller.level >= QueryController.LEVEL_VISTRAIL:
            self.query_box.editButton.setEnabled(True)
        self.query_box.setManualResetEnabled(True)

        from vistrails.gui.vistrails_window import _app
        _app.notify('query_pipeline_changed',
                    self.p_controller.current_pipeline)

    def set_display_view(self, view_type):
        self.current_display = view_type
        self.stacked_widget.setCurrentIndex(view_type)

    def get_current_view(self):
        return self.stacked_widget.currentWidget()

    def set_action_defaults(self):
        self.action_defaults = \
            {
             'execute': [('setEnabled', True, self.set_execute_action),
                          ('setIcon', False, CurrentTheme.VISUAL_QUERY_ICON),
                          ('setToolTip', False, 'Execute a visual query')],
             'publishWeb': [('setEnabled', False, False)],
             'publishPaper': [('setEnabled', False, False)],
            }

    def set_execute_action(self, pipeline=None):
        if not self.vt_controller:
            return False
        if pipeline is None:
            pipeline = self.p_controller.current_pipeline
        if self.current_display == QQueryView.VISUAL_SEARCH_VIEW:
            return self.pipeline_non_empty(pipeline)
        return False

    def pipeline_non_empty(self, pipeline):
        return pipeline is not None and len(pipeline.modules) > 0

    def vistrailChanged(self):
        from vistrails.gui.vistrails_window import _app
        self.p_controller.current_pipeline.ensure_connection_specs()
        _app.notify('query_pipeline_changed',
                    self.p_controller.current_pipeline)

    def query_changed(self, query=None):
        if query is None:
            self.query_controller.reset_search()
        # FIXME add support for changing the query to something specific

    # DAK: removed this call as the query view maintains its own
    # "current version"
    # def version_changed(self, version_id):
    #     self.vt_controller.change_selected_version(version_id)
    #     self.version_result_view.select_current_version()
    #     self.query_controller.update_results()

    def result_version_selected(self,
                                version_id,
                                by_click,
                                do_validate=True,
                                from_root=False,
                                double_click=False):
        if by_click:
            hide_upgrades = getattr(get_vistrails_configuration(),
                                    'hideUpgrades', True)
            self.query_controller.search.setCurrentController(
                self.vt_controller)
            self.vt_controller.change_selected_version(version_id,
                                                       hide_upgrades,
                                                       hide_upgrades,
                                                       from_root)
            if double_click:
                self.query_controller.set_level(QueryController.LEVEL_WORKFLOW)
                self.query_controller.show_workflow_matches()
Esempio n. 6
0
 def get_vertex_map(g):
     return Bidict([(v, k) for (k, v) in enumerate(g.iter_vertices())])
Esempio n. 7
0
 def get_edge_map(g):
     itor = enumerate(imap(lambda x: x[2], g.iter_all_edges()))
     return Bidict([(v, k) for (k, v) in itor])
Esempio n. 8
0
class QAliasList(QtGui.QTreeWidget):
    """
    QAliasList just inherits from QListView to have a customized
    list and items

    """
    #signals
    aliasUpdated = pyqtSignal(Alias)
    aliasRemoved = pyqtSignal(str)
    highlightModule = pyqtSignal(int)

    def __init__(self, controller, panel, parent=None):
        """ QAliasList(parent: QWidget) -> QAliasTable

        """
        QtGui.QTreeWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
                           QtGui.QSizePolicy.Expanding)
        self.setRootIsDecorated(False)
        self.panel = panel
        self.aliases = Bidict()
        self.alias_widgets = {}
        self.controller = controller
        self.header().setStretchLastSection(True)
        self.setHeaderLabels(["Position", "Name", "Type"])
        self.itemSelectionChanged.connect(self.setPreviousSelected)
        self.connect(
            self,
            QtCore.SIGNAL(
                "currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"),
            self.currentAliasChanged)
        self.previousSelected = -1

    @pyqtSlot()
    def setPreviousSelected(self):
        if len(self.selectedItems()) == 1:
            item = self.selectedItems()[0]
            self.previousSelected = self.indexOfTopLevelItem(item)
        else:
            self.previousSelected = -1

    def processCellChanges(self, row, col):
        """ processCellChanges(row: int, col: int) -> None
        Event handler for capturing when the contents in a cell changes

        """
        item = self.item(row, col)
        if col == 0:
            old_alias = item.alias.alias
            new_alias = str(item.text())
            if new_alias in self.aliases.keys():
                QtGui.QMessageBox.warning(
                    self, "VisMashup", """Label name %s already exists. 
                                          Please type a different name. """ %
                    new_alias)
                item.setText(old_alias)
                return
            elif new_alias == '':
                del self.aliases[old_alias]
                wdgt = self.cellWidget(row, 1)
                del self.alias_widgets[wdgt]
                item.alias.alias = ''
                self.removeRow(row)
                wdgt.deleteLater()
                self.updateRowNumbers()
            else:
                self.aliases[new_alias] = self.aliases[old_alias]
                del self.aliases[old_alias]
                item.alias.alias = new_alias

        elif col == 1:
            wdgt = self.cellWidget(row, col)
            if wdgt is not None:
                item.alias.value = wdgt.contents()
        self.aliasUpdated.emit(item.alias)

    def currentAliasChanged(self, current, previous):
        if current:
            if ((previous is not None and current.alias != previous.alias)
                    or previous is None):
                self.highlightModule.emit(current.alias.component.vtmid)
        else:
            self.highlightModule.emit(-1)

    def _getOtherParameterInfo(self, pipeline, id, ptype):
        parameter = pipeline.db_get_object(ptype, id)
        return (parameter.type, parameter.strValue, 1, parameter.pos)

    def createAliasItem(self, alias):
        """ createAliasRow( alias: core.mashup.Alias) -> AliasItem
            Creates a row in the list
            
        """

        alias.pos = self.topLevelItemCount()
        labels = [str(alias.component.pos), str(alias.name), \
                  str(alias.component.type)]
        item = QAliasListItem(self, alias, labels)
        item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)

        return alias

    def populateFromMashup(self, mashupController):
        #print "populateFromMashup ", self , self.previousSelected
        if self.controller != mashupController:
            self.controller = mashupController
        self.itemSelectionChanged.disconnect(self.setPreviousSelected)
        self.aliases = {}
        self.alias_cache = {}
        self.alias_widgets = {}
        self.clear()
        mashup = self.controller.currentMashup
        if len(mashup.alias_list) > 0:
            for alias in mashup.alias_list:
                alias = self.createAliasItem(copy.copy(alias))
                self.aliases[alias.name] = alias

        if self.previousSelected > -1:
            if self.previousSelected >= self.topLevelItemCount():
                self.previousSelected = self.topLevelItemCount() - 1
            item = self.topLevelItem(self.previousSelected)
            self.setItemSelected(item, True)
            self.setCurrentItem(item)
        self.itemSelectionChanged.connect(self.setPreviousSelected)

    def updatePosNumbers(self):
        new_order = []
        for idx in range(self.topLevelItemCount()):
            item = self.topLevelItem(idx)
            new_order.append(item.alias.component.pos)
            item.setText(0, str(idx))
        return new_order

    def moveItemToNewPos(self, old, new):
        """moveItemToNewPos(old:int, new:int) -> None
        Move item from pos old to pos new
        
        """
        self.itemSelectionChanged.disconnect(self.panel.updateInspector)
        item = self.takeTopLevelItem(old)
        self.insertTopLevelItem(new, item)
        self.clearSelection()
        new_order = self.updatePosNumbers()
        self.setItemSelected(item, True)
        self.itemSelectionChanged.connect(self.panel.updateInspector)
        self.controller.reorderAliases(new_order)

    def keyPressEvent(self, event):
        """ keyPressEvent(event: QKeyEvent) -> None
         Capture 'Del', 'Backspace' for deleting aliases
       
        """
        if (event.key() in [QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete]):
            self.removeCurrentAlias()

    @pyqtSlot(bool)
    def removeCurrentAlias(self, checked=False):
        item = self.currentItem()
        if not item:
            return
        name = item.alias.name
        # item will get recreated after question dialog shows so keep only index
        pos = self.indexOfTopLevelItem(item)
        res = show_question(
            "Mashups",
            "Are you sure do you want to remove '%s' from the mashup?" % name,
            [YES_BUTTON, NO_BUTTON], NO_BUTTON)
        if res == YES_BUTTON:
            self.previousSelected = pos
            self.takeTopLevelItem(pos)
            del self.aliases[name]

            self.updatePosNumbers()
            if pos >= self.topLevelItemCount() - 1:
                pos = self.topLevelItemCount() - 1
            self.previousSelected = pos
            if pos != -1:
                new_item = self.topLevelItem(pos)
                self.setCurrentItem(new_item)
                self.setItemSelected(new_item, True)
            self.aliasRemoved.emit(name)
Esempio n. 9
0
class QAliasList(QtGui.QTreeWidget):
    """
    QAliasList just inherits from QListView to have a customized
    list and items

    """
    #signals
    aliasUpdated = pyqtSignal(Alias)
    aliasRemoved = pyqtSignal(str)
    highlightModule = pyqtSignal(int)
    
    def __init__(self, controller, panel, parent=None):
        """ QAliasList(parent: QWidget) -> QAliasTable

        """
        QtGui.QTreeWidget.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Expanding,
                           QtGui.QSizePolicy.Expanding)
        self.setRootIsDecorated(False)
        self.panel = panel
        self.aliases = Bidict()
        self.alias_widgets = {}
        self.controller = controller
        self.header().setStretchLastSection(True)
        self.setHeaderLabels(["Position", "Name", "Type"])
        self.itemSelectionChanged.connect(self.setPreviousSelected)
        self.connect(self,
                     QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"),
                     self.currentAliasChanged)
        self.previousSelected = -1
    
    @pyqtSlot() 
    def setPreviousSelected(self):
        if len(self.selectedItems()) == 1:
            item = self.selectedItems()[0]
            self.previousSelected = self.indexOfTopLevelItem(item)
        else:
            self.previousSelected = -1      
    
    def processCellChanges(self, row, col):
        """ processCellChanges(row: int, col: int) -> None
        Event handler for capturing when the contents in a cell changes

        """
        item = self.item(row, col)
        if col == 0:
            old_alias = item.alias.alias
            new_alias = str(item.text())
            if new_alias in self.aliases.keys():
                QtGui.QMessageBox.warning(self,
                                          "VisMashup",
                                          """Label name %s already exists. 
                                          Please type a different name. """ % 
                                          new_alias)
                item.setText(old_alias)
                return
            elif new_alias == '':
                del self.aliases[old_alias]
                wdgt = self.cellWidget(row, 1)
                del self.alias_widgets[wdgt]
                item.alias.alias = ''
                self.removeRow(row)
                wdgt.deleteLater()
                self.updateRowNumbers()
            else:
                self.aliases[new_alias] = self.aliases[old_alias]
                del self.aliases[old_alias]
                item.alias.alias = new_alias
                
        elif col == 1:
            wdgt = self.cellWidget(row,col)
            if wdgt is not None:
                item.alias.value = wdgt.contents()
        self.aliasUpdated.emit(item.alias)
        
    def currentAliasChanged(self, current, previous):
        if current:
            if ((previous is not None and current.alias != previous.alias) or
                previous is None):
                self.highlightModule.emit(current.alias.component.vtmid)
        else:
            self.highlightModule.emit(-1)
        
    def _getOtherParameterInfo(self, pipeline, id, ptype):
        parameter = pipeline.db_get_object(ptype,id)
        return (parameter.type, parameter.strValue, 1, parameter.pos)
        
    def createAliasItem(self, alias):
        """ createAliasRow( alias: core.mashup.Alias) -> AliasItem
            Creates a row in the list
            
        """
        
        alias.pos = self.topLevelItemCount()
        labels = [str(alias.component.pos), str(alias.name), \
                  str(alias.component.type)]
        item = QAliasListItem(self, alias, labels)
        item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable )
        
        return alias
     
    def populateFromMashup(self, mashupController):
        #print "populateFromMashup ", self , self.previousSelected    
        if self.controller != mashupController:
            self.controller = mashupController
        self.itemSelectionChanged.disconnect(self.setPreviousSelected)
        self.aliases = {}
        self.alias_cache = {}
        self.alias_widgets = {}
        self.clear()
        mashup = self.controller.currentMashup
        if len(mashup.alias_list) > 0:
            for alias in mashup.alias_list:
                alias = self.createAliasItem(copy.copy(alias))
                self.aliases[alias.name] = alias
        
        if self.previousSelected > -1:
            if self.previousSelected >= self.topLevelItemCount():
                self.previousSelected = self.topLevelItemCount()-1
            item = self.topLevelItem(self.previousSelected)
            self.setItemSelected(item, True)
            self.setCurrentItem(item)
        self.itemSelectionChanged.connect(self.setPreviousSelected)
            
    def updatePosNumbers(self):
        new_order = []
        for idx in range(self.topLevelItemCount()):
            item = self.topLevelItem(idx)
            new_order.append(item.alias.component.pos)
            item.setText(0,str(idx))
        return new_order
            
    def moveItemToNewPos(self, old, new):
        """moveItemToNewPos(old:int, new:int) -> None
        Move item from pos old to pos new
        
        """
        self.itemSelectionChanged.disconnect(self.panel.updateInspector)
        item = self.takeTopLevelItem(old)
        self.insertTopLevelItem(new,item)
        self.clearSelection()
        new_order = self.updatePosNumbers()
        self.setItemSelected(item, True)
        self.itemSelectionChanged.connect(self.panel.updateInspector)
        self.controller.reorderAliases(new_order)
            
    def keyPressEvent(self, event):
        """ keyPressEvent(event: QKeyEvent) -> None
         Capture 'Del', 'Backspace' for deleting aliases
       
        """       
        if (event.key() in [QtCore.Qt.Key_Backspace, QtCore.Qt.Key_Delete]):
            self.removeCurrentAlias()
                
    @pyqtSlot(bool)
    def removeCurrentAlias(self, checked=False):
        item = self.currentItem()
        if not item:
            return
        name = item.alias.name
        # item will get recreated after question dialog shows so keep only index
        pos = self.indexOfTopLevelItem(item)
        res = show_question("Mashups", 
                "Are you sure do you want to remove '%s' from the mashup?"%name,
                [YES_BUTTON, NO_BUTTON], NO_BUTTON)
        if res == YES_BUTTON:
            self.previousSelected = pos 
            self.takeTopLevelItem(pos)
            del self.aliases[name]

            self.updatePosNumbers()
            if pos >= self.topLevelItemCount() - 1:
                pos = self.topLevelItemCount() - 1
            self.previousSelected = pos
            if pos != -1:
                new_item = self.topLevelItem(pos)
                self.setCurrentItem(new_item)
                self.setItemSelected(new_item, True)
            self.aliasRemoved.emit(name)        
Esempio n. 10
0
class PortSpec(DBPortSpec):

    port_type_map = Bidict([('input', 'destination'), ('output', 'source'),
                            ('invalid', 'invalid')])
    end_point_map = Bidict([('source', PortEndPoint.Source),
                            ('destination', PortEndPoint.Destination),
                            ('invalid', PortEndPoint.Invalid)])

    ##########################################################################
    # Constructors and copy

    def __init__(self, *args, **kwargs):
        signature = None
        if 'signature' in kwargs:
            signature = kwargs['signature']
            del kwargs['signature']
        sigstring = None
        if 'sigstring' in kwargs:
            sigstring = kwargs['sigstring']
            del kwargs['sigstring']
        defaults = None
        if 'defaults' in kwargs:
            defaults = kwargs['defaults']
            del kwargs['defaults']
        labels = None
        if 'labels' in kwargs:
            labels = kwargs['labels']
            del kwargs['labels']
        values = None
        if 'values' in kwargs:
            values = kwargs['values']
            del kwargs['values']
        entry_types = None
        if 'entry_types' in kwargs:
            entry_types = kwargs['entry_types']
            del kwargs['entry_types']

        if 'items' in kwargs and 'portSpecItems' not in kwargs:
            kwargs['portSpecItems'] = kwargs['items']
            del kwargs['items']

        if 'optional' not in kwargs:
            kwargs['optional'] = 0  # False
        elif not isinstance(kwargs['optional'], (int, long)):
            if isinstance(kwargs['optional'], bool):
                if kwargs['optional']:
                    kwargs['optional'] = 1
                else:
                    kwargs['optional'] = 0
            else:
                raise VistrailsInternalError("Cannot parse 'optional' kw "
                                             "-- must be an int or bool")
        if 'min_conns' not in kwargs:
            kwargs['min_conns'] = 0
        elif kwargs['optional'] == 1 and kwargs['min_conns'] > 0:
            raise VistrailsInternalError("A mandatory port cannot be set "
                                         "to optional")
        if 'max_conns' not in kwargs:
            kwargs['max_conns'] = -1
        if kwargs['min_conns'] >= 0 and kwargs['max_conns'] >= 0 and \
                kwargs['min_conns'] > kwargs['max_conns']:
            raise VistrailsInternalError("Minimum number of connections "
                                         "cannot be greater than maximum "
                                         "number of connections")

        if 'sort_key' not in kwargs:
            kwargs['sort_key'] = -1
        if 'depth' not in kwargs:
            kwargs['depth'] = 0
        if 'id' not in kwargs:
            kwargs['id'] = -1
        if 'tooltip' in kwargs:
            self._tooltip = kwargs['tooltip']
            del kwargs['tooltip']
        else:
            self._tooltip = None

        if 'docstring' in kwargs:
            self._docstring = kwargs['docstring']
            del kwargs['docstring']
        else:
            self._docstring = None
        if 'shape' in kwargs:
            self._shape = kwargs['shape']
            del kwargs['shape']
        else:
            self._shape = None

        DBPortSpec.__init__(self, *args, **kwargs)

        if sum(1 for container in (self.port_spec_items, signature, sigstring)
               if container) > 1:
            raise ValueError("Please specify only one of portSpecItems,"
                             " signature, or sigstring kwargs.")
        self.create_spec_items(self.port_spec_items, signature, sigstring,
                               defaults, labels, values, entry_types)

        self._short_sigstring = None
        # if signature is not None:
        #     self.create_entries(signature)
        # if not self.sigstring and self._entries is not None:
        #     # create sigstring from entries
        #     self.create_sigstring_and_descriptors()
        # DAKOOP: removed this---we will check in module_registry and pipeline
        # validation, this way, we can let errors go all the way up
        #         elif self._entries is None and self.sigstring:
        #             # create entries from sigstring
        #             self.create_entries_and_descriptors()
        #         else:
        #             raise VistrailsInternalError("Need to specify signature or "
        #                                          "sigstring to create PortSpec")
        # if self._entries is not None and self._tooltip is None:
        #     self.create_tooltip()
        self.is_valid = True

    def __copy__(self):
        return PortSpec.do_copy(self)

    def do_copy(self, new_ids=False, id_scope=None, id_remap=None):
        cp = DBPortSpec.do_copy(self, new_ids, id_scope, id_remap)
        cp._short_sigstring = self._short_sigstring
        cp._tooltip = self._tooltip
        cp._shape = self._shape
        cp._docstring = self._docstring
        cp.is_valid = self.is_valid
        cp.__class__ = PortSpec
        # if cp._entries is not None:
        #     cp.create_tooltip()
        return cp

    @staticmethod
    def convert(_port_spec):
        if _port_spec.__class__ == PortSpec:
            return
        _port_spec.__class__ = PortSpec
        for _port_spec_item in _port_spec.db_portSpecItems:
            PortSpecItem.convert(_port_spec_item)
        _port_spec._short_sigstring = None
        _port_spec._tooltip = None
        _port_spec._shape = None
        _port_spec._docstring = None
        _port_spec.is_valid = True

        _port_spec.port_spec_items.sort(key=operator.attrgetter('db_pos'))

    @staticmethod
    def from_sigstring(sigstring):
        """from_sig(sigstring: string) -> PortSpec

        Returns a portspec from the given sigstring.

        """
        return PortSpec(sigstring=sigstring)

    ##########################################################################
    # Properties

    id = DBPortSpec.db_id
    name = DBPortSpec.db_name
    type = DBPortSpec.db_type
    optional = DBPortSpec.db_optional
    sort_key = DBPortSpec.db_sort_key
    min_conns = DBPortSpec.db_min_conns
    max_conns = DBPortSpec.db_max_conns
    _depth = DBPortSpec.db_depth
    port_spec_items = DBPortSpec.db_portSpecItems
    items = DBPortSpec.db_portSpecItems

    def _get_sigstring(self):
        return create_port_spec_string(
            [i.spec_tuple for i in self.port_spec_items])

    sigstring = property(_get_sigstring)

    def is_mandatory(self):
        return (self.min_conns > 0)

    def _get_labels(self):
        return [i.label for i in self.port_spec_items]

    labels = property(_get_labels)

    def _get_defaults(self):
        return [i.default for i in self.port_spec_items]

    defaults = property(_get_defaults)

    def _get_short_sigstring(self):
        if self._short_sigstring is None:
            self.create_tooltip()
        return self._short_sigstring

    short_sigstring = property(_get_short_sigstring)

    def _get_signature(self):
        signature = []
        for i in self.port_spec_items:
            signature.append((i.descriptor.module, i.label))
        return signature

    signature = property(_get_signature)

    def _get_depth(self):
        return self._depth or 0

    def _set_depth(self, depth):
        self._depth = depth

    depth = property(_get_depth, _set_depth)

    def toolTip(self):
        if self._tooltip is None:
            self.create_tooltip()
        return self._tooltip

    def shape(self):
        return self._shape

    def docstring(self):
        return self._docstring

    def descriptors(self):
        return [i.descriptor for i in self.port_spec_items]

    ##########################################################################
    # Methods

    def _resize_attrs(self, target, *lists):
        for rlist in lists:
            if len(target) > len(rlist):
                rlist.extend(None for i in xrange(len(target) - len(rlist)))

    def _set_attrs(self, item, *attrs):
        attr_order = ['default', 'label', 'values', 'entry_type']
        if item is None:
            kwargs = dict(izip(attr_order, attrs))
            return kwargs
        else:
            for (attr_key, attr) in izip(attr_order, attrs):
                if attr is not None:
                    setattr(item, attr_key, attr)

    def create_spec_items(self,
                          items=None,
                          signature=None,
                          sigstring=None,
                          defaults=None,
                          labels=None,
                          values=None,
                          entry_types=None):
        if defaults is None:
            defaults = []
        elif isinstance(defaults, basestring):
            defaults = literal_eval(defaults)
        if labels is None:
            labels = []
        elif isinstance(labels, basestring):
            labels = literal_eval(labels)
        if values is None:
            values = []
        elif isinstance(values, basestring):
            values = literal_eval(values)
        if entry_types is None:
            entry_types = []
        elif isinstance(entry_types, basestring):
            entry_types = literal_eval(entry_types)
        attrs = [defaults, labels, values, entry_types]
        if items:
            self.set_items(items, *attrs)
        elif signature is not None:
            items = self.get_items_from_entries(signature, *attrs)
        elif sigstring is not None:
            items = self.get_items_from_sigstring(sigstring, *attrs)
        self.port_spec_items = items

    def set_items(self, items, *attrs):
        self._resize_attrs(items, *attrs)
        for i, item_tuple in enumerate(izip(items, *attrs)):
            item_tuple[0].pos = i
            self._set_attrs(*item_tuple)

    def get_items_from_entries(self, signature, *attrs):
        # This is reasonably messy code. The intent is that a
        # signature given by the user in a call like this
        # add_input_port(module, name, signature) should be one of the
        # following:

        # type only: add_input_port(_, _, Float)
        # type plus description: add_input_port(_, _, (Float, 'radius'))

        # multiple parameters, where each parameter can be either of the above:
        # add_input_port(_, _, [Float, (Integer, 'count')])

        registry = get_module_registry()
        entries = []

        def canonicalize(sig_item):
            if isinstance(sig_item, tuple):
                # assert len(sig_item) == 2
                # assert isinstance(sig_item[0], type)
                # assert isinstance(sig_item[1], str)
                descriptor = registry.get_descriptor(sig_item[0])
                label = sig_item[1]
                return (descriptor, label)
            elif isinstance(sig_item, list):
                descriptor = registry.get_descriptor_by_name(
                    get_vistrails_basic_pkg_id(), 'List')
                return (descriptor, None)
            else:
                # isinstance(sig_item, type):
                return (registry.get_descriptor(sig_item), None)

        # def _add_entry(sig_item):
        ps_items = []
        if not isinstance(signature, list):
            signature = [signature]
        self._resize_attrs(signature, *attrs)
        for i, item_tuple in enumerate(izip(signature, *attrs)):
            descriptor, item_label = canonicalize(item_tuple[0])
            kwargs = self._set_attrs(None, *item_tuple[1:])
            if not kwargs['label']:
                if item_label != "<no description>":
                    kwargs['label'] = item_label
            ps_item = PortSpecItem(pos=i,
                                   package=descriptor.identifier,
                                   module=descriptor.name,
                                   namespace=descriptor.namespace,
                                   **kwargs)
            ps_items.append(ps_item)
        return ps_items

    def get_items_from_sigstring(self, sigstring, *attrs):
        ps_items = []
        specs_list = parse_port_spec_string(sigstring)
        if len(specs_list) == 0:
            return ps_items

        self._resize_attrs(specs_list, *attrs)
        for i, item_tuple in enumerate(izip(specs_list, *attrs)):
            kwargs = self._set_attrs(None, *item_tuple[1:])
            ps_item = PortSpecItem(pos=i,
                                   package=item_tuple[0][0],
                                   module=item_tuple[0][1],
                                   namespace=item_tuple[0][2],
                                   **kwargs)
            ps_items.append(ps_item)
        return ps_items

    def create_tooltip(self):
        """Creates a short_sigstring that does not include package names for
        use with the tooltip. Note, however, that such sigstrings
        can't be used to reconstruct a spec. They should only be used
        for human-readable purposes.
        """

        self._short_sigstring = \
            "(" + ",".join(d.name for d in self.descriptors()) + ")"
        if self.type in ['input', 'output']:
            port_string = self.type.capitalize()
        else:
            port_string = 'Invalid'
        _depth = " (depth %s)" % self.depth if self.depth else ''
        self._tooltip = "%s port %s\n%s%s" % (port_string, self.name,
                                              self._short_sigstring, _depth)

    ##########################################################################
    # Operators

    def __str__(self):
        """__str__() -> str - Returns a string representation of an PortSpec
        object. 

        """
        rep = "<portSpec id=%s name=%s type=%s signature=%s depth=%s />"
        return rep % (str(self.id), str(self.name), str(
            self.type), str(self.sigstring), str(self.depth))

    def __eq__(self, other):
        """ __eq__(other: PortSpec) -> boolean
        Returns True if self and other have the same attributes. Used by == 
        operator. 
        
        """
        if self is None and other is None:
            return True
        if type(self) != type(other) or \
                self.name != other.name or \
                self.type != other.type:
            return False
        if len(self.descriptors()) != len(other.descriptors()):
            return False
        for (mine, their) in izip(self.descriptors(), other.descriptors()):
            if mine != their:
                return False
        return True

    def __ne__(self, other):
        return not self.__eq__(other)

    def type_equals(self, other):
        """type_equals(other: PortSpec) -> Bool

        Checks equality ignoring description strings. Only cares about types.
        Does not do subtyping or supertyping: match must be perfect.

        """
        if self is None and other is None:
            return True
        if len(self.descriptors()) != len(other.descriptors()):
            return False
        for (mine, their) in izip(self.descriptors(), other.descriptors()):
            if mine != their:
                return False
        return True

    def key_no_id(self):
        """key_no_id(): tuple. returns a tuple that identifies
        the port without caring about ids. Used for sorting
        port lists."""
        return (self.type, self.name, self.signature)