| @@ -1607,8 +1607,8 @@ class HostWindow(QMainWindow): | |||
| else: | |||
| portType = patchcanvas.PORT_TYPE_NULL | |||
| isAlternate = False | |||
| patchcanvas.addPort(clientId, portId, portName, portMode, portType, isAlternate) | |||
| print('addPort', portId, portGroupId) | |||
| patchcanvas.addPort(clientId, portId, portName, portMode, portType, portGroupId, isAlternate) | |||
| self.updateMiniCanvasLater() | |||
| @pyqtSlot(int, int) | |||
| @@ -132,6 +132,7 @@ class Canvas(object): | |||
| self.group_list = [] | |||
| self.port_list = [] | |||
| self.port_group_list = [] | |||
| self.connection_list = [] | |||
| self.animation_list = [] | |||
| self.group_plugin_map = {} | |||
| @@ -143,6 +144,8 @@ class Canvas(object): | |||
| self.last_connection_id = 0 | |||
| self.initial_pos = QPointF(0, 0) | |||
| self.size_rect = QRectF() | |||
| self.is_line_mov = False | |||
| def callback(self, action, value1, value2, value_str): | |||
| print("Canvas::callback({}, {}, {}, {})".format(action, value1, value2, value_str)) | |||
| @@ -169,10 +172,21 @@ class port_dict_t(object): | |||
| 'port_name', | |||
| 'port_mode', | |||
| 'port_type', | |||
| 'port_group_id', | |||
| 'is_alternate', | |||
| 'widget' | |||
| ] | |||
| class port_group_dict_t(object): | |||
| __slots__ = [ | |||
| 'port_group_id', | |||
| 'group_id', | |||
| 'port_mode', | |||
| 'port_type', | |||
| 'port_id_list', | |||
| 'widget' | |||
| ] | |||
| class connection_dict_t(object): | |||
| __slots__ = [ | |||
| 'connection_id', | |||
| @@ -39,6 +39,7 @@ from . import ( | |||
| PORT_TYPE_PARAMETER, | |||
| ) | |||
| from .utils import CanvasGetPortGroupPosition | |||
| from .canvasportglow import CanvasPortGlow | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| @@ -98,18 +99,20 @@ class CanvasBezierLine(QGraphicsPathItem): | |||
| if self.item1.getPortMode() == PORT_MODE_OUTPUT: | |||
| item1_x = self.item1.scenePos().x() + self.item1.getPortWidth() + 12 | |||
| port_posinport_group1, port_group_lenght1 = CanvasGetPortPositionAndPortGroupLenght(self.item1.getPortId(), self.item1.getPortGroupId()) | |||
| port_pos_1, port_group_len_1 = CanvasGetPortGroupPosition( | |||
| self.item1.getGroupId(), self.item1.getPortId(), | |||
| self.item1.getPortGroupId()) | |||
| if port_group_lenght1 > 2: | |||
| if port_group_len_1 > 2: | |||
| phi = 0.75 | |||
| else: | |||
| phi = 0.62 | |||
| if port_group_lenght1 > 1: | |||
| if port_group_len_1 > 1: | |||
| first_old_y = canvas.theme.port_height * phi | |||
| last_old_y = canvas.theme.port_height * (port_group_lenght1 - phi) | |||
| delta = (last_old_y - first_old_y) / (port_group_lenght1 -1) | |||
| old_y1 = first_old_y + (port_posinport_group1 * delta) - (canvas.theme.port_height * port_posinport_group1) | |||
| last_old_y = canvas.theme.port_height * (port_group_len_1 - phi) | |||
| delta = (last_old_y - first_old_y) / (port_group_len_1 -1) | |||
| old_y1 = first_old_y + (port_pos_1 * delta) - (canvas.theme.port_height * port_pos_1) | |||
| else: | |||
| old_y1 = canvas.theme.port_height / 2 | |||
| @@ -117,18 +120,20 @@ class CanvasBezierLine(QGraphicsPathItem): | |||
| item2_x = self.item2.scenePos().x() | |||
| port_posinport_group2, port_group_lenght2 = CanvasGetPortPositionAndPortGroupLenght(self.item2.getPortId(), self.item2.getPortGroupId()) | |||
| port_pos_2, port_group_len_2 = CanvasGetPortGroupPosition( | |||
| self.item2.getGroupId(), self.item2.getPortId(), | |||
| self.item2.getPortGroupId()) | |||
| if port_group_lenght2 > 2: | |||
| if port_group_len_2 > 2: | |||
| phi = 0.75 | |||
| else: | |||
| phi = 0.62 | |||
| if port_group_lenght2 > 1: | |||
| if port_group_len_2 > 1: | |||
| first_old_y = canvas.theme.port_height * phi | |||
| last_old_y = canvas.theme.port_height * (port_group_lenght2 - phi) | |||
| delta = (last_old_y - first_old_y) / (port_group_lenght2 -1) | |||
| old_y2 = first_old_y + (port_posinport_group2 * delta) - (canvas.theme.port_height * port_posinport_group2) | |||
| last_old_y = canvas.theme.port_height * (port_group_len_2 - phi) | |||
| delta = (last_old_y - first_old_y) / (port_group_len_2 -1) | |||
| old_y2 = first_old_y + (port_pos_2 * delta) - (canvas.theme.port_height * port_pos_2) | |||
| else: | |||
| old_y2 = canvas.theme.port_height / 2 | |||
| @@ -51,12 +51,17 @@ from . import ( | |||
| from .canvasbezierlinemov import CanvasBezierLineMov | |||
| from .canvaslinemov import CanvasLineMov | |||
| from .theme import Theme | |||
| from .utils import CanvasGetFullPortName, CanvasGetPortConnectionList | |||
| from .utils import ( | |||
| CanvasGetFullPortName, | |||
| CanvasGetPortConnectionList, | |||
| CanvasGetPortGroupPosition, | |||
| CanvasGetPortPrintName) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class CanvasPort(QGraphicsItem): | |||
| def __init__(self, group_id, port_id, port_name, port_mode, port_type, is_alternate, parent): | |||
| def __init__(self, group_id, port_id, port_name, port_mode, | |||
| port_type, port_group_id, is_alternate, parent): | |||
| QGraphicsItem.__init__(self) | |||
| self.setParentItem(parent) | |||
| @@ -66,6 +71,7 @@ class CanvasPort(QGraphicsItem): | |||
| self.m_port_mode = port_mode | |||
| self.m_port_type = port_type | |||
| self.m_port_name = port_name | |||
| self.m_port_group_id = port_group_id | |||
| self.m_is_alternate = is_alternate | |||
| # Base Variables | |||
| @@ -76,8 +82,10 @@ class CanvasPort(QGraphicsItem): | |||
| self.m_port_font.setPixelSize(canvas.theme.port_font_size) | |||
| self.m_port_font.setWeight(canvas.theme.port_font_state) | |||
| self.m_line_mov = None | |||
| self.m_line_mov_list = [] | |||
| self.m_dotcon_list = [] | |||
| self.m_hover_item = None | |||
| self.m_last_selected_state = False | |||
| self.m_mouse_down = False | |||
| self.m_cursor_moving = False | |||
| @@ -102,6 +110,9 @@ class CanvasPort(QGraphicsItem): | |||
| def getPortName(self): | |||
| return self.m_port_name | |||
| def getPortGroupId(self): | |||
| return self.m_port_group_id | |||
| def getFullPortName(self): | |||
| return self.parentItem().getGroupName() + ":" + self.m_port_name | |||
| @@ -119,6 +130,10 @@ class CanvasPort(QGraphicsItem): | |||
| self.m_port_type = port_type | |||
| self.update() | |||
| def setPortGroupId(self, port_group_id): | |||
| self.m_port_group_id = port_group_id | |||
| self.update() | |||
| def setPortName(self, port_name): | |||
| if QFontMetrics(self.m_port_font).width(port_name) < QFontMetrics(self.m_port_font).width(self.m_port_name): | |||
| QTimer.singleShot(0, canvas.scene.update) | |||
| @@ -132,7 +147,95 @@ class CanvasPort(QGraphicsItem): | |||
| self.m_port_width = port_width | |||
| self.update() | |||
| def deleteLine2(self): | |||
| for line_mov in self.m_line_mov_list: | |||
| if self.m_line_mov_list.index(line_mov) > 0: | |||
| canvas.scene.removeItem(line_mov) | |||
| else: | |||
| line_mov.setPortPosInPortGroupTo(PORT_IN_PORT_GROUP_POSITION_MONO) | |||
| self.m_line_mov_list = self.m_line_mov_list[:1] | |||
| def resetDotLines(self): | |||
| for connection in self.m_dotcon_list: | |||
| if connection.widget.isReadyToDisc(): | |||
| connection.widget.setReadyToDisc(False) | |||
| connection.widget.updateLineGradient() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(False) | |||
| self.m_dotcon_list.clear() | |||
| def SetAsStereo(self, port_id): | |||
| port_id_list = [] | |||
| for port in canvas.port_list: | |||
| if port.port_id in (self.m_port_id, port_id): | |||
| port_id_list.append(port.port_id) | |||
| CanvasAddPortGroup(self.m_group_id, self.m_port_mode, self.m_port_type, port_id_list ) | |||
| group_name = CanvasGetGroupName(self.m_group_id) | |||
| port_name_list = [] | |||
| # get new port_group_num | |||
| canvas.settings.beginGroup("CanvasPortGroups") | |||
| all_port_group_nums = canvas.settings.childKeys() | |||
| canvas.settings.endGroup() | |||
| n = 1 | |||
| new_port_group_num_name = 'PortGroup_%i' % n | |||
| while new_port_group_num_name in all_port_group_nums: | |||
| n +=1 | |||
| new_port_group_num_name = 'PortGroup_%i' % n | |||
| port_name_list = [] | |||
| for port in canvas.port_list: | |||
| if port.port_id in port_id_list: | |||
| port_name_list.append(port.port_name) | |||
| canvas.settings.remove("ForcedMonoPorts/%s:%s" % (group_name, port.port_name)) | |||
| port_group_tab = [ group_name, self.m_port_mode ] + port_name_list | |||
| canvas.settings.setValue("CanvasPortGroups/%s" % new_port_group_num_name, port_group_tab) | |||
| #canvas.callback(ACTION_SAVE_PORT_GROUP, port_id_list.copy(), (self.m_port_mode, group_name, port_name_list), '') | |||
| self.parentItem().updatePositions() | |||
| def connectToHover(self): | |||
| if self.m_hover_item: | |||
| if self.m_hover_item.type() == CanvasPortType: | |||
| hover_port_id_list = [ self.m_hover_item.getPortId() ] | |||
| elif self.m_hover_item.type() == CanvasPortGroupType: | |||
| hover_port_id_list = self.m_hover_item.getPortsList() | |||
| hover_group_id = self.m_hover_item.getGroupId() | |||
| con_list = [] | |||
| ports_connected_list = [] | |||
| for porthover_id in hover_port_id_list: | |||
| for connection in canvas.connection_list: | |||
| if ((connection.group_out_id == self.m_group_id | |||
| and connection.port_out_id == self.m_port_id | |||
| and connection.group_in_id == hover_group_id | |||
| and connection.port_in_id == porthover_id) | |||
| or (connection.group_out_id == hover_group_id | |||
| and connection.port_out_id == porthover_id | |||
| and connection.group_in_id == self.m_group_id | |||
| and connection.port_in_id == self.m_port_id)): | |||
| con_list.append(connection) | |||
| ports_connected_list.append(porthover_id) | |||
| if len(con_list) == len(hover_port_id_list): | |||
| for connection in con_list: | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
| else: | |||
| for porthover_id in hover_port_id_list: | |||
| if not porthover_id in ports_connected_list: | |||
| if self.m_port_mode == PORT_MODE_OUTPUT: | |||
| conn = "%i:%i:%i:%i" % (self.m_group_id, self.m_port_id, hover_group_id, porthover_id) | |||
| else: | |||
| conn = "%i:%i:%i:%i" % (hover_group_id, porthover_id, self.m_group_id, self.m_port_id) | |||
| canvas.callback(ACTION_PORTS_CONNECT, '', '', conn) | |||
| def type(self): | |||
| return CanvasPortType | |||
| @@ -173,14 +276,23 @@ class CanvasPort(QGraphicsItem): | |||
| ): | |||
| connection.widget.setLocked(True) | |||
| if not self.m_line_mov: | |||
| if not self.m_line_mov_list: | |||
| port_pos, port_group_len = CanvasGetPortGroupPosition( | |||
| self.m_group_id, self.m_port_id, | |||
| self.m_port_group_id) | |||
| if options.use_bezier_lines: | |||
| self.m_line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, self) | |||
| line_mov = CanvasBezierLineMov(self.m_port_mode, | |||
| self.m_port_type, port_pos, | |||
| port_group_len, self) | |||
| else: | |||
| self.m_line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, self) | |||
| canvas.last_z_value += 1 | |||
| self.m_line_mov.setZValue(canvas.last_z_value) | |||
| line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, | |||
| port_pos, port_group_len, self) | |||
| line_mov.setPortPosInPortGroupTo(0) | |||
| self.m_line_mov_list.append(line_mov) | |||
| canvas.is_line_mov = True | |||
| line_mov.setZValue(canvas.last_z_value) | |||
| canvas.last_z_value += 1 | |||
| self.parentItem().setZValue(canvas.last_z_value) | |||
| @@ -188,7 +300,7 @@ class CanvasPort(QGraphicsItem): | |||
| items = canvas.scene.items(event.scenePos(), Qt.ContainsItemShape, Qt.AscendingOrder) | |||
| #for i in range(len(items)): | |||
| for _, itemx in enumerate(items): | |||
| if itemx.type() != CanvasPortType: | |||
| if not itemx.type() in (CanvasPortType, CanvasPortGroupType): | |||
| continue | |||
| if itemx == self: | |||
| continue | |||
| @@ -201,21 +313,99 @@ class CanvasPort(QGraphicsItem): | |||
| if item is not None: | |||
| if item.getPortMode() != self.m_port_mode and item.getPortType() == self.m_port_type: | |||
| item.setSelected(True) | |||
| self.m_hover_item = item | |||
| if item.type() == CanvasPortGroupType: | |||
| if self.m_hover_item != item: | |||
| self.m_hover_item = item | |||
| self.resetDotLines() | |||
| if len(self.m_line_mov_list) <= 1: | |||
| #make original line going to first port of the hover port_group | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setPortPosInPortGroupTo(0) | |||
| line_mov.setPortGroupLenghtTo(len(self.m_hover_item.m_port_id_list)) | |||
| port_pos, port_group_len = CanvasGetPortGroupPosition( | |||
| self.m_group_id, self.m_port_id, self.m_port_group_id) | |||
| #create one line for each port of the hover port_group | |||
| for x in range(1, len(self.m_hover_item.m_port_id_list)): | |||
| if options.use_bezier_lines: | |||
| line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, port_pos, port_group_len, self) | |||
| else: | |||
| line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, port_pos, port_group_len, self) | |||
| line_mov.setPortPosInPortGroupTo(x) | |||
| line_mov.setPortGroupLenghtTo(len(self.m_hover_item.m_port_id_list)) | |||
| self.m_line_mov_list.append(line_mov) | |||
| hover_group_id = self.m_hover_item.getGroupId() | |||
| for port_id in self.m_hover_item.getPortsList(): | |||
| for connection in canvas.connection_list: | |||
| if ((connection.group_out_id == self.m_group_id | |||
| and connection.port_out_id == self.m_port_id | |||
| and connection.group_in_id == hover_group_id | |||
| and connection.port_in_id == port_id) | |||
| or (connection.group_out_id == hover_group_id | |||
| and connection.port_out_id == port_id | |||
| and connection.group_in_id == self.m_group_id | |||
| and connection.port_in_id == self.m_port_id)): | |||
| self.m_dotcon_list.append(connection) | |||
| if len(self.m_dotcon_list) == len(self.m_hover_item.getPortsList()): | |||
| for connection in self.m_dotcon_list: | |||
| connection.widget.setReadyToDisc(True) | |||
| connection.widget.updateLineGradient() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(True) | |||
| elif item.type() == CanvasPortType: | |||
| if self.m_hover_item != item: | |||
| self.m_hover_item = item | |||
| self.deleteLine2() | |||
| self.resetDotLines() | |||
| for connection in canvas.connection_list: | |||
| if ((connection.group_out_id == self.m_group_id | |||
| and connection.port_out_id == self.m_port_id | |||
| and connection.group_in_id == hover_group_id | |||
| and connection.port_in_id == port_id) | |||
| or (connection.group_out_id == hover_group_id | |||
| and connection.port_out_id == port_id | |||
| and connection.group_in_id == self.m_group_id | |||
| and connection.port_in_id == self.m_port_id)): | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(True) | |||
| connection.widget.setReadyToDisc(True) | |||
| connection.widget.updateLineGradient() | |||
| self.m_dotcon_list.append(connection) | |||
| elif connection.widget.isReadyToDisc(): | |||
| connection.widget.setReadyToDisc(False) | |||
| connection.widget.updateLineGradient() | |||
| else: | |||
| self.m_hover_item = None | |||
| self.deleteLine2() | |||
| self.resetDotLines() | |||
| else: | |||
| self.m_hover_item = None | |||
| self.deleteLine2() | |||
| self.resetDotLines() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.updateLinePos(event.scenePos()) | |||
| return event.accept() | |||
| self.m_line_mov.updateLinePos(event.scenePos()) | |||
| QGraphicsItem.mouseMoveEvent(self, event) | |||
| def mouseReleaseEvent(self, event): | |||
| if self.m_mouse_down: | |||
| if self.m_line_mov is not None: | |||
| item = self.m_line_mov | |||
| self.m_line_mov = None | |||
| canvas.scene.removeItem(item) | |||
| del item | |||
| if self.m_line_mov_list: | |||
| for line_mov in self.m_line_mov_list: | |||
| item = line_mov | |||
| canvas.scene.removeItem(item) | |||
| del item | |||
| self.m_line_mov_list.clear() | |||
| for connection in canvas.connection_list: | |||
| if ( | |||
| @@ -228,34 +418,7 @@ class CanvasPort(QGraphicsItem): | |||
| connection.widget.setLocked(False) | |||
| if self.m_hover_item: | |||
| # TODO: a better way to check already existing connection | |||
| for connection in canvas.connection_list: | |||
| hover_group_id = self.m_hover_item.getGroupId() | |||
| hover_port_id = self.m_hover_item.getPortId() | |||
| # FIXME clean ths big if stuff | |||
| if ( | |||
| (connection.group_out_id == self.m_group_id and | |||
| connection.port_out_id == self.m_port_id and | |||
| connection.group_in_id == hover_group_id and | |||
| connection.port_in_id == hover_port_id) | |||
| or | |||
| (connection.group_out_id == hover_group_id and | |||
| connection.port_out_id == hover_port_id and | |||
| connection.group_in_id == self.m_group_id and | |||
| connection.port_in_id == self.m_port_id) | |||
| ): | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
| break | |||
| else: | |||
| if self.m_port_mode == PORT_MODE_OUTPUT: | |||
| conn = "%i:%i:%i:%i" % (self.m_group_id, self.m_port_id, | |||
| self.m_hover_item.getGroupId(), self.m_hover_item.getPortId()) | |||
| canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn) | |||
| else: | |||
| conn = "%i:%i:%i:%i" % (self.m_hover_item.getGroupId(), | |||
| self.m_hover_item.getPortId(), self.m_group_id, self.m_port_id) | |||
| canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn) | |||
| self.connectToHover() | |||
| canvas.scene.clearSelection() | |||
| @@ -269,7 +432,6 @@ class CanvasPort(QGraphicsItem): | |||
| def contextMenuEvent(self, event): | |||
| event.accept() | |||
| canvas.scene.clearSelection() | |||
| self.setSelected(True) | |||
| @@ -281,7 +443,7 @@ class CanvasPort(QGraphicsItem): | |||
| if len(conn_list) > 0: | |||
| for conn_id, group_id, port_id in conn_list: | |||
| act_x_disc = discMenu.addAction(CanvasGetFullPortName(group_id, port_id)) | |||
| act_x_disc.setData(conn_id) | |||
| act_x_disc.setData([conn_id]) | |||
| act_x_disc.triggered.connect(canvas.qobject.PortContextMenuDisconnect) | |||
| else: | |||
| act_x_disc = discMenu.addAction("No connections") | |||
| @@ -290,6 +452,38 @@ class CanvasPort(QGraphicsItem): | |||
| menu.addMenu(discMenu) | |||
| act_x_disc_all = menu.addAction("Disconnect &All") | |||
| act_x_sep_1 = menu.addSeparator() | |||
| if self.m_port_type == PORT_TYPE_AUDIO_JACK and self.m_port_group_id: | |||
| StereoMenu = QMenu('Set as Stereo with', menu) | |||
| menu.addMenu(StereoMenu) | |||
| #get list of available mono ports settables as stereo with port | |||
| port_cousin_list = [] | |||
| for port in canvas.port_list: | |||
| if (port.port_type == PORT_TYPE_AUDIO_JACK | |||
| and port.group_id == self.m_group_id | |||
| and port.port_mode == self.m_port_mode): | |||
| port_cousin_list.append(port.port_id) | |||
| selfport_index = port_cousin_list.index(self.m_port_id) | |||
| stereo_able_ids_list = [] | |||
| if selfport_index > 0: | |||
| stereo_able_ids_list.append(port_cousin_list[selfport_index -1]) | |||
| if selfport_index < len(port_cousin_list) -1: | |||
| stereo_able_ids_list.append(port_cousin_list[selfport_index +1]) | |||
| at_least_one = False | |||
| for port in canvas.port_list: | |||
| if port.port_id in stereo_able_ids_list and not port.port_group_id: | |||
| act_x_setasstereo = StereoMenu.addAction(port.port_name) | |||
| act_x_setasstereo.setData([self, port.port_id]) | |||
| act_x_setasstereo.triggered.connect(canvas.qobject.SetasStereoWith) | |||
| at_least_one = True | |||
| if not at_least_one: | |||
| act_x_setasstereo = StereoMenu.addAction('no available mono port') | |||
| act_x_setasstereo.setEnabled(False) | |||
| act_x_info = menu.addAction("Get &Info") | |||
| act_x_rename = menu.addAction("&Rename") | |||
| @@ -305,23 +499,24 @@ class CanvasPort(QGraphicsItem): | |||
| act_selected = menu.exec_(event.screenPos()) | |||
| if act_selected == act_x_disc_all: | |||
| self.triggerDisconnect(conn_list) | |||
| for conn_id, group_id, port_id in conn_list: | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, conn_id, 0, "") | |||
| elif act_selected == act_x_info: | |||
| canvas.callback(ACTION_PORT_INFO, self.m_group_id, self.m_port_id, "") | |||
| elif act_selected == act_x_rename: | |||
| canvas.callback(ACTION_PORT_RENAME, self.m_group_id, self.m_port_id, "") | |||
| def setPortSelected(self, yesno): | |||
| for connection in canvas.connection_list: | |||
| if ( | |||
| (connection.group_out_id == self.m_group_id and | |||
| connection.port_out_id == self.m_port_id) | |||
| connection.port_out_id == self.m_port_id) | |||
| or | |||
| (connection.group_in_id == self.m_group_id and | |||
| connection.port_in_id == self.m_port_id) | |||
| ): | |||
| connection.port_in_id == self.m_port_id) | |||
| ): | |||
| connection.widget.updateLineSelected() | |||
| def itemChange(self, change, value): | |||
| @@ -336,12 +531,19 @@ class CanvasPort(QGraphicsItem): | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, conn_id, 0, "") | |||
| def boundingRect(self): | |||
| return QRectF(0, 0, self.m_port_width + 12, self.m_port_height) | |||
| if self.m_port_group_id: | |||
| if self.m_port_mode == PORT_MODE_INPUT: | |||
| return QRectF(0, 0, canvas.theme.port_in_port_group_width, self.m_port_height) | |||
| else: | |||
| return QRectF(self.m_port_width +12 - canvas.theme.port_in_port_group_width, | |||
| 0, canvas.theme.port_in_port_group_width, self.m_port_height) | |||
| else: | |||
| return QRectF(0, 0, self.m_port_width + 12, self.m_port_height) | |||
| def paint(self, painter, option, widget): | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL)) | |||
| selected = self.isSelected() | |||
| theme = canvas.theme | |||
| if self.m_port_type == PORT_TYPE_AUDIO_JACK: | |||
| @@ -380,7 +582,7 @@ class CanvasPort(QGraphicsItem): | |||
| lineHinting = poly_pen.widthF() / 2 | |||
| poly_locx = [0, 0, 0, 0, 0] | |||
| poly_locx = [0, 0, 0, 0, 0, 0] | |||
| poly_corner_xhinting = (float(canvas.theme.port_height)/2) % floor(float(canvas.theme.port_height)/2) | |||
| if poly_corner_xhinting == 0: | |||
| poly_corner_xhinting = 0.5 * (1 - 7 / (float(canvas.theme.port_height)/2)) | |||
| @@ -394,12 +596,14 @@ class CanvasPort(QGraphicsItem): | |||
| poly_locx[2] = self.m_port_width + 12 - poly_corner_xhinting | |||
| poly_locx[3] = self.m_port_width + 5 - lineHinting | |||
| poly_locx[4] = lineHinting | |||
| poly_locx[5] = canvas.theme.port_in_port_group_width | |||
| elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: | |||
| poly_locx[0] = lineHinting | |||
| poly_locx[1] = self.m_port_width + 5 - lineHinting | |||
| poly_locx[2] = self.m_port_width + 5 - lineHinting | |||
| poly_locx[3] = self.m_port_width + 5 - lineHinting | |||
| poly_locx[4] = lineHinting | |||
| poly_locx[5] = canvas.theme.port_in_port_group_width | |||
| else: | |||
| qCritical("PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) | |||
| return | |||
| @@ -413,12 +617,14 @@ class CanvasPort(QGraphicsItem): | |||
| poly_locx[2] = 0 + poly_corner_xhinting | |||
| poly_locx[3] = 7 + lineHinting | |||
| poly_locx[4] = self.m_port_width + 12 - lineHinting | |||
| poly_locx[5] = self.m_port_width + 12 - canvas.theme.port_in_port_group_width - lineHinting | |||
| elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: | |||
| poly_locx[0] = self.m_port_width + 12 - lineHinting | |||
| poly_locx[1] = 5 + lineHinting | |||
| poly_locx[2] = 5 + lineHinting | |||
| poly_locx[3] = 5 + lineHinting | |||
| poly_locx[4] = self.m_port_width + 12 - lineHinting | |||
| poly_locx[5] = self.m_port_width + 12 -canvas.theme.port_in_port_group_width - lineHinting | |||
| else: | |||
| qCritical("PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) | |||
| return | |||
| @@ -427,13 +633,46 @@ class CanvasPort(QGraphicsItem): | |||
| qCritical("PatchCanvas::CanvasPort.paint() - invalid port mode '%s'" % port_mode2str(self.m_port_mode)) | |||
| return | |||
| polygon = QPolygonF() | |||
| polygon += QPointF(poly_locx[0], lineHinting) | |||
| polygon += QPointF(poly_locx[1], lineHinting) | |||
| polygon += QPointF(poly_locx[2], float(canvas.theme.port_height)/2) | |||
| polygon += QPointF(poly_locx[3], canvas.theme.port_height - lineHinting) | |||
| polygon += QPointF(poly_locx[4], canvas.theme.port_height - lineHinting) | |||
| polygon += QPointF(poly_locx[0], lineHinting) | |||
| if self.m_is_alternate: | |||
| poly_color = poly_color.darker(180) | |||
| #poly_pen.setColor(poly_pen.color().darker(110)) | |||
| #text_pen.setColor(text_pen.color()) #.darker(150)) | |||
| #conn_pen.setColor(conn_pen.color()) #.darker(150)) | |||
| polygon = QPolygonF() | |||
| if self.m_port_group_id: | |||
| first_of_port_group = False | |||
| last_of_port_group = False | |||
| for port_group in canvas.port_group_list: | |||
| if port_group.port_group_id == self.m_port_group_id: | |||
| if self.m_port_id == port_group.port_id_list[0]: | |||
| first_of_port_group = True | |||
| if self.m_port_id == port_group.port_id_list[-1]: | |||
| last_of_port_group = True | |||
| break | |||
| if first_of_port_group: | |||
| polygon += QPointF(poly_locx[0] , lineHinting) | |||
| polygon += QPointF(poly_locx[5] , lineHinting) | |||
| else: | |||
| polygon += QPointF(poly_locx[0] , 0) | |||
| polygon += QPointF(poly_locx[5] , 0) | |||
| if last_of_port_group: | |||
| polygon += QPointF(poly_locx[5], canvas.theme.port_height - lineHinting) | |||
| polygon += QPointF(poly_locx[0], canvas.theme.port_height - lineHinting) | |||
| else: | |||
| polygon += QPointF(poly_locx[5], canvas.theme.port_height) | |||
| polygon += QPointF(poly_locx[0], canvas.theme.port_height) | |||
| else: | |||
| polygon += QPointF(poly_locx[0], lineHinting) | |||
| polygon += QPointF(poly_locx[1], lineHinting) | |||
| polygon += QPointF(poly_locx[2], float(canvas.theme.port_height)/2) | |||
| polygon += QPointF(poly_locx[3], canvas.theme.port_height - lineHinting) | |||
| polygon += QPointF(poly_locx[4], canvas.theme.port_height - lineHinting) | |||
| polygon += QPointF(poly_locx[0], lineHinting) | |||
| if canvas.theme.port_bg_pixmap: | |||
| portRect = polygon.boundingRect().adjusted(-lineHinting+1, -lineHinting+1, lineHinting-1, lineHinting-1) | |||
| @@ -447,21 +686,44 @@ class CanvasPort(QGraphicsItem): | |||
| painter.setPen(text_pen) | |||
| painter.setFont(self.m_port_font) | |||
| painter.drawText(text_pos, self.m_port_name) | |||
| if self.m_port_group_id: | |||
| print_name = CanvasGetPortPrintName( | |||
| self.m_group_id, self.m_port_id, | |||
| self.m_port_group_id) | |||
| print_name_size = QFontMetrics(self.m_port_font).width(print_name) | |||
| if self.m_port_mode == PORT_MODE_OUTPUT: | |||
| text_pos = QPointF(self.m_port_width + 9 - print_name_size, canvas.theme.port_text_ypos) | |||
| if print_name_size > (canvas.theme.port_in_port_group_width - 6): | |||
| painter.setPen(QPen(poly_color, 3)) | |||
| painter.drawLine(poly_locx[5], 3, poly_locx[5], canvas.theme.port_height - 3) | |||
| painter.setPen(text_pen) | |||
| painter.setFont(self.m_port_font) | |||
| painter.drawText(text_pos, print_name) | |||
| else: | |||
| painter.drawText(text_pos, self.m_port_name) | |||
| if self.isSelected() != self.m_last_selected_state: | |||
| for connection in canvas.connection_list: | |||
| if ((connection.group_out_id == self.m_group_id and connection.port_out_id == self.m_port_id) or | |||
| (connection.group_in_id == self.m_group_id and connection.port_in_id == self.m_port_id)): | |||
| connection.widget.setLineSelected(self.isSelected()) | |||
| if canvas.theme.idx == Theme.THEME_OOSTUDIO and canvas.theme.port_bg_pixmap: | |||
| conn_pen.setCosmetic(True) | |||
| conn_pen.setWidthF(0.4) | |||
| painter.setPen(conn_pen) | |||
| painter.setPen(Qt.NoPen) | |||
| painter.setBrush(conn_pen.brush()) | |||
| if self.m_port_mode == PORT_MODE_INPUT: | |||
| connLineX = portRect.left()+1 | |||
| connRect = QRectF(portRect.topLeft(), QSizeF(2, portRect.height())) | |||
| else: | |||
| connLineX = portRect.right()-1 | |||
| conn_path = QPainterPath() | |||
| conn_path.addRect(QRectF(connLineX-1, portRect.top(), 2, portRect.height())) | |||
| painter.fillPath(conn_path, conn_pen.brush()) | |||
| painter.drawLine(QLineF(connLineX, portRect.top(), connLineX, portRect.bottom())) | |||
| connRect = QRectF(QPointF(portRect.right()-2, portRect.top()), QSizeF(2, portRect.height())) | |||
| painter.drawRect(connRect) | |||
| self.m_last_selected_state = self.isSelected() | |||
| painter.restore() | |||
| @@ -0,0 +1,694 @@ | |||
| #!/usr/bin/env python3 | |||
| # -*- coding: utf-8 -*- | |||
| # PatchBay Canvas engine using QGraphicsView/Scene | |||
| # Copyright (C) 2010-2019 Filipe Coelho <falktx@falktx.com> | |||
| # | |||
| # 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 math import floor | |||
| from PyQt5.QtCore import qCritical, Qt, QLineF, QPointF, QRectF, QTimer | |||
| from PyQt5.QtGui import QCursor, QFont, QFontMetrics, QPainter, QPainterPath, QPen, QPolygonF | |||
| from PyQt5.QtWidgets import QGraphicsItem, QMenu | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom) | |||
| from . import ( | |||
| canvas, | |||
| features, | |||
| options, | |||
| port_mode2str, | |||
| port_type2str, | |||
| CanvasPortType, | |||
| ANTIALIASING_FULL, | |||
| ACTION_PORT_INFO, | |||
| ACTION_PORT_RENAME, | |||
| ACTION_PORTS_CONNECT, | |||
| ACTION_PORTS_DISCONNECT, | |||
| PORT_MODE_INPUT, | |||
| PORT_MODE_OUTPUT, | |||
| PORT_TYPE_AUDIO_JACK, | |||
| PORT_TYPE_MIDI_ALSA, | |||
| PORT_TYPE_MIDI_JACK, | |||
| PORT_TYPE_PARAMETER, | |||
| ) | |||
| from .canvasbezierlinemov import CanvasBezierLineMov | |||
| from .canvaslinemov import CanvasLineMov | |||
| from .theme import Theme | |||
| from .utils import CanvasGetFullPortName, CanvasGetPortConnectionList, CanvasGetPortGroupPosition | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class CanvasPortGroup(QGraphicsItem): | |||
| def __init__(self, port_group_id, port_mode, port_type, port_id_list, parent): | |||
| QGraphicsItem.__init__(self) | |||
| self.setParentItem(parent) | |||
| # Save Variables, useful for later | |||
| self.m_port_group_id = port_group_id | |||
| self.m_port_mode = port_mode | |||
| self.m_port_type = port_type | |||
| self.m_port_id_list = port_id_list | |||
| self.m_group_id = parent.getGroupId() | |||
| # Base Variables | |||
| self.m_port_group_width = 15 | |||
| self.m_port_group_height = canvas.theme.port_height | |||
| self.m_port_group_font = QFont() | |||
| self.m_port_group_font.setFamily(canvas.theme.port_font_name) | |||
| self.m_port_group_font.setPixelSize(canvas.theme.port_font_size) | |||
| self.m_port_group_font.setWeight(canvas.theme.port_font_state) | |||
| self.m_line_mov_list = [] | |||
| self.m_r_click_conn = None | |||
| self.m_r_click_time = 0 | |||
| self.m_dotcon_list = [] | |||
| self.m_hover_item = None | |||
| self.m_last_selected_state = False | |||
| self.m_mouse_down = False | |||
| self.m_cursor_moving = False | |||
| self.setFlags(QGraphicsItem.ItemIsSelectable) | |||
| def getPortGroupId(self): | |||
| return self.m_port_group_id | |||
| def getPortMode(self): | |||
| return self.m_port_mode | |||
| def getPortType(self): | |||
| return self.m_port_type | |||
| def getGroupId(self): | |||
| return self.m_group_id | |||
| def getPortWidth(self): | |||
| return self.m_port_group_width | |||
| def getPortGroupWidth(self): | |||
| return self.m_port_group_width | |||
| def getPortGroupHeight(self): | |||
| return self.m_port_height | |||
| def getPortsList(self): | |||
| return self.m_port_id_list | |||
| def setPortMode(self, port_mode): | |||
| self.m_port_mode = port_mode | |||
| self.update() | |||
| def type(self): | |||
| return CanvasPortGroupType | |||
| def setPortGroupWidth(self, port_group_width): | |||
| if port_group_width < self.m_port_group_width: | |||
| QTimer.singleShot(0, canvas.scene.update) | |||
| self.m_port_group_width = port_group_width | |||
| self.update() | |||
| def SplitToMonos(self): | |||
| groupItem = self.parentItem() | |||
| CanvasSplitPortGroup(self.m_port_group_id) | |||
| groupItem.updatePositions() | |||
| def ConnectToHover(self): | |||
| if self.m_hover_item: | |||
| if self.m_hover_item.type() == CanvasPortType: | |||
| hover_port_id_list = [ self.m_hover_item.getPortId() ] | |||
| elif self.m_hover_item.type() == CanvasPortGroupType: | |||
| hover_port_id_list = self.m_hover_item.getPortsList() | |||
| con_list = [] | |||
| ports_connected_list = [] | |||
| for port in canvas.port_list: | |||
| if port.port_id == hover_port_id_list[0]: | |||
| hover_port_group_id = port.group_id | |||
| break | |||
| else: | |||
| return | |||
| for port in canvas.port_list: | |||
| if port.port_id in self.m_port_id_list: | |||
| selfgroup_id = port.group_id | |||
| break | |||
| else: | |||
| return | |||
| for portself_id in self.m_port_id_list: | |||
| for porthover_id in hover_port_id_list: | |||
| for connection in canvas.connection_list: | |||
| if ( (connection.port_out_id == portself_id and connection.port_in_id == porthover_id) or | |||
| (connection.port_out_id == porthover_id and connection.port_in_id == portself_id) ): | |||
| if ( (self.m_port_id_list.index(portself_id) % len(hover_port_id_list)) == | |||
| (hover_port_id_list.index(porthover_id) % len(self.m_port_id_list)) ): | |||
| con_list.append(connection) | |||
| ports_connected_list.append([portself_id, porthover_id]) | |||
| else: | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
| maxport_group = len(hover_port_id_list) if len(hover_port_id_list) > len(self.m_port_id_list) else len(self.m_port_id_list) | |||
| if len(con_list) == maxport_group: | |||
| for connection in con_list: | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
| else: | |||
| for portself_id in self.m_port_id_list: | |||
| for porthover_id in hover_port_id_list: | |||
| if ((self.m_port_id_list.index(portself_id) % len(hover_port_id_list)) == | |||
| (hover_port_id_list.index(porthover_id) % len(self.m_port_id_list))): | |||
| if not [portself_id, porthover_id] in ports_connected_list: | |||
| if self.m_port_mode == PORT_MODE_OUTPUT: | |||
| conn = "%i:%i:%i:%i" % (selfgroup_id, portself_id, hover_port_group_id, porthover_id) | |||
| else: | |||
| conn = "%i:%i:%i:%i" % (hover_port_group_id, porthover_id, selfgroup_id, portself_id) | |||
| canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn) | |||
| def resetDotLines(self): | |||
| for connection in self.m_dotcon_list: | |||
| if connection.widget.isReadyToDisc(): | |||
| connection.widget.setReadyToDisc(False) | |||
| connection.widget.updateLineGradient() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(False) | |||
| def resetLineMovPositions(self): | |||
| for line_mov in self.m_line_mov_list: | |||
| if self.m_line_mov_list.index(line_mov) < len(self.m_port_id_list): | |||
| line_mov.setPortPosInPortGroupTo(line_mov.m_port_posinport_group) | |||
| line_mov.setPortGroupLenghtTo(line_mov.m_port_group_lenght) | |||
| else: | |||
| item = line_mov | |||
| canvas.scene.removeItem(item) | |||
| del item | |||
| self.m_line_mov_list = self.m_line_mov_list[:len(self.m_port_id_list)] | |||
| def mousePressEvent(self, event): | |||
| if event.button() == Qt.LeftButton: | |||
| self.m_hover_item = None | |||
| self.m_mouse_down = True | |||
| self.m_cursor_moving = False | |||
| #elif event.button() == Qt.RightButton: | |||
| #if canvas.is_line_mov: | |||
| #if self.m_hover_item: | |||
| #self.ConnectToHover() | |||
| ##self.m_r_click_conn = self.m_hover_item | |||
| ##self.m_r_click_time = time.time() | |||
| #for line_mov in self.m_line_mov_list: | |||
| #line_mov.toggleReadyToDisc() | |||
| #line_mov.updateLinePos(event.scenePos()) | |||
| QGraphicsItem.mousePressEvent(self, event) | |||
| def mouseMoveEvent(self, event): | |||
| if self.m_mouse_down: | |||
| if not self.m_cursor_moving: | |||
| self.setCursor(QCursor(Qt.CrossCursor)) | |||
| self.m_cursor_moving = True | |||
| for connection in canvas.connection_list: | |||
| if connection.port_out_id in self.m_port_id_list or connection.port_in_id in self.m_port_id_list: | |||
| connection.widget.setLocked(True) | |||
| if not self.m_line_mov_list: | |||
| self.m_r_click_conn = None | |||
| canvas.last_z_value += 1 | |||
| self.setZValue(canvas.last_z_value) | |||
| canvas.last_z_value += 1 | |||
| for port in canvas.port_list: | |||
| if port.port_id in self.m_port_id_list: | |||
| port.widget.setZValue(canvas.last_z_value) | |||
| #for port in canvas.port_list: | |||
| #if (not port.port_id in self.m_port_id_list and | |||
| #(port.port_type != self.m_port_type or | |||
| #port.port_mode == self.m_port_mode)): | |||
| #port.widget.setOpacity(0.35) | |||
| #for port_group in canvas.port_group_list: | |||
| #if (port_group.port_group_id != self.m_port_group_id and | |||
| #(port_group.port_type != self.m_port_type or | |||
| #port_group.port_mode == self.m_port_mode)): | |||
| #port_group.widget.setOpacity(0.35) | |||
| for port_id in self.m_port_id_list: | |||
| port_posinport_group, port_group_lenght = CanvasGetPortPositionAndPortGroupLenght(port_id, self.m_port_group_id) | |||
| if options.use_bezier_lines: | |||
| line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, port_posinport_group, port_group_lenght, self) | |||
| else: | |||
| line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, port_posinport_group, port_group_lenght, self) | |||
| #line_mov.setZValue(canvas.last_z_value) | |||
| self.m_line_mov_list.append(line_mov) | |||
| canvas.is_line_mov = True | |||
| canvas.last_z_value += 1 | |||
| self.parentItem().setZValue(canvas.last_z_value) | |||
| item = None | |||
| items = canvas.scene.items(event.scenePos(), Qt.ContainsItemShape, Qt.AscendingOrder) | |||
| for i in range(len(items)): | |||
| if items[i].type() == CanvasPortType or items[i].type() == CanvasPortGroupType: | |||
| if items[i] != self: | |||
| if not item: | |||
| item = items[i] | |||
| elif items[i].parentItem().zValue() > item.parentItem().zValue(): | |||
| item = items[i] | |||
| if self.m_hover_item and self.m_hover_item != item: | |||
| self.m_hover_item.setSelected(False) | |||
| if item: | |||
| if item.getPortMode() != self.m_port_mode and item.getPortType() == self.m_port_type: | |||
| item.setSelected(True) | |||
| if item.type() == CanvasPortType: | |||
| if self.m_hover_item != item: | |||
| self.m_hover_item = item | |||
| self.resetDotLines() | |||
| self.resetLineMovPositions() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setPortPosInPortGroupTo(PORT_IN_PORT_GROUP_POSITION_MONO) | |||
| self.m_dotcon_list = [] | |||
| for port_id in self.m_port_id_list: | |||
| for connection in canvas.connection_list: | |||
| if ( (connection.port_out_id == self.m_hover_item.getPortId() and connection.port_in_id == port_id) or | |||
| (connection.port_out_id == port_id and connection.port_in_id == self.m_hover_item.getPortId()) ): | |||
| self.m_dotcon_list.append(connection) | |||
| if len(self.m_dotcon_list) == len(self.m_port_id_list): | |||
| for connection in self.m_dotcon_list: | |||
| connection.widget.setReadyToDisc(True) | |||
| connection.widget.updateLineGradient() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(True) | |||
| elif item.type() == CanvasPortGroupType: | |||
| if self.m_hover_item != item: | |||
| self.m_hover_item = item | |||
| self.resetDotLines() | |||
| self.resetLineMovPositions() | |||
| if len(self.m_hover_item.m_port_id_list) <= len(self.m_line_mov_list): | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setPortPosInPortGroupTo(line_mov.m_port_posinport_group % len(self.m_hover_item.m_port_id_list)) | |||
| line_mov.setPortGroupLenghtTo(len(self.m_hover_item.m_port_id_list)) | |||
| else: | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setPortGroupLenghtTo(len(self.m_hover_item.m_port_id_list)) | |||
| #create new lines when line is hover a biggest port_group | |||
| for x in range(len(self.m_port_id_list), len(self.m_hover_item.m_port_id_list)): | |||
| port_posinport_group = x % len(self.m_port_id_list) | |||
| port_group_lenght = len(self.m_port_id_list) | |||
| if options.use_bezier_lines: | |||
| line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, port_posinport_group, port_group_lenght, self) | |||
| else: | |||
| line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, port_posinport_group, port_group_lenght, self) | |||
| line_mov.setPortPosInPortGroupTo(x) | |||
| line_mov.setPortGroupLenghtTo(len(self.m_hover_item.m_port_id_list)) | |||
| self.m_line_mov_list.append(line_mov) | |||
| self.m_dotcon_list = [] | |||
| symetric_con_list = [] | |||
| for portself_id in self.m_port_id_list: | |||
| for porthover_id in self.m_hover_item.getPortsList(): | |||
| for connection in canvas.connection_list: | |||
| if ( (connection.port_out_id == portself_id and connection.port_in_id == porthover_id) or | |||
| (connection.port_out_id == porthover_id and connection.port_in_id == portself_id) ): | |||
| if (self.m_port_id_list.index(portself_id) % len(self.m_hover_item.getPortsList())) == (self.m_hover_item.m_port_id_list.index(porthover_id) % len(self.m_port_id_list)): | |||
| self.m_dotcon_list.append(connection) | |||
| symetric_con_list.append(connection) | |||
| else: | |||
| self.m_dotcon_list.append(connection) | |||
| connection.widget.setReadyToDisc(True) | |||
| connection.widget.updateLineGradient() | |||
| if len(self.m_port_id_list) >= len(self.m_hover_item.getPortsList()): | |||
| biggest_list = self.m_port_id_list | |||
| else: | |||
| biggest_list = self.m_hover_item.getPortsList() | |||
| if len(symetric_con_list) == len(biggest_list): | |||
| for connection in self.m_dotcon_list: | |||
| connection.widget.setReadyToDisc(True) | |||
| connection.widget.updateLineGradient() | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.setReadyToDisc(True) | |||
| else: | |||
| self.m_hover_item = None | |||
| self.m_r_click_conn = None | |||
| self.resetDotLines() | |||
| self.resetLineMovPositions() | |||
| for port_id in self.m_port_id_list: | |||
| port_posinport_group = self.m_port_id_list.index(port_id) | |||
| self.m_line_mov_list[port_posinport_group].setPortPosInPortGroupTo(port_posinport_group) | |||
| else: | |||
| if self.m_hover_item: | |||
| self.m_hover_item = None | |||
| self.m_r_click_conn = None | |||
| self.resetDotLines() | |||
| self.resetLineMovPositions() | |||
| for port_id in self.m_port_id_list: | |||
| port_posinport_group = self.m_port_id_list.index(port_id) | |||
| self.m_line_mov_list[port_posinport_group].setPortPosInPortGroupTo(port_posinport_group) | |||
| for line_mov in self.m_line_mov_list: | |||
| line_mov.updateLinePos(event.scenePos()) | |||
| return event.accept() | |||
| QGraphicsItem.mouseMoveEvent(self, event) | |||
| def mouseReleaseEvent(self, event): | |||
| if event.button() == Qt.LeftButton: | |||
| if self.m_mouse_down: | |||
| for line_mov in self.m_line_mov_list: | |||
| item = line_mov | |||
| canvas.scene.removeItem(item) | |||
| del item | |||
| self.m_line_mov_list.clear() | |||
| for port in canvas.port_list: | |||
| port.widget.setOpacity(1) | |||
| for port_group in canvas.port_group_list: | |||
| port_group.widget.setOpacity(1) | |||
| for connection in canvas.connection_list: | |||
| if connection.port_out_id in self.m_port_id_list or connection.port_in_id in self.m_port_id_list: | |||
| connection.widget.setLocked(False) | |||
| if self.m_hover_item: | |||
| #if self.m_r_click_conn != self.m_hover_item: | |||
| #if time.time() > self.m_r_click_time + 0.3: | |||
| self.ConnectToHover() | |||
| canvas.scene.clearSelection() | |||
| else: | |||
| if self.m_r_click_conn: | |||
| canvas.scene.clearSelection() | |||
| if self.m_cursor_moving: | |||
| self.setCursor(QCursor(Qt.ArrowCursor)) | |||
| self.m_hover_item = None | |||
| self.m_mouse_down = False | |||
| self.m_cursor_moving = False | |||
| canvas.is_line_mov = False | |||
| QGraphicsItem.mouseReleaseEvent(self, event) | |||
| def contextMenuEvent(self, event): | |||
| if canvas.is_line_mov: | |||
| return event.ignore() | |||
| canvas.scene.clearSelection() | |||
| self.setSelected(True) | |||
| menu = QMenu() | |||
| discMenu = QMenu("Disconnect", menu) | |||
| #get all connected ports and all connected groups | |||
| all_connected_ports_ids = [] | |||
| group_ids_list = [] | |||
| for selfport_id in self.m_port_id_list: | |||
| con_list = CanvasGetPortConnectionList(self.m_group_id, selfport_id) | |||
| for con_id, group_id, port_id in con_list: | |||
| for port in canvas.port_list: | |||
| if port.port_id == port_id: | |||
| if not port.group_id in group_ids_list: | |||
| group_ids_list.append(port.group_id) | |||
| if not port_id in all_connected_ports_ids: | |||
| all_connected_ports_ids.append(port_id) | |||
| #Display 'no connection' action in disconnect menu | |||
| if len(all_connected_ports_ids) == 0: | |||
| action_noconnection = discMenu.addAction('no connection') | |||
| action_noconnection.setEnabled(False) | |||
| #check each group to get no trouble with ports in the same port_group which could have non-consecutive port ids | |||
| for group_id in group_ids_list: | |||
| #get a list of connected port from this group | |||
| gr_port_ids_list = [] | |||
| for port in canvas.port_list: | |||
| if port.group_id == group_id: | |||
| if port.port_id in all_connected_ports_ids: | |||
| if not port.port_id in gr_port_ids_list: | |||
| gr_port_ids_list.append(port.port_id) | |||
| port_group_list_ids = [] | |||
| port_group_dirty_connect_list = [] #is used to display individual ports of port_group or not | |||
| last_is_dirty_port_group = False #is used to display menu separator or not | |||
| #create action for each port of this group connected to the box | |||
| for port in canvas.port_list: | |||
| if port.port_id in gr_port_ids_list: | |||
| #get port connection list | |||
| port_con_list = [] | |||
| for connection in canvas.connection_list: | |||
| if ( (connection.port_out_id in self.m_port_id_list and connection.port_in_id == port.port_id) or | |||
| (connection.port_out_id == port.port_id and connection.port_in_id in self.m_port_id_list) ): | |||
| port_con_list.append(connection.connection_id) | |||
| if port.port_group_id: | |||
| port_alone_connected = False | |||
| if not port.port_group_id in port_group_list_ids: | |||
| port_group_list_ids.append(port.port_group_id) | |||
| for port_group in canvas.port_group_list: | |||
| if port_group.port_group_id == port.port_group_id: | |||
| #count ports from port_group connected to the box | |||
| c = 0 | |||
| for p in port_group.port_id_list: | |||
| if p in all_connected_ports_ids: | |||
| c += 1 | |||
| if c == 1: | |||
| port_alone_connected = True | |||
| #Set disconnect port action if port is the only one of the port_group connected to the box | |||
| if port_alone_connected: | |||
| if last_is_dirty_port_group: | |||
| discMenu.addSeparator() | |||
| last_is_dirty_port_group = False | |||
| full_port_name = CanvasGetFullPortName(port.port_id) | |||
| act_x_disc_port = discMenu.addAction(full_port_name) | |||
| act_x_disc_port.setData(port_con_list) | |||
| act_x_disc_port.triggered.connect(canvas.qobject.PortContextMenuDisconnect) | |||
| else: | |||
| #get port_group connection list | |||
| port_group_con_list = [] | |||
| for connection in canvas.connection_list: | |||
| if (connection.port_out_id in self.m_port_id_list and connection.port_in_id in port_group.port_id_list or | |||
| connection.port_out_id in port_group.port_id_list and connection.port_in_id in self.m_port_id_list): | |||
| port_group_con_list.append(connection.connection_id) | |||
| if connection.port_out_id in self.m_port_id_list: | |||
| if (self.m_port_id_list.index(connection.port_out_id) % len(port_group.port_id_list) != | |||
| port_group.port_id_list.index(connection.port_in_id) % len(self.m_port_id_list) ): | |||
| port_group_dirty_connect_list.append(port_group.port_group_id) | |||
| else: | |||
| if (self.m_port_id_list.index(connection.port_in_id) % len(port_group.port_id_list) != | |||
| port_group.port_id_list.index(connection.port_out_id) % len(self.m_port_id_list) ): | |||
| port_group_dirty_connect_list.append(port_group.port_group_id) | |||
| if port_group.port_group_id in port_group_dirty_connect_list: | |||
| discMenu.addSeparator() | |||
| last_is_dirty_port_group = True | |||
| elif last_is_dirty_port_group: | |||
| discMenu.addSeparator() | |||
| last_is_dirty_port_group = False | |||
| #set port_group action in submenu | |||
| port_group_print_name = CanvasGetPortGroupFullName(port_group.port_group_id) | |||
| act_x_disc_port_group = discMenu.addAction(port_group_print_name) | |||
| act_x_disc_port_group.setData(port_group_con_list) | |||
| act_x_disc_port_group.triggered.connect(canvas.qobject.PortContextMenuDisconnect) | |||
| #set port action in submenu (if port is in a port_group and isn't the only one connected to the box) | |||
| if not port_alone_connected and port.port_group_id in port_group_dirty_connect_list: | |||
| port_print_name = CanvasGetPortPrintName(port.port_id, port.port_group_id) | |||
| act_x_disc_port = discMenu.addAction(' → ' + port_print_name) | |||
| act_x_disc_port.setData(port_con_list) | |||
| act_x_disc_port.triggered.connect(canvas.qobject.PortContextMenuDisconnect) | |||
| else: | |||
| if last_is_dirty_port_group: | |||
| discMenu.addSeparator() | |||
| last_is_dirty_port_group = False | |||
| #set port action in submenu (if port is not in a port_group) | |||
| full_port_name = CanvasGetFullPortName(port.group_id, port.port_id) | |||
| act_x_disc_port = discMenu.addAction(full_port_name) | |||
| act_x_disc_port.setData(port_con_list) | |||
| act_x_disc_port.triggered.connect(canvas.qobject.PortContextMenuDisconnect) | |||
| menu.addMenu(discMenu) | |||
| act_x_disc_alltheport_group = menu.addAction("Disconnect &All") | |||
| act_x_sep_1 = menu.addSeparator() | |||
| act_x_setasmono = menu.addAction('Split to Monos') | |||
| act_selected = menu.exec_(event.screenPos()) | |||
| if act_selected == act_x_disc_alltheport_group: | |||
| for connection in canvas.connection_list: | |||
| if connection.port_out_id in self.m_port_id_list or connection.port_in_id in self.m_port_id_list: | |||
| canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "") | |||
| elif act_selected == act_x_setasmono: | |||
| self.SplitToMonos() | |||
| event.accept() | |||
| def boundingRect(self): | |||
| self.m_port_group_width = self.getPortGroupWidth() | |||
| if self.m_port_mode == PORT_MODE_INPUT: | |||
| return QRectF(canvas.theme.port_in_port_group_width, 0, self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width, canvas.theme.port_height * len(self.m_port_id_list)) | |||
| else: | |||
| return QRectF(0, 0, self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width, canvas.theme.port_height * len(self.m_port_id_list)) | |||
| def paint(self, painter, option, widget): | |||
| painter.save() | |||
| painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL)) | |||
| lineHinting = canvas.theme.port_audio_jack_pen.widthF() / 2 | |||
| poly_locx = [0, 0, 0, 0, 0] | |||
| poly_corner_xhinting = (float(canvas.theme.port_height)/2) % floor(float(canvas.theme.port_height)/2) | |||
| if poly_corner_xhinting == 0: | |||
| poly_corner_xhinting = 0.5 * (1 - 7 / (float(canvas.theme.port_height)/2)) | |||
| if self.m_port_mode == PORT_MODE_INPUT: | |||
| port_width = canvas.theme.port_in_port_group_width | |||
| for port in canvas.port_list: | |||
| if port.port_id in self.m_port_id_list: | |||
| port_print_name = CanvasGetPortPrintName(port.port_id, self.m_port_group_id) | |||
| port_in_p_width = QFontMetrics(self.m_port_group_font).width(port_print_name) + 3 | |||
| port_width = max(port_width, port_in_p_width) | |||
| text_pos = QPointF(port_width + 3, canvas.theme.port_text_ypos + (canvas.theme.port_height * (len(self.m_port_id_list) -1)/2)) | |||
| if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON: | |||
| poly_locx[0] = canvas.theme.port_in_port_group_width - lineHinting | |||
| poly_locx[1] = self.m_port_group_width + 5 + lineHinting | |||
| poly_locx[2] = self.m_port_group_width + 12 + lineHinting | |||
| poly_locx[3] = self.m_port_group_width + 5 + lineHinting | |||
| poly_locx[4] = canvas.theme.port_in_port_group_width - lineHinting | |||
| elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: | |||
| poly_locx[0] = canvas.theme.port_in_port_group_width - lineHinting | |||
| poly_locx[1] = self.m_port_group_width + 5 + lineHinting | |||
| poly_locx[2] = self.m_port_group_width + 5 + lineHinting | |||
| poly_locx[3] = self.m_port_group_width + 5 + lineHinting | |||
| poly_locx[4] = canvas.theme.port_in_port_group_width - lineHinting | |||
| else: | |||
| qCritical("PatchCanvas::CanvasPortGroup.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) | |||
| return | |||
| elif self.m_port_mode == PORT_MODE_OUTPUT: | |||
| text_pos = QPointF(9, canvas.theme.port_text_ypos + (canvas.theme.port_height * (len(self.m_port_id_list) -1)/2)) | |||
| if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON: | |||
| poly_locx[0] = self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width - lineHinting | |||
| poly_locx[1] = 7 + lineHinting | |||
| poly_locx[2] = 0 + lineHinting | |||
| poly_locx[3] = 7 + lineHinting | |||
| poly_locx[4] = self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width - lineHinting | |||
| elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE: | |||
| poly_locx[0] = self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width - lineHinting | |||
| poly_locx[1] = 5 + lineHinting | |||
| poly_locx[2] = 5 + lineHinting | |||
| poly_locx[3] = 5 + lineHinting | |||
| poly_locx[4] = self.m_port_group_width + 12 - canvas.theme.port_in_port_group_width - lineHinting | |||
| else: | |||
| qCritical("PatchCanvas::CanvasPortGroup.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode) | |||
| return | |||
| else: | |||
| qCritical("PatchCanvas::CanvasPortGroup.paint() - invalid port mode '%s'" % port_mode2str(self.m_port_mode)) | |||
| return | |||
| poly_pen = canvas.theme.port_group_audio_jack_pen_sel if self.isSelected() else canvas.theme.port_group_audio_jack_pen | |||
| text_pen = canvas.theme.port_audio_jack_text_sel if self.isSelected() else canvas.theme.port_audio_jack_text | |||
| if self.m_port_mode == PORT_MODE_OUTPUT: | |||
| real_port_group_width = self.m_port_group_width - canvas.theme.port_in_port_group_width | |||
| port_group_gradient = QLinearGradient(real_port_group_width -40, 0, real_port_group_width, 0) | |||
| port_group_gradient.setColorAt(0, canvas.theme.port_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_audio_jack_bg) | |||
| port_group_gradient.setColorAt(1, canvas.theme.port_group_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_group_audio_jack_bg) | |||
| else: | |||
| port_group_gradient = QLinearGradient(canvas.theme.port_in_port_group_width, 0, canvas.theme.port_in_port_group_width + 40, 0) | |||
| port_group_gradient.setColorAt(0, canvas.theme.port_group_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_group_audio_jack_bg) | |||
| port_group_gradient.setColorAt(1, canvas.theme.port_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_audio_jack_bg) | |||
| polygon = QPolygonF() | |||
| polygon += QPointF(poly_locx[0], lineHinting) | |||
| polygon += QPointF(poly_locx[1], lineHinting) | |||
| polygon += QPointF(poly_locx[2], float(canvas.theme.port_height / 2) ) | |||
| polygon += QPointF(poly_locx[2], float(canvas.theme.port_height * (len(self.m_port_id_list) - 1/2)) ) | |||
| polygon += QPointF(poly_locx[3], canvas.theme.port_height * len(self.m_port_id_list) - lineHinting) | |||
| polygon += QPointF(poly_locx[4], canvas.theme.port_height * len(self.m_port_id_list) - lineHinting) | |||
| if canvas.theme.port_bg_pixmap: | |||
| portRect = polygon.boundingRect() | |||
| portPos = portRect.topLeft() | |||
| painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos) | |||
| else: | |||
| painter.setBrush(port_group_gradient) | |||
| painter.setPen(poly_pen) | |||
| painter.drawPolygon(polygon) | |||
| painter.setPen(text_pen) | |||
| painter.setFont(self.m_port_group_font) | |||
| port_group_name = CanvasGetPortGroupName(self.m_port_id_list) | |||
| painter.drawText(text_pos, port_group_name) | |||
| if self.isSelected() != self.m_last_selected_state: | |||
| CanvasUpdateSelectedLines() | |||
| self.m_last_selected_state = self.isSelected() | |||
| painter.restore() | |||
| @@ -31,6 +31,7 @@ from . import ( | |||
| options, | |||
| group_dict_t, | |||
| port_dict_t, | |||
| port_group_dict_t, | |||
| connection_dict_t, | |||
| bool2str, | |||
| icon2str, | |||
| @@ -57,6 +58,7 @@ from .canvasbezierline import CanvasBezierLine | |||
| from .canvasline import CanvasLine | |||
| from .theme import Theme, getDefaultTheme, getThemeName | |||
| from .utils import CanvasCallback, CanvasGetNewGroupPos, CanvasItemFX, CanvasRemoveItemFX | |||
| from .utils import CanvasGetPortGroupPosition | |||
| # FIXME | |||
| from . import * | |||
| @@ -226,6 +228,7 @@ def clear(): | |||
| canvas.group_list = [] | |||
| canvas.port_list = [] | |||
| canvas.port_group_list = [] | |||
| canvas.connection_list = [] | |||
| canvas.group_plugin_map = {} | |||
| @@ -448,6 +451,7 @@ def splitGroup(group_id): | |||
| port_dict.port_name = port.port_name | |||
| port_dict.port_mode = port.port_mode | |||
| port_dict.port_type = port.port_type | |||
| port_dict.port_group_id = port.port_group_id | |||
| port_dict.is_alternate = port.is_alternate | |||
| port_dict.widget = None | |||
| ports_data.append(port_dict) | |||
| @@ -536,6 +540,7 @@ def joinGroup(group_id): | |||
| port_dict.port_name = port.port_name | |||
| port_dict.port_mode = port.port_mode | |||
| port_dict.port_type = port.port_type | |||
| port_dict.port_group_id = port.port_group_id | |||
| port_dict.is_alternate = port.is_alternate | |||
| port_dict.widget = None | |||
| ports_data.append(port_dict) | |||
| @@ -696,7 +701,7 @@ def setGroupAsPlugin(group_id, plugin_id, hasUI, hasInlineDisplay): | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| def addPort(group_id, port_id, port_name, port_mode, port_type, is_alternate=False): | |||
| def addPort(group_id, port_id, port_name, port_mode, port_type, port_group_id, is_alternate=False): | |||
| if canvas.debug: | |||
| print("PatchCanvas::addPort(%i, %i, %s, %s, %s, %s)" % ( | |||
| group_id, port_id, port_name.encode(), | |||
| @@ -718,7 +723,9 @@ def addPort(group_id, port_id, port_name, port_mode, port_type, is_alternate=Fal | |||
| else: | |||
| n = 0 | |||
| box_widget = group.widgets[n] | |||
| port_widget = box_widget.addPortFromGroup(port_id, port_mode, port_type, port_name, is_alternate) | |||
| port_widget = box_widget.addPortFromGroup( | |||
| port_id, port_mode, port_type, | |||
| port_name, port_group_id, is_alternate) | |||
| break | |||
| if not (box_widget and port_widget): | |||
| @@ -732,6 +739,7 @@ def addPort(group_id, port_id, port_name, port_mode, port_type, is_alternate=Fal | |||
| port_dict.port_name = port_name | |||
| port_dict.port_mode = port_mode | |||
| port_dict.port_type = port_type | |||
| port_dict.port_group_id = port_group_id | |||
| port_dict.is_alternate = is_alternate | |||
| port_dict.widget = port_widget | |||
| canvas.port_list.append(port_dict) | |||
| @@ -807,7 +815,7 @@ def connectPorts(connection_id, group_out_id, port_out_id, group_in_id, port_in_ | |||
| 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: | |||
| @@ -83,6 +83,71 @@ def CanvasGetPortConnectionList(group_id, port_id): | |||
| return conn_list | |||
| def CanvasGetPortGroupPosition(group_id, port_id, port_group_id): | |||
| if port_group_id < 0: | |||
| return (0, 1) | |||
| for port_group in canvas.port_group_list: | |||
| if (port_group.group_id == group_id | |||
| and port_group.port_group_id == port_group_id): | |||
| for i in range(len(port_group.port_id_list)): | |||
| if port_id == port_group.port_id_list[i]: | |||
| return (i, len(port_group.port_id_list)) | |||
| return (0, 1) | |||
| def CanvasGetPortGroupName(group_id, ports_ids_list): | |||
| ports_names = [] | |||
| for port in canvas.port_list: | |||
| if port.group_id == group_id and port.port_id in ports_ids_list: | |||
| ports_names.append(port.port_name) | |||
| if len(ports_names) < 2: | |||
| return '' | |||
| port_group_name_ends = ( ' ', '_', '.', '-', '#', ':', 'out', 'in', 'Out', | |||
| 'In', 'Output', 'Input', 'output', 'input' ) | |||
| # set port_group name | |||
| port_group_name = '' | |||
| checkCharacter = True | |||
| for c in ports_names[0]: | |||
| for eachname in ports_names: | |||
| if not eachname.startswith(port_group_name + c): | |||
| checkCharacter = False | |||
| break | |||
| if not checkCharacter: | |||
| break | |||
| port_group_name += c | |||
| # reduce port_group name until it ends with one of the characters | |||
| # in port_group_name_ends | |||
| check = False | |||
| while not check: | |||
| for x in port_group_name_ends: | |||
| if port_group_name.endswith(x): | |||
| check = True | |||
| break | |||
| if len(port_group_name) == 0 or port_group_name in ports_names: | |||
| check = True | |||
| if not check: | |||
| port_group_name = port_group_name[:-1] | |||
| return port_group_name | |||
| def CanvasGetPortPrintName(group_id, port_id, port_group_id): | |||
| for port_group in canvas.port_group_list: | |||
| if (port_group.group_id == group_id | |||
| and port_group.port_group_id == port_group_id): | |||
| port_group_name = CanvasGetPortGroupName(group_id, | |||
| port_group.port_id_list) | |||
| for port in canvas.port_list: | |||
| if port.group_id == group_id and port.port_id == port_id: | |||
| return port.port_name.replace(port_group_name, '', 1) | |||
| def CanvasCallback(action, value1, value2, value_str): | |||
| if canvas.debug: | |||
| print("PatchCanvas::CanvasCallback(%i, %i, %i, %s)" % (action, value1, value2, value_str.encode())) | |||