[gthumb: 2/4] [change_date] added the change_date task
- From: Paolo Bacchilega <paobac src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gthumb: 2/4] [change_date] added the change_date task
- Date: Sat, 6 Feb 2010 17:05:25 +0000 (UTC)
commit e49a52df8f0afbf32f7d95af3f11edace1e08103
Author: Paolo Bacchilega <paobac src gnome org>
Date: Fri Feb 5 20:26:30 2010 +0100
[change_date] added the change_date task
extensions/change_date/Makefile.am | 2 +
extensions/change_date/data/ui/change-date.ui | 260 ++++++++++++++++++-
extensions/change_date/dlg-change-date.c | 167 ++++++++++++-
extensions/change_date/gth-change-date-task.c | 348 +++++++++++++++++++++++++
extensions/change_date/gth-change-date-task.h | 76 ++++++
gthumb/gio-utils.c | 19 ++
gthumb/gio-utils.h | 4 +
gthumb/glib-utils.c | 21 ++
gthumb/glib-utils.h | 5 +
gthumb/gth-browser.c | 3 +-
gthumb/gth-file-data.c | 10 +
gthumb/gth-file-data.h | 1 +
gthumb/gth-time.c | 29 ++
gthumb/gth-time.h | 4 +
14 files changed, 941 insertions(+), 8 deletions(-)
---
diff --git a/extensions/change_date/Makefile.am b/extensions/change_date/Makefile.am
index d3daed7..9fb44b4 100644
--- a/extensions/change_date/Makefile.am
+++ b/extensions/change_date/Makefile.am
@@ -10,6 +10,8 @@ libchange_date_la_SOURCES = \
callbacks.h \
dlg-change-date.c \
dlg-change-date.h \
+ gth-change-date-task.c \
+ gth-change-date-task.h \
main.c
libchange_date_la_CFLAGS = $(GTHUMB_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
diff --git a/extensions/change_date/data/ui/change-date.ui b/extensions/change_date/data/ui/change-date.ui
index 36a7582..4741c15 100644
--- a/extensions/change_date/data/ui/change-date.ui
+++ b/extensions/change_date/data/ui/change-date.ui
@@ -12,7 +12,7 @@
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
- <property name="spacing">2</property>
+ <property name="spacing">6</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
@@ -43,7 +43,86 @@
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="vbox57">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="change_last_modified_checkbutton">
+ <property name="label" translatable="yes">_Last modified date</property>
+ <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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="change_comment_checkbutton">
+ <property name="label" translatable="yes">Co_mment date</property>
+ <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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="change_datetime_checkbutton">
+ <property name="label" translatable="yes">Exif DateTime tag</property>
+ <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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="change_datetimeoriginal_checkbutton">
+ <property name="label" translatable="yes">Exif DateTimeOriginal tag</property>
+ <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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="change_datetimedigitized_checkbutton">
+ <property name="label" translatable="yes">Exif DateTimeDigitized tag</property>
+ <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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
</child>
</object>
<packing>
@@ -79,7 +158,176 @@
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="vbox48">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="vbox49">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="to_following_date_radiobutton">
+ <property name="label" translatable="yes">The _following date:</property>
+ <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="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkHBox" id="date_selector_box">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="to_last_modified_date_radiobutton">
+ <property name="label" translatable="yes">File _modified date</property>
+ <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="group">to_following_date_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="to_creation_date_radiobutton">
+ <property name="label" translatable="yes">File c_reation date</property>
+ <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="group">to_following_date_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="to_photo_original_date_radiobutton">
+ <property name="label" translatable="yes">Date p_hoto was taken</property>
+ <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="group">to_following_date_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox54">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkHBox" id="hbox71">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="adjust_timezone_radiobutton">
+ <property name="label" translatable="yes">A_djust by</property>
+ <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="group">to_following_date_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="timezone_box">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSpinButton" id="adjust_timezone_spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="adjustment">timezone_adjustment</property>
+ <property name="climb_rate">1</property>
+ <property name="numeric">True</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label102">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">hours</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
</child>
</object>
<packing>
@@ -158,4 +406,10 @@
<action-widget response="0">ok_button</action-widget>
</action-widgets>
</object>
+ <object class="GtkAdjustment" id="timezone_adjustment">
+ <property name="lower">-23</property>
+ <property name="upper">23</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
</interface>
diff --git a/extensions/change_date/dlg-change-date.c b/extensions/change_date/dlg-change-date.c
index cc35bfe..6f6a698 100644
--- a/extensions/change_date/dlg-change-date.c
+++ b/extensions/change_date/dlg-change-date.c
@@ -3,7 +3,7 @@
/*
* GThumb
*
- * Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ * Copyright (C) 2001-2010 The 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
@@ -23,12 +23,18 @@
#include <config.h>
#include <gtk/gtk.h>
#include <gthumb.h>
+#include "gth-change-date-task.h"
+
+
+#define GET_WIDGET(x) (_gtk_builder_get_widget (data->builder, (x)))
+#define IS_ACTIVE(x) (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (x)))
typedef struct {
GthBrowser *browser;
GtkBuilder *builder;
GtkWidget *dialog;
+ GtkWidget *date_selector;
GList *file_list;
} DialogData;
@@ -43,11 +49,104 @@ dialog_destroy_cb (GtkWidget *widget,
}
+static void
+ok_button_clicked (GtkWidget *button,
+ DialogData *data)
+{
+ GthChangeFields change_fields;
+ GthChangeType change_type;
+ GthDateTime *date_time;
+ int time_adjustment;
+ GthTask *task;
+
+ date_time = NULL;
+
+ change_fields = 0;
+ if (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton")))
+ change_fields |= GTH_CHANGE_LAST_MODIFIED_DATE;
+ if (IS_ACTIVE (GET_WIDGET ("change_comment_checkbutton")))
+ change_fields |= GTH_CHANGE_COMMENT_DATE;
+ if (IS_ACTIVE (GET_WIDGET ("change_datetime_checkbutton")))
+ change_fields |= GTH_CHANGE_EXIF_DATETIME_TAG;
+ if (IS_ACTIVE (GET_WIDGET ("change_datetimeoriginal_checkbutton")))
+ change_fields |= GTH_CHANGE_EXIF_DATETIMEORIGINAL_TAG;
+ if (IS_ACTIVE (GET_WIDGET ("change_datetimedigitized_checkbutton")))
+ change_fields |= GTH_CHANGE_EXIF_DATETIMEDIGITIZED_TAG;
+
+ if (IS_ACTIVE (GET_WIDGET ("to_following_date_radiobutton"))) {
+ change_type = GTH_CHANGE_TO_FOLLOWING_DATE;
+ date_time = gth_datetime_new ();
+ gth_time_selector_get_value (GTH_TIME_SELECTOR (data->date_selector), date_time);
+ }
+ else if (IS_ACTIVE (GET_WIDGET ("to_last_modified_date_radiobutton")))
+ change_type = GTH_CHANGE_TO_FILE_MODIFIED_DATE;
+ else if (IS_ACTIVE (GET_WIDGET ("to_creation_date_radiobutton")))
+ change_type = GTH_CHANGE_TO_FILE_CREATION_DATE;
+ else if (IS_ACTIVE (GET_WIDGET ("to_photo_original_date_radiobutton")))
+ change_type = GTH_CHANGE_TO_PHOTO_ORIGINAL_DATE;
+ else if (IS_ACTIVE (GET_WIDGET ("adjust_timezone_radiobutton"))) {
+ change_type = GTH_CHANGE_ADJUST_TIMEZONE;
+ time_adjustment = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_timezone_spinbutton")));
+ }
+
+ task = gth_change_date_task_new (data->file_list,
+ change_fields,
+ change_type,
+ date_time,
+ time_adjustment);
+ gth_browser_exec_task (data->browser, task, FALSE);
+ gtk_widget_destroy (data->dialog);
+
+ g_object_unref (task);
+ gth_datetime_free (date_time);
+}
+
+
+static void
+help_button_cb (GtkWidget *widget,
+ DialogData *data)
+{
+ show_help_dialog (GTK_WINDOW (data->dialog), "gthumb-change-date");
+}
+
+
+static void
+update_sensitivity (DialogData *data)
+{
+ gtk_widget_set_sensitive (GET_WIDGET ("ok_button"),
+ (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton"))
+ || IS_ACTIVE (GET_WIDGET ("change_comment_checkbutton"))
+ || IS_ACTIVE (GET_WIDGET ("change_datetime_checkbutton"))
+ || IS_ACTIVE (GET_WIDGET ("change_datetimeoriginal_checkbutton"))
+ || IS_ACTIVE (GET_WIDGET ("change_datetimedigitized_checkbutton"))));
+ gtk_widget_set_sensitive (data->date_selector, IS_ACTIVE (GET_WIDGET ("to_following_date_radiobutton")));
+ gtk_widget_set_sensitive (GET_WIDGET ("timezone_box"), IS_ACTIVE (GET_WIDGET ("adjust_timezone_radiobutton")));
+
+ if (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton"))) {
+ gtk_widget_set_sensitive (GET_WIDGET ("to_last_modified_date_radiobutton"), FALSE);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_last_modified_date_radiobutton"))))
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_following_date_radiobutton")), TRUE);
+ }
+ else
+ gtk_widget_set_sensitive (GET_WIDGET ("to_last_modified_date_radiobutton"), TRUE);
+}
+
+
+static void
+radio_button_clicked (GtkWidget *button,
+ DialogData *data)
+{
+ update_sensitivity (data);
+}
+
+
void
dlg_change_date (GthBrowser *browser,
GList *file_list)
{
- DialogData *data;
+ DialogData *data;
+ GTimeVal timeval;
+ GthDateTime *datetime;
data = g_new0 (DialogData, 1);
data->browser = browser;
@@ -56,20 +155,80 @@ dlg_change_date (GthBrowser *browser,
/* Get the widgets. */
- data->dialog = _gtk_builder_get_widget (data->builder, "change_date_dialog");
+ data->dialog = GET_WIDGET ("change_date_dialog");
+ data->date_selector = gth_time_selector_new ();
+
+ datetime = gth_datetime_new ();
+ g_get_current_time (&timeval);
+ gth_datetime_from_timeval (datetime, &timeval);
+ gth_time_selector_set_value (GTH_TIME_SELECTOR (data->date_selector), datetime);
+ gtk_widget_show (data->date_selector);
+ gtk_box_pack_start (GTK_BOX (GET_WIDGET ("date_selector_box")), data->date_selector, TRUE, TRUE, 0);
+ gth_datetime_free (datetime);
+
/* Set widgets data. */
+ update_sensitivity (data);
+
/* Set the signals handlers. */
g_signal_connect (G_OBJECT (data->dialog),
"destroy",
G_CALLBACK (dialog_destroy_cb),
data);
- g_signal_connect_swapped (_gtk_builder_get_widget (data->builder, "close_button"),
+ g_signal_connect_swapped (GET_WIDGET ("close_button"),
"clicked",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (data->dialog));
+ g_signal_connect (GET_WIDGET ("ok_button"),
+ "clicked",
+ G_CALLBACK (ok_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("help_button"),
+ "clicked",
+ G_CALLBACK (help_button_cb),
+ data);
+ g_signal_connect (GET_WIDGET ("change_last_modified_checkbutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("change_comment_checkbutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("change_datetime_checkbutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("change_datetimeoriginal_checkbutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("change_datetimedigitized_checkbutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("to_following_date_radiobutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("to_last_modified_date_radiobutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("to_creation_date_radiobutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("to_photo_original_date_radiobutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
+ g_signal_connect (GET_WIDGET ("adjust_timezone_radiobutton"),
+ "clicked",
+ G_CALLBACK (radio_button_clicked),
+ data);
/* run dialog. */
diff --git a/extensions/change_date/gth-change-date-task.c b/extensions/change_date/gth-change-date-task.c
new file mode 100644
index 0000000..5ad93fd
--- /dev/null
+++ b/extensions/change_date/gth-change-date-task.c
@@ -0,0 +1,348 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2010 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "gth-change-date-task.h"
+
+
+struct _GthChangeDateTaskPrivate {
+ GList *files; /* GFile */
+ GList *file_list; /* GthFileData */
+ GthChangeFields fields;
+ GthChangeType change_type;
+ GthDateTime *date_time;
+ int timezone_offset;
+ int n_files;
+ int n_current;
+ GList *current;
+};
+
+
+static gpointer parent_class = NULL;
+
+
+static void
+gth_change_date_task_finalize (GObject *object)
+{
+ GthChangeDateTask *self;
+
+ self = GTH_CHANGE_DATE_TASK (object);
+
+ _g_object_list_unref (self->priv->file_list);
+ _g_object_list_unref (self->priv->files);
+ gth_datetime_free (self->priv->date_time);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+set_date_from_change_type (GthChangeDateTask *self,
+ GthFileData *file_data,
+ GthDateTime *date_time)
+{
+ if (self->priv->change_type == GTH_CHANGE_TO_FOLLOWING_DATE) {
+ gth_datetime_copy (self->priv->date_time, date_time);
+ }
+ else if (self->priv->change_type == GTH_CHANGE_TO_FILE_MODIFIED_DATE) {
+ gth_datetime_from_timeval (date_time, gth_file_data_get_modification_time (file_data));
+ }
+ else if (self->priv->change_type == GTH_CHANGE_TO_FILE_CREATION_DATE) {
+ gth_datetime_from_timeval (date_time, gth_file_data_get_creation_time (file_data));
+ }
+ else if (self->priv->change_type == GTH_CHANGE_TO_PHOTO_ORIGINAL_DATE) {
+ GTimeVal time_val;
+
+ if (gth_file_data_get_digitalization_time (file_data, &time_val))
+ gth_datetime_from_timeval (date_time, &time_val);
+ }
+}
+
+
+static void
+update_modification_time (GthChangeDateTask *self)
+{
+ GthDateTime *date_time;
+ GList *scan;
+ GError *error = NULL;
+
+ if ((self->priv->fields & GTH_CHANGE_LAST_MODIFIED_DATE) == 0) {
+ gth_task_completed (GTH_TASK (self), NULL);
+ return;
+ }
+
+ date_time = gth_datetime_new ();
+ for (scan = self->priv->file_list; scan; scan = scan->next) {
+ GthFileData *file_data = scan->data;
+ GTimeVal timeval;
+
+ gth_datetime_clear (date_time);
+ set_date_from_change_type (self, file_data, date_time);
+ if (! gth_datetime_valid (date_time))
+ continue;
+
+ if (gth_datetime_to_timeval (date_time, &timeval)) {
+ if (! _g_file_set_modification_time (file_data->file,
+ &timeval,
+ gth_task_get_cancellable (GTH_TASK (self)),
+ &error))
+ {
+ break;
+ }
+ }
+ }
+ gth_task_completed (GTH_TASK (self), error);
+
+ gth_datetime_free (date_time);
+}
+
+
+static void
+write_metadata_reasy_cb (GError *error,
+ gpointer user_data)
+{
+ GthChangeDateTask *self = user_data;
+
+ if (error != NULL) {
+ gth_task_completed (GTH_TASK (self), error);
+ return;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (gth_task_get_cancellable (GTH_TASK (self)), &error)) {
+ gth_task_completed (GTH_TASK (self), error);
+ return;
+ }
+
+ update_modification_time (self);
+}
+
+
+static void
+info_ready_cb (GList *files,
+ GError *error,
+ gpointer user_data)
+{
+ GthChangeDateTask *self = user_data;
+ GthDateTime *date_time;
+ GList *scan;
+ GPtrArray *attribute_v;
+
+ if (error != NULL) {
+ gth_task_completed (GTH_TASK (self), error);
+ return;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (gth_task_get_cancellable (GTH_TASK (self)), &error)) {
+ gth_task_completed (GTH_TASK (self), error);
+ return;
+ }
+
+ date_time = gth_datetime_new ();
+ self->priv->file_list = _g_object_list_ref (files);
+ for (scan = self->priv->file_list; scan; scan = scan->next) {
+ GthFileData *file_data = scan->data;
+ char *raw;
+ char *formatted;
+
+ if (self->priv->change_type == GTH_CHANGE_ADJUST_TIMEZONE) {
+ /* FIXME */
+ return;
+ }
+
+ gth_datetime_clear (date_time);
+ set_date_from_change_type (self, file_data, date_time);
+ if (! gth_datetime_valid (date_time))
+ continue;
+
+ raw = gth_datetime_to_exif_date (date_time);
+ formatted = gth_datetime_strftime (date_time, "%x");
+ if (self->priv->fields & GTH_CHANGE_COMMENT_DATE) {
+ GObject *metadata;
+
+ metadata = (GObject *) gth_metadata_new ();
+ g_object_set (metadata,
+ "id", "general::datetime",
+ "raw", raw,
+ "formatted", formatted,
+ NULL);
+ g_file_info_set_attribute_object (file_data->info, "general::datetime", metadata);
+ g_object_unref (metadata);
+ }
+ else if (self->priv->fields & GTH_CHANGE_EXIF_DATETIME_TAG) {
+ GObject *metadata;
+
+ metadata = (GObject *) gth_metadata_new ();
+ g_object_set (metadata,
+ "id", "Exif::Image::DateTime",
+ "raw", raw,
+ "formatted", formatted,
+ NULL);
+ g_file_info_set_attribute_object (file_data->info, "Exif::Image::DateTime", metadata);
+
+ g_object_unref (metadata);
+ }
+ else if (self->priv->fields & GTH_CHANGE_EXIF_DATETIMEORIGINAL_TAG) {
+ GObject *metadata;
+
+ metadata = (GObject *) gth_metadata_new ();
+ g_object_set (metadata,
+ "id", "Exif::Photo::DateTimeOriginal",
+ "raw", raw,
+ "formatted", formatted,
+ NULL);
+ g_file_info_set_attribute_object (file_data->info, "Exif::Photo::DateTimeOriginal", metadata);
+
+ g_object_unref (metadata);
+ }
+ else if (self->priv->fields & GTH_CHANGE_EXIF_DATETIMEDIGITIZED_TAG) {
+ GObject *metadata;
+
+ metadata = (GObject *) gth_metadata_new ();
+ g_object_set (metadata,
+ "id", "Exif::Photo::DateTimeDigitized",
+ "raw", raw,
+ "formatted", formatted,
+ NULL);
+ g_file_info_set_attribute_object (file_data->info, "Exif::Photo::DateTimeDigitized", metadata);
+
+ g_object_unref (metadata);
+ }
+
+ g_free (formatted);
+ g_free (raw);
+ }
+
+ attribute_v = g_ptr_array_new ();
+ if (self->priv->fields & GTH_CHANGE_COMMENT_DATE)
+ g_ptr_array_add (attribute_v, "general::datetime");
+ if (self->priv->fields & GTH_CHANGE_EXIF_DATETIME_TAG)
+ g_ptr_array_add (attribute_v, "Exif::Image::DateTime");
+ if (self->priv->fields & GTH_CHANGE_EXIF_DATETIMEORIGINAL_TAG)
+ g_ptr_array_add (attribute_v, "Exif::Photo::DateTimeOriginal");
+ if (self->priv->fields & GTH_CHANGE_EXIF_DATETIMEDIGITIZED_TAG)
+ g_ptr_array_add (attribute_v, "Exif::Photo::DateTimeDigitized");
+ if (attribute_v->len > 0) {
+ char *attributes;
+
+ attributes = _g_string_array_join (attribute_v, ",");
+ _g_write_metadata_async (self->priv->file_list,
+ attributes,
+ gth_task_get_cancellable (GTH_TASK (self)),
+ write_metadata_reasy_cb,
+ self);
+
+ g_free (attributes);
+ }
+ else
+ update_modification_time (self);
+
+ g_ptr_array_free (attribute_v, TRUE);
+ gth_datetime_free (date_time);
+}
+
+
+static void
+gth_change_date_task_exec (GthTask *task)
+{
+ GthChangeDateTask *self = GTH_CHANGE_DATE_TASK (task);
+
+ _g_query_all_metadata_async (self->priv->files,
+ FALSE,
+ TRUE,
+ "*",
+ gth_task_get_cancellable (task),
+ info_ready_cb,
+ self);
+}
+
+
+static void
+gth_change_date_task_class_init (GthChangeDateTaskClass *klass)
+{
+ GObjectClass *object_class;
+ GthTaskClass *task_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (GthChangeDateTaskPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gth_change_date_task_finalize;
+
+ task_class = GTH_TASK_CLASS (klass);
+ task_class->exec = gth_change_date_task_exec;
+}
+
+
+static void
+gth_change_date_task_init (GthChangeDateTask *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_CHANGE_DATE_TASK, GthChangeDateTaskPrivate);
+ self->priv->date_time = gth_datetime_new ();
+}
+
+
+GType
+gth_change_date_task_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type) {
+ GTypeInfo type_info = {
+ sizeof (GthChangeDateTaskClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gth_change_date_task_class_init,
+ NULL,
+ NULL,
+ sizeof (GthChangeDateTask),
+ 0,
+ (GInstanceInitFunc) gth_change_date_task_init
+ };
+
+ type = g_type_register_static (GTH_TYPE_TASK,
+ "GthChangeDateTask",
+ &type_info,
+ 0);
+ }
+
+ return type;
+}
+
+
+GthTask *
+gth_change_date_task_new (GList *files, /* GthFileData */
+ GthChangeFields fields,
+ GthChangeType change_type,
+ GthDateTime *date_time,
+ int timezone_offset)
+{
+ GthChangeDateTask *self;
+
+ self = GTH_CHANGE_DATE_TASK (g_object_new (GTH_TYPE_CHANGE_DATE_TASK, NULL));
+ self->priv->files = gth_file_data_list_to_file_list (files);
+ self->priv->fields = fields;
+ self->priv->change_type = change_type;
+ gth_datetime_copy (date_time, self->priv->date_time);
+ self->priv->timezone_offset = timezone_offset;
+
+ return (GthTask *) self;
+}
diff --git a/extensions/change_date/gth-change-date-task.h b/extensions/change_date/gth-change-date-task.h
new file mode 100644
index 0000000..bc0af0e
--- /dev/null
+++ b/extensions/change_date/gth-change-date-task.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2010 The 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef GTH_CHANGE_DATE_TASK_H
+#define GTH_CHANGE_DATE_TASK_H
+
+#include <glib.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ GTH_CHANGE_LAST_MODIFIED_DATE = 1 << 0,
+ GTH_CHANGE_COMMENT_DATE = 1 << 1,
+ GTH_CHANGE_EXIF_DATETIME_TAG = 1 << 2,
+ GTH_CHANGE_EXIF_DATETIMEORIGINAL_TAG = 1 << 3,
+ GTH_CHANGE_EXIF_DATETIMEDIGITIZED_TAG = 1 << 4,
+} GthChangeFields;
+
+typedef enum {
+ GTH_CHANGE_TO_FOLLOWING_DATE,
+ GTH_CHANGE_TO_FILE_MODIFIED_DATE,
+ GTH_CHANGE_TO_FILE_CREATION_DATE,
+ GTH_CHANGE_TO_PHOTO_ORIGINAL_DATE,
+ GTH_CHANGE_ADJUST_TIMEZONE
+} GthChangeType;
+
+#define GTH_TYPE_CHANGE_DATE_TASK (gth_change_date_task_get_type ())
+#define GTH_CHANGE_DATE_TASK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_CHANGE_DATE_TASK, GthChangeDateTask))
+#define GTH_CHANGE_DATE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_TYPE_CHANGE_DATE_TASK, GthChangeDateTaskClass))
+#define GTH_IS_CHANGE_DATE_TASK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_CHANGE_DATE_TASK))
+#define GTH_IS_CHANGE_DATE_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_CHANGE_DATE_TASK))
+#define GTH_CHANGE_DATE_TASK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_CHANGE_DATE_TASK, GthChangeDateTaskClass))
+
+typedef struct _GthChangeDateTask GthChangeDateTask;
+typedef struct _GthChangeDateTaskClass GthChangeDateTaskClass;
+typedef struct _GthChangeDateTaskPrivate GthChangeDateTaskPrivate;
+
+struct _GthChangeDateTask {
+ GthTask __parent;
+ GthChangeDateTaskPrivate *priv;
+};
+
+struct _GthChangeDateTaskClass {
+ GthTaskClass __parent;
+};
+
+GType gth_change_date_task_get_type (void);
+GthTask * gth_change_date_task_new (GList *files, /* GthFileData */
+ GthChangeFields fields,
+ GthChangeType change_type,
+ GthDateTime *date_time,
+ int timezone_offset);
+
+G_END_DECLS
+
+#endif /* GTH_CHANGE_DATE_TASK_H */
diff --git a/gthumb/gio-utils.c b/gthumb/gio-utils.c
index df149bc..fd54af9 100644
--- a/gthumb/gio-utils.c
+++ b/gthumb/gio-utils.c
@@ -2298,3 +2298,22 @@ _g_directory_make (GFile *file,
NULL,
error);
}
+
+
+gboolean
+_g_file_set_modification_time (GFile *file,
+ GTimeVal *timeval,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GFileInfo *info;
+ gboolean result;
+
+ info = g_file_info_new ();
+ g_file_info_set_modification_time (info, timeval);
+ result = g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, cancellable, error);
+
+ g_object_unref (info);
+
+ return result;
+}
diff --git a/gthumb/gio-utils.h b/gthumb/gio-utils.h
index ec8bf68..42a322f 100644
--- a/gthumb/gio-utils.h
+++ b/gthumb/gio-utils.h
@@ -167,6 +167,10 @@ GFile * _g_directory_create_unique (GFile *parent,
const char *display_name,
const char *suffix,
GError **error);
+gboolean _g_file_set_modification_time (GFile *file,
+ GTimeVal *timeval,
+ GCancellable *cancellable,
+ GError **error);
/* convenience macros */
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index fcc1158..b7987df 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -1104,6 +1104,27 @@ _g_str_remove_suffix (const char *s,
}
+/* Array utils*/
+
+
+char *
+_g_string_array_join (GPtrArray *array,
+ const char *separator)
+{
+ GString *s;
+ int i;
+
+ s = g_string_new ("");
+ for (i = 0; i < array->len; i++) {
+ if ((i > 0) && (separator != NULL))
+ g_string_append (s, separator);
+ g_string_append (s, g_ptr_array_index (array, i));
+ }
+
+ return g_string_free (s, FALSE);
+}
+
+
/* Regexp utils */
static char **
diff --git a/gthumb/glib-utils.h b/gthumb/glib-utils.h
index d9fbc60..b1cc1ba 100644
--- a/gthumb/glib-utils.h
+++ b/gthumb/glib-utils.h
@@ -182,6 +182,11 @@ int _g_strv_find (char **v,
char * _g_str_remove_suffix (const char *s,
const char *suffix);
+/* Array utils*/
+
+char * _g_string_array_join (GPtrArray *array,
+ const char *separator);
+
/* Regexp utils */
GRegex ** get_regexps_from_pattern (const char *pattern_string,
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 57bdee6..0dc616c 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -4522,7 +4522,8 @@ _gth_browser_load_file (GthBrowser *browser,
}
if ((browser->priv->current_file != NULL) && g_file_equal (file_data->file, browser->priv->current_file->file)) {
- gth_window_set_current_page (GTH_WINDOW (browser), GTH_BROWSER_PAGE_VIEWER);
+ if (view)
+ gth_window_set_current_page (GTH_WINDOW (browser), GTH_BROWSER_PAGE_VIEWER);
return;
}
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index 054ab2e..6885468 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -32,6 +32,7 @@
#define GTH_FILE_DATA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_FILE_DATA, GthFileDataPrivate))
struct _GthFileDataPrivate {
+ GTimeVal ctime; /* creation time */
GTimeVal mtime; /* modification time */
GTimeVal dtime; /* digitalization time */
char *sort_key;
@@ -264,6 +265,15 @@ gth_file_data_get_modification_time (GthFileData *self)
}
+GTimeVal *
+gth_file_data_get_creation_time (GthFileData *self)
+{
+ self->priv->ctime.tv_sec = g_file_info_get_attribute_uint64 (self->info, G_FILE_ATTRIBUTE_TIME_CREATED);
+ self->priv->ctime.tv_usec = g_file_info_get_attribute_uint32 (self->info, G_FILE_ATTRIBUTE_TIME_CREATED_USEC);
+ return &self->priv->ctime;
+}
+
+
static const char *try_digitalization_tag[] = {
"Exif::Photo::DateTimeOriginal",
"Xmp::exif::DateTimeOriginal",
diff --git a/gthumb/gth-file-data.h b/gthumb/gth-file-data.h
index a55bafd..8740f3d 100644
--- a/gthumb/gth-file-data.h
+++ b/gthumb/gth-file-data.h
@@ -83,6 +83,7 @@ const char * gth_file_data_get_mime_type (GthFileData *self);
const char * gth_file_data_get_filename_sort_key (GthFileData *self);
time_t gth_file_data_get_mtime (GthFileData *self);
GTimeVal * gth_file_data_get_modification_time (GthFileData *self);
+GTimeVal * gth_file_data_get_creation_time (GthFileData *self);
gboolean gth_file_data_get_digitalization_time (GthFileData *self,
GTimeVal *_time);
gboolean gth_file_data_is_readable (GthFileData *self);
diff --git a/gthumb/gth-time.c b/gthumb/gth-time.c
index 2ec4068..a829e09 100644
--- a/gthumb/gth-time.c
+++ b/gthumb/gth-time.c
@@ -105,6 +105,19 @@ gth_datetime_free (GthDateTime *dt)
void
+gth_datetime_copy (GthDateTime *src,
+ GthDateTime *dest)
+{
+ if (gth_datetime_valid (src)) {
+ *dest->date = *src->date;
+ *dest->time = *src->time;
+ }
+ else
+ gth_datetime_clear (dest);
+}
+
+
+void
gth_datetime_clear (GthDateTime *dt)
{
gth_time_clear (dt->time);
@@ -264,6 +277,22 @@ gth_datetime_to_struct_tm (GthDateTime *dt,
}
+gboolean
+gth_datetime_to_timeval (GthDateTime *dt,
+ GTimeVal *tv)
+{
+ char *exif_date;
+ gboolean result;
+
+ exif_date = gth_datetime_to_exif_date (dt);
+ result = _g_time_val_from_exif_date (exif_date, tv);
+
+ g_free (exif_date);
+
+ return result;
+}
+
+
char *
gth_datetime_strftime (GthDateTime *dt,
const char *format)
diff --git a/gthumb/gth-time.h b/gthumb/gth-time.h
index a9c9feb..4ad5322 100644
--- a/gthumb/gth-time.h
+++ b/gthumb/gth-time.h
@@ -52,6 +52,8 @@ void gth_time_set_hms (GthTime *time,
GthDateTime * gth_datetime_new (void);
void gth_datetime_free (GthDateTime *dt);
void gth_datetime_clear (GthDateTime *dt);
+void gth_datetime_copy (GthDateTime *src,
+ GthDateTime *dest);
gboolean gth_datetime_valid (GthDateTime *dt);
void gth_datetime_from_timeval (GthDateTime *dt,
GTimeVal *tv);
@@ -62,6 +64,8 @@ void gth_datetime_from_struct_tm (GthDateTime *dt,
char * gth_datetime_to_exif_date (GthDateTime *dt);
void gth_datetime_to_struct_tm (GthDateTime *dt,
struct tm *tm);
+gboolean gth_datetime_to_timeval (GthDateTime *dt,
+ GTimeVal *tv);
char * gth_datetime_strftime (GthDateTime *dt,
const char *format);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]