Collection of tools useful for audio production
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.

374 lines
11KB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Imports (Global)
  4. from PyQt4.QtCore import pyqtSlot, Qt, QTimer, SIGNAL, SLOT
  5. from PyQt4.QtGui import QAbstractSpinBox, QComboBox, QCursor, QDialog, QInputDialog, QMenu, QPainter, QProgressBar, QValidator
  6. from PyQt4.QtGui import QStyleFactory
  7. from math import isnan
  8. # Imports (Custom)
  9. import ui_inputdialog_value
  10. def fix_value(value, minimum, maximum):
  11. if isnan(value):
  12. print("Parameter is NaN! - %f" % value)
  13. return minimum
  14. elif value < minimum:
  15. print("Parameter too low! - %f/%f" % (value, minimum))
  16. return minimum
  17. elif value > maximum:
  18. print("Parameter too high! - %f/%f" % (value, maximum))
  19. return maximum
  20. else:
  21. return value
  22. #QPlastiqueStyle = QStyleFactory.create("Plastique")
  23. # Custom InputDialog with Scale Points support
  24. class CustomInputDialog(QDialog, ui_inputdialog_value.Ui_Dialog):
  25. def __init__(self, parent, label, current, minimum, maximum, step, scalePoints):
  26. QDialog.__init__(self, parent)
  27. self.setupUi(self)
  28. self.label.setText(label)
  29. self.doubleSpinBox.setMinimum(minimum)
  30. self.doubleSpinBox.setMaximum(maximum)
  31. self.doubleSpinBox.setValue(current)
  32. self.doubleSpinBox.setSingleStep(step)
  33. self.ret_value = current
  34. if not scalePoints:
  35. self.groupBox.setVisible(False)
  36. self.resize(200, 0)
  37. else:
  38. text = "<table>"
  39. for scalePoint in scalePoints:
  40. text += "<tr><td align='right'>%f</td><td align='left'> - %s</td></tr>" % (scalePoint['value'], scalePoint['label'])
  41. text += "</table>"
  42. self.textBrowser.setText(text)
  43. self.resize(200, 300)
  44. self.connect(self, SIGNAL("accepted()"), self.setReturnValue)
  45. def setReturnValue(self):
  46. self.ret_value = self.doubleSpinBox.value()
  47. def done(self, r):
  48. QDialog.done(self, r)
  49. self.close()
  50. # Progress-Bar used for ParamSpinBox
  51. class ParamProgressBar(QProgressBar):
  52. def __init__(self, parent):
  53. QProgressBar.__init__(self, parent)
  54. self._minimum = 0.0
  55. self._maximum = 1.0
  56. self._step_small = 0.0
  57. self._rvalue = 0.0
  58. self._label = ""
  59. self._pre_label = " "
  60. self._left_click_down = False
  61. self._textCall = None
  62. self.setMinimum(0)
  63. self.setMaximum(1000)
  64. self.setValue(0)
  65. self.setFormat("(none)")
  66. def set_minimum(self, value):
  67. self._minimum = value
  68. def set_maximum(self, value):
  69. self._maximum = value
  70. def set_value(self, value):
  71. self._rvalue = value
  72. vper = (value - self._minimum) / (self._maximum - self._minimum)
  73. self.setValue(vper * 1000)
  74. def set_label(self, label):
  75. self._label = label.strip()
  76. if self._label == "(coef)":
  77. self._label = ""
  78. self._pre_label = "*"
  79. self.update()
  80. def set_text_call(self, textCall):
  81. self._textCall = textCall
  82. def handleMouseEventPos(self, pos):
  83. xper = float(pos.x()) / self.width()
  84. value = xper * (self._maximum - self._minimum) + self._minimum
  85. if value < self._minimum:
  86. value = self._minimum
  87. elif value > self._maximum:
  88. value = self._maximum
  89. self.emit(SIGNAL("valueChangedFromBar(double)"), value)
  90. def mousePressEvent(self, event):
  91. if event.button() == Qt.LeftButton:
  92. self.handleMouseEventPos(event.pos())
  93. self._left_click_down = True
  94. else:
  95. self._left_click_down = False
  96. QProgressBar.mousePressEvent(self, event)
  97. def mouseMoveEvent(self, event):
  98. if self._left_click_down:
  99. self.handleMouseEventPos(event.pos())
  100. QProgressBar.mouseMoveEvent(self, event)
  101. def mouseReleaseEvent(self, event):
  102. self._left_click_down = False
  103. QProgressBar.mouseReleaseEvent(self, event)
  104. def paintEvent(self, event):
  105. if self._textCall:
  106. self.setFormat("%s %s %s" % (self._pre_label, self._textCall(), self._label))
  107. else:
  108. self.setFormat("%s %f %s" % (self._pre_label, self._rvalue, self._label))
  109. QProgressBar.paintEvent(self, event)
  110. # Special SpinBox used for parameters
  111. class ParamSpinBox(QAbstractSpinBox):
  112. def __init__(self, parent):
  113. QAbstractSpinBox.__init__(self, parent)
  114. self._minimum = 0.0
  115. self._maximum = 1.0
  116. self._default = 0.0
  117. self._value = None
  118. self._step = 0.0
  119. self._step_small = 0.0
  120. self._step_large = 0.0
  121. self._read_only = False
  122. self._scalepoints = None
  123. self._have_scalepoints = False
  124. self.bar = ParamProgressBar(self)
  125. self.bar.setContextMenuPolicy(Qt.NoContextMenu)
  126. self.bar.show()
  127. self.lineEdit().setVisible(False)
  128. self.connect(self.bar, SIGNAL("valueChangedFromBar(double)"), self.handleValueChangedFromBar)
  129. self.connect(self, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomMenu)
  130. QTimer.singleShot(0, self, SLOT("slot_updateBarGeometry()"))
  131. #def force_plastique_style(self):
  132. #self.setStyle(QPlastiqueStyle)
  133. def set_minimum(self, value):
  134. self._minimum = value
  135. self.bar.set_minimum(value)
  136. def set_maximum(self, value):
  137. self._maximum = value
  138. self.bar.set_maximum(value)
  139. def set_default(self, value):
  140. value = fix_value(value, self._minimum, self._maximum)
  141. self._default = value
  142. def set_value(self, value, send=True):
  143. value = fix_value(value, self._minimum, self._maximum)
  144. if self._value != value:
  145. self._value = value
  146. self.bar.set_value(value)
  147. if self._have_scalepoints:
  148. self.set_scalepoint_value(value)
  149. if send:
  150. self.emit(SIGNAL("valueChanged(double)"), value)
  151. self.update()
  152. return True
  153. else:
  154. return False
  155. def set_step(self, value):
  156. if value == 0.0:
  157. self._step = 0.001
  158. else:
  159. self._step = value
  160. def set_step_small(self, value):
  161. if value == 0.0:
  162. self._step_small = 0.0001
  163. else:
  164. self._step_small = value
  165. def set_step_large(self, value):
  166. if value == 0.0:
  167. self._step_large = 0.1
  168. else:
  169. self._step_large = value
  170. def set_label(self, label):
  171. self.bar.set_label(label)
  172. def set_text_call(self, textCall):
  173. self.bar.set_text_call(textCall)
  174. def set_read_only(self, yesno):
  175. self.setButtonSymbols(QAbstractSpinBox.UpDownArrows if yesno else QAbstractSpinBox.NoButtons)
  176. self._read_only = yesno
  177. self.setReadOnly(yesno)
  178. def set_scalepoints(self, scalepoints, use_scalepoints):
  179. if len(scalepoints) > 0:
  180. self._scalepoints = scalepoints
  181. self._have_scalepoints = use_scalepoints
  182. if use_scalepoints:
  183. # Hide ProgressBar and create a ComboBox
  184. self.bar.close()
  185. self.box = QComboBox(self)
  186. self.box.setContextMenuPolicy(Qt.NoContextMenu)
  187. self.box.show()
  188. self.slot_updateBarGeometry()
  189. for scalepoint in scalepoints:
  190. self.box.addItem("%f - %s" % (scalepoint['value'], scalepoint['label']))
  191. if self._value != None:
  192. self.set_scalepoint_value(self._value)
  193. self.connect(self.box, SIGNAL("currentIndexChanged(QString)"), self.handleValueChangedFromBox)
  194. else:
  195. self._scalepoints = None
  196. def set_scalepoint_value(self, value):
  197. value = self.get_nearest_scalepoint(value)
  198. for i in range(self.box.count()):
  199. if float(self.box.itemText(i).split(" - ", 1)[0] == value):
  200. self.box.setCurrentIndex(i)
  201. break
  202. def get_nearest_scalepoint(self, real_value):
  203. final_value = 0.0
  204. for i in range(len(self._scalepoints)):
  205. scale_value = self._scalepoints[i]['value']
  206. if i == 0:
  207. final_value = scale_value
  208. else:
  209. srange1 = abs(real_value - scale_value)
  210. srange2 = abs(real_value - final_value)
  211. if srange2 > srange1:
  212. final_value = scale_value
  213. return final_value
  214. def handleValueChangedFromBar(self, value):
  215. if self._read_only:
  216. return
  217. step = int(0.5 + ((value - self._minimum) / self._step))
  218. real_value = self._minimum + (step * self._step)
  219. self.set_value(real_value)
  220. def handleValueChangedFromBox(self, box_text):
  221. if self._read_only:
  222. return
  223. value = float(box_text.split(" - ", 1)[0])
  224. last_scale_value = self._scalepoints[len(self._scalepoints) - 1]['value']
  225. if value == last_scale_value:
  226. value = self._maximum
  227. self.set_value(value)
  228. def showCustomMenu(self, pos):
  229. menu = QMenu(self)
  230. act_x_reset = menu.addAction(self.tr("Reset (%f)" % self._default))
  231. menu.addSeparator()
  232. act_x_copy = menu.addAction(self.tr("Copy (%f)" % self._value))
  233. if False and not self._read_only:
  234. act_x_paste = menu.addAction(self.tr("Paste (%s)" % "TODO"))
  235. else:
  236. act_x_paste = menu.addAction(self.tr("Paste"))
  237. act_x_paste.setEnabled(False)
  238. menu.addSeparator()
  239. act_x_set = menu.addAction(self.tr("Set value..."))
  240. if self._read_only:
  241. act_x_reset.setEnabled(False)
  242. act_x_paste.setEnabled(False)
  243. act_x_set.setEnabled(False)
  244. # TODO - NOT IMPLEMENTED YET
  245. act_x_copy.setEnabled(False)
  246. act_x_sel = menu.exec_(QCursor.pos())
  247. if act_x_sel == act_x_set:
  248. dialog = CustomInputDialog(self, self.parent().label.text(), self._value, self._minimum, self._maximum, self._step, self._scalepoints)
  249. if dialog.exec_():
  250. value = dialog.ret_value
  251. self.set_value(value)
  252. elif act_x_sel == act_x_copy:
  253. pass
  254. elif act_x_sel == act_x_paste:
  255. pass
  256. elif act_x_sel == act_x_reset:
  257. self.set_value(self._default)
  258. def stepBy(self, steps):
  259. if steps == 0 or self._value == None:
  260. return
  261. value = self._value + (steps * self._step)
  262. if value < self._minimum:
  263. value = self._minimum
  264. elif value > self._maximum:
  265. value = self._maximum
  266. self.set_value(value)
  267. def stepEnabled(self):
  268. if self._read_only or self._value == None:
  269. return QAbstractSpinBox.StepNone
  270. elif self._value <= self._minimum:
  271. return QAbstractSpinBox.StepUpEnabled
  272. elif self._value >= self._maximum:
  273. return QAbstractSpinBox.StepDownEnabled
  274. else:
  275. return QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled
  276. def updateAll(self):
  277. self.update()
  278. self.bar.update()
  279. if self._have_scalepoints:
  280. self.box.update()
  281. @pyqtSlot()
  282. def slot_updateBarGeometry(self):
  283. self.bar.setGeometry(self.lineEdit().geometry())
  284. if self._have_scalepoints:
  285. self.box.setGeometry(self.lineEdit().geometry())
  286. def resizeEvent(self, event):
  287. QTimer.singleShot(0, self, SLOT("slot_updateBarGeometry()"))
  288. QAbstractSpinBox.resizeEvent(self, event)