Refactored TweetPane and MyTwitter to be more loosely coupled
This commit is contained in:
parent
9100d8493b
commit
2f2a4d926d
149
mytwitter.py
149
mytwitter.py
|
@ -13,10 +13,6 @@ class MyTwitter():
|
||||||
|
|
||||||
""" Display Tweets, post to twitter """
|
""" Display Tweets, post to twitter """
|
||||||
|
|
||||||
# Precompile a regex for searching for @ at the beginning of a string
|
|
||||||
at_check = re.compile('^@')
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
config = ConfigParser.ConfigParser()
|
config = ConfigParser.ConfigParser()
|
||||||
config.read(os.path.expanduser("~/.mytwitter"))
|
config.read(os.path.expanduser("~/.mytwitter"))
|
||||||
|
@ -89,7 +85,7 @@ class MyTwitter():
|
||||||
pane = self.tweet_notebook.get_nth_page(i)
|
pane = self.tweet_notebook.get_nth_page(i)
|
||||||
list_name = pane.get_list_name()
|
list_name = pane.get_list_name()
|
||||||
|
|
||||||
if pane.is_single_tweet():
|
if pane.get_single_tweet() is not None:
|
||||||
continue
|
continue
|
||||||
elif list_name is None or list_name == 'Home':
|
elif list_name is None or list_name == 'Home':
|
||||||
statuses = self.api.GetHomeTimeline(count=self.num_entries)
|
statuses = self.api.GetHomeTimeline(count=self.num_entries)
|
||||||
|
@ -118,7 +114,7 @@ class MyTwitter():
|
||||||
self.update_entry.set_text("")
|
self.update_entry.set_text("")
|
||||||
self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id)
|
self.api.PostUpdate(text, in_reply_to_status_id=self.reply_id)
|
||||||
self.reply_id = None
|
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):
|
def update_status_callback(self, widget):
|
||||||
|
@ -132,7 +128,7 @@ class MyTwitter():
|
||||||
self.update_count.set_label(new_count)
|
self.update_count.set_label(new_count)
|
||||||
|
|
||||||
# If reply_id is set, unset it if we have removed the @ symbol
|
# 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
|
self.reply_id = None
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,14 +140,14 @@ class MyTwitter():
|
||||||
print "STUB: help->about not yet implemented"
|
print "STUB: help->about not yet implemented"
|
||||||
|
|
||||||
|
|
||||||
def on_reply(self, widget):
|
def on_reply(self, widget, data):
|
||||||
self.update_entry.set_text('@' + widget.screen_name + ' ')
|
self.update_entry.set_text('@' + data['screen_name'] + ' ')
|
||||||
self.reply_id = widget.id
|
self.reply_id = data['id']
|
||||||
self.update_entry.grab_focus()
|
self.update_entry.grab_focus()
|
||||||
|
|
||||||
|
|
||||||
def on_retweet(self, widget):
|
def on_retweet(self, widget, data):
|
||||||
self.api.PostRetweet(widget.id)
|
self.api.PostRetweet(data['id'])
|
||||||
|
|
||||||
|
|
||||||
def on_reply_to(self, widget, data):
|
def on_reply_to(self, widget, data):
|
||||||
|
@ -186,12 +182,24 @@ class MyTwitter():
|
||||||
# This code modified from create_custom_tab in:
|
# This code modified from create_custom_tab in:
|
||||||
# http://www.daa.com.au/pipermail/pygtk/2006-April/012216.html
|
# http://www.daa.com.au/pipermail/pygtk/2006-April/012216.html
|
||||||
def add_to_notebook(self, name, single_tweet=None):
|
def add_to_notebook(self, name, single_tweet=None):
|
||||||
try:
|
new_pane = TweetPane(name, self.num_entries, single_tweet)
|
||||||
new_pane = TweetPane(name, self, single_tweet)
|
|
||||||
except HTTPError:
|
|
||||||
return
|
|
||||||
self.tweet_notebook.append_page(new_pane, new_pane.get_tab_label())
|
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
|
self.tweet_notebook.set_current_page(-1) # switch to the new pane
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,6 +220,10 @@ class MyTwitter():
|
||||||
self.update_windows()
|
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
|
### end class MyTwitter
|
||||||
|
|
||||||
|
|
||||||
|
@ -226,14 +238,15 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
It also gets some data from its parent, including num_entries
|
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)
|
gtk.ScrolledWindow.__init__(self)
|
||||||
|
|
||||||
|
self.updated_once = False
|
||||||
|
|
||||||
self.single_tweet = single_tweet
|
self.single_tweet = single_tweet
|
||||||
|
|
||||||
self.list_name = list_name
|
self.list_name = list_name
|
||||||
|
|
||||||
self.mytwitter = mytwitter
|
|
||||||
self.tab_label = CloseTabLabel(self.list_name)
|
self.tab_label = CloseTabLabel(self.list_name)
|
||||||
|
|
||||||
# These handle determining which tweets are unread
|
# These handle determining which tweets are unread
|
||||||
|
@ -243,8 +256,8 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
|
|
||||||
self.tweets = []
|
self.tweets = []
|
||||||
|
|
||||||
self.num_entries = self.mytwitter.num_entries
|
self.num_entries = num_entries
|
||||||
if self.is_single_tweet():
|
if self.single_tweet is not None:
|
||||||
self.num_entries = 1
|
self.num_entries = 1
|
||||||
|
|
||||||
self.init_widgets()
|
self.init_widgets()
|
||||||
|
@ -260,10 +273,9 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
for i in range(0, self.num_entries):
|
for i in range(0, self.num_entries):
|
||||||
self.tweets.append(TweetBox())
|
self.tweets.append(TweetBox())
|
||||||
tweet_box.pack_start(self.tweets[i], expand=False)
|
tweet_box.pack_start(self.tweets[i], expand=False)
|
||||||
self.tweets[i].connect('reply', self.mytwitter.on_reply)
|
self.tweets[i].connect('reply', self.on_tweet_reply)
|
||||||
self.tweets[i].connect('retweet', self.mytwitter.on_retweet)
|
self.tweets[i].connect('retweet', self.on_retweet)
|
||||||
self.tweets[i].connect('in-reply-to', self.mytwitter.on_reply_to)
|
self.tweets[i].connect('in-reply-to', self.on_tweet_reply_to)
|
||||||
|
|
||||||
|
|
||||||
viewport.add(tweet_box)
|
viewport.add(tweet_box)
|
||||||
|
|
||||||
|
@ -277,9 +289,6 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||||
self.show_all()
|
self.show_all()
|
||||||
|
|
||||||
if self.is_single_tweet():
|
|
||||||
self.update_window(None)
|
|
||||||
|
|
||||||
|
|
||||||
def update_window(self, raw_statuses, using_results=False):
|
def update_window(self, raw_statuses, using_results=False):
|
||||||
if using_results:
|
if using_results:
|
||||||
|
@ -287,9 +296,8 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
else:
|
else:
|
||||||
statuses = raw_statuses
|
statuses = raw_statuses
|
||||||
|
|
||||||
if (self.is_single_tweet()):
|
if self.updated_once is False:
|
||||||
statuses = []
|
self.updated_once = True
|
||||||
statuses.append(self.mytwitter.api.GetStatus(self.single_tweet))
|
|
||||||
|
|
||||||
# If this is our first load of this list, don't treat anything as new!
|
# If this is our first load of this list, don't treat anything as new!
|
||||||
if self.last_tweet_read is None:
|
if self.last_tweet_read is None:
|
||||||
|
@ -339,8 +347,24 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
return self.tab_label
|
return self.tab_label
|
||||||
|
|
||||||
|
|
||||||
def is_single_tweet(self):
|
def get_single_tweet(self):
|
||||||
return self.single_tweet is not None
|
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
|
# To keep things simple elsewhere and improve code reuse
|
||||||
|
@ -370,6 +394,19 @@ class TweetPane(gtk.ScrolledWindow):
|
||||||
|
|
||||||
### end class TweetPane
|
### 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):
|
class TweetBox(gtk.VBox):
|
||||||
|
|
||||||
|
@ -524,6 +561,18 @@ class TweetBox(gtk.VBox):
|
||||||
|
|
||||||
# end class TweetBox
|
# 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):
|
class CloseTabLabel(gtk.EventBox):
|
||||||
'''
|
'''
|
||||||
|
@ -561,7 +610,7 @@ class CloseTabLabel(gtk.EventBox):
|
||||||
tabBox.pack_start(self.label, False)
|
tabBox.pack_start(self.label, False)
|
||||||
tabBox.pack_start(tabButton, 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
|
# needed, otherwise even calling show_all on the notebook won't
|
||||||
# make the hbox contents appear.
|
# make the hbox contents appear.
|
||||||
|
@ -574,18 +623,25 @@ class CloseTabLabel(gtk.EventBox):
|
||||||
|
|
||||||
|
|
||||||
def on_clicked(self, event):
|
def on_clicked(self, event):
|
||||||
self.emit('close_clicked')
|
self.emit('close-clicked')
|
||||||
|
|
||||||
|
|
||||||
def on_button_press(self, event, direction):
|
def on_button_press(self, event, direction):
|
||||||
self.emit('label_clicked')
|
self.emit('label-clicked')
|
||||||
|
|
||||||
|
|
||||||
### end class CloseTabLabel
|
### 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():
|
class Status():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.user = User()
|
self.user = User()
|
||||||
|
@ -600,22 +656,5 @@ class User():
|
||||||
|
|
||||||
# main
|
# 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()
|
my_twitter = MyTwitter()
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
Reference in New Issue
Block a user