As we saw before, it is possible to compose the interface for your application using multiple views; this holds true whether the view has an associated controller or not. I'm not going to provide an example embedding views and controllers because it's not very enlightening; it is easy to extend the original UI Composition example to use controller associated to the views, and that example is much more interesting if adapted to a ObjectList.
Since delegates inherit from views, it is also possible to compose a delegate with multiple child delegates (and even mix and match them with views). The requirement that the parent delegate be based on glade is the same, too: you should subclass GladeDelegate for your main window, though any kind of view can be attached to it.
The nice part about doing UI composition using delegates is that the interface and interaction is well encapsulated in a single class, and if you are careful when writing a child delegate, you can reuse that class in as many places of your applications as you like. I'm going to use the ObjectList from the last example to build a (rather fake) news browsing application in the next example:
#!/usr/bin/env python import os import gtk from kiwi.ui import gadgets from kiwi.ui.delegates import Delegate, SlaveDelegate from kiwi.ui.objectlist import ObjectList, Column class NewsItem: def __init__(self, title, author, url): self.title, self.author, self.url = title, author, url # Friendly Pigdog.org news news = [ NewsItem("Smallpox Vaccinations for EVERYONE", "JRoyale", "http://www.pigdog.org/auto/Power_Corrupts/link/2700.html"), NewsItem("Is that uranium in your pocket or are you just happy to see me?", "Baron Earl", "http://www.pigdog.org/auto/bad_people/link/2699.html"), NewsItem("Cut 'n Paste", "Baron Earl", "http://www.pigdog.org/auto/ArtFux/link/2690.html"), NewsItem("A Slippery Exit", "Reverend CyberSatan", "http://www.pigdog.org/auto/TheCorporateFuck/link/2683.html"), NewsItem("Those Crazy Dutch Have Resurrected Elvis", "Miss Conduct", "http://www.pigdog.org/auto/viva_la_musica/link/2678.html") ] my_columns = [Column("title", sorted=True, tooltip="Title of article", width=50), Column("author", tooltip="Author of article"), Column("url", title="Address", visible=False, tooltip="Address of article")] class Shell(Delegate): widgets = ["ok", "cancel", "header", "footer", "title"] def __init__(self): Delegate.__init__(self, gladefile="news_shell", delete_handler=self.quit_if_last) # paint header and footer; they are eventboxes that hold a # label and buttonbox respectively gadgets.set_background(self.header, "white") gadgets.set_background(self.footer, "#A0A0A0") gadgets.set_foreground(self.title, "blue") # Create the delegate and set it up objectlist = ObjectList(my_columns, news) objectlist.connect('selection-changed', self.news_selected) objectlist.connect('double-click', self.double_click) slave = SlaveDelegate(toplevel=objectlist) self.attach_slave("placeholder", slave) slave.focus_toplevel() # Must be done after attach self.slave = slave def news_selected(self, the_list, item): objectlist = self.slave.get_toplevel() print "%s %s %s\n" % (item.title, item.author, item.url) def double_click(self, the_list, selected_object): self.emit('result', selected_object.url) self.hide_and_quit() def on_ok__clicked(self, *args): objectlist = self.slave.get_toplevel() item = objectlist.get_selected() if item: self.emit('result', item.url) self.hide_and_quit() def on_cancel__clicked(self, *args): self.hide_and_quit() url = None shell = Shell() shell.show_all() def get_url(view, result): global url url = result shell.connect('result', get_url) gtk.main() if url is not None: # Try to run BROWSER (or lynx) on the URL returned browser = os.environ.get("BROWSER", "lynx") os.system("%s %s" % (browser, url))
Let's have a quick look at the code:
row_selected()
for the select_row
signal, which will be
called when a row is selected.
retval
and
use it as input to run a browser for the selected news item (okay, so
the app is not really a browser, I lied).
This example shows a lot of the power of Kiwi; in a few lines, and with a little work in Glade, we have a working application that looks decent, behaves well and isn't hard to maintain. The next section will go on describing Proxies, which are high-level Views that represent an instance or part of it.