[pygtk] Re: progressbar for file managing

John Dennis jdennis at redhat.com
Wed Apr 18 03:53:30 WST 2007


On Tue, 2007-04-17 at 21:15 +0000, Fabian Braennstroem wrote:
> Thanks for your advice! I tried to adjust your lines a bit, but I
> was not successful:
> 
>     def progress_pulse(self):
>         if self.load_in_progress:
>             self.progress.pulse()
>             return True                 # call again
>         else:
>             return False                # do not call again
> 
> 
> 
>     def on_load_data(self , state ):
>         if state == 'start':
>             self.load_in_progress = True
>             self.progress.pulse()
>             gobject.timeout_add(1, self.progress_pulse)
>         if state == 'stop':
>             self.load_in_progress = False
> 
>     def callback(self, widget, data=None):
>         i=0
>         n=100
> 
>         self.on_load_data('start')
> 
>         shutil.copytree(file1,"/home/fab/test_copy2")
> 
>         self.on_load_data('stop')
> 
> 
> The progressbar starts to run, if the directory already exists and
> 'shutil' stops with an error message; if the copying works than
> there is no progressbar movement... strange. Do you know, what I am
> doing wrong?

It's the same thing I told you originally, you can't both perform a
synchronous copy and update the GUI at the same time. You also have to
understand how the GTK event loop works.

Timeout callbacks are processed in the event loop. Your copy routine is
processed in the event loop. They cannot proceed in parallel because the
event loop is sequential. 

In one iteration of the event loop your copy routine installs a timeout
callback with load_in_progress=True, does the copy, then sets
load_in_progress=False. Sometime later the event loop gets to your
timeout handler and calls it. But guess what the value of
load_in_progress is?

I'm guessing the reason it works in an error condition is because
copytree raises an exception which you don't catch (its caught by the
event loop instead), thus you never set load_in_progress to False, then
when the event loop calls your timeout handler load_in_progress is True
and you pulse. BTW, 1 millisecond timeout is way too short.

You can cause the event loop to run during the copy with something like
this:

while gtk.events_pending():
   gtk.main_iteration(False)

But this has to be done inside the copy operation, or you have to
structure the copy to be performed in chunks (e.g. idle_add()). But you
can't do what you want to do if the copy operation is completely
synchronous in one call (as copytree is) and you only have one thread.
-- 
John Dennis <jdennis at redhat.com>

Learn. Network. Experience open source.
Red Hat Summit San Diego  |  May 9-11, 2007
Learn more: http://www.redhat.com/promo/summit/2007




More information about the pygtk mailing list