5
Gwibber Client Interface Library
6
SegPhault (Ryan Paul) - 05/26/2007
10
import gtk, pango, gobject
11
import urllib2, base64, time, datetime, os
12
from service import twitter
14
DEFAULT_UPDATE_INTERVAL = 1000 * 60 * 5
16
class UpdateManager(gobject.GObject):
18
"twitter-update-starting": (gobject.SIGNAL_RUN_FIRST, None, (object,)),
19
"twitter-update-finished": (gobject.SIGNAL_RUN_FIRST, None, (object,)),
20
"twitter-update-nochange": (gobject.SIGNAL_RUN_FIRST, None, (object,)),
21
"twitter-update-failed": (gobject.SIGNAL_RUN_FIRST, None, (object,)),
22
"twitter-update-change": (gobject.SIGNAL_RUN_FIRST, None, (object,)),
24
def __init__(self, twit, interval=DEFAULT_UPDATE_INTERVAL, timeline=twitter.FRIENDS_TIMELINE):
25
self.__gobject_init__()
26
self.twitter, self.last_update, self.timeline = twit, None, timeline
27
self.set_interval(interval)
29
def set_interval(self, interval):
30
self.refresh_interval = interval
31
if hasattr(self, "timeout"): gobject.source_remove(self.timeout)
32
self.timeout = gobject.timeout_add(self.refresh_interval, self.update)
35
if self.last_update and self.data:
37
if f == self.last_update[0]: break
41
self.emit("twitter-update-starting", self)
43
self.data = tuple(self.twitter.get_timeline(self.timeline))
44
if self.data == self.last_update: self.emit("twitter-update-nochange", self.data)
45
else: self.emit("twitter-update-change", list(self.compare()))
46
self.last_update = self.data
47
except: self.emit("twitter-update-failed", self)
48
self.emit("twitter-update-finished", self.data)
51
class StatusMessage(gtk.TextView):
52
def __init__(self, name, message, created_at):
53
gtk.TextView.__init__(self)
54
self.set_wrap_mode(gtk.WRAP_WORD)
55
self.set_editable(False)
57
self.modify_base(gtk.STATE_NORMAL,
58
gtk.Image().rc_get_style().bg[gtk.STATE_NORMAL])
60
self.new_tag("name", weight=pango.WEIGHT_BOLD, scale=pango.SCALE_LARGE)
61
self.new_tag("time", scale=pango.SCALE_SMALL)
62
self.new_tag("text", pixels_above_lines=4)
64
self.add_text(name, "name")
65
self.add_text(" (%s)" % created_at, "time")
66
self.add_text("\n%s" % message, "text")
68
def add_text(self, text, tag=None):
70
self.get_buffer().insert_with_tags_by_name(
71
self.get_buffer().get_bounds()[1], text, tag)
72
else: self.get_buffer().insert(self.get_buffer().get_bounds()[1], text)
74
def new_tag(self, name, **props):
75
tag = gtk.TextTag(name)
76
for k, v in props.items(): tag.set_property(k, v)
77
self.get_buffer().get_tag_table().add(tag)
79
class UserIcon(gtk.Image):
80
def __init__(self, user):
81
gtk.Image.__init__(self)
82
self.set_from_file(self.user_image_path(user))
85
def user_image_path(self, user, cache_dir="%s/.gwibber/imgcache" % os.path.expanduser("~")):
86
timestamp = user["profile_image_url"].split("/")[-1].split("?")[-1]
87
if not os.path.exists(cache_dir): os.makedirs(cache_dir)
88
img_path = os.path.join(cache_dir, "%s-%s" % (user["id"], timestamp))
90
if not os.path.exists(img_path):
91
output = open(img_path, "w+")
92
output.write(urllib2.urlopen(user["profile_image_url"]).read())
97
class StatusList(gtk.VBox):
98
def __init__(self, data):
99
gtk.VBox.__init__(self)
100
self.set_spacing(5); self.set_border_width(5)
102
for user, status in data:
103
hb = gtk.HBox(); hb.set_border_width(5); hb.set_spacing(10)
104
hb.pack_start(UserIcon(user), False, False)
105
hb.pack_start(StatusMessage(user["name"], status["text"],
106
twitter.parse_time(status["created_at"])))
108
frame = gtk.Frame(); frame.add(hb)
109
self.pack_start(frame, False, False)