Re: [pygtk] freeze when trying to dynamically update menus

2004-07-24 Thread John Finlay
Abel Daniel wrote:
I was trying to implement dynamic menus. The idea is that the
menu-items are created when the menu is activated (shown). This would
be for an undo-menu where the menu-items would name the previously
done editing actions, so dynamically creating the menu is vital.
With a bit of help from #pygtk (on gimpnet) I came up with the
attached code. (Most of the code is the itemfactory example from the
pygtk tutorial.) The problem appears if the dynamically created menu is
the first sub-menu from the menubar. When activating this menu the
second time, the app freezes and I get a lot of the following messages
on stderr:
  (itemfactory.py:2223): Gtk-CRITICAL **: file gtkwidget.c: line
  3359 (gtk_widget_event): assertion `WIDGET_REALIZED_FOR_EVENT
  (widget, event)' failed
(It looked like one for each redraw.)
(This means that I have to go to a console with Ctrl-Alt-F2 and kill
the app. X is unusable after triggering the bug, as the app won't give
up focus, so mouseclicks go nowhere.)
If the dynamically created menu is the second sub-menu from the
menubar, (which means the menuitem which's 'activated' signal triggers
the re-creation of the menu is not on the menubar, but in a submenu)
it works fine.
In the attached code, the menu Options->Test works, but the top-level
Test does not.
Is this a bug in my code? 

 

I don't know what the problem is with your code but maybe my mods may be 
useful. I think the "select" signal is more useful for dynamically 
updating the submenus.  In the update_menu() method remove the current 
menuitems and add the new ones (or whatever changes you want). Spec 
'/Options/Test' and '/Text' as "" items. Modified program attached.

Hope this helps.
John
#!/usr/bin/env python

# example itemfactory.py

import gtk
import time

class ItemFactoryExample:
# Obligatory basic callback
def print_hello(self, widget, data):
print "Hello, World!"

def update_menu(self, widget):
submenu = widget.get_submenu()
# remove previous submenu items
for c in submenu.get_children():
submenu.remove(c)
t=time.time()
menu_item = gtk.MenuItem(label=str(t))
menu_item.show() #??
# add new menuitem
submenu.append(menu_item)

# This is the ItemFactoryEntry structure used to generate new menus.
# Item 1: The menu path. The letter after the underscore indicates an
# accelerator key once the menu is open.
# Item 2: The accelerator key for the entry
# Item 3: The callback.
# Item 4: The callback action.  This changes the parameters with
# which the callback is called.  The default is 0.
# Item 5: The item type, used to define what kind of an item it is.
#   Here are the possible values:

#   NULL   -> ""
#   "" -> ""
#   ""  -> create a title item
#   ""   -> create a simple item
#   ""  -> create a check item
#   "" -> create a toggle item
#   ""  -> create a radio item
#-> path of a radio item to link against
#   ""  -> create a separator
#   "" -> create an item to hold sub items (optional)
#   "" -> create a right justified branch 

def get_main_menu(self, window):
accel_group = gtk.AccelGroup()

# This function initializes the item factory.
# Param 1: The type of menu - can be MenuBar, Menu,
#  or OptionMenu.
# Param 2: The path of the menu.
# Param 3: A reference to an AccelGroup. The item factory sets up
#  the accelerator table while generating menus.
item_factory = gtk.ItemFactory(gtk.MenuBar, "", accel_group)

# This method generates the menu items. Pass to the item factory
#  the list of menu items
item_factory.create_items(self.menu_items)

# connect to the "select" signal to update submenus
menuitem = item_factory.get_item('/Test') # <-- SWITCH HERE !!!
menuitem.connect('select', self.update_menu)
menuitem = item_factory.get_item('/Options/Test')
menuitem.connect('select', self.update_menu)



# Attach the new accelerator group to the window.
window.add_accel_group(accel_group)

# need to keep a reference to item_factory to prevent its destruction
self.item_factory = item_factory
# Finally, return the actual menu bar created by the item factory.
return item_factory.get_widget("")

def __init__(self):
self.menu_items = (
( "/_File", None, None, 0, "" ),
( "/File/_New", "N", self.print_hello, 0, None ),
( "/File/_Open","O", self.print_hello, 0, None ),
( "/File/_Save","S", self.print_hello, 0, None ),
( "/File/Save _As", None, None, 0, None ),

[pygtk] freeze when trying to dynamically update menus

2004-07-23 Thread Abel Daniel

I was trying to implement dynamic menus. The idea is that the
menu-items are created when the menu is activated (shown). This would
be for an undo-menu where the menu-items would name the previously
done editing actions, so dynamically creating the menu is vital.

With a bit of help from #pygtk (on gimpnet) I came up with the
attached code. (Most of the code is the itemfactory example from the
pygtk tutorial.) The problem appears if the dynamically created menu is
the first sub-menu from the menubar. When activating this menu the
second time, the app freezes and I get a lot of the following messages
on stderr:

   (itemfactory.py:2223): Gtk-CRITICAL **: file gtkwidget.c: line
   3359 (gtk_widget_event): assertion `WIDGET_REALIZED_FOR_EVENT
   (widget, event)' failed

