Skip to content

Commit

Permalink
Merge remote-tracking branch 'tom/qtgui/range_type'
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcorgan committed Apr 26, 2015
2 parents 34d490c + 15fc0e3 commit cfd73d7
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 111 deletions.
209 changes: 115 additions & 94 deletions gr-qtgui/grc/qtgui_range.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,105 +6,126 @@
###################################################
-->
<block>
<name>QT GUI Range</name>
<key>variable_qtgui_range</key>
<import>from gnuradio.qtgui import Range, RangeWidget</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#set $win = 'self._%s_win'%$id
<name>QT GUI Range</name>
<key>variable_qtgui_range</key>
<import>from gnuradio.qtgui import Range, RangeWidget</import>
<var_make>self.$(id) = $(id) = $value</var_make>
<make>#set $win = 'self._%s_win'%$id
#set $range = 'self._%s_range'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(range) = Range($start, $stop, $step, $value, $min_len)
$(win) = RangeWidget($range, self.set_$(id), $label, "$widget")
$(win) = RangeWidget($range, self.set_$(id), $label, "$widget", $rangeType)
$(gui_hint()($win))</make>
<callback>self.set_$(id)($value)</callback>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>
<param>
<name>Default Value</name>
<key>value</key>
<value>50</value>
<type>real</type>
</param>
<param>
<name>Start</name>
<key>start</key>
<value>0</value>
<type>real</type>
</param>
<param>
<name>Stop</name>
<key>stop</key>
<value>100</value>
<type>real</type>
</param>
<param>
<name>Step</name>
<key>step</key>
<value>1</value>
<type>real</type>
</param>
<param>
<name>Widget</name>
<key>widget</key>
<value>counter_slider</value>
<type>enum</type>
<hide>part</hide>
<option><name>Counter + Slider</name><key>counter_slider</key></option>
<option><name>Counter</name><key>counter</key></option>
<option><name>Slider</name><key>slider</key></option>
<option><name>Knob</name><key>dial</key></option>
</param>
<param>
<name>Orientation</name>
<key>orient</key>
<value>Qt.Horizontal</value>
<type>enum</type>
<hide>#if $widget() == "slider" then 'part' else 'all'#</hide>
<option>
<name>Horizontal</name>
<key>Qt.Horizontal</key>
<opt>scalepos:BottomScale</opt>
<opt>minfcn:setMinimumWidth</opt>
</option>
<option>
<name>Vertical</name>
<key>Qt.Vertical</key>
<opt>scalepos:LeftScale</opt>
<opt>minfcn:setMinimumHeight</opt>
</option>
</param>
<param>
<name>Minimum Length</name>
<key>min_len</key>
<value>200</value>
<type>int</type>
<hide>part</hide>
</param>
<!-- from min_len <hide>#if $widget().split('_')[0] in ("slider", "counter") then 'part' else 'all'#</hide>-->
<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>
<check>$start &lt;= $value &lt;= $stop</check>
<check>$start &lt; $stop</check>
<doc>
This block creates a variable with a slider. \
Leave the label blank to use the variable id as the label. \
The value must be a real number. \
The value must be between the start and the stop.
<callback>self.set_$(id)($value)</callback>

The GUI hint can be used to position the widget within the application. \
The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
Both the tab specification and the grid position are optional.
</doc>
<param>
<name>Label</name>
<key>label</key>
<value></value>
<type>string</type>
<hide>#if $label() then 'none' else 'part'#</hide>
</param>

<param>
<name>Type</name>
<key>rangeType</key>
<value>"float"</value>
<type>enum</type>
<hide>part</hide>
<option><name>Float</name><key>float</key><opt>type:float</opt></option>
<option><name>Int</name><key>int</key><opt>type:int</opt></option>
</param>

<param>
<name>Default Value</name>
<key>value</key>
<value>50</value>
<type>$rangeType.type</type>
</param>

<param>
<name>Start</name>
<key>start</key>
<value>0</value>
<type>$rangeType.type</type>
</param>

<param>
<name>Stop</name>
<key>stop</key>
<value>100</value>
<type>$rangeType.type</type>
</param>

<param>
<name>Step</name>
<key>step</key>
<value>1</value>
<type>$rangeType.type</type>
</param>

<param>
<name>Widget</name>
<key>widget</key>
<value>counter_slider</value>
<type>enum</type>
<hide>part</hide>
<option><name>Counter + Slider</name><key>counter_slider</key></option>
<option><name>Counter</name><key>counter</key></option>
<option><name>Slider</name><key>slider</key></option>
<option><name>Knob</name><key>dial</key></option>
</param>

<param>
<name>Orientation</name>
<key>orient</key>
<value>Qt.Horizontal</value>
<type>enum</type>
<hide>#if $widget() == "slider" then 'part' else 'all'#</hide>
<option>
<name>Horizontal</name>
<key>Qt.Horizontal</key>
<opt>scalepos:BottomScale</opt>
<opt>minfcn:setMinimumWidth</opt>
</option>
<option>
<name>Vertical</name>
<key>Qt.Vertical</key>
<opt>scalepos:LeftScale</opt>
<opt>minfcn:setMinimumHeight</opt>
</option>
</param>

<param>
<name>Minimum Length</name>
<key>min_len</key>
<value>200</value>
<type>int</type>
<hide>part</hide>
</param>
<!-- from min_len <hide>#if $widget().split('_')[0] in ("slider", "counter") then 'part' else 'all'#</hide>-->

<param>
<name>GUI Hint</name>
<key>gui_hint</key>
<value></value>
<type>gui_hint</type>
<hide>part</hide>
</param>

<check>$start &lt;= $value &lt;= $stop</check>
<check>$start &lt; $stop</check>

