[gthumb/ext] [photo importer] another batch of changes



commit e36ecaf07916197a7a2a5c67cae1bb0de9e1d2d1
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Wed Aug 12 00:10:14 2009 +0200

    [photo importer] another batch of changes
    
    Changed the gth_file_store API in order to use GtkTreeIter to
    iterate through the items; added a new selection mode based on
    checkboxes.  Added a filter to the photo importer dialog.
    Added other file type tests such as video and audio.

 extensions/image_viewer/gth-image-viewer-page.c    |   20 +-
 .../photo_importer/data/ui/photo-importer.ui       |  268 ++++++++------
 extensions/photo_importer/dlg-photo-importer.c     |  184 +++++++--
 gthumb/gth-browser.c                               |   81 +++--
 gthumb/gth-cell-renderer-thumbnail.c               |  285 +++++---------
 gthumb/gth-file-list.c                             |  282 +++++++++------
 gthumb/gth-file-list.h                             |    8 +-
 gthumb/gth-file-selection.c                        |   85 +++--
 gthumb/gth-file-selection.h                        |    4 +
 gthumb/gth-file-store.c                            |  400 ++++++++++++++------
 gthumb/gth-file-store.h                            |  117 +++---
 gthumb/gth-icon-view.c                             |    9 +
 gthumb/gth-main-default-tests.c                    |   40 ++
 13 files changed, 1076 insertions(+), 707 deletions(-)
