I had some time this weekend, as well as some motivation, to add a couple more things to ExifTagger.
One of the things that took longer than I expected to sort out was how to change the cursor to a watch prior to doing an expensive (time wise) operation in a call back. Loading my 7 MP digital photos takes ~ 4 secs on my laptop, which is enough time that I’d like to provide user feedback that something is happening. The naive approach to this is:
sub new_img { my $file = shift; $glade->get_widget('main_window')->window->set_cursor( Gtk2::Gdk::Cursor->new("watch") ); $img = ExifTagger::Image->new($file); load_image(_target_image_size()); _populate_fields(); $glade->get_widget('main_window')->window->set_cursor(undef); }
This doesn’t work, due to the way gtk works. set_cursor is effectively a signal, which triggers a built in call back just like any of the call backs you would write yourself. The net effect of this is as follows:
pop new_img_signal start new_img push set_cursor_signal load_file load_image populate_exif_fields push set_cursor_signal end pop set_cursor_signal start set_cursor # watch pop set_cursor_signal start set_cursor # normal
The following is how I solved the problem. There may be a more elegant solution, but this is working quite well for me:
sub new_img { my $file = shift; $glade->get_widget('main_window')->window->set_cursor( Gtk2::Gdk::Cursor->new("watch") ); Glib::Idle->add(sub { $img = ExifTagger::Image->new($file); load_image(_target_image_size()); _populate_fields(); $glade->get_widget('main_window')->window->set_cursor(undef); }); }
Which lets the set_cursor call run, has the gtk main loop go idle, then schedules the rest of the work.