[gthumb: 4/23] added work queues extension as a more powerful way to select files



commit 15ff06824915e1167f19f7a4836474e5a7e67d34
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Wed Feb 15 22:34:07 2012 +0100

    added work queues extension as a more powerful way to select files
    
    [new feature]

 configure.ac                                       |    1 +
 extensions/Makefile.am                             |    1 +
 extensions/work_queues/Makefile.am                 |   31 ++
 extensions/work_queues/actions.c                   |   24 ++
 extensions/work_queues/actions.h                   |   30 ++
 extensions/work_queues/callbacks.c                 |   78 ++++
 extensions/work_queues/callbacks.h                 |   30 ++
 .../work_queues/gth-file-source-work-queues.c      |  308 +++++++++++++++
 .../work_queues/gth-file-source-work-queues.h      |   51 +++
 extensions/work_queues/gth-queue-manager.c         |  416 ++++++++++++++++++++
 extensions/work_queues/gth-queue-manager.h         |   74 ++++
 extensions/work_queues/main.c                      |   54 +++
 extensions/work_queues/work_queues.extension.in.in |   12 +
 gthumb/gth-main.c                                  |    1 +
 14 files changed, 1111 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 42e5916..8300dca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -695,6 +695,7 @@ extensions/webalbums/data/albumthemes/ClassicClips/Makefile
 extensions/webalbums/data/albumthemes/NeatRound/Makefile
 extensions/webalbums/data/albumthemes/Wiki/Makefile
 extensions/webalbums/data/ui/Makefile
+extensions/work_queues/Makefile
 gthumb/Makefile
 po/Makefile.in
 tests/Makefile
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index 20ecbdc..ae85e78 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -57,6 +57,7 @@ SUBDIRS = 			\
 	resize_images		\
 	search			\
 	slideshow		\
+	work_queues		\
 	$(EXPORTERS)		\
 	$(IMPORTERS)		\
 	$(OTHER_TOOLS)		\
