From 77f72c197e00e1f46e9050c30a1416679ae148ca Mon Sep 17 00:00:00 2001 From: Julio Biason Date: Sat, 18 Apr 2009 10:57:53 +1000 Subject: [PATCH] Removed a lot of (now) unused code. Some should return. --- mitterlib/ui/ui_pygtk.py | 909 +-------------------------------------- 1 file changed, 12 insertions(+), 897 deletions(-) diff --git a/mitterlib/ui/ui_pygtk.py b/mitterlib/ui/ui_pygtk.py index a9e902f..469af0a 100644 --- a/mitterlib/ui/ui_pygtk.py +++ b/mitterlib/ui/ui_pygtk.py @@ -38,82 +38,14 @@ from mitterlib.ui.helpers import timesince # Constants -URL_RE = re.compile( - r'((?:(?:https?|ftp)://|www[-\w]*\.)[^\s\n\r]+[-\w+&@#%=~])', re.I) - _log = logging.getLogger('ui.pygtk') -class Columns: - (PIC, NAME, MESSAGE, USERNAME, ID, DATETIME, ALL_DATA) = range(7) - class Interface(object): """Linux/GTK interface for Mitter.""" NAMESPACE = 'pygtk' - def systray_cb(self, widget, user_param=None): - if self.window.get_property('visible') and self.window.is_active(): - x, y = self.window.get_position() - self.prefs['position_x'] = x - self.prefs['position_y'] = y - self.window.hide() - else: - self.window.move( - self.prefs['position_x'], - self.prefs['position_y']) - self.window.deiconify() - self.window.present() - - def create_settings_dialog(self): - """Creates the settings dialog.""" - - self.settings_window = gtk.Dialog(title="Settings", - parent=self.window, flags=gtk.DIALOG_MODAL | - gtk.DIALOG_DESTROY_WITH_PARENT, - buttons=(gtk.STOCK_CANCEL, 0, gtk.STOCK_OK, 1)) - self.settings_box = gtk.Table(rows=4, columns=2, homogeneous=False) - - username_label = gtk.Label('Username:') - password_label = gtk.Label('Password:') - refresh_label = gtk.Label('Refresh interval (minutes):') - https_label = gtk.Label('Use secure connections (HTTPS):') - - labels = [username_label, password_label, refresh_label, https_label] - for label in labels: - label.set_alignment(0, 0.5) - label.set_padding(2, 0) - - self.username_field = gtk.Entry() - self.password_field = gtk.Entry() - self.password_field.set_visibility(False) - - self.refresh_interval_field = gtk.SpinButton() - self.refresh_interval_field.set_range(1, 99) - self.refresh_interval_field.set_numeric(True) - self.refresh_interval_field.set_value(self.prefs['refresh_interval']) - self.refresh_interval_field.set_increments(1, 5) - - self.https_field = gtk.CheckButton() - self.https_field.set_active(self.https) - - self.settings_box.attach(username_label, 0, 1, 0, 1) - self.settings_box.attach(self.username_field, 1, 2, 0, 1) - self.settings_box.attach(password_label, 0, 1, 1, 2) - self.settings_box.attach(self.password_field, 1, 2, 1, 2) - self.settings_box.attach(refresh_label, 0, 1, 2, 3) - self.settings_box.attach(self.refresh_interval_field, 1, 2, 2, 3) - self.settings_box.attach(https_label, 0, 1, 3, 4) - self.settings_box.attach(self.https_field, 1, 2, 3, 4) - - self.settings_box.show_all() - self.settings_window.vbox.pack_start(self.settings_box, True, - True, 0) - self.settings_window.connect('close', self.close_dialog) - self.settings_window.connect('response', self.update_preferences) - - return - def show_about(self, widget): """Show the about dialog.""" @@ -143,823 +75,6 @@ class Interface(object): about_window.hide() - # ------------------------------------------------------------ - # Widget creation functions - # ------------------------------------------------------------ - - # ------------------------------------------------------------ - # Grid cell content callback - # ------------------------------------------------------------ - - # Non-widget attached callbacks - def set_auto_refresh(self): - """Configure auto-refresh of tweets every `interval` minutes""" - - if self._refresh_id: - gobject.source_remove(self._refresh_id) - - self._refresh_id = gobject.timeout_add( - self.prefs['refresh_interval']*60*1000, - self.refresh, None) - - return - - def update_friends_list(self): - """Fetch the user's list of twitter friends and add it - to the friends_store for @reply autocompletion""" - - _log.debug('Checking friends list...') - friends = self.twitter.friends_list(self.post_update_friends_list) - return - - def post_update_friends_list(self, friends, error): - """Function called after we fetch the friends list.""" - - _log.debug('Received the friends list') - - if error == 401: # TODO: Constants for this? - # not authorized - _log.error('User is not authorized yet') - return - - if error in (500, 502, 503): - _log.error('Twitter asked us to try getting friends list' \ - ' sometime later') - gobject.timeout_add(5*60*1000, self.update_friends_list) - return - - if error: - # any error - # well, we just don't add any friends, then. - _log.error('Error getting friend list, leaving list empty') - return - - # I'm not really sure if we need to set the thread locking here (as we - # are just updating the store), but better safe than sorry! - - gtk.gdk.threads_enter() - # Sometimes due to twitter API quirks and moon phases, the friends - # list ends up getting populated more than once. So watch for - # duplicates.... - known_friends = [row[0] for row in self.friends_store] - _log.debug('known_friends: %s' % " ".join(known_friends)) - for friend in friends: - try: - screen_name = '@' + friend['screen_name'] + ': ' - if screen_name not in known_friends: - _log.debug('Adding "%s" to the list' % (screen_name)) - self.friends_store.append([screen_name]) - except Exception, e: - # No `error` does not always mean twitter sent us good data - _log.error('Error processing friend list. %s' % str(e)) - - gtk.gdk.threads_leave() - _log.debug('friends list processing complete') - return - - def prune_grid_store(self): - """Prune the grid_store by removing the oldest rows.""" - - if len(self.grid_store) <= MAX_STATUS_DISPLAY: - return True # Required by gobject.idle_add() for this to be called - # again - - _log.debug("prune_grid_store called") - - gtk.gdk.threads_enter() - - self.grid.freeze_child_notify() - self.grid.set_model(None) - - # Since I don't know how to get the last row in grid_store, - # I'll reverse the list and then pop out the first row instead. - - self.grid_store.set_sort_column_id(Columns.DATETIME, - gtk.SORT_ASCENDING) - - iter = self.grid_store.get_iter_first() - - while (len(self.grid_store) > MAX_STATUS_DISPLAY) and iter: - _log.debug("popping off tweet with id %s" % - self.grid_store.get_value(iter, Columns.ID)) - self.grid_store.remove(iter) # iter is auto set to next row - - - self.grid_store.set_sort_column_id(Columns.DATETIME, - gtk.SORT_DESCENDING) - self.grid.set_model(self.grid_store) - self.grid.thaw_child_notify() - - gtk.gdk.threads_leave() - return True - - # Main window callbacks - def size_request(self, widget, requisition, data=None): - """Callback when the window changes its sizes. We use it to set the - proper word-wrapping for the message column.""" - - self.prefs['width'], self.prefs['height'] = self.window.get_size() - - # this is based on a mail of Kristian Rietveld, on gtk maillist - - if not len(self.grid_store): - # nothing to rearrange - return - - column = self.message_column - iter = self.grid_store.get_iter_first() - path = self.grid_store.get_path(iter) - - column_rectangle = self.grid.get_cell_area(path, column) - - width = column_rectangle.width - _log.debug('Width=%d' % (width)) - - # there should be only - renderers = column.get_cell_renderers() - for render in renderers: - _log.debug('Render update') - render.set_property('wrap-width', width) - - while iter: - path = self.grid_store.get_path(iter) - self.grid_store.row_changed(path, iter) - iter = self.grid_store.iter_next(iter) - - return - - def notify_reset(self, widget, event, user_data=None): - if getattr(event, 'in_', False): - self._main_window.set_urgency_hint(False) - if self._systray: - self._systray.set_tooltip('Mitter: Click to toggle ' \ - 'window visibility.') - self._systray.set_from_file(self._app_icon) - self.unread_tweets = 0 - return - - def notify(self, new_tweets=0): - """Set the window hint as urgent, so Mitter window will flash, - notifying the user about the new messages. Also send a notification - message with one of the new tweets.""" - self.window.set_urgency_hint(True) - if self._systray and self.unread_tweets > 0: - self._systray.set_tooltip('Mitter: %s new' % self.unread_tweets) - self._systray.set_from_file(self._app_icon_alert) - - if self.action_group.get_action('MuteNotify').get_active(): - _log.debug('notifications are currently muted') - return - - if new_tweets and len(self.grid_store) > 0: - iter = self.grid_store.get_iter_first() - while iter: - sender = self.grid_store.get_value(iter, Columns.USERNAME) - if sender == self.username_field.get_text(): - iter = self.grid_store.iter_next(iter) - continue - else: - tweet = self.grid_store.get_value(iter, Columns.MESSAGE) - _log.debug('notify_broadcast with this tweet: %s' % - tweet) - break - - if new_tweets > 1: - msg = '%d unread tweets including ' \ - 'this from %s:
%s' % (self.unread_tweets, - sender, tweet) - else: - msg = 'One new tweet from %s:
%s' % (sender, - tweet) - - if self.systray: - gtk.gdk.threads_enter() - screen, rect, orientation = self.systray.get_geometry() - gtk.gdk.threads_leave() - self.notify_broadcast(msg, rect.x, rect.y) - return - - # settings callbacks - def show_settings(self, widget, user_data=None): - """Create and display the settings window.""" - - self.settings_window.show() - self.settings_window.run() - - return - - def close_dialog(self, user_data=None): - """Hide the dialog window.""" - - return True - - def update_preferences(self, widget, response_id=0, user_data=None): - """ - Update the user preferences when the user press the "OK" button in the - settings window.""" - - if response_id == 1: - self.statusbar.push(self.statusbar_context, - 'Saving your profile...') - - self.save_interface_prefs() - - # update the (internal) twitter prefences too! - - self.twitter.username = self.username_field.get_text() - self.twitter.password = self.password_field.get_text() - self.twitter.https = self.https_field.get_active() - refresh_interval = self.refresh_interval_field.get_value_as_int() - self.prefs['refresh_interval'] = refresh_interval - - # update the list - - self.refresh(None) - self.update_friends_list() - self.statusbar.pop(self.statusbar_context) - - # update auto-refresh - - self.set_auto_refresh() - - self.settings_window.hide() - - return True - - # update status - def update_status(self, user_data=None): - """Update the user status on Twitter.""" - - status = self.update_text.get_text() - status = status.strip() - if not str_len(status): - return - - self.update_text.set_sensitive(False) - self.statusbar.push(self.statusbar_context, 'Updating your status...') - - if str_len(status) > 140: - error_message = 'Your message has more than 140 characters and' \ - ' Twitter may truncate it. It would still be visible ' \ - 'on the website. Do you still wish to go ahead?' - if str_len(status) > 160: - error_message = 'Your message has more than 160 characters ' \ - 'and it is very likely Twitter will refuse it. You ' \ - 'can try shortening your URLs before posting. Do ' \ - 'you still wish to go ahead?' - - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_QUESTION, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - message_format="Your status update message is too long.", - buttons=gtk.BUTTONS_YES_NO) - error_dialog.format_secondary_text(error_message) - - response = error_dialog.run() - error_dialog.destroy() - if response == gtk.RESPONSE_NO: - self.statusbar.pop(self.statusbar_context) - self.update_text.set_sensitive(True) - self.window.set_focus(self.update_text) - return - - data = self.twitter.update(status, self.post_update_status) - - def post_update_status(self, data, error): - """Function called after we receive the answer from the update - status.""" - - if error: - gtk.gdk.threads_enter() - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_ERROR, - message_format='Error updating status. Please try again.', - buttons=gtk.BUTTONS_OK) - error_dialog.connect("response", lambda *a: - error_dialog.destroy()) - error_dialog.run() - gtk.gdk.threads_leave() - else: - if data: - # i wonder if this will really work - self.post_refresh([data], None, False) - else: - self.refresh(None, False) - - gtk.gdk.threads_enter() - self.update_text.set_text("") - gtk.gdk.threads_leave() - - gtk.gdk.threads_enter() - self.statusbar.pop(self.statusbar_context) - self.update_text.set_sensitive(True) - self.window.set_focus(self.update_text) - gtk.gdk.threads_leave() - - return True - - def shrink_url(self, widget, user_data=None): - bounds = self.update_text.get_selection_bounds() - if not bounds: - return - else: - start, end = bounds - - longurl = self.update_text.get_chars(start, end).strip() - if not longurl: - return - - _log.debug('shrink url request for: %s' % longurl) - - self.update_text.set_sensitive(False) - self.statusbar.push(self.statusbar_context, 'Shrinking URL...') - - self.twitter.download('http://is.gd/api.php?longurl=' + longurl, - self.post_shrink_url, longurl=longurl, - start=start, end=end) - - def post_shrink_url(self, url, error, longurl, start, end): - if error: - _log.error("Exception in shrinking url. ' \ - 'Error code: %s" % error) - # error dialog - gtk.gdk.threads_enter() - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_ERROR, - message_format='Failed to shrink the URL %s' % longurl, - buttons=gtk.BUTTONS_OK) - error_dialog.connect("response", lambda *a: - error_dialog.destroy()) - error_dialog.run() - gtk.gdk.threads_leave() - else: - _log.debug('Got shrunk url: %s' % url) - char = self.update_text.get_chars(start-1, start) - if start and not char.isspace(): - url = ' '+url - char = self.update_text.get_chars(end, end+1) - if not char.isspace(): - url = url+' ' - - gtk.gdk.threads_enter() - self.update_text.delete_text(start, end) - self.update_text.insert_text(url, start) - self.update_text.set_position(start+len(url)) - gtk.gdk.threads_leave() - - gtk.gdk.threads_enter() - self.statusbar.pop(self.statusbar_context) - self.update_text.set_sensitive(True) - self.update_text.grab_focus() - gtk.gdk.threads_leave() - - # post related callbacks - def reply_tweet(self, widget, user_data=None): - """Reply by putting the username in your input""" - cursor = self.grid.get_cursor() - if not cursor: - return - - path = cursor[0] - iter = self.grid_store.get_iter(path) - username = self.grid_store.get_value(iter, Columns.USERNAME) - text_insert = '@%s: ' % (username) - - _log.debug('Inserting reply text: %s' % (text_insert)) - - status = self.update_text.get_text() - status = text_insert + status - self.update_text.set_text(status) - self.window.set_focus(self.update_text) - self.update_text.set_position(len(status)) - - def retweet(self, widget, user_data=None): - """Retweet by putting the string rt and username in your input""" - - cursor = self.grid.get_cursor() - if not cursor: - return - - path = cursor[0] - iter = self.grid_store.get_iter(path) - username = self.grid_store.get_value(iter, Columns.USERNAME) - msg = self.grid_store.get_value(iter, Columns.MESSAGE) - text_insert = 'RT @%s: %s' % (username, msg) - - _log.debug('Inserting retweet text: %s' % (text_insert)) - - status = text_insert + self.update_text.get_text() - self.update_text.set_text(status) - self.window.set_focus(self.update_text) - self.update_text.set_position(str_len(status)) - - def delete_tweet(self, widget, user_data=None): - """Delete a twit.""" - - cursor = self.grid.get_cursor() - if not cursor: - return - - path = cursor[0] - iter = self.grid_store.get_iter(path) - tweet_id = int(self.grid_store.get_value(iter, Columns.ID)) - _log.debug('Deleting tweet: %d' % (tweet_id)) - - self.statusbar.push(self.statusbar_context, 'Deleting tweet...') - - self.twitter.tweet_destroy(tweet_id, self.post_delete_tweet, - tweet=tweet_id) - - return - - def post_delete_tweet(self, data, error, tweet): - """Function called after we delete a tweet on the server.""" - - if error: - gtk.gdk.threads_enter() - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_ERROR, - message_format='Error deleting tweet. Please try again.', - buttons=gtk.BUTTONS_OK) - error_dialog.connect("response", lambda *a: - error_dialog.destroy()) - error_dialog.run() - gtk.gdk.threads_leave() - else: - # locate that tweet in the store and remove it. - iter = self.grid_store.get_iter_first() - tweet = int(tweet) - while iter: - id = self.grid_store.get_value(iter, Columns.ID) - if int(id) == tweet: - self.grid_store.remove(iter) - break - iter = self.grid_store.iter_next(iter) - - # update the interface - gtk.gdk.threads_enter() - self.statusbar.pop(self.statusbar_context) - self.grid.queue_draw() - gtk.gdk.threads_leave() - - return - - def check_post(self, treeview, user_data=None): - """Callback when one of the rows is selected.""" - cursor = treeview.get_cursor() - if not cursor: - return - - path = cursor[0] - iter = self.grid_store.get_iter(path) - username = self.grid_store.get_value(iter, Columns.USERNAME) - - delete_action = self.action_group.get_action('Delete') - - if username == self.username_field.get_text(): - delete_action.set_property('sensitive', True) - else: - delete_action.set_property('sensitive', False) - - return - - def open_post(self, treeview, path, view_column, user_data=None): - """Callback when one of the rows in activated.""" - - iter = self.grid_store.get_iter(path) - username = self.grid_store.get_value(iter, Columns.USERNAME) - tweet_id = self.grid_store.get_value(iter, Columns.ID) - message = self.grid_store.get_value(iter, Columns.MESSAGE) - urls = url_re.search(message) - if urls: - # message contains a link; go to the link instead - url = urls.groups()[0] - else: - url = 'http://twitter.com/%s/statuses/%s/' % (username, tweet_id) - - self.open_url(path, url) - - def click_post(self, treeview, event, user_data=None): - """Callback when a mouse click event occurs on one of the rows.""" - - if event.button != 3: - # Only right clicks are processed - return False - - x = int(event.x) - y = int(event.y) - - pth = treeview.get_path_at_pos(x, y) - if not pth: - # The click wasn't on a row - return False - - path, col, cell_x, cell_y = pth - treeview.grab_focus() - treeview.set_cursor(path, col, 0) - - self.show_post_popup(treeview, event) - return True - - def show_post_popup(self, treeview, event, user_data=None): - """Shows the popup context menu in the treeview""" - - cursor = treeview.get_cursor() - if not cursor: - return - - path = cursor[0] - row_iter = self.grid_store.get_iter(path) - - popup_menu = gtk.Menu() - popup_menu.set_screen(self.window.get_screen()) - - # An open submenu with various choices underneath - open_menu_items = [] - - tweet = self.grid_store.get_value(row_iter, Columns.ALL_DATA) - - urls = url_re.findall(tweet['text']) - for url in urls: - if len(url) > 20: - item_name = url[:20] + '...' - else: - item_name = url - item = gtk.MenuItem(item_name) - item.connect('activate', self.open_url, url) - open_menu_items.append(item) - - if tweet['in_reply_to_status_id']: - # I wish twitter made it easy to construct target url - # without having to make another API call - reply_to = re.search(r'@(?P\w+)', tweet['text']) - if reply_to: - url = 'http://twitter.com/%s/statuses/%s' % ( - reply_to.group('user'), - tweet['in_reply_to_status_id']) - item = gtk.MenuItem('In reply to') - item.connect('activate', self.open_url, url) - open_menu_items.append(item) - - item = gtk.MenuItem('This tweet') - username = self.grid_store.get_value(row_iter, Columns.USERNAME) - tweet_id = self.grid_store.get_value(row_iter, Columns.ID) - url = 'http://twitter.com/%s/statuses/%s/' % (username, tweet_id) - item.connect('activate', self.open_url, url) - open_menu_items.append(item) - - open_menu = gtk.Menu() - for item in open_menu_items: - open_menu.append(item) - - open_item = gtk.MenuItem("Open") - open_item.set_submenu(open_menu) - popup_menu.append(open_item) - - # Reply, only if it's not yourself - item = gtk.MenuItem("Reply") - item.connect('activate', self.reply_tweet, "Reply") - if username == self.username_field.get_text(): - item.set_property('sensitive', False) - popup_menu.append(item) - - # Retweet, only if it's not yourself - item = gtk.MenuItem("Retweet") - item.connect('activate', self.retweet, "Retweet") - if username == self.username_field.get_text(): - item.set_property('sensitive', False) - popup_menu.append(item) - - item = gtk.MenuItem("Delete") - item.connect('activate', self.delete_tweet, "Delete") - if username != self.username_field.get_text(): - item.set_property('sensitive', False) - - popup_menu.append(item) - - popup_menu.show_all() - - if event: - b = event.button - t = event.time - else: - b = 1 - t = 0 - - popup_menu.popup(None, None, None, b, t) - - return True - - # action callbacks - # (yes, settings should be here, but there are more settings-related - # callbacks, so let's keep them together somewhere else) - def open_url(self, source, url): - """Simply opens specified url in new browser tab. We need source - parameter so that this function can be used as an event callback""" - - _log.debug('opening url: %s' % url) - import webbrowser - webbrowser.open_new_tab(url) - self.window.set_focus(self.update_text) - - def refresh(self, widget, notify=True): - """Update the list of twits.""" - - if self.last_update: - self.statusbar.pop(self.statusbar_context) - self.last_update = datetime.datetime.now() - - _log.debug('Updating list of tweets...') - self.statusbar.push(self.statusbar_context, - 'Updating list of tweets...') - - self.twitter.friends_timeline(self.post_refresh, notify=notify) - - return True # required by gobject.timeout_add - - def post_refresh(self, data, error, notify): - """Function called when the system retrieves the list of new - tweets.""" - - _log.debug('Data: %s' % (str(data))) - - if error == 401: - # Not authorized, popup the settings window - gtk.gdk.threads_enter() - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_ERROR, - message_format='Autorization error, check your login ' \ - 'information in the prefrences', - buttons=gtk.BUTTONS_OK) - error_dialog.connect("response", lambda *a: - error_dialog.destroy()) - error_dialog.run() - gtk.gdk.threads_leave() - return - - if not data: - gtk.gdk.threads_enter() - self.statusbar.pop(self.statusbar_context) - self.show_last_update() - _log.debug('No new data') - gtk.gdk.threads_leave() - return - - known_tweets = [row[Columns.ID] for row in self.grid_store] - need_notify = False - new_tweets = 0 - new_tweets_list = [] - - for tweet in data: - id = tweet['id'] - if str(id) in known_tweets: - _log.debug('Tweet %s is already in the list' % (id)) - continue - - created_at = tweet['created_at'] - display_name = tweet['user']['name'] - username = tweet['user']['screen_name'] - user_pic = tweet['user']['profile_image_url'] - message = tweet['text'] - - new_tweets_list.append((user_pic, display_name, message, username, - id, created_at, tweet)) - self.queue_pic(user_pic) - - _log.debug('New tweet with id %s from %s' % (id, username)) - if not username == self.username_field.get_text(): - # we don't want to be notified about tweets from ourselves, - # but from everyone else it is fine. - new_tweets += 1 - - # add the new tweets in the store - gtk.gdk.threads_enter() - for data in new_tweets_list: - self.grid_store.append(data) - - self.statusbar.pop(self.statusbar_context) - - # there is new stuff, so we move to the top - - p = self.grid_store.get_path(self.grid_store.get_iter_first()) - self.grid.scroll_to_cell(p) - self.show_last_update() - _log.debug('Tweets updated') - gtk.gdk.threads_leave() - - if new_tweets and notify: - self.unread_tweets += new_tweets - self.notify(new_tweets) - - self.refresh_rate_limit() - self.prune_grid_store() - - # ------------------------------------------------------------ - # Helper functions - # ------------------------------------------------------------ - def clear_list(self): - """Clear the list, so we can add more items.""" - - self.grid_store.clear() - - return - - def refresh_rate_limit(self): - """Request the rate limit and check if we are doing okay.""" - self.twitter.rate_limit_status(self.post_refresh_rate_limit) - return - - def post_refresh_rate_limit(self, data, error): - """Callback for the refresh_rate_limit.""" - if error or not data: - _log.error('Error fetching rate limit') - return - - # Check if we are running low on our limit - reset_time = datetime.datetime.fromtimestamp( - int(data['reset_time_in_seconds'])) - - if reset_time < datetime.datetime.now(): - # Clock differences can cause this - return - - time_delta = reset_time - datetime.datetime.now() - mins_till_reset = time_delta.seconds/60 # Good enough! - needed_hits = mins_till_reset/self.prefs['refresh_interval'] - remaining_hits = int(data['remaining_hits']) - - _log.debug('remaining_hits: %s. reset in %s mins.' - % (remaining_hits, mins_till_reset)) - - if needed_hits > remaining_hits: - gtk.gdk.threads_enter() - error_dialog = gtk.MessageDialog(parent=self.window, - type=gtk.MESSAGE_WARNING, - flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - message_format='Refresh rate too high', - buttons=gtk.BUTTONS_OK) - error_dialog.format_secondary_text( - "You have only %d twitter requests left until your " \ - "request count is reset in %d minutes. But at your " \ - "current refresh rate (every %d minutes), you will " \ - "exhaust your limit within %d minutes. You should " \ - "consider increasing the refresh interval in Mitter's " \ - "Settings dialog." % (remaining_hits, mins_till_reset, - self.prefs['refresh_interval'], - remaining_hits * self.prefs['refresh_interval'])) - error_dialog.connect("response", lambda *a: - error_dialog.destroy()) - error_dialog.run() - gtk.gdk.threads_leave() - - def show_last_update(self): - """Add the last update time in the status bar.""" - - last_update = self.last_update.strftime('%H:%M') - next_update = (self.last_update + - datetime.timedelta(minutes=self.prefs[ - 'refresh_interval'])).strftime('%H:%M') - - message = 'Last update %s, next update %s' % (last_update, - next_update) - self.statusbar.push(self.statusbar_context, message) - return - - def queue_pic(self, pic): - """Check if the pic is in the queue or already downloaded. If it is - not in any of those, add it to the download queue.""" - if pic in self.user_pics: - return - - if pic in self.pic_queue: - return - - self.pic_queue.add(pic) - self.twitter.download(pic, self.post_pic_download, id=pic) - return - - def post_pic_download(self, data, error, id): - """Function called once we downloaded the user pic.""" - - _log.debug('Received pic %s' % (id)) - - if error or not data: - _log.debug('Error with the pic, not loading') - return - - loader = gtk.gdk.PixbufLoader() - loader.write(data) - loader.close() - - self.user_pics[id] = loader.get_pixbuf() - self.pic_queue.discard(id) - - # finally, request the grid to redraw itself - gtk.gdk.threads_enter() - self.grid.queue_draw() - gtk.gdk.threads_leave() - - return # ------------------------------------------------------------ # Helper functions # ------------------------------------------------------------ @@ -1063,7 +178,7 @@ class Interface(object): message_renderer.set_property('width', 10) message_column = gtk.TreeViewColumn('Message', - message_renderer, text=1) + message_renderer) message_column.set_cell_data_func(message_renderer, self._cell_renderer_message) self.grid.append_column(message_column) @@ -1088,7 +203,7 @@ class Interface(object): refresh_action = gtk.Action('Refresh', '_Refresh', 'Update the listing', gtk.STOCK_REFRESH) - refresh_action.connect('activate', self.refresh) + #refresh_action.connect('activate', self.refresh) quit_action = gtk.Action('Quit', '_Quit', 'Exit Mitter', gtk.STOCK_QUIT) @@ -1096,7 +211,7 @@ class Interface(object): settings_action = gtk.Action('Settings', '_Settings', 'Settings', gtk.STOCK_PREFERENCES) - settings_action.connect('activate', self.show_settings) + #settings_action.connect('activate', self.show_settings) update_action = gtk.Action('Update', '_Update', 'Update your status', gtk.STOCK_ADD) @@ -1106,19 +221,19 @@ class Interface(object): delete_action = gtk.Action('Delete', '_Delete', 'Delete a post', gtk.STOCK_DELETE) delete_action.set_property('sensitive', False) - delete_action.connect('activate', self.delete_tweet) + #delete_action.connect('activate', self.delete_tweet) about_action = gtk.Action('About', '_About', 'About Mitter', gtk.STOCK_ABOUT) about_action.connect('activate', self.show_about) - shrink_url_action = gtk.Action('ShrinkURL', 'Shrink _URL', - 'Shrink selected URL', gtk.STOCK_EXECUTE) - shrink_url_action.connect('activate', self.shrink_url) + #shrink_url_action = gtk.Action('ShrinkURL', 'Shrink _URL', + # 'Shrink selected URL', gtk.STOCK_EXECUTE) + #shrink_url_action.connect('activate', self.shrink_url) - mute_action = gtk.ToggleAction('MuteNotify', '_Mute Notifications', - 'Mutes notifications on new tweets', gtk.STOCK_MEDIA_PAUSE) - mute_action.set_active(False) + #mute_action = gtk.ToggleAction('MuteNotify', '_Mute Notifications', + # 'Mutes notifications on new tweets', gtk.STOCK_MEDIA_PAUSE) + #mute_action.set_active(False) post_action = gtk.Action('Posts', '_Posts', 'Post management', None) @@ -1140,8 +255,8 @@ class Interface(object): self.action_group.add_action(edit_action) self.action_group.add_action(help_action) self.action_group.add_action(about_action) - self.action_group.add_action_with_accel(shrink_url_action, 'u') - self.action_group.add_action_with_accel(mute_action, 'm') + #self.action_group.add_action_with_accel(shrink_url_action, 'u') + #self.action_group.add_action_with_accel(mute_action, 'm') self.action_group.add_action_with_accel(update_action, 'Return')