import gtk import gobject import imaplib import math from datetime import datetime, timedelta class Window(object): def __init__(self, title, conf): self.conf = conf self.count = 0 self.connection = None self.fgcolor = ''.join(map(lambda x: '%02x' % int(0xFF * x), self.conf['fgcolor'])) self.font_sz = int(1024 * self.conf['font_size']) if not 'width' in self.conf: self.conf['width'] = 32 if not 'height' in self.conf: self.conf['height'] = 32 if not 'mailbox' in self.conf: self.conf['mailbox'] = 'Inbox' if not 'updaterate' in self.conf: self.conf['updaterate'] = 5000 if not 'fgcolor' in self.conf: self.conf['fgcolor'] = (0.0, 0.0, 0.0) if not 'bgcolor' in self.conf: self.conf['bgcolor'] = (1.0, 0.5, 0.0) if not 'bgcolor2' in self.conf: self.conf['bgcolor2'] = (1.0, 1.0, 1.0) if not 'flash_rate' in self.conf: self.conf['flash_rate'] = 3000 if not 'font_size' in self.conf: self.conf['font_size'] = 18 sticky = True if 'sticky' in self.conf: sticky = self.conf['sticky'] self.window = gtk.Window() self.window.set_title(title) self.window.set_decorated(False) if sticky: self.window.stick() self.window.connect('destroy', self.destroy_event) self.label = gtk.Label('-') self.viewport = gtk.Viewport() self.viewport.set_shadow_type(gtk.SHADOW_OUT) self.viewport.add(self.label) self.viewport.connect('button-release-event', self.button_release) self.viewport.set_events(gtk.gdk.BUTTON_RELEASE_MASK) self.viewport.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(*map(lambda x: int(65535 * x), self.conf['bgcolor']))) self.window.add(self.viewport) self.connect() self.window.show_all() if 'x' in self.conf and 'y' in self.conf: self.window.move(self.conf['x'], self.conf['y']) self.window.resize(self.conf['width'], self.conf['height']) def run(self): gtk.main() def connect(self): try: self.connection = imaplib.IMAP4_SSL( self.conf['server'], self.conf['port']) self.connection.login(self.conf['user'], self.conf['password']) self.update() gobject.timeout_add(self.conf['updaterate'], self.update) except: self.connection = None def disconnect(self): if self.connection is not None: self.connection = None def update_conf(self): w, h = self.window.get_size() self.conf['width'] = w self.conf['height'] = h x, y = self.window.get_position() self.conf['x'] = x self.conf['y'] = y def update(self): if self.connection is not None: try: self.connection.select(self.conf['mailbox']) msgs = self.connection.search(None, 'UnSeen')[1][0].split() old_count = self.count self.count = len(msgs) if (self.conf['flash_rate'] > 0 and old_count == 0 and self.count > 0): self.flash_start_dt = datetime.now() gobject.timeout_add(100, self.do_flash) except: self.connection = None self.update_count() return self.connection is not None def update_count(self): if self.connection is None: self.label.set_text('-') else: self.label.set_markup( ('%d' % (self.fgcolor, self.font_sz, self.count))) def do_flash(self): if self.count > 0: delta = datetime.now() - self.flash_start_dt delta_msec = delta.seconds * 1000 + delta.microseconds / 1000 period = delta_msec / float(self.conf['flash_rate']) mix = (math.sin(math.pi * 2 * period) + 1.0) / 2.0 else: mix = 0 linear_combination = lambda (x, y): x + (y - x) * mix bg1 = self.conf['bgcolor'] bg2 = self.conf['bgcolor2'] flash_bgcolor = map(linear_combination, zip(bg1, bg2)) self.viewport.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(*map(lambda x: int(65535 * x), flash_bgcolor))) return self.count > 0 def destroy_event(self): self.disconnect() self.update_conf() gtk.main_quit() return False def button_release(self, widget, event): if event.button == 3: self.destroy_event() return True