Changeset 686

Show
Ignore:
Timestamp:
08/13/05 10:06:36 (3 years ago)
Author:
tzanko
Message:

Added support for the docbook format, and UI to insert cells in the notebook

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • nbshell/trunk/ChangeLog

    r679 r686  
     108.13.2005: 
     2    * Changed format of notebook files. Now nbshell supports the 
     3    docbook format. 
     4 
     5    * Refactored methods for inserting cells in the notebook and added 
     6    UI to use them 
     7 
    1808.10.2005: 
    29    * Added a type variable in each XXXDocumnetPlugin class the 
  • nbshell/trunk/nbshell/FigurePlugin.py

    r679 r686  
    6363 
    6464    type = 'figure' 
    65      
     65    def __len__(self): 
     66        return 1 
     67     
     68    def Split(self, pos): 
     69        assert(0) 
     70         
    6671    def Clear(self): 
    6772        """Clears all data""" 
     
    188193        index = self.view.GetIndex(self.id) 
    189194        self.view.DeleteCell(index, update) 
     195         
     196    position = property(fget = lambda :0, fset = lambda x:None) 
    190197 
    191198class FigureCtrl(wx.Window): 
  • nbshell/trunk/nbshell/PlainTextPlugin.py

    r683 r686  
    4646    #    return "encoded" #Probably only the python code plugin should be raw 
    4747         
    48     def CreateDocumentPlugin(self,document): 
     48    def CreateDocumentPlugin(self,document, text = None): 
    4949        """Creates the document part of the plugin. The returned object is  
    5050        stored in ipgDocument.celllist and is responsible for storing and 
    5151        serialization of data. "data" contains initial data for the plugin. 
    5252        """ 
    53         return PlainTextDocumentPlugin(document
     53        return PlainTextDocumentPlugin(document, text
    5454     
    5555    def CreateViewPlugin(self,docplugin, view): 
     
    7272 
    7373class PlainTextDocumentPlugin(object): 
    74     def __init__(self, document): 
     74    def __init__(self, document, text = None): 
    7575        """Initialization. If element is <sheet> then the text is 
    7676        element.text. If the element is something else, then the text is 
     
    7979        self.document = document 
    8080        self.sheet = document.sheet 
    81         self.text = '' 
     81        self.text = text or '' 
    8282        self.index = None   #Set by AddCell, InsertCell, DeleteCell 
    8383        self.view = None    #This plugin is designed for a single view. For 
     
    134134         
    135135    def __len__(self): 
    136         return self.view.window.GetLenght() 
     136        return self.view.window.GetLength() 
    137137     
    138138    def SetSavePoint(self): 
     
    175175        if update: 
    176176            self.view.Update() 
    177         return text[pos:] 
     177        return lambda p:\ 
     178            self.sheet.InsertCell('plaintext', p, update = False, text = text[pos:]) 
    178179 
    179180class PlainTextNotebookViewPlugin(object): 
  • nbshell/trunk/nbshell/PythonPlugin.py

    r679 r686  
    7373    #    return "raw" #Probably only the python code plugin should be raw 
    7474         
    75     def CreateDocumentPlugin(self,document, ipython_block): 
     75    def CreateDocumentPlugin(self,document, element): 
    7676        """Creates the document part of the plugin. The returned object is  
    7777        stored in ipgDocument.celllist and is responsible for storing and 
    78         serialization of data. "data" contains initial data for the plugin. 
     78        serialization of data. 
    7979        """ 
    80         return PythonDocumentPlugin(document, ipython_block
     80        return PythonDocumentPlugin(document, element
    8181     
    8282    def CreateViewPlugin(self,docplugin, view): 
     
    100100 
    101101class PythonDocumentPlugin(object): 
    102     def __init__(self, document, ipython_block): 
     102    def __init__(self, document, element): 
    103103        """Initialization. ipython-block is a Elemtent object holding a 
    104104        <ipython-block> tag""" 
    105105        self.document = document 
    106106        self.sheet = document.sheet 
    107         self.block = ipython_block #TODO: a better name? 
    108         self.logid = self.block.get('logid', 'default-log')  
     107        self.element = element 
     108        self.logid = self.element.get('logid', 'default-log')  
    109109        self.log = document.logs[self.logid] 
    110110        self.notebook = document.notebook 
     
    114114                            #multiple views there should be some modifications 
    115115        #print "block:" 
    116         #etree.dump(self.block) #dbg 
     116        #etree.dump(self.element) #dbg 
    117117        self.cells = \ 
    118118        [notebook.Cell(self.notebook.get_cell(x.attrib['number'],self.logid))\ 
    119          for x in self.block
     119         for x in self.element
    120120         
    121121    type = 'python' 
    122122     
    123123    def __len__ (self): 
    124         return len(self.block
     124        return len(self.element
    125125     
    126126    def Clear(self): 
    127127        """Clears all data""" 
    128         self.block.clear() 
    129         self.block.attrib['logid'] = self.logid 
     128        self.element.clear() 
     129        self.element.attrib['logid'] = self.logid 
    130130        self.cells = [] 
    131131        self.view.Update() 
     
    140140    def GetStuff(self, id): #TODO: a better name 
    141141        """Returns a tuple (type, elem) where type is the type of the id'th 
    142         element in self.block and elem is the the corresponding element in the 
     142        element in self.element and elem is the the corresponding element in the 
    143143        cell in the log""" 
    144144         
    145145        #print "id -> %s"%(str(id),) #dbg 
    146         type = self.block[id].attrib['type'] 
     146        type = self.element[id].attrib['type'] 
    147147        #print "type-> %s"%(type,) #dbg 
    148148        return (type, self.cells[id].element.find(type)) 
     
    154154         
    155155        root = etree.Element('ipython-block', logid = self.logid) 
    156         for elem in self.block[pos:]: 
     156        for elem in self.element[pos:]: 
    157157            root.append(elem) 
    158         del self.block[pos:] 
     158        del self.element[pos:] 
    159159        del self.cells[pos:] 
    160160        #TODO: spagetti 
    161161        self.sheet.Update(dicts = True, update = update) 
    162         return root 
     162        return lambda p:\ 
     163            self.sheet.InsertCell('python', p, update = False, element = root) 
    163164 
    164165    def GetFactory(self): 
     
    198199        return self.id 
    199200         
    200     #self.position is a property which gives the index in self.soc.block of 
     201    #self.position is a property which gives the index in self.doc.element of 
    201202    #the ipython-cell on which the cursor currently is. 
    202203    def __get_position(self): 
    203         linenum = self.window.GetCurrentLine() 
    204         if self.line2log[linenum] is not None: 
    205             return self.line2log[linenum][0] 
     204        pos = self.window.GetCurrentPos() 
     205        linenum = self.window.LineFromPosition(pos) 
     206        if pos == self.window.GetLength(): 
     207            return len(self.line2log) 
     208        elif self.line2log[linenum] is not None: 
     209            return len(self.doc.element) 
    206210        else: 
    207211            l = len(self.line2log) 
     
    209213                linenum +=1 
    210214            if linenum == l: 
    211                 return len(self.doc.block
     215                return len(self.doc.element
    212216            else: 
    213217                return self.line2log[linenum][0] 
     
    288292        #every little change that can occur. Think of a way to avoid this 
    289293        cells = self.doc.cells 
    290         block = self.doc.block 
     294        block = self.doc.element 
    291295        #print "data->", data #dbg 
    292296         
     
    371375         
    372376        #get the number of digits of the number of the input 
    373         item = self.doc.block[line[0]] 
     377        item = self.doc.element[line[0]] 
    374378        type = self.doc.GetStuff(line[0])[0] 
    375379        strnumber = item.attrib['number'] 
     
    496500        else: 
    497501            pos = self.line2log[linenum][0] 
    498             if pos == len(self.doc.block) -1: 
     502            if pos == len(self.doc.element) -1: 
    499503                #this block has only one cell, so do nothing 
    500504                return 
  • nbshell/trunk/nbshell/Sheet.py

    r683 r686  
    1313__version__ = Release.version 
    1414 
     15import StringIO 
    1516 
    1617from lxml import etree 
     
    1920 
    2021from nbshell import PythonPlugin 
    21 from nbshell.utils import getindex, getiterator2 
     22from nbshell.utils import * 
    2223 
    2324 
     
    4142        # 'special', 'output', etc. The values of the dictionary are lists of 
    4243        # tuples of the type (block, id) where block is a PythonDocumentPlugin 
    43         # object and the corresponding element is block.block[id] 
     44        # object and the corresponding element is block.element[id] 
    4445        self.cell2sheet = {} 
    4546        # sheet2sheet is a dictionary. For each element in a block it returns 
     
    5556         
    5657    def __get_current_cell(self): 
     58        if self._currentcell is None: 
     59            self.__set_current_cell(self.celllist[0]) 
    5760        return self._currentcell 
     61 
    5862    def __set_current_cell(self, cell): 
    5963        self._currentcell = cell 
     
    6569        pos. If pos=-1 insert at the end. **kwds is passed to the 
    6670        plugin.Returns an instance to the cell""" 
    67         #TODO: Update the dicts here 
    6871        factory = self.factory[type] 
    6972        cell = factory.CreateDocumentPlugin(self.doc, **kwds) 
     
    7477            print 'cell-> %s, pos->%s'%(str(cell),str(pos)) #dbg 
    7578            self.__insert_cell(cell, pos) 
     79 
     80        #TODO: Smarter update of the dicts here 
     81        self.Update(update = False, dicts = True) 
    7682        if update: 
    7783            view.Update() 
     
    148154     
    149155    def UpdateDoc(self): 
    150         """Updates data from the view""" 
     156        """Updates data from the view. Then updates self.element, from the 
     157        internal representation of data. If there was some error, throws an 
     158        exception""" 
    151159        for doccell in self.celllist: 
    152160            doccell.view.UpdateDoc() 
    153161             
    154      
     162            #Get the xml from the document 
     163            text = StringIO.StringIO() 
     164            text.write('<sheet>') 
     165            for doccell in self.celllist: 
     166                if doccell.type == 'plaintext': 
     167                    text.write(doccell.text) 
     168                elif doccell.type == 'python': 
     169                    etr = etree.ElementTree(doccell.element) 
     170                    etr.write(text, encoding='utf-8') 
     171                elif doccell.type == 'figure': 
     172                    etr = etree.ElementTree(doccell.element) 
     173                    etr.write(text, encoding = 'utf-8') 
     174            text.write('</sheet>') 
     175            text.flush() 
     176            text = StringIO.StringIO(text.getvalue()) 
     177            #Convert to etree.Element 
     178            etr = etree.ElementTree() 
     179            try: 
     180                etr.parse(text) 
     181            except: 
     182                #TODO: Handle syntax errors here  
     183                 
     184                #NBDOC: The notebook should check the documents for syntax 
     185                #errors and be able to give meanigful description of errors to 
     186                #the user 
     187                 
     188                raise #dbg 
     189            self.element = etr.getroot() 
     190            # Now remove the old sheet and replace it with the new one 
     191            oldsheet = self.notebook.root.find('sheet') 
     192            if oldsheet is not None: 
     193                self.notebook.root.remove(oldsheet) 
     194            self.notebook.root.append(self.element) 
     195 
    155196    def __append_plaintext_cell(self, iterator, prevlist, elemlist,\ 
    156197                                endtaglist, update = True): 
     
    187228                if elem.tag in tag2type.keys(): 
    188229                    self.InsertCell(tag2type[elem.tag], update = False, \ 
    189                                     ipython_block = elem) 
     230                                    element = elem) 
    190231                    l = len(elemlist) 
    191232                    prevlist = elemlist[:-1] 
     
    335376        self.cell2sheet = {} 
    336377        self.sheet2sheet = {} 
    337         for block in self.celllist: 
    338             # check if block is a PythonDocumentPlugin object 
    339             try: 
    340                 logid = block.logid 
    341             except: 
    342                 continue 
     378        for block in filter(lambda x:x.type=='python', self.celllist): 
     379            logid = block.logid 
    343380            for (i, cell) in enumerate(block.cells): 
    344                 key = (logid, cell.number, block.block[i].attrib['type']) 
     381                key = (logid, cell.number, block.element[i].attrib['type']) 
    345382                val = self.cell2sheet.get(key,[]) 
    346383                val.append((block, i)) 
     
    397434         
    398435        #1. Add the element 
    399         l = len(block.block
     436        l = len(block.element
    400437        if pos is None: 
    401438            pos = l 
     
    405442 
    406443        element = etree.Element('ipython-cell',type = type, number = str(number)) 
    407         block.block[pos:pos] = [element] 
     444        block.element[pos:pos] = [element] 
    408445        block.cells[pos:pos] = [cell] 
    409446         
     
    437474         
    438475        #1. Delete the element 
    439         l = len(block.block
     476        l = len(block.element
    440477        if pos < 0: 
    441478            pos = l + pos 
    442         elem = block.block[pos] 
    443         del(block.block[pos]) 
     479        elem = block.element[pos] 
     480        del(block.element[pos]) 
    444481        del(block.cells[pos]) 
    445482        if update: 
     
    496533                #1.1.1 Yes. Check if one of the elements is on the insert 
    497534                #position. 
    498                 if len(block.block)>pos2add and \ 
     535                if len(block.element)>pos2add and \ 
    499536                   block.cells[pos2add] == cell and \ 
    500                    block.block[pos2add].attrib['type'] == type : 
     537                   block.element[pos2add].attrib['type'] == type : 
    501538                    #Increment the insert position 
    502539                    pos2add += 1 
     
    641678                lastfig = self.celllist[index] 
    642679                codeelem = etree.Element('ipython-block', logid = block.logid) 
    643                 #Fix the text 
    644                 if index < len(self.celllist)-1 and\ 
    645                    self.celllist[index+1].type == 'plaintext': 
    646                     textblock = self.celllist[index+1] 
    647                     codeelem.tail = textblock.GetText() 
    648                     textblock.element = codeelem 
    649                     blocklist.append(textblock) 
    650680                #Insert the new block 
    651681                block = self.InsertCell('python', index+1, update = False,\ 
    652                                         ipython_block = codeelem) 
     682                                        element = codeelem) 
    653683                self.Update(update = False, dicts = True) 
    654684                retvalue = block 
     
    666696#            self.__update_list(blocklist) 
    667697 
    668  
    669698    def ReplaceCells(self, logid, oldcell, newcell, update = True): 
    670699        """Changes all the <ipython-cell type=..., number=oldcell.number> elements to 
     
    677706            val = self.cell2sheet.get((logid, oldcell.number, type),[]) 
    678707            for (block,pos) in val: 
    679                 block.block[pos].attrib['number'] = str(newcell.number) 
     708                block.element[pos].attrib['number'] = str(newcell.number) 
    680709                block.cells[pos] = newcell 
    681710        self.Update(update, dicts = True) 
    682711 
    683712    def InsertText(self, block, pos, update = True): 
    684         """Splits the given block and inserts a text cell""" 
    685         index = getindex(self.element,block.block) 
    686         #Get the XML for the new ipython-block 
    687         nextblock = block.Split(pos) 
    688         #update the old text cell to point to the new block 
    689         oldtextcell = self.celllist[block.index+1] 
    690         nextblock.tail = oldtextcell.GetText() 
    691         oldtextcell.element = nextblock 
    692         #insert nextblock in the sheet 
    693         self.element[index+1:index+1] = [nextblock] 
    694         ind = oldtextcell.index 
    695         self.InsertCell('python',ind, update = False, \ 
    696                         ipython_block = nextblock) 
    697         #insert a new text cell in the celllist 
    698         self.InsertCell('plaintext', ind, update = False, element = block.block) 
    699         #update 
    700         self.Update(dicts = True) 
    701         if update: 
    702             self.__update_list(self.celllist[ind-1:ind+2]) 
    703             self.view.Update() 
    704              
    705     def InsertCode(self, block, pos, update = True): 
    706         """Splits the given text block and inserts a code block. The logid 
    707         for the new block is set in self.currentlog""" 
     713        """Splits the given block and inserts an empty text cell""" 
     714        self.Insert(block, pos,\ 
     715                    check = lambda block, prev, next, pos:\ 
     716                        (block.type != 'plaintext') and 
     717                        (pos > 0 or prev == None or prev.type != 'plaintext') and\ 
     718                        (pos < len(block) or next == None or next.type != 'plaintext'),\ 
     719                    insert = lambda pos:  
     720                        self.InsertCell('plaintext', pos, update = False, text = ''),\ 
     721                    update = update) 
     722     
     723    def InsertCode(self, block, pos, logid = None, update = True): 
     724        """Splits the given text block and inserts an empty code block. If 
     725        logid is None self.currentlog is used""" 
     726        if logid is None: 
     727            logid = self.currentlog 
    708728        assert(self.last) #The last inputs must be set 
    709         newtext = block.Split(pos, update = False) 
    710         #Create the new code element 
    711         codeelement = etree.Element('ipython-block',logid=self.currentlog) 
    712         #Delete the last element of self.currentlog from the sheet  
    713         log = self.doc.logs[self.currentlog] 
    714         key = (self.currentlog, log.lastcell.number, 'input') 
    715         value = self.cell2sheet[key] 
    716         while len(value)>0: 
    717             blk, position = value[0] 
    718             self.DeleteElement(blk,position,update = False) 
    719         #insert the last element in codeelement 
    720         codeelement.append(etree.Element('ipython-cell',type='input',\ 
    721                                          number = str(key[1]))) 
    722         #set newtext at the tail 
    723         codeelement.tail = newtext 
    724         #get the index in the <sheet> element where we must insert the new cell 
    725         id = block.index 
    726         l = len(self.celllist) 
    727         while id<l: 
    728             try: 
    729                 self.celllist[id].log 
    730             except: 
    731                 id+=1 
    732             else: 
    733                 break 
    734         print 'new element:' #dbg 
    735         etree.dump(codeelement) #dbg 
    736         if id==l: #we must append the new element at the end of <sheet> 
    737             index = len(self.element) 
    738             self.element[index:index] = [codeelement] 
    739         else: 
    740             #insert the new code element  
    741             index = getindex(self.element,self.celllist[id].block) 
    742             self.element[index:index] = [codeelement] 
    743         #insert the new cells in celllist 
    744         self.InsertCell('python',pos=block.index+1,update = False,\ 
    745                         ipython_block = codeelement) 
    746         self.InsertCell('plaintext', pos = block.index+2, update = False,\ 
    747                         element = codeelement) 
    748         print 'new sheet:' #dbg 
    749         etree.dump(self.element) #dbg 
    750         #update stuff. I could update only the modified cells, but I'm lazy 
    751         self.Update(update,dicts = True) 
    752          
     729         
     730        def insert(p): 
     731            #Delete the last element of self.currentlog from the sheet  
     732            log = self.doc.logs[logid] 
     733            key = (logid, log.lastcell.number, 'input') 
     734            value = self.cell2sheet[key] 
     735            while len(value)>0: 
     736                blk, position = value[0] 
     737                self.DeleteElement(blk,position,update = False) 
     738            #insert the last element in codeelement 
     739            codeelement = etree.Element('ipython-block', logid = logid) 
     740            etree.SubElement(codeelement, 'ipython-cell',type='input',\ 
     741                             number = str(key[1])) 
     742            return self.InsertCell('python', p, update = False,\ 
     743                                   element = codeelement) 
     744 
     745 
     746        self.Insert(block, pos, 
     747                    check = lambda block, prev, next, pos:\ 
     748                        (block.type != 'python' or block.logid != logid) and\ 
     749                        (pos > 0 or prev == None or prev.type != 'python' or\ 
     750                         prev.logid != logid) and\ 
     751                        (pos < len(block) or next == None or next.type != 'python'\ 
     752                         or next.logid != logid),\ 
     753                    insert = insert, update = False) 
     754        self.Update(update) 
     755 
    753756    def InsertFigure(self, block, pos, figurexml, update = True): 
    754757        """Inserts the given figure at the given position in the given block. 
    755758        Returns the new block 
    756759        """ 
    757          
    758         fig_elem = etree.XML(figurexml) 
    759         #Figure out where to insert the figure, according to the type of the 
    760         #block 
    761          
    762         if block.type == 'python': 
    763             #This is a python block. Then if pos points to the position after 
    764             #the end of the block, insert the figure after the block. If not 
    765             #split the block and insert the figure at the given position. 
    766             index = getindex(self.element, block.block) 
    767             if pos >= len(block): # here we are using the __len__ method 
    768                 #Insert the xml in the sheet 
    769                 self.element[index+1:index+1] = [fig_elem] 
    770                 #Fix the text after the given element 
    771                 if self.celllist[block.index+1].type == 'plaintext': 
    772                     textblock = self.celllist[block.index+1] 
    773                     fig_elem.tail = textblock.GetText() 
    774                     textblock.element = fig_elem 
    775                 #Insert in the view 
    776                 figcell = self.InsertCell('figure', pos = block.index+1,\ 
    777                                           update = False, element= fig_elem) 
    778                 self.Update(update = update, dicts = True) 
    779             else: #We have to split the given block 
    780                 #Get the XML for the new ipython-block 
    781                 nextblock = block.Split(pos) 
    782                 #update the old text cell to point to the new block 
    783                 oldtextcell = self.celllist[block.index+1] 
    784                 if oldtextcell.type == 'plaintext': 
    785                     nextblock.tail = oldtextcell.GetText() 
    786                     oldtextcell.element = nextblock 
    787                 #insert nextblock in the sheet 
    788                 self.element[index+1:index+1] = [nextblock] 
    789                 self.InsertCell('python',pos = block.index+1, update = False, \ 
    790                                 ipython_block = nextblock) 
    791                 #insert the figure 
    792                 self.element[index+1:index+1] = [fig_elem] 
    793                 figcell = self.InsertCell('figure', block.index+1,\ 
    794                                           update = False, element = fig_elem) 
    795                 #update 
    796                 self.Update(update = update, dicts = True) 
    797             return figcell 
    798         else: 
    799             raise NotImplementedError 
    800  
     760        self.Insert(block, pos,\ 
     761                    check = lambda cur, prev, next, pos:True,\ 
     762                    insert = lambda pos:\ 
     763                        self.InsertCell('figure', pos, update = False,  
     764                                        element = etree.XML(figurexml)), 
     765                    update = update) 
     766     
     767    def Insert(self, block, pos, check = lambda cur, prev, next, pos:True, 
     768               insert = lambda pos:None, update = True): 
     769        """Inserts something in the given block at the given position. The 
     770        block is inserted if the check function returns True. The actual 
     771        insertion is done by the insert function, which is given one 
     772        parameter, the index in the celllist where the new block must be 
     773        inserted. The insert function must return the new block""" 
     774        print 'block.index ->', block.index 
     775        if check(block,\ 
     776                 ifelse(block.index>0,\ 
     777                        lambda:self.celllist[block.index-1], lambda:None),\ 
     778                 ifelse(block.index < len(self.celllist)-1,\ 
     779                        lambda:self.celllist[block.index+1], lambda:None),pos): 
     780            if pos == 0: 
     781                list = [insert(block.index)] 
     782            elif pos == len(block): 
     783                list = [insert(block.index+1)] 
     784            else: 
     785                newinsert = block.Split(pos) 
     786                list = [insert(block.index+1), newinsert(block.index+2)] 
     787            if update: 
     788                self.__update_list(list) 
     789                self.view.Update() 
  • nbshell/trunk/nbshell/frame.py

    r668 r686  
    1313__version__ = Release.version 
    1414 
     15import StringIO 
     16 
    1517import wx 
     18 
     19from nbshell import SimpleXMLWriter 
    1620 
    1721def idgen(): 
     
    3236#NBShell menu identifiers 
    3337ID_RERUN = id_iter.next() 
     38 
     39#Insert menu identifiers 
     40ID_INSERT_TEXT = id_iter.next() 
     41ID_INSERT_CODE = id_iter.next() 
     42ID_INSERT_FIGURE = id_iter.next() 
    3443 
    3544class ipnFrame(wx.Frame): 
     
    7584        nbshellmenu.Append(ID_RERUN, "&Rerun", "Rerun the notebook") 
    7685        wx.EVT_MENU(self, ID_RERUN, self.OnRerun) 
     86         
     87        insertmenu = wx.Menu() 
     88        insertmenu.Append(ID_INSERT_TEXT, "Insert Text", "Inserts a text cell") 
     89        insertmenu.Append(ID_INSERT_CODE, "Insert Code", "Inserts a new empty code cell") 
     90        insertmenu.Append(ID_INSERT_FIGURE, "Insert Figure...", "Inserts a figure") 
     91        wx.EVT_MENU(self, ID_INSERT_CODE, self.OnInsertCode) 
     92        wx.EVT_MENU(self, ID_INSERT_TEXT, self.OnInsertText) 
     93        wx.EVT_MENU(self, ID_INSERT_FIGURE, self.OnInsertFigure) 
     94         
    7795        menu = wx.MenuBar() 
    7896        menu.Append(filemenu, "&File") 
     97        menu.Append(insertmenu, "&Insert") 
    7998        menu.Append(nbshellmenu, "&NBShell") 
    8099        self.SetMenuBar(menu) 
     
    175194    def OnRerun(self,evt): 
    176195        self.app.document.Rerun() 
     196     
     197    def OnInsertText(self, evt): 
     198        sheet = self.app.document.sheet 
     199        block = sheet.currentcell 
     200        sheet.InsertText(block, block.view.position, update = True) 
     201     
     202    def OnInsertCode(self, evt): 
     203        sheet = self.app.document.sheet 
     204        block = sheet.currentcell 
     205        sheet.InsertCode(block, block.view.position, update = True) 
     206         
     207    def OnInsertFigure(self, evt = None): 
     208        dlg = wx.FileDialog(self, "Choose a Fifure", \ 
     209                            wildcard = "PNG files (*.png)|*.png",style = wx.OPEN) 
     210        val = dlg.ShowModal() 
     211        if val == wx.ID_CANCEL: 
     212            return None 
     213        else: 
     214            filename = dlg.GetPath() 
     215            sheet = self.app.document.sheet 
     216            text = StringIO.StringIO() 
     217            #We use XMLWriter, to avoid problems with a filename with special symbols, 
     218            #for example: blah.png"/><some random xml code>.png 
     219            writer = SimpleXMLWriter.XMLWriter(text, encoding = 'utf-8') 
     220            writer.start('ipython-figure', type = "png", filename = filename) 
     221            writer.end() 
     222             
     223            sheet.InsertFigure(sheet.currentcell, sheet.currentcell.view.position, 
     224               figurexml = text.getvalue()) 
     225            text.close() 
     226 
  • nbshell/trunk/nbshell/ipnDocument.py

    r683 r686  
    107107            self.sheet.Update(update = True) 
    108108            etree.dump(self.notebook.root) #dbg 
     109            #Set the current cell and position 
    109110        except: 
    110111            #self.Clear() #TODO: This does not work well if an exception occured.  
  • nbshell/trunk/nbshell/utils.py

    r683 r686  
    4444def getiterator2(root): 
    4545    """Returns an iterator which for each subelement yields a tuple of all 
    46     elements in the path from the root to the given subelement""" 
     46    elements in the path from the root to the given subelement, excluding the 
     47    root. The root element is not returned""" 
    4748     
    48     root_tup = (root,) 
    49     yield root_tup 
    5049    #Recursive generators, yummy :) 
    5150    for subelement in root: 
     51        yield (subelement,) 
    5252        iter = getiterator2(subelement) 
    5353        for result in iter: 
    54             yield root_tup + result 
     54            yield (subelement,) + result 
     55             
     56def default(func, default = None): 
     57    """If func throws an exception returns default, else returns the result of 
     58    the function""" 
     59    try: 
     60        res = func() 
     61    except: 
     62        res = default 
     63    return res 
     64 
     65def ifelse(expr1, expr2, expr3): 
     66    """If expr1 is True returns expr2(), else returns expr3(). expr2 and expr3 
     67    are functions. To use ifelse for regular expressions use: 
     68        ifelse(expr1, lambda:expr2, lambda:expr3)""" 
     69    #This ensures that ifelse(1, lambda:None, lambda:2) will return None, not 2 
     70    #expr2 and expr 
     71    return ((expr1) and (expr2(),) or (expr3(),))[0]