### Navigation

- index
- next |
- previous |
- Model-View-Controller and Observer patterns for PyGTK 1.99.1 documentation »

# A simple application

This section describes the process of creation of a sample application, from the design with Glade, to the integration of views and code inside the MVC-O Infrastructure.

We want to design and implement a simple application constituted by only one window, containing two string labels. One label shows a text, while the other shows the number of characters displayed (i.e. the length of the string) by the first one. There is also a button the user can press. By pressing the button, the user can change the displayed text, and of course this action might change also the displayed text length accordingly. Figure The sample Application gives an idea on how the application should appear.

The sample Application

## Glade

Figure Designing the example by means of Glade for GTK2 shows Glade and a project named `example`. The sample GUI has only one top-level window (named `window1`).

Designing the example by means of Glade for GTK2

The Widget Tree Window shows the widgets hierarchy. There are essentially the three main components (one button and two labels), grouped inside a set of containers, which supplies alignments and resizing capabilities.

On the right side of Figure Designing the example by means of Glade for GTK2, the Properties Window shows that the widget named `button1` has signal `clicked` associated with function `on_button1_clicked`. This means that the Controller will have to supply this function in order to handle the `click` event occurring in `button1`.

## Implementation

The implementation is slightly elaborate for this example, because the goal here is to show how the sample application can be implemented by using the MVC-O Infrastructure.

A basic knowledge of any Object Oriented programming language is sufficient to understand how this example has been pushed inside the MVC-O framework. On the contrary, a fair knowledge of the Python language is required in order to understand the code details.

More description section is Details of implementation.

### Model

Class `ExampleModel` is as simple as class `ExampleView`. As for `ExampleView`, it extends a base class of the MVC-O Infrastructure, class `Model`. The state is represented by a set of possible messages, as well as by the current message index. The current message index is also an observable property. A couple of methods are supplied in order to access the state.

    # file model.py
    from gtkmvc import Model

    class ExampleModel (Model):
       """The model contains a set of messages
       and an observable property that represent the current message
       index"""

       # Observable property: code for that is automatically generated
       # by metaclass constructor. The controller will be the observer
       # for this property
       message_index = -1   # -1 is the initial value
       __observables__ = ("message_index",)

       def __init__(self):
           Model.__init__(self)

           self.messages= ("I am patient with stupidity",
                           "but not with those",
                           "who are proud of it.",
                           "(Edith Sitwell)",
                           )
           return

       def get_message(self, index): return self.messages[index]

       def set_next_message(self):
           # this changes the observable property:
           self.message_index = (self.message_index + 1) % len(self.messages)
           return

       pass # end of class

Notice that class instance members are declared to be observable through the special class variable `__observables__`, which is a list of names (string) of the properties that are observable.

The base class Model belongs to a meta-class which automatically searches for observable properties and generates the needed code to handle the notification. When the value of variable `message_index` changes, all registered observers will be notified.

### View

In the example, the View is implemented inside the class `ExampleView` shown below.

    # file view.py
    import os.path
    from gtkmvc import View

    GLADE_PATH = "./"

    class ExampleView (View):
       """The application view. Contains only the main window1 tree."""
       builder = os.path.join(GLADE_PATH, "example.glade")
       top = "window1"

       def set_msg(self, msg):
          self['label_text'].set_text(msg)
          self['label_text_len'].set_text(str(len(msg)))
          return

       pass # end of class

Class `ExampleView` extends the generic `View` class, which performs most of the job, as described above. Class members `builder` and `top` are used instead of calling `View` constructor directly.

### Controller

Class `ExampleController` contains the GUI logic of the application. The controller handles two signals and the observable property notification. Signals are the `destroy` event, invoked when the application quits, and the `on_button1_clicked`, fired when `button1` is pressed.

    # file ctrl.py
    from gtk import main_quit
    from gtkmvc import Controller

    class ExampleController(Controller):
       """The only one controller. Handles the button clicked signal, and
       notifications about one observable property."""

       def register_view(self, view):
           # Connects the exiting signal:
           view.get_top_widget().connect("destroy", main_quit)
           return

       # Signal
       def on_button1_clicked(self, button):
           """Handles the signal clicked for button1. Changes the model."""
           self.model.set_next_message()
           return

       # Observables notifications
       @Controller.observe("message_index", assign=True)
       def value_change(self, model, name, info):
           """The model is changed and the view must be updated"""
           msg = self.model.get_message(info.new)

           self.view.set_msg(msg)
           return

       pass # end of class

The `destroy` signal is connected when the View registers itself inside the controller, by using the method override of `register_view`. Method `on_button1_clicked` calls a method inside the model which changes a part of the state inside the model. Since that part of the state is an observable property, the associated observer (which is the controller itself) is notified of the modification, by calling method `value_change`. This method updates the view connected to the controller.

### The Launcher (main)

The `main()` code creates a (m,v,c) triple and launches `gtk.main()`. All the rest is cosmetics.

    import gtk

    from model import ExampleModel
    from ctrl import ExampleController
    from view import ExampleView
    import gtkmvc

    def check_requirements():
       gtkmvc.require("1.99.1")
       return

    def setup_env(development_state=False):
       # This is how developers should set gtkmvc logging level (by
       # default debugging info is not shown):
       if development_state:
           import logging
           logging.getLogger("gtkmvc").setLevel(logging.DEBUG)
           pass
       return

    def main():
       m = ExampleModel()
       v = ExampleView()
       c = ExampleController(m, v)

       gtk.main()
       return

    if __name__ == "__main__":
       check_requirements()
       setup_env(development_state=True)
       main()
       pass

### Navigation

- index
- next |
- previous |
- Model-View-Controller and Observer patterns for PyGTK 1.99.1 documentation »