Python-Ref > GUI programming with PyGTK > Real world example > Cookbook GUI II.
 
 

<-^^->

Cookbook GUI II.

This version add support for actual viewing of the recipes.
In this version of the cookbook program we add a very simple support for viewing of recipes.
We will show how to remove items from a menu and from a box. We will show how to derive our own widget from one of the widgets provided in GTK.
Expand/Shrink
<cookbook>
  <recipe>
    <title>Cheese cake</title>
    <text>Here comes the description for preparation of a cheese cake.</text>
    <ingredient amount="500g">soft cheese</ingredient>
    <ingredient amount="2">eggs</ingredient>
    <ingredient amount="100g">sugar</ingredient>
    <ingredient>raisins</ingredient>
  </recipe>
  <recipe>
    <title>Rosted duck</title>
    <text>Here we describe how to prepare a roasted duck.</text>
    <ingredient amount="1">duck</ingredient>
    <ingredient>cumin</ingredient>
    <ingredient amount="1">apple</ingredient>
  </recipe>
</cookbook>
  1   import xml.dom.minidom as dom
  2   
  3   class Recipe( object):
  4   
  5     dom_element_name = "recipe"
  6   
  7     def __init__( self, title="", text=""):
  8       self.title = title
  9       self.text = text
 10       self.ingredients = []
 11   
 12     def __str__( self):
 13       return "Recipe: %s (%d ingredients)" % (self.title, len( self.ingredients))
 14   
 15     def read_dom_element( self, e):
 16       titles = e.getElementsByTagName( "title")
 17       if not titles:
 18         raise ValueError( "Could not find title in the dom element")
 19       elif len( titles) > 1:
 20         print >> sys.stderr, "Warning: more than one title in dom element\n", titles
 21       self.title = get_all_text_from_element( titles[0])
 22       texts = e.getElementsByTagName( "text")
 23       if texts:
 24         self.text = get_all_text_from_element( texts[0])
 25       for ie in e.getElementsByTagName( Ingredient.dom_element_name):
 26         i = Ingredient()
 27         i.read_dom_element( ie)
 28         self.add_ingredient( i)
 29   
 30     def get_dom_element( self, doc):
 31       el = doc.createElement( self.dom_element_name)
 32       for attr_name in ['title','text']:
 33         attr_el = doc.createElement( attr_name)
 34         attr_el.appendChild( doc.createTextNode( getattr( self, attr_name)))
 35         el.appendChild( attr_el)
 36       for i in self.ingredients:
 37         ie = i.get_dom_element( doc)
 38         el.appendChild( ie)
 39       return el
 40   
 41     def add_ingredient( self, i):
 42       self.ingredients.append( i)
 43   
 44   
 45   class Ingredient( object):
 46   
 47     dom_element_name = "ingredient"
 48   
 49     def __init__( self, name="", amount=""):
 50       self.name = name
 51       self.amount = amount
 52   
 53     def __str__( self):
 54       if self.amount:
 55         return "%s %s" % (self.amount, self.title)
 56       else:
 57         return "%s" % self.title
 58   
 59     def read_dom_element( self, e):
 60       if e.hasAttribute( "amount"):
 61         self.amount = e.getAttribute( "amount")
 62       self.name = get_all_text_from_element( e)
 63   
 64     def get_dom_element( self, doc):
 65       el = doc.createElement( self.dom_element_name)
 66       if self.amount:
 67         el.setAttribute( "amount", str( self.amount))
 68       el.appendChild( doc.createTextNode( self.name))
 69       return el
 70   
 71   
 72   
 73   class CookBook( object):
 74   
 75     def __init__( self):
 76       self.recipes = []
 77   
 78     def __str__( self):
 79       return "Cookbook: %d recipes" % len( self.recipes)
 80   
 81     def read_xml_file( self, filename):
 82       doc = dom.parse( filename)
 83       for el in doc.getElementsByTagName( Recipe.dom_element_name):
 84         rec = Recipe()
 85         rec.read_dom_element( el)
 86         self.recipes.append( rec)
 87   
 88     def write_xml_file( self, filename):
 89       doc = dom.Document()
 90       root = doc.createElement( "cookbook")
 91       doc.appendChild( root)
 92       for rec in self.recipes:
 93         e = rec.get_dom_element( doc)
 94         root.appendChild( e)
 95       f = file( filename, "w")
 96       f.write( doc.toxml())
 97   
 98     def add_recipe( self, recipe):
 99       self.recipes.append( recipe)
