qobserver: Handle editable combo boxes in 'SLOT()'
[git-cola.git] / cola / observable.py
bloba87ecb186d7048fd81f33f058d2fd460a438d520
1 # Copyright (c) 2008 David Aguilar
2 """This module provides the Observable class"""
4 import types
6 class Observable(object):
7 """Handles subject/observer notifications."""
8 def __init__(self):
9 self.observers = set()
10 self.message_observers = {}
11 self.notification_enabled = True
12 self.register_messages()
14 def register_messages(self, messages=None):
15 """
16 Automatically register all class-scope message names.
18 There are two rules at play here:
20 1. Message names must be defined at class scope. e.g.:
22 class ObservableFoo(Observable):
23 message_foo = 'foo'
25 2. Message name variables must begin with the string 'message_'
27 Providing a 'messages' dict avoids this built-in behavior but
28 does not guarantee that the messages names are registered for
29 clones or unserialized objects.
31 """
32 if messages:
33 self.message_observers.update(messages)
34 else:
35 for k, v in self.__class__.__dict__.iteritems():
36 if k.startswith('message_') and type(v) in types.StringTypes:
37 self.message_observers[v] = set()
39 def add_observer(self, observer):
40 """Adds an observer to this model"""
41 self.observers.add(observer)
43 def add_message_observer(self, message, observer):
44 """Add an observer for a specific message."""
45 observers = self.message_observers.setdefault(message, set())
46 observers.add(observer)
48 def remove_observer(self, observer):
49 """Removes an observer"""
50 if observer in self.observers:
51 self.observers.remove(observer)
52 for message, observers in self.message_observers.items():
53 if observer in observers:
54 observers.remove(observer)
56 def notify_observers(self, *param):
57 """Notifies observers about attribute changes"""
58 if not self.notification_enabled:
59 return
60 for observer in self.observers:
61 observer.notify(*param)
63 def notify_message_observers(self, message, *args, **opts):
64 """Pythonic signals and slots."""
65 if not self.notification_enabled:
66 return
67 if message not in self.message_observers:
68 raise ValueError('%s is not a valid message name.' % message)
69 observers = self.message_observers[message]
70 for method in observers:
71 method(*args, **opts)