Browse Source

Start rework of DigitalPeakMeter class

tags/1.9.6
falkTX 9 years ago
parent
commit
e48c8f753b
1 changed files with 215 additions and 112 deletions
  1. +215
    -112
      source/widgets/digitalpeakmeter.py

+ 215
- 112
source/widgets/digitalpeakmeter.py View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-


# Digital Peak Meter, a custom Qt4 widget # Digital Peak Meter, a custom Qt4 widget
# Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
# Copyright (C) 2011-2015 Filipe Coelho <falktx@falktx.com>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as # modify it under the terms of the GNU General Public License as
@@ -36,151 +36,231 @@ else:
# Widget Class # Widget Class


class DigitalPeakMeter(QWidget): class DigitalPeakMeter(QWidget):
# enum Color
COLOR_GREEN = 1
COLOR_BLUE = 2

# enum Orientation # enum Orientation
HORIZONTAL = 1 HORIZONTAL = 1
VERTICAL = 2 VERTICAL = 2


# enum Color
GREEN = 1
BLUE = 2

# enum Style # enum Style
STYLE_DEFAULT = 1 STYLE_DEFAULT = 1
STYLE_OPENAV = 2 STYLE_OPENAV = 2
STYLE_RNCBC = 3


def __init__(self, parent): def __init__(self, parent):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)


self.fChannels = 0
self.fDrawLines = True
self.fOrientation = self.VERTICAL
# defaults are VERTICAL, COLOR_GREEN, STYLE_DEFAULT

self.fChannelCount = 0
self.fChannelData = []
self.fLastChannelData = []

self.fMeterColor = self.COLOR_GREEN
self.fMeterColorBase = QColor(93, 231, 61)
self.fMeterColorBaseAlt = QColor(15, 110, 15, 100)

self.fMeterLinesEnabled = True
self.fMeterOrientation = self.VERTICAL
self.fMeterStyle = self.STYLE_DEFAULT

self.fMeterBackground = QColor("#111111")
self.fMeterGradient = QLinearGradient(0, 0, 0, 0)

self.fSmoothMultiplier = 1 self.fSmoothMultiplier = 1


self.fColorBackground = QColor("#111111")
self.fGradientMeter = QLinearGradient(0, 0, 1, 1)
self.updateGrandient()


self.fMeterStyle = self.STYLE_DEFAULT
# --------------------------------------------------------------------------------------------------------


self.setChannels(0)
self.setColor(self.GREEN)
def channelCount(self):
return self.fChannelCount


def displayMeter(self, meter, level, forced = False):
if meter <= 0 or meter > self.fChannels:
return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - invalid meter number" % (meter, level))
if not isinstance(level, float):
return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - meter value must be float" % (meter, level))
def setChannelCount(self, count):
if self.fChannelCount == count:
return


i = meter - 1
if count < 0:
return qCritical("DigitalPeakMeter::setChannelCount(%i) - channel count must be a positive integer or zero" % count)


if self.fSmoothMultiplier > 0 and not forced:
level = (self.fLastValueData[i] * self.fSmoothMultiplier + level) / float(self.fSmoothMultiplier + 1)
self.fChannelCount = count
self.fChannelData = []
self.fLastChannelData = []


if level < 0.001:
level = 0.0
elif level > 0.999:
level = 1.0
for x in range(count):
self.fChannelData.append(0.0)
self.fLastChannelData.append(0.0)


if self.fChannelsData[i] != level:
self.fChannelsData[i] = level
self.update()
# --------------------------------------------------------------------------------------------------------

def meterColor(self):
return self.fMeterColor


self.fLastValueData[i] = level
def setMeterColor(self, color):
if self.fMeterColor == color:
return


def setChannels(self, channels):
if channels < 0:
return qCritical("DigitalPeakMeter::setChannels(%i) - 'channels' must be a positive integer" % channels)
if color not in (self.COLOR_GREEN, self.COLOR_BLUE):
return qCritical("DigitalPeakMeter::setMeterColor(%i) - invalid color" % color)


self.fChannels = channels
self.fChannelsData = []
self.fLastValueData = []
self.fMeterColor = color