100   
101   # help functions
102   
103   def get_all_text_from_element( el):
104       text = ""
105       for ch in el.childNodes:
106           if isinstance( ch, dom.Element):
107               text += get_all_text_from_element( ch)
108           if isinstance( ch, dom.Text):
109               text += ch.data
110       return text
111       
112   # end of help functions
113   
114   
115   if __name__ == "__main__":
116     c = CookBook()
117     c.read_xml_file( "infiles/cookbook2.xml")
118     print c
119     for rec in c.recipes:
120       print rec
121     new = Recipe( "Potato dumplings")
122     new.text = "Preparation instructions for czech potato dumplings"
123     c.add_recipe( new)
124     new.add_ingredient( Ingredient( name="potatoes", amount="500g"))
125     c.write_xml_file( "cookbook2-2.xml")
126     print c
  1   import pygtk
  2   pygtk.require('2.0')
  3   # import the GTK module
  4   import gtk
  5   
  6   from cookbook3_1 import Recipe
  7   
  8   class RecipeBox( gtk.VBox):
  9   
 10     def __init__( self, recipe, *args, **kw):
 11       gtk.VBox.__init__( self, *args, **kw)
 12       self.recipe = recipe
 13       self.create_interior()
 14   
 15     def create_interior( self):
 16       # title
 17       l = gtk.Label()
 18       l.set_markup( '<span size="large" weight="bold">%s</span>' % self.recipe.title) 
 19       l.show()
 20       l.set_alignment( 0, 0) 
 21       l.set_padding( 10, 0) 
 22       self.pack_start( l, expand=False, padding=10)
 23       # table to place ingredients in
 24       itable = gtk.Table( 2, len( self.recipe.ingredients))
 25       self.pack_start( itable, expand=False)
 26       # ingredients
 27       i = 0
 28       for ingredient in self.recipe.ingredients:
 29         # amount
 30         l = gtk.Label()
 31         l.set_markup( "<b><i>%s</i></b>" % ingredient.amount)
 32         l.show()
 33         l.set_alignment( 1, 0) # align right 
 34         itable.attach( l, 0, 1, i, i+1, xoptions=gtk.FILL, xpadding=10)
 35         # name 
 36         l = gtk.Label()
 37         l.set_markup( "<i>%s</i>" % ingredient.name)
 38         l.show()
 39         l.set_alignment( 0, 0) # align left 
 40         itable.attach( l, 1, 2, i, i+1, xoptions=gtk.FILL)
 41         i += 1
 42       itable.show()
 43       # text
 44       l = gtk.Label( self.recipe.text)
 45       l.show()
 46       l.set_alignment( 0, 0)
 47       l.set_padding( 10, 0)
 48       self.pack_start( l, expand=False, padding=10)
 49       
  1   import pygtk
  2   pygtk.require('2.0')
  3   # import the GTK module
  4   import gtk
  5   
  6   from cookbook3_1 import CookBook
  7   from recipe_gui4_1 import RecipeBox
  8   
  9   class CookBookGUI:
 10   
 11     version = "4.1"
 12   
 13     def __init__( self):
 14       self.cookbook = CookBook()
 15       self.window = gtk.Window()
 16       self.window.set_title( "CookBookGUI, version %s" % self.version)
 17       self.window.set_size_request( 400, 300)
 18       self.window.connect( "destroy", self.destroy)
 19       self.create_interior()
 20       self.window.show_all()
 21       self.update_status()
 22   
 23     def create_interior( self):
 24       self.mainbox = gtk.VBox()
 25       self.window.add( self.mainbox)
 26       # menu
 27       self.menu_bar = self.create_menu_bar()
 28       self.menu_bar.show()
 29       self.mainbox.pack_start( self.menu_bar, expand=False, fill=False)
 30       # label for status
 31       self.status = gtk.Label()
 32       self.status.set_alignment( 0.98, 0)
 33       self.mainbox.pack_end( self.status, expand=False, fill=False)
 34       self.status.show()
 35       # initialization of an empty rb argument - it will store an RecipeBox later 
 36       self.rb = None 
 37       # show the box
 38       self.mainbox.show()
 39   
 40     def create_menu_bar( self):
 41       # the file menu
 42       file_menu = gtk.Menu()
 43       open_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_OPEN)
 44       open_item.connect( "activate", self.open_file)
 45       self.save_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_SAVE)
 46       self.save_item.connect( "activate", self.save_file)
 47       quit_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_QUIT)
 48       quit_item.connect( "activate", self.quit)
 49       for i in [open_item, self.save_item, gtk.SeparatorMenuItem(), quit_item]:
 50         i.show()
 51         file_menu.append( i)
 52       # the recipe menu
 53       self.recipe_menu = gtk.Menu()
 54       self.quit_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_QUIT)
 55       self.recipe_menu.append( self.quit_item)
 56       self.quit_item.show()
 57       # menu bar
 58       menu_bar = gtk.MenuBar()
 59       file_menu_item = gtk.MenuItem( "File")
 60       file_menu_item.set_submenu( file_menu)
 61       menu_bar.append( file_menu_item)
 62       recipe_menu_item = gtk.MenuItem( "Recipes")
 63       recipe_menu_item.set_submenu( self.recipe_menu)
 64       menu_bar.append( recipe_menu_item)
 65       return menu_bar
 66   
 67     def update_status( self):
 68       self.status.set_markup( "<b>%d</b> recipes" % len( self.cookbook.recipes))
 69       if len( self.cookbook.recipes) > 0:
 70         self.save_item.set_sensitive( True)
 71       else:
 72         self.save_item.set_sensitive( False)
 73       # clean the recipe menu 
 74       for child in self.recipe_menu.get_children(): 
 75         self.recipe_menu.remove( child) 
 76       # repopulate the menu
 77       for recipe in self.cookbook.recipes:
 78         item = gtk.MenuItem( recipe.title)
 79         item.connect( "activate", self.show_recipe, recipe)
 80         item.show()
 81         self.recipe_menu.append( item)
 82   
 83     def main( self):
 84       gtk.main()
 85   
 86     def destroy( self, w):
 87       gtk.main_quit()
 88   
 89     def open_file( self, w, data=None):
 90       d = gtk.FileChooserDialog( title="Select a file",
 91                                  parent=self.window,
 92                                  action=gtk.FILE_CHOOSER_ACTION_OPEN,
 93                                  buttons=(gtk.STOCK_OK,gtk.RESPONSE_ACCEPT,
 94                                           gtk.STOCK_CANCEL,gtk.RESPONSE_REJECT)
 95                                  )
 96       # create filters
 97       f1 = gtk.FileFilter()
 98       f1.set_name( "All files")
 99       f1.add_pattern( "*")
