[gthumb] find duplicates: added ability to eliminate all the duplicates at once leaving only the newest or th



commit a70202fb3bca61ff29157717dd16a36e8b6babe8
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Jul 3 12:05:04 2011 +0200

    find duplicates: added ability to eliminate all the duplicates at once leaving only the newest or the oldest one
    
    [bug #342887, new feature]

 extensions/find_duplicates/Makefile.am             |    2 +
 extensions/find_duplicates/data/ui/Makefile.am     |    5 +-
 .../data/ui/find-duplicates-choose-folders.ui      |   88 ++++
 .../data/ui/find-duplicates-dialog.ui              |  269 +++++++----
 extensions/find_duplicates/gth-find-duplicates.c   |  494 +++++++++++++++-----
 .../find_duplicates/gth-folder-chooser-dialog.c    |  224 +++++++++
 .../find_duplicates/gth-folder-chooser-dialog.h    |   56 +++
 7 files changed, 929 insertions(+), 209 deletions(-)
---
diff --git a/extensions/find_duplicates/Makefile.am b/extensions/find_duplicates/Makefile.am
index e4830a4..145a39b 100644
--- a/extensions/find_duplicates/Makefile.am
+++ b/extensions/find_duplicates/Makefile.am
@@ -12,6 +12,8 @@ libfind_duplicates_la_SOURCES = 	\
 	dlg-find-duplicates.h		\
 	gth-find-duplicates.c		\
 	gth-find-duplicates.h		\
+	gth-folder-chooser-dialog.c	\
+	gth-folder-chooser-dialog.h	\
 	main.c
 
 libfind_duplicates_la_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
diff --git a/extensions/find_duplicates/data/ui/Makefile.am b/extensions/find_duplicates/data/ui/Makefile.am
index 2aca39f..5235a09 100644
--- a/extensions/find_duplicates/data/ui/Makefile.am
+++ b/extensions/find_duplicates/data/ui/Makefile.am
@@ -1,5 +1,8 @@
 uidir = $(pkgdatadir)/ui
-ui_DATA = find-duplicates.ui find-duplicates-dialog.ui
+ui_DATA = 					\
+	find-duplicates.ui			\
+	find-duplicates-choose-folders.ui	\
+	find-duplicates-dialog.ui
 EXTRA_DIST = $(ui_DATA)
 
 -include $(top_srcdir)/git.mk
diff --git a/extensions/find_duplicates/data/ui/find-duplicates-choose-folders.ui b/extensions/find_duplicates/data/ui/find-duplicates-choose-folders.ui
new file mode 100644
index 0000000..553fd0f
--- /dev/null
+++ b/extensions/find_duplicates/data/ui/find-duplicates-choose-folders.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.24"/>
+  <object class="GtkVBox" id="folder_chooser">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkLabel" id="label1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">_Folders:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">folders_treeview</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow1">
+        <property name="width_request">300</property>
+        <property name="height_request">300</property>
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="shadow_type">in</property>
+        <property name="hscrollbar_policy">automatic</property>
+        <property name="vscrollbar_policy">automatic</property>
+        <child>
+          <object class="GtkTreeView" id="folders_treeview">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="model">folders_liststore</property>
+            <property name="headers_visible">False</property>
+            <property name="headers_clickable">False</property>
+            <property name="search_column">1</property>
+            <child internal-child="selection">
+              <object class="GtkTreeSelection" id="treeview-selection"/>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                <child>
+                  <object class="GtkCellRendererToggle" id="folder_cellrenderertoggle"/>
+                  <attributes>
+                    <attribute name="active">2</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                <child>
+                  <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1">
+                    <property name="icon_name">folder</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                  <attributes>
+                    <attribute name="text">1</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkListStore" id="folders_liststore">
+    <columns>
+      <!-- column-name file -->
+      <column type="GObject"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name selected -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+</interface>
diff --git a/extensions/find_duplicates/data/ui/find-duplicates-dialog.ui b/extensions/find_duplicates/data/ui/find-duplicates-dialog.ui
index 4257443..ddb1d99 100644
--- a/extensions/find_duplicates/data/ui/find-duplicates-dialog.ui
+++ b/extensions/find_duplicates/data/ui/find-duplicates-dialog.ui
@@ -1,7 +1,6 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <requires lib="gtk+" version="2.16"/>
-  <!-- interface-naming-policy project-wide -->
+  <requires lib="gtk+" version="2.24"/>
   <object class="GtkListStore" id="files_liststore">
     <columns>
       <!-- column-name file -->
@@ -17,6 +16,7 @@
     </columns>
   </object>
   <object class="GtkDialog" id="find_duplicates_dialog">
+    <property name="can_focus">False</property>
     <property name="border_width">6</property>
     <property name="title" translatable="yes">Search for Duplicates</property>
     <property name="destroy_with_parent">True</property>
@@ -24,102 +24,190 @@
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox12">
         <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <property name="spacing">6</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area12">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="help_button">
+                <property name="label">gtk-help</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="stop_button">
+                <property name="label">gtk-stop</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="close_button">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkVBox" id="vbox13">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="border_width">6</property>
             <property name="spacing">6</property>
             <child>
               <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="spacing">20</property>
                 <child>
                   <object class="GtkHBox" id="hbox1">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="spacing">24</property>
                     <child>
                       <object class="GtkVBox" id="vbox4">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <child>
                           <object class="GtkImage" id="image1">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <property name="stock">gtk-find</property>
                             <property name="icon-size">6</property>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
+                        <property name="fill">True</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkVBox" id="vbox2">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="spacing">6</property>
                         <child>
                           <object class="GtkLabel" id="progress_label">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <property name="xalign">0</property>
                             <property name="ellipsize">end</property>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkVBox" id="vbox3">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <property name="spacing">3</property>
                             <child>
                               <object class="GtkProgressBar" id="search_progressbar">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="search_details_label">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="xalign">0</property>
                                 <property name="ellipsize">end</property>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">1</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
                     <property name="position">0</property>
                   </packing>
                 </child>
               </object>
               <packing>
                 <property name="expand">False</property>
+                <property name="fill">True</property>
                 <property name="position">0</property>
               </packing>
             </child>
             <child>
               <object class="GtkHSeparator" id="hseparator7">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
               </object>
               <packing>
                 <property name="expand">False</property>
+                <property name="fill">True</property>
                 <property name="padding">6</property>
                 <property name="position">1</property>
               </packing>
@@ -127,23 +215,28 @@
             <child>
               <object class="GtkNotebook" id="pages_notebook">
                 <property name="visible">True</property>
+                <property name="can_focus">False</property>
                 <property name="show_tabs">False</property>
                 <property name="show_border">False</property>
                 <child>
                   <object class="GtkVBox" id="vbox19">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="spacing">12</property>
                     <child>
                       <object class="GtkVBox" id="vbox18">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="spacing">6</property>
                         <child>
                           <object class="GtkHBox" id="hbox46">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <property name="spacing">5</property>
                             <child>
                               <object class="GtkLabel" id="label73">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="xalign">0</property>
                                 <property name="label" translatable="yes">Duplicates:</property>
                               </object>
@@ -156,6 +249,7 @@
                             <child>
                               <object class="GtkLabel" id="total_duplicates_label">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="xalign">0</property>
                               </object>
                               <packing>
@@ -167,51 +261,85 @@
                           </object>
                           <packing>
                             <property name="expand">False</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkHBox" id="duplicates_list_box">
+                          <object class="GtkVBox" id="duplicates_list_box">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <child>
                               <placeholder/>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkVBox" id="vbox16">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="spacing">6</property>
                         <child>
-                          <object class="GtkLabel" id="label78">
+                          <object class="GtkHBox" id="box1">
                             <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Files:</property>
+                            <property name="can_focus">False</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkLabel" id="label78">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Files:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="total_files_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
                           </object>
                           <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkHBox" id="hbox50">
                             <property name="visible">True</property>
+                            <property name="can_focus">False</property>
                             <child>
                               <object class="GtkVBox" id="vbox14">
                                 <property name="visible">True</property>
+                                <property name="can_focus">False</property>
                                 <property name="spacing">5</property>
                                 <child>
                                   <object class="GtkHBox" id="hbox51">
                                     <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
                                     <property name="spacing">6</property>
                                     <child>
                                       <object class="GtkScrolledWindow" id="files_scrolledwindow">
@@ -219,9 +347,9 @@
                                         <property name="height_request">200</property>
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
-                                        <property name="hscrollbar_policy">automatic</property>
-                                        <property name="vscrollbar_policy">automatic</property>
                                         <property name="shadow_type">in</property>
+                                        <property name="hscrollbar_policy">automatic</property>
+                                        <property name="vscrollbar_policy">automatic</property>                                        
                                         <child>
                                           <object class="GtkTreeView" id="files_treeview">
                                             <property name="visible">True</property>
@@ -229,6 +357,9 @@
                                             <property name="model">files_liststore</property>
                                             <property name="rules_hint">True</property>
                                             <property name="enable_search">False</property>
+                                            <child internal-child="selection">
+                                              <object class="GtkTreeSelection" id="treeview-selection1"/>
+                                            </child>
                                             <child>
                                               <object class="GtkTreeViewColumn" id="treeviewcolumn4">
                                                 <property name="sizing">autosize</property>
@@ -291,36 +422,39 @@
                                         </child>
                                       </object>
                                       <packing>
+                                        <property name="expand">True</property>
+                                        <property name="fill">True</property>
                                         <property name="position">0</property>
                                       </packing>
                                     </child>
                                     <child>
                                       <object class="GtkVBox" id="files_commands_hbox">
                                         <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
                                         <property name="spacing">5</property>
                                         <child>
-                                          <object class="GtkButton" id="view_button">
-                                            <property name="label" translatable="yes">_View</property>
+                                          <object class="GtkVBox" id="select_button_box">
                                             <property name="visible">True</property>
-                                            <property name="sensitive">False</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="use_underline">True</property>
+                                            <property name="can_focus">False</property>
+                                            <child>
+                                              <placeholder/>
+                                            </child>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
-                                            <property name="fill">False</property>
+                                            <property name="fill">True</property>
                                             <property name="position">0</property>
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkButton" id="delete_button">
-                                            <property name="label">gtk-delete</property>
+                                          <object class="GtkButton" id="view_button">
+                                            <property name="label" translatable="yes">_View</property>
                                             <property name="visible">True</property>
                                             <property name="sensitive">False</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">True</property>
-                                            <property name="use_stock">True</property>
+                                            <property name="use_action_appearance">False</property>
+                                            <property name="use_underline">True</property>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
@@ -329,12 +463,14 @@
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkButton" id="select_all_button">
-                                            <property name="label" translatable="yes">Select _All</property>
+                                          <object class="GtkButton" id="delete_button">
+                                            <property name="label" translatable="yes">_Delete</property>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">True</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="use_underline">True</property>
+                                            <property name="image_position">right</property>
                                           </object>
                                           <packing>
                                             <property name="expand">False</property>
@@ -343,44 +479,41 @@
                                           </packing>
                                         </child>
                                         <child>
-                                          <object class="GtkButton" id="unselect_all_button">
-                                            <property name="label" translatable="yes">_Unselect All</property>
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="use_underline">True</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="fill">False</property>
-                                            <property name="position">3</property>
-                                          </packing>
+                                          <placeholder/>
                                         </child>
                                       </object>
                                       <packing>
                                         <property name="expand">False</property>
+                                        <property name="fill">True</property>
                                         <property name="pack_type">end</property>
                                         <property name="position">1</property>
                                       </packing>
                                     </child>
                                   </object>
                                   <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
                                     <property name="position">0</property>
                                   </packing>
                                 </child>
                               </object>
                               <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
                                 <property name="position">0</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">True</property>
+                            <property name="fill">True</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
+                        <property name="fill">True</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
@@ -389,6 +522,7 @@
                 <child type="tab">
                   <object class="GtkLabel" id="label80">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="label" translatable="yes">label80</property>
                   </object>
                   <packing>
@@ -398,26 +532,33 @@
                 <child>
                   <object class="GtkHBox" id="hbox53">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="spacing">10</property>
                     <child>
                       <object class="GtkImage" id="image43">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">1</property>
                         <property name="stock">gtk-dialog-warning</property>
                         <property name="icon-size">6</property>
                       </object>
                       <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
                         <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkLabel" id="label82">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
                         <property name="xalign">0</property>
                         <property name="label" translatable="yes">No duplicates found.</property>
                         <property name="wrap">True</property>
                       </object>
                       <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
@@ -429,6 +570,7 @@
                 <child type="tab">
                   <object class="GtkLabel" id="label81">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="label" translatable="yes">label81</property>
                   </object>
                   <packing>
@@ -438,67 +580,18 @@
                 </child>
               </object>
               <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
                 <property name="position">2</property>
               </packing>
             </child>
           </object>
           <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
             <property name="position">1</property>
           </packing>
         </child>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area12">
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="help_button">
-                <property name="label">gtk-help</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-                <property name="secondary">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="stop_button">
-                <property name="label">gtk-stop</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="close_button">
-                <property name="label">gtk-close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
       </object>
     </child>
     <action-widgets>
diff --git a/extensions/find_duplicates/gth-find-duplicates.c b/extensions/find_duplicates/gth-find-duplicates.c
index 3af3c0f..997ce62 100644
--- a/extensions/find_duplicates/gth-find-duplicates.c
+++ b/extensions/find_duplicates/gth-find-duplicates.c
@@ -26,10 +26,36 @@
 #include <extensions/catalogs/gth-catalog.h>
 #include <extensions/file_manager/actions.h>
 #include "gth-find-duplicates.h"
+#include "gth-folder-chooser-dialog.h"
 
 
 #define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
 #define BUFFER_SIZE 4096
+#define SELECT_COMMAND_ID_DATA "delete-command-id"
+
+
+typedef enum {
+	SELECT_LEAVE_NEWEST,
+	SELECT_LEAVE_OLDEST,
+	SELECT_BY_FOLDER,
+	SELECT_ALL,
+	SELECT_NONE
+} SelectID;
+
+
+typedef struct {
+	const char *display_name;
+	SelectID    id;
+} SelectCommand;
+
+
+SelectCommand select_commands[] = {
+	{ N_("leave the newest duplicates"), SELECT_LEAVE_NEWEST },
+	{ N_("leave the oldest duplicates"), SELECT_LEAVE_OLDEST },
+	{ N_("by folder..."), SELECT_BY_FOLDER },
+	{ N_("all files"), SELECT_ALL },
+	{ N_("no file"), SELECT_NONE }
+};
 
 
 struct _GthFindDuplicatesPrivate
@@ -40,6 +66,8 @@ struct _GthFindDuplicatesPrivate
 	GthTest       *test;
 	GtkBuilder    *builder;
 	GtkWidget     *duplicates_list;
+	GtkWidget     *select_button;
+	GtkWidget     *select_menu;
 	GString       *attributes;
 	GCancellable  *cancellable;
 	gboolean       io_operation;
@@ -184,6 +212,150 @@ gth_find_duplicates_get_type (void)
 }
 
 
+static void
+update_file_list_sensitivity (GthFindDuplicates *self)
+{
+	GtkTreeModel *model;
+	GtkTreeIter   iter;
+	gboolean      one_active = FALSE;
+
+	model = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			gboolean active;
+
+			gtk_tree_model_get (model, &iter, 1, &active, -1);
+			if (active) {
+				one_active = TRUE;
+				break;
+			}
+		}
+		while (gtk_tree_model_iter_next (model, &iter));
+	}
+
+	gtk_widget_set_sensitive (GET_WIDGET ("view_button"), one_active);
+	gtk_widget_set_sensitive (GET_WIDGET ("delete_button"), one_active);
+}
+
+
+static void
+update_file_list_selection_info (GthFindDuplicates *self)
+{
+	GtkTreeModel *model;
+	GtkTreeIter   iter;
+	int           n_files;
+	goffset       total_size;
+	char         *size_formatted;
+	char         *text;
+
+	n_files = 0;
+	total_size = 0;
+
+	model = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			GthFileData *file_data;
+			gboolean     active;
+
+			gtk_tree_model_get (model, &iter,
+					    0, &file_data,
+					    1, &active,
+					    -1);
+
+			if (active) {
+				n_files += 1;
+				total_size += g_file_info_get_size (file_data->info);
+			}
+
+			_g_object_unref (file_data);
+		}
+		while (gtk_tree_model_iter_next (model, &iter));
+	}
+
+	size_formatted = g_format_size_for_display (total_size);
+	text = g_strdup_printf (g_dngettext (NULL, "%d file (%s)", "%d files (%s)", n_files), n_files, size_formatted);
+	gtk_label_set_text (GTK_LABEL (GET_WIDGET ("total_files_label")), text);
+
+	g_free (text);
+	g_free (size_formatted);
+}
+
+
+static GList *
+get_duplicates_file_data_list (GthFindDuplicates *self)
+{
+	GtkWidget *duplicates_view;
+	GList     *items;
+	GList     *file_data_list;
+
+	duplicates_view = gth_file_list_get_view (GTH_FILE_LIST (self->priv->duplicates_list));
+	items = gth_file_selection_get_selected (GTH_FILE_SELECTION (duplicates_view));
+	file_data_list = gth_file_list_get_files (GTH_FILE_LIST (self->priv->duplicates_list), items);
+	if (file_data_list == NULL)
+		file_data_list = gth_file_store_get_visibles (GTH_FILE_STORE (gth_file_view_get_model (GTH_FILE_VIEW (duplicates_view))));
+
+	_gtk_tree_path_list_free (items);
+
+	return file_data_list;
+}
+
+
+static void
+duplicates_list_view_selection_changed_cb (GthFileView *fileview,
+					   gpointer     user_data)
+{
+	GthFindDuplicates *self = user_data;
+	GList             *file_data_list;
+	GList             *scan;
+
+	file_data_list = get_duplicates_file_data_list (self);
+
+	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("files_liststore")));
+
+	for (scan = file_data_list; scan; scan = scan->next) {
+		GthFileData    *selected_file_data = (GthFileData *) scan->data;
+		const char     *checksum;
+		DuplicatedData *d_data;
+		GList          *scan_duplicated;
+
+		checksum = g_file_info_get_attribute_string (selected_file_data->info, "find-duplicates::checksum");
+		d_data = g_hash_table_lookup (self->priv->duplicated, checksum);
+
+		g_return_if_fail (d_data != NULL);
+
+		for (scan_duplicated = d_data->files; scan_duplicated; scan_duplicated = scan_duplicated->next) {
+			GthFileData *file_data = scan_duplicated->data;
+			GFile       *parent;
+			char        *parent_name;
+			GtkTreeIter  iter;
+
+			parent = g_file_get_parent (file_data->file);
+			if (parent != NULL)
+				parent_name = g_file_get_parse_name (parent);
+			else
+				parent_name = NULL;
+			gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("files_liststore")), &iter);
+			gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("files_liststore")), &iter,
+					    0, file_data,
+					    1, TRUE,
+					    2, g_file_info_get_display_name (file_data->info),
+					    3, parent_name,
+					    4, g_file_info_get_attribute_string (file_data->info, "gth::file::display-mtime"),
+					    -1);
+
+			g_free (parent_name);
+			g_object_unref (parent);
+		}
+	}
+
+	update_file_list_sensitivity (self);
+	update_file_list_selection_info (self);
+
+	_g_object_list_unref (file_data_list);
+
+}
+
+
 static void start_next_checksum (GthFindDuplicates *self);
 
 
