diff --git a/mytwitter.py b/mytwitter.py index c6c54e1..fb9fbb6 100755 --- a/mytwitter.py +++ b/mytwitter.py @@ -13,10 +13,6 @@ class MyTwitter(): """ Display Tweets, post to twitter """ - # Precompile a regex for searching for @ at the beginning of a string - at_check = re.compile('^@') - - def __init__(self): config = ConfigParser.ConfigParser() config.read(os.path.expanduser("~/.mytwitter")) @@ -89,7 +85,7 @@ class MyTwitter(): pane = self.tweet_notebook.get_nth_page(i) list_name = pane.get_list_name() - if pane.is_single_tweet(): + if pane.get_single_tweet() is not None: continue elif list_name is None or list_name == 'Home': statuses = self.api.GetHomeTimeline(count=self.num_entries) @@ -118,7 +114,7 @@ class MyTwitter(): self.update_entry.set_text("") self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id) self.reply_id = None - self.status_bar.push(self.context_id, 'Tweet Posted') + self.update_status_bar('Tweet Posted') def update_status_callback(self, widget): @@ -132,7 +128,7 @@ class MyTwitter(): self.update_count.set_label(new_count) # If reply_id is set, unset it if we have removed the @ symbol - if self.reply_id is not None and not MyTwitter.at_check.match(self.update_entry.get_text()): + if self.reply_id is not None and not re.match('@', self.update_entry.get_text()): self.reply_id = None @@ -144,14 +140,14 @@ class MyTwitter(): print "STUB: help->about not yet implemented" - def on_reply(self, widget): - self.update_entry.set_text('@' + widget.screen_name + ' ') - self.reply_id = widget.id + def on_reply(self, widget, data): + self.update_entry.set_text('@' + data['screen_name'] + ' ') + self.reply_id = data['id'] self.update_entry.grab_focus() - def on_retweet(self, widget): - self.api.PostRetweet(widget.id) + def on_retweet(self, widget, data): + self.api.PostRetweet(data['id']) def on_reply_to(self, widget, data): @@ -186,12 +182,24 @@ class MyTwitter(): # This code modified from create_custom_tab in: # http://www.daa.com.au/pipermail/pygtk/2006-April/012216.html def add_to_notebook(self, name, single_tweet=None): - try: - new_pane = TweetPane(name, self, single_tweet) - except HTTPError: - return + new_pane = TweetPane(name, self.num_entries, single_tweet) self.tweet_notebook.append_page(new_pane, new_pane.get_tab_label()) - new_pane.get_tab_label().connect('close_clicked', self.remove_view, name) + new_pane.get_tab_label().connect('close-clicked', self.remove_view, name) + new_pane.connect('tweet-reply', self.on_reply) + new_pane.connect('tweet-retweet', self.on_retweet) + new_pane.connect('tweet-in-reply-to', self.on_reply_to) + + # Special logic for single tweet pane + if single_tweet is not None: + try: + statuses = [] + statuses.append(self.api.GetStatus(single_tweet)) + new_pane.update_window(statuses) + except HTTPError: + self.tweet_notebook.remove_page(-1) + self.update_status_bar('Error retrieving tweet id: ' + str(single_tweet)) + return + self.tweet_notebook.set_current_page(-1) # switch to the new pane @@ -212,6 +220,10 @@ class MyTwitter(): self.update_windows() + def update_status_bar(self, text): + self.status_bar.pop(self.context_id) + self.status_bar.push(self.context_id, text) + ### end class MyTwitter @@ -226,14 +238,15 @@ class TweetPane(gtk.ScrolledWindow): It also gets some data from its parent, including num_entries ''' - def __init__(self, list_name, mytwitter, single_tweet=None): + def __init__(self, list_name, num_entries=20, single_tweet=None): gtk.ScrolledWindow.__init__(self) + self.updated_once = False + self.single_tweet = single_tweet self.list_name = list_name - self.mytwitter = mytwitter self.tab_label = CloseTabLabel(self.list_name) # These handle determining which tweets are unread @@ -243,8 +256,8 @@ class TweetPane(gtk.ScrolledWindow): self.tweets = [] - self.num_entries = self.mytwitter.num_entries - if self.is_single_tweet(): + self.num_entries = num_entries + if self.single_tweet is not None: self.num_entries = 1 self.init_widgets() @@ -260,10 +273,9 @@ class TweetPane(gtk.ScrolledWindow): for i in range(0, self.num_entries): self.tweets.append(TweetBox()) tweet_box.pack_start(self.tweets[i], expand=False) - self.tweets[i].connect('reply', self.mytwitter.on_reply) - self.tweets[i].connect('retweet', self.mytwitter.on_retweet) - self.tweets[i].connect('in-reply-to', self.mytwitter.on_reply_to) - + self.tweets[i].connect('reply', self.on_tweet_reply) + self.tweets[i].connect('retweet', self.on_retweet) + self.tweets[i].connect('in-reply-to', self.on_tweet_reply_to) viewport.add(tweet_box) @@ -277,9 +289,6 @@ class TweetPane(gtk.ScrolledWindow): self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) self.show_all() - if self.is_single_tweet(): - self.update_window(None) - def update_window(self, raw_statuses, using_results=False): if using_results: @@ -287,9 +296,8 @@ class TweetPane(gtk.ScrolledWindow): else: statuses = raw_statuses - if (self.is_single_tweet()): - statuses = [] - statuses.append(self.mytwitter.api.GetStatus(self.single_tweet)) + if self.updated_once is False: + self.updated_once = True # If this is our first load of this list, don't treat anything as new! if self.last_tweet_read is None: @@ -339,8 +347,24 @@ class TweetPane(gtk.ScrolledWindow): return self.tab_label - def is_single_tweet(self): - return self.single_tweet is not None + def get_single_tweet(self): + return self.single_tweet + + + def updated_once(self): + return self.updated_once + + + def on_tweet_reply(self, widget): + self.emit('tweet-reply', {'screen_name': widget.screen_name, 'id': widget.id}) + + + def on_retweet(self, widget): + self.emit('tweet-retweet', {'id': widget.id}) + + + def on_tweet_reply_to(self, widget, data): + self.emit('tweet-in-reply-to', data) # To keep things simple elsewhere and improve code reuse @@ -370,6 +394,19 @@ class TweetPane(gtk.ScrolledWindow): ### end class TweetPane +# signals for TweetPane + +gobject.signal_new("tweet-reply", TweetPane, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) +gobject.signal_new("tweet-retweet", TweetPane, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) +gobject.signal_new("tweet-in-reply-to", TweetPane, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) + + class TweetBox(gtk.VBox): @@ -524,6 +561,18 @@ class TweetBox(gtk.VBox): # end class TweetBox +# signals for TweetBox +gobject.signal_new("reply", TweetBox, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, ()) +gobject.signal_new("retweet", TweetBox, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, ()) +gobject.signal_new("in-reply-to", TweetBox, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) + + class CloseTabLabel(gtk.EventBox): ''' @@ -561,7 +610,7 @@ class CloseTabLabel(gtk.EventBox): tabBox.pack_start(self.label, False) tabBox.pack_start(tabButton, False) - self.connect('button_press_event', self.on_button_press) + self.connect('button-press-event', self.on_button_press) # needed, otherwise even calling show_all on the notebook won't # make the hbox contents appear. @@ -574,18 +623,25 @@ class CloseTabLabel(gtk.EventBox): def on_clicked(self, event): - self.emit('close_clicked') + self.emit('close-clicked') def on_button_press(self, event, direction): - self.emit('label_clicked') + self.emit('label-clicked') ### end class CloseTabLabel +# signals for CloseTabLabel +gobject.signal_new("close-clicked", CloseTabLabel, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, ()) +gobject.signal_new("label-clicked", CloseTabLabel, + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, ()) + + -# A couple of lame faux-classes because the Twitter API needs a kick -# in the face class Status(): def __init__(self): self.user = User() @@ -600,22 +656,5 @@ class User(): # main -# Create custom events for TweetBox -gobject.signal_new("close_clicked", CloseTabLabel, - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, ()) -gobject.signal_new("label_clicked", CloseTabLabel, - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, ()) -gobject.signal_new("reply", TweetBox, - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, ()) -gobject.signal_new("retweet", TweetBox, - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, ()) -gobject.signal_new("in-reply-to", TweetBox, - gobject.SIGNAL_RUN_LAST, - gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)) - my_twitter = MyTwitter() gtk.main()