100       f2 = gtk.FileFilter()
101       f2.set_name( "XML files")
102       f2.add_pattern( "*.xml")
103       d.add_filter( f2)
104       d.add_filter( f1)
105       # run the dialog
106       ok = d.run()
107       if ok != gtk.RESPONSE_ACCEPT:
108         d.destroy()
109         return
110       filename = d.get_filename()
111       d.destroy()
112       self.cookbook.read_xml_file( filename)
113       self.update_status()
114   
115     def save_file( self, w, data=None):
116       d = gtk.FileChooserDialog( title="Select a file to save in..",
117                                  parent=self.window,
118                                  action=gtk.FILE_CHOOSER_ACTION_SAVE,
119                                  buttons=(gtk.STOCK_OK,gtk.RESPONSE_ACCEPT,
120                                           gtk.STOCK_CANCEL,gtk.RESPONSE_REJECT)
121                                  )
122       # create filters
123       f1 = gtk.FileFilter()
124       f1.set_name( "All files")
125       f1.add_pattern( "*")
126       f2 = gtk.FileFilter()
127       f2.set_name( "XML files")
128       f2.add_pattern( "*.xml")
129       d.add_filter( f2)
130       d.add_filter( f1)
131       # run the dialog
132       ok = d.run()
133       if ok != gtk.RESPONSE_ACCEPT:
134         d.destroy()
135         return
136       filename = d.get_filename()
137       d.destroy()
138       self.cookbook.write_xml_file( filename)
139   
140     def show_recipe( self, w, recipe):
141       if self.rb:
142         # close the current recipe
143         self.mainbox.remove( self.rb) 
144         self.rb.destroy() 
145       self.rb = RecipeBox( recipe) 
146       self.mainbox.pack_start( self.rb)
147       self.rb.show()
148   
149     def quit( self, w, data=None):
150       self.destroy( w)
151   
152   if __name__ == "__main__":
153     m = CookBookGUI()
154     m.main()
Screenshot:
Program screenshot cookbook_gui4_1.pngProgram screenshot cookbook_gui4_1a.png
Doba běhu: 607.8 ms
The next version just makes the appearance of the recipe nicer by using a scrolled widget to display the recipe.
Expand/Shrink
<cookbook>
  <recipe>
    <title>Cheese cake</title>
    <text>Here comes the description for preparation of a cheese cake.</text>
    <ingredient amount="500g">soft cheese</ingredient>
    <ingredient amount="2">eggs</ingredient>
    <ingredient amount="100g">sugar</ingredient>
    <ingredient>raisins</ingredient>
  </recipe>
  <recipe>
    <title>Rosted duck</title>
    <text>Here we describe how to prepare a roasted duck.</text>
    <ingredient amount="1">duck</ingredient>
    <ingredient>cumin</ingredient>
    <ingredient amount="1">apple</ingredient>
  </recipe>
