[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r6151 - in grc/trunk: data notes src src/Elements src/
From: |
jblum |
Subject: |
[Commit-gnuradio] r6151 - in grc/trunk: data notes src src/Elements src/Graphics src/SignalBlockDefs |
Date: |
Fri, 17 Aug 2007 19:53:26 -0600 (MDT) |
Author: jblum
Date: 2007-08-17 19:53:23 -0600 (Fri, 17 Aug 2007)
New Revision: 6151
Modified:
grc/trunk/data/preferences.grc.dtd
grc/trunk/notes/notes.txt
grc/trunk/src/ActionHandler.py
grc/trunk/src/Actions.py
grc/trunk/src/Colors.py
grc/trunk/src/Constants.py
grc/trunk/src/Editor.py
grc/trunk/src/Elements/Connection.py
grc/trunk/src/Elements/Element.py
grc/trunk/src/Elements/GraphicalElement.py
grc/trunk/src/Elements/GraphicalParam.py
grc/trunk/src/Elements/GraphicalSignalBlock.py
grc/trunk/src/Elements/GraphicalSocket.py
grc/trunk/src/Elements/SignalBlock.py
grc/trunk/src/Elements/Socket.py
grc/trunk/src/Elements/Utils.py
grc/trunk/src/ExecFlowGraph.py
grc/trunk/src/Graphics/Bars.py
grc/trunk/src/Graphics/Dialogs.py
grc/trunk/src/Graphics/FlowGraph.py
grc/trunk/src/Graphics/MainWindow.py
grc/trunk/src/Graphics/SignalBlockSelectionWindow.py
grc/trunk/src/Preferences.py
grc/trunk/src/SignalBlockDefs/Packet.py
grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
grc/trunk/src/StateCache.py
grc/trunk/src/Variables.py
Log:
editor: multiple file open tabbed window, tuntap IO block
Modified: grc/trunk/data/preferences.grc.dtd
===================================================================
--- grc/trunk/data/preferences.grc.dtd 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/data/preferences.grc.dtd 2007-08-18 01:53:23 UTC (rev 6151)
@@ -25,14 +25,13 @@
<!DOCTYPE preferences [
<!-- The preferences contains:
identifying information: time stamp, host name, version,
- and a list of categories, each with their own preferences.
-->
+ and a list of preferences, each with their key/value pair.
-->
<!ELEMENT preferences (timestamp?, hostname?, version?, categories>
<!ELEMENT timestamp (#PCDATA)> <!-- The time stamp for the
modification date. (optional) -->
<!ELEMENT hostname (#PCDATA)> <!-- The hostname of the
computer. (optional) -->
<!ELEMENT version (#PCDATA)> <!-- The program and program
version. (optional) -->
- <!ELEMENT categories (category*)> <!-- The list of
categories. (tag required) -->
- <!ELEMENT category (title?, prefs)> <!-- A
category. (0 or more) -->
- <!ELEMENT title (#PCDATA)> <!-- The title
of the category. (optional) -->
- <!ELEMENT prefs (pref*)> <!-- The list
of preferences for this category. (tag required) -->
- <!ELEMENT pref (#PCDATA)> <!-- A
preference. (0 or more) -->
+ <!ELEMENT prefs (pref*)> <!-- The list of preferences.
(tag required) -->
+ <!ELEMENT pref (key, value)> <!-- A pref. (0 or
more) -->
+ <!ELEMENT key (#PCDATA)> <!-- The unique
key of the preference. (tag required) -->
+ <!ELEMENT value (#PCDATA)> <!-- The value
of the preference. (tag required) -->
]>
Modified: grc/trunk/notes/notes.txt
===================================================================
--- grc/trunk/notes/notes.txt 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/notes/notes.txt 2007-08-18 01:53:23 UTC (rev 6151)
@@ -4,7 +4,6 @@
-usrp quad souce, set z == 1 to ignore Q inputs
-blks blocks, add filesave for logging
-combine add/mult with add/mult vector
--tun/tap block (with input and output)
-multi-channel scope
############ Known Problems: ####################
@@ -12,6 +11,7 @@
-socket controllers should be intelligent on shrinkage
-usrp transmit dies in lock/unlock
-packet blocks freeze in lock/unlock
+-packet: remove flush when freezes fixed
############ Features to Add: ####################
-startup tips
Modified: grc/trunk/src/ActionHandler.py
===================================================================
--- grc/trunk/src/ActionHandler.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/ActionHandler.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -27,11 +27,11 @@
pygtk.require('2.0')
import gtk
import Graphics
-from StateCache import StateCache
-import ParseXML
import Preferences
from threading import Thread
import Messages
+import ParseXML
+import random
class ActionHandler:
"""
@@ -39,28 +39,26 @@
and handle button presses and flow graph operations from the GUI.
"""
- def __init__(self, input_arg_file_path=''):
+ def __init__(self, file_paths):
"""!
ActionHandler constructor.
Create the main window, setup the message handler, import the
preferences,
and connect all of the action handlers. Finally, enter the gtk
main loop and block.
- @param input_arg_file_path a flow graph file passed from
command line
+ @param file_paths a list of flow graph file passed from command
line
"""
if PY_GTK_ICON:
gtk.window_set_default_icon_from_file(PY_GTK_ICON)
- for action in ACTIONS_LIST: action.connect('activate',
self._handle_actions)
- self.pid_file = None
+ for action in ACTIONS_LIST: action.connect('activate',
self._handle_actions)
### create the main window and setup the Messages ###
self.main_window = Graphics.MainWindow(self.handle_states)
+ Preferences.load(self.main_window)
+ self.get_flow_graph = self.main_window.get_flow_graph
Messages.register_messenger(self.main_window.add_report_line)
Messages.register_messenger(sys.stdout.write)
Messages.send_init()
- self.flow_graph = self.main_window.flow_graph
self.main_window.connect('delete_event', self._quit)
self.main_window.connect('key_press_event',
self._handle_key_press)
- # determine the initial flow graph file, preference to
command line input #
- if input_arg_file_path: self.flow_graph_file_path =
os.path.abspath(input_arg_file_path)
- else: self.flow_graph_file_path =
Preferences.get_default_flow_graph()
- self.saved = True
+ #flow graph settings
+ self.init_file_paths = file_paths
self.handle_states(APPLICATION_INITIALIZE)
# enter the mainloop
gtk.gdk.threads_init()
@@ -93,22 +91,22 @@
elif event.state & gtk.gdk.CONTROL_MASK and keyname == 'n':
self.handle_states(FLOW_GRAPH_NEW)
#################### Delete ###############################
- elif self.flow_graph.get_focus_flag() and keyname == 'Delete':
#mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname ==
'Delete': #mouse focus
self.handle_states(ELEMENT_DELETE)
#################### Rotate ###############################
- elif self.flow_graph.get_focus_flag() and keyname == 'Right':
#mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname ==
'Right': #mouse focus
self.handle_states(SIGNAL_BLOCK_ROTATE_RIGHT)
- elif self.flow_graph.get_focus_flag() and keyname == 'Left':
#mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname ==
'Left': #mouse focus
self.handle_states(SIGNAL_BLOCK_ROTATE_LEFT)
#################### Data Type
###############################
- elif self.flow_graph.get_focus_flag() and keyname == 'Down':
#mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname ==
'Down': #mouse focus
self.handle_states(SIGNAL_BLOCK_INC_TYPE)
- elif self.flow_graph.get_focus_flag() and keyname == 'Up':
#mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname ==
'Up': #mouse focus
self.handle_states(SIGNAL_BLOCK_DEC_TYPE)
#################### Socket Controllers
###############################
- elif self.flow_graph.get_focus_flag() and keyname in
('equal','plus', 'KP_Add'): #mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname in
('equal','plus', 'KP_Add'): #mouse focus
self.handle_states(SOCKET_CONTROLLER_INC)
- elif self.flow_graph.get_focus_flag() and keyname in ('minus',
'KP_Subtract'): #mouse focus
+ elif self.get_flow_graph().get_focus_flag() and keyname in
('minus', 'KP_Subtract'): #mouse focus
self.handle_states(SOCKET_CONTROLLER_DEC)
#################### Exec/Stop/Print
###############################
elif keyname == 'F5':
@@ -118,7 +116,7 @@
elif keyname == 'Print':
self.handle_states(FLOW_GRAPH_SCREEN_CAPTURE)
#propagate this if the fg is not in focus or nothing is selected
- return self.flow_graph.get_focus_flag() and
self.flow_graph.is_selected()
+ return self.get_flow_graph().get_focus_flag() and
self.get_flow_graph().is_selected()
def _quit(self, window, event):
"""!
@@ -138,7 +136,7 @@
"""
self.handle_states(event.get_name())
- def handle_states(self, state):
+ def handle_states(self, state=''):
"""!
Handle the state changes in the GUI.
Handle all of the state changes that arise from the action
handler or other Graphics and
@@ -157,33 +155,18 @@
# enable a select few actions
Graphics.enable_usrp_diagnostics() #try to enable
usrp diagnostics
for action in (
- APPLICATION_QUIT, FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS,
+ APPLICATION_QUIT, FLOW_GRAPH_NEW,
FLOW_GRAPH_OPEN, FLOW_GRAPH_SAVE_AS, FLOW_GRAPH_CLOSE,
ABOUT_WINDOW_DISPLAY,
DATA_TYPES_WINDOW_DISPLAY, HOTKEYS_WINDOW_DISPLAY, MATH_EXPR_WINDOW_DISPLAY,
FLOW_GRAPH_WINDOW_RESIZE, PREFS_WINDOW_DISPLAY,
FLOW_GRAPH_SCREEN_CAPTURE,
- ): get_action_from_name(action).set_sensitive(True)
- if self.flow_graph_file_path == '':
- initial_state =
ParseXML.from_xml(ParseXML.from_file(INITIAL_FLOW_GRAPH_FILE))
- self.flow_graph.from_nested_data(initial_state)
- self.state_cache = StateCache(initial_state)
- else: #otherwise try to use the file path
- try:
- self.handle_states(NOTHING_SELECT)
-
Messages.send_start_load(self.flow_graph_file_path)
- initial_state =
ParseXML.from_xml(ParseXML.from_file(self.flow_graph_file_path))
-
self.flow_graph.from_nested_data(initial_state)
- Messages.send_end_load()
- self.state_cache =
StateCache(initial_state)
- except Exception, e: #if the data is bad,
display error and call INIT with None for the file path
- Messages.send_fail_load(e)
- self.flow_graph_file_path = ''
-
self.handle_states(APPLICATION_INITIALIZE)
- self.saved = True
- elif state == APPLICATION_QUIT:
- if self._loose_changes():
- self.handle_states(FLOW_GRAPH_STOP)
-
Preferences.set_default_flow_graph(self.flow_graph_file_path)
+ ): get_action_from_name(action).set_sensitive(True)
+ if not self.init_file_paths and
Preferences.restore_files(): self.init_file_paths = Preferences.files_open()
+ if not self.init_file_paths: self.init_file_paths = ['']
+ for file_path in self.init_file_paths:
self.main_window.new_page(file_path)
+ elif state == APPLICATION_QUIT:
+ if self.main_window.close_pages():
Preferences.save(self.main_window)
gtk.main_quit()
+ exit(0)
##############################################################################################
# Selections
##############################################################################################
@@ -197,46 +180,46 @@
elif state == NOTHING_SELECT:
for action in (ELEMENT_DELETE,
SIGNAL_BLOCK_PARAM_MODIFY, SIGNAL_BLOCK_ROTATE_RIGHT,
SIGNAL_BLOCK_ROTATE_LEFT):
get_action_from_name(action).set_sensitive(False)
- self.flow_graph.unselect()
+ self.get_flow_graph().unselect()
##############################################################################################
# Move/Rotate/Delete/Create
##############################################################################################
elif state == SIGNAL_BLOCK_MOVE:
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == SIGNAL_BLOCK_ROTATE_LEFT:
- if self.flow_graph.rotate_selected(DIR_LEFT):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if self.get_flow_graph().rotate_selected(DIR_LEFT):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == SIGNAL_BLOCK_ROTATE_RIGHT:
- if self.flow_graph.rotate_selected(DIR_RIGHT):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if self.get_flow_graph().rotate_selected(DIR_RIGHT):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == ELEMENT_DELETE:
- if self.flow_graph.delete_selected():
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
+ if self.get_flow_graph().delete_selected():
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
self.handle_states(NOTHING_SELECT)
- self.saved = False
+ self.main_window.set_saved(False)
elif state == CONNECTION_CREATE or state ==
SIGNAL_BLOCK_CREATE:
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
self.handle_states(NOTHING_SELECT)
- self.saved = False
+ self.main_window.set_saved(False)
elif state == SIGNAL_BLOCK_INC_TYPE:
- if self.flow_graph.type_controller_modify_selected(1):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if
self.get_flow_graph().type_controller_modify_selected(1):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == SIGNAL_BLOCK_DEC_TYPE:
- if self.flow_graph.type_controller_modify_selected(-1):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if
self.get_flow_graph().type_controller_modify_selected(-1):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == SOCKET_CONTROLLER_INC:
- if self.flow_graph.socket_controller_modify_selected(1):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if
self.get_flow_graph().socket_controller_modify_selected(1):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == SOCKET_CONTROLLER_DEC:
- if
self.flow_graph.socket_controller_modify_selected(-1):
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if
self.get_flow_graph().socket_controller_modify_selected(-1):
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
##############################################################################################
# Window stuff
##############################################################################################
@@ -244,7 +227,7 @@
Graphics.USRPDiagnosticsDialog()
elif state == PREFS_WINDOW_DISPLAY:
Graphics.PreferencesDialog()
- self.flow_graph.update()
+ self.get_flow_graph().update()
elif state == ABOUT_WINDOW_DISPLAY:
Graphics.AboutDialog()
elif state == DATA_TYPES_WINDOW_DISPLAY:
@@ -254,71 +237,68 @@
elif state == MATH_EXPR_WINDOW_DISPLAY:
Graphics.MathExprDialog()
elif state == FLOW_GRAPH_WINDOW_RESIZE:
- dimensions =
Graphics.FlowGraphWindowSizeDialog(self.flow_graph.get_size_request()).run()
+ dimensions =
Graphics.FlowGraphWindowSizeDialog(self.main_window.get_size_request()).run()
if dimensions != None:
- self.flow_graph.set_size_request(dimensions[0],
dimensions[1])
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+
self.main_window.set_size_request(dimensions[0], dimensions[1])
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
##############################################################################################
# Variable and Param Modifications
##############################################################################################
elif state == SIGNAL_BLOCK_PARAM_MODIFY:
- if self.flow_graph.param_modify_selected():
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+ if self.get_flow_graph().param_modify_selected():
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
elif state == VARIABLE_MODIFY:
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
- self.flow_graph.update()
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
+ self.get_flow_graph().update()
elif state == VARIABLE_REORDER:
-
self.state_cache.save_new_state(self.flow_graph.to_nested_data())
- self.saved = False
+
self.main_window.get_state_cache().save_new_state(self.get_flow_graph().to_nested_data())
+ self.main_window.set_saved(False)
##############################################################################################
# Undo/Redo
##############################################################################################
elif state == FLOW_GRAPH_UNDO:
- nested_data = self.state_cache.get_prev_state()
+ nested_data =
self.main_window.get_state_cache().get_prev_state()
if nested_data != None:
self.handle_states(NOTHING_SELECT)
- self.flow_graph.from_nested_data(nested_data)
- self.saved = False
+
self.get_flow_graph().from_nested_data(nested_data)
+ self.main_window.set_saved(False)
elif state == FLOW_GRAPH_REDO:
- nested_data = self.state_cache.get_next_state()
+ nested_data =
self.main_window.get_state_cache().get_next_state()
if nested_data != None:
self.handle_states(NOTHING_SELECT)
- self.flow_graph.from_nested_data(nested_data)
- self.saved = False
+
self.get_flow_graph().from_nested_data(nested_data)
+ self.main_window.set_saved(False)
##############################################################################################
# New/Open/Save
##############################################################################################
elif state == FLOW_GRAPH_NEW:
- if self._loose_changes():
- self.flow_graph_file_path = ''
- self.handle_states(APPLICATION_INITIALIZE)
+ self.main_window.new_page()
elif state == FLOW_GRAPH_OPEN:
- if self._loose_changes():
- file_path =
Graphics.OpenFlowGraphFileDialog(self.flow_graph_file_path).run()
- if file_path != None:
- self.flow_graph_file_path = file_path
-
self.handle_states(APPLICATION_INITIALIZE)
+ file_path =
Graphics.OpenFlowGraphFileDialog(self.get_flow_graph() and
self.main_window.get_file_path() or '').run()
+ if file_path != None:
self.main_window.new_page(file_path)
+ elif state == FLOW_GRAPH_CLOSE:
+ self.main_window.close_page()
elif state == FLOW_GRAPH_SAVE:
- if self.flow_graph_file_path == '':
self.handle_states(FLOW_GRAPH_SAVE_AS)
+ if not self.main_window.get_file_path():
self.handle_states(FLOW_GRAPH_SAVE_AS)
else:
try:
-
ParseXML.to_file(ParseXML.to_xml(self.flow_graph.to_nested_data()),
self.flow_graph_file_path)
- self.saved = True
+
ParseXML.to_file(ParseXML.to_xml(self.get_flow_graph().to_nested_data()),
self.main_window.get_file_path())
+ self.main_window.set_saved(True)
except IOError:
-
Messages.send_fail_save(self.flow_graph_file_path)
- self.saved = False
+
Messages.send_fail_save(self.main_window.get_file_path())
+ self.main_window.set_saved(False)
elif state == FLOW_GRAPH_SAVE_AS:
- file_path =
Graphics.SaveFlowGraphFileDialog(self.flow_graph_file_path).run()
+ file_path =
Graphics.SaveFlowGraphFileDialog(self.main_window.get_file_path()).run()
if file_path != None:
- self.flow_graph_file_path = file_path
+ self.main_window.set_file_path(file_path)
self.handle_states(FLOW_GRAPH_SAVE)
elif state == FLOW_GRAPH_SCREEN_CAPTURE:
- file_path =
Graphics.SaveImageFileDialog(self.flow_graph_file_path).run()
+ file_path =
Graphics.SaveImageFileDialog(self.main_window.get_file_path()).run()
if file_path != None:
- pixmap = self.flow_graph.pixmap
+ pixmap = self.get_flow_graph().pixmap
width, height = pixmap.get_size()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,
0, 8, width, height)
pixbuf.get_from_drawable(pixmap,
pixmap.get_colormap(), 0, 0, 0, 0, width, height)
@@ -327,49 +307,32 @@
# Run/Stop
##############################################################################################
elif state == FLOW_GRAPH_EXEC:
- if self.pid_file == None:
- self.handle_states(FLOW_GRAPH_SAVE)
- if self.flow_graph_file_path != '':
ExecFlowGraphThread(self)
+ if not self.main_window.get_pid_file():
+ if not self.main_window.get_saved() or not
self.main_window.get_file_path():
+ self.handle_states(FLOW_GRAPH_SAVE)
#only save if file path missing or not saved
+ if self.main_window.get_saved() and
self.main_window.get_file_path():
+ ExecFlowGraphThread(self) #only
exec if file path and saved
elif state == FLOW_GRAPH_STOP:
MUTEX.lock()
- if self.pid_file!= None:
- try: os.kill(int(open(self.pid_file,
'r').read()), 9)
- except: print "could not kill pid file:
%s"%self.pid_file
+ if self.main_window.get_pid_file():
+ try:
os.kill(int(open(self.main_window.get_pid_file(), 'r').read()), 9)
+ except: print "could not kill pid file:
%s"%self.main_window.get_pid_file()
MUTEX.unlock()
+ elif state == '': #pass and run the global actions
+ pass
else: print "!!! State not handled !!!"
##############################################################################################
# Global Actions for all States
##############################################################################################
#set the exec button if the flow graph is valid and is not
already running
MUTEX.lock()
-
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(self.flow_graph.is_valid()
and self.pid_file == None)
-
get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(self.pid_file != None)
+
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(self.get_flow_graph().is_valid()
and not self.main_window.get_pid_file())
+
get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(self.main_window.get_pid_file()
!= '')
MUTEX.unlock()
#saved status
- if self.saved: #set the window title and grey out the save
button
-
get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(False)
- if self.flow_graph_file_path == '':
- self.main_window.set_title(NEW_FLOGRAPH_TITLE)
- else:
self.main_window.set_title(self.flow_graph_file_path)
- else: #set the window title with a * and activate the save
button
-
get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(True)
- if self.flow_graph_file_path == '':
- self.main_window.set_title(NEW_FLOGRAPH_TITLE +
'*')
- else:
self.main_window.set_title(self.flow_graph_file_path + '*')
- #hide/show the reports window based on the preferences
+ get_action_from_name(FLOW_GRAPH_SAVE).set_sensitive(not
self.main_window.get_saved())
+ self.main_window.set_title()
Preferences.show_reports_window(self.main_window)
-
- def _loose_changes(self):
- """!
- Loose unsaved changes to flow graph?
- If the save was not greyed-out, the user is presented with a
dialog.
- @return true if save is greyed-out, or the user's choice.
- """
- return not
get_action_from_name(FLOW_GRAPH_SAVE).get_sensitive() or \
- Graphics.MessageDialogHelper(
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
'Unsaved Changes!',
- 'Would you like to discard your unsaved
changes?'
- ) == gtk.RESPONSE_YES
class ExecFlowGraphThread(Thread):
"""Execute the flow graph as a new process and wait on it to finish."""
@@ -379,18 +342,31 @@
@param action_handler an instance of an ActionHandler
"""
Thread.__init__(self)
- self.action_handler = action_handler
- self.pid_file = self.action_handler.pid_file =
'/tmp/grc-%d.pid'%os.getpid()
- self.report_file = '/tmp/grc-%d.report'%os.getpid()
- self.flow_graph_file_path =
self.action_handler.flow_graph_file_path
+ self.handle_states = action_handler.handle_states
+ self.flow_graph = action_handler.get_flow_graph()
+ self.main_window = action_handler.main_window
+ #random id so multiple flow graphs can run w/o files
intersecting
+ rand_id = random.randint(10000, 99999)
+ #store page and dont use main window calls in run
+ self.page = self.main_window.get_page()
+ #set files
+ self.file_path = self.main_window.get_file_path()
+ self.report_file = '/tmp/grc-%d-%d.report'%(os.getpid(),
rand_id)
+ self.pid_file = '/tmp/grc-%d-%d.pid'%(os.getpid(), rand_id)
+ self.main_window.set_pid_file(self.pid_file)
get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(False)
get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(True)
- Messages.send_start_exec(self.flow_graph_file_path)
+ Messages.send_start_exec(self.main_window.get_file_path())
self.start()
def run(self):
"""Execute the flow graph."""
- cmd = '%s "%s" --pid_file="%s" 2>
"%s"'%(DEFAULT_FLOW_GRAPH_EXEC, self.flow_graph_file_path, self.pid_file,
self.report_file)
+ cmd = '%s "%s" --pid_file="%s" 2> "%s"'%(
+ DEFAULT_FLOW_GRAPH_EXEC,
+ self.file_path,
+ self.pid_file,
+ self.report_file,
+ )
os.system(cmd)
try:
report = open(self.report_file, 'r')
@@ -402,7 +378,7 @@
try: os.remove(self.pid_file)
except: print "could not remove pid file: %s"%self.pid_file
MUTEX.lock()
- self.action_handler.pid_file = None
- get_action_from_name(FLOW_GRAPH_STOP).set_sensitive(False)
- get_action_from_name(FLOW_GRAPH_EXEC).set_sensitive(True)
+ self.page.pid_file = ''
MUTEX.unlock()
+ self.handle_states()
+
Modified: grc/trunk/src/Actions.py
===================================================================
--- grc/trunk/src/Actions.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Actions.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -61,6 +61,7 @@
FLOW_GRAPH_REDO = 'flow graph redo'
FLOW_GRAPH_SAVE = 'flow graph save'
FLOW_GRAPH_SAVE_AS = 'flow graph save as'
+FLOW_GRAPH_CLOSE = 'flow graph close'
FLOW_GRAPH_NEW = 'flow graph new'
FLOW_GRAPH_WINDOW_RESIZE = 'flow graph window resize'
FLOW_GRAPH_EXEC = 'flow graph exec'
@@ -83,6 +84,7 @@
gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open a flow graph from file',
'gtk-open'),
gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save this flow graph',
'gtk-save'),
gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the open flow graph
as...', 'gtk-save-as'),
+ gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the open flow graph',
'gtk-close'),
gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', 'gtk-quit'),
gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph',
'gtk-undo'),
gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph',
'gtk-redo'),
@@ -101,6 +103,8 @@
gtk.Action(FLOW_GRAPH_STOP, '_Stop', 'Stop the flow graph', 'gtk-stop'),
gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a
screen capture of the flow graph', 'gtk-print'),
)
+
+ACTIONS_DICT = dict((action.get_name(), action) for action in ACTIONS_LIST)
def get_action_from_name(action_name):
"""!
@@ -110,8 +114,7 @@
@throw KeyError bad action name
@return a gtk action object
"""
- for action in ACTIONS_LIST:
- if action.get_name() == action_name: return action
+ if ACTIONS_DICT.has_key(action_name): return ACTIONS_DICT[action_name]
raise KeyError('Action Name: "%s" does not exist'%action_name)
\ No newline at end of file
Modified: grc/trunk/src/Colors.py
===================================================================
--- grc/trunk/src/Colors.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Colors.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -58,3 +58,4 @@
SHORT_VECTOR_COLOR = COLORMAP.alloc_color(SHORT_VECTOR_COLOR_SPEC, True, True)
#background for shorts (yellowish)
INT_VECTOR_COLOR = COLORMAP.alloc_color(INT_VECTOR_COLOR_SPEC, True, True)
#background for ints (greenish)
BYTE_VECTOR_COLOR = COLORMAP.alloc_color(BYTE_VECTOR_COLOR_SPEC, True, True)
#background for bytes (purplish)
+
Modified: grc/trunk/src/Constants.py
===================================================================
--- grc/trunk/src/Constants.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Constants.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -34,7 +34,7 @@
######################################################################################################
##The current version of this code
-VERSION = '0.70 alpha'
+VERSION = '0.70 beta'
##The name to appear in the main window for a flow graph that has not been
saved to file.
NEW_FLOGRAPH_TITLE = 'untitled'
@@ -44,8 +44,7 @@
address@hidden
######################################################################################################
-## Length of connector buds on Sockets(s) in pixels and
-# allowable rotation angles for Element(s) in degrees @{
+## Signal block connector lengths
######################################################################################################
##The length that a connection must extend from the socket until the length
depends on the index of the socket.
@@ -54,6 +53,10 @@
##The length that a connection must extend from the initial length times the
index of the socket, after this length, the connection may have a bend.
CONNECTOR_EXTENSION_LENGTH = 11
+######################################################################################################
+## Signal block rotations
+######################################################################################################
+
##List of possible angles (in degrees) that a signal block and its parameters
can be rotated to.
POSSIBLE_ROTATIONS = (0, 90, 180, 270)
@@ -62,7 +65,6 @@
##direction of rotation right.
DIR_RIGHT = 'right'
address@hidden
######################################################################################################
## Dimension constraints for the various windows (in pixels)
@@ -143,7 +145,7 @@
##How close can the mouse get to the window border before mouse events are
ignored.
BORDER_PROXIMITY_SENSITIVITY = 10
-##How close can the mouse 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.
@@ -151,6 +153,9 @@
##The redrawing sensitivity, how many motion detection events must occur
before a redraw?
MOTION_DETECT_REDRAWING_SENSITIVITY = 3
+
+##How close the mouse click can be to a connection and register a connection
select.
+CONNECTION_SELECT_SENSITIVITY = 5
address@hidden
######################################################################################################
Modified: grc/trunk/src/Editor.py
===================================================================
--- grc/trunk/src/Editor.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Editor.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -25,7 +25,7 @@
from optparse import OptionParser
if __name__ == "__main__":
- usage = "usage: %prog optional_flow_graph"+FLOW_GRAPH_FILE_EXTENSION
+ usage = "usage: %prog optional_flow_graphs"+FLOW_GRAPH_FILE_EXTENSION
version = """
GNU Radio Companion %s
@@ -44,7 +44,5 @@
exit(-1)
# end import of modules #
from ActionHandler import ActionHandler
- if len(args): ActionHandler(args[0])
- else: ActionHandler()
- exit(0)
+ ActionHandler(args)
Modified: grc/trunk/src/Elements/Connection.py
===================================================================
--- grc/trunk/src/Elements/Connection.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Elements/Connection.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -40,7 +40,7 @@
@param socket2 another input/output socket
@throw InvalidConnectionException cant connect
"""
- Element.Element.__init__(self, parent, (0,0), 0)
+ Element.Element.__init__(self, parent, (0, 0), 0)
#If an input socket that is already connected is passed to the
constructor,
#the logic will use the output socket that it is connected to.
#This way, a user could try to connect an unconnected input
socket to a signal on another input.
@@ -63,9 +63,9 @@
def get_coordinate(self):
"""!Get the 0,0 coordinate.
Coordinates are irrelevant in connection.
- @return 0,0
+ @return 0, 0
"""
- return (0,0)
+ return 0, 0
def get_rotation(self):
"""!Get the 0 degree rotation.
@@ -93,4 +93,5 @@
print "disconnecting"
for socket in self.sockets: socket.disconnect(self)
self.get_parent().remove_element(self)
+
\ No newline at end of file
Modified: grc/trunk/src/Elements/Element.py
===================================================================
--- grc/trunk/src/Elements/Element.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Elements/Element.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -21,7 +21,7 @@
#signal blocks, input sockets, output sockets and connections.
address@hidden Josh Blum
-from Constants import POSSIBLE_ROTATIONS,DIR_LEFT,DIR_RIGHT
+from Constants import
POSSIBLE_ROTATIONS,DIR_LEFT,DIR_RIGHT,CONNECTION_SELECT_SENSITIVITY
class Element:
"""
@@ -54,11 +54,8 @@
def clear(self):
"""Empty the lines and areas."""
- self.areas_dict = dict()
- self.lines_dict = dict()
- for rotation in POSSIBLE_ROTATIONS:
- self.areas_dict[rotation] = list()
- self.lines_dict[rotation] = list()
+ self.areas_dict = dict((rotation, list()) for rotation in
POSSIBLE_ROTATIONS)
+ self.lines_dict = dict((rotation, list()) for rotation in
POSSIBLE_ROTATIONS)
def set_coordinate(self, coor):
"""!
@@ -99,8 +96,8 @@
Move the element by adding the delta_coor to the current
coordinate.
@param delta_coor (delta_x,delta_y) tuple
"""
- deltaX,deltaY = delta_coor
- X,Y = self.get_coordinate()
+ deltaX, deltaY = delta_coor
+ X, Y = self.get_coordinate()
self.coor = (X+deltaX, Y+deltaY)
def add_area(self, rel_coor, area, rotation=None):
@@ -133,24 +130,14 @@
Is this Element selected at given coordinate/is the coordinate
encompassed by one of the areas or lines?
@return self if one of the areas/lines encompasses coor, else
None.
"""
- in_between = lambda A, B, point: point >= min(A,B) and point <=
max(A,B)
- X,Y = self.get_coordinate()
- x,y = coor
- for (rX,rY),(W,H) in self.areas_dict[self.get_rotation()]:
- aX = X + rX
- aY = Y + rY
- if in_between(aX, aX+W, x) and in_between(aY, aY+H, y):
- return self
- maxDist = 5
- for line in self.lines_dict[self.get_rotation()]:
- (x1, y1),(x2, y2) = line #assume horizontal or
vertical lines
- x1 = x1 + X
- y1 = y1 + Y
- x2 = x2 + X
- y2 = y2 + Y
- if (x1 == x2 and x >= x2-maxDist and x <= x2+maxDist
and y <= max(y1,y2) and y >= min(y1,y2)) or\
- (y1 == y2 and y >= y2-maxDist and y <=
y2+maxDist and x <= max(x1,x2) and x >= min(x1,x2)):
- return self
+ in_between = lambda p, a, b: p >= min(a, b) and p <= max(a, b)
+ x,y = [a-b for a,b in zip(coor, self.get_coordinate())]
+ for (x1,y1), (w,h) in self.areas_dict[self.get_rotation()]:
+ if in_between(x, x1, x1+w) and in_between(y, y1, y1+h):
return self
+ for (x1, y1), (x2, y2) in self.lines_dict[self.get_rotation()]:
#assume horizontal or vertical lines
+ if x1 == x2: x1, x2 = x1-CONNECTION_SELECT_SENSITIVITY,
x2+CONNECTION_SELECT_SENSITIVITY
+ if y1 == y2: y1, y2 = y1-CONNECTION_SELECT_SENSITIVITY,
y2+CONNECTION_SELECT_SENSITIVITY
+ if in_between(x, x1, x2) and in_between(y, y1, y2):
return self
return None
def get_rotation(self):
Modified: grc/trunk/src/Elements/GraphicalElement.py
===================================================================
--- grc/trunk/src/Elements/GraphicalElement.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Elements/GraphicalElement.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -51,12 +51,10 @@
aY = Y + rY
gc.foreground = BG_color
window.draw_rectangle(gc, True, aX, aY, W, H)
- if self.is_highlighted(): gc.foreground = Colors.H_COLOR
- else: gc.foreground = FG_color
+ gc.foreground = self.is_highlighted() and
Colors.H_COLOR or FG_color
window.draw_rectangle(gc, False, aX, aY, W, H)
for (x1, y1),(x2, y2) in self.lines_dict[self.get_rotation()]:
- if self.is_highlighted(): gc.foreground = Colors.H_COLOR
- else: gc.foreground = FG_color
+ gc.foreground = self.is_highlighted() and
Colors.H_COLOR or FG_color
window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2)
\ No newline at end of file
Modified: grc/trunk/src/Elements/GraphicalParam.py
===================================================================
--- grc/trunk/src/Elements/GraphicalParam.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Elements/GraphicalParam.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -219,3 +219,4 @@
desc = pango.FontDescription(PARAM_FONT)
layout.set_font_description(desc)
return layout
+
Modified: grc/trunk/src/Elements/GraphicalSignalBlock.py
===================================================================
--- grc/trunk/src/Elements/GraphicalSignalBlock.py 2007-08-17 21:45:46 UTC
(rev 6150)
+++ grc/trunk/src/Elements/GraphicalSignalBlock.py 2007-08-18 01:53:23 UTC
(rev 6151)
@@ -154,3 +154,4 @@
return True
else: socket_controller.set_data(old_data)
#restore previous value
return False
+
Modified: grc/trunk/src/Elements/GraphicalSocket.py
===================================================================
--- grc/trunk/src/Elements/GraphicalSocket.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Elements/GraphicalSocket.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -155,4 +155,5 @@
class GraphicalOutputSocket(GraphicalSocket):
""" The socket for output """
type = Socket.OutputSocket.type
+
\ No newline at end of file
Modified: grc/trunk/src/Elements/SignalBlock.py
===================================================================
--- grc/trunk/src/Elements/SignalBlock.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Elements/SignalBlock.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -262,4 +262,5 @@
except Exception, e: Messages.send_error_load('Signal block
"%s" could not be created:\n\t%s'%(id,e))
return None, None #not found!, return None tuple
from_nested_data = staticmethod(from_nested_data)
+
\ No newline at end of file
Modified: grc/trunk/src/Elements/Socket.py
===================================================================
--- grc/trunk/src/Elements/Socket.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Elements/Socket.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -105,7 +105,8 @@
Get the data type. If the parsed vlen > 1, then return the
vectorized data type.
@return the data type
"""
- if self.vlen != None and self.vlen.is_valid() and
self.vlen.parse() > 1: return DataTypes.vectorize(self.data_type)
+ if self.vlen != None and self.vlen.is_valid() and
self.vlen.parse() > 1:
+ return DataTypes.vectorize(self.data_type)
return self.data_type
def get_index(self):
@@ -162,4 +163,5 @@
class OutputSocket(Socket):
""" The socket for output """
type = 'output socket'
+
\ No newline at end of file
Modified: grc/trunk/src/Elements/Utils.py
===================================================================
--- grc/trunk/src/Elements/Utils.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Elements/Utils.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -57,4 +57,3 @@
## test method for connections
is_connection = lambda obj: obj!= None and obj.type == Connection.type
-
Modified: grc/trunk/src/ExecFlowGraph.py
===================================================================
--- grc/trunk/src/ExecFlowGraph.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/ExecFlowGraph.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -59,7 +59,7 @@
self.started = False
def connect(self, *points):
- """
+ """!
Override connect so that we can connect internal hier blocks.
@param points the blocks to connect.
"""
@@ -118,16 +118,16 @@
@param function the callback function
@param data_type_params a list of data types
"""
- print "***\nBegin A callback\n%s\n\n***"%function
+ #print "***\nBegin A callback\n%s\n\n***"%function
try: function(*map(lambda param: param.parse(),
data_type_params))
except Exception, e: print "***\n\nerror parsing a callback ->
ignoring\n%s...\n\n***"%e
- print "***\nEnd A callback\n***"
+ #print "***\nEnd A callback\n***"
def parse_callbacks(self):
"""For each call back, parse all of the data and
call the registered callback function on that data."""
- MUTEX.lock()
- print "***\n\nCallback Time BEGIN\n\n***"
+ #MUTEX.lock()
+ #print "***\n\nCallback Time BEGIN\n\n***"
if self.started:
if self.callbacks: #parse regular callbacks
for function, data_type_params in
self.callbacks:
@@ -137,8 +137,8 @@
for function, data_type_params in
self.callbacks_locked + self.callbacks_cond:
self._parse_callback(function,
*data_type_params)
self._hb.unlock()
- print "***\n\nCallback Time END\n\n***"
- MUTEX.unlock()
+ #print "***\n\nCallback Time END\n\n***"
+ #MUTEX.unlock()
def _parse_nested_data(self, nested_data):
"""!
Modified: grc/trunk/src/Graphics/Bars.py
===================================================================
--- grc/trunk/src/Graphics/Bars.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Graphics/Bars.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -55,6 +55,7 @@
None,
FLOW_GRAPH_SCREEN_CAPTURE,
None,
+ FLOW_GRAPH_CLOSE,
APPLICATION_QUIT,
]),
(gtk.Action('Edit', '_Edit', None, None), [
Modified: grc/trunk/src/Graphics/Dialogs.py
===================================================================
--- grc/trunk/src/Graphics/Dialogs.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Graphics/Dialogs.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -55,19 +55,15 @@
gtk.Dialog.__init__(self, buttons=('gtk-close',
gtk.RESPONSE_CLOSE))
self.set_title("Preferences")
self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
- vbox = gtk.VBox()
+ notebook = gtk.Notebook()
for title,notes,params in Preferences.PREFS_LIST:
if title:
- label = gtk.Label()
- label.set_markup('<b> ----- '+title+' -----
</b>')
- vbox.pack_start(label, False, padding=5)
- for param in params:
vbox.pack_start(param.get_input_object(), False)
- if notes: vbox.pack_start(TextDisplay(notes),
False, padding=5)
- #add the scrolled window for the preferences
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
- scrolled_window.add_with_viewport(vbox)
- self.vbox.pack_start(scrolled_window, True)
+ vbox = gtk.VBox()
+ vbox.pack_start(gtk.Label(), False) #blank
label for spacing
+ for param, key in params:
vbox.pack_start(param.get_input_object(), False)
+ if notes: vbox.pack_start(TextDisplay(notes),
False, padding=5)
+ notebook.append_page(vbox, gtk.Label(title))
+ self.vbox.pack_start(notebook, True)
self.show_all()
self.run()
self.destroy()
Modified: grc/trunk/src/Graphics/FlowGraph.py
===================================================================
--- grc/trunk/src/Graphics/FlowGraph.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Graphics/FlowGraph.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -56,6 +56,7 @@
@param handle_states the callback function
@param variable_modification_window var mod window also for
callbacks
"""
+ #setup
self.elements = list()
self.remove_element = lambda e: self.elements.remove(e)
self.gc = None
@@ -82,6 +83,10 @@
self.count = 0
self.pixmap = None
+###########################################################################
+# Flow Graph Access Methods
+###########################################################################
+
def _handle_focus_event(self, widget, event, focus_flag):
"""Record the focus state of the flow graph window."""
self.focus_flag = focus_flag
@@ -94,21 +99,18 @@
index = 0
while True:
id = tag+str(index)
- index = index + 1
- id_found = False
- for element in self.elements:
- if Utils.is_signal_block(element) and id ==
element.get_id():
- id_found = True
- break
- if not id_found: #make sure that a
unique id was created
- rot = 0 #(0, 180)[random.randint(0,1)]
+ index = index + 1
+ if not [
+ None for element in self.elements if
Utils.is_signal_block(element) and id == element.get_id()
+ ]: #make sure that the id is not used by
another signal block
+ rot = 0
vAdj =
self.get_parent().get_vadjustment().get_value()
hAdj =
self.get_parent().get_hadjustment().get_value()
x = random.randint(100,400)+int(hAdj)
y = random.randint(100,400)+int(vAdj)
self.elements.append(
- SignalBlockDefs.get_signal_block(self,
(x, y), rot, tag, id, GraphicalSignalBlock
- )[0])
+ SignalBlockDefs.get_signal_block(self,
(x, y), rot, tag, id, GraphicalSignalBlock)[0]
+ )
self.handle_states(SIGNAL_BLOCK_CREATE)
self.update()
return
@@ -221,7 +223,7 @@
@return the selected element or None
"""
# check the elements #
- for i,element in enumerate(reversed(self.elements)):
+ for element in reversed(self.elements):
if element.what_is_selected(coor) != None:
self.elements.remove(element)
self.elements.append(element)
@@ -259,6 +261,7 @@
for element in self.elements:
if not element.is_valid(): return False
return True
+ #return all([element.is_valid() for element in self.elements])
#python 2.5 and higher
def update(self):
"""Call update on all elements."""
@@ -487,7 +490,12 @@
try: self.elements.append(GraphicalConnection(self,
input_socket, output_socket))
except ConnectionException:
Messages.send_error_load('Could not connect
"%s" input[%d] and "%s" output[%d].'%(
- input_signal_block_id,
input_socket_index, output_signal_block_id, output_socket_index))
+ input_signal_block_id,
+ input_socket_index,
+ output_signal_block_id,
+ output_socket_index,
+ )
+ )
self.selected_element = None
self.update()
# done importing the flow graph #
Modified: grc/trunk/src/Graphics/MainWindow.py
===================================================================
--- grc/trunk/src/Graphics/MainWindow.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/Graphics/MainWindow.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -21,6 +21,7 @@
address@hidden Josh Blum
from Constants import *
+from Actions import *
import pygtk
pygtk.require('2.0')
import gtk
@@ -28,9 +29,80 @@
from FlowGraph import FlowGraph
from SignalBlockSelectionWindow import SignalBlockSelectionWindow
from VariableModificationWindow import VariableModificationWindow
-from Dialogs import TextDisplay
+from Dialogs import TextDisplay,MessageDialogHelper
+from StateCache import StateCache
import Preferences
+import Messages
+import ParseXML
+import os
+############################################################
+## Notebook Page
+############################################################
+
+class Page(gtk.HBox):
+ """A page in the notebook."""
+
+ def __init__(self, main_window):
+ """
+ Page constructor.
+ @param main_window main window
+ """
+ self.main_window = main_window
+ gtk.HBox.__init__(self, False, 0)
+ self.show()
+ self.pid_file = ''
+ self.file_path = ''
+ self.saved = True
+ #tab box to hold label and close button
+ self.tab = gtk.HBox(False, 0)
+ #setup tab label
+ self.label = gtk.Label()
+ self.tab.pack_start(self.label, True, False, 0)
+ #setup button image
+ image = gtk.Image()
+ image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU)
+ #setup image box
+ image_box = gtk.HBox(False, 0)
+ image_box.pack_start(image, True, False, 0)
+ #setup the button
+ button = gtk.Button()
+ button.connect("clicked", self.handle_button)
+ button.set_relief(gtk.RELIEF_NONE)
+ button.add(image_box)
+ #button size
+ w, h = gtk.icon_size_lookup_for_settings(button.get_settings(),
gtk.ICON_SIZE_MENU)
+ button.set_size_request(w+6, h+6)
+ self.tab.pack_start(button)
+ self.tab.show_all()
+
+ def handle_button(self, button):
+ """
+ The button was clicked.
+ Make the current page selected, then close.
+ @param the button
+ """
+ self.main_window.page_to_be_closed = self
+ self.main_window.handle_states(FLOW_GRAPH_CLOSE)
+
+ def set_text(self, text):
+ """
+ Set the text in this label.
+ @param text the new text
+ """
+ self.label.set_text(text)
+
+ def get_tab(self):
+ """
+ Get the gtk widget for this page's tab.
+ @return gtk widget
+ """
+ return self.tab
+
+############################################################
+## Main window
+############################################################
+
class MainWindow(gtk.Window):
"""The topmost window with menus, the tool bar, and other major
windows."""
@@ -39,33 +111,40 @@
MainWindow contructor.
@param handle_states the callback function
"""
+ #setup window
self.handle_states = handle_states
gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
vbox = gtk.VBox()
hbox = gtk.HBox()
self.add(vbox)
- self.set_title("")
#create the menu bar and toolbar
vbox.pack_start(Bars.MenuBar(), False)
vbox.pack_start(Bars.Toolbar(), False)
# create variable modification window #
- variable_modification_window =
VariableModificationWindow(self.handle_states)
- # create a flow_graph #
- self.flow_graph = FlowGraph(self.handle_states,
variable_modification_window)
- #add the scrolled window for the flow graph
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_size_request(MIN_WINDOW_WIDTH,
MIN_WINDOW_HEIGHT)
- scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
- scrolled_window.add_with_viewport(self.flow_graph)
- fg_and_report_box = gtk.VBox()
- fg_and_report_box.pack_start(scrolled_window)
+ self.variable_modification_window =
VariableModificationWindow(self.handle_states)
+ self.flow_graph = FlowGraph(self.handle_states,
self.variable_modification_window)
+ #setup scrolled window
+ self.scrolled_window = gtk.ScrolledWindow()
+ self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH,
MIN_WINDOW_HEIGHT)
+ self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
+ self.scrolled_window.add_with_viewport(self.flow_graph)
+ # create the notebook #
+ self.notebook = gtk.Notebook()
+ self.page_to_be_closed = None
+ self.current_page = None
+ self.notebook.set_show_border(False)
+ self.notebook.set_scrollable(True)
+ self.notebook.connect("switch-page", self.handle_page_change)
+ fg_and_report_box = gtk.VBox(False, 0)
+ fg_and_report_box.pack_start(self.notebook, False, False, 0)
+ fg_and_report_box.pack_start(self.scrolled_window)
hbox.pack_start(fg_and_report_box)
vbox.pack_start(hbox)
#create the side windows
side_box = gtk.VBox()
hbox.pack_start(side_box, False)
- side_box.pack_start(variable_modification_window, False)
#dont allow resize
-
side_box.pack_start(SignalBlockSelectionWindow(self.flow_graph)) #all resize,
selection window can have more space
+ side_box.pack_start(self.variable_modification_window, False)
#dont allow resize
+
side_box.pack_start(SignalBlockSelectionWindow(self.get_flow_graph)) #all
resize, selection window can have more space
#create the reports window
self.text_display = TextDisplay()
#house the reports in a scrolled window
@@ -100,13 +179,30 @@
vadj = self.reports_scrolled_window.get_vadjustment()
vadj.set_value(vadj.upper)
- def set_title(self, title):
+ def set_title(self):
"""!
Set the title and prepend the program name.
@param title the window title
- """
- prepend_str = MAIN_WINDOW_PREFIX + ' - Editing: '
- gtk.Window.set_title(self, prepend_str + str(title))
+ """
+ if self.get_page():
+ title = ''.join((
+ MAIN_WINDOW_PREFIX,
+ ' - Editing: ',
+ (self.get_file_path() or
NEW_FLOGRAPH_TITLE),
+ (self.get_saved() and ' ' or '*'),
#blank must be non empty
+ )
+ )
+ else: title = MAIN_WINDOW_PREFIX + ' - Editor '
+ gtk.Window.set_title(self, title)
+ #set tab titles
+ for page_num in range(self.notebook.get_n_pages()):
+ page = self.notebook.get_nth_page(page_num)
+ page.set_text(''.join((
+
(os.path.split(page.file_path)[1] or NEW_FLOGRAPH_TITLE),
+ (page.saved and ' ' or '*'),
#blank must be non empty
+ )
+ )
+ )
def show_reports_window(self, show):
"""!
@@ -116,4 +212,174 @@
"""
if show: self.reports_scrolled_window.show()
else: self.reports_scrolled_window.hide()
-
\ No newline at end of file
+
+ ############################################################
+ ## Pages: New/Open, Close, Change
+ ############################################################
+
+ def _get_files(self):
+ """
+ Get the file names for all the pages, in order.
+ @return list of file paths
+ """
+ return [self.notebook.get_nth_page(page_num).file_path for
page_num in range(self.notebook.get_n_pages())]
+
+ def new_page(self, file_path=''):
+ """!
+ Create a new notebook page.
+ Set the tab to be selected.
+ @param file_path optional file to load into the flow graph
+ """
+ if file_path and file_path in self._get_files(): #already open
+ page =
self.notebook.get_nth_page(self._get_files().index(file_path))
+ self.set_page(page)
+ return
+ page = Page(self)
+ page.file_path = file_path
+ if page.file_path:
+ try: #try to load from file
+ Messages.send_start_load(page.file_path)
+ initial_state =
ParseXML.from_xml(ParseXML.from_file(page.file_path))
+
self.get_flow_graph().from_nested_data(initial_state)
+ page.state_cache = StateCache(initial_state)
+ Messages.send_end_load()
+ except Exception, e:
+ Messages.send_fail_load(e)
+ return
+ else: #load the default file
+ initial_state =
ParseXML.from_xml(ParseXML.from_file(INITIAL_FLOW_GRAPH_FILE))
+ self.get_flow_graph().from_nested_data(initial_state)
+ page.state_cache = StateCache(initial_state)
+ self.notebook.append_page(page, page.get_tab())
+ self.set_page(page)
+
+ def handle_page_change(self, notebook, page, page_num):
+ """!
+ Handle a page change. When the user clicks on a new tab,
+ reload the flow graph to update the vars window and
+ call handle states (select nothing) to update the buttons.
+ @param notebook the notebook
+ @param page new page
+ @param page_num new page number
+ """
+ self.current_page = self.notebook.get_nth_page(page_num)
+ state = self.get_state_cache().get_current_state()
+ self.get_flow_graph().from_nested_data(state)
+ self.handle_states(NOTHING_SELECT)
+
+ def close_pages(self):
+ """
+ Close all the pages in this notebook.
+ @return true if all closed
+ """
+ files = filter(lambda file: file, self._get_files()) #filter
blank files
+ for page in [self.notebook.get_nth_page(page_num) for page_num
in range(self.notebook.get_n_pages())]:
+ self.page_to_be_closed = page
+ self.close_page(False)
+ if self.notebook.get_n_pages(): return False
+ Preferences.save_files_open(files)
+ return True
+
+ def close_page(self, ensure=True):
+ """
+ Close the current flow graph.
+ If ensure: ensure there is at least one page in the notebook,
+ call new page if get page is none.
+ @param ensure boolean
+ """
+ if not self.page_to_be_closed: self.page_to_be_closed =
self.get_page()
+ if self._loose_changes():
+ self.handle_states(FLOW_GRAPH_STOP)
+
self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed))
+ if ensure and self.notebook.get_n_pages() == 0: self.new_page()
#no pages, make a new one
+ self.page_to_be_closed = None #set the page to be closed back
to None
+
+ def _loose_changes(self):
+ """!
+ Loose unsaved changes to flow graph?
+ If the save was not greyed-out, the user is presented with a
dialog.
+ @return true if save is greyed-out, or the user's choice.
+ """
+ if self.page_to_be_closed.saved: return True
+ self.set_page(self.page_to_be_closed) #show the page before
showing the confirm dialog
+ return MessageDialogHelper(
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved
Changes!',
+ 'Would you like to discard your unsaved changes?'
+ ) == gtk.RESPONSE_YES
+
+ def get_page(self):
+ """!
+ Get the selected page.
+ @return the selected page
+ """
+ return self.current_page
+
+ def set_page(self, page):
+ """
+ Set the current page.
+ @param page the page widget
+ """
+ self.current_page = page
+
self.notebook.set_current_page(self.notebook.page_num(self.current_page))
+
+ ############################################################
+ ## Access flow graph variables
+ ############################################################
+
+ def get_flow_graph(self):
+ """
+ Get the flow graph in this main window.
+ @return the flow graph
+ """
+ return self.flow_graph
+
+ def get_pid_file(self):
+ """!
+ Get the pid file for the flow graph.
+ @return the pid file or ''
+ """
+ return self.get_page().pid_file
+
+ def set_pid_file(self, pid_file=''):
+ """!
+ Set the pid file, '' for no pid file.
+ @param pid_file file path string
+ """
+ self.get_page().pid_file = pid_file
+
+ def get_file_path(self):
+ """!
+ Get the file path for the flow graph.
+ @return the file path or ''
+ """
+ return self.get_page().file_path
+
+ def set_file_path(self, file_path=''):
+ """!
+ Set the file path, '' for no file path.
+ @param file_path file path string
+ """
+ self.get_page().file_path = os.path.abspath(file_path)
+
+ def get_saved(self):
+ """!
+ Get the saved status for the flow graph.
+ @return true if saved
+ """
+ return self.get_page().saved
+
+ def set_saved(self, saved=True):
+ """!
+ Set the saved status.
+ @param saved boolean status
+ """
+ self.get_page().saved = saved
+
+ def get_state_cache(self):
+ """!
+ Get the state cache for the flow graph.
+ @return the state cache
+ """
+ return self.get_page().state_cache
+
+
\ No newline at end of file
Modified: grc/trunk/src/Graphics/SignalBlockSelectionWindow.py
===================================================================
--- grc/trunk/src/Graphics/SignalBlockSelectionWindow.py 2007-08-17
21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Graphics/SignalBlockSelectionWindow.py 2007-08-18
01:53:23 UTC (rev 6151)
@@ -30,16 +30,16 @@
class SignalBlockSelectionWindow(gtk.VBox):
"""The signal block selection window."""
- def __init__(self, flow_graph):
+ def __init__(self, get_flow_graph):
"""!
SignalBlockSelectionWindow constructor.
Show all possible signal blocks in this dialog.
Each signal block is represented by a gtk label of its tag and
an add button.
The add button tells the flow graph to create the selected
block. and add it to the flow graph.
- @param flow_graph the flow graph
+ @param get_flow_graph get the selected flow graph
"""
gtk.VBox.__init__(self)
- self.flow_graph = flow_graph
+ self.get_flow_graph = get_flow_graph
#title label
label = gtk.Label()
label.set_markup('<b>Signal Blocks</b>')
@@ -96,8 +96,9 @@
def _handle_add_button(self, widget):
"""Handle the add button clicked signal.
Add the signal block to the flow graph."""
- selection = self.treeview.get_selection()
- model, iter = selection.get_selected()
- if iter != None and not model.iter_has_child(iter):
self.flow_graph.add_signal_block(model.get_value(iter, 0))
+ if self.get_flow_graph():
+ selection = self.treeview.get_selection()
+ model, iter = selection.get_selected()
+ if iter != None and not model.iter_has_child(iter):
self.get_flow_graph().add_signal_block(model.get_value(iter, 0))
\ No newline at end of file
Modified: grc/trunk/src/Preferences.py
===================================================================
--- grc/trunk/src/Preferences.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Preferences.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -20,18 +20,18 @@
#Holds global preferences stored as GraphicalParams.
address@hidden Josh Blum
-from DataTypes import Bool,FileOpen,Enum,Int
-from Elements import GraphicalParam
+from DataTypes import Bool,Enum,Int,String
+from Elements import GraphicalParam, Param
import time,socket #for tagging saved files
from Constants import *
import ParseXML
import Messages
CONNECTION_CHECKING_PREF = GraphicalParam('Connection Checking',
Bool(true='Match Data Types', false='Ignore Data Types', default=True))
-PARAM_CHECKING_PREF = GraphicalParam('GraphicalParameter Checking',
Bool(true='Verify GraphicalParameters', false='Ignore Invalid GraphicalParams',
default=True))
+PARAM_CHECKING_PREF = GraphicalParam('Parameter Checking', Bool(true='Verify
Parameters', false='Ignore Invalid Params', default=True))
SOCKET_CHECKING_PREF = GraphicalParam('Socket Checking', Bool(true='Require
Connections', false='Allow Open Sockets', default=True))
-RESTORE_FLOW_GRAPH_PREF = GraphicalParam('Restore Flow Graph',
Bool(true='Overwrite Default Flow Graph', false='Keep Default Flow Graph',
default=True))
-DEFAULT_FLOW_GRAPH_PREF = GraphicalParam('Default Flow Graph', FileOpen('',
allow_blank=True))
+FILES_OPEN_PREF = Param('Files Open', String())
+RESTORE_FILES_PREF = GraphicalParam('Restore Open Files', Bool(true='Yes',
false='No', default=True))
SNAP_TO_GRID_PREF = GraphicalParam('Snap to Grid', Bool(true='On',
false='Off', default=False))
GRID_SIZE_PREF = GraphicalParam('Grid Size (pixels)', Enum([
('10 pixels', 10),
@@ -46,8 +46,8 @@
('100 pixels', 100),], 2))
SHOW_GRID_PREF = GraphicalParam('Grid Points', Bool(true='Show Grid',
false='Hide Grid', default=False))
REPORTS_WIN_SHOW_PREF = GraphicalParam('Reports Window', Bool(true='Show
Reports Window', false='Hide Reports Window', default=True))
-MAIN_WINDOW_WIDTH_PREF = GraphicalParam('Main Window Width',
Int(DEFAULT_MAIN_WINDOW_WIDTH))
-MAIN_WINDOW_HEIGHT_PREF = GraphicalParam('Main Window Height',
Int(DEFAULT_MAIN_WINDOW_HEIGHT))
+MAIN_WINDOW_WIDTH_PREF = Param('Main Window Width',
Int(DEFAULT_MAIN_WINDOW_WIDTH))
+MAIN_WINDOW_HEIGHT_PREF = Param('Main Window Height',
Int(DEFAULT_MAIN_WINDOW_HEIGHT))
###########################################################################
# List of Preferences
@@ -55,34 +55,33 @@
PREFS_LIST = [ #(title, notes, list of preferences)
("Verification", '', [
- CONNECTION_CHECKING_PREF,
- PARAM_CHECKING_PREF,
- SOCKET_CHECKING_PREF,
- ]),
- ("File Paths", '''\
-The default flow graph controls which flow graph will be loaded when the
program is started. \
-If the default flow graph is left blank, a blank flow graph will be loaded at
start-up. \
-File paths passed via a command line argument always proceed the default flow
graph. \
-Upon exit, if the overwrite option is set, the default flow graph will be
overwritten with the current flow graph. \
-''', [
- RESTORE_FLOW_GRAPH_PREF,
- DEFAULT_FLOW_GRAPH_PREF,
- ]),
+ (CONNECTION_CHECKING_PREF, 'connection_check'),
+ (PARAM_CHECKING_PREF, 'param_check'),
+ (SOCKET_CHECKING_PREF, 'socket_check'),
+ ]
+ ),
("Grid Options", '''\
Snap to Grid forces the upper right corner of the signal block to align with a
grid point. \
''', [
- SNAP_TO_GRID_PREF,
- GRID_SIZE_PREF,
- SHOW_GRID_PREF,
- ]),
+ (SNAP_TO_GRID_PREF, 'snap_to_grid'),
+ (GRID_SIZE_PREF, 'grid_size'),
+ (SHOW_GRID_PREF, 'show_grid'),
+ ]
+ ),
("Misc Options", '', [
- REPORTS_WIN_SHOW_PREF,
- ]),
+ (REPORTS_WIN_SHOW_PREF, 'show_reports_window'),
+ (RESTORE_FILES_PREF, 'restore_files'),
+ ]
+ ),
('', '', [ #put hidden prefs here
- MAIN_WINDOW_WIDTH_PREF,
- MAIN_WINDOW_HEIGHT_PREF,
- ]),
- ]
+ (FILES_OPEN_PREF, 'files_open'),
+ (MAIN_WINDOW_WIDTH_PREF, 'window_width'),
+ (MAIN_WINDOW_HEIGHT_PREF, 'window_height'),
+ ]
+ ),
+]
+
+PREFS_DICT = dict((key, param) for param, key in reduce(lambda l1, l2: l1 +
l2, zip(*PREFS_LIST)[2]))
###########################################################################
# Preference Access Methods
@@ -103,16 +102,14 @@
Convert the param's data to nested format.
@return the nested format
"""
- categories = list()
+ prefs = [('pref', [('key', key), ('value',
param.get_data_type().get_data())]) for key,param in PREFS_DICT.iteritems()]
nested_data = ('preferences', [
-
('timestamp', str(time.time())),
-
('hostname', socket.gethostname()),
-
('version', VERSION),
-
('categories', categories),])
- for title,notes,params in PREFS_LIST:
- prefs = list()
- categories.append(('category', [('title', title), ('prefs',
prefs)]))
- for param in params: prefs.append(('pref',
param.get_data_type().get_data()))
+ ('timestamp', str(time.time())),
+ ('hostname', socket.gethostname()),
+ ('version', VERSION),
+ ('prefs', prefs),
+ ]
+ )
return nested_data
def _from_nested(nested_data):
@@ -122,14 +119,13 @@
"""
find_data = ParseXML.find_data
preferences = find_data([nested_data], 'preferences')
- categories = find_data(preferences, 'categories')
- for i,category in enumerate(categories):
- category = find_data([category], 'category')
- prefs = find_data(category, 'prefs')
- for j,pref in enumerate(prefs):
- pref = find_data([pref], 'pref')
- try: PREFS_LIST[i][2][j].get_data_type().set_data(pref)
- except: pass
+ prefs = find_data(preferences, 'prefs')
+ for pref in prefs:
+ pref = find_data([pref], 'pref')
+ key = find_data(pref, 'key')
+ value = find_data(pref, 'value')
+ try: PREFS_DICT[key].get_data_type().set_data(value)
+ except: pass
def load(window=None):
"""!
@@ -156,17 +152,16 @@
###########################################################################
# Special methods for specific program functionalities
###########################################################################
-def set_default_flow_graph(file_path):
- ''' Set the new default flow graph path, only if the restore option is
true. '''
- if _get_value(RESTORE_FLOW_GRAPH_PREF):
- DEFAULT_FLOW_GRAPH_PREF.get_data_type().set_data(file_path)
-
-def get_default_flow_graph():
- ''' Get the default flow graph path. Return a blank string if the path
is invalid. '''
- if DEFAULT_FLOW_GRAPH_PREF.get_data_type().is_valid():
- return _get_value(DEFAULT_FLOW_GRAPH_PREF)
- return ''
+def restore_files():
+ return _get_value(RESTORE_FILES_PREF)
+
+def files_open():
+ return _get_value(FILES_OPEN_PREF).split('\n')
+
+def save_files_open(files):
+ FILES_OPEN_PREF.get_data_type().set_data('\n'.join(files))
+
def check_connections():
return _get_value(CONNECTION_CHECKING_PREF)
Modified: grc/trunk/src/SignalBlockDefs/Packet.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/Packet.py 2007-08-17 21:45:46 UTC (rev
6150)
+++ grc/trunk/src/SignalBlockDefs/Packet.py 2007-08-18 01:53:23 UTC (rev
6151)
@@ -260,6 +260,32 @@
ifs = ioctl(tun_fd, TUNSETIFF, struct.pack("16sH",
virtual_device_filename, mode))
ifname = ifs[:16].strip("\x00")
return tun_fd, ifname
+
+class TunTapHelper(gr.hier_block2):
+ """Make the tun tap hier2 block and start threads."""
+ def __init__(self, item_size, tun_fd, ifname):
+ """!
+ TunTapHelper constructor.
+ @param item_size the size in bytes of the IO data stream
+ @param tun_fd the file descriptor for the virtual device
+ @param ifname the name of virtual interface
+ """
+ #create hier block
+ gr.hier_block2.__init__(
+ self, 'tun_tap',
+ gr.io_signature(1, 1, item_size),
+ gr.io_signature(1, 1, item_size)
+ )
+ msg_source = gr.message_source(item_size, DEFAULT_QUEUE_LIMIT)
+ msgq_source = msg_source.msgq()
+ msgq_sink = gr.msg_queue(DEFAULT_QUEUE_LIMIT)
+ msg_sink = gr.message_sink(item_size, msgq_sink, False)
+ #start threads
+ TunSinkThread(msgq_sink, tun_fd, ifname)
+ TunSourceThread(msgq_source, item_size, tun_fd, ifname)
+ #connect
+ self.connect(self, msg_sink)
+ self.connect(msg_source, self)
class TunSinkThread(threading.Thread):
"""
@@ -285,21 +311,54 @@
while self.keep_running:
msg = self.msgq.delete_head() # blocking read of
message queue
os.write(self.tun_fd, msg.to_string())
+
+class TunSourceThread(threading.Thread):
+ """
+ Thread to forward data from the virtual device to the message queue.
+ """
+ def __init__(self, msgq, item_size, tun_fd, ifname):
+ """!
+ TunSourceThread contructor.
+ @param msgq the message queue for outgoing data
+ @param item_size the size of the stream in bytes
+ @param tun_fd the file descriptor for the virtual device
+ @param ifname the name of virtual interface
+ """
+ self.msgq = msgq
+ self.item_size = item_size
+ self.tun_fd = tun_fd
+ threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.keep_running = True
+ self.start()
+ print 'Created tun source thread for device "%s".'%ifname
+
+ def run(self):
+ """In an endless while loop: read the msgq and write to tun."""
+ r = ''
+ while self.keep_running:
+ sr = r + os.read(self.tun_fd, 128)
+ num_items = len(sr)/self.item_size
+ r_index = self.item_size*num_items
+ s = sr[0:r_index] #portion of string divisible by
item size
+ r = sr[r_index:] #residual portion of string
smaller then item size
+ if s: self.msgq.insert_tail(gr.message_from_string(s,
self.item_size))
#######################################################################################
## TUN/TAP Block Defs
#######################################################################################
-def TunSink(sb):
+def TunTap(sb):
gr.message_sink #uses
type = Enum(all_choices, 1)
- sb.add_input_socket('in', Variable(type))
+ sb.add_input_socket('in', Variable(type))
+ sb.add_output_socket('out', Variable(type))
sb.add_param('Type', type, False, type=True)
sb.add_param('Tun Device', String(DEFAULT_TUN_DEVICE))
sb.add_param('Virtual Device', String(DEFAULT_VIRTUAL_DEVICE))
sb.add_param('IP Address', String(DEFAULT_IP_ADDR))
sb.set_docs('''\
-Write data from a gnuradio data stream into a virtual ethernet interface.
+Foward data between gnuradio and a virtual ethernet interface.
---
Tun Device: File path to the tun device.
@@ -315,8 +374,7 @@
#try to set the ip address
ip_addr = ip_addr.parse()
if ip_addr: os.system('ifconfig %s %s'%(ifname, ip_addr))
- TunSinkThread(msgq, tun_fd, ifname)
- return gr.message_sink(item_size, msgq, False)
+ return TunTapHelper(item_size, tun_fd, ifname)
return sb, make
\ No newline at end of file
Modified: grc/trunk/src/SignalBlockDefs/SignalBlockTree.py
===================================================================
--- grc/trunk/src/SignalBlockDefs/SignalBlockTree.py 2007-08-17 21:45:46 UTC
(rev 6150)
+++ grc/trunk/src/SignalBlockDefs/SignalBlockTree.py 2007-08-18 01:53:23 UTC
(rev 6151)
@@ -58,7 +58,6 @@
('Audio Sink', Audio.AudioSink),
('USRP Sink', USRP.USRPSink),
('USRP Dual Sink', USRP.USRPDualSink),
- ('Tun Sink', Packet.TunSink),
]),
('Graphical Sinks', [
('Numerical Sink',
GraphicalSinks.NumericalSink),
@@ -184,7 +183,8 @@
('Valve', Misc.Valve),
('Selector', Misc.Selector),
('Head', Misc.Head),
- ('Skip Head', Misc.SkipHead),
+ ('Skip Head', Misc.SkipHead),
+ ('Tun Tap', Packet.TunTap),
('RMS', Misc.RMS),
('About', Misc.About),
('Note', Misc.Note),
Modified: grc/trunk/src/StateCache.py
===================================================================
--- grc/trunk/src/StateCache.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/StateCache.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -40,8 +40,7 @@
self.num_prev_states = 0
self.num_next_states = 0
self.states[0] = initial_state
- get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(False)
- get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
+ self.update_actions()
def save_new_state(self, state):
"""!
@@ -54,14 +53,14 @@
self.num_prev_states = self.num_prev_states + 1
if self.num_prev_states == STATE_CACHE_SIZE:
self.num_prev_states = STATE_CACHE_SIZE - 1
self.num_next_states = 0
- get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(True)
- get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
+ self.update_actions()
def get_current_state(self):
"""!
Get the state at the current index.
@return the current state (nested data)
"""
+ self.update_actions()
return self.states[self.current_state_index]
def get_prev_state(self):
@@ -73,8 +72,6 @@
self.current_state_index = (self.current_state_index +
STATE_CACHE_SIZE -1)%STATE_CACHE_SIZE
self.num_next_states = self.num_next_states + 1
self.num_prev_states = self.num_prev_states - 1
- if self.num_prev_states == 0:
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(False)
-
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(True)
return self.get_current_state()
return None
@@ -87,8 +84,14 @@
self.current_state_index = (self.current_state_index +
1)%STATE_CACHE_SIZE
self.num_next_states = self.num_next_states - 1
self.num_prev_states = self.num_prev_states + 1
- if self.num_next_states == 0:
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(False)
-
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(True)
return self.get_current_state()
return None
+
+ def update_actions(self):
+ """
+ Update the undo and redo actions based on the number of next
and prev states.
+ """
+
get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(self.num_next_states != 0)
+
get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(self.num_prev_states != 0)
+
\ No newline at end of file
Modified: grc/trunk/src/Variables.py
===================================================================
--- grc/trunk/src/Variables.py 2007-08-17 21:45:46 UTC (rev 6150)
+++ grc/trunk/src/Variables.py 2007-08-18 01:53:23 UTC (rev 6151)
@@ -59,9 +59,7 @@
# make sure that the key name is valid #
if not is_key_name_valid(key): raise KeyError, '"%s" is a invalid key
name!'%key
# count the number of blank strings in min, max, and step #
- num_blanks = 0
- for var in (min, max, step):
- if var == '': num_blanks = num_blanks + 1
+ num_blanks = [min, max, step].count('')
if num_blanks == 3: pass #allow the vars to be registered normally
else: #num_blanks is less than 3
try: float(value) #make sure that value is a float
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r6151 - in grc/trunk: data notes src src/Elements src/Graphics src/SignalBlockDefs,
jblum <=