def __init__(self): logger.info("Starting application.") upgrade_manager = UpgradeManager() upgrade_manager.check() # TODO: Disabled and switched from use of AsyncNotifier on # 2007-02-05. Possible problem with pynotify and threading, threading # was our decision to disable to get users up and running with a 0.0.6 # bugfix release. Re-enable once the issue is resolved. #gtk.gdk.threads_init() # Maintain a map of events that have alert windows open to ensure # we don't popup multiple windows for the same event that hasn't # been confirmed by the user: self.__open_alerts = {} self.config = WujaConfiguration(GCONF_PATH) self.notifier = None self.prefs_dialog = None self.calendar_window = None self.updating = False self.feed_update_event_source = None actions = ( ("calendar", gtk.STOCK_INDEX, "View Calendar", None, None, self.__open_calendar), ("preferences", gtk.STOCK_PREFERENCES, None, None, None, self.__open_preferences_dialog), ("update_feeds", gtk.STOCK_REFRESH, "Update Feeds", None, None, self.__update_feeds), ("debug_feeds", gtk.STOCK_EXECUTE, "Debug Feeds", None, None, self.__debug_feeds), ("about", gtk.STOCK_ABOUT, None, None, None, self.__open_about_dialog), ("quit", gtk.STOCK_QUIT, None, None, None, self.destroy)) action_group = gtk.ActionGroup("wuja_menu") action_group.add_actions(actions) ui_mgr = gtk.UIManager() ui_mgr.add_ui_from_file(find_file_on_path("wuja/data/wuja-menu.xml")) ui_mgr.insert_action_group(action_group, 0) self.menu = ui_mgr.get_widget("/wuja_menu") self.menu.show_all() self.tray_icon = trayicon.TrayIcon("wuja") self.tray_icon.connect('button_press_event', self.__clicked) tray_image = gtk.Image() tray_image.set_from_file( find_file_on_path("wuja/data/wuja-icon-24x24.png")) event_box = gtk.EventBox() event_box.add(tray_image) self.tray_icon.add(event_box) self.tray_icon.show_all() self.build_notifier()
def setUp(self): self.config = WujaConfiguration(GCONF_TEST_PATH)
class WujaApplication: """ The main Wuja application. """ def __init__(self): logger.info("Starting application.") upgrade_manager = UpgradeManager() upgrade_manager.check() # TODO: Disabled and switched from use of AsyncNotifier on # 2007-02-05. Possible problem with pynotify and threading, threading # was our decision to disable to get users up and running with a 0.0.6 # bugfix release. Re-enable once the issue is resolved. #gtk.gdk.threads_init() # Maintain a map of events that have alert windows open to ensure # we don't popup multiple windows for the same event that hasn't # been confirmed by the user: self.__open_alerts = {} self.config = WujaConfiguration(GCONF_PATH) self.notifier = None self.prefs_dialog = None self.calendar_window = None self.updating = False self.feed_update_event_source = None actions = ( ("calendar", gtk.STOCK_INDEX, "View Calendar", None, None, self.__open_calendar), ("preferences", gtk.STOCK_PREFERENCES, None, None, None, self.__open_preferences_dialog), ("update_feeds", gtk.STOCK_REFRESH, "Update Feeds", None, None, self.__update_feeds), ("debug_feeds", gtk.STOCK_EXECUTE, "Debug Feeds", None, None, self.__debug_feeds), ("about", gtk.STOCK_ABOUT, None, None, None, self.__open_about_dialog), ("quit", gtk.STOCK_QUIT, None, None, None, self.destroy)) action_group = gtk.ActionGroup("wuja_menu") action_group.add_actions(actions) ui_mgr = gtk.UIManager() ui_mgr.add_ui_from_file(find_file_on_path("wuja/data/wuja-menu.xml")) ui_mgr.insert_action_group(action_group, 0) self.menu = ui_mgr.get_widget("/wuja_menu") self.menu.show_all() self.tray_icon = trayicon.TrayIcon("wuja") self.tray_icon.connect('button_press_event', self.__clicked) tray_image = gtk.Image() tray_image.set_from_file( find_file_on_path("wuja/data/wuja-icon-24x24.png")) event_box = gtk.EventBox() event_box.add(tray_image) self.tray_icon.add(event_box) self.tray_icon.show_all() self.build_notifier() def _reset_feed_update(self): """ Restart the feed update timer. """ self.feed_update_event_source = gobject.timeout_add( FEED_UPDATE_INTERVAL * 1000 * 60, self.notifier.update) logger.debug("Updating feeds from Google servers every %s minutes." % FEED_UPDATE_INTERVAL) def __update_feeds(self, widget): """ Pass call to update feeds along to the notifier and reset timers. """ gobject.source_remove(self.feed_update_event_source) self.notifier.update() self._reset_feed_update() def __debug_feeds(self, widget): """ Print out debug info on all feeds to the log file. """ logger.info("Calendar Debug Info:") for cal in self.notifier.cache.load_all(): logger.info(cal.title + ":") for entry in cal.entries: logger.info(" " + entry.get_debug_info()) def __clicked(self, widget, data): """ Handle mouse clicks on the tray icon. (pop up the menu) """ # 1 = left, 2 = middle, 3 = right: self.menu.popup(None, None, None, data.button, data.time) def __open_preferences_dialog(self, widget): """ Open the preferences dialog. """ self.prefs_dialog = PreferencesDialog(self.config, self.notifier) def __open_calendar(self, widget): """ Open the calendar display dialog. """ self.calendar_window = CalendarWindow(self.notifier.cache, self.config) def __close_dialog(self, widget): """ Close the preferences dialog. """ self.prefs_dialog.close() def __open_about_dialog(self, widget): """ Open the about dialog. """ glade_file = 'wuja/data/wuja-about.glade' glade_xml = gtk.glade.XML(find_file_on_path(glade_file)) about_dialog = glade_xml.get_widget('WujaAbout') signals = { 'on_WujaAbout_close': self.__close_about_dialog, } glade_xml.signal_autoconnect(signals) about_dialog.show_all() def __close_about_dialog(self, widget, response): """ Close the about dialog. """ widget.destroy() def build_notifier(self): """ Builds the notifier object. """ self.notifier = Notifier(self.config) # register ourselves as an observer self.notifier.connect("feeds-updated", self.notify) gobject.timeout_add(NOTIFICATION_INTERVAL * 1000 * 60, self.notifier.check_for_notifications) self.notifier.check_for_notifications() logger.debug("Checking for notifications every %s minutes." % NOTIFICATION_INTERVAL) self._reset_feed_update() def delete_event(self, widget, event, data=None): """ GTK function. """ return False def destroy(self, widget, data=None): """ Quit the application. """ self.notifier.cache.close() gtk.main_quit() def notify(self, notifier, event): """ Triggered by the notifier when a notifaction of an event needs to go out to the user. """ self.display_notification(None, event) def display_notification(self, widget, event): """ Display a notification for an event. Check first to see if we already have a notification open. """ # Check if we already have a notification window open for this event: if self.__open_alerts.has_key(event.key): logger.debug("Alert window already open for event: " + \ event.entry.title) return alert_type = self.config.get_alert_type() if alert_type == ALERT_NOTIFICATION: alert_window = AlertNotification(event, self.tray_icon, self.config) else: alert_window = AlertDialog(event, self.config) alert_window.connect("alert-closed", self.on_alert_closed) self.__open_alerts[event.key] = alert_window def on_alert_closed(self, alert): self.__open_alerts.pop(alert.event.key) def main(self): """ Launches the GTK main loop. """ gtk.main()
class WujaConfigurationTests(unittest.TestCase): def setUp(self): self.config = WujaConfiguration(GCONF_TEST_PATH) def tearDown(self): # NOTE: Couldn't find a way to actually delete the directory, this just # unsets all the properties beneath it. client = gconf.client_get_default() client.recursive_unset(GCONF_TEST_PATH, gconf.UNSET_INCLUDING_SCHEMA_NAMES) def test_add_feed_url(self): self.config.add_feed_url('url1') urls = self.config.get_feed_urls() self.assertEqual(1, len(urls)) self.assertEqual('url1', urls[0]) def test_add_multiple_feed_urls(self): urls = ['url1', 'url2', 'url3'] for url in urls: self.config.add_feed_url(url) result_urls = self.config.get_feed_urls() self.assertEqual(urls, result_urls) def test_remove_feed_url(self): urls = ['url1', 'url2', 'url3'] for url in urls: self.config.add_feed_url(url) self.config.remove_feed_url(urls[1]) self.assertEqual([urls[0], urls[2]], self.config.get_feed_urls()) def test_remove_nonexistent_url(self): urls = ['url1', 'url2', 'url3'] for url in urls: self.config.add_feed_url(url) self.assertRaises(ValueError, self.config.remove_feed_url, 'not a real url') def test_remove_all_urls(self): urls = ['url1', 'url2', 'url3'] for url in urls: self.config.add_feed_url(url) self.config.remove_all_feed_urls() self.assertEqual(0, len(self.config.get_feed_urls())) def test_basic_url_replacement(self): """ /basic URLs lack data Wuja needs. """ urls = ['url1/basic'] for url in urls: self.config.add_feed_url(url) lookup_urls = self.config.get_feed_urls() self.assertEqual('url1/full', lookup_urls[0]) def test_ignore_empty_url(self): """ Add an emptry string URL and ensure it doesn't get added to the configuration. """ self.assertEqual(0, len(self.config.get_feed_urls())) self.config.add_feed_url('') self.assertEqual(0, len(self.config.get_feed_urls())) def test_default_timestamp_format(self): """ If no timestamp is defined in gconf, test that a default value is returned. """ self.assertEqual(DEFAULT_TIMESTAMP_FORMAT, self.config.get_timestamp_format()) def test_set_timestamp_format(self): client = gconf.client_get_default() self.assertEqual(None, client.get_string(os.path.join(GCONF_TEST_PATH, "timestamp_format"))) new_format = "%H:%M" self.config.set_timestamp_format(new_format) self.assertEqual(new_format, self.config.get_timestamp_format()) def test_set_reminder(self): client = gconf.client_get_default() self.assertEqual(None, client.get_string(os.path.join(GCONF_TEST_PATH, "default_reminder"))) # Reminder should default to 10 if the user hasn't set one explicitly: self.assertEqual(DEFAULT_REMINDER, self.config.get_reminder()) self.config.set_reminder(25) self.assertEqual(25, self.config.get_reminder()) def test_set_snooze(self): client = gconf.client_get_default() self.assertEqual(None, client.get_string(os.path.join(GCONF_TEST_PATH, "snooze_mins"))) # Snooze should default to 10 if the user hasn't set one explicitly: self.assertEqual(DEFAULT_SNOOZE, self.config.get_snooze()) self.config.set_snooze(25) self.assertEqual(25, self.config.get_snooze())