James,
The ExtensionClass based pygtk looks great so far. I've been watching CVS
as you built it up and have been waiting for you to announce that it is
ready for folks to look at it.
I've attached a CVS diff that make the generated code use
PyArg_ParseTupleAndKeywords instead of PyArg_ParseTuple. This allows
keywords to be used to override default arguments, like in the old pygtk.
My implemention is kind-of brute force. It could be changed to only use
ParseTupleAndKeywords for functions and methods that have been assigned
default argument values.
The GtkItemFactory code in both the old and new pygtk has a refcount
problem. The attached python code demonstrates the bug. I have looked at
the gtk+ code and do not see a simple fix. Maybe someone else will.
Basically, gtk_item_factory_create_item() does not allow a GtkDestroyNotify
to be specified for the callback_data.
I look forward to using the added capabilities of the new pygtk in a
reorg/rewrite of our hyperspectral code.
I'm glad that you agreed that using ExtensionClass was a good idea.
Later,
Toby
Diff.out
import sys
import ltihooks
from gtk import *
import gtk
class SuperButton(GtkButton):
def __init__(self,args):
GtkButton.__init__(self,args)
self.msg='I am a super button'
def __del__(self):
print 'SuperButton.__del__'
def itemf_cb(arg,w):
if hasattr(w,'count'):
w.count=w.count+1
else:
w.count=1
print 'itemf_cb():', arg, w, w.count
class TestWindow(GtkWindow):
def __init__(self):
GtkWindow.__init__(self)
self.set_title('TestWindow')
self.connect('delete_event', self.quit)
box=GtkVBox()
self.add(box)
# BUG: GtkItemFactory.create_items() has no (at least not obvious) way to
Py_DECREF the callback.
# This one keeps TestWindow.__del__ from being called
cb=self.itemf_cb
# This one puts the problem somewhere else.
#cb=itemf_cb
self.itemf = GtkItemFactory(GtkMenuBar.get_type(), "main", None)
self.itemf.create_items([
('/_File', None, None, 0, 'Branch'),
('/_File/_New', 'controlN', cb, 0, ''),
('/_File/sep1', None, None, 0, 'Separator'),
('/_File/E_xit','controlX',cb, 0, ''),
('/_Help', None, None, 0, 'LastBranch'),
('/_Help/_About', 'controlA', cb, 0, '')
])
self.menubar = self.itemf.get_widget('main')
self.menubar.show()
hb=GtkHandleBox()
hb.show()
box.pack_start(hb, expand=FALSE)
hb.add(self.menubar)
lab=GtkLabel('Hello')
lab.set_text('Hello')
lab.show()
box.pack_start_defaults(lab)
but=SuperButton('Push 1')
box.add(but)
but.connect('clicked', self.pushed, ([1,2,3],'ok'))
but.n=1
but=GtkButton('Push 2')
box.pack_start(but,0,0)
but.connect('clicked', self.pushed )
but.n=2
but=GtkToggleButton('Toggle')
but.connect('toggled', self.toggled)
box.pack_start(but,0,0)
but=GtkButton('Quit')
box.add(but)
but.connect('clicked', self.quit)
self.show_all()
def quit(self,*args):
print 'quit:', args
self.hide()
self.destroy()
main_quit()
def pushed(self,b, *args):
print 'pushed:', b.get('GtkButton::label'), b, b.n, args, sys.getrefcount(b),
sys.getrefcount(self)
if hasattr(b,'msg'):
print 'msg:',b.msg
b.n=b.n+1
def toggled(self,b, *args):
print 'toggled:', b, args
def itemf_cb(self,arg,w):
if hasattr(w,'count'):
w.count=w.count+1
else:
w.count=1
print 'TestWindow.itemf_cb():', self, arg, w, w.count
def __del__(self):
print 'TestWindow.__del__()'
w=TestWindow()
w.show_all()
mainloop()
print 'There are %d bogus references left for TestWindow instance' %
(sys.getrefcount(w)-2)