From 21cc755839e07f2aae9b5f0bfb075527250c0f56 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul.cercueil@analog.com> Date: Tue, 29 Sep 2015 11:25:47 +0200 Subject: gr-qtgui: update for Qt5 This commit switch the gr-qtgui blocks from being usable with Qt4 to being usable with Qt5. Signed-off-by: Paul Cercueil <paul.cercueil@analog.com> --- gr-qtgui/python/qtgui/range.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'gr-qtgui/python/qtgui') diff --git a/gr-qtgui/python/qtgui/range.py b/gr-qtgui/python/qtgui/range.py index 3eafc9002e..c04ef75422 100755 --- a/gr-qtgui/python/qtgui/range.py +++ b/gr-qtgui/python/qtgui/range.py @@ -21,7 +21,7 @@ # Boston, MA 02110-1301, USA. # -from PyQt4 import Qt, QtCore, QtGui +from PyQt5 import Qt, QtCore, QtWidgets class Range(object): @@ -63,10 +63,10 @@ class Range(object): return (val*self.step+self.min) -class RangeWidget(QtGui.QWidget): +class RangeWidget(QtWidgets.QWidget): def __init__(self, ranges, slot, label, style, rangeType=float): """ Creates the QT Range widget """ - QtGui.QWidget.__init__(self) + QtWidgets.QWidget.__init__(self) self.range = ranges self.style = style @@ -97,10 +97,10 @@ class RangeWidget(QtGui.QWidget): layout.addWidget(self.d_widget) self.setLayout(layout) - class Dial(QtGui.QDial): + class Dial(QtWidgets.QDial): """ Creates the range using a dial """ def __init__(self, parent, ranges, slot, rangeType=float): - QtGui.QDial.__init__(self, parent) + QtWidgets.QDial.__init__(self, parent) self.rangeType = rangeType @@ -123,10 +123,10 @@ class RangeWidget(QtGui.QWidget): val = self.range.map_range(value) self.notifyChanged(self.rangeType(val)) - class Slider(QtGui.QSlider): + class Slider(QtWidgets.QSlider): """ Creates the range using a slider """ def __init__(self, parent, ranges, slot, rangeType=float): - QtGui.QSlider.__init__(self, QtCore.Qt.Horizontal, parent) + QtWidgets.QSlider.__init__(self, QtCore.Qt.Horizontal, parent) self.rangeType = rangeType @@ -165,18 +165,18 @@ class RangeWidget(QtGui.QWidget): event.accept() # Use repaint rather than calling the super mousePressEvent. # Calling super causes issue where slider jumps to wrong value. - QtGui.QSlider.repaint(self) + QtWidgets.QSlider.repaint(self) def mouseMoveEvent(self, event): new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width() self.setValue(new) event.accept() - QtGui.QSlider.repaint(self) + QtWidgets.QSlider.repaint(self) - class Counter(QtGui.QDoubleSpinBox): + class Counter(QtWidgets.QDoubleSpinBox): """ Creates the range using a counter """ def __init__(self, parent, ranges, slot, rangeType=float): - QtGui.QDoubleSpinBox.__init__(self, parent) + QtWidgets.QDoubleSpinBox.__init__(self, parent) self.rangeType = rangeType @@ -195,10 +195,10 @@ class RangeWidget(QtGui.QWidget): """ Handle the valueChanged signal by converting to the right type """ self.notifyChanged(self.rangeType(value)) - class CounterSlider(QtGui.QWidget): + class CounterSlider(QtWidgets.QWidget): """ Creates the range using a counter and slider """ def __init__(self, parent, ranges, slot, rangeType=float): - QtGui.QWidget.__init__(self, parent) + QtWidgets.QWidget.__init__(self, parent) self.rangeType = rangeType -- cgit v1.2.3 From fef76c211cbe6a6c7c0645c181d27635971d841b Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul.cercueil@analog.com> Date: Tue, 21 Jun 2016 18:16:06 +0200 Subject: gr-qtgui: Fix range.py to work with both Qt4 and Qt5 Signed-off-by: Paul Cercueil <paul.cercueil@analog.com> --- gr-qtgui/python/qtgui/CMakeLists.txt | 10 +- gr-qtgui/python/qtgui/range.py | 259 --------------------------------- gr-qtgui/python/qtgui/range.py.cmakein | 258 ++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+), 260 deletions(-) delete mode 100755 gr-qtgui/python/qtgui/range.py create mode 100755 gr-qtgui/python/qtgui/range.py.cmakein (limited to 'gr-qtgui/python/qtgui') diff --git a/gr-qtgui/python/qtgui/CMakeLists.txt b/gr-qtgui/python/qtgui/CMakeLists.txt index 4fa4d0f484..e1a07fddd6 100644 --- a/gr-qtgui/python/qtgui/CMakeLists.txt +++ b/gr-qtgui/python/qtgui/CMakeLists.txt @@ -20,9 +20,17 @@ ######################################################################## include(GrPython) +if (DESIRED_QT_VERSION MATCHES 4) + set(PY_QT_IMPORT "from PyQt4 import Qt, QtCore, QtGui as QtWidgets") +else() + set(PY_QT_IMPORT "from PyQt5 import Qt, QtCore, QtWidgets") +endif() + +configure_file(range.py.cmakein "${CMAKE_CURRENT_BINARY_DIR}/range.py" @ONLY) + GR_PYTHON_INSTALL( FILES __init__.py - range.py + "${CMAKE_CURRENT_BINARY_DIR}/range.py" DESTINATION ${GR_PYTHON_DIR}/gnuradio/qtgui COMPONENT "qtgui_python" ) diff --git a/gr-qtgui/python/qtgui/range.py b/gr-qtgui/python/qtgui/range.py deleted file mode 100755 index c04ef75422..0000000000 --- a/gr-qtgui/python/qtgui/range.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2015 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from PyQt5 import Qt, QtCore, QtWidgets - - -class Range(object): - def __init__(self, minv, maxv, step, default, min_length): - self.min = float(minv) - self.max = float(maxv) - self.step = float(step) - self.default = float(default) - self.min_length = min_length - self.find_precision() - self.find_nsteps() - - def find_precision(self): - # Get the decimal part of the step - temp = str(float(self.step) - int(self.step))[2:] - precision = len(temp) if temp is not '0' else 0 - precision = min(precision, 13) - - if precision == 0 and self.max < 100: - self.precision = 1 # Always have a decimal in this case - else: - self.precision = (precision + 2) if precision > 0 else 0 - - def find_nsteps(self): - self.nsteps = (self.max + self.step - self.min)/self.step - - def demap_range(self, val): - if val > self.max: - val = self.max - if val < self.min: - val = self.min - return ((val-self.min)/self.step) - - def map_range(self, val): - if val > self.nsteps: - val = self.max - if val < 0: - val = 0 - return (val*self.step+self.min) - - -class RangeWidget(QtWidgets.QWidget): - def __init__(self, ranges, slot, label, style, rangeType=float): - """ Creates the QT Range widget """ - QtWidgets.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. - self.notifyChanged = slot - - layout = Qt.QHBoxLayout() - label = Qt.QLabel(label) - layout.addWidget(label) - - if style == "dial": - self.d_widget = self.Dial(self, self.range, self.notifyChanged, rangeType) - elif style == "slider": - 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, rangeType) - else: - # The CounterSlider needs its own internal handlers before calling notifyChanged - self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged, rangeType) - - layout.addWidget(self.d_widget) - self.setLayout(layout) - - class Dial(QtWidgets.QDial): - """ Creates the range using a dial """ - def __init__(self, parent, ranges, slot, rangeType=float): - QtWidgets.QDial.__init__(self, parent) - - self.rangeType = rangeType - - # Setup the dial - self.setRange(0, ranges.nsteps-1) - self.setSingleStep(1) - self.setNotchesVisible(True) - self.range = ranges - - # Round the initial value to the closest tick - temp = int(round(ranges.demap_range(ranges.default), 0)) - self.setValue(temp) - - # Setup the slots - self.valueChanged.connect(self.changed) - self.notifyChanged = 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(self.rangeType(val)) - - class Slider(QtWidgets.QSlider): - """ Creates the range using a slider """ - def __init__(self, parent, ranges, slot, rangeType=float): - QtWidgets.QSlider.__init__(self, QtCore.Qt.Horizontal, parent) - - self.rangeType = rangeType - - # Setup the slider - #self.setFocusPolicy(QtCore.Qt.NoFocus) - self.setRange(0, ranges.nsteps - 1) - self.setTickPosition(2) - self.setSingleStep(1) - self.range = ranges - - # Round the initial value to the closest tick - temp = int(round(ranges.demap_range(ranges.default), 0)) - self.setValue(temp) - - if ranges.nsteps > ranges.min_length: - interval = int(ranges.nsteps/ranges.min_length) - self.setTickInterval(interval) - self.setPageStep(interval) - else: - self.setTickInterval(1) - self.setPageStep(1) - - # Setup the handler function - self.valueChanged.connect(self.changed) - self.notifyChanged = 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(self.rangeType(val)) - - def mousePressEvent(self, event): - if((event.button() == QtCore.Qt.LeftButton)): - new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width() - self.setValue(new) - event.accept() - # Use repaint rather than calling the super mousePressEvent. - # Calling super causes issue where slider jumps to wrong value. - QtWidgets.QSlider.repaint(self) - - def mouseMoveEvent(self, event): - new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width() - self.setValue(new) - event.accept() - QtWidgets.QSlider.repaint(self) - - class Counter(QtWidgets.QDoubleSpinBox): - """ Creates the range using a counter """ - def __init__(self, parent, ranges, slot, rangeType=float): - QtWidgets.QDoubleSpinBox.__init__(self, parent) - - self.rangeType = rangeType - - # Setup the counter - self.setRange(ranges.min, ranges.max) - self.setValue(ranges.default) - self.setSingleStep(ranges.step) - self.setKeyboardTracking(False) - self.setDecimals(ranges.precision) - - # The counter already handles floats and can be connected directly. - 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(QtWidgets.QWidget): - """ Creates the range using a counter and slider """ - def __init__(self, parent, ranges, slot, rangeType=float): - QtWidgets.QWidget.__init__(self, parent) - - self.rangeType = rangeType - - # Slot to call in the parent - self.notifyChanged = slot - - 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() - layout.addWidget(self.slider) - layout.addWidget(self.counter) - self.setLayout(layout) - - # Flag to ignore the slider event caused by a change to the counter. - self.ignoreSlider = False - self.range = ranges - - def sliderChanged(self, value): - """ Handles changing the counter when the slider is updated """ - # 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(self.rangeType(value)) - self.notifyChanged(self.rangeType(value)) - self.ignoreSlider = False - - def counterChanged(self, value): - """ Handles changing the slider when the counter is updated """ - # Get the current slider value and check to see if the new value changes it - current = self.slider.value() - new = int(round(self.range.demap_range(value), 0)) - - # If it needs to change, ignore the slider event - # Otherwise, the slider will cause the counter to round to the nearest tick - if current != new: - self.ignoreSlider = True - self.slider.setValue(new) - - 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 diff --git a/gr-qtgui/python/qtgui/range.py.cmakein b/gr-qtgui/python/qtgui/range.py.cmakein new file mode 100755 index 0000000000..45aa762ae3 --- /dev/null +++ b/gr-qtgui/python/qtgui/range.py.cmakein @@ -0,0 +1,258 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2015 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +@PY_QT_IMPORT@ + +class Range(object): + def __init__(self, minv, maxv, step, default, min_length): + self.min = float(minv) + self.max = float(maxv) + self.step = float(step) + self.default = float(default) + self.min_length = min_length + self.find_precision() + self.find_nsteps() + + def find_precision(self): + # Get the decimal part of the step + temp = str(float(self.step) - int(self.step))[2:] + precision = len(temp) if temp is not '0' else 0 + precision = min(precision, 13) + + if precision == 0 and self.max < 100: + self.precision = 1 # Always have a decimal in this case + else: + self.precision = (precision + 2) if precision > 0 else 0 + + def find_nsteps(self): + self.nsteps = (self.max + self.step - self.min)/self.step + + def demap_range(self, val): + if val > self.max: + val = self.max + if val < self.min: + val = self.min + return ((val-self.min)/self.step) + + def map_range(self, val): + if val > self.nsteps: + val = self.max + if val < 0: + val = 0 + return (val*self.step+self.min) + + +class RangeWidget(QtWidgets.QWidget): + def __init__(self, ranges, slot, label, style, rangeType=float): + """ Creates the QT Range widget """ + QtWidgets.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. + self.notifyChanged = slot + + layout = Qt.QHBoxLayout() + label = Qt.QLabel(label) + layout.addWidget(label) + + if style == "dial": + self.d_widget = self.Dial(self, self.range, self.notifyChanged, rangeType) + elif style == "slider": + 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, rangeType) + else: + # The CounterSlider needs its own internal handlers before calling notifyChanged + self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged, rangeType) + + layout.addWidget(self.d_widget) + self.setLayout(layout) + + class Dial(QtWidgets.QDial): + """ Creates the range using a dial """ + def __init__(self, parent, ranges, slot, rangeType=float): + QtWidgets.QDial.__init__(self, parent) + + self.rangeType = rangeType + + # Setup the dial + self.setRange(0, ranges.nsteps-1) + self.setSingleStep(1) + self.setNotchesVisible(True) + self.range = ranges + + # Round the initial value to the closest tick + temp = int(round(ranges.demap_range(ranges.default), 0)) + self.setValue(temp) + + # Setup the slots + self.valueChanged.connect(self.changed) + self.notifyChanged = 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(self.rangeType(val)) + + class Slider(QtWidgets.QSlider): + """ Creates the range using a slider """ + def __init__(self, parent, ranges, slot, rangeType=float): + QtWidgets.QSlider.__init__(self, QtCore.Qt.Horizontal, parent) + + self.rangeType = rangeType + + # Setup the slider + #self.setFocusPolicy(QtCore.Qt.NoFocus) + self.setRange(0, ranges.nsteps - 1) + self.setTickPosition(2) + self.setSingleStep(1) + self.range = ranges + + # Round the initial value to the closest tick + temp = int(round(ranges.demap_range(ranges.default), 0)) + self.setValue(temp) + + if ranges.nsteps > ranges.min_length: + interval = int(ranges.nsteps/ranges.min_length) + self.setTickInterval(interval) + self.setPageStep(interval) + else: + self.setTickInterval(1) + self.setPageStep(1) + + # Setup the handler function + self.valueChanged.connect(self.changed) + self.notifyChanged = 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(self.rangeType(val)) + + def mousePressEvent(self, event): + if((event.button() == QtCore.Qt.LeftButton)): + new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width() + self.setValue(new) + event.accept() + # Use repaint rather than calling the super mousePressEvent. + # Calling super causes issue where slider jumps to wrong value. + QtWidgets.QSlider.repaint(self) + + def mouseMoveEvent(self, event): + new = self.minimum() + ((self.maximum()-self.minimum()) * event.x()) / self.width() + self.setValue(new) + event.accept() + QtWidgets.QSlider.repaint(self) + + class Counter(QtWidgets.QDoubleSpinBox): + """ Creates the range using a counter """ + def __init__(self, parent, ranges, slot, rangeType=float): + QtWidgets.QDoubleSpinBox.__init__(self, parent) + + self.rangeType = rangeType + + # Setup the counter + self.setRange(ranges.min, ranges.max) + self.setValue(ranges.default) + self.setSingleStep(ranges.step) + self.setKeyboardTracking(False) + self.setDecimals(ranges.precision) + + # The counter already handles floats and can be connected directly. + 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(QtWidgets.QWidget): + """ Creates the range using a counter and slider """ + def __init__(self, parent, ranges, slot, rangeType=float): + QtWidgets.QWidget.__init__(self, parent) + + self.rangeType = rangeType + + # Slot to call in the parent + self.notifyChanged = slot + + 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() + layout.addWidget(self.slider) + layout.addWidget(self.counter) + self.setLayout(layout) + + # Flag to ignore the slider event caused by a change to the counter. + self.ignoreSlider = False + self.range = ranges + + def sliderChanged(self, value): + """ Handles changing the counter when the slider is updated """ + # 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(self.rangeType(value)) + self.notifyChanged(self.rangeType(value)) + self.ignoreSlider = False + + def counterChanged(self, value): + """ Handles changing the slider when the counter is updated """ + # Get the current slider value and check to see if the new value changes it + current = self.slider.value() + new = int(round(self.range.demap_range(value), 0)) + + # If it needs to change, ignore the slider event + # Otherwise, the slider will cause the counter to round to the nearest tick + if current != new: + self.ignoreSlider = True + self.slider.setValue(new) + + 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 -- cgit v1.2.3