Changeset 8956

Show
Ignore:
Timestamp:
07/20/08 14:50:25
Author:
jblum
Message:

block tree class and better handling of categories

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • grc/trunk/notes/todo.txt

    r8939 r8956  
    1 ############    Blocks to Add:  #################### 
    2 -pad source/sink 
     1############ Blocks to Add: #################### 
    32-hier block 
    43-optparse block 
    54-ofdm wrappers 
    65 
    7 ############   Features to Add:        #################### 
     6############ Features to Add: #################### 
    87-save working directory after close 
    98-create sub-flow graphs to be used in larger flow graphs 
     
    1211-default platform for preferences block 
    1312-command line option for additional block wrappers 
    14 -block tree class 
    15 -dtd for external blocks 
    1613-hotkeys in action descriptions 
    17 -variables dependent on variables that change 
    1814-log slider gui control 
    1915-variable resolution graph structure 
     16-move checks from grc Block to grc_gnuradio specific 
     17 
     18############ Problems: #################### 
    2019-catch error on open non-existant files 
     20-block tree window maps block by name 
     21-variables dependent on variables that change 
    2122 
    22 ############   Suggestions:    #################### 
     23############ Suggestions: #################### 
    2324-simple usrp 
    2425-tune_result in usrp.py needs __str__ method 
  • grc/trunk/src/grc/Constants.py

    r8651 r8956  
    126126 
    127127###################################################################################################### 
    128 #      A state is recorded for each change to the flow graph, the size dictates how many states we can record  
     128# A state is recorded for each change to the flow graph, the size dictates how many states we can record  
    129129###################################################################################################### 
    130130 
     
    155155 
    156156##The default user preferences file. 
    157 PREFERENCES_FILE_PATH = os.path.join(DEFAULT_FILE_PATH, '.grc.xml'
     157PREFERENCES_FILE_PATH = os.path.join(DEFAULT_FILE_PATH, FLOW_GRAPH_FILE_EXTENSION
    158158##@} 
    159159 
  • grc/trunk/src/grc/elements/Block.py

    r8808 r8956  
    6464                name = n['name'] 
    6565                key = n['key'] 
     66                category = Utils.exists_or_else(n, 'category', '') 
    6667                params = Utils.listify(n, 'param') 
    6768                checks = Utils.listify(n, 'check') 
     
    7374                self._name = name 
    7475                self._key = key 
     76                self._category = category 
    7577                #create the param objects 
    7678                self._params = odict() 
     
    176178        def get_key(self): return self._key 
    177179 
     180        def get_category(self): return self._category 
     181 
    178182        def get_doc(self): return '' 
    179183 
  • grc/trunk/src/grc/elements/Platform.py

    r8939 r8956  
    5454                self._default_flow_graph = default_flow_graph 
    5555                self._generator = generator 
    56                 #load the block tree 
    57                 f = self._block_tree 
    58                 try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd')) 
    59                 except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e)) 
    60                 n = ParseXML.from_file(f)['block_tree'] 
    61                 #build nested tree object 
    62                 self._block_tree_nested = [(c['name'], Utils.listify(c, 'block')) for c in Utils.listify(n, 'cat')] 
    63                 self._keys_in_tree = sum([Utils.listify(c, 'block') for c in Utils.listify(n, 'cat')], []) 
    6456                #create a dummy flow graph for the blocks 
    6557                self._flow_graph = _Element(self) 
     
    7365                                        for filename in filter(lambda f: f.endswith('.xml'), filenames): 
    7466                                                self._load_block(os.path.join(dirpath, filename)) 
    75                 #handle blocks not in the tree 
    76                 custom_keys = set(self.get_block_keys()) - set(self._keys_in_tree) 
    77                 custom_keys = filter(lambda k: self._blocks_n[k].has_key('category') , custom_keys) 
    78                 for custom_key in custom_keys: 
    79                         custom_category = self._blocks_n[custom_key]['category'] 
    80                         found = False 
    81                         for category, keys in self._block_tree_nested: 
    82                                 if category == custom_category: 
    83                                         category.append(custom_key) 
    84                                         found = True 
    85                         if not found: self._block_tree_nested.append((custom_category, [custom_key])) 
    8667 
    8768        def _load_block(self, f): 
     
    9879                self._blocks_n[key] = n 
    9980 
     81        def load_block_tree(self, block_tree): 
     82                """! 
     83                Load a block tree with categories and blocks. 
     84                Step 1: Load all blocks from the xml specification. 
     85                Step 2: Load blocks with builtin category specifications. 
     86                @param block_tree the block tree object 
     87                """ 
     88                #load the block tree 
     89                f = self._block_tree 
     90                try: ParseXML.validate_dtd(f, os.path.join(DATA_DIR, 'block_tree.dtd')) 
     91                except ParseXML.XMLSyntaxError, e: self._exit_with_error('Block tree "%s" failed: \n\t%s'%(f, e)) 
     92                n = ParseXML.from_file(f)['block_tree'] 
     93                #add all blocks in the tree 
     94                for category, block_keys in [(c['name'], Utils.listify(c, 'block')) for c in Utils.listify(n, 'cat')]: 
     95                        block_tree.add_category(category) 
     96                        for block_key in block_keys: block_tree.add_block(self.get_block(block_key), category) 
     97                #add all other blocks, use the catgory 
     98                for block in self.get_blocks(): 
     99                        #blocks with empty categories are in the xml block tree or hidden 
     100                        if block.get_category() and not block_tree.has_block(block): 
     101                                block_tree.add_block(block, block.get_category()) 
     102 
    100103        def __str__(self): return 'Platform - %s(%s)'%(self.get_name(), self.get_key()) 
    101104 
     
    103106 
    104107        def get_new_flow_graph(self): return self.FlowGraph(self) 
    105  
    106         def get_block_tree(self): return self._block_tree_nested 
    107108 
    108109        def get_default_flow_graph(self): return self._default_flow_graph 
  • grc/trunk/src/grc/gui/BlockTreeWindow.py

    r8924 r8956  
    1717Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
    1818""" 
    19 ##@package grc.gui.SignalBlockSelectionWindow 
    20 #The signal block selection window gives the user a tree selection to choose a signal block. 
     19##@package grc.gui.BlockTreeWindow 
     20#The block selection panel gives the user a tree selection to choose a block. 
    2121#@author Josh Blum 
    2222 
     23from grc.BlockTree import BlockTree as _BlockTree 
    2324from grc.Constants import * 
    2425import pygtk 
     
    2728import gobject 
    2829 
    29 class SignalBlockSelectionWindow(gtk.VBox): 
    30         """The signal block selection window.""" 
     30class BlockTreeWindow(gtk.VBox, _BlockTree): 
     31        """The block selection panel.""" 
    3132 
    3233        def __init__(self, platform, get_flow_graph): 
     
    4041                """ 
    4142                gtk.VBox.__init__(self) 
     43                _BlockTree.__init__(self) 
     44                self.platform = platform 
    4245                self.get_flow_graph = get_flow_graph 
    4346                #make the tree model for holding blocks 
     
    5154                selection.connect('changed', self._handle_selection_change) 
    5255                renderer = gtk.CellRendererText() 
    53                 column = gtk.TreeViewColumn("Signal Blocks", renderer, text=0) 
     56                column = gtk.TreeViewColumn('Blocks', renderer, text=0) 
    5457                self.treeview.append_column(column) 
    5558                #make the scrolled window to hold the tree view 
     
    6568                #map names to keys 
    6669                self.names = dict() 
     70                #map categories to iters 
     71                self.categories = dict() 
    6772                #add blocks and categories 
    68                 for category, keys in platform.get_block_tree(): 
    69                         iter = self.treestore.insert_before(None, None) 
    70                         self.treestore.set_value(iter, 0, category) 
    71                         for key in keys: 
    72                                 if key not in platform.get_block_keys(): 
    73                                         print 'Block with key "%s" cannot be found in %s -> ignoring...'%(key, platform) 
    74                                         continue 
    75                                 name = platform.get_block(key).get_name() 
    76                                 if name in self.names.keys(): 
    77                                         print '%s has more than one block with name "%s".'%(platform, name) 
    78                                         print 'Although block names do not have to be unique, this gui requires that that are.' 
    79                                         print 'Please rename the block to avoid problems.' 
    80                                         continue 
    81                                 self.names[name] = key 
    82                                 new_iter = self.treestore.insert_before(iter, None) 
    83                                 self.treestore.set_value(new_iter, 0, name) 
     73                self.platform.load_block_tree(self) 
    8474                #initialize 
    8575                self._handle_selection_change() 
     76                 
     77        def add_block(self, block, category): 
     78                """! 
     79                Add a block with category to this selection window. 
     80                Call base class add block, then add to the tree store. 
     81                @param block the block object 
     82                @param category the category string 
     83                """ 
     84                if block.get_name() in self.names.keys(): 
     85                        print '%s has more than one block with name "%s".'%(self.platform, block.get_name()) 
     86                        print 'Although block names do not have to be unique, this gui requires that that are.' 
     87                        print 'Please rename the block to avoid problems.' 
     88                        return 
     89                _BlockTree.add_block(self, block, category) 
     90                new_iter = self.treestore.insert_before(self.categories[category], None) 
     91                self.treestore.set_value(new_iter, 0, block.get_name()) 
     92                self.names[block.get_name()] = block.get_key() 
     93                 
     94        def add_category(self, category): 
     95                """! 
     96                Add a category to this selection window. 
     97                Call base class add category, then add to the tree store. 
     98                @param category the category string 
     99                """ 
     100                _BlockTree.add_category(self, category) 
     101                iter = self.treestore.insert_before(None, None) 
     102                self.treestore.set_value(iter, 0, category) 
     103                self.categories[category] = iter 
    86104 
    87105        def _handle_mouse_button_press(self, widget, event): 
  • grc/trunk/src/grc/gui/MainWindow.py

    r8590 r8956  
    2727import gtk 
    2828import Bars 
    29 from SignalBlockSelectionWindow import SignalBlockSelectionWindow 
     29from BlockTreeWindow import BlockTreeWindow 
    3030from Dialogs import TextDisplay,MessageDialogHelper 
    3131from DrawingArea import DrawingArea 
     
    3737############################################################ 
    3838##      Main window 
    39 ############################################################            
    40                  
     39############################################################ 
     40 
    4141class MainWindow(gtk.Window): 
    4242        """The topmost window with menus, the tool bar, and other major windows.""" 
    43          
     43 
    4444        def __init__(self, handle_states, platform): 
    4545                """! 
     
    5050                #setup window 
    5151                self.handle_states = handle_states 
    52                 gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)          
     52                gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) 
    5353                vbox = gtk.VBox() 
    5454                hbox = gtk.HBox() 
    5555                self.add(vbox) 
    56                 #create the menu bar and toolbar        
    57                 vbox.pack_start(Bars.MenuBar(), False)  
    58                 vbox.pack_start(Bars.Toolbar(), False)          
     56                #create the menu bar and toolbar 
     57                vbox.pack_start(Bars.MenuBar(), False) 
     58                vbox.pack_start(Bars.Toolbar(), False) 
    5959                #setup scrolled window 
    6060                self.scrolled_window = gtk.ScrolledWindow() 
    61                 self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)      
     61                self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) 
    6262                self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 
    6363                self.drawing_area = DrawingArea(self) 
     
    7474                fg_and_report_box.pack_start(self.scrolled_window) 
    7575                hbox.pack_start(fg_and_report_box) 
    76                 vbox.pack_start(hbox)           
     76                vbox.pack_start(hbox) 
    7777                #create the side windows 
    7878                side_box = gtk.VBox() 
    7979                hbox.pack_start(side_box, False) 
    80                 side_box.pack_start(SignalBlockSelectionWindow(platform, self.get_flow_graph)) #allow resize, selection window can have more space 
    81                 #create the reports window              
     80                side_box.pack_start(BlockTreeWindow(platform, self.get_flow_graph)) #allow resize, selection window can have more space 
     81                #create the reports window 
    8282                self.text_display = TextDisplay() 
    8383                #house the reports in a scrolled window 
     
    8585                self.reports_scrolled_window.set_size_request(-1, REPORTS_WINDOW_HEIGHT) 
    8686                self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 
    87                 self.reports_scrolled_window.add_with_viewport(self.text_display)       
     87                self.reports_scrolled_window.add_with_viewport(self.text_display) 
    8888                fg_and_report_box.pack_end(self.reports_scrolled_window, False) #dont allow resize, fg should get all the space 
    89                 #show all but the main window container and the reports window  
     89                #show all but the main window container and the reports window 
    9090                vbox.show_all() 
    9191                self.notebook.hide() 
    92                 self._show_reports_window(False)  
    93                 # load preferences and show the main window  
     92                self._show_reports_window(False) 
     93                # load preferences and show the main window 
    9494                Preferences.load() 
    9595                self.resize(*Preferences.window_size()) 
     
    9999        ##      Event Handlers 
    100100        ############################################################ 
    101                  
     101 
    102102        def _quit(self, window, event): 
    103103                """! 
    104104                Handle the delete event from the main window. 
    105                 Generated by pressing X to close, alt+f4, or right click+close.         
     105                Generated by pressing X to close, alt+f4, or right click+close. 
    106106                This method in turns calls the state handler to quit. 
    107                 @return true            
     107                @return true 
    108108                """ 
    109109                self.handle_states(APPLICATION_QUIT) 
    110                 return True     
    111                  
     110                return True 
     111 
    112112        def _handle_page_change(self, notebook, page, page_num): 
    113113                """! 
    114114                Handle a page change. When the user clicks on a new tab, 
    115                 reload the flow graph to update the vars window and  
     115                reload the flow graph to update the vars window and 
    116116                call handle states (select nothing) to update the buttons. 
    117117                @param notebook the notebook 
     
    124124                self.get_flow_graph().import_data(state) 
    125125                self.get_flow_graph().update() 
    126                 self.handle_states(NOTHING_SELECT)  
    127                  
     126                self.handle_states(NOTHING_SELECT) 
     127 
    128128        ############################################################ 
    129129        ##      Report Window 
    130130        ############################################################ 
    131          
     131 
    132132        def add_report_line(self, line): 
    133133                """! 
     
    135135                @param line the new text 
    136136                """ 
    137                 self.text_display.insert(line)          
     137                self.text_display.insert(line) 
    138138                vadj = self.reports_scrolled_window.get_vadjustment() 
    139139                vadj.set_value(vadj.upper) 
    140                                                  
     140 
    141141        def _show_reports_window(self, show): 
    142142                """! 
     
    147147                if show: self.reports_scrolled_window.show() 
    148148                else: self.reports_scrolled_window.hide() 
    149                  
     149 
    150150        ############################################################ 
    151151        ##      Pages: create and close 
    152152        ############################################################ 
    153          
     153 
    154154        def new_page(self, file_path='', show=False): 
    155155                """! 
     
    163163                        page = self.notebook.get_nth_page(self._get_files().index(file_path)) 
    164164                        self._set_page(page) 
    165                         return          
     165                        return 
    166166                try: #try to load from file 
    167167                        if file_path: Messages.send_start_load(file_path) 
     
    171171                        flow_graph.handle_states = self.handle_states 
    172172                        page = Page( 
    173                                 self,  
     173                                self, 
    174174                                flow_graph=flow_graph, 
    175175                                file_path=file_path, 
     
    178178                except Exception, e: #return on failure 
    179179                        Messages.send_fail_load(e) 
    180                         return  
     180                        return 
    181181                #add this page to the notebook 
    182182                self.notebook.append_page(page, page.get_tab()) 
     
    184184                except: pass #gtk too old 
    185185                self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START) 
    186                 #only show if blank or manual  
    187                 if not file_path or show: self._set_page(page)  
    188                  
     186                #only show if blank or manual 
     187                if not file_path or show: self._set_page(page) 
     188 
    189189        def close_pages(self): 
    190190                """ 
    191                 Close all the pages in this notebook.           
     191                Close all the pages in this notebook. 
    192192                @return true if all closed 
    193193                """ 
     
    204204                Preferences.save() 
    205205                return True 
    206                          
     206 
    207207        def close_page(self, ensure=True): 
    208208                """ 
     
    217217                        self._set_page(self.page_to_be_closed) 
    218218                #unsaved? ask the user 
    219                 if not self.page_to_be_closed.get_saved() and self._save_changes():  
     219                if not self.page_to_be_closed.get_saved() and self._save_changes(): 
    220220                        self.handle_states(FLOW_GRAPH_SAVE) #try to save 
    221221                        if not self.page_to_be_closed.get_saved(): #still unsaved? 
     
    228228                if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one 
    229229                self.page_to_be_closed = None #set the page to be closed back to None 
    230          
     230 
    231231        ############################################################ 
    232232        ##      Misc 
     
    239239                Show/hide the reports window. 
    240240                @param title the window title 
    241                 """     
     241                """ 
    242242                if self.get_page(): 
    243243                        title = ''.join(( 
     
    249249                        ) 
    250250                else: title = MAIN_WINDOW_PREFIX + ' - Editor ' 
    251                 gtk.Window.set_title(self, title)       
     251                gtk.Window.set_title(self, title) 
    252252                #set tab titles 
    253253                for page in self._get_pages(): 
     
    261261                #reports window 
    262262                self._show_reports_window(Preferences.show_reports_window()) 
    263                 #show/hide notebook tabs  
     263                #show/hide notebook tabs 
    264264                if len(self._get_pages()) > 1: self.notebook.show() 
    265265                else: self.notebook.hide() 
    266                  
     266 
    267267        def get_page(self): 
    268268                """! 
     
    289289                """ 
    290290                self.current_page = page 
    291                 self.notebook.set_current_page(self.notebook.page_num(self.current_page))                       
     291                self.notebook.set_current_page(self.notebook.page_num(self.current_page)) 
    292292 
    293293        def _save_changes(self): 
    294294                """! 
    295                 Save changes to flow graph?             
     295                Save changes to flow graph? 
    296296                @return true if yes 
    297297                """ 
    298298                return MessageDialogHelper( 
    299                         gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!',  
     299                        gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!', 
    300300                        'Would you like to save changes before closing?' 
    301301                ) == gtk.RESPONSE_YES 
    302                  
     302 
    303303        def _get_files(self): 
    304304                """ 
     
    313313                @return list of pages 
    314314                """ 
    315                 return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())]        
    316  
     315                return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())] 
     316 
  • grc/trunk/src/grc/gui/ParamsDialog.py

    r8924 r8956  
    1717Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
    1818""" 
    19 ##@package grc.gui.SignalBlockParamsDialog 
    20 #A dialog for editing a signal block's parameters. 
     19##@package grc.gui.ParamsDialog 
     20#A dialog for editing a block's parameters. 
    2121#@author Josh Blum 
    2222 
     
    4141        return hbox 
    4242 
    43 class SignalBlockParamsDialog(gtk.Dialog): 
    44         """A dialog box to set signal block parameters.""" 
     43class ParamsDialog(gtk.Dialog): 
     44        """A dialog box to set block parameters.""" 
    4545 
    4646        def __init__(self, block): 
  • grc/trunk/src/grc/gui/elements/FlowGraph.py

    r8810 r8956  
    2525from grc.Actions import * 
    2626from Colors import BACKGROUND_COLOR, TXT_COLOR 
    27 from grc.gui.SignalBlockParamsDialog import SignalBlockParamsDialog 
     27from grc.gui.ParamsDialog import ParamsDialog 
    2828from Element import Element 
    2929from grc.elements import FlowGraph as _FlowGraph 
     
    166166                """ 
    167167                if self.get_selected_block(): 
    168                         signal_block_params_dialog = SignalBlockParamsDialog(self.get_selected_block()) 
     168                        signal_block_params_dialog = ParamsDialog(self.get_selected_block()) 
    169169                        changed = signal_block_params_dialog.run() 
    170170                        self.update() 
  • grc/trunk/src/grc_gnuradio/Generator.py

    r8910 r8956  
    2626import stat 
    2727from Cheetah.Template import Template 
    28 from grc.Constants import FLOW_GRAPH_FILE_EXTENSION 
    2928 
    3029##The default binary to execute python files. 
     
    4039 
    4140        def __init__(self, flow_graph, file_path): 
     41                """! 
     42                Initialize the generator object. 
     43                Determine the file to generate. 
     44                @param flow_graph the flow graph object 
     45                @param file_path the path to write the file to 
     46                """ 
    4247                self._flow_graph = flow_graph 
    4348                filename = self._flow_graph.get_option('id') + '.py' 
     
    5762        def get_popen(self): 
    5863                """! 
    59                 Generate and execute this python flow graph. 
    60                 @param file_path the file path of the flow graph 
     64                Execute this python flow graph. 
    6165                @return a popen object 
    6266                """