# Source code for terminatorlib.plugins.activitywatch

    #!/usr/bin/python
    # Terminator by Chris Jones <cmsj@tenshu.net>
    # GPL v2 only
    """activitywatch.py - Terminator Plugin to watch a terminal for activity"""

    import time
    import gtk
    import gobject

    from terminatorlib.config import Config
    import terminatorlib.plugin as plugin
    from terminatorlib.translation import _
    from terminatorlib.util import err, dbg
    from terminatorlib.version import APP_NAME

    try:
        import pynotify
        # Every plugin you want Terminator to load *must* be listed in 'AVAILABLE'
        # This is inside this try so we only make the plugin available if pynotify
        #  is present on this computer.
        AVAILABLE = ['ActivityWatch', 'InactivityWatch']
    except ImportError:
        err(_('ActivityWatch plugin unavailable: please install python-notify'))

    config = Config()
    inactive_period = float(config.plugin_get('InactivityWatch', 'inactive_period',
                                            10.0))
    watch_interval = int(config.plugin_get('InactivityWatch', 'watch_interval',
                                           5000))
    hush_period = float(config.plugin_get('ActivityWatch', 'hush_period',
                                            10.0))

    class ActivityWatch(plugin.MenuItem):
        """Add custom commands to the terminal menu"""
        capabilities = ['terminal_menu']
        watches = None
        last_notifies = None
        timers = None

        def __init__(self):
            plugin.MenuItem.__init__(self)
            if not self.watches:
                self.watches = {}
            if not self.last_notifies:
                self.last_notifies = {}
            if not self.timers:
                self.timers = {}

            pynotify.init(APP_NAME.capitalize())

        def callback(self, menuitems, menu, terminal):
            """Add our menu item to the menu"""
            item = gtk.CheckMenuItem(_('Watch for _activity'))
            item.set_active(self.watches.has_key(terminal))
            if item.get_active():
                item.connect("activate", self.unwatch, terminal)
            else:
                item.connect("activate", self.watch, terminal)
            menuitems.append(item)
            dbg('Menu item appended')

        def watch(self, _widget, terminal):
            """Watch a terminal"""
            vte = terminal.get_vte()
            self.watches[terminal] = vte.connect('contents-changed',
                                                 self.notify, terminal)

        def unwatch(self, _widget, terminal):
            """Stop watching a terminal"""
            vte = terminal.get_vte()
            vte.disconnect(self.watches[terminal])
            del(self.watches[terminal])

        def notify(self, _vte, terminal):
            """Notify that a terminal did something"""
            show_notify = False

            # Don't notify if the user is already looking at this terminal.
            if terminal.vte.flags() & gtk.HAS_FOCUS:
                return True

            note = pynotify.Notification(_('Terminator'), _('Activity in: %s') %
                                      terminal.get_window_title(), 'terminator')

            this_time = time.mktime(time.gmtime())
            if not self.last_notifies.has_key(terminal):
                show_notify = True
            else:
                last_time = self.last_notifies[terminal]
                if this_time - last_time > hush_period:
                    show_notify = True

            if show_notify == True:
                note.show()
                self.last_notifies[terminal] = this_time

            return True

    class InactivityWatch(plugin.MenuItem):
        """Add custom commands to notify when a terminal goes inactive"""
        capabilities = ['terminal_menu']
        watches = None
        last_activities = None
        timers = None

        def __init__(self):
            plugin.MenuItem.__init__(self)
            if not self.watches:
                self.watches = {}
            if not self.last_activities:
                self.last_activities = {}
            if not self.timers:
                self.timers = {}

            pynotify.init(APP_NAME.capitalize())

        def callback(self, menuitems, menu, terminal):
            """Add our menu item to the menu"""
            item = gtk.CheckMenuItem(_("Watch for _silence"))
            item.set_active(self.watches.has_key(terminal))
            if item.get_active():
                item.connect("activate", self.unwatch, terminal)
            else:
                item.connect("activate", self.watch, terminal)
            menuitems.append(item)
            dbg('Menu items appended')

        def watch(self, _widget, terminal):
            """Watch a terminal"""
            vte = terminal.get_vte()
            self.watches[terminal] = vte.connect('contents-changed',
                                                 self.reset_timer, terminal)
            timeout_id = gobject.timeout_add(watch_interval, self.check_times, terminal)
            self.timers[terminal] = timeout_id
            dbg('timer %s added for %s' %(timeout_id, terminal))

        def unwatch(self, _vte, terminal):
            """Unwatch a terminal"""
            vte = terminal.get_vte()
            vte.disconnect(self.watches[terminal])
            del(self.watches[terminal])
            gobject.source_remove(self.timers[terminal])
            del(self.timers[terminal])

        def reset_timer(self, _vte, terminal):
            """Reset the last-changed time for a terminal"""
            time_now = time.mktime(time.gmtime())
            self.last_activities[terminal] = time_now
            dbg('reset activity time for %s' % terminal)

        def check_times(self, terminal):
            """Check if this terminal has gone silent"""
            time_now = time.mktime(time.gmtime())
            if not self.last_activities.has_key(terminal):
                dbg('Terminal %s has no last activity' % terminal)
                return True

            dbg('seconds since last activity: %f (%s)' % (time_now - self.last_activities[terminal], terminal))
            if time_now - self.last_activities[terminal] >= inactive_period:
                del(self.last_activities[terminal])
                note = pynotify.Notification(_('Terminator'), _('Silence in: %s') %
                                             terminal.get_window_title(), 'terminator')
                note.show()

            return True