@@ -255,6 +427,7 @@ file_input_stream_read_ready_cb (GObject      *source,
 			g_list_free (list);
 		}
 
+		duplicates_list_view_selection_changed_cb (NULL, self);
 		start_next_checksum (self);
 
 		return;
@@ -439,93 +612,6 @@ help_button_clicked_cb (GtkButton *button,
 
 
 static void
-update_file_list_sensitivity (GthFindDuplicates *self)
-{
-	GtkTreeModel *model;
-	GtkTreeIter   iter;
-	gboolean      one_active = FALSE;
-
-	model = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
-	if (gtk_tree_model_get_iter_first (model, &iter)) {
-		do {
-			gboolean active;
-
-			gtk_tree_model_get (model, &iter, 1, &active, -1);
-			if (active) {
-				one_active = TRUE;
-				break;
-			}
-		}
-		while (gtk_tree_model_iter_next(model, &iter));
-	}
-
-	gtk_widget_set_sensitive (GET_WIDGET ("view_button"), one_active);
-	gtk_widget_set_sensitive (GET_WIDGET ("delete_button"), one_active);
-}
-
-
-static void
-duplicates_list_view_selection_changed_cb (GthFileView *fileview,
-					   gpointer     user_data)
-{
-	GthFindDuplicates *self = user_data;
-	GtkWidget         *duplicates_view;
-	int                n_selected;
-
-	duplicates_view = gth_file_list_get_view (GTH_FILE_LIST (self->priv->duplicates_list));
-	n_selected = gth_file_selection_get_n_selected (GTH_FILE_SELECTION (duplicates_view));
-	if (n_selected == 1) {
-		GList          *items;
-		GList          *file_list;
-		GthFileData    *selected_file_data;
-		const char     *checksum;
-		DuplicatedData *d_data;
-		GList          *scan;
-
-		items = gth_file_selection_get_selected (GTH_FILE_SELECTION (duplicates_view));
-		file_list = gth_file_list_get_files (GTH_FILE_LIST (self->priv->duplicates_list), items);
-		selected_file_data = (GthFileData *) file_list->data;
-
-		gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("files_liststore")));
-
-		checksum = g_file_info_get_attribute_string (selected_file_data->info, "find-duplicates::checksum");
-		d_data = g_hash_table_lookup (self->priv->duplicated, checksum);
-
-		g_return_if_fail (d_data != NULL);
-
-		for (scan = d_data->files; scan; scan = scan->next) {
-			GthFileData *file_data = scan->data;
-			GFile       *parent;
-			char        *parent_name;
-			GtkTreeIter  iter;
-
-			parent = g_file_get_parent (file_data->file);
-			if (parent != NULL)
-				parent_name = g_file_get_parse_name (parent);
-			else
-				parent_name = NULL;
-			gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("files_liststore")), &iter);
-			gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("files_liststore")), &iter,
-					    0, file_data,
-					    1, TRUE,
-					    2, g_file_info_get_display_name (file_data->info),
-					    3, parent_name,
-					    4, g_file_info_get_attribute_string (file_data->info, "gth::file::display-mtime"),
-					    -1);
-
-			g_free (parent_name);
-			g_object_unref (parent);
-		}
-
-		update_file_list_sensitivity (self);
-
-		_g_object_list_unref (file_list);
-		_gtk_tree_path_list_free (items);
-	}
-}
-
-
-static void
 file_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
                 		    char                  *path,
                 		    gpointer               user_data)
