pyGTK -- how to wait for modal dialog?

Mitch Chapman chapman at bioreason.com
Thu Oct 12 12:31:56 EDT 2000


Steffen Ries wrote:
> ...
> I came up with a similar solution, but I can't say whether *that* one
> is recommended:
> [...sample code omitted...]

Your solution is similar to the one recommended in Havoc 
Pennington's "Gtk+/GNOME Application Development", so it must
be good :)
See section 7.2, pp. 129-131, for the related discussion.

Havoc notes that there's a potential for race conditions.
I assume most of these arise from the fact that you can close
a dialog by clicking on one of the dialog buttons, and also by
using the window manager to close the window.

Havoc's book is available online.  Here's the relevant URL:
	http://developer.gnome.org/doc/GGAD/sec-modaldialogs.html

Your solution is also similar to the one in use at Bioreason,
as discussed in (self-serving plug) the April, 2000, issue of 
Dr. Dobb's.  Sample code is available here:
	http://www.ddj.com/ftp/2000/2000_04/pygtk.zip/

(Sample code is also attached, so why am I telling you this? =8)

--
Mitch Chapman
chapman at bioreason.com
-------------- next part --------------
#!/usr/bin/env python
"""ModalDialog.py:
This module provides pygtk ModalDialogs."""
import gtk

class ModalDialog(gtk.GtkDialog):
    """This class extends GtkDialog to give it modal behavior."""
    def __init__(self, master=None):
        """Initialize a new instance."""
        gtk.GtkDialog.__init__(self)
        self.master = master
        self.set_modal(gtk.TRUE)
        if self.master:
            self.set_transient_for(self.master)
            
        # Capture attempts to delete/destroy self.  It's hard to reuse
        # a dialog when Gtk+ has destroyed its components.
        self.connect("delete_event", self.deleteEH)
        
    def runModal(self):
        """Display the dialog and start a modal event loop."""
        self.show()
        # Invoke a nested Gtk+ event loop.
        gtk.mainloop()

    def endModal(self, *args):
        """Terminate the modal event loop and dismiss the dialog."""
        self.hide()
        gtk.mainquit()

    def deleteEH(self, *args):
        """Event handler invoked when the dialog is deleted."""
        self.endModal()
        # The return value tells Gtk+ that the delete event has
        # been processed.  Without a return value of true, Gtk+
        # will provide the default deletion behavior:  it will destroy
        # self's visuals.
        return gtk.TRUE
    

def main():
    """Module mainline (for standalone execution)"""
    class Test:
        """Tests the behavior of class ModalDialog."""
        def __init__(self):
            import AppWindow
            
            win = self.window = AppWindow.AppWindow(title="ModalDialog Demo")
            win.show()

            box = gtk.GtkVBox()
            win.add(box)
            box.show()
            
            btn = gtk.GtkButton("Go Modal...")
            btn.connect("clicked", self.goModalCB)
            box.pack_start(btn, expand=gtk.FALSE, fill=gtk.FALSE)
            btn.show()

            btn = gtk.GtkButton("Quit")
            btn.connect("clicked", gtk.mainquit)
            box.pack_start(btn, expand=gtk.FALSE, fill=gtk.FALSE)
            btn.show()

            self.dlg = self.buildDialog()

        def buildDialog(self):
            """Build a sample modal dialog."""
            result = ModalDialog(master=self.window)
            result.set_position(gtk.WIN_POS_MOUSE)
            result.set_title("The Spanish Inquisition")
            
            # Add some content.
            # A GtkDialog provides two pre-built containers:
            # vbox is where all of the "custom" controls, e.g.
            # entry fields and comboboxes, belong.
            # action_area appears at the bottom of the dialog, and
            # is a good place for the dialog buttons.
            label = gtk.GtkLabel("NOOoobody expects\n\n"
                                 "the Spanish Inquisition!")
            result.vbox.pack_start(label, padding=5)
            label.show()
            
            closeBtn = gtk.GtkButton("Close")
            closeBtn.connect("clicked", result.endModal)
            result.action_area.pack_start(closeBtn)
            closeBtn.show()
            return result
        
        def goModalCB(self, *args):
            """Callback invoked when the 'Go Modal...' button is clicked."""
            self.dlg.runModal()
            
    test = Test()
    gtk.mainloop()

    
if __name__ == "__main__":
    main()


More information about the Python-list mailing list