</cookbook>
  1   import xml.dom.minidom as dom
  2   
  3   class Recipe( object):
  4   
  5     dom_element_name = "recipe"
  6   
  7     def __init__( self, title="", text=""):
  8       self.title = title
  9       self.text = text
 10       self.ingredients = []
 11   
 12     def __str__( self):
 13       return "Recipe: %s (%d ingredients)" % (self.title, len( self.ingredients))
 14   
 15     def read_dom_element( self, e):
 16       titles = e.getElementsByTagName( "title")
 17       if not titles:
 18         raise ValueError( "Could not find title in the dom element")
 19       elif len( titles) > 1:
 20         print >> sys.stderr, "Warning: more than one title in dom element\n", titles
 21       self.title = get_all_text_from_element( titles[0])
 22       texts = e.getElementsByTagName( "text")
 23       if texts:
 24         self.text = get_all_text_from_element( texts[0])
 25       for ie in e.getElementsByTagName( Ingredient.dom_element_name):
 26         i = Ingredient()
 27         i.read_dom_element( ie)
 28         self.add_ingredient( i)
 29   
 30     def get_dom_element( self, doc):
 31       el = doc.createElement( self.dom_element_name)
 32       for attr_name in ['title','text']:
 33         attr_el = doc.createElement( attr_name)
 34         attr_el.appendChild( doc.createTextNode( getattr( self, attr_name)))
 35         el.appendChild( attr_el)
 36       for i in self.ingredients:
 37         ie = i.get_dom_element( doc)
 38         el.appendChild( ie)
 39       return el
 40   
 41     def add_ingredient( self, i):
 42       self.ingredients.append( i)
 43   
 44   
 45   class Ingredient( object):
 46   
 47     dom_element_name = "ingredient"
 48   
 49     def __init__( self, name="", amount=""):
 50       self.name = name
 51       self.amount = amount
 52   
 53     def __str__( self):
 54       if self.amount:
 55         return "%s %s" % (self.amount, self.title)
 56       else:
 57         return "%s" % self.title
 58   
 59     def read_dom_element( self, e):
 60       if e.hasAttribute( "amount"):
 61         self.amount = e.getAttribute( "amount")
 62       self.name = get_all_text_from_element( e)
 63   
 64     def get_dom_element( self, doc):
 65       el = doc.createElement( self.dom_element_name)
 66       if self.amount:
 67         el.setAttribute( "amount", str( self.amount))
 68       el.appendChild( doc.createTextNode( self.name))
 69       return el
 70   
 71   
 72   
 73   class CookBook( object):
 74   
 75     def __init__( self):
 76       self.recipes = []
 77   
 78     def __str__( self):
 79       return "Cookbook: %d recipes" % len( self.recipes)
 80   
 81     def read_xml_file( self, filename):
 82       doc = dom.parse( filename)
 83       for el in doc.getElementsByTagName( Recipe.dom_element_name):
 84         rec = Recipe()
 85         rec.read_dom_element( el)
 86         self.recipes.append( rec)
 87   
 88     def write_xml_file( self, filename):
 89       doc = dom.Document()
 90       root = doc.createElement( "cookbook")
 91       doc.appendChild( root)
 92       for rec in self.recipes:
 93         e = rec.get_dom_element( doc)
 94         root.appendChild( e)
 95       f = file( filename, "w")
 96       f.write( doc.toxml())
 97   
 98     def add_recipe( self, recipe):
 99       self.recipes.append( recipe)
