allow to extend an album
authorGuillaume Cottenceau <gcottenc@gmail.com>
Wed, 31 Dec 2008 23:36:43 +0000 (00:36 +0100)
committerGuillaume Cottenceau <gcottenc@gmail.com>
Wed, 31 Dec 2008 23:36:43 +0000 (00:36 +0100)
bin/booh
data/booh/images/stock-scale-16.png [new file with mode: 0644]

index 176e4a4..a86bb63 100755 (executable)
--- a/bin/booh
+++ b/bin/booh
@@ -2721,7 +2721,7 @@ def change_dir
     if $xmldir.child_byname_notattr('dir', 'deleted')
         #- title edition
         frame, $subalbums_title = create_editzone($subalbums_sw, 0, nil)
-        $subalbums_title.buffer.text = $xmldir.attributes['subdirs-caption']
+        $subalbums_title.buffer.text = $xmldir.attributes['subdirs-caption'] || ''
         $subalbums_title.set_justification(Gtk::Justification::CENTER)
         $subalbums_vb.pack_start(Gtk::Alignment.new(0.5, 0.5, 0.5, 0).add(frame), false, false)
         #- this album image/caption
@@ -2977,7 +2977,7 @@ def open_file(filename)
 
     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 = $sort_by_exif_date.sensitive = true
+    $save.sensitive = $save_as.sensitive = $merge_current.sensitive = $merge_newsubs.sensitive = $merge.sensitive = $extend.sensitive = $generate.sensitive = $view_wa.sensitive = $properties.sensitive = $remove_all_captions.sensitive = $sort_by_exif_date.sensitive = true
     return nil
 end
 
@@ -4081,6 +4081,9 @@ def create_menu_and_toolbar
     $merge.image = Gtk::Image.new("#{$FPATH}/images/stock-reset-16.png")
     tooltips.set_tip($merge, utf8(_("Take into account new/removed subalbums (subdirectories) and new/removed photos/videos in existing subalbums (anywhere)")), nil)
     filesubmenu.append(            Gtk::SeparatorMenuItem.new)
+    filesubmenu.append($extend   = Gtk::ImageMenuItem.new(utf8(_("Extend album..."))).set_sensitive(false))
+    $extend.image = Gtk::Image.new("#{$FPATH}/images/stock-scale-16.png")
+    filesubmenu.append(            Gtk::SeparatorMenuItem.new)
     filesubmenu.append($generate = Gtk::ImageMenuItem.new(utf8(_("Generate web-album"))).set_sensitive(false))
     $generate.image = Gtk::Image.new("#{$FPATH}/images/stock-web-16.png")
     tooltips.set_tip($generate, utf8(_("(Re)generate web-album from latest changes into the destination directory")), nil)
@@ -4101,6 +4104,7 @@ def create_menu_and_toolbar
     $merge_current.signal_connect('activate') { merge_current }
     $merge_newsubs.signal_connect('activate') { merge_newsubs }
     $merge.signal_connect('activate') { merge }
+    $extend.signal_connect('activate') { extend_ }
     $generate.signal_connect('activate') {
         save_current_file
         call_backend("booh-backend --config '#{$filename}' --verbose-level #{$verbose_level} #{additional_booh_options}",
@@ -4498,6 +4502,140 @@ below the Document Root), and specify this location in the password protect dial
     }
 end
 
