Beispiel #1
0
def get_wf_graph(w_list, workflow_info=None, pdf=False):
    """run_and_get_results(w_list: list of (locator, version), 
                           workflow_info:str, pdf:bool)
    Load all workflows in wf_list and dump their graph to workflow_info.
    
    """
    result = []
    if is_running_gui():
        from gui.vistrail_controller import VistrailController as \
             GUIVistrailController
        for locator, workflow in w_list:
            try:
                (v, abstractions, thumbnails, mashups) = load_vistrail(locator)
                controller = GUIVistrailController()
                if type(workflow) == type("str"):
                    version = v.get_version_number(workflow)
                elif type(workflow) in [type(1), long]:
                    version = workflow
                elif workflow is None:
                    version = controller.get_latest_version_in_graph()
                else:
                    msg = "Invalid version tag or number: %s" % workflow
                    raise VistrailsInternalError(msg)
                controller.change_selected_version(version)

                if (workflow_info is not None
                        and controller.current_pipeline is not None):
                    from gui.pipeline_view import QPipelineView
                    pipeline_view = QPipelineView()
                    controller.current_pipeline_view = pipeline_view.scene()
                    controller.set_vistrail(v, locator, abstractions,
                                            thumbnails, mashups)
                    pipeline_view.scene().setupScene(
                        controller.current_pipeline)
                    if pdf:
                        base_fname = "%s_%s_pipeline.pdf" % (
                            locator.short_name, version)
                        filename = os.path.join(workflow_info, base_fname)
                        pipeline_view.scene().saveToPDF(filename)
                    else:
                        base_fname = "%s_%s_pipeline.png" % (
                            locator.short_name, version)
                        filename = os.path.join(workflow_info, base_fname)
                        pipeline_view.scene().saveToPNG(filename)
                    del pipeline_view
                    result.append((True, ""))
            except Exception, e:
                result.append((False, str(e)))
def get_wf_graph(w_list, workflow_info=None, pdf=False):
    """run_and_get_results(w_list: list of (locator, version), 
                           workflow_info:str, pdf:bool)
    Load all workflows in wf_list and dump their graph to workflow_info.
    
    """
    result = []
    if is_running_gui():
        from gui.vistrail_controller import VistrailController as \
             GUIVistrailController
        for locator, workflow in w_list:
            try:
                (v, abstractions , thumbnails, mashups)  = load_vistrail(locator)
                controller = GUIVistrailController()
                if type(workflow) == type("str"):
                    version = v.get_version_number(workflow)
                elif type(workflow) in [ type(1), long]:
                    version = workflow
                elif workflow is None:
                    version = controller.get_latest_version_in_graph()
                else:
                    msg = "Invalid version tag or number: %s" % workflow
                    raise VistrailsInternalError(msg)
                controller.change_selected_version(version)
            
                if (workflow_info is not None and 
                    controller.current_pipeline is not None):
                    from gui.pipeline_view import QPipelineView
                    pipeline_view = QPipelineView()
                    controller.current_pipeline_view = pipeline_view.scene()
                    controller.set_vistrail(v, locator, abstractions, thumbnails,
                                        mashups)
                    pipeline_view.scene().setupScene(controller.current_pipeline)
                    if pdf:
                        base_fname = "%s_%s_pipeline.pdf" % (locator.short_name, version)
                        filename = os.path.join(workflow_info, base_fname)
                        pipeline_view.scene().saveToPDF(filename)
                    else:
                        base_fname = "%s_%s_pipeline.png" % (locator.short_name, version)
                        filename = os.path.join(workflow_info, base_fname)
                        pipeline_view.scene().saveToPNG(filename)
                    del pipeline_view
                    result.append((True, ""))
            except Exception, e:
                result.append((False, str(e)))