for x in range(channels):
self.fChannelsData.append(0.0)
self.fLastValueData.append(0.0)
if color == self.COLOR_GREEN:
self.fMeterColorBase = QColor(93, 231, 61)
self.fMeterColorBaseAlt = QColor(15, 110, 15, 100)
elif color == self.COLOR_BLUE:
self.fMeterColorBase = QColor(82, 238, 248)
self.fMeterColorBaseAlt = QColor(15, 15, 110, 100)


def setColor(self, color):
if color == self.GREEN:
self.fColorBase = QColor(93, 231, 61)
self.fColorBaseAlt = QColor(15, 110, 15, 100)
elif color == self.BLUE:
self.fColorBase = QColor(82, 238, 248)
self.fColorBaseAlt = QColor(15, 15, 110, 100)
else:
return qCritical("DigitalPeakMeter::setColor(%i) - invalid color" % color)
self.updateGrandient()

# --------------------------------------------------------------------------------------------------------

def meterLinesEnabled(self):
return self.fMeterLinesEnabled

def setMeterLinesEnabled(self, yesNo):
if self.fMeterLinesEnabled == yesNo:
return

self.fMeterLinesEnabled = yesNo

# --------------------------------------------------------------------------------------------------------

def meterOrientation(self):
return self.fMeterOrientation

def setMeterOrientation(self, orientation):
if self.fMeterOrientation == orientation:
return


self.setOrientation(self.fOrientation)
if orientation not in (self.HORIZONTAL, self.VERTICAL):
return qCritical("DigitalPeakMeter::setMeterOrientation(%i) - invalid orientation" % orientation)

self.fMeterOrientation = orientation

self.updateGrandient()

# --------------------------------------------------------------------------------------------------------

def meterStyle(self):
return self.fMeterStyle


def setMeterStyle(self, style): def setMeterStyle(self, style):
self.fMeterStyle = style
self.setOrientation(self.fOrientation)
if self.fMeterStyle == style:
return


def setLinesEnabled(self, yesNo):
self.fDrawLines = yesNo
if style not in (self.STYLE_DEFAULT, self.STYLE_OPENAV, self.STYLE_RNCBC):
return qCritical("DigitalPeakMeter::setMeterStyle(%i) - invalid style" % style)


def setOrientation(self, orientation):
self.fOrientation = orientation
self.fGradientMeter = QLinearGradient(0, 0, 1, 1)
self.fMeterStyle = style


if self.fMeterStyle == self.STYLE_OPENAV:
self.fGradientMeter.setColorAt(0.0, self.fColorBase)
self.fGradientMeter.setColorAt(1.0, self.fColorBase)
if style == self.STYLE_DEFAULT:
self.fMeterBackground = QColor("#111111")
elif style == self.STYLE_OPENAV:
self.fMeterBackground = QColor("#1A1A1A")
elif style == self.STYLE_RNCBC:
self.fMeterBackground = QColor("#111111")


elif self.fOrientation == self.HORIZONTAL:
self.fGradientMeter.setColorAt(0.0, self.fColorBase)
self.fGradientMeter.setColorAt(0.2, self.fColorBase)
self.fGradientMeter.setColorAt(0.4, self.fColorBase)
self.fGradientMeter.setColorAt(0.6, self.fColorBase)
self.fGradientMeter.setColorAt(0.8, Qt.yellow)
self.fGradientMeter.setColorAt(1.0, Qt.red)
self.updateGrandient()


elif self.fOrientation == self.VERTICAL:
self.fGradientMeter.setColorAt(0.0, Qt.red)
self.fGradientMeter.setColorAt(0.2, Qt.yellow)
self.fGradientMeter.setColorAt(0.4, self.fColorBase)
self.fGradientMeter.setColorAt(0.6, self.fColorBase)
self.fGradientMeter.setColorAt(0.8, self.fColorBase)
self.fGradientMeter.setColorAt(1.0, self.fColorBase)
# --------------------------------------------------------------------------------------------------------


else:
return qCritical("DigitalPeakMeter::setOrientation(%i) - invalid orientation" % orientation)
def smoothMultiplier(self):
return self.fSmoothMultiplier


