#!/usr/bin/env python3 # -*- coding: utf-8 -*- # PatchBay Canvas engine using QGraphicsView/Scene # Copyright (C) 2010-2019 Filipe Coelho # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # For a full copy of the GNU General Public License see the doc/GPL.txt file. # ------------------------------------------------------------------------------------------------------------ # Imports (Global) from PyQt5.QtCore import pyqtSlot, qCritical, qFatal, qWarning, QObject from PyQt5.QtCore import QPointF, QRectF, QTimer # ------------------------------------------------------------------------------------------------------------ # Imports (Custom) from . import ( canvas, features, options, group_dict_t, port_dict_t, connection_dict_t, bool2str, icon2str, split2str, port_mode2str, port_type2str, CanvasIconType, CanvasRubberbandType, ACTION_PORTS_DISCONNECT, EYECANDY_FULL, ICON_APPLICATION, ICON_HARDWARE, ICON_LADISH_ROOM, PORT_MODE_INPUT, PORT_MODE_OUTPUT, SPLIT_YES, SPLIT_NO, SPLIT_UNDEF, MAX_PLUGIN_ID_ALLOWED, ) from .canvasbox import CanvasBox from .canvasbezierline import CanvasBezierLine from .canvasline import CanvasLine from .theme import Theme, getDefaultTheme, getThemeName from .utils import CanvasCallback, CanvasGetNewGroupPos, CanvasItemFX, CanvasRemoveItemFX # FIXME from . import * from .scene import PatchScene from carla_shared import QSafeSettings # ------------------------------------------------------------------------------------------------------------ class CanvasObject(QObject): def __init__(self, parent=None): QObject.__init__(self, parent) @pyqtSlot() def AnimationFinishedShow(self): animation = self.sender() if animation: animation.forceStop() canvas.animation_list.remove(animation) @pyqtSlot() def AnimationFinishedHide(self): animation = self.sender() if animation: animation.forceStop() canvas.animation_list.remove(animation) item = animation.item() if item: item.hide() @pyqtSlot() def AnimationFinishedDestroy(self): animation = self.sender() if animation: animation.forceStop() canvas.animation_list.remove(animation) item = animation.item() if item: CanvasRemoveItemFX(item) @pyqtSlot() def PortContextMenuConnect(self): try: sources, targets = self.sender().data() except: return for port_type in (PORT_TYPE_AUDIO_JACK, PORT_TYPE_MIDI_JACK, PORT_TYPE_MIDI_ALSA): source_ports = sources[port_type] target_ports = targets[port_type] source_ports_len = len(source_ports) target_ports_len = len(target_ports) if source_ports_len == 0 or target_ports_len == 0: continue for i in range(min(source_ports_len, target_ports_len)): data = "%i:%i:%i:%i" % (source_ports[i][0], source_ports[i][1], target_ports[i][0], target_ports[i][1]) CanvasCallback(ACTION_PORTS_CONNECT, 0, 0, data) if source_ports_len == 1 and target_ports_len > 1: for i in range(1, target_ports_len): data = "%i:%i:%i:%i" % (source_ports[0][0], source_ports[0][1], target_ports[i][0], target_ports[i][1]) CanvasCallback(ACTION_PORTS_CONNECT, 0, 0, data) @pyqtSlot() def PortContextMenuDisconnect(self): try: connectionId = int(self.sender().data()) except: return CanvasCallback(ACTION_PORTS_DISCONNECT, connectionId, 0, "") # ------------------------------------------------------------------------------------------------------------ def getStoredCanvasPosition(key, fallback_pos): try: return canvas.settings.value("CanvasPositions/" + key, fallback_pos, type=QPointF) except: return fallback_pos def getStoredCanvasSplit(group_name, fallback_split_mode): try: return canvas.settings.value("CanvasPositions/%s_SPLIT" % group_name, fallback_split_mode, type=int) except: return fallback_split_mode # ------------------------------------------------------------------------------------------------------------ def init(appName, scene, callback, debug=False): if debug: print("PatchCanvas::init(\"%s\", %s, %s, %s)" % (appName, scene, callback, bool2str(debug))) if canvas.initiated: qCritical("PatchCanvas::init() - already initiated") return if not callback: qFatal("PatchCanvas::init() - fatal error: callback not set") return canvas.callback = callback canvas.debug = debug canvas.scene = scene canvas.last_z_value = 0 canvas.last_connection_id = 0 canvas.initial_pos = QPointF(0, 0) canvas.size_rect = QRectF() if not canvas.qobject: canvas.qobject = CanvasObject() if not canvas.settings: canvas.settings = QSafeSettings("falkTX", appName) if canvas.theme: del canvas.theme canvas.theme = None for i in range(Theme.THEME_MAX): this_theme_name = getThemeName(i) if this_theme_name == options.theme_name: canvas.theme = Theme(i) break if not canvas.theme: canvas.theme = Theme(getDefaultTheme()) canvas.scene.updateTheme() canvas.initiated = True def clear(): if canvas.debug: print("PatchCanvas::clear()") group_list_ids = [] port_list_ids = [] connection_list_ids = [] for group in canvas.group_list: group_list_ids.append(group.group_id) for port in canvas.port_list: port_list_ids.append((port.group_id, port.port_id)) for connection in canvas.connection_list: connection_list_ids.append(connection.connection_id) for idx in connection_list_ids: disconnectPorts(idx) for group_id, port_id in port_list_ids: removePort(group_id, port_id) for idx in group_list_ids: removeGroup(idx) canvas.last_z_value = 0 canvas.last_connection_id = 0 canvas.group_list = [] canvas.port_list = [] canvas.connection_list = [] canvas.group_plugin_map = {} canvas.scene.clearSelection() animatedItems = [] for animation in canvas.animation_list: animatedItems.append(animation.item()) for item in canvas.scene.items(): if item.type() in (CanvasIconType, CanvasRubberbandType) or item in animatedItems: continue canvas.scene.removeItem(item) del item canvas.initiated = False QTimer.singleShot(0, canvas.scene.update) # ------------------------------------------------------------------------------------------------------------ def setInitialPos(x, y): if canvas.debug: print("PatchCanvas::setInitialPos(%i, %i)" % (x, y)) canvas.initial_pos.setX(x) canvas.initial_pos.setY(y) def setCanvasSize(x, y, width, height): if canvas.debug: print("PatchCanvas::setCanvasSize(%i, %i, %i, %i)" % (x, y, width, height)) canvas.size_rect.setX(x) canvas.size_rect.setY(y) canvas.size_rect.setWidth(width) canvas.size_rect.setHeight(height) canvas.scene.updateLimits() canvas.scene.fixScaleFactor() def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION): if canvas.debug: print("PatchCanvas::addGroup(%i, %s, %s, %s)" % ( group_id, group_name.encode(), split2str(split), icon2str(icon))) for group in canvas.group_list: if group.group_id == group_id: qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists" % ( group_id, group_name.encode(), split2str(split), icon2str(icon))) return if split == SPLIT_UNDEF: isHardware = bool(icon == ICON_HARDWARE) if features.handle_group_pos: split = getStoredCanvasSplit(group_name, SPLIT_YES if isHardware else split) elif isHardware: split = SPLIT_YES group_box = CanvasBox(group_id, group_name, icon) group_dict = group_dict_t() group_dict.group_id = group_id group_dict.group_name = group_name group_dict.split = bool(split == SPLIT_YES) group_dict.icon = icon group_dict.plugin_id = -1 group_dict.plugin_ui = False group_dict.plugin_inline = False group_dict.widgets = [group_box, None] if split == SPLIT_YES: group_box.setSplit(True, PORT_MODE_OUTPUT) if features.handle_group_pos: group_box.setPos(getStoredCanvasPosition(group_name + "_OUTPUT", CanvasGetNewGroupPos(False))) else: group_box.setPos(CanvasGetNewGroupPos(False)) group_sbox = CanvasBox(group_id, group_name, icon) group_sbox.setSplit(True, PORT_MODE_INPUT) group_dict.widgets[1] = group_sbox if features.handle_group_pos: group_sbox.setPos(getStoredCanvasPosition(group_name + "_INPUT", CanvasGetNewGroupPos(True))) else: group_sbox.setPos(CanvasGetNewGroupPos(True)) canvas.last_z_value += 1 group_sbox.setZValue(canvas.last_z_value) if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups: CanvasItemFX(group_sbox, True, False) group_sbox.checkItemPos() else: group_box.setSplit(False) if features.handle_group_pos: group_box.setPos(getStoredCanvasPosition(group_name, CanvasGetNewGroupPos(False))) else: # Special ladish fake-split groups horizontal = bool(icon == ICON_HARDWARE or icon == ICON_LADISH_ROOM) group_box.setPos(CanvasGetNewGroupPos(horizontal)) group_box.checkItemPos() canvas.last_z_value += 1 group_box.setZValue(canvas.last_z_value) canvas.group_list.append(group_dict) if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups: CanvasItemFX(group_box, True, False) return QTimer.singleShot(0, canvas.scene.update) def removeGroup(group_id): if canvas.debug: print("PatchCanvas::removeGroup(%i)" % group_id) for group in canvas.group_list: if group.group_id == group_id: item = group.widgets[0] group_name = group.group_name if group.split: s_item = group.widgets[1] if features.handle_group_pos: canvas.settings.setValue("CanvasPositions/%s_OUTPUT" % group_name, item.pos()) canvas.settings.setValue("CanvasPositions/%s_INPUT" % group_name, s_item.pos()) canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_YES) if options.eyecandy == EYECANDY_FULL: CanvasItemFX(s_item, False, True) else: s_item.removeIconFromScene() canvas.scene.removeItem(s_item) del s_item else: if features.handle_group_pos: canvas.settings.setValue("CanvasPositions/%s" % group_name, item.pos()) canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_NO) if options.eyecandy == EYECANDY_FULL: CanvasItemFX(item, False, True) else: item.removeIconFromScene() canvas.scene.removeItem(item) del item canvas.group_list.remove(group) canvas.group_plugin_map.pop(group.plugin_id, None) QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::removeGroup(%i) - unable to find group to remove" % group_id) def renameGroup(group_id, new_group_name): if canvas.debug: print("PatchCanvas::renameGroup(%i, %s)" % (group_id, new_group_name.encode())) for group in canvas.group_list: if group.group_id == group_id: group.group_name = new_group_name group.widgets[0].setGroupName(new_group_name) if group.split and group.widgets[1]: group.widgets[1].setGroupName(new_group_name) QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::renameGroup(%i, %s) - unable to find group to rename" % (group_id, new_group_name.encode())) def splitGroup(group_id): if canvas.debug: print("PatchCanvas::splitGroup(%i)" % group_id) item = None group_name = "" group_icon = ICON_APPLICATION plugin_id = -1 plugin_ui = False plugin_inline = False ports_data = [] conns_data = [] # Step 1 - Store all Item data for group in canvas.group_list: if group.group_id == group_id: if group.split: qCritical("PatchCanvas::splitGroup(%i) - group is already split" % group_id) return item = group.widgets[0] group_name = group.group_name group_icon = group.icon plugin_id = group.plugin_id plugin_ui = group.plugin_ui plugin_inline = group.plugin_inline break if not item: qCritical("PatchCanvas::splitGroup(%i) - unable to find group to split" % group_id) return port_list_ids = list(item.getPortList()) for port in canvas.port_list: if port.port_id in port_list_ids: port_dict = port_dict_t() port_dict.group_id = port.group_id port_dict.port_id = port.port_id port_dict.port_name = port.port_name port_dict.port_mode = port.port_mode port_dict.port_type = port.port_type port_dict.is_alternate = port.is_alternate port_dict.widget = None ports_data.append(port_dict) for connection in canvas.connection_list: if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids: connection_dict = connection_dict_t() connection_dict.connection_id = connection.connection_id connection_dict.group_in_id = connection.group_in_id connection_dict.port_in_id = connection.port_in_id connection_dict.group_out_id = connection.group_out_id connection_dict.port_out_id = connection.port_out_id connection_dict.widget = None conns_data.append(connection_dict) # Step 2 - Remove Item and Children for conn in conns_data: disconnectPorts(conn.connection_id) for port_id in port_list_ids: removePort(group_id, port_id) removeGroup(group_id) # Step 3 - Re-create Item, now split addGroup(group_id, group_name, SPLIT_YES, group_icon) if plugin_id >= 0: setGroupAsPlugin(group_id, plugin_id, plugin_ui, plugin_inline) for port in ports_data: addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type, port.is_alternate) for conn in conns_data: connectPorts(conn.connection_id, conn.group_out_id, conn.port_out_id, conn.group_in_id, conn.port_in_id) QTimer.singleShot(0, canvas.scene.update) def joinGroup(group_id): if canvas.debug: print("PatchCanvas::joinGroup(%i)" % group_id) item = None s_item = None group_name = "" group_icon = ICON_APPLICATION plugin_id = -1 plugin_ui = False plugin_inline = False ports_data = [] conns_data = [] # Step 1 - Store all Item data for group in canvas.group_list: if group.group_id == group_id: if not group.split: qCritical("PatchCanvas::joinGroup(%i) - group is not split" % group_id) return item = group.widgets[0] s_item = group.widgets[1] group_name = group.group_name group_icon = group.icon plugin_id = group.plugin_id plugin_ui = group.plugin_ui plugin_inline = group.plugin_inline break # FIXME if not (item and s_item): qCritical("PatchCanvas::joinGroup(%i) - unable to find groups to join" % group_id) return port_list_ids = list(item.getPortList()) port_list_idss = s_item.getPortList() for port_id in port_list_idss: if port_id not in port_list_ids: port_list_ids.append(port_id) for port in canvas.port_list: if port.port_id in port_list_ids: port_dict = port_dict_t() port_dict.group_id = port.group_id port_dict.port_id = port.port_id port_dict.port_name = port.port_name port_dict.port_mode = port.port_mode port_dict.port_type = port.port_type port_dict.is_alternate = port.is_alternate port_dict.widget = None ports_data.append(port_dict) for connection in canvas.connection_list: if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids: connection_dict = connection_dict_t() connection_dict.connection_id = connection.connection_id connection_dict.group_in_id = connection.group_in_id connection_dict.port_in_id = connection.port_in_id connection_dict.group_out_id = connection.group_out_id connection_dict.port_out_id = connection.port_out_id connection_dict.widget = None conns_data.append(connection_dict) # Step 2 - Remove Item and Children for conn in conns_data: disconnectPorts(conn.connection_id) for port_id in port_list_ids: removePort(group_id, port_id) removeGroup(group_id) # Step 3 - Re-create Item, now together addGroup(group_id, group_name, SPLIT_NO, group_icon) if plugin_id >= 0: setGroupAsPlugin(group_id, plugin_id, plugin_ui, plugin_inline) for port in ports_data: addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type, port.is_alternate) for conn in conns_data: connectPorts(conn.connection_id, conn.group_out_id, conn.port_out_id, conn.group_in_id, conn.port_in_id) QTimer.singleShot(0, canvas.scene.update) # ------------------------------------------------------------------------------------------------------------ def getGroupPos(group_id, port_mode=PORT_MODE_OUTPUT): if canvas.debug: print("PatchCanvas::getGroupPos(%i, %s)" % (group_id, port_mode2str(port_mode))) for group in canvas.group_list: if group.group_id == group_id: return group.widgets[1 if (group.split and port_mode == PORT_MODE_INPUT) else 0].pos() qCritical("PatchCanvas::getGroupPos(%i, %s) - unable to find group" % (group_id, port_mode2str(port_mode))) return QPointF(0, 0) def saveGroupPositions(): if canvas.debug: print("PatchCanvas::getGroupPositions()") ret = [] for group in canvas.group_list: if group.split: pos1 = group.widgets[0].pos() pos2 = group.widgets[1].pos() else: pos1 = group.widgets[0].pos() pos2 = QPointF(0, 0) ret.append({ "name" : group.group_name, "pos1x": pos1.x(), "pos1y": pos1.y(), "pos2x": pos2.x(), "pos2y": pos2.y(), "split": group.split, }) return ret def restoreGroupPositions(dataList): if canvas.debug: print("PatchCanvas::restoreGroupPositions(...)") mapping = {} for group in canvas.group_list: mapping[group.group_name] = group for data in dataList: name = data['name'] group = mapping.get(name, None) if group is None: continue group.widgets[0].setPos(data['pos1x'], data['pos1y']) if group.split and group.widgets[1]: group.widgets[1].setPos(data['pos2x'], data['pos2y']) def setGroupPos(group_id, group_pos_x, group_pos_y): setGroupPosFull(group_id, group_pos_x, group_pos_y, group_pos_x, group_pos_y) def setGroupPosFull(group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i): if canvas.debug: print("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i)" % ( group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i)) for group in canvas.group_list: if group.group_id == group_id: group.widgets[0].setPos(group_pos_x_o, group_pos_y_o) if group.split and group.widgets[1]: group.widgets[1].setPos(group_pos_x_i, group_pos_y_i) QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i) - unable to find group to reposition" % ( group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i)) # ------------------------------------------------------------------------------------------------------------ def setGroupIcon(group_id, icon): if canvas.debug: print("PatchCanvas::setGroupIcon(%i, %s)" % (group_id, icon2str(icon))) for group in canvas.group_list: if group.group_id == group_id: group.icon = icon group.widgets[0].setIcon(icon) if group.split and group.widgets[1]: group.widgets[1].setIcon(icon) QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon" % (group_id, icon2str(icon))) def setGroupAsPlugin(group_id, plugin_id, hasUI, hasInlineDisplay): if canvas.debug: print("PatchCanvas::setGroupAsPlugin(%i, %i, %s, %s)" % ( group_id, plugin_id, bool2str(hasUI), bool2str(hasInlineDisplay))) for group in canvas.group_list: if group.group_id == group_id: group.plugin_id = plugin_id group.plugin_ui = hasUI group.plugin_inline = hasInlineDisplay group.widgets[0].setAsPlugin(plugin_id, hasUI, hasInlineDisplay) if group.split and group.widgets[1]: group.widgets[1].setAsPlugin(plugin_id, hasUI, hasInlineDisplay) canvas.group_plugin_map[plugin_id] = group return qCritical("PatchCanvas::setGroupAsPlugin(%i, %i, %s, %s) - unable to find group to set as plugin" % ( group_id, plugin_id, bool2str(hasUI), bool2str(hasInlineDisplay))) # ------------------------------------------------------------------------------------------------------------ def addPort(group_id, port_id, port_name, port_mode, port_type, is_alternate=False): if canvas.debug: print("PatchCanvas::addPort(%i, %i, %s, %s, %s, %s)" % ( group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type), bool2str(is_alternate))) for port in canvas.port_list: if port.group_id == group_id and port.port_id == port_id: qWarning("PatchCanvas::addPort(%i, %i, %s, %s, %s) - port already exists" % ( group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type))) return box_widget = None port_widget = None for group in canvas.group_list: if group.group_id == group_id: if group.split and group.widgets[0].getSplittedMode() != port_mode and group.widgets[1]: n = 1 else: n = 0 box_widget = group.widgets[n] port_widget = box_widget.addPortFromGroup(port_id, port_mode, port_type, port_name, is_alternate) break if not (box_widget and port_widget): qCritical("PatchCanvas::addPort(%i, %i, %s, %s, %s) - Unable to find parent group" % ( group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type))) return port_dict = port_dict_t() port_dict.group_id = group_id port_dict.port_id = port_id port_dict.port_name = port_name port_dict.port_mode = port_mode port_dict.port_type = port_type port_dict.is_alternate = is_alternate port_dict.widget = port_widget canvas.port_list.append(port_dict) box_widget.updatePositions() if options.eyecandy == EYECANDY_FULL: CanvasItemFX(port_widget, True, False) return QTimer.singleShot(0, canvas.scene.update) def removePort(group_id, port_id): if canvas.debug: print("PatchCanvas::removePort(%i, %i)" % (group_id, port_id)) for port in canvas.port_list: if port.group_id == group_id and port.port_id == port_id: item = port.widget item.parentItem().removePortFromGroup(port_id) canvas.scene.removeItem(item) canvas.port_list.remove(port) del item QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::removePort(%i, %i) - Unable to find port to remove" % (group_id, port_id)) def renamePort(group_id, port_id, new_port_name): if canvas.debug: print("PatchCanvas::renamePort(%i, %i, %s)" % (group_id, port_id, new_port_name.encode())) for port in canvas.port_list: if port.group_id == group_id and port.port_id == port_id: port.port_name = new_port_name port.widget.setPortName(new_port_name) port.widget.parentItem().updatePositions() QTimer.singleShot(0, canvas.scene.update) return qCritical("PatchCanvas::renamePort(%i, %i, %s) - Unable to find port to rename" % ( group_id, port_id, new_port_name.encode())) def connectPorts(connection_id, group_out_id, port_out_id, group_in_id, port_in_id): if canvas.debug: print("PatchCanvas::connectPorts(%i, %i, %i, %i, %i)" % ( connection_id, group_out_id, port_out_id, group_in_id, port_in_id)) port_out = None port_in = None port_out_parent = None port_in_parent = None for port in canvas.port_list: if port.group_id == group_out_id and port.port_id == port_out_id: port_out = port.widget port_out_parent = port_out.parentItem() elif port.group_id == group_in_id and port.port_id == port_in_id: port_in = port.widget port_in_parent = port_in.parentItem() # FIXME if not (port_out and port_in): qCritical("PatchCanvas::connectPorts(%i, %i, %i, %i, %i) - unable to find ports to connect" % ( connection_id, group_out_id, port_out_id, group_in_id, port_in_id)) return connection_dict = connection_dict_t() connection_dict.connection_id = connection_id connection_dict.group_in_id = group_in_id connection_dict.port_in_id = port_in_id connection_dict.group_out_id = group_out_id connection_dict.port_out_id = port_out_id if options.use_bezier_lines: connection_dict.widget = CanvasBezierLine(port_out, port_in, None) else: connection_dict.widget = CanvasLine(port_out, port_in, None) canvas.scene.addItem(connection_dict.widget) port_out_parent.addLineFromGroup(connection_dict.widget, connection_id) port_in_parent.addLineFromGroup(connection_dict.widget, connection_id) canvas.last_z_value += 1 port_out_parent.setZValue(canvas.last_z_value) port_in_parent.setZValue(canvas.last_z_value) canvas.last_z_value += 1 connection_dict.widget.setZValue(canvas.last_z_value) canvas.connection_list.append(connection_dict) if options.eyecandy == EYECANDY_FULL: item = connection_dict.widget CanvasItemFX(item, True, False) return QTimer.singleShot(0, canvas.scene.update) def disconnectPorts(connection_id): if canvas.debug: print("PatchCanvas::disconnectPorts(%i)" % connection_id) line = None item1 = None item2 = None group1id = port1id = 0 group2id = port2id = 0 for connection in canvas.connection_list: if connection.connection_id == connection_id: group1id = connection.group_out_id group2id = connection.group_in_id port1id = connection.port_out_id port2id = connection.port_in_id line = connection.widget canvas.connection_list.remove(connection) break if not line: qCritical("PatchCanvas::disconnectPorts(%i) - unable to find connection ports" % connection_id) return for port in canvas.port_list: if port.group_id == group1id and port.port_id == port1id: item1 = port.widget break if not item1: qCritical("PatchCanvas::disconnectPorts(%i) - unable to find output port" % connection_id) return for port in canvas.port_list: if port.group_id == group2id and port.port_id == port2id: item2 = port.widget break if not item2: qCritical("PatchCanvas::disconnectPorts(%i) - unable to find input port" % connection_id) return item1.parentItem().removeLineFromGroup(connection_id) item2.parentItem().removeLineFromGroup(connection_id) if options.eyecandy == EYECANDY_FULL: CanvasItemFX(line, False, True) return canvas.scene.removeItem(line) del line QTimer.singleShot(0, canvas.scene.update) # ------------------------------------------------------------------------------------------------------------ def arrange(): if canvas.debug: print("PatchCanvas::arrange()") # ------------------------------------------------------------------------------------------------------------ def updateZValues(): if canvas.debug: print("PatchCanvas::updateZValues()") for group in canvas.group_list: group.widgets[0].resetLinesZValue() if group.split and group.widgets[1]: group.widgets[1].resetLinesZValue() # ------------------------------------------------------------------------------------------------------------ def redrawPluginGroup(plugin_id): group = canvas.group_plugin_map.get(plugin_id, None) if group is None: #qCritical("PatchCanvas::redrawPluginGroup(%i) - unable to find group" % plugin_id) return group.widgets[0].redrawInlineDisplay() if group.split and group.widgets[1]: group.widgets[1].redrawInlineDisplay() def handlePluginRemoved(plugin_id): if canvas.debug: print("PatchCanvas::handlePluginRemoved(%i)" % plugin_id) group = canvas.group_plugin_map.pop(plugin_id, None) if group is not None: group.plugin_id = -1 group.plugin_ui = False group.plugin_inline = False group.widgets[0].removeAsPlugin() if group.split and group.widgets[1]: group.widgets[1].removeAsPlugin() for group in canvas.group_list: if group.plugin_id < plugin_id or group.plugin_id > MAX_PLUGIN_ID_ALLOWED: continue group.plugin_id -= 1 group.widgets[0].m_plugin_id -= 1 if group.split and group.widgets[1]: group.widgets[1].m_plugin_id -= 1 canvas.group_plugin_map[plugin_id] = group def handleAllPluginsRemoved(): if canvas.debug: print("PatchCanvas::handleAllPluginsRemoved()") canvas.group_plugin_map = {} for group in canvas.group_list: if group.plugin_id < 0: continue if group.plugin_id > MAX_PLUGIN_ID_ALLOWED: continue group.plugin_id = -1 group.plugin_ui = False group.plugin_inline = False group.widgets[0].removeAsPlugin() if group.split and group.widgets[1]: group.widgets[1].removeAsPlugin() # ------------------------------------------------------------------------------------------------------------