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',     '<control>N', cb, 0, ''),
            ('/_File/sep1',     None,   None, 0, '<Separator>'),
            ('/_File/E_xit',    '<control>X',    cb, 0, ''),

            ('/_Help',          None,         None, 0, '<LastBranch>'),
            ('/_Help/_About',   '<control>A', 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)

Reply via email to