]> git.saurik.com Git - wxWidgets.git/commitdiff
The obligatory Slashdot headlines retriever. Every self-respecting modern
authorHarco de Hilster <harcoh@caos.kun.nl>
Sun, 31 Jan 1999 19:55:22 +0000 (19:55 +0000)
committerHarco de Hilster <harcoh@caos.kun.nl>
Sun, 31 Jan 1999 19:55:22 +0000 (19:55 +0000)
widget library has to have one... I think it also makes a nice demonstration
of wxPython's capabilities.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1536 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

utils/wxPython/tests/wxSlash.py [new file with mode: 0644]

diff --git a/utils/wxPython/tests/wxSlash.py b/utils/wxPython/tests/wxSlash.py
new file mode 100644 (file)
index 0000000..855389a
--- /dev/null
@@ -0,0 +1,342 @@
+#!/usr/bin/python
+from wxPython.wx import *
+from httplib import HTTP
+from htmllib import HTMLParser
+import os
+import re
+import formatter
+
+__doc__ = """This is wxSlash 1.0
+
+    It's the obligatory Slashdot.org headlines reader that any modern
+widget set/library must have in order to be taken seriously :-)
+
+    Usage is quite simple; wxSlash attempts to download the 'ultramode.txt'
+file from http://slashdot.org, which contains the headlines in a computer
+friendly format. It then displays said headlines in a wxWindows list control.
+
+    You can read articles using either Python's html library or an external 
+browser. Uncheck the 'browser->internal' menu item to use the latter option.
+Use the settings dialog box to set how external browser is started.
+
+    This code is available under the wxWindows license, see elsewhere. If you
+modify this code, be aware of the fact that slashdot.org's maintainer,
+CmdrTaco, explicitly asks 'ultramode.txt' downloaders not to do this 
+automatically more than twice per hour. If this feature is abused, CmdrTaco
+may remove the ultramode file completely and that will make a *lot* of people
+unhappy.
+
+    I want to thank Alex Shnitman whose slashes.pl (Perl/GTK) script gave me
+the idea for this applet.
+
+    Have fun with it,
+
+    Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)
+"""
+
+class HTMLTextView(wxFrame):
+    def __init__(self, parent, id, title='HTMLTextView', url=None):
+        wxFrame.__init__(self, parent, id, title, wxPyDefaultPosition,
+                         wxSize(600,400))
+
+        self.mainmenu = wxMenuBar()
+
+        menu = wxMenu()
+        menu.Append(201, '&Open URL...', 'Open URL')
+        EVT_MENU(self, 201, self.OnFileOpen)
+        menu.Append(209, 'E&xit', 'Exit viewer')
+        EVT_MENU(self, 209, self.OnFileExit)
+
+        self.mainmenu.Append(menu, '&File')
+        self.SetMenuBar(self.mainmenu)
+        self.CreateStatusBar(1)
+        
+        self.text = wxTextCtrl(self, -1, "", wxPyDefaultPosition,
+                               wxPyDefaultSize, wxTE_MULTILINE | wxTE_READONLY)
+
+        if (url):
+            self.OpenURL(url)
+
+    def logprint(self, x):
+        self.SetStatusText(x)
+        
+    def OpenURL(self, url):
+        self.url = url
+        m = re.match('file:(\S+)\s*', url)
+        if m:
+            f = open(m.groups()[0],'r')
+        else:
+            m = re.match('http://([^/]+)(/\S*)\s*', url)
+            if m:
+                host = m.groups()[0]
+                path = m.groups()[1]
+            else:
+                m = re.match('http://(\S+)\s*', url)
+                if not m:
+                    # Invalid URL
+                    self.logprint("Invalid or unsupported URL: %s" % (url))
+                    return
+                host = m.groups()[0]
+                path = ''
+            f = RetrieveAsFile(host,path,self.logprint)
+        if not f:
+            self.logprint("Could not open %s" % (url))
+            return
+        self.logprint("Receiving data...")
+        data = f.read()
+        tmp = open('/tmp/html.txt','w')
+        fmt = formatter.AbstractFormatter(formatter.DumbWriter(tmp))
+        p = HTMLParser(fmt)
+        self.logprint("Parsing data...")
+        p.feed(data)
+        p.close()
+        tmp.close()
+        tmp = open('/tmp/html.txt', 'r')
+        self.text.SetValue(tmp.read())
+        self.SetTitle(url)
+        self.logprint(url)
+        
+    def OnFileOpen(self, event):
+        dlg = wxTextEntryDialog(self, "Enter URL to open:", "")
+        if dlg.ShowModal() == wxID_OK:
+            url = dlg.GetValue()
+        else:
+            url = None
+        if url:
+            self.OpenURL(url)
+
+    def OnFileExit(self, event):
+        self.Close()
+
+    def OnCloseWindow(self, event):
+        self.Destroy()
+        
+
+def ParseSlashdot(f):
+    art_sep = re.compile('%%\r?\n')
+    line_sep = re.compile('\r?\n')
+    data = f.read()
+    list = art_sep.split(data)
+    art_list = []
+    for i in range(1,len(list)-1):
+        art_list.append(line_sep.split(list[i]))
+    return art_list
+        
+def myprint(x):
+    print x
+    
+def RetrieveAsFile(host, path='', logprint = myprint):
+    try:
+        h = HTTP(host)
+    except:
+        logprint("Failed to create HTTP connection to %s... is the network available?" % (host))
+        return None
+    h.putrequest('GET',path)
+    h.putheader('Accept','text/html')
+    h.putheader('Accept','text/plain')
+    h.endheaders()
+    errcode, errmsg, headers = h.getreply()
+    if errcode != 200:
+        logprint("HTTP error code %d: %s" % (errcode, errmsg))
+        return None
+    f = h.getfile()
+#    f = open('/home/harm/ultramode.txt','r')
+    return f
+
+# This one isn't defined in the default wxPython modules...
+def EVT_LIST_ITEM_SELECTED(win, id, func):
+    win.Connect(id, -1, wxEVT_COMMAND_LIST_ITEM_SELECTED, func)
+    
+class AppStatusBar(wxStatusBar):
+    def __init__(self, parent):
+        wxStatusBar.__init__(self,parent, -1)
+        self.SetFieldsCount(2)
+        self.SetStatusWidths([100,-1])
+        self.but = wxButton(self, 1001, "Refresh")
+        EVT_BUTTON(self, 1001, parent.OnViewRefresh)
+        self.OnSize(None)
+        
+    def logprint(self,x):
+        self.SetStatusText(x,1)
+
+    def OnSize(self, event):
+        rect = self.GetFieldRect(0)
+        self.but.SetPosition(wxPoint(rect.x+2, rect.y+2))
+       # The width/height we get is false. Why? Now I use a stupid trick:
+       rect2 = self.GetFieldRect(1)
+       rect.width = rect2.x - 8;
+       rect.height = 25;
+        self.but.SetSize(wxSize(rect.width-4, rect.height-4))
+
+# This is a simple timer class to start a function after a short delay;
+# For example, if you're about to perform function f which may take a long
+# time, write "Please wait" in the statusbar, then create a QuickTimer(f)
+# object to automatically call f after a short delay. That way, wxWindows
+# will get a chance to update the statusbar before the long function is 
+# called.
+# FIXME: can this be done better using an OnIdle kind of thing?
+class QuickTimer(wxTimer):
+    def __init__(self, func, wait=100):
+       wxTimer.__init__(self)
+       self.callback = func
+       self.Start(wait); # wait .1 second (.001 second doesn't work. why?)
+    def Notify(self):
+       self.Stop();
+       apply(self.callback, ());
+
+class AppFrame(wxFrame):
+    def __init__(self, parent, id, title):
+        wxFrame.__init__(self, parent, id, title, wxPyDefaultPosition,
+                         wxSize(650, 250))
+
+       # if the window manager closes the window:
+       EVT_CLOSE(self, self.OnCloseWindow);
+
+       # Now Create the menu bar and items
+        self.mainmenu = wxMenuBar()
+
+        menu = wxMenu()
+        menu.Append(209, 'E&xit', 'Enough of this already!')
+        EVT_MENU(self, 209, self.OnFileExit)
+        self.mainmenu.Append(menu, '&File')
+        menu = wxMenu()
+        menu.Append(210, '&Refresh', 'Refresh headlines')
+        EVT_MENU(self, 210, self.OnViewRefresh)
+        menu.Append(211, '&Slashdot Index', 'View Slashdot index')
+        EVT_MENU(self, 211, self.OnViewIndex)
+        menu.Append(212, 'Selected &Article', 'View selected article')
+        EVT_MENU(self, 212, self.OnViewArticle)
+        self.mainmenu.Append(menu, '&View')
+        menu = wxMenu()
+        menu.Append(220, '&Internal', 'Use internal text browser',TRUE)
+        menu.Check(220, true)
+        self.UseInternal = 1;
+        EVT_MENU(self, 220, self.OnBrowserInternal)
+        menu.Append(222, '&Settings...', 'External browser Settings')
+        EVT_MENU(self, 222, self.OnBrowserSettings)
+        self.mainmenu.Append(menu, '&Browser')
+       menu = wxMenu()
+       menu.Append(230, '&About', 'Some documentation');
+       EVT_MENU(self, 230, self.OnAbout)
+       self.mainmenu.Append(menu, '&Help')
+        
+        self.SetMenuBar(self.mainmenu)
+        
+        self.BrowserSettings = "netscape -remote 'OpenURL(%s, new_window)'"
+        
+       # A status bar to tell people what's happening
+       self.sb = AppStatusBar(self)
+        self.SetStatusBar(self.sb)
+        
+        self.list = wxListCtrl(self, 1100)
+       self.list.SetSingleStyle(wxLC_REPORT)
+       self.list.InsertColumn(0, 'Subject')
+       self.list.InsertColumn(1, 'Date')
+       self.list.InsertColumn(2, 'Posted by')
+       self.list.InsertColumn(3, 'Comments')
+        self.list.SetColumnWidth(0, 300)
+        self.list.SetColumnWidth(1, 150)
+        self.list.SetColumnWidth(2, 100)
+        self.list.SetColumnWidth(3, 100)
+
+        EVT_LIST_ITEM_SELECTED(self, 1100, self.OnItemSelected)
+        
+       self.logprint("Connecting to slashdot... Please wait.")
+       # Need a longer time here. Don't really know why
+       self.timer = QuickTimer(self.DoRefresh, 1000)
+
+    def logprint(self, x):
+        self.sb.logprint(x)
+        
+    def OnFileExit(self, event):
+        self.Destroy()
+
+    def DoRefresh(self):
+        f = RetrieveAsFile('slashdot.org','/ultramode.txt',self.sb.logprint)
+        art_list = ParseSlashdot(f)
+        self.list.DeleteAllItems()
+        self.url = []
+        self.current = -1
+        i = 0;
+        for article in art_list:
+            self.list.InsertStringItem(i, article[0])
+            self.list.SetItemString(i, 1, article[2])
+            self.list.SetItemString(i, 2, article[3])
+            self.list.SetItemString(i, 3, article[6])
+            self.url.append(article[1])
+            i = i + 1
+       self.logprint("File retrieved OK.")
+
+    def OnViewRefresh(self, event):
+       self.timer = QuickTimer(self.DoRefresh)
+       self.logprint("Connecting to slashdot... Please wait.");
+
+    def DoViewIndex(self):
+        if self.UseInternal:
+            self.view = HTMLTextView(self, -1, 'slashdot.org',
+                                     'http://slashdot.org')
+            self.view.Show(true)
+        else:
+            self.logprint(self.BrowserSettings % ('http://slashdot.org'))
+            os.system(self.BrowserSettings % ('http://slashdot.org'))
+       self.logprint("OK")
+
+    def OnViewIndex(self, event):
+       self.logprint("Starting browser... Please wait.")
+       self.timer = QuickTimer(self.DoViewIndex)
+
+    def DoViewArticle(self):
+        if self.current<0: return
+        url = self.url[self.current]
+        if self.UseInternal:
+            self.view = HTMLTextView(self, -1, url, url)
+            self.view.Show(true)
+        else:
+            self.logprint(self.BrowserSettings % (url))
+            os.system(self.BrowserSettings % (url))
+       self.logprint("OK")
+
+    def OnViewArticle(self, event):
+       self.logprint("Starting browser... Please wait.")
+       self.timer = QuickTimer(self.DoViewArticle)
+
+    def OnBrowserInternal(self, event):
+        if self.mainmenu.Checked(220):
+            self.UseInternal = 1
+        else:
+            self.UseInternal = 0
+        
+    def OnBrowserSettings(self, event):
+        dlg = wxTextEntryDialog(self, "Enter command to view URL.\nUse %s as a placeholder for the URL.", "", self.BrowserSettings);
+        if dlg.ShowModal() == wxID_OK:
+            self.BrowserSettings = dlg.GetValue()
+
+    def OnAbout(self, event):
+       dlg = wxMessageDialog(self, __doc__, "wxSlash", wxOK | wxICON_INFORMATION)
+       dlg.ShowModal()
+        
+    def OnItemSelected(self, event):
+        self.current = event.m_itemIndex
+        self.logprint("URL: %s" % (self.url[self.current]))
+        
+    def OnCloseWindow(self, event):
+        self.Destroy()
+
+class MyApp(wxApp):
+    def OnInit(self):
+        frame = AppFrame(NULL, -1, "Slashdot Breaking News")
+        frame.Show(true)
+        self.SetTopWindow(frame)
+        return true
+
+#
+# main thingy
+#
+if __name__ == '__main__':
+    app = MyApp(0)
+    app.MainLoop()
+
+
+
+
+