Browse Source

add canvasportgroup.py, save work

pull/935/head
houston 6 years ago
parent
commit
12c7bd3efa
7 changed files with 1138 additions and 90 deletions
  1. +2
    -2
      source/frontend/carla_host.py
  2. +14
    -0
      source/frontend/patchcanvas/__init__.py
  3. +17
    -12
      source/frontend/patchcanvas/canvasbezierline.py
  4. +335
    -73
      source/frontend/patchcanvas/canvasport.py
  5. +694
    -0
      source/frontend/patchcanvas/canvasportgroup.py
  6. +11
    -3
      source/frontend/patchcanvas/patchcanvas.py
  7. +65
    -0
      source/frontend/patchcanvas/utils.py

+ 2
- 2
source/frontend/carla_host.py View File

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


+ 14
- 0
source/frontend/patchcanvas/__init__.py View File

@@ -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',


+ 17
- 12
source/frontend/patchcanvas/canvasbezierline.py View File

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


+ 335
- 73
source/frontend/patchcanvas/canvasport.py View File

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



+ 694
- 0
source/frontend/patchcanvas/canvasportgroup.py View File

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

+ 11
- 3
source/frontend/patchcanvas/patchcanvas.py View File

@@ -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:


+ 65
- 0
source/frontend/patchcanvas/utils.py View File

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


Loading…
Cancel
Save