100   
101   # help functions
102   
103   def get_all_text_from_element( el):
104       text = ""
105       for ch in el.childNodes:
106           if isinstance( ch, dom.Element):
107               text += get_all_text_from_element( ch)
108           if isinstance( ch, dom.Text):
109               text += ch.data
110       return text
111       
112   # end of help functions
113   
114   
115   if __name__ == "__main__":
116     c = CookBook()
117     c.read_xml_file( "infiles/cookbook2.xml")
118     print c
119     for rec in c.recipes:
120       print rec
121     new = Recipe( "Potato dumplings")
122     new.text = "Preparation instructions for czech potato dumplings"
123     c.add_recipe( new)
124     new.add_ingredient( Ingredient( name="potatoes", amount="500g"))
125     c.write_xml_file( "cookbook2-2.xml")
126     print c
  1   import pygtk
  2   pygtk.require('2.0')
  3   # import the GTK module
  4   import gtk
  5   
  6   from cookbook3_1 import Recipe
  7   
  8   class RecipeBox( gtk.ScrolledWindow):
  9   
 10     def __init__( self, recipe, *args, **kw):
 11       gtk.ScrolledWindow.__init__( self, *args, **kw)
 12       self.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 
 13       self.recipe = recipe
 14       self.create_interior()
 15   
 16     def create_interior( self):
 17       self.box = gtk.VBox() 
 18       self.add_with_viewport( self.box) 
 19       self.box.show()
 20       # title
 21       l = gtk.Label()
 22       l.set_markup( '<span size="large" weight="bold">%s</span>' % self.recipe.title)
 23       l.show()
 24       l.set_alignment( 0, 0)
 25       l.set_padding( 10, 0)
 26       self.box.pack_start( l, expand=False, padding=10)
 27       # table to place ingredients in
 28       itable = gtk.Table( 2, len( self.recipe.ingredients))
 29       self.box.pack_start( itable, expand=False)
 30       # ingredients
 31       i = 0
 32       for ingredient in self.recipe.ingredients:
 33         # amount
 34         l = gtk.Label()
 35         l.set_markup( "<b><i>%s</i></b>" % ingredient.amount)
 36         l.show()
 37         l.set_alignment( 1, 0) # align right
 38         itable.attach( l, 0, 1, i, i+1, xoptions=gtk.FILL, xpadding=10)
 39         # name 
 40         l = gtk.Label()
 41         l.set_markup( "<i>%s</i>" % ingredient.name)
 42         l.show()
 43         l.set_alignment( 0, 0) # align left
 44         itable.attach( l, 1, 2, i, i+1, xoptions=gtk.FILL)
 45         i += 1
 46       itable.show()
 47       # text
 48       l = gtk.Label( self.recipe.text)
 49       l.show()
 50       l.set_alignment( 0, 0)
 51       l.set_padding( 10, 0)
 52       self.box.pack_start( l, expand=False, padding=10)
  1   import pygtk
  2   pygtk.require('2.0')
  3   # import the GTK module
  4   import gtk
  5   
  6   from cookbook3_1 import CookBook
  7   from recipe_gui4_2 import RecipeBox
  8   
  9   class CookBookGUI:
 10   
 11     version = "4.2"
 12   
 13     def __init__( self):
 14       self.cookbook = CookBook()
 15       self.window = gtk.Window()
 16       self.window.set_title( "CookBookGUI, version %s" % self.version)
 17       self.window.set_size_request( 400, 300)
 18       self.window.connect( "destroy", self.destroy)
 19       self.create_interior()
 20       self.window.show_all()
 21       self.update_status()
 22   
 23     def create_interior( self):
 24       self.mainbox = gtk.VBox()
 25       self.window.add( self.mainbox)
 26       # menu
 27       self.menu_bar = self.create_menu_bar()
 28       self.menu_bar.show()
 29       self.mainbox.pack_start( self.menu_bar, expand=False, fill=False)
 30       # label for status
 31       self.status = gtk.Label()
 32       self.status.set_alignment( 0.98, 0)
 33       self.mainbox.pack_end( self.status, expand=False, fill=False)
 34       self.status.show()
 35       # initialization of an empty rb argument - it will store an RecipeBox later 
 36       self.rb = None 
 37       # show the box
 38       self.mainbox.show()
 39   
 40     def create_menu_bar( self):
 41       # the file menu
 42       file_menu = gtk.Menu()
 43       open_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_OPEN)
 44       open_item.connect( "activate", self.open_file)
 45       self.save_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_SAVE)
 46       self.save_item.connect( "activate", self.save_file)
 47       quit_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_QUIT)
 48       quit_item.connect( "activate", self.quit)
 49       for i in [open_item, self.save_item, gtk.SeparatorMenuItem(), quit_item]:
 50         i.show()
 51         file_menu.append( i)
 52       # the recipe menu
 53       self.recipe_menu = gtk.Menu()
 54       self.quit_item = gtk.ImageMenuItem( stock_id=gtk.STOCK_QUIT)
 55       self.recipe_menu.append( self.quit_item)
 56       self.quit_item.show()
 57       # menu bar
 58       menu_bar = gtk.MenuBar()
 59       file_menu_item = gtk.MenuItem( "File")
 60       file_menu_item.set_submenu( file_menu)
 61       menu_bar.append( file_menu_item)
 62       recipe_menu_item = gtk.MenuItem( "Recipes")
 63       recipe_menu_item.set_submenu( self.recipe_menu)
 64       menu_bar.append( recipe_menu_item)
 65       return menu_bar
 66   
 67     def update_status( self):
 68       self.status.set_markup( "<b>%d</b> recipes" % len( self.cookbook.recipes))
 69       if len( self.cookbook.recipes) > 0:
 70         self.save_item.set_sensitive( True)
 71       else:
 72         self.save_item.set_sensitive( False)
 73       # clean the recipe menu 
 74       for child in self.recipe_menu.get_children(): 
 75         self.recipe_menu.remove( child) 
 76       # repopulate the menu
 77       for recipe in self.cookbook.recipes:
 78         item = gtk.MenuItem( recipe.title)
 79         item.connect( "activate", self.show_recipe, recipe)
 80         item.show()
 81         self.recipe_menu.append( item)
 82   
 83     def main( self):
 84       gtk.main()
 85   
 86     def destroy( self, w):
 87       gtk.main_quit()
 88   
 89     def open_file( self, w, data=None):
 90       d = gtk.FileChooserDialog( title="Select a file",
 91                                  parent=self.window,
 92                                  action=gtk.FILE_CHOOSER_ACTION_OPEN,
 93                                  buttons=(gtk.STOCK_OK,gtk.RESPONSE_ACCEPT,
 94                                           gtk.STOCK_CANCEL,gtk.RESPONSE_REJECT)
 95                                  )
 96       # create filters
 97       f1 = gtk.FileFilter()
 98       f1.set_name( "All files")
 99       f1.add_pattern( "*")
