""" MVP.py Module that provides a Model-View-Presenter framework for use with Straw """ __copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc." __license__ = """ Straw is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Straw is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ import pygtk pygtk.require('2.0') from gtk import glade import Event __doc__ = "A MVP framework. Contains base classes for views and presenters." class View(object): """Base class for widget-based view objects.""" def __init__(self, widget, model = None, presenter = None): self._widget = widget self._model = model self._presenter = presenter if model is not None: self._model_set() if presenter is not None: self._presenter_set() self._initialize() self._connect_signals(widget) def _connect_signals(self, widget): raise NotImplemented def _initialize(self): """Called from the constructor after the instance variables have been set and the corresponding initialization functions have been called, but before connecting gtk signals.""" pass def _model_set(self): """Called when the model is set.""" pass def _presenter_set(self): """Called when the presenter is set.""" pass def get_model(self): return self._model def set_model(self, model): self._model = model if model: # don't call model_set if model is None. This prevents objects # relying on model_set to fail (or gtk throwing a warning when # model is not a gtk.TreeModel). self._model_set() model = property(get_model, set_model, None, doc="The model object.") def get_presenter(self): return self._presenter def set_presenter(self, presenter): self._presenter = presenter self._presenter_set() presenter = property(get_presenter, set_presenter, None, "The presenter object.") class WidgetView(View): def __init__(self, widget, model=None, presenter=None): View.__init__(self, widget, model, presenter) def _connect_signals(self, widget): xml = glade.get_widget_tree(widget) nameFuncMap = {} for key in dir(self.__class__): if key[:4] == '_on_': nameFuncMap[key[1:]] = getattr(self, key) xml.signal_autoconnect(nameFuncMap) class GladeView(View): def __init__(self, widget, model=None, presenter=None): View.__init__(self, widget, model, presenter) def _connect_signals(self, widget): nameFuncMap = {} for key in dir(self.__class__): if key[:4] == '_on_': nameFuncMap[key[1:]] = getattr(self, key) widget.signal_autoconnect(nameFuncMap) class BasicPresenter(object, Event.SignalEmitter): """Base class for basic (non-composite) presenters.""" def __init__(self, model = None, view = None): Event.SignalEmitter.__init__(self) self._model = model self._view = view if model is not None: self._model_set() if view is not None: view.model = model view.presenter = self self._view_set() self._initialize() def _initialize(self): pass def _model_set(self): pass def _view_set(self): pass def get_view(self): return self._view def set_view(self, view): self._view = view view.presenter = self view.model = self._model self._view_set() view = property(get_view, set_view, None, """The view component. Setting this als sets the view object's presenter and model attributes.""") def get_model(self): return self._model def set_model(self, model): self._model = model if self._view is not None: self._view.model = model self._model_set() model = property(get_model, set_model, None, """The model component. Setting this also sets the view object's (if defined) model attribute.""")