1# This file is part of Gajim.
2#
3# Gajim is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published
5# by the Free Software Foundation; version 3 only.
6#
7# Gajim is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
14
15'''
16Global Events Dispatcher module.
17
18:author: Mateusz Biliński <mateusz@bilinski.it>
19:since: 8th August 2008
20:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
21:copyright: Copyright (2011) Yann Leboulanger <asterix@lagaule.org>
22:license: GPL
23'''
24
25import logging
26import traceback
27import inspect
28
29from nbxmpp import NodeProcessed
30
31log = logging.getLogger('gajim.c.ged')
32
33PRECORE = 10
34CORE = 20
35POSTCORE = 30
36PREGUI = 40
37PREGUI1 = 50
38GUI1 = 60
39POSTGUI1 = 70
40PREGUI2 = 80
41GUI2 = 90
42POSTGUI2 = 100
43POSTGUI = 110
44
45OUT_PREGUI = 10
46OUT_PREGUI1 = 20
47OUT_GUI1 = 30
48OUT_POSTGUI1 = 40
49OUT_PREGUI2 = 50
50OUT_GUI2 = 60
51OUT_POSTGUI2 = 70
52OUT_POSTGUI = 80
53OUT_PRECORE = 90
54OUT_CORE = 100
55OUT_POSTCORE = 110
56
57class GlobalEventsDispatcher:
58
59    def __init__(self):
60        self.handlers = {}
61
62    def register_event_handler(self, event_name, priority, handler):
63        if event_name in self.handlers:
64            handlers_list = self.handlers[event_name]
65            i = 0
66            for i, handler_tuple in enumerate(handlers_list):
67                if priority < handler_tuple[0]:
68                    break
69            else:
70                # no event with smaller prio found, put it at the end
71                i += 1
72
73            handlers_list.insert(i, (priority, handler))
74        else:
75            self.handlers[event_name] = [(priority, handler)]
76
77    def remove_event_handler(self, event_name, priority, handler):
78        if event_name in self.handlers:
79            try:
80                self.handlers[event_name].remove((priority, handler))
81            except ValueError as error:
82                log.warning(
83                    '''Function (%s) with priority "%s" never
84                    registered as handler of event "%s". Couldn\'t remove.
85                    Error: %s''', handler, priority, event_name, error)
86
87    def raise_event(self, event_name, *args, **kwargs):
88        log.debug('Raise event: %s', event_name)
89        if event_name in self.handlers:
90            node_processed = False
91            # Iterate over a copy of the handlers list, so while iterating
92            # the original handlers list can be modified
93            for _priority, handler in list(self.handlers[event_name]):
94                try:
95                    if inspect.ismethod(handler):
96                        log.debug('Call handler %s on %s',
97                                  handler.__name__,
98                                  handler.__self__)
99                    else:
100                        log.debug('Call handler %s', handler.__name__)
101                    if handler(*args, **kwargs):
102                        return True
103                except NodeProcessed:
104                    node_processed = True
105                except Exception:
106                    log.error('Error while running an event handler: %s',
107                              handler)
108                    traceback.print_exc()
109            if node_processed:
110                raise NodeProcessed
111