+def extend_
+    if ! ask_save_modifications(utf8(_("Save modifications?")),
+                                utf8(_("You need to save or discard your changes before extending the album.")),
+                                { :no => Gtk::Stock::DISCARD })
+        return
+    end
+
+    #- handle discard
+    $xmldoc = REXML::Document.new(File.new($orig_filename))
+    $modified = false
+
+    dialog = Gtk::Dialog.new(utf8(_("Extend the album")),
+                             $main_window,
+                             Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
+                             [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK],
+                             [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
+
+    lbl = Gtk::Label.new
+    lbl.markup = utf8(
+_("If you want this album to be part of a larger album, you can choose to
+<b>extend</b> it. This album will become a sub-album of the larger album.
+A new directory will be created in source and destination directories with
+the specified name, and everything currently in there will be moved down.
+A typical use case is a ski album, with <span foreground='darkblue'>Tignes</span> and <span foreground='darkblue'>Courchevel</span> subalbums;
+if you want to extend it to a vacations album, then you may input the
+name <span foreground='darkblue'>Ski</span>; after the album is extended, then you may create other
+directories at the same level as <span foreground='darkblue'>Ski</span> in the source directory, such as
+<span foreground='darkblue'>Summers</span> and <span foreground='darkblue'>Christmas</span> and arrange related photos/videos in there."))
+    dialog.vbox.add(lbl)
+    dialog.vbox.add(Gtk::Label.new)
+
+    new_tv = Gtk::TreeView.new.set_size_request(-1, 150)
+    new_tv.append_column(Gtk::TreeViewColumn.new('', Gtk::CellRendererText.new, { :text => 0 }))
+    new_tv.set_headers_visible(false)
+    new_tv.selection.mode = Gtk::SELECTION_NONE
+    new_tv.set_model(new_ts = Gtk::TreeStore.new(String))
+    topdir = $xmldoc.elements['//dir']
+    append_dir_elem = proc { |parent_iter, xmldir|
+        child_iter = new_ts.append(parent_iter)
+        child_iter[0] = File.basename(xmldir.attributes['path'])
+        xmldir.elements.each('dir') { |elem|
+            if !elem.attributes['deleted']
+                append_dir_elem.call(child_iter, elem)
+            end
+        }
+        child_iter
+    }
+    top = new_ts.append(nil)
+    top[0] = File.basename(topdir.attributes['path'])
+    new_top = append_dir_elem.call(top, topdir)
+    new_tv.expand_all
+    new_sw = Gtk::ScrolledWindow.new(nil, nil)
+    new_sw.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC)
+    new_sw.add(new_tv)
+    dialog.vbox.add(Gtk::HBox.new.pack_start(Gtk::Label.new(utf8(_("New layout: "))), false, false, 0).pack_start(new_sw, true, true, 0))
+    dialog.vbox.add(Gtk::Label.new)
+
+    dialog.vbox.add(Gtk::HBox.new.pack_start(Gtk::Label.new(utf8(_("Directory name:"))), false, false, 0).pack_start(e = Gtk::Entry.new.set_text(File.basename($xmldoc.root.attributes['source'])), true, true, 0))
+#    dialog.window_position = Gtk::Window::POS_MOUSE
+    new_top[0] = e.text
+    e.signal_connect('changed') {
+        new_top[0] = e.text
+    }
+    dialog.show_all
+    e.grab_focus
+
+    keepon = true
+    while keepon
+        dialog.run { |response|
+            perform = proc {
+                name = e.text
+                if name =~ /'/
+                    show_popup(dialog, utf8(_("Source directory or sub-directories can't contain a single-quote character, sorry: %s") % name))
+                    return true
+                end
+                name = from_utf8(name)
+                source = from_utf8($xmldoc.root.attributes['source'])
+                dest = from_utf8($xmldoc.root.attributes['destination'])
+                if File.exists?("#{source}/#{name}")
+                    show_popup(dialog, utf8(_("%s already exists.") % "#{source}/#{name}"))
+                    return true
+                end
+                if ! FileTest.writable?(source)
+                    show_popup(dialog, utf8(_("No write access to '%s'.") % source))
+                    return true
+                end
+                if File.exists?("#{dest}/#{name}")
+                    show_popup(dialog, utf8(_("%s already exists.") % "#{dest}/#{name}"))
+                    return true
+                end
+                tomove1 = Dir.entries(source) - [ '.', '..' ]
+                tomove2 = Dir.entries(dest) - [ '.', '..' ]
+                begin
+                    Dir.mkdir("#{source}/#{name}")
+                    Dir.mkdir("#{dest}/#{name}")
+                rescue Exception
+                    show_popup(dialog, utf8(_("Erroneous name.")))
+                    puts $!
+                    return true
+                end
+                tomove1.each { |file|
+                    sys("mv '#{source}/#{file}' '#{source}/#{name}'")
+                }
+                tomove2.each { |file|
+                    sys("mv '#{dest}/#{file}' '#{dest}/#{name}'")
+                }
+
+                substmatch = /^#{Regexp.quote($xmldoc.root.attributes['source'])}/
+                substrepl = $xmldoc.root.attributes['source'] + '/' + utf8(name)
+                substelems = [ 'path', 'subdirs-captionfile', 'thumbnails-captionfile' ]
+                $xmldoc.elements.each('//dir') { |elem|
+                    substelems.each { |elname|
+                        if el = elem.attributes[elname]
+                            elem.add_attribute(elname, el.sub(substmatch, substrepl))
+                        end
+                    }
+                }
+
+                $xmldoc.root.add_element('dir', { 'path' => utf8(source) }).add_element($xmldoc.root.elements[1].remove)
+                save_current_file_user
+                open_file($orig_filename)
+                return false
+            }
+
+            if response == Gtk::Dialog::RESPONSE_OK
+                keepon = perform.call
+            else
+                keepon = false
+            end
+        }
+    end
+    dialog.destroy
+end
+
 def create_main_window
 
     mb, tb = create_menu_and_toolbar
diff --git a/data/booh/images/stock-scale-16.png b/data/booh/images/stock-scale-16.png
new file mode 100644 (file)
index 0000000..996b859
Binary files /dev/null and b/data/booh/images/stock-scale-16.png differ