summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/python
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-02-27 17:22:17 -0500
committerTom Rondeau <trondeau@vt.edu>2013-02-27 17:29:14 -0500
commiteaedba3fa9969e6579afe986200b128285b3b9c9 (patch)
tree7a2c5bd4e6697d4200215e2251b6078b146ea85a /gnuradio-core/src/python
parentfc911a81fce33ad7127806a8cbe44fa151cea188 (diff)
ctrlport: Allows drag-and-drop from table list to a plotter to add a new curve to the plot.
Diffstat (limited to 'gnuradio-core/src/python')
-rw-r--r--gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py672
-rwxr-xr-xgnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor50
2 files changed, 298 insertions, 424 deletions
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
index 091f0642c6..1bcf6bf807 100644
--- a/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012 Free Software Foundation, Inc.
+# Copyright 2012,2013 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -32,34 +32,68 @@ except ImportError:
print "Error: Program requires PyQt4 and gr-qtgui."
sys.exit(1)
-class GrDataPlotterC(gr.top_block):
- def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+class GrDataPlotParent(gr.top_block, QtGui.QWidget):
+ # Setup signals
+ plotupdated = QtCore.pyqtSignal(QtGui.QWidget)
+
+ def __init__(self, name, rate, pmin=None, pmax=None):
gr.top_block.__init__(self)
+ QtGui.QWidget.__init__(self, None)
- self._stripchart = stripchart
self._name = name
self._npts = 500
- samp_rate = 1.0
+ self._rate = rate
+ self.knobnames = [name,]
+
+ self.layout = QtGui.QVBoxLayout()
+ self.setLayout(self.layout)
+
+ self.setAcceptDrops(True)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ def _setup(self, nconnections):
+ self.stop()
+ self.wait()
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.time_sink_c(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ if(self.layout.count() > 0):
+ # Remove and disconnect. Making sure no references to snk
+ # remain so that the plot gets deleted.
+ self.layout.removeWidget(self.py_window)
+ self.disconnect(self.thr, (self.snk, 0))
+ self.disconnect(self.src[0], self.thr)
+ for n in xrange(1, self._ncons):
+ self.disconnect(self.src[n], (self.snk,n))
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._ncons = nconnections
+ self._data_len = self._ncons*[0,]
- self.snk.set_line_label(0, "Real")
- self.snk.set_line_label(1, "Imag")
+ self.thr = blocks.throttle(self._datasize, self._rate)
+ self.snk = self.get_qtsink()
+
+ self.connect(self.thr, (self.snk, 0))
+
+ self._last_data = []
+ self.src = []
+ for n in xrange(self._ncons):
+ self.set_line_label(n, self.knobnames[n])
+
+ self._last_data.append(int(self._npts)*[0,])
+ self.src.append(self.get_vecsource())
+
+ if(n == 0):
+ self.connect(self.src[n], self.thr)
+ else:
+ self.connect(self.src[n], (self.snk,n))
self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self.layout.addWidget(self.py_window)
+
def __del__(self):
pass
+ def close(self):
+ self.snk.close()
+
def qwidget(self):
return self.py_window
@@ -69,162 +103,162 @@ class GrDataPlotterC(gr.top_block):
def semilogy(self, en=True):
self.snk.enable_semilogy(en)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ def dragEnterEvent(self, e):
+ e.acceptProposedAction()
+
+ def dropEvent(self, e):
+ self.knobnames.append(str(e.mimeData().text()))
+
+ # create a new qwidget plot with the new data stream.
+ self._setup(len(self.knobnames))
+
+ # emit that this plot has been updated with a new qwidget.
+ self.plotupdated.emit(self)
+
+ e.acceptProposedAction()
+
+ def data_to_complex(self, data):
+ if(self._iscomplex):
+ data_r = data[0::2]
+ data_i = data[1::2]
+ data = [complex(r,i) for r,i in zip(data_r, data_i)]
+ return data
def update(self, data):
# Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
+ npts = self.get_npts()
if(self._npts != npts):
# Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
+ for n in xrange(self._ncons):
+ if(npts < self._npts):
+ if(self._data_len[n] < npts):
+ self._last_data[n] = self._last_data[n][0:npts]
+ else:
+ self._last_data[n] = self._last_data[n][self._data_len[n]-npts:self._data_len[n]]
+ self._data_len[n] = npts
else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
+ self._last_data[n] += (npts - self._npts)*[0,]
self._npts = npts
self.snk.reset()
-
+
if(self._stripchart):
# Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) == list):
+ data[n] = self.data_to_complex(data[n])
+ if(len(data[n]) > self._npts):
+ self.src[n].set_data(data[n])
+ self._last_data[n] = data[n][-self._npts:]
+ else:
+ newdata = self._last_data[n][-(self._npts-len(data)):]
+ newdata += data[n]
+ self.src[n].set_data(newdata)
+ self._last_data[n] = newdata
+
+ else: # single value update
+ if(self._iscomplex):
+ data[n] = complex(data[n][0], data[n][1])
+ if(self._data_len[n] < self._npts):
+ self._last_data[n][self._data_len[n]] = data[n]
+ self._data_len[n] += 1
+ else:
+ self._last_data[n] = self._last_data[n][1:]
+ self._last_data[n].append(data[n])
+ self.src[n].set_data(self._last_data[n])
else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ for n in xrange(self._ncons):
+ if(type(data[n]) != list):
+ data[n] = [data[n],]
+ data[n] = self.data_to_complex(data[n])
+ self.src[n].set_data(data[n])
+
+
-class GrDataPlotterF(gr.top_block):
+class GrDataPlotterC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
self._stripchart = stripchart
- self._name = name
- self._npts = 500
- samp_rate = 1.0
+ self._datasize = gr.sizeof_gr_complex
+ self._iscomplex = True
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._setup(1)
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_sink_f(self._npts, samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_qtsink(self):
+ snk = qtgui.time_sink_c(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def __del__(self):
- pass
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
- def qwidget(self):
- return self.py_window
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(2*n+0, "Re{" + self.knobnames[n] + "}")
+ self.snk.set_line_label(2*n+1, "Im{" + self.knobnames[n] + "}")
- def name(self):
- return self._name
- def semilogy(self, en=True):
- self.snk.enable_semilogy(en)
+class GrDataPlotterF(GrDataPlotParent):
+ def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False):
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- def stem(self, en=True):
- self.snk.enable_stem_plot(en)
+ self._stripchart = stripchart
+ self._datasize = gr.sizeof_float
+ self._iscomplex = False
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
+ self._setup(1)
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
+ def stem(self, en=True):
+ self.snk.enable_stem_plot(en)
- if(self._stripchart):
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
- else:
- if(type(data) != list):
- data = [data,]
- self.src.set_data(data)
+ def get_qtsink(self):
+ snk = qtgui.time_sink_f(self._npts, 1.0,
+ self._name, self._ncons)
+ snk.enable_autoscale(True)
+ return snk
+
+ def get_vecsource(self):
+ return gr.vector_source_f([])
+
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
+
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterConst(gr.top_block):
+
+class GrDataPlotterConst(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._npts = 500
- samp_rate = 1.0
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = False
+ self._iscomplex = True
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._setup(1)
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.const_sink_c(self._npts,
- self._name, 1)
- self.snk.enable_autoscale(True)
+ def get_qtsink(self):
+ snk = qtgui.const_sink_c(self._npts,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- self.connect(self.src, self.thr, (self.snk, 0))
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
-
- def __del__(self):
- pass
-
- def qwidget(self):
- return self.py_window
-
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.nsamps()
+ return self._npts
def scatter(self, en=True):
if(en):
@@ -232,327 +266,133 @@ class GrDataPlotterConst(gr.top_block):
else:
self.snk.set_line_style(0, 1)
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.nsamps()
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrDataPlotterPsdC(gr.top_block):
+class GrDataPlotterPsdC(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_gr_complex
+ self._stripchart = True
+ self._iscomplex = True
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
-
- self.src = gr.vector_source_c([])
- self.thr = blocks.throttle(gr.sizeof_gr_complex, rate)
- self.snk = qtgui.freq_sink_c(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._setup(1)
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_c(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- def __del__(self):
- pass
+ def get_vecsource(self):
+ return gr.vector_source_c([])
- def qwidget(self):
- return self.py_window
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- def name(self):
- return self._name
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
-
-class GrDataPlotterPsdF(gr.top_block):
+class GrDataPlotterPsdF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._name = name
- self._samp_rate = 1.0
- self._fftsize = 2048
+ self._datasize = gr.sizeof_float
+ self._stripchart = True
+ self._iscomplex = False
+
+ self._npts = 2048
self._wintype = gr.firdes.WIN_BLACKMAN_hARRIS
self._fc = 0
-
- self._last_data = self._fftsize*[0,]
- self._data_len = 0
-
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.freq_sink_f(self._fftsize, self._wintype,
- self._fc, self._samp_rate,
- self._name, 1)
- self.snk.enable_autoscale(True)
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._setup(1)
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_qtsink(self):
+ snk = qtgui.freq_sink_f(self._npts, self._wintype,
+ self._fc, 1.0,
+ self._name,
+ self._ncons)
+ snk.enable_autoscale(True)
+ return snk
- def __del__(self):
- pass
-
- def qwidget(self):
- return self.py_window
-
- def name(self):
- return self._name
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- fftsize = self.snk.fft_size()
- if(self._fftsize != fftsize):
+ def get_npts(self):
+ self._npts = self.snk.fft_size()
+ return self._npts
- # Adjust buffers to accomodate new settings
- if(fftsize < self._fftsize):
- if(self._data_len < fftsize):
- self._last_data = self._last_data[0:fftsize]
- else:
- self._last_data = self._last_data[self._data_len-fftsize:self._data_len]
- self._data_len = fftsize
- else:
- self._last_data += (fftsize - self._fftsize)*[0,]
- self._fftsize = fftsize
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- data_r = data[0::2]
- data_i = data[1::2]
- data = [complex(r,i) for r,i in zip(data_r, data_i)]
- if(len(data) > self._fftsize):
- self.src.set_data(data)
- self._last_data = data[-self._fftsize:]
- else:
- newdata = self._last_data[-(self._fftsize-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._fftsize):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrTimeRasterF(gr.top_block):
+class GrTimeRasterF(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
-
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self.src = gr.vector_source_f([])
- self.thr = blocks.throttle(gr.sizeof_float, rate)
- self.snk = qtgui.time_raster_sink_f(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._npts = 10
+ self._rows = 40
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._datasize = gr.sizeof_float
+ self._stripchart = False
+ self._iscomplex = False
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ self._setup(1)
- def __del__(self):
- pass
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_f(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def qwidget(self):
- return self.py_window
+ def get_vecsource(self):
+ return gr.vector_source_f([])
- def name(self):
- return self._name
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = int(self.snk.num_cols())
- if(self._npts != npts):
-
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
-class GrTimeRasterB(gr.top_block):
+class GrTimeRasterB(GrDataPlotParent):
def __init__(self, name, rate, pmin=None, pmax=None):
- gr.top_block.__init__(self)
-
- self._name = name
- self._npts = 100
- self._rows = 100
- samp_rate = 1.0
+ GrDataPlotParent.__init__(self, name, rate, pmin, pmax)
- self._last_data = self._npts*[0,]
- self._data_len = 0
+ self._npts = 10
+ self._rows = 40
- self.src = gr.vector_source_b([])
- self.thr = blocks.throttle(gr.sizeof_char, rate)
- self.snk = qtgui.time_raster_sink_b(samp_rate, self._npts, self._rows,
- [], [], self._name, 1)
+ self._datasize = gr.sizeof_char
+ self._stripchart = False
+ self._iscomplex = False
- self.connect(self.src, self.thr, (self.snk, 0))
+ self._setup(1)
- self.py_window = sip.wrapinstance(self.snk.pyqwidget(), QtGui.QWidget)
+ def get_qtsink(self):
+ snk = qtgui.time_raster_sink_b(1.0, self._npts, self._rows,
+ [], [], self._name,
+ self._ncons)
+ return snk
- def __del__(self):
- pass
-
- def qwidget(self):
- return self.py_window
-
- def name(self):
- return self._name
+ def get_vecsource(self):
+ return gr.vector_source_b([])
- def update(self, data):
- # Ask GUI if there has been a change in nsamps
- npts = self.snk.num_cols()
- if(self._npts != npts):
+ def get_npts(self):
+ self._npts = self.snk.num_cols()
+ return self._npts
- # Adjust buffers to accomodate new settings
- if(npts < self._npts):
- if(self._data_len < npts):
- self._last_data = self._last_data[0:npts]
- else:
- self._last_data = self._last_data[self._data_len-npts:self._data_len]
- self._data_len = npts
- else:
- self._last_data += (npts - self._npts)*[0,]
- self._npts = npts
- self.snk.reset()
-
- # Update the plot data depending on type
- if(type(data) == list):
- if(len(data) > self._npts):
- self.src.set_data(data)
- self._last_data = data[-self._npts:]
- else:
- newdata = self._last_data[-(self._npts-len(data)):]
- newdata += data
- self.src.set_data(newdata)
- self._last_data = newdata
-
- else: # single value update
- if(self._data_len < self._npts):
- self._last_data[self._data_len] = data
- self._data_len += 1
- else:
- self._last_data = self._last_data[1:]
- self._last_data.append(data)
- self.src.set_data(self._last_data)
+ def set_line_label(self, n, name):
+ self.snk.set_line_label(n, self.knobnames[n])
class GrDataPlotterValueTable:
diff --git a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
index 3f717da5ca..d5d349a38a 100755
--- a/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
+++ b/gnuradio-core/src/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -55,7 +55,7 @@ class MAINWindow(QtGui.QMainWindow):
def __init__(self, radio, port, interface):
super(MAINWindow, self).__init__()
- self.updateRate = 2000;
+ self.updateRate = 1000;
self.conns = []
self.plots = []
self.knobprops = []
@@ -83,7 +83,7 @@ class MAINWindow(QtGui.QMainWindow):
icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
self.setWindowIcon(icon)
- # Locally turn off ControlPort export from GR. This prevents
+ # Locally turn off ControlPort export from GR. This prevents
# our GR-based plotters from launching their own ControlPort
# instance (and possibly causing a port collision if one has
# been specified).
@@ -222,17 +222,44 @@ class MAINWindow(QtGui.QMainWindow):
else:
self.newPlotPsdC(tag, uid, title)
+ def startDrag(self, e):
+ drag = QtGui.QDrag(self)
+ mime_data = QtCore.QMimeData()
+
+ mime_data.setText(e.text(0))
+ drag.setMimeData(mime_data)
+
+ drop = drag.start()
+
def createPlot(self, plot, uid, title):
plot.start()
self.plots[uid].append(plot)
- self.mdiArea.addSubWindow(plot.qwidget())
- plot.qwidget().setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.mdiArea.addSubWindow(plot)
+ plot.setWindowTitle("{0}: {1}".format(title, plot.name()))
self.connect(plot.qwidget(),
QtCore.SIGNAL('destroyed(QObject*)'),
self.destroyPlot)
- plot.qwidget().show()
+ # when the plot is updated via drag-and-drop, we need to be
+ # notified of the new qwidget that's created so we can
+ # properly destroy it.
+ plot.plotupdated.connect(self.plotUpdated)
+
+ plot.show()
+
+ def plotUpdated(self, q):
+ # the plot has been updated with a new qwidget; make sure this
+ # gets dies to the destroyPlot function.
+ for i, plots in enumerate(self.plots):
+ for p in plots:
+ if(p == q):
+ #plots.remove(p)
+ #plots.append(q)
+ self.connect(q.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ break
def destroyPlot(self, obj):
for plots in self.plots:
@@ -280,7 +307,9 @@ class MAINWindow(QtGui.QMainWindow):
def update(self, knobs, uid):
#sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
for plot in self.plots[uid]:
- data = knobs[plot.name()].value
+ data = []
+ for n in plot.knobnames:
+ data.append(knobs[n].value)
plot.update(data)
plot.stop()
plot.wait()
@@ -636,7 +665,7 @@ class MForm(QtGui.QWidget):
self.constupdatediv = 0
self.tableupdatediv = 0
plotsize=250
-
+
# make table
self.table = GrDataPlotterValueTable(uid, self, 0, 0, 400, 200)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
@@ -644,7 +673,7 @@ class MForm(QtGui.QWidget):
self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed)
self.table.treeWidget.setSortingEnabled(True)
self.table.treeWidget.setDragEnabled(True)
-
+
# add things to layouts
self.horizontalLayout.addWidget(self.table.treeWidget)
@@ -662,6 +691,11 @@ class MForm(QtGui.QWidget):
QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
self.parent.newSub);
+ # Allow drag/drop event from table item to plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'),
+ self.parent.startDrag)
+
def openMenu(self, pos):
index = self.table.treeWidget.selectedIndexes()
item = self.table.treeWidget.itemFromIndex(index[0])