100       f2 = gtk.FileFilter()
101       f2.set_name( "XML files")
102       f2.add_pattern( "*.xml")
103       d.add_filter( f2)
104       d.add_filter( f1)
105       # run the dialog
106       ok = d.run()
107       if ok != gtk.RESPONSE_ACCEPT:
108         d.destroy()
109         return
110       filename = d.get_filename()
111       d.destroy()
112       self.cookbook.read_xml_file( filename)
113       self.update_status()
114   
115     def save_file( self, w, data=None):
116       d = gtk.FileChooserDialog( title="Select a file to save in..",
117                                  parent=self.window,
118                                  action=gtk.FILE_CHOOSER_ACTION_SAVE,
119                                  buttons=(gtk.STOCK_OK,gtk.RESPONSE_ACCEPT,
120                                           gtk.STOCK_CANCEL,gtk.RESPONSE_REJECT)
121                                  )
122       # create filters
123       f1 = gtk.FileFilter()
124       f1.set_name( "All files")
125       f1.add_pattern( "*")
126       f2 = gtk.FileFilter()
127       f2.set_name( "XML files")
128       f2.add_pattern( "*.xml")
129       d.add_filter( f2)
130       d.add_filter( f1)
131       # run the dialog
132       ok = d.run()
133       if ok != gtk.RESPONSE_ACCEPT:
134         d.destroy()
135         return
136       filename = d.get_filename()
137       d.destroy()
138       self.cookbook.write_xml_file( filename)
139   
140     def show_recipe( self, w, recipe):
141       if self.rb:
142         # close the current recipe
143         self.mainbox.remove( self.rb) 
144         self.rb.destroy() 
145       self.rb = RecipeBox( recipe) 
146       self.mainbox.pack_start( self.rb)
147       self.rb.show()
148   
149     def quit( self, w, data=None):
150       self.destroy( w)
151   
152   if __name__ == "__main__":
153     m = CookBookGUI()
154     m.main()
Screenshot:
Program screenshot cookbook_gui4_2.png
Doba běhu: 536.5 ms