diff --git a/README b/README
index 2415c25..1ec4fc7 100644
--- a/README
+++ b/README
@@ -7,8 +7,7 @@ mytwitter is a simple python twitter application. I wrote it for two reasons:
While I doubt it will be terribly useful for anyone other than me, feel free to take it for a spin and let me know how it goes. You'll need the following python modules:
-* Pmw
-* Tkinter
+* pyGTK
* dateutil
* twitter (the dev version, not 0.6), along with my patch (included here)
diff --git a/default.glade b/default.glade
new file mode 100644
index 0000000..c62476b
--- /dev/null
+++ b/default.glade
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+ True
+ MyTwitter
+ GTK_WINDOW_TOPLEVEL
+ GTK_WIN_POS_NONE
+ False
+ 400
+ 600
+ True
+ False
+ True
+ False
+ False
+ GDK_WINDOW_TYPE_HINT_NORMAL
+ GDK_GRAVITY_NORTH_WEST
+ True
+ False
+
+
+
+ True
+ False
+ 0
+
+
+
+
+ 0
+ False
+ False
+
+
+
+
+
+
+ 0
+ True
+ True
+
+
+
+
+
+ True
+ False
+ 0
+
+
+
+ True
+ True
+ Refresh
+ True
+ GTK_RELIEF_NORMAL
+ True
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ Friends
+ False
+ True
+ True
+
+
+
+ 0
+ False
+ False
+
+
+
+
+
+
+
+
+ 0
+ False
+ True
+
+
+
+
+
+ True
+ False
+ 0
+
+
+
+ True
+ True
+ True
+ True
+ 140
+
+ True
+ •
+ False
+
+
+
+ 0
+ True
+ True
+
+
+
+
+
+ True
+ True
+ Update
+ True
+ GTK_RELIEF_NORMAL
+ True
+
+
+
+ 0
+ False
+ False
+
+
+
+
+
+ True
+ 0/140
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0.5
+ 0.5
+ 0
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 0
+ False
+ False
+
+
+
+
+ 0
+ False
+ True
+
+
+
+
+
+ True
+ True
+
+
+ 0
+ False
+ False
+
+
+
+
+
+
+
diff --git a/mytwitter.py b/mytwitter.py
index 488b05a..6b3b356 100755
--- a/mytwitter.py
+++ b/mytwitter.py
@@ -2,16 +2,14 @@
#
# Custom twitter client... mostly for learning Python
-import sys, twitter, wx, ConfigParser, os, tkMessageBox, datetime, dateutil.tz
+import sys, twitter, ConfigParser, os, datetime, dateutil.tz, gtk, gtk.glade, gobject
-class TwitWindow(wx.Frame):
+class MyTwitter():
""" Display Tweets, post to twitter """
- def __init__(self, parent, title):
- wx.Frame.__init__(self, parent, title=title, size=(300,600))
-
+ def __init__(self):
config = ConfigParser.ConfigParser()
config.read(os.path.expanduser("~/.mytwitter"))
self.username = config.get('global', 'username')
@@ -22,101 +20,45 @@ class TwitWindow(wx.Frame):
self.labels = []
self.texts = []
+ # Authenticate with twitter, set up the API object
+ self.api = twitter.Api(username=self.username, password=self.password)
+
+ # Load up all the GUI stuff
+ self.init_user_interface('./default.glade')
self.init_widgets()
+ def init_user_interface(self, path_to_skin):
+ self.widget_tree=gtk.glade.XML(path_to_skin, "window")
+ self.widget_tree.signal_autoconnect(self)
+
+
def init_widgets(self):
- main_sizer = wx.BoxSizer(wx.VERTICAL)
+ self.tweet_box = self.widget_tree.get_widget('tweet_box')
+ self.update_entry = self.widget_tree.get_widget('update_entry')
+ self.update_count = self.widget_tree.get_widget('update_count')
- # Create the scrolled frame that will hold the tweets
- tweet_view = wx.ScrolledWindow(self)
- tweet_sizer = wx.BoxSizer(wx.VERTICAL)
-
- # Status bar
- self.CreateStatusBar()
-
- # Menu bar
- filemenu = wx.Menu()
- filemenu.Append(wx.ID_ABOUT, "&About", "About MyTwitter")
- menu_exit = filemenu.Append(wx.ID_EXIT, "E&xit", "Close MyTwitter")
- self.Bind(wx.EVT_MENU, self.on_exit, menu_exit)
-
- menu_bar = wx.MenuBar()
- menu_bar.Append(filemenu, "&File")
-
- self.SetMenuBar(menu_bar)
-
- # Create labels and text widgets
+ # Build us some labels...
for i in range(0, self.num_entries):
- self.labels.append(wx.TextCtrl(tweet_view, style=wx.TE_READONLY))
- self.texts.append(wx.TextCtrl(tweet_view, style=wx.TE_MULTILINE | wx.TE_READONLY))
- self.labels[i].SetDefaultStyle(wx.TextAttr('DARK_BLUE'))
- self.texts[i].SetDefaultStyle(wx.TextAttr('LIGHT_BLUE'))
- tweet_sizer.Add(self.labels[i])
- tweet_sizer.Add(self.texts[i])
+ self.labels.append(gtk.Label())
+ self.tweet_box.pack_start(self.labels[i])
+ self.labels[i].set_alignment(0.0, 0.0)
+ self.labels[i].set_selectable(True)
+ self.labels[i].set_line_wrap(True)
+ self.texts.append(gtk.Label())
+ self.tweet_box.pack_start(self.texts[i])
+ self.texts[i].set_alignment(0.0, 0.0)
+ self.texts[i].set_selectable(True)
+ self.texts[i].set_line_wrap(True)
- # Layout the tweet view widget
- width,height=tweet_view.GetSizeTuple()
- tweet_view.SetSizerAndFit(tweet_sizer)
- tweet_view.SetScrollbars(0, 20, 0, height/20)
- tweet_view.SetSize((300,400))
-
- # A button to refresh manually
- button_sizer = wx.BoxSizer(wx.HORIZONTAL)
- refresh_button = wx.Button(self, label="Refresh")
- refresh_button.Bind(wx.EVT_BUTTON, self.update_window)
+ self.tweet_box.show_all()
- button_sizer.Add(refresh_button)
-
- # Create an update box at the bottom of the window
- update_sizer = wx.BoxSizer(wx.HORIZONTAL)
-
- self.update_entry = wx.TextCtrl(self)
- self.update_entry.Bind(wx.EVT_TEXT, self.char_counter)
- self.update_entry.Bind(wx.EVT_TEXT_ENTER, self.update_status_callback)
-
- update_button = wx.Button(self, label="Update")
- update_button.Bind(wx.EVT_BUTTON, self.update_status)
-
- self.update_count = wx.StaticText(self, label="0/140")
-
- update_sizer.Add(self.update_entry, 1, wx.EXPAND)
- update_sizer.Add(update_button)
- update_sizer.Add(self.update_count)
-
- ### Set up bindings
-
- # Bind scrollwheel to move the tweets, as well as page up/down
- # fixme: convert this to wxPython
- # self.tkroot.bind_all("", self.scroll_wheel)
- # self.tkroot.bind_all("", self.scroll_wheel)
- # self.tkroot.bind_all("", self.line_up)
- # self.tkroot.bind_all("", self.line_down)
- # self.tkroot.bind_all("", self.page_up)
- # self.tkroot.bind_all("", self.page_down)
-
- # Pack the top level together
- main_sizer.Add(tweet_view, 1, wx.EXPAND)
- main_sizer.Add(button_sizer)
- main_sizer.Add(update_sizer)
-
- self.SetSizerAndFit(main_sizer)
-
- # Init the twitter API
- self.api = twitter.Api(username=self.username, password=self.password)
-
- # Updates!
- self.timer = wx.Timer(self)
- self.timer.Bind(wx.EVT_TIMER, self.update_window_callback)
- self.timer.Start(self.refresh_time * 1000)
+ # Timer to update periodically
self.update_window()
-
- # end of init_widgets
+ gobject.timeout_add(self.refresh_time * 100, self.update_window)
def update_window(self):
- print "DEBUG: update_window()"
-
timezone = dateutil.tz.gettz()
time_format = "%Y.%m.%d %H:%M:%S %Z"
@@ -131,33 +73,22 @@ class TwitWindow(wx.Frame):
timestring = timestamp.astimezone(timezone).strftime(time_format)
labeltext = user.name + " (" + user.screen_name + ") " + timestring
- self.labels[i].Clear()
- self.labels[i].AppendText(labeltext)
+ self.labels[i].set_text(labeltext)
# Display the text of the tweet
- self.texts[i].Clear()
- self.texts[i].AppendText(statuses[i].text)
-
-
- def update_window_callback(self, event):
- self.update_window()
+ self.texts[i].set_text(statuses[i].text)
def update_status(self):
- text = self.update_entry.GetValue()
- if len(text) > 140:
- d = wx.MessageDialog(self, 'Tweet too long', 'Tweets must be <= 140 characters');
- d.ShowModal()
- d.Destroy()
- return
- self.update_entry.Clear()
+ text = self.update_entry.get_text()
+ self.update_entry.set_text(none)
self.api.PostUpdate(text)
self.update_window()
# Just calls update_status, here so that things
# that pass an event can be used
- def update_status_callback(self, event):
+ def update_status_callback(self, widget):
self.update_status()
@@ -186,12 +117,18 @@ class TwitWindow(wx.Frame):
# self.tweet_view.yview('scroll', 5, 'units');
- def char_counter(self, event):
- new_count = str(len(self.update_entry.GetValue())) + "/140"
- self.update_count.SetLabel(new_count)
+ def char_counter(self, widget):
+ new_count = str(len(self.update_entry.get_text())) + "/140"
+ self.update_count.set_label(new_count)
+
+
+ def gtk_main_quit(self, widget):
+ gtk.main_quit()
+
+
+ def on_about(self, widget):
+ print "DEBUG: help->about not yet implemented"
- def on_exit(self, event):
- self.Close(True)
### end class TwitWindow
@@ -218,7 +155,5 @@ def print_formatted(statuses):
# main
-app = wx.App(False)
-root = TwitWindow(None, "MyTwitter")
-root.Show(True)
-app.MainLoop()
+my_twitter = MyTwitter()
+gtk.main()