def doit(cancels=cancels, reaction=reaction, args=dictadd(template_info, info), eventinfo=eventinfo): cancellable = reaction(**eventinfo)(**args) if hasattr(cancellable, 'cancel'): cancels.put(ref(cancellable))
def fire(topic, **info): ''' Presents a simple interface for firing notification events. >> fire('error', title = 'Connection Error', msg = 'A connection could not be established') topic one or more of the topic keys listed in src/gui/notificationview.py, i.e., "message.received.initial" info special keyword arguments giving information about the event. Each notification topic expects different arguments, and some "Reactions" (i.e., Popup windows) also look for options here. Extra arguments are passed to "Reactions" the user has set up to trigger for specific topics. Topics use dotted notation to indicate a hierarchy. If "message.received.initial" is fired and there is a sound effect set to trigger for "message.received", it will play. Only one type of each "Reaction" is allowed to fire for each event, so if a sound effect is set for "message" as well, it will not play. ''' assert '_' not in topic, 'underscores not allowed in topic names' # topic can be a string, or a list of strings. if isinstance(topic, basestring): topic = [topic] else: assert isinstance(topic, list) # todo: iterable # fire the longest topic strings first, since they will be deepest in the tree. topics = sorted(set(chain(*(_topics_from_string(t) for t in topic))), reverse=True) log.debug('fired topics %r', topics) types = set() cancels = cancellables() fired = False try: notifications = get_user_notifications() except AttributeError: return log.warning('no notifications yet') # If this topic is in a set of topics to always fire, mark # 'always_show' as True in the info dict. (See below) always_show = info.get('always_show', []) always_show = set(always_show) if always_show is not None else set() for topic in topics: always_show.update(always_fire.get(topic, [])) if 'buddy' in info: # First, try buddy specific events. try: idstr = info['buddy'].idstr() buddy_events = notifications.get(idstr, []) except: buddy_events = [] log.debug('found %d buddy specific events', len(buddy_events)) if buddy_events: fired = True firetopics(topics, buddy_events, types=types, cancels=cancels, **info) # Then fire "generic" events set for all buddies. generic_events = notifications.get(None, []) if generic_events: fired = True firetopics(topics, generic_events, types=types, cancels=cancels, **info) if always_show: # Optionally, "mandatory" reaction types can be specified. # If we haven't fired them yet, do so. import gui.notificationview as nview # map reaction names -> reaction classes G = globals() reactions = set(G[name] for name in always_show) # TODO: this block should be factored out and replaced by another call to firetopics ninfo = nview.get_notification_info() didFireType = set() for topic in topics: for reaction in reactions - types: if reaction in didFireType: continue args = dictadd(ninfo.get(topic, {}), info) def doit(cancels=cancels, reaction=reaction, args=args): cancellable = reaction()(**args) if hasattr(cancellable, 'cancel'): cancels.put(ref(cancellable)) didFireType.add(reaction) wx.CallAfter(doit) fired = True # Call "on_done" if specified. try: on_done = info['on_done'] except KeyError: pass else: if not fired: log.info('Calling on_done callback') with traceguard: on_done() # return a delegate lowercased typenames of all event types that were triggered return cancels
def fire(topic, **info): ''' Presents a simple interface for firing notification events. >> fire('error', title = 'Connection Error', msg = 'A connection could not be established') topic one or more of the topic keys listed in src/gui/notificationview.py, i.e., "message.received.initial" info special keyword arguments giving information about the event. Each notification topic expects different arguments, and some "Reactions" (i.e., Popup windows) also look for options here. Extra arguments are passed to "Reactions" the user has set up to trigger for specific topics. Topics use dotted notation to indicate a hierarchy. If "message.received.initial" is fired and there is a sound effect set to trigger for "message.received", it will play. Only one type of each "Reaction" is allowed to fire for each event, so if a sound effect is set for "message" as well, it will not play. ''' assert '_' not in topic, 'underscores not allowed in topic names' # topic can be a string, or a list of strings. if isinstance(topic, basestring): topic = [topic] else: assert isinstance(topic, list) # todo: iterable # fire the longest topic strings first, since they will be deepest in the tree. topics = sorted(set(chain(*(_topics_from_string(t) for t in topic))), reverse=True) log.debug('fired topics %r', topics) types = set() cancels = cancellables() fired = False try: notifications = get_user_notifications() except AttributeError: return log.warning('no notifications yet') # If this topic is in a set of topics to always fire, mark # 'always_show' as True in the info dict. (See below) always_show = info.get('always_show', []) always_show = set(always_show) if always_show is not None else set() for topic in topics: always_show.update(always_fire.get(topic, [])) if 'buddy' in info: # First, try buddy specific events. try: idstr = info['buddy'].idstr() buddy_events = notifications.get(idstr, []) except: buddy_events = [] log.debug('found %d buddy specific events', len(buddy_events)) if buddy_events: fired = True firetopics(topics, buddy_events, types = types, cancels = cancels, **info) # Then fire "generic" events set for all buddies. generic_events = notifications.get(None, []) if generic_events: fired = True firetopics(topics, generic_events, types = types, cancels = cancels, **info) if always_show: # Optionally, "mandatory" reaction types can be specified. # If we haven't fired them yet, do so. import gui.notificationview as nview # map reaction names -> reaction classes G = globals() reactions = set(G[name] for name in always_show) # TODO: this block should be factored out and replaced by another call to firetopics ninfo = nview.get_notification_info() didFireType = set() for topic in topics: for reaction in reactions - types: if reaction in didFireType: continue args = dictadd(ninfo.get(topic, {}), info) def doit(cancels=cancels, reaction=reaction, args=args): cancellable = reaction()(**args) if hasattr(cancellable, 'cancel'): cancels.put(ref(cancellable)) didFireType.add(reaction) wx.CallAfter(doit) fired = True # Call "on_done" if specified. try: on_done = info['on_done'] except KeyError: pass else: if not fired: log.info('Calling on_done callback') with traceguard: on_done() # return a delegate lowercased typenames of all event types that were triggered return cancels
def doit(cancels = cancels, reaction = reaction, args = dictadd(template_info, info), eventinfo = eventinfo): cancellable = reaction(**eventinfo)(**args) if hasattr(cancellable, 'cancel'): cancels.put(ref(cancellable))