self.updateSizes()
def setSmoothMultiplier(self, value):
if self.fSmoothMultiplier == value:
return


def setSmoothRelease(self, value):
if not isinstance(value, int):
return qCritical("DigitalPeakMeter::setSmoothMultiplier() - value must be an integer")
if value < 0: if value < 0:
value = 0
elif value > 5:
value = 5
return qCritical("DigitalPeakMeter::setSmoothMultiplier(%i) - value must be >= 0" % value)
if value > 5:
return qCritical("DigitalPeakMeter::setSmoothMultiplier(%i) - value must be < 5" % value)


self.fSmoothMultiplier = value self.fSmoothMultiplier = value


def minimumSizeHint(self):
return QSize(10, 10)
# --------------------------------------------------------------------------------------------------------


def sizeHint(self):
return QSize(self.fWidth, self.fHeight)
def displayMeter(self, meter, level, forced = False):
if not isinstance(meter, int):
return qCritical("DigitalPeakMeter::displayMeter(,) - meter value must be an integer")
if not isinstance(level, float):
return qCritical("DigitalPeakMeter::displayMeter(%i,) - level value must be a float" % (meter,))
if meter <= 0 or meter > self.fChannelCount:
return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - invalid meter number" % (meter, level))


def updateSizes(self):
self.fWidth = self.width()
self.fHeight = self.height()
self.fSizeMeter = 0
i = meter - 1


if self.fOrientation == self.HORIZONTAL:
self.fGradientMeter.setFinalStop(self.fWidth, 0)
if self.fSmoothMultiplier > 0 and not forced:
level = (self.fLastChannelData[i] * float(self.fSmoothMultiplier) + level) / float(self.fSmoothMultiplier + 1)


if self.fChannels > 0:
self.fSizeMeter = self.fHeight / self.fChannels
if level < 0.001:
level = 0.0
elif level > 0.999:
level = 1.0


elif self.fOrientation == self.VERTICAL:
self.fGradientMeter.setFinalStop(0, self.fHeight)
if self.fChannelData[i] != level:
self.fChannelData[i] = level
self.update()

self.fLastChannelData[i] = level

# --------------------------------------------------------------------------------------------------------

def updateGrandient(self):
self.fMeterGradient = QLinearGradient(0, 0, 1, 1)

if self.fMeterStyle == self.STYLE_OPENAV:
self.fMeterGradient.setColorAt(0.0, self.fMeterColorBase)
self.fMeterGradient.setColorAt(1.0, self.fMeterColorBase)


if self.fChannels > 0:
self.fSizeMeter = self.fWidth / self.fChannels
elif self.fMeterOrientation == self.HORIZONTAL:
self.fMeterGradient.setColorAt(0.0, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.2, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.4, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.6, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.8, Qt.yellow)
self.fMeterGradient.setColorAt(1.0, Qt.red)

elif self.fMeterOrientation == self.VERTICAL:
self.fMeterGradient.setColorAt(0.0, Qt.red)
self.fMeterGradient.setColorAt(0.2, Qt.yellow)
self.fMeterGradient.setColorAt(0.4, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.6, self.fMeterColorBase)
self.fMeterGradient.setColorAt(0.8, self.fMeterColorBase)
self.fMeterGradient.setColorAt(1.0, self.fMeterColorBase)

self.updateGrandientFinalStop()

def updateGrandientFinalStop(self):
if self.fMeterOrientation == self.HORIZONTAL:
self.fMeterGradient.setFinalStop(self.width(), 0)

elif self.fMeterOrientation == self.VERTICAL:
self.fMeterGradient.setFinalStop(0, self.height())

# --------------------------------------------------------------------------------------------------------

def minimumSizeHint(self):
return QSize(10, 10)

def sizeHint(self):
return QSize(self.width(), self.height())

# --------------------------------------------------------------------------------------------------------


def paintEvent(self, event): def paintEvent(self, event):
painter = QPainter(self) painter = QPainter(self)
event.accept() event.accept()


width = self.width()
height = self.height()

