wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

monitor.py (3924B)


      1 from threading import Lock, Timer
      2 
      3 from pygmi import client
      4 from pygmi.fs import *
      5 
      6 __all__ = 'monitors', 'defmonitor', 'Monitor'
      7 
      8 monitors = {}
      9 
     10 def defmonitor(*args, **kwargs):
     11     """
     12     Defines a new monitor to appear in wmii's bar based on
     13     the wrapped function. Creates a new Monitor object,
     14     initialized with *args and **kwargs. The wrapped function
     15     is assigned to the 'action' keyword argument for the
     16     Monitor, its name is assigned to the 'name' argument.
     17 
     18     The new monitor is added to the 'monitors' dict in this
     19     module.
     20     """
     21     def monitor(fn):
     22         kwargs['action'] = fn
     23         if not args and 'name' not in kwargs:
     24             kwargs['name'] = fn.__name__
     25         monitor = Monitor(*args, **kwargs)
     26         monitors[monitor.name] = monitor
     27         return monitor
     28     if args and callable(args[0]):
     29         fn = args[0]
     30         args = args[1:]
     31         return monitor(fn)
     32     return monitor
     33 
     34 class Monitor(object):
     35     """
     36     A class to manage status monitors for wmii's bar. The bar item
     37     is updated on a fixed interval based on the values returned
     38     by the 'action' method.
     39 
     40     Property active: When true, the monitor is updated at regular
     41              intervals. When false, monitor is hidden.
     42     Property name: The name of the monitor, which acts as the name
     43            of the bar in wmii's filesystem.
     44     Property interval: The update interval, in seconds.
     45     Property side: The side of the bar on which to place the monitor.
     46     Property action: A function of no arguments which returns the
     47             value of the monitor. Called at each update interval.
     48             May return a string, a tuple of (Color, string), or None
     49             to hide the monitor for one iteration.
     50     """
     51     side = 'right'
     52     interval = 1.0
     53 
     54     define = classmethod(defmonitor)
     55 
     56     def __init__(self, name=None, interval=None, side=None,
     57                  action=None, colors=None, label=None):
     58         """
     59         Initializes the new monitor. For parameter values, see the
     60         corresponding property values in the class's docstring.
     61 
     62         Param colors: The initial colors for the monitor.
     63         Param label:  The initial label for the monitor.
     64         """
     65         if side:
     66             self.side = side
     67         if name:
     68             self.name = name
     69         if interval:
     70             self.interval = interval
     71         if action:
     72             self.action = action
     73 
     74         self.lock = Lock()
     75         self.timer = None
     76         self.button = Button(self.side, self.name, colors, label)
     77         self.tick()
     78 
     79     def tick(self):
     80         """
     81         Called internally at the interval defined by #interval.
     82         Calls #action and updates the monitor based on the result.
     83         """
     84         if self.timer and monitors.get(self.name, None) is not self:
     85             return
     86         if self.active:
     87             label = self.getlabel()
     88             if isinstance(label, basestring):
     89                 label = None, label
     90             with self.lock:
     91                 if self.active:
     92                     if label is None:
     93                         self.button.remove()
     94                     else:
     95                         self.button.create(*label)
     96 
     97                     self.timer = Timer(self.interval, self.tick)
     98                     self.timer.name = 'Monitor-Timer-%s' % self.name
     99                     self.timer.daemon = True
    100                     self.timer.start()
    101 
    102     def getlabel(self):
    103         """
    104         Calls #action and returns the result, ignoring any
    105         exceptions.
    106         """
    107         try:
    108             return self.action(self)
    109         except Exception:
    110             return None
    111 
    112     _active = True
    113     @property
    114     def active(self):
    115         return self._active
    116 
    117     @active.setter
    118     def active(self, val):
    119         with self.lock:
    120             self._active = bool(val)
    121         if val:
    122             self.tick()
    123         else:
    124             self.button.remove()
    125 
    126 # vim:se sts=4 sw=4 et: