sync
authorgc <gc>
Sat, 14 Jul 2007 14:05:41 +0000 (14:05 +0000)
committergc <gc>
Sat, 14 Jul 2007 14:05:41 +0000 (14:05 +0000)
bin/booh-classifier

index f221ffbec2a2c06ba37bb1647377206897addb4c..fddab2722c7fbbc6bbabe67edb8d06b623ad733d 100644 (file)
@@ -379,7 +379,7 @@ class MainView < Gtk::DrawingArea
                     puts "background main preloading triggered..."
                     if ! @index.nil?
                         w, h = window.size
-                        for j in 1 .. $config['preload-distance']
+                        for j in 1 .. $config['preload-distance'].to_i
                             i = @index + j
                             if i < $allentries.size
                                 $allentries[i].pixbuf_main(w, h)
@@ -649,11 +649,17 @@ def thumbnail_keypressed(entry, event)
                         bt.modify_bg(Gtk::StateType::ACTIVE, color.darker)
                     }
                     bt.clicked
+                    entry.signal_connect('changed') {  #- cannot add a new tag with first letter of an existing tag
+                        while $tags.has_key?(entry.text[0,1])
+                            entry.text = entry.text.sub(/./, '')
+                        end
+                    }
                     if show_popup($main_window,
                                   utf8(_("You typed the text character '%s', which is not associated with a tag.\nType in the full name of the tag below to create a new one.")) % char,
                                   { :okcancel => true, :bottomwidget => vb, :data_getter => proc { text = entry.text },
-                                    :stuff_connector => proc { |stuff| entry.select_region(0, 0); entry.position = -1;
-                                          entry.signal_connect('activate') { stuff[:dialog].response(Gtk::Dialog::RESPONSE_OK) } } } )
+                                    :stuff_connector => proc { |stuff| entry.select_region(0, 0)
+                                                                       entry.position = -1
+                                                                       entry.signal_connect('activate') { stuff[:dialog].response(Gtk::Dialog::RESPONSE_OK) } } } )
                         if text.length > 0
                             char = text[0,1]  #- in case it changed
                             tag = Tag.new(text)
@@ -675,12 +681,18 @@ def thumbnail_keypressed(entry, event)
     end
 end
 
+def sb_msg(msg)
+    $statusbar.pop(0)
+    if msg
+        $statusbar.push(0, utf8(msg))
+    end
+end
+    
 def show_entries
     e = Thread.new {
         t1 = Time.now
         show_mem
-        ctid = $statusbar.get_context_id('images loading')
-        $statusbar.push(ctid, utf8(_("Loading images...")))
+        sb_msg(_("Loading images..."))
         tooltips = Gtk::Tooltips.new
         counter = 0
         $allentries.each_with_index { |entry, i|
@@ -705,29 +717,34 @@ def show_entries
             end
         }
         check_memory_free_cache_if_needed
-        $statusbar.pop(ctid)
-        $statusbar.push(0, utf8(_("%d images loaded.") % counter))
+        sb_msg(_("%d images loaded.") % counter)
         puts "time: #{Time.now - t1}"
     }
     e.priority = -1
 end
 
 def open_dir(path)
