Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

patchcanvas.py 103KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # PatchBay Canvas engine using QGraphicsView/Scene
  4. # Copyright (C) 2010-2014 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Config)
  19. from carla_config import *
  20. # ------------------------------------------------------------------------------------------------------------
  21. # Imports (Global)
  22. if config_UseQt5:
  23. from PyQt5.QtCore import pyqtSignal, pyqtSlot, qCritical, qFatal, qWarning, Qt, QObject
  24. from PyQt5.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer
  25. from PyQt5.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath
  26. from PyQt5.QtGui import QCursor, QFont, QFontMetrics
  27. from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer
  28. from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem
  29. from PyQt5.QtWidgets import QGraphicsColorizeEffect, QGraphicsDropShadowEffect, QMenu
  30. else:
  31. from PyQt4.QtCore import pyqtSignal, pyqtSlot, qCritical, qFatal, qWarning, Qt, QObject
  32. from PyQt4.QtCore import QAbstractAnimation, QLineF, QPointF, QRectF, QSizeF, QSettings, QTimer
  33. from PyQt4.QtGui import QColor, QLinearGradient, QPen, QPolygonF, QPainter, QPainterPath
  34. from PyQt4.QtGui import QCursor, QFont, QFontMetrics
  35. from PyQt4.QtGui import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsPathItem
  36. from PyQt4.QtGui import QGraphicsColorizeEffect, QGraphicsDropShadowEffect, QMenu
  37. from PyQt4.QtSvg import QGraphicsSvgItem, QSvgRenderer
  38. # ------------------------------------------------------------------------------------------------------------
  39. # Imports (Theme)
  40. from patchcanvas_theme import *
  41. # ------------------------------------------------------------------------------
  42. # patchcanvas-api.h
  43. # Maximum Id for a plugin, treated as invalid/zero if above this value
  44. MAX_PLUGIN_ID_ALLOWED = 0x7FF
  45. # Port Mode
  46. PORT_MODE_NULL = 0
  47. PORT_MODE_INPUT = 1
  48. PORT_MODE_OUTPUT = 2
  49. # Port Type
  50. PORT_TYPE_NULL = 0
  51. PORT_TYPE_AUDIO_JACK = 1
  52. PORT_TYPE_MIDI_JACK = 2
  53. PORT_TYPE_MIDI_ALSA = 3
  54. PORT_TYPE_PARAMETER = 4
  55. # Callback Action
  56. ACTION_GROUP_INFO = 0 # group_id, N, N
  57. ACTION_GROUP_RENAME = 1 # group_id, N, N
  58. ACTION_GROUP_SPLIT = 2 # group_id, N, N
  59. ACTION_GROUP_JOIN = 3 # group_id, N, N
  60. ACTION_PORT_INFO = 4 # group_id, port_id, N
  61. ACTION_PORT_RENAME = 5 # group_id, port_id, N
  62. ACTION_PORTS_CONNECT = 6 # N, N, "outG:outP:inG:inP"
  63. ACTION_PORTS_DISCONNECT = 7 # conn_id, N, N
  64. ACTION_PLUGIN_CLONE = 8 # plugin_id, N, N
  65. ACTION_PLUGIN_EDIT = 9 # plugin_id, N, N
  66. ACTION_PLUGIN_RENAME = 10 # plugin_id, N, N
  67. ACTION_PLUGIN_REPLACE = 11 # plugin_id, N, N
  68. ACTION_PLUGIN_REMOVE = 12 # plugin_id, N, N
  69. ACTION_PLUGIN_SHOW_UI = 13 # plugin_id, N, N
  70. ACTION_BG_RIGHT_CLICK = 14 # N, N, N
  71. # Icon
  72. ICON_APPLICATION = 0
  73. ICON_HARDWARE = 1
  74. ICON_DISTRHO = 2
  75. ICON_FILE = 3
  76. ICON_PLUGIN = 4
  77. ICON_LADISH_ROOM = 5
  78. # Split Option
  79. SPLIT_UNDEF = 0
  80. SPLIT_NO = 1
  81. SPLIT_YES = 2
  82. # Antialiasing Option
  83. ANTIALIASING_NONE = 0
  84. ANTIALIASING_SMALL = 1
  85. ANTIALIASING_FULL = 2
  86. # Eye-Candy Option
  87. EYECANDY_NONE = 0
  88. EYECANDY_SMALL = 1
  89. EYECANDY_FULL = 2
  90. # Canvas options
  91. class options_t(object):
  92. __slots__ = [
  93. 'theme_name',
  94. 'auto_hide_groups',
  95. 'auto_select_items',
  96. 'use_bezier_lines',
  97. 'antialiasing',
  98. 'eyecandy'
  99. ]
  100. # Canvas features
  101. class features_t(object):
  102. __slots__ = [
  103. 'group_info',
  104. 'group_rename',
  105. 'port_info',
  106. 'port_rename',
  107. 'handle_group_pos'
  108. ]
  109. # ------------------------------------------------------------------------------
  110. # patchcanvas.h
  111. # object types
  112. CanvasBoxType = QGraphicsItem.UserType + 1
  113. CanvasIconType = QGraphicsItem.UserType + 2
  114. CanvasPortType = QGraphicsItem.UserType + 3
  115. CanvasLineType = QGraphicsItem.UserType + 4
  116. CanvasBezierLineType = QGraphicsItem.UserType + 5
  117. CanvasLineMovType = QGraphicsItem.UserType + 6
  118. CanvasBezierLineMovType = QGraphicsItem.UserType + 7
  119. # object lists
  120. class group_dict_t(object):
  121. __slots__ = [
  122. 'group_id',
  123. 'group_name',
  124. 'split',
  125. 'icon',
  126. 'plugin_id',
  127. 'plugin_ui',
  128. 'widgets'
  129. ]
  130. class port_dict_t(object):
  131. __slots__ = [
  132. 'group_id',
  133. 'port_id',
  134. 'port_name',
  135. 'port_mode',
  136. 'port_type',
  137. 'is_alternate',
  138. 'widget'
  139. ]
  140. class connection_dict_t(object):
  141. __slots__ = [
  142. 'connection_id',
  143. 'group_in_id',
  144. 'port_in_id',
  145. 'group_out_id',
  146. 'port_out_id',
  147. 'widget'
  148. ]
  149. class animation_dict_t(object):
  150. __slots__ = [
  151. 'animation',
  152. 'item'
  153. ]
  154. # Main Canvas object
  155. class Canvas(object):
  156. __slots__ = [
  157. 'scene',
  158. 'callback',
  159. 'debug',
  160. 'last_z_value',
  161. 'last_connection_id',
  162. 'initial_pos',
  163. 'size_rect',
  164. 'group_list',
  165. 'port_list',
  166. 'connection_list',
  167. 'animation_list',
  168. 'qobject',
  169. 'settings',
  170. 'theme',
  171. 'initiated'
  172. ]
  173. # ------------------------------------------------------------------------------
  174. # patchcanvas.cpp
  175. class CanvasObject(QObject):
  176. def __init__(self, parent=None):
  177. QObject.__init__(self, parent)
  178. @pyqtSlot()
  179. def AnimationFinishedShow(self):
  180. animation = self.sender()
  181. if animation:
  182. animation.forceStop()
  183. canvas.animation_list.remove(animation)
  184. @pyqtSlot()
  185. def AnimationFinishedHide(self):
  186. animation = self.sender()
  187. if animation:
  188. animation.forceStop()
  189. canvas.animation_list.remove(animation)
  190. item = animation.item()
  191. if item: item.hide()
  192. @pyqtSlot()
  193. def AnimationFinishedDestroy(self):
  194. animation = self.sender()
  195. if animation:
  196. animation.forceStop()
  197. canvas.animation_list.remove(animation)
  198. item = animation.item()
  199. if item: CanvasRemoveItemFX(item)
  200. @pyqtSlot()
  201. def PortContextMenuDisconnect(self):
  202. try:
  203. connectionId = int(self.sender().data())
  204. except:
  205. return
  206. CanvasCallback(ACTION_PORTS_DISCONNECT, connectionId, 0, "")
  207. # Global objects
  208. canvas = Canvas()
  209. canvas.qobject = None
  210. canvas.settings = None
  211. canvas.theme = None
  212. canvas.initiated = False
  213. canvas.group_list = []
  214. canvas.port_list = []
  215. canvas.connection_list = []
  216. canvas.animation_list = []
  217. options = options_t()
  218. options.theme_name = getDefaultThemeName()
  219. options.auto_hide_groups = False
  220. options.auto_select_items = False
  221. options.use_bezier_lines = True
  222. options.antialiasing = ANTIALIASING_SMALL
  223. options.eyecandy = EYECANDY_SMALL
  224. features = features_t()
  225. features.group_info = False
  226. features.group_rename = False
  227. features.port_info = False
  228. features.port_rename = False
  229. features.handle_group_pos = False
  230. # Internal functions
  231. def bool2str(check):
  232. return "True" if check else "False"
  233. def port_mode2str(port_mode):
  234. if port_mode == PORT_MODE_NULL:
  235. return "PORT_MODE_NULL"
  236. elif port_mode == PORT_MODE_INPUT:
  237. return "PORT_MODE_INPUT"
  238. elif port_mode == PORT_MODE_OUTPUT:
  239. return "PORT_MODE_OUTPUT"
  240. else:
  241. return "PORT_MODE_???"
  242. def port_type2str(port_type):
  243. if port_type == PORT_TYPE_NULL:
  244. return "PORT_TYPE_NULL"
  245. elif port_type == PORT_TYPE_AUDIO_JACK:
  246. return "PORT_TYPE_AUDIO_JACK"
  247. elif port_type == PORT_TYPE_MIDI_JACK:
  248. return "PORT_TYPE_MIDI_JACK"
  249. elif port_type == PORT_TYPE_MIDI_ALSA:
  250. return "PORT_TYPE_MIDI_ALSA"
  251. elif port_type == PORT_TYPE_PARAMETER:
  252. return "PORT_TYPE_MIDI_PARAMETER"
  253. else:
  254. return "PORT_TYPE_???"
  255. def icon2str(icon):
  256. if icon == ICON_APPLICATION:
  257. return "ICON_APPLICATION"
  258. elif icon == ICON_HARDWARE:
  259. return "ICON_HARDWARE"
  260. elif icon == ICON_DISTRHO:
  261. return "ICON_DISTRHO"
  262. elif icon == ICON_FILE:
  263. return "ICON_FILE"
  264. elif icon == ICON_PLUGIN:
  265. return "ICON_PLUGIN"
  266. elif icon == ICON_LADISH_ROOM:
  267. return "ICON_LADISH_ROOM"
  268. else:
  269. return "ICON_???"
  270. def split2str(split):
  271. if split == SPLIT_UNDEF:
  272. return "SPLIT_UNDEF"
  273. elif split == SPLIT_NO:
  274. return "SPLIT_NO"
  275. elif split == SPLIT_YES:
  276. return "SPLIT_YES"
  277. else:
  278. return "SPLIT_???"
  279. def getStoredCanvasPosition(key, fallback_pos):
  280. try:
  281. return canvas.settings.value("CanvasPositions/" + key, fallback_pos, type=QPointF)
  282. except:
  283. return fallback_pos
  284. def getStoredCanvasSplit(group_name, fallback_split_mode):
  285. try:
  286. return canvas.settings.value("CanvasPositions/%s_SPLIT" % group_name, fallback_split_mode, type=int)
  287. except:
  288. return fallback_split_mode
  289. # PatchCanvas API
  290. def setOptions(new_options):
  291. if canvas.initiated: return
  292. options.theme_name = new_options.theme_name
  293. options.auto_hide_groups = new_options.auto_hide_groups
  294. options.auto_select_items = new_options.auto_select_items
  295. options.use_bezier_lines = new_options.use_bezier_lines
  296. options.antialiasing = new_options.antialiasing
  297. options.eyecandy = new_options.eyecandy
  298. def setFeatures(new_features):
  299. if canvas.initiated: return
  300. features.group_info = new_features.group_info
  301. features.group_rename = new_features.group_rename
  302. features.port_info = new_features.port_info
  303. features.port_rename = new_features.port_rename
  304. features.handle_group_pos = new_features.handle_group_pos
  305. def init(appName, scene, callback, debug=False):
  306. if debug:
  307. print("PatchCanvas::init(\"%s\", %s, %s, %s)" % (appName, scene, callback, bool2str(debug)))
  308. if canvas.initiated:
  309. qCritical("PatchCanvas::init() - already initiated")
  310. return
  311. if not callback:
  312. qFatal("PatchCanvas::init() - fatal error: callback not set")
  313. return
  314. canvas.scene = scene
  315. canvas.callback = callback
  316. canvas.debug = debug
  317. canvas.last_z_value = 0
  318. canvas.last_connection_id = 0
  319. canvas.initial_pos = QPointF(0, 0)
  320. canvas.size_rect = QRectF()
  321. if not canvas.qobject: canvas.qobject = CanvasObject()
  322. if not canvas.settings: canvas.settings = QSettings("falkTX", appName)
  323. if canvas.theme:
  324. del canvas.theme
  325. canvas.theme = None
  326. for i in range(Theme.THEME_MAX):
  327. this_theme_name = getThemeName(i)
  328. if this_theme_name == options.theme_name:
  329. canvas.theme = Theme(i)
  330. break
  331. if not canvas.theme:
  332. canvas.theme = Theme(getDefaultTheme())
  333. canvas.scene.updateTheme()
  334. canvas.initiated = True
  335. def clear():
  336. if canvas.debug:
  337. print("PatchCanvas::clear()")
  338. group_list_ids = []
  339. port_list_ids = []
  340. connection_list_ids = []
  341. for group in canvas.group_list:
  342. group_list_ids.append(group.group_id)
  343. for port in canvas.port_list:
  344. port_list_ids.append((port.group_id, port.port_id))
  345. for connection in canvas.connection_list:
  346. connection_list_ids.append(connection.connection_id)
  347. for idx in connection_list_ids:
  348. disconnectPorts(idx)
  349. for group_id, port_id in port_list_ids:
  350. removePort(group_id, port_id)
  351. for idx in group_list_ids:
  352. removeGroup(idx)
  353. canvas.last_z_value = 0
  354. canvas.last_connection_id = 0
  355. canvas.group_list = []
  356. canvas.port_list = []
  357. canvas.connection_list = []
  358. canvas.scene.clearSelection()
  359. animatedItems = []
  360. for animation in canvas.animation_list:
  361. animatedItems.append(animation.item())
  362. for item in canvas.scene.items():
  363. if item.type() != CanvasIconType and item not in animatedItems:
  364. canvas.scene.removeItem(item)
  365. del item
  366. canvas.initiated = False
  367. QTimer.singleShot(0, canvas.scene.update)
  368. def setInitialPos(x, y):
  369. if canvas.debug:
  370. print("PatchCanvas::setInitialPos(%i, %i)" % (x, y))
  371. canvas.initial_pos.setX(x)
  372. canvas.initial_pos.setY(y)
  373. def setCanvasSize(x, y, width, height):
  374. if canvas.debug:
  375. print("PatchCanvas::setCanvasSize(%i, %i, %i, %i)" % (x, y, width, height))
  376. canvas.size_rect.setX(x)
  377. canvas.size_rect.setY(y)
  378. canvas.size_rect.setWidth(width)
  379. canvas.size_rect.setHeight(height)
  380. def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION):
  381. if canvas.debug:
  382. print("PatchCanvas::addGroup(%i, %s, %s, %s)" % (group_id, group_name.encode(), split2str(split), icon2str(icon)))
  383. for group in canvas.group_list:
  384. if group.group_id == group_id:
  385. qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists" % (group_id, group_name.encode(), split2str(split), icon2str(icon)))
  386. return
  387. if split == SPLIT_UNDEF:
  388. isHardware = bool(icon == ICON_HARDWARE)
  389. if features.handle_group_pos:
  390. split = getStoredCanvasSplit(group_name, SPLIT_YES if isHardware else split)
  391. elif isHardware:
  392. split = SPLIT_YES
  393. group_box = CanvasBox(group_id, group_name, icon)
  394. group_dict = group_dict_t()
  395. group_dict.group_id = group_id
  396. group_dict.group_name = group_name
  397. group_dict.split = bool(split == SPLIT_YES)
  398. group_dict.icon = icon
  399. group_dict.plugin_id = -1
  400. group_dict.plugin_ui = False
  401. group_dict.widgets = [group_box, None]
  402. if split == SPLIT_YES:
  403. group_box.setSplit(True, PORT_MODE_OUTPUT)
  404. if features.handle_group_pos:
  405. group_box.setPos(getStoredCanvasPosition(group_name + "_OUTPUT", CanvasGetNewGroupPos(False)))
  406. else:
  407. group_box.setPos(CanvasGetNewGroupPos(False))
  408. group_sbox = CanvasBox(group_id, group_name, icon)
  409. group_sbox.setSplit(True, PORT_MODE_INPUT)
  410. group_dict.widgets[1] = group_sbox
  411. if features.handle_group_pos:
  412. group_sbox.setPos(getStoredCanvasPosition(group_name + "_INPUT", CanvasGetNewGroupPos(True)))
  413. else:
  414. group_sbox.setPos(CanvasGetNewGroupPos(True))
  415. canvas.last_z_value += 1
  416. group_sbox.setZValue(canvas.last_z_value)
  417. if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups:
  418. CanvasItemFX(group_sbox, True, False)
  419. group_sbox.checkItemPos()
  420. else:
  421. group_box.setSplit(False)
  422. if features.handle_group_pos:
  423. group_box.setPos(getStoredCanvasPosition(group_name, CanvasGetNewGroupPos(False)))
  424. else:
  425. # Special ladish fake-split groups
  426. horizontal = bool(icon == ICON_HARDWARE or icon == ICON_LADISH_ROOM)
  427. group_box.setPos(CanvasGetNewGroupPos(horizontal))
  428. group_box.checkItemPos()
  429. canvas.last_z_value += 1
  430. group_box.setZValue(canvas.last_z_value)
  431. canvas.group_list.append(group_dict)
  432. if options.eyecandy == EYECANDY_FULL and not options.auto_hide_groups:
  433. return CanvasItemFX(group_box, True, False)
  434. QTimer.singleShot(0, canvas.scene.update)
  435. def removeGroup(group_id):
  436. if canvas.debug:
  437. print("PatchCanvas::removeGroup(%i)" % group_id)
  438. for group in canvas.group_list:
  439. if group.group_id == group_id:
  440. item = group.widgets[0]
  441. group_name = group.group_name
  442. if group.split:
  443. s_item = group.widgets[1]
  444. if features.handle_group_pos:
  445. canvas.settings.setValue("CanvasPositions/%s_OUTPUT" % group_name, item.pos())
  446. canvas.settings.setValue("CanvasPositions/%s_INPUT" % group_name, s_item.pos())
  447. canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_YES)
  448. if options.eyecandy == EYECANDY_FULL:
  449. CanvasItemFX(s_item, False, True)
  450. else:
  451. s_item.removeIconFromScene()
  452. canvas.scene.removeItem(s_item)
  453. del s_item
  454. else:
  455. if features.handle_group_pos:
  456. canvas.settings.setValue("CanvasPositions/%s" % group_name, item.pos())
  457. canvas.settings.setValue("CanvasPositions/%s_SPLIT" % group_name, SPLIT_NO)
  458. if options.eyecandy == EYECANDY_FULL:
  459. CanvasItemFX(item, False, True)
  460. else:
  461. item.removeIconFromScene()
  462. canvas.scene.removeItem(item)
  463. del item
  464. canvas.group_list.remove(group)
  465. QTimer.singleShot(0, canvas.scene.update)
  466. return
  467. qCritical("PatchCanvas::removeGroup(%i) - unable to find group to remove" % group_id)
  468. def renameGroup(group_id, new_group_name):
  469. if canvas.debug:
  470. print("PatchCanvas::renameGroup(%i, %s)" % (group_id, new_group_name.encode()))
  471. for group in canvas.group_list:
  472. if group.group_id == group_id:
  473. group.group_name = new_group_name
  474. group.widgets[0].setGroupName(new_group_name)
  475. if group.split and group.widgets[1]:
  476. group.widgets[1].setGroupName(new_group_name)
  477. QTimer.singleShot(0, canvas.scene.update)
  478. return
  479. qCritical("PatchCanvas::renameGroup(%i, %s) - unable to find group to rename" % (group_id, new_group_name.encode()))
  480. def splitGroup(group_id):
  481. if canvas.debug:
  482. print("PatchCanvas::splitGroup(%i)" % group_id)
  483. item = None
  484. group_name = ""
  485. group_icon = ICON_APPLICATION
  486. plugin_id = -1
  487. plugin_ui = False
  488. ports_data = []
  489. conns_data = []
  490. # Step 1 - Store all Item data
  491. for group in canvas.group_list:
  492. if group.group_id == group_id:
  493. if group.split:
  494. qCritical("PatchCanvas::splitGroup(%i) - group is already splitted" % group_id)
  495. return
  496. item = group.widgets[0]
  497. group_name = group.group_name
  498. group_icon = group.icon
  499. plugin_id = group.plugin_id
  500. plugin_ui = group.plugin_ui
  501. break
  502. if not item:
  503. qCritical("PatchCanvas::splitGroup(%i) - unable to find group to split" % group_id)
  504. return
  505. port_list_ids = list(item.getPortList())
  506. for port in canvas.port_list:
  507. if port.port_id in port_list_ids:
  508. port_dict = port_dict_t()
  509. port_dict.group_id = port.group_id
  510. port_dict.port_id = port.port_id
  511. port_dict.port_name = port.port_name
  512. port_dict.port_mode = port.port_mode
  513. port_dict.port_type = port.port_type
  514. port_dict.is_alternate = port.is_alternate
  515. port_dict.widget = None
  516. ports_data.append(port_dict)
  517. for connection in canvas.connection_list:
  518. if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids:
  519. connection_dict = connection_dict_t()
  520. connection_dict.connection_id = connection.connection_id
  521. connection_dict.group_in_id = connection.group_in_id
  522. connection_dict.port_in_id = connection.port_in_id
  523. connection_dict.group_out_id = connection.group_out_id
  524. connection_dict.port_out_id = connection.port_out_id
  525. connection_dict.widget = None
  526. conns_data.append(connection_dict)
  527. # Step 2 - Remove Item and Children
  528. for conn in conns_data:
  529. disconnectPorts(conn.connection_id)
  530. for port_id in port_list_ids:
  531. removePort(group_id, port_id)
  532. removeGroup(group_id)
  533. # Step 3 - Re-create Item, now splitted
  534. addGroup(group_id, group_name, SPLIT_YES, group_icon)
  535. if plugin_id >= 0:
  536. setGroupAsPlugin(group_id, plugin_id, plugin_ui)
  537. for port in ports_data:
  538. addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type, port.is_alternate)
  539. for conn in conns_data:
  540. connectPorts(conn.connection_id, conn.group_out_id, conn.port_out_id, conn.group_in_id, conn.port_in_id)
  541. QTimer.singleShot(0, canvas.scene.update)
  542. def joinGroup(group_id):
  543. if canvas.debug:
  544. print("PatchCanvas::joinGroup(%i)" % group_id)
  545. item = None
  546. s_item = None
  547. group_name = ""
  548. group_icon = ICON_APPLICATION
  549. plugin_id = -1
  550. plugin_ui = False
  551. ports_data = []
  552. conns_data = []
  553. # Step 1 - Store all Item data
  554. for group in canvas.group_list:
  555. if group.group_id == group_id:
  556. if not group.split:
  557. qCritical("PatchCanvas::joinGroup(%i) - group is not splitted" % group_id)
  558. return
  559. item = group.widgets[0]
  560. s_item = group.widgets[1]
  561. group_name = group.group_name
  562. group_icon = group.icon
  563. plugin_id = group.plugin_id
  564. plugin_ui = group.plugin_ui
  565. break
  566. # FIXME
  567. if not (item and s_item):
  568. qCritical("PatchCanvas::joinGroup(%i) - unable to find groups to join" % group_id)
  569. return
  570. port_list_ids = list(item.getPortList())
  571. port_list_idss = s_item.getPortList()
  572. for port_id in port_list_idss:
  573. if port_id not in port_list_ids:
  574. port_list_ids.append(port_id)
  575. for port in canvas.port_list:
  576. if port.port_id in port_list_ids:
  577. port_dict = port_dict_t()
  578. port_dict.group_id = port.group_id
  579. port_dict.port_id = port.port_id
  580. port_dict.port_name = port.port_name
  581. port_dict.port_mode = port.port_mode
  582. port_dict.port_type = port.port_type
  583. port_dict.is_alternate = port.is_alternate
  584. port_dict.widget = None
  585. ports_data.append(port_dict)
  586. for connection in canvas.connection_list:
  587. if connection.port_out_id in port_list_ids or connection.port_in_id in port_list_ids:
  588. connection_dict = connection_dict_t()
  589. connection_dict.connection_id = connection.connection_id
  590. connection_dict.group_in_id = connection.group_in_id
  591. connection_dict.port_in_id = connection.port_in_id
  592. connection_dict.group_out_id = connection.group_out_id
  593. connection_dict.port_out_id = connection.port_out_id
  594. connection_dict.widget = None
  595. conns_data.append(connection_dict)
  596. # Step 2 - Remove Item and Children
  597. for conn in conns_data:
  598. disconnectPorts(conn.connection_id)
  599. for port_id in port_list_ids:
  600. removePort(group_id, port_id)
  601. removeGroup(group_id)
  602. # Step 3 - Re-create Item, now together
  603. addGroup(group_id, group_name, SPLIT_NO, group_icon)
  604. if plugin_id >= 0:
  605. setGroupAsPlugin(group_id, plugin_id, plugin_ui)
  606. for port in ports_data:
  607. addPort(group_id, port.port_id, port.port_name, port.port_mode, port.port_type, port.is_alternate)
  608. for conn in conns_data:
  609. connectPorts(conn.connection_id, conn.group_out_id, conn.port_out_id, conn.group_in_id, conn.port_in_id)
  610. QTimer.singleShot(0, canvas.scene.update)
  611. def getGroupPos(group_id, port_mode=PORT_MODE_OUTPUT):
  612. if canvas.debug:
  613. print("PatchCanvas::getGroupPos(%i, %s)" % (group_id, port_mode2str(port_mode)))
  614. for group in canvas.group_list:
  615. if group.group_id == group_id:
  616. if group.split:
  617. if port_mode == PORT_MODE_OUTPUT:
  618. return group.widgets[0].pos()
  619. elif port_mode == PORT_MODE_INPUT:
  620. return group.widgets[1].pos()
  621. else:
  622. return QPointF(0, 0)
  623. else:
  624. return group.widgets[0].pos()
  625. qCritical("PatchCanvas::getGroupPos(%i, %s) - unable to find group" % (group_id, port_mode2str(port_mode)))
  626. return QPointF(0, 0)
  627. def saveGroupPositions():
  628. if canvas.debug:
  629. print("PatchCanvas::getGroupPositions()")
  630. ret = []
  631. for group in canvas.group_list:
  632. if group.split:
  633. pos1 = group.widgets[0].pos()
  634. pos2 = group.widgets[1].pos()
  635. else:
  636. pos1 = group.widgets[0].pos()
  637. pos2 = QPointF(0, 0)
  638. ret.append({
  639. "name" : group.group_name,
  640. "pos1x": pos1.x(),
  641. "pos1y": pos1.y(),
  642. "pos2x": pos2.x(),
  643. "pos2y": pos2.y(),
  644. "split": group.split,
  645. })
  646. return ret
  647. def restoreGroupPositions(dataList):
  648. if canvas.debug:
  649. print("PatchCanvas::restoreGroupPositions(...)")
  650. map = {}
  651. for group in canvas.group_list:
  652. map[group.group_name] = group
  653. for data in dataList:
  654. name = data['name']
  655. group = map.get(name, None)
  656. if group is None:
  657. continue
  658. group.widgets[0].setPos(data['pos1x'], data['pos1y'])
  659. if group.split and group.widgets[1]:
  660. group.widgets[1].setPos(data['pos2x'], data['pos2y'])
  661. def setGroupPos(group_id, group_pos_x, group_pos_y):
  662. setGroupPosFull(group_id, group_pos_x, group_pos_y, group_pos_x, group_pos_y)
  663. def setGroupPosFull(group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i):
  664. if canvas.debug:
  665. print("PatchCanvas::setGroupPos(%i, %i, %i, %i, %i)" % (group_id, group_pos_x_o, group_pos_y_o, group_pos_x_i, group_pos_y_i))
  666. for group in canvas.group_list:
  667. if group.group_id == group_id:
  668. group.widgets[0].setPos(group_pos_x_o, group_pos_y_o)
  669. if group.split and group.widgets[1]:
  670. group.widgets[1].setPos(group_pos_x_i, group_pos_y_i)
  671. QTimer.singleShot(0, canvas.scene.update)
  672. return
  673. 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))
  674. def setGroupIcon(group_id, icon):
  675. if canvas.debug:
  676. print("PatchCanvas::setGroupIcon(%i, %s)" % (group_id, icon2str(icon)))
  677. for group in canvas.group_list:
  678. if group.group_id == group_id:
  679. group.icon = icon
  680. group.widgets[0].setIcon(icon)
  681. if group.split and group.widgets[1]:
  682. group.widgets[1].setIcon(icon)
  683. QTimer.singleShot(0, canvas.scene.update)
  684. return
  685. qCritical("PatchCanvas::setGroupIcon(%i, %s) - unable to find group to change icon" % (group_id, icon2str(icon)))
  686. def setGroupAsPlugin(group_id, plugin_id, hasUi):
  687. if canvas.debug:
  688. print("PatchCanvas::setGroupAsPlugin(%i, %i, %s)" % (group_id, plugin_id, bool2str(hasUi)))
  689. for group in canvas.group_list:
  690. if group.group_id == group_id:
  691. group.plugin_id = plugin_id
  692. group.plugin_ui = hasUi
  693. group.widgets[0].setAsPlugin(plugin_id, hasUi)
  694. if group.split and group.widgets[1]:
  695. group.widgets[1].setAsPlugin(plugin_id, hasUi)
  696. return
  697. qCritical("PatchCanvas::setGroupAsPlugin(%i, %i, %s) - unable to find group to set as plugin" % (group_id, plugin_id, bool2str(hasUi)))
  698. def addPort(group_id, port_id, port_name, port_mode, port_type, is_alternate=False):
  699. if canvas.debug:
  700. print("PatchCanvas::addPort(%i, %i, %s, %s, %s, %s)" % (group_id, port_id, port_name.encode(), port_mode2str(port_mode), port_type2str(port_type), bool2str(is_alternate)))
  701. for port in canvas.port_list:
  702. if port.group_id == group_id and port.port_id == port_id:
  703. 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)))
  704. return
  705. box_widget = None
  706. port_widget = None
  707. for group in canvas.group_list:
  708. if group.group_id == group_id:
  709. if group.split and group.widgets[0].getSplittedMode() != port_mode and group.widgets[1]:
  710. n = 1
  711. else:
  712. n = 0
  713. box_widget = group.widgets[n]
  714. port_widget = box_widget.addPortFromGroup(port_id, port_mode, port_type, port_name, is_alternate)
  715. break
  716. if not (box_widget and port_widget):
  717. 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)))
  718. return
  719. port_dict = port_dict_t()
  720. port_dict.group_id = group_id
  721. port_dict.port_id = port_id
  722. port_dict.port_name = port_name
  723. port_dict.port_mode = port_mode
  724. port_dict.port_type = port_type
  725. port_dict.is_alternate = is_alternate
  726. port_dict.widget = port_widget
  727. canvas.port_list.append(port_dict)
  728. box_widget.updatePositions()
  729. if options.eyecandy == EYECANDY_FULL:
  730. return CanvasItemFX(port_widget, True, False)
  731. QTimer.singleShot(0, canvas.scene.update)
  732. def removePort(group_id, port_id):
  733. if canvas.debug:
  734. print("PatchCanvas::removePort(%i, %i)" % (group_id, port_id))
  735. for port in canvas.port_list:
  736. if port.group_id == group_id and port.port_id == port_id:
  737. item = port.widget
  738. item.parentItem().removePortFromGroup(port_id)
  739. canvas.scene.removeItem(item)
  740. canvas.port_list.remove(port)
  741. del item
  742. QTimer.singleShot(0, canvas.scene.update)
  743. return
  744. qCritical("PatchCanvas::removePort(%i, %i) - Unable to find port to remove" % (group_id, port_id))
  745. def renamePort(group_id, port_id, new_port_name):
  746. if canvas.debug:
  747. print("PatchCanvas::renamePort(%i, %i, %s)" % (group_id, port_id, new_port_name.encode()))
  748. for port in canvas.port_list:
  749. if port.group_id == group_id and port.port_id == port_id:
  750. port.port_name = new_port_name
  751. port.widget.setPortName(new_port_name)
  752. port.widget.parentItem().updatePositions()
  753. QTimer.singleShot(0, canvas.scene.update)
  754. return
  755. qCritical("PatchCanvas::renamePort(%i, %i, %s) - Unable to find port to rename" % (group_id, port_id, new_port_name.encode()))
  756. def connectPorts(connection_id, group_out_id, port_out_id, group_in_id, port_in_id):
  757. if canvas.debug:
  758. print("PatchCanvas::connectPorts(%i, %i, %i, %i, %i)" % (connection_id, group_out_id, port_out_id, group_in_id, port_in_id))
  759. port_out = None
  760. port_in = None
  761. port_out_parent = None
  762. port_in_parent = None
  763. for port in canvas.port_list:
  764. if port.group_id == group_out_id and port.port_id == port_out_id:
  765. port_out = port.widget
  766. port_out_parent = port_out.parentItem()
  767. elif port.group_id == group_in_id and port.port_id == port_in_id:
  768. port_in = port.widget
  769. port_in_parent = port_in.parentItem()
  770. # FIXME
  771. if not (port_out and port_in):
  772. qCritical("PatchCanvas::connectPorts(%i, %i, %i, %i, %i) - unable to find ports to connect" % (connection_id, group_out_id, port_out_id, group_in_id, port_in_id))
  773. return
  774. connection_dict = connection_dict_t()
  775. connection_dict.connection_id = connection_id
  776. connection_dict.group_in_id = group_in_id
  777. connection_dict.port_in_id = port_in_id
  778. connection_dict.group_out_id = group_out_id
  779. connection_dict.port_out_id = port_out_id
  780. if options.use_bezier_lines:
  781. connection_dict.widget = CanvasBezierLine(port_out, port_in, None)
  782. else:
  783. connection_dict.widget = CanvasLine(port_out, port_in, None)
  784. canvas.scene.addItem(connection_dict.widget)
  785. port_out_parent.addLineFromGroup(connection_dict.widget, connection_id)
  786. port_in_parent.addLineFromGroup(connection_dict.widget, connection_id)
  787. canvas.last_z_value += 1
  788. port_out_parent.setZValue(canvas.last_z_value)
  789. port_in_parent.setZValue(canvas.last_z_value)
  790. canvas.last_z_value += 1
  791. connection_dict.widget.setZValue(canvas.last_z_value)
  792. canvas.connection_list.append(connection_dict)
  793. if options.eyecandy == EYECANDY_FULL:
  794. item = connection_dict.widget
  795. return CanvasItemFX(item, True, False)
  796. QTimer.singleShot(0, canvas.scene.update)
  797. def disconnectPorts(connection_id):
  798. if canvas.debug:
  799. print("PatchCanvas::disconnectPorts(%i)" % connection_id)
  800. line = None
  801. item1 = None
  802. item2 = None
  803. group1id = port1id = 0
  804. group2id = port2id = 0
  805. for connection in canvas.connection_list:
  806. if connection.connection_id == connection_id:
  807. group1id = connection.group_out_id
  808. group2id = connection.group_in_id
  809. port1id = connection.port_out_id
  810. port2id = connection.port_in_id
  811. line = connection.widget
  812. canvas.connection_list.remove(connection)
  813. break
  814. if not line:
  815. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find connection ports" % connection_id)
  816. return
  817. for port in canvas.port_list:
  818. if port.group_id == group1id and port.port_id == port1id:
  819. item1 = port.widget
  820. break
  821. if not item1:
  822. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find output port" % connection_id)
  823. return
  824. for port in canvas.port_list:
  825. if port.group_id == group2id and port.port_id == port2id:
  826. item2 = port.widget
  827. break
  828. if not item2:
  829. qCritical("PatchCanvas::disconnectPorts(%i) - unable to find input port" % connection_id)
  830. return
  831. item1.parentItem().removeLineFromGroup(connection_id)
  832. item2.parentItem().removeLineFromGroup(connection_id)
  833. if options.eyecandy == EYECANDY_FULL:
  834. return CanvasItemFX(line, False, True)
  835. canvas.scene.removeItem(line)
  836. del line
  837. QTimer.singleShot(0, canvas.scene.update)
  838. def arrange():
  839. if canvas.debug:
  840. print("PatchCanvas::arrange()")
  841. def updateZValues():
  842. if canvas.debug:
  843. print("PatchCanvas::updateZValues()")
  844. for group in canvas.group_list:
  845. group.widgets[0].resetLinesZValue()
  846. if group.split and group.widgets[1]:
  847. group.widgets[1].resetLinesZValue()
  848. def handlePluginRemoved(plugin_id):
  849. if canvas.debug:
  850. print("PatchCanvas::handlePluginRemoved(%i)" % plugin_id)
  851. for group in canvas.group_list:
  852. if group.plugin_id < plugin_id or group.plugin_id > MAX_PLUGIN_ID_ALLOWED:
  853. continue
  854. group.plugin_id -= 1
  855. group.widgets[0].m_plugin_id -= 1
  856. if group.split and group.widgets[1]:
  857. group.widgets[1].m_plugin_id -= 1
  858. def handleAllPluginsRemoved():
  859. if canvas.debug:
  860. print("PatchCanvas::handleAllPluginsRemoved()")
  861. for group in canvas.group_list:
  862. if group.plugin_id > MAX_PLUGIN_ID_ALLOWED:
  863. continue
  864. group.plugin_id = -1
  865. group.plugin_ui = False
  866. group.widgets[0].m_plugin_id = -1
  867. group.widgets[0].m_plugin_ui = False
  868. if group.split and group.widgets[1]:
  869. group.widgets[1].m_plugin_id = -1
  870. group.widgets[1].m_plugin_ui = False
  871. # Extra Internal functions
  872. def CanvasGetNewGroupPos(horizontal):
  873. if canvas.debug:
  874. print("PatchCanvas::CanvasGetNewGroupPos(%s)" % bool2str(horizontal))
  875. new_pos = QPointF(canvas.initial_pos.x(), canvas.initial_pos.y())
  876. items = canvas.scene.items()
  877. break_loop = False
  878. while not break_loop:
  879. break_for = False
  880. for i in range(len(items)):
  881. item = items[i]
  882. if item and item.type() == CanvasBoxType:
  883. if item.sceneBoundingRect().contains(new_pos):
  884. if horizontal:
  885. new_pos += QPointF(item.boundingRect().width() + 15, 0)
  886. else:
  887. new_pos += QPointF(0, item.boundingRect().height() + 15)
  888. break_for = True
  889. break
  890. if i >= len(items) - 1 and not break_for:
  891. break_loop = True
  892. return new_pos
  893. def CanvasGetFullPortName(group_id, port_id):
  894. if canvas.debug:
  895. print("PatchCanvas::CanvasGetFullPortName(%i, %i)" % (group_id, port_id))
  896. for port in canvas.port_list:
  897. if port.group_id == group_id and port.port_id == port_id:
  898. group_id = port.group_id
  899. for group in canvas.group_list:
  900. if group.group_id == group_id:
  901. return group.group_name + ":" + port.port_name
  902. break
  903. qCritical("PatchCanvas::CanvasGetFullPortName(%i, %i) - unable to find port" % (group_id, port_id))
  904. return ""
  905. def CanvasGetPortConnectionList(group_id, port_id):
  906. if canvas.debug:
  907. print("PatchCanvas::CanvasGetPortConnectionList(%i, %i)" % (group_id, port_id))
  908. conn_list = []
  909. for connection in canvas.connection_list:
  910. if connection.group_out_id == group_id and connection.port_out_id == port_id:
  911. conn_list.append((connection.connection_id, connection.group_in_id, connection.port_in_id))
  912. elif connection.group_in_id == group_id and connection.port_in_id == port_id:
  913. conn_list.append((connection.connection_id, connection.group_out_id, connection.port_out_id))
  914. return conn_list
  915. def CanvasCallback(action, value1, value2, value_str):
  916. if canvas.debug:
  917. print("PatchCanvas::CanvasCallback(%i, %i, %i, %s)" % (action, value1, value2, value_str.encode()))
  918. canvas.callback(action, value1, value2, value_str)
  919. def CanvasItemFX(item, show, destroy):
  920. if canvas.debug:
  921. print("PatchCanvas::CanvasItemFX(%s, %s, %s)" % (item, bool2str(show), bool2str(destroy)))
  922. # Check if the item already has an animation
  923. for animation in canvas.animation_list:
  924. if animation.item() == item:
  925. animation.forceStop()
  926. canvas.animation_list.remove(animation)
  927. del animation
  928. break
  929. animation = CanvasFadeAnimation(item, show)
  930. animation.setDuration(750 if show else 500)
  931. if show:
  932. animation.finished.connect(canvas.qobject.AnimationFinishedShow)
  933. else:
  934. if destroy:
  935. animation.finished.connect(canvas.qobject.AnimationFinishedDestroy)
  936. else:
  937. animation.finished.connect(canvas.qobject.AnimationFinishedHide)
  938. canvas.animation_list.append(animation)
  939. animation.start()
  940. def CanvasRemoveItemFX(item):
  941. if canvas.debug:
  942. print("PatchCanvas::CanvasRemoveItemFX(%s)" % item)
  943. if item.type() == CanvasBoxType:
  944. item.removeIconFromScene()
  945. canvas.scene.removeItem(item)
  946. del item
  947. QTimer.singleShot(0, canvas.scene.update)
  948. # ------------------------------------------------------------------------------
  949. # patchscene.cpp
  950. class PatchScene(QGraphicsScene):
  951. scaleChanged = pyqtSignal(float)
  952. sceneGroupMoved = pyqtSignal(int, int, QPointF)
  953. pluginSelected = pyqtSignal(list)
  954. def __init__(self, parent, view):
  955. QGraphicsScene.__init__(self, parent)
  956. self.m_ctrl_down = False
  957. self.m_mouse_down_init = False
  958. self.m_mouse_rubberband = False
  959. self.addRubberBand()
  960. self.m_view = view
  961. if not self.m_view:
  962. qFatal("PatchCanvas::PatchScene() - invalid view")
  963. self.selectionChanged.connect(self.slot_selectionChanged)
  964. def addRubberBand(self):
  965. self.m_rubberband = self.addRect(QRectF(0, 0, 0, 0))
  966. self.m_rubberband.setZValue(-1)
  967. self.m_rubberband.hide()
  968. self.m_rubberband_selection = False
  969. self.m_rubberband_orig_point = QPointF(0, 0)
  970. def clear(self):
  971. QGraphicsScene.clear(self)
  972. # Re-add rubberband, that just got deleted
  973. self.addRubberBand()
  974. def fixScaleFactor(self):
  975. scale = self.m_view.transform().m11()
  976. if scale > 3.0:
  977. self.m_view.resetTransform()
  978. self.m_view.scale(3.0, 3.0)
  979. elif scale < 0.2:
  980. self.m_view.resetTransform()
  981. self.m_view.scale(0.2, 0.2)
  982. self.scaleChanged.emit(self.m_view.transform().m11())
  983. def updateTheme(self):
  984. self.setBackgroundBrush(canvas.theme.canvas_bg)
  985. self.m_rubberband.setPen(canvas.theme.rubberband_pen)
  986. self.m_rubberband.setBrush(canvas.theme.rubberband_brush)
  987. def zoom_fit(self):
  988. min_x = min_y = max_x = max_y = None
  989. first_value = True
  990. items_list = self.items()
  991. if len(items_list) > 0:
  992. for item in items_list:
  993. if item and item.isVisible() and item.type() == CanvasBoxType:
  994. pos = item.scenePos()
  995. rect = item.boundingRect()
  996. if first_value:
  997. min_x = pos.x()
  998. elif pos.x() < min_x:
  999. min_x = pos.x()
  1000. if first_value:
  1001. min_y = pos.y()
  1002. elif pos.y() < min_y:
  1003. min_y = pos.y()
  1004. if first_value:
  1005. max_x = pos.x() + rect.width()
  1006. elif pos.x() + rect.width() > max_x:
  1007. max_x = pos.x() + rect.width()
  1008. if first_value:
  1009. max_y = pos.y() + rect.height()
  1010. elif pos.y() + rect.height() > max_y:
  1011. max_y = pos.y() + rect.height()
  1012. first_value = False
  1013. if not first_value:
  1014. self.m_view.fitInView(min_x, min_y, abs(max_x - min_x), abs(max_y - min_y), Qt.KeepAspectRatio)
  1015. self.fixScaleFactor()
  1016. def zoom_in(self):
  1017. if self.m_view.transform().m11() < 3.0:
  1018. self.m_view.scale(1.2, 1.2)
  1019. self.scaleChanged.emit(self.m_view.transform().m11())
  1020. def zoom_out(self):
  1021. if self.m_view.transform().m11() > 0.2:
  1022. self.m_view.scale(0.8, 0.8)
  1023. self.scaleChanged.emit(self.m_view.transform().m11())
  1024. def zoom_reset(self):
  1025. self.m_view.resetTransform()
  1026. self.scaleChanged.emit(1.0)
  1027. @pyqtSlot()
  1028. def slot_selectionChanged(self):
  1029. items_list = self.selectedItems()
  1030. if len(items_list) == 0:
  1031. self.pluginSelected.emit([])
  1032. return
  1033. plugin_list = []
  1034. for item in items_list:
  1035. if item and item.isVisible():
  1036. group_item = None
  1037. if item.type() == CanvasBoxType:
  1038. group_item = item
  1039. elif item.type() == CanvasPortType:
  1040. group_item = item.parentItem()
  1041. #elif item.type() in (CanvasLineType, CanvasBezierLineType, CanvasLineMovType, CanvasBezierLineMovType):
  1042. #plugin_list = []
  1043. #break
  1044. if group_item is not None and group_item.m_plugin_id >= 0:
  1045. plugin_id = group_item.m_plugin_id
  1046. if plugin_id > MAX_PLUGIN_ID_ALLOWED:
  1047. plugin_id = 0
  1048. plugin_list.append(plugin_id)
  1049. self.pluginSelected.emit(plugin_list)
  1050. def keyPressEvent(self, event):
  1051. if not self.m_view:
  1052. return event.ignore()
  1053. if event.key() == Qt.Key_Control:
  1054. self.m_ctrl_down = True
  1055. elif event.key() == Qt.Key_Home:
  1056. self.zoom_fit()
  1057. return event.accept()
  1058. elif self.m_ctrl_down:
  1059. if event.key() == Qt.Key_Plus:
  1060. self.zoom_in()
  1061. return event.accept()
  1062. elif event.key() == Qt.Key_Minus:
  1063. self.zoom_out()
  1064. return event.accept()
  1065. elif event.key() == Qt.Key_1:
  1066. self.zoom_reset()
  1067. return event.accept()
  1068. QGraphicsScene.keyPressEvent(self, event)
  1069. def keyReleaseEvent(self, event):
  1070. if event.key() == Qt.Key_Control:
  1071. self.m_ctrl_down = False
  1072. QGraphicsScene.keyReleaseEvent(self, event)
  1073. def mousePressEvent(self, event):
  1074. self.m_mouse_down_init = bool(event.button() == Qt.LeftButton)
  1075. self.m_mouse_rubberband = False
  1076. QGraphicsScene.mousePressEvent(self, event)
  1077. def mouseMoveEvent(self, event):
  1078. if self.m_mouse_down_init:
  1079. self.m_mouse_down_init = False
  1080. self.m_mouse_rubberband = bool(len(self.selectedItems()) == 0)
  1081. if self.m_mouse_rubberband:
  1082. if not self.m_rubberband_selection:
  1083. self.m_rubberband.show()
  1084. self.m_rubberband_selection = True
  1085. self.m_rubberband_orig_point = event.scenePos()
  1086. pos = event.scenePos()
  1087. if pos.x() > self.m_rubberband_orig_point.x():
  1088. x = self.m_rubberband_orig_point.x()
  1089. else:
  1090. x = pos.x()
  1091. if pos.y() > self.m_rubberband_orig_point.y():
  1092. y = self.m_rubberband_orig_point.y()
  1093. else:
  1094. y = pos.y()
  1095. self.m_rubberband.setRect(x, y, abs(pos.x() - self.m_rubberband_orig_point.x()), abs(pos.y() - self.m_rubberband_orig_point.y()))
  1096. return event.accept()
  1097. QGraphicsScene.mouseMoveEvent(self, event)
  1098. def mouseReleaseEvent(self, event):
  1099. if self.m_rubberband_selection:
  1100. items_list = self.items()
  1101. if len(items_list) > 0:
  1102. for item in items_list:
  1103. if item and item.isVisible() and item.type() == CanvasBoxType:
  1104. item_rect = item.sceneBoundingRect()
  1105. item_top_left = QPointF(item_rect.x(), item_rect.y())
  1106. item_bottom_right = QPointF(item_rect.x() + item_rect.width(), item_rect.y() + item_rect.height())
  1107. if self.m_rubberband.contains(item_top_left) and self.m_rubberband.contains(item_bottom_right):
  1108. item.setSelected(True)
  1109. self.m_rubberband.hide()
  1110. self.m_rubberband.setRect(0, 0, 0, 0)
  1111. self.m_rubberband_selection = False
  1112. else:
  1113. items_list = self.selectedItems()
  1114. for item in items_list:
  1115. if item and item.isVisible() and item.type() == CanvasBoxType:
  1116. item.checkItemPos()
  1117. self.sceneGroupMoved.emit(item.getGroupId(), item.getSplittedMode(), item.scenePos())
  1118. if len(items_list) > 1:
  1119. canvas.scene.update()
  1120. self.m_mouse_down_init = False
  1121. self.m_mouse_rubberband = False
  1122. QGraphicsScene.mouseReleaseEvent(self, event)
  1123. def wheelEvent(self, event):
  1124. if not self.m_view:
  1125. return event.ignore()
  1126. if self.m_ctrl_down:
  1127. factor = 1.41 ** (event.delta() / 240.0)
  1128. self.m_view.scale(factor, factor)
  1129. self.fixScaleFactor()
  1130. return event.accept()
  1131. QGraphicsScene.wheelEvent(self, event)
  1132. def contextMenuEvent(self, event):
  1133. if len(self.selectedItems()) == 0:
  1134. event.accept()
  1135. canvas.callback(ACTION_BG_RIGHT_CLICK, 0, 0, "")
  1136. else:
  1137. QGraphicsScene.contextMenuEvent(self, event)
  1138. # ------------------------------------------------------------------------------
  1139. # canvasfadeanimation.cpp
  1140. class CanvasFadeAnimation(QAbstractAnimation):
  1141. def __init__(self, item, show):
  1142. QAbstractAnimation.__init__(self)
  1143. self.m_show = show
  1144. self.m_duration = 0
  1145. self.m_item = item
  1146. def item(self):
  1147. return self.m_item
  1148. def forceStop(self):
  1149. self.blockSignals(True)
  1150. self.stop()
  1151. def setDuration(self, time):
  1152. if self.m_item.opacity() == 0 and not self.m_show:
  1153. self._duration = 0
  1154. else:
  1155. self.m_item.show()
  1156. self.m_duration = time
  1157. def duration(self):
  1158. return self.m_duration
  1159. def updateCurrentTime(self, time):
  1160. if self.m_duration == 0:
  1161. return
  1162. if self.m_show:
  1163. value = float(time) / self.m_duration
  1164. else:
  1165. value = 1.0 - (float(time) / self.m_duration)
  1166. try:
  1167. self.m_item.setOpacity(value)
  1168. except:
  1169. print("Error: failed to animate canvas item, already destroyed?")
  1170. self.forceStop()
  1171. canvas.animation_list.remove(self)
  1172. return
  1173. if self.m_item.type() == CanvasBoxType:
  1174. self.m_item.setShadowOpacity(value)
  1175. def updateDirection(self, direction):
  1176. pass
  1177. def updateState(self, oldState, newState):
  1178. pass
  1179. # ------------------------------------------------------------------------------
  1180. # canvasline.cpp
  1181. class CanvasLine(QGraphicsLineItem):
  1182. def __init__(self, item1, item2, parent):
  1183. QGraphicsLineItem.__init__(self, parent)
  1184. self.item1 = item1
  1185. self.item2 = item2
  1186. self.m_locked = False
  1187. self.m_lineSelected = False
  1188. self.setGraphicsEffect(None)
  1189. self.updateLinePos()
  1190. def isLocked(self):
  1191. return self.m_locked
  1192. def setLocked(self, yesno):
  1193. self.m_locked = yesno
  1194. def isLineSelected(self):
  1195. return self.m_lineSelected
  1196. def setLineSelected(self, yesno):
  1197. if self.m_locked:
  1198. return
  1199. if options.eyecandy == EYECANDY_FULL:
  1200. if yesno:
  1201. self.setGraphicsEffect(CanvasPortGlow(self.item1.getPortType(), self.toGraphicsObject()))
  1202. else:
  1203. self.setGraphicsEffect(None)
  1204. self.m_lineSelected = yesno
  1205. self.updateLineGradient()
  1206. def updateLinePos(self):
  1207. if self.item1.getPortMode() == PORT_MODE_OUTPUT:
  1208. line = QLineF(self.item1.scenePos().x() + self.item1.getPortWidth() + 12,
  1209. self.item1.scenePos().y() + float(canvas.theme.port_height)/2,
  1210. self.item2.scenePos().x(),
  1211. self.item2.scenePos().y() + float(canvas.theme.port_height)/2)
  1212. self.setLine(line)
  1213. self.m_lineSelected = False
  1214. self.updateLineGradient()
  1215. def type(self):
  1216. return CanvasLineType
  1217. def updateLineGradient(self):
  1218. pos_top = self.boundingRect().top()
  1219. pos_bot = self.boundingRect().bottom()
  1220. if self.item2.scenePos().y() >= self.item1.scenePos().y():
  1221. pos1 = 0
  1222. pos2 = 1
  1223. else:
  1224. pos1 = 1
  1225. pos2 = 0
  1226. port_type1 = self.item1.getPortType()
  1227. port_type2 = self.item2.getPortType()
  1228. port_gradient = QLinearGradient(0, pos_top, 0, pos_bot)
  1229. if port_type1 == PORT_TYPE_AUDIO_JACK:
  1230. port_gradient.setColorAt(pos1, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
  1231. elif port_type1 == PORT_TYPE_MIDI_JACK:
  1232. port_gradient.setColorAt(pos1, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
  1233. elif port_type1 == PORT_TYPE_MIDI_ALSA:
  1234. port_gradient.setColorAt(pos1, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
  1235. elif port_type1 == PORT_TYPE_PARAMETER:
  1236. port_gradient.setColorAt(pos1, canvas.theme.line_parameter_sel if self.m_lineSelected else canvas.theme.line_parameter)
  1237. if port_type2 == PORT_TYPE_AUDIO_JACK:
  1238. port_gradient.setColorAt(pos2, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
  1239. elif port_type2 == PORT_TYPE_MIDI_JACK:
  1240. port_gradient.setColorAt(pos2, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
  1241. elif port_type2 == PORT_TYPE_MIDI_ALSA:
  1242. port_gradient.setColorAt(pos2, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
  1243. elif port_type2 == PORT_TYPE_PARAMETER:
  1244. port_gradient.setColorAt(pos2, canvas.theme.line_parameter_sel if self.m_lineSelected else canvas.theme.line_parameter)
  1245. self.setPen(QPen(port_gradient, 2))
  1246. def paint(self, painter, option, widget):
  1247. painter.save()
  1248. painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
  1249. QGraphicsLineItem.paint(self, painter, option, widget)
  1250. painter.restore()
  1251. # ------------------------------------------------------------------------------
  1252. # canvasbezierline.cpp
  1253. class CanvasBezierLine(QGraphicsPathItem):
  1254. def __init__(self, item1, item2, parent):
  1255. QGraphicsPathItem.__init__(self, parent)
  1256. self.item1 = item1
  1257. self.item2 = item2
  1258. self.m_locked = False
  1259. self.m_lineSelected = False
  1260. self.setBrush(QColor(0, 0, 0, 0))
  1261. self.setGraphicsEffect(None)
  1262. self.updateLinePos()
  1263. def isLocked(self):
  1264. return self.m_locked
  1265. def setLocked(self, yesno):
  1266. self.m_locked = yesno
  1267. def isLineSelected(self):
  1268. return self.m_lineSelected
  1269. def setLineSelected(self, yesno):
  1270. if self.m_locked:
  1271. return
  1272. if options.eyecandy == EYECANDY_FULL:
  1273. if yesno:
  1274. self.setGraphicsEffect(CanvasPortGlow(self.item1.getPortType(), self.toGraphicsObject()))
  1275. else:
  1276. self.setGraphicsEffect(None)
  1277. self.m_lineSelected = yesno
  1278. self.updateLineGradient()
  1279. def updateLinePos(self):
  1280. if self.item1.getPortMode() == PORT_MODE_OUTPUT:
  1281. item1_x = self.item1.scenePos().x() + self.item1.getPortWidth() + 12
  1282. item1_y = self.item1.scenePos().y() + float(canvas.theme.port_height)/2
  1283. item2_x = self.item2.scenePos().x()
  1284. item2_y = self.item2.scenePos().y() + float(canvas.theme.port_height)/2
  1285. item1_mid_x = abs(item1_x - item2_x) / 2
  1286. item1_new_x = item1_x + item1_mid_x
  1287. item2_mid_x = abs(item1_x - item2_x) / 2
  1288. item2_new_x = item2_x - item2_mid_x
  1289. path = QPainterPath(QPointF(item1_x, item1_y))
  1290. path.cubicTo(item1_new_x, item1_y, item2_new_x, item2_y, item2_x, item2_y)
  1291. self.setPath(path)
  1292. self.m_lineSelected = False
  1293. self.updateLineGradient()
  1294. def type(self):
  1295. return CanvasBezierLineType
  1296. def updateLineGradient(self):
  1297. pos_top = self.boundingRect().top()
  1298. pos_bot = self.boundingRect().bottom()
  1299. if self.item2.scenePos().y() >= self.item1.scenePos().y():
  1300. pos1 = 0
  1301. pos2 = 1
  1302. else:
  1303. pos1 = 1
  1304. pos2 = 0
  1305. port_type1 = self.item1.getPortType()
  1306. port_type2 = self.item2.getPortType()
  1307. port_gradient = QLinearGradient(0, pos_top, 0, pos_bot)
  1308. if port_type1 == PORT_TYPE_AUDIO_JACK:
  1309. port_gradient.setColorAt(pos1, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
  1310. elif port_type1 == PORT_TYPE_MIDI_JACK:
  1311. port_gradient.setColorAt(pos1, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
  1312. elif port_type1 == PORT_TYPE_MIDI_ALSA:
  1313. port_gradient.setColorAt(pos1, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
  1314. elif port_type1 == PORT_TYPE_PARAMETER:
  1315. port_gradient.setColorAt(pos1, canvas.theme.line_parameter_sel if self.m_lineSelected else canvas.theme.line_parameter)
  1316. if port_type2 == PORT_TYPE_AUDIO_JACK:
  1317. port_gradient.setColorAt(pos2, canvas.theme.line_audio_jack_sel if self.m_lineSelected else canvas.theme.line_audio_jack)
  1318. elif port_type2 == PORT_TYPE_MIDI_JACK:
  1319. port_gradient.setColorAt(pos2, canvas.theme.line_midi_jack_sel if self.m_lineSelected else canvas.theme.line_midi_jack)
  1320. elif port_type2 == PORT_TYPE_MIDI_ALSA:
  1321. port_gradient.setColorAt(pos2, canvas.theme.line_midi_alsa_sel if self.m_lineSelected else canvas.theme.line_midi_alsa)
  1322. elif port_type2 == PORT_TYPE_PARAMETER:
  1323. port_gradient.setColorAt(pos2, canvas.theme.line_parameter_sel if self.m_lineSelected else canvas.theme.line_parameter)
  1324. self.setPen(QPen(port_gradient, 2))
  1325. def paint(self, painter, option, widget):
  1326. painter.save()
  1327. painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
  1328. QGraphicsPathItem.paint(self, painter, option, widget)
  1329. painter.restore()
  1330. # ------------------------------------------------------------------------------
  1331. # canvaslivemov.cpp
  1332. class CanvasLineMov(QGraphicsLineItem):
  1333. def __init__(self, port_mode, port_type, parent):
  1334. QGraphicsLineItem.__init__(self, parent)
  1335. self.m_port_mode = port_mode
  1336. self.m_port_type = port_type
  1337. # Port position doesn't change while moving around line
  1338. self.p_lineX = self.scenePos().x()
  1339. self.p_lineY = self.scenePos().y()
  1340. self.p_width = self.parentItem().getPortWidth()
  1341. if port_type == PORT_TYPE_AUDIO_JACK:
  1342. pen = QPen(canvas.theme.line_audio_jack, 2)
  1343. elif port_type == PORT_TYPE_MIDI_JACK:
  1344. pen = QPen(canvas.theme.line_midi_jack, 2)
  1345. elif port_type == PORT_TYPE_MIDI_ALSA:
  1346. pen = QPen(canvas.theme.line_midi_alsa, 2)
  1347. elif port_type == PORT_TYPE_PARAMETER:
  1348. pen = QPen(canvas.theme.line_parameter, 2)
  1349. else:
  1350. qWarning("PatchCanvas::CanvasLineMov(%s, %s, %s) - invalid port type" % (port_mode2str(port_mode), port_type2str(port_type), parent))
  1351. pen = QPen(Qt.black)
  1352. self.setPen(pen)
  1353. def updateLinePos(self, scenePos):
  1354. item_pos = [0, 0]
  1355. if self.m_port_mode == PORT_MODE_INPUT:
  1356. item_pos[0] = 0
  1357. item_pos[1] = float(canvas.theme.port_height)/2
  1358. elif self.m_port_mode == PORT_MODE_OUTPUT:
  1359. item_pos[0] = self.p_width + 12
  1360. item_pos[1] = float(canvas.theme.port_height)/2
  1361. else:
  1362. return
  1363. line = QLineF(item_pos[0], item_pos[1], scenePos.x() - self.p_lineX, scenePos.y() - self.p_lineY)
  1364. self.setLine(line)
  1365. def type(self):
  1366. return CanvasLineMovType
  1367. def paint(self, painter, option, widget):
  1368. painter.save()
  1369. painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
  1370. QGraphicsLineItem.paint(self, painter, option, widget)
  1371. painter.restore()
  1372. # ------------------------------------------------------------------------------
  1373. # canvasbezierlinemov.cpp
  1374. class CanvasBezierLineMov(QGraphicsPathItem):
  1375. def __init__(self, port_mode, port_type, parent):
  1376. QGraphicsPathItem.__init__(self, parent)
  1377. self.m_port_mode = port_mode
  1378. self.m_port_type = port_type
  1379. # Port position doesn't change while moving around line
  1380. self.p_itemX = self.scenePos().x()
  1381. self.p_itemY = self.scenePos().y()
  1382. self.p_width = self.parentItem().getPortWidth()
  1383. if port_type == PORT_TYPE_AUDIO_JACK:
  1384. pen = QPen(canvas.theme.line_audio_jack, 2)
  1385. elif port_type == PORT_TYPE_MIDI_JACK:
  1386. pen = QPen(canvas.theme.line_midi_jack, 2)
  1387. elif port_type == PORT_TYPE_MIDI_ALSA:
  1388. pen = QPen(canvas.theme.line_midi_alsa, 2)
  1389. elif port_type == PORT_TYPE_PARAMETER:
  1390. pen = QPen(canvas.theme.line_parameter, 2)
  1391. else:
  1392. qWarning("PatchCanvas::CanvasBezierLineMov(%s, %s, %s) - invalid port type" % (port_mode2str(port_mode), port_type2str(port_type), parent))
  1393. pen = QPen(Qt.black)
  1394. self.setBrush(QColor(0, 0, 0, 0))
  1395. self.setPen(pen)
  1396. def updateLinePos(self, scenePos):
  1397. if self.m_port_mode == PORT_MODE_INPUT:
  1398. old_x = 0
  1399. old_y = float(canvas.theme.port_height)/2
  1400. mid_x = abs(scenePos.x() - self.p_itemX) / 2
  1401. new_x = old_x - mid_x
  1402. elif self.m_port_mode == PORT_MODE_OUTPUT:
  1403. old_x = self.p_width + 12
  1404. old_y = float(canvas.theme.port_height)/2
  1405. mid_x = abs(scenePos.x() - (self.p_itemX + old_x)) / 2
  1406. new_x = old_x + mid_x
  1407. else:
  1408. return
  1409. final_x = scenePos.x() - self.p_itemX
  1410. final_y = scenePos.y() - self.p_itemY
  1411. path = QPainterPath(QPointF(old_x, old_y))
  1412. path.cubicTo(new_x, old_y, new_x, final_y, final_x, final_y)
  1413. self.setPath(path)
  1414. def type(self):
  1415. return CanvasBezierLineMovType
  1416. def paint(self, painter, option, widget):
  1417. painter.save()
  1418. painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing))
  1419. QGraphicsPathItem.paint(self, painter, option, widget)
  1420. painter.restore()
  1421. # ------------------------------------------------------------------------------
  1422. # canvasport.cpp
  1423. class CanvasPort(QGraphicsItem):
  1424. def __init__(self, group_id, port_id, port_name, port_mode, port_type, is_alternate, parent):
  1425. QGraphicsItem.__init__(self, parent)
  1426. # Save Variables, useful for later
  1427. self.m_group_id = group_id
  1428. self.m_port_id = port_id
  1429. self.m_port_mode = port_mode
  1430. self.m_port_type = port_type
  1431. self.m_port_name = port_name
  1432. self.m_is_alternate = is_alternate
  1433. # Base Variables
  1434. self.m_port_width = 15
  1435. self.m_port_height = canvas.theme.port_height
  1436. self.m_port_font = QFont()
  1437. self.m_port_font.setFamily(canvas.theme.port_font_name)
  1438. self.m_port_font.setPixelSize(canvas.theme.port_font_size)
  1439. self.m_port_font.setWeight(canvas.theme.port_font_state)
  1440. self.m_line_mov = None
  1441. self.m_hover_item = None
  1442. self.m_last_selected_state = False
  1443. self.m_mouse_down = False
  1444. self.m_cursor_moving = False
  1445. self.setFlags(QGraphicsItem.ItemIsSelectable)
  1446. if options.auto_select_items:
  1447. self.setAcceptHoverEvents(True)
  1448. def getGroupId(self):
  1449. return self.m_group_id
  1450. def getPortId(self):
  1451. return self.m_port_id
  1452. def getPortMode(self):
  1453. return self.m_port_mode
  1454. def getPortType(self):
  1455. return self.m_port_type
  1456. def getPortName(self):
  1457. return self.m_port_name
  1458. def getFullPortName(self):
  1459. return self.parentItem().getGroupName() + ":" + self.m_port_name
  1460. def getPortWidth(self):
  1461. return self.m_port_width
  1462. def getPortHeight(self):
  1463. return self.m_port_height
  1464. def setPortMode(self, port_mode):
  1465. self.m_port_mode = port_mode
  1466. self.update()
  1467. def setPortType(self, port_type):
  1468. self.m_port_type = port_type
  1469. self.update()
  1470. def setPortName(self, port_name):
  1471. if QFontMetrics(self.m_port_font).width(port_name) < QFontMetrics(self.m_port_font).width(self.m_port_name):
  1472. QTimer.singleShot(0, canvas.scene.update)
  1473. self.m_port_name = port_name
  1474. self.update()
  1475. def setPortWidth(self, port_width):
  1476. if port_width < self.m_port_width:
  1477. QTimer.singleShot(0, canvas.scene.update)
  1478. self.m_port_width = port_width
  1479. self.update()
  1480. def type(self):
  1481. return CanvasPortType
  1482. def hoverEnterEvent(self, event):
  1483. if options.auto_select_items:
  1484. self.setSelected(True)
  1485. QGraphicsItem.hoverEnterEvent(self, event)
  1486. def hoverLeaveEvent(self, event):
  1487. if options.auto_select_items:
  1488. self.setSelected(False)
  1489. QGraphicsItem.hoverLeaveEvent(self, event)
  1490. def mousePressEvent(self, event):
  1491. self.m_hover_item = None
  1492. self.m_mouse_down = bool(event.button() == Qt.LeftButton)
  1493. self.m_cursor_moving = False
  1494. QGraphicsItem.mousePressEvent(self, event)
  1495. def mouseMoveEvent(self, event):
  1496. if self.m_mouse_down:
  1497. if not self.m_cursor_moving:
  1498. self.setCursor(QCursor(Qt.CrossCursor))
  1499. self.m_cursor_moving = True
  1500. for connection in canvas.connection_list:
  1501. if ((connection.group_out_id == self.m_group_id and connection.port_out_id == self.m_port_id) or
  1502. (connection.group_in_id == self.m_group_id and connection.port_in_id == self.m_port_id)):
  1503. connection.widget.setLocked(True)
  1504. if not self.m_line_mov:
  1505. if options.use_bezier_lines:
  1506. self.m_line_mov = CanvasBezierLineMov(self.m_port_mode, self.m_port_type, self)
  1507. else:
  1508. self.m_line_mov = CanvasLineMov(self.m_port_mode, self.m_port_type, self)
  1509. canvas.last_z_value += 1
  1510. self.m_line_mov.setZValue(canvas.last_z_value)
  1511. canvas.last_z_value += 1
  1512. self.parentItem().setZValue(canvas.last_z_value)
  1513. item = None
  1514. items = canvas.scene.items(event.scenePos(), Qt.ContainsItemShape, Qt.AscendingOrder)
  1515. for i in range(len(items)):
  1516. if items[i].type() == CanvasPortType:
  1517. if items[i] != self:
  1518. if not item:
  1519. item = items[i]
  1520. elif items[i].parentItem().zValue() > item.parentItem().zValue():
  1521. item = items[i]
  1522. if self.m_hover_item and self.m_hover_item != item:
  1523. self.m_hover_item.setSelected(False)
  1524. if item:
  1525. if item.getPortMode() != self.m_port_mode and item.getPortType() == self.m_port_type:
  1526. item.setSelected(True)
  1527. self.m_hover_item = item
  1528. else:
  1529. self.m_hover_item = None
  1530. else:
  1531. self.m_hover_item = None
  1532. self.m_line_mov.updateLinePos(event.scenePos())
  1533. return event.accept()
  1534. QGraphicsItem.mouseMoveEvent(self, event)
  1535. def mouseReleaseEvent(self, event):
  1536. if self.m_mouse_down:
  1537. if self.m_line_mov is not None:
  1538. item = self.m_line_mov
  1539. self.m_line_mov = None
  1540. canvas.scene.removeItem(item)
  1541. del item
  1542. for connection in canvas.connection_list:
  1543. if ((connection.group_out_id == self.m_group_id and connection.port_out_id == self.m_port_id) or
  1544. (connection.group_in_id == self.m_group_id and connection.port_in_id == self.m_port_id)):
  1545. connection.widget.setLocked(False)
  1546. if self.m_hover_item:
  1547. # TODO: a better way to check already existing connection
  1548. for connection in canvas.connection_list:
  1549. hover_group_id = self.m_hover_item.getGroupId()
  1550. hover_port_id = self.m_hover_item.getPortId()
  1551. if (
  1552. (connection.group_out_id == self.m_group_id and connection.port_out_id == self.m_port_id and
  1553. connection.group_in_id == hover_group_id and connection.port_in_id == hover_port_id) or
  1554. (connection.group_out_id == hover_group_id and connection.port_out_id == hover_port_id and
  1555. connection.group_in_id == self.m_group_id and connection.port_in_id == self.m_port_id)
  1556. ):
  1557. canvas.callback(ACTION_PORTS_DISCONNECT, connection.connection_id, 0, "")
  1558. break
  1559. else:
  1560. if self.m_port_mode == PORT_MODE_OUTPUT:
  1561. conn = "%i:%i:%i:%i" % (self.m_group_id, self.m_port_id, self.m_hover_item.getGroupId(), self.m_hover_item.getPortId())
  1562. canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn)
  1563. else:
  1564. conn = "%i:%i:%i:%i" % (self.m_hover_item.getGroupId(), self.m_hover_item.getPortId(), self.m_group_id, self.m_port_id)
  1565. canvas.callback(ACTION_PORTS_CONNECT, 0, 0, conn)
  1566. canvas.scene.clearSelection()
  1567. if self.m_cursor_moving:
  1568. self.setCursor(QCursor(Qt.ArrowCursor))
  1569. self.m_hover_item = None
  1570. self.m_mouse_down = False
  1571. self.m_cursor_moving = False
  1572. QGraphicsItem.mouseReleaseEvent(self, event)
  1573. def contextMenuEvent(self, event):
  1574. canvas.scene.clearSelection()
  1575. self.setSelected(True)
  1576. menu = QMenu()
  1577. discMenu = QMenu("Disconnect", menu)
  1578. conn_list = CanvasGetPortConnectionList(self.m_group_id, self.m_port_id)
  1579. if len(conn_list) > 0:
  1580. for conn_id, group_id, port_id in conn_list:
  1581. act_x_disc = discMenu.addAction(CanvasGetFullPortName(group_id, port_id))
  1582. act_x_disc.setData(conn_id)
  1583. act_x_disc.triggered.connect(canvas.qobject.PortContextMenuDisconnect)
  1584. else:
  1585. act_x_disc = discMenu.addAction("No connections")
  1586. act_x_disc.setEnabled(False)
  1587. menu.addMenu(discMenu)
  1588. act_x_disc_all = menu.addAction("Disconnect &All")
  1589. act_x_sep_1 = menu.addSeparator()
  1590. act_x_info = menu.addAction("Get &Info")
  1591. act_x_rename = menu.addAction("&Rename")
  1592. if not features.port_info:
  1593. act_x_info.setVisible(False)
  1594. if not features.port_rename:
  1595. act_x_rename.setVisible(False)
  1596. if not (features.port_info and features.port_rename):
  1597. act_x_sep_1.setVisible(False)
  1598. act_selected = menu.exec_(event.screenPos())
  1599. if act_selected == act_x_disc_all:
  1600. for conn_id, group_id, port_id in conn_list:
  1601. canvas.callback(ACTION_PORTS_DISCONNECT, conn_id, 0, "")
  1602. elif act_selected == act_x_info:
  1603. canvas.callback(ACTION_PORT_INFO, self.m_group_id, self.m_port_id, "")
  1604. elif act_selected == act_x_rename:
  1605. canvas.callback(ACTION_PORT_RENAME, self.m_group_id, self.m_port_id, "")
  1606. event.accept()
  1607. def boundingRect(self):
  1608. return QRectF(0, 0, self.m_port_width + 12, self.m_port_height)
  1609. def paint(self, painter, option, widget):
  1610. painter.save()
  1611. painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL))
  1612. poly_locx = [0, 0, 0, 0, 0]
  1613. if self.m_port_mode == PORT_MODE_INPUT:
  1614. text_pos = QPointF(3, canvas.theme.port_text_ypos)
  1615. if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON:
  1616. poly_locx[0] = 0
  1617. poly_locx[1] = self.m_port_width + 5
  1618. poly_locx[2] = self.m_port_width + 12
  1619. poly_locx[3] = self.m_port_width + 5
  1620. poly_locx[4] = 0
  1621. elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE:
  1622. poly_locx[0] = 0
  1623. poly_locx[1] = self.m_port_width + 5
  1624. poly_locx[2] = self.m_port_width + 5
  1625. poly_locx[3] = self.m_port_width + 5
  1626. poly_locx[4] = 0
  1627. else:
  1628. qCritical("PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode)
  1629. return
  1630. elif self.m_port_mode == PORT_MODE_OUTPUT:
  1631. text_pos = QPointF(9, canvas.theme.port_text_ypos)
  1632. if canvas.theme.port_mode == Theme.THEME_PORT_POLYGON:
  1633. poly_locx[0] = self.m_port_width + 12
  1634. poly_locx[1] = 7
  1635. poly_locx[2] = 0
  1636. poly_locx[3] = 7
  1637. poly_locx[4] = self.m_port_width + 12
  1638. elif canvas.theme.port_mode == Theme.THEME_PORT_SQUARE:
  1639. poly_locx[0] = self.m_port_width + 12
  1640. poly_locx[1] = 5
  1641. poly_locx[2] = 5
  1642. poly_locx[3] = 5
  1643. poly_locx[4] = self.m_port_width + 12
  1644. else:
  1645. qCritical("PatchCanvas::CanvasPort.paint() - invalid theme port mode '%s'" % canvas.theme.port_mode)
  1646. return
  1647. else:
  1648. qCritical("PatchCanvas::CanvasPort.paint() - invalid port mode '%s'" % port_mode2str(self.m_port_mode))
  1649. return
  1650. if self.m_port_type == PORT_TYPE_AUDIO_JACK:
  1651. poly_color = canvas.theme.port_audio_jack_bg_sel if self.isSelected() else canvas.theme.port_audio_jack_bg
  1652. poly_pen = canvas.theme.port_audio_jack_pen_sel if self.isSelected() else canvas.theme.port_audio_jack_pen
  1653. text_pen = canvas.theme.port_audio_jack_text_sel if self.isSelected() else canvas.theme.port_audio_jack_text
  1654. conn_pen = canvas.theme.port_audio_jack_pen_sel
  1655. elif self.m_port_type == PORT_TYPE_MIDI_JACK:
  1656. poly_color = canvas.theme.port_midi_jack_bg_sel if self.isSelected() else canvas.theme.port_midi_jack_bg
  1657. poly_pen = canvas.theme.port_midi_jack_pen_sel if self.isSelected() else canvas.theme.port_midi_jack_pen
  1658. text_pen = canvas.theme.port_midi_jack_text_sel if self.isSelected() else canvas.theme.port_midi_jack_text
  1659. conn_pen = canvas.theme.port_midi_jack_pen_sel
  1660. elif self.m_port_type == PORT_TYPE_MIDI_ALSA:
  1661. poly_color = canvas.theme.port_midi_alsa_bg_sel if self.isSelected() else canvas.theme.port_midi_alsa_bg
  1662. poly_pen = canvas.theme.port_midi_alsa_pen_sel if self.isSelected() else canvas.theme.port_midi_alsa_pen
  1663. text_pen = canvas.theme.port_midi_alsa_text_sel if self.isSelected() else canvas.theme.port_midi_alsa_text
  1664. conn_pen = canvas.theme.port_midi_alsa_pen_sel
  1665. elif self.m_port_type == PORT_TYPE_PARAMETER:
  1666. poly_color = canvas.theme.port_parameter_bg_sel if self.isSelected() else canvas.theme.port_parameter_bg
  1667. poly_pen = canvas.theme.port_parameter_pen_sel if self.isSelected() else canvas.theme.port_parameter_pen
  1668. text_pen = canvas.theme.port_parameter_text_sel if self.isSelected() else canvas.theme.port_parameter_text
  1669. conn_pen = canvas.theme.port_parameter_pen_sel
  1670. else:
  1671. qCritical("PatchCanvas::CanvasPort.paint() - invalid port type '%s'" % port_type2str(self.m_port_type))
  1672. return
  1673. if self.m_is_alternate:
  1674. poly_color = poly_color.darker(180)
  1675. #poly_pen.setColor(poly_pen.color().darker(110))
  1676. #text_pen.setColor(text_pen.color()) #.darker(150))
  1677. #conn_pen.setColor(conn_pen.color()) #.darker(150))
  1678. polygon = QPolygonF()
  1679. polygon += QPointF(poly_locx[0], 0)
  1680. polygon += QPointF(poly_locx[1], 0)
  1681. polygon += QPointF(poly_locx[2], float(canvas.theme.port_height)/2)
  1682. polygon += QPointF(poly_locx[3], canvas.theme.port_height)
  1683. polygon += QPointF(poly_locx[4], canvas.theme.port_height)
  1684. if canvas.theme.port_bg_pixmap:
  1685. portRect = polygon.boundingRect()
  1686. portPos = portRect.topLeft()
  1687. painter.drawTiledPixmap(portRect, canvas.theme.port_bg_pixmap, portPos)
  1688. else:
  1689. painter.setBrush(poly_color) #.lighter(200))
  1690. painter.setPen(poly_pen)
  1691. painter.drawPolygon(polygon)
  1692. painter.setPen(text_pen)
  1693. painter.setFont(self.m_port_font)
  1694. painter.drawText(text_pos, self.m_port_name)
  1695. if self.isSelected() != self.m_last_selected_state:
  1696. for connection in canvas.connection_list:
  1697. if ((connection.group_out_id == self.m_group_id and connection.port_out_id == self.m_port_id) or
  1698. (connection.group_in_id == self.m_group_id and connection.port_in_id == self.m_port_id)):
  1699. connection.widget.setLineSelected(self.isSelected())
  1700. if canvas.theme.idx == Theme.THEME_OOSTUDIO and canvas.theme.port_bg_pixmap:
  1701. painter.setPen(Qt.NoPen)
  1702. painter.setBrush(conn_pen.brush())
  1703. if self.m_port_mode == PORT_MODE_INPUT:
  1704. connRect = QRectF(portRect.topLeft(), QSizeF(2, portRect.height()))
  1705. else:
  1706. connRect = QRectF(QPointF(portRect.right()-2, portRect.top()), QSizeF(2, portRect.height()))
  1707. painter.drawRect(connRect)
  1708. self.m_last_selected_state = self.isSelected()
  1709. painter.restore()
  1710. # ------------------------------------------------------------------------------
  1711. # canvasbox.cpp
  1712. class cb_line_t(object):
  1713. __slots__ = [
  1714. 'line',
  1715. 'connection_id'
  1716. ]
  1717. class CanvasBox(QGraphicsItem):
  1718. def __init__(self, group_id, group_name, icon, parent=None):
  1719. QGraphicsItem.__init__(self, parent)
  1720. # Save Variables, useful for later
  1721. self.m_group_id = group_id
  1722. self.m_group_name = group_name
  1723. # plugin Id, < 0 if invalid
  1724. self.m_plugin_id = -1
  1725. self.m_plugin_ui = False
  1726. # Base Variables
  1727. self.p_width = 50
  1728. self.p_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1
  1729. self.m_last_pos = QPointF()
  1730. self.m_splitted = False
  1731. self.m_splitted_mode = PORT_MODE_NULL
  1732. self.m_cursor_moving = False
  1733. self.m_forced_split = False
  1734. self.m_mouse_down = False
  1735. self.m_port_list_ids = []
  1736. self.m_connection_lines = []
  1737. # Set Font
  1738. self.m_font_name = QFont()
  1739. self.m_font_name.setFamily(canvas.theme.box_font_name)
  1740. self.m_font_name.setPixelSize(canvas.theme.box_font_size)
  1741. self.m_font_name.setWeight(canvas.theme.box_font_state)
  1742. self.m_font_port = QFont()
  1743. self.m_font_port.setFamily(canvas.theme.port_font_name)
  1744. self.m_font_port.setPixelSize(canvas.theme.port_font_size)
  1745. self.m_font_port.setWeight(canvas.theme.port_font_state)
  1746. # Icon
  1747. if canvas.theme.box_use_icon:
  1748. self.icon_svg = CanvasIcon(icon, self.m_group_name, self)
  1749. else:
  1750. self.icon_svg = None
  1751. # Shadow
  1752. if options.eyecandy:
  1753. self.shadow = CanvasBoxShadow(self.toGraphicsObject())
  1754. self.shadow.setFakeParent(self)
  1755. self.setGraphicsEffect(self.shadow)
  1756. else:
  1757. self.shadow = None
  1758. # Final touches
  1759. self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
  1760. # Wait for at least 1 port
  1761. if options.auto_hide_groups:
  1762. self.setVisible(False)
  1763. self.setFlag(QGraphicsItem.ItemIsFocusable, True)
  1764. if options.auto_select_items:
  1765. self.setAcceptHoverEvents(True)
  1766. self.updatePositions()
  1767. canvas.scene.addItem(self)
  1768. def getGroupId(self):
  1769. return self.m_group_id
  1770. def getGroupName(self):
  1771. return self.m_group_name
  1772. def isSplitted(self):
  1773. return self.m_splitted
  1774. def getSplittedMode(self):
  1775. return self.m_splitted_mode
  1776. def getPortCount(self):
  1777. return len(self.m_port_list_ids)
  1778. def getPortList(self):
  1779. return self.m_port_list_ids
  1780. def setAsPlugin(self, plugin_id, hasUi):
  1781. self.m_plugin_id = plugin_id
  1782. self.m_plugin_ui = hasUi
  1783. def setIcon(self, icon):
  1784. if self.icon_svg is not None:
  1785. self.icon_svg.setIcon(icon, self.m_group_name)
  1786. def setSplit(self, split, mode=PORT_MODE_NULL):
  1787. self.m_splitted = split
  1788. self.m_splitted_mode = mode
  1789. def setGroupName(self, group_name):
  1790. self.m_group_name = group_name
  1791. self.updatePositions()
  1792. def setShadowOpacity(self, opacity):
  1793. if self.shadow:
  1794. self.shadow.setOpacity(opacity)
  1795. def addPortFromGroup(self, port_id, port_mode, port_type, port_name, is_alternate):
  1796. if len(self.m_port_list_ids) == 0:
  1797. if options.auto_hide_groups:
  1798. if options.eyecandy == EYECANDY_FULL:
  1799. CanvasItemFX(self, True, False)
  1800. self.setVisible(True)
  1801. new_widget = CanvasPort(self.m_group_id, port_id, port_name, port_mode, port_type, is_alternate, self)
  1802. port_dict = port_dict_t()
  1803. port_dict.group_id = self.m_group_id
  1804. port_dict.port_id = port_id
  1805. port_dict.port_name = port_name
  1806. port_dict.port_mode = port_mode
  1807. port_dict.port_type = port_type
  1808. port_dict.is_alternate = is_alternate
  1809. port_dict.widget = new_widget
  1810. self.m_port_list_ids.append(port_id)
  1811. return new_widget
  1812. def removePortFromGroup(self, port_id):
  1813. if port_id in self.m_port_list_ids:
  1814. self.m_port_list_ids.remove(port_id)
  1815. else:
  1816. qCritical("PatchCanvas::CanvasBox.removePort(%i) - unable to find port to remove" % port_id)
  1817. return
  1818. if len(self.m_port_list_ids) > 0:
  1819. self.updatePositions()
  1820. elif self.isVisible():
  1821. if options.auto_hide_groups:
  1822. if options.eyecandy == EYECANDY_FULL:
  1823. CanvasItemFX(self, False, False)
  1824. else:
  1825. self.setVisible(False)
  1826. def addLineFromGroup(self, line, connection_id):
  1827. new_cbline = cb_line_t()
  1828. new_cbline.line = line
  1829. new_cbline.connection_id = connection_id
  1830. self.m_connection_lines.append(new_cbline)
  1831. def removeLineFromGroup(self, connection_id):
  1832. for connection in self.m_connection_lines:
  1833. if connection.connection_id == connection_id:
  1834. self.m_connection_lines.remove(connection)
  1835. return
  1836. qCritical("PatchCanvas::CanvasBox.removeLineFromGroup(%i) - unable to find line to remove" % connection_id)
  1837. def checkItemPos(self):
  1838. if not canvas.size_rect.isNull():
  1839. pos = self.scenePos()
  1840. if not (canvas.size_rect.contains(pos) and canvas.size_rect.contains(pos + QPointF(self.p_width, self.p_height))):
  1841. if pos.x() < canvas.size_rect.x():
  1842. self.setPos(canvas.size_rect.x(), pos.y())
  1843. elif pos.x() + self.p_width > canvas.size_rect.width():
  1844. self.setPos(canvas.size_rect.width() - self.p_width, pos.y())
  1845. pos = self.scenePos()
  1846. if pos.y() < canvas.size_rect.y():
  1847. self.setPos(pos.x(), canvas.size_rect.y())
  1848. elif pos.y() + self.p_height > canvas.size_rect.height():
  1849. self.setPos(pos.x(), canvas.size_rect.height() - self.p_height)
  1850. def removeIconFromScene(self):
  1851. if self.icon_svg is None:
  1852. return
  1853. item = self.icon_svg
  1854. self.icon_svg = None
  1855. canvas.scene.removeItem(item)
  1856. del item
  1857. def updatePositions(self):
  1858. self.prepareGeometryChange()
  1859. max_in_width = 0
  1860. max_in_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing
  1861. max_out_width = 0
  1862. max_out_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing
  1863. port_spacing = canvas.theme.port_height + canvas.theme.port_spacing
  1864. have_audio_jack_in = have_midi_jack_in = have_midi_alsa_in = have_parameter_in = False
  1865. have_audio_jack_out = have_midi_jack_out = have_midi_alsa_out = have_parameter_out = False
  1866. # reset box size
  1867. self.p_width = 50
  1868. self.p_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1
  1869. # Check Text Name size
  1870. app_name_size = QFontMetrics(self.m_font_name).width(self.m_group_name) + 30
  1871. if app_name_size > self.p_width:
  1872. self.p_width = app_name_size
  1873. # Get Port List
  1874. port_list = []
  1875. for port in canvas.port_list:
  1876. if port.group_id == self.m_group_id and port.port_id in self.m_port_list_ids:
  1877. port_list.append(port)
  1878. # Get Max Box Width/Height
  1879. for port in port_list:
  1880. if port.port_mode == PORT_MODE_INPUT:
  1881. max_in_height += port_spacing
  1882. size = QFontMetrics(self.m_font_port).width(port.port_name)
  1883. if size > max_in_width:
  1884. max_in_width = size
  1885. if port.port_type == PORT_TYPE_AUDIO_JACK and not have_audio_jack_in:
  1886. have_audio_jack_in = True
  1887. max_in_height += canvas.theme.port_spacingT
  1888. elif port.port_type == PORT_TYPE_MIDI_JACK and not have_midi_jack_in:
  1889. have_midi_jack_in = True
  1890. max_in_height += canvas.theme.port_spacingT
  1891. elif port.port_type == PORT_TYPE_MIDI_ALSA and not have_midi_alsa_in:
  1892. have_midi_alsa_in = True
  1893. max_in_height += canvas.theme.port_spacingT
  1894. elif port.port_type == PORT_TYPE_PARAMETER and not have_parameter_in:
  1895. have_parameter_in = True
  1896. max_in_height += canvas.theme.port_spacingT
  1897. elif port.port_mode == PORT_MODE_OUTPUT:
  1898. max_out_height += port_spacing
  1899. size = QFontMetrics(self.m_font_port).width(port.port_name)
  1900. if size > max_out_width:
  1901. max_out_width = size
  1902. if port.port_type == PORT_TYPE_AUDIO_JACK and not have_audio_jack_out:
  1903. have_audio_jack_out = True
  1904. max_out_height += canvas.theme.port_spacingT
  1905. elif port.port_type == PORT_TYPE_MIDI_JACK and not have_midi_jack_out:
  1906. have_midi_jack_out = True
  1907. max_out_height += canvas.theme.port_spacingT
  1908. elif port.port_type == PORT_TYPE_MIDI_ALSA and not have_midi_alsa_out:
  1909. have_midi_alsa_out = True
  1910. max_out_height += canvas.theme.port_spacingT
  1911. elif port.port_type == PORT_TYPE_PARAMETER and not have_parameter_out:
  1912. have_parameter_out = True
  1913. max_out_height += canvas.theme.port_spacingT
  1914. if canvas.theme.port_spacingT == 0:
  1915. max_in_height += 2
  1916. max_out_height += 2
  1917. final_width = 30 + max_in_width + max_out_width
  1918. if final_width > self.p_width:
  1919. self.p_width = final_width
  1920. if max_in_height > self.p_height:
  1921. self.p_height = max_in_height
  1922. if max_out_height > self.p_height:
  1923. self.p_height = max_out_height
  1924. # Remove bottom space
  1925. self.p_height -= canvas.theme.port_spacingT
  1926. if canvas.theme.box_header_spacing > 0:
  1927. if len(port_list) == 0:
  1928. self.p_height -= canvas.theme.box_header_spacing
  1929. else:
  1930. self.p_height -= canvas.theme.box_header_spacing/2
  1931. last_in_pos = canvas.theme.box_header_height + canvas.theme.box_header_spacing
  1932. last_out_pos = canvas.theme.box_header_height + canvas.theme.box_header_spacing
  1933. last_in_type = PORT_TYPE_NULL
  1934. last_out_type = PORT_TYPE_NULL
  1935. # Re-position ports, AUDIO_JACK
  1936. for port in port_list:
  1937. if port.port_type != PORT_TYPE_AUDIO_JACK:
  1938. continue
  1939. if port.port_mode == PORT_MODE_INPUT:
  1940. if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
  1941. last_in_pos += canvas.theme.port_spacingT
  1942. port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
  1943. port.widget.setPortWidth(max_in_width)
  1944. last_in_pos += port_spacing
  1945. last_in_type = port.port_type
  1946. elif port.port_mode == PORT_MODE_OUTPUT:
  1947. if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
  1948. last_out_pos += canvas.theme.port_spacingT
  1949. port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
  1950. port.widget.setPortWidth(max_out_width)
  1951. last_out_pos += port_spacing
  1952. last_out_type = port.port_type
  1953. # Re-position ports, MIDI_JACK
  1954. for port in port_list:
  1955. if port.port_type != PORT_TYPE_MIDI_JACK:
  1956. continue
  1957. if port.port_mode == PORT_MODE_INPUT:
  1958. if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
  1959. last_in_pos += canvas.theme.port_spacingT
  1960. port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
  1961. port.widget.setPortWidth(max_in_width)
  1962. last_in_pos += port_spacing
  1963. last_in_type = port.port_type
  1964. elif port.port_mode == PORT_MODE_OUTPUT:
  1965. if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
  1966. last_out_pos += canvas.theme.port_spacingT
  1967. port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
  1968. port.widget.setPortWidth(max_out_width)
  1969. last_out_pos += port_spacing
  1970. last_out_type = port.port_type
  1971. # Re-position ports, MIDI_ALSA
  1972. for port in port_list:
  1973. if port.port_type != PORT_TYPE_MIDI_ALSA:
  1974. continue
  1975. if port.port_mode == PORT_MODE_INPUT:
  1976. if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
  1977. last_in_pos += canvas.theme.port_spacingT
  1978. port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
  1979. port.widget.setPortWidth(max_in_width)
  1980. last_in_pos += port_spacing
  1981. last_in_type = port.port_type
  1982. elif port.port_mode == PORT_MODE_OUTPUT:
  1983. if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
  1984. last_out_pos += canvas.theme.port_spacingT
  1985. port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
  1986. port.widget.setPortWidth(max_out_width)
  1987. last_out_pos += port_spacing
  1988. last_out_type = port.port_type
  1989. # Re-position ports, PARAMETER
  1990. for port in port_list:
  1991. if port.port_type != PORT_TYPE_PARAMETER:
  1992. continue
  1993. if port.port_mode == PORT_MODE_INPUT:
  1994. if last_in_type != PORT_TYPE_NULL and port.port_type != last_in_type:
  1995. last_in_pos += canvas.theme.port_spacingT
  1996. port.widget.setPos(QPointF(1 + canvas.theme.port_offset, last_in_pos))
  1997. port.widget.setPortWidth(max_in_width)
  1998. last_in_pos += port_spacing
  1999. last_in_type = port.port_type
  2000. elif port.port_mode == PORT_MODE_OUTPUT:
  2001. if last_out_type != PORT_TYPE_NULL and port.port_type != last_out_type:
  2002. last_out_pos += canvas.theme.port_spacingT
  2003. port.widget.setPos(QPointF(self.p_width - max_out_width - canvas.theme.port_offset - 13, last_out_pos))
  2004. port.widget.setPortWidth(max_out_width)
  2005. last_out_pos += port_spacing
  2006. last_out_type = port.port_type
  2007. self.repaintLines(True)
  2008. self.update()
  2009. def repaintLines(self, forced=False):
  2010. if self.pos() != self.m_last_pos or forced:
  2011. for connection in self.m_connection_lines:
  2012. connection.line.updateLinePos()
  2013. self.m_last_pos = self.pos()
  2014. def resetLinesZValue(self):
  2015. for connection in canvas.connection_list:
  2016. if connection.port_out_id in self.m_port_list_ids and connection.port_in_id in self.m_port_list_ids:
  2017. z_value = canvas.last_z_value
  2018. else:
  2019. z_value = canvas.last_z_value - 1
  2020. connection.widget.setZValue(z_value)
  2021. def type(self):
  2022. return CanvasBoxType
  2023. def contextMenuEvent(self, event):
  2024. menu = QMenu()
  2025. discMenu = QMenu("Disconnect", menu)
  2026. conn_list = []
  2027. conn_list_ids = []
  2028. for port_id in self.m_port_list_ids:
  2029. tmp_conn_list = CanvasGetPortConnectionList(self.m_group_id, port_id)
  2030. for conn_id, group_id, port_id in tmp_conn_list:
  2031. if conn_id not in conn_list_ids:
  2032. conn_list.append((conn_id, group_id, port_id))
  2033. conn_list_ids.append(conn_id)
  2034. if len(conn_list) > 0:
  2035. for conn_id, group_id, port_id in conn_list:
  2036. act_x_disc = discMenu.addAction(CanvasGetFullPortName(group_id, port_id))
  2037. act_x_disc.setData(conn_id)
  2038. act_x_disc.triggered.connect(canvas.qobject.PortContextMenuDisconnect)
  2039. else:
  2040. act_x_disc = discMenu.addAction("No connections")
  2041. act_x_disc.setEnabled(False)
  2042. menu.addMenu(discMenu)
  2043. act_x_disc_all = menu.addAction("Disconnect &All")
  2044. act_x_sep1 = menu.addSeparator()
  2045. act_x_info = menu.addAction("Info")
  2046. act_x_rename = menu.addAction("Rename")
  2047. act_x_sep2 = menu.addSeparator()
  2048. act_x_split_join = menu.addAction("Join" if self.m_splitted else "Split")
  2049. if not features.group_info:
  2050. act_x_info.setVisible(False)
  2051. if not features.group_rename:
  2052. act_x_rename.setVisible(False)
  2053. if not (features.group_info and features.group_rename):
  2054. act_x_sep1.setVisible(False)
  2055. if self.m_plugin_id >= 0 and self.m_plugin_id <= MAX_PLUGIN_ID_ALLOWED:
  2056. menu.addSeparator()
  2057. act_p_edit = menu.addAction("Edit")
  2058. act_p_ui = menu.addAction("Show Custom UI")
  2059. menu.addSeparator()
  2060. act_p_clone = menu.addAction("Clone")
  2061. act_p_rename = menu.addAction("Rename...")
  2062. act_p_replace = menu.addAction("Replace...")
  2063. act_p_remove = menu.addAction("Remove")
  2064. if not self.m_plugin_ui:
  2065. act_p_ui.setVisible(False)
  2066. else:
  2067. act_p_edit = act_p_ui = None
  2068. act_p_clone = act_p_rename = None
  2069. act_p_replace = act_p_remove = None
  2070. haveIns = haveOuts = False
  2071. for port in canvas.port_list:
  2072. if port.group_id == self.m_group_id and port.port_id in self.m_port_list_ids:
  2073. if port.port_mode == PORT_MODE_INPUT:
  2074. haveIns = True
  2075. elif port.port_mode == PORT_MODE_OUTPUT:
  2076. haveOuts = True
  2077. if not (self.m_splitted or bool(haveIns and haveOuts)):
  2078. act_x_sep2.setVisible(False)
  2079. act_x_split_join.setVisible(False)
  2080. act_selected = menu.exec_(event.screenPos())
  2081. if act_selected is None:
  2082. pass
  2083. elif act_selected == act_x_disc_all:
  2084. for conn_id in conn_list_ids:
  2085. canvas.callback(ACTION_PORTS_DISCONNECT, conn_id, 0, "")
  2086. elif act_selected == act_x_info:
  2087. canvas.callback(ACTION_GROUP_INFO, self.m_group_id, 0, "")
  2088. elif act_selected == act_x_rename:
  2089. canvas.callback(ACTION_GROUP_RENAME, self.m_group_id, 0, "")
  2090. elif act_selected == act_x_split_join:
  2091. if self.m_splitted:
  2092. canvas.callback(ACTION_GROUP_JOIN, self.m_group_id, 0, "")
  2093. else:
  2094. canvas.callback(ACTION_GROUP_SPLIT, self.m_group_id, 0, "")
  2095. elif act_selected == act_p_edit:
  2096. canvas.callback(ACTION_PLUGIN_EDIT, self.m_plugin_id, 0, "")
  2097. elif act_selected == act_p_ui:
  2098. canvas.callback(ACTION_PLUGIN_SHOW_UI, self.m_plugin_id, 0, "")
  2099. elif act_selected == act_p_clone:
  2100. canvas.callback(ACTION_PLUGIN_CLONE, self.m_plugin_id, 0, "")
  2101. elif act_selected == act_p_rename:
  2102. canvas.callback(ACTION_PLUGIN_RENAME, self.m_plugin_id, 0, "")
  2103. elif act_selected == act_p_replace:
  2104. canvas.callback(ACTION_PLUGIN_REPLACE, self.m_plugin_id, 0, "")
  2105. elif act_selected == act_p_remove:
  2106. canvas.callback(ACTION_PLUGIN_REMOVE, self.m_plugin_id, 0, "")
  2107. event.accept()
  2108. def keyPressEvent(self, event):
  2109. if self.m_plugin_id >= 0 and event.key() == Qt.Key_Delete:
  2110. canvas.callback(ACTION_PLUGIN_REMOVE, self.m_plugin_id, 0, "")
  2111. return event.accept()
  2112. QGraphicsItem.keyPressEvent(self, event)
  2113. def hoverEnterEvent(self, event):
  2114. if options.auto_select_items:
  2115. if len(canvas.scene.selectedItems()) > 0:
  2116. canvas.scene.clearSelection()
  2117. self.setSelected(True)
  2118. QGraphicsItem.hoverEnterEvent(self, event)
  2119. def mouseDoubleClickEvent(self, event):
  2120. if self.m_plugin_id >= 0:
  2121. canvas.callback(ACTION_PLUGIN_SHOW_UI if self.m_plugin_ui else ACTION_PLUGIN_EDIT, self.m_plugin_id, 0, "")
  2122. return event.accept()
  2123. QGraphicsItem.mouseDoubleClickEvent(self, event)
  2124. def mousePressEvent(self, event):
  2125. canvas.last_z_value += 1
  2126. self.setZValue(canvas.last_z_value)
  2127. self.resetLinesZValue()
  2128. self.m_cursor_moving = False
  2129. if event.button() == Qt.RightButton:
  2130. canvas.scene.clearSelection()
  2131. self.setSelected(True)
  2132. self.m_mouse_down = False
  2133. return event.accept()
  2134. elif event.button() == Qt.LeftButton:
  2135. if self.sceneBoundingRect().contains(event.scenePos()):
  2136. self.m_mouse_down = True
  2137. else:
  2138. # Fix a weird Qt behaviour with right-click mouseMove
  2139. self.m_mouse_down = False
  2140. return event.ignore()
  2141. else:
  2142. self.m_mouse_down = False
  2143. QGraphicsItem.mousePressEvent(self, event)
  2144. def mouseMoveEvent(self, event):
  2145. if self.m_mouse_down:
  2146. if not self.m_cursor_moving:
  2147. self.setCursor(QCursor(Qt.SizeAllCursor))
  2148. self.m_cursor_moving = True
  2149. self.repaintLines()
  2150. QGraphicsItem.mouseMoveEvent(self, event)
  2151. def mouseReleaseEvent(self, event):
  2152. if self.m_cursor_moving:
  2153. self.setCursor(QCursor(Qt.ArrowCursor))
  2154. self.m_mouse_down = False
  2155. self.m_cursor_moving = False
  2156. QGraphicsItem.mouseReleaseEvent(self, event)
  2157. def boundingRect(self):
  2158. return QRectF(0, 0, self.p_width, self.p_height)
  2159. def paint(self, painter, option, widget):
  2160. painter.save()
  2161. painter.setRenderHint(QPainter.Antialiasing, False)
  2162. # Draw rectangle
  2163. if self.isSelected():
  2164. painter.setPen(canvas.theme.box_pen_sel)
  2165. else:
  2166. painter.setPen(canvas.theme.box_pen)
  2167. if canvas.theme.box_bg_type == Theme.THEME_BG_GRADIENT:
  2168. box_gradient = QLinearGradient(0, 0, 0, self.p_height)
  2169. box_gradient.setColorAt(0, canvas.theme.box_bg_1)
  2170. box_gradient.setColorAt(1, canvas.theme.box_bg_2)
  2171. painter.setBrush(box_gradient)
  2172. else:
  2173. painter.setBrush(canvas.theme.box_bg_1)
  2174. painter.drawRect(0, 0, self.p_width, self.p_height)
  2175. # Draw pixmap header
  2176. if canvas.theme.box_header_pixmap:
  2177. painter.setPen(Qt.NoPen)
  2178. painter.setBrush(canvas.theme.box_bg_2)
  2179. painter.drawRect(1, 1, self.p_width-2, canvas.theme.box_header_height)
  2180. headerPos = QPointF(1, 1)
  2181. headerRect = QRectF(2, 2, self.p_width-4, canvas.theme.box_header_height-3)
  2182. painter.drawTiledPixmap(headerRect, canvas.theme.box_header_pixmap, headerPos)
  2183. # Draw text
  2184. painter.setFont(self.m_font_name)
  2185. if self.isSelected():
  2186. painter.setPen(canvas.theme.box_text_sel)
  2187. else:
  2188. painter.setPen(canvas.theme.box_text)
  2189. if canvas.theme.box_use_icon:
  2190. textPos = QPointF(25, canvas.theme.box_text_ypos)
  2191. else:
  2192. appNameSize = QFontMetrics(self.m_font_name).width(self.m_group_name)
  2193. rem = self.p_width - appNameSize
  2194. textPos = QPointF(rem/2, canvas.theme.box_text_ypos)
  2195. painter.drawText(textPos, self.m_group_name)
  2196. self.repaintLines()
  2197. painter.restore()
  2198. # ------------------------------------------------------------------------------
  2199. # canvasicon.cpp
  2200. class CanvasIcon(QGraphicsSvgItem):
  2201. def __init__(self, icon, name, parent):
  2202. QGraphicsSvgItem.__init__(self, parent)
  2203. self.m_renderer = None
  2204. self.p_size = QRectF(0, 0, 0, 0)
  2205. self.m_colorFX = QGraphicsColorizeEffect(self)
  2206. self.m_colorFX.setColor(canvas.theme.box_text.color())
  2207. self.setGraphicsEffect(self.m_colorFX)
  2208. self.setIcon(icon, name)
  2209. def setIcon(self, icon, name):
  2210. name = name.lower()
  2211. icon_path = ""
  2212. if icon == ICON_APPLICATION:
  2213. self.p_size = QRectF(3, 2, 19, 18)
  2214. if "audacious" in name:
  2215. icon_path = ":/scalable/pb_audacious.svg"
  2216. self.p_size = QRectF(5, 4, 16, 16)
  2217. elif "clementine" in name:
  2218. icon_path = ":/scalable/pb_clementine.svg"
  2219. self.p_size = QRectF(5, 4, 16, 16)
  2220. elif "distrho" in name:
  2221. icon_path = ":/scalable/pb_distrho.svg"
  2222. self.p_size = QRectF(5, 4, 14, 14)
  2223. elif "jamin" in name:
  2224. icon_path = ":/scalable/pb_jamin.svg"
  2225. self.p_size = QRectF(5, 3, 16, 16)
  2226. elif "mplayer" in name:
  2227. icon_path = ":/scalable/pb_mplayer.svg"
  2228. self.p_size = QRectF(5, 4, 16, 16)
  2229. elif "vlc" in name:
  2230. icon_path = ":/scalable/pb_vlc.svg"
  2231. self.p_size = QRectF(5, 3, 16, 16)
  2232. else:
  2233. icon_path = ":/scalable/pb_generic.svg"
  2234. self.p_size = QRectF(4, 3, 16, 16)
  2235. elif icon == ICON_HARDWARE:
  2236. icon_path = ":/scalable/pb_hardware.svg"
  2237. self.p_size = QRectF(5, 2, 16, 16)
  2238. elif icon == ICON_DISTRHO:
  2239. icon_path = ":/scalable/pb_distrho.svg"
  2240. self.p_size = QRectF(5, 4, 14, 14)
  2241. elif icon == ICON_FILE:
  2242. icon_path = ":/scalable/pb_file.svg"
  2243. self.p_size = QRectF(5, 4, 12, 14)
  2244. elif icon == ICON_PLUGIN:
  2245. icon_path = ":/scalable/pb_plugin.svg"
  2246. self.p_size = QRectF(5, 4, 14, 14)
  2247. elif icon == ICON_LADISH_ROOM:
  2248. # TODO - make a unique ladish-room icon
  2249. icon_path = ":/scalable/pb_hardware.svg"
  2250. self.p_size = QRectF(5, 2, 16, 16)
  2251. else:
  2252. self.p_size = QRectF(0, 0, 0, 0)
  2253. qCritical("PatchCanvas::CanvasIcon.setIcon(%s, %s) - unsupported icon requested" % (icon2str(icon), name.encode()))
  2254. return
  2255. self.m_renderer = QSvgRenderer(icon_path, canvas.scene)
  2256. self.setSharedRenderer(self.m_renderer)
  2257. self.update()
  2258. def type(self):
  2259. return CanvasIconType
  2260. def boundingRect(self):
  2261. return self.p_size
  2262. def paint(self, painter, option, widget):
  2263. if self.m_renderer:
  2264. painter.save()
  2265. painter.setRenderHint(QPainter.Antialiasing, False)
  2266. painter.setRenderHint(QPainter.TextAntialiasing, False)
  2267. self.m_renderer.render(painter, self.p_size)
  2268. painter.restore()
  2269. else:
  2270. QGraphicsSvgItem.paint(self, painter, option, widget)
  2271. # ------------------------------------------------------------------------------
  2272. # canvasportglow.cpp
  2273. class CanvasPortGlow(QGraphicsDropShadowEffect):
  2274. def __init__(self, port_type, parent):
  2275. QGraphicsDropShadowEffect.__init__(self, parent)
  2276. self.setBlurRadius(12)
  2277. self.setOffset(0, 0)
  2278. if port_type == PORT_TYPE_AUDIO_JACK:
  2279. self.setColor(canvas.theme.line_audio_jack_glow)
  2280. elif port_type == PORT_TYPE_MIDI_JACK:
  2281. self.setColor(canvas.theme.line_midi_jack_glow)
  2282. elif port_type == PORT_TYPE_MIDI_ALSA:
  2283. self.setColor(canvas.theme.line_midi_alsa_glow)
  2284. elif port_type == PORT_TYPE_PARAMETER:
  2285. self.setColor(canvas.theme.line_parameter_glow)
  2286. # ------------------------------------------------------------------------------
  2287. # canvasboxshadow.cpp
  2288. class CanvasBoxShadow(QGraphicsDropShadowEffect):
  2289. def __init__(self, parent):
  2290. QGraphicsDropShadowEffect.__init__(self, parent)
  2291. self.m_fakeParent = None
  2292. self.setBlurRadius(20)
  2293. self.setColor(canvas.theme.box_shadow)
  2294. self.setOffset(0, 0)
  2295. def setFakeParent(self, fakeParent):
  2296. self.m_fakeParent = fakeParent
  2297. def setOpacity(self, opacity):
  2298. color = QColor(canvas.theme.box_shadow)
  2299. color.setAlphaF(opacity)
  2300. self.setColor(color)
  2301. def draw(self, painter):
  2302. if self.m_fakeParent:
  2303. self.m_fakeParent.repaintLines()
  2304. QGraphicsDropShadowEffect.draw(self, painter)