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)
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)