]> git.saurik.com Git - wxWidgets.git/blame - utils/wxPython/tests/wxSlash.py
Added more makefiles
[wxWidgets.git] / utils / wxPython / tests / wxSlash.py
CommitLineData
18b79501
HH
1#!/usr/bin/python
2from wxPython.wx import *
3from httplib import HTTP
4from htmllib import HTMLParser
5import os
6import re
7import formatter
8
9__doc__ = """This is wxSlash 1.0
10
11 It's the obligatory Slashdot.org headlines reader that any modern
12widget set/library must have in order to be taken seriously :-)
13
14 Usage is quite simple; wxSlash attempts to download the 'ultramode.txt'
15file from http://slashdot.org, which contains the headlines in a computer
16friendly format. It then displays said headlines in a wxWindows list control.
17
73c5ed36 18 You can read articles using either Python's html library or an external
18b79501
HH
19browser. Uncheck the 'browser->internal' menu item to use the latter option.
20Use the settings dialog box to set how external browser is started.
21
22 This code is available under the wxWindows license, see elsewhere. If you
23modify this code, be aware of the fact that slashdot.org's maintainer,
73c5ed36 24CmdrTaco, explicitly asks 'ultramode.txt' downloaders not to do this
18b79501
HH
25automatically more than twice per hour. If this feature is abused, CmdrTaco
26may remove the ultramode file completely and that will make a *lot* of people
27unhappy.
28
29 I want to thank Alex Shnitman whose slashes.pl (Perl/GTK) script gave me
30the idea for this applet.
31
32 Have fun with it,
33
34 Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)
35"""
36
37class HTMLTextView(wxFrame):
38 def __init__(self, parent, id, title='HTMLTextView', url=None):
39 wxFrame.__init__(self, parent, id, title, wxPyDefaultPosition,
40 wxSize(600,400))
41
42 self.mainmenu = wxMenuBar()
43
44 menu = wxMenu()
45 menu.Append(201, '&Open URL...', 'Open URL')
46 EVT_MENU(self, 201, self.OnFileOpen)
47 menu.Append(209, 'E&xit', 'Exit viewer')
48 EVT_MENU(self, 209, self.OnFileExit)
49
50 self.mainmenu.Append(menu, '&File')
51 self.SetMenuBar(self.mainmenu)
52 self.CreateStatusBar(1)
73c5ed36 53
18b79501
HH
54 self.text = wxTextCtrl(self, -1, "", wxPyDefaultPosition,
55 wxPyDefaultSize, wxTE_MULTILINE | wxTE_READONLY)
56
57 if (url):
58 self.OpenURL(url)
59
60 def logprint(self, x):
61 self.SetStatusText(x)
73c5ed36 62
18b79501
HH
63 def OpenURL(self, url):
64 self.url = url
65 m = re.match('file:(\S+)\s*', url)
66 if m:
67 f = open(m.groups()[0],'r')
68 else:
69 m = re.match('http://([^/]+)(/\S*)\s*', url)
70 if m:
71 host = m.groups()[0]
72 path = m.groups()[1]
73 else:
74 m = re.match('http://(\S+)\s*', url)
75 if not m:
76 # Invalid URL
77 self.logprint("Invalid or unsupported URL: %s" % (url))
78 return
79 host = m.groups()[0]
80 path = ''
81 f = RetrieveAsFile(host,path,self.logprint)
82 if not f:
83 self.logprint("Could not open %s" % (url))
84 return
85 self.logprint("Receiving data...")
86 data = f.read()
f855e630 87 tmp = open('tmphtml.txt','w')
18b79501
HH
88 fmt = formatter.AbstractFormatter(formatter.DumbWriter(tmp))
89 p = HTMLParser(fmt)
90 self.logprint("Parsing data...")
91 p.feed(data)
92 p.close()
93 tmp.close()
f855e630 94 tmp = open('tmphtml.txt', 'r')
18b79501
HH
95 self.text.SetValue(tmp.read())
96 self.SetTitle(url)
97 self.logprint(url)
73c5ed36 98
18b79501
HH
99 def OnFileOpen(self, event):
100 dlg = wxTextEntryDialog(self, "Enter URL to open:", "")
101 if dlg.ShowModal() == wxID_OK:
102 url = dlg.GetValue()
103 else:
104 url = None
105 if url:
106 self.OpenURL(url)
107
108 def OnFileExit(self, event):
109 self.Close()
110
111 def OnCloseWindow(self, event):
112 self.Destroy()
73c5ed36 113
18b79501
HH
114
115def ParseSlashdot(f):
116 art_sep = re.compile('%%\r?\n')
117 line_sep = re.compile('\r?\n')
118 data = f.read()
119 list = art_sep.split(data)
120 art_list = []
121 for i in range(1,len(list)-1):
122 art_list.append(line_sep.split(list[i]))
123 return art_list
73c5ed36 124
18b79501
HH
125def myprint(x):
126 print x
73c5ed36 127
18b79501
HH
128def RetrieveAsFile(host, path='', logprint = myprint):
129 try:
130 h = HTTP(host)
131 except:
132 logprint("Failed to create HTTP connection to %s... is the network available?" % (host))
133 return None
134 h.putrequest('GET',path)
135 h.putheader('Accept','text/html')
136 h.putheader('Accept','text/plain')
137 h.endheaders()
138 errcode, errmsg, headers = h.getreply()
139 if errcode != 200:
140 logprint("HTTP error code %d: %s" % (errcode, errmsg))
141 return None
142 f = h.getfile()
143# f = open('/home/harm/ultramode.txt','r')
144 return f
145
73c5ed36 146
18b79501
HH
147class AppStatusBar(wxStatusBar):
148 def __init__(self, parent):
149 wxStatusBar.__init__(self,parent, -1)
150 self.SetFieldsCount(2)
151 self.SetStatusWidths([100,-1])
152 self.but = wxButton(self, 1001, "Refresh")
153 EVT_BUTTON(self, 1001, parent.OnViewRefresh)
154 self.OnSize(None)
73c5ed36 155
18b79501
HH
156 def logprint(self,x):
157 self.SetStatusText(x,1)
158
159 def OnSize(self, event):
160 rect = self.GetFieldRect(0)
161 self.but.SetPosition(wxPoint(rect.x+2, rect.y+2))
162 # The width/height we get is false. Why? Now I use a stupid trick:
163 rect2 = self.GetFieldRect(1)
164 rect.width = rect2.x - 8;
165 rect.height = 25;
166 self.but.SetSize(wxSize(rect.width-4, rect.height-4))
167
168# This is a simple timer class to start a function after a short delay;
169# For example, if you're about to perform function f which may take a long
170# time, write "Please wait" in the statusbar, then create a QuickTimer(f)
171# object to automatically call f after a short delay. That way, wxWindows
73c5ed36 172# will get a chance to update the statusbar before the long function is
18b79501
HH
173# called.
174# FIXME: can this be done better using an OnIdle kind of thing?
175class QuickTimer(wxTimer):
176 def __init__(self, func, wait=100):
177 wxTimer.__init__(self)
178 self.callback = func
179 self.Start(wait); # wait .1 second (.001 second doesn't work. why?)
180 def Notify(self):
181 self.Stop();
182 apply(self.callback, ());
183
184class AppFrame(wxFrame):
185 def __init__(self, parent, id, title):
186 wxFrame.__init__(self, parent, id, title, wxPyDefaultPosition,
187 wxSize(650, 250))
188
189 # if the window manager closes the window:
190 EVT_CLOSE(self, self.OnCloseWindow);
191
192 # Now Create the menu bar and items
193 self.mainmenu = wxMenuBar()
194
195 menu = wxMenu()
196 menu.Append(209, 'E&xit', 'Enough of this already!')
197 EVT_MENU(self, 209, self.OnFileExit)
198 self.mainmenu.Append(menu, '&File')
199 menu = wxMenu()
200 menu.Append(210, '&Refresh', 'Refresh headlines')
201 EVT_MENU(self, 210, self.OnViewRefresh)
202 menu.Append(211, '&Slashdot Index', 'View Slashdot index')
203 EVT_MENU(self, 211, self.OnViewIndex)
204 menu.Append(212, 'Selected &Article', 'View selected article')
205 EVT_MENU(self, 212, self.OnViewArticle)
206 self.mainmenu.Append(menu, '&View')
207 menu = wxMenu()
208 menu.Append(220, '&Internal', 'Use internal text browser',TRUE)
209 menu.Check(220, true)
210 self.UseInternal = 1;
211 EVT_MENU(self, 220, self.OnBrowserInternal)
212 menu.Append(222, '&Settings...', 'External browser Settings')
213 EVT_MENU(self, 222, self.OnBrowserSettings)
214 self.mainmenu.Append(menu, '&Browser')
215 menu = wxMenu()
216 menu.Append(230, '&About', 'Some documentation');
217 EVT_MENU(self, 230, self.OnAbout)
218 self.mainmenu.Append(menu, '&Help')
73c5ed36 219
18b79501 220 self.SetMenuBar(self.mainmenu)
73c5ed36 221
18b79501 222 self.BrowserSettings = "netscape -remote 'OpenURL(%s, new_window)'"
73c5ed36 223
18b79501
HH
224 # A status bar to tell people what's happening
225 self.sb = AppStatusBar(self)
226 self.SetStatusBar(self.sb)
73c5ed36 227
18b79501
HH
228 self.list = wxListCtrl(self, 1100)
229 self.list.SetSingleStyle(wxLC_REPORT)
230 self.list.InsertColumn(0, 'Subject')
231 self.list.InsertColumn(1, 'Date')
232 self.list.InsertColumn(2, 'Posted by')
233 self.list.InsertColumn(3, 'Comments')
234 self.list.SetColumnWidth(0, 300)
235 self.list.SetColumnWidth(1, 150)
236 self.list.SetColumnWidth(2, 100)
237 self.list.SetColumnWidth(3, 100)
238
239 EVT_LIST_ITEM_SELECTED(self, 1100, self.OnItemSelected)
73c5ed36 240
18b79501
HH
241 self.logprint("Connecting to slashdot... Please wait.")
242 # Need a longer time here. Don't really know why
243 self.timer = QuickTimer(self.DoRefresh, 1000)
244
245 def logprint(self, x):
246 self.sb.logprint(x)
73c5ed36 247
18b79501
HH
248 def OnFileExit(self, event):
249 self.Destroy()
250
251 def DoRefresh(self):
252 f = RetrieveAsFile('slashdot.org','/ultramode.txt',self.sb.logprint)
253 art_list = ParseSlashdot(f)
254 self.list.DeleteAllItems()
255 self.url = []
256 self.current = -1
257 i = 0;
258 for article in art_list:
259 self.list.InsertStringItem(i, article[0])
260 self.list.SetItemString(i, 1, article[2])
261 self.list.SetItemString(i, 2, article[3])
262 self.list.SetItemString(i, 3, article[6])
263 self.url.append(article[1])
264 i = i + 1
265 self.logprint("File retrieved OK.")
266
267 def OnViewRefresh(self, event):
268 self.timer = QuickTimer(self.DoRefresh)
269 self.logprint("Connecting to slashdot... Please wait.");
270
271 def DoViewIndex(self):
272 if self.UseInternal:
273 self.view = HTMLTextView(self, -1, 'slashdot.org',
274 'http://slashdot.org')
275 self.view.Show(true)
276 else:
277 self.logprint(self.BrowserSettings % ('http://slashdot.org'))
278 os.system(self.BrowserSettings % ('http://slashdot.org'))
279 self.logprint("OK")
280
281 def OnViewIndex(self, event):
282 self.logprint("Starting browser... Please wait.")
283 self.timer = QuickTimer(self.DoViewIndex)
284
285 def DoViewArticle(self):
286 if self.current<0: return
287 url = self.url[self.current]
288 if self.UseInternal:
289 self.view = HTMLTextView(self, -1, url, url)
290 self.view.Show(true)
291 else:
292 self.logprint(self.BrowserSettings % (url))
293 os.system(self.BrowserSettings % (url))
294 self.logprint("OK")
295
296 def OnViewArticle(self, event):
297 self.logprint("Starting browser... Please wait.")
298 self.timer = QuickTimer(self.DoViewArticle)
299
300 def OnBrowserInternal(self, event):
301 if self.mainmenu.Checked(220):
302 self.UseInternal = 1
303 else:
304 self.UseInternal = 0
73c5ed36 305
18b79501
HH
306 def OnBrowserSettings(self, event):
307 dlg = wxTextEntryDialog(self, "Enter command to view URL.\nUse %s as a placeholder for the URL.", "", self.BrowserSettings);
308 if dlg.ShowModal() == wxID_OK:
309 self.BrowserSettings = dlg.GetValue()
310
311 def OnAbout(self, event):
312 dlg = wxMessageDialog(self, __doc__, "wxSlash", wxOK | wxICON_INFORMATION)
313 dlg.ShowModal()
73c5ed36 314
18b79501
HH
315 def OnItemSelected(self, event):
316 self.current = event.m_itemIndex
317 self.logprint("URL: %s" % (self.url[self.current]))
73c5ed36 318
18b79501
HH
319 def OnCloseWindow(self, event):
320 self.Destroy()
321
322class MyApp(wxApp):
323 def OnInit(self):
324 frame = AppFrame(NULL, -1, "Slashdot Breaking News")
325 frame.Show(true)
326 self.SetTopWindow(frame)
327 return true
328
329#
330# main thingy
331#
332if __name__ == '__main__':
333 app = MyApp(0)
334 app.MainLoop()
335
336
337
338
339