if self.fMeterStyle == self.STYLE_OPENAV: if self.fMeterStyle == self.STYLE_OPENAV:
painter.setPen(QColor("#1A1A1A")) painter.setPen(QColor("#1A1A1A"))
painter.setBrush(QColor("#1A1A1A")) painter.setBrush(QColor("#1A1A1A"))
@@ -188,35 +268,35 @@ class DigitalPeakMeter(QWidget):
painter.setPen(Qt.black) painter.setPen(Qt.black)
painter.setBrush(Qt.black) painter.setBrush(Qt.black)


painter.drawRect(0, 0, self.fWidth, self.fHeight)
painter.drawRect(0, 0, width, height)


meterX = 0 meterX = 0
startX = -1 if self.fMeterStyle == self.STYLE_OPENAV else 0 startX = -1 if self.fMeterStyle == self.STYLE_OPENAV else 0
padding = 2 if self.fMeterStyle == self.STYLE_OPENAV else 0 padding = 2 if self.fMeterStyle == self.STYLE_OPENAV else 0


painter.setPen(self.fColorBackground)
painter.setBrush(self.fGradientMeter)
painter.setPen(self.fMeterBackground) # FIXME ?
painter.setBrush(self.fMeterGradient)


if self.fMeterStyle == self.STYLE_OPENAV:
color = self.fGradientMeter.stops()[0][1]
painter.setPen(color)
color.setAlphaF(0.5)
painter.setBrush(color)
del color
#if self.fMeterStyle == self.STYLE_OPENAV:
#color = self.fMeterGradient.stops()[0][1]
#painter.setPen(color)
#color.setAlphaF(0.5)
#painter.setBrush(color)
#del color


for i in range(self.fChannels):
for i in range(self.fChannelCount):
level = self.fChannelsData[i] level = self.fChannelsData[i]


if self.fOrientation == self.HORIZONTAL:
value = level * float(self.fWidth)
elif self.fOrientation == self.VERTICAL:
value = float(self.fHeight) - (level * float(self.fHeight))
if self.fMeterOrientation == self.HORIZONTAL:
value = level * float(width)
elif self.fMeterOrientation == self.VERTICAL:
value = float(height) - (level * float(height))
else: else:
value = 0.0 value = 0.0


if self.fOrientation == self.HORIZONTAL:
if self.fMeterOrientation == self.HORIZONTAL:
painter.drawRect(startX, meterX+padding, int(value), self.fSizeMeter-padding*(1 if self.fChannels > 1 else 2)) painter.drawRect(startX, meterX+padding, int(value), self.fSizeMeter-padding*(1 if self.fChannels > 1 else 2))
elif self.fOrientation == self.VERTICAL:
elif self.fMeterOrientation == self.VERTICAL:
painter.drawRect(meterX, int(value), self.fSizeMeter, self.fHeight) painter.drawRect(meterX, int(value), self.fSizeMeter, self.fHeight)


meterX += self.fSizeMeter meterX += self.fSizeMeter
@@ -287,7 +367,30 @@ class DigitalPeakMeter(QWidget):
painter.setPen(QColor(110, 15, 15, 100)) painter.setPen(QColor(110, 15, 15, 100))
painter.drawLine(2, lsmall - (lsmall * 0.96), lfull-2.0, lsmall - (lsmall * 0.96)) painter.drawLine(2, lsmall - (lsmall * 0.96), lfull-2.0, lsmall - (lsmall * 0.96))


# --------------------------------------------------------------------------------------------------------

def resizeEvent(self, event): def resizeEvent(self, event):
self.updateSizes()
self.updateGrandientFinalStop()
QWidget.resizeEvent(self, event) QWidget.resizeEvent(self, event)


# ------------------------------------------------------------------------------------------------------------
# Main Testing

if __name__ == '__main__':
import sys
import resources_rc

if config_UseQt5:
from PyQt5.QtWidgets import QApplication
else:
from PyQt4.QtGui import QApplication

app = QApplication(sys.argv)

gui = DigitalPeakMeter(None)
gui.setChannelCount(2)
gui.displayMeter(1, 0.5)
gui.displayMeter(2, 0.8)
gui.show()

sys.exit(app.exec_())

Loading…
Cancel
Save