summaryrefslogtreecommitdiff
path: root/grc/python
diff options
context:
space:
mode:
Diffstat (limited to 'grc/python')
-rw-r--r--grc/python/Block.py43
-rw-r--r--grc/python/Constants.py66
-rw-r--r--grc/python/FlowGraph.py1
-rw-r--r--grc/python/Generator.py39
-rw-r--r--grc/python/Port.py13
-rw-r--r--grc/python/block.dtd5
-rw-r--r--grc/python/default_flow_graph.grc4
-rw-r--r--grc/python/flow_graph.tmpl33
8 files changed, 142 insertions, 62 deletions
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 48b827792e..303aa85ed5 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -17,22 +17,18 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from collections import defaultdict
+import itertools
+import collections
+from .. base.Constants import BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI
from .. base.Block import Block as _Block
from .. gui.Block import Block as _GUIBlock
+
from . FlowGraph import _variable_matcher
import extract_docs
-class Block(_Block, _GUIBlock):
-
- def is_virtual_sink(self): return self.get_key() == 'virtual_sink'
- def is_virtual_source(self): return self.get_key() == 'virtual_source'
- ##for make source to keep track of indexes
- _source_count = 0
- ##for make sink to keep track of indexes
- _sink_count = 0
+class Block(_Block, _GUIBlock):
def __init__(self, flow_graph, n):
"""
@@ -52,9 +48,9 @@ class Block(_Block, _GUIBlock):
self._var_make = n.find('var_make')
self._checks = n.findall('check')
self._callbacks = n.findall('callback')
- self._throttle = n.find('throttle') or ''
self._bus_structure_source = n.find('bus_structure_source') or ''
self._bus_structure_sink = n.find('bus_structure_sink') or ''
+ self.port_counters = [itertools.count(), itertools.count()]
#build the block
_Block.__init__(
self,
@@ -78,8 +74,6 @@ class Block(_Block, _GUIBlock):
except: return ''
- def throttle(self): return bool(self._throttle)
-
def validate(self):
"""
Validate this block.
@@ -102,13 +96,22 @@ class Block(_Block, _GUIBlock):
self.get_parent().evaluate(value)
except Exception as err:
self.add_error_message('Value "%s" cannot be evaluated:\n%s' % (value, err))
+
# check if this is a GUI block and matches the selected generate option
current_generate_option = self.get_parent().get_option('generate_options')
- for label, option in (('WX GUI', 'wx_gui'), ('QT GUI', 'qt_gui')):
- if self.get_name().startswith(label) and current_generate_option != option:
+
+ def check_generate_mode(label, flag, valid_options):
+ block_requires_mode = (
+ flag in self.get_flags() or
+ self.get_name().upper().startswith(label)
+ )
+ if block_requires_mode and current_generate_option not in valid_options:
self.add_error_message("Can't generate this block in mode " +
repr(current_generate_option))
+ check_generate_mode('WX GUI', BLOCK_FLAG_NEED_WX_GUI, ('wx_gui',))
+ check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
+
def rewrite(self):
"""
Add and remove ports to adjust for the nports.
@@ -130,13 +133,13 @@ class Block(_Block, _GUIBlock):
master_port.remove_clone(port)
ports.remove(port)
# add more cloned ports
- for i in range(num_ports, nports):
+ for j in range(num_ports, nports):
port = master_port.add_clone()
- ports.insert(ports.index(master_port) + i, port)
+ ports.insert(ports.index(master_port) + j, port)
self.back_ofthe_bus(ports)
# renumber non-message/-msg ports
- domain_specific_port_index = defaultdict(int)
+ domain_specific_port_index = collections.defaultdict(int)
for port in filter(lambda p: p.get_key().isdigit(), ports):
domain = port.get_domain()
port._key = str(domain_specific_port_index[domain])
@@ -204,3 +207,9 @@ class Block(_Block, _GUIBlock):
if 'self.' in callback: return callback
return 'self.%s.%s'%(self.get_id(), callback)
return map(make_callback, self._callbacks)
+
+ def is_virtual_sink(self):
+ return self.get_key() == 'virtual_sink'
+
+ def is_virtual_source(self):
+ return self.get_key() == 'virtual_source'
diff --git a/grc/python/Constants.py b/grc/python/Constants.py
index 79ff8bab35..1df1fc492b 100644
--- a/grc/python/Constants.py
+++ b/grc/python/Constants.py
@@ -50,31 +50,55 @@ FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
+
+# Updating colors. Using the standard color pallette from:
+# http://www.google.com/design/spec/style/color.html#color-color-palette
+# Most are based on the main, primary color standard. Some are within
+# that color's spectrum when it was deemed necessary.
+GRC_COLOR_BROWN = '#795548'
+GRC_COLOR_BLUE = '#2196F3'
+GRC_COLOR_LIGHT_GREEN = '#8BC34A'
+GRC_COLOR_GREEN = '#4CAF50'
+GRC_COLOR_AMBER = '#FFC107'
+GRC_COLOR_PURPLE = '#9C27B0'
+GRC_COLOR_CYAN = '#00BCD4'
+GRC_COLOR_GR_ORANGE = '#FF6905'
+GRC_COLOR_ORANGE = '#F57C00'
+GRC_COLOR_LIME = '#CDDC39'
+GRC_COLOR_TEAL = '#009688'
+GRC_COLOR_YELLOW = '#FFEB3B'
+GRC_COLOR_PINK = '#F50057'
+GRC_COLOR_LIGHT_PURPLE = '#E040FB'
+GRC_COLOR_DARK_GREY = '#72706F'
+GRC_COLOR_GREY = '#BDBDBD'
+GRC_COLOR_WHITE = '#FFFFFF'
+
+
CORE_TYPES = ( #name, key, sizeof, color
- ('Complex Float 64', 'fc64', 16, '#CC8C69'),
- ('Complex Float 32', 'fc32', 8, '#3399FF'),
- ('Complex Integer 64', 'sc64', 16, '#66CC00'),
- ('Complex Integer 32', 'sc32', 8, '#33cc66'),
- ('Complex Integer 16', 'sc16', 4, '#cccc00'),
- ('Complex Integer 8', 'sc8', 2, '#cc00cc'),
- ('Float 64', 'f64', 8, '#66CCCC'),
- ('Float 32', 'f32', 4, '#FF8C69'),
- ('Integer 64', 's64', 8, '#99FF33'),
- ('Integer 32', 's32', 4, '#00FF99'),
- ('Integer 16', 's16', 2, '#FFFF66'),
- ('Integer 8', 's8', 1, '#FF66FF'),
- ('Message Queue', 'msg', 0, '#777777'),
- ('Async Message', 'message', 0, '#C0C0C0'),
- ('Bus Connection', 'bus', 0, '#FFFFFF'),
- ('Wildcard', '', 0, '#FFFFFF'),
+ ('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN),
+ ('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE),
+ ('Complex Integer 64', 'sc64', 16, GRC_COLOR_LIGHT_GREEN),
+ ('Complex Integer 32', 'sc32', 8, GRC_COLOR_GREEN),
+ ('Complex Integer 16', 'sc16', 4, GRC_COLOR_AMBER),
+ ('Complex Integer 8', 'sc8', 2, GRC_COLOR_PURPLE),
+ ('Float 64', 'f64', 8, GRC_COLOR_CYAN),
+ ('Float 32', 'f32', 4, GRC_COLOR_ORANGE),
+ ('Integer 64', 's64', 8, GRC_COLOR_LIME),
+ ('Integer 32', 's32', 4, GRC_COLOR_TEAL),
+ ('Integer 16', 's16', 2, GRC_COLOR_YELLOW),
+ ('Integer 8', 's8', 1, GRC_COLOR_LIGHT_PURPLE),
+ ('Message Queue', 'msg', 0, GRC_COLOR_DARK_GREY),
+ ('Async Message', 'message', 0, GRC_COLOR_GREY),
+ ('Bus Connection', 'bus', 0, GRC_COLOR_WHITE),
+ ('Wildcard', '', 0, GRC_COLOR_WHITE),
)
ALIAS_TYPES = {
- 'complex' : (8, '#3399FF'),
- 'float' : (4, '#FF8C69'),
- 'int' : (4, '#00FF99'),
- 'short' : (2, '#FFFF66'),
- 'byte' : (1, '#FF66FF'),
+ 'complex' : (8, GRC_COLOR_BLUE),
+ 'float' : (4, GRC_COLOR_ORANGE),
+ 'int' : (4, GRC_COLOR_TEAL),
+ 'short' : (2, GRC_COLOR_YELLOW),
+ 'byte' : (1, GRC_COLOR_LIGHT_PURPLE),
}
TYPE_TO_COLOR = dict()
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
index d7337b8a96..49530af8a3 100644
--- a/grc/python/FlowGraph.py
+++ b/grc/python/FlowGraph.py
@@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import expr_utils
from .. base.FlowGraph import FlowGraph as _FlowGraph
from .. gui.FlowGraph import FlowGraph as _GUIFlowGraph
-from .. base.odict import odict
import re
_variable_matcher = re.compile('^(variable\w*)$')
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index a3f9f10fc1..98b671dde5 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -27,6 +27,7 @@ from Cheetah.Template import Template
from .. gui import Messages
from .. base import ParseXML
from .. base import odict
+from .. base.Constants import BLOCK_FLAG_NEED_QT_GUI
from . Constants import TOP_BLOCK_FILE_MODE, FLOW_GRAPH_TEMPLATE, \
XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD
@@ -47,9 +48,13 @@ class Generator(object):
"""
self._generate_options = flow_graph.get_option('generate_options')
if self._generate_options == 'hb':
- self._generator = HierBlockGenerator(flow_graph, file_path)
+ generator_cls = HierBlockGenerator
+ elif self._generate_options == 'hb_qt_gui':
+ generator_cls = QtHierBlockGenerator
else:
- self._generator = TopBlockGenerator(flow_graph, file_path)
+ generator_cls = TopBlockGenerator
+
+ self._generator = generator_cls(flow_graph, file_path)
def get_generate_options(self):
return self._generate_options
@@ -86,8 +91,8 @@ class TopBlockGenerator(object):
def write(self):
"""generate output and write it to files"""
# do throttle warning
- throttling_blocks = filter(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks())
- if not throttling_blocks and self._generate_options != 'hb':
+ throttling_blocks = filter(lambda b: b.throtteling(), self._flow_graph.get_enabled_blocks())
+ if not throttling_blocks and not self._generate_options.startswith('hb'):
Messages.send_warning("This flow graph may not have flow control: "
"no audio or RF hardware blocks found. "
"Add a Misc->Throttle block to your flow "
@@ -325,3 +330,29 @@ class HierBlockGenerator(TopBlockGenerator):
n = {'block': block_n}
return n
+
+
+class QtHierBlockGenerator(HierBlockGenerator):
+
+ def _build_block_n_from_flow_graph_io(self):
+ n = HierBlockGenerator._build_block_n_from_flow_graph_io(self)
+ block_n = n['block']
+
+ if not block_n['name'].upper().startswith('QT GUI'):
+ block_n['name'] = 'QT GUI ' + block_n['name']
+
+ block_n.insert_after('category', 'flags', BLOCK_FLAG_NEED_QT_GUI)
+
+ gui_hint_param = odict()
+ gui_hint_param['name'] = 'GUI Hint'
+ gui_hint_param['key'] = 'gui_hint'
+ gui_hint_param['value'] = ''
+ gui_hint_param['type'] = 'gui_hint'
+ gui_hint_param['hide'] = 'part'
+ block_n['param'].append(gui_hint_param)
+
+ block_n['make'] += (
+ "\n#set $win = 'self.%s' % $id"
+ "\n${gui_hint()($win)}"
+ )
+ return n
diff --git a/grc/python/Port.py b/grc/python/Port.py
index 765e1d7423..249d7aed71 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -100,14 +100,11 @@ class Port(_Port, _GUIPort):
elif n['domain'] == GR_MESSAGE_DOMAIN:
n['key'] = n['name']
n['type'] = 'message' # for port color
- if n['type'] == 'msg': n['key'] = 'msg'
- if dir == 'source' and not n.find('key'):
- n['key'] = str(block._source_count)
- block._source_count += 1
- if dir == 'sink' and not n.find('key'):
- n['key'] = str(block._sink_count)
- block._sink_count += 1
- #build the port
+ if n['type'] == 'msg':
+ n['key'] = 'msg'
+ if not n.find('key'):
+ n['key'] = str(next(block.port_counters[dir == 'source']))
+ # build the port
_Port.__init__(
self,
block=block,
diff --git a/grc/python/block.dtd b/grc/python/block.dtd
index 8cfd3dd392..145f4d8610 100644
--- a/grc/python/block.dtd
+++ b/grc/python/block.dtd
@@ -25,7 +25,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Top level element.
A block contains a name, ...parameters list, and list of IO ports.
-->
-<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, var_value?, make, callback*, param_tab_order?, param*, bus_sink?, bus_source?, check*, sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)>
+<!ELEMENT block (name, key, category?, throttle?, flags?, import*, var_make?, var_value?,
+ make, callback*, param_tab_order?, param*, bus_sink?, bus_source?, check*,
+ sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)>
<!--
Sub level elements.
-->
@@ -64,3 +66,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
<!ELEMENT callback (#PCDATA)>
<!ELEMENT optional (#PCDATA)>
<!ELEMENT throttle (#PCDATA)>
+<!ELEMENT flags (#PCDATA)>
diff --git a/grc/python/default_flow_graph.grc b/grc/python/default_flow_graph.grc
index 53d39e885a..059509d34b 100644
--- a/grc/python/default_flow_graph.grc
+++ b/grc/python/default_flow_graph.grc
@@ -14,7 +14,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(10, 10)</value>
+ <value>(8, 8)</value>
</param>
<param>
<key>_rotation</key>
@@ -33,7 +33,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(10, 170)</value>
+ <value>(8, 160)</value>
</param>
<param>
<key>_rotation</key>
diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index 814b513213..3dd772b6ee 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -1,4 +1,4 @@
-#if $generate_options != 'hb'
+#if not $generate_options.startswith('hb')
#!/usr/bin/env python2
#end if
########################################################
@@ -61,7 +61,8 @@ sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnura
#end if
#for $imp in $imports
-$(imp.replace(" # grc-generated hier_block", ""))
+##$(imp.replace(" # grc-generated hier_block", ""))
+$imp
#end for
########################################################
@@ -76,6 +77,7 @@ $(imp.replace(" # grc-generated hier_block", ""))
#if $generate_options == 'wx_gui'
#import gtk
#set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0)
+
class $(class_name)(grc_wxgui.top_block_gui):
def __init__($param_str):
@@ -85,7 +87,7 @@ 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'
-from distutils.version import StrictVersion
+
class $(class_name)(gr.top_block, Qt.QWidget):
def __init__($param_str):
@@ -110,16 +112,21 @@ class $(class_name)(gr.top_block, Qt.QWidget):
self.settings = Qt.QSettings("GNU Radio", "$class_name")
self.restoreGeometry(self.settings.value("geometry").toByteArray())
-
#elif $generate_options == 'no_gui'
+
class $(class_name)(gr.top_block):
def __init__($param_str):
gr.top_block.__init__(self, "$title")
-#elif $generate_options == 'hb'
+#elif $generate_options.startswith('hb')
#set $in_sigs = $flow_graph.get_hier_block_stream_io('in')
#set $out_sigs = $flow_graph.get_hier_block_stream_io('out')
+
+#if $generate_options == 'hb_qt_gui'
+class $(class_name)(gr.hier_block2, Qt.QWidget):
+#else
class $(class_name)(gr.hier_block2):
+#end if
#def make_io_sig($io_sigs)
#set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs]
#if len($io_sigs) == 0
@@ -143,6 +150,14 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
#for $pad in $flow_graph.get_hier_block_message_io('out')
self.message_port_register_hier_in("$pad['label']")
#end for
+ #if $generate_options == 'hb_qt_gui'
+
+ Qt.QWidget.__init__(self)
+ self.top_layout = Qt.QVBoxLayout()
+ self.top_grid_layout = Qt.QGridLayout()
+ self.top_layout.addLayout(self.top_grid_layout)
+ self.setLayout(self.top_layout)
+ #end if
#end if
#if $flow_graph.get_option('thread_safe_setters')
@@ -304,7 +319,7 @@ $param.get_make()#slurp
#end if
$short_id#slurp
#end def
-#if $generate_options != 'hb'
+#if not $generate_options.startswith('hb')
if __name__ == '__main__':
parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
@@ -334,7 +349,8 @@ if __name__ == '__main__':
tb.Wait()
#end if
#elif $generate_options == 'qt_gui'
- if(StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0")):
+ from distutils.version import StrictVersion
+ if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
Qt.QApplication.setGraphicsSystem(gr.prefs().get_string('qtgui','style','raster'))
qapp = Qt.QApplication(sys.argv)
tb = $(class_name)($(', '.join($params_eq_list)))
@@ -346,6 +362,7 @@ if __name__ == '__main__':
#end if
#end if
tb.show()
+
def quitting():
tb.stop()
tb.wait()
@@ -358,7 +375,7 @@ if __name__ == '__main__':
sys.stderr.write("Monitor '{0}' does not have an enable ('en') parameter.".format("tb.$m.get_id()"))
#end for
qapp.exec_()
- tb = None #to clean up Qt widgets
+ tb = None # to clean up Qt widgets
#elif $generate_options == 'no_gui'
tb = $(class_name)($(', '.join($params_eq_list)))
#set $run_options = $flow_graph.get_option('run_options')