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.

paramspinbox.py 19KB

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
Frontend widget enhancements (#767) * optimization: MainWindow resize event (no more issue #148) minimap: Brightness-aware shading on side gaps * CarlaStyle: more careful rounded corner drawing Rounded rectangles have transparent corners even with opaque colors. During compositing colors from several such objects are mixed, producing unexpected artifacts. Also outer contour must have bigger rounding - values for inner/outer rects are spreaded to be around of original 2.0px, to preserve original look. * CarlaStyle: better separator color Create separator color from softened text color. * paramspinbox: Keep scrollbar size closer to outer frame Unless QStyle allowes any widget style, or it is entries and scrollbars provide essential way to control or read frame parameters, scrollbar is still set a bit smaller to counter theme-side deviations between scrollbar and spinbox visible height while real height is equal. * CarlaStyle: better light shade * CarlaStyle: fix visible spinbox height regression When spinbox is in one row with scrollbar or entry field, all vertically expanding, spinbox look a bit lower. * CarlaStyle: completed spinbox buttons light border * CarlaStyle: fixed spinbox button rects, better borderwidth balance Integer button rectangles now produce pixel-aligned non-overlaping, still centered rectangles. SpinBox border width is reduced to minimum, right enough to keep entry widget corners out of outer rounded border parts. * CarlaStyle: constification (SpinBox drawing) * CarlaStyle: spinbox drawing fixes Rely to correct buttons rectangles, handle correctly both even and odd spinbox heights. Disappeared buttons highlight glitch, appeared when moving mouse one button to another. * CarlaStyle, SpinBox: contrast highlight margin between buttons * CarlaStyle spinbox: more careful buttons highlight * CarlaStyle, spinbox: better arrows placement * paramspinbox: Hide scrollbar border * CarlaStyle: nicer rounded corners in deep-dark colors (less radius deviation) * CarlaStyle CT_ToolButton: took less space than combobox in same layout As in designer, carla_host.ui has plus/minus buttons size 25x24, with height equal to adjacent combobox. It seems, system carla style already got fix.
6 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
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
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
Frontend widget enhancements (#767) * optimization: MainWindow resize event (no more issue #148) minimap: Brightness-aware shading on side gaps * CarlaStyle: more careful rounded corner drawing Rounded rectangles have transparent corners even with opaque colors. During compositing colors from several such objects are mixed, producing unexpected artifacts. Also outer contour must have bigger rounding - values for inner/outer rects are spreaded to be around of original 2.0px, to preserve original look. * CarlaStyle: better separator color Create separator color from softened text color. * paramspinbox: Keep scrollbar size closer to outer frame Unless QStyle allowes any widget style, or it is entries and scrollbars provide essential way to control or read frame parameters, scrollbar is still set a bit smaller to counter theme-side deviations between scrollbar and spinbox visible height while real height is equal. * CarlaStyle: better light shade * CarlaStyle: fix visible spinbox height regression When spinbox is in one row with scrollbar or entry field, all vertically expanding, spinbox look a bit lower. * CarlaStyle: completed spinbox buttons light border * CarlaStyle: fixed spinbox button rects, better borderwidth balance Integer button rectangles now produce pixel-aligned non-overlaping, still centered rectangles. SpinBox border width is reduced to minimum, right enough to keep entry widget corners out of outer rounded border parts. * CarlaStyle: constification (SpinBox drawing) * CarlaStyle: spinbox drawing fixes Rely to correct buttons rectangles, handle correctly both even and odd spinbox heights. Disappeared buttons highlight glitch, appeared when moving mouse one button to another. * CarlaStyle, SpinBox: contrast highlight margin between buttons * CarlaStyle spinbox: more careful buttons highlight * CarlaStyle, spinbox: better arrows placement * paramspinbox: Hide scrollbar border * CarlaStyle: nicer rounded corners in deep-dark colors (less radius deviation) * CarlaStyle CT_ToolButton: took less space than combobox in same layout As in designer, carla_host.ui has plus/minus buttons size 25x24, with height equal to adjacent combobox. It seems, system carla style already got fix.
6 years ago
Frontend widget enhancements (#767) * optimization: MainWindow resize event (no more issue #148) minimap: Brightness-aware shading on side gaps * CarlaStyle: more careful rounded corner drawing Rounded rectangles have transparent corners even with opaque colors. During compositing colors from several such objects are mixed, producing unexpected artifacts. Also outer contour must have bigger rounding - values for inner/outer rects are spreaded to be around of original 2.0px, to preserve original look. * CarlaStyle: better separator color Create separator color from softened text color. * paramspinbox: Keep scrollbar size closer to outer frame Unless QStyle allowes any widget style, or it is entries and scrollbars provide essential way to control or read frame parameters, scrollbar is still set a bit smaller to counter theme-side deviations between scrollbar and spinbox visible height while real height is equal. * CarlaStyle: better light shade * CarlaStyle: fix visible spinbox height regression When spinbox is in one row with scrollbar or entry field, all vertically expanding, spinbox look a bit lower. * CarlaStyle: completed spinbox buttons light border * CarlaStyle: fixed spinbox button rects, better borderwidth balance Integer button rectangles now produce pixel-aligned non-overlaping, still centered rectangles. SpinBox border width is reduced to minimum, right enough to keep entry widget corners out of outer rounded border parts. * CarlaStyle: constification (SpinBox drawing) * CarlaStyle: spinbox drawing fixes Rely to correct buttons rectangles, handle correctly both even and odd spinbox heights. Disappeared buttons highlight glitch, appeared when moving mouse one button to another. * CarlaStyle, SpinBox: contrast highlight margin between buttons * CarlaStyle spinbox: more careful buttons highlight * CarlaStyle, spinbox: better arrows placement * paramspinbox: Hide scrollbar border * CarlaStyle: nicer rounded corners in deep-dark colors (less radius deviation) * CarlaStyle CT_ToolButton: took less space than combobox in same layout As in designer, carla_host.ui has plus/minus buttons size 25x24, with height equal to adjacent combobox. It seems, system carla style already got fix.
6 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Parameter SpinBox, a custom Qt widget
  4. # Copyright (C) 2011-2019 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 (Global)
  19. from math import isnan, modf
  20. from random import random
  21. from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QTimer
  22. from PyQt5.QtGui import QCursor, QPalette
  23. from PyQt5.QtWidgets import QAbstractSpinBox, QApplication, QComboBox, QDialog, QMenu, QProgressBar
  24. # ------------------------------------------------------------------------------------------------------------
  25. # Imports (Custom)
  26. import ui_inputdialog_value
  27. from carla_shared import countDecimalPoints
  28. # ------------------------------------------------------------------------------------------------------------
  29. # Get a fixed value within min/max bounds
  30. def geFixedValue(name, value, minimum, maximum):
  31. if isnan(value):
  32. print("Parameter '%s' is NaN! - %f" % (name, value))
  33. return minimum
  34. if value < minimum:
  35. print("Parameter '%s' too low! - %f/%f" % (name, value, minimum))
  36. return minimum
  37. if value > maximum:
  38. print("Parameter '%s' too high! - %f/%f" % (name, value, maximum))
  39. return maximum
  40. return value
  41. # ------------------------------------------------------------------------------------------------------------
  42. # Custom InputDialog with Scale Points support
  43. class CustomInputDialog(QDialog):
  44. def __init__(self, parent, label, current, minimum, maximum, step, stepSmall, scalePoints, prefix, suffix):
  45. QDialog.__init__(self, parent)
  46. self.ui = ui_inputdialog_value.Ui_Dialog()
  47. self.ui.setupUi(self)
  48. self.ui.label.setText(label)
  49. self.ui.doubleSpinBox.setDecimals(countDecimalPoints(step, stepSmall))
  50. self.ui.doubleSpinBox.setRange(minimum, maximum)
  51. self.ui.doubleSpinBox.setSingleStep(step)
  52. self.ui.doubleSpinBox.setValue(current)
  53. self.ui.doubleSpinBox.setPrefix(prefix)
  54. self.ui.doubleSpinBox.setSuffix(suffix)
  55. if not scalePoints:
  56. self.ui.groupBox.setVisible(False)
  57. self.resize(200, 0)
  58. else:
  59. text = "<table>"
  60. for scalePoint in scalePoints:
  61. text += "<tr><td align='right'>%f</td><td align='left'> - %s</td></tr>" % (scalePoint['value'], scalePoint['label'])
  62. text += "</table>"
  63. self.ui.textBrowser.setText(text)
  64. self.resize(200, 300)
  65. self.fRetValue = current
  66. self.accepted.connect(self.slot_setReturnValue)
  67. def returnValue(self):
  68. return self.fRetValue
  69. @pyqtSlot()
  70. def slot_setReturnValue(self):
  71. self.fRetValue = self.ui.doubleSpinBox.value()
  72. def done(self, r):
  73. QDialog.done(self, r)
  74. self.close()
  75. # ------------------------------------------------------------------------------------------------------------
  76. # ProgressBar used for ParamSpinBox
  77. class ParamProgressBar(QProgressBar):
  78. # signals
  79. dragStateChanged = pyqtSignal(bool)
  80. valueChanged = pyqtSignal(float)
  81. def __init__(self, parent):
  82. QProgressBar.__init__(self, parent)
  83. self.fLeftClickDown = False
  84. self.fIsInteger = False
  85. self.fIsReadOnly = False
  86. self.fMinimum = 0.0
  87. self.fMaximum = 1.0
  88. self.fInitiated = False
  89. self.fRealValue = 0.0
  90. self.fLastPaintedValue = None
  91. self.fCurrentPaintedText = ""
  92. self.fName = ""
  93. self.fLabelPrefix = ""
  94. self.fLabelSuffix = ""
  95. self.fTextCall = None
  96. self.fValueCall = None
  97. self.setFormat("(none)")
  98. # Fake internal value, 10'000 precision
  99. QProgressBar.setMinimum(self, 0)
  100. QProgressBar.setMaximum(self, 10000)
  101. QProgressBar.setValue(self, 0)
  102. def setMinimum(self, value):
  103. self.fMinimum = value
  104. def setMaximum(self, value):
  105. self.fMaximum = value
  106. def setValue(self, value):
  107. if (self.fRealValue == value or isnan(value)) and self.fInitiated:
  108. return False
  109. self.fInitiated = True
  110. self.fRealValue = value
  111. div = float(self.fMaximum - self.fMinimum)
  112. if div == 0.0:
  113. print("Parameter '%s' division by 0 prevented (value:%f, min:%f, max:%f)" % (self.fName,
  114. value,
  115. self.fMaximum,
  116. self.fMinimum))
  117. vper = 1.0
  118. elif isnan(value):
  119. print("Parameter '%s' is NaN (value:%f, min:%f, max:%f)" % (self.fName,
  120. value,
  121. self.fMaximum,
  122. self.fMinimum))
  123. vper = 1.0
  124. else:
  125. vper = float(value - self.fMinimum) / div
  126. if vper < 0.0:
  127. vper = 0.0
  128. elif vper > 1.0:
  129. vper = 1.0
  130. if self.fValueCall is not None:
  131. self.fValueCall(value)
  132. QProgressBar.setValue(self, int(vper * 10000))
  133. return True
  134. def setSuffixes(self, prefix, suffix):
  135. self.fLabelPrefix = prefix
  136. self.fLabelSuffix = suffix
  137. # force refresh of text value
  138. self.fLastPaintedValue = None
  139. self.update()
  140. def setName(self, name):
  141. self.fName = name
  142. def setReadOnly(self, yesNo):
  143. self.fIsReadOnly = yesNo
  144. def setTextCall(self, textCall):
  145. self.fTextCall = textCall
  146. def setValueCall(self, valueCall):
  147. self.fValueCall = valueCall
  148. def handleMouseEventPos(self, pos):
  149. if self.fIsReadOnly:
  150. return
  151. xper = float(pos.x()) / float(self.width())
  152. value = xper * (self.fMaximum - self.fMinimum) + self.fMinimum
  153. if self.fIsInteger:
  154. value = round(value)
  155. if value < self.fMinimum:
  156. value = self.fMinimum
  157. elif value > self.fMaximum:
  158. value = self.fMaximum
  159. if self.setValue(value):
  160. self.valueChanged.emit(value)
  161. def mousePressEvent(self, event):
  162. if self.fIsReadOnly:
  163. return
  164. if event.button() == Qt.LeftButton:
  165. self.handleMouseEventPos(event.pos())
  166. self.fLeftClickDown = True
  167. self.dragStateChanged.emit(True)
  168. else:
  169. self.fLeftClickDown = False
  170. QProgressBar.mousePressEvent(self, event)
  171. def mouseMoveEvent(self, event):
  172. if self.fIsReadOnly:
  173. return
  174. if self.fLeftClickDown:
  175. self.handleMouseEventPos(event.pos())
  176. QProgressBar.mouseMoveEvent(self, event)
  177. def mouseReleaseEvent(self, event):
  178. if self.fIsReadOnly:
  179. return
  180. self.fLeftClickDown = False
  181. self.dragStateChanged.emit(False)
  182. QProgressBar.mouseReleaseEvent(self, event)
  183. def paintEvent(self, event):
  184. if self.fTextCall is not None:
  185. if self.fLastPaintedValue != self.fRealValue:
  186. self.fLastPaintedValue = self.fRealValue
  187. self.fCurrentPaintedText = self.fTextCall()
  188. self.setFormat("%s%s%s" % (self.fLabelPrefix, self.fCurrentPaintedText, self.fLabelSuffix))
  189. elif self.fIsInteger:
  190. self.setFormat("%s%i%s" % (self.fLabelPrefix, int(self.fRealValue), self.fLabelSuffix))
  191. else:
  192. self.setFormat("%s%f%s" % (self.fLabelPrefix, self.fRealValue, self.fLabelSuffix))
  193. QProgressBar.paintEvent(self, event)
  194. # ------------------------------------------------------------------------------------------------------------
  195. # Special SpinBox used for parameters
  196. class ParamSpinBox(QAbstractSpinBox):
  197. # signals
  198. valueChanged = pyqtSignal(float)
  199. def __init__(self, parent):
  200. QAbstractSpinBox.__init__(self, parent)
  201. self.fName = ""
  202. self.fLabelPrefix = ""
  203. self.fLabelSuffix = ""
  204. self.fMinimum = 0.0
  205. self.fMaximum = 1.0
  206. self.fDefault = 0.0
  207. self.fValue = None
  208. self.fStep = 0.01
  209. self.fStepSmall = 0.0001
  210. self.fStepLarge = 0.1
  211. self.fIsReadOnly = False
  212. self.fScalePoints = None
  213. self.fUseScalePoints = False
  214. self.fBar = ParamProgressBar(self)
  215. self.fBar.setContextMenuPolicy(Qt.NoContextMenu)
  216. #self.fBar.show()
  217. barPalette = self.fBar.palette()
  218. barPalette.setColor(QPalette.Window, Qt.transparent)
  219. self.fBar.setPalette(barPalette)
  220. self.fBox = None
  221. self.lineEdit().hide()
  222. self.customContextMenuRequested.connect(self.slot_showCustomMenu)
  223. self.fBar.valueChanged.connect(self.slot_progressBarValueChanged)
  224. self.dragStateChanged = self.fBar.dragStateChanged
  225. QTimer.singleShot(0, self.slot_updateProgressBarGeometry)
  226. def setDefault(self, value):
  227. value = geFixedValue(self.fName, value, self.fMinimum, self.fMaximum)
  228. self.fDefault = value
  229. def setMinimum(self, value):
  230. self.fMinimum = value
  231. self.fBar.setMinimum(value)
  232. def setMaximum(self, value):
  233. self.fMaximum = value
  234. self.fBar.setMaximum(value)
  235. def setValue(self, value):
  236. if not self.fIsReadOnly:
  237. value = geFixedValue(self.fName, value, self.fMinimum, self.fMaximum)
  238. if self.fBar.fIsInteger:
  239. value = round(value)
  240. if self.fValue == value:
  241. return False
  242. self.fValue = value
  243. self.fBar.setValue(value)
  244. if self.fUseScalePoints:
  245. self._setScalePointValue(value)
  246. self.valueChanged.emit(value)
  247. self.update()
  248. return True
  249. def setStep(self, value):
  250. if value == 0.0:
  251. self.fStep = 0.001
  252. else:
  253. self.fStep = value
  254. if self.fStepSmall > value:
  255. self.fStepSmall = value
  256. if self.fStepLarge < value:
  257. self.fStepLarge = value
  258. self.fBar.fIsInteger = bool(self.fStepSmall == 1.0)
  259. def setStepSmall(self, value):
  260. if value == 0.0:
  261. self.fStepSmall = 0.0001
  262. elif value > self.fStep:
  263. self.fStepSmall = self.fStep
  264. else:
  265. self.fStepSmall = value
  266. self.fBar.fIsInteger = bool(self.fStepSmall == 1.0)
  267. def setStepLarge(self, value):
  268. if value == 0.0:
  269. self.fStepLarge = 0.1
  270. elif value < self.fStep:
  271. self.fStepLarge = self.fStep
  272. else:
  273. self.fStepLarge = value
  274. def setLabel(self, label):
  275. prefix = ""
  276. suffix = label.strip()
  277. if suffix == "(coef)":
  278. prefix = "* "
  279. suffix = ""
  280. else:
  281. suffix = " " + suffix
  282. self.fLabelPrefix = prefix
  283. self.fLabelSuffix = suffix
  284. self.fBar.setSuffixes(prefix, suffix)
  285. def setName(self, name):
  286. self.fName = name
  287. self.fBar.setName(name)
  288. def setTextCallback(self, textCall):
  289. self.fBar.setTextCall(textCall)
  290. def setValueCallback(self, valueCall):
  291. self.fBar.setValueCall(valueCall)
  292. def setReadOnly(self, yesNo):
  293. self.fIsReadOnly = yesNo
  294. self.fBar.setReadOnly(yesNo)
  295. self.setButtonSymbols(QAbstractSpinBox.UpDownArrows if yesNo else QAbstractSpinBox.NoButtons)
  296. QAbstractSpinBox.setReadOnly(self, yesNo)
  297. # FIXME use change event
  298. def setEnabled(self, yesNo):
  299. self.fBar.setEnabled(yesNo)
  300. QAbstractSpinBox.setEnabled(self, yesNo)
  301. def setScalePoints(self, scalePoints, useScalePoints):
  302. if len(scalePoints) == 0:
  303. self.fScalePoints = None
  304. self.fUseScalePoints = False
  305. return
  306. self.fScalePoints = scalePoints
  307. self.fUseScalePoints = useScalePoints
  308. if not useScalePoints:
  309. return
  310. # Hide ProgressBar and create a ComboBox
  311. self.fBar.close()
  312. self.fBox = QComboBox(self)
  313. self.fBox.setContextMenuPolicy(Qt.NoContextMenu)
  314. #self.fBox.show()
  315. self.slot_updateProgressBarGeometry()
  316. # Add items, sorted
  317. boxItemValues = []
  318. for scalePoint in scalePoints:
  319. value = scalePoint['value']
  320. if self.fStep == 1.0:
  321. label = "%i - %s" % (int(value), scalePoint['label'])
  322. else:
  323. label = "%f - %s" % (value, scalePoint['label'])
  324. if len(boxItemValues) == 0:
  325. self.fBox.addItem(label)
  326. boxItemValues.append(value)
  327. else:
  328. if value < boxItemValues[0]:
  329. self.fBox.insertItem(0, label)
  330. boxItemValues.insert(0, value)
  331. elif value > boxItemValues[-1]:
  332. self.fBox.addItem(label)
  333. boxItemValues.append(value)
  334. else:
  335. for index in range(len(boxItemValues)):
  336. if value >= boxItemValues[index]:
  337. self.fBox.insertItem(index+1, label)
  338. boxItemValues.insert(index+1, value)
  339. break
  340. if self.fValue is not None:
  341. self._setScalePointValue(self.fValue)
  342. self.fBox.currentIndexChanged['QString'].connect(self.slot_comboBoxIndexChanged)
  343. def setToolTip(self, text):
  344. self.fBar.setToolTip(text)
  345. QAbstractSpinBox.setToolTip(self, text)
  346. def stepBy(self, steps):
  347. if steps == 0 or self.fValue is None:
  348. return
  349. value = self.fValue + (self.fStep * steps)
  350. if value < self.fMinimum:
  351. value = self.fMinimum
  352. elif value > self.fMaximum:
  353. value = self.fMaximum
  354. self.setValue(value)
  355. def stepEnabled(self):
  356. if self.fIsReadOnly or self.fValue is None:
  357. return QAbstractSpinBox.StepNone
  358. if self.fValue <= self.fMinimum:
  359. return QAbstractSpinBox.StepUpEnabled
  360. if self.fValue >= self.fMaximum:
  361. return QAbstractSpinBox.StepDownEnabled
  362. return (QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled)
  363. def updateAll(self):
  364. self.update()
  365. self.fBar.update()
  366. if self.fBox is not None:
  367. self.fBox.update()
  368. def resizeEvent(self, event):
  369. QAbstractSpinBox.resizeEvent(self, event)
  370. self.slot_updateProgressBarGeometry()
  371. @pyqtSlot(str)
  372. def slot_comboBoxIndexChanged(self, boxText):
  373. if self.fIsReadOnly:
  374. return
  375. value = float(boxText.split(" - ", 1)[0])
  376. lastScaleValue = self.fScalePoints[-1]['value']
  377. if value == lastScaleValue:
  378. value = self.fMaximum
  379. self.setValue(value)
  380. @pyqtSlot(float)
  381. def slot_progressBarValueChanged(self, value):
  382. if self.fIsReadOnly:
  383. return
  384. if value <= self.fMinimum:
  385. realValue = self.fMinimum
  386. elif value >= self.fMaximum:
  387. realValue = self.fMaximum
  388. else:
  389. curStep = int((value - self.fMinimum) / self.fStep + 0.5)
  390. realValue = self.fMinimum + (self.fStep * curStep)
  391. if realValue < self.fMinimum:
  392. realValue = self.fMinimum
  393. elif realValue > self.fMaximum:
  394. realValue = self.fMaximum
  395. self.setValue(realValue)
  396. @pyqtSlot()
  397. def slot_showCustomMenu(self):
  398. clipboard = QApplication.instance().clipboard()
  399. pasteText = clipboard.text()
  400. pasteValue = None
  401. if pasteText:
  402. try:
  403. pasteValue = float(pasteText)
  404. except:
  405. pass
  406. menu = QMenu(self)
  407. actReset = menu.addAction(self.tr("Reset (%f)" % self.fDefault))
  408. actRandom = menu.addAction(self.tr("Random"))
  409. menu.addSeparator()
  410. actCopy = menu.addAction(self.tr("Copy (%f)" % self.fValue))
  411. if pasteValue is None:
  412. actPaste = menu.addAction(self.tr("Paste"))
  413. actPaste.setEnabled(False)
  414. else:
  415. actPaste = menu.addAction(self.tr("Paste (%f)" % pasteValue))
  416. menu.addSeparator()
  417. actSet = menu.addAction(self.tr("Set value..."))
  418. if self.fIsReadOnly:
  419. actReset.setEnabled(False)
  420. actRandom.setEnabled(False)
  421. actPaste.setEnabled(False)
  422. actSet.setEnabled(False)
  423. actSel = menu.exec_(QCursor.pos())
  424. if actSel == actReset:
  425. self.setValue(self.fDefault)
  426. elif actSel == actRandom:
  427. value = random() * (self.fMaximum - self.fMinimum) + self.fMinimum
  428. self.setValue(value)
  429. elif actSel == actCopy:
  430. clipboard.setText("%f" % self.fValue)
  431. elif actSel == actPaste:
  432. self.setValue(pasteValue)
  433. elif actSel == actSet:
  434. dialog = CustomInputDialog(self, self.fName, self.fValue, self.fMinimum, self.fMaximum,
  435. self.fStep, self.fStepSmall, self.fScalePoints,
  436. self.fLabelPrefix, self.fLabelSuffix)
  437. if dialog.exec_():
  438. value = dialog.returnValue()
  439. self.setValue(value)
  440. @pyqtSlot()
  441. def slot_updateProgressBarGeometry(self):
  442. geometry = self.lineEdit().geometry()
  443. dx = geometry.x()-1
  444. dy = geometry.y()-1
  445. geometry.adjust(-dx, -dy, dx, dy)
  446. self.fBar.setGeometry(geometry)
  447. if self.fUseScalePoints:
  448. self.fBox.setGeometry(geometry)
  449. def _getNearestScalePoint(self, realValue):
  450. finalValue = 0.0
  451. for i in range(len(self.fScalePoints)):
  452. scaleValue = self.fScalePoints[i]["value"]
  453. if i == 0:
  454. finalValue = scaleValue
  455. else:
  456. srange1 = abs(realValue - scaleValue)
  457. srange2 = abs(realValue - finalValue)
  458. if srange2 > srange1:
  459. finalValue = scaleValue
  460. return finalValue
  461. def _setScalePointValue(self, value):
  462. value = self._getNearestScalePoint(value)
  463. for i in range(self.fBox.count()):
  464. if float(self.fBox.itemText(i).split(" - ", 1)[0]) == value:
  465. self.fBox.setCurrentIndex(i)
  466. break