| @@ -7,6 +7,11 @@ | |||||
| from abc import abstractmethod | from abc import abstractmethod | ||||
| import markdown | |||||
| import subprocess | |||||
| import shlex | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Imports (PyQt) | # Imports (PyQt) | ||||
| @@ -14,7 +19,7 @@ from qt_compat import qt_config | |||||
| if qt_config == 5: | if qt_config == 5: | ||||
| from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray | from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray | ||||
| from PyQt5.QtGui import QCursor, QIcon, QPalette, QPixmap | |||||
| from PyQt5.QtGui import QCursor, QIcon, QPalette, QPixmap, QFont | |||||
| from PyQt5.QtWidgets import ( | from PyQt5.QtWidgets import ( | ||||
| QDialog, | QDialog, | ||||
| QFileDialog, | QFileDialog, | ||||
| @@ -24,10 +29,13 @@ if qt_config == 5: | |||||
| QScrollArea, | QScrollArea, | ||||
| QVBoxLayout, | QVBoxLayout, | ||||
| QWidget, | QWidget, | ||||
| QGraphicsScene, | |||||
| QGraphicsTextItem, | |||||
| QGraphicsView, | |||||
| ) | ) | ||||
| elif qt_config == 6: | elif qt_config == 6: | ||||
| from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray | from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QByteArray | ||||
| from PyQt6.QtGui import QCursor, QIcon, QPalette, QPixmap | |||||
| from PyQt6.QtGui import QCursor, QIcon, QPalette, QPixmap, QFont | |||||
| from PyQt6.QtWidgets import ( | from PyQt6.QtWidgets import ( | ||||
| QDialog, | QDialog, | ||||
| QFileDialog, | QFileDialog, | ||||
| @@ -37,6 +45,9 @@ elif qt_config == 6: | |||||
| QScrollArea, | QScrollArea, | ||||
| QVBoxLayout, | QVBoxLayout, | ||||
| QWidget, | QWidget, | ||||
| QGraphicsScene, | |||||
| QGraphicsTextItem, | |||||
| QGraphicsView, | |||||
| ) | ) | ||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| @@ -981,6 +992,10 @@ class PluginEdit(QDialog): | |||||
| self.ui.tabWidget.currentWidget().verticalScrollBar().setValue(scrollVal) | self.ui.tabWidget.currentWidget().verticalScrollBar().setValue(scrollVal) | ||||
| def reloadPrograms(self): | def reloadPrograms(self): | ||||
| # jpka: That's wrong place fot it of course, please move to correct one. | |||||
| self._createDescriptionWidgets(self.tr("Description")) | |||||
| # Programs | # Programs | ||||
| self.ui.cb_programs.blockSignals(True) | self.ui.cb_programs.blockSignals(True) | ||||
| self.ui.cb_programs.clear() | self.ui.cb_programs.clear() | ||||
| @@ -1678,6 +1693,92 @@ class PluginEdit(QDialog): | |||||
| #------------------------------------------------------------------ | #------------------------------------------------------------------ | ||||
| def _createDescriptionWidgets(self, tabPageName): | |||||
| if self.fPluginInfo['type'] not in (PLUGIN_INTERNAL, PLUGIN_LV2, PLUGIN_SF2): | |||||
| return | |||||
| # jpka: To be filled from 'rdfs:comment' FIXME | |||||
| strDescrFlatMdHtml = "To be filled from rdfs:comment. Test **bold** & _italic_ markdown." | |||||
| # This one converts to html, i.e. 'unmarkdown's. | |||||
| strDescrHtml = markdown.markdown(strDescrFlatMdHtml) | |||||
| realPluginName = self.fPluginInfo['name'] or "(none)" | |||||
| if self.fPluginInfo['type'] == PLUGIN_LV2: | |||||
| strTemp = self.fPluginInfo['label'] | |||||
| strURI = '<a href=' + strTemp + '>' + strTemp + '</a>' | |||||
| elif self.fPluginInfo['type'] == PLUGIN_SF2: | |||||
| strURI = '<b>' + self.fPluginInfo['maker'] + '</b> using ' +\ | |||||
| '<b>' + self.fPluginInfo['label'] + '</b> sound font' | |||||
| # if with autodetection of sf2dump: | |||||
| # jpka: This adds 'libgig' dependency for 'sf2dump'. | |||||
| # jpka: To be filled with real .sf2 filename, line below is tests only. FIXME | |||||
| strSoundFontFile = '/usr/share/sounds/sf2/' + realPluginName + '.sf2' | |||||
| strCmd = 'sf2dump ' + strSoundFontFile | |||||
| result = subprocess.run(shlex.split | |||||
| (f'sh -c "set -o pipefail ; timeout 0.2 ' + strCmd +\ | |||||
| ' | sed /Samples/q"'), | |||||
| stdout=subprocess.PIPE) | |||||
| ret = result.returncode | |||||
| strCmdHt = '<tt> <u>' + strCmd + '</u> </tt>' | |||||
| if (ret == 0): | |||||
| if MACOS: | |||||
| # jpka: Please check it. FIXME | |||||
| strEOL = '\r' | |||||
| elif WINDOWS: | |||||
| # jpka: Please check it. FIXME | |||||
| strEOL = '\r\n' | |||||
| else: | |||||
| strEOL = '\n' | |||||
| strResult = result.stdout.decode('utf-8')\ | |||||
| .replace('\t', ' • ')\ | |||||
| .replace(strEOL, '<br>') +\ | |||||
| '<i>Please use ' + strCmdHt + ' for full info.</i>' | |||||
| else: | |||||
| strResult = 'Err ' + str(ret) + ' while run ' + strCmdHt + ' .' | |||||
| strDescrHtml = strResult | |||||
| # if no sf2dump: | |||||
| # strDescrHtml = "<small>(No sf2dump support, sorry.)</small>" | |||||
| else: | |||||
| strURI = "Carla Internal Plugin" | |||||
| if self.host.get_program_count(self.fPluginId) == 0: | |||||
| strLoadState = "" | |||||
| else: | |||||
| strLoadState = '<div style="letter-spacing:1px"><br>'\ | |||||
| '<b>Note: </b>This plugin collected some presets for you.<br>'\ | |||||
| 'Use <i>Edit</i> tab, then <i>Load State</i> button.</div>' | |||||
| scene = QGraphicsScene(self) | |||||
| text = QGraphicsTextItem("",None) | |||||
| text.setTextInteractionFlags(Qt.TextSelectableByMouse) | |||||
| # jpka: Should be like this, but not work. FIXME | |||||
| # text.setTextWidth(self.ui.tabWidget.geometry().width()); | |||||
| # text.setTextWidth(self.ui.tabWidget.tabs.geometry().width()); | |||||
| # text.setTextWidth(self.ui.tabWidget.widget(1).geometry().width()); | |||||
| # text.setTextWidth(self.ui.tabWidget.size().width()); | |||||
| text.setTextWidth(600); | |||||
| # text.setFont(QFont("Arial, 16")) # NOTE: All Qt sizes are in Pt; real px~=4/3Pt. | |||||
| text.setHtml('<body>' +\ | |||||
| '<h1>' + realPluginName + '</h1><br>' +\ | |||||
| strURI + '<br><br>' +\ | |||||
| '<div style="line-height:1.25;">' + strDescrHtml + '</div>' +\ | |||||
| strLoadState +\ | |||||
| '<body>'); | |||||
| scene.addItem(text) | |||||
| view = QGraphicsView(scene, self) | |||||
| self.ui.tabWidget.addTab(view, tabPageName) | |||||
| #------------------------------------------------------------------ | |||||
| def testTimer(self): | def testTimer(self): | ||||
| self.fIdleTimerId = self.startTimer(50) | self.fIdleTimerId = self.startTimer(50) | ||||