def get_vt_graph(vt_list, tree_info, pdf=False): """get_vt_graph(vt_list: list of locator, tree_info:str) Load all vistrails in vt_list and dump their tree to tree_info. """ result = [] if is_running_gui(): from gui.vistrail_controller import VistrailController as \ GUIVistrailController for locator in vt_list: try: (v, abstractions , thumbnails, mashups) = load_vistrail(locator) controller = GUIVistrailController() if tree_info is not None: from gui.version_view import QVersionTreeView version_view = QVersionTreeView() from gui.pipeline_view import QPipelineView pipeline_view = QPipelineView() controller.current_pipeline_view = pipeline_view.scene() controller.set_vistrail(v, locator, abstractions, thumbnails, mashups) version_view.scene().setupScene(controller) if pdf: base_fname = "graph_%s.pdf" % locator.short_name filename = os.path.join(tree_info, base_fname) version_view.scene().saveToPDF(filename) else: base_fname = "graph_%s.png" % locator.short_name filename = os.path.join(tree_info, base_fname) version_view.scene().saveToPNG(filename) del version_view result.append((True, "")) except Exception, e: result.append((False, str(e)))
def mousePressEvent(self, event): """ mousePressEvent(event: QMouseEvent) -> None Toggle port selection """ buttons = self.translateButton(event) if buttons == QtCore.Qt.LeftButton: scenePos = self.mapToScene(event.pos()) item = self.scene().itemAt(scenePos) if type(item) == QGraphicsPortItem: is_input = item.port.type == 'input' if self.single_output and not is_input and len( self._selected_output_ports ) > 0 and item != self._selected_output_ports[0]: # Deselect current output port if another port selected in single output mode self._selected_output_ports[0].setPen( CurrentTheme.PORT_PEN) del self._selected_output_ports[:] if is_input: port_set = self._selected_input_ports else: port_set = self._selected_output_ports if item in port_set: port_set.remove(item) else: port_set.append(item) self._clicked_port = item else: self._clicked_port = None event.accept() else: QPipelineView.mousePressEvent(self, event)
def mousePressEvent(self, event): """ mousePressEvent(event: QMouseEvent) -> None Toggle port selection """ buttons = self.translateButton(event) if buttons == QtCore.Qt.LeftButton: scenePos = self.mapToScene(event.pos()) item = self.scene().itemAt(scenePos) if type(item) == QGraphicsPortItem: is_input = item.port.type == 'input' if self.single_output and not is_input and len(self._selected_output_ports) > 0 and item != self._selected_output_ports[0]: # Deselect current output port if another port selected in single output mode self._selected_output_ports[0].setPen(CurrentTheme.PORT_PEN) del self._selected_output_ports[:] if is_input: port_set = self._selected_input_ports else: port_set = self._selected_output_ports if item in port_set: port_set.remove(item) else: port_set.append(item) self._clicked_port = item else: self._clicked_port = None event.accept() else: QPipelineView.mousePressEvent(self, event)
def get_vt_graph(vt_list, tree_info, pdf=False): """get_vt_graph(vt_list: list of locator, tree_info:str) Load all vistrails in vt_list and dump their tree to tree_info. """ result = [] if is_running_gui(): from gui.vistrail_controller import VistrailController as \ GUIVistrailController for locator in vt_list: try: (v, abstractions, thumbnails, mashups) = load_vistrail(locator) controller = GUIVistrailController() if tree_info is not None: from gui.version_view import QVersionTreeView version_view = QVersionTreeView() from gui.pipeline_view import QPipelineView pipeline_view = QPipelineView() controller.current_pipeline_view = pipeline_view.scene() controller.set_vistrail(v, locator, abstractions, thumbnails, mashups) version_view.scene().setupScene(controller) if pdf: base_fname = "graph_%s.pdf" % locator.short_name filename = os.path.join(tree_info, base_fname) version_view.scene().saveToPDF(filename) else: base_fname = "graph_%s.png" % locator.short_name filename = os.path.join(tree_info, base_fname) version_view.scene().saveToPNG(filename) del version_view result.append((True, "")) except Exception, e: result.append((False, str(e)))
def __init__(self, parent=None): """ QPipelineView(parent: QWidget) -> QPipelineView Initialize the graphics view and its properties """ QPipelineView.__init__(self, parent) self.setWindowTitle('Annotated Pipeline') self.inspector = PipelineInspector()
def paintEvent(self, event): """ paintEvent(event: QPaintEvent) -> None Fit pipeline to view on first paint """ if not self._shown: self._shown = True self.scene().fitToView(self) QPipelineView.paintEvent(self, event)
def mouseDoubleClickEvent(self, event): """ mouseDoubleClickEvent(event: QMouseEvent) -> None Disallow left button double clicks """ buttons = self.translateButton(event) if buttons == QtCore.Qt.LeftButton: event.accept() else: QPipelineView.mouseDoubleClickEvent(self, event)
def mouseMoveEvent(self, event): """ mousePressEvent(event: QMouseEvent) -> None Disallow left click and drag """ buttons = self.translateButton(event) if buttons == QtCore.Qt.LeftButton: event.accept() else: QPipelineView.mouseMoveEvent(self, event)
def set_controller(self, controller): QPipelineView.set_controller(self, controller) #print "@@@ set_controller called", id(self.controller), len(self.controller.vistrail.actions) if not hasattr(self.controller, 'loaded_workflow_execs'): self.controller.loaded_workflow_execs = {} for e in self.controller.read_log().workflow_execs: # set workflow names e.db_name = controller.get_pipeline_name(e.parent_version)[10:] self.controller.loaded_workflow_execs[e] = e self.log = self.controller.loaded_workflow_execs
def set_controller(self, controller): QPipelineView.set_controller(self, controller) #print "@@@ set_controller called", id(self.controller), len(self.controller.vistrail.actions) if not hasattr(self.controller, 'loaded_workflow_execs'): self.controller.loaded_workflow_execs = {} for e in self.controller.read_log().workflow_execs: # set workflow names e.db_name = controller.get_pipeline_name( e.parent_version)[10:] self.controller.loaded_workflow_execs[e] = e self.log = self.controller.loaded_workflow_execs
def __init__(self, parent=None): QPipelineView.__init__(self, parent) self.setReadOnlyMode(True) self.set_title("Provenance") self.log = None self.execution = None self.parentExecution = None self.isUpdating = False # self.exec_to_wf_map = {} # self.workflow_execs = [] # Hook shape selecting functions self.connect(self.scene(), QtCore.SIGNAL("moduleSelected"), self.moduleSelected)
def mouseReleaseEvent(self, event): """ mouseReleaseEvent(event: QMouseEvent) -> None Update port highlighting """ if event.button() == QtCore.Qt.LeftButton: port = self._clicked_port if port is not None: if port in self._selected_input_ports or port in self._selected_output_ports: port.setPen(CurrentTheme.PORT_SELECTED_PEN) else: port.setPen(CurrentTheme.PORT_PEN) event.accept() else: QPipelineView.mouseReleaseEvent(self, event)
def __init__(self, parent=None): """ QPipelineTab(parent: QWidget) -> QPipelineTab Make it a main window with dockable area and a QPipelineView in the middle """ QDockContainer.__init__(self, parent) self.setWindowTitle('Pipeline') self.pipelineView = QPipelineView() self.pipelineView.scene().pipeline_tab = proxy(self) self.setCentralWidget(self.pipelineView) self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.methodPalette = QMethodPalette(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.methodPalette.toolWindow()) self.moduleMethods = QModuleMethods(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleMethods.toolWindow()) self.connect(self.toolWindow(), QtCore.SIGNAL('topLevelChanged(bool)'), self.updateWindowTitle) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('moduleSelected'), self.moduleSelected) self.connect(self.pipelineView, QtCore.SIGNAL('resetQuery()'), self.resetQuery) self.controller = None
def __init__(self, parent, scene, single_output=False, include_module_ids=[]): """ QReadOnlyPortSelectPipelineView(parent: QPipelineView, scene: QGraphicsScene, single_output: bool, include_module_ids: list) -> QReadOnlyPortSelectPipelineView Create a read only pipeline view that only allows selection of ports from the modules in include_module_ids. If single_output is True, only one output port can be selected at a time. """ QPipelineView.__init__(self, parent) self.single_output = single_output self._shown = False self._selected_input_ports = [] self._selected_output_ports = [] # Create custom scene scene_copy = QPipelineScene(self) scene_copy.controller = scene.controller scene_copy.setupScene(scene.pipeline) scene_copy.selectAll() if include_module_ids: # Remove modules not in the include list and associated connections sel_modules, sel_connections = scene_copy.get_selected_item_ids() [ scene_copy.remove_module(m_id) for m_id in sel_modules if m_id not in include_module_ids ] [ scene_copy.remove_connection(c_id) for c_id in sel_connections if c_id not in scene_copy.get_selected_item_ids()[1] ] # Hide configure button on modules for item in scene_copy.selectedItems(): if type(item) == QGraphicsModuleItem: for c_item in item.childItems(): if type(c_item) == QGraphicsConfigureItem: c_item.setVisible(False) # Unselect everything and use the newly created scene scene_copy.clearSelection() scene_copy.updateSceneBoundingRect() self.setScene(scene_copy)
def paintEvent(self, event): """ paintEvent(event: QPaintEvent) -> None Paint an overlay annotation on spreadsheet cell modules """ QPipelineView.paintEvent(self, event) # super(QAnnotatedPipelineView, self).paintEvent(event) if self.scene(): painter = QtGui.QPainter(self.viewport()) for mId, annotatedId in \ self.inspector.annotated_modules.iteritems(): item = self.scene().modules[mId] br = item.sceneBoundingRect() rect = QtCore.QRect(self.mapFromScene(br.topLeft()), self.mapFromScene(br.bottomRight())) QAnnotatedPipelineView.drawId(painter, rect, annotatedId) painter.end()
def __init__(self, parent=None): """ QPipelineTab(parent: QWidget) -> QPipelineTab Make it a main window with dockable area and a QPipelineView in the middle """ QDockContainer.__init__(self, parent) self.setWindowTitle('Pipeline') self.pipelineView = QPipelineView() self.pipelineView.scene().pipeline_tab = proxy(self) self.setCentralWidget(self.pipelineView) self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.methodPalette = QMethodPalette(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.methodPalette.toolWindow()) self.moduleMethods = QModuleMethods(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleMethods.toolWindow()) self.moduleConfig = QModuleConfiguration(self, self.pipelineView.scene()) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleConfig.toolWindow()) self.vistrailVars = QVistrailVariables(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.vistrailVars.toolWindow()) self.connect(self.toolWindow(), QtCore.SIGNAL('topLevelChanged(bool)'), self.updateWindowTitle) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('moduleSelected'), self.moduleSelected) self.connect(self.moduleConfig, QtCore.SIGNAL('doneConfigure'), self.pipelineView.scene().perform_configure_done_actions) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('showConfigureWindow'), self.moduleConfig.activate) self.connect(self.pipelineView, QtCore.SIGNAL('resetQuery()'), self.resetQuery) self.controller = None
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 paintEvent(self, event): """ paintEvent(event: QPaintEvent) -> None Paint an overlay annotation on spreadsheet cell modules """ QPipelineView.paintEvent(self, event) # super(QAnnotatedPipelineView, self).paintEvent(event) if self.scene(): painter = QtGui.QPainter(self.viewport()) for mId, annotatedId in \ self.inspector.annotated_modules.iteritems(): if mId not in self.scene().modules: # faulty annotated_modules entry continue item = self.scene().modules[mId] br = item.sceneBoundingRect() rect = QtCore.QRect(self.mapFromScene(br.topLeft()), self.mapFromScene(br.bottomRight())) QAnnotatedPipelineView.drawId(painter, rect, annotatedId) painter.end()
def __init__(self, parent, scene, single_output=False, include_module_ids=[]): """ QReadOnlyPortSelectPipelineView(parent: QPipelineView, scene: QGraphicsScene, single_output: bool, include_module_ids: list) -> QReadOnlyPortSelectPipelineView Create a read only pipeline view that only allows selection of ports from the modules in include_module_ids. If single_output is True, only one output port can be selected at a time. """ QPipelineView.__init__(self, parent) self.single_output = single_output self._shown = False self._selected_input_ports = [] self._selected_output_ports = [] # Create custom scene scene_copy = QPipelineScene(self) scene_copy.controller = scene.controller scene_copy.setupScene(scene.pipeline) scene_copy.selectAll() if include_module_ids: # Remove modules not in the include list and associated connections sel_modules, sel_connections = scene_copy.get_selected_item_ids() [scene_copy.remove_module(m_id) for m_id in sel_modules if m_id not in include_module_ids] [scene_copy.remove_connection(c_id) for c_id in sel_connections if c_id not in scene_copy.get_selected_item_ids()[1]] # Hide configure button on modules for item in scene_copy.selectedItems(): if type(item) == QGraphicsModuleItem: for c_item in item.childItems(): if type(c_item) == QGraphicsConfigureItem: c_item.setVisible(False) # Unselect everything and use the newly created scene scene_copy.clearSelection() scene_copy.updateSceneBoundingRect() self.setScene(scene_copy)
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 createPipelineView(self): """ createPipelineView() -> None Create a center pipeline view for Visual Diff and setup the view based on the diff result self.diff """ # Initialize the shape engine self.pipelineView = QPipelineView() self.setCentralWidget(self.pipelineView) # Add all the shapes into the view self.createDiffPipeline() # Hook shape selecting functions self.connect(self.pipelineView.scene(), QtCore.SIGNAL("moduleSelected"), self.moduleSelected)
def __init__(self, parent=None): QPipelineView.__init__(self, parent) self.setBackgroundBrush(CurrentTheme.QUERY_RESULT_BACKGROUND_BRUSH) self.scene().set_read_only_mode(True)
def __init__(self, parent=None): QPipelineView.__init__(self, parent) self.setBackgroundBrush(CurrentTheme.QUERY_BACKGROUND_BRUSH) self.scene().current_pipeline = Pipeline() self.query_controller = None
class QPipelineTab(QDockContainer, QToolWindowInterface): """ QPipelineTab is a tab widget setting QPipelineView in a center while having surrounding tool windows for manipulating a pipeline """ def __init__(self, parent=None): """ QPipelineTab(parent: QWidget) -> QPipelineTab Make it a main window with dockable area and a QPipelineView in the middle """ QDockContainer.__init__(self, parent) self.setWindowTitle('Pipeline') self.pipelineView = QPipelineView() self.pipelineView.scene().pipeline_tab = proxy(self) self.setCentralWidget(self.pipelineView) self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.methodPalette = QMethodPalette(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.methodPalette.toolWindow()) self.moduleMethods = QModuleMethods(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleMethods.toolWindow()) self.moduleConfig = QModuleConfiguration(self, self.pipelineView.scene()) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleConfig.toolWindow()) self.vistrailVars = QVistrailVariables(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.vistrailVars.toolWindow()) self.connect(self.toolWindow(), QtCore.SIGNAL('topLevelChanged(bool)'), self.updateWindowTitle) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('moduleSelected'), self.moduleSelected) self.connect(self.moduleConfig, QtCore.SIGNAL('doneConfigure'), self.pipelineView.scene().perform_configure_done_actions) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('showConfigureWindow'), self.moduleConfig.activate) self.connect(self.pipelineView, QtCore.SIGNAL('resetQuery()'), self.resetQuery) self.controller = None def addViewActionsToMenu(self, menu): """addViewActionsToMenu(menu: QMenu) -> None Add toggle view actions to menu """ menu.addAction(self.methodPalette.toolWindow().toggleViewAction()) menu.addAction(self.moduleMethods.toolWindow().toggleViewAction()) menu.addAction(self.moduleConfig.toolWindow().toggleViewAction()) menu.addAction(self.vistrailVars.toolWindow().toggleViewAction()) def removeViewActionsFromMenu(self, menu): """removeViewActionsFromMenu(menu: QMenu) -> None Remove toggle view actions from menu """ menu.removeAction(self.methodPalette.toolWindow().toggleViewAction()) menu.removeAction(self.moduleMethods.toolWindow().toggleViewAction()) menu.removeAction(self.moduleConfig.toolWindow().toggleViewAction()) menu.removeAction(self.vistrailVars.toolWindow().toggleViewAction()) def updatePipeline(self, pipeline): """ updatePipeline(pipeline: Pipeline) -> None Setup the pipeline to display and control a specific pipeline """ self.pipelineView.scene().setupScene(pipeline) def updateWindowTitle(self, topLevel): """ updateWindowTitle(topLevel: bool) -> None Change the current widget title depends on the top level status """ if topLevel: self.setWindowTitle('Pipeline <' + self.toolWindow().parent().windowTitle() + '>') else: self.setWindowTitle('Pipeline') def moduleSelected(self, moduleId, selection=[]): """ moduleChanged(moduleId: int, selection: [QGraphicsModuleItem]) -> None Set up the view when module selection has been changed """ if self.pipelineView.scene().controller: pipeline = self.pipelineView.scene().controller.current_pipeline else: pipeline = None if pipeline and pipeline.modules.has_key(moduleId): module = pipeline.modules[moduleId] self.methodPalette.setEnabled(True) self.moduleMethods.setEnabled(True) self.moduleConfig.setEnabled(True) else: module = None self.methodPalette.setEnabled(False) self.moduleMethods.setEnabled(False) self.moduleConfig.setEnabled(False) self.methodPalette.setUpdatesEnabled(False) self.moduleMethods.setUpdatesEnabled(False) self.moduleConfig.setUpdatesEnabled(False) try: self.methodPalette.updateModule(module) self.moduleMethods.updateModule(module) self.moduleConfig.updateModule(module) self.emit(QtCore.SIGNAL('moduleSelectionChange'), [m.id for m in selection]) finally: self.methodPalette.setUpdatesEnabled(True) self.moduleMethods.setUpdatesEnabled(True) self.moduleConfig.setUpdatesEnabled(True) def setController(self, controller): """ setController(controller: VistrailController) -> None Assign a vistrail controller to this pipeline view """ oldController = self.pipelineView.scene().controller if oldController != controller: if oldController != None: self.disconnect(oldController, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) oldController.current_pipeline_view = None self.controller = controller self.pipelineView.scene().controller = controller self.connect(controller, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) self.methodPalette.controller = controller self.moduleMethods.controller = controller self.moduleConfig.controller = controller self.vistrailVars.updateController(controller) controller.current_pipeline_view = self.pipelineView.scene() def versionChanged(self, newVersion): """ versionChanged(newVersion: int) -> None Update the pipeline when the new vistrail selected in the controller """ self.updatePipeline(self.controller.current_pipeline) def resetQuery(self): """ resetQuery() -> None pass along the signal """ self.emit(QtCore.SIGNAL('resetQuery()')) def checkModuleConfigPanel(self): """ checkModuleConfigPanel(self) -> None This will ask if user wants to save changes """ if self.moduleConfig.hasChanges: self.moduleConfig.confWidget.widget.askToSaveChanges()
def run_and_get_results(w_list, parameters='', workflow_info=None, update_vistrail=True, extra_info=None, reason='Console Mode Execution'): """run_and_get_results(w_list: list of (locator, version), parameters: str, workflow_info:str, update_vistrail: boolean, extra_info:dict) Run all workflows in w_list, and returns an interpreter result object. version can be a tag name or a version id. """ elements = parameters.split("$&$") aliases = {} result = [] for locator, workflow in w_list: (v, abstractions , thumbnails, mashups) = load_vistrail(locator) controller = VistrailController(auto_save=update_vistrail) controller.set_vistrail(v, locator, abstractions, thumbnails, mashups) 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) for e in elements: pos = e.find("=") if pos != -1: key = e[:pos].strip() value = e[pos+1:].strip() if controller.current_pipeline.has_alias(key): aliases[key] = value if workflow_info is not None and controller.current_pipeline is not None: if is_running_gui(): from gui.pipeline_view import QPipelineView pipeline_view = QPipelineView() pipeline_view.scene().setupScene(controller.current_pipeline) base_fname = "%s_%s_pipeline.pdf" % (locator.short_name, version) filename = os.path.join(workflow_info, base_fname) pipeline_view.scene().saveToPDF(filename) del pipeline_view else: debug.critical("Cannot save pipeline figure when not " "running in gui mode") base_fname = "%s_%s_pipeline.xml" % (locator.short_name, version) filename = os.path.join(workflow_info, base_fname) core.db.io.save_workflow(controller.current_pipeline, filename) if not update_vistrail: conf = get_vistrails_configuration() if conf.has('thumbs'): conf.thumbs.autoSave = False (results, _) = \ controller.execute_current_workflow(custom_aliases=aliases, extra_info=extra_info, reason=reason) new_version = controller.current_version if new_version != version: debug.warning("Version '%s' (%s) was upgraded. The actual " "version executed was %s" % \ (workflow, version, new_version)) run = results[0] run.workflow_info = (locator.name, new_version) run.pipeline = controller.current_pipeline if update_vistrail: controller.write_vistrail(locator) result.append(run) return result
class QPipelineTab(QDockContainer, QToolWindowInterface): """ QPipelineTab is a tab widget setting QPipelineView in a center while having surrounding tool windows for manipulating a pipeline """ def __init__(self, parent=None): """ QPipelineTab(parent: QWidget) -> QPipelineTab Make it a main window with dockable area and a QPipelineView in the middle """ QDockContainer.__init__(self, parent) self.setWindowTitle('Pipeline') self.pipelineView = QPipelineView() self.pipelineView.scene().pipeline_tab = proxy(self) self.setCentralWidget(self.pipelineView) self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.methodPalette = QMethodPalette(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.methodPalette.toolWindow()) self.moduleMethods = QModuleMethods(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleMethods.toolWindow()) self.moduleConfig = QModuleConfiguration(self, self.pipelineView.scene()) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleConfig.toolWindow()) self.vistrailVars = QVistrailVariables(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.vistrailVars.toolWindow()) self.connect(self.toolWindow(), QtCore.SIGNAL('topLevelChanged(bool)'), self.updateWindowTitle) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('moduleSelected'), self.moduleSelected) self.connect(self.moduleConfig, QtCore.SIGNAL('doneConfigure'), self.pipelineView.scene().perform_configure_done_actions) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('showConfigureWindow'), self.moduleConfig.activate) self.connect(self.pipelineView, QtCore.SIGNAL('resetQuery()'), self.resetQuery) self.controller = None def addViewActionsToMenu(self, menu): """addViewActionsToMenu(menu: QMenu) -> None Add toggle view actions to menu """ menu.addAction(self.methodPalette.toolWindow().toggleViewAction()) menu.addAction(self.moduleMethods.toolWindow().toggleViewAction()) menu.addAction(self.moduleConfig.toolWindow().toggleViewAction()) menu.addAction(self.vistrailVars.toolWindow().toggleViewAction()) def removeViewActionsFromMenu(self, menu): """removeViewActionsFromMenu(menu: QMenu) -> None Remove toggle view actions from menu """ menu.removeAction(self.methodPalette.toolWindow().toggleViewAction()) menu.removeAction(self.moduleMethods.toolWindow().toggleViewAction()) menu.removeAction(self.moduleConfig.toolWindow().toggleViewAction()) menu.removeAction(self.vistrailVars.toolWindow().toggleViewAction()) def updatePipeline(self, pipeline): """ updatePipeline(pipeline: Pipeline) -> None Setup the pipeline to display and control a specific pipeline """ self.pipelineView.scene().setupScene(pipeline) def updateWindowTitle(self, topLevel): """ updateWindowTitle(topLevel: bool) -> None Change the current widget title depends on the top level status """ if topLevel: self.setWindowTitle('Pipeline <' + self.toolWindow().parent().windowTitle()+'>') else: self.setWindowTitle('Pipeline') def moduleSelected(self, moduleId, selection = []): """ moduleChanged(moduleId: int, selection: [QGraphicsModuleItem]) -> None Set up the view when module selection has been changed """ if self.pipelineView.scene().controller: pipeline = self.pipelineView.scene().controller.current_pipeline else: pipeline = None if pipeline and pipeline.modules.has_key(moduleId): module = pipeline.modules[moduleId] self.methodPalette.setEnabled(True) self.moduleMethods.setEnabled(True) self.moduleConfig.setEnabled(True) else: module = None self.methodPalette.setEnabled(False) self.moduleMethods.setEnabled(False) self.moduleConfig.setEnabled(False) self.methodPalette.setUpdatesEnabled(False) self.moduleMethods.setUpdatesEnabled(False) self.moduleConfig.setUpdatesEnabled(False) try: self.methodPalette.updateModule(module) self.moduleMethods.updateModule(module) self.moduleConfig.updateModule(module) self.emit(QtCore.SIGNAL('moduleSelectionChange'), [m.id for m in selection]) finally: self.methodPalette.setUpdatesEnabled(True) self.moduleMethods.setUpdatesEnabled(True) self.moduleConfig.setUpdatesEnabled(True) def setController(self, controller): """ setController(controller: VistrailController) -> None Assign a vistrail controller to this pipeline view """ oldController = self.pipelineView.scene().controller if oldController!=controller: if oldController!=None: self.disconnect(oldController, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) oldController.current_pipeline_view = None self.controller = controller self.pipelineView.scene().controller = controller self.connect(controller, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) self.methodPalette.controller = controller self.moduleMethods.controller = controller self.moduleConfig.controller = controller self.vistrailVars.updateController(controller) controller.current_pipeline_view = self.pipelineView.scene() def versionChanged(self, newVersion): """ versionChanged(newVersion: int) -> None Update the pipeline when the new vistrail selected in the controller """ self.updatePipeline(self.controller.current_pipeline) def resetQuery(self): """ resetQuery() -> None pass along the signal """ self.emit(QtCore.SIGNAL('resetQuery()')) def checkModuleConfigPanel(self): """ checkModuleConfigPanel(self) -> None This will ask if user wants to save changes """ if self.moduleConfig.hasChanges: self.moduleConfig.confWidget.widget.askToSaveChanges()
class QPipelineTab(QDockContainer, QToolWindowInterface): """ QPipelineTab is a tab widget setting QPipelineView in a center while having surrounding tool windows for manipulating a pipeline """ def __init__(self, parent=None): """ QPipelineTab(parent: QWidget) -> QPipelineTab Make it a main window with dockable area and a QPipelineView in the middle """ QDockContainer.__init__(self, parent) self.setWindowTitle('Pipeline') self.pipelineView = QPipelineView() self.pipelineView.scene().pipeline_tab = proxy(self) self.setCentralWidget(self.pipelineView) self.toolWindow().setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures) self.toolWindow().hide() self.methodPalette = QMethodPalette(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.methodPalette.toolWindow()) self.moduleMethods = QModuleMethods(self) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.moduleMethods.toolWindow()) self.connect(self.toolWindow(), QtCore.SIGNAL('topLevelChanged(bool)'), self.updateWindowTitle) self.connect(self.pipelineView.scene(), QtCore.SIGNAL('moduleSelected'), self.moduleSelected) self.connect(self.pipelineView, QtCore.SIGNAL('resetQuery()'), self.resetQuery) self.controller = None def addViewActionsToMenu(self, menu): """addViewActionsToMenu(menu: QMenu) -> None Add toggle view actions to menu """ menu.addAction(self.methodPalette.toolWindow().toggleViewAction()) menu.addAction(self.moduleMethods.toolWindow().toggleViewAction()) def removeViewActionsFromMenu(self, menu): """removeViewActionsFromMenu(menu: QMenu) -> None Remove toggle view actions from menu """ menu.removeAction(self.methodPalette.toolWindow().toggleViewAction()) menu.removeAction(self.moduleMethods.toolWindow().toggleViewAction()) def updatePipeline(self, pipeline): """ updatePipeline(pipeline: Pipeline) -> None Setup the pipeline to display and control a specific pipeline """ self.pipelineView.scene().setupScene(pipeline) def updateWindowTitle(self, topLevel): """ updateWindowTitle(topLevel: bool) -> None Change the current widget title depends on the top level status """ if topLevel: self.setWindowTitle('Pipeline <' + self.toolWindow().parent().windowTitle()+'>') else: self.setWindowTitle('Pipeline') def moduleSelected(self, moduleId, selection = []): """ moduleChanged(moduleId: int, selection: [QGraphicsModuleItem]) -> None Set up the view when module selection has been changed """ if self.pipelineView.scene().controller: pipeline = self.pipelineView.scene().controller.current_pipeline else: pipeline = None if pipeline and pipeline.modules.has_key(moduleId): module = pipeline.modules[moduleId] self.methodPalette.setEnabled(True) self.moduleMethods.setEnabled(True) else: module = None self.methodPalette.setEnabled(False) self.moduleMethods.setEnabled(False) self.methodPalette.setUpdatesEnabled(False) self.moduleMethods.setUpdatesEnabled(False) try: self.methodPalette.updateModule(module) self.moduleMethods.updateModule(module) self.emit(QtCore.SIGNAL('moduleSelectionChange'), [m.id for m in selection]) finally: self.methodPalette.setUpdatesEnabled(True) self.moduleMethods.setUpdatesEnabled(True) def setController(self, controller): """ setController(controller: VistrailController) -> None Assign a vistrail controller to this pipeline view """ oldController = self.pipelineView.scene().controller if oldController!=controller: if oldController!=None: self.disconnect(oldController, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) self.disconnect(oldController, QtCore.SIGNAL('flushMoveActions()'), self.flushMoveActions) oldController.current_pipeline_view = None self.controller = controller self.pipelineView.scene().controller = controller self.connect(controller, QtCore.SIGNAL('versionWasChanged'), self.versionChanged) self.connect(controller, QtCore.SIGNAL('flushMoveActions()'), self.flushMoveActions) self.methodPalette.controller = controller self.moduleMethods.controller = controller controller.current_pipeline_view = self.pipelineView.scene() def versionChanged(self, newVersion): """ versionChanged(newVersion: int) -> None Update the pipeline when the new vistrail selected in the controller """ self.updatePipeline(self.controller.current_pipeline) def flushMoveActions(self): """ flushMoveActions() -> None Update all move actions into vistrail """ controller = self.pipelineView.scene().controller moves = [] for (mId, item) in self.pipelineView.scene().modules.iteritems(): module = controller.current_pipeline.modules[mId] (dx,dy) = (item.scenePos().x(), -item.scenePos().y()) if (dx != module.center.x or dy != module.center.y): moves.append((mId, dx, dy)) if len(moves)>0: controller.quiet = True controller.move_module_list(moves) controller.quiet = False def resetQuery(self): """ resetQuery() -> None pass along the signal """ self.emit(QtCore.SIGNAL('resetQuery()'))
def run_and_get_results(w_list, parameters='', workflow_info=None, update_vistrail=True, extra_info=None, reason='Console Mode Execution'): """run_and_get_results(w_list: list of (locator, version), parameters: str, workflow_info:str, update_vistrail: boolean, extra_info:dict) Run all workflows in w_list, and returns an interpreter result object. version can be a tag name or a version id. """ elements = parameters.split("$&$") aliases = {} result = [] for locator, workflow in w_list: (v, abstractions, thumbnails, mashups) = load_vistrail(locator) controller = VistrailController(auto_save=update_vistrail) controller.set_vistrail(v, locator, abstractions, thumbnails, mashups) 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) for e in elements: pos = e.find("=") if pos != -1: key = e[:pos].strip() value = e[pos + 1:].strip() if controller.current_pipeline.has_alias(key): aliases[key] = value if workflow_info is not None and controller.current_pipeline is not None: if is_running_gui(): from gui.pipeline_view import QPipelineView pipeline_view = QPipelineView() pipeline_view.scene().setupScene(controller.current_pipeline) base_fname = "%s_%s_pipeline.pdf" % (locator.short_name, version) filename = os.path.join(workflow_info, base_fname) pipeline_view.scene().saveToPDF(filename) del pipeline_view else: debug.critical("Cannot save pipeline figure when not " "running in gui mode") base_fname = "%s_%s_pipeline.xml" % (locator.short_name, version) filename = os.path.join(workflow_info, base_fname) core.db.io.save_workflow(controller.current_pipeline, filename) if not update_vistrail: conf = get_vistrails_configuration() if conf.has('thumbs'): conf.thumbs.autoSave = False (results, _) = \ controller.execute_current_workflow(custom_aliases=aliases, extra_info=extra_info, reason=reason) new_version = controller.current_version if new_version != version: debug.warning("Version '%s' (%s) was upgraded. The actual " "version executed was %s" % \ (workflow, version, new_version)) run = results[0] run.workflow_info = (locator.name, new_version) run.pipeline = controller.current_pipeline if update_vistrail: controller.write_vistrail(locator) result.append(run) return result
class QVisualDiff(QtGui.QMainWindow): """ QVisualDiff is a main widget for Visual Diff containing a GL Widget to draw the pipeline """ def __init__(self, vistrail, v1, v2, controller, parent=None, f=QtCore.Qt.WindowFlags()): """ QVisualDiff(vistrail: Vistrail, v1: str, v2: str, parent: QWidget, f: WindowFlags) -> QVisualDiff Initialize with all """ # Set up the version name correctly v1Name = vistrail.getVersionName(v1) if not v1Name: v1Name = 'Version %d' % v1 v2Name = vistrail.getVersionName(v2) if not v2Name: v2Name = 'Version %d' % v2 # Actually perform the diff and store its result self.diff = vistrail.getPipelineDiff(v1, v2) self.v1_name = v1Name self.v2_name = v2Name self.v1 = v1 self.v2 = v2 self.controller = controller # Create the top-level Visual Diff window windowDecors = f | QtCore.Qt.Dialog |QtCore.Qt.WindowMaximizeButtonHint QtGui.QMainWindow.__init__(self, parent) self.setWindowTitle('Visual Diff - from %s to %s' % (v1Name, v2Name)) self.setMouseTracking(True) self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)) self.createPipelineView() self.createToolBar() self.createToolWindows(v1Name, v2Name) def createPipelineView(self): """ createPipelineView() -> None Create a center pipeline view for Visual Diff and setup the view based on the diff result self.diff """ # Initialize the shape engine self.pipelineView = QPipelineView() self.setCentralWidget(self.pipelineView) # Add all the shapes into the view self.createDiffPipeline() # Hook shape selecting functions self.connect(self.pipelineView.scene(), QtCore.SIGNAL("moduleSelected"), self.moduleSelected) def createToolBar(self): """ createToolBar() -> None Create the default toolbar of Visual Diff window with two buttons to toggle the Parameter Inspector and Legend window """ # Initialize the Visual Diff toolbar self.toolBar = self.addToolBar('Visual Diff Toolbar') self.toolBar.setMovable(False) # Add the Show Parameter Inspector action self.showInspectorAction = self.toolBar.addAction( CurrentTheme.VISUAL_DIFF_SHOW_PARAM_ICON, 'Show Parameter Inspector window') self.showInspectorAction.setCheckable(True) self.connect(self.showInspectorAction, QtCore.SIGNAL("toggled(bool)"), self.toggleShowInspector) # Add the Show Legend window action self.showLegendsAction = self.toolBar.addAction( CurrentTheme.VISUAL_DIFF_SHOW_LEGEND_ICON, 'Show Legends') self.showLegendsAction.setCheckable(True) self.connect(self.showLegendsAction, QtCore.SIGNAL("toggled(bool)"), self.toggleShowLegend) # Add the create analogy action self.createAnalogyAction = self.toolBar.addAction( CurrentTheme.VISUAL_DIFF_CREATE_ANALOGY_ICON, 'Create analogy') self.connect(self.createAnalogyAction, QtCore.SIGNAL("triggered()"), self.createAnalogy) def createAnalogy(self): default = 'from %s to %s' % (self.v1_name, self.v2_name) (result, ok) = QtGui.QInputDialog.getText(None, "Enter Analogy Name", "Name of analogy:", QtGui.QLineEdit.Normal, default) if not ok: return result = str(result) try: self.controller.add_analogy(result, self.v1, self.v2) except: QtGui.QMessageBox.warning(self, QtCore.QString("Error"), QtCore.QString("Analogy name already exists"), QtGui.QMessageBox.Ok, QtGui.QMessageBox.NoButton, QtGui.QMessageBox.NoButton) def createToolWindows(self, v1Name, v2Name): """ createToolWindows(v1Name: str, v2Name: str) -> None Create Inspector and Legend window """ self.inspector = QParamInspector(v1Name, v2Name, self) self.inspector.resize(QtCore.QSize( *CurrentTheme.VISUAL_DIFF_PARAMETER_WINDOW_SIZE)) self.legendWindow = QLegendWindow(v1Name, v2Name,self) def moduleSelected(self, id, selectedItems): """ moduleSelected(id: int, selectedItems: [QGraphicsItem]) -> None When the user click on a module, display its parameter changes in the Inspector """ if len(selectedItems)!=1 or id==-1: self.moduleUnselected() return # Interprete the diff result and setup item models (p1, p2, v1Andv2, v1Only, v2Only, paramChanged) = self.diff # Set the window title if id>self.maxId1: self.inspector.setWindowTitle('Parameter Changes - %s' % p2.modules[id-self.maxId1-1].name) else: self.inspector.setWindowTitle('Parameter Changes - %s' % p1.modules[id].name) # Clear the old inspector functions = self.inspector.functionsTab.model() # annotations = self.inspector.annotationsTab.model() functions.clearList() # annotations.clearList() # Find the parameter changed module matching = None for ((m1id, m2id), paramMatching) in paramChanged: if m1id==id: matching = paramMatching break # If the module has no parameter changed, just display nothing if not matching: return # Else just layout the diff on a table functions.insertRows(0,len(matching)) currentRow = 0 for (f1, f2) in matching: if f1[0]!=None: functions.setData( functions.index(currentRow, 0), QtCore.QVariant('%s(%s)' % (f1[0], ','.join(v[1] for v in f1[1])))) if f2[0]!=None: functions.setData( functions.index(currentRow, 1), QtCore.QVariant('%s(%s)' % (f2[0], ','.join(v[1] for v in f2[1])))) if f1==f2: functions.disableRow(currentRow) currentRow += 1 self.inspector.functionsTab.resizeRowsToContents() # self.inspector.annotationsTab.resizeRowsToContents() def moduleUnselected(self): """ moduleUnselected() -> None When a user selects nothing, make sure to display nothing as well """ # self.inspector.annotationsTab.model().clearList() self.inspector.functionsTab.model().clearList() self.inspector.setWindowTitle('Parameter Changes - None') def toggleShowInspector(self): """ toggleShowInspector() -> None Show/Hide the inspector when toggle this button """ if self.inspector.firstTime: max_geom = QtGui.QApplication.desktop().screenGeometry(self) if (self.frameSize().width() < max_geom.width() - self.inspector.width()): self.inspector.move(self.pos().x()+self.frameSize().width(), self.pos().y()) else: self.inspector.move(self.pos().x()+self.frameSize().width()- self.inspector.frameSize().width(), self.pos().y() + self.legendWindow.frameSize().height()) self.inspector.firstTime = False self.inspector.setVisible(self.showInspectorAction.isChecked()) def toggleShowLegend(self): """ toggleShowLegend() -> None Show/Hide the legend window when toggle this button """ if self.legendWindow.firstTime: self.legendWindow.move(self.pos().x()+self.frameSize().width()- self.legendWindow.frameSize().width(), self.pos().y()) self.legendWindow.setVisible(self.showLegendsAction.isChecked()) if self.legendWindow.firstTime: self.legendWindow.firstTime = False self.legendWindow.setFixedSize(self.legendWindow.size()) def createDiffPipeline(self): """ createDiffPipeline() -> None Actually walk through the self.diff result and add all modules into the pipeline view """ # Interprete the diff result (p1, p2, v1Andv2, v1Only, v2Only, paramChanged) = self.diff p1.ensure_connection_specs() p2.ensure_connection_specs() p_both = Pipeline() # the abstraction map is the same for both p1 and p2 p_both.set_abstraction_map(p1.abstraction_map) scene = self.pipelineView.scene() scene.clearItems() # FIXME HACK: We will create a dummy object that looks like a # controller so that the qgraphicsmoduleitems and the scene # are happy. It will simply store the pipeline will all # modules and connections of the diff, and know how to copy stuff class DummyController(object): def __init__(self, pip): self.current_pipeline = pip self.search = None def copy_modules_and_connections(self, module_ids, connection_ids): """copy_modules_and_connections(module_ids: [long], connection_ids: [long]) -> str Serializes a list of modules and connections """ pipeline = Pipeline() pipeline.set_abstraction_map( \ self.current_pipeline.abstraction_map) for module_id in module_ids: module = self.current_pipeline.modules[module_id] if module.vtType == AbstractionModule.vtType: abstraction = \ pipeline.abstraction_map[module.abstraction_id] pipeline.add_abstraction(abstraction) pipeline.add_module(module) for connection_id in connection_ids: connection = self.current_pipeline.connections[connection_id] pipeline.add_connection(connection) return core.db.io.serialize(pipeline) controller = DummyController(p_both) scene.controller = controller # Find the max version id from v1 and start the adding process self.maxId1 = 0 for m1id in p1.modules.keys(): if m1id>self.maxId1: self.maxId1 = m1id shiftId = self.maxId1 + 1 # First add all shared modules, just use v1 module id for (m1id, m2id) in v1Andv2: item = scene.addModule(p1.modules[m1id], CurrentTheme.VISUAL_DIFF_SHARED_BRUSH) item.controller = controller p_both.add_module(copy.copy(p1.modules[m1id])) # Then add parameter changed version for ((m1id, m2id), matching) in paramChanged: m1 = p1.modules[m1id] m2 = p2.modules[m2id] #this is a hack for modules with a dynamic local registry. #The problem arises when modules have the same name but different #input/output ports. We just make sure that the module we add to # the canvas has the ports from both modules, so we don't have # addconnection errors. if m1.registry: m1ports = m1.port_specs.itervalues() ports = {} for p in m1.port_specs.itervalues(): ports[p.name] = p for port in m2.port_specs.itervalues(): if not ports.has_key(port.name): m1.add_port_to_registry(port) else: if ports[port.name].spec != port.spec: #if we add this port, we will get port overloading. #To avoid this, just cast the current port to be of # Module or Variant type. new_port = ports[port.name] m1.delete_port_from_registry(new_port.id) if new_port.type == 'input': new_port.spec = "(Module)" else: new_port.spec = "(Variant)" m1.add_port_to_registry(new_port) item = scene.addModule(p1.modules[m1id], CurrentTheme.VISUAL_DIFF_PARAMETER_CHANGED_BRUSH) item.controller = controller p_both.add_module(copy.copy(p1.modules[m1id])) # Now add the ones only applicable for v1, still using v1 ids for m1id in v1Only: item = scene.addModule(p1.modules[m1id], CurrentTheme.VISUAL_DIFF_FROM_VERSION_BRUSH) item.controller = controller p_both.add_module(copy.copy(p1.modules[m1id])) # Now add the ones for v2 only but must shift the ids away from v1 for m2id in v2Only: p2.modules[m2id].id = m2id + shiftId item = scene.addModule(p2.modules[m2id], CurrentTheme.VISUAL_DIFF_TO_VERSION_BRUSH) item.controller = controller p_both.add_module(copy.copy(p2.modules[m2id])) # Create a mapping between share modules between v1 and v2 v1Tov2 = {} v2Tov1 = {} for (m1id, m2id) in v1Andv2: v1Tov2[m1id] = m2id v2Tov1[m2id] = m1id for ((m1id, m2id), matching) in paramChanged: v1Tov2[m1id] = m2id v2Tov1[m2id] = m1id # Next we're going to add connections, only connections of # v2Only need to shift their ids if p1.connections.keys(): connectionShift = max(p1.connections.keys())+1 else: connectionShift = 0 allConnections = copy.copy(p1.connections) sharedConnections = [] v2OnlyConnections = [] for (cid2, connection2) in copy.copy(p2.connections.items()): if connection2.sourceId in v2Only: connection2.sourceId += shiftId else: connection2.sourceId = v2Tov1[connection2.sourceId] if connection2.destinationId in v2Only: connection2.destinationId += shiftId else: connection2.destinationId = v2Tov1[connection2.destinationId] # Is this connection also shared by p1? shared = False for (cid1, connection1) in p1.connections.items(): if (connection1.sourceId==connection2.sourceId and connection1.destinationId==connection2.destinationId and connection1.source.name==connection2.source.name and connection1.destination.name==connection2.destination.name): sharedConnections.append(cid1) shared = True break if not shared: allConnections[cid2+connectionShift] = connection2 connection2.id = cid2+connectionShift v2OnlyConnections.append(cid2+connectionShift) connectionItems = [] for c in allConnections.values(): p_both.add_connection(copy.copy(c)) connectionItems.append(scene.addConnection(c)) # Color Code connections for c in connectionItems: if c.id in sharedConnections: pass elif c.id in v2OnlyConnections: pen = QtGui.QPen(CurrentTheme.CONNECTION_PEN) pen.setBrush(CurrentTheme.VISUAL_DIFF_TO_VERSION_BRUSH) c.connectionPen = pen else: pen = QtGui.QPen(CurrentTheme.CONNECTION_PEN) pen.setBrush(CurrentTheme.VISUAL_DIFF_FROM_VERSION_BRUSH) c.connectionPen = pen scene.updateSceneBoundingRect() scene.fitToView(self.pipelineView, True)