---
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 3c875f2..fcca66e 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -561,9 +561,9 @@ gth_image_viewer_page_real_view (GthViewerPage *base,
 {
 	GthImageViewerPage *self;
 	GthFileStore       *file_store;
-	int                 file_pos;
-	GthFileData        *next_file_data;
-	GthFileData        *prev_file_data;
+	GtkTreeIter         iter;
+	GthFileData        *next_file_data = NULL;
+	GthFileData        *prev_file_data = NULL;
 
 	self = (GthImageViewerPage*) base;
 	g_return_if_fail (file_data != NULL);
@@ -572,9 +572,17 @@ gth_image_viewer_page_real_view (GthViewerPage *base,
 	self->priv->file_data = gth_file_data_dup (file_data);
 
 	file_store = gth_browser_get_file_store (self->priv->browser);
-	file_pos = gth_file_store_find_visible (file_store, file_data->file);
-	next_file_data = gth_file_store_get_file_at_pos (file_store, file_pos + 1);
-	prev_file_data = gth_file_store_get_file_at_pos (file_store, file_pos - 1);
+	if (gth_file_store_find_visible (file_store, file_data->file, &iter)) {
+		GtkTreeIter iter2;
+
+		iter2 = iter;
+		if (gth_file_store_get_next_visible (file_store, &iter2))
+			next_file_data = gth_file_store_get_file (file_store, &iter2);
+
+		iter2 = iter;
+		if (gth_file_store_get_prev_visible (file_store, &iter2))
+			prev_file_data = gth_file_store_get_file (file_store, &iter2);
+	}
 
 	gth_image_preloader_load (self->priv->preloader,
 				  file_data,
diff --git a/extensions/photo_importer/data/ui/photo-importer.ui b/extensions/photo_importer/data/ui/photo-importer.ui
index 2695c01..2a9f8a1 100644
--- a/extensions/photo_importer/data/ui/photo-importer.ui
+++ b/extensions/photo_importer/data/ui/photo-importer.ui
@@ -19,133 +19,152 @@
             <property name="orientation">vertical</property>
             <property name="spacing">12</property>
             <child>
-              <object class="GtkTable" id="table1">
+              <object class="GtkHBox" id="hbox3">
                 <property name="visible">True</property>
-                <property name="n_rows">4</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">6</property>
+                <property name="spacing">12</property>
                 <child>
-                  <object class="GtkLabel" id="label1">
+                  <object class="GtkVBox" id="vbox2">
                     <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Destination:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">destination_filechooserbutton</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="subfolder_label">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">S_ubFolder:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Tags:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">tags_entry</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkFileChooserButton" id="destination_filechooserbutton">
-                    <property name="visible">True</property>
-                    <property name="action">select-folder</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="tags_entry">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="invisible_char">&#x25CF;</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="subfolder_box">
-                    <property name="visible">True</property>
-                    <property name="spacing">6</property>
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkHBox" id="subfolder_type_box">
+                      <object class="GtkTable" id="table1">
                         <property name="visible">True</property>
+                        <property name="n_rows">4</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">6</property>
+                        <property name="row_spacing">6</property>
                         <child>
-                          <placeholder/>
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Destination:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">destination_filechooserbutton</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="subfolder_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">S_ubFolder:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label3">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Tags:</property>
+                            <property name="use_underline">True</property>
+                            <property name="mnemonic_widget">tags_entry</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkFileChooserButton" id="destination_filechooserbutton">
+                            <property name="visible">True</property>
+                            <property name="action">select-folder</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="tags_entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="invisible_char">&#x25CF;</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="subfolder_box">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <object class="GtkHBox" id="subfolder_type_box">
+                                <property name="visible">True</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="subfolder_entry">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="source_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">_Source:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="source_box">
+                            <property name="visible">True</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                          </packing>
                         </child>
-                      </object>
-                      <packing>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkEntry" id="subfolder_entry">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="invisible_char">&#x25CF;</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
-                        <property name="position">1</property>
+                        <property name="position">0</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="source_label">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Source:</property>
-                    <property name="use_underline">True</property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="source_box">
-                    <property name="visible">True</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
+                    <property name="position">0</property>
                   </packing>
                 </child>
               </object>
@@ -175,7 +194,7 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkHBox" id="hbox2">
+                  <object class="GtkHBox" id="list_command_box">
                     <property name="visible">True</property>
                     <property name="spacing">6</property>
                     <child>
@@ -205,13 +224,22 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkCheckButton" id="filter_checkbutton">
-                        <property name="label" translatable="yes">_Show All</property>
+                      <object class="GtkHBox" id="filter_box">
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="use_underline">True</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="filter_label">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">S_how:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
diff --git a/extensions/photo_importer/dlg-photo-importer.c b/extensions/photo_importer/dlg-photo-importer.c
index e2deb6c..5eb65dc 100644
--- a/extensions/photo_importer/dlg-photo-importer.c
+++ b/extensions/photo_importer/dlg-photo-importer.c
@@ -55,6 +55,8 @@ typedef struct {
 	DoneFunc       done_func;
 	gboolean       cancelling;
 	gulong         monitor_event;
+	GtkWidget     *filter_combobox;
+	GList         *general_tests;
 } DialogData;
 
 
@@ -80,9 +82,11 @@ destroy_dialog (gpointer user_data)
 	g_object_unref (data->vfs_source);
 	g_object_unref (data->builder);
 	_g_object_unref (data->source);
+	_g_object_unref (data->last_source);
 	_g_object_unref (data->cancellable);
 	_g_object_list_unref (data->files);
-	_g_object_unref (data->last_source);
+	_g_string_list_free (data->general_tests);
+
 	g_free (data);
 }
 
@@ -142,6 +146,17 @@ ok_clicked_cb (GtkWidget  *widget,
 
 
 static void
+update_sensitivity (DialogData *data)
+{
+	gboolean can_import;
+
+	can_import = data->source != NULL;
+	gtk_widget_set_sensitive (GET_WIDGET ("ok_button"), can_import);
+	gtk_widget_set_sensitive (GET_WIDGET ("list_command_box"), can_import);
+}
+
+
+static void
 list_ready_cb (GList    *files,
 	       GError   *error,
 	       gpointer  user_data)
@@ -152,19 +167,19 @@ list_ready_cb (GList    *files,
 
 	if (data->cancelling) {
 		gth_file_list_cancel (GTH_FILE_LIST (data->file_list), cancel_done, data);
-		return;
 	}
-
-	if (error != NULL) {
+	else if (error != NULL) {
 		_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not load the folder"), &error);
-		return;
 	}
+	else {
+		_g_object_unref (data->last_source);
+		data->last_source = g_file_dup (data->source);
 
-	_g_object_unref (data->last_source);
-	data->last_source = g_file_dup (data->source);
+		data->files = _g_object_list_ref (files);
+		gth_file_list_set_files (GTH_FILE_LIST (data->file_list), data->files);
+	}
 
-	data->files = _g_object_list_ref (files);
-	gth_file_list_set_files (GTH_FILE_LIST (data->file_list), data->files);
+	update_sensitivity (data);
 }
 
 
@@ -180,6 +195,7 @@ list_source_files (gpointer user_data)
 
 	if (data->source == NULL) {
 		gth_file_list_clear (GTH_FILE_LIST (data->file_list), _("(Empty)"));
+		update_sensitivity (data);
 		return;
 	}
 
@@ -202,6 +218,7 @@ list_source_files (gpointer user_data)
 static void
 load_file_list (DialogData *data)
 {
+	update_sensitivity (data);
 	if (_g_file_equal (data->source, data->last_source))
 		return;
 	cancel (data, list_source_files);
@@ -244,27 +261,11 @@ source_list_changed_cb (GtkWidget  *widget,
 
 
 static void
-filter_checkbutton_toggled_cb (GtkToggleButton *togglebutton,
-			       gpointer         user_data)
-{
-	DialogData *data = user_data;
-	GthTest    *test = NULL;
-
-	if (! gtk_toggle_button_get_active (togglebutton))
-		test = gth_main_get_test ("file::type::is_media");
-
-	gth_file_list_set_filter (GTH_FILE_LIST (data->file_list), test);
-
-	_g_object_unref (test);
-}
-
-
-static void
 update_source_list (DialogData *data)
 {
-	gboolean    source_available = FALSE;
-	GList       *mounts;
-	GList       *scan;
+	gboolean  source_available = FALSE;
+	GList    *mounts;
+	GList    *scan;
 
 	gtk_list_store_clear (data->source_store);
 
@@ -330,6 +331,67 @@ entry_points_changed_cb (GthMonitor *monitor,
 }
 
 
+static void
+filter_combobox_changed_cb (GtkComboBox *widget,
+			    DialogData  *data)
+{
+	int         idx;
+	const char *test_id;
+	GthTest    *test;
+
+	idx = gtk_combo_box_get_active (widget);
+	test_id = g_list_nth (data->general_tests, idx)->data;
+	test = gth_main_get_test (test_id);
+	gth_file_list_set_filter (GTH_FILE_LIST (data->file_list), test);
+
+	g_object_unref (test);
+}
+
+
+static void
+select_all_button_clicked_cb (GtkButton  *button,
+			      DialogData *data)
+{
+	GthFileStore *file_store;
+	GtkTreeIter   iter;
+
+	file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (data->file_list))));
+	if (gth_file_store_get_first (file_store, &iter)) {
+		do {
+			gth_file_store_queue_set (file_store,
+						  &iter,
+						  GTH_FILE_STORE_CHECKED_COLUMN, TRUE,
+						  -1);
+		}
+		while (gth_file_store_get_next (file_store, &iter));
+
+		gth_file_store_exec_set (file_store);
+	}
+}
+
+
+static void
+select_none_button_clicked_cb (GtkButton  *button,
+			       DialogData *data)
+{
+	GthFileStore *file_store;
+	GtkTreeIter   iter;
+
+	file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (data->file_list))));
+	if (gth_file_store_get_first (file_store, &iter)) {
+		do {
+			gth_file_store_queue_set (file_store,
+						  &iter,
+						  GTH_FILE_STORE_CHECKED_COLUMN, FALSE,
+						  -1);
+		}
+		while (gth_file_store_get_next (file_store, &iter));
+
+		gth_file_store_exec_set (file_store);
+	}
+}
+
+
 void
 dlg_photo_importer (GthBrowser *browser,
 		    GFile      *source)
@@ -337,7 +399,10 @@ dlg_photo_importer (GthBrowser *browser,
 	DialogData      *data;
 	GtkCellRenderer *renderer;
 	GthFileDataSort *sort_type;
-	GthTest         *test;
+	GList           *tests, *scan;
+	char            *general_filter;
+	int              i, active_filter;
+	int              i_general;
 
 	if (gth_browser_get_dialog (browser, "photo_importer") != NULL) {
 		gtk_window_present (GTK_WINDOW (gth_browser_get_dialog (browser, "photo_importer")));
@@ -394,30 +459,58 @@ dlg_photo_importer (GthBrowser *browser,
 
 	gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("subfolder_label")), data->subfolder_type_list);
 
-	data->file_list = gth_file_list_new ();
+	data->file_list = gth_file_list_new (GTH_FILE_LIST_TYPE_SELECTOR);
 	sort_type = gth_main_get_sort_type ("file::mtime");
 	gth_file_list_set_sort_func (GTH_FILE_LIST (data->file_list), sort_type->cmp_func, FALSE);
 	gth_file_list_enable_thumbs (GTH_FILE_LIST (data->file_list), TRUE);
 	gth_file_list_set_thumb_size (GTH_FILE_LIST (data->file_list), 128);
 	gth_file_list_set_caption (GTH_FILE_LIST (data->file_list), "standard::display-name,gth::file::display-size");
 
-	test = gth_main_get_test ("file::type::is_media");
-	gth_file_list_set_filter (GTH_FILE_LIST (data->file_list), test);
-	g_object_unref (test);
-
 	gtk_widget_show (data->file_list);
 	gtk_box_pack_start (GTK_BOX (GET_WIDGET ("filelist_box")), data->file_list, TRUE, TRUE, 0);
 
+	/**/
+
+	tests = gth_main_get_all_tests ();
+	general_filter = "file::type::is_media"; /* default value */
+	active_filter = 0;
+
+	data->filter_combobox = gtk_combo_box_new_text ();
+	for (i = 0, i_general = -1, scan = tests; scan; scan = scan->next, i++) {
+		const char *registered_test_id = scan->data;
+		GthTest    *test;
+
+		if (strncmp (registered_test_id, "file::type::", 12) != 0)
+			continue;
+
+		i_general += 1;
+		test = gth_main_get_test (registered_test_id);
+		if (strcmp (registered_test_id, general_filter) == 0) {
+			active_filter = i_general;
+			gth_file_list_set_filter (GTH_FILE_LIST (data->file_list), test);
+		}
+
+		data->general_tests = g_list_prepend (data->general_tests, g_strdup (gth_test_get_id (test)));
+		gtk_combo_box_append_text (GTK_COMBO_BOX (data->filter_combobox), gth_test_get_display_name (test));
+		g_object_unref (test);
+	}
+	data->general_tests = g_list_reverse (data->general_tests);
+
+	gtk_combo_box_set_active (GTK_COMBO_BOX (data->filter_combobox), active_filter);
+	gtk_widget_show (data->filter_combobox);
+	gtk_container_add (GTK_CONTAINER (GET_WIDGET ("filter_box")), data->filter_combobox);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("filter_label")), data->filter_combobox);
+	gtk_label_set_use_underline (GTK_LABEL (GET_WIDGET ("filter_label")), TRUE);
+
+	_g_string_list_free (tests);
+
 	/* Set the signals handlers. */
 
 	g_signal_connect (G_OBJECT (data->dialog),
 			  "delete-event",
 			  G_CALLBACK (delete_event_cb),
 			  data);
-	/*g_signal_connect (G_OBJECT (data->dialog),
-			  "destroy",
-			  G_CALLBACK (destroy_cb),
-			  data);*/
 	g_signal_connect (GET_WIDGET ("ok_button"),
 			  "clicked",
 			  G_CALLBACK (ok_clicked_cb),
@@ -430,9 +523,17 @@ dlg_photo_importer (GthBrowser *browser,
 			  "changed",
 			  G_CALLBACK (source_list_changed_cb),
 			  data);
-	g_signal_connect (GET_WIDGET ("filter_checkbutton"),
-			  "toggled",
-			  G_CALLBACK (filter_checkbutton_toggled_cb),
+	g_signal_connect (data->filter_combobox,
+			  "changed",
+			  G_CALLBACK (filter_combobox_changed_cb),
+			  data);
+	g_signal_connect (GET_WIDGET ("select_all_button"),
+			  "clicked",
+			  G_CALLBACK (select_all_button_clicked_cb),
+			  data);
+	g_signal_connect (GET_WIDGET ("select_none_button"),
+			  "clicked",
+			  G_CALLBACK (select_none_button_clicked_cb),
 			  data);
 
 	data->monitor_event = g_signal_connect (gth_main_get_default_monitor (),
@@ -447,5 +548,4 @@ dlg_photo_importer (GthBrowser *browser,
 	gtk_widget_show (data->dialog);
 
 	update_source_list (data);
-	/*load_file_list (data);*/
 }
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 137cad8..820fba7 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -442,7 +442,7 @@ gth_browser_update_title (GthBrowser *browser)
 		int           pos;
 
 		file_store = gth_browser_get_file_store (browser);
-		pos = gth_file_store_find_visible (file_store, browser->priv->current_file->file);
+		pos = gth_file_store_get_pos (file_store, browser->priv->current_file->file);
 		if (pos >= 0)
 			g_string_append_printf (title, " (%d/%d)", pos + 1, gth_file_store_n_visibles (file_store));
 	}
@@ -475,7 +475,7 @@ gth_browser_update_sensitivity (GthBrowser *browser)
 	modified = gth_browser_get_file_modified (browser);
 
 	if (browser->priv->current_file != NULL)
-		current_file_pos = gth_file_store_find_visible (gth_browser_get_file_store (browser), browser->priv->current_file->file);
+		current_file_pos = gth_file_store_get_pos (gth_browser_get_file_store (browser), browser->priv->current_file->file);
 	else
 		current_file_pos = -1;
 	n_files = gth_file_store_n_visibles (gth_browser_get_file_store (browser));
@@ -2320,7 +2320,7 @@ folder_changed_cb (GthMonitor      *monitor,
 
 		file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (browser->priv->file_list))));
 		for (scan = list; scan; scan = scan->next) {
-			if (gth_file_store_find (file_store, (GFile *) scan->data) >= 0) {
+			if (gth_file_store_find_visible (file_store, (GFile *) scan->data, NULL)) {
 				update_file_list = TRUE;
 				break;
 			}
@@ -2356,16 +2356,21 @@ folder_changed_cb (GthMonitor      *monitor,
 				link = _g_file_list_find_file (list, browser->priv->current_file->file);
 				if (link != NULL) {
 					GthFileStore *file_store;
-					int           pos;
+					GtkTreeIter   iter;
+					gboolean      found = FALSE;
 
 					current_file_deleted = TRUE;
+
 					file_store = gth_browser_get_file_store (browser);
-					pos = gth_file_store_find_visible (file_store, browser->priv->current_file->file);
-					new_file = gth_file_store_get_file_at_pos (file_store, pos + 1);
-					if (new_file == NULL)
-						new_file = gth_file_store_get_file_at_pos (file_store, pos - 1);
-					if (new_file != NULL)
-						new_file = g_object_ref (new_file);
+					if (gth_file_store_find_visible (file_store, browser->priv->current_file->file, &iter)) {
+						if (gth_file_store_get_next_visible (file_store, &iter))
+							found = TRUE;
+						else if (gth_file_store_get_prev_visible (file_store, &iter))
+							found = TRUE;
+					}
+
+					if (found)
+						new_file = g_object_ref (gth_file_store_get_file (file_store, &iter));
 				}
 			}
 
@@ -3164,7 +3169,7 @@ _gth_browser_construct (GthBrowser *browser)
 
 	/* the file list */
 
-	browser->priv->file_list = gth_file_list_new ();
+	browser->priv->file_list = gth_file_list_new (GTH_FILE_LIST_TYPE_NORMAL);
 	gth_browser_set_sort_order (browser,
 				    gth_main_get_sort_type (eel_gconf_get_string (PREF_SORT_TYPE, "gth::file::mtime")),
 				    FALSE);
@@ -3806,18 +3811,22 @@ static gboolean
 view_focused_image (GthBrowser *browser)
 {
 	GthFileView *view;
-	int          pos;
-	GthFileData *focused_file;
+	int          n;
+	GtkTreeIter  iter;
+	GthFileData *focused_file = NULL;
 
 	if (browser->priv->current_file == NULL)
 		return FALSE;
 
 	view = GTH_FILE_VIEW (gth_browser_get_file_list_view (browser));
-	pos = gth_file_view_get_cursor (view);
-	if (pos == -1)
+	n = gth_file_view_get_cursor (view);
+	if (n == -1)
 		return FALSE;
 
-	focused_file = gth_file_store_get_file_at_pos (GTH_FILE_STORE (gth_file_view_get_model (view)), pos);
+	if (! gth_file_store_get_nth_visible (GTH_FILE_STORE (gth_file_view_get_model (view)), n, &iter))
+		return FALSE;
+
+	focused_file = gth_file_store_get_file (GTH_FILE_STORE (gth_file_view_get_model (view)), &iter);
 	if (focused_file == NULL)
 		return FALSE;
 
@@ -3844,15 +3853,19 @@ gth_browser_show_next_image (GthBrowser *browser,
 			pos = gth_file_list_next_file (GTH_FILE_LIST (browser->priv->file_list), -1, skip_broken, only_selected, TRUE);
 	}
 	else {
-		pos = gth_file_store_find_visible (gth_browser_get_file_store (browser), browser->priv->current_file->file);
+		pos = gth_file_store_get_pos (gth_browser_get_file_store (browser), browser->priv->current_file->file);
 		pos = gth_file_list_next_file (GTH_FILE_LIST (browser->priv->file_list), pos, skip_broken, only_selected, FALSE);
 	}
 
 	if (pos >= 0) {
-		GthFileData *file_data;
+		GtkTreeIter  iter;
 
-		file_data = gth_file_store_get_file_at_pos (GTH_FILE_STORE (gth_file_view_get_model (view)), pos);
-		gth_browser_load_file (browser, file_data, TRUE);
+		if (gth_file_store_get_nth_visible (GTH_FILE_STORE (gth_file_view_get_model (view)), pos, &iter)) {
+			GthFileData *file_data;
+
+			file_data = gth_file_store_get_file (GTH_FILE_STORE (gth_file_view_get_model (view)), &iter);
+			gth_browser_load_file (browser, file_data, TRUE);
+		}
 	}
 
 	return (pos >= 0);
@@ -3878,15 +3891,19 @@ gth_browser_show_prev_image (GthBrowser *browser,
 			pos = gth_file_list_prev_file (GTH_FILE_LIST (browser->priv->file_list), -1, skip_broken, only_selected, TRUE);
 	}
 	else {
-		pos = gth_file_store_find_visible (gth_browser_get_file_store (browser), browser->priv->current_file->file);
+		pos = gth_file_store_get_pos (gth_browser_get_file_store (browser), browser->priv->current_file->file);
 		pos = gth_file_list_prev_file (GTH_FILE_LIST (browser->priv->file_list), pos, skip_broken, only_selected, FALSE);
 	}
 
 	if (pos >= 0) {
-		GthFileData *file_data;
+		GtkTreeIter iter;
 
-		file_data = gth_file_store_get_file_at_pos (GTH_FILE_STORE (gth_file_view_get_model (view)), pos);
-		gth_browser_load_file (browser, file_data, TRUE);
+		if (gth_file_store_get_nth_visible (GTH_FILE_STORE (gth_file_view_get_model (view)), pos, &iter)) {
+			GthFileData *file_data;
+
+			file_data = gth_file_store_get_file (GTH_FILE_STORE (gth_file_view_get_model (view)), &iter);
+			gth_browser_load_file (browser, file_data, TRUE);
+		}
 	}
 
 	return (pos >= 0);
@@ -3900,6 +3917,7 @@ gth_browser_show_first_image (GthBrowser *browser,
 {
 	int          pos;
 	GthFileView *view;
+	GtkTreeIter  iter;
 	GthFileData *file_data;
 
 	pos = gth_file_list_first_file (GTH_FILE_LIST (browser->priv->file_list), skip_broken, only_selected);
@@ -3907,7 +3925,11 @@ gth_browser_show_first_image (GthBrowser *browser,
 		return FALSE;
 
 	view = GTH_FILE_VIEW (gth_browser_get_file_list_view (browser));
-	file_data = gth_file_store_get_file_at_pos (GTH_FILE_STORE (gth_file_view_get_model (view)), pos);
+
+	if (! gth_file_store_get_nth_visible (GTH_FILE_STORE (gth_file_view_get_model (view)), pos, &iter))
+		return FALSE;
+
+	file_data = gth_file_store_get_file (GTH_FILE_STORE (gth_file_view_get_model (view)), &iter);
 	gth_browser_load_file (browser, file_data, TRUE);
 
 	return TRUE;
@@ -3921,6 +3943,7 @@ gth_browser_show_last_image (GthBrowser *browser,
 {
 	int          pos;
 	GthFileView *view;
+	GtkTreeIter  iter;
 	GthFileData *file_data;
 
 	pos = gth_file_list_last_file (GTH_FILE_LIST (browser->priv->file_list), skip_broken, only_selected);
@@ -3928,7 +3951,11 @@ gth_browser_show_last_image (GthBrowser *browser,
 		return FALSE;
 
 	view = GTH_FILE_VIEW (gth_browser_get_file_list_view (browser));
-	file_data = gth_file_store_get_file_at_pos (GTH_FILE_STORE (gth_file_view_get_model (view)), pos);
+
+	if (! gth_file_store_get_nth_visible (GTH_FILE_STORE (gth_file_view_get_model (view)), pos, &iter))
+		return FALSE;
+
+	file_data = gth_file_store_get_file (GTH_FILE_STORE (gth_file_view_get_model (view)), &iter);
 	gth_browser_load_file (browser, file_data, TRUE);
 
 	return TRUE;
@@ -3973,7 +4000,7 @@ _gth_browser_make_file_visible (GthBrowser  *browser,
 	GtkWidget     *view;
 	GthVisibility  visibility;
 
-	file_pos = gth_file_store_find_visible (GTH_FILE_STORE (gth_browser_get_file_store (browser)), file_data->file);
+	file_pos = gth_file_store_get_pos (GTH_FILE_STORE (gth_browser_get_file_store (browser)), file_data->file);
 	if (file_pos < 0)
 		return;
 
diff --git a/gthumb/gth-cell-renderer-thumbnail.c b/gthumb/gth-cell-renderer-thumbnail.c
index 965b550..cdbecfc 100644
--- a/gthumb/gth-cell-renderer-thumbnail.c
+++ b/gthumb/gth-cell-renderer-thumbnail.c
@@ -39,6 +39,8 @@ enum {
 	PROP_SIZE,
 	PROP_IS_ICON,
 	PROP_THUMBNAIL,
+	PROP_CHECKED,
+	PROP_SELECTED,
 	PROP_FILE
 };
 
@@ -49,6 +51,8 @@ struct _GthCellRendererThumbnailPrivate
 	gboolean     is_icon;
 	GdkPixbuf   *thumbnail;
 	GthFileData *file;
+	gboolean     checked;
+	gboolean     selected;
 };
 
 
@@ -96,6 +100,12 @@ gth_cell_renderer_thumbnail_get_property (GObject    *object,
 	case PROP_FILE:
 		g_value_set_object (value, self->priv->file);
 		break;
+	case PROP_CHECKED:
+		g_value_set_boolean (value, self->priv->checked);
+		break;
+	case PROP_SELECTED:
+		g_value_set_boolean (value, self->priv->selected);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -126,6 +136,12 @@ gth_cell_renderer_thumbnail_set_property (GObject      *object,
 	case PROP_FILE:
 		self->priv->file = g_value_dup_object (value);
 		break;
+	case PROP_CHECKED:
+		self->priv->checked = g_value_get_boolean (value);
+		break;
+	case PROP_SELECTED:
+		self->priv->selected = g_value_get_boolean (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -150,8 +166,14 @@ gth_cell_renderer_thumbnail_get_size (GtkCellRenderer *cell,
 
   	self = GTH_CELL_RENDERER_THUMBNAIL (cell);
 
-  	image_width = gdk_pixbuf_get_width (self->priv->thumbnail);
-	image_height = gdk_pixbuf_get_height (self->priv->thumbnail);
+  	if (self->priv->thumbnail != NULL) {
+  		image_width = gdk_pixbuf_get_width (self->priv->thumbnail);
+  		image_height = gdk_pixbuf_get_height (self->priv->thumbnail);
+  	}
+  	else {
+  		image_width = 0;
+  		image_height = 0;
+  	}
 
 	if (self->priv->is_icon || (self->priv->thumbnail == NULL) || ((image_width < self->priv->size) && (image_height < self->priv->size))) {
 		calc_width  = (int) (cell->xpad * 2) + (THUMBNAIL_X_BORDER * 2) + self->priv->size;
@@ -183,189 +205,57 @@ gth_cell_renderer_thumbnail_get_size (GtkCellRenderer *cell,
 
 
 /* From gtkcellrendererpixbuf.c
- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb redhat com> */
+ * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb redhat com>
+ *
+ * modified for gthumb */
 static GdkPixbuf *
 create_colorized_pixbuf (GdkPixbuf *src,
-			 GdkColor  *new_color)
+			 GdkColor  *new_color,
+			 gdouble    alpha)
 {
-  gint i, j;
-  gint width, height, has_alpha, src_row_stride, dst_row_stride;
-  gint red_value, green_value, blue_value;
-  guchar *target_pixels;
-  guchar *original_pixels;
-  guchar *pixsrc;
-  guchar *pixdest;
-  GdkPixbuf *dest;
-
-  red_value = new_color->red / 255.0;
-  green_value = new_color->green / 255.0;
-  blue_value = new_color->blue / 255.0;
-
-  dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
-                         gdk_pixbuf_get_has_alpha (src),
-                         gdk_pixbuf_get_bits_per_sample (src),
-                         gdk_pixbuf_get_width (src),
-                         gdk_pixbuf_get_height (src));
-
-  has_alpha = gdk_pixbuf_get_has_alpha (src);
-  width = gdk_pixbuf_get_width (src);
-  height = gdk_pixbuf_get_height (src);
-  src_row_stride = gdk_pixbuf_get_rowstride (src);
-  dst_row_stride = gdk_pixbuf_get_rowstride (dest);
-  target_pixels = gdk_pixbuf_get_pixels (dest);
-  original_pixels = gdk_pixbuf_get_pixels (src);
-
-  for (i = 0; i < height; i++) {
-    pixdest = target_pixels + i*dst_row_stride;
-    pixsrc = original_pixels + i*src_row_stride;
-    for (j = 0; j < width; j++) {
-      *pixdest++ = (*pixsrc++ * red_value) >> 8;
-      *pixdest++ = (*pixsrc++ * green_value) >> 8;
-      *pixdest++ = (*pixsrc++ * blue_value) >> 8;
-      if (has_alpha) {
-        *pixdest++ = *pixsrc++;
-      }
-    }
-  }
-  return dest;
-}
-
-
-/*
-static void
-gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
-				    GdkWindow            *window,
-				    GtkWidget            *widget,
-				    GdkRectangle         *background_area,
-				    GdkRectangle         *cell_area,
-				    GdkRectangle         *expose_area,
-				    GtkCellRendererState  flags)
-{
-	GthCellRendererThumbnail *self;
-	GtkStateType              state;
-	GdkRectangle              thumb_rect;
-	GdkRectangle              draw_rect;
-	GdkRectangle              image_rect;
-	cairo_t                  *cr;
-	cairo_path_t             *cr_path;
-	GdkPixbuf                *pixbuf;
-	GdkPixbuf                *colorized = NULL;
-
-	self = GTH_CELL_RENDERER_THUMBNAIL (cell);
-
- 	gth_cell_renderer_thumbnail_get_size (cell, widget, cell_area,
- 					      &thumb_rect.x,
- 					      &thumb_rect.y,
- 					      &thumb_rect.width,
- 					      &thumb_rect.height);
-
-	thumb_rect.x += cell_area->x + cell->xpad;
-  	thumb_rect.y += cell_area->y + cell->ypad;
-  	thumb_rect.width  -= cell->xpad * 2;
-  	thumb_rect.height -= cell->ypad * 2;
-
-	if (! gdk_rectangle_intersect (cell_area, &thumb_rect, &draw_rect)
-	    || ! gdk_rectangle_intersect (expose_area, &thumb_rect, &draw_rect))
-	{
-		return;
-	}
-
-  	if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
-  		state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
-  	else
-  		state = ((flags & GTK_CELL_RENDERER_FOCUSED) == GTK_CELL_RENDERER_FOCUSED) ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;
-
-	cr = gdk_cairo_create (window);
-
-	if (state == GTK_STATE_NORMAL)
-		gdk_cairo_set_source_color (cr, &widget->style->bg[state]);
-	else
-		gdk_cairo_set_source_color (cr, &widget->style->base[state]);
-
-#define R 7
-#define B 8
-
-	cairo_move_to (cr, thumb_rect.x, thumb_rect.y + R);
-	cairo_arc (cr, thumb_rect.x + R, thumb_rect.y + R, R, 1.0 * M_PI, 1.5 * M_PI);
-	cairo_rel_line_to (cr, thumb_rect.width - (R * 2), 0);
-	cairo_arc (cr, thumb_rect.x + thumb_rect.width - R, thumb_rect.y + R, R, 1.5 * M_PI, 2.0 * M_PI);
-	cairo_rel_line_to (cr, 0, thumb_rect.height - (R * 2));
-	cairo_arc (cr, thumb_rect.x + thumb_rect.width - R, thumb_rect.y + thumb_rect.height - R, R, 0.0 * M_PI, 0.5 * M_PI);
-	cairo_rel_line_to (cr, - (thumb_rect.width - (R * 2)), 0);
-	cairo_arc (cr, thumb_rect.x + R, thumb_rect.y + thumb_rect.height - R, R, 0.5 * M_PI, 1.0 * M_PI);
-	cairo_close_path (cr);
-	cr_path = cairo_copy_path (cr);
-	cairo_fill (cr);
-
-	gdk_cairo_set_source_color (cr, &widget->style->dark[state]);
-	cairo_set_line_width (cr, 0.5);
-	cairo_append_path (cr, cr_path);
-	cairo_stroke (cr);
-
-	cairo_path_destroy (cr_path);
-
-	if (self->priv->is_icon) {
-		gdk_cairo_set_source_color (cr, &widget->style->base[GTK_STATE_NORMAL]);
-		image_rect.width = thumb_rect.width - B;
-		image_rect.height = thumb_rect.height - B;
-		image_rect.x = thumb_rect.x + (thumb_rect.width - image_rect.width) / 2;
-		image_rect.y = thumb_rect.y + (thumb_rect.height - image_rect.height) / 2;
-		gdk_cairo_rectangle (cr, &image_rect);
-		cairo_fill (cr);
-	}
-
-	pixbuf = self->priv->thumbnail;
-
-	if (pixbuf != NULL) {
-		if ((flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_PRELIT)) != 0) {
-			colorized = create_colorized_pixbuf (pixbuf, &widget->style->base[state]);
-			pixbuf = colorized;
+	gint i, j;
+	gint width, height, has_alpha, src_row_stride, dst_row_stride;
+	gint red_value, green_value, blue_value;
+	guchar *target_pixels;
+	guchar *original_pixels;
+	guchar *pixsrc;
+	guchar *pixdest;
+	GdkPixbuf *dest;
+
+	red_value = new_color->red / 255.0;
+	green_value = new_color->green / 255.0;
+	blue_value = new_color->blue / 255.0;
+
+	dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+			       TRUE /*gdk_pixbuf_get_has_alpha (src)*/,
+			       gdk_pixbuf_get_bits_per_sample (src),
+			       gdk_pixbuf_get_width (src),
+			       gdk_pixbuf_get_height (src));
+
+	has_alpha = gdk_pixbuf_get_has_alpha (src);
+	width = gdk_pixbuf_get_width (src);
+	height = gdk_pixbuf_get_height (src);
+	src_row_stride = gdk_pixbuf_get_rowstride (src);
+	dst_row_stride = gdk_pixbuf_get_rowstride (dest);
+	target_pixels = gdk_pixbuf_get_pixels (dest);
+	original_pixels = gdk_pixbuf_get_pixels (src);
+
+	for (i = 0; i < height; i++) {
+		pixdest = target_pixels + i*dst_row_stride;
+		pixsrc = original_pixels + i*src_row_stride;
+		for (j = 0; j < width; j++) {
+			*pixdest++ = (*pixsrc++ * red_value) >> 8;
+			*pixdest++ = (*pixsrc++ * green_value) >> 8;
+			*pixdest++ = (*pixsrc++ * blue_value) >> 8;
+			if (has_alpha)
+				*pixdest++ = (*pixsrc++ * alpha);
+			else
+				*pixdest++ = (255 * alpha);
 		}
-
-		image_rect.width = gdk_pixbuf_get_width (pixbuf);
-		image_rect.height = gdk_pixbuf_get_height (pixbuf);
-		image_rect.x = thumb_rect.x + (thumb_rect.width - image_rect.width) / 2;
-		image_rect.y = thumb_rect.y + (thumb_rect.height - image_rect.height) / 2;
-		gdk_cairo_set_source_pixbuf (cr, pixbuf, image_rect.x, image_rect.y);
-		gdk_cairo_rectangle (cr, &draw_rect);
-		cairo_fill (cr);
-
-		if (! self->priv->is_icon && ! gdk_pixbuf_get_has_alpha (pixbuf)) {
-			gdk_cairo_set_source_color (cr, &widget->style->dark[state]);
-			cairo_set_line_width (cr, 0.25);
-			gdk_cairo_rectangle (cr, &image_rect);
-			cairo_stroke (cr);
-		}
-	}
-
-	cairo_destroy (cr);
-
-	if (GTK_WIDGET_HAS_FOCUS (widget)
-	    && ((flags & GTK_CELL_RENDERER_FOCUSED) == GTK_CELL_RENDERER_FOCUSED))
-	{
-		GtkStateType focus_state;
-
-		if ((flags & GTK_CELL_RENDERER_SELECTED) != 0)
-                	focus_state = GTK_STATE_NORMAL;
-        	else
-                	focus_state = state;
-
-		gtk_paint_focus (widget->style,
-				 window,
-				 focus_state,
-				 &draw_rect,
-				 widget,
-				 "",
-				 cell_area->x + (B / 4),
-				 cell_area->y + (B / 4),
-				 cell_area->width - (B / 2) + 1,
-				 cell_area->height - (B / 2) + 1);
 	}
 
-	if (colorized != NULL)
-		g_object_unref (colorized);
+	return dest;
 }
-*/
 
 
 static void
@@ -412,6 +302,8 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 		return;
 	}
 
+	cr = gdk_cairo_create (window);
+
     	image_rect.width = gdk_pixbuf_get_width (pixbuf);
 	image_rect.height = gdk_pixbuf_get_height (pixbuf);
 	image_rect.x = thumb_rect.x + (thumb_rect.width - image_rect.width) * .5;
@@ -427,8 +319,6 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 	if (self->priv->is_icon || (state != GTK_STATE_NORMAL) || ((image_rect.width < self->priv->size) && (image_rect.height < self->priv->size))) {
 		int R = 7;
 
-		cr = gdk_cairo_create (window);
-
 		if (state == GTK_STATE_NORMAL)
 			gdk_cairo_set_source_color (cr, &widget->style->bg[state]);
 		else
@@ -445,8 +335,6 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
 		cairo_close_path (cr);
 		cr_path = cairo_copy_path (cr);
 		cairo_fill (cr);
-
-		cairo_destroy (cr);
 	}
 
 	if (! self->priv->is_icon && ! ((image_rect.width < self->priv->size) && (image_rect.height < self->priv->size))) {
@@ -508,8 +396,8 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
   				    image_rect.height + 1);*/
 	}
 
-  	if ((flags & (GTK_CELL_RENDERER_SELECTED | GTK_CELL_RENDERER_PRELIT)) != 0) {
-		colorized = create_colorized_pixbuf (pixbuf, &style->base[state]);
+  	if (! self->priv->checked || ((flags & (GTK_CELL_RENDERER_SELECTED | GTK_CELL_RENDERER_PRELIT)) != 0)) {
+		colorized = create_colorized_pixbuf (pixbuf, &style->base[state], self->priv->checked ? 1.0 : 0.33);
 		pixbuf = colorized;
 	}
 
@@ -524,6 +412,20 @@ gth_cell_renderer_thumbnail_render (GtkCellRenderer      *cell,
   			 GDK_RGB_DITHER_NORMAL,
   			 0, 0);
 
+  	/*if (! self->priv->checked) {
+  		cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.5);
+		cairo_set_line_width (cr, 6.0);
+
+		cairo_move_to (cr, thumb_rect.x, thumb_rect.y);
+		cairo_line_to (cr, thumb_rect.x + thumb_rect.width, thumb_rect.y + thumb_rect.height);
+		cairo_stroke (cr);
+		cairo_move_to (cr, thumb_rect.x + thumb_rect.width, thumb_rect.y);
+		cairo_line_to (cr, thumb_rect.x, thumb_rect.y + thumb_rect.height);
+		cairo_stroke (cr);
+  	}*/
+
+  	cairo_destroy (cr);
+
   	if (colorized != NULL)
 		g_object_unref (colorized);
 }
@@ -577,6 +479,20 @@ gth_cell_renderer_thumbnail_class_init (GthCellRendererThumbnailClass *klass)
 							      "The file data",
 							      GTH_TYPE_FILE_DATA,
 							      G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_CHECKED,
+					 g_param_spec_boolean ("checked",
+					 		       "Checked",
+							       "Whether the image has been checked by the user",
+							       TRUE,
+							       G_PARAM_READWRITE));
+	g_object_class_install_property (object_class,
+					 PROP_SELECTED,
+					 g_param_spec_boolean ("selected",
+					 		       "Selected",
+							       "Whether the image has been selected by the user",
+							       FALSE,
+							       G_PARAM_READWRITE));
 }
 
 
@@ -585,6 +501,7 @@ gth_cell_renderer_thumbnail_init (GthCellRendererThumbnail *self)
 {
 	self->priv = g_new0 (GthCellRendererThumbnailPrivate, 1);
 	self->priv->size = DEFAULT_THUMBNAIL_SIZE;
+	self->priv->checked = TRUE;
 }
 
 
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index ca6390f..9cbe90e 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -83,6 +83,7 @@ enum {
 
 struct _GthFileListPrivateData
 {
+	GthFileListType  type;
 	GtkWidget       *notebook;
 	GtkWidget       *view;
 	GtkWidget       *message;
@@ -104,6 +105,7 @@ struct _GthFileListPrivateData
 	GList           *queue; /* list of GthFileListOp */
 	GtkCellRenderer *thumbnail_renderer;
 	GtkCellRenderer *text_renderer;
+	GtkCellRenderer *checkbox_renderer;
 
 	char           **caption_attributes_v;
 
@@ -298,15 +300,18 @@ update_thumb_in_file_view (GthFileList *file_list)
 
 	pixbuf = gth_thumb_loader_get_pixbuf (file_list->priv->thumb_loader);
 	if (pixbuf != NULL) {
-		gth_file_store_queue_set (file_store,
-					  gth_file_store_get_abs_pos (file_store, file_list->priv->thumb_pos),
-					  NULL,
-					  pixbuf,
-					  FALSE,
-					  NULL);
-		file_list->priv->dirty = TRUE;
-		if (file_list->priv->dirty_event == 0)
-			file_list->priv->dirty_event = g_timeout_add (UPDATE_THUMBNAILS_TIMEOUT, flash_queue_cb, file_list);
+		GtkTreeIter iter;
+
+		if (gth_file_store_get_nth_visible (file_store, file_list->priv->thumb_pos, &iter)) {
+			gth_file_store_queue_set (file_store,
+						  &iter,
+						  GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+						  GTH_FILE_STORE_IS_ICON_COLUMN, FALSE,
+						  -1);
+			file_list->priv->dirty = TRUE;
+			if (file_list->priv->dirty_event == 0)
+				file_list->priv->dirty_event = g_timeout_add (UPDATE_THUMBNAILS_TIMEOUT, flash_queue_cb, file_list);
+		}
 	}
 }
 
@@ -316,27 +321,24 @@ set_mime_type_icon (GthFileList *file_list,
 		    GthFileData *file_data)
 {
 	GthFileStore *file_store;
-	int           pos;
+	GtkTreeIter   iter;
 	GIcon        *icon;
 	GdkPixbuf    *pixbuf;
 
 	file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
 
-	pos = gth_file_store_find (file_store, file_data->file);
-	if (pos < 0)
+	if (! gth_file_store_find (file_store, file_data->file, &iter))
 		return;
 
 	icon = g_file_info_get_icon (file_data->info);
 	pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
 	gth_file_store_queue_set (file_store,
-				  pos,
-				  NULL,
-				  pixbuf,
-				  TRUE,
-				  NULL);
-
-	if (pixbuf != NULL)
-		g_object_unref (pixbuf);
+				  &iter,
+				  GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+				  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
+				  -1);
+
+	_g_object_unref (pixbuf);
 }
 
 
@@ -434,7 +436,39 @@ file_view_drag_data_get_cb (GtkWidget        *widget,
 
 
 static void
-gth_file_list_construct (GthFileList *file_list)
+checkbox_toggled_cb (GtkCellRendererToggle *cell_renderer,
+                     char                  *path,
+                     gpointer               user_data)
+{
+	GthFileList  *file_list = user_data;
+	GtkTreePath  *tpath;
+	GthFileStore *file_store;
+	GtkTreeIter   iter;
+
+	tpath = gtk_tree_path_new_from_string (path);
+	if (tpath == NULL)
+		return;
+
+	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+	if (gtk_tree_model_get_iter (GTK_TREE_MODEL (file_store), &iter, tpath)) {
+		gboolean checked;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (file_store), &iter,
+				    GTH_FILE_STORE_CHECKED_COLUMN, &checked,
+				    -1);
+		gth_file_store_set (file_store,
+				    &iter,
+				    GTH_FILE_STORE_CHECKED_COLUMN, ! checked,
+				    -1);
+	}
+
+	gtk_tree_path_free (tpath);
+}
+
+
+static void
+gth_file_list_construct (GthFileList     *file_list,
+			 GthFileListType  list_type)
 {
 	GtkWidget       *scrolled;
 	GtkAdjustment   *vadj;
@@ -445,6 +479,8 @@ gth_file_list_construct (GthFileList *file_list)
 	GtkTargetEntry  *targets;
 	int              n_targets;
 
+	file_list->priv->type = list_type;
+
 	/* thumbnail loader */
 
 	file_list->priv->thumb_loader = gth_thumb_loader_new (file_list->priv->thumb_size, file_list->priv->thumb_size);
@@ -492,6 +528,11 @@ gth_file_list_construct (GthFileList *file_list)
 	file_list->priv->view = gth_icon_view_new_with_model (GTK_TREE_MODEL (model));
 	g_object_unref (model);
 
+	if (file_list->priv->type == GTH_FILE_LIST_TYPE_SELECTOR)
+		gth_file_selection_set_selection_mode (GTH_FILE_SELECTION (file_list->priv->view), GTK_SELECTION_NONE);
+	else
+		gth_file_selection_set_selection_mode (GTH_FILE_SELECTION (file_list->priv->view), GTK_SELECTION_MULTIPLE);
+
 	target_list = gtk_target_list_new (NULL, 0);
 	gtk_target_list_add_uri_targets (target_list, 0);
 	gtk_target_list_add_text_targets (target_list, 0);
@@ -510,6 +551,22 @@ gth_file_list_construct (GthFileList *file_list)
 			  G_CALLBACK (file_view_drag_data_get_cb),
 			  file_list);
 
+	/* checkbox */
+
+	file_list->priv->checkbox_renderer = renderer = gtk_cell_renderer_toggle_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (file_list->priv->view), renderer, FALSE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
+					renderer,
+					"active", GTH_FILE_STORE_CHECKED_COLUMN,
+					NULL);
+	g_object_set (file_list->priv->checkbox_renderer,
+		      "visible", (file_list->priv->type != GTH_FILE_LIST_TYPE_NORMAL),
+		      NULL);
+	g_signal_connect (file_list->priv->checkbox_renderer,
+			  "toggled",
+			  G_CALLBACK (checkbox_toggled_cb),
+			  file_list);
+
 	/* thumbnail */
 
 	file_list->priv->thumbnail_renderer = renderer = gth_cell_renderer_thumbnail_new ();
@@ -518,12 +575,31 @@ gth_file_list_construct (GthFileList *file_list)
 		      "yalign", 1.0,
 		      NULL);
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (file_list->priv->view), renderer, FALSE);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
-					renderer,
-					"thumbnail", GTH_FILE_STORE_THUMBNAIL_COLUMN,
-					"is_icon", GTH_FILE_STORE_IS_ICON_COLUMN,
-					"file", GTH_FILE_STORE_FILE_COLUMN,
-					NULL);
+
+
+	if (file_list->priv->type == GTH_FILE_LIST_TYPE_BROWSER)
+		gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
+						renderer,
+						"thumbnail", GTH_FILE_STORE_THUMBNAIL_COLUMN,
+						"is_icon", GTH_FILE_STORE_IS_ICON_COLUMN,
+						"file", GTH_FILE_STORE_FILE_DATA_COLUMN,
+						"selected", GTH_FILE_STORE_CHECKED_COLUMN,
+						NULL);
+	else if (file_list->priv->type == GTH_FILE_LIST_TYPE_SELECTOR)
+		gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
+						renderer,
+						"thumbnail", GTH_FILE_STORE_THUMBNAIL_COLUMN,
+						"is_icon", GTH_FILE_STORE_IS_ICON_COLUMN,
+						"file", GTH_FILE_STORE_FILE_DATA_COLUMN,
+						"checked", GTH_FILE_STORE_CHECKED_COLUMN,
+						NULL);
+	else
+		gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (file_list->priv->view),
+						renderer,
+						"thumbnail", GTH_FILE_STORE_THUMBNAIL_COLUMN,
+						"is_icon", GTH_FILE_STORE_IS_ICON_COLUMN,
+						"file", GTH_FILE_STORE_FILE_DATA_COLUMN,
+						NULL);
 
 	/* text */
 
@@ -591,12 +667,12 @@ gth_file_list_get_type (void)
 
 
 GtkWidget*
-gth_file_list_new (void)
+gth_file_list_new (GthFileListType list_type)
 {
 	GtkWidget *widget;
 
 	widget = GTK_WIDGET (g_object_new (GTH_TYPE_FILE_LIST, NULL));
-	gth_file_list_construct (GTH_FILE_LIST (widget));
+	gth_file_list_construct (GTH_FILE_LIST (widget), list_type);
 
 	return widget;
 }
@@ -722,25 +798,26 @@ gfl_add_files (GthFileList *file_list,
 	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
 
 	for (scan = files; scan; scan = scan->next) {
-		GthFileData *fd = scan->data;
+		GthFileData *file_data = scan->data;
 		GIcon       *icon;
 		GdkPixbuf   *pixbuf = NULL;
 		GString     *metadata;
 
-		if (g_file_info_get_file_type (fd->info) != G_FILE_TYPE_REGULAR)
+		if (g_file_info_get_file_type (file_data->info) != G_FILE_TYPE_REGULAR)
 			continue;
 
-		if (gth_file_store_find (file_store, fd->file) >= 0)
+		if (gth_file_store_find (file_store, file_data->file, NULL))
 			continue;
 
-		icon = g_file_info_get_icon (fd->info);
+		icon = g_file_info_get_icon (file_data->info);
 		pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
-		metadata = _gth_file_list_get_metadata (file_list, fd);
+		metadata = _gth_file_list_get_metadata (file_list, file_data);
 		gth_file_store_queue_add (file_store,
-					  fd,
+					  file_data,
 					  pixbuf,
 					  TRUE,
-					  metadata->str);
+					  metadata->str,
+					  TRUE);
 
 		g_string_free (metadata, TRUE);
 		if (pixbuf != NULL)
@@ -773,12 +850,11 @@ gfl_delete_files (GthFileList *file_list,
 
 	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
 	for (scan = files; scan; scan = scan->next) {
-		GFile *file = scan->data;
-		int    abs_pos;
+		GFile       *file = scan->data;
+		GtkTreeIter  iter;
 
-		abs_pos = gth_file_store_find (file_store, file);
-		if (abs_pos >= 0)
-			gth_file_store_queue_remove (file_store, abs_pos);
+		if (gth_file_store_find (file_store, file, &iter))
+			gth_file_store_queue_remove (file_store, &iter);
 	}
 	gth_file_store_exec_remove (file_store);
 	_gth_file_list_update_pane (file_list);
@@ -806,17 +882,14 @@ gfl_update_files (GthFileList *file_list,
 
 	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
 	for (scan = files; scan; scan = scan->next) {
-		GthFileData *fd = scan->data;
-		int          abs_pos;
+		GthFileData *file_data = scan->data;
+		GtkTreeIter  iter;
 
-		abs_pos = gth_file_store_find (file_store, fd->file);
-		if (abs_pos >= 0)
+		if (gth_file_store_find (file_store, file_data->file, &iter))
 			gth_file_store_queue_set (file_store,
-						  abs_pos,
-						  fd,
-						  NULL,
-						  -1,
-						  NULL);
+						  &iter,
+						  GTH_FILE_STORE_FILE_DATA_COLUMN, file_data,
+						  -1);
 	}
 	gth_file_store_exec_set (file_store);
 	_gth_file_list_update_pane (file_list);
@@ -841,20 +914,14 @@ gfl_rename_file (GthFileList *file_list,
 		 GthFileData *file_data)
 {
 	GthFileStore *file_store;
-	int           abs_pos;
+	GtkTreeIter   iter;
 
 	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
-	abs_pos = gth_file_store_find (file_store, file);
-	if (abs_pos < 0)
-		return;
-
-	gth_file_store_queue_set (file_store,
-				  abs_pos,
-				  file_data,
-				  NULL,
-				  -1,
-				  NULL);
-	gth_file_store_exec_set (file_store);
+	if (gth_file_store_find (file_store, file, &iter))
+		gth_file_store_set (file_store,
+				    &iter,
+				    GTH_FILE_STORE_FILE_DATA_COLUMN, file_data,
+				    -1);
 	_gth_file_list_update_pane (file_list);
 }
 
@@ -989,34 +1056,32 @@ gfl_enable_thumbs (GthFileList *file_list,
 		   gboolean     enable)
 {
 	GthFileStore *file_store;
-	GList        *files, *scan;
-	int           pos;
+	GtkTreeIter   iter;
 
 	file_list->priv->load_thumbs = enable;
 
 	file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
-	files = gth_file_store_get_all (file_store);
-	pos = 0;
-	for (scan = files; scan; scan = scan->next) {
-		GthFileData *fd = scan->data;
-		GIcon       *icon;
-		GdkPixbuf   *pixbuf = NULL;
-
-		fd->thumb_loaded = FALSE;
-		fd->thumb_created = FALSE;
-		fd->error = FALSE;
-
-		icon = g_file_info_get_icon (fd->info);
-		pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
-
-		gth_file_store_set (file_store, pos, NULL, pixbuf, TRUE, NULL);
+	if (gth_file_store_get_first (file_store, &iter)) {
+		do {
+			GthFileData *file_data;
+			GIcon       *icon;
+			GdkPixbuf   *pixbuf;
+
+			file_data = gth_file_store_get_file (file_store, &iter);
+			icon = g_file_info_get_icon (file_data->info);
+			pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+			gth_file_store_queue_set (file_store,
+						  &iter,
+						  GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+						  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
+						  -1);
 
-		if (pixbuf != NULL)
-			g_object_unref (pixbuf);
+			_g_object_unref (pixbuf);
+		}
+		while (gth_file_store_get_next (file_store, &iter));
 
-		pos++;
+		gth_file_store_exec_set (file_store);
 	}
-	_g_object_list_unref (files);
 
 	start_update_next_thumb (file_list);
 }
@@ -1057,11 +1122,9 @@ void
 gth_file_list_set_caption (GthFileList *file_list,
 			   const char  *attributes)
 {
-	GthFileStore  *file_store;
-	GList         *list;
-	GList         *scan;
-	int            pos;
-	gboolean       metadata_visible;
+	GthFileStore *file_store;
+	GtkTreeIter   iter;
+	gboolean      metadata_visible;
 
 	g_strfreev (file_list->priv->caption_attributes_v);
 	file_list->priv->caption_attributes_v = g_strsplit (attributes, ",", -1);
@@ -1073,25 +1136,24 @@ gth_file_list_set_caption (GthFileList *file_list,
 		      NULL);
 
 	file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+	if (gth_file_store_get_first (file_store, &iter)) {
+		do {
+			GthFileData *file_data;
+			GString     *metadata;
 
-	list = gth_file_store_get_all (file_store);
-	for (scan = list, pos = 0; scan; scan = scan->next, pos++) {
-		GthFileData *file_data = scan->data;
-		GString     *metadata;
+			file_data = gth_file_store_get_file (file_store, &iter);
+			metadata = _gth_file_list_get_metadata (file_list, file_data);
+			gth_file_store_queue_set (file_store,
+						  &iter,
+						  GTH_FILE_STORE_METADATA_COLUMN, metadata,
+						  -1);
 
-		metadata = _gth_file_list_get_metadata (file_list, file_data);
-		gth_file_store_queue_set (file_store,
-					  pos,
-					  NULL,
-					  NULL,
-					  -1,
-					  metadata->str);
+			g_string_free (metadata, TRUE);
+		}
+		while (gth_file_store_get_next (file_store, &iter));
 
-		g_string_free (metadata, TRUE);
+		gth_file_store_exec_set (file_store);
 	}
-	gth_file_store_exec_set (file_store);
-
-	_g_object_list_unref (list);
 }
 
 
@@ -1123,24 +1185,22 @@ set_loading_icon (GthFileList *file_list,
 		  GthFileData *file_data)
 {
 	GthFileStore *file_store;
-	int           pos;
+	GtkTreeIter   iter;
 	GIcon        *icon;
 	GdkPixbuf    *pixbuf;
 
 	file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
 
-	pos = gth_file_store_find (file_store, file_data->file);
-	if (pos < 0)
+	if (! gth_file_store_find (file_store, file_data->file, &iter))
 		return;
 
 	icon = g_themed_icon_new ("image-loading");
 	pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
 	gth_file_store_queue_set (file_store,
-				  pos,
-				  NULL,
-				  pixbuf,
-				  TRUE,
-				  NULL);
+				  &iter,
+				  GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+				  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
+				  -1);
 
 	_g_object_unref (pixbuf);
 	g_object_unref (icon);
diff --git a/gthumb/gth-file-list.h b/gthumb/gth-file-list.h
index 35a9b1d..35b0f08 100644
--- a/gthumb/gth-file-list.h
+++ b/gthumb/gth-file-list.h
@@ -31,6 +31,12 @@
 
 G_BEGIN_DECLS
 
+typedef enum {
+	GTH_FILE_LIST_TYPE_NORMAL,
+	GTH_FILE_LIST_TYPE_BROWSER,
+	GTH_FILE_LIST_TYPE_SELECTOR
+} GthFileListType;
+
 #define GTH_TYPE_FILE_LIST            (gth_file_list_get_type ())
 #define GTH_FILE_LIST(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_FILE_LIST, GthFileList))
 #define GTH_FILE_LIST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_FILE_LIST, GthFileListClass))
@@ -52,7 +58,7 @@ struct _GthFileListClass {
 };
 
 GType          gth_file_list_get_type       (void);
-GtkWidget *    gth_file_list_new            (void);
+GtkWidget *    gth_file_list_new            (GthFileListType       list_type);
 void           gth_file_list_cancel         (GthFileList          *file_list,
 					     DoneFunc              done_func,
 					     gpointer              user_data);
diff --git a/gthumb/gth-file-selection.c b/gthumb/gth-file-selection.c
index 81076cc..9994851 100644
--- a/gthumb/gth-file-selection.c
+++ b/gthumb/gth-file-selection.c
@@ -19,97 +19,106 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
  */
- 
+
 #include "gth-file-selection.h"
 
 
-GList * 
-gth_file_selection_get_selected (GthFileSelection *self) 
+
+void
+gth_file_selection_set_selection_mode (GthFileSelection *self,
+				       GtkSelectionMode  mode)
+{
+	GTH_FILE_SELECTION_GET_INTERFACE (self)->set_selection_mode (self, mode);
+}
+
+
+GList *
+gth_file_selection_get_selected (GthFileSelection *self)
 {
 	return GTH_FILE_SELECTION_GET_INTERFACE (self)->get_selected (self);
 }
 
 
-void 
-gth_file_selection_select (GthFileSelection *self, 
-			   int               pos) 
+void
+gth_file_selection_select (GthFileSelection *self,
+			   int               pos)
 {
 	GTH_FILE_SELECTION_GET_INTERFACE (self)->select (self, pos);
 }
 
 
-void 
-gth_file_selection_unselect (GthFileSelection *self, 
-			     int               pos) 
+void
+gth_file_selection_unselect (GthFileSelection *self,
+			     int               pos)
 {
 	GTH_FILE_SELECTION_GET_INTERFACE (self)->unselect (self, pos);
 }
 
 
-void 
-gth_file_selection_select_all (GthFileSelection *self) 
+void
+gth_file_selection_select_all (GthFileSelection *self)
 {
 	GTH_FILE_SELECTION_GET_INTERFACE (self)->select_all (self);
 }
 
 
-void 
-gth_file_selection_unselect_all (GthFileSelection *self) 
+void
+gth_file_selection_unselect_all (GthFileSelection *self)
 {
 	GTH_FILE_SELECTION_GET_INTERFACE (self)->unselect_all (self);
 }
 
 
-gboolean 
-gth_file_selection_is_selected (GthFileSelection *self, 
-				int               pos) 
+gboolean
+gth_file_selection_is_selected (GthFileSelection *self,
+				int               pos)
 {
 	return GTH_FILE_SELECTION_GET_INTERFACE (self)->is_selected (self, pos);
 }
 
 
-GtkTreePath * 
-gth_file_selection_get_first_selected (GthFileSelection *self) 
+GtkTreePath *
+gth_file_selection_get_first_selected (GthFileSelection *self)
 {
 	return GTH_FILE_SELECTION_GET_INTERFACE (self)->get_first_selected (self);
 }
 
 
-GtkTreePath * 
-gth_file_selection_get_last_selected (GthFileSelection *self) 
+GtkTreePath *
+gth_file_selection_get_last_selected (GthFileSelection *self)
 {
 	return GTH_FILE_SELECTION_GET_INTERFACE (self)->get_last_selected (self);
 }
 
 
-guint 
-gth_file_selection_get_n_selected (GthFileSelection *self) 
+guint
+gth_file_selection_get_n_selected (GthFileSelection *self)
 {
 	return GTH_FILE_SELECTION_GET_INTERFACE (self)->get_n_selected (self);
 }
 
 
-GType 
-gth_file_selection_get_type (void) 
+GType
+gth_file_selection_get_type (void)
 {
 	static GType type = 0;
-	
+
 	if (type == 0) {
-		static const GTypeInfo g_define_type_info = { 
-			sizeof (GthFileSelectionIface), 
-			(GBaseInitFunc) NULL, 
-			(GBaseFinalizeFunc) NULL, 
-			(GClassInitFunc) NULL, 
-			(GClassFinalizeFunc) NULL, 
-			NULL, 
-			0, 
-			0, 
-			(GInstanceInitFunc) NULL, 
+		static const GTypeInfo g_define_type_info = {
+			sizeof (GthFileSelectionIface),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) NULL,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			0,
+			0,
+			(GInstanceInitFunc) NULL,
 			NULL
 		};
-		type = g_type_register_static (G_TYPE_INTERFACE, 
-					       "GthFileSelection", 
-					       &g_define_type_info, 
+		type = g_type_register_static (G_TYPE_INTERFACE,
+					       "GthFileSelection",
+					       &g_define_type_info,
 					       0);
 	}
 	return type;
diff --git a/gthumb/gth-file-selection.h b/gthumb/gth-file-selection.h
index 20fb749..e309436 100644
--- a/gthumb/gth-file-selection.h
+++ b/gthumb/gth-file-selection.h
@@ -42,6 +42,8 @@ struct _GthFileSelectionIface {
 
 	/*< virtual functions >*/
 
+	void          (*set_selection_mode) (GthFileSelection *self,
+					     GtkSelectionMode  mode);
 	GList *       (*get_selected)       (GthFileSelection *self);
 	void          (*select)             (GthFileSelection *self,
 					     int               pos);
@@ -57,6 +59,8 @@ struct _GthFileSelectionIface {
 };
 
 GType         gth_file_selection_get_type           (void);
+void          gth_file_selection_set_selection_mode (GthFileSelection *self,
+						     GtkSelectionMode  mode);
 GList *       gth_file_selection_get_selected       (GthFileSelection *self);
 void          gth_file_selection_select             (GthFileSelection *self,
 						     int               pos);
diff --git a/gthumb/gth-file-store.c b/gthumb/gth-file-store.c
index 4534d7f..cc8e8e7 100644
--- a/gthumb/gth-file-store.c
+++ b/gthumb/gth-file-store.c
@@ -35,10 +35,11 @@ static GType column_type[GTH_FILE_STORE_N_COLUMNS] = { G_TYPE_INVALID, };
 
 
 typedef struct {
-	GthFileData *file;
+	GthFileData *file_data;
 	GdkPixbuf   *thumbnail;
 	gboolean     is_icon;
 	char        *metadata;
+	gboolean     checked;
 
 	/*< private >*/
 
@@ -83,9 +84,9 @@ _gth_file_row_set_file (GthFileRow  *row,
 {
 	if (file != NULL) {
 		g_object_ref (file);
-		if (row->file != NULL)
-			g_object_unref (row->file);
-		row->file = file;
+		if (row->file_data != NULL)
+			g_object_unref (row->file_data);
+		row->file_data = file;
 	}
 }
 
@@ -125,10 +126,11 @@ _gth_file_row_copy (GthFileRow *row)
 	GthFileRow *row2;
 
 	row2 = _gth_file_row_new ();
-	_gth_file_row_set_file (row2, row->file);
+	_gth_file_row_set_file (row2, row->file_data);
 	_gth_file_row_set_thumbnail (row2, row->thumbnail);
 	_gth_file_row_set_metadata (row2, row->metadata);
 	row2->is_icon = row->is_icon;
+	row2->checked = row->checked;
 	row2->pos = row->pos;
 	row2->abs_pos = row->abs_pos;
 	row2->visible = row->visible;
@@ -141,8 +143,8 @@ _gth_file_row_copy (GthFileRow *row)
 static void
 _gth_file_row_free (GthFileRow *row)
 {
-	if (row->file != NULL)
-		g_object_unref (row->file);
+	if (row->file_data != NULL)
+		g_object_unref (row->file_data);
 	if (row->thumbnail != NULL)
 		g_object_unref (row->thumbnail);
 	g_free (row->metadata);
@@ -222,11 +224,12 @@ gth_file_store_init (GthFileStore *file_store)
 	file_store->priv->filter = gth_test_new ();
 
 	if (column_type[0] == G_TYPE_INVALID) {
-		column_type[GTH_FILE_STORE_FILE_COLUMN] = GTH_TYPE_FILE_DATA;
+		column_type[GTH_FILE_STORE_FILE_DATA_COLUMN] = GTH_TYPE_FILE_DATA;
 		column_type[GTH_FILE_STORE_THUMBNAIL_COLUMN] = GDK_TYPE_PIXBUF;
 		column_type[GTH_FILE_STORE_IS_ICON_COLUMN] = G_TYPE_BOOLEAN;
 		column_type[GTH_FILE_STORE_FILENAME_COLUMN] = G_TYPE_STRING;
 		column_type[GTH_FILE_STORE_METADATA_COLUMN] = G_TYPE_STRING;
+		column_type[GTH_FILE_STORE_CHECKED_COLUMN] = G_TYPE_BOOLEAN;
 	}
 }
 
@@ -326,9 +329,9 @@ gth_file_store_get_value (GtkTreeModel *tree_model,
 	row = (GthFileRow*) iter->user_data;
 
 	switch (column) {
-	case GTH_FILE_STORE_FILE_COLUMN:
+	case GTH_FILE_STORE_FILE_DATA_COLUMN:
 		g_value_init (value, GTH_TYPE_FILE_DATA);
-		g_value_set_object (value, row->file);
+		g_value_set_object (value, row->file_data);
 		break;
 	case GTH_FILE_STORE_THUMBNAIL_COLUMN:
 		g_value_init (value, GDK_TYPE_PIXBUF);
@@ -340,12 +343,16 @@ gth_file_store_get_value (GtkTreeModel *tree_model,
 		break;
 	case GTH_FILE_STORE_FILENAME_COLUMN:
 		g_value_init (value, G_TYPE_STRING);
-		g_value_set_string (value, g_file_info_get_display_name (row->file->info));
+		g_value_set_string (value, g_file_info_get_display_name (row->file_data->info));
 		break;
 	case GTH_FILE_STORE_METADATA_COLUMN:
 		g_value_init (value, G_TYPE_STRING);
 		g_value_set_string (value, row->metadata);
 		break;
+	case GTH_FILE_STORE_CHECKED_COLUMN:
+		g_value_init (value, G_TYPE_BOOLEAN);
+		g_value_set_boolean (value, row->checked);
+		break;
 	}
 }
 
@@ -501,7 +508,7 @@ gth_file_store_drag_data_get (GtkTreeDragSource *drag_source,
 		char **uris;
 
 		uris = g_new (char *, 2);
-		uris[0] = g_file_get_uri (row->file->file);
+		uris[0] = g_file_get_uri (row->file_data->file);
 		uris[1] = NULL;
 		gtk_selection_data_set_uris (selection_data, uris);
 		retval = TRUE;
@@ -511,7 +518,7 @@ gth_file_store_drag_data_get (GtkTreeDragSource *drag_source,
 	else if (gtk_selection_data_targets_include_text (selection_data)) {
 		char *parse_name;
 
-		parse_name = g_file_get_parse_name (row->file->file);
+		parse_name = g_file_get_parse_name (row->file_data->file);
 		gtk_selection_data_set_text (selection_data, parse_name, -1);
 		retval = TRUE;
 
@@ -526,23 +533,14 @@ gth_file_store_drag_data_delete (GtkTreeDragSource *drag_source,
                                  GtkTreePath       *path)
 {
 	GthFileStore *file_store;
-	int          *indices, n;
-	GthFileRow   *row;
+	GtkTreeIter   iter;
 
 	g_return_val_if_fail (path != NULL, FALSE);
 
 	file_store = GTH_FILE_STORE (drag_source);
-
-	indices = gtk_tree_path_get_indices (path);
-	n = indices[0];
-	if ((n < 0) || (n >= file_store->priv->num_rows))
+	if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (file_store), &iter, path))
 		return FALSE;
-
-	row = file_store->priv->rows[n];
-	g_return_val_if_fail (row != NULL, FALSE);
-	g_return_val_if_fail (row->pos == n, FALSE);
-
-	gth_file_store_remove (file_store, row->abs_pos);
+	gth_file_store_remove (file_store, &iter);
 
 	return TRUE;
 }
@@ -648,7 +646,7 @@ _gth_file_store_get_files (GthFileStore *file_store)
 
 	for (i = 0; i < file_store->priv->tot_rows; i++) {
 		GthFileRow *row = file_store->priv->all_rows[i];
-		files = g_list_prepend (files, g_object_ref (row->file));
+		files = g_list_prepend (files, g_object_ref (row->file_data));
 	}
 
 	return  g_list_reverse (files);
@@ -686,7 +684,7 @@ campare_row_func (gconstpointer a,
 		result = 1 /*strcmp (gth_file_data_get_filename_sort_key (row_a->file),
 			       gth_file_data_get_filename_sort_key (row_b->file))*/;
 	else
-		result = file_store->priv->cmp_func (row_a->file, row_b->file);
+		result = file_store->priv->cmp_func (row_a->file_data, row_b->file_data);
 
 	if (file_store->priv->inverse_sort)
 		result = result * -1;
@@ -820,7 +818,7 @@ g_print ("UPDATE VISIBILITY\n");
 		GthFileRow *row = all_rows[i];
 
 		row->abs_pos = i;
-		files = g_list_prepend (files, g_object_ref (row->file));
+		files = g_list_prepend (files, g_object_ref (row->file_data));
 	}
 	files = g_list_reverse (files);
 
@@ -831,7 +829,7 @@ g_print ("UPDATE VISIBILITY\n");
 
 		for (i = 0; i < all_rows_n; i++) {
 			row = all_rows[i];
-			if (row->file == file)
+			if (row->file_data == file)
 				break;
 		}
 
@@ -865,7 +863,7 @@ g_print ("UPDATE VISIBILITY\n");
 		/* search old_rows[i] in new_rows */
 
 		for (j = 0; j < new_rows_n; j++)
-			if (old_rows[i]->file == new_rows[j]->file)
+			if (old_rows[i]->file_data == new_rows[j]->file_data)
 				break;
 
 		if (j < new_rows_n)
@@ -890,7 +888,7 @@ g_print ("  DELETE: %d\n", old_rows[i]->pos);
 		for (i = 0, j = 0; i < old_rows_n; i++) {
 			if (old_rows[i] != NULL) {
 				old_rows[j] = old_rows[i];
-				old_rows[j]->abs_pos = j;
+				/*old_rows[j]->abs_pos = j; FIXME: check if this is correct */
 				j++;
 			}
 		}
@@ -912,7 +910,7 @@ g_print ("  DELETE: %d\n", old_rows[i]->pos);
 			/* search new_rows[i] in old_rows */
 
 			for (j = 0; j < old_rows_n; j++)
-				if (new_rows[i]->file == old_rows[j]->file)
+				if (new_rows[i]->file_data == old_rows[j]->file_data)
 					break;
 
 			if (j >= old_rows_n)
@@ -989,7 +987,7 @@ g_print ("\n");
 		GtkTreePath *path;
 		GtkTreeIter  iter;
 
-		if ((i < file_store->priv->num_rows) && (new_rows[i]->file == file_store->priv->rows[i]->file))
+		if ((i < file_store->priv->num_rows) && (new_rows[i]->file_data == file_store->priv->rows[i]->file_data))
 			continue;
 
 #ifdef DEBUG_FILE_STORE
@@ -1083,7 +1081,7 @@ gth_file_store_get_all (GthFileStore *file_store)
 	int    i;
 
 	for (i = 0; i < file_store->priv->tot_rows; i++)
-		list = g_list_prepend (list, g_object_ref (file_store->priv->all_rows[i]->file));
+		list = g_list_prepend (list, g_object_ref (file_store->priv->all_rows[i]->file_data));
 
 	return g_list_reverse (list);
 }
@@ -1103,7 +1101,7 @@ gth_file_store_get_visibles (GthFileStore *file_store)
 	int    i;
 
 	for (i = 0; i < file_store->priv->num_rows; i++)
-		list = g_list_prepend (list, g_object_ref (file_store->priv->rows[i]->file));
+		list = g_list_prepend (list, g_object_ref (file_store->priv->rows[i]->file_data));
 
 	return g_list_reverse (list);
 }
@@ -1122,80 +1120,195 @@ gth_file_store_get_file (GthFileStore *file_store,
 {
 	g_return_val_if_fail (VALID_ITER (iter, file_store), NULL);
 
-	return ((GthFileRow *) iter->user_data)->file;
+	return ((GthFileRow *) iter->user_data)->file_data;
 }
 
 
-GthFileData *
-gth_file_store_get_file_at_pos (GthFileStore *file_store,
-				int           pos)
+gboolean
+gth_file_store_find (GthFileStore *file_store,
+		     GFile        *file,
+		     GtkTreeIter  *iter)
 {
-	GthFileData *file_data = NULL;
-	GtkTreePath *path;
-	GtkTreeIter  iter;
+	gboolean found = FALSE;
+	int      i;
 
-	if (pos < 0)
-		return NULL;
+	for (i = 0; i < file_store->priv->tot_rows; i++) {
+		GthFileRow *row = file_store->priv->all_rows[i];
 
-	path = gtk_tree_path_new ();
-	gtk_tree_path_append_index (path, pos);
-	if (gtk_tree_model_get_iter (GTK_TREE_MODEL (file_store), &iter, path))
-		file_data = gth_file_store_get_file (file_store, &iter);
+		if (row == NULL)
+			continue;
 
-	gtk_tree_path_free (path);
+		if (g_file_equal (row->file_data->file, file)) {
+			if (iter != NULL) {
+				iter->stamp = file_store->priv->stamp;
+				iter->user_data = row;
+			}
+			found = TRUE;
+			break;
+		}
+	}
 
-	return file_data;
+	return found;
 }
 
 
-GthFileData *
-gth_file_store_get_file_at_abs_pos (GthFileStore *file_store,
-				    int           abs_pos)
+gboolean
+gth_file_store_find_visible (GthFileStore *file_store,
+			     GFile        *file,
+			     GtkTreeIter  *iter)
 {
-	if ((abs_pos < 0) || (abs_pos >= file_store->priv->tot_rows))
-		return NULL;
-	else
-		return g_object_ref (file_store->priv->all_rows[abs_pos]->file);
+	gboolean found = FALSE;
+	int      i;
+
+	for (i = 0; i < file_store->priv->num_rows; i++) {
+		GthFileRow *row = file_store->priv->rows[i];
+
+		if (row == NULL)
+			continue;
+
+		if (g_file_equal (row->file_data->file, file)) {
+			if (iter != NULL) {
+				iter->stamp = file_store->priv->stamp;
+				iter->user_data = row;
+			}
+			found = TRUE;
+			break;
+		}
+	}
+
+	return found;
 }
 
 
 int
-gth_file_store_find (GthFileStore *file_store,
-		     GFile        *file)
+gth_file_store_get_pos (GthFileStore *file_store,
+			GFile        *file)
 {
-	int i;
+	GtkTreeIter iter;
+	GthFileRow *row;
 
-	for (i = 0; i < file_store->priv->tot_rows; i++) {
-		GthFileRow *row = file_store->priv->all_rows[i];
+	if (! gth_file_store_find_visible (file_store, file, &iter))
+		return -1;
 
-		if (row == NULL)
-			continue;
+	row = iter.user_data;
+
+	return row->pos;
+}
 
-		if (g_file_equal (row->file->file, file))
-			return row->abs_pos;
+
+gboolean
+gth_file_store_get_nth (GthFileStore *file_store,
+		        int           n,
+		        GtkTreeIter  *iter)
+{
+	GthFileRow *row;
+
+	if (file_store->priv->tot_rows <= n)
+		return FALSE;
+
+	row = file_store->priv->all_rows[n];
+	g_return_val_if_fail (row != NULL, FALSE);
+
+	if (iter != NULL) {
+		iter->stamp = file_store->priv->stamp;
+		iter->user_data = row;
 	}
 
-	return -1;
+	return TRUE;
 }
 
 
-int
-gth_file_store_find_visible (GthFileStore *file_store,
-			     GFile        *file)
+gboolean
+gth_file_store_get_next (GthFileStore *file_store,
+			 GtkTreeIter  *iter)
 {
-	int i;
+	GthFileRow *row;
 
-	for (i = 0; i < file_store->priv->num_rows; i++) {
-		GthFileRow *row = file_store->priv->rows[i];
+	if ((iter == NULL) || (iter->user_data == NULL))
+		return FALSE;
+
+	g_return_val_if_fail (VALID_ITER (iter, file_store), FALSE);
+
+  	row = (GthFileRow*) iter->user_data;
+	if (row->abs_pos + 1 >= file_store->priv->tot_rows)
+		return FALSE;
+
+	if (iter != NULL) {
+		iter->stamp = file_store->priv->stamp;
+		iter->user_data = file_store->priv->all_rows[row->abs_pos + 1];
+	}
+
+	return TRUE;
+}
 
-		if (row == NULL)
-			continue;
 
-		if (g_file_equal (row->file->file, file))
-			return row->pos;
+gboolean
+gth_file_store_get_nth_visible (GthFileStore *file_store,
+				int           n,
+				GtkTreeIter  *iter)
+{
+	GthFileRow *row;
+
+	if (file_store->priv->num_rows <= n)
+		return FALSE;
+
+	row = file_store->priv->rows[n];
+	g_return_val_if_fail (row != NULL, FALSE);
+
+	if (iter != NULL) {
+		iter->stamp = file_store->priv->stamp;
+		iter->user_data = row;
 	}
 
-	return -1;
+	return TRUE;
+}
+
+
+gboolean
+gth_file_store_get_next_visible (GthFileStore *file_store,
+				 GtkTreeIter  *iter)
+{
+	GthFileRow *row;
+
+	if ((iter == NULL) || (iter->user_data == NULL))
+		return FALSE;
+
+	g_return_val_if_fail (VALID_ITER (iter, file_store), FALSE);
+
+  	row = (GthFileRow*) iter->user_data;
+	if (row->pos + 1 >= file_store->priv->num_rows)
+		return FALSE;
+
+	if (iter != NULL) {
+		iter->stamp = file_store->priv->stamp;
+		iter->user_data = file_store->priv->rows[row->pos + 1];
+	}
+
+	return TRUE;
+}
+
+
+gboolean
+gth_file_store_get_prev_visible (GthFileStore *file_store,
+				 GtkTreeIter  *iter)
+{
+	GthFileRow *row;
+
+	if ((iter == NULL) || (iter->user_data == NULL))
+		return FALSE;
+
+	g_return_val_if_fail (VALID_ITER (iter, file_store), FALSE);
+
+  	row = (GthFileRow*) iter->user_data;
+	if (row->pos == 0)
+		return FALSE;
+
+	if (iter != NULL) {
+		iter->stamp = file_store->priv->stamp;
+		iter->user_data = file_store->priv->rows[row->pos - 1];
+	}
+
+	return TRUE;
 }
 
 
@@ -1204,9 +1317,10 @@ gth_file_store_add (GthFileStore *file_store,
 		    GthFileData  *file,
 		    GdkPixbuf    *thumbnail,
 		    gboolean      is_icon,
-		    const char   *metadata)
+		    const char   *metadata,
+		    gboolean      checked)
 {
-	gth_file_store_queue_add (file_store, file, thumbnail, is_icon, metadata);
+	gth_file_store_queue_add (file_store, file, thumbnail, is_icon, metadata, checked);
 	gth_file_store_exec_add (file_store);
 }
 
@@ -1216,31 +1330,19 @@ gth_file_store_queue_add (GthFileStore *file_store,
 			  GthFileData  *file,
 			  GdkPixbuf    *thumbnail,
 			  gboolean      is_icon,
-			  const char   *metadata)
+			  const char   *metadata,
+			  gboolean      checked)
 {
 	GthFileRow *row;
 
 	g_return_if_fail (file != NULL);
 
-	/*file_store->priv->tot_rows++;
-	if (file_store->priv->tot_rows > file_store->priv->size) {
-		file_store->priv->size += REALLOC_STEP;
-		file_store->priv->all_rows = g_realloc (file_store->priv->all_rows, sizeof (GthFileRow*) * file_store->priv->size);
-	}
-
-	row = _gth_file_row_new ();
-	_gth_file_row_set_file (row, file);
-	_gth_file_row_set_thumbnail (row, thumbnail);
-	_gth_file_row_set_metadata (row, metadata);
-	row->is_icon = is_icon;
-  	row->abs_pos = file_store->priv->tot_rows - 1;
-	file_store->priv->all_rows[row->abs_pos] = row;*/
-
 	row = _gth_file_row_new ();
 	_gth_file_row_set_file (row, file);
 	_gth_file_row_set_thumbnail (row, thumbnail);
 	_gth_file_row_set_metadata (row, metadata);
 	row->is_icon = is_icon;
+	row->checked = checked;
 	file_store->priv->queue = g_list_prepend (file_store->priv->queue, row);
 }
 
@@ -1253,41 +1355,87 @@ gth_file_store_exec_add (GthFileStore *file_store)
 }
 
 
+static void
+gth_file_store_queue_set_valist (GthFileStore *file_store,
+			         GtkTreeIter  *iter,
+			         va_list       var_args)
+{
+	GthFileRow  *row;
+	int          column;
+
+	g_return_if_fail (VALID_ITER (iter, file_store));
+
+  	row = (GthFileRow*) iter->user_data;
+
+  	column = va_arg (var_args, int);
+  	while (column != -1) {
+  		GthFileData *file_data;
+  		GdkPixbuf   *thumbnail;
+  		const char  *metadata;
+
+  		switch (column) {
+  		case GTH_FILE_STORE_FILE_DATA_COLUMN:
+  			file_data = va_arg (var_args, GthFileData *);
+  			g_return_if_fail (GTH_IS_FILE_DATA (file_data));
+  			_gth_file_row_set_file (row, file_data);
+  			file_store->priv->update_filter = TRUE;
+  			row->changed = TRUE;
+  			break;
+  		case GTH_FILE_STORE_THUMBNAIL_COLUMN:
+  			thumbnail = va_arg (var_args, GdkPixbuf *);
+  			g_return_if_fail (GDK_IS_PIXBUF (thumbnail));
+
+  			_gth_file_row_set_thumbnail (row, thumbnail);
+  			row->changed = TRUE;
+  			break;
+  		case GTH_FILE_STORE_IS_ICON_COLUMN:
+  			row->is_icon = va_arg (var_args, gboolean);
+  			row->changed = TRUE;
+  			break;
+  		case GTH_FILE_STORE_METADATA_COLUMN:
+  			metadata = va_arg (var_args, const char *);
+  			_gth_file_row_set_metadata (row, metadata);
+  			row->changed = TRUE;
+  			break;
+  		case GTH_FILE_STORE_CHECKED_COLUMN:
+  			row->checked = va_arg (var_args, gboolean);
+  			row->changed = TRUE;
+  			break;
+  		default:
+  			g_warning ("%s: Invalid column number %d added to iter (remember to end your list of columns with a -1)", G_STRLOC, column);
+  			break;
+  		}
+
+  		column = va_arg (var_args, int);
+  	}
+}
+
+
 void
 gth_file_store_set (GthFileStore *file_store,
-		    int           abs_pos,
-		    GthFileData  *file,
-		    GdkPixbuf    *thumbnail,
-		    gboolean      is_icon,
-		    const char   *metadata)
+		    GtkTreeIter  *iter,
+		    ...)
 {
-	gth_file_store_queue_set (file_store, abs_pos, file, thumbnail, is_icon, metadata);
+	va_list var_args;
+
+	va_start (var_args, iter);
+	gth_file_store_queue_set_valist (file_store, iter, var_args);
+	va_end (var_args);
+
 	gth_file_store_exec_set (file_store);
 }
 
 
 void
 gth_file_store_queue_set (GthFileStore *file_store,
-			  int           abs_pos,
-			  GthFileData  *file,
-			  GdkPixbuf    *thumbnail,
-			  gboolean      is_icon,
-			  const char   *metadata)
+			  GtkTreeIter  *iter,
+			  ...)
 {
-	GthFileRow *row;
-
-	g_return_if_fail ((abs_pos >= 0) && (abs_pos < file_store->priv->tot_rows));
-
-	row = file_store->priv->all_rows[abs_pos];
-	_gth_file_row_set_file (row, file);
-	_gth_file_row_set_thumbnail (row, thumbnail);
-	_gth_file_row_set_metadata (row, metadata);
-	if (is_icon != -1)
-		row->is_icon = is_icon;
-	row->changed = TRUE;
+	va_list var_args;
 
-	if (file != NULL)
-		file_store->priv->update_filter = TRUE;
+	va_start (var_args, iter);
+	gth_file_store_queue_set_valist (file_store, iter, var_args);
+	va_end (var_args);
 }
 
 
@@ -1320,20 +1468,24 @@ gth_file_store_exec_set (GthFileStore *file_store)
 
 void
 gth_file_store_remove (GthFileStore *file_store,
-		       int           abs_pos)
+		       GtkTreeIter  *iter)
 {
-	gth_file_store_queue_remove (file_store, abs_pos);
+	gth_file_store_queue_remove (file_store, iter);
 	gth_file_store_exec_remove (file_store);
 }
 
 
 void
 gth_file_store_queue_remove (GthFileStore *file_store,
-			     int           abs_pos)
+			     GtkTreeIter  *iter)
 {
-	g_return_if_fail ((abs_pos >= 0) && (abs_pos < file_store->priv->tot_rows));
+	GthFileRow  *row;
+
+	g_return_if_fail (VALID_ITER (iter, file_store));
+
+  	row = (GthFileRow*) iter->user_data;
 
-	file_store->priv->queue = g_list_prepend (file_store->priv->queue, file_store->priv->all_rows[abs_pos]);
+	file_store->priv->queue = g_list_prepend (file_store->priv->queue, file_store->priv->all_rows[row->abs_pos]);
 }
 
 
diff --git a/gthumb/gth-file-store.h b/gthumb/gth-file-store.h
index d3169c7..ef49dda 100644
--- a/gthumb/gth-file-store.h
+++ b/gthumb/gth-file-store.h
@@ -41,11 +41,12 @@ typedef struct _GthFileStorePrivate  GthFileStorePrivate;
 typedef struct _GthFileStoreClass    GthFileStoreClass;
 
 enum {
-	GTH_FILE_STORE_FILE_COLUMN,
+	GTH_FILE_STORE_FILE_DATA_COLUMN,
 	GTH_FILE_STORE_THUMBNAIL_COLUMN,
 	GTH_FILE_STORE_IS_ICON_COLUMN,
 	GTH_FILE_STORE_FILENAME_COLUMN,
 	GTH_FILE_STORE_METADATA_COLUMN,
+	GTH_FILE_STORE_CHECKED_COLUMN,
 	GTH_FILE_STORE_N_COLUMNS
 };
 
@@ -60,59 +61,67 @@ struct _GthFileStoreClass
 	GObjectClass __parent_class;
 };
 
-GType           gth_file_store_get_type        (void) G_GNUC_CONST;
-GthFileStore *  gth_file_store_new             (void);
-int             gth_file_store_get_abs_pos     (GthFileStore         *file_store,
-					        int                   pos);
-void            gth_file_store_set_filter      (GthFileStore         *file_store,
-					        GthTest              *filter);
-void            gth_file_store_set_sort_func   (GthFileStore         *file_store,
-					        GthFileDataCompFunc   cmp_func,
-					        gboolean              inverse_sort);
-GList *         gth_file_store_get_all         (GthFileStore         *file_store);
-int             gth_file_store_n_files         (GthFileStore         *file_store);
-GList *         gth_file_store_get_visibles    (GthFileStore         *file_store);
-int             gth_file_store_n_visibles      (GthFileStore         *file_store);
-GthFileData *   gth_file_store_get_file        (GthFileStore         *file_store,
-					        GtkTreeIter          *iter);
-GthFileData *   gth_file_store_get_file_at_pos (GthFileStore         *file_store,
-					        int                   pos);
-GthFileData *   gth_file_store_get_file_at_abs_pos (GthFileStore     *file_store,
-					        int                   abs_pos);
-int             gth_file_store_find            (GthFileStore         *file_store,
-					        GFile                *file);
-int             gth_file_store_find_visible    (GthFileStore         *file_store,
-					        GFile                *file);
-void            gth_file_store_add             (GthFileStore         *file_store,
-					        GthFileData          *file,
-					        GdkPixbuf            *thumbnail,
-					        gboolean              is_icon,
-					        const char           *metadata);
-void            gth_file_store_queue_add       (GthFileStore         *file_store,
-					        GthFileData          *file,
-					        GdkPixbuf            *thumbnail,
-					        gboolean              is_icon,
-					        const char           *metadata);
-void            gth_file_store_exec_add        (GthFileStore         *file_store);
-void            gth_file_store_set             (GthFileStore         *file_store,
-					        int                   abs_pos,
-					        GthFileData          *file,
-					        GdkPixbuf            *thumbnail,
-					        gboolean              is_icon,
-					        const char           *metadata);
-void            gth_file_store_queue_set       (GthFileStore         *file_store,
-					        int                   abs_pos,
-					        GthFileData          *file,
-					        GdkPixbuf            *thumbnail,
-					        gboolean              is_icon,
-					        const char           *metadata);
-void            gth_file_store_exec_set        (GthFileStore         *file_store);
-void            gth_file_store_remove          (GthFileStore         *file_store,
-					        int                   abs_pos);
-void            gth_file_store_queue_remove    (GthFileStore         *file_store,
-					        int                   abs_pos);
-void            gth_file_store_exec_remove     (GthFileStore         *file_store);
-void            gth_file_store_clear           (GthFileStore         *file_store);
+GType           gth_file_store_get_type          (void) G_GNUC_CONST;
+GthFileStore *  gth_file_store_new               (void);
+void            gth_file_store_set_filter        (GthFileStore         *file_store,
+					          GthTest              *filter);
+void            gth_file_store_set_sort_func     (GthFileStore         *file_store,
+					          GthFileDataCompFunc   cmp_func,
+					          gboolean              inverse_sort);
+GList *         gth_file_store_get_all           (GthFileStore         *file_store);
+int             gth_file_store_n_files           (GthFileStore         *file_store);
+GList *         gth_file_store_get_visibles      (GthFileStore         *file_store);
+int             gth_file_store_n_visibles        (GthFileStore         *file_store);
+GthFileData *   gth_file_store_get_file          (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+gboolean        gth_file_store_find              (GthFileStore         *file_store,
+						  GFile                *file,
+					          GtkTreeIter          *iter);
+gboolean        gth_file_store_find_visible      (GthFileStore         *file_store,
+						  GFile                *file,
+					          GtkTreeIter          *iter);
+int             gth_file_store_get_pos           (GthFileStore         *file_store,
+						  GFile                *file);
+#define         gth_file_store_get_first(file_store, iter) gth_file_store_get_nth (file_store, 0, iter)
+gboolean        gth_file_store_get_nth           (GthFileStore         *file_store,
+						  int                   n,
+					          GtkTreeIter          *iter);
+gboolean        gth_file_store_get_next          (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+#define         gth_file_store_get_first_visible(file_store, iter) gth_file_store_get_nth_visible(file_store, 0, iter)
+gboolean        gth_file_store_get_nth_visible   (GthFileStore         *file_store,
+						  int                   n,
+					          GtkTreeIter          *iter);
+gboolean        gth_file_store_get_next_visible  (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+gboolean        gth_file_store_get_prev_visible  (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+void            gth_file_store_add               (GthFileStore         *file_store,
+					          GthFileData          *file,
+					          GdkPixbuf            *thumbnail,
+					          gboolean              is_icon,
+					          const char           *metadata,
+					          gboolean              checked);
+void            gth_file_store_queue_add         (GthFileStore         *file_store,
+					          GthFileData          *file,
+					          GdkPixbuf            *thumbnail,
+					          gboolean              is_icon,
+					          const char           *metadata,
+					          gboolean              checked);
+void            gth_file_store_exec_add          (GthFileStore         *file_store);
+void            gth_file_store_set               (GthFileStore         *file_store,
+					          GtkTreeIter          *iter,
+					          ...);
+void            gth_file_store_queue_set         (GthFileStore         *file_store,
+					          GtkTreeIter          *iter,
+					          ...);
+void            gth_file_store_exec_set          (GthFileStore         *file_store);
+void            gth_file_store_remove            (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+void            gth_file_store_queue_remove      (GthFileStore         *file_store,
+					          GtkTreeIter          *iter);
+void            gth_file_store_exec_remove       (GthFileStore         *file_store);
+void            gth_file_store_clear             (GthFileStore         *file_store);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-icon-view.c b/gthumb/gth-icon-view.c
index c13b7d7..38e2570 100644
--- a/gthumb/gth-icon-view.c
+++ b/gthumb/gth-icon-view.c
@@ -248,6 +248,14 @@ gth_icon_view_unset_drag_dest (GthFileView *self)
 }
 
 
+static void
+gth_icon_view_real_set_selection_mode (GthFileSelection *base,
+				       GtkSelectionMode  mode)
+{
+	gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (base), mode);
+}
+
+
 static GList *
 gth_icon_view_real_get_selected (GthFileSelection *base)
 {
@@ -443,6 +451,7 @@ static void
 gth_icon_view_gth_file_selection_interface_init (GthFileSelectionIface *iface)
 {
 	gth_icon_view_gth_file_selection_parent_iface = g_type_interface_peek_parent (iface);
+	iface->set_selection_mode = gth_icon_view_real_set_selection_mode;
 	iface->get_selected = gth_icon_view_real_get_selected;
 	iface->select = gth_icon_view_real_select;
 	iface->unselect = gth_icon_view_real_unselect;
diff --git a/gthumb/gth-main-default-tests.c b/gthumb/gth-main-default-tests.c
index c479d06..8b8ecd8 100644
--- a/gthumb/gth-main-default-tests.c
+++ b/gthumb/gth-main-default-tests.c
@@ -52,6 +52,34 @@ is_image_test (GthTest       *test,
 
 
 static gint64
+is_video_test (GthTest       *test,
+	       GthFileData   *file,
+	       gconstpointer *data)
+{
+	gboolean result = FALSE;
+
+	if (file->info != NULL)
+		result = _g_mime_type_is_video (gth_file_data_get_mime_type (file));
+
+	return result;
+}
+
+
+static gint64
+is_audio_test (GthTest       *test,
+	       GthFileData   *file,
+	       gconstpointer *data)
+{
+	gboolean result = FALSE;
+
+	if (file->info != NULL)
+		result = _g_mime_type_is_audio (gth_file_data_get_mime_type (file));
+
+	return result;
+}
+
+
+static gint64
 is_media_test (GthTest       *test,
 	       GthFileData   *file,
 	       gconstpointer *data)
@@ -119,6 +147,18 @@ gth_main_register_default_tests (void)
 				"data-type", GTH_TEST_DATA_TYPE_NONE,
 				"get-data-func", is_image_test,
 				NULL);
+	gth_main_register_test ("file::type::is_video",
+				GTH_TYPE_TEST_SIMPLE,
+				"display-name", _("Video"),
+				"data-type", GTH_TEST_DATA_TYPE_NONE,
+				"get-data-func", is_video_test,
+				NULL);
+	gth_main_register_test ("file::type::is_audio",
+				GTH_TYPE_TEST_SIMPLE,
+				"display-name", _("Audio"),
+				"data-type", GTH_TEST_DATA_TYPE_NONE,
+				"get-data-func", is_audio_test,
+				NULL);
 	gth_main_register_test ("file::type::is_media",
 				GTH_TYPE_TEST_SIMPLE,
 				"display-name", _("Media"),



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