+    #- remove visual stuff, so that user will see something is happening
+    reset_tags
+    reset_thumbnails
+    $mainview.set_shown_entry(nil)
+    sb_msg(_("Scanning source directory..."))
+
     path = File.expand_path(path.sub(%r|/$|, ''))
     examined_dirs = `find '#{path}' -type d -follow`.sort.collect { |v| v.chomp }
     #- validate first
     examined_dirs.each { |dir|
         if dir =~ /'/
-            show_popup($main_window, utf8(_("Source directory or sub-directories can't contain a single-quote character, sorry: %s") % dir))
+            return utf8(_("Source directory or sub-directories can't contain a single-quote character, sorry: %s") % dir)
         end
         Dir.entries(dir).each { |file|
             if file =~ /['"\[\]]/
-                show_popup($main_window, utf8(_("Files can't contain any of the characters ', \", [ or ], sorry: %s") % "#{dir}/#{file}"))
+                return utf8(_("Files can't contain any of the characters ', \", [ or ], sorry: %s") % "#{dir}/#{file}")
             end
         }
     }
+
     #- scan for populate second
-    $allentries = []
     examined_dirs.each { |dir|
         if File.basename(dir) =~ /^\./
             msg 1, _("Ignoring directory %s, begins with a dot (indicating a hidden directory)") % dir
@@ -735,12 +752,14 @@ def open_dir(path)
         end
         Dir.entries(dir).each { |file|
             type = entry2type(file)
-           if type && $allentries.size < 2
+           if type && $allentries.size < 10
                 $allentries << Entry.new(File.join(dir, file), type)
             end
         }
     }
     show_entries
+    $execute.sensitive = true
+    return nil
 end
 
 def open_dir_popup
@@ -790,8 +809,142 @@ def try_quit(*options)
     Gtk.main_quit
 end
 
-def create_menubar
-    
+def execute
+    dialog = Gtk::Dialog.new
+    dialog.title = utf8(_("Booh message"))
+
+    vb1 = Gtk::VBox.new(false, 5)
+    label = Gtk::Label.new.set_markup(utf8(_("You're about to <b>execute</b> actions on the marked images.\nPlease confirm below the actions. This operation is not undoable!")))
+    vb1.pack_start(label, false, false)
+
+    table = Gtk::Table.new(0, 0, false)
+    table.set_row_spacings(5)
+    table.set_column_spacings(5)
+    table.attach(Gtk::Label.new.set_markup(utf8(_("<b>Tag name:</b>"))).set_justify(Gtk::Justification::CENTER), 0, 1, 0, 1, Gtk::FILL, Gtk::FILL, 5, 0)
+    table.attach(Gtk::Label.new.set_markup(utf8(_("<b>Amount of pictures:</b>"))).set_justify(Gtk::Justification::CENTER), 1, 2, 0, 1, Gtk::FILL, Gtk::FILL, 5, 0)
+    table.attach(Gtk::Label.new.set_markup(utf8(_("<b>Pictures examples:</b>"))).set_justify(Gtk::Justification::CENTER), 2, 3, 0, 1, Gtk::FILL, Gtk::FILL, 5, 0)
+    table.attach(Gtk::Label.new.set_markup(utf8(_("<b>Action to perform:</b>"))).set_justify(Gtk::Justification::CENTER), 3, 4, 0, 1, Gtk::FILL, Gtk::FILL, 5, 0)
+    add_row = proc { |row, name, color, truthproc, normal|
+        table.attach(Gtk::Alignment.new(0, 0.5, 1, 0).add(Gtk::EventBox.new.add(Gtk::Label.new.set_markup(name)).modify_bg(Gtk::StateType::NORMAL, color)),
+                     0, 1, row, row + 1, Gtk::FILL, Gtk::FILL, 5, 5)
+        counter = 0
+        examples = Gtk::HBox.new(false, 5)
+        $allentries.each { |entry|
+            if truthproc.call(entry)
+                counter += 1
+                if counter < 4
+                    examples.pack_start(Gtk::Image.new(entry.pixbuf_thumbnail), false, false)
+                elsif counter == 4
+                    examples.pack_start(Gtk::Label.new.set_markup("<b>...</b>"), false, false)
+                end
+            end
+        }
+        table.attach(Gtk::Label.new(counter.to_s).set_justify(Gtk::Justification::CENTER), 1, 2, row, row + 1, 0, 0, 5, 5)
+        table.attach(examples, 2, 3, row, row + 1, Gtk::FILL, Gtk::FILL, 5, 5)
+
+        combostore = Gtk::ListStore.new(Gdk::Pixbuf, String)
+        iter = combostore.append
+        if normal
+            iter[0] = $main_window.render_icon(Gtk::Stock::GO_FORWARD, Gtk::IconSize::MENU)
+            iter[1] = utf8(_("Move to:"))
+        else
+            iter[0] = $main_window.render_icon(Gtk::Stock::DELETE, Gtk::IconSize::MENU)
+            iter[1] = utf8(_("Permanently remove"))
+        end
+        iter = combostore.append
+        iter[0] = $main_window.render_icon(Gtk::Stock::MEDIA_STOP, Gtk::IconSize::MENU)
+        iter[1] = utf8(_("Do nothing"))
+        combo = Gtk::ComboBox.new(combostore)
+        combo.active = 0
+        renderer = Gtk::CellRendererPixbuf.new
+        combo.pack_start(renderer, false)
+        combo.set_attributes(renderer, :pixbuf => 0)
+        renderer = Gtk::CellRendererText.new
+        combo.pack_start(renderer, true)
+        combo.set_attributes(renderer, :text => 1)
+
+        if normal
+            pathbutton = Gtk::Button.new.add(pathlabel = Gtk::Label.new.set_markup(utf8(_("<i>(unset)</i>"))))
+            pathbutton.signal_connect('clicked') {
+                fc = Gtk::FileChooserDialog.new(utf8(_("Specify the directory where to move the pictures to")),
+                                                nil,
+                                                Gtk::FileChooser::ACTION_SELECT_FOLDER,
+                                                nil,
+                                                [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT], [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
+                fc.transient_for = dialog
+                if fc.run == Gtk::Dialog::RESPONSE_ACCEPT
+                    pathlabel.text = fc.filename
+                end    
+                fc.destroy
+            }
+            combo.signal_connect('changed') {
+                pathbutton.sensitive = combo.active == 0
+            }
+            vb = Gtk::VBox.new(false, 5)
+            vb.pack_start(combo, false, false)
+            vb.pack_start(pathbutton, false, false)
+            table.attach(Gtk::Alignment.new(0, 0.5, 1, 0).add(vb), 3, 4, row, row + 1, Gtk::FILL, Gtk::FILL, 5, 5)
+            { :combo => combo, :pathlabel => pathlabel }
+        else
+            table.attach(Gtk::Alignment.new(0, 0.5, 1, 0).add(combo), 3, 4, row, row + 1, Gtk::FILL, Gtk::FILL, 5, 5)
+            { :combo => combo }
+        end
+    }
+    stuff = {}
+    stuff['toremove'] = add_row.call(1, utf8(_("<i>to remove</i>")), Gdk::Color.new(65535, 0, 0), proc { |entry| entry.removed }, false)
+    $tags.values.each_with_index { |tag, row| stuff[tag] = add_row.call(row + 2, tag.name, tag.color, proc { |entry| entry.tagged == tag }, true) }
+    vb1.pack_start(sw = Gtk::ScrolledWindow.new(nil, nil).add_with_viewport(table).set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC), true, true)
+
+    toremove_amount = $allentries.find_all { |entry| entry.removed }.size
+    check_removal = Gtk::CheckButton.new(utf8(_("I have noticed I am about to permanently remove the %d above mentioned pictures.") % toremove_amount))
+    if toremove_amount > 0
+        vb1.pack_start(check_removal, false, false)
+        stuff['toremove'][:combo].signal_connect('changed') { |widget|
+            check_removal.sensitive = widget.active == 0
+        }
+    end
+
+    dialog.vbox.add(vb1)
+
+    dialog.set_default_size(800, 600)
+    dialog.add_button(Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL)
+    dialog.add_button(Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK)
+    dialog.window_position = Gtk::Window::POS_MOUSE
+    dialog.transient_for = $main_window
+
+    dialog.show_all
+
+    while true
+        dialog.run { |response|        
+            if response == Gtk::Dialog::RESPONSE_OK
+                if toremove_amount > 0 && ! check_removal.active? && check_removal.sensitive?
+                    show_popup(dialog, utf8(_("You have not confirmed that you noticed the permanent removal of the pictures marked for deletion.")))
+                    break
+                end
+                stuff.keys.each { |key|
+                    if key.is_a?(Tag) && stuff[key][:combo].active == 0
+                        path = stuff[key][:pathlabel].text
+                        puts path
+                        puts stuff[key][:pathlabel].markup
+                        if path == utf8(_("<i>(unset)</i>"))
+                            show_popup(dialog, utf8(_("You have not selected a directory where to move %s.") % key.name))
+                            break
+                        end
+                        st = File.stat(path)
+                        if ! st.directory? || ! st.writable?
+                            show_popup(dialog, utf8(_("Directory where to move %s is not valid or not writable.") % key.name))
+                            break
+                        end
+                    end
+                }
+            end
+            dialog.destroy
+            return
+        }
+    end
+end
+
+def create_menubar    
     #- menu
     mb = Gtk::MenuBar.new
 
@@ -844,7 +997,14 @@ def reset_tags
     for child in $tags_vbox.children
         $tags_vbox.remove(child)
     end
-    $tags_vbox.pack_start(Gtk::Label.new(utf8(_("Tags list:"))).set_justify(Gtk::Justification::CENTER), false, false)
+    $tags_vbox.pack_start(Gtk::Label.new(utf8(_("Tags list:"))).set_justify(Gtk::Justification::CENTER), false, false).show_all
+end
+
+def reset_thumbnails
+    $allentries = []
+    for child in $imagesline.children
+        $imagesline.remove(child)
+    end
 end
 
 def create_main_window
@@ -854,14 +1014,13 @@ def create_main_window
     main_vbox = Gtk::VBox.new(false, 0)
     main_vbox.pack_start(mb, false, false)
     mainview_hbox = Gtk::HBox.new
-    mainview_hbox.pack_start(tags_vbox_vbox = Gtk::VBox.new(false, 0), false, true)
-    tags_vbox_vbox.pack_start($tags_vbox = Gtk::VBox.new(false, 5), false, false)
+    mainview_hbox.pack_start(Gtk::Alignment.new(0.5, 0, 0, 0).add($tags_vbox = Gtk::VBox.new(false, 5)), false, true)
     reset_tags
     mainview_hbox.pack_start($mainview = MainView.new, true, true)
     main_vbox.pack_start(mainview_hbox, true, true)
     $imagesline_sw = Gtk::ScrolledWindow.new(nil, nil)
     $imagesline_sw.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_NEVER)
-    $imagesline_sw.add_with_viewport($imagesline = Gtk::HBox.new(false, 0))
+    $imagesline_sw.add_with_viewport($imagesline = Gtk::HBox.new(false, 0).show)
     main_vbox.pack_start($imagesline_sw, false, false)
     main_vbox.pack_end($statusbar = Gtk::Statusbar.new, false, false)