@@ -547,6 +633,7 @@ file_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
 	gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, ! active, -1);
 
 	update_file_list_sensitivity (self);
+	update_file_list_selection_info (self);
 
 	gtk_tree_path_free (tree_path);
 }
@@ -618,45 +705,197 @@ delete_button_clicked_cb (GtkWidget *button,
 	GList             *file_data_list;
 
 	file_data_list = get_selected_files (self);
-	if (file_data_list != NULL)
+	if (file_data_list != NULL) {
 		gth_file_mananger_delete_files (GTK_WINDOW (GET_WIDGET ("find_duplicates_dialog")), file_data_list);
-
-	_g_object_list_unref (file_data_list);
+		_g_object_list_unref (file_data_list);
+	}
 }
 
 
 static void
-select_all_files (GthFindDuplicates *self,
-		  gboolean           active)
+select_files_leaving_one (GthFindDuplicates *self,
+			  GtkTreeModel      *model,
+			  SelectID           selection_type)
 {
-	GtkTreeModel *model;
-	GtkTreeIter   iter;
+	GHashTable  *newest_files;
+	GList       *file_data_list;
+	GList       *scan;
+	GtkTreeIter  iter;
 
-	model = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
-	if (! gtk_tree_model_get_iter_first (model, &iter))
-		return;
+	newest_files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	file_data_list = get_duplicates_file_data_list (self);
 
-	do {
-		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, active, -1);
+	for (scan = file_data_list; scan; scan = scan->next) {
+		GthFileData    *selected_file_data = (GthFileData *) scan->data;
+		const char     *checksum;
+		DuplicatedData *d_data;
+		GList          *scan_duplicated;
+		GthFileData    *newest_file = NULL;
+
+		checksum = g_file_info_get_attribute_string (selected_file_data->info, "find-duplicates::checksum");
+		d_data = g_hash_table_lookup (self->priv->duplicated, checksum);
+
+		g_return_if_fail (d_data != NULL);
+
+		for (scan_duplicated = d_data->files; scan_duplicated; scan_duplicated = scan_duplicated->next) {
+			GthFileData *file_data = scan_duplicated->data;
+
+			if (newest_file != NULL) {
+				GTimeVal *t_newest_file;
+				GTimeVal *t_file_data;
+				gboolean  is_newest = FALSE;
+
+				t_newest_file = gth_file_data_get_modification_time (newest_file);
+				t_file_data = gth_file_data_get_modification_time (file_data);
+
+				switch (selection_type) {
+				case SELECT_LEAVE_NEWEST:
+					is_newest = _g_time_val_cmp (t_file_data, t_newest_file) < 0;
+					break;
+				case SELECT_LEAVE_OLDEST:
+					is_newest = _g_time_val_cmp (t_file_data, t_newest_file) > 0;
+					break;
+				default:
+					break;
+				}
+
+				if (is_newest) {
+					g_object_unref (newest_file);
+					newest_file = g_object_ref (file_data);
+				}
+			}
+			else
+				newest_file = g_object_ref (file_data);
+		}
+
+		g_hash_table_insert (newest_files, g_strdup (checksum), newest_file);
 	}
-	while (gtk_tree_model_iter_next (model, &iter));
 
-	update_file_list_sensitivity (self);
-}
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			GthFileData *file_data;
+			const char  *checksum;
+			GthFileData *newest_file;
+			gboolean     active;
 
