classifier: allow to sort by EXIF dates
authorgc <gc>
Tue, 16 Oct 2007 20:39:18 +0000 (20:39 +0000)
committergc <gc>
Tue, 16 Oct 2007 20:39:18 +0000 (20:39 +0000)
bin/booh
bin/booh-classifier
lib/booh/booh-lib.rb

index 18861ee..68454e0 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -137,6 +137,9 @@ It is generally available with the 'ImageMagick' software package.")), { :pos_ce
         show_popup($main_window, utf8(_("The program 'identify' is needed to get images sizes and EXIF data. Please install it.
 It is generally available with the 'ImageMagick' software package.")), { :pos_centered => true })
     end
+    if !system("which exif >/dev/null 2>/dev/null")
+        show_popup($main_window, utf8(_("The program 'exif' is needed to view EXIF data. Please install it.")), { :pos_centered => true })
+    end
     missing = %w(transcode mencoder).delete_if { |prg| system("which #{prg} >/dev/null 2>/dev/null") }
     if missing != []
         show_popup($main_window, utf8(_("The following program(s) are needed to handle videos: '%s'. Videos will be ignored.") % missing.join(', ')), { :pos_centered => true })
@@ -2139,42 +2142,53 @@ def sort_by_exif_date
     }
 
     #- look for EXIF dates
-    w = Gtk::Window.new
-    w.set_transient_for($main_window)
-    w.modal = true
-    vb = Gtk::VBox.new(false, 5).set_border_width(5)
-    vb.pack_start(Gtk::Label.new(utf8(_("Scanning sub-album looking for EXIF dates..."))), false, false)
-    vb.pack_start(pb = Gtk::ProgressBar.new, false, false)
-    bottom = Gtk::Alignment.new(0.5, 0.5, 0, 0).add(b = Gtk::Button.new(utf8(_("_Abort"))))
-    b.image = Gtk::Image.new("#{$FPATH}/images/stock-close-24.png")
-    vb.pack_end(bottom, false, false)
-    w.add(vb)
-    w.signal_connect('delete-event') { w.destroy }
-    w.window_position = Gtk::Window::POS_CENTER
-    w.show_all
-
-    aborted = false
-    b.signal_connect('clicked') { aborted = true }
     dates = {}
-    i = 0
-    current_order.each { |f|
-        i += 1
-        if entry2type(f) == 'image'
-            pb.text = f
-            pb.fraction = i.to_f / current_order.size
-            Gtk.main_iteration while Gtk.events_pending?
+
+    if current_order.size > 20
+        w = Gtk::Window.new
+        w.set_transient_for($main_window)
+        w.modal = true
+        vb = Gtk::VBox.new(false, 5).set_border_width(5)
+        vb.pack_start(Gtk::Label.new(utf8(_("Scanning sub-album looking for EXIF dates..."))), false, false)
+        vb.pack_start(pb = Gtk::ProgressBar.new, false, false)
+        bottom = Gtk::Alignment.new(0.5, 0.5, 0, 0).add(b = Gtk::Button.new(utf8(_("_Abort"))))
+        b.image = Gtk::Image.new("#{$FPATH}/images/stock-close-24.png")
+        vb.pack_end(bottom, false, false)
+        w.add(vb)
+        w.signal_connect('delete-event') { w.destroy }
+        w.window_position = Gtk::Window::POS_CENTER
+        w.show_all
+
+        aborted = false
+        b.signal_connect('clicked') { aborted = true }
+        i = 0
+        current_order.each { |f|
+            i += 1
+            if entry2type(f) == 'image'
+                pb.text = f
+                pb.fraction = i.to_f / current_order.size
+                Gtk.main_iteration while Gtk.events_pending?
+                date_time = Exif.datetimeoriginal(from_utf8($current_path + "/" + f))
+                if ! date_time.nil?
+                    dates[f] = date_time
+                end
+            end
+            if aborted
+                break
+            end
+        }
+        w.destroy
+        if aborted
+            return
+        end
+
+    else
+        current_order.each { |f|
             date_time = Exif.datetimeoriginal(from_utf8($current_path + "/" + f))
             if ! date_time.nil?
                 dates[f] = date_time
             end
-        end
-        if aborted
-            break
-        end
-    }
-    w.destroy
-    if aborted
-        return
+        }
     end
 
     saves = {}
@@ -2184,17 +2198,8 @@ def sort_by_exif_date
         end
     }
 
-    #- find a good fallback for all entries without a date (still next to the item they were next to)
-    neworder = dates.keys.sort { |a,b| dates[a] <=> dates[b] }
-    for i in 0 .. current_order.size - 1
-        if ! neworder.include?(current_order[i])
-            j = i - 1
-            while j > 0 && ! neworder.include?(current_order[j])
-                j -= 1
-            end
-            neworder[(neworder.index(current_order[j]) || -1 ) + 1, 0] = current_order[i]
-        end
-    end
+    neworder = smartsort(current_order, dates)
+
     neworder.each { |f|
         $xmldir.add_element(saves[f].name, saves[f].attributes)
     }
index ca9ce5d..f64afe4 100644 (file)
@@ -24,6 +24,7 @@ require 'tempfile'
 require 'thread'
 
 require 'gtk2'
+require 'booh/libadds'
 
 require 'gettext'
 include GetText
@@ -42,6 +43,7 @@ $options = [
     [ '--help',          '-h', GetoptLong::NO_ARGUMENT,       _("Get help message") ],
 
     [ '--verbose-level', '-v', GetoptLong::REQUIRED_ARGUMENT, _("Set max verbosity level (0: errors, 1: warnings, 2: important messages, 3: other messages)") ],
+    [ '--sort-by-exif-date', '-s', GetoptLong::NO_ARGUMENT, _("Sort entries by EXIF date") ],
 ]
 
 def usage
@@ -64,6 +66,9 @@ def handle_options
             when '--verbose-level'
                 $verbose_level = arg.to_i
 
+            when '--sort-by-exif-date'
+                $sort_by_exif_date = true
+
             end
         end
     rescue
@@ -956,7 +961,20 @@ def open_dir(path)
             msg 1, _("Ignoring directory %s, begins with a dot (indicating a hidden directory)") % dir
             next
         end
-        Dir.entries(dir).sort.each { |file|
+        entries = Dir.entries(dir)
+        if $sort_by_exif_date
+            dates = {}
+            entries.each { |file|
+                date_time = Exif.datetimeoriginal(File.join(dir, file))
+                if ! date_time.nil?
+                    dates[file] = date_time
+                end
+            }
+            entries = smartsort(entries, dates)
+        else
+            entries.sort!
+        end
+        entries.each { |file|
             type = entry2type(file)
             if type
                 $allentries << Entry.new(File.join(dir, file), type)
index 3bfe17b..cac7b01 100644 (file)
@@ -806,6 +806,22 @@ French: Guillaume Cottenceau')),
                                               :logo => Gdk::Pixbuf.new("#{$FPATH}/images/logo.png") })
     end
 
+    def smartsort(entries, sort_criterions)
+        #- sort "entries" according to "sort_criterions" but find a good fallback for all entries without a
+        #- criterion value (still next to the item they were next to)
+        sorted_entries = sort_criterions.keys.sort { |a,b| sort_criterions[a] <=> sort_criterions[b] }
+        for i in 0 .. entries.size - 1
+            if ! sorted_entries.include?(entries[i])
+                j = i - 1
+                while j > 0 && ! sorted_entries.include?(entries[j])
+                    j -= 1
+                end
+                sorted_entries[(sorted_entries.index(entries[j]) || -1 ) + 1, 0] = entries[i]
+            end
+        end
+        return sorted_entries
+    end
+
 end
 
 class File