[gthumb] find duplicates: added ability to eliminate all the duplicates at once leaving only the newest or th
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] find duplicates: added ability to eliminate all the duplicates at once leaving only the newest or th
- Date: Sun, 3 Jul 2011 10:10:07 +0000 (UTC)
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]