-static void
-select_all_button_clicked_cb (GtkWidget *button,
-			      gpointer   user_data)
-{
-	select_all_files (GTH_FIND_DUPLICATES (user_data), TRUE);
+			gtk_tree_model_get (model, &iter, 0, &file_data, -1);
+			checksum = g_file_info_get_attribute_string (file_data->info, "find-duplicates::checksum");
+			newest_file = g_hash_table_lookup (newest_files, checksum);
+			active = ((newest_file == NULL) || ! g_file_equal (newest_file->file, file_data->file));
+			gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, active, -1);
+
+			g_object_unref (file_data);
+		}
+		while (gtk_tree_model_iter_next (model, &iter));
+	}
+
+	_g_object_list_unref (file_data_list);
+	g_hash_table_unref (newest_files);
 }
 
 
 static void
-unselect_all_button_clicked_cb (GtkWidget *button,
-			        gpointer   user_data)
+select_menu_item_activate_cb (GtkMenuItem *menu_item,
+         		      gpointer     user_data)
 {
-	select_all_files (GTH_FIND_DUPLICATES (user_data), FALSE);
+	GthFindDuplicates *self = user_data;
+	SelectID           id;
+	GtkTreeModel      *model;
+	GtkTreeIter        iter;
+
+	model = GTK_TREE_MODEL (GET_WIDGET ("files_liststore"));
+
+	id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), SELECT_COMMAND_ID_DATA));
+	switch (id) {
+	case SELECT_ALL:
+	case SELECT_NONE:
+		if (gtk_tree_model_get_iter_first (model, &iter)) {
+			do {
+				gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, (id == SELECT_ALL), -1);
+			}
+			while (gtk_tree_model_iter_next (model, &iter));
+		}
+		break;
+
+	case SELECT_BY_FOLDER:
+		{
+			GHashTable *folders_table;
+			GList      *folders = NULL;
+			GtkWidget  *dialog;
+			GHashTable *selected_folders = NULL;
+
+			folders_table = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
+
+			if (gtk_tree_model_get_iter_first (model, &iter)) {
+				do {
+					GthFileData *file_data;
+					GFile       *folder;
+
+					gtk_tree_model_get (model, &iter, 0, &file_data, -1);
+
+					folder = g_file_get_parent (file_data->file);
+					if (folder != NULL) {
+						if (g_hash_table_lookup (folders_table, folder) == NULL)
+							g_hash_table_insert (folders_table, g_object_ref (folder), GINT_TO_POINTER (1));
+
+						g_object_unref (folder);
+					}
+
+					g_object_unref (file_data);
+				}
+				while (gtk_tree_model_iter_next (model, &iter));
+
+				folders = g_hash_table_get_keys (folders_table);
+			}
+
+			dialog = gth_folder_chooser_dialog_new (folders);
+			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (GET_WIDGET ("find_duplicates_dialog")));
+			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+			gtk_widget_show (dialog);
+
+			switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
+			case GTK_RESPONSE_OK:
+				selected_folders = gth_folder_chooser_dialog_get_selected (GTH_FOLDER_CHOOSER_DIALOG (dialog));
+				break;
+			default:
+				break;
+			}
+			gtk_widget_destroy (dialog);
+
+			if (selected_folders != NULL) {
+				if (gtk_tree_model_get_iter_first (model, &iter)) {
+					do {
+						GthFileData *file_data;
+						GFile       *parent;
+						gboolean     active;
+
+						gtk_tree_model_get (model, &iter, 0, &file_data, -1);
+						parent = g_file_get_parent (file_data->file);
+						active = (parent != NULL) && g_hash_table_lookup (selected_folders, parent) != NULL;
+						gtk_list_store_set (GTK_LIST_STORE (model), &iter, 1, active, -1);
+
+						_g_object_unref (parent);
+						g_object_unref (file_data);
+					}
+					while (gtk_tree_model_iter_next (model, &iter));
+				}
+
+				g_hash_table_unref (selected_folders);
+			}
+
+			g_list_free (folders);
+			g_hash_table_unref (folders_table);
+		}
+		break;
+
+	case SELECT_LEAVE_NEWEST:
+	case SELECT_LEAVE_OLDEST:
+		select_files_leaving_one (self, model, id);
+		break;
+	}
+
+	update_file_list_sensitivity (self);
+	update_file_list_selection_info (self);
 }
 
 