(It looked like one for each redraw.)

(This means that I have to go to a console with Ctrl-Alt-F2 and kill
the app. X is unusable after triggering the bug, as the app won't give
up focus, so mouseclicks go nowhere.)

If the dynamically created menu is the second sub-menu from the
menubar, (which means the menuitem which's 'activated' signal triggers
the re-creation of the menu is not on the menubar, but in a submenu)
it works fine.

In the attached code, the menu Options->Test works, but the top-level
Test does not.

Is this a bug in my code? 

Thanks in advance,
Abel Daniel

#!/usr/bin/env python

# example itemfactory.py

import gtk
import time

class ItemFactoryExample:
# Obligatory basic callback
def print_hello(self, widget, data):
print "Hello, World!"

def update_menu(self, widget):
#print 'updating'
t=time.time()
menu = gtk.Menu()
menu_item = gtk.MenuItem(label=str(t))
menu.append(menu_item)
menu_item.show() #??

widget.set_submenu(menu)
menu.show()
#widget.show()
#print 'updated:', t

# This is the ItemFactoryEntry structure used to generate new menus.
# Item 1: The menu path. The letter after the underscore indicates an
# accelerator key once the menu is open.
# Item 2: The accelerator key for the entry
# Item 3: The callback.
# Item 4: The callback action.  This changes the parameters with
# which the callback is called.  The default is 0.
# Item 5: The item type, used to define what kind of an item it is.
#   Here are the possible values:

#   NULL   -> ""
#   "" -> ""
#   ""  -> create a title item
#   ""   -> create a simple item
#   ""  -> create a check item
#   "" -> create a toggle item
#   ""  -> create a radio item
#-> path of a radio item to link against
#   ""  -> create a separator
#   "" -> create an item to hold sub items (optional)
#   "" -> create a right justified branch 

def get_main_menu(self, window):
accel_group = gtk.AccelGroup()

# This function initializes the item factory.
# Param 1: The type of menu - can be MenuBar, Menu,
#  or OptionMenu.
# Param 2: The path of the menu.
# Param 3: A reference to an AccelGroup. The item factory sets up
#  the accelerator table while generating menus.
item_factory = gtk.ItemFactory(gtk.MenuBar, "", accel_group)

# This method generates the menu items. Pass to the item factory
#  the list of menu items
item_factory.create_items(self.menu_items)

menuitem = item_factory.get_widget('/Test') # <-- SWITCH HERE !!!
menuitem.connect('activate', self.update_menu)
menuitem = item_factory.get_widget('/Options/Test')
menuitem.connect('activate', self.update_menu)



# Attach the new accelerator group to the window.
window.add_accel_group(accel_group)

# need to keep a reference to item_factory to prevent its destruction
self.item_factory = item_factory
# Finally, return the actual menu bar created by the item factory.
return item_factory.get_widget("")

def __init__(self):
self.menu_items = (
( "/_File", None, None, 0, "" ),
( "/File/_New", "N", self.print_hello, 0, None ),
( "/File/_Open","O", self.print_hello, 0, None ),
( "/File/_Save","S", self.print_hello, 0, None ),
( "/File/Save _As", None, None, 0, None ),
( "/File/sep1", None, None, 0, "" ),
( "/File/Quit", "Q", gtk.mainquit, 0, None ),
( "/_Options",  None, None, 0, "" ),
( "/Options/Test",  None, None, 0, None ),
( "/Test",  None, None, 0, None ),
( "/_Help", None, None, 0, "" ),
( "/_Help/About",   None, None, 0, None