<doc>
This block creates a variable with a slider. \
Leave the label blank to use the variable id as the label. \
The value must be a real number. \
The value must be between the start and the stop.

The GUI hint can be used to position the widget within the application. \
The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
Both the tab specification and the grid position are optional.
</doc>
</block>
67 changes: 50 additions & 17 deletions gr-qtgui/python/qtgui/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ def map_range(self, val):


class RangeWidget(QtGui.QWidget):
def __init__(self, ranges, slot, label, style):
def __init__(self, ranges, slot, label, style, rangeType=float):
""" Creates the QT Range widget """
QtGui.QWidget.__init__(self)

self.range = ranges
self.style = style

# rangeType tells the block how to return the value as a standard
self.rangeType = rangeType

# Top-block function to call when any value changes
# Some widgets call this directly when their value changes.
# Others have intermediate functions to map the value into the right range.
Expand All @@ -81,24 +84,26 @@ def __init__(self, ranges, slot, label, style):
layout.addWidget(label)

if style == "dial":
self.d_widget = self.Dial(self, self.range, self.notifyChanged)
self.d_widget = self.Dial(self, self.range, self.notifyChanged, rangeType)
elif style == "slider":
self.d_widget = self.Slider(self, self.range, self.notifyChanged)
self.d_widget = self.Slider(self, self.range, self.notifyChanged, rangeType)
elif style == "counter":
# The counter widget can be directly wired to the notifyChanged slot
self.d_widget = self.Counter(self, self.range, self.notifyChanged)
self.d_widget = self.Counter(self, self.range, self.notifyChanged, rangeType)
else:
# The CounterSlider needs its own internal handlers before calling notifyChanged
self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged)
self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged, rangeType)

layout.addWidget(self.d_widget)
self.setLayout(layout)

class Dial(QtGui.QDial):
""" Creates the range using a dial """
def __init__(self, parent, ranges, slot):
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDial.__init__(self, parent)

self.rangeType = rangeType

# Setup the dial
self.setRange(0, ranges.nsteps-1)
self.setSingleStep(1)
Expand All @@ -116,13 +121,15 @@ def __init__(self, parent, ranges, slot):
def changed(self, value):
""" Handles maping the value to the right range before calling the slot. """
val = self.range.map_range(value)
self.notifyChanged(val)
self.notifyChanged(self.rangeType(val))

class Slider(QtGui.QSlider):
""" Creates the range using a slider """
def __init__(self, parent, ranges, slot):
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QSlider.__init__(self, QtCore.Qt.Horizontal, parent)

self.rangeType = rangeType

# Setup the slider
#self.setFocusPolicy(QtCore.Qt.NoFocus)
self.setRange(0, ranges.nsteps - 1)
Expand All @@ -149,7 +156,7 @@ def __init__(self, parent, ranges, slot):
def changed(self, value):
""" Handle the valueChanged signal and map the value into the correct range """
val = self.range.map_range(value)
self.notifyChanged(val)
self.notifyChanged(self.rangeType(val))

def mousePressEvent(self, event):
if((event.button() == QtCore.Qt.LeftButton)):
Expand All @@ -168,9 +175,11 @@ def mouseMoveEvent(self, event):

class Counter(QtGui.QDoubleSpinBox):
""" Creates the range using a counter """
def __init__(self, parent, ranges, slot):
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDoubleSpinBox.__init__(self, parent)

self.rangeType = rangeType

# Setup the counter
self.setRange(ranges.min, ranges.max)
self.setValue(ranges.default)
Expand All @@ -179,18 +188,25 @@ def __init__(self, parent, ranges, slot):
self.setDecimals(ranges.precision)

# The counter already handles floats and can be connected directly.
self.valueChanged.connect(slot)
self.valueChanged.connect(self.changed)
self.notifyChanged = slot

def changed(self, value):
""" Handle the valueChanged signal by converting to the right type """
self.notifyChanged(self.rangeType(value))

class CounterSlider(QtGui.QWidget):
""" Creates the range using a counter and slider """
def __init__(self, parent, ranges, slot):
def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QWidget.__init__(self, parent)

self.rangeType = rangeType

# Slot to call in the parent
self.notifyChanged = slot

self.slider = RangeWidget.Slider(parent, ranges, self.sliderChanged)
self.counter = RangeWidget.Counter(parent, ranges, self.counterChanged)
self.slider = RangeWidget.Slider(parent, ranges, self.sliderChanged, rangeType)
self.counter = RangeWidget.Counter(parent, ranges, self.counterChanged, rangeType)

# Need another horizontal layout to wrap the other widgets.
layout = Qt.QHBoxLayout()
Expand All @@ -207,8 +223,8 @@ def sliderChanged(self, value):
# If the counter was changed, ignore any of these events
if not self.ignoreSlider:
# Value is already float. Just set the counter
self.counter.setValue(value)
self.notifyChanged(value)
self.counter.setValue(self.rangeType(value))
self.notifyChanged(self.rangeType(value))
self.ignoreSlider = False

def counterChanged(self, value):
Expand All @@ -223,4 +239,21 @@ def counterChanged(self, value):
self.ignoreSlider = True
self.slider.setValue(new)

self.notifyChanged(value)
self.notifyChanged(self.rangeType(value))


if __name__ == "__main__":
from PyQt4 import Qt
import sys

def valueChanged(frequency):
print("Value updated - " + str(frequency))

app = Qt.QApplication(sys.argv)
widget = RangeWidget(Range(0, 100, 10, 1, 100), valueChanged, "Test", "counter_slider", int)

widget.show()
widget.setWindowTitle("Test Qt Range")
app.exec_()

widget = None

0 comments on commit cfd73d7

Please sign in to comment.