class QVistrailView(QDockContainer):
    """
    QVistrailView is a widget containing four stacked widgets: Pipeline View,
    Version Tree View, Query View and Parameter Exploration view
    for manipulating vistrails.
    """
    def __init__(self, parent=None):
        """ QVistrailItem(parent: QWidget) -> QVistrailItem
        Make it a main window with dockable area
        
        """
        QDockContainer.__init__(self, parent)
        
        # The window title is the name of the vistrail file
        self.setWindowTitle('untitled%s'%vistrails_default_file_type())

        # Create the views
        self.pipelineTab = QPipelineTab()
        self.versionTab = QVersionTab()
        self.connect(self.versionTab.versionProp,
                     QtCore.SIGNAL('textQueryChange(bool)'),
                     self.setQueryMode)

        self.pipelineTab.pipelineView.setPIPScene(
            self.versionTab.versionView.scene())
        self.versionTab.versionView.setPIPScene(            
            self.pipelineTab.pipelineView.scene())
        self.versionTab.versionView.scene()._pipeline_scene = self.pipelineTab.pipelineView.scene()
        self.queryTab = QQueryTab()

        self.peTab = QParameterExplorationTab()
        self.peTab.annotatedPipelineView.setScene(
            self.pipelineTab.pipelineView.scene())
        
        # Setup a central stacked widget for pipeline view and version
        # tree view
        self.stackedWidget = QtGui.QStackedWidget()
        self.setCentralWidget(self.stackedWidget)
        self.stackedWidget.addWidget(self.pipelineTab)
        self.stackedWidget.addWidget(self.versionTab)
        self.stackedWidget.addWidget(self.queryTab)
        self.stackedWidget.addWidget(self.peTab)
        self.stackedWidget.setCurrentIndex(1)

        # Initialize the vistrail controller
        self.controller = VistrailController()
        self.controller.vistrail_view = self
        self.connect(self.controller,
                     QtCore.SIGNAL('stateChanged'),
                     self.stateChanged)
        self.connect(self.controller,
                     QtCore.SIGNAL('new_action'),
                     self.new_action)

        self.connect(self.versionTab.versionView.scene(),
                     QtCore.SIGNAL('versionSelected(int,bool)'),
                     self.versionSelected)

        self.connect(self.versionTab,
                     QtCore.SIGNAL('twoVersionsSelected(int,int)'),
                     self.twoVersionsSelected)
        self.connect(self.queryTab,
                     QtCore.SIGNAL('queryPipelineChange'),
                     self.queryPipelineChange)
        self.connect(self.peTab,
                     QtCore.SIGNAL('exploreChange(bool)'),
                     self.exploreChange)

        # We also keep track where this vistrail comes from
        # So we can save in the right place
        self.locator = None
        
        self.closeEventHandler = None

        # the redo stack stores the undone action ids 
        # (undo is automatic with us, through the version tree)
        self.redo_stack = []

        # Keep the state of the execution button and menu items for the view
        self.execQueryEnabled = False
        self.execDiffEnabled = False
        self.execExploreEnabled = False
        self.execPipelineEnabled = False
        self.execDiffId1 = -1
        self.execDiffId2 = -1

    def updateCursorState(self, mode):
        """ updateCursorState(mode: Int) -> None 
        Change cursor state in all different modes.

        """
        self.pipelineTab.pipelineView.setDefaultCursorState(mode)
        self.versionTab.versionView.setDefaultCursorState(mode)
        self.queryTab.pipelineView.setDefaultCursorState(mode)
        if self.parent().parent().parent().pipViewAction.isChecked():
            self.pipelineTab.pipelineView.pipFrame.graphicsView.setDefaultCursorState(mode)
            self.versionTab.versionView.pipFrame.graphicsView.setDefaultCursorState(mode)


    def flush_changes(self):
        """Flush changes in the vistrail before closing or saving.
        """
        # Quick workaround for notes focus out bug (ticket #182)
        # There's probably a much better way to fix this.
        prop = self.versionTab.versionProp
        prop.versionNotes.commit_changes()

    def setup_view(self, version=None):
        """setup_view(version = None:int) -> None

        Sets up the correct view for a fresh vistrail.

        Previously, there was a method setInitialView and another
        setOpenView.

        They were supposed to do different things but the code was
        essentially identical.

        FIXME: this means that the different calls are being handled
        somewhere else in the code. Figure this out."""

        if version is None:
            self.controller.select_latest_version()
            version = self.controller.current_version
        self.versionSelected(version, False)
        self.setPIPMode(True)
        self.setQueryMode(False)
       
    def setPIPMode(self, on):
        """ setPIPMode(on: bool) -> None
        Set the PIP state for the view

        """
        self.pipelineTab.pipelineView.setPIPEnabled(on)
        self.versionTab.versionView.setPIPEnabled(on)

    def setQueryMode(self, on):
        """ setQueryMode(on: bool) -> None
        Set the Reset Query button mode for the view
        
        """
        self.pipelineTab.pipelineView.setQueryEnabled(on)
        self.versionTab.versionView.setQueryEnabled(on)
        self.queryTab.pipelineView.setQueryEnabled(on)

    def setMethodsMode(self, on):
        """ setMethodsMode(on: bool) -> None
        Set the methods panel state for the view

        """
        if on:
            self.pipelineTab.methodPalette.toolWindow().show()
        else:
            self.pipelineTab.methodPalette.toolWindow().hide()

    def setSetMethodsMode(self, on):
        """ setSetMethodsMode(on: bool) -> None
        Set the set methods panel state for the view

        """
        if on:
            self.pipelineTab.moduleMethods.toolWindow().show()
        else:
            self.pipelineTab.moduleMethods.toolWindow().hide()

    def setPropertiesMode(self, on):
        """ setPropertiesMode(on: bool) -> None
        Set the properties panel state for the view

        """
        if on:
            self.versionTab.versionProp.toolWindow().show()
        else:
            self.versionTab.versionProp.toolWindow().hide()

    def setPropertiesOverlayMode(self, on):
        """ setPropertiesMode(on: bool) -> None
        Set the properties overlay state for the view

        """
        if on:
            self.versionTab.versionView.versionProp.show()
        else:
            self.versionTab.versionView.versionProp.hide()

    def viewModeChanged(self, index):
        """ viewModeChanged(index: int) -> None        
        Slot for switching different views when the tab's current
        widget is changed
        
        """
        if self.stackedWidget.count()>index:
            self.stackedWidget.setCurrentIndex(index)

    def sizeHint(self):
        """ sizeHint(self) -> QSize
        Return recommended size of the widget
        
        """
        return QtCore.QSize(1024, 768)

    def set_vistrail(self, vistrail, locator=None):
        """ set_vistrail(vistrail: Vistrail, locator: BaseLocator) -> None
        Assign a vistrail to this view, and start interacting with it
        
        """
        self.vistrail = vistrail
        self.locator = locator
        self.controller.set_vistrail(vistrail, locator)
        self.versionTab.setController(self.controller)
        self.pipelineTab.setController(self.controller)
        self.peTab.setController(self.controller)

    def stateChanged(self):
        """ stateChanged() -> None

        Handles 'stateChanged' signal from VistrailController
        
        Update the window and tab title
        
        """
        title = self.controller.name
        if title=='':
            title = 'untitled%s'%vistrails_default_file_type()
        if self.controller.changed:
            title += '*'
        self.setWindowTitle(title)
        # propagate the state change to the version prop
        # maybe in the future we should propagate as a signal
        versionId = self.controller.current_version
        self.versionTab.versionProp.updateVersion(versionId)

    def emitDockBackSignal(self):
        """ emitDockBackSignal() -> None
        Emit a signal for the View Manager to take this widget back
        
        """
        self.emit(QtCore.SIGNAL('dockBack'), self)

    def closeEvent(self, event):
        """ closeEvent(event: QCloseEvent) -> None
        Only close if we save information
        
        """
        if self.closeEventHandler:
            if self.closeEventHandler(self):
                event.accept()
            else:
                event.ignore()
        else:
            #I think there's a problem with two pipeline views and the same
            #scene on Macs. After assigning a new scene just before deleting
            #seems to solve the problem
            self.peTab.annotatedPipelineView.setScene(QtGui.QGraphicsScene())
            return QDockContainer.closeEvent(self, event)
            # super(QVistrailView, self).closeEvent(event)

    def queryVistrail(self, on=True):
        """ queryVistrail(on: bool) -> None
        Inspecting the query tab to get a pipeline for querying
        
        """
        if on:
            queryPipeline = self.queryTab.controller.current_pipeline
            if queryPipeline:
                self.controller.query_by_example(queryPipeline)
                self.setQueryMode(True)
        else:
            self.controller.set_search(None)
            self.setQueryMode(False)

    def createPopupMenu(self):
        """ createPopupMenu() -> QMenu
        Create a pop up menu that has a list of all tool windows of
        the current tab of the view. Tool windows can be toggled using
        this menu
        
        """
        return self.stackedWidget.currentWidget().createPopupMenu()

    def executeParameterExploration(self):
        """ executeParameterExploration() -> None
        Execute the current parameter exploration in the exploration tab
        
        """
        self.peTab.performParameterExploration()

    def versionSelected(self, versionId, byClick):
        """ versionSelected(versionId: int, byClick: bool) -> None
        A version has been selected/unselected, update the controller
        and the pipeline view
        
        """
        if self.controller:
            self.controller.reset_pipeline_view = byClick
            self.controller.change_selected_version(versionId)
            self.controller.invalidate_version_tree(False)
            if byClick:
                self.controller.current_pipeline_view.fitToAllViews(True)
            self.versionTab.versionProp.updateVersion(versionId)
            self.versionTab.versionView.versionProp.updateVersion(versionId)
            self.redo_stack = []
            self.emit(QtCore.SIGNAL('versionSelectionChange'),versionId)
            self.execPipelineEnabled = versionId>-1
            self.execDiffEnabled = False
            self.execExploreChange = False
            self.emit(QtCore.SIGNAL('execStateChange()'))

    def twoVersionsSelected(self, id1, id2):
        """ twoVersionsSelected(id1: Int, id2: Int) -> None
        Just echo the signal from the view
        
        """
        self.execDiffEnabled = True
        self.execDiffId1 = id1
        self.execDiffId2 = id2
        self.emit(QtCore.SIGNAL('execStateChange()'))

    def queryPipelineChange(self, notEmpty):
        """ queryPipelineChange(notEmpty: bool) -> None
        Update the status of tool bar buttons if there are
        modules on the query canvas
        
        """
        self.execQueryEnabled = notEmpty
        self.emit(QtCore.SIGNAL('execStateChange()'))
                  
    def exploreChange(self, notEmpty):
        """ exploreChange(notEmpty: bool) -> None
        Update the status of tool bar buttons if there are
        parameters in the exploration canvas
        
        """
        self.execExploreEnabled = notEmpty
        self.emit(QtCore.SIGNAL('execStateChange()'))

    ##########################################################################
    # Undo/redo

    def set_pipeline_selection(self, old_action, new_action, optype):
        # Sets up the right selection based on the the old and new
        # actions coming from undo/redo.
        pScene = self.pipelineTab.pipelineView.scene()
        # select things, if appropriate
        def old_deletion_test():
            return (old_action and
                    any(old_action.operations,
                        lambda x: x.vtType == 'delete'))
        def old_deletion():
            # Previous action was a deletion, select what was just
            # deleted and undone
            for op in old_action.operations:
                if op.what == 'module' and op.vtType == 'delete':
                    module = pScene.modules[op.objectId]
                    module.setSelected(True)
        def old_move_test():
            return (old_action and
                    any(old_action.operations,
                        lambda x: x.what == 'location' and x.vtType == 'change'))
        def old_move():
            for op in old_action.operations:
                if op.what == 'location' and op.vtType == 'change':
                    module = pScene.modules[op.parentObjId]
                    module.setSelected(True)
        def new_addition_test():
            return (new_action and
                    any(new_action.operations,
                        lambda x: x.vtType == 'add'))
        def new_addition():
            # This action was an addition, select the thing that was
            # added in this version
            for op in new_action.operations:
                if op.what == 'module' and op.vtType == 'add':
                    module = pScene.modules[op.objectId]
                    module.setSelected(True)
        def new_move_test():
             return (new_action and
                     any(new_action.operations,
                         lambda x: x.what == 'location' and x.vtType == 'change'))
        def new_move():
            # some action was a move, select the things that were moved
            for op in new_action.operations:
                if op.what == 'location' and op.vtType == 'change':
                    module = pScene.modules[op.parentObjId]
                    module.setSelected(True)

        old_deletion_pair = (old_deletion_test, old_deletion)
        old_move_pair = (old_move_test, old_move)
        new_addition_pair = (new_addition_test, new_addition)
        new_move_pair = (new_move_test, new_move)

        dispatch = {'undo': [old_deletion_pair,
                             old_move_pair,
                             new_addition_pair,
                             new_move_pair],
                    'redo': [new_move_pair,
                             new_addition_pair,
                             old_move_pair,
                             old_deletion_pair]}
        assert optype in dispatch
        for (test, handler) in dispatch[optype]:
            if test():
                handler()
                return
        # If we get here, we couldn't recognize the action
        # FIXME: Add tests and handlers for change parameter
        

    def undo(self):
        """Performs one undo step, moving up the version tree."""
        action_map = self.controller.vistrail.actionMap
        old_action = action_map.get(self.controller.current_version, None)
        self.redo_stack.append(self.controller.current_version) 
        self.controller.show_parent_version()
        new_action = action_map.get(self.controller.current_version, None)
        self.set_pipeline_selection(old_action, new_action, 'undo')
        return self.controller.current_version
        
    def redo(self):
        """Performs one redo step if possible, moving down the version tree."""
        action_map = self.controller.vistrail.actionMap
        old_action = action_map.get(self.controller.current_version, None)
        if not self.can_redo():
            critical("Redo on an empty redo stack. Ignoring.")
            return
        next_version = self.redo_stack[-1]
        self.redo_stack = self.redo_stack[:-1]
        self.controller.show_child_version(next_version)
        new_action = action_map[self.controller.current_version]
        self.set_pipeline_selection(old_action, new_action, 'redo')
        return next_version

    def can_redo(self):
        return len(self.redo_stack) <> 0

    def new_action(self, action):
        """new_action

        Handler for VistrailController.new_action

        """
        self.redo_stack = []
Beispiel #4
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.scene()
        # self.vt_controller.vistrail_view.set_controller(self.vt_controller)
        self.vt_controller.set_vistrail(controller.vistrail, None,
                                        set_log_on_vt=False)
        self.vt_controller.change_selected_version(controller.current_version)
        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):
        self.vt_controller.set_vistrail(self.controller.vistrail, None,
                                        set_log_on_vt=False)
        self.vt_controller.change_selected_version(
            self.controller.current_version)

    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.scene()
        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 gui.module_palette import QModulePalette
        from 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 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 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 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 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

    def version_changed(self, version_id):
        self.vt_controller.change_selected_version(version_id)
        
    def result_version_selected(self, version_id, by_click, do_validate=True,
                                from_root=False, double_click=False):
        if by_click:
            self.query_controller.search.setCurrentVistrail(
                self.vt_controller.vistrail)
            self.vt_controller.change_selected_version(version_id, by_click, 
                                                       do_validate, from_root)
            if double_click:
                self.query_controller.set_level(QueryController.LEVEL_WORKFLOW)
                self.query_controller.show_workflow_matches()