diff options
-rw-r--r-- | config/grc_gr_qtgui.m4 | 3 | ||||
-rw-r--r-- | gr-qtgui/Makefile.am | 1 | ||||
-rw-r--r-- | gr-qtgui/grc/Makefile.am | 3 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_sink_x.xml | 18 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_tab_widget.xml | 84 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_variable_slider.xml | 30 | ||||
-rw-r--r-- | grc/blocks/options.xml | 2 | ||||
-rw-r--r-- | grc/python/Generator.py | 4 | ||||
-rw-r--r-- | grc/python/Param.py | 25 | ||||
-rw-r--r-- | grc/python/flow_graph.tmpl | 13 |
10 files changed, 161 insertions, 22 deletions
diff --git a/config/grc_gr_qtgui.m4 b/config/grc_gr_qtgui.m4 index 4027bb332..c14f984c3 100644 --- a/config/grc_gr_qtgui.m4 +++ b/config/grc_gr_qtgui.m4 @@ -1,4 +1,4 @@ -dnl Copyright 2001,2002,2003,2004,2005,2006,2008 Free Software Foundation, Inc. +dnl Copyright 2001,2002,2003,2004,2005,2006,2008,2011 Free Software Foundation, Inc. dnl dnl This file is part of GNU Radio dnl @@ -82,6 +82,7 @@ AC_DEFUN([GRC_GR_QTGUI],[ AC_CONFIG_FILES([ \ gr-qtgui/Makefile \ + gr-qtgui/grc/Makefile \ gr-qtgui/src/Makefile \ gr-qtgui/src/lib/Makefile \ gr-qtgui/src/python/Makefile \ diff --git a/gr-qtgui/Makefile.am b/gr-qtgui/Makefile.am index 66746e5e8..30b249589 100644 --- a/gr-qtgui/Makefile.am +++ b/gr-qtgui/Makefile.am @@ -26,5 +26,4 @@ DIST_SUBDIRS = src if PYTHON SUBDIRS += grc -SUBDIRS += python endif diff --git a/gr-qtgui/grc/Makefile.am b/gr-qtgui/grc/Makefile.am index 226e9d137..132d1a2e0 100644 --- a/gr-qtgui/grc/Makefile.am +++ b/gr-qtgui/grc/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2010 Free Software Foundation, Inc. +# Copyright 2010-2011 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,4 +25,5 @@ grcblocksdir = $(grc_blocksdir) dist_grcblocks_DATA = \ qtgui_sink_x.xml \ + qtgui_tab_widget.xml \ qtgui_variable_slider.xml diff --git a/gr-qtgui/grc/qtgui_sink_x.xml b/gr-qtgui/grc/qtgui_sink_x.xml index 8182f8d94..6e5c9549b 100644 --- a/gr-qtgui/grc/qtgui_sink_x.xml +++ b/gr-qtgui/grc/qtgui_sink_x.xml @@ -8,10 +8,12 @@ <name>QT GUI Sink</name> <key>qtgui_sink_x</key> <category>Graphical Sinks</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>qtgui.$(type.fcn)( + <make>#set $win = 'self._%s_win'%$id +qtgui.$(type.fcn)( $fftsize, \#fftsize $wintype, \#wintype $fc, \#fc @@ -23,8 +25,8 @@ $plottime, \#plottime $plotconst, \#plotconst ) -self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), QtGui.QWidget) -self.layout.addWidget(self._$(id)_win)</make> +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> @@ -114,11 +116,21 @@ self.layout.addWidget(self._$(id)_win)</make> <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..66597b454 --- /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> + <import>from PyQt4 import Qt</import> + <make>#set $win = 'self.%s'%$id +$win = Qt.QTabWidget(None) +#for i, label in enumerate([$label0, $label1, $label2, $label3, $label4]) +#if int($num_tabs()) > $i +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 if +#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/grc/qtgui_variable_slider.xml b/gr-qtgui/grc/qtgui_variable_slider.xml index 5587fdc27..239d90903 100644 --- a/gr-qtgui/grc/qtgui_variable_slider.xml +++ b/gr-qtgui/grc/qtgui_variable_slider.xml @@ -6,35 +6,35 @@ ################################################### --> <block> - <name>QT GUI Variable Slider</name> + <name>QT GUI Slider</name> <key>variable_qtgui_slider</key> <category>Variables</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 = '_%s_sizer'%$id + <make>#set $win = '_%s_layout'%$id $win = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom) self._$(id)_tool_bar = Qt.QToolBar(self) $(win).addWidget(self._$(id)_tool_bar) #if $label() -self._$(id)_tool_bar.addWidget(Qt.QLabel($label, self._$(id)_tool_bar)) +self._$(id)_tool_bar.addWidget(Qt.QLabel($label, None)) #else -self._$(id)_tool_bar.addWidget(Qt.QLabel($id, self._$(id)_tool_bar)) +self._$(id)_tool_bar.addWidget(Qt.QLabel($id, None)) #end if -self._$(id)_counter = Qwt.QwtCounter(self._$(id)_tool_bar) +self._$(id)_counter = Qwt.QwtCounter(None) self._$(id)_counter.setRange($start, $stop, $step) self._$(id)_counter.setNumButtons(2) self._$(id)_counter.setValue($value) self._$(id)_tool_bar.addWidget(self._$(id)_counter) -$(win).connect(self._$(id)_counter, Qt.SIGNAL('valueChanged(double)'), self.set_$(id)) -self._$(id)_slider = Qwt.QwtSlider(self._$(id)_tool_bar) +self._$(id)_counter.valueChanged.connect(self.set_$(id)) +self._$(id)_slider = Qwt.QwtSlider(None) self._$(id)_slider.setRange($start, $stop, $step) self._$(id)_slider.setValue($value) self._$(id)_slider.setOrientation(Qt.$orient) self._$(id)_slider.setScalePosition($orient.scalepos) -$(win).connect(self._$(id)_slider, Qt.SIGNAL('valueChanged(double)'), self.set_$(id)) +self._$(id)_slider.valueChanged.connect(self.set_$(id)) $(win).addWidget(self._$(id)_slider) -self.layout.addLayout($win)</make> +$(gui_hint()($win))</make> <callback>self.set_$(id)($value)</callback> <callback>self._$(id)_counter.setValue($id)</callback> <callback>self._$(id)_slider.setValue($id)</callback> @@ -68,7 +68,6 @@ self.layout.addLayout($win)</make> <key>step</key> <value>1</value> <type>real</type> - <hide>part</hide> </param> <param> <name>Orientation</name> @@ -87,6 +86,13 @@ self.layout.addLayout($win)</make> <opt>scalepos:Qwt.QwtSlider.RightScale</opt> </option> </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> @@ -94,5 +100,9 @@ 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/grc/blocks/options.xml b/grc/blocks/options.xml index 62ceeba0f..ed4d3c1d8 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -16,7 +16,7 @@ from grc_gnuradio import wxgui as grc_wxgui import wx #end if #if $generate_options() == 'qt_gui' -from PyQt4 import QtGui +from PyQt4 import Qt import sys #end if #if $generate_options() != 'hb' diff --git a/grc/python/Generator.py b/grc/python/Generator.py index d53802bef..7d08b914b 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -100,6 +100,10 @@ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') filter(lambda b: b.get_key() == 'notebook', blocks), lambda n: n.get_id(), lambda n: n.get_param('notebook').get_value(), ) + notebooks += expr_utils.sort_objects( + filter(lambda b: b.get_key() == 'qtgui_tab_widget', blocks), + lambda n: n.get_id(), lambda n: n.get_param('gui_hint').get_value(), + ) #list of regular blocks (all blocks minus the special ones) blocks = filter(lambda b: b not in (imports + parameters + variables + probes + notebooks), blocks) + probes #list of connections where each endpoint is enabled diff --git a/grc/python/Param.py b/grc/python/Param.py index 6dd008d1d..27258faab 100644 --- a/grc/python/Param.py +++ b/grc/python/Param.py @@ -99,7 +99,7 @@ class Param(_Param, _GUIParam): 'hex', 'string', 'bool', 'file_open', 'file_save', 'id', 'stream_id', - 'grid_pos', 'notebook', + 'grid_pos', 'notebook', 'gui_hint', 'import', ) @@ -354,6 +354,29 @@ class Param(_Param, _GUIParam): except: raise Exception, 'Stream ID "%s" is not found.'%v return v ######################### + # GUI Position/Hint + ######################### + elif t == 'gui_hint': + if ':' in v: tab, pos = v.split(':') + elif '@' in v: tab, pos = v, '' + else: tab, pos = '', v + + if '@' in tab: tab, index = tab.split('@') + else: index = '?' + + widget_str = ({ + (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)', + (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)', + (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)', + (False, False): 'self.top_layout.addWidget(%(widget)s)', + }[bool(tab), bool(pos)])%{'tab': tab, 'index': index, 'widget': '%s', 'pos': pos} + + def gui_hint(ws, w): + if 'layout' in w: ws = ws.replace('addWidget', 'addLayout') + return ws%w + + return lambda w: gui_hint(widget_str, w) + ######################### # Grid Position Type ######################### elif t == 'grid_pos': diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 108e15ca0..88049a9ef 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -60,12 +60,14 @@ class $(class_name)(grc_wxgui.top_block_gui): self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) #end if #elif $generate_options == 'qt_gui' -class $(class_name)(gr.top_block, QtGui.QWidget): +class $(class_name)(gr.top_block, Qt.QWidget): def __init__($param_str): gr.top_block.__init__(self, "$title") - QtGui.QWidget.__init__(self) - self.layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom, self) + Qt.QWidget.__init__(self) + self.top_layout = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) #elif $generate_options == 'no_gui' class $(class_name)(gr.top_block): @@ -203,6 +205,9 @@ self.$port.get_parent().get_id()#slurp ######################################################## #for $var in $parameters + $variables #set $id = $var.get_id() + def get_$(id)(self): + return self.$id + def set_$(id)(self, $id): self.$id = $id #for $callback in $var_id2cbs[$id] @@ -250,7 +255,7 @@ if __name__ == '__main__': tb = $(class_name)($(', '.join($params_eq_list))) tb.Run($flow_graph.get_option('run')) #elif $generate_options == 'qt_gui' - qapp = QtGui.QApplication(sys.argv) + qapp = Qt.QApplication(sys.argv) tb = $(class_name)($(', '.join($params_eq_list))) tb.start() tb.show() |