add "sort by exif date" feature suggested by JC
[booh] / bin / booh
index fbb4cafc506e03d644db0115faac1aa1874c653a..68972cd3c40d45bf22991dc355aec0356ed6b3ac 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -1881,6 +1881,81 @@ def save_changes(*forced)
     }
 end
 
     }
 end
 
+def sort_by_exif_date
+    $modified = true
+    save_changes
+    current_order = []
+    $xmldir.elements.each { |element|
+        if element.name == 'image' || element.name == 'video'
+            current_order << element.attributes['filename']
+        end
+    }
+
+    #- 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?
+            date_time = `identify -format "%[EXIF:DateTime]" '#{from_utf8($current_path + "/" + f)}'`.chomp
+            if $? == 0 && date_time != ''
+                dates[f] = date_time
+            end
+        end
+        if aborted
+            break
+        end
+    }
+    w.destroy
+    if aborted
+        return
+    end
+
+    saves = {}
+    $xmldir.elements.each { |element|
+        if element.name == 'image' || element.name == 'video'
+            saves[element.attributes['filename']] = element.remove
+        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.each { |f|
+        $xmldir.add_element(saves[f].name, saves[f].attributes)
+    }
+
+    #- let the auto-table reflect new ordering
+    change_dir
+end
+
 def remove_all_captions
     $modified = true
     texts = {}
 def remove_all_captions
     $modified = true
     texts = {}
@@ -2444,7 +2519,7 @@ def open_file(filename)
 
     populate_subalbums_treeview(true)
 
 
     populate_subalbums_treeview(true)
 
-    $save.sensitive = $save_as.sensitive = $merge_current.sensitive = $merge_newsubs.sensitive = $merge.sensitive = $generate.sensitive = $view_wa.sensitive = $properties.sensitive = $remove_all_captions.sensitive = true
+    $save.sensitive = $save_as.sensitive = $merge_current.sensitive = $merge_newsubs.sensitive = $merge.sensitive = $generate.sensitive = $view_wa.sensitive = $properties.sensitive = $remove_all_captions.sensitive = $sort_by_exif_date.sensitive = true
     return nil
 end
 
     return nil
 end
 
@@ -3461,6 +3536,8 @@ Click to view it in your browser:") % $xmldoc.root.attributes['destination']),
     editsubmenu.append($undo_mb = Gtk::ImageMenuItem.new(Gtk::Stock::UNDO).set_sensitive(false))
     editsubmenu.append($redo_mb = Gtk::ImageMenuItem.new(Gtk::Stock::REDO).set_sensitive(false))
     editsubmenu.append(           Gtk::SeparatorMenuItem.new)
     editsubmenu.append($undo_mb = Gtk::ImageMenuItem.new(Gtk::Stock::UNDO).set_sensitive(false))
     editsubmenu.append($redo_mb = Gtk::ImageMenuItem.new(Gtk::Stock::REDO).set_sensitive(false))
     editsubmenu.append(           Gtk::SeparatorMenuItem.new)
+    editsubmenu.append($sort_by_exif_date = Gtk::ImageMenuItem.new(utf8(_("Sort by EXIF date"))).set_sensitive(false))
+    $sort_by_exif_date.image = Gtk::Image.new("#{$FPATH}/images/sort_by_exif_date.png")
     editsubmenu.append($remove_all_captions = Gtk::ImageMenuItem.new(utf8(_("Remove all captions in this sub-album"))).set_sensitive(false))
     $remove_all_captions.image = Gtk::Image.new("#{$FPATH}/images/stock-tool-eraser-16.png")
     tooltips.set_tip($remove_all_captions, utf8(_("Mainly useful when you don't want to type any caption, that will remove default captions made of filenames")), nil)
     editsubmenu.append($remove_all_captions = Gtk::ImageMenuItem.new(utf8(_("Remove all captions in this sub-album"))).set_sensitive(false))
     $remove_all_captions.image = Gtk::Image.new("#{$FPATH}/images/stock-tool-eraser-16.png")
     tooltips.set_tip($remove_all_captions, utf8(_("Mainly useful when you don't want to type any caption, that will remove default captions made of filenames")), nil)
@@ -3470,6 +3547,7 @@ Click to view it in your browser:") % $xmldoc.root.attributes['destination']),
     mb.append(editmenu)
 
     $remove_all_captions.signal_connect('activate') { remove_all_captions }
     mb.append(editmenu)
 
     $remove_all_captions.signal_connect('activate') { remove_all_captions }
+    $sort_by_exif_date.signal_connect('activate') { sort_by_exif_date }
 
     prefs.signal_connect('activate') { preferences }
     
 
     prefs.signal_connect('activate') { preferences }