no longer use internalized rexml
[booh] / bin / booh-classifier
index 37f224d64b1a1616ced8515883527110de5aa8de..3be4fab23d05dc1e5ca9ee46b0649b64d269b3c6 100644 (file)
@@ -10,7 +10,7 @@
 # called Boo, so this one will be it "Booh". Or whatever.
 #
 #
-# Copyright (c) 2004-2009 Guillaume Cottenceau <http://zarb.org/~gc/resource/gc_mail.png>
+# Copyright (c) 2004-2013 Guillaume Cottenceau <http://zarb.org/~gc/resource/gc_mail.png>
 #
 # This software may be freely redistributed under the terms of the GNU
 # public license version 2.
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
+begin
+    require 'rubygems'
+rescue LoadError
+end
+
 require 'getoptlong'
 require 'tempfile'
 
@@ -29,7 +34,7 @@ require 'gettext'
 include GetText
 bindtextdomain("booh")
 
-require 'booh/rexml/document'
+require 'rexml/document'
 include REXML
 
 require 'booh/booh-lib'
@@ -73,7 +78,7 @@ def handle_options
             when '--version'
                 puts _("Booh version %s
 
-Copyright (c) 2005-2009 Guillaume Cottenceau.
+Copyright (c) 2005-2013 Guillaume Cottenceau.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % $VERSION
 
@@ -310,14 +315,14 @@ class Entry
             if @pixbuf_full.width.to_f / @pixbuf_full.height > width.to_f / height
                 resized_height = @pixbuf_full.height * (width.to_f/@pixbuf_full.width)
                 if @pixbuf_full.width > width || @pixbuf_full.height > resized_height
-                    @pixbuf_main = @pixbuf_full.scale(width, resized_height, Gdk::Pixbuf::INTERP_BILINEAR)
+                    @pixbuf_main = @pixbuf_full.scale(width, resized_height, :bilinear)
                 else
                     @pixbuf_main = @pixbuf_full
                 end
             else
                 resized_width = @pixbuf_full.width * (height.to_f/@pixbuf_full.height)
                 if @pixbuf_full.width > resized_width || @pixbuf_full.height > height
-                    @pixbuf_main = @pixbuf_full.scale(resized_width, height, Gdk::Pixbuf::INTERP_BILINEAR)
+                    @pixbuf_main = @pixbuf_full.scale(resized_width, height, :bilinear)
                 else
                     @pixbuf_main = @pixbuf_full
                 end
@@ -343,7 +348,7 @@ class Entry
         if @pixbuf_thumbnail.nil?
             if @pixbuf_main
                 msg 3, ">>> pixbuf_thumbnail from main #{path}"
-                @pixbuf_thumbnail = @pixbuf_main.scale(@pixbuf_main.width * (Entry.thumbnails_height.to_f/@pixbuf_main.height), Entry.thumbnails_height, Gdk::Pixbuf::INTERP_BILINEAR)
+                @pixbuf_thumbnail = @pixbuf_main.scale(@pixbuf_main.width * (Entry.thumbnails_height.to_f/@pixbuf_main.height), Entry.thumbnails_height, :bilinear)
             else
                 msg 3, ">>> pixbuf_thumbnail from file #{path}"
                 @pixbuf_thumbnail = load_into_pixbuf_at_size { |w, h|
@@ -472,7 +477,7 @@ class Entry
             #- use a pixbuf loader and check Gtk.events_pending? on each chunk, to keep the UI responsive even
             #- if loaded pictures are several MBs large
             if @loader.nil?
-                @loader = Gdk::PixbufLoader.new
+                @loader = GdkPixbuf::PixbufLoader.new
                 @loader.signal_connect('size-prepared') { |l, w, h|
                     @loader.set_size(*specify_size.call(w, h))
                 }
@@ -893,12 +898,16 @@ def show_popup(parent, msg, *options)
     end
     if options[:okcancel]
         cancel = dialog.add_button(Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL)
+        dialog.add_button(Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK)
+    elsif options[:yestoall]
+        cancel = dialog.add_button(Gtk::Stock::NO, Gtk::Dialog::RESPONSE_NO)
         if ! options[:bottomwidget]
             cancel.grab_focus
         end
-        dialog.add_button(Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK)
+        dialog.add_button(Gtk::Stock::YES, Gtk::Dialog::RESPONSE_YES)
+        dialog.add_button(utf8(_("Yes to all")), Gtk::Dialog::RESPONSE_ACCEPT)
     else
-        ok = dialog.add_button(Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK).grab_focus
+        ok = dialog.add_button(Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK)
         if ! options[:bottomwidget]
             ok.grab_focus
         end
@@ -939,6 +948,8 @@ def show_popup(parent, msg, *options)
             dialog.destroy
             if options[:okcancel]
                 return response == Gtk::Dialog::RESPONSE_OK
+            elsif options[:yestoall]
+                return response == Gtk::Dialog::RESPONSE_YES ? 'yes' : response == Gtk::Dialog::RESPONSE_ACCEPT ? 'yestoall' : 'no'
             end
         }
     else
@@ -1232,7 +1243,7 @@ def show_entries(allentries)
     update_counters
     sb_msg(_("Loading images..."))
     $loading_progressbar.fraction = 0
-    $loading_progressbar.text = utf8(_("Loading... %d%") % 0)
+    $loading_progressbar.text = utf8(_("Loading... %d%%") % 0)
     $loading_progressbar.show
     t1 = Time.now
     total_loaded_files = 0
@@ -1284,7 +1295,7 @@ def show_entries(allentries)
             allentries.delete_at(i)
         end
         $loading_progressbar.fraction = i.to_f / allentries.size
-        $loading_progressbar.text = utf8(_("Loading... %d%") % (100 * $loading_progressbar.fraction))
+        $loading_progressbar.text = utf8(_("Loading... %d%%") % (100 * $loading_progressbar.fraction))
         if $quit
             return
         end
@@ -1322,7 +1333,7 @@ def open_dir(*paths)
         $workingdir = path
         entries = []
         if File.directory?(path)
-            examined_dirs = `find '#{path}' -type d -follow`.sort.collect { |v| v.chomp }
+            examined_dirs = `find '#{path}' -type d -follow`.split("\n").sort.collect { |v| v.chomp }
             #- validate first
             examined_dirs.each { |dir|
                 if dir =~ /'/
@@ -1364,6 +1375,8 @@ def open_dir(*paths)
                 date_time = Exif.datetimeoriginal(file)
                 if ! date_time.nil?
                     dates[file] = date_time
+                elsif file =~ /(20\d{2}).?(\d{2}).?(\d{2}).(\d{2}).?(\d{2}).?(\d{2})/
+                    dates[file] = "#$1:#$2:#$3 #$4:#$5:#$6"
                 end
             }
             entries = smartsort(entries, dates)
@@ -1397,7 +1410,7 @@ def open_dir_popup
     ok = false
     load = false
     while !ok
-        if fc.run == Gtk::Dialog::RESPONSE_ACCEPT
+        if fc.run == Gtk::Dialog::RESPONSE_ACCEPT && fc.filename
             msg = open_dir(fc.filename)
             if msg
                 show_popup(fc, msg)
@@ -1472,7 +1485,7 @@ def execute
         table.attach(examples, 2, 3, row, row + 1, Gtk::FILL, Gtk::FILL, 5, 5)
 
         if counter == 0
-            return {}
+            next {}
         end
 
         combostore = Gtk::ListStore.new(Gdk::Pixbuf, String)
@@ -1511,7 +1524,7 @@ def execute
                 if lastpath
                     fc.current_folder = lastpath
                 end
-                if fc.run == Gtk::Dialog::RESPONSE_ACCEPT
+                if fc.run == Gtk::Dialog::RESPONSE_ACCEPT && fc.filename
                     pathlabel.text = fc.filename
                     pathlabel.set_alignment(0, 0.5)
                 end
@@ -1589,7 +1602,7 @@ def execute
                         end
                         begin
                             Dir.mkdir(destination)
-                        rescue Errno::EEXIST
+                        rescue
                         end
                         begin
                             st = File.stat(destination)
@@ -1598,7 +1611,7 @@ def execute
                             problem = true
                             break
                         end
-                        if ! st.directory? || ! st.writable?
+                        if ! st.directory? || ! writable(destination)
                             show_popup(dialog, utf8(_("Directory %s, where to move/copy %s, is not valid or not writable.") % [destination, key.name]))
                             problem = true
                             break
@@ -1630,16 +1643,36 @@ def execute
                     begin
                         moved = 0
                         copied = 0
+                        ignored_errors = []
                         stuff.keys.each { |key|
                             if key.is_a?(Label) && stuff[key][:combo] && stuff[key][:combo].active <= 1
                                 destination = stuff[key][:pathlabel].text
                                 label2entries[key].each { |entry|
                                     if stuff[key][:combo].active == 0
-                                        system("cp -dp '#{entry.path}' '#{destination}'") or raise "failed to copy '#{entry.path}'"
-                                        copied += 1
+                                        result = `cp -dp '#{entry.path}' '#{destination}' 2>&1`
                                     elsif stuff[key][:combo].active == 1
-                                        system("mv '#{entry.path}' '#{destination}'") or raise "failed to move '#{entry.path}'"
-                                        moved += 1
+                                        result = `mv '#{entry.path}' '#{destination}' 2>&1`
+                                    end
+                                    if $?.exitstatus > 0
+                                        simplified_error = result.sub(/#{Regexp.quote(destination + '/' + File.basename(entry.path))}/, '').  #'
+                                                                  sub(/#{Regexp.quote(entry.path)}/, '').
+                                                                  sub(/#{Regexp.quote(File.basename(entry.path))}/, '')
+                                        if ! ignored_errors.include?(simplified_error)
+                                            response = show_popup($main_window,
+                                                                  utf8(_("Failure:\n\n%s\nDo you wish to continue?" % result)),
+                                                                  { :yestoall => true })
+                                            if response == 'no'
+                                                raise "failure on '#{entry.path}'"
+                                            elsif response == 'yestoall'
+                                                ignored_errors << simplified_error
+                                            end
+                                        end
+                                    else
+                                        if stuff[key][:combo].active == 0
+                                            copied += 1
+                                        else
+                                            moved += 1
+                                        end
                                     end
                                 }
                             end
@@ -1654,8 +1687,7 @@ def execute
                             }
                         end
                     rescue
-                        msg 1, "woops: #{$!}"
-                        show_popup(dialog, utf8(_("Unexpected error: '%s'.") % $!))
+                        msg 1, "woops: #{$!}\n" + $@.join("\n")
                     end
                     show_popup(dialog, utf8(_("Successfully moved %d files, copied %d file, and removed %d files.") % [ moved, copied, removed ]))
                     dialog.destroy
@@ -1956,7 +1988,7 @@ def reset_labels
                                                     pack_start($unlabelled_counter = Gtk::Label.new.set_markup('<tt>0</tt>'), false, false).show_all)
     $unlabelled_button.active = true
     $unlabelled_button.signal_connect('toggled') { update_all_visibilities }
-    lbl = Gtk::Label.new.set_markup(utf8(_("<i>to rem</i>")))
+    lbl = Gtk::Label.new.set_markup(utf8(_("<i>to remove</i>")))
     $labels_vbox.pack_start(Gtk::HBox.new(false, 5).pack_start($toremove_button = Gtk::CheckButton.new.add(evt = Gtk::EventBox.new.add(lbl)), false, false).
                                                     pack_start(Gtk::Label.new, true, true).
                                                     pack_start($toremove_counter = Gtk::Label.new.set_markup('<tt>0</tt>'), false, false).show_all)
@@ -1991,7 +2023,7 @@ end
 
 def create_main_window
 
-    $videoborder_pixbuf = Gdk::Pixbuf.new("#{$FPATH}/images/video_border.png")
+    $videoborder_pixbuf = GdkPixbuf::Pixbuf.new(:file => "#{$FPATH}/images/video_border.png")
     $videoborder_pixmap, = $videoborder_pixbuf.render_pixmap_and_mask(0)
 
     mb = create_menubar
@@ -2001,7 +2033,7 @@ def create_main_window
     mainview_hbox = Gtk::HBox.new
     mainview_hbox.pack_start(Gtk::Alignment.new(0.5, 0, 1, 1).add(left_vbox = Gtk::VBox.new(false, 5)), false, true)
     left_vbox.pack_start(($labels_vbox = Gtk::VBox.new(false, 5)), false, true)
-    left_vbox.pack_end($loading_progressbar = Gtk::ProgressBar.new.set_text(utf8(_("Loading... %d%") % 0)), false, true)
+    left_vbox.pack_end($loading_progressbar = Gtk::ProgressBar.new.set_text(utf8(_("Loading... %d%%") % 0)), false, true)
     mainview_hbox.pack_start($mainview = MainView.new, true, true)
     main_vbox.pack_start(mainview_hbox, true, true)
     $imagesline_sw = Gtk::ScrolledWindow.new(nil, nil)