commit-gnuradio
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]