| 
							- #!/usr/bin/env python3
 - # -*- coding: utf-8 -*-
 - 
 - # PatchBay Canvas engine using QGraphicsView/Scene
 - # Copyright (C) 2010-2012 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 GPL.txt file
 - 
 - # TODO - apply last changes to c++ (2 commits + theme changes)
 - 
 - # Imports (Global)
 - from PyQt4.QtCore import pyqtSlot, qDebug, qCritical, qFatal, qWarning, Qt, QObject, SIGNAL, SLOT
 - from PyQt4.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer
 - from PyQt4.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath
 - from PyQt4.QtGui import QCursor, QFont, QFontMetrics, QInputDialog, QLineEdit, QMenu
 - from PyQt4.QtGui import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem
 - from PyQt4.QtGui import QGraphicsColorizeEffect, QGraphicsDropShadowEffect
 - from PyQt4.QtSvg import QGraphicsSvgItem, QSvgRenderer
 - 
 - # Imports (Theme)
 - from patchcanvas_theme import *
 - 
 - # ------------------------------------------------------------------------------
 - # patchcanvas-api.h
 - 
 - # Port Mode
 - PORT_MODE_NULL   = 0
 - PORT_MODE_INPUT  = 1
 - PORT_MODE_OUTPUT = 2
 - 
 - # Port Type
 - PORT_TYPE_NULL       = 0
 - PORT_TYPE_AUDIO_JACK = 1
 - PORT_TYPE_MIDI_JACK  = 2
 - PORT_TYPE_MIDI_A2J   = 3
 - PORT_TYPE_MIDI_ALSA  = 4
 - 
 - # Callback Action
 - ACTION_GROUP_INFO       = 0 # group_id, N, N
 - ACTION_GROUP_RENAME     = 1 # group_id, N, new_name
 - ACTION_GROUP_SPLIT      = 2 # group_id, N, N
 - ACTION_GROUP_JOIN       = 3 # group_id, N, N
 - ACTION_PORT_INFO        = 4 # port_id, N, N
 - ACTION_PORT_RENAME      = 5 # port_id, N, new_name
 - ACTION_PORTS_CONNECT    = 6 # out_id, in_id, N
 - ACTION_PORTS_DISCONNECT = 7 # conn_id, N, N
 - 
 - # Icon
 - ICON_APPLICATION = 0
 - ICON_HARDWARE    = 1
 - ICON_DISTRHO     = 2
 - ICON_FILE        = 3
 - ICON_PLUGIN      = 4
 - ICON_LADISH_ROOM = 5
 - 
 - # Split Option
 - SPLIT_UNDEF = 0
 - SPLIT_NO    = 1
 - SPLIT_YES   = 2
 - 
 - # Antialiasing Option
 - ANTIALIASING_NONE  = 0
 - ANTIALIASING_SMALL = 1
 - ANTIALIASING_FULL  = 2
 - 
 - # Eye-Candy Option
 - EYECANDY_NONE  = 0
 - EYECANDY_SMALL = 1
 - EYECANDY_FULL  = 2
 - 
 - # Canvas options
 - class options_t(object):
 -     __slots__ = [
 -         'theme_name',
 -         'auto_hide_groups',
 -         'use_bezier_lines',
 -         'antialiasing',
 -         'eyecandy'
 -     ]
 - 
 - # Canvas features
 - class features_t(object):
 -     __slots__ = [
 -         'group_info',
 -         'group_rename',
 -         'port_info',
 -         'port_rename',
 -         'handle_group_pos'
 -     ]
 - 
 - # ------------------------------------------------------------------------------
 - # patchcanvas.h
 - 
 - # object types
 - CanvasBoxType           = QGraphicsItem.UserType + 1
 - CanvasIconType          = QGraphicsItem.UserType + 2
 - CanvasPortType          = QGraphicsItem.UserType + 3
 - CanvasLineType          = QGraphicsItem.UserType + 4
 - CanvasBezierLineType    = QGraphicsItem.UserType + 5
 - CanvasLineMovType       = QGraphicsItem.UserType + 6
 - CanvasBezierLineMovType = QGraphicsItem.UserType + 7
 - 
 - # object lists
 - class group_dict_t(object):
 -     __slots__ = [
 -         'group_id',
 -         'group_name',
 -         'split',
 -         'icon',
 -         'widgets'
 -     ]
 - 
 - class port_dict_t(object):
 -     __slots__ = [
 -         'group_id',
 -         'port_id',
 -         'port_name',
 -         'port_mode',
 -         'port_type',
 -         'widget'
 -     ]
 - 
 - class connection_dict_t(object):
 -     __slots__ = [
 -         'connection_id',
 -         'port_in_id',
 -         'port_out_id',
 -         'widget'
 -     ]
 - 
 - class animation_dict_t(object):
 -     __slots__ = [
 -         'animation',
 -         'item'
 -     ]
 - 
 - # Main Canvas object
 - class Canvas(object):
 -     __slots__ = [
 -         'scene',
 -         'callback',
 -         'debug',
 -         'last_z_value',
 -         'last_connection_id',
 -         'initial_pos',
 -         'size_rect',
 -         'group_list',
 -         'port_list',
 -         'connection_list',
 -         'animation_list',
 -         'qobject',
 -         'settings',
 -         'theme',
 -         'initiated'
 -     ]
 - 
 - # ------------------------------------------------------------------------------
 - # patchcanvas.cpp
 - 
 - class CanvasObject(QObject):
 -     def __init__(self, parent=None):
 -         QObject.__init__(self, parent)
 - 
 -     @pyqtSlot()
 -     def AnimationIdle(self):
 -         animation = self.sender()
 -         if animation:
 -             CanvasRemoveAnimation(animation)
 - 
 -     @pyqtSlot()
 -     def AnimationHide(self):
 -         animation = self.sender()
 -         if animation:
 -             item = animation.item()
 -             if item:
 -                 item.hide()
 -             CanvasRemoveAnimation(animation)
 - 
 -     @pyqtSlot()
 -     def AnimationDestroy(self):
 -         animation = self.sender()
 -         if animation:
 -             item = animation.item()
 -             if item:
 -                 CanvasRemoveItemFX(item)
 -             CanvasRemoveAnimation(animation)
 - 
 -     @pyqtSlot()
 -     def CanvasPostponedGroups(self):
 -         CanvasPostponedGroups()
 - 
 -     @pyqtSlot()
 -     def PortContextMenuDisconnect(self):
 -         try:
 -             connectionId = int(self.sender().data())
 -         except:
 -             return
 - 
 -         CanvasCallback(ACTION_PORTS_DISCONNECT, connectionId, 0, "")
 - 
 - # Global objects
 - canvas = Canvas()
 - canvas.qobject    = None
 - canvas.settings   = None
 - canvas.theme      = None
 - canvas.initiated  = False
 - canvas.group_list = []
 - canvas.port_list  = []
 - canvas.connection_list = []
 - canvas.animation_list  = []
 - 
 - options = options_t()
 - options.theme_name = getDefaultThemeName()
 - options.auto_hide_groups = False
 - options.use_bezier_lines = True
 - options.antialiasing = ANTIALIASING_SMALL
 - options.eyecandy     = EYECANDY_SMALL
 - 
 - features = features_t()
 - features.group_info   = False
 - features.group_rename = False
 - features.port_info    = False
 - features.port_rename  = False
 - features.handle_group_pos = False
 - 
 - # Internal functions
 - def bool2str(check):
 -     return "True" if check else "False"
 - 
 - def port_mode2str(port_mode):
 -     if port_mode == PORT_MODE_NULL:
 -         return "PORT_MODE_NULL"
 -     elif port_mode == PORT_MODE_INPUT:
 -         return "PORT_MODE_INPUT"
 -     elif port_mode == PORT_MODE_OUTPUT:
 -         return "PORT_MODE_OUTPUT"
 -     else:
 -         return "PORT_MODE_???"
 - 
 - def port_type2str(port_type):
 -     if port_type == PORT_TYPE_NULL:
 -         return "PORT_TYPE_NULL"
 -     elif port_type == PORT_TYPE_AUDIO_JACK:
 -         return "PORT_TYPE_AUDIO_JACK"
 -     elif port_type == PORT_TYPE_MIDI_JACK:
 -         return "PORT_TYPE_MIDI_JACK"
 -     elif port_type == PORT_TYPE_MIDI_A2J:
 -         return "PORT_TYPE_MIDI_A2J"
 -     elif port_type == PORT_TYPE_MIDI_ALSA:
 -         return "PORT_TYPE_MIDI_ALSA"
 -     else:
 -         return "PORT_TYPE_???"
 - 
 - def icon2str(icon):
 -     if icon == ICON_HARDWARE:
 -         return "ICON_HARDWARE"
 -     elif ICON_APPLICATION:
 -         return "ICON_APPLICATION"
 -     elif ICON_LADISH_ROOM:
 -         return "ICON_LADISH_ROOM"
 -     else:
 -         return "ICON_???"
 - 
 - def split2str(split):
 -     if split == SPLIT_UNDEF:
 -         return "SPLIT_UNDEF"
 -     elif split == SPLIT_NO:
 -         return "SPLIT_NO"
 -     elif split == SPLIT_YES:
 -         return "SPLIT_YES"
 -     else:
 -         return "SPLIT_???"
 - 
 - # PatchCanvas API
 - def setOptions(new_options):
 -     if canvas.initiated: return
 -     options.theme_name       = new_options.theme_name
 -     options.auto_hide_groups = new_options.auto_hide_groups
 -     options.use_bezier_lines = new_options.use_bezier_lines
 -     options.antialiasing = new_options.antialiasing
 -     options.eyecandy     = new_options.eyecandy
 - 
 - def setFeatures(new_features):
 -     if canvas.initiated: return
 -     features.group_info   = new_features.group_info
 -     features.group_rename = new_features.group_rename
 -     features.port_info    = new_features.port_info
 -     features.port_rename  = new_features.port_rename
 -     features.handle_group_pos = new_features.handle_group_pos
 - 
 - def init(appName, scene, callback, debug=False):
 -     if debug:
 -         qDebug("PatchCanvas::init(\"%s\", %s, %s, %s)" % (appName, scene, callback, bool2str(debug)))
 - 
 -     if canvas.initiated:
 -         qCritical("PatchCanvas::init() - already initiated")
 -         return
 - 
 -     if not callback:
 -         qFatal("PatchCanvas::init() - fatal error: callback not set")
 -         return
 - 
 -     canvas.scene    = scene
 -     canvas.callback = callback
 -     canvas.debug    = debug
 - 
 -     canvas.last_z_value = 0
 -     canvas.last_connection_id = 0
 -     canvas.initial_pos = QPointF(0, 0)
 -     canvas.size_rect = QRectF()
 - 
 -     if not canvas.qobject:  canvas.qobject = CanvasObject()
 -     if not canvas.settings: canvas.settings = QSettings("Cadence", appName)
 - 
 -     if canvas.theme:
 -         del canvas.theme
 -         canvas.theme = None
 - 
 -     for i in range(Theme.THEME_MAX):
 -         this_theme_name = getThemeName(i)
 -         if this_theme_name == options.theme_name:
 -             canvas.theme = Theme(i)
 -             break
 - 
 -     if not canvas.theme:
 -         canvas.theme = Theme(getDefaultTheme())
 - 
 -     canvas.scene.updateTheme()
 - 
 -     canvas.initiated = True
 - 
 - def clear():
 -     if canvas.debug:
 -         qDebug("PatchCanvas::clear()")
 - 
 -     group_list_ids = []
 -     port_list_ids  = []
 -     connection_list_ids = []
 - 
 -     for group in canvas.group_list:
 -         group_list_ids.append(group.group_id)
 - 
 -     for port in canvas.port_list:
 -         port_list_ids.append(port.port_id)
 - 
 -     for connection in canvas.connection_list:
 -         connection_list_ids.append(connection.connection_id)
 - 
 -     for idx in connection_list_ids:
 -         disconnectPorts(idx)
 - 
 -     for idx in port_list_ids:
 -         removePort(idx)
 - 
 -     for idx in group_list_ids:
 -         removeGroup(idx)
 - 
 -     canvas.last_z_value = 0
 -     canvas.last_connection_id = 0
 - 
 -     canvas.group_list = []
 -     canvas.port_list = []
 -     canvas.connection_list = []
 - 
 -     canvas.scene.clear()
 - 
 -     canvas.initiated = False
 - 
 - def setInitialPos(x, y):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::setInitialPos(%i, %i)" % (x, y))
 - 
 -     canvas.initial_pos.setX(x)
 -     canvas.initial_pos.setY(y)
 - 
 - def setCanvasSize(x, y, width, height):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::setCanvasSize(%i, %i, %i, %i)" % (x, y, width, height))
 - 
 -     canvas.size_rect.setX(x)
 -     canvas.size_rect.setY(y)
 -     canvas.size_rect.setWidth(width)
 -     canvas.size_rect.setHeight(height)
 - 
 - def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::addGroup(%i, %s, %s, %s)" % (group_id, group_name.encode(), split2str(split), icon2str(icon)))
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists" % (group_id, group_name.encode(), split2str(split), icon2str(icon)))
 -             return
 - 
 -     if split == SPLIT_UNDEF and features.handle_group_pos:
 -         split = canvas.settings.value("CanvasPositions/%s_SPLIT" % group_name, split, type=int)
 - 
 -     group_box = CanvasBox(group_id, group_name, icon)
 - 
 -     group_dict = group_dict_t()
 -     group_dict.group_id = group_id
 -     group_dict.group_name = group_name
 -     group_dict.split = bool(split == SPLIT_YES)
 -     group_dict.icon = icon
 -     group_dict.widgets = [group_box, None]
 - 
 -     if split == SPLIT_YES:
 -         group_box.setSplit(True, PORT_MODE_OUTPUT)
 - 
 -         if features.handle_group_pos:
 -             group_box.setPos(canvas.settings.value("CanvasPositions/%s_OUTPUT" % group_name, CanvasGetNewGroupPos(), type=QPointF))
 -         else:
 -             group_box.setPos(CanvasGetNewGroupPos())
 - 
 -         group_sbox = CanvasBox(group_id, group_name, icon)
 -         group_sbox.setSplit(True, PORT_MODE_INPUT)
 - 
 -         group_dict.widgets[1] = group_sbox
 - 
 -         if features.handle_group_pos:
 -             group_sbox.setPos(canvas.settings.value("CanvasPositions/%s_INPUT" % group_name, CanvasGetNewGroupPos(True), type=QPointF))
 -         else:
 -             group_sbox.setPos(CanvasGetNewGroupPos(True))
 - 
 -         canvas.last_z_value += 1
 -         group_sbox.setZValue(canvas.last_z_value)
 - 
 -         if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups:
 -             CanvasItemFX(group_sbox, True)
 - 
 -     else:
 -         group_box.setSplit(False)
 - 
 -         if features.handle_group_pos:
 -             group_box.setPos(canvas.settings.value("CanvasPositions/%s" % group_name, CanvasGetNewGroupPos(), type=QPointF))
 -         else:
 -             # Special ladish fake-split groups
 -             horizontal = bool(icon == ICON_HARDWARE or icon == ICON_LADISH_ROOM)
 -             group_box.setPos(CanvasGetNewGroupPos(horizontal))
 - 
 -     group_box.checkItemPos()
 - 
 -     canvas.last_z_value += 1
 -     group_box.setZValue(canvas.last_z_value)
 - 
 -     canvas.group_list.append(group_dict)
 - 
 -     if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups:
 -         CanvasItemFX(group_box, True)
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def removeGroup(group_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::removeGroup(%i)" % group_id)
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             item = group.widgets[0]
 -             group_name = group.group_name
 - 
 -             if group.split:
 -                 s_item = group.widgets[1]
 - 
 -                 if features.handle_group_pos:
 -                     canvas.settings.setValue("CanvasPositions/%s_OUTPUT" % group_name, item.pos())
 -                     canvas.settings.setValue("CanvasPositions/%s_INPUT" % group_name, s_item.pos())
 -                     canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_YES)
 - 
 -                 if options.eyecandy == EYECANDY_FULL:
 -                     CanvasItemFX(s_item, False, True)
 -                 else:
 -                     s_item.removeIconFromScene()
 -                     canvas.scene.removeItem(s_item)
 -                     del s_item
 - 
 -             else:
 -                 if features.handle_group_pos:
 -                     canvas.settings.setValue("CanvasPositions/%s" % group_name, item.pos())
 -                     canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_NO)
 - 
 -             if options.eyecandy == EYECANDY_FULL:
 -                 CanvasItemFX(item, False, True)
 -             else:
 -                 item.removeIconFromScene()
 -                 canvas.scene.removeItem(item)
 -                 del item
 - 
 -             canvas.group_list.remove(group)
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::removeGroup(%i) - unable to find group to remove" % group_id)
 - 
 - def renameGroup(group_id, new_group_name):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::renameGroup(%i, %s)" % (group_id, new_group_name.encode()))
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             group.group_name = new_group_name
 -             group.widgets[0].setGroupName(new_group_name)
 - 
 -             if group.split and group.widgets[1]:
 -                 group.widgets[1].setGroupName(new_group_name)
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::renameGroup(%i, %s) - unable to find group to rename" % (group_id, new_group_name.encode()))
 - 
 - def splitGroup(group_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::splitGroup(%i)" % group_id)
 - 
 -     item = None
 -     group_name = ""
 -     group_icon = ICON_APPLICATION
 -     ports_data = []
 -     conns_data = []
 - 
 -     # Step 1 - Store all Item data
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             if group.split:
 -                 qCritical("PatchCanvas::splitGroup(%i) - group is already splitted" % group_id)
 -                 return
 - 
 -             item = group.widgets[0]
 -             group_name = group.group_name
 -             group_icon = group.icon
 -             break
 - 
 -     if not item:
 -         qCritical("PatchCanvas::splitGroup(%i) - unable to find group to split" % group_id)
 -         return
 - 
 -     port_list_ids = list(item.getPortList())
 - 
 -     for port in canvas.port_list:
 -         if port.port_id in port_list_ids:
 -             port_dict = port_dict_t()
 -             port_dict.group_id = port.group_id
 -             port_dict.port_id = port.port_id
 -             port_dict.port_name = port.port_name
 -             port_dict.port_mode = port.port_mode
 -             port_dict.port_type = port.port_type
 -             port_dict.widget = None
 -             ports_data.append(port_dict)
 - 
 -     for connection in canvas.connection_list:
 -         if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids:
 -             connection_dict = connection_dict_t()
 -             connection_dict.connection_id = connection.connection_id
 -             connection_dict.port_in_id = connection.port_in_id
 -             connection_dict.port_out_id = connection.port_out_id
 -             connection_dict.widget = None
 -             conns_data.append(connection_dict)
 - 
 -     # Step 2 - Remove Item and Children
 -     for conn in conns_data:
 -         disconnectPorts(conn.connection_id)
 - 
 -     for port_id in port_list_ids:
 -         removePort(port_id)
 - 
 -     removeGroup(group_id)
 - 
 -     # Step 3 - Re-create Item, now splitted
 -     addGroup(group_id, group_name, SPLIT_YES, group_icon)
 - 
 -     for port in ports_data:
 -         addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type)
 - 
 -     for conn in conns_data:
 -         connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id)
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def joinGroup(group_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::joinGroup(%i)" % group_id)
 - 
 -     item   = None
 -     s_item = None
 -     group_name = ""
 -     group_icon = ICON_APPLICATION
 -     ports_data = []
 -     conns_data = []
 - 
 -     # Step 1 - Store all Item data
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             if not group.split:
 -                 qCritical("PatchCanvas::joinGroup(%i) - group is not splitted" % group_id)
 -                 return
 - 
 -             item = group.widgets[0]
 -             s_item = group.widgets[1]
 -             group_name = group.group_name
 -             group_icon = group.icon
 -             break
 - 
 -     # FIXME
 -     if not (item and s_item):
 -         qCritical("PatchCanvas::joinGroup(%i) - unable to find groups to join" % group_id)
 -         return
 - 
 -     port_list_ids = list(item.getPortList())
 -     port_list_idss = s_item.getPortList()
 - 
 -     for port_id in port_list_idss:
 -         if port_id not in port_list_ids:
 -             port_list_ids.append(port_id)
 - 
 -     for port in canvas.port_list:
 -         if port.port_id in port_list_ids:
 -             port_dict = port_dict_t()
 -             port_dict.group_id = port.group_id
 -             port_dict.port_id = port.port_id
 -             port_dict.port_name = port.port_name
 -             port_dict.port_mode = port.port_mode
 -             port_dict.port_type = port.port_type
 -             port_dict.widget = None
 -             ports_data.append(port_dict)
 - 
 -     for connection in canvas.connection_list:
 -         if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids:
 -             connection_dict = connection_dict_t()
 -             connection_dict.connection_id = connection.connection_id
 -             connection_dict.port_in_id = connection.port_in_id
 -             connection_dict.port_out_id = connection.port_out_id
 -             connection_dict.widget = None
 -             conns_data.append(connection_dict)
 - 
 -     # Step 2 - Remove Item and Children
 -     for conn in conns_data:
 -         disconnectPorts(conn.connection_id)
 - 
 -     for port_id in port_list_ids:
 -         removePort(port_id)
 - 
 -     removeGroup(group_id)
 - 
 -     # Step 3 - Re-create Item, now together
 -     addGroup(group_id, group_name, SPLIT_NO, group_icon)
 - 
 -     for port in ports_data:
 -         addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type)
 - 
 -     for conn in conns_data:
 -         connectPorts(conn.connection_id, conn.port_out_id, conn.port_in_id)
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def getGroupPos(group_id, port_mode=PORT_MODE_OUTPUT):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::getGroupPos(%i, %s)" % (group_id, port_mode2str(port_mode)))
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             if group.split:
 -                 if port_mode == PORT_MODE_OUTPUT:
 -                     return group.widgets[0].pos()
 -                 elif port_mode == PORT_MODE_INPUT:
 -                     return group.widgets[1].pos()
 -                 else:
 -                     return QPointF(0, 0)
 -             else:
 -                 return group.widgets[0].pos()
 - 
 -     qCritical("PatchCanvas::getGroupPos(%i, %s) - unable to find group" % (group_id, port_mode2str(port_mode)))
 -     return QPointF(0, 0)
 - 
 - def setGroupPos(group_id, group_pos_x, group_pos_y):
 -     setGroupPosFull(group_id, group_pos_x, group_pos_y, group_pos_x, group_pos_y)
 - 
 - def setGroupPosFull(group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i)" % (group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i))
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             group.widgets[0].setPos(group_pos_x_o, group_pos_y_o)
 - 
 -             if group.split and group.widgets[1]:
 -                 group.widgets[1].setPos(group_pos_x_i, group_pos_y_i)
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i) - unable to find group to reposition" % (group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i))
 - 
 - def setGroupIcon(group_id, icon):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::setGroupIcon(%i, %s)" % (group_id, icon2str(icon)))
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             group.icon = icon
 -             group.widgets[0].setIcon(icon)
 - 
 -             if group.split and group.widgets[1]:
 -                 group.widgets[1].setIcon(icon)
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon" % (group_id, icon2str(icon)))
 - 
 - def addPort(group_id, port_id, port_name, port_mode, port_type):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::addPort(%i, %i, %s, %s, %s)" % (group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type)))
 - 
 -     for port in canvas.port_list:
 -         if port.group_id == group_id and port.port_id == port_id:
 -             qWarning("PatchCanvas::addPort(%i, %i, %s, %s, %s) - port already exists" % (group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type)))
 -             return
 - 
 -     box_widget  = None
 -     port_widget = None
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             if group.split and group.widgets[0].getSplittedMode() != port_mode and group.widgets[1]:
 -                 n = 1
 -             else:
 -                 n = 0
 -             box_widget  = group.widgets[n]
 -             port_widget = box_widget.addPortFromGroup(port_id, port_mode, port_type, port_name)
 -             break
 - 
 -     if not (box_widget and port_widget):
 -         qCritical("PatchCanvas::addPort(%i, %i, %s, %s, %s) - Unable to find parent group" % (group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type)))
 -         return
 - 
 -     if options.eyecandy == EYECANDY_FULL:
 -         CanvasItemFX(port_widget, True)
 - 
 -     port_dict = port_dict_t()
 -     port_dict.group_id  = group_id
 -     port_dict.port_id   = port_id
 -     port_dict.port_name = port_name
 -     port_dict.port_mode = port_mode
 -     port_dict.port_type = port_type
 -     port_dict.widget = port_widget
 -     canvas.port_list.append(port_dict)
 - 
 -     box_widget.updatePositions()
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def removePort(port_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::removePort(%i)" % port_id)
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_id:
 -             item = port.widget
 -             item.parentItem().removePortFromGroup(port_id)
 -             canvas.scene.removeItem(item)
 -             del item
 - 
 -             canvas.port_list.remove(port)
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::removePort(%i) - Unable to find port to remove" % port_id)
 - 
 - def renamePort(port_id, new_port_name):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::renamePort(%i, %s)" % (port_id, new_port_name.encode()))
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_id:
 -             port.port_name = new_port_name
 -             port.widget.setPortName(new_port_name)
 -             port.widget.parentItem().updatePositions()
 - 
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 -             return
 - 
 -     qCritical("PatchCanvas::renamePort(%i, %s) - Unable to find port to rename" % (port_id, new_port_name.encode()))
 - 
 - def connectPorts(connection_id, port_out_id, port_in_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::connectPorts(%i, %i, %i)" % (connection_id, port_out_id, port_in_id))
 - 
 -     port_out = None
 -     port_in  = None
 -     port_out_parent = None
 -     port_in_parent  = None
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_out_id:
 -             port_out = port.widget
 -             port_out_parent = port_out.parentItem()
 -         elif port.port_id == port_in_id:
 -             port_in = port.widget
 -             port_in_parent = port_in.parentItem()
 - 
 -     # FIXME
 -     if not (port_out and port_in):
 -         qCritical("PatchCanvas::connectPorts(%i, %i, %i) - unable to find ports to connect" % (connection_id, port_out_id, port_in_id))
 -         return
 - 
 -     connection_dict = connection_dict_t()
 -     connection_dict.connection_id = connection_id
 -     connection_dict.port_out_id = port_out_id
 -     connection_dict.port_in_id = port_in_id
 - 
 -     if options.use_bezier_lines:
 -         connection_dict.widget = CanvasBezierLine(port_out, port_in, None)
 -     else:
 -         connection_dict.widget = CanvasLine(port_out, port_in, None)
 - 
 -     port_out_parent.addLineFromGroup(connection_dict.widget, connection_id)
 -     port_in_parent.addLineFromGroup(connection_dict.widget, connection_id)
 - 
 -     canvas.last_z_value += 1
 -     port_out_parent.setZValue(canvas.last_z_value)
 -     port_in_parent.setZValue(canvas.last_z_value)
 - 
 -     canvas.last_z_value += 1
 -     connection_dict.widget.setZValue(canvas.last_z_value)
 - 
 -     canvas.connection_list.append(connection_dict)
 - 
 -     if options.eyecandy == EYECANDY_FULL:
 -         item = connection_dict.widget
 -         CanvasItemFX(item, True)
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def disconnectPorts(connection_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::disconnectPorts(%i)" % connection_id)
 - 
 -     port_1_id = port_2_id = 0
 -     line = None
 -     item1 = None
 -     item2 = None
 - 
 -     for connection in canvas.connection_list:
 -         if connection.connection_id == connection_id:
 -             port_1_id = connection.port_out_id
 -             port_2_id = connection.port_in_id
 -             line = connection.widget
 -             canvas.connection_list.remove(connection)
 -             break
 - 
 -     if not line:
 -         qCritical("PatchCanvas::disconnectPorts(%i) - unable to find connection ports" % connection_id)
 -         return
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_1_id:
 -             item1 = port.widget
 -             break
 - 
 -     if not item1:
 -         qCritical("PatchCanvas::disconnectPorts(%i) - unable to find output port" % connection_id)
 -         return
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_2_id:
 -             item2 = port.widget
 -             break
 - 
 -     if not item2:
 -         qCritical("PatchCanvas::disconnectPorts(%i) - unable to find input port" % connection_id)
 -         return
 - 
 -     item1.parentItem().removeLineFromGroup(connection_id)
 -     item2.parentItem().removeLineFromGroup(connection_id)
 - 
 -     if options.eyecandy == EYECANDY_FULL:
 -         CanvasItemFX(line, False, True)
 -     else:
 -         line.deleteFromScene()
 - 
 -     QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 - def arrange():
 -     if canvas.debug:
 -         qDebug("PatchCanvas::arrange()")
 - 
 - def updateZValues():
 -     if canvas.debug:
 -         qDebug("PatchCanvas::updateZValues()")
 - 
 -     for group in canvas.group_list:
 -         group.widgets[0].resetLinesZValue()
 - 
 -         if group.split and group.widgets[1]:
 -             group.widgets[1].resetLinesZValue()
 - 
 - # Extra Internal functions
 - 
 - def CanvasGetGroupName(group_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetGroupName(%i)" % group_id)
 - 
 -     for group in canvas.group_list:
 -         if group.group_id == group_id:
 -             return group.group_name
 - 
 -     qCritical("PatchCanvas::CanvasGetGroupName(%i) - unable to find group" % group_id)
 -     return ""
 - 
 - def CanvasGetGroupPortCount(group_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetGroupPortCount(%i)" % group_id)
 - 
 -     port_count = 0
 -     for port in canvas.port_list:
 -         if port.group_id == group_id:
 -             port_count += 1
 - 
 -     return port_count
 - 
 - def CanvasGetNewGroupPos(horizontal=False):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetNewGroupPos(%s)" % bool2str(horizontal))
 - 
 -     new_pos = QPointF(canvas.initial_pos.x(), canvas.initial_pos.y())
 -     items = canvas.scene.items()
 - 
 -     break_loop = False
 -     while not break_loop:
 -         break_for = False
 -         for i in range(len(items)):
 -             item = items[i]
 -             if item and item.type() == CanvasBoxType:
 -                 if item.sceneBoundingRect().contains(new_pos):
 -                     if horizontal:
 -                         new_pos += QPointF(item.boundingRect().width() + 15, 0)
 -                     else:
 -                         new_pos += QPointF(0, item.boundingRect().height() + 15)
 -                     break_for = True
 -                     break
 - 
 -             if i >= len(items) - 1 and not break_for:
 -                 break_loop = True
 - 
 -     return new_pos
 - 
 - def CanvasGetFullPortName(port_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetFullPortName(%i)" % port_id)
 - 
 -     for port in canvas.port_list:
 -         if port.port_id == port_id:
 -             group_id = port.group_id
 -             for group in canvas.group_list:
 -                 if group.group_id == group_id:
 -                     return group.group_name + ":" + port.port_name
 -             break
 - 
 -     qCritical("PatchCanvas::CanvasGetFullPortName(%i) - unable to find port" % port_id)
 -     return ""
 - 
 - def CanvasGetPortConnectionList(port_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetPortConnectionList(%i)" % port_id)
 - 
 -     port_con_list = []
 - 
 -     for connection in canvas.connection_list:
 -         if connection.port_out_id == port_id or connection.port_in_id == port_id:
 -             port_con_list.append(connection.connection_id)
 - 
 -     return port_con_list
 - 
 - def CanvasGetConnectedPort(connection_id, port_id):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasGetConnectedPort(%i, %i)" % (connection_id, port_id))
 - 
 -     for connection in canvas.connection_list:
 -         if connection.connection_id == connection_id:
 -             if connection.port_out_id == port_id:
 -                 return connection.port_in_id
 -             else:
 -                 return connection.port_out_id
 - 
 -     qCritical("PatchCanvas::CanvasGetConnectedPort(%i, %i) - unable to find connection" % (connection_id, port_id))
 -     return 0
 - 
 - def CanvasRemoveAnimation(f_animation):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasRemoveAnimation(%s)" % f_animation)
 - 
 -     for animation in canvas.animation_list:
 -         if animation.animation == f_animation:
 -             canvas.animation_list.remove(animation)
 -             del animation.animation
 -             break
 - 
 - def CanvasPostponedGroups():
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasPostponedGroups()")
 - 
 - def CanvasCallback(action, value1, value2, value_str):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasCallback(%i, %i, %i, %s)" % (action, value1, value2, value_str.encode()))
 - 
 -     canvas.callback(action, value1, value2, value_str)
 - 
 - def CanvasItemFX(item, show, destroy=False):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasItemFX(%s, %s, %s)" % (item, bool2str(show), bool2str(destroy)))
 - 
 -     # Check if item already has an animationItemFX
 -     for animation in canvas.animation_list:
 -         if animation.item == item:
 -             animation.animation.stop()
 -             canvas.animation_list.remove(animation)
 -             del animation.animation
 -             break
 - 
 -     animation = CanvasFadeAnimation(item, show)
 -     animation.setDuration(750 if show else 500)
 - 
 -     animation_dict = animation_dict_t()
 -     animation_dict.animation = animation
 -     animation_dict.item = item
 -     canvas.animation_list.append(animation_dict)
 - 
 -     if show:
 -         canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationIdle()"))
 -     else:
 -         if destroy:
 -             canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationDestroy()"))
 -         else:
 -             canvas.qobject.connect(animation, SIGNAL("finished()"), SLOT("AnimationHide()"))
 - 
 -     animation.start()
 - 
 - def CanvasRemoveItemFX(item):
 -     if canvas.debug:
 -         qDebug("PatchCanvas::CanvasRemoveItemFX(%s)" % item)
 - 
 -     if item.type() == CanvasBoxType:
 -         item.removeIconFromScene()
 -         canvas.scene.removeItem(item)
 - 
 -     elif item.type() == CanvasPortType:
 -         canvas.scene.removeItem(item)
 - 
 -     elif item.type() in (CanvasLineType, CanvasBezierLineType):
 -         pass #item.deleteFromScene()
 - 
 -     # Force deletion of item if needed
 -     if item.type() in (CanvasBoxType, CanvasPortType):
 -         del item
 - 
 - # ------------------------------------------------------------------------------
 - # patchscene.cpp
 - 
 - class PatchScene(QGraphicsScene):
 -     def __init__(self, parent, view):
 -         QGraphicsScene.__init__(self, parent)
 - 
 -         self.m_ctrl_down = False
 -         self.m_mouse_down_init = False
 -         self.m_mouse_rubberband = False
 - 
 -         self.addRubberBand()
 - 
 -         self.m_view = view
 -         if not self.m_view:
 -             qFatal("PatchCanvas::PatchScene() - invalid view")
 - 
 -     def addRubberBand(self):
 -         self.m_rubberband = self.addRect(QRectF(0, 0, 0, 0))
 -         self.m_rubberband.setZValue(-1)
 -         self.m_rubberband.hide()
 -         self.m_rubberband_selection = False
 -         self.m_rubberband_orig_point = QPointF(0, 0)
 - 
 -     def clear(self):
 -         QGraphicsScene.clear(self)
 - 
 -         # Re-add rubberband, that just got deleted
 -         self.addRubberBand()
 - 
 -     def fixScaleFactor(self):
 -         scale = self.m_view.transform().m11()
 -         if scale > 3.0:
 -             self.m_view.resetTransform()
 -             self.m_view.scale(3.0, 3.0)
 -         elif scale < 0.2:
 -             self.m_view.resetTransform()
 -             self.m_view.scale(0.2, 0.2)
 -         self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11())
 - 
 -     def updateTheme(self):
 -         self.setBackgroundBrush(canvas.theme.canvas_bg)
 -         self.m_rubberband.setPen(canvas.theme.rubberband_pen)
 -         self.m_rubberband.setBrush(canvas.theme.rubberband_brush)
 - 
 -     def zoom_fit(self):
 -         min_x = min_y = max_x = max_y = None
 -         first_value = True
 - 
 -         items_list = self.items()
 - 
 -         if len(items_list) > 0:
 -             for item in items_list:
 -                 if item and item.isVisible() and item.type() == CanvasBoxType:
 -                     pos = item.scenePos()
 -                     rect = item.boundingRect()
 - 
 -                     if first_value:
 -                         min_x = pos.x()
 -                     elif pos.x() < min_x:
 -                         min_x = pos.x()
 - 
 -                     if first_value:
 -                         min_y = pos.y()
 -                     elif pos.y() < min_y:
 -                         min_y = pos.y()
 - 
 -                     if first_value:
 -                         max_x = pos.x() + rect.width()
 -                     elif pos.x() + rect.width() > max_x:
 -                         max_x = pos.x() + rect.width()
 - 
 -                     if first_value:
 -                         max_y = pos.y() + rect.height()
 -                     elif pos.y() + rect.height() > max_y:
 -                         max_y = pos.y() + rect.height()
 - 
 -                     first_value = False
 - 
 -             if not first_value:
 -                 self.m_view.fitInView(min_x, min_y, abs(max_x - min_x), abs(max_y - min_y), Qt.KeepAspectRatio)
 -                 self.fixScaleFactor()
 - 
 -     def zoom_in(self):
 -         if self.m_view.transform().m11() < 3.0:
 -             self.m_view.scale(1.2, 1.2)
 -         self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11())
 - 
 -     def zoom_out(self):
 -         if self.m_view.transform().m11() > 0.2:
 -             self.m_view.scale(0.8, 0.8)
 -         self.emit(SIGNAL("scaleChanged(double)"), self.m_view.transform().m11())
 - 
 -     def zoom_reset(self):
 -         self.m_view.resetTransform()
 -         self.emit(SIGNAL("scaleChanged(double)"), 1.0)
 - 
 -     def keyPressEvent(self, event):
 -         if not self.m_view:
 -             return event.ignore()
 - 
 -         if event.key() == Qt.Key_Control:
 -             self.m_ctrl_down = True
 - 
 -         elif event.key() == Qt.Key_Home:
 -             self.zoom_fit()
 -             return event.accept()
 - 
 -         elif self.m_ctrl_down:
 -             if event.key() == Qt.Key_Plus:
 -                 self.zoom_in()
 -                 return event.accept()
 -             elif event.key() == Qt.Key_Minus:
 -                 self.zoom_out()
 -                 return event.accept()
 -             elif event.key() == Qt.Key_1:
 -                 self.zoom_reset()
 -                 return event.accept()
 - 
 -         QGraphicsScene.keyPressEvent(self, event)
 - 
 -     def keyReleaseEvent(self, event):
 -         if event.key() == Qt.Key_Control:
 -             self.m_ctrl_down = False
 -         QGraphicsScene.keyReleaseEvent(self, event)
 - 
 -     def mousePressEvent(self, event):
 -         self.m_mouse_down_init  = bool(event.button() == Qt.LeftButton)
 -         self.m_mouse_rubberband = False
 -         QGraphicsScene.mousePressEvent(self, event)
 - 
 -     def mouseMoveEvent(self, event):
 -         if self.m_mouse_down_init:
 -             self.m_mouse_down_init  = False
 -             self.m_mouse_rubberband = bool(len(self.selectedItems()) == 0)
 - 
 -         if self.m_mouse_rubberband:
 -             if not self.m_rubberband_selection:
 -                 self.m_rubberband.show()
 -                 self.m_rubberband_selection = True
 -                 self.m_rubberband_orig_point = event.scenePos()
 - 
 -             pos = event.scenePos()
 - 
 -             if pos.x() > self.m_rubberband_orig_point.x():
 -                 x = self.m_rubberband_orig_point.x()
 -             else:
 -                 x = pos.x()
 - 
 -             if pos.y() > self.m_rubberband_orig_point.y():
 -                 y = self.m_rubberband_orig_point.y()
 -             else:
 -                 y = pos.y()
 - 
 -             self.m_rubberband.setRect(x, y, abs(pos.x() - self.m_rubberband_orig_point.x()), abs(pos.y() - self.m_rubberband_orig_point.y()))
 -             return event.accept()
 - 
 -         QGraphicsScene.mouseMoveEvent(self, event)
 - 
 -     def mouseReleaseEvent(self, event):
 -         if self.m_rubberband_selection:
 -             items_list = self.items()
 -             if len(items_list) > 0:
 -                 for item in items_list:
 -                     if item and item.isVisible() and item.type() == CanvasBoxType:
 -                         item_rect = item.sceneBoundingRect()
 -                         item_top_left = QPointF(item_rect.x(), item_rect.y())
 -                         item_bottom_right = QPointF(item_rect.x() + item_rect.width(), item_rect.y() + item_rect.height())
 - 
 -                         if self.m_rubberband.contains(item_top_left) and self.m_rubberband.contains(item_bottom_right):
 -                             item.setSelected(True)
 - 
 -                 self.m_rubberband.hide()
 -                 self.m_rubberband.setRect(0, 0, 0, 0)
 -                 self.m_rubberband_selection = False
 - 
 -         else:
 -             items_list = self.selectedItems()
 -             for item in items_list:
 -                 if item and item.isVisible() and item.type() == CanvasBoxType:
 -                     item.checkItemPos()
 -                     self.emit(SIGNAL("sceneGroupMoved(int, int, QPointF)"), item.getGroupId(), item.getSplittedMode(), item.scenePos())
 - 
 -             if len(items_list) > 1:
 -                 canvas.scene.update()
 - 
 -         self.m_mouse_down_init  = False
 -         self.m_mouse_rubberband = False
 -         QGraphicsScene.mouseReleaseEvent(self, event)
 - 
 -     def wheelEvent(self, event):
 -         if not self.m_view:
 -             return event.ignore()
 - 
 -         if self.m_ctrl_down:
 -             factor = 1.41 ** (event.delta() / 240.0)
 -             self.m_view.scale(factor, factor)
 - 
 -             self.fixScaleFactor()
 -             return event.accept()
 - 
 -         QGraphicsScene.wheelEvent(self, event)
 - 
 - # ------------------------------------------------------------------------------
 - # canvasfadeanimation.cpp
 - 
 - class CanvasFadeAnimation(QAbstractAnimation):
 -     def __init__(self, item, show, parent=None):
 -         QAbstractAnimation.__init__(self, parent)
 - 
 -         self.m_show = show
 -         self.m_duration = 0
 -         self.m_item = item
 - 
 -     def item(self):
 -         return self.m_item
 - 
 -     def setDuration(self, time):
 -         if self.m_item.opacity() == 0 and not self.m_show:
 -             self._duration = 0
 -         else:
 -             self.m_item.show()
 -             self.m_duration = time
 - 
 -     def duration(self):
 -         return self.m_duration
 - 
 -     def updateCurrentTime(self, time):
 -         if self.m_duration == 0:
 -             return
 - 
 -         if self.m_show:
 -             value = float(time) / self.m_duration
 -         else:
 -             value = 1.0 - (float(time) / self.m_duration)
 - 
 -         self.m_item.setOpacity(value)
 - 
 -         if self.m_item.type() == CanvasBoxType:
 -             self.m_item.setShadowOpacity(value)
 - 
 -     def updateDirection(self, direction):
 -         pass
 - 
 -     def updateState(self, oldState, newState):
 -         pass
 - 
 - # ------------------------------------------------------------------------------
 - # canvasline.cpp
 - 
 - class CanvasLine(QGraphicsLineItem):
 -     def __init__(self, item1, item2, parent):
 -         QGraphicsLineItem.__init__(self, parent, canvas.scene)
 - 
 -         self.item1 = item1
 -         self.item2 = item2
 - 
 -         self.m_locked = False
 -         self.m_lineSelected = False
 - 
 -         self.setGraphicsEffect(None)
 -         self.updateLinePos()
 - 
 -     def deleteFromScene(self):
 -         canvas.scene.removeItem(self)
 -         del self
 - 
 -     def isLocked(self):
 -         return self.m_locked
 - 
 -     def setLocked(self, yesno):
 -         self.m_locked = yesno
 - 
 -     def isLineSelected(self):
 -         return self.m_lineSelected
 - 
 -     def setLineSelected(self, yesno):
 -         if self.m_locked:
 -             return
 - 
 -         if options.eyecandy == EYECANDY_FULL:
 -             if yesno:
 -                 self.setGraphicsEffect(CanvasPortGlow(self.item1.getPortType(), self.toGraphicsObject()))
 -             else:
 -                 self.setGraphicsEffect(None)
 - 
 -         self.m_lineSelected = yesno
 -         self.updateLineGradient()
 - 
 -     def updateLinePos(self):
 -         if self.item1.getPortMode() == PORT_MODE_OUTPUT:
 -             line = QLineF(self.item1.scenePos().x() + self.item1.getPortWidth() + 12,
 -                           self.item1.scenePos().y() + float(canvas.theme.port_height)/2,
 -                           self.item2.scenePos().x(),
 -                           self.item2.scenePos().y() + float(canvas.theme.port_height)/2)
 -             self.setLine(line)
 - 
 -             self.m_lineSelected = False
 -             self.updateLineGradient()
 - 
 -     def type(self):
 -         return CanvasLineType
 - 
 -     def updateLineGradient(self):
 -         pos_top = self.boundingRect().top()
 -         pos_bot = self.boundingRect().bottom()
 -         if self.item2.scenePos().y() >= self.item1.scenePos().y():
 -             pos1 = 0
 -             pos2 = 1
 -         else:
 -             pos1 = 1
 -             pos2 = 0
 - 
 -         port_type1 = self.item1.getPortType()
 -         port_type2 = self.item2.getPortType()
 -         port_gradient = QLinearGradient(0, pos_top, 0, pos_bot)
 - 
 -         if port_type1 == PORT_TYPE_AUDIO_JACK:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
 -         elif port_type1 == PORT_TYPE_MIDI_JACK:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
 -         elif port_type1 == PORT_TYPE_MIDI_A2J:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_a2j_sel if self.m_lineSelected else canvas.theme.line_midi_a2j)
 -         elif port_type1 == PORT_TYPE_MIDI_ALSA:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
 - 
 -         if port_type2 == PORT_TYPE_AUDIO_JACK:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
 -         elif port_type2 == PORT_TYPE_MIDI_JACK:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
 -         elif port_type2 == PORT_TYPE_MIDI_A2J:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_a2j_sel if self.m_lineSelected else canvas.theme.line_midi_a2j)
 -         elif port_type2 == PORT_TYPE_MIDI_ALSA:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
 - 
 -         self.setPen(QPen(port_gradient, 2))
 - 
 -     def paint(self, painter, option, widget):
 -         painter.save()
 -         painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
 -         QGraphicsLineItem.paint(self, painter, option, widget)
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvasbezierline.cpp
 - 
 - class CanvasBezierLine(QGraphicsPathItem):
 -     def __init__(self, item1, item2, parent):
 -         QGraphicsPathItem.__init__(self, parent, canvas.scene)
 - 
 -         self.item1 = item1
 -         self.item2 = item2
 - 
 -         self.m_locked = False
 -         self.m_lineSelected = False
 - 
 -         self.setBrush(QColor(0, 0, 0, 0))
 -         self.setGraphicsEffect(None)
 -         self.updateLinePos()
 - 
 -     def deleteFromScene(self):
 -         canvas.scene.removeItem(self)
 -         del self
 - 
 -     def isLocked(self):
 -         return self.m_locked
 - 
 -     def setLocked(self, yesno):
 -         self.m_locked = yesno
 - 
 -     def isLineSelected(self):
 -         return self.m_lineSelected
 - 
 -     def setLineSelected(self, yesno):
 -         if self.m_locked:
 -             return
 - 
 -         if options.eyecandy == EYECANDY_FULL:
 -             if yesno:
 -                 self.setGraphicsEffect(CanvasPortGlow(self.item1.getPortType(), self.toGraphicsObject()))
 -             else:
 -                 self.setGraphicsEffect(None)
 - 
 -         self.m_lineSelected = yesno
 -         self.updateLineGradient()
 - 
 -     def updateLinePos(self):
 -         if self.item1.getPortMode() == PORT_MODE_OUTPUT:
 -             item1_x = self.item1.scenePos().x() + self.item1.getPortWidth() + 12
 -             item1_y = self.item1.scenePos().y() + float(canvas.theme.port_height)/2
 - 
 -             item2_x = self.item2.scenePos().x()
 -             item2_y = self.item2.scenePos().y() + float(canvas.theme.port_height)/2
 - 
 -             item1_mid_x = abs(item1_x - item2_x) / 2
 -             item1_new_x = item1_x + item1_mid_x
 - 
 -             item2_mid_x = abs(item1_x - item2_x) / 2
 -             item2_new_x = item2_x - item2_mid_x
 - 
 -             path = QPainterPath(QPointF(item1_x, item1_y))
 -             path.cubicTo(item1_new_x, item1_y, item2_new_x, item2_y, item2_x, item2_y)
 -             self.setPath(path)
 - 
 -             self.m_lineSelected = False
 -             self.updateLineGradient()
 - 
 -     def type(self):
 -         return CanvasBezierLineType
 - 
 -     def updateLineGradient(self):
 -         pos_top = self.boundingRect().top()
 -         pos_bot = self.boundingRect().bottom()
 -         if self.item2.scenePos().y() >= self.item1.scenePos().y():
 -             pos1 = 0
 -             pos2 = 1
 -         else:
 -             pos1 = 1
 -             pos2 = 0
 - 
 -         port_type1 = self.item1.getPortType()
 -         port_type2 = self.item2.getPortType()
 -         port_gradient = QLinearGradient(0, pos_top, 0, pos_bot)
 - 
 -         if port_type1 == PORT_TYPE_AUDIO_JACK:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
 -         elif port_type1 == PORT_TYPE_MIDI_JACK:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
 -         elif port_type1 == PORT_TYPE_MIDI_A2J:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_a2j_sel if self.m_lineSelected else canvas.theme.line_midi_a2j)
 -         elif port_type1 == PORT_TYPE_MIDI_ALSA:
 -             port_gradient.setColorAt(pos1, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
 - 
 -         if port_type2 == PORT_TYPE_AUDIO_JACK:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
 -         elif port_type2 == PORT_TYPE_MIDI_JACK:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
 -         elif port_type2 == PORT_TYPE_MIDI_A2J:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_a2j_sel if self.m_lineSelected else canvas.theme.line_midi_a2j)
 -         elif port_type2 == PORT_TYPE_MIDI_ALSA:
 -             port_gradient.setColorAt(pos2, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
 - 
 -         self.setPen(QPen(port_gradient, 2))
 - 
 -     def paint(self, painter, option, widget):
 -         painter.save()
 -         painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
 -         QGraphicsPathItem.paint(self, painter, option, widget)
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvaslivemov.cpp
 - 
 - class CanvasLineMov(QGraphicsLineItem):
 -     def __init__(self, port_mode, port_type, parent):
 -         QGraphicsLineItem.__init__(self, parent, canvas.scene)
 - 
 -         self.m_port_mode = port_mode
 -         self.m_port_type = port_type
 - 
 -         # Port position doesn't change while moving around line
 -         self.p_lineX = self.scenePos().x()
 -         self.p_lineY = self.scenePos().y()
 -         self.p_width = self.parentItem().getPortWidth()
 - 
 -         if port_type == PORT_TYPE_AUDIO_JACK:
 -             pen = QPen(canvas.theme.line_audio_jack, 2)
 -         elif port_type == PORT_TYPE_MIDI_JACK:
 -             pen = QPen(canvas.theme.line_midi_jack, 2)
 -         elif port_type == PORT_TYPE_MIDI_A2J:
 -             pen = QPen(canvas.theme.line_midi_a2j, 2)
 -         elif port_type == PORT_TYPE_MIDI_ALSA:
 -             pen = QPen(canvas.theme.line_midi_alsa, 2)
 -         else:
 -             qWarning("PatchCanvas::CanvasLineMov(%s, %s, %s) - invalid port type" % (port_mode2str(port_mode), port_type2str(port_type), parent))
 -             pen = QPen(Qt.black)
 - 
 -         self.setPen(pen)
 - 
 -     def deleteFromScene(self):
 -         canvas.scene.removeItem(self)
 -         del self
 - 
 -     def updateLinePos(self, scenePos):
 -         item_pos = [0, 0]
 - 
 -         if self.m_port_mode == PORT_MODE_INPUT:
 -             item_pos[0] = 0
 -             item_pos[1] = float(canvas.theme.port_height)/2
 -         elif self.m_port_mode == PORT_MODE_OUTPUT:
 -             item_pos[0] = self.p_width + 12
 -             item_pos[1] = float(canvas.theme.port_height)/2
 -         else:
 -             return
 - 
 -         line = QLineF(item_pos[0], item_pos[1], scenePos.x() - self.p_lineX, scenePos.y() - self.p_lineY)
 -         self.setLine(line)
 - 
 -     def type(self):
 -         return CanvasLineMovType
 - 
 -     def paint(self, painter, option, widget):
 -         painter.save()
 -         painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
 -         QGraphicsLineItem.paint(self, painter, option, widget)
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvasbezierlinemov.cpp
 - 
 - class CanvasBezierLineMov(QGraphicsPathItem):
 -     def __init__(self, port_mode, port_type, parent):
 -         QGraphicsPathItem.__init__(self, parent, canvas.scene)
 - 
 -         self.m_port_mode = port_mode
 -         self.m_port_type = port_type
 - 
 -         # Port position doesn't change while moving around line
 -         self.p_itemX = self.scenePos().x()
 -         self.p_itemY = self.scenePos().y()
 -         self.p_width = self.parentItem().getPortWidth()
 - 
 -         if port_type == PORT_TYPE_AUDIO_JACK:
 -             pen = QPen(canvas.theme.line_audio_jack, 2)
 -         elif port_type == PORT_TYPE_MIDI_JACK:
 -             pen = QPen(canvas.theme.line_midi_jack, 2)
 -         elif port_type == PORT_TYPE_MIDI_A2J:
 -             pen = QPen(canvas.theme.line_midi_a2j, 2)
 -         elif port_type == PORT_TYPE_MIDI_ALSA:
 -             pen = QPen(canvas.theme.line_midi_alsa, 2)
 -         else:
 -             qWarning("PatchCanvas::CanvasBezierLineMov(%s, %s, %s) - invalid port type" % (port_mode2str(port_mode), port_type2str(port_type), parent))
 -             pen = QPen(Qt.black)
 - 
 -         self.setBrush(QColor(0, 0, 0, 0))
 -         self.setPen(pen)
 - 
 -     def deleteFromScene(self):
 -         canvas.scene.removeItem(self)
 -         del self
 - 
 -     def updateLinePos(self, scenePos):
 -         if self.m_port_mode == PORT_MODE_INPUT:
 -             old_x = 0
 -             old_y = float(canvas.theme.port_height)/2
 -             mid_x = abs(scenePos.x() - self.p_itemX) / 2
 -             new_x = old_x - mid_x
 -         elif self.m_port_mode == PORT_MODE_OUTPUT:
 -             old_x = self.p_width + 12
 -             old_y = float(canvas.theme.port_height)/2
 -             mid_x = abs(scenePos.x() - (self.p_itemX + old_x)) / 2
 -             new_x = old_x + mid_x
 -         else:
 -             return
 - 
 -         final_x = scenePos.x() - self.p_itemX
 -         final_y = scenePos.y() - self.p_itemY
 - 
 -         path = QPainterPath(QPointF(old_x, old_y))
 -         path.cubicTo(new_x, old_y, new_x, final_y, final_x, final_y)
 -         self.setPath(path)
 - 
 -     def type(self):
 -         return CanvasBezierLineMovType
 - 
 -     def paint(self, painter, option, widget):
 -         painter.save()
 -         painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
 -         QGraphicsPathItem.paint(self, painter, option, widget)
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvasport.cpp
 - 
 - class CanvasPort(QGraphicsItem):
 -     def __init__(self, port_id, port_name, port_mode, port_type, parent):
 -         QGraphicsItem.__init__(self, parent, canvas.scene)
 - 
 -         # Save Variables, useful for later
 -         self.m_port_id = port_id
 -         self.m_port_mode = port_mode
 -         self.m_port_type = port_type
 -         self.m_port_name = port_name
 - 
 -         # Base Variables
 -         self.m_port_width  = 15
 -         self.m_port_height = canvas.theme.port_height
 -         self.m_port_font = QFont(canvas.theme.port_font_name, canvas.theme.port_font_size, canvas.theme.port_font_state)
 - 
 -         self.m_line_mov = None
 -         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 getPortId(self):
 -         return self.m_port_id
 - 
 -     def getPortMode(self):
 -         return self.m_port_mode
 - 
 -     def getPortType(self):
 -         return self.m_port_type
 - 
 -     def getPortName(self):
 -         return self.m_port_name
 - 
 -     def getFullPortName(self):
 -         return self.parentItem().getGroupName() + ":" + self.m_port_name
 - 
 -     def getPortWidth(self):
 -         return self.m_port_width
 - 
 -     def getPortHeight(self):
 -         return self.m_port_height
 - 
 -     def setPortMode(self, port_mode):
 -         self.m_port_mode = port_mode
 -         self.update()
 - 
 -     def setPortType(self, port_type):
 -         self.m_port_type = port_type
 -         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, SLOT("update()"))
 - 
 -         self.m_port_name = port_name
 -         self.update()
 - 
 -     def setPortWidth(self, port_width):
 -         if port_width < self.m_port_width:
 -             QTimer.singleShot(0, canvas.scene, SLOT("update()"))
 - 
 -         self.m_port_width = port_width
 -         self.update()
 - 
 -     def type(self):
 -         return CanvasPortType
 - 
 -     def mousePressEvent(self, event):
 -         self.m_hover_item = None
 -         self.m_mouse_down = bool(event.button() == Qt.LeftButton)
 -         self.m_cursor_moving = False
 -         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 == self.m_port_id or connection.port_in_id == self.m_port_id:
 -                         connection.widget.setLocked(True)
 - 
 -             if not self.m_line_mov:
 -                 if options.use_bezier_lines:
 -                     self.m_line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, 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)
 -                 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:
 -                     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:
 -                 a2j_connection = bool(item.getPortType() == PORT_TYPE_MIDI_JACK and self.m_port_type == PORT_TYPE_MIDI_A2J) or (item.getPortType() == PORT_TYPE_MIDI_A2J and self.m_port_type == PORT_TYPE_MIDI_JACK)
 - 
 -                 if item.getPortMode() != self.m_port_mode and (item.getPortType() == self.m_port_type or a2j_connection):
 -                     item.setSelected(True)
 -                     self.m_hover_item = item
 -                 else:
 -                     self.m_hover_item = None
 -             else:
 -                 self.m_hover_item = None
 - 
 -             self.m_line_mov.updateLinePos(event.scenePos())
 -             return event.accept()
 - 
 -         QGraphicsItem.mouseMoveEvent(self, event)
 - 
 -     def mouseReleaseEvent(self, event):
 -         if self.m_mouse_down:
 -             if self.m_line_mov:
 -                 self.m_line_mov.deleteFromScene()
 -                 self.m_line_mov = None
 - 
 -             for connection in canvas.connection_list:
 -                 if connection.port_out_id == self.m_port_id or connection.port_in_id == self.m_port_id:
 -                     connection.widget.setLocked(False)
 - 
 -             if self.m_hover_item:
 -                 check = False
 -                 for connection in canvas.connection_list:
 -                     if ( (connection.port_out_id == self.m_port_id and connection.port_in_id == self.m_hover_item.getPortId()) or
 -                          (connection.port_out_id == self.m_hover_item.getPortId() and connection.port_in_id == self.m_port_id) ):
 -                         canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "")
 -                         check = True
 -                         break
 - 
 -                 if not check:
 -                     if self.m_port_mode == PORT_MODE_OUTPUT:
 -                         canvas.callback(ACTION_PORTS_CONNECT, self.m_port_id, self.m_hover_item.getPortId(), "")
 -                     else:
 -                         canvas.callback(ACTION_PORTS_CONNECT, self.m_hover_item.getPortId(), self.m_port_id, "")
 - 
 -                 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
 -         QGraphicsItem.mouseReleaseEvent(self, event)
 - 
 -     def contextMenuEvent(self, event):
 -         canvas.scene.clearSelection()
 -         self.setSelected(True)
 - 
 -         menu = QMenu()
 -         discMenu = QMenu("Disconnect", menu)
 - 
 -         port_con_list = CanvasGetPortConnectionList(self.m_port_id)
 - 
 -         if len(port_con_list) > 0:
 -             for port_id in port_con_list:
 -                 port_con_id = CanvasGetConnectedPort(port_id, self.m_port_id)
 -                 act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id))
 -                 act_x_disc.setData(port_id)
 -                 QObject.connect(act_x_disc, SIGNAL("triggered()"), canvas.qobject, SLOT("PortContextMenuDisconnect()"))
 -         else:
 -             act_x_disc = discMenu.addAction("No connections")
 -             act_x_disc.setEnabled(False)
 - 
 -         menu.addMenu(discMenu)
 -         act_x_disc_all = menu.addAction("Disconnect &All")
 -         act_x_sep_1 = menu.addSeparator()
 -         act_x_info = menu.addAction("Get &Info")
 -         act_x_rename = menu.addAction("&Rename")
 - 
 -         if not features.port_info:
 -             act_x_info.setVisible(False)
 - 
 -         if not features.port_rename:
 -             act_x_rename.setVisible(False)
 - 
 -         if not (features.port_info and features.port_rename):
 -             act_x_sep_1.setVisible(False)
 - 
 -         act_selected = menu.exec_(event.screenPos())
 - 
 -         if act_selected == act_x_disc_all:
 -             for port_id in port_con_list:
 -                 canvas.callback(ACTION_PORTS_DISCONNECT, port_id, 0, "")
 - 
 -         elif act_selected == act_x_info:
 -             canvas.callback(ACTION_PORT_INFO, self.m_port_id, 0, "")
 - 
 -         elif act_selected == act_x_rename:
 -             new_name_try = QInputDialog.getText(None, "Rename Port", "New name:", QLineEdit.Normal, self.m_port_name)
 -             if new_name_try[1] and new_name_try[0]: # 1 - bool ok, 0 - return text
 -                 canvas.callback(ACTION_PORT_RENAME, self.m_port_id, 0, new_name_try[0])
 - 
 -         event.accept()
 - 
 -     def boundingRect(self):
 -         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))
 - 
 -         poly_locx = [0, 0, 0, 0, 0]
 - 
 -         if self.m_port_mode == PORT_MODE_INPUT:
 -             text_pos = QPointF(3, canvas.theme.port_text_ypos)
 - 
 -             if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON:
 -                 poly_locx[0] = 0
 -                 poly_locx[1] = self.m_port_width + 5
 -                 poly_locx[2] = self.m_port_width + 12
 -                 poly_locx[3] = self.m_port_width + 5
 -                 poly_locx[4] = 0
 -             elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE:
 -                 poly_locx[0] = 0
 -                 poly_locx[1] = self.m_port_width + 5
 -                 poly_locx[2] = self.m_port_width + 5
 -                 poly_locx[3] = self.m_port_width + 5
 -                 poly_locx[4] = 0
 -             else:
 -                 qCritical("PatchCanvas::CanvasPort.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)
 - 
 -             if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON:
 -                 poly_locx[0] = self.m_port_width + 12
 -                 poly_locx[1] = 7
 -                 poly_locx[2] = 0
 -                 poly_locx[3] = 7
 -                 poly_locx[4] = self.m_port_width + 12
 -             elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE:
 -                 poly_locx[0] = self.m_port_width + 12
 -                 poly_locx[1] = 5
 -                 poly_locx[2] = 5
 -                 poly_locx[3] = 5
 -                 poly_locx[4] = self.m_port_width + 12
 -             else:
 -                 qCritical("PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode)
 -                 return
 - 
 -         else:
 -             qCritical("PatchCanvas::CanvasPort.paint() - invalid port mode '%s'" % port_mode2str(self.m_port_mode))
 -             return
 - 
 -         if self.m_port_type == PORT_TYPE_AUDIO_JACK:
 -             poly_color = canvas.theme.port_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_audio_jack_bg
 -             poly_pen = canvas.theme.port_audio_jack_pen_sel  if self.isSelected() else canvas.theme.port_audio_jack_pen
 -             text_pen = canvas.theme.port_audio_jack_text_sel if self.isSelected() else canvas.theme.port_audio_jack_text
 -             conn_pen = canvas.theme.port_audio_jack_pen_sel
 -         elif self.m_port_type == PORT_TYPE_MIDI_JACK:
 -             poly_color = canvas.theme.port_midi_jack_bg_sel if self.isSelected() else canvas.theme.port_midi_jack_bg
 -             poly_pen = canvas.theme.port_midi_jack_pen_sel  if self.isSelected() else canvas.theme.port_midi_jack_pen
 -             text_pen = canvas.theme.port_midi_jack_text_sel if self.isSelected() else canvas.theme.port_midi_jack_text
 -             conn_pen = canvas.theme.port_midi_jack_pen_sel
 -         elif self.m_port_type == PORT_TYPE_MIDI_A2J:
 -             poly_color = canvas.theme.port_midi_a2j_bg_sel if self.isSelected() else canvas.theme.port_midi_a2j_bg
 -             poly_pen = canvas.theme.port_midi_a2j_pen_sel  if self.isSelected() else canvas.theme.port_midi_a2j_pen
 -             text_pen = canvas.theme.port_midi_a2j_text_sel if self.isSelected() else canvas.theme.port_midi_a2j_text
 -             conn_pen = canvas.theme.port_midi_a2j_pen_sel
 -         elif self.m_port_type == PORT_TYPE_MIDI_ALSA:
 -             poly_color = canvas.theme.port_midi_alsa_bg_sel if self.isSelected() else canvas.theme.port_midi_alsa_bg
 -             poly_pen = canvas.theme.port_midi_alsa_pen_sel  if self.isSelected() else canvas.theme.port_midi_alsa_pen
 -             text_pen = canvas.theme.port_midi_alsa_text_sel if self.isSelected() else canvas.theme.port_midi_alsa_text
 -             conn_pen = canvas.theme.port_midi_alsa_pen_sel
 -         else:
 -             qCritical("PatchCanvas::CanvasPort.paint() - invalid port type '%s'" % port_type2str(self.m_port_type))
 -             return
 - 
 -         polygon  = QPolygonF()
 -         polygon += QPointF(poly_locx[0], 0)
 -         polygon += QPointF(poly_locx[1], 0)
 -         polygon += QPointF(poly_locx[2], float(canvas.theme.port_height)/2)
 -         polygon += QPointF(poly_locx[3], canvas.theme.port_height)
 -         polygon += QPointF(poly_locx[4], canvas.theme.port_height)
 - 
 -         if canvas.theme.port_bg_pixmap:
 -             portRect = polygon.boundingRect()
 -             portPos  = portRect.topLeft()
 -             painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos)
 -         else:
 -             painter.setBrush(poly_color)
 - 
 -         painter.setPen(poly_pen)
 -         painter.drawPolygon(polygon)
 - 
 -         painter.setPen(text_pen)
 -         painter.setFont(self.m_port_font)
 -         painter.drawText(text_pos, self.m_port_name)
 - 
 -         if self.isSelected() != self.m_last_selected_state:
 -             for connection in canvas.connection_list:
 -                 if connection.port_out_id == self.m_port_id or 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:
 -             painter.setPen(Qt.NoPen)
 -             painter.setBrush(conn_pen.brush())
 - 
 -             if self.m_port_mode == PORT_MODE_INPUT:
 -                 connRect = QRectF(portRect.topLeft(), QSizeF(2, portRect.height()))
 -             else:
 -                 connRect = QRectF(QPointF(portRect.right()-2, portRect.top()), QSizeF(2, portRect.height()))
 - 
 -             painter.drawRect(connRect)
 - 
 -         self.m_last_selected_state = self.isSelected()
 - 
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvasbox.cpp
 - 
 - class cb_line_t(object):
 -     __slots__ = [
 -         'line',
 -         'connection_id'
 -     ]
 - 
 - class CanvasBox(QGraphicsItem):
 -     def __init__(self, group_id, group_name, icon, parent=None):
 -         QGraphicsItem.__init__(self, parent, canvas.scene)
 - 
 -         # Save Variables, useful for later
 -         self.m_group_id   = group_id
 -         self.m_group_name = group_name
 - 
 -         # Base Variables
 -         self.p_width  = 50
 -         self.p_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1
 - 
 -         self.m_last_pos = QPointF()
 -         self.m_splitted = False
 -         self.m_splitted_mode = PORT_MODE_NULL
 - 
 -         self.m_cursor_moving = False
 -         self.m_forced_split = False
 -         self.m_mouse_down = False
 - 
 -         self.m_port_list_ids = []
 -         self.m_connection_lines = []
 - 
 -         # Set Font
 -         self.m_font_name = QFont(canvas.theme.box_font_name, canvas.theme.box_font_size, canvas.theme.box_font_state)
 -         self.m_font_port = QFont(canvas.theme.port_font_name, canvas.theme.port_font_size, canvas.theme.port_font_state)
 - 
 -         # Icon
 -         if canvas.theme.box_use_icon:
 -             self.icon_svg = CanvasIcon(icon, self.m_group_name, self)
 -         else:
 -             self.icon_svg = None
 - 
 -         # Shadow
 -         if options.eyecandy:
 -             self.shadow = CanvasBoxShadow(self.toGraphicsObject())
 -             self.shadow.setFakeParent(self)
 -             self.setGraphicsEffect(self.shadow)
 -         else:
 -             self.shadow = None
 - 
 -         # Final touches
 -         self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
 - 
 -         # Wait for at least 1 port
 -         if options.auto_hide_groups:
 -             self.setVisible(False)
 - 
 -         self.updatePositions()
 - 
 -     def getGroupId(self):
 -         return self.m_group_id
 - 
 -     def getGroupName(self):
 -         return self.m_group_name
 - 
 -     def isSplitted(self):
 -         return self.m_splitted
 - 
 -     def getSplittedMode(self):
 -         return self.m_splitted_mode
 - 
 -     def getPortCount(self):
 -         return len(self.m_port_list_ids)
 - 
 -     def getPortList(self):
 -         return self.m_port_list_ids
 - 
 -     def setIcon(self, icon):
 -         if self.icon_svg:
 -             self.icon_svg.setIcon(icon, self.m_group_name)
 - 
 -     def setSplit(self, split, mode=PORT_MODE_NULL):
 -         self.m_splitted = split
 -         self.m_splitted_mode = mode
 - 
 -     def setGroupName(self, group_name):
 -         self.m_group_name = group_name
 -         self.updatePositions()
 - 
 -     def setShadowOpacity(self, opacity):
 -         if self.shadow:
 -             self.shadow.setOpacity(opacity)
 - 
 -     def addPortFromGroup(self, port_id, port_mode, port_type, port_name):
 -         if len(self.m_port_list_ids) == 0:
 -             if options.auto_hide_groups:
 -                 if options.eyecandy == EYECANDY_FULL:
 -                     CanvasItemFX(self, True)
 -                 self.setVisible(True)
 - 
 -         new_widget = CanvasPort(port_id, port_name, port_mode, port_type, self)
 - 
 -         port_dict = port_dict_t()
 -         port_dict.group_id = self.m_group_id
 -         port_dict.port_id = port_id
 -         port_dict.port_name = port_name
 -         port_dict.port_mode = port_mode
 -         port_dict.port_type = port_type
 -         port_dict.widget = new_widget
 - 
 -         self.m_port_list_ids.append(port_id)
 - 
 -         return new_widget
 - 
 -     def removePortFromGroup(self, port_id):
 -         if port_id in self.m_port_list_ids:
 -             self.m_port_list_ids.remove(port_id)
 -         else:
 -             qCritical("PatchCanvas::CanvasBox.removePort(%i) - unable to find port to remove" % port_id)
 -             return
 - 
 -         if len(self.m_port_list_ids) > 0:
 -             self.updatePositions()
 - 
 -         elif self.isVisible():
 -             if options.auto_hide_groups:
 -                 if options.eyecandy == EYECANDY_FULL:
 -                     CanvasItemFX(self, False)
 -                 else:
 -                     self.setVisible(False)
 - 
 -     def addLineFromGroup(self, line, connection_id):
 -         new_cbline = cb_line_t()
 -         new_cbline.line = line
 -         new_cbline.connection_id = connection_id
 -         self.m_connection_lines.append(new_cbline)
 - 
 -     def removeLineFromGroup(self, connection_id):
 -         for connection in self.m_connection_lines:
 -             if connection.connection_id == connection_id:
 -                 self.m_connection_lines.remove(connection)
 -                 return
 -         qCritical("PatchCanvas::CanvasBox.removeLineFromGroup(%i) - unable to find line to remove" % connection_id)
 - 
 -     def checkItemPos(self):
 -         if not canvas.size_rect.isNull():
 -             pos = self.scenePos()
 -             if not (canvas.size_rect.contains(pos) and canvas.size_rect.contains(pos + QPointF(self.p_width, self.p_height))):
 -                 if pos.x() < canvas.size_rect.x():
 -                     self.setPos(canvas.size_rect.x(), pos.y())
 -                 elif pos.x() + self.p_width > canvas.size_rect.width():
 -                     self.setPos(canvas.size_rect.width() - self.p_width, pos.y())
 - 
 -                 pos = self.scenePos()
 -                 if pos.y() < canvas.size_rect.y():
 -                     self.setPos(pos.x(), canvas.size_rect.y())
 -                 elif pos.y() + self.p_height > canvas.size_rect.height():
 -                     self.setPos(pos.x(), canvas.size_rect.height() - self.p_height)
 - 
 -     def removeIconFromScene(self):
 -         if self.icon_svg:
 -             canvas.scene.removeItem(self.icon_svg)
 - 
 -     def updatePositions(self):
 -         self.prepareGeometryChange()
 - 
 -         max_in_width  = 0
 -         max_in_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing
 -         max_out_width  = 0
 -         max_out_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing
 -         port_spacing   = canvas.theme.port_height + canvas.theme.port_spacing
 - 
 -         have_audio_jack_in = have_midi_jack_in = have_midi_a2j_in = have_midi_alsa_in = False
 -         have_audio_jack_out = have_midi_jack_out = have_midi_a2j_out = have_midi_alsa_out = False
 - 
 -         # reset box size
 -         self.p_width  = 50
 -         self.p_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1
 - 
 -         # Check Text Name size
 -         app_name_size = QFontMetrics(self.m_font_name).width(self.m_group_name) + 30
 -         if app_name_size > self.p_width:
 -             self.p_width = app_name_size
 - 
 -         # Get Port List
 -         port_list = []
 -         for port in canvas.port_list:
 -             if port.port_id in self.m_port_list_ids:
 -                 port_list.append(port)
 - 
 -         # Get Max Box Width/Height
 -         for port in port_list:
 -             if port.port_mode == PORT_MODE_INPUT:
 -                 max_in_height += port_spacing
 - 
 -                 size = QFontMetrics(self.m_font_port).width(port.port_name)
 -                 if size > max_in_width:
 -                     max_in_width = size
 - 
 -                 if port.port_type == PORT_TYPE_AUDIO_JACK and not have_audio_jack_in:
 -                     have_audio_jack_in = True
 -                     max_in_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_JACK and not have_midi_jack_in:
 -                     have_midi_jack_in = True
 -                     max_in_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_A2J and not have_midi_a2j_in:
 -                     have_midi_a2j_in = True
 -                     max_in_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_ALSA and not have_midi_alsa_in:
 -                     have_midi_alsa_in = True
 -                     max_in_height += canvas.theme.port_spacingT
 - 
 -             elif port.port_mode == PORT_MODE_OUTPUT:
 -                 max_out_height += port_spacing
 - 
 -                 size = QFontMetrics(self.m_font_port).width(port.port_name)
 -                 if size > max_out_width:
 -                     max_out_width = size
 - 
 -                 if port.port_type == PORT_TYPE_AUDIO_JACK and not have_audio_jack_out:
 -                     have_audio_jack_out = True
 -                     max_out_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_JACK and not have_midi_jack_out:
 -                     have_midi_jack_out = True
 -                     max_out_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_A2J and not have_midi_a2j_out:
 -                     have_midi_a2j_out = True
 -                     max_out_height += canvas.theme.port_spacingT
 -                 elif port.port_type == PORT_TYPE_MIDI_ALSA and not have_midi_alsa_out:
 -                     have_midi_alsa_out = True
 -                     max_out_height += canvas.theme.port_spacingT
 - 
 -         if canvas.theme.port_spacingT == 0:
 -             max_in_height  += 2
 -             max_out_height += 2
 - 
 -         final_width = 30 + max_in_width + max_out_width
 -         if final_width > self.p_width:
 -             self.p_width = final_width
 - 
 -         if max_in_height > self.p_height:
 -             self.p_height = max_in_height
 - 
 -         if max_out_height > self.p_height:
 -             self.p_height = max_out_height
 - 
 -         # Remove bottom space
 -         self.p_height -= canvas.theme.port_spacingT
 - 
 -         if canvas.theme.box_header_spacing > 0:
 -             if len(port_list) == 0:
 -                 self.p_height -= canvas.theme.box_header_spacing
 -             else:
 -                 self.p_height -= canvas.theme.box_header_spacing/2
 - 
 -         last_in_pos  = canvas.theme.box_header_height + canvas.theme.box_header_spacing
 -         last_out_pos = canvas.theme.box_header_height + canvas.theme.box_header_spacing
 -         last_in_type  = PORT_TYPE_NULL
 -         last_out_type = PORT_TYPE_NULL
 - 
 -         # Re-position ports, AUDIO_JACK
 -         for port in port_list:
 -             if port.port_type == PORT_TYPE_AUDIO_JACK:
 -                 if port.port_mode == PORT_MODE_INPUT:
 -                     port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
 -                     port.widget.setPortWidth(max_in_width)
 - 
 -                     last_in_pos += port_spacing
 -                     last_in_type = port.port_type
 - 
 -                 elif port.port_mode == PORT_MODE_OUTPUT:
 -                     port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
 -                     port.widget.setPortWidth(max_out_width)
 - 
 -                     last_out_pos += port_spacing
 -                     last_out_type = port.port_type
 - 
 -         # Re-position ports, MIDI_JACK
 -         for port in port_list:
 -             if port.port_type == PORT_TYPE_MIDI_JACK:
 -                 if port.port_mode == PORT_MODE_INPUT:
 -                     if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
 -                         last_in_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
 -                     port.widget.setPortWidth(max_in_width)
 - 
 -                     last_in_pos += port_spacing
 -                     last_in_type = port.port_type
 - 
 -                 elif port.port_mode == PORT_MODE_OUTPUT:
 -                     if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
 -                         last_out_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
 -                     port.widget.setPortWidth(max_out_width)
 - 
 -                     last_out_pos += port_spacing
 -                     last_out_type = port.port_type
 - 
 -         # Re-position ports, MIDI_A2J
 -         for port in port_list:
 -             if port.port_type == PORT_TYPE_MIDI_A2J:
 -                 if port.port_mode == PORT_MODE_INPUT:
 -                     if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
 -                         last_in_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
 -                     port.widget.setPortWidth(max_in_width)
 - 
 -                     last_in_pos += port_spacing
 -                     last_in_type = port.port_type
 - 
 -                 elif port.port_mode == PORT_MODE_OUTPUT:
 -                     if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
 -                         last_out_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
 -                     port.widget.setPortWidth(max_out_width)
 - 
 -                     last_out_pos += port_spacing
 -                     last_out_type = port.port_type
 - 
 -         # Re-position ports, MIDI_ALSA
 -         for port in port_list:
 -             if port.port_type == PORT_TYPE_MIDI_ALSA:
 -                 if port.port_mode == PORT_MODE_INPUT:
 -                     if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
 -                         last_in_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
 -                     port.widget.setPortWidth(max_in_width)
 - 
 -                     last_in_pos += port_spacing
 -                     last_in_type = port.port_type
 - 
 -                 elif port.port_mode == PORT_MODE_OUTPUT:
 -                     if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
 -                         last_out_pos += canvas.theme.port_spacingT
 - 
 -                     port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
 -                     port.widget.setPortWidth(max_out_width)
 - 
 -                     last_out_pos += port_spacing
 -                     last_out_type = port.port_type
 - 
 -         self.repaintLines(True)
 -         self.update()
 - 
 -     def repaintLines(self, forced=False):
 -         if self.pos() != self.m_last_pos or forced:
 -             for connection in self.m_connection_lines:
 -                 connection.line.updateLinePos()
 - 
 -         self.m_last_pos = self.pos()
 - 
 -     def resetLinesZValue(self):
 -         for connection in canvas.connection_list:
 -             if connection.port_out_id in self.m_port_list_ids and connection.port_in_id in self.m_port_list_ids:
 -                 z_value = canvas.last_z_value
 -             else:
 -                 z_value = canvas.last_z_value - 1
 - 
 -             connection.widget.setZValue(z_value)
 - 
 -     def type(self):
 -         return CanvasBoxType
 - 
 -     def contextMenuEvent(self, event):
 -         menu = QMenu()
 -         discMenu = QMenu("Disconnect", menu)
 - 
 -         port_con_list = []
 -         port_con_list_ids = []
 - 
 -         for port_id in self.m_port_list_ids:
 -             tmp_port_con_list = CanvasGetPortConnectionList(port_id)
 -             for port_con_id in tmp_port_con_list:
 -                 if port_con_id not in port_con_list:
 -                     port_con_list.append(port_con_id)
 -                     port_con_list_ids.append(port_id)
 - 
 -         if len(port_con_list) > 0:
 -             for i in range(len(port_con_list)):
 -                 port_con_id = CanvasGetConnectedPort(port_con_list[i], port_con_list_ids[i])
 -                 act_x_disc = discMenu.addAction(CanvasGetFullPortName(port_con_id))
 -                 act_x_disc.setData(port_con_list[i])
 -                 QObject.connect(act_x_disc, SIGNAL("triggered()"), canvas.qobject, SLOT("PortContextMenuDisconnect()"))
 -         else:
 -             act_x_disc = discMenu.addAction("No connections")
 -             act_x_disc.setEnabled(False)
 - 
 -         menu.addMenu(discMenu)
 -         act_x_disc_all = menu.addAction("Disconnect &All")
 -         act_x_sep1 = menu.addSeparator()
 -         act_x_info = menu.addAction("&Info")
 -         act_x_rename = menu.addAction("&Rename")
 -         act_x_sep2 = menu.addSeparator()
 -         act_x_split_join = menu.addAction("Join" if self.m_splitted else "Split")
 - 
 -         if not features.group_info:
 -             act_x_info.setVisible(False)
 - 
 -         if not features.group_rename:
 -             act_x_rename.setVisible(False)
 - 
 -         if not (features.group_info and features.group_rename):
 -             act_x_sep1.setVisible(False)
 - 
 -         haveIns = haveOuts = False
 -         for port in canvas.port_list:
 -             if port.port_id in self.m_port_list_ids:
 -                 if port.port_mode == PORT_MODE_INPUT:
 -                     haveIns = True
 -                 elif port.port_mode == PORT_MODE_OUTPUT:
 -                     haveOuts = True
 - 
 -         if not (self.m_splitted or bool(haveIns and haveOuts)):
 -             act_x_sep2.setVisible(False)
 -             act_x_split_join.setVisible(False)
 - 
 -         act_selected = menu.exec_(event.screenPos())
 - 
 -         if act_selected == act_x_disc_all:
 -             for port_id in port_con_list:
 -                 canvas.callback(ACTION_PORTS_DISCONNECT, port_id, 0, "")
 - 
 -         elif act_selected == act_x_info:
 -             canvas.callback(ACTION_GROUP_INFO, self.m_group_id, 0, "")
 - 
 -         elif act_selected == act_x_rename:
 -             new_name_try = QInputDialog.getText(None, "Rename Group", "New name:", QLineEdit.Normal, self.m_group_name)
 -             if new_name_try[1] and new_name_try[0]: # 1 - bool ok, 0 - return text
 -                 canvas.callback(ACTION_GROUP_RENAME, self.m_group_id, 0, new_name_try[0])
 - 
 -         elif act_selected == act_x_split_join:
 -             if self.m_splitted:
 -                 canvas.callback(ACTION_GROUP_JOIN, self.m_group_id, 0, "")
 -             else:
 -                 canvas.callback(ACTION_GROUP_SPLIT, self.m_group_id, 0, "")
 - 
 -         event.accept()
 - 
 -     def mousePressEvent(self, event):
 -         canvas.last_z_value += 1
 -         self.setZValue(canvas.last_z_value)
 -         self.resetLinesZValue()
 -         self.m_cursor_moving = False
 - 
 -         if event.button() == Qt.RightButton:
 -             canvas.scene.clearSelection()
 -             self.setSelected(True)
 -             self.m_mouse_down = False
 -             return event.accept()
 - 
 -         elif event.button() == Qt.LeftButton:
 -             if self.sceneBoundingRect().contains(event.scenePos()):
 -                 self.m_mouse_down = True
 -             else:
 -                 # Fix a weird Qt behaviour with right-click mouseMove
 -                 self.m_mouse_down = False
 -                 return event.ignore()
 - 
 -         else:
 -             self.m_mouse_down = False
 - 
 -         QGraphicsItem.mousePressEvent(self, event)
 - 
 -     def mouseMoveEvent(self, event):
 -         if self.m_mouse_down:
 -             if not self.m_cursor_moving:
 -                 self.setCursor(QCursor(Qt.SizeAllCursor))
 -                 self.m_cursor_moving = True
 -             self.repaintLines()
 -         QGraphicsItem.mouseMoveEvent(self, event)
 - 
 -     def mouseReleaseEvent(self, event):
 -         if self.m_cursor_moving:
 -             self.setCursor(QCursor(Qt.ArrowCursor))
 -         self.m_mouse_down = False
 -         self.m_cursor_moving = False
 -         QGraphicsItem.mouseReleaseEvent(self, event)
 - 
 -     def boundingRect(self):
 -         return QRectF(0, 0, self.p_width, self.p_height)
 - 
 -     def paint(self, painter, option, widget):
 -         painter.save()
 -         painter.setRenderHint(QPainter.Antialiasing, False)
 - 
 -         # Draw rectangle
 -         if self.isSelected():
 -             painter.setPen(canvas.theme.box_pen_sel)
 -         else:
 -             painter.setPen(canvas.theme.box_pen)
 - 
 -         if canvas.theme.box_bg_type == Theme.THEME_BG_GRADIENT:
 -             box_gradient = QLinearGradient(0, 0, 0, self.p_height)
 -             box_gradient.setColorAt(0, canvas.theme.box_bg_1)
 -             box_gradient.setColorAt(1, canvas.theme.box_bg_2)
 -             painter.setBrush(box_gradient)
 -         else:
 -             painter.setBrush(canvas.theme.box_bg_1)
 - 
 -         painter.drawRect(0, 0, self.p_width, self.p_height)
 - 
 -         # Draw pixmap header
 -         if canvas.theme.box_header_pixmap:
 -             painter.setPen(Qt.NoPen)
 -             painter.setBrush(canvas.theme.box_bg_2)
 -             painter.drawRect(1, 1, self.p_width-2, canvas.theme.box_header_height)
 - 
 -             headerPos  = QPointF(1, 1)
 -             headerRect = QRectF(2, 2, self.p_width-4, canvas.theme.box_header_height-3)
 -             painter.drawTiledPixmap(headerRect, canvas.theme.box_header_pixmap, headerPos)
 - 
 -         # Draw text
 -         painter.setFont(self.m_font_name)
 - 
 -         if self.isSelected():
 -             painter.setPen(canvas.theme.box_text_sel)
 -         else:
 -             painter.setPen(canvas.theme.box_text)
 - 
 -         if canvas.theme.box_use_icon:
 -             textPos = QPointF(25, canvas.theme.box_text_ypos)
 -         else:
 -             appNameSize = QFontMetrics(self.m_font_name).width(self.m_group_name)
 -             rem = self.p_width - appNameSize
 -             textPos = QPointF(rem/2, canvas.theme.box_text_ypos)
 - 
 -         painter.drawText(textPos, self.m_group_name)
 - 
 -         self.repaintLines()
 - 
 -         painter.restore()
 - 
 - # ------------------------------------------------------------------------------
 - # canvasicon.cpp
 - 
 - class CanvasIcon(QGraphicsSvgItem):
 -     def __init__(self, icon, name, parent):
 -         QGraphicsSvgItem.__init__(self, parent)
 - 
 -         self.m_renderer = None
 -         self.p_size = QRectF(0, 0, 0, 0)
 - 
 -         self.m_colorFX = QGraphicsColorizeEffect(self)
 -         self.m_colorFX.setColor(canvas.theme.box_text.color())
 - 
 -         self.setGraphicsEffect(self.m_colorFX)
 -         self.setIcon(icon, name)
 - 
 -     def setIcon(self, icon, name):
 -         name = name.lower()
 -         icon_path = ""
 - 
 -         if icon == ICON_APPLICATION:
 -             self.p_size = QRectF(3, 2, 19, 18)
 - 
 -             if "audacious" in name:
 -                 icon_path   = ":/scalable/pb_audacious.svg"
 -                 self.p_size = QRectF(5, 4, 16, 16)
 -             elif "clementine" in name:
 -                 icon_path = ":/scalable/pb_clementine.svg"
 -                 self.p_size = QRectF(5, 4, 16, 16)
 -             elif "distrho" in name:
 -                 icon_path = ":/scalable/pb_distrho.svg"
 -                 self.p_size = QRectF(5, 4, 14, 14)
 -             elif "jamin" in name:
 -                 icon_path = ":/scalable/pb_jamin.svg"
 -                 self.p_size = QRectF(5, 3, 16, 16)
 -             elif "mplayer" in name:
 -                 icon_path = ":/scalable/pb_mplayer.svg"
 -                 self.p_size = QRectF(5, 4, 16, 16)
 -             elif "vlc" in name:
 -                 icon_path = ":/scalable/pb_vlc.svg"
 -                 self.p_size = QRectF(5, 3, 16, 16)
 - 
 -             else:
 -                 icon_path = ":/scalable/pb_generic.svg"
 -                 self.p_size = QRectF(4, 3, 16, 16)
 - 
 -         elif icon == ICON_HARDWARE:
 -             icon_path = ":/scalable/pb_hardware.svg"
 -             self.p_size = QRectF(5, 2, 16, 16)
 - 
 -         elif icon == ICON_DISTRHO:
 -             icon_path = ":/scalable/pb_distrho.svg"
 -             self.p_size = QRectF(5, 4, 14, 14)
 - 
 -         elif icon == ICON_FILE:
 -             icon_path = ":/scalable/pb_file.svg"
 -             self.p_size = QRectF(5, 4, 12, 14)
 - 
 -         elif icon == ICON_PLUGIN:
 -             icon_path = ":/scalable/pb_plugin.svg"
 -             self.p_size = QRectF(5, 4, 14, 14)
 - 
 -         elif icon == ICON_LADISH_ROOM:
 -             # TODO - make a unique ladish-room icon
 -             icon_path = ":/scalable/pb_hardware.svg"
 -             self.p_size = QRectF(5, 2, 16, 16)
 - 
 -         else:
 -             self.p_size = QRectF(0, 0, 0, 0)
 -             qCritical("PatchCanvas::CanvasIcon.setIcon(%s, %s) - unsupported icon requested" % (icon2str(icon), name.encode()))
 -             return
 - 
 -         self.m_renderer = QSvgRenderer(icon_path, canvas.scene)
 -         self.setSharedRenderer(self.m_renderer)
 -         self.update()
 - 
 -     def type(self):
 -         return CanvasIconType
 - 
 -     def boundingRect(self):
 -         return self.p_size
 - 
 -     def paint(self, painter, option, widget):
 -         if self.m_renderer:
 -             painter.save()
 -             painter.setRenderHint(QPainter.Antialiasing, False)
 -             painter.setRenderHint(QPainter.TextAntialiasing, False)
 -             self.m_renderer.render(painter, self.p_size)
 -             painter.restore()
 -         else:
 -             QGraphicsSvgItem.paint(self, painter, option, widget)
 - 
 - # ------------------------------------------------------------------------------
 - # canvasportglow.cpp
 - 
 - class CanvasPortGlow(QGraphicsDropShadowEffect):
 -     def __init__(self, port_type, parent):
 -         QGraphicsDropShadowEffect.__init__(self, parent)
 - 
 -         self.setBlurRadius(12)
 -         self.setOffset(0, 0)
 - 
 -         if port_type == PORT_TYPE_AUDIO_JACK:
 -             self.setColor(canvas.theme.line_audio_jack_glow)
 -         elif port_type == PORT_TYPE_MIDI_JACK:
 -             self.setColor(canvas.theme.line_midi_jack_glow)
 -         elif port_type == PORT_TYPE_MIDI_A2J:
 -             self.setColor(canvas.theme.line_midi_a2j_glow)
 -         elif port_type == PORT_TYPE_MIDI_ALSA:
 -             self.setColor(canvas.theme.line_midi_alsa_glow)
 - 
 - # ------------------------------------------------------------------------------
 - # canvasboxshadow.cpp
 - 
 - class CanvasBoxShadow(QGraphicsDropShadowEffect):
 -     def __init__(self, parent):
 -         QGraphicsDropShadowEffect.__init__(self, parent)
 - 
 -         self.m_fakeParent = None
 - 
 -         self.setBlurRadius(20)
 -         self.setColor(canvas.theme.box_shadow)
 -         self.setOffset(0, 0)
 - 
 -     def setFakeParent(self, fakeParent):
 -         self.m_fakeParent = fakeParent
 - 
 -     def setOpacity(self, opacity):
 -         color = QColor(canvas.theme.box_shadow)
 -         color.setAlphaF(opacity)
 -         self.setColor(color)
 - 
 -     def draw(self, painter):
 -         if self.m_fakeParent:
 -             self.m_fakeParent.repaintLines()
 -         QGraphicsDropShadowEffect.draw(self, painter)
 
 
  |