Ejemplo n.º 1
0
 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))
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
 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))