@@ -668,6 +907,7 @@ gth_find_duplicates_exec (GthBrowser *browser,
 {
 	GthFindDuplicates *self;
 	const char        *test_attributes;
+	int                i;
 
 	self = (GthFindDuplicates *) g_object_new (GTH_TYPE_FIND_DUPLICATES, NULL);
 
@@ -690,13 +930,35 @@ gth_find_duplicates_exec (GthBrowser *browser,
 
 	self->priv->builder = _gtk_builder_new_from_file ("find-duplicates-dialog.ui", "find_duplicates");
 	self->priv->duplicates_list = gth_file_list_new (gth_icon_view_new (), GTH_FILE_LIST_TYPE_NORMAL, FALSE);
-	gth_file_selection_set_selection_mode (GTH_FILE_SELECTION (gth_file_list_get_view (GTH_FILE_LIST (self->priv->duplicates_list))), GTK_SELECTION_SINGLE);
+	gth_file_selection_set_selection_mode (GTH_FILE_SELECTION (gth_file_list_get_view (GTH_FILE_LIST (self->priv->duplicates_list))), GTK_SELECTION_MULTIPLE);
 	gth_file_list_set_caption (GTH_FILE_LIST (self->priv->duplicates_list), "find-duplicates::n-duplicates,gth::file::display-size");
 	gth_file_list_set_thumb_size (GTH_FILE_LIST (self->priv->duplicates_list), 112);
-	gtk_widget_set_size_request (self->priv->duplicates_list, -1, 200);
+	gtk_widget_set_size_request (self->priv->duplicates_list, -1, 300);
 	gtk_widget_show (self->priv->duplicates_list);
 	gtk_container_add (GTK_CONTAINER (GET_WIDGET ("duplicates_list_box")), self->priv->duplicates_list);
 
+	self->priv->select_button = gth_menu_button_new ();
+	gth_menu_button_set_label (GTH_MENU_BUTTON (self->priv->select_button), _("Select"));
+	gtk_widget_show (self->priv->select_button);
+	gtk_box_pack_start (GTK_BOX (GET_WIDGET ("select_button_box")), self->priv->select_button, FALSE, FALSE, 0);
+
+	self->priv->select_menu = gtk_menu_new ();
+	for (i = 0; i < G_N_ELEMENTS (select_commands); i++) {
+		SelectCommand *command = &select_commands[i];
+		GtkWidget     *menu_item;
+
+		menu_item = gtk_menu_item_new_with_label (_(command->display_name));
+		g_object_set_data (G_OBJECT (menu_item), SELECT_COMMAND_ID_DATA, GINT_TO_POINTER (command->id));
+		gtk_widget_show (menu_item);
+		g_signal_connect (menu_item,
+				  "activate",
+				  G_CALLBACK (select_menu_item_activate_cb),
+				  self);
+
+		gtk_menu_shell_append (GTK_MENU_SHELL (self->priv->select_menu), menu_item);
+	}
+	gth_menu_button_set_menu (GTH_MENU_BUTTON (self->priv->select_button), self->priv->select_menu);
+
 	g_signal_connect (GET_WIDGET ("find_duplicates_dialog"),
 			  "destroy",
 			  G_CALLBACK (find_duplicates_dialog_destroy_cb),
@@ -729,14 +991,6 @@ gth_find_duplicates_exec (GthBrowser *browser,
 			  "clicked",
 			  G_CALLBACK (delete_button_clicked_cb),
 			  self);
-	g_signal_connect (GET_WIDGET ("select_all_button"),
-			  "clicked",
-			  G_CALLBACK (select_all_button_clicked_cb),
-			  self);
-	g_signal_connect (GET_WIDGET ("unselect_all_button"),
-			  "clicked",
-			  G_CALLBACK (unselect_all_button_clicked_cb),
-			  self);
 
 	gtk_widget_show (GET_WIDGET ("find_duplicates_dialog"));
 	gtk_window_set_transient_for (GTK_WINDOW (GET_WIDGET ("find_duplicates_dialog")), GTK_WINDOW (self->priv->browser));
diff --git a/extensions/find_duplicates/gth-folder-chooser-dialog.c b/extensions/find_duplicates/gth-folder-chooser-dialog.c
new file mode 100644
index 0000000..12bf56b
--- /dev/null
+++ b/extensions/find_duplicates/gth-folder-chooser-dialog.c
@@ -0,0 +1,224 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "gth-folder-chooser-dialog.h"
+
+#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
+
+
+enum {
+	FOLDER_FILE_COLUMN,
+	FOLDER_NAME_COLUMN,
+	FOLDER_SELECTED_COLUMN
+};
+
+
+static gpointer parent_class = NULL;
+
+
+struct _GthFolderChooserDialogPrivate {
+	GtkBuilder *builder;
+};
+
+
+static void
+gth_folder_chooser_dialog_finalize (GObject *object)
+{
+	GthFolderChooserDialog *self;
+
+	self = GTH_FOLDER_CHOOSER_DIALOG (object);
+
+	_g_object_unref (self->priv->builder);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+gth_folder_chooser_dialog_class_init (GthFolderChooserDialogClass *klass)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GthFolderChooserDialogPrivate));
+
+	object_class = (GObjectClass*) klass;
+	object_class->finalize = gth_folder_chooser_dialog_finalize;
+}
+
+
+static void
+folder_cellrenderertoggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
+                		      char                  *path,
+                		      gpointer               user_data)
+{
+	GthFolderChooserDialog *self = user_data;
+	GtkTreeModel           *model;
+	GtkTreePath            *tree_path;
+	GtkTreeIter             iter;
+	gboolean                selected;
+
+	model = GTK_TREE_MODEL (GET_WIDGET ("folders_liststore"));
+	tree_path = gtk_tree_path_new_from_string (path);
+	if (! gtk_tree_model_get_iter (model, &iter, tree_path)) {
+		gtk_tree_path_free (tree_path);
+		return;
+	}
+
+	gtk_tree_model_get (model, &iter, FOLDER_SELECTED_COLUMN, &selected, -1);
+	gtk_list_store_set (GTK_LIST_STORE (model), &iter, FOLDER_SELECTED_COLUMN, ! selected, -1);
+
+	gtk_tree_path_free (tree_path);
+}
+
+
+static void
+gth_folder_chooser_dialog_init (GthFolderChooserDialog *self)
+{
+	GtkWidget *content;
+
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_FOLDER_CHOOSER_DIALOG, GthFolderChooserDialogPrivate);
+	self->priv->builder = _gtk_builder_new_from_file ("find-duplicates-choose-folders.ui", "find_duplicates");
+
+	gtk_window_set_resizable (GTK_WINDOW (self), TRUE);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 5);
+	gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+
+	content = _gtk_builder_get_widget (self->priv->builder, "folder_chooser");
+	gtk_container_set_border_width (GTK_CONTAINER (content), 5);
+	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), content, TRUE, TRUE, 0);
+
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GET_WIDGET ("folders_liststore")), FOLDER_NAME_COLUMN, GTK_SORT_ASCENDING);
+
+	g_signal_connect (GET_WIDGET ("folder_cellrenderertoggle"),
+			  "toggled",
+			  G_CALLBACK (folder_cellrenderertoggle_toggled_cb),
+			  self);
+
+	gtk_dialog_add_button (GTK_DIALOG (self),
+			       GTK_STOCK_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (self),
+			       GTK_STOCK_OK,
+			       GTK_RESPONSE_OK);
+	gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+}
+
+
+GType
+gth_folder_chooser_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (type == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (GthFolderChooserDialogClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) gth_folder_chooser_dialog_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (GthFolderChooserDialog),
+			0,
+			(GInstanceInitFunc) gth_folder_chooser_dialog_init,
+			NULL
+		};
+		type = g_type_register_static (GTK_TYPE_DIALOG,
+					       "GthFolderChooserDialog",
+					       &g_define_type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+static void
+gth_folder_chooser_dialog_construct (GthFolderChooserDialog *self,
+				     GList                  *folders)
+{
+	GtkTreeIter  iter;
+	GList       *scan;
+	int          idx;
+
+	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("folders_liststore")));
+
+	for (scan = folders, idx = 0; scan; scan = scan->next, idx++) {
+		GFile *folder = scan->data;
+		char  *display_name;
+
+		display_name = g_file_get_parse_name (folder);
+		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("folders_liststore")), &iter);
+		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("folders_liststore")), &iter,
+				    FOLDER_FILE_COLUMN, folder,
+				    FOLDER_NAME_COLUMN, display_name,
+				    FOLDER_SELECTED_COLUMN, FALSE,
+				    -1);
+
+		g_free (display_name);
+	}
+}
+
+
+GtkWidget *
+gth_folder_chooser_dialog_new (GList *folders)
+{
+	GthFolderChooserDialog *self;
+
+	self = g_object_new (GTH_TYPE_FOLDER_CHOOSER_DIALOG, NULL);
+	gth_folder_chooser_dialog_construct (self, folders);
+
+	return (GtkWidget *) self;
+}
+
+
+GHashTable *
+gth_folder_chooser_dialog_get_selected (GthFolderChooserDialog *self)
+{
+	GHashTable   *folders;
+	GtkTreeModel *model;
+	GtkTreeIter   iter;
+
+	folders = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
+
+	model = GTK_TREE_MODEL (GET_WIDGET ("folders_liststore"));
+	if (gtk_tree_model_get_iter_first (model, &iter)) {
+		do {
+			GFile    *folder;
+			gboolean  selected;
+
+			gtk_tree_model_get (model, &iter,
+					    FOLDER_FILE_COLUMN, &folder,
+					    FOLDER_SELECTED_COLUMN, &selected,
+					    -1);
+
+			if (selected)
+				g_hash_table_insert (folders, g_object_ref (folder), GINT_TO_POINTER (1));
+
+			g_object_unref (folder);
+		}
+		while (gtk_tree_model_iter_next (model, &iter));
+	}
+
+	return folders;
+}
diff --git a/extensions/find_duplicates/gth-folder-chooser-dialog.h b/extensions/find_duplicates/gth-folder-chooser-dialog.h
new file mode 100644
index 0000000..8fb2cc2
--- /dev/null
+++ b/extensions/find_duplicates/gth-folder-chooser-dialog.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_FOLDER_CHOOSER_DIALOG_H
+#define GTH_FOLDER_CHOOSER_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_FOLDER_CHOOSER_DIALOG            (gth_folder_chooser_dialog_get_type ())
+#define GTH_FOLDER_CHOOSER_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_FOLDER_CHOOSER_DIALOG, GthFolderChooserDialog))
+#define GTH_FOLDER_CHOOSER_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_FOLDER_CHOOSER_DIALOG, GthFolderChooserDialogClass))
+#define GTH_IS_FOLDER_CHOOSER_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_FOLDER_CHOOSER_DIALOG))
+#define GTH_IS_FOLDER_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_FOLDER_CHOOSER_DIALOG))
+#define GTH_FOLDER_CHOOSER_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTH_TYPE_FOLDER_CHOOSER_DIALOG, GthFolderChooserDialogClass))
+
+typedef struct _GthFolderChooserDialog GthFolderChooserDialog;
+typedef struct _GthFolderChooserDialogClass GthFolderChooserDialogClass;
+typedef struct _GthFolderChooserDialogPrivate GthFolderChooserDialogPrivate;
+
+struct _GthFolderChooserDialog {
+	GtkDialog parent_instance;
+	GthFolderChooserDialogPrivate *priv;
+};
+
+struct _GthFolderChooserDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType        gth_folder_chooser_dialog_get_type     (void);
+GtkWidget *  gth_folder_chooser_dialog_new          (GList *folders);
+GHashTable * gth_folder_chooser_dialog_get_selected (GthFolderChooserDialog *self);
+
+G_END_DECLS
+
+#endif /* GTH_FOLDER_CHOOSER_DIALOG_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]