summaryrefslogtreecommitdiff
path: root/gr-qtgui/python/qtgui/levelgauge.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-qtgui/python/qtgui/levelgauge.py')
-rw-r--r--gr-qtgui/python/qtgui/levelgauge.py214
1 files changed, 214 insertions, 0 deletions
diff --git a/gr-qtgui/python/qtgui/levelgauge.py b/gr-qtgui/python/qtgui/levelgauge.py
new file mode 100644
index 0000000000..cee33eb58d
--- /dev/null
+++ b/gr-qtgui/python/qtgui/levelgauge.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2020 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+from threading import Lock
+import sys
+
+from PyQt5.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QLabel, QProgressBar
+from PyQt5.QtGui import QColor
+from PyQt5.QtCore import Qt as Qtc
+from PyQt5.QtCore import pyqtSignal
+from PyQt5.QtGui import QPalette
+
+from gnuradio import gr
+import pmt
+
+class LabeledLevelGauge(QFrame):
+ # Positions: 1 = above, 2=below, 3=left, 4=right
+ def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black',
+ minValue=0, maxValue=100, maxSize=80, position=1, isVertical=True,
+ isFloat=False, scaleFactor=1, showValue=False, parent=None):
+ QFrame.__init__(self, parent)
+ self.numberControl = LevelGauge(barColor, backgroundColor, minValue, maxValue,
+ maxSize, isVertical, isFloat, scaleFactor, showValue,
+ parent)
+
+ if position < 3:
+ layout = QVBoxLayout()
+ else:
+ layout = QHBoxLayout()
+
+ self.lbl = lbl
+ self.showvalue = showValue
+ self.isFloat = isFloat
+ self.isVertical = isVertical
+ self.scaleFactor = scaleFactor
+
+ self.lblcontrol = QLabel(lbl, self)
+ self.lblcontrol.setAlignment(Qtc.AlignCenter)
+
+ # For whatever reason, the progressbar doesn't show the number in the bar if it's
+ # vertical, only if it's horizontal
+ if self.showvalue and (isFloat or self.isVertical):
+ textstr = self.buildTextStr(minValue/self.scaleFactor)
+ self.lblcontrol.setText(textstr)
+
+ if fontColor != 'default':
+ self.lblcontrol.setStyleSheet("QLabel { color : " + fontColor + "; }")
+
+ # add top or left
+ if len:
+ if position == 1 or position == 3:
+ layout.addWidget(self.lblcontrol)
+ else:
+ self.hasLabel = False
+
+ layout.addWidget(self.numberControl)
+
+ # Add bottom or right
+ if len:
+ if position == 2 or position == 4:
+ layout.addWidget(self.lblcontrol)
+
+ layout.setAlignment(Qtc.AlignCenter | Qtc.AlignVCenter)
+ self.setLayout(layout)
+
+ self.show()
+
+ def buildTextStr(self, new_value):
+ textstr = ""
+ if len(self.lbl) > 0:
+ textstr = self.lbl + " - "
+
+ if self.isFloat:
+ textstr += "%.2f" % (new_value)
+ else:
+ textstr += str(new_value)
+
+ return textstr
+
+ def valChanged(self, new_value):
+ if not self.showvalue:
+ return
+
+ if self.isFloat or self.isVertical:
+ if self.lbl:
+ textstr = self.buildTextStr(new_value)
+ self.lblcontrol.setText(textstr)
+
+ def setValue(self, new_value):
+ self.valChanged(new_value)
+
+ if int(self.scaleFactor) != 1:
+ new_value = int(new_value * self.scaleFactor)
+
+ self.numberControl.setValue(new_value)
+
+class LevelGauge(QProgressBar):
+ # Notifies to avoid thread conflicts on paints
+ updateInt = pyqtSignal(int)
+ updateFloat = pyqtSignal(float)
+
+ def __init__(self, barColor='blue', backgroundColor='white', minValue=0, maxValue=100,
+ maxSize=80, isVertical=True, isFloat=False, scaleFactor=1, showValue=False,
+ parent=None):
+ super().__init__(parent)
+
+ self.updateInt.connect(self.onUpdateInt)
+ self.updateFloat.connect(self.onUpdateFloat)
+
+ self.lock = Lock()
+
+ self.maxSize = maxSize
+
+ p = super().palette()
+
+ if backgroundColor != 'default':
+ p.setColor(QPalette.Base, QColor(backgroundColor))
+
+ if barColor != 'default':
+ p.setColor(QPalette.Highlight, QColor(barColor))
+
+ if backgroundColor != 'default' or barColor != 'default':
+ super().setPalette(p)
+
+ if (not isFloat) and showValue:
+ super().setFormat("%v") # This shows the number in the bar itself.
+ super().setTextVisible(True)
+ else:
+ super().setTextVisible(False)
+
+ super().setMinimum(minValue)
+ super().setMaximum(maxValue)
+
+ if isVertical:
+ super().setOrientation(Qtc.Vertical)
+ else:
+ super().setOrientation(Qtc.Horizontal)
+
+ def onUpdateInt(self, new_value):
+ if new_value > super().maximum():
+ new_value = super().maximum()
+ elif new_value < super().minimum():
+ new_value = super().minimum()
+
+ self.lock.acquire()
+ super().setValue(new_value)
+ self.lock.release()
+
+ def onUpdateFloat(self, new_value):
+ if new_value > super().maximum():
+ new_value = super().maximum()
+ elif new_value < super().minimum():
+ new_value = super().minimum()
+
+ self.lock.acquire()
+ super().setValue(new_value)
+ self.lock.release()
+
+ def setValue(self, new_value):
+ if type(new_value) == int:
+ self.updateInt.emit(new_value)
+ else:
+ self.updateFloat.emit(new_value)
+
+class GrLevelGauge(gr.sync_block, LabeledLevelGauge):
+ """
+ This block creates a level gauge. The value can be set either
+ with a variable or an input message.
+
+ NOTE: This control has some quirks due to the fact that
+ QProgressBar only accepts integers. If you want to work with
+ floats, you have to use the scaleFactor to map incoming values
+ to the specified min/max range. For instance if the min/max
+ are 0-100 but your incoming values are 0.0-1.0, you will need
+ to set a scalefactor of 100.
+ """
+ def __init__(self, lbl='', barColor='blue', backgroundColor='white', fontColor='black',
+ minValue=0, maxValue=100, maxSize=80, isVertical=True, position=1,
+ isFloat=False, scaleFactor=1, showValue=False, parent=None):
+ gr.sync_block.__init__(self, name="LevelGauge", in_sig=None, out_sig=None)
+ LabeledLevelGauge.__init__(self, lbl, barColor, backgroundColor, fontColor, minValue,
+ maxValue, maxSize, position, isVertical, isFloat,
+ scaleFactor, showValue, parent)
+ self.lbl = lbl
+
+ if minValue > maxValue:
+ gr.log.error("Min value is greater than max value.")
+ sys.exit(1)
+
+ self.message_port_register_in(pmt.intern("value"))
+ self.set_msg_handler(pmt.intern("value"), self.msgHandler)
+
+ def msgHandler(self, msg):
+ try:
+ new_val = pmt.to_python(pmt.cdr(msg))
+
+ if type(new_val) == float or type(new_val) == int:
+ super().setValue(new_val)
+ else:
+ gr.log.error("Value received was not an int or a float: %s" % str(type(new_val)))
+
+ except Exception as e:
+ gr.log.error("Error with message conversion: %s" % str(e))
+
+ def setValue(self, new_value):
+ super().setValue(new_value)