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.

carla_rack.py 23KB

11 years ago
11 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla rack widget code
  4. # Copyright (C) 2011-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 Qt, QSize, QTimer
  24. from PyQt5.QtGui import QPixmap
  25. from PyQt5.QtWidgets import QAbstractItemView, QApplication, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QScrollBar
  26. else:
  27. from PyQt4.QtCore import Qt, QSize, QTimer
  28. from PyQt4.QtGui import QAbstractItemView, QApplication, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPixmap, QScrollBar
  29. # ------------------------------------------------------------------------------------------------------------
  30. # Imports (Custom Stuff)
  31. from carla_skin import *
  32. # ------------------------------------------------------------------------------------------------------------
  33. # Rack widget item
  34. class CarlaRackItem(QListWidgetItem):
  35. kRackItemType = QListWidgetItem.UserType + 1
  36. def __init__(self, parent, pluginId):
  37. QListWidgetItem.__init__(self, parent, self.kRackItemType)
  38. self.fParent = parent
  39. self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
  40. #self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled|Qt.ItemIsDragEnabled|Qt.ItemIsDropEnabled)
  41. self.createWidget(pluginId)
  42. # -----------------------------------------------------------------
  43. def createWidget(self, pluginId):
  44. self.widget = createPluginSlot(self.fParent, pluginId)
  45. self.widget.setFixedHeight(self.widget.getFixedHeight())
  46. self.setSizeHint(QSize(640, self.widget.getFixedHeight()))
  47. self.fParent.setItemWidget(self, self.widget)
  48. # -----------------------------------------------------------------
  49. def close(self):
  50. self.widget.fEditDialog.close()
  51. def reloadAll(self, pluginId):
  52. self.widget.fEditDialog.close()
  53. del self.widget
  54. self.createWidget(pluginId)
  55. # ------------------------------------------------------------------------------------------------------------
  56. # Rack widget list
  57. class CarlaRackList(QListWidget):
  58. def __init__(self, parent):
  59. QListWidget.__init__(self, parent)
  60. exts = gCarla.host.get_supported_file_extensions().split(";") if gCarla.host is not None else ["wav",]
  61. # plugin files
  62. exts.append("dll")
  63. if MACOS:
  64. exts.append("dylib")
  65. if not WINDOWS:
  66. exts.append("so")
  67. self.fSupportedExtensions = tuple(i.replace("*.","") for i in exts)
  68. self.fWasLastDragValid = False
  69. self.setMinimumWidth(640+20) # required by zita, 591 was old value
  70. self.setSelectionMode(QAbstractItemView.SingleSelection)
  71. self.setSortingEnabled(False)
  72. #self.setSortingEnabled(True)
  73. self.setDragEnabled(True)
  74. self.setDragDropMode(QAbstractItemView.DropOnly)
  75. self.setDropIndicatorShown(True)
  76. self.viewport().setAcceptDrops(True)
  77. self.setFrameShape(QFrame.NoFrame)
  78. self.setFrameShadow(QFrame.Plain)
  79. self.fPixmapL = QPixmap(":/bitmaps/rack_interior_left.png")
  80. self.fPixmapR = QPixmap(":/bitmaps/rack_interior_right.png")
  81. self.fPixmapWidth = self.fPixmapL.width()
  82. def isDragEventValid(self, urls):
  83. for url in urls:
  84. filename = url.toLocalFile()
  85. if os.path.isdir(filename):
  86. if os.path.exists(os.path.join(filename, "manifest.ttl")):
  87. return True
  88. elif os.path.isfile(filename):
  89. if filename.lower().endswith(self.fSupportedExtensions):
  90. return True
  91. return False
  92. def dragEnterEvent(self, event):
  93. if self.isDragEventValid(event.mimeData().urls()):
  94. self.fWasLastDragValid = True
  95. event.acceptProposedAction()
  96. return
  97. self.fWasLastDragValid = False
  98. QListWidget.dragEnterEvent(self, event)
  99. def dragMoveEvent(self, event):
  100. if self.fWasLastDragValid:
  101. event.acceptProposedAction()
  102. tryItem = self.itemAt(event.pos())
  103. if tryItem is not None:
  104. self.setCurrentRow(tryItem.widget.getPluginId())
  105. else:
  106. self.setCurrentRow(-1)
  107. return
  108. QListWidget.dragMoveEvent(self, event)
  109. #def dragLeaveEvent(self, event):
  110. #self.fWasLastDragValid = False
  111. #QListWidget.dragLeaveEvent(self, event)
  112. def dropEvent(self, event):
  113. event.acceptProposedAction()
  114. urls = event.mimeData().urls()
  115. if len(urls) == 0:
  116. return
  117. tryItem = self.itemAt(event.pos())
  118. if tryItem is not None:
  119. pluginId = tryItem.widget.getPluginId()
  120. gCarla.host.replace_plugin(pluginId)
  121. for url in urls:
  122. filename = url.toLocalFile()
  123. if not gCarla.host.load_file(filename):
  124. CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"),
  125. self.tr("Failed to load file"),
  126. gCarla.host.get_last_error(), QMessageBox.Ok, QMessageBox.Ok)
  127. if tryItem is not None:
  128. gCarla.host.replace_plugin(self.parent().fPluginCount)
  129. #tryItem.widget.setActive(True, True, True)
  130. def mousePressEvent(self, event):
  131. if self.itemAt(event.pos()) is None:
  132. event.accept()
  133. self.setCurrentRow(-1)
  134. return
  135. QListWidget.mousePressEvent(self, event)
  136. def paintEvent(self, event):
  137. painter = QPainter(self.viewport())
  138. painter.drawTiledPixmap(0, 0, self.fPixmapWidth, self.height(), self.fPixmapL)
  139. painter.drawTiledPixmap(self.width()-self.fPixmapWidth-2, 0, self.fPixmapWidth, self.height(), self.fPixmapR)
  140. QListWidget.paintEvent(self, event)
  141. # ------------------------------------------------------------------------------------------------------------
  142. # Rack widget
  143. class CarlaRackW(QFrame):
  144. def __init__(self, parent, doSetup = True):
  145. QFrame.__init__(self, parent)
  146. self.fLayout = QHBoxLayout(self)
  147. self.fLayout.setContentsMargins(0, 0, 0, 0)
  148. self.fLayout.setSpacing(0)
  149. self.setLayout(self.fLayout)
  150. self.fPadLeft = QLabel(self)
  151. self.fPadLeft.setFixedWidth(25)
  152. self.fPadLeft.setObjectName("PadLeft")
  153. self.fPadLeft.setText("")
  154. self.fPadRight = QLabel(self)
  155. self.fPadRight.setFixedWidth(25)
  156. self.fPadRight.setObjectName("PadRight")
  157. self.fPadRight.setText("")
  158. self.fRack = CarlaRackList(self)
  159. self.fRack.setObjectName("CarlaRackList")
  160. self.fRack.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  161. self.fRack.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  162. self.fRack.currentRowChanged.connect(self.slot_currentRowChanged)
  163. sb = self.fRack.verticalScrollBar()
  164. self.fScrollBar = QScrollBar(Qt.Vertical, self)
  165. self.fScrollBar.setMinimum(sb.minimum())
  166. self.fScrollBar.setMaximum(sb.maximum())
  167. self.fScrollBar.setValue(sb.value())
  168. #sb.actionTriggered.connect(self.fScrollBar.triggerAction)
  169. #sb.sliderMoved.connect(self.fScrollBar.)
  170. #sb.sliderPressed.connect(self.fScrollBar.)
  171. #sb.sliderReleased.connect(self.fScrollBar.)
  172. sb.rangeChanged.connect(self.fScrollBar.setRange)
  173. sb.valueChanged.connect(self.fScrollBar.setValue)
  174. self.fScrollBar.rangeChanged.connect(sb.setRange)
  175. self.fScrollBar.valueChanged.connect(sb.setValue)
  176. self.fLayout.addWidget(self.fPadLeft)
  177. self.fLayout.addWidget(self.fRack)
  178. self.fLayout.addWidget(self.fPadRight)
  179. self.fLayout.addWidget(self.fScrollBar)
  180. # -------------------------------------------------------------
  181. # Internal stuff
  182. self.fParent = parent
  183. self.fPluginCount = 0
  184. self.fPluginList = []
  185. self.fCurrentRow = -1
  186. self.fLastSelectedItem = None
  187. # -------------------------------------------------------------
  188. # Set-up GUI stuff
  189. #app = QApplication.instance()
  190. #pal1 = app.palette().base().color()
  191. #pal2 = app.palette().button().color()
  192. #col1 = "stop:0 rgb(%i, %i, %i)" % (pal1.red(), pal1.green(), pal1.blue())
  193. #col2 = "stop:1 rgb(%i, %i, %i)" % (pal2.red(), pal2.green(), pal2.blue())
  194. self.setStyleSheet("""
  195. QLabel#PadLeft {
  196. background-image: url(:/bitmaps/rack_padding_left.png);
  197. background-repeat: repeat-y;
  198. }
  199. QLabel#PadRight {
  200. background-image: url(:/bitmaps/rack_padding_right.png);
  201. background-repeat: repeat-y;
  202. }
  203. CarlaRackList#CarlaRackList {
  204. background-color: black;
  205. }
  206. """)
  207. # -------------------------------------------------------------
  208. # Connect actions to functions
  209. if not doSetup: return
  210. parent.ui.menu_Canvas.hide()
  211. parent.ui.act_plugins_enable.triggered.connect(self.slot_pluginsEnable)
  212. parent.ui.act_plugins_disable.triggered.connect(self.slot_pluginsDisable)
  213. parent.ui.act_plugins_volume100.triggered.connect(self.slot_pluginsVolume100)
  214. parent.ui.act_plugins_mute.triggered.connect(self.slot_pluginsMute)
  215. parent.ui.act_plugins_wet100.triggered.connect(self.slot_pluginsWet100)
  216. parent.ui.act_plugins_bypass.triggered.connect(self.slot_pluginsBypass)
  217. parent.ui.act_plugins_center.triggered.connect(self.slot_pluginsCenter)
  218. parent.ui.act_plugins_panic.triggered.connect(self.slot_pluginsDisable)
  219. parent.ui.act_settings_configure.triggered.connect(self.slot_configureCarla)
  220. parent.ParameterValueChangedCallback.connect(self.slot_handleParameterValueChangedCallback)
  221. parent.ParameterDefaultChangedCallback.connect(self.slot_handleParameterDefaultChangedCallback)
  222. parent.ParameterMidiChannelChangedCallback.connect(self.slot_handleParameterMidiChannelChangedCallback)
  223. parent.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback)
  224. parent.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback)
  225. parent.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback)
  226. parent.OptionChangedCallback.connect(self.slot_handleOptionChangedCallback)
  227. parent.UiStateChangedCallback.connect(self.slot_handleUiStateChangedCallback)
  228. parent.NoteOnCallback.connect(self.slot_handleNoteOnCallback)
  229. parent.NoteOffCallback.connect(self.slot_handleNoteOffCallback)
  230. parent.UpdateCallback.connect(self.slot_handleUpdateCallback)
  231. parent.ReloadInfoCallback.connect(self.slot_handleReloadInfoCallback)
  232. parent.ReloadParametersCallback.connect(self.slot_handleReloadParametersCallback)
  233. parent.ReloadProgramsCallback.connect(self.slot_handleReloadProgramsCallback)
  234. parent.ReloadAllCallback.connect(self.slot_handleReloadAllCallback)
  235. # -----------------------------------------------------------------
  236. def getPluginCount(self):
  237. return self.fPluginCount
  238. # -----------------------------------------------------------------
  239. def addPlugin(self, pluginId, isProjectLoading):
  240. pitem = CarlaRackItem(self.fRack, pluginId)
  241. self.fPluginList.append(pitem)
  242. self.fPluginCount += 1
  243. if not isProjectLoading:
  244. pitem.widget.setActive(True, True, True)
  245. def removePlugin(self, pluginId):
  246. if pluginId >= self.fPluginCount:
  247. return
  248. pitem = self.fPluginList[pluginId]
  249. if pitem is None:
  250. return
  251. self.fPluginCount -= 1
  252. self.fPluginList.pop(pluginId)
  253. self.fRack.takeItem(pluginId)
  254. pitem.close()
  255. del pitem
  256. # push all plugins 1 slot back
  257. for i in range(pluginId, self.fPluginCount):
  258. pitem = self.fPluginList[i]
  259. pitem.widget.setId(i)
  260. def renamePlugin(self, pluginId, newName):
  261. if pluginId >= self.fPluginCount:
  262. return
  263. pitem = self.fPluginList[pluginId]
  264. if pitem is None:
  265. return
  266. pitem.widget.setName(newName)
  267. def disablePlugin(self, pluginId, errorMsg):
  268. if pluginId >= self.fPluginCount:
  269. return
  270. pitem = self.fPluginList[pluginId]
  271. if pitem is None:
  272. return
  273. def removeAllPlugins(self):
  274. while self.fRack.takeItem(0):
  275. pass
  276. for i in range(self.fPluginCount):
  277. pitem = self.fPluginList[i]
  278. if pitem is None:
  279. break
  280. pitem.close()
  281. del pitem
  282. self.fPluginCount = 0
  283. self.fPluginList = []
  284. # -----------------------------------------------------------------
  285. def engineStarted(self):
  286. pass
  287. def engineStopped(self):
  288. pass
  289. def engineChanged(self):
  290. pass
  291. # -----------------------------------------------------------------
  292. def idleFast(self):
  293. for i in range(self.fPluginCount):
  294. pitem = self.fPluginList[i]
  295. if pitem is None:
  296. break
  297. pitem.widget.idleFast()
  298. def idleSlow(self):
  299. for i in range(self.fPluginCount):
  300. pitem = self.fPluginList[i]
  301. if pitem is None:
  302. break
  303. pitem.widget.idleSlow()
  304. # -----------------------------------------------------------------
  305. def projectLoadingStarted(self):
  306. self.fRack.setEnabled(False)
  307. def projectLoadingFinished(self):
  308. self.fRack.setEnabled(True)
  309. # -----------------------------------------------------------------
  310. def saveSettings(self, settings):
  311. pass
  312. def showEditDialog(self, pluginId):
  313. if pluginId >= self.fPluginCount:
  314. return
  315. pitem = self.fPluginList[pluginId]
  316. if pitem is None:
  317. return
  318. pitem.widget.slot_showEditDialog(True)
  319. # -----------------------------------------------------------------
  320. @pyqtSlot()
  321. def slot_pluginsEnable(self):
  322. if not gCarla.host.is_engine_running():
  323. return
  324. for i in range(self.fPluginCount):
  325. pitem = self.fPluginList[i]
  326. if pitem is None:
  327. break
  328. pitem.widget.setActive(True, True, True)
  329. @pyqtSlot()
  330. def slot_pluginsDisable(self):
  331. if not gCarla.host.is_engine_running():
  332. return
  333. for i in range(self.fPluginCount):
  334. pitem = self.fPluginList[i]
  335. if pitem is None:
  336. break
  337. pitem.widget.setActive(False, True, True)
  338. @pyqtSlot()
  339. def slot_pluginsVolume100(self):
  340. if not gCarla.host.is_engine_running():
  341. return
  342. for i in range(self.fPluginCount):
  343. pitem = self.fPluginList[i]
  344. if pitem is None:
  345. break
  346. pitem.widget.setInternalParameter(PLUGIN_CAN_VOLUME, 1.0)
  347. @pyqtSlot()
  348. def slot_pluginsMute(self):
  349. if not gCarla.host.is_engine_running():
  350. return
  351. for i in range(self.fPluginCount):
  352. pitem = self.fPluginList[i]
  353. if pitem is None:
  354. break
  355. pitem.widget.setInternalParameter(PLUGIN_CAN_VOLUME, 0.0)
  356. @pyqtSlot()
  357. def slot_pluginsWet100(self):
  358. if not gCarla.host.is_engine_running():
  359. return
  360. for i in range(self.fPluginCount):
  361. pitem = self.fPluginList[i]
  362. if pitem is None:
  363. break
  364. pitem.widget.setInternalParameter(PLUGIN_CAN_DRYWET, 1.0)
  365. @pyqtSlot()
  366. def slot_pluginsBypass(self):
  367. if not gCarla.host.is_engine_running():
  368. return
  369. for i in range(self.fPluginCount):
  370. pitem = self.fPluginList[i]
  371. if pitem is None:
  372. break
  373. pitem.widget.setInternalParameter(PLUGIN_CAN_DRYWET, 0.0)
  374. @pyqtSlot()
  375. def slot_pluginsCenter(self):
  376. if not gCarla.host.is_engine_running():
  377. return
  378. for i in range(self.fPluginCount):
  379. pitem = self.fPluginList[i]
  380. if pitem is None:
  381. break
  382. pitem.widget.setInternalParameter(PARAMETER_BALANCE_LEFT, -1.0)
  383. pitem.widget.setInternalParameter(PARAMETER_BALANCE_RIGHT, 1.0)
  384. pitem.widget.setInternalParameter(PARAMETER_PANNING, 0.0)
  385. # -----------------------------------------------------------------
  386. @pyqtSlot()
  387. def slot_configureCarla(self):
  388. if self.fParent is None or not self.fParent.openSettingsWindow(False, False):
  389. return
  390. self.fParent.loadSettings(False)
  391. # -----------------------------------------------------------------
  392. @pyqtSlot(int, int, float)
  393. def slot_handleParameterValueChangedCallback(self, pluginId, index, value):
  394. if pluginId >= self.fPluginCount:
  395. return
  396. pitem = self.fPluginList[pluginId]
  397. if pitem is None:
  398. return
  399. pitem.widget.setParameterValue(index, value, True)
  400. @pyqtSlot(int, int, float)
  401. def slot_handleParameterDefaultChangedCallback(self, pluginId, index, value):
  402. if pluginId >= self.fPluginCount:
  403. return
  404. pitem = self.fPluginList[pluginId]
  405. if pitem is None:
  406. return
  407. pitem.widget.setParameterDefault(index, value)
  408. @pyqtSlot(int, int, int)
  409. def slot_handleParameterMidiCcChangedCallback(self, pluginId, index, cc):
  410. if pluginId >= self.fPluginCount:
  411. return
  412. pitem = self.fPluginList[pluginId]
  413. if pitem is None:
  414. return
  415. pitem.widget.setParameterMidiControl(index, cc)
  416. @pyqtSlot(int, int, int)
  417. def slot_handleParameterMidiChannelChangedCallback(self, pluginId, index, channel):
  418. if pluginId >= self.fPluginCount:
  419. return
  420. pitem = self.fPluginList[pluginId]
  421. if pitem is None:
  422. return
  423. pitem.widget.setParameterMidiChannel(index, channel)
  424. # -----------------------------------------------------------------
  425. @pyqtSlot(int, int)
  426. def slot_handleProgramChangedCallback(self, pluginId, index):
  427. if pluginId >= self.fPluginCount:
  428. return
  429. pitem = self.fPluginList[pluginId]
  430. if pitem is None:
  431. return
  432. pitem.widget.setProgram(index, True)
  433. @pyqtSlot(int, int)
  434. def slot_handleMidiProgramChangedCallback(self, pluginId, index):
  435. if pluginId >= self.fPluginCount:
  436. return
  437. pitem = self.fPluginList[pluginId]
  438. if pitem is None:
  439. return
  440. pitem.widget.setMidiProgram(index, True)
  441. # -----------------------------------------------------------------
  442. @pyqtSlot(int, int, bool)
  443. def slot_handleOptionChangedCallback(self, pluginId, option, yesNo):
  444. if pluginId >= self.fPluginCount:
  445. return
  446. pitem = self.fPluginList[pluginId]
  447. if pitem is None:
  448. return
  449. pitem.widget.setOption(option, yesNo)
  450. # -----------------------------------------------------------------
  451. @pyqtSlot(int, int)
  452. def slot_handleUiStateChangedCallback(self, pluginId, state):
  453. if pluginId >= self.fPluginCount:
  454. return
  455. pitem = self.fPluginList[pluginId]
  456. if pitem is None:
  457. return
  458. pitem.widget.customUiStateChanged(state)
  459. # -----------------------------------------------------------------
  460. @pyqtSlot(int, int, int, int)
  461. def slot_handleNoteOnCallback(self, pluginId, channel, note, velo):
  462. if pluginId >= self.fPluginCount:
  463. return
  464. pitem = self.fPluginList[pluginId]
  465. if pitem is None:
  466. return
  467. pitem.widget.sendNoteOn(channel, note)
  468. @pyqtSlot(int, int, int)
  469. def slot_handleNoteOffCallback(self, pluginId, channel, note):
  470. if pluginId >= self.fPluginCount:
  471. return
  472. pitem = self.fPluginList[pluginId]
  473. if pitem is None:
  474. return
  475. pitem.widget.sendNoteOff(channel, note)
  476. # -----------------------------------------------------------------
  477. @pyqtSlot(int)
  478. def slot_handleUpdateCallback(self, pluginId):
  479. if pluginId >= self.fPluginCount:
  480. return
  481. pitem = self.fPluginList[pluginId]
  482. if pitem is None:
  483. return
  484. pitem.widget.fEditDialog.updateInfo()
  485. @pyqtSlot(int)
  486. def slot_handleReloadInfoCallback(self, pluginId):
  487. if pluginId >= self.fPluginCount:
  488. return
  489. pitem = self.fPluginList[pluginId]
  490. if pitem is None:
  491. return
  492. pitem.widget.fEditDialog.reloadInfo()
  493. @pyqtSlot(int)
  494. def slot_handleReloadParametersCallback(self, pluginId):
  495. if pluginId >= self.fPluginCount:
  496. return
  497. pitem = self.fPluginList[pluginId]
  498. if pitem is None:
  499. return
  500. pitem.widget.fEditDialog.reloadParameters()
  501. @pyqtSlot(int)
  502. def slot_handleReloadProgramsCallback(self, pluginId):
  503. if pluginId >= self.fPluginCount:
  504. return
  505. pitem = self.fPluginList[pluginId]
  506. if pitem is None:
  507. return
  508. pitem.widget.fEditDialog.reloadPrograms()
  509. @pyqtSlot(int)
  510. def slot_handleReloadAllCallback(self, pluginId):
  511. if pluginId >= self.fPluginCount:
  512. return
  513. pitem = self.fPluginList[pluginId]
  514. if pitem is None:
  515. return
  516. self.fRack.setCurrentRow(-1)
  517. self.fCurrentRow = -1
  518. self.fLastSelectedItem = None
  519. pitem.reloadAll(pluginId)
  520. # -----------------------------------------------------------------
  521. @pyqtSlot(int)
  522. def slot_currentRowChanged(self, row):
  523. self.fCurrentRow = row
  524. if self.fLastSelectedItem is not None:
  525. self.fLastSelectedItem.setSelected(False)
  526. if row < 0 or row >= self.fPluginCount or self.fPluginList[row] is None:
  527. self.fLastSelectedItem = None
  528. return
  529. pitem = self.fPluginList[row]
  530. pitem.widget.setSelected(True)
  531. self.fLastSelectedItem = pitem.widget
  532. # -----------------------------------------------------------------