| |   |
| 1 | #! /usr/bin/env python |
| 2 | # -*- coding: iso-8859-1 -*- |
| 3 | # |
| 4 | # Copyright (C) 2008 by Rodrigo Lazo |
| 5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify |
| 7 | # it under the terms of the GNU General Public License as published by |
| 8 | # the Free Software Foundation; either version 2 of the License, or |
| 9 | # (at your option) any later version. |
| 10 | # |
| 11 | # This program is distributed in the hope that it will be useful, |
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | # GNU General Public License for more details. |
| 15 | # |
| 16 | # You should have received a copy of the GNU General Public License |
| 17 | # along with this program; if not, write to the Free Software |
| 18 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | |
| 20 | """ |
| 21 | GoogleMail Sentinel. |
| 22 | |
| 23 | Yet another GoogleMail Notifier. Checks your GoogleMail's inbox |
| 24 | periodically for new mail using feeds(atom). This program creates an |
| 25 | icon in the task bar when running and notifies about new mail through |
| 26 | popups. |
| 27 | """ |
| 28 | |
| 29 | |
| 30 | import pygtk |
| 31 | pygtk.require('2.0') |
| 32 | import time |
| 33 | import gtk |
| 34 | import gobject |
| 35 | import pynotify |
| 36 | import locale, gettext |
| 37 | import sys |
| 38 | import os |
| 39 | from os.path import dirname, pardir |
| 40 | from gettext import gettext as _ |
| 41 | from ConfigParser import ConfigParser |
| 42 | from gmailatom import GmailAtom |
| 43 | |
| 44 | APP_NAME = "Gmail-Sentinel" |
| 45 | APP_VERSION = "0.1" |
| 46 | APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail and Gmail are trademarks of Google, Inc.") |
| 47 | APP_DESCRIPTION = _('GoogleMail Sentinel') |
| 48 | APP_WEBSITE = 'http://code.google.com/p/gmail-sentinel/' |
| 49 | |
| 50 | # Path definition |
| 51 | SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share')) |
| 52 | LOCALE_PATH = os.path.join(SHARE_PATH, 'locale') |
| 53 | |
| 54 | # L10n initialization |
| 55 | locale.setlocale(locale.LC_ALL, '') |
| 56 | gettext.textdomain('gmail-sentinel') |
| 57 | gettext.bindtextdomain('gmail-sentinel', LOCALE_PATH) |
| 58 | |
| 59 | class GmailNotification: |
| 60 | """ Notification pop-up. """ |
| 61 | |
| 62 | def __init__ (self, data, count, timeout, icon_file): |
| 63 | self.data = data |
| 64 | body = "<i>%s: </i>%s\n<i>%s: </i>%s\n%s" % (_("From"), |
| 65 | self.data['sender'], |
| 66 | _("Subject"), |
| 67 | self.data['subject'], |
| 68 | self.data["snippet"]) |
| 69 | self.popup = pynotify.Notification(_("You have %d new messages")%count, |
| 70 | body) |
| 71 | self.popup.set_icon_from_pixbuf(gtk.gdk.pixbuf_new_from_file(icon_file)) |
| 72 | self.popup.set_timeout(timeout) |
| 73 | |
| 74 | def attach_to_status_icon (self, status_icon): |
| 75 | """ Make the popup appear from the WIDGET""" |
| 76 | self.popup.attach_to_status_icon(status_icon) |
| 77 | |
| 78 | def show (self): |
| 79 | """ Displays the notification""" |
| 80 | self.popup.show() |
| 81 | |
| 82 | |
| 83 | class GmailStatusIcon(gtk.StatusIcon): |
| 84 | """Status Icon for the system tray.""" |
| 85 | |
| 86 | def __init__(self, media_path): |
| 87 | gtk.StatusIcon.__init__(self) |
| 88 | self.current_icon_path = media_path |
| 89 | self.active_icon = os.path.join(self.current_icon_path, |
| 90 | 'active.png') |
| 91 | self.inactive_icon = os.path.join(self.current_icon_path, |
| 92 | 'inactive.png') |
| 93 | self.gmail_icon = os.path.join(self.current_icon_path, |
| 94 | 'gmail-icon.png') |
| 95 | menu = ''' |
| 96 | <ui> |
| 97 | <menubar name="Menubar"> |
| 98 | <menu action="Menu"> |
| 99 | <menuitem action="About"/> |
| 100 | <menuitem action="Quit"/> |
| 101 | </menu> |
| 102 | </menubar> |
| 103 | </ui> |
| 104 | ''' |
| 105 | actions = [ |
| 106 | ('Menu', None, _('Menu')), |
| 107 | ('About', gtk.STOCK_ABOUT, _('_About...'), |
| 108 | None, _('About'), self.on_about), |
| 109 | ('Quit', gtk.STOCK_QUIT, _('_Quit'), |
| 110 | None,_('Quit'), self.on_quit), |
| 111 | ] |
| 112 | ag = gtk.ActionGroup('Actions') |
| 113 | ag.add_actions(actions) |
| 114 | self.manager = gtk.UIManager() |
| 115 | self.manager.insert_action_group(ag, 0) |
| 116 | self.manager.add_ui_from_string(menu) |
| 117 | self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent |
| 118 | self.set_from_file(self.inactive_icon) |
| 119 | self.set_visible(True) |
| 120 | self.connect('popup-menu', self.on_popup_menu) |
| 121 | |
| 122 | def on_quit(self, *args): |
| 123 | """Kills the application. Callback function.""" |
| 124 | sys.exit() |
| 125 | |
| 126 | def on_popup_menu(self, status, button, timing): |
| 127 | """Displays the popup menu.""" |
| 128 | self.menu.popup(None, None, None, button, timing) |
| 129 | |
| 130 | def on_about(self, data): |
| 131 | """Displays the about window""" |
| 132 | dialog = gtk.AboutDialog() |
| 133 | dialog.set_name(APP_NAME) |
| 134 | dialog.set_version(APP_VERSION) |
| 135 | dialog.set_copyright(APP_COPYRIGHT) |
| 136 | dialog.set_comments(APP_DESCRIPTION) |
| 137 | dialog.set_website(APP_WEBSITE) |
| 138 | dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon)) |
| 139 | dialog.run() |
| 140 | dialog.destroy() |
| 141 | |
| 142 | def set_from_file(self, path): |
| 143 | """Helper function to handle media path.""" |
| 144 | if path != self.current_icon_path: |
| 145 | self.current_icon_path = path |
| 146 | gtk.StatusIcon.set_from_file(self, path) |
| 147 | |
| 148 | class Gnotify: |
| 149 | """Main class.""" |
| 150 | |
| 151 | def __init__ (self): |
| 152 | """Initializer. Creates the status icon and opens the |
| 153 | connection.""" |
| 154 | self.config = ConfigParser() |
| 155 | self.connection = None |
| 156 | self.unread_msg_count = 0 |
| 157 | |
| 158 | if not self.load_configuration(): |
| 159 | print "Configuration file does not exist." |
| 160 | sys.exit(1) |
| 161 | |
| 162 | self.status_icon = GmailStatusIcon(self.config.get('media', 'path')) |
| 163 | # Make sure the status icon shows up |
| 164 | while gtk.events_pending(): |
| 165 | gtk.main_iteration(True) |
| 166 | if self.connect() : |
| 167 | self.check_inbox() |
| 168 | # The multiplier is to simplify the configuration |
| 169 | # file. Converts the miliseconds into seconds |
| 170 | interval = int(self.config.get('gmail', 'checkinterval'))*1000 |
| 171 | self.main_timer = gobject.timeout_add(interval, self.check_inbox) |
| 172 | |
| 173 | def load_configuration (self): |
| 174 | """Loads the configuration. If file does not exist returns |
| 175 | false, if the configuration file is bad formatted it will die |
| 176 | loudly.""" |
| 177 | filename = os.path.expanduser("~/.gmail-sentinel.conf") |
| 178 | if not os.path.exists(filename): |
| 179 | return False |
| 180 | |
| 181 | self.config.read([filename]) |
| 182 | return True |
| 183 | |
| 184 | def connect (self): |
| 185 | """Creates a connection. The connection itself do the |
| 186 | parsing.""" |
| 187 | if self.connection is None: |
| 188 | try: |
| 189 | print "connecting..." |
| 190 | self.status_icon.set_tooltip(_("Connecting...")) |
| 191 | self.connection = GmailAtom(self.config.get('gmail','username'), |
| 192 | self.config.get('gmail','password')) |
| 193 | except: |
| 194 | print "login failed, will retry" |
| 195 | self.status_icon.set_tooltip(_("Connection failed")) |
| 196 | return False |
| 197 | self.connection.refreshInfo() |
| 198 | print "connection successful... continuing" |
| 199 | self.status_icon.set_tooltip(_("Connected")) |
| 200 | return True |
| 201 | |
| 202 | def check_inbox(self): |
| 203 | """Checks for new mail.""" |
| 204 | # Revisar si esta el pop up y eliminarlo |
| 205 | if self.connection is None and self.connect() is False: |
| 206 | # Try again latter |
| 207 | return True |
| 208 | print "----------" |
| 209 | print "checking for new mail ("+time.strftime("%Y/%m/%d %H:%M:%S", |
| 210 | time.localtime())+")" |
| 211 | while gtk.events_pending(): |
| 212 | gtk.main_iteration( True ) |
| 213 | |
| 214 | if not self.has_new_mail(): |
| 215 | # Check again later |
| 216 | self.unread_msg_count > 0 or \ |
| 217 | self.status_icon.set_from_file(self.status_icon.inactive_icon) |
| 218 | return True |
| 219 | self.status_icon.set_from_file(self.status_icon.active_icon) |
| 220 | count = self.connection.getUnreadMsgCount() |
| 221 | last_message = self.get_last_message() |
| 222 | print "%s new messages" % count |
| 223 | # The multiplier is to simplify the configuration |
| 224 | # file. Converts the miliseconds into seconds |
| 225 | timeout = int(self.config.get('options', 'popuptime'))*1000 |
| 226 | popup = GmailNotification(last_message, count, timeout, |
| 227 | self.status_icon.active_icon) |
| 228 | popup.attach_to_status_icon(self.status_icon) |
| 229 | popup.show() |
| 230 | return True |
| 231 | |
| 232 | def has_new_mail (self): |
| 233 | """Checks if new mail has arrived.""" |
| 234 | try: |
| 235 | # Hackerish? |
| 236 | self.connection.refreshInfo() |
| 237 | current_msg_count = self.connection.getUnreadMsgCount() |
| 238 | new_mail = current_msg_count > 0 and \ |
| 239 | current_msg_count != self.unread_msg_count |
| 240 | self.unread_msg_count = current_msg_count |
| 241 | return new_mail |
| 242 | except: |
| 243 | print "getUnreadMsgCount() failed, will try again soon" |
| 244 | self.unread_msg_count = 0 |
| 245 | return False |
| 246 | |
| 247 | def get_last_message (self): |
| 248 | """ Returns the sender, subject and snippet of the last |
| 249 | message retrieved.""" |
| 250 | return {'sender' : self.connection.getMsgAuthorName(0), |
| 251 | 'subject' : self.connection.getMsgTitle(0), |
| 252 | 'snippet' : self.connection.getMsgSummary(0)[:40] + "..."} |
| 253 | |
| 254 | def main (self): |
| 255 | """ Mailoop""" |
| 256 | gtk.main() |
| 257 | |
| 258 | if __name__ == "__main__": |
| 259 | pynotify.init(APP_NAME) |
| 260 | notifier = Gnotify() |
| 261 | notifier.main() |
| toggle raw diff |
--- /dev/null
+++ b/gmail-sentinel.py
@@ -0,0 +1,261 @@
+#! /usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+#
+# Copyright (C) 2008 by Rodrigo Lazo
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+GoogleMail Sentinel.
+
+Yet another GoogleMail Notifier. Checks your GoogleMail's inbox
+periodically for new mail using feeds(atom). This program creates an
+icon in the task bar when running and notifies about new mail through
+popups.
+"""
+
+
+import pygtk
+pygtk.require('2.0')
+import time
+import gtk
+import gobject
+import pynotify
+import locale, gettext
+import sys
+import os
+from os.path import dirname, pardir
+from gettext import gettext as _
+from ConfigParser import ConfigParser
+from gmailatom import GmailAtom
+
+APP_NAME = "Gmail-Sentinel"
+APP_VERSION = "0.1"
+APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail and Gmail are trademarks of Google, Inc.")
+APP_DESCRIPTION = _('GoogleMail Sentinel')
+APP_WEBSITE = 'http://code.google.com/p/gmail-sentinel/'
+
+# Path definition
+SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share'))
+LOCALE_PATH = os.path.join(SHARE_PATH, 'locale')
+
+# L10n initialization
+locale.setlocale(locale.LC_ALL, '')
+gettext.textdomain('gmail-sentinel')
+gettext.bindtextdomain('gmail-sentinel', LOCALE_PATH)
+
+class GmailNotification:
+ """ Notification pop-up. """
+
+ def __init__ (self, data, count, timeout, icon_file):
+ self.data = data
+ body = "<i>%s: </i>%s\n<i>%s: </i>%s\n%s" % (_("From"),
+ self.data['sender'],
+ _("Subject"),
+ self.data['subject'],
+ self.data["snippet"])
+ self.popup = pynotify.Notification(_("You have %d new messages")%count,
+ body)
+ self.popup.set_icon_from_pixbuf(gtk.gdk.pixbuf_new_from_file(icon_file))
+ self.popup.set_timeout(timeout)
+
+ def attach_to_status_icon (self, status_icon):
+ """ Make the popup appear from the WIDGET"""
+ self.popup.attach_to_status_icon(status_icon)
+
+ def show (self):
+ """ Displays the notification"""
+ self.popup.show()
+
+
+class GmailStatusIcon(gtk.StatusIcon):
+ """Status Icon for the system tray."""
+
+ def __init__(self, media_path):
+ gtk.StatusIcon.__init__(self)
+ self.current_icon_path = media_path
+ self.active_icon = os.path.join(self.current_icon_path,
+ 'active.png')
+ self.inactive_icon = os.path.join(self.current_icon_path,
+ 'inactive.png')
+ self.gmail_icon = os.path.join(self.current_icon_path,
+ 'gmail-icon.png')
+ menu = '''
+ <ui>
+ <menubar name="Menubar">
+ <menu action="Menu">
+ <menuitem action="About"/>
+ <menuitem action="Quit"/>
+ </menu>
+ </menubar>
+ </ui>
+ '''
+ actions = [
+ ('Menu', None, _('Menu')),
+ ('About', gtk.STOCK_ABOUT, _('_About...'),
+ None, _('About'), self.on_about),
+ ('Quit', gtk.STOCK_QUIT, _('_Quit'),
+ None,_('Quit'), self.on_quit),
+ ]
+ ag = gtk.ActionGroup('Actions')
+ ag.add_actions(actions)
+ self.manager = gtk.UIManager()
+ self.manager.insert_action_group(ag, 0)
+ self.manager.add_ui_from_string(menu)
+ self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent
+ self.set_from_file(self.inactive_icon)
+ self.set_visible(True)
+ self.connect('popup-menu', self.on_popup_menu)
+
+ def on_quit(self, *args):
+ """Kills the application. Callback function."""
+ sys.exit()
+
+ def on_popup_menu(self, status, button, timing):
+ """Displays the popup menu."""
+ self.menu.popup(None, None, None, button, timing)
+
+ def on_about(self, data):
+ """Displays the about window"""
+ dialog = gtk.AboutDialog()
+ dialog.set_name(APP_NAME)
+ dialog.set_version(APP_VERSION)
+ dialog.set_copyright(APP_COPYRIGHT)
+ dialog.set_comments(APP_DESCRIPTION)
+ dialog.set_website(APP_WEBSITE)
+ dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon))
+ dialog.run()
+ dialog.destroy()
+
+ def set_from_file(self, path):
+ """Helper function to handle media path."""
+ if path != self.current_icon_path:
+ self.current_icon_path = path
+ gtk.StatusIcon.set_from_file(self, path)
+
+class Gnotify:
+ """Main class."""
+
+ def __init__ (self):
+ """Initializer. Creates the status icon and opens the
+ connection."""
+ self.config = ConfigParser()
+ self.connection = None
+ self.unread_msg_count = 0
+
+ if not self.load_configuration():
+ print "Configuration file does not exist."
+ sys.exit(1)
+
+ self.status_icon = GmailStatusIcon(self.config.get('media', 'path'))
+ # Make sure the status icon shows up
+ while gtk.events_pending():
+ gtk.main_iteration(True)
+ if self.connect() :
+ self.check_inbox()
+ # The multiplier is to simplify the configuration
+ # file. Converts the miliseconds into seconds
+ interval = int(self.config.get('gmail', 'checkinterval'))*1000
+ self.main_timer = gobject.timeout_add(interval, self.check_inbox)
+
+ def load_configuration (self):
+ """Loads the configuration. If file does not exist returns
+ false, if the configuration file is bad formatted it will die
+ loudly."""
+ filename = os.path.expanduser("~/.gmail-sentinel.conf")
+ if not os.path.exists(filename):
+ return False
+
+ self.config.read([filename])
+ return True
+
+ def connect (self):
+ """Creates a connection. The connection itself do the
+ parsing."""
+ if self.connection is None:
+ try:
+ print "connecting..."
+ self.status_icon.set_tooltip(_("Connecting..."))
+ self.connection = GmailAtom(self.config.get('gmail','username'),
+ self.config.get('gmail','password'))
+ except:
+ print "login failed, will retry"
+ self.status_icon.set_tooltip(_("Connection failed"))
+ return False
+ self.connection.refreshInfo()
+ print "connection successful... continuing"
+ self.status_icon.set_tooltip(_("Connected"))
+ return True
+
+ def check_inbox(self):
+ """Checks for new mail."""
+ # Revisar si esta el pop up y eliminarlo
+ if self.connection is None and self.connect() is False:
+ # Try again latter
+ return True
+ print "----------"
+ print "checking for new mail ("+time.strftime("%Y/%m/%d %H:%M:%S",
+ time.localtime())+")"
+ while gtk.events_pending():
+ gtk.main_iteration( True )
+
+ if not self.has_new_mail():
+ # Check again later
+ self.unread_msg_count > 0 or \
+ self.status_icon.set_from_file(self.status_icon.inactive_icon)
+ return True
+ self.status_icon.set_from_file(self.status_icon.active_icon)
+ count = self.connection.getUnreadMsgCount()
+ last_message = self.get_last_message()
+ print "%s new messages" % count
+ # The multiplier is to simplify the configuration
+ # file. Converts the miliseconds into seconds
+ timeout = int(self.config.get('options', 'popuptime'))*1000
+ popup = GmailNotification(last_message, count, timeout,
+ self.status_icon.active_icon)
+ popup.attach_to_status_icon(self.status_icon)
+ popup.show()
+ return True
+
+ def has_new_mail (self):
+ """Checks if new mail has arrived."""
+ try:
+ # Hackerish?
+ self.connection.refreshInfo()
+ current_msg_count = self.connection.getUnreadMsgCount()
+ new_mail = current_msg_count > 0 and \
+ current_msg_count != self.unread_msg_count
+ self.unread_msg_count = current_msg_count
+ return new_mail
+ except:
+ print "getUnreadMsgCount() failed, will try again soon"
+ self.unread_msg_count = 0
+ return False
+
+ def get_last_message (self):
+ """ Returns the sender, subject and snippet of the last
+ message retrieved."""
+ return {'sender' : self.connection.getMsgAuthorName(0),
+ 'subject' : self.connection.getMsgTitle(0),
+ 'snippet' : self.connection.getMsgSummary(0)[:40] + "..."}
+
+ def main (self):
+ """ Mailoop"""
+ gtk.main()
+
+if __name__ == "__main__":
+ pynotify.init(APP_NAME)
+ notifier = Gnotify()
+ notifier.main() |
| |   |
| 0 | | #! /usr/bin/env python |
| 1 | | # -*- coding: iso-8859-1 -*- |
| 2 | | # |
| 3 | | # Copyright (C) 2008 by Rodrigo Lazo |
| 4 | | # |
| 5 | | # This program is free software; you can redistribute it and/or modify |
| 6 | | # it under the terms of the GNU General Public License as published by |
| 7 | | # the Free Software Foundation; either version 2 of the License, or |
| 8 | | # (at your option) any later version. |
| 9 | | # |
| 10 | | # This program is distributed in the hope that it will be useful, |
| 11 | | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | | # GNU General Public License for more details. |
| 14 | | # |
| 15 | | # You should have received a copy of the GNU General Public License |
| 16 | | # along with this program; if not, write to the Free Software |
| 17 | | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | | |
| 19 | | """ |
| 20 | | GoogleMail Sentinel. |
| 21 | | |
| 22 | | Yet another GoogleMail Notifier. Checks your GoogleMail's inbox |
| 23 | | periodically for new mail using feeds(atom). This program creates an |
| 24 | | icon in the task bar when running and notifies about new mail through |
| 25 | | popups. |
| 26 | | """ |
| 27 | | |
| 28 | | |
| 29 | | import pygtk |
| 30 | | pygtk.require('2.0') |
| 31 | | import time |
| 32 | | import gtk |
| 33 | | import gobject |
| 34 | | import pynotify |
| 35 | | import locale, gettext |
| 36 | | import sys |
| 37 | | import os |
| 38 | | from os.path import dirname, pardir |
| 39 | | from gettext import gettext as _ |
| 40 | | from ConfigParser import ConfigParser |
| 41 | | from gmailatom import GmailAtom |
| 42 | | |
| 43 | | APP_NAME = "GSentinel" |
| 44 | | APP_VERSION = "0.1" |
| 45 | | APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail is a trademark of Google, Inc.") |
| 46 | | APP_DESCRIPTION = _('GoogleMail Sentinel') |
| 47 | | APP_WEBSITE = 'http://rlazo.supersized.org/gnotify.html/' |
| 48 | | |
| 49 | | # Path definition |
| 50 | | SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share')) |
| 51 | | LOCALE_PATH = os.path.join(SHARE_PATH, 'locale') |
| 52 | | |
| 53 | | # L10n initialization |
| 54 | | locale.setlocale(locale.LC_ALL, '') |
| 55 | | gettext.textdomain('gsentinel') |
| 56 | | gettext.bindtextdomain('gsentinel', LOCALE_PATH) |
| 57 | | |
| 58 | | class GmailNotification: |
| 59 | | """ Notification pop-up. """ |
| 60 | | |
| 61 | | def __init__ (self, data, count, timeout, icon_file): |
| 62 | | self.data = data |
| 63 | | body = "<i>%s: </i>%s\n<i>%s: </i>%s\n%s" % (_("From"), |
| 64 | | self.data['sender'], |
| 65 | | _("Subject"), |
| 66 | | self.data['subject'], |
| 67 | | self.data["snippet"]) |
| 68 | | self.popup = pynotify.Notification(_("You have %d new messages")%count, |
| 69 | | body) |
| 70 | | self.popup.set_icon_from_pixbuf(gtk.gdk.pixbuf_new_from_file(icon_file)) |
| 71 | | self.popup.set_timeout(timeout) |
| 72 | | |
| 73 | | def attach_to_status_icon (self, status_icon): |
| 74 | | """ Make the popup appear from the WIDGET""" |
| 75 | | self.popup.attach_to_status_icon(status_icon) |
| 76 | | |
| 77 | | def show (self): |
| 78 | | """ Displays the notification""" |
| 79 | | self.popup.show() |
| 80 | | |
| 81 | | |
| 82 | | class GmailStatusIcon(gtk.StatusIcon): |
| 83 | | """Status Icon for the system tray.""" |
| 84 | | |
| 85 | | def __init__(self, media_path): |
| 86 | | gtk.StatusIcon.__init__(self) |
| 87 | | self.current_icon_path = media_path |
| 88 | | self.active_icon = os.path.join(self.current_icon_path, |
| 89 | | 'active.png') |
| 90 | | self.inactive_icon = os.path.join(self.current_icon_path, |
| 91 | | 'inactive.png') |
| 92 | | self.gmail_icon = os.path.join(self.current_icon_path, |
| 93 | | 'gmail-icon.png') |
| 94 | | menu = ''' |
| 95 | | <ui> |
| 96 | | <menubar name="Menubar"> |
| 97 | | <menu action="Menu"> |
| 98 | | <menuitem action="About"/> |
| 99 | | <menuitem action="Quit"/> |
| 100 | | </menu> |
| 101 | | </menubar> |
| 102 | | </ui> |
| 103 | | ''' |
| 104 | | actions = [ |
| 105 | | ('Menu', None, _('Menu')), |
| 106 | | ('About', gtk.STOCK_ABOUT, _('_About...'), |
| 107 | | None, _('About'), self.on_about), |
| 108 | | ('Quit', gtk.STOCK_QUIT, _('_Quit'), |
| 109 | | None,_('Quit'), self.on_quit), |
| 110 | | ] |
| 111 | | ag = gtk.ActionGroup('Actions') |
| 112 | | ag.add_actions(actions) |
| 113 | | self.manager = gtk.UIManager() |
| 114 | | self.manager.insert_action_group(ag, 0) |
| 115 | | self.manager.add_ui_from_string(menu) |
| 116 | | self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent |
| 117 | | self.set_from_file(self.inactive_icon) |
| 118 | | self.set_visible(True) |
| 119 | | self.connect('popup-menu', self.on_popup_menu) |
| 120 | | |
| 121 | | def on_quit(self, *args): |
| 122 | | """Kills the application. Callback function.""" |
| 123 | | sys.exit() |
| 124 | | |
| 125 | | def on_popup_menu(self, status, button, timing): |
| 126 | | """Displays the popup menu.""" |
| 127 | | self.menu.popup(None, None, None, button, timing) |
| 128 | | |
| 129 | | def on_about(self, data): |
| 130 | | """Displays the about window""" |
| 131 | | dialog = gtk.AboutDialog() |
| 132 | | dialog.set_name(APP_NAME) |
| 133 | | dialog.set_version(APP_VERSION) |
| 134 | | dialog.set_copyright(APP_COPYRIGHT) |
| 135 | | dialog.set_comments(APP_DESCRIPTION) |
| 136 | | dialog.set_website(APP_WEBSITE) |
| 137 | | dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon)) |
| 138 | | dialog.run() |
| 139 | | dialog.destroy() |
| 140 | | |
| 141 | | def set_from_file(self, path): |
| 142 | | """Helper function to handle media path.""" |
| 143 | | if path != self.current_icon_path: |
| 144 | | self.current_icon_path = path |
| 145 | | gtk.StatusIcon.set_from_file(self, path) |
| 146 | | |
| 147 | | class Gnotify: |
| 148 | | """Main class.""" |
| 149 | | |
| 150 | | def __init__ (self): |
| 151 | | """Initializer. Creates the status icon and opens the |
| 152 | | connection.""" |
| 153 | | self.config = ConfigParser() |
| 154 | | self.connection = None |
| 155 | | self.unread_msg_count = 0 |
| 156 | | |
| 157 | | if not self.load_configuration(): |
| 158 | | print "Configuration file does not exist." |
| 159 | | sys.exit(1) |
| 160 | | |
| 161 | | self.status_icon = GmailStatusIcon(self.config.get('media', 'path')) |
| 162 | | # Make sure the status icon shows up |
| 163 | | while gtk.events_pending(): |
| 164 | | gtk.main_iteration(True) |
| 165 | | if self.connect() : |
| 166 | | self.check_inbox() |
| 167 | | # The multiplier is to simplify the configuration |
| 168 | | # file. Converts the miliseconds into seconds |
| 169 | | interval = int(self.config.get('gmail', 'checkinterval'))*1000 |
| 170 | | self.main_timer = gobject.timeout_add(interval, self.check_inbox) |
| 171 | | |
| 172 | | def load_configuration (self): |
| 173 | | """Loads the configuration. If file does not exist returns |
| 174 | | false, if the configuration file is bad formatted it will die |
| 175 | | loudly.""" |
| 176 | | filename = os.path.expanduser("~/.gsentinel.conf") |
| 177 | | if not os.path.exists(filename): |
| 178 | | return False |
| 179 | | |
| 180 | | self.config.read([filename]) |
| 181 | | return True |
| 182 | | |
| 183 | | def connect (self): |
| 184 | | """Creates a connection. The connection itself do the |
| 185 | | parsing.""" |
| 186 | | if self.connection is None: |
| 187 | | try: |
| 188 | | print "connecting..." |
| 189 | | self.status_icon.set_tooltip(_("Connecting...")) |
| 190 | | self.connection = GmailAtom(self.config.get('gmail','username'), |
| 191 | | self.config.get('gmail','password')) |
| 192 | | except: |
| 193 | | print "login failed, will retry" |
| 194 | | self.status_icon.set_tooltip(_("Connection failed")) |
| 195 | | return False |
| 196 | | self.connection.refreshInfo() |
| 197 | | print "connection successful... continuing" |
| 198 | | self.status_icon.set_tooltip(_("Connected")) |
| 199 | | return True |
| 200 | | |
| 201 | | def check_inbox(self): |
| 202 | | """Checks for new mail.""" |
| 203 | | # Revisar si esta el pop up y eliminarlo |
| 204 | | if self.connection is None and self.connect() is False: |
| 205 | | # Try again latter |
| 206 | | return True |
| 207 | | print "----------" |
| 208 | | print "checking for new mail ("+time.strftime("%Y/%m/%d %H:%M:%S", |
| 209 | | time.localtime())+")" |
| 210 | | while gtk.events_pending(): |
| 211 | | gtk.main_iteration( True ) |
| 212 | | |
| 213 | | if not self.has_new_mail(): |
| 214 | | # Check again later |
| 215 | | self.unread_msg_count > 0 or \ |
| 216 | | self.status_icon.set_from_file(self.status_icon.inactive_icon) |
| 217 | | return True |
| 218 | | self.status_icon.set_from_file(self.status_icon.active_icon) |
| 219 | | count = self.connection.getUnreadMsgCount() |
| 220 | | last_message = self.get_last_message() |
| 221 | | print "%s new messages" % count |
| 222 | | # The multiplier is to simplify the configuration |
| 223 | | # file. Converts the miliseconds into seconds |
| 224 | | timeout = int(self.config.get('options', 'popuptime'))*1000 |
| 225 | | popup = GmailNotification(last_message, count, timeout, |
| 226 | | self.status_icon.active_icon) |
| 227 | | popup.attach_to_status_icon(self.status_icon) |
| 228 | | popup.show() |
| 229 | | return True |
| 230 | | |
| 231 | | def has_new_mail (self): |
| 232 | | """Checks if new mail has arrived.""" |
| 233 | | try: |
| 234 | | # Hackerish? |
| 235 | | self.connection.refreshInfo() |
| 236 | | current_msg_count = self.connection.getUnreadMsgCount() |
| 237 | | new_mail = current_msg_count > 0 and \ |
| 238 | | current_msg_count != self.unread_msg_count |
| 239 | | self.unread_msg_count = current_msg_count |
| 240 | | return new_mail |
| 241 | | except: |
| 242 | | print "getUnreadMsgCount() failed, will try again soon" |
| 243 | | self.unread_msg_count = 0 |
| 244 | | return False |
| 245 | | |
| 246 | | def get_last_message (self): |
| 247 | | """ Returns the sender, subject and snippet of the last |
| 248 | | message retrieved.""" |
| 249 | | return {'sender' : self.connection.getMsgAuthorName(0), |
| 250 | | 'subject' : self.connection.getMsgTitle(0), |
| 251 | | 'snippet' : self.connection.getMsgSummary(0)[:40] + "..."} |
| 252 | | |
| 253 | | def main (self): |
| 254 | | """ Mailoop""" |
| 255 | | gtk.main() |
| 256 | | |
| 257 | | if __name__ == "__main__": |
| 258 | | pynotify.init(APP_NAME) |
| 259 | | notifier = Gnotify() |
| 260 | | notifier.main() |
| toggle raw diff |
--- a/gsentinel.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#! /usr/bin/env python
-# -*- coding: iso-8859-1 -*-
-#
-# Copyright (C) 2008 by Rodrigo Lazo
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-GoogleMail Sentinel.
-
-Yet another GoogleMail Notifier. Checks your GoogleMail's inbox
-periodically for new mail using feeds(atom). This program creates an
-icon in the task bar when running and notifies about new mail through
-popups.
-"""
-
-
-import pygtk
-pygtk.require('2.0')
-import time
-import gtk
-import gobject
-import pynotify
-import locale, gettext
-import sys
-import os
-from os.path import dirname, pardir
-from gettext import gettext as _
-from ConfigParser import ConfigParser
-from gmailatom import GmailAtom
-
-APP_NAME = "GSentinel"
-APP_VERSION = "0.1"
-APP_COPYRIGHT = "(C)2008 Rodrigo Lazo.\n" + _("GoogleMail is a trademark of Google, Inc.")
-APP_DESCRIPTION = _('GoogleMail Sentinel')
-APP_WEBSITE = 'http://rlazo.supersized.org/gnotify.html/'
-
-# Path definition
-SHARE_PATH = os.path.abspath(os.path.join(dirname(__file__), pardir, pardir, 'share'))
-LOCALE_PATH = os.path.join(SHARE_PATH, 'locale')
-
-# L10n initialization
-locale.setlocale(locale.LC_ALL, '')
-gettext.textdomain('gsentinel')
-gettext.bindtextdomain('gsentinel', LOCALE_PATH)
-
-class GmailNotification:
- """ Notification pop-up. """
-
- def __init__ (self, data, count, timeout, icon_file):
- self.data = data
- body = "<i>%s: </i>%s\n<i>%s: </i>%s\n%s" % (_("From"),
- self.data['sender'],
- _("Subject"),
- self.data['subject'],
- self.data["snippet"])
- self.popup = pynotify.Notification(_("You have %d new messages")%count,
- body)
- self.popup.set_icon_from_pixbuf(gtk.gdk.pixbuf_new_from_file(icon_file))
- self.popup.set_timeout(timeout)
-
- def attach_to_status_icon (self, status_icon):
- """ Make the popup appear from the WIDGET"""
- self.popup.attach_to_status_icon(status_icon)
-
- def show (self):
- """ Displays the notification"""
- self.popup.show()
-
-
-class GmailStatusIcon(gtk.StatusIcon):
- """Status Icon for the system tray."""
-
- def __init__(self, media_path):
- gtk.StatusIcon.__init__(self)
- self.current_icon_path = media_path
- self.active_icon = os.path.join(self.current_icon_path,
- 'active.png')
- self.inactive_icon = os.path.join(self.current_icon_path,
- 'inactive.png')
- self.gmail_icon = os.path.join(self.current_icon_path,
- 'gmail-icon.png')
- menu = '''
- <ui>
- <menubar name="Menubar">
- <menu action="Menu">
- <menuitem action="About"/>
- <menuitem action="Quit"/>
- </menu>
- </menubar>
- </ui>
- '''
- actions = [
- ('Menu', None, _('Menu')),
- ('About', gtk.STOCK_ABOUT, _('_About...'),
- None, _('About'), self.on_about),
- ('Quit', gtk.STOCK_QUIT, _('_Quit'),
- None,_('Quit'), self.on_quit),
- ]
- ag = gtk.ActionGroup('Actions')
- ag.add_actions(actions)
- self.manager = gtk.UIManager()
- self.manager.insert_action_group(ag, 0)
- self.manager.add_ui_from_string(menu)
- self.menu = self.manager.get_widget('/Menubar/Menu/About').props.parent
- self.set_from_file(self.inactive_icon)
- self.set_visible(True)
- self.connect('popup-menu', self.on_popup_menu)
-
- def on_quit(self, *args):
- """Kills the application. Callback function."""
- sys.exit()
-
- def on_popup_menu(self, status, button, timing):
- """Displays the popup menu."""
- self.menu.popup(None, None, None, button, timing)
-
- def on_about(self, data):
- """Displays the about window"""
- dialog = gtk.AboutDialog()
- dialog.set_name(APP_NAME)
- dialog.set_version(APP_VERSION)
- dialog.set_copyright(APP_COPYRIGHT)
- dialog.set_comments(APP_DESCRIPTION)
- dialog.set_website(APP_WEBSITE)
- dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.gmail_icon))
- dialog.run()
- dialog.destroy()
-
- def set_from_file(self, path):
- """Helper function to handle media path."""
- if path != self.current_icon_path:
- self.current_icon_path = path
- gtk.StatusIcon.set_from_file(self, path)
-
-class Gnotify:
- """Main class."""
-
- def __init__ (self):
- """Initializer. Creates the status icon and opens the
- connection."""
- self.config = ConfigParser()
- self.connection = None
- self.unread_msg_count = 0
-
- if not self.load_configuration():
- print "Configuration file does not exist."
- sys.exit(1)
-
- self.status_icon = GmailStatusIcon(self.config.get('media', 'path'))
- # Make sure the status icon shows up
- while gtk.events_pending():
- gtk.main_iteration(True)
- if self.connect() :
- self.check_inbox()
- # The multiplier is to simplify the configuration
- # file. Converts the miliseconds into seconds
- interval = int(self.config.get('gmail', 'checkinterval'))*1000
- self.main_timer = gobject.timeout_add(interval, self.check_inbox)
-
- def load_configuration (self):
- """Loads the configuration. If file does not exist returns
- false, if the configuration file is bad formatted it will die
- loudly."""
- filename = os.path.expanduser("~/.gsentinel.conf")
- if not os.path.exists(filename):
- return False
-
- self.config.read([filename])
- return True
-
- def connect (self):
- """Creates a connection. The connection itself do the
- parsing."""
- if self.connection is None:
- try:
- print "connecting..."
- self.status_icon.set_tooltip(_("Connecting..."))
- self.connection = GmailAtom(self.config.get('gmail','username'),
- self.config.get('gmail','password'))
- except:
- print "login failed, will retry"
- self.status_icon.set_tooltip(_("Connection failed"))
- return False
- self.connection.refreshInfo()
- print "connection successful... continuing"
- self.status_icon.set_tooltip(_("Connected"))
- return True
-
- def check_inbox(self):
- """Checks for new mail."""
- # Revisar si esta el pop up y eliminarlo
- if self.connection is None and self.connect() is False:
- # Try again latter
- return True
- print "----------"
- print "checking for new mail ("+time.strftime("%Y/%m/%d %H:%M:%S",
- time.localtime())+&q |