2.9.7 Models

The kiwi.model module Model classes. As discussed before, the Model class provides a mechanism for updating the user interface based on changed performed in the model instance.

This is a powerful mechanism that allows you to guarantee that the interface is always up-to-date with relation to an instance; it should be used with care, however, because the update semantics are not trivial to understand - just imagine having custom callbacks that alter the same attribute as the proxy callback and you will understand why it is easy to get in recursive loops. This tip I can offer you, therefore: avoid altering the model in custom callbacks, and only do it in special situations.

You can also attach multiple proxies to the same model and have them update automatically; the next section will discuss this further. Before passing on to that, however, I need to describe a special Model called PickledModel. To demonstrate by example, I will revisit the first example we saw in this text, the Person editor from section 2. Let's see the code again:


#!/usr/bin/env python
import gtk
from kiwi.model import PickledModel
from kiwi.ui.delegates import ProxyDelegate

# define the class that holds our application data
class Person(PickledModel):
    pass
person = Person.unpickle()

# create and run a proxy interface attached to person
view = ProxyDelegate(person, gladefile="Person",
                     widgets=["address", 'name', 'phone'],
                     delete_handler=gtk.main_quit)
view.focus_topmost()
view.show_and_loop()

# save changes done to the instance
person.save()

Looking at the code, you might notice three special issues:

  1. The class our model inherits from is FrameWork.PickledModel.
  2. We actually get our model instance by making a call to Person.unpickle(), passing the class Person as an argument.
  3. We call person.save() at the end of the program.

PickledModel offers a very cheap way to offer persistence for your model instances. If you are familiar with the ZODB, think of PickledModel as a cheapo implementation that allows you to save and restore an instance. To use it:

  1. Have your model class inherit from PickledModel.

  2. Use the PickledModel.unpickle which is a class method on your model. it takes a filename as the optional second parameter (if omitted, it uses the name of the class, with an extension of ".pickle"). The method will try and load the model state from a pickle file, and if it doesn't exist, will create a new model and return it to you. If the pickle file is damaged, it will save it with the extension ".err" (avoiding it being erased by an unwitting save() call).

  3. Use the save() method to save the pickle when you are ready. You may specify a filename to it; otherwise, it uses the default filename specified through the set_filename() method. Note that PickledModel.unpickle makes the filename it tried to used the default by calling set_filename() internally.

The diary3.py example in examples/diary/ uses pickling in a more involved manner and is recommended as a reference.