1212import websucker
1313import sys
1414import os
15- try :
16- import threading
17- except ImportError :
18- threading = None
15+ import threading
16+ import Queue
17+ import time
1918
20- VERBOSE = 1
19+ VERBOSE = 2
2120
2221
2322try :
@@ -27,27 +26,74 @@ class Canceled(Exception):
2726 Canceled = __name__ + ".Canceled"
2827
2928
30- class App (websucker .Sucker ):
29+ class SuckerThread (websucker .Sucker ):
3130
32- def __init__ (self , top = None ):
31+ stopit = 0
32+ savedir = None
33+ rootdir = None
34+
35+ def __init__ (self , msgq ):
36+ self .msgq = msgq
3337 websucker .Sucker .__init__ (self )
3438 self .setflags (verbose = VERBOSE )
3539 self .urlopener .addheaders = [
3640 ('User-agent' , 'websucker/%s' % websucker .__version__ ),
37- ##('Accept', 'text/html'),
38- ##('Accept', 'text/plain'),
39- ##('Accept', 'text/*'),
40- ##('Accept', 'image/gif'),
41- ##('Accept', 'image/jpeg'),
42- ##('Accept', 'image/*'),
43- ##('Accept', '*/*'),
4441 ]
42+
43+ def message (self , format , * args ):
44+ if args :
45+ format = format % args
46+ ##print format
47+ self .msgq .put (format )
4548
46- if not top :
47- top = Tk ()
48- top .title ("websucker GUI" )
49- top .iconname ("wsgui" )
50- top .wm_protocol ('WM_DELETE_WINDOW' , self .exit )
49+ def run1 (self , url ):
50+ try :
51+ try :
52+ self .reset ()
53+ self .addroot (url )
54+ self .run ()
55+ except Canceled :
56+ self .message ("[canceled]" )
57+ else :
58+ self .message ("[done]" )
59+ finally :
60+ self .msgq .put (None )
61+
62+ def savefile (self , text , path ):
63+ if self .stopit :
64+ raise Canceled
65+ websucker .Sucker .savefile (self , text , path )
66+
67+ def getpage (self , url ):
68+ if self .stopit :
69+ raise Canceled
70+ return websucker .Sucker .getpage (self , url )
71+
72+ def savefilename (self , url ):
73+ path = websucker .Sucker .savefilename (self , url )
74+ if self .savedir :
75+ n = len (self .rootdir )
76+ if path [:n ] == self .rootdir :
77+ path = path [n :]
78+ while path [:1 ] == os .sep :
79+ path = path [1 :]
80+ path = os .path .join (self .savedir , path )
81+ return path
82+
83+ def XXXaddrobot (self , * args ):
84+ pass
85+
86+ def XXXisallowed (self , * args ):
87+ return 1
88+
89+
90+
91+ class App :
92+
93+ sucker = None
94+ msgq = None
95+
96+ def __init__ (self , top ):
5197 self .top = top
5298 top .columnconfigure (99 , weight = 1 )
5399 self .url_label = Label (top , text = "URL:" )
@@ -56,13 +102,12 @@ def __init__(self, top=None):
56102 self .url_entry .grid (row = 0 , column = 1 , sticky = 'we' ,
57103 columnspan = 99 )
58104 self .url_entry .focus_set ()
105+ self .url_entry .bind ("<Key-Return>" , self .go )
59106 self .dir_label = Label (top , text = "Directory:" )
60107 self .dir_label .grid (row = 1 , column = 0 , sticky = 'e' )
61108 self .dir_entry = Entry (top )
62109 self .dir_entry .grid (row = 1 , column = 1 , sticky = 'we' ,
63110 columnspan = 99 )
64- self .exit_button = Button (top , text = "Exit" , command = self .exit )
65- self .exit_button .grid (row = 2 , column = 0 , sticky = 'w' )
66111 self .go_button = Button (top , text = "Go" , command = self .go )
67112 self .go_button .grid (row = 2 , column = 1 , sticky = 'w' )
68113 self .cancel_button = Button (top , text = "Cancel" ,
@@ -74,41 +119,35 @@ def __init__(self, top=None):
74119 self .auto_button .grid (row = 2 , column = 3 , sticky = 'w' )
75120 self .status_label = Label (top , text = "[idle]" )
76121 self .status_label .grid (row = 2 , column = 4 , sticky = 'w' )
77- sys .stdout = self
78122 self .top .update_idletasks ()
79123 self .top .grid_propagate (0 )
80124
81- def mainloop (self ):
82- self .top .mainloop ()
83-
84- def exit (self ):
85- self .stopit = 1
86- self .message ("[exiting...]" )
87- self .top .update_idletasks ()
88- self .top .quit ()
89-
90- buffer = ""
91-
92- def write (self , text ):
93- self .top .update ()
94- if self .stopit :
95- raise Canceled
96- sys .stderr .write (text )
97- lines = string .split (text , "\n " )
98- if len (lines ) > 1 :
99- self .buffer = ""
100- self .buffer = self .buffer + lines [- 1 ]
101- if string .strip (self .buffer ):
102- self .message (self .buffer )
103-
104125 def message (self , text , * args ):
105126 if args :
106127 text = text % args
107- self .status_label .config (text = text )
108- stopit = 0
128+ self .status_label .config (text = text )
109129
110- def go (self ):
111- if self .stopit :
130+ def check_msgq (self ):
131+ while not self .msgq .empty ():
132+ msg = self .msgq .get ()
133+ if msg is None :
134+ self .go_button .configure (state = NORMAL )
135+ self .auto_button .configure (state = NORMAL )
136+ self .cancel_button .configure (state = DISABLED )
137+ if self .sucker :
138+ self .sucker .stopit = 0
139+ self .top .bell ()
140+ else :
141+ self .message (msg )
142+ self .top .after (100 , self .check_msgq )
143+
144+ def go (self , event = None ):
145+ if not self .msgq :
146+ self .msgq = Queue .Queue (0 )
147+ self .check_msgq ()
148+ if not self .sucker :
149+ self .sucker = SuckerThread (self .msgq )
150+ if self .sucker .stopit :
112151 return
113152 self .url_entry .selection_range (0 , END )
114153 url = self .url_entry .get ()
@@ -120,42 +159,22 @@ def go(self):
120159 self .rooturl = url
121160 dir = string .strip (self .dir_entry .get ())
122161 if not dir :
123- self .savedir = None
162+ self .sucker . savedir = None
124163 else :
125- self .savedir = dir
126- self .rootdir = os .path .dirname (
164+ self .sucker . savedir = dir
165+ self .sucker . rootdir = os .path .dirname (
127166 websucker .Sucker .savefilename (self , url ))
128167 self .go_button .configure (state = DISABLED )
129168 self .auto_button .configure (state = DISABLED )
130169 self .cancel_button .configure (state = NORMAL )
131- self .status_label ['text' ] = '[running...]'
132- self .top .update_idletasks ()
133- if threading :
134- t = threading .Thread (target = self .run1 , args = (url ,))
135- t .start ()
136- else :
137- self .run1 (url )
138-
139- def run1 (self , url ):
140- self .reset ()
141- self .addroot (url )
142- self .stopit = 0
143- try :
144- try :
145- self .run ()
146- except Canceled :
147- self .message ("[canceled]" )
148- else :
149- self .message ("[done]" )
150- self .top .bell ()
151- finally :
152- self .go_button .configure (state = NORMAL )
153- self .auto_button .configure (state = NORMAL )
154- self .cancel_button .configure (state = DISABLED )
155- self .stopit = 0
170+ self .message ( '[running...]' )
171+ self .sucker .stopit = 0
172+ t = threading .Thread (target = self .sucker .run1 , args = (url ,))
173+ t .start ()
156174
157175 def cancel (self ):
158- self .stopit = 1
176+ if self .sucker :
177+ self .sucker .stopit = 1
159178 self .message ("[canceling...]" )
160179
161180 def auto (self ):
@@ -175,32 +194,51 @@ def auto(self):
175194 return
176195 self .url_entry .delete (0 , END )
177196 self .url_entry .insert (0 , text )
178- self .top .update_idletasks ()
179197 self .go ()
198+
199+
200+ class AppArray :
201+
202+ def __init__ (self , top = None ):
203+ if not top :
204+ top = Tk ()
205+ top .title ("websucker GUI" )
206+ top .iconname ("wsgui" )
207+ top .wm_protocol ('WM_DELETE_WINDOW' , self .exit )
208+ self .top = top
209+ self .appframe = Frame (self .top )
210+ self .appframe .pack (fill = 'both' )
211+ self .applist = []
212+ self .exit_button = Button (top , text = "Exit" , command = self .exit )
213+ self .exit_button .pack (side = RIGHT )
214+ self .new_button = Button (top , text = "New" , command = self .addsucker )
215+ self .new_button .pack (side = LEFT )
216+ self .addsucker ()
217+ ##self.applist[0].url_entry.insert(END, "http://www.python.org/doc/essays/")
218+
219+ def addsucker (self ):
220+ self .top .geometry ("" )
221+ frame = Frame (self .appframe , borderwidth = 2 , relief = GROOVE )
222+ frame .pack (fill = 'x' )
223+ app = App (frame )
224+ self .applist .append (app )
225+
226+ done = 0
227+
228+ def mainloop (self ):
229+ while not self .done :
230+ time .sleep (0.1 )
231+ self .top .update ()
180232
181- def savefile (self , text , path ):
182- self .top .update ()
183- if self .stopit :
184- raise Canceled
185- websucker .Sucker .savefile (self , text , path )
186-
187- def getpage (self , url ):
188- self .top .update ()
189- if self .stopit :
190- raise Canceled
191- return websucker .Sucker .getpage (self , url )
192-
193- def savefilename (self , url ):
194- path = websucker .Sucker .savefilename (self , url )
195- if self .savedir :
196- n = len (self .rootdir )
197- if path [:n ] == self .rootdir :
198- path = path [n :]
199- while path [:1 ] == os .sep :
200- path = path [1 :]
201- path = os .path .join (self .savedir , path )
202- return path
233+ def exit (self ):
234+ for app in self .applist :
235+ app .cancel ()
236+ app .message ("[exiting...]" )
237+ self .done = 1
238+
203239
240+ def main ():
241+ AppArray ().mainloop ()
204242
205243if __name__ == '__main__' :
206- App (). mainloop ()
244+ main ()
0 commit comments