summaryrefslogtreecommitdiff
path: root/grc
diff options
context:
space:
mode:
Diffstat (limited to 'grc')
-rw-r--r--grc/base/Block.py96
-rw-r--r--grc/base/Constants.py10
-rw-r--r--grc/base/FlowGraph.py34
-rw-r--r--grc/base/Param.py2
-rw-r--r--grc/blocks/.gitignore1
-rw-r--r--grc/blocks/CMakeLists.txt22
-rw-r--r--grc/blocks/options.xml22
-rw-r--r--grc/blocks/variable_struct.xml.py98
-rw-r--r--grc/freedesktop/CMakeLists.txt2
-rwxr-xr-xgrc/freedesktop/convert.sh14
-rw-r--r--grc/freedesktop/gnuradio-grc.desktop1
-rw-r--r--grc/freedesktop/gnuradio_logo_icon-square.svg124
-rw-r--r--grc/freedesktop/grc-icon-128.pngbin3570 -> 4758 bytes
-rw-r--r--grc/freedesktop/grc-icon-16.pngbin0 -> 537 bytes
-rw-r--r--grc/freedesktop/grc-icon-24.pngbin0 -> 840 bytes
-rw-r--r--grc/freedesktop/grc-icon-256.pngbin7843 -> 9762 bytes
-rw-r--r--grc/freedesktop/grc-icon-256.svg216
-rw-r--r--grc/freedesktop/grc-icon-32.pngbin1060 -> 1148 bytes
-rw-r--r--grc/freedesktop/grc-icon-48.pngbin1691 -> 1796 bytes
-rw-r--r--grc/freedesktop/grc-icon-64.pngbin1893 -> 2355 bytes
-rw-r--r--grc/freedesktop/grc_setup_freedesktop.in2
-rw-r--r--grc/grc.conf.in2
-rw-r--r--grc/gui/ActionHandler.py52
-rw-r--r--grc/gui/Actions.py37
-rw-r--r--grc/gui/Bars.py5
-rw-r--r--grc/gui/Block.py24
-rw-r--r--grc/gui/Colors.py1
-rw-r--r--grc/gui/Constants.py74
-rw-r--r--grc/gui/FlowGraph.py18
-rw-r--r--grc/gui/Platform.py2
-rw-r--r--grc/gui/Port.py46
-rw-r--r--grc/gui/Preferences.py98
-rw-r--r--grc/gui/PropsDialog.py58
-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.py94
-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.tmpl42
-rwxr-xr-xgrc/scripts/gnuradio-companion9
42 files changed, 885 insertions, 453 deletions
diff --git a/grc/base/Block.py b/grc/base/Block.py
index afe326bbf4..2a20c22ef7 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -19,12 +19,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from . import odict
from . Constants import ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB
+from . Constants import BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS
+from . Constants import BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED
from Element import Element
from Cheetah.Template import Template
from UserDict import UserDict
from itertools import imap
+
class TemplateArg(UserDict):
"""
A cheetah template argument created from a param.
@@ -46,11 +49,16 @@ class TemplateArg(UserDict):
def __call__(self):
return self._param.get_evaluated()
-def _get_keys(lst): return [elem.get_key() for elem in lst]
+
+def _get_keys(lst):
+ return [elem.get_key() for elem in lst]
+
+
def _get_elem(lst, key):
try: return lst[_get_keys(lst).index(key)]
except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
+
class Block(Element):
def __init__(self, flow_graph, n):
@@ -73,6 +81,10 @@ class Block(Element):
self._name = n.find('name')
self._key = n.find('key')
self._category = n.find('category') or ''
+ self._flags = n.find('flags') or ''
+ # Backwards compatibility
+ if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags:
+ self._flags += BLOCK_FLAG_THROTTLE
self._grc_source = n.find('grc_source') or ''
self._block_wrapper_path = n.find('block_wrapper_path')
self._bussify_sink = n.find('bus_sink')
@@ -143,6 +155,10 @@ class Block(Element):
and (self._key != "pad_sink"))
is_variable = self._key.startswith('variable')
+ # Disable blocks that are virtual/pads or variables
+ if not is_not_virtual_or_pad or is_variable:
+ self._flags += BLOCK_FLAG_DISABLE_BYPASS
+
if is_not_virtual_or_pad and not is_variable:
self.get_params().append(self.get_parent().get_parent().Param(
block=self,
@@ -197,7 +213,6 @@ class Block(Element):
})
))
-
def back_ofthe_bus(self, portlist):
portlist.sort(key=lambda p: p._type == 'bus')
@@ -205,6 +220,35 @@ class Block(Element):
buslist = [p for p in ports if p._type == 'bus']
return buslist or ports
+ # Main functions to get and set the block state
+ # Also kept get_enabled and set_enabled to keep compatibility
+ def get_state(self):
+ """
+ Gets the block's current state.
+
+ Returns:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ try: return int(eval(self.get_param('_enabled').get_value()))
+ except: return BLOCK_ENABLED
+
+ def set_state(self, state):
+ """
+ Sets the state for the block.
+
+ Args:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ if state in [BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED]:
+ self.get_param('_enabled').set_value(str(state))
+ else:
+ self.get_param('_enabled').set_value(str(BLOCK_ENABLED))
+
+ # Enable/Disable Aliases
def get_enabled(self):
"""
Get the enabled state of the block.
@@ -212,8 +256,7 @@ class Block(Element):
Returns:
true for enabled
"""
- try: return eval(self.get_param('_enabled').get_value())
- except: return True
+ return not (self.get_state() == BLOCK_DISABLED)
def set_enabled(self, enabled):
"""
@@ -221,8 +264,45 @@ class Block(Element):
Args:
enabled: true for enabled
+
+ Returns:
+ True if block changed state
"""
- self.get_param('_enabled').set_value(str(enabled))
+ old_state = self.get_state()
+ new_state = BLOCK_ENABLED if enabled else BLOCK_DISABLED
+ self.set_state(new_state)
+ return old_state != new_state
+
+ # Block bypassing
+ def get_bypassed(self):
+ """
+ Check if the block is bypassed
+ """
+ return self.get_state() == BLOCK_BYPASSED
+
+ def set_bypassed(self):
+ """
+ Bypass the block
+
+ Returns:
+ True if block chagnes state
+ """
+ if self.get_state() != BLOCK_BYPASSED and self.can_bypass():
+ self.set_state(BLOCK_BYPASSED)
+ return True
+ return False
+
+ def can_bypass(self):
+ """ Check the number of sinks and sources and see if this block can be bypassed """
+ # Check to make sure this is a single path block
+ # Could possibly support 1 to many blocks
+ if len(self.get_sources()) != 1 or len(self.get_sinks()) != 1:
+ return False
+ if not (self.get_sources()[0].get_type() == self.get_sinks()[0].get_type()):
+ return False
+ if self.bypass_disabled():
+ return False
+ return True
def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
@@ -240,6 +320,10 @@ class Block(Element):
def get_block_wrapper_path(self): return self._block_wrapper_path
def get_comment(self): return self.get_param('comment').get_value()
+ def get_flags(self): return self._flags
+ def throtteling(self): return BLOCK_FLAG_THROTTLE in self._flags
+ def bypass_disabled(self): return BLOCK_FLAG_DISABLE_BYPASS in self._flags
+
##############################################
# Access Params
##############################################
@@ -414,7 +498,7 @@ class Block(Element):
"""
n = odict()
n['key'] = self.get_key()
- n['param'] = map(lambda p: p.export_data(), self.get_params())
+ n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str))
if 'bus' in map(lambda a: a.get_type(), self.get_sinks()):
n['bus_sink'] = str(1);
if 'bus' in map(lambda a: a.get_type(), self.get_sources()):
diff --git a/grc/base/Constants.py b/grc/base/Constants.py
index efae0ecbb5..1e83de63b5 100644
--- a/grc/base/Constants.py
+++ b/grc/base/Constants.py
@@ -38,3 +38,13 @@ DOMAIN_DTD = os.path.join(DATA_DIR, 'domain.dtd')
GR_STREAM_DOMAIN = "gr_stream"
GR_MESSAGE_DOMAIN = "gr_message"
DEFAULT_DOMAIN = GR_STREAM_DOMAIN
+
+BLOCK_FLAG_THROTTLE = 'throttle'
+BLOCK_FLAG_DISABLE_BYPASS = 'disable_bypass'
+BLOCK_FLAG_NEED_QT_GUI = 'need_qt_gui'
+BLOCK_FLAG_NEED_WX_GUI = 'need_ex_gui'
+
+# Block States
+BLOCK_DISABLED = 0
+BLOCK_ENABLED = 1
+BLOCK_BYPASSED = 2
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index fb25b46821..52ec741db8 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -78,9 +78,6 @@ class FlowGraph(Element):
bus_structure = block.form_bus_structure('sink');
if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
-
-
-
if len(get_p_gui()) > len(bus_structure):
times = range(len(bus_structure), len(get_p_gui()));
for i in times:
@@ -100,8 +97,6 @@ class FlowGraph(Element):
port = block.get_parent().get_parent().Port(block=block, n=n, dir=direc);
get_p().append(port);
-
-
for child in self.get_children(): child.rewrite()
refactor_bus_structure();
@@ -126,13 +121,13 @@ class FlowGraph(Element):
def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
def get_blocks_unordered(self): return filter(lambda e: e.is_block(), self.get_elements())
def get_blocks(self):
- blocks = self.get_blocks_unordered();
- for i in range(len(blocks)):
- if blocks[i].get_key() == 'variable':
- blk = blocks[i];
- blocks.remove(blk);
- blocks.insert(1, blk);
- return blocks;
+ # refactored the slow, ugly version
+ # don't know why we need this here, using it for sorted export_data()
+ return sorted(self.get_blocks_unordered(), key=lambda b: (
+ b.get_key() != 'options', # options to the front
+ not b.get_key().startswith('variable'), # then vars
+ str(b)
+ ))
def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
def get_children(self): return self.get_elements()
def get_elements(self):
@@ -152,13 +147,22 @@ class FlowGraph(Element):
def get_enabled_blocks(self):
"""
- Get a list of all blocks that are enabled.
+ Get a list of all blocks that are enabled and not bypassed.
Returns:
a list of blocks
"""
return filter(lambda b: b.get_enabled(), self.get_blocks())
+ def get_bypassed_blocks(self):
+ """
+ Get a list of all blocks that are bypassed.
+
+ Returns:
+ a list of blocks
+ """
+ return filter(lambda b: b.get_bypassed(), self.get_blocks())
+
def get_enabled_connections(self):
"""
Get a list of all connections that are enabled.
@@ -250,8 +254,8 @@ class FlowGraph(Element):
"""
n = odict()
n['timestamp'] = self._timestamp
- n['block'] = [block.export_data() for block in self.get_blocks()]
- n['connection'] = [connection.export_data() for connection in self.get_connections()]
+ n['block'] = [b.export_data() for b in self.get_blocks()] # already sorted
+ n['connection'] = [c.export_data() for c in sorted(self.get_connections(), key=str)]
instructions = odict({
'created': self.get_parent().get_version_short(),
'format': FLOW_GRAPH_FILE_FORMAT_VERSION,
diff --git a/grc/base/Param.py b/grc/base/Param.py
index 94be8b0fe0..c2f413ccbe 100644
--- a/grc/base/Param.py
+++ b/grc/base/Param.py
@@ -140,7 +140,7 @@ class Param(Element):
def get_color(self): return '#FFFFFF'
def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
def is_param(self): return True
- def get_name(self): return self._name
+ def get_name(self): return self.get_parent().resolve_dependencies(self._name).strip()
def get_key(self): return self._key
def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip()
diff --git a/grc/blocks/.gitignore b/grc/blocks/.gitignore
new file mode 100644
index 0000000000..2ac4a79e69
--- /dev/null
+++ b/grc/blocks/.gitignore
@@ -0,0 +1 @@
+variable_struct.xml
diff --git a/grc/blocks/CMakeLists.txt b/grc/blocks/CMakeLists.txt
index 98b6512a09..0c2a1f7901 100644
--- a/grc/blocks/CMakeLists.txt
+++ b/grc/blocks/CMakeLists.txt
@@ -18,6 +18,26 @@
# Boston, MA 02110-1301, USA.
########################################################################
+include(GrPython)
+
file(GLOB xml_files "*.xml")
-install(FILES ${xml_files} DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "grc")
+macro(GEN_BLOCK_XML _generator _xml_block)
+ set(generator ${CMAKE_CURRENT_SOURCE_DIR}/${_generator})
+ set(xml_block ${CMAKE_CURRENT_BINARY_DIR}/${_xml_block})
+ list(APPEND generated_xml_files ${xml_block})
+ add_custom_command(
+ DEPENDS ${generator} OUTPUT ${xml_block}
+ COMMAND ${PYTHON_EXECUTABLE} ${generator} ${xml_block}
+ )
+endmacro(GEN_BLOCK_XML)
+
+GEN_BLOCK_XML(variable_struct.xml.py variable_struct.xml)
+
+add_custom_target(grc_generated_xml ALL DEPENDS ${generated_xml_files})
+
+install(
+ FILES ${xml_files} ${generated_xml_files}
+ DESTINATION ${GRC_BLOCKS_DIR}
+ COMPONENT "grc"
+)
diff --git a/grc/blocks/options.xml b/grc/blocks/options.xml
index 6588dc72d0..dc02b83c2a 100644
--- a/grc/blocks/options.xml
+++ b/grc/blocks/options.xml
@@ -19,7 +19,7 @@ import wx
from PyQt4 import Qt
import sys
#end if
-#if $generate_options() != 'hb'
+#if not $generate_options().startswith('hb')
from optparse import OptionParser
from gnuradio.eng_option import eng_option
from gnuradio import eng_notation
@@ -49,9 +49,9 @@ else: self.stop(); self.wait()</callback>
<hide>#if $description() then 'none' else 'part'#</hide>
</param>
<param>
- <name>Window Size</name>
+ <name>Canvas Size</name>
<key>window_size</key>
- <value>1280, 1024</value>
+ <value></value>
<type>int_vector</type>
<hide>part</hide>
</param>
@@ -76,13 +76,17 @@ else: self.stop(); self.wait()</callback>
<name>Hier Block</name>
<key>hb</key>
</option>
+ <option>
+ <name>QT GUI Hier Block</name>
+ <key>hb_qt_gui</key>
+ </option>
</param>
<param>
<name>Category</name>
<key>category</key>
<value>Custom</value>
<type>string</type>
- <hide>#if $generate_options() == 'hb' then 'none' else 'all'#</hide>
+ <hide>#if $generate_options().startswith('hb') then 'none' else 'all'#</hide>
</param>
<param>
<name>Run Options</name>
@@ -129,7 +133,7 @@ else: self.stop(); self.wait()</callback>
<key>max_nouts</key>
<value>0</value>
<type>int</type>
- <hide>#if $generate_options() == 'hb'
+ <hide>#if $generate_options().startswith('hb')
all#slurp
#elif $max_nouts()
none#slurp
@@ -142,7 +146,7 @@ part#slurp
<key>realtime_scheduling</key>
<value></value>
<type>enum</type>
- <hide>#if $generate_options() == 'hb'
+ <hide>#if $generate_options().startswith('hb')
all#slurp
#elif $realtime_scheduling()
none#slurp
@@ -174,9 +178,9 @@ part#slurp
</option>
<tab>Advanced</tab>
</param>
- <check>len($window_size) == 2</check>
- <check>300 &lt;= $(window_size)[0] &lt;= 4096</check>
- <check>300 &lt;= $(window_size)[1] &lt;= 4096</check>
+ <check>not $window_size or len($window_size) == 2</check>
+ <check>not $window_size or 300 &lt;= $(window_size)[0] &lt;= 4096</check>
+ <check>not $window_size or 300 &lt;= $(window_size)[1] &lt;= 4096</check>
<doc>
The options block sets special parameters for the flow graph. \
Only one option block is allowed per flow graph.
diff --git a/grc/blocks/variable_struct.xml.py b/grc/blocks/variable_struct.xml.py
new file mode 100644
index 0000000000..e43200828b
--- /dev/null
+++ b/grc/blocks/variable_struct.xml.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+MAX_NUM_FIELDS = 20
+
+HEADER = """\
+<block>
+ <name>Struct Variable</name>
+ <key>variable_struct</key>
+ <category>Variables</category>
+ <import>def struct(data): return type('Struct', (object,), data)()</import>
+ <var_make>self.$id = $id = struct({{#slurp
+#for $i in range({0}):
+#set $field = $getVar('field' + str(i))
+#if len(str($field)) > 2
+$field: $getVar('value' + str(i)), #slurp
+#end if
+#end for
+}})</var_make>
+ <var_value>struct({{#slurp
+#for $i in range({0}):
+#set $field = $getVar('field' + str(i))
+#if len(str($field)) > 2
+$field: $getVar('value' + str(i)), #slurp
+#end if
+#end for
+}})</var_value>
+ <make></make>
+"""
+
+FIELD0 = """\
+ <param>
+ <name>Field 0</name>
+ <key>field0</key>
+ <value>field0</value>
+ <type>string</type>
+ <hide>part</hide>
+ <tab>Fields</tab>
+ </param>
+"""
+
+FIELDS = """\
+ <param>
+ <name>Field {0}</name>
+ <key>field{0}</key>
+ <value></value>
+ <type>string</type>
+ <hide>part</hide>
+ <tab>Fields</tab>
+ </param>
+"""
+
+VALUES = """\
+ <param>
+ <name>$field{0}()</name>
+ <key>value{0}</key>
+ <value>0</value>
+ <type>raw</type>
+ <hide>#if $field{0}() then 'none' else 'all'#</hide>
+ </param>
+"""
+
+CHECKS = """\
+ <check>($str($field{0}) or "a")[0].isalpha()</check>
+ <check>($str($field{0}) or "a").isalnum()</check>
+"""
+
+FOOTER = """\
+ <doc>This is a simple struct/record like variable.
+
+Attribute/field names can be specified in the tab 'Fields'.
+For each non-empty field a parameter with type raw is shown.
+Value access via the dot operator, e.g. "variable_struct_0.field0"
+ </doc>
+</block>
+"""
+
+
+def make_xml(num_fields):
+ return ''.join((
+ HEADER.format(num_fields),
+ FIELD0, ''.join(FIELDS.format(i) for i in range(1, num_fields)),
+ ''.join(VALUES.format(i) for i in range(num_fields)),
+ ''.join(CHECKS.format(i) for i in range(num_fields)),
+ FOOTER
+ ))
+
+
+if __name__ == '__main__':
+ import sys
+ try:
+ filename = sys.argv[1]
+ except IndexError:
+ filename = __file__[:-3]
+
+ data = make_xml(MAX_NUM_FIELDS)
+
+ with open(filename, 'w') as fp:
+ fp.write(data.encode())
diff --git a/grc/freedesktop/CMakeLists.txt b/grc/freedesktop/CMakeLists.txt
index d95fe04ac5..47e836f697 100644
--- a/grc/freedesktop/CMakeLists.txt
+++ b/grc/freedesktop/CMakeLists.txt
@@ -26,6 +26,8 @@ install(FILES
grc-icon-64.png
grc-icon-48.png
grc-icon-32.png
+ grc-icon-24.png
+ grc-icon-16.png
gnuradio-grc.xml
gnuradio-grc.desktop
DESTINATION ${grc_freedesktop_path}
diff --git a/grc/freedesktop/convert.sh b/grc/freedesktop/convert.sh
new file mode 100755
index 0000000000..e2cba264a6
--- /dev/null
+++ b/grc/freedesktop/convert.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+SRC="gnuradio_logo_icon-square.svg"
+SIZES="16 24 32 48 64 128 256"
+
+for size in $SIZES
+do
+ inkscape --without-gui \
+ --export-png="grc-icon-$size.png" \
+ --export-area=8.0:8.0:141.316:141.316 \
+ --export-width=$size \
+ --export-height=$size \
+ $SRC;
+done
diff --git a/grc/freedesktop/gnuradio-grc.desktop b/grc/freedesktop/gnuradio-grc.desktop
index 5fd0497808..39beeca1b8 100644
--- a/grc/freedesktop/gnuradio-grc.desktop
+++ b/grc/freedesktop/gnuradio-grc.desktop
@@ -6,3 +6,4 @@ Exec=gnuradio-companion %F
Categories=Development;
MimeType=application/gnuradio-grc;
Icon=gnuradio-grc
+StartupWMClass=gnuradio-companion
diff --git a/grc/freedesktop/gnuradio_logo_icon-square.svg b/grc/freedesktop/gnuradio_logo_icon-square.svg
new file mode 100644
index 0000000000..3b54bf4001
--- /dev/null
+++ b/grc/freedesktop/gnuradio_logo_icon-square.svg
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="150"
+ height="150"
+ id="svg3965"
+ version="1.1"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="gnuradio_logo_icon.svg">
+ <defs
+ id="defs3967" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.959798"
+ inkscape:cx="139.75154"
+ inkscape:cy="47.200773"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1176"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata3970">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-57.226591,-6.6600272)">
+ <g
+ id="g4684"
+ transform="translate(30,0)">
+ <path
+ class="fil3"
+ d="m 136.1636,73.874976 c 3.50539,3.465 5.25827,7.69571 5.25827,12.691774 0,4.87524 -1.7426,9.05563 -5.2278,12.54083 -3.4852,3.4852 -7.64539,5.22779 -12.48024,5.22779 -3.39165,0 -6.44775,-0.82488 -9.16795,-2.47464 l -6.34075,6.34075 c 3.94548,4.48866 5.91804,9.83941 5.91804,16.05189 0,6.69649 -2.39351,12.43842 -7.18087,17.22578 -4.78701,4.78736 -10.5013,7.18087 -17.142875,7.18087 -6.751771,0 -12.535866,-2.38004 -17.350511,-7.13977 -4.815,-4.75937 -7.222323,-10.51511 -7.222323,-17.26688 0,-6.75248 2.324055,-12.53587 6.973582,-17.35087 4.648819,-4.815 10.349292,-7.22232 17.101417,-7.22232 5.988189,0 11.18799,1.78334 15.60083,5.34968 l 6.03602,-6.03567 c -3.40972,-3.437 -5.11441,-7.57948 -5.11441,-12.42744 0,-4.915634 1.69228,-9.126144 5.07685,-12.631534 0.31429,-0.32528 0.63532,-0.63567 0.96272,-0.93083 l -6.1728,-6.17279 c -2.68193,2.54799 -5.857438,3.82216 -9.526533,3.82216 -3.871062,0 -7.187598,-1.36453 -9.948188,-4.09358 -2.760945,-2.72906 -4.141418,-6.02929 -4.141418,-9.90071 0,-3.87142 1.332993,-7.18795 3.998622,-9.94854 2.66563,-2.76095 5.933977,-4.14142 9.805394,-4.14142 3.967086,0 7.330393,1.36488 10.091693,4.09394 2.76024,2.7287 4.14071,6.06082 4.14071,9.99602 0,2.69256 -0.67465,5.11583 -2.02429,7.27016 l 6.85275,6.85311 c 2.49768,-1.40351 5.30114,-2.10544 8.41146,-2.10544 5.03646,0 9.3072,1.73233 12.8126,5.19768 z M 96.164267,48.757896 c -2.189409,0 -4.030157,0.77704 -5.521535,2.3322 -1.491378,1.5548 -2.237244,3.4115 -2.237244,5.56937 0,2.22094 0.729921,4.07764 2.189764,5.56937 1.459842,1.49138 3.316181,2.23689 5.569015,2.23689 2.126339,0 3.927043,-0.76925 5.402833,-2.30846 1.47543,-1.53922 2.21315,-3.37182 2.21315,-5.4978 0,-1.0474 -0.19027,-2.04697 -0.57118,-2.99905 -0.38055,-0.95209 -0.9202,-1.77697 -1.61823,-2.47536 -0.69838,-0.72957 -1.53106,-1.31669 -2.499092,-1.76102 -0.967677,-0.44433 -1.943504,-0.66614 -2.927481,-0.66614 z m -6.364842,61.714484 c -3.818976,0 -7.028858,1.35567 -9.629645,4.06736 -2.601496,2.71205 -3.902244,5.94992 -3.902244,9.71363 0,3.87354 1.272755,7.11141 3.818976,9.71291 2.545512,2.60079 5.78374,3.90153 9.712913,3.90153 3.708071,0 6.848858,-1.34185 9.422362,-4.02661 2.573153,-2.6837 3.860433,-5.87976 3.860433,-9.58783 0,-1.82693 -0.33201,-3.56989 -0.99638,-5.23028 -0.66401,-1.66039 -1.60476,-3.09933 -2.822596,-4.31681 -1.217481,-1.27311 -2.670236,-2.29677 -4.358622,-3.07169 -1.687323,-0.77492 -3.389528,-1.16221 -5.105197,-1.16221 z M 123.71383,76.534226 c -2.78043,0 -5.11724,0.98681 -7.01078,2.96115 -1.8939,1.97433 -2.84067,4.33133 -2.84067,7.071374 0,2.82048 0.92657,5.17748 2.78008,7.07138 1.8535,1.89354 4.21051,2.84032 7.07137,2.84032 2.6993,0 4.98579,-0.97725 6.85949,-2.93138 1.87335,-1.95414 2.8102,-4.28067 2.8102,-6.98032 0,-1.3298 -0.24165,-2.599014 -0.72532,-3.807634 -0.4833,-1.20863 -1.16822,-2.25638 -2.05476,-3.14256 -0.88654,-0.92693 -1.94421,-1.67209 -3.17303,-2.23618 -1.22882,-0.56445 -2.46756,-0.84615 -3.71658,-0.84615 z"
+ id="path3484"
+ inkscape:connector-curvature="0"
+ style="fill:#ff6905;fill-rule:evenodd" />
+ <path
+ class="fil3"
+ d="m 71.293796,36.662816 c 4.548897,-8.03374 13.97622,-13.55421 24.865865,-13.55421 10.854209,0 20.255669,5.48503 24.821569,13.4759 l 5.54103,-5.68453 c -6.21354,-9.32279 -17.48799,-15.55547 -30.362599,-15.55547 -12.967086,0 -24.311338,6.32303 -30.49618,15.7578 l 5.630315,5.56051 z"
+ id="path3486"
+ inkscape:connector-curvature="0"
+ style="fill:#ff6905;fill-rule:evenodd" />
+ <path
+ class="fil3"
+ d="m 96.092693,28.893756 c -9.484725,0 -17.688189,4.48441 -21.598228,10.99595 l 5.61685,5.5474 c 2.163189,-5.05347 8.501457,-8.71335 15.981378,-8.71335 7.554687,0 13.944327,3.73358 16.044447,8.86536 l 5.55449,-5.69835 c -3.91004,-6.51224 -12.1135,-10.99701 -21.598937,-10.99701 z"
+ id="path3488"
+ inkscape:connector-curvature="0"
+ style="fill:#ff6905;fill-rule:evenodd" />
+ <text
+ x="195.22275"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3496"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="256.77316"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3506"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="279.70544"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3510"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="344.62241"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3520"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="473.09561"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3538"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="548.49011"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3550"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ <text
+ x="687.89447"
+ y="148.5569"
+ class="fil4 fnt0"
+ id="text3570"
+ style="font-size:17.76259804px;font-weight:bold;fill:#969594;fill-rule:evenodd;font-family:Harabara" />
+ </g>
+ </g>
+</svg>
diff --git a/grc/freedesktop/grc-icon-128.png b/grc/freedesktop/grc-icon-128.png
index d94ef35dc3..13efe806ba 100644
--- a/grc/freedesktop/grc-icon-128.png
+++ b/grc/freedesktop/grc-icon-128.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-16.png b/grc/freedesktop/grc-icon-16.png
new file mode 100644
index 0000000000..bdd1823b3d
--- /dev/null
+++ b/grc/freedesktop/grc-icon-16.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-24.png b/grc/freedesktop/grc-icon-24.png
new file mode 100644
index 0000000000..a124768125
--- /dev/null
+++ b/grc/freedesktop/grc-icon-24.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-256.png b/grc/freedesktop/grc-icon-256.png
index e4e8e54ae1..077688eac5 100644
--- a/grc/freedesktop/grc-icon-256.png
+++ b/grc/freedesktop/grc-icon-256.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-256.svg b/grc/freedesktop/grc-icon-256.svg
deleted file mode 100644
index 87526d46c6..0000000000
--- a/grc/freedesktop/grc-icon-256.svg
+++ /dev/null
@@ -1,216 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="256"
- height="256"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.44.1"
- version="1.0"
- sodipodi:docbase="/home/past/src"
- sodipodi:docname="grc-icon-v3.svg"
- inkscape:export-filename="/home/past/src/grc-icon-v3.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient3661">
- <stop
- style="stop-color:#0012dc;stop-opacity:1;"
- offset="0"
- id="stop3663" />
- <stop
- style="stop-color:#8b92ff;stop-opacity:0.55371898;"
- offset="1"
- id="stop3665" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3661"
- id="linearGradient2801"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(-162.6648,798.0997)"
- x1="17.664845"
- y1="132.0565"
- x2="157.82524"
- y2="132.0565" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="2.7382812"
- inkscape:cx="126.48791"
- inkscape:cy="128.00013"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="true"
- gridoriginx="1px"
- gridoriginy="1px"
- gridspacingx="2px"
- gridspacingy="2px"
- guidecolor="#00ff0a"
- guideopacity="0.49803922"
- inkscape:grid-points="true"
- inkscape:window-width="1098"
- inkscape:window-height="904"
- inkscape:window-x="149"
- inkscape:window-y="42"
- showguides="true"
- inkscape:guide-bbox="true"
- inkscape:object-points="true"
- inkscape:object-nodes="true"
- inkscape:object-bbox="true">
- <sodipodi:guide
- orientation="vertical"
- position="224"
- id="guide10639" />
- <sodipodi:guide
- orientation="vertical"
- position="227.64729"
- id="guide10641" />
- <sodipodi:guide
- orientation="vertical"
- position="220"
- id="guide10643" />
- <sodipodi:guide
- orientation="horizontal"
- position="268.4015"
- id="guide10645" />
- </sodipodi:namedview>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <cc:license
- rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
- <dc:creator>
- <cc:Agent>
- <dc:title>Patrick Strasser &lt;patrick.strasser@tugraz.at&gt;</dc:title>
- </cc:Agent>
- </dc:creator>
- <dc:description>Icon/Symbol for the GNURadio Companion</dc:description>
- <dc:title>grc-icon.svg</dc:title>
- <dc:date>2007-02-23</dc:date>
- </cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/by-sa/2.5/">
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Reproduction" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Distribution" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Notice" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Attribution" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/ShareAlike" />
- </cc:License>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Ebene 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-796.3622)">
- <g
- id="g7451"
- transform="matrix(1.025628,0,0,1.030546,-0.101723,-32.00742)">
- <path
- id="rect2760"
- d="M 4.1981031,916.37787 L 160.00074,916.37787 L 160.00074,1048.3467 L 4.1981031,1048.3467 L 4.1981031,916.37787 z "
- style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.78145933;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <g
- transform="matrix(0.995753,0,0,1.003897,164.8198,-8.972397)"
- id="g2789"
- style="stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none">
- <rect
- style="fill:url(#linearGradient2801);fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.78288651;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect9020"
- width="140.1604"
- height="16.796082"
- x="-145"
- y="921.75818" />
- <path
- style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.78288651;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M -161.50649,938.55428 L -4.8395996,938.55428"
- id="path9005" />
- </g>
- </g>
- <g
- id="g5503"
- transform="matrix(1.028571,0,0,1.172413,-5.14284,-137.9928)">
- <rect
- y="800.36212"
- x="40"
- height="116.00005"
- width="140"
- id="rect4562"
- style="fill:#f3c690;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.28504848;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <g
- transform="matrix(0.921053,0,0,1,26.93956,1.859948)"
- id="g3694">
- <path
- style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.59084845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 44,820.3622 L 136.35974,820.3622"
- id="path4564" />
- <path
- style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.59084749;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 80,811.74976 L 80,828.3622"
- id="path5451" />
- </g>
- <g
- id="g5499">
- <rect
- style="fill:white;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.28504944;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect7223"
- width="140"
- height="68.000015"
- x="40"
- y="848.36218" />
- <path
- style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:7.28505039;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 57.001362,905.90132 C 88.923615,905.8552 86.182775,867.89142 95.399136,867.52563 C 104.60967,867.16008 113.73233,867.60291 124.38688,868.00066 C 137.23411,868.48027 130.39915,906.48027 162.99863,906.48027"
- id="path7225"
- sodipodi:nodetypes="czss" />
- </g>
- </g>
- <rect
- style="fill:#b890f3;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999952;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect14319"
- width="79.999992"
- height="64.000023"
- x="27.999992"
- y="960.36249" />
- <rect
- style="fill:#f3c690;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999905;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect15206"
- width="24.000004"
- height="24.000004"
- x="108"
- y="980.36218" />
- <path
- id="path13320"
- style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:7.99999666;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
- d="M 220.97574,800.36203 L 220.97574,865.80513 C 236.42474,865.93437 248.49884,861.19996 248.96304,854.45866 C 249.42721,847.71737 237.26568,843.20829 221.81667,846.27676 C 206.36767,849.34522 193.45938,858.02071 192.98843,867.61976 C 192.53101,876.94268 204.68583,884.63729 220.13479,885.43882 C 235.58379,885.69443 248.49884,880.72833 248.96304,873.98703 C 249.42721,867.24575 237.26567,862.73666 221.81666,865.80513 C 206.36766,868.8736 193.45939,877.54909 192.98843,887.14813 C 192.53101,896.47106 204.68582,904.16566 220.13479,904.86701 C 235.5838,905.02246 248.49885,900.05636 248.96305,893.31506 C 249.42722,886.57378 237.26568,882.06469 221.81667,885.13316 C 206.36767,888.20162 193.45939,896.87711 192.98844,906.47616 C 192.53102,915.79909 204.68583,923.49369 220.13479,923.98015 C 235.58379,923.92069 248.49884,918.95459 248.96304,912.21329 C 249.42721,905.47201 237.26567,900.96293 221.81666,904.0314 C 206.36766,907.09986 193.45939,915.77535 192.98843,925.37439 C 192.53101,934.69732 207.20989,943.06708 221.81667,943.00644 L 221.81667,967.97713 C 221.63716,982.45754 209.62079,992.36197 195.88792,992.36199 L 132.42659,992.36199"
- sodipodi:nodetypes="cccssscssscssscssccc" />
- </g>
-</svg>
diff --git a/grc/freedesktop/grc-icon-32.png b/grc/freedesktop/grc-icon-32.png
index 1e4f4f6c5a..a345aace3c 100644
--- a/grc/freedesktop/grc-icon-32.png
+++ b/grc/freedesktop/grc-icon-32.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-48.png b/grc/freedesktop/grc-icon-48.png
index caddc92ad4..c522a5d0ec 100644
--- a/grc/freedesktop/grc-icon-48.png
+++ b/grc/freedesktop/grc-icon-48.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-64.png b/grc/freedesktop/grc-icon-64.png
index fa8e06e280..df4f6dc07b 100644
--- a/grc/freedesktop/grc-icon-64.png
+++ b/grc/freedesktop/grc-icon-64.png
Binary files differ
diff --git a/grc/freedesktop/grc_setup_freedesktop.in b/grc/freedesktop/grc_setup_freedesktop.in
index 1e3546197d..87a388e2ec 100644
--- a/grc/freedesktop/grc_setup_freedesktop.in
+++ b/grc/freedesktop/grc_setup_freedesktop.in
@@ -27,7 +27,7 @@
# @SRCDIR@
##################################################
-ICON_SIZES="32 48 64 128 256"
+ICON_SIZES="16 24 32 48 64 128 256"
if [ -n "$2" ]; then
SRCDIR="$2"
else
diff --git a/grc/grc.conf.in b/grc/grc.conf.in
index 99ae9caff5..71c4f63bca 100644
--- a/grc/grc.conf.in
+++ b/grc/grc.conf.in
@@ -6,3 +6,5 @@
global_blocks_path = @blocksdir@
local_blocks_path =
xterm_executable = @GRC_XTERM_EXE@
+canvas_font_size = 8
+canvas_default_size = 1280, 1024
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index fee96624bb..15565127e3 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -18,7 +18,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
import os
-import signal
from Constants import IMAGE_FILE_EXTENSION
import Actions
import pygtk
@@ -29,15 +28,17 @@ import subprocess
import Preferences
from threading import Thread
import Messages
-from .. base import ParseXML
+from .. base import ParseXML, Constants
from MainWindow import MainWindow
from PropsDialog import PropsDialog
from ParserErrorsDialog import ParserErrorsDialog
import Dialogs
from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveReportsFileDialog, SaveImageFileDialog
+from . Constants import DEFAULT_CANVAS_SIZE
gobject.threads_init()
+
class ActionHandler:
"""
The action handler will setup all the major window components,
@@ -124,6 +125,7 @@ class ActionHandler:
Actions.CLEAR_REPORTS, Actions.SAVE_REPORTS,
Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID,
Actions.TOGGLE_SHOW_BLOCK_COMMENTS,
+ Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB,
): action.set_sensitive(True)
if ParseXML.xml_failures:
Messages.send_xml_errors_if_any(ParseXML.xml_failures)
@@ -146,6 +148,7 @@ class ActionHandler:
Actions.TOGGLE_SCROLL_LOCK,
Actions.TOGGLE_SNAP_TO_GRID,
Actions.TOGGLE_SHOW_BLOCK_COMMENTS,
+ Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB,
): action.load_from_preferences()
elif action == Actions.APPLICATION_QUIT:
if self.main_window.close_pages():
@@ -171,6 +174,11 @@ class ActionHandler:
self.get_flow_graph().update()
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_BYPASS:
+ if self.get_flow_graph().bypass_selected():
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
##################################################
# Cut/Copy/Paste
##################################################
@@ -405,6 +413,8 @@ class ActionHandler:
action.save_to_preferences()
elif action == Actions.TOGGLE_SHOW_BLOCK_COMMENTS:
action.save_to_preferences()
+ elif action == Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB:
+ action.save_to_preferences()
##################################################
# Param Modifications
##################################################
@@ -553,23 +563,34 @@ class ActionHandler:
##################################################
# Global Actions for all States
##################################################
+ selected_block = self.get_flow_graph().get_selected_block()
+ selected_blocks = self.get_flow_graph().get_selected_blocks()
+
#update general buttons
Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not self.get_flow_graph().is_valid())
Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
- Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block()))
- Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_ROTATE_CW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(selected_block))
+ Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_ROTATE_CW.set_sensitive(bool(selected_blocks))
#update cut/copy/paste
- Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_CUT.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_COPY.set_sensitive(bool(selected_blocks))
Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard))
- #update enable/disable
- Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_CREATE_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BUSSIFY_SOURCES.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BUSSIFY_SINKS.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ #update enable/disable/bypass
+ can_enable = any(block.get_state() != Constants.BLOCK_ENABLED
+ for block in selected_blocks)
+ can_disable = any(block.get_state() != Constants.BLOCK_DISABLED
+ for block in selected_blocks)
+ can_bypass_all = all(block.can_bypass() for block in selected_blocks) \
+ and any (not block.get_bypassed() for block in selected_blocks)
+ Actions.BLOCK_ENABLE.set_sensitive(can_enable)
+ Actions.BLOCK_DISABLE.set_sensitive(can_disable)
+ Actions.BLOCK_BYPASS.set_sensitive(can_bypass_all)
+
+ Actions.BLOCK_CREATE_HIER.set_sensitive(bool(selected_blocks))
+ Actions.OPEN_HIER.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SOURCES.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SINKS.set_sensitive(bool(selected_blocks))
Actions.RELOAD_BLOCKS.set_sensitive(True)
Actions.FIND_BLOCKS.set_sensitive(True)
#set the exec and stop buttons
@@ -578,7 +599,8 @@ class ActionHandler:
Actions.FLOW_GRAPH_SAVE.set_sensitive(not self.get_page().get_saved())
self.main_window.update()
try: #set the size of the flow graph area (if changed)
- new_size = self.get_flow_graph().get_option('window_size')
+ new_size = (self.get_flow_graph().get_option('window_size') or
+ DEFAULT_CANVAS_SIZE)
if self.get_flow_graph().get_size() != tuple(new_size):
self.get_flow_graph().set_size(*new_size)
except: pass
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index b2b3a76386..d864db7e16 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -106,7 +106,8 @@ class Action(gtk.Action, _ActionBase):
Pass additional arguments such as keypresses.
"""
- def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
+ def __init__(self, keypresses=(), name=None, label=None, tooltip=None,
+ stock_id=None):
"""
Create a new Action instance.
@@ -129,7 +130,8 @@ class ToggleAction(gtk.ToggleAction, _ActionBase):
Pass additional arguments such as keypresses.
"""
- def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None, preference_name=None):
+ def __init__(self, keypresses=(), name=None, label=None, tooltip=None,
+ stock_id=None, preference_name=None, default=True):
"""
Create a new ToggleAction instance.
@@ -137,22 +139,24 @@ class ToggleAction(gtk.ToggleAction, _ActionBase):
key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
the: regular gtk.Action parameters (defaults to None)
"""
- if name is None: name = label
+ if name is None:
+ name = label
gtk.ToggleAction.__init__(self,
- name=name, label=label,
- tooltip=tooltip, stock_id=stock_id,
+ name=name, label=label, tooltip=tooltip, stock_id=stock_id,
)
- #register this action
_ActionBase.__init__(self, label, keypresses)
self.preference_name = preference_name
+ self.default = default
def load_from_preferences(self):
if self.preference_name is not None:
- self.set_active(Preferences.bool_entry(self.preference_name))
+ self.set_active(Preferences.bool_entry(self.preference_name,
+ default=self.default))
def save_to_preferences(self):
if self.preference_name is not None:
- Preferences.bool_entry(self.preference_name, self.get_active())
+ Preferences.bool_entry(self.preference_name,
+ value=self.get_active())
########################################################################
# Actions
@@ -247,6 +251,12 @@ BLOCK_DISABLE = Action(
stock_id=gtk.STOCK_DISCONNECT,
keypresses=(gtk.keysyms.d, NO_MODS_MASK),
)
+BLOCK_BYPASS = Action(
+ label='_Bypass',
+ tooltip='Bypass the selected block',
+ stock_id=gtk.STOCK_MEDIA_FORWARD,
+ keypresses=(gtk.keysyms.b, NO_MODS_MASK),
+)
TOGGLE_SNAP_TO_GRID = ToggleAction(
label='_Snap to grid',
tooltip='Snap blocks to a grid for an easier connection alignment',
@@ -268,6 +278,13 @@ TOGGLE_SHOW_BLOCK_COMMENTS = ToggleAction(
tooltip="Show comment beneath each block",
preference_name='show_block_comments'
)
+TOGGLE_SHOW_CODE_PREVIEW_TAB = ToggleAction(
+ label='Generated Code Preview',
+ tooltip="Show a preview of the code generated for each Block in its "
+ "Properties Dialog",
+ preference_name='show_generated_code_tab',
+ default=False,
+)
BLOCK_CREATE_HIER = Action(
label='C_reate Hier',
tooltip='Create hier block from selected blocks',
@@ -298,13 +315,13 @@ ERRORS_WINDOW_DISPLAY = Action(
stock_id=gtk.STOCK_DIALOG_ERROR,
)
TOGGLE_REPORTS_WINDOW = ToggleAction(
- label='Show _Reports',
+ label='Show _Reports Panel',
tooltip='Toggle visibility of the Report widget',
keypresses=(gtk.keysyms.r, gtk.gdk.CONTROL_MASK),
preference_name='reports_window_visible'
)
TOGGLE_BLOCKS_WINDOW = ToggleAction(
- label='Show _Block Tree',
+ label='Show _Block Tree Panel',
tooltip='Toggle visibility of the block tree widget',
keypresses=(gtk.keysyms.b, gtk.gdk.CONTROL_MASK),
preference_name='blocks_window_visible'
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 40ce20536c..f0f8dac7fb 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -49,6 +49,7 @@ TOOLBAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
Actions.TOGGLE_HIDE_DISABLED_BLOCKS,
None,
Actions.FIND_BLOCKS,
@@ -85,6 +86,7 @@ MENU_BAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
Actions.BLOCK_PARAM_MODIFY,
]),
@@ -101,6 +103,8 @@ MENU_BAR_LIST = (
Actions.TOGGLE_SNAP_TO_GRID,
Actions.TOGGLE_SHOW_BLOCK_COMMENTS,
None,
+ Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB,
+ None,
Actions.ERRORS_WINDOW_DISPLAY,
Actions.FIND_BLOCKS,
]),
@@ -134,6 +138,7 @@ CONTEXT_MENU_LIST = [
Actions.BLOCK_ROTATE_CW,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
(gtk.Action('More', '_More', None, None), [
Actions.BLOCK_CREATE_HIER,
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 60f19fc1a4..11273a537b 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -22,10 +22,10 @@ import Utils
import Colors
from .. base import odict
from Constants import BORDER_PROXIMITY_SENSITIVITY
-from Constants import \
- BLOCK_LABEL_PADDING, \
- PORT_SEPARATION, LABEL_SEPARATION, \
+from Constants import (
+ BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION,
PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS, BLOCK_FONT, PARAM_FONT
+)
import Actions
import pygtk
pygtk.require('2.0')
@@ -72,6 +72,7 @@ class Block(Element):
))
Element.__init__(self)
self._comment_pixmap = None
+ self.has_busses = [False, False] # source, sink
def get_coordinate(self):
"""
@@ -145,7 +146,9 @@ class Block(Element):
"""Create the labels for the signal block."""
Element.create_labels(self)
self._bg_color = self.is_dummy_block() and Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
+ self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR or \
self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
+
layouts = list()
#create the main layout
layout = gtk.DrawingArea().create_pango_layout('')
@@ -188,13 +191,14 @@ class Block(Element):
self.vertical_label = self.get_parent().new_pixmap(height, width)
Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label)
#calculate width and height needed
- self.W = self.label_width + 2*BLOCK_LABEL_PADDING
+ self.W = self.label_width + 2 * BLOCK_LABEL_PADDING
+
def get_min_height_for_ports():
visible_ports = filter(lambda p: not p.get_hide(), ports)
H = 2*PORT_BORDER_SEPARATION + len(visible_ports) * PORT_SEPARATION
if visible_ports: H -= ports[0].H
return H
- self.H = max(*(
+ self.H = max(
[ # labels
self.label_height + 2 * BLOCK_LABEL_PADDING
] +
@@ -202,11 +206,15 @@ class Block(Element):
get_min_height_for_ports() for ports in (self.get_sources_gui(), self.get_sinks_gui())
] +
[ # bus ports only
- 4 * PORT_BORDER_SEPARATION +
- sum([port.H + PORT_SEPARATION for port in ports if port.get_type() == 'bus']) - PORT_SEPARATION
+ 2 * PORT_BORDER_SEPARATION +
+ sum([port.H + PORT_SPACING for port in ports if port.get_type() == 'bus']) - PORT_SPACING
for ports in (self.get_sources_gui(), self.get_sinks_gui())
]
- ))
+ )
+ self.has_busses = [
+ any(port.get_type() == 'bus' for port in ports)
+ for ports in (self.get_sources_gui(), self.get_sinks_gui())
+ ]
self.create_comment_label()
def create_comment_label(self):
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
index f64106b03f..52c95e8edf 100644
--- a/grc/gui/Colors.py
+++ b/grc/gui/Colors.py
@@ -38,6 +38,7 @@ try:
#block color constants
BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
+ BLOCK_BYPASSED_COLOR = get_color('#FFFFE6')
#connection color constants
CONNECTION_ENABLED_COLOR = get_color('black')
CONNECTION_DISABLED_COLOR = get_color('#BBBBBB')
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 0dc6279fd2..a8395f631e 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -18,78 +18,104 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
import pygtk
+
pygtk.require('2.0')
import gtk
import os
+import sys
+from gnuradio import gr
+
+_gr_prefs = gr.prefs()
+
-##default path for the open/save dialogs
+# default path for the open/save dialogs
DEFAULT_FILE_PATH = os.getcwd()
-##file extensions
+# file extensions
IMAGE_FILE_EXTENSION = '.png'
TEXT_FILE_EXTENSION = '.txt'
-##name for new/unsaved flow graphs
+# name for new/unsaved flow graphs
NEW_FLOGRAPH_TITLE = 'untitled'
-##main window constraints
+# main window constraints
MIN_WINDOW_WIDTH = 600
MIN_WINDOW_HEIGHT = 400
-##dialog constraints
+# dialog constraints
MIN_DIALOG_WIDTH = 500
MIN_DIALOG_HEIGHT = 500
-##default sizes
+# default sizes
DEFAULT_BLOCKS_WINDOW_WIDTH = 100
DEFAULT_REPORTS_WINDOW_WIDTH = 100
-## flow-graph canvas fonts
+
+try: # ugly, but matches current code style
+ raw = _gr_prefs.get_string('grc', 'canvas_default_size', '1280, 1024')
+ DEFAULT_CANVAS_SIZE = tuple(int(x.strip('() ')) for x in raw.split(','))
+ if len(DEFAULT_CANVAS_SIZE) != 2 or not all(300 < x < 4096 for x in DEFAULT_CANVAS_SIZE):
+ raise Exception()
+except:
+ DEFAULT_CANVAS_SIZE = 1280, 1024
+ print >> sys.stderr, "Error: invalid 'canvas_default_size' setting."
+
+# flow-graph canvas fonts
+try: # ugly, but matches current code style
+ FONT_SIZE = _gr_prefs.get_long('grc', 'canvas_font_size', 8)
+ if FONT_SIZE <= 0:
+ raise Exception()
+except:
+ FONT_SIZE = 8
+ print >> sys.stderr, "Error: invalid 'canvas_font_size' setting."
FONT_FAMILY = "Sans"
-FONT_SIZE = 8
BLOCK_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE)
PORT_FONT = BLOCK_FONT
PARAM_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE - 0.5)
-##The size of the state saving cache in the flow graph (for undo/redo functionality)
+# size of the state saving cache in the flow graph (undo/redo functionality)
STATE_CACHE_SIZE = 42
-##Shared targets for drag and drop of blocks
+# Shared targets for drag and drop of blocks
DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)]
-#label constraint dimensions
+# label constraint dimensions
LABEL_SEPARATION = 3
BLOCK_LABEL_PADDING = 7
PORT_LABEL_PADDING = 2
-#port constraint dimensions
-PORT_SEPARATION = 32
-PORT_BORDER_SEPARATION = 9
+# canvas grid size
+CANVAS_GRID_SIZE = 8
+
+# port constraint dimensions
+PORT_BORDER_SEPARATION = 8
+PORT_SPACING = 2 * PORT_BORDER_SEPARATION
+PORT_SEPARATION = PORT_SPACING + 2 * PORT_LABEL_PADDING + int(1.5 * FONT_SIZE)
+PORT_SEPARATION += -PORT_SEPARATION % (2 * CANVAS_GRID_SIZE) # even multiple
+
PORT_MIN_WIDTH = 20
PORT_LABEL_HIDDEN_WIDTH = 10
-#minimal length of connector
+# minimal length of connector
CONNECTOR_EXTENSION_MINIMAL = 11
-#increment length for connector
+# increment length for connector
CONNECTOR_EXTENSION_INCREMENT = 11
-#connection arrow dimensions
+# connection arrow dimensions
CONNECTOR_ARROW_BASE = 13
CONNECTOR_ARROW_HEIGHT = 17
-#possible rotations in degrees
+# possible rotations in degrees
POSSIBLE_ROTATIONS = (0, 90, 180, 270)
-#How close can the mouse get to the window border before mouse events are ignored.
+# How close can the mouse get to the window border before mouse events are ignored.
BORDER_PROXIMITY_SENSITIVITY = 50
-#How close the mouse can get to the edge of the visible window before scrolling is invoked.
+# How close the mouse can get to the edge of the visible window before scrolling is invoked.
SCROLL_PROXIMITY_SENSITIVITY = 30
-#When the window has to be scrolled, move it this distance in the required direction.
+# When the window has to be scrolled, move it this distance in the required direction.
SCROLL_DISTANCE = 15
-#How close the mouse click can be to a line and register a connection select.
+# How close the mouse click can be to a line and register a connection select.
LINE_SELECT_SENSITIVITY = 5
-# canvas grid size
-CANVAS_GRID_SIZE = 8
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 97f814f1bf..bf6e1eed78 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -211,9 +211,21 @@ class FlowGraph(Element):
"""
changed = False
for selected_block in self.get_selected_blocks():
- if selected_block.get_enabled() != enable:
- selected_block.set_enabled(enable)
- changed = True
+ if selected_block.set_enabled(enable): changed = True
+ return changed
+
+ def bypass_selected(self):
+ """
+ Bypass the selected blocks.
+
+ Args:
+ None
+ Returns:
+ true if changed
+ """
+ changed = False
+ for selected_block in self.get_selected_blocks():
+ if selected_block.set_bypassed(): changed = True
return changed
def move_selected(self, delta_coordinate):
diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py
index db77ff2112..eda28a0e94 100644
--- a/grc/gui/Platform.py
+++ b/grc/gui/Platform.py
@@ -25,4 +25,4 @@ class Platform(Element):
self._prefs_file = prefs_file
- def get_prefs_file(self): return self._prefs_file \ No newline at end of file
+ def get_prefs_file(self): return self._prefs_file
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 9abda878bf..93372ead93 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -18,10 +18,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from Element import Element
-from Constants import \
- PORT_SEPARATION, CONNECTOR_EXTENSION_MINIMAL, \
- CONNECTOR_EXTENSION_INCREMENT, \
+from Constants import (
+ PORT_SEPARATION, PORT_SPACING, CONNECTOR_EXTENSION_MINIMAL,
+ CONNECTOR_EXTENSION_INCREMENT, CANVAS_GRID_SIZE,
PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT
+)
from .. base.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN
import Utils
import Actions
@@ -79,56 +80,55 @@ class Port(Element):
#reverse the order of ports for these rotations
if rotation in (180, 270):
index = length-index-1
- offset = (self.get_parent().H - (length-1)*PORT_SEPARATION - self.H)/2
+
+ port_separation = PORT_SEPARATION \
+ if self.get_parent().has_busses[self.is_source()] \
+ else max([port.H for port in ports]) + PORT_SPACING
+
+ offset = (self.get_parent().H - (length-1)*port_separation - self.H)/2
#create areas and connector coordinates
if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
- x = -1*W
- y = PORT_SEPARATION*index+offset
+ x = -W
+ y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x-1, y+self.H/2)
elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
x = self.get_parent().W
- y = PORT_SEPARATION*index+offset
+ y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x+1+W, y+self.H/2)
elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
- y = -1*W
- x = PORT_SEPARATION*index+offset
+ y = -W
+ x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
self._connector_coordinate = (x+self.H/2, y-1)
elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
y = self.get_parent().W
- x = PORT_SEPARATION*index+offset
+ x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
self._connector_coordinate = (x+self.H/2, y+1+W)
#the connector length
self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index
- def modify_height(self, start_height):
- type_dict = {'bus':(lambda a: a * 3)};
-
- if self.get_type() in type_dict:
- return type_dict[self.get_type()](start_height);
- else:
- return start_height;
-
def create_labels(self):
"""Create the labels for the socket."""
Element.create_labels(self)
self._bg_color = Colors.get_color(self.get_color())
- #create the layout
+ # create the layout
layout = gtk.DrawingArea().create_pango_layout('')
layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, font=PORT_FONT))
self.w, self.h = layout.get_pixel_size()
- self.W, self.H = 2*PORT_LABEL_PADDING + self.w, 2*PORT_LABEL_PADDING+self.h
- self.H = self.modify_height(self.H)
- #create the pixmap
+ self.W = 2 * PORT_LABEL_PADDING + self.w
+ self.H = 2 * PORT_LABEL_PADDING + self.h * (
+ 3 if self.get_type() == 'bus' else 1)
+ self.H += self.H % 2
+ # create the pixmap
pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h)
gc = pixmap.new_gc()
gc.set_foreground(self._bg_color)
pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h)
pixmap.draw_layout(gc, 0, 0, layout)
- #create vertical and horizontal pixmaps
+ # create vertical and horizontal pixmaps
self.horizontal_label = pixmap
if self.is_vertical():
self.vertical_label = self.get_parent().get_parent().new_pixmap(self.h, self.w)
diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py
index e7b05519ea..109fe5e85e 100644
--- a/grc/gui/Preferences.py
+++ b/grc/gui/Preferences.py
@@ -18,24 +18,34 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
import ConfigParser
-import os
+
_platform = None
_config_parser = ConfigParser.ConfigParser()
-def file_extension(): return '.'+_platform.get_key()
+
+def file_extension():
+ return '.'+_platform.get_key()
+
def load(platform):
global _platform
_platform = platform
- #create sections
+ # create sections
_config_parser.add_section('main')
_config_parser.add_section('files_open')
- try: _config_parser.read(_platform.get_prefs_file())
- except: pass
+ try:
+ _config_parser.read(_platform.get_prefs_file())
+ except:
+ pass
+
+
def save():
- try: _config_parser.write(open(_platform.get_prefs_file(), 'w'))
- except: pass
+ try:
+ _config_parser.write(open(_platform.get_prefs_file(), 'w'))
+ except:
+ pass
+
###########################################################################
# Special methods for specific program functionalities
@@ -46,49 +56,63 @@ def main_window_size(size=None):
_config_parser.set('main', 'main_window_width', size[0])
_config_parser.set('main', 'main_window_height', size[1])
else:
- try: return (
- _config_parser.getint('main', 'main_window_width'),
- _config_parser.getint('main', 'main_window_height'),
- )
- except: return (1, 1)
-
-def file_open(file=None):
- if file is not None: _config_parser.set('main', 'file_open', file)
+ try:
+ w = _config_parser.getint('main', 'main_window_width')
+ h = _config_parser.getint('main', 'main_window_height')
+ except:
+ w, h = 1, 1
+ return w, h
+
+
+def file_open(filename=None):
+ if filename is not None:
+ _config_parser.set('main', 'file_open', filename)
else:
- try: return _config_parser.get('main', 'file_open')
- except: return ''
+ try:
+ return _config_parser.get('main', 'file_open')
+ except:
+ return ''
+
def files_open(files=None):
if files is not None:
- _config_parser.remove_section('files_open') #clear section
+ _config_parser.remove_section('files_open') # clear section
_config_parser.add_section('files_open')
- for i, file in enumerate(files):
- _config_parser.set('files_open', 'file_open_%d'%i, file)
+ for i, filename in enumerate(files):
+ _config_parser.set('files_open', 'file_open_%d' % i, filename)
+
else:
- files = list()
- i = 0
- while True:
- try:
- files.append(_config_parser.get('files_open', 'file_open_%d'%i))
- except:
- return files
- i += 1
+ try:
+ files = [value for name, value in _config_parser.items('files_open')
+ if name.startswith('file_open_')]
+ except:
+ files = []
+ return files
+
def reports_window_position(pos=None):
- if pos is not None: _config_parser.set('main', 'reports_window_position', pos)
+ if pos is not None:
+ _config_parser.set('main', 'reports_window_position', pos)
else:
- try: return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0
- except: return -1
+ try:
+ return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0
+ except:
+ return -1
+
def blocks_window_position(pos=None):
- if pos is not None: _config_parser.set('main', 'blocks_window_position', pos)
+ if pos is not None:
+ _config_parser.set('main', 'blocks_window_position', pos)
else:
- try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0
- except: return -1
+ try:
+ return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0
+ except:
+ return -1
+
-def bool_entry(key, active=None, default=True):
- if active is not None:
- _config_parser.set('main', key, active)
+def bool_entry(key, value=None, default=True):
+ if value is not None:
+ _config_parser.set('main', key, value)
else:
try:
return _config_parser.getboolean('main', key)
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
index 470e2d59d8..abf242691f 100644
--- a/grc/gui/PropsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -21,9 +21,11 @@ import pygtk
pygtk.require('2.0')
import gtk
+import Actions
from Dialogs import SimpleTextDisplay
-from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
+from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT, FONT_SIZE
import Utils
+import pango
TAB_LABEL_MARKUP_TMPL="""\
#set $foreground = $valid and 'black' or 'red'
@@ -101,6 +103,20 @@ class PropsDialog(gtk.Dialog):
self._docs_box.add_with_viewport(self._docs_text_display)
notebook.append_page(self._docs_box, gtk.Label("Documentation"))
+ # Generated code for the block
+ if Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB.get_active():
+ self._code_text_display = code_view = SimpleTextDisplay()
+ code_view.set_wrap_mode(gtk.WRAP_NONE)
+ code_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD)
+ code_view.modify_font(pango.FontDescription(
+ 'monospace %d' % FONT_SIZE))
+ code_box = gtk.ScrolledWindow()
+ code_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ code_box.add_with_viewport(self._code_text_display)
+ notebook.append_page(code_box, gtk.Label("Generated Code"))
+ else:
+ self._code_text_display = None
+
# Error Messages for the block
self._error_messages_text_display = SimpleTextDisplay()
self._error_box = gtk.ScrolledWindow()
@@ -127,9 +143,10 @@ class PropsDialog(gtk.Dialog):
true if changed
"""
old_hash = self._hash
- #create a tuple of things from each param that affects the params box
+ # create a tuple of things from each param that affects the params box
self._hash = hash(tuple([(
- hash(param), param.get_type(), param.get_hide() == 'all',
+ hash(param), param.get_name(), param.get_type(),
+ param.get_hide() == 'all',
) for param in self._block.get_params()]))
return self._hash != old_hash
@@ -138,7 +155,7 @@ class PropsDialog(gtk.Dialog):
A change occurred within a param:
Rewrite/validate the block and update the gui.
"""
- #update for the block
+ # update for the block
self._block.rewrite()
self._block.validate()
self._update_gui()
@@ -155,9 +172,9 @@ class PropsDialog(gtk.Dialog):
Update the documentation block.
Hide the box if there are no docs.
"""
- #update the params box
+ # update the params box
if self._params_changed():
- #hide params box before changing
+ # hide params box before changing
for tab, label, vbox in self._params_boxes:
vbox.hide_all()
# empty the params box
@@ -173,17 +190,38 @@ class PropsDialog(gtk.Dialog):
input_widget = param.get_input(self._handle_changed, self._activate_apply)
vbox.pack_start(input_widget, input_widget.expand)
label.set_markup(Utils.parse_template(TAB_LABEL_MARKUP_TMPL, valid=box_all_valid, tab=tab))
- #show params box with new params
+ # show params box with new params
vbox.show_all()
- #update the errors box
+ # update the errors box
if self._block.is_valid():
self._error_box.hide()
else:
self._error_box.show()
messages = '\n\n'.join(self._block.get_error_messages())
self._error_messages_text_display.set_text(messages)
- #update the docs box
+ # update the docs box
self._docs_text_display.set_text(self._block.get_doc())
+ # update the generated code
+ self._update_generated_code_page()
+
+ def _update_generated_code_page(self):
+ if not self._code_text_display:
+ return # user disabled code preview
+
+ buffer = self._code_text_display.get_buffer()
+ block = self._block
+
+ def insert(header, text):
+ if not text:
+ return
+ buffer.insert_with_tags_by_name(buffer.get_end_iter(), header, 'b')
+ buffer.insert(buffer.get_end_iter(), text)
+
+ buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
+ insert('# Imports\n', '\n'.join(block.get_imports()))
+ if block.get_key().startswith('variable'):
+ insert('\n\n# Variables\n', block.get_var_make())
+ insert('\n\n# Blocks\n', block.get_make())
def _handle_key_press(self, widget, event):
"""
@@ -209,3 +247,5 @@ class PropsDialog(gtk.Dialog):
self.set_response_sensitive(gtk.RESPONSE_APPLY, False)
return True
return False
+
+
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 14a5ee7e2a..f807b59ad1 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 "
@@ -165,18 +170,65 @@ class TopBlockGenerator(object):
except:
pass
return code
+
blocks = expr_utils.sort_objects(
- self._flow_graph.get_enabled_blocks(),
+ filter(lambda b: b.get_enabled() and not b.get_bypassed(), self._flow_graph.get_blocks()),
lambda b: b.get_id(), _get_block_sort_text
)
- # list of regular blocks (all blocks minus the special ones)
+ # List of regular blocks (all blocks minus the special ones)
blocks = filter(lambda b: b not in (imports + parameters), blocks)
- # list of connections where each endpoint is enabled (sorted by domains, block names)
- connections = filter(lambda c: not (c.is_bus() or c.is_msg()), self._flow_graph.get_enabled_connections())
+
+ # Filter out virtual sink connections
+ cf = lambda c: not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
+ connections = filter(cf, self._flow_graph.get_enabled_connections())
+
+ # Get the virtual blocks and resolve their conenctions
+ virtual = filter(lambda c: c.get_source().get_parent().is_virtual_source(), connections)
+ for connection in virtual:
+ source = connection.get_source().resolve_virtual_source()
+ sink = connection.get_sink()
+ resolved = self._flow_graph.get_parent().Connection(flow_graph=self._flow_graph, porta=source, portb=sink)
+ connections.append(resolved)
+ # Remove the virtual connection
+ connections.remove(connection)
+
+ # Bypassing blocks: Need to find all the enabled connections for the block using
+ # the *connections* object rather than get_connections(). Create new connections
+ # that bypass the selected block and remove the existing ones. This allows adjacent
+ # bypassed blocks to see the newly created connections to downstream blocks,
+ # allowing them to correctly construct bypass connections.
+ bypassed_blocks = self._flow_graph.get_bypassed_blocks()
+ for block in bypassed_blocks:
+ # Get the upstream connection (off of the sink ports)
+ # Use *connections* not get_connections()
+ get_source_connection = lambda c: c.get_sink() == block.get_sinks()[0]
+ source_connection = filter(get_source_connection, connections)
+ # The source connection should never have more than one element.
+ assert (len(source_connection) == 1)
+
+ # Get the source of the connection.
+ source_port = source_connection[0].get_source()
+
+ # Loop through all the downstream connections
+ get_sink_connections = lambda c: c.get_source() == block.get_sources()[0]
+ for sink in filter(get_sink_connections, connections):
+ if not sink.get_enabled():
+ # Ignore disabled connections
+ continue
+ sink_port = sink.get_sink()
+ connection = self._flow_graph.get_parent().Connection(flow_graph=self._flow_graph, porta=source_port, portb=sink_port)
+ connections.append(connection)
+ # Remove this sink connection
+ connections.remove(sink)
+ # Remove the source connection
+ connections.remove(source_connection[0])
+
+ # List of connections where each endpoint is enabled (sorted by domains, block names)
connections.sort(key=lambda c: (
c.get_source().get_domain(), c.get_sink().get_domain(),
c.get_source().get_parent().get_id(), c.get_sink().get_parent().get_id()
))
+
connection_templates = self._flow_graph.get_parent().get_connection_templates()
msgs = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections())
# list of variable names
@@ -329,3 +381,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..3cc16e7e14 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')
@@ -240,15 +255,8 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
#for $con in $connections
#set global $source = $con.get_source()
#set global $sink = $con.get_sink()
- ##resolve virtual sources to the actual sources
- #if $source.get_parent().is_virtual_source()
- #set global $source = $source.resolve_virtual_source()
- #end if
- ##do not generate connections with virtual sinks
- #if not $sink.get_parent().is_virtual_sink()
- #include source=$connection_templates[($source.get_domain(), $sink.get_domain())]
+ #include source=$connection_templates[($source.get_domain(), $sink.get_domain())]
- #end if
#end for
########################################################
@@ -304,7 +312,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 +342,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 +355,7 @@ if __name__ == '__main__':
#end if
#end if
tb.show()
+
def quitting():
tb.stop()
tb.wait()
@@ -358,7 +368,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')
diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion
index 6b7a8295ba..77345bed1a 100755
--- a/grc/scripts/gnuradio-companion
+++ b/grc/scripts/gnuradio-companion
@@ -61,6 +61,14 @@ def show_gtk_error_dialog(title, message):
d.run()
+def check_gtk_init():
+ try:
+ gtk.init_check()
+ except RuntimeError:
+ print 'GTK initialization failed - bailing'
+ exit(-1)
+
+
def check_gnuradio_import():
try:
from gnuradio import gr
@@ -114,6 +122,7 @@ def main():
if __name__ == '__main__':
+ check_gtk_init()
check_gnuradio_import()
ensure_blocks_path()
main()