diff options
author | Tom Rondeau | 2011-04-08 15:37:29 -0400 |
---|---|---|
committer | Tom Rondeau | 2011-04-08 15:37:29 -0400 |
commit | 21b64f070a3eb38ab044529a6ddd9cd6b6d0a2cb (patch) | |
tree | 4e72909a051b0a4ac428252d15f34b53bcc986b6 /gr-qtgui | |
parent | d7093fd06d0ec37f6ba2841d202fe90f4fa3661e (diff) | |
parent | 5c358afd00347f5da7a59dd73ea79cd3df26659d (diff) | |
download | gnuradio-21b64f070a3eb38ab044529a6ddd9cd6b6d0a2cb.tar.gz gnuradio-21b64f070a3eb38ab044529a6ddd9cd6b6d0a2cb.tar.bz2 gnuradio-21b64f070a3eb38ab044529a6ddd9cd6b6d0a2cb.zip |
Merge branch 'master' into constell_obj
Conflicts:
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
gr-audio-oss/src/Makefile.swig.gen
gr-audio/swig/Makefile.swig.gen
Diffstat (limited to 'gr-qtgui')
-rw-r--r-- | gr-qtgui/Makefile.am | 7 | ||||
-rw-r--r-- | gr-qtgui/grc/.gitignore | 2 | ||||
-rw-r--r-- | gr-qtgui/grc/Makefile.am | 33 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_check_box.xml | 83 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_chooser.xml | 251 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_entry.xml | 68 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_label.xml | 66 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_range.xml | 211 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_sink_x.xml | 136 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_tab_widget.xml | 84 | ||||
-rw-r--r-- | gr-qtgui/src/lib/qtgui.h | 17 | ||||
-rw-r--r-- | gr-qtgui/src/lib/qtgui_sink_c.cc | 13 | ||||
-rw-r--r-- | gr-qtgui/src/lib/qtgui_sink_c.h | 4 | ||||
-rw-r--r-- | gr-qtgui/src/lib/qtgui_sink_f.cc | 13 | ||||
-rw-r--r-- | gr-qtgui/src/lib/qtgui_sink_f.h | 4 | ||||
-rw-r--r-- | gr-qtgui/src/python/.gitignore | 1 | ||||
-rw-r--r-- | gr-qtgui/src/python/Makefile.am | 21 | ||||
-rwxr-xr-x | gr-qtgui/src/python/qa_qtgui.py | 46 | ||||
-rw-r--r-- | gr-qtgui/src/python/run_tests.in | 10 |
19 files changed, 1034 insertions, 36 deletions
diff --git a/gr-qtgui/Makefile.am b/gr-qtgui/Makefile.am index d53f96c1f..e794266cb 100644 --- a/gr-qtgui/Makefile.am +++ b/gr-qtgui/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008-2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,3 +23,8 @@ include $(top_srcdir)/Makefile.common SUBDIRS = src DIST_SUBDIRS = src + +if PYTHON +SUBDIRS += grc +DIST_SUBDIRS += grc +endif diff --git a/gr-qtgui/grc/.gitignore b/gr-qtgui/grc/.gitignore new file mode 100644 index 000000000..b336cc7ce --- /dev/null +++ b/gr-qtgui/grc/.gitignore @@ -0,0 +1,2 @@ +/Makefile +/Makefile.in diff --git a/gr-qtgui/grc/Makefile.am b/gr-qtgui/grc/Makefile.am new file mode 100644 index 000000000..b3114268c --- /dev/null +++ b/gr-qtgui/grc/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2010-2011 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. +# + +include $(top_srcdir)/Makefile.common + +grcblocksdir = $(grc_blocksdir) + +dist_grcblocks_DATA = \ + qtgui_check_box.xml \ + qtgui_entry.xml \ + qtgui_label.xml \ + qtgui_range.xml \ + qtgui_sink_x.xml \ + qtgui_tab_widget.xml \ + qtgui_chooser.xml diff --git a/gr-qtgui/grc/qtgui_check_box.xml b/gr-qtgui/grc/qtgui_check_box.xml new file mode 100644 index 000000000..95f4f968a --- /dev/null +++ b/gr-qtgui/grc/qtgui_check_box.xml @@ -0,0 +1,83 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Variable Check Box: +## a gui check box form +################################################### + --> +<block> + <name>QT GUI Check Box</name> + <key>variable_qtgui_check_box</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <var_make>self.$(id) = $(id) = $value</var_make> + <make>#set $win = '_%s_check_box'%$id +#if not $label() + #set $label = '"%s"'%$id +#end if +$win = Qt.QCheckBox($label) +self._$(id)_choices = {True: $true, False: $false} +self._$(id)_choices_inv = dict((v,k) for k,v in self._$(id)_choices.iteritems()) +self._$(id)_callback = lambda i: $(win).setChecked(self._$(id)_choices_inv[i]) +self._$(id)_callback(self.$id) +$(win).stateChanged.connect(lambda i: self.set_$(id)(self._$(id)_choices[bool(i)])) +$(gui_hint()($win))</make> + <callback>self.set_$(id)($value)</callback> + <callback>self._$(id)_callback($id)</callback> + <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>type</key> + <value>int</value> + <type>enum</type> + <hide>part</hide> + <option><name>Float</name><key>real</key><opt>conv:float</opt></option> + <option><name>Integer</name><key>int</key><opt>conv:int</opt></option> + <option><name>String</name><key>string</key><opt>conv:str</opt></option> + <option><name>Boolean</name><key>bool</key><opt>conv:bool</opt></option> + <option><name>Any</name><key>raw</key><opt>conv:eval</opt></option> + </param> + <param> + <name>Default Value</name> + <key>value</key> + <value>True</value> + <type>$type</type> + </param> + <param> + <name>True</name> + <key>true</key> + <value>True</value> + <type>$type</type> + </param> + <param> + <name>False</name> + <key>false</key> + <value>False</value> + <type>$type</type> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <check>$value in ($true, $false)</check> + <doc> +This block creates a variable check box. \ +Leave the label blank to use the variable id as the label. + +A check box selects between two values of similar type. \ +Te values do not necessarily need to be of boolean type. + +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> diff --git a/gr-qtgui/grc/qtgui_chooser.xml b/gr-qtgui/grc/qtgui_chooser.xml new file mode 100644 index 000000000..cb5090289 --- /dev/null +++ b/gr-qtgui/grc/qtgui_chooser.xml @@ -0,0 +1,251 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Variable Chooser: +## A chooser, radio buttons +################################################### + --> +<block> + <name>QT GUI Chooser</name> + <key>variable_qtgui_chooser</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <var_make>self.$(id) = $(id) = $value</var_make> + <make>#slurp +#set $all_options = [$option0, $option1, $option2, $option3, $option4][:int($num_opts())] +#set $all_labels = [$label0, $label1, $label2, $label3, $label4][:int($num_opts())] +#if not $label() + #set $label = '"%s"'%$id +#end if +######################################################################## +## Create the options list +######################################################################## +#if int($num_opts()) +self._$(id)_options = (#slurp + #for $ch in $all_options +$ch, #slurp + #end for +) +#else +self._$(id)_options = $options +#end if +######################################################################## +## Create the labels list +######################################################################## +#if int($num_opts()) +self._$(id)_labels = (#slurp + #for i, $lbl in enumerate($all_labels) + #if $lbl() +$lbl, #slurp + #else +str(self._$(id)_options[$i]), #slurp + #end if + #end for +) +#elif $labels() +self._$(id)_labels = $labels +#else +self._$(id)_labels = map(str, self._$(id)_options) +#end if +######################################################################## +## Create the combo box +######################################################################## +#if $widget() == 'combo_box' +#set $win = 'self._%s_tool_bar'%$id +$win = Qt.QToolBar(self) +$(win).addWidget(Qt.QLabel($label+": ")) +self._$(id)_combo_box = Qt.QComboBox() +$(win).addWidget(self._$(id)_combo_box) +for label in self._$(id)_labels: self._$(id)_combo_box.addItem(label) +self._$(id)_callback = lambda i: self._$(id)_combo_box.setCurrentIndex(self._$(id)_options.index(i)) +self._$(id)_callback(self.$id) +self._$(id)_combo_box.currentIndexChanged.connect( + lambda i: self.set_$(id)(self._$(id)_options[i])) +#end if +######################################################################## +## Create the radio buttons +######################################################################## +#if $widget() == 'radio_buttons' +#set $win = 'self._%s_group_box'%$id +$win = Qt.QGroupBox($label) +self._$(id)_box = $(orient)() +self._$(id)_button_group = Qt.QButtonGroup() +$(win).setLayout(self._$(id)_box) +for i, label in enumerate(self._$(id)_labels): + radio_button = Qt.QRadioButton(label) + self._$(id)_box.addWidget(radio_button) + self._$(id)_button_group.addButton(radio_button, i) +self._$(id)_callback = lambda i: self._$(id)_button_group.button(self._$(id)_options.index(i)).setChecked(True) +self._$(id)_callback(self.$id) +self._$(id)_button_group.buttonClicked[int].connect( + lambda i: self.set_$(id)(self._$(id)_options[i])) +#end if +$(gui_hint()($win))</make> + <callback>self.set_$(id)($value)</callback> + <callback>self._$(id)_callback($id)</callback> + <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>type</key> + <value>int</value> + <type>enum</type> + <hide>part</hide> + <option><name>Float</name><key>real</key></option> + <option><name>Integer</name><key>int</key></option> + <option><name>String</name><key>string</key></option> + <option><name>Any</name><key>raw</key></option> + </param> + <param> + <name>Num Options</name> + <key>num_opts</key> + <value>3</value> + <type>enum</type> + <option><name>List</name><key>0</key></option> + <option><name>1</name><key>1</key></option> + <option><name>2</name><key>2</key></option> + <option><name>3</name><key>3</key></option> + <option><name>4</name><key>4</key></option> + <option><name>5</name><key>5</key></option> + </param> + <param> + <name>Default Value</name> + <key>value</key> + <value>0</value> + <type>$type</type> + </param> + <param> + <name>Options</name> + <key>options</key> + <value>[0, 1, 2]</value> + <type>raw</type> + <hide>#if int($num_opts()) then 'all' else 'none'#</hide> + </param> + <param> + <name>Labels</name> + <key>labels</key> + <value>[]</value> + <type>raw</type> + <hide>#if int($num_opts()) then 'all' else 'none'#</hide> + </param> + <param> + <name>Option 0</name> + <key>option0</key> + <value>0</value> + <type>$type</type> + <hide>#if int($num_opts()) > 0 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 0</name> + <key>label0</key> + <value></value> + <type>string</type> + <hide>$((int($num_opts()) > 0) and ($label0() and 'none' or 'part') or 'all')</hide> + </param> + <param> + <name>Option 1</name> + <key>option1</key> + <value>1</value> + <type>$type</type> + <hide>#if int($num_opts()) > 1 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 1</name> + <key>label1</key> + <value></value> + <type>string</type> + <hide>$((int($num_opts()) > 1) and ($label1() and 'none' or 'part') or 'all')</hide> + </param> + <param> + <name>Option 2</name> + <key>option2</key> + <value>2</value> + <type>$type</type> + <hide>#if int($num_opts()) > 2 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 2</name> + <key>label2</key> + <value></value> + <type>string</type> + <hide>$((int($num_opts()) > 2) and ($label2() and 'none' or 'part') or 'all')</hide> + </param> + <param> + <name>Option 3</name> + <key>option3</key> + <value>3</value> + <type>$type</type> + <hide>#if int($num_opts()) > 3 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 3</name> + <key>label3</key> + <value></value> + <type>string</type> + <hide>$((int($num_opts()) > 3) and ($label3() and 'none' or 'part') or 'all')</hide> + </param> + <param> + <name>Option 4</name> + <key>option4</key> + <value>4</value> + <type>$type</type> + <hide>#if int($num_opts()) > 4 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 4</name> + <key>label4</key> + <value></value> + <type>string</type> + <hide>$((int($num_opts()) > 4) and ($label4() and 'none' or 'part') or 'all')</hide> + </param> + <param> + <name>Widget</name> + <key>widget</key> + <value>combo_box</value> + <type>enum</type> + <hide>part</hide> + <option><name>Combo Box</name><key>combo_box</key></option> + <option><name>Radio Buttons</name><key>radio_buttons</key></option> + </param> + <param> + <name>Orientation</name> + <key>orient</key> + <value>Qt.QVBoxLayout</value> + <type>enum</type> + <hide>#if $widget() == 'radio_buttons' then 'part' else 'all'#</hide> + <option> + <name>Horizontal</name> + <key>Qt.QHBoxLayout</key> + </option> + <option> + <name>Vertical</name> + <key>Qt.QVBoxLayout</key> + </option> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <doc> +This block creates a variable with enumerated options. \ +The gui widget is implemented as a combo box or radio button group. \ +Leave the label blank to use the variable id as the label. + +Choose the number of options available to your chooser. \ +When the label is left blank, the option will be used as the label. \ +Set the number of options to "list" to enter a single list of options and labels. \ +When the labels is an empty list, the options will be used as the label. + +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> diff --git a/gr-qtgui/grc/qtgui_entry.xml b/gr-qtgui/grc/qtgui_entry.xml new file mode 100644 index 000000000..1a98402a0 --- /dev/null +++ b/gr-qtgui/grc/qtgui_entry.xml @@ -0,0 +1,68 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Variable Text Entry: +## a gui text box form +################################################### + --> +<block> + <name>QT GUI Entry</name> + <key>variable_qtgui_entry</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <import>from gnuradio import eng_notation</import> + <var_make>self.$(id) = $(id) = $value</var_make> + <make>#set $win = 'self._%s_tool_bar'%$id +$win = Qt.QToolBar(self) +#if not $label() + #set $label = '"%s"'%$id +#end if +$(win).addWidget(Qt.QLabel($label+": ")) +self._$(id)_line_edit = Qt.QLineEdit(str(self.$id)) +self._$(id)_tool_bar.addWidget(self._$(id)_line_edit) +self._$(id)_line_edit.returnPressed.connect( + lambda: self.set_$(id)($(type.conv)(self._$(id)_line_edit.text().toAscii()))) +$(gui_hint()($win))</make> + <callback>self.set_$(id)($value)</callback> + <callback>self._$(id)_line_edit.setText($(type.str)($id))</callback> + <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>type</key> + <value>int</value> + <type>enum</type> + <hide>part</hide> + <option><name>Float</name><key>real</key><opt>conv:eng_notation.str_to_num</opt><opt>str:eng_notation.num_to_str</opt></option> + <option><name>Integer</name><key>int</key><opt>conv:int</opt><opt>str:str</opt></option> + <option><name>String</name><key>string</key><opt>conv:str</opt><opt>str:str</opt></option> + <option><name>Boolean</name><key>bool</key><opt>conv:bool</opt><opt>str:str</opt></option> + <option><name>Any</name><key>raw</key><opt>conv:eval</opt><opt>str:repr</opt></option> + </param> + <param> + <name>Default Value</name> + <key>value</key> + <value>0</value> + <type>$type</type> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <doc> +This block creates a variable with a text entry box. \ +Leave the label blank to use the variable id as the label. + +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> diff --git a/gr-qtgui/grc/qtgui_label.xml b/gr-qtgui/grc/qtgui_label.xml new file mode 100644 index 000000000..5049118c4 --- /dev/null +++ b/gr-qtgui/grc/qtgui_label.xml @@ -0,0 +1,66 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Variable Label Text: +## a gui static text form +################################################### + --> +<block> + <name>QT GUI Label</name> + <key>variable_qtgui_label</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <import>from gnuradio import eng_notation</import> + <var_make>self.$(id) = $(id) = $value</var_make> + <make>#set $win = 'self._%s_tool_bar'%$id +$win = Qt.QToolBar(self) +#if not $label() + #set $label = '"%s"'%$id +#end if +$(win).addWidget(Qt.QLabel($label+": ")) +self._$(id)_label = Qt.QLabel(str(self.$id)) +self._$(id)_tool_bar.addWidget(self._$(id)_label) +$(gui_hint()($win))</make> + <callback>self.set_$(id)($value)</callback> + <callback>self._$(id)_label.setText($(type.str)($id))</callback> + <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>type</key> + <value>int</value> + <type>enum</type> + <hide>part</hide> + <option><name>Float</name><key>real</key><opt>conv:eng_notation.str_to_num</opt><opt>str:eng_notation.num_to_str</opt></option> + <option><name>Integer</name><key>int</key><opt>conv:int</opt><opt>str:str</opt></option> + <option><name>String</name><key>string</key><opt>conv:str</opt><opt>str:str</opt></option> + <option><name>Boolean</name><key>bool</key><opt>conv:bool</opt><opt>str:str</opt></option> + <option><name>Any</name><key>raw</key><opt>conv:eval</opt><opt>str:repr</opt></option> + </param> + <param> + <name>Default Value</name> + <key>value</key> + <value>0</value> + <type>$type</type> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <doc> +This block creates a variable with a label widget for text. \ +Leave the label blank to use the variable id as the label. + +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> diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml new file mode 100644 index 000000000..6b0555f98 --- /dev/null +++ b/gr-qtgui/grc/qtgui_range.xml @@ -0,0 +1,211 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Variable Range: +## ranged widgets like a slider or a knob +################################################### + --> +<block> + <name>QT GUI Range</name> + <key>variable_qtgui_range</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <import>import PyQt4.Qwt5 as Qwt</import> + <var_make>self.$(id) = $(id) = $value</var_make> + <make>#set $win = 'self._%s_layout'%$id +#if not $label() + #set $label = '"%s"'%$id +#end if +######################################################################## +#if $widget() == "knob" +######################################################################## +$win = Qt.QVBoxLayout() +self._$(id)_knob = Qwt.QwtKnob() +self._$(id)_knob.setRange($start, $stop, $step) +self._$(id)_knob.setValue(self.$id) +self._$(id)_knob.valueChanged.connect(self.set_$(id)) +$(win).addWidget(self._$(id)_knob) +self._$(id)_label = Qt.QLabel($label) +self._$(id)_label.setAlignment(Qt.Qt.AlignTop | Qt.Qt.AlignHCenter) +$(win).addWidget(self._$(id)_label) +#end if +######################################################################## +#if $widget() == "thermo" +######################################################################## +$win = Qt.QVBoxLayout() +self._$(id)_label = Qt.QLabel($label) +self._$(id)_thermo = Qwt.QwtThermo() +self._$(id)_thermo.setScalePosition(Qwt.QwtThermo.$orient.scalepos) +self._$(id)_thermo.setRange($start, $stop) +self._$(id)_thermo.setValue(self.$id) +self._$(id)_thermo.$(orient.minfcn)($min_len) +#if 'horizontal' in $orient().lower() +self._$(id)_label.setAlignment(Qt.Qt.AlignBottom | Qt.Qt.AlignHCenter) +$(win).addWidget(self._$(id)_label) +$(win).addWidget(self._$(id)_thermo) +#elif 'vertical' in $orient().lower() +self._$(id)_label.setAlignment(Qt.Qt.AlignTop) +$(win).addWidget(self._$(id)_thermo) +$(win).addWidget(self._$(id)_label) +#end if +#end if +######################################################################## +#if $widget() == "counter" +######################################################################## +$win = Qt.QHBoxLayout() +$(win).addWidget(Qt.QLabel($label+": ")) +self._$(id)_counter = Qwt.QwtCounter() +self._$(id)_counter.setRange($start, $stop, $step) +self._$(id)_counter.setNumButtons(2) +self._$(id)_counter.setMinimumWidth($min_len) +self._$(id)_counter.setValue(self.$id) +$(win).addWidget(self._$(id)_counter) +self._$(id)_counter.valueChanged.connect(self.set_$(id)) +#end if +######################################################################## +#if $widget() == "slider" +######################################################################## +$win = Qt.QVBoxLayout() +self._$(id)_label = Qt.QLabel($label) +self._$(id)_slider = Qwt.QwtSlider(None, Qt.$orient, Qwt.QwtSlider.$orient.scalepos, Qwt.QwtSlider.BgSlot) +self._$(id)_slider.setRange($start, $stop, $step) +self._$(id)_slider.setValue(self.$id) +self._$(id)_slider.$(orient.minfcn)($min_len) +self._$(id)_slider.valueChanged.connect(self.set_$(id)) +#if 'horizontal' in $orient().lower() +self._$(id)_label.setAlignment(Qt.Qt.AlignBottom | Qt.Qt.AlignHCenter) +$(win).addWidget(self._$(id)_label) +$(win).addWidget(self._$(id)_slider) +#elif 'vertical' in $orient().lower() +self._$(id)_label.setAlignment(Qt.Qt.AlignTop) +$(win).addWidget(self._$(id)_slider) +$(win).addWidget(self._$(id)_label) +#end if +#end if +######################################################################## +#if $widget() == "counter_slider" +######################################################################## +$win = Qt.QVBoxLayout() +self._$(id)_tool_bar = Qt.QToolBar(self) +$(win).addWidget(self._$(id)_tool_bar) +self._$(id)_tool_bar.addWidget(Qt.QLabel($label+": ")) +self._$(id)_counter = Qwt.QwtCounter() +self._$(id)_counter.setRange($start, $stop, $step) +self._$(id)_counter.setNumButtons(2) +self._$(id)_counter.setValue(self.$id) +self._$(id)_tool_bar.addWidget(self._$(id)_counter) +self._$(id)_counter.valueChanged.connect(self.set_$(id)) +self._$(id)_slider = Qwt.QwtSlider(None, Qt.Qt.Horizontal, Qwt.QwtSlider.BottomScale, Qwt.QwtSlider.BgSlot) +self._$(id)_slider.setRange($start, $stop, $step) +self._$(id)_slider.setValue(self.$id) +self._$(id)_slider.setMinimumWidth($min_len) +self._$(id)_slider.valueChanged.connect(self.set_$(id)) +$(win).addWidget(self._$(id)_slider) +#end if +$(gui_hint()($win))</make> + <callback>self.set_$(id)($value)</callback> + <callback>#if $widget() == "knob" +self._$(id)_knob.setValue($id) +#end if +#if $widget() == "thermo" +self._$(id)_thermo.setValue($id) +#end if +#if $widget() == "counter" +self._$(id)_counter.setValue($id) +#end if +#if $widget() == "slider" +self._$(id)_slider.setValue($id) +#end if +#if $widget() == "counter_slider" +self._$(id)_counter.setValue($id) +self._$(id)_slider.setValue($id) +#end if</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>knob</key></option> + <option><name>Thermo</name><key>thermo</key></option> + </param> + <param> + <name>Orientation</name> + <key>orient</key> + <value>Qt.Horizontal</value> + <type>enum</type> + <hide>#if $widget() in ("slider", "thermo") 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>#if $widget().split('_')[0] in ("slider", "counter", "thermo") then 'part' else 'all'#</hide> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <check>$start <= $value <= $stop</check> + <check>$start < $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> diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml new file mode 100644 index 000000000..7a5f5ec13 --- /dev/null +++ b/gr-qtgui/grc/qtgui_sink_x.xml @@ -0,0 +1,136 @@ +<?xml version="1.0"?> +<!-- +################################################### +##QT GUI Sink +################################################### + --> +<block> + <name>QT GUI Sink</name> + <key>qtgui_sink_x</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <import>from gnuradio.qtgui import qtgui</import> + <import>from gnuradio.gr import firdes</import> + <import>import sip</import> + <make>#set $win = 'self._%s_win'%$id +qtgui.$(type.fcn)( + $fftsize, \#fftsize + $wintype, \#wintype + $fc, \#fc + $bw, \#bw + $name, \#name + $plotfreq, \#plotfreq + $plotwaterfall, \#plotwaterfall + $plotwaterfall3d, \#plotwaterfall3d + $plottime, \#plottime + $plotconst, \#plotconst +) +self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) +$(gui_hint()($win))</make> + <callback>set_frequency_range($fc, $bw)</callback> + <param> + <name>Type</name> + <key>type</key> + <value>complex</value> + <type>enum</type> + <option><name>Complex</name><key>complex</key><opt>fcn:sink_c</opt></option> + <option><name>Float</name><key>float</key><opt>fcn:sink_f</opt></option> + </param> + <param> + <name>Name</name> + <key>name</key> + <value>QT GUI Plot</value> + <type>string</type> + </param> + <param> + <name>FFT Size</name> + <key>fftsize</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Window Type</name> + <key>wintype</key> + <value>firdes.WIN_BLACKMAN_hARRIS</value> + <type>int</type> + <hide>part</hide> + <option> + <name>Blackman-harris</name> + <key>firdes.WIN_BLACKMAN_hARRIS</key> + </option> + </param> + <param> + <name>Center Frequency (Hz)</name> + <key>fc</key> + <value>0</value> + <type>real</type> + </param> + <param> + <name>Bandwidth (Hz)</name> + <key>bw</key> + <value>samp_rate</value> + <type>real</type> + </param> + <param> + <name>Plot Frequency</name> + <key>plotfreq</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option><name>On</name><key>True</key></option> + <option><name>Off</name><key>False</key></option> + </param> + <param> + <name>Plot Waterfall</name> + <key>plotwaterfall</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option><name>On</name><key>True</key></option> + <option><name>Off</name><key>False</key></option> + </param> + <param> + <name>Plot Waterfall 3D</name> + <key>plotwaterfall3d</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option><name>On</name><key>True</key></option> + <option><name>Off</name><key>False</key></option> + </param> + <param> + <name>Plot Time</name> + <key>plottime</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option><name>On</name><key>True</key></option> + <option><name>Off</name><key>False</key></option> + </param> + <param> + <name>Plot Const</name> + <key>plotconst</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option><name>On</name><key>True</key></option> + <option><name>Off</name><key>False</key></option> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <sink> + <name>in</name> + <type>$type</type> + <nports>$num_inputs</nports> + </sink> + <doc> +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> diff --git a/gr-qtgui/grc/qtgui_tab_widget.xml b/gr-qtgui/grc/qtgui_tab_widget.xml new file mode 100644 index 000000000..f90054109 --- /dev/null +++ b/gr-qtgui/grc/qtgui_tab_widget.xml @@ -0,0 +1,84 @@ +<?xml version="1.0"?> +<!-- +################################################### +##WX GUI Notebook +################################################### + --> +<block> + <name>QT GUI Tab Widget</name> + <key>qtgui_tab_widget</key> + <category>QT GUI Widgets</category> + <import>from PyQt4 import Qt</import> + <make>#set $win = 'self.%s'%$id +Qt.QTabWidget() +#set $all_labels = [$label0, $label1, $label2, $label3, $label4][:int($num_tabs())] +#for i, label in enumerate($all_labels) +self.$(id)_widget_$(i) = Qt.QWidget() +self.$(id)_layout_$(i) = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.$(id)_widget_$(i)) +self.$(id)_grid_layout_$(i) = Qt.QGridLayout() +self.$(id)_layout_$(i).addLayout(self.$(id)_grid_layout_$(i)) +$(win).addTab(self.$(id)_widget_$(i), $label) +#end for +$(gui_hint()($win))</make> + <param> + <name>Num Tabs</name> + <key>num_tabs</key> + <value>1</value> + <type>enum</type> + <option><name>1</name><key>1</key></option> + <option><name>2</name><key>2</key></option> + <option><name>3</name><key>3</key></option> + <option><name>4</name><key>4</key></option> + <option><name>5</name><key>5</key></option> + </param> + <param> + <name>Label 0</name> + <key>label0</key> + <value>Tab 0</value> + <type>string</type> + <hide>#if int($num_tabs()) > 0 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 1</name> + <key>label1</key> + <value>Tab 1</value> + <type>string</type> + <hide>#if int($num_tabs()) > 1 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 2</name> + <key>label2</key> + <value>Tab 2</value> + <type>string</type> + <hide>#if int($num_tabs()) > 2 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 3</name> + <key>label3</key> + <value>Tab 3</value> + <type>string</type> + <hide>#if int($num_tabs()) > 3 then 'none' else 'all'#</hide> + </param> + <param> + <name>Label 4</name> + <key>label4</key> + <value>Tab 4</value> + <type>string</type> + <hide>#if int($num_tabs()) > 4 then 'none' else 'all'#</hide> + </param> + <param> + <name>GUI Hint</name> + <key>gui_hint</key> + <value></value> + <type>gui_hint</type> + <hide>part</hide> + </param> + <doc> +This block creates a tabbed widget to organize other widgets. \ +The ID of this block can be used as the tab_id in the GUI hints of other widgets. + +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> diff --git a/gr-qtgui/src/lib/qtgui.h b/gr-qtgui/src/lib/qtgui.h index 6edbca12c..9831697ac 100644 --- a/gr-qtgui/src/lib/qtgui.h +++ b/gr-qtgui/src/lib/qtgui.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,30 +23,31 @@ #ifndef INCLUDED_QTGUI_H #define INCLUDED_QTGUI_H +#include <gruel/thread.h> #include <qapplication.h> #include "SpectrumGUIClass.h" class qtgui_event : public QEvent { private: - pthread_mutex_t *pmutex; + gruel::mutex &d_mutex; public: - qtgui_event(pthread_mutex_t *mut) - : QEvent((QEvent::Type)(QEvent::User+101)) + qtgui_event(gruel::mutex &mutex) + : QEvent((QEvent::Type)(QEvent::User+101)), + d_mutex(mutex) { - pmutex = mut; + //nop } void lock() { - pthread_mutex_lock(pmutex); - + d_mutex.lock(); } void unlock() { - pthread_mutex_unlock(pmutex); + d_mutex.unlock(); } }; diff --git a/gr-qtgui/src/lib/qtgui_sink_c.cc b/gr-qtgui/src/lib/qtgui_sink_c.cc index c12c451b0..05c7b28d5 100644 --- a/gr-qtgui/src/lib/qtgui_sink_c.cc +++ b/gr-qtgui/src/lib/qtgui_sink_c.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010 Free Software Foundation, Inc. + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -72,7 +72,6 @@ qtgui_sink_c::qtgui_sink_c (int fftsize, int wintype, } d_main_gui = NULL; - pthread_mutex_init(&d_pmutex, NULL); lock(); // Perform fftshift operation; @@ -107,12 +106,12 @@ qtgui_sink_c::forecast(int noutput_items, gr_vector_int &ninput_items_required) void qtgui_sink_c::lock() { - pthread_mutex_lock(&d_pmutex); + d_mutex.lock(); } void qtgui_sink_c::unlock() { - pthread_mutex_unlock(&d_pmutex); + d_mutex.unlock(); } @@ -151,7 +150,7 @@ qtgui_sink_c::initialize(const bool opengl) set_update_time(0.1); d_object = new qtgui_obj(d_qApplication); - qApp->postEvent(d_object, new qtgui_event(&d_pmutex)); + qApp->postEvent(d_object, new qtgui_event(d_mutex)); } @@ -289,7 +288,7 @@ qtgui_sink_c::general_work (int noutput_items, int j=0; const gr_complex *in = (const gr_complex*)input_items[0]; - pthread_mutex_lock(&d_pmutex); + gruel::scoped_lock lock(d_mutex); // Update the FFT size from the application fftresize(); @@ -322,8 +321,6 @@ qtgui_sink_c::general_work (int noutput_items, } } - pthread_mutex_unlock(&d_pmutex); - consume_each(j); return j; } diff --git a/gr-qtgui/src/lib/qtgui_sink_c.h b/gr-qtgui/src/lib/qtgui_sink_c.h index 9aee66503..bbf9983b0 100644 --- a/gr-qtgui/src/lib/qtgui_sink_c.h +++ b/gr-qtgui/src/lib/qtgui_sink_c.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -76,7 +76,7 @@ private: double d_bandwidth; std::string d_name; - pthread_mutex_t d_pmutex; + gruel::mutex d_mutex; bool d_shift; gri_fft_complex *d_fft; diff --git a/gr-qtgui/src/lib/qtgui_sink_f.cc b/gr-qtgui/src/lib/qtgui_sink_f.cc index ab4fd082d..984c2803c 100644 --- a/gr-qtgui/src/lib/qtgui_sink_f.cc +++ b/gr-qtgui/src/lib/qtgui_sink_f.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009,2010 Free Software Foundation, Inc. + * Copyright 2008,2009,2010,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -72,7 +72,6 @@ qtgui_sink_f::qtgui_sink_f (int fftsize, int wintype, } d_main_gui = NULL; - pthread_mutex_init(&d_pmutex, NULL); lock(); // Perform fftshift operation; @@ -107,12 +106,12 @@ qtgui_sink_f::forecast(int noutput_items, gr_vector_int &ninput_items_required) void qtgui_sink_f::lock() { - pthread_mutex_lock(&d_pmutex); + d_mutex.lock(); } void qtgui_sink_f::unlock() { - pthread_mutex_unlock(&d_pmutex); + d_mutex.unlock(); } void @@ -146,7 +145,7 @@ qtgui_sink_f::initialize(const bool opengl) set_update_time(0.1); d_object = new qtgui_obj(d_qApplication); - qApp->postEvent(d_object, new qtgui_event(&d_pmutex)); + qApp->postEvent(d_object, new qtgui_event(d_mutex)); } void @@ -284,7 +283,7 @@ qtgui_sink_f::general_work (int noutput_items, int j=0; const float *in = (const float*)input_items[0]; - pthread_mutex_lock(&d_pmutex); + gruel::scoped_lock lock(d_mutex); // Update the FFT size from the application fftresize(); @@ -317,8 +316,6 @@ qtgui_sink_f::general_work (int noutput_items, } } - pthread_mutex_unlock(&d_pmutex); - consume_each(j); return j; } diff --git a/gr-qtgui/src/lib/qtgui_sink_f.h b/gr-qtgui/src/lib/qtgui_sink_f.h index 0cac35d90..d80a6a198 100644 --- a/gr-qtgui/src/lib/qtgui_sink_f.h +++ b/gr-qtgui/src/lib/qtgui_sink_f.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -74,7 +74,7 @@ private: double d_bandwidth; std::string d_name; - pthread_mutex_t d_pmutex; + gruel::mutex d_mutex; bool d_shift; gri_fft_complex *d_fft; diff --git a/gr-qtgui/src/python/.gitignore b/gr-qtgui/src/python/.gitignore index b336cc7ce..604b402c5 100644 --- a/gr-qtgui/src/python/.gitignore +++ b/gr-qtgui/src/python/.gitignore @@ -1,2 +1,3 @@ /Makefile /Makefile.in +/run_tests diff --git a/gr-qtgui/src/python/Makefile.am b/gr-qtgui/src/python/Makefile.am index 31df63a44..0953a71e5 100644 --- a/gr-qtgui/src/python/Makefile.am +++ b/gr-qtgui/src/python/Makefile.am @@ -21,18 +21,25 @@ include $(top_srcdir)/Makefile.common +TESTS = +EXTRA_DIST += run_tests.in \ + qt_digital_window.ui + +if PYTHON +TESTS += run_tests +DISTCLEANFILES += run_tests + +qtguipythondir = $(grpythondir)/qtgui + noinst_PYTHON = \ pyqt_example_f.py \ pyqt_example.py \ qt_digital.py \ qt_digital_window.py \ usrp2_display.py \ - usrp_display.py - -EXTRA_DIST += \ - qt_digital_window.ui - -qtguipythondir = $(grpythondir)/qtgui + usrp_display.py \ + qa_qtgui.py -qtguipython_PYTHON = \ +qtguipython_PYTHON = \ __init__.py +endif diff --git a/gr-qtgui/src/python/qa_qtgui.py b/gr-qtgui/src/python/qa_qtgui.py new file mode 100755 index 000000000..fbf0de46e --- /dev/null +++ b/gr-qtgui/src/python/qa_qtgui.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# Copyright 2011 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 gnuradio import gr, gr_unittest +import qtgui +from PyQt4 import QtGui, QtCore +import sys, sip + +class test_qtgui(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + pass + # Test to make sure we can instantiate these + #self.qapp = QtGui.QApplication(sys.argv) + #self.qtsnk = qtgui.sink_c(1024, gr.firdes.WIN_BLACKMAN_hARRIS, + # 0, 1, "Test", + # True, True, False, True, True) + + +if __name__ == '__main__': + gr_unittest.run(test_qtgui, "test_qtgui.xml") diff --git a/gr-qtgui/src/python/run_tests.in b/gr-qtgui/src/python/run_tests.in new file mode 100644 index 000000000..909194752 --- /dev/null +++ b/gr-qtgui/src/python/run_tests.in @@ -0,0 +1,10 @@ +#!/bin/sh + +# 1st parameter is absolute path to component source directory +# 2nd parameter is absolute path to component build directory +# 3rd parameter is path to Python QA directory + +@top_builddir@/run_tests.sh \ + @abs_top_srcdir@/gr-qtgui \ + @abs_top_builddir@/gr-qtgui \ + @srcdir@ |