diff --git a/extensions/work_queues/Makefile.am b/extensions/work_queues/Makefile.am
new file mode 100644
index 0000000..624ac54
--- /dev/null
+++ b/extensions/work_queues/Makefile.am
@@ -0,0 +1,31 @@
+extensiondir = $(pkglibdir)/extensions
+extension_LTLIBRARIES = libwork_queues.la
+
+libwork_queues_la_SOURCES = 		\
+	actions.c			\
+	actions.h			\
+	callbacks.c			\
+	callbacks.h			\
+	gth-file-source-work-queues.c 	\
+	gth-file-source-work-queues.h	\
+	gth-queue-manager.c		\
+	gth-queue-manager.h		\
+	main.c
+
+libwork_queues_la_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
+libwork_queues_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
+libwork_queues_la_LIBADD = $(GTHUMB_LIBS)
+libwork_queues_la_DEPENDENCIES = $(top_builddir)/gthumb/gthumb$(EXEEXT)
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = work_queues.extension.in.in
+extensionini_DATA = $(extensionini_in_files:.extension.in.in=.extension)
+
+ GTHUMB_EXTENSION_IN_RULE@
+ GTHUMB_EXTENSION_RULE@
+
+EXTRA_DIST = $(extensionini_in_files) 
+
+DISTCLEANFILES = $(extensionini_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/extensions/work_queues/actions.c b/extensions/work_queues/actions.c
new file mode 100644
index 0000000..109bb90
--- /dev/null
+++ b/extensions/work_queues/actions.c
@@ -0,0 +1,24 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <gthumb.h>
diff --git a/extensions/work_queues/actions.h b/extensions/work_queues/actions.h
new file mode 100644
index 0000000..b4ef1e1
--- /dev/null
+++ b/extensions/work_queues/actions.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ACTIONS_H
+#define ACTIONS_H
+
+#include <gtk/gtk.h>
+
+#define DEFINE_ACTION(x) void x (GtkAction *action, gpointer data);
+
+
+#endif /* ACTIONS_H */
diff --git a/extensions/work_queues/callbacks.c b/extensions/work_queues/callbacks.c
new file mode 100644
index 0000000..940eafa
--- /dev/null
+++ b/extensions/work_queues/callbacks.c
@@ -0,0 +1,78 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gthumb.h>
+#include "actions.h"
+#include "gth-file-source-work-queues.h"
+#include "gth-queue-manager.h"
+
+
+static void
+gth_browser_activate_action_add_to_work_queue (GthBrowser *browser,
+					       int         n_queue)
+{
+	char  *uri;
+	GFile *folder;
+	GList *items;
+	GList *file_list = NULL;
+	GList *files;
+
+	uri = g_strdup_printf ("queue:///%d", n_queue);
+	folder = g_file_new_for_uri (uri);
+	items = gth_file_selection_get_selected (GTH_FILE_SELECTION (gth_browser_get_file_list_view (browser)));
+	file_list = gth_file_list_get_files (GTH_FILE_LIST (gth_browser_get_file_list (browser)), items);
+	files = gth_file_data_list_to_file_list (file_list);
+	gth_queue_manager_add_files (folder, files, -1);
+
+	_g_object_list_unref (files);
+	_g_object_list_unref (file_list);
+	_gtk_tree_path_list_free (items);
+	g_object_unref (folder);
+	g_free (uri);
+}
+
+
+gpointer
+work_queues__gth_browser_file_list_key_press_cb (GthBrowser  *browser,
+						 GdkEventKey *event)
+{
+	gpointer result = NULL;
+	guint    modifiers;
+
+	modifiers = gtk_accelerator_get_default_mod_mask ();
+	if ((event->state & modifiers) != GDK_MOD1_MASK)
+		return NULL;
+
+	switch (gdk_keyval_to_lower (event->keyval)) {
+	case GDK_KEY_1:
+	case GDK_KEY_2:
+	case GDK_KEY_3:
+		gth_browser_activate_action_add_to_work_queue (browser, gdk_keyval_to_lower (event->keyval) - GDK_KEY_1 + 1);
+		result = GINT_TO_POINTER (1);
+		break;
+	}
+
+	return result;
+}
diff --git a/extensions/work_queues/callbacks.h b/extensions/work_queues/callbacks.h
new file mode 100644
index 0000000..c650ab5
--- /dev/null
+++ b/extensions/work_queues/callbacks.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CALLBACKS_H
+#define CALLBACKS_H
+
+#include <gthumb.h>
+
+gpointer  work_queues__gth_browser_file_list_key_press_cb (GthBrowser  *browser,
+							   GdkEventKey *event);
+
+#endif /* CALLBACKS_H */
diff --git a/extensions/work_queues/gth-file-source-work-queues.c b/extensions/work_queues/gth-file-source-work-queues.c
new file mode 100644
index 0000000..1101784
--- /dev/null
+++ b/extensions/work_queues/gth-file-source-work-queues.c
@@ -0,0 +1,308 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gthumb.h>
+#include "gth-file-source-work-queues.h"
+#include "gth-queue-manager.h"
+
+
+struct _GthFileSourceWorkQueuesPrivate {
+	ListReady  ready_func;
+	gpointer   ready_data;
+};
+
+
+G_DEFINE_TYPE (GthFileSourceWorkQueues, gth_file_source_work_queues, GTH_TYPE_FILE_SOURCE)
+
+
+static GList *
+get_entry_points (GthFileSource *file_source)
+{
+	GList     *list = NULL;
+	GFile     *file;
+	GFileInfo *info;
+
+	file = g_file_new_for_uri ("queue:///");
+	info = gth_file_source_get_file_info (file_source, file, GFILE_BASIC_ATTRIBUTES);
+	list = g_list_append (list, gth_file_data_new (file, info));
+
+	g_object_unref (info);
+	g_object_unref (file);
+
+	return list;
+}
+
+
+static GFile *
+gth_file_source_work_queues_to_gio_file (GthFileSource *file_source,
+					 GFile         *file)
+{
+	return g_file_dup (file);
+}
+
+
+static void
+update_file_info (GthFileSource *file_source,
+		  GFile         *file,
+		  GFileInfo     *info)
+{
+	gth_queue_manager_update_file_info (file, info);
+}
+
+
+static GFileInfo *
+gth_file_source_work_queues_get_file_info (GthFileSource *file_source,
+					   GFile         *file,
+					   const char    *attributes)
+{
+	GFileInfo *file_info;
+
+	file_info = g_file_info_new ();
+	update_file_info (file_source, file, file_info);
+
+	return file_info;
+}
+
+
+static GthFileData *
+gth_file_source_work_queues_get_file_data (GthFileSource *file_source,
+					   GFile         *file,
+					   GFileInfo     *info)
+{
+	GthFileData *file_data = NULL;
+
+	switch (g_file_info_get_file_type (info)) {
+	case G_FILE_TYPE_REGULAR:
+		file_data = gth_file_data_new (file, info);
+		break;
+
+	case G_FILE_TYPE_DIRECTORY:
+		update_file_info (file_source, file, info);
+		file_data = gth_file_data_new (file, info);
+		break;
+
+	default:
+		break;
+	}
+
+	return file_data;
+}
+
+
+static void
+gth_file_source_work_queues_write_metadata (GthFileSource *file_source,
+					    GthFileData   *file_data,
+					    const char    *attributes,
+					    ReadyCallback  callback,
+					    gpointer       user_data)
+{
+	object_ready_with_error (file_source, callback, user_data, NULL);
+}
+
+
+static void
+gth_file_source_work_queues_read_metadata (GthFileSource *file_source,
+					   GthFileData   *file_data,
+					   const char    *attributes,
+					   ReadyCallback  callback,
+					   gpointer       user_data)
+{
+	update_file_info (file_source, file_data->file, file_data->info);
+	object_ready_with_error (file_source, callback, user_data, NULL);
+}
+
+
+static void
+gth_file_source_work_queues_rename (GthFileSource *file_source,
+				    GFile         *file,
+				    const char    *edit_name,
+				    ReadyCallback  callback,
+				    gpointer       user_data)
+{
+	object_ready_with_error (file_source, callback, user_data, NULL);
+}
+
+
+static void
+gth_file_source_work_queues_for_each_child (GthFileSource        *file_source,
+					    GFile                *parent,
+					    gboolean              recursive,
+					    const char           *attributes,
+					    StartDirCallback      start_dir_func,
+					    ForEachChildCallback  for_each_file_func,
+					    ReadyCallback         ready_func,
+					    gpointer              user_data)
+{
+	if (start_dir_func != NULL) {
+		GFileInfo *info;
+		GError    *error = NULL;
+
+		info = gth_file_source_work_queues_get_file_info (file_source, parent, "");
+
+		switch (start_dir_func (parent, info, &error, user_data)) {
+		case DIR_OP_CONTINUE:
+			break;
+		case DIR_OP_SKIP:
+			object_ready_with_error (file_source, ready_func, user_data, NULL);
+			return;
+		case DIR_OP_STOP:
+			object_ready_with_error (file_source, ready_func, user_data, error);
+			g_object_unref (info);
+			return;
+		}
+
+		g_object_unref (info);
+	}
+
+
+	gth_queue_manager_for_each_child (parent,
+					  attributes,
+					  gth_file_source_get_cancellable (file_source),
+					  for_each_file_func,
+					  ready_func,
+					  user_data);
+}
+
+
+static void
+gth_file_source_work_queues_copy (GthFileSource    *file_source,
+				  GthFileData      *destination,
+				  GList            *file_list, /* GFile * list */
+				  gboolean          move,
+				  int               destination_position,
+				  ProgressCallback  progress_callback,
+				  DialogCallback    dialog_callback,
+				  ReadyCallback     ready_callback,
+				  gpointer          user_data)
+{
+	if (gth_queue_manager_add_files (destination->file,
+					 file_list,
+					 destination_position))
+	{
+		gth_monitor_folder_changed (gth_main_get_default_monitor (),
+					    destination->file,
+					    file_list,
+				            GTH_MONITOR_EVENT_CREATED);
+	}
+
+	object_ready_with_error (file_source, ready_callback, user_data, NULL);
+}
+
+
+static gboolean
+gth_file_source_work_queues_can_cut (GthFileSource *file_source,
+				     GFile         *file)
+{
+	return FALSE;
+}
+
+
+static gboolean
+gth_file_source_work_queues_is_reorderable (GthFileSource *file_source)
+{
+	return TRUE;
+}
+
+
+static void
+gth_file_source_work_queues_reorder (GthFileSource *file_source,
+				     GthFileData   *destination,
+				     GList         *visible_files, /* GFile list */
+				     GList         *files_to_move, /* GFile list */
+				     int            dest_pos,
+				     ReadyCallback  callback,
+				     gpointer       data)
+{
+	gth_queue_manager_reorder (destination->file,
+				   visible_files,
+				   files_to_move,
+				   dest_pos);
+	object_ready_with_error (file_source, callback, data, NULL);
+}
+
+
+static void
+gth_file_source_work_queues_remove (GthFileSource *file_source,
+				    GthFileData   *location,
+				    GList         *file_list /* GthFileData list */,
+				    gboolean       permanently,
+				    GtkWindow     *parent)
+{
+	GList *files;
+
+	files = gth_file_data_list_to_file_list (file_list);
+	gth_queue_manager_remove_files (location->file, files);
+
+	_g_object_list_unref (files);
+}
+
+
+static void
+gth_file_source_work_queues_finalize (GObject *object)
+{
+	GthFileSourceWorkQueues *self = GTH_FILE_SOURCE_WORK_QUEUES (object);
+
+	if (self->priv != NULL) {
+		g_free (self->priv);
+		self->priv = NULL;
+	}
+
+	G_OBJECT_CLASS (gth_file_source_work_queues_parent_class)->finalize (object);
+}
+
+
+static void
+gth_file_source_work_queues_class_init (GthFileSourceWorkQueuesClass *class)
+{
+	GObjectClass       *object_class;
+	GthFileSourceClass *file_source_class;
+
+	object_class = (GObjectClass*) class;
+	object_class->finalize = gth_file_source_work_queues_finalize;
+
+	file_source_class = (GthFileSourceClass*) class;
+	file_source_class->get_entry_points = get_entry_points;
+	file_source_class->to_gio_file = gth_file_source_work_queues_to_gio_file;
+	file_source_class->get_file_info = gth_file_source_work_queues_get_file_info;
+	file_source_class->get_file_data = gth_file_source_work_queues_get_file_data;
+	file_source_class->write_metadata = gth_file_source_work_queues_write_metadata;
+	file_source_class->read_metadata = gth_file_source_work_queues_read_metadata;
+	file_source_class->rename = gth_file_source_work_queues_rename;
+	file_source_class->for_each_child = gth_file_source_work_queues_for_each_child;
+	file_source_class->copy = gth_file_source_work_queues_copy;
+	file_source_class->can_cut = gth_file_source_work_queues_can_cut;
+	file_source_class->is_reorderable  = gth_file_source_work_queues_is_reorderable;
+	file_source_class->reorder = gth_file_source_work_queues_reorder;
+	file_source_class->remove = gth_file_source_work_queues_remove;
+}
+
+
+static void
+gth_file_source_work_queues_init (GthFileSourceWorkQueues *self)
+{
+	gth_file_source_add_scheme (GTH_FILE_SOURCE (self), "queue");
+
+	self->priv = g_new0 (GthFileSourceWorkQueuesPrivate, 1);
+}
diff --git a/extensions/work_queues/gth-file-source-work-queues.h b/extensions/work_queues/gth-file-source-work-queues.h
new file mode 100644
index 0000000..15713f1
--- /dev/null
+++ b/extensions/work_queues/gth-file-source-work-queues.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_FILE_SOURCE_WORK_QUEUES_H
+#define GTH_FILE_SOURCE_WORK_QUEUES_H
+
+#include <gthumb.h>
+
+#define GTH_TYPE_FILE_SOURCE_WORK_QUEUES         (gth_file_source_work_queues_get_type ())
+#define GTH_FILE_SOURCE_WORK_QUEUES(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_FILE_SOURCE_WORK_QUEUES, GthFileSourceWorkQueues))
+#define GTH_FILE_SOURCE_WORK_QUEUES_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_FILE_SOURCE_WORK_QUEUES, GthFileSourceWorkQueuesClass))
+#define GTH_IS_FILE_SOURCE_WORK_QUEUES(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_FILE_SOURCE_WORK_QUEUES))
+#define GTH_IS_FILE_SOURCE_WORK_QUEUES_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_FILE_SOURCE_WORK_QUEUES))
+#define GTH_FILE_SOURCE_WORK_QUEUES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_FILE_SOURCE_WORK_QUEUES, GthFileSourceWorkQueuesClass))
+
+typedef struct _GthFileSourceWorkQueues         GthFileSourceWorkQueues;
+typedef struct _GthFileSourceWorkQueuesPrivate  GthFileSourceWorkQueuesPrivate;
+typedef struct _GthFileSourceWorkQueuesClass    GthFileSourceWorkQueuesClass;
+
+struct _GthFileSourceWorkQueues
+{
+	GthFileSource __parent;
+	GthFileSourceWorkQueuesPrivate *priv;
+};
+
+struct _GthFileSourceWorkQueuesClass
+{
+	GthFileSourceClass __parent_class;
+};
+
+GType gth_file_source_work_queues_get_type (void) G_GNUC_CONST;
+
+#endif /* GTH_FILE_SOURCE_WORK_QUEUES_H */
diff --git a/extensions/work_queues/gth-queue-manager.c b/extensions/work_queues/gth-queue-manager.c
new file mode 100644
index 0000000..d8ad465
--- /dev/null
+++ b/extensions/work_queues/gth-queue-manager.c
@@ -0,0 +1,416 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "gth-queue-manager.h"
+
+
+#define N_QUEUES 3
+
+
+struct _GthQueueManagerPrivate {
+	GList  *files[N_QUEUES];
+	GMutex *mutex;
+};
+
+
+G_DEFINE_TYPE (GthQueueManager,
+	       gth_queue_manager,
+	       G_TYPE_OBJECT)
+
+
+static GthQueueManager *the_manager = NULL;
+
+
+static GObject *
+gth_queue_manager_constructor (GType                  type,
+			       guint                  n_construct_params,
+			       GObjectConstructParam *construct_params)
+{
+	static GObject *object = NULL;
+
+	if (the_manager == NULL) {
+		object = G_OBJECT_CLASS (gth_queue_manager_parent_class)->constructor (type, n_construct_params, construct_params);
+		the_manager = GTH_QUEUE_MANAGER (object);
+	}
+	else
+		object =  G_OBJECT (the_manager);
+
+	return object;
+}
+
+
+static void
+gth_queue_manager_finalize (GObject *object)
+{
+	GthQueueManager *self;
+	int              i;
+
+	self = GTH_QUEUE_MANAGER (object);
+
+	for (i = 0; i < N_QUEUES; i++)
+		_g_object_list_unref (self->priv->files[i]);
+	g_mutex_free (self->priv->mutex);
+
+	G_OBJECT_CLASS (gth_queue_manager_parent_class)->finalize (object);
+}
+
+
+static void
+gth_queue_manager_class_init (GthQueueManagerClass *klass)
+{
+	GObjectClass *object_class;
+
+	g_type_class_add_private (klass, sizeof (GthQueueManagerPrivate));
+
+	object_class = (GObjectClass*) klass;
+	object_class->constructor = gth_queue_manager_constructor;
+	object_class->finalize = gth_queue_manager_finalize;
+}
+
+static void
+gth_queue_manager_init (GthQueueManager *self)
+{
+	int i;
+
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_QUEUE_MANAGER, GthQueueManagerPrivate);
+	self->priv->mutex = g_mutex_new ();
+	for (i = 0; i < N_QUEUES; i++)
+		self->priv->files[i] = NULL;
+}
+
+
+static GthQueueManager *
+gth_queue_manager_get_default (void)
+{
+	return (GthQueueManager*) g_object_new (GTH_TYPE_QUEUE_MANAGER, NULL);
+}
+
+
+/* -- gth_queue_manager_for_each_child -- */
+
+
+typedef struct {
+	GthQueueManager      *queue_manager;
+	GList                *files;
+	GList                *current_file;
+	char                 *attributes;
+	GCancellable         *cancellable;
+	ForEachChildCallback  for_each_file_func;
+	ReadyCallback         ready_callback;
+	gpointer              user_data;
+} ForEachChildData;
+
+
+static void
+fec_data_free (ForEachChildData *data)
+{
+	_g_object_list_unref (data->files);
+	g_free (data->attributes);
+	_g_object_unref (data->cancellable);
+	g_free (data);
+}
+
+
+static void
+queue_manager_fec_done (ForEachChildData *data,
+			GError           *error)
+{
+	if (data->ready_callback != NULL)
+		data->ready_callback (NULL, error, data->user_data);
+	fec_data_free (data);
+}
+
+
+static void
+fec__file_info_ready_cb (GObject      *source_object,
+			 GAsyncResult *result,
+			 gpointer      user_data)
+{
+	ForEachChildData *data = user_data;
+	GFile            *file;
+	GFileInfo        *info;
+
+	file = (GFile*) source_object;
+	info = g_file_query_info_finish (file, result, NULL);
+	if (info != NULL) {
+		if (data->for_each_file_func != NULL)
+			data->for_each_file_func (file, info, data->user_data);
+		g_object_unref (info);
+	}
+
+	data->current_file = data->current_file->next;
+	if (data->current_file == NULL) {
+		queue_manager_fec_done (data, NULL);
+		return;
+	}
+
+	g_file_query_info_async ((GFile *) data->current_file->data,
+				 data->attributes,
+				 0,
+				 G_PRIORITY_DEFAULT,
+				 data->cancellable,
+				 fec__file_info_ready_cb,
+				 data);
+
+}
+
+
+static void
+queue_manager_fec_done_cb (GObject  *object,
+			   GError   *error,
+			   gpointer  user_data)
+{
+	queue_manager_fec_done (user_data, NULL);
+}
+
+
+static int
+_g_file_get_n_queue (GFile *file)
+{
+	char *uri;
+	int   n = -1;
+
+	uri = g_file_get_uri (file);
+	if (! g_str_has_prefix (uri, "queue:///"))
+		n = -1;
+	else if (strcmp (uri, "queue:///") == 0)
+		n = 0;
+	else
+		n = atoi (uri + strlen ("queue:///"));
+
+	g_free (uri);
+
+	return n;
+}
+
+
+void
+gth_queue_manager_update_file_info (GFile     *file,
+				    GFileInfo *info)
+{
+	int   n_queue;
+	char *display_name;
+
+	n_queue = _g_file_get_n_queue (file);
+
+	g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+	g_file_info_set_content_type (info, "gthumb/queue");
+	g_file_info_set_icon (info, g_themed_icon_new ("work-queue"));
+	g_file_info_set_sort_order (info, n_queue);
+	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
+	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, FALSE);
+	if (n_queue > 0) {
+		g_file_info_set_attribute_boolean (info, "gthumb::no-child", TRUE);
+		display_name = g_strdup_printf (_("Queue %d"), n_queue);
+	}
+	else if (n_queue == 0)
+		display_name = g_strdup (_("Work Queues"));
+	else
+		display_name = g_strdup ("???");
+	g_file_info_set_display_name (info, display_name);
+
+	g_free (display_name);
+}
+
+
+static void
+_gth_queue_manager_for_each_queue (gpointer user_data)
+{
+	ForEachChildData *data = user_data;
+	int               i;
+
+	for (i = 0; i < N_QUEUES; i++) {
+		char      *uri;
+		GFile     *file;
+		GFileInfo *info;
+
+		uri = g_strdup_printf ("queue:///%d", i + 1);
+		file = g_file_new_for_uri (uri);
+		info = g_file_info_new ();
+		gth_queue_manager_update_file_info (file, info);
+		data->for_each_file_func (file, info, data->user_data);
+
+		g_object_unref (info);
+		g_object_unref (file);
+		g_free (uri);
+	}
+
+	object_ready_with_error (data->queue_manager,
+				 data->ready_callback,
+				 data->user_data,
+				 NULL);
+	fec_data_free (data);
+}
+
+
+void
+gth_queue_manager_for_each_child (GFile                *folder,
+				  const char           *attributes,
+				  GCancellable         *cancellable,
+				  ForEachChildCallback  for_each_file_func,
+				  ReadyCallback         ready_callback,
+				  gpointer              user_data)
+{
+	GthQueueManager  *self;
+	int               n_queue;
+	ForEachChildData *data;
+
+	self = gth_queue_manager_get_default ();
+	n_queue = _g_file_get_n_queue (folder);
+
+	g_mutex_lock (self->priv->mutex);
+	data = g_new0 (ForEachChildData, 1);
+	data->queue_manager = self;
+	if (n_queue > 0)
+		data->files = _g_object_list_ref (self->priv->files[n_queue - 1]);
+	data->current_file = data->files;
+	data->attributes = g_strdup (attributes);
+	data->cancellable = _g_object_ref(cancellable);
+	data->for_each_file_func = for_each_file_func;
+	data->ready_callback = ready_callback;
+	data->user_data = user_data;
+	g_mutex_unlock (self->priv->mutex);
+
+	if (n_queue == 0) {
+		call_when_idle (_gth_queue_manager_for_each_queue, data);
+	}
+	else if (data->current_file != NULL)
+		g_file_query_info_async ((GFile *) data->current_file->data,
+					 data->attributes,
+					 0,
+					 G_PRIORITY_DEFAULT,
+					 data->cancellable,
+					 fec__file_info_ready_cb,
+					 data);
+	else
+		object_ready_with_error (NULL, queue_manager_fec_done_cb, data, NULL);
+}
+
+
+gboolean
+gth_queue_manager_add_files (GFile *folder,
+			     GList *file_list, /* GFile list */
+			     int    destination_position)
+{
+	GthQueueManager *self;
+	int              n_queue;
+	GList           *new_list;
+	GList           *link;
+
+	if (! g_file_has_uri_scheme (folder, "queue"))
+		return FALSE;
+
+	self = gth_queue_manager_get_default ();
+	n_queue = _g_file_get_n_queue (folder);
+	if (n_queue <= 0)
+		return FALSE;
+
+	g_mutex_lock (self->priv->mutex);
+
+	new_list = _g_file_list_dup (file_list);
+	link = g_list_nth (self->priv->files[n_queue - 1], destination_position);
+	if (link != NULL) {
+		GList *last_new;
+
+		/* insert 'new_list' before 'link' */
+
+		if (link->prev != NULL)
+			link->prev->next = new_list;
+		new_list->prev = link->prev;
+
+		last_new = g_list_last (new_list);
+		last_new->next = link;
+		link->prev = last_new;
+	}
+	else
+		self->priv->files[n_queue - 1] = g_list_concat (self->priv->files[n_queue - 1], new_list);
+
+	gth_monitor_folder_changed (gth_main_get_default_monitor (),
+				    folder,
+				    file_list,
+				    GTH_MONITOR_EVENT_CREATED);
+
+	g_mutex_unlock (self->priv->mutex);
+
+	return TRUE;
+}
+
+
+void
+gth_queue_manager_remove_files (GFile *folder,
+				GList *file_list)
+{
+	GthQueueManager *self;
+	int              n_queue;
+	GHashTable      *files_to_remove;
+	GList           *scan;
+	GList           *new_list;
+
+	self = gth_queue_manager_get_default ();
+	n_queue = _g_file_get_n_queue (folder);
+	if (n_queue <= 0)
+		return;
+
+	g_mutex_lock (self->priv->mutex);
+
+	files_to_remove = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
+	for (scan = file_list; scan; scan = scan->next)
+		g_hash_table_insert (files_to_remove, scan->data, GINT_TO_POINTER (1));
+
+	new_list = NULL;
+	for (scan = self->priv->files[n_queue - 1]; scan; scan = scan->next) {
+		GFile *file = scan->data;
+
+		if (g_hash_table_lookup (files_to_remove, file))
+			continue;
+
+		new_list = g_list_prepend (new_list, g_object_ref (file));
+	}
+	new_list = g_list_reverse (new_list);
+
+	g_hash_table_unref (files_to_remove);
+
+	_g_object_list_unref (self->priv->files[n_queue - 1]);
+	self->priv->files[n_queue - 1] = new_list;
+
+	gth_monitor_folder_changed (gth_main_get_default_monitor (),
+				    folder,
+				    file_list,
+				    GTH_MONITOR_EVENT_REMOVED);
+
+	g_mutex_unlock (self->priv->mutex);
+}
+
+
+void
+gth_queue_manager_reorder (GFile *folder,
+			   GList *visible_files, /* GFile list */
+			   GList *files_to_move, /* GFile list */
+			   int    dest_pos)
+{
+	/* FIXME */
+}
diff --git a/extensions/work_queues/gth-queue-manager.h b/extensions/work_queues/gth-queue-manager.h
new file mode 100644
index 0000000..2af79a7
--- /dev/null
+++ b/extensions/work_queues/gth-queue-manager.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_QUEUE_MANAGER_H
+#define GTH_QUEUE_MANAGER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_QUEUE_MANAGER         (gth_queue_manager_get_type ())
+#define GTH_QUEUE_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_QUEUE_MANAGER, GthQueueManager))
+#define GTH_QUEUE_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_QUEUE_MANAGER, GthQueueManagerClass))
+#define GTH_IS_QUEUE_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_QUEUE_MANAGER))
+#define GTH_IS_QUEUE_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_QUEUE_MANAGER))
+#define GTH_QUEUE_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_QUEUE_MANAGER, GthQueueManagerClass))
+
+typedef struct _GthQueueManager         GthQueueManager;
+typedef struct _GthQueueManagerPrivate  GthQueueManagerPrivate;
+typedef struct _GthQueueManagerClass    GthQueueManagerClass;
+
+struct _GthQueueManager {
+	GObject __parent;
+	GthQueueManagerPrivate *priv;
+};
+
+struct _GthQueueManagerClass {
+	GObjectClass __parent_class;
+};
+
+GType    gth_queue_manager_get_type         (void) G_GNUC_CONST;
+
+void     gth_queue_manager_for_each_child   (GFile                *folder,
+					     const char           *attributes,
+					     GCancellable         *cancellable,
+					     ForEachChildCallback  for_each_file_func,
+					     ReadyCallback         ready_callback,
+					     gpointer              user_data);
+gboolean gth_queue_manager_add_files        (GFile                *folder,
+					     GList                *file_list, /* GFile list */
+					     int                   destination_position);
+void     gth_queue_manager_remove_files     (GFile                *folder,
+		    	    	    	     GList                *file_list);
+void     gth_queue_manager_reorder          (GFile                *folder,
+					     GList                *visible_files, /* GFile list */
+					     GList                *files_to_move, /* GFile list */
+					     int                   dest_pos);
+void     gth_queue_manager_update_file_info (GFile                *file,
+				    	     GFileInfo            *info);
+
+G_END_DECLS
+
+#endif /* GTH_QUEUE_MANAGER_H */
+
diff --git a/extensions/work_queues/main.c b/extensions/work_queues/main.c
new file mode 100644
index 0000000..9185a5c
--- /dev/null
+++ b/extensions/work_queues/main.c
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gthumb.h>
+#include "callbacks.h"
+#include "gth-file-source-work-queues.h"
+
+
+G_MODULE_EXPORT void
+gthumb_extension_activate (void)
+{
+	gth_main_register_file_source (GTH_TYPE_FILE_SOURCE_WORK_QUEUES);
+	gth_hook_add_callback ("gth-browser-file-list-key-press", 10, G_CALLBACK (work_queues__gth_browser_file_list_key_press_cb), NULL);
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_deactivate (void)
+{
+}
+
+
+G_MODULE_EXPORT gboolean
+gthumb_extension_is_configurable (void)
+{
+	return FALSE;
+}
+
+
+G_MODULE_EXPORT void
+gthumb_extension_configure (GtkWindow *parent)
+{
+}
diff --git a/extensions/work_queues/work_queues.extension.in.in b/extensions/work_queues/work_queues.extension.in.in
new file mode 100644
index 0000000..e94a2ac
--- /dev/null
+++ b/extensions/work_queues/work_queues.extension.in.in
@@ -0,0 +1,12 @@
+[Extension]
+_Name=Work Queues
+_Description=Advanced file selection.
+_Authors=gthumb development team
+Copyright=Copyright  2008-2012 The Free Software Foundation, Inc.
+Version=%VERSION%
+URL=http://live.gnome.org/gthumb
+Category=Browser
+
+[Loader]
+Type=module
+File=%LIBRARY%
diff --git a/gthumb/gth-main.c b/gthumb/gth-main.c
index a505256..0b11f3a 100644
--- a/gthumb/gth-main.c
+++ b/gthumb/gth-main.c
@@ -1206,6 +1206,7 @@ gth_main_activate_extensions (void)
 						"search",
 						"slideshow",
 						"webalbums",
+						"work_queues",
 						NULL };
 	int                   i;
 	GError               *error = NULL;



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