1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  GThumb
5  *
6  *  Copyright (C) 2001-2010 The Free Software Foundation, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <gtk/gtk.h>
24 #include <gthumb.h>
25 #include "dlg-change-date.h"
26 #include "gth-change-date-task.h"
27 #include "preferences.h"
28 
29 
30 #define GET_WIDGET(x) (_gtk_builder_get_widget (data->builder, (x)))
31 #define IS_ACTIVE(x) (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (x)))
32 #define HOURS_TO_SECONDS(h) ((h) * 3600)
33 #define MINS_TO_SECONDS(h) ((h) * 60)
34 
35 
36 typedef struct {
37 	GthBrowser *browser;
38 	GtkBuilder *builder;
39 	GSettings  *settings;
40 	GtkWidget  *dialog;
41 	GtkWidget  *date_selector;
42 	GList      *file_list;
43 } DialogData;
44 
45 
46 static void
dialog_destroy_cb(GtkWidget * widget,DialogData * data)47 dialog_destroy_cb (GtkWidget  *widget,
48 		   DialogData *data)
49 {
50 	_g_object_list_unref (data->file_list);
51 	g_object_unref (data->settings);
52 	g_object_unref (data->builder);
53 	g_free (data);
54 }
55 
56 
57 static void
ok_button_clicked(GtkWidget * button,DialogData * data)58 ok_button_clicked (GtkWidget  *button,
59 		   DialogData *data)
60 {
61 	GthChangeFields  change_fields;
62 	GthChangeType    change_type;
63 	GthDateTime     *date_time;
64 	int              time_adjustment;
65 	GthTask         *task;
66 
67 	date_time = NULL;
68 
69 	change_fields = 0;
70 	if (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton")))
71 		change_fields |= GTH_CHANGE_LAST_MODIFIED_DATE;
72 	if (IS_ACTIVE (GET_WIDGET ("change_comment_checkbutton")))
73 		change_fields |= GTH_CHANGE_COMMENT_DATE;
74 
75 	change_type = 0;
76 	time_adjustment = 0;
77 	if (IS_ACTIVE (GET_WIDGET ("to_following_date_radiobutton"))) {
78 		change_type = GTH_CHANGE_TO_FOLLOWING_DATE;
79 		date_time = gth_datetime_new ();
80 		gth_time_selector_get_value (GTH_TIME_SELECTOR (data->date_selector), date_time);
81 	}
82 	else if (IS_ACTIVE (GET_WIDGET ("to_last_modified_date_radiobutton")))
83 		change_type = GTH_CHANGE_TO_FILE_MODIFIED_DATE;
84 	else if (IS_ACTIVE (GET_WIDGET ("to_creation_date_radiobutton")))
85 		change_type = GTH_CHANGE_TO_FILE_CREATION_DATE;
86 	else if (IS_ACTIVE (GET_WIDGET ("to_photo_original_date_radiobutton")))
87 		change_type = GTH_CHANGE_TO_PHOTO_ORIGINAL_DATE;
88 	else if (IS_ACTIVE (GET_WIDGET ("adjust_time_radiobutton"))) {
89 		change_type = GTH_CHANGE_ADJUST_TIME;
90 		time_adjustment = (HOURS_TO_SECONDS (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_h_spinbutton"))))
91 				   + MINS_TO_SECONDS (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_m_spinbutton"))))
92 				   + gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_s_spinbutton"))));
93 		if (gtk_combo_box_get_active (GTK_COMBO_BOX (GET_WIDGET ("adjust_sign_combobox"))) == 1)
94 			time_adjustment = -time_adjustment;
95 	}
96 
97 	/* save the preferences */
98 
99 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_SET_LAST_MODIFIED_DATE, (change_fields & GTH_CHANGE_LAST_MODIFIED_DATE) == GTH_CHANGE_LAST_MODIFIED_DATE);
100 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_SET_COMMENT_DATE, (change_fields & GTH_CHANGE_COMMENT_DATE) == GTH_CHANGE_COMMENT_DATE);
101 
102 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_TO_FOLLOWING_DATE, change_type == GTH_CHANGE_TO_FOLLOWING_DATE);
103 	if (change_type == GTH_CHANGE_TO_FOLLOWING_DATE) {
104 		char *s;
105 		s = gth_datetime_to_exif_date (date_time);
106 		g_settings_set_string (data->settings, PREF_CHANGE_DATE_DATE, s);
107 		g_free (s);
108 	}
109 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_TO_FILE_MODIFIED_DATE, change_type == GTH_CHANGE_TO_FILE_MODIFIED_DATE);
110 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_TO_FILE_CREATION_DATE, change_type == GTH_CHANGE_TO_FILE_CREATION_DATE);
111 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_TO_PHOTO_ORIGINAL_DATE, change_type == GTH_CHANGE_TO_PHOTO_ORIGINAL_DATE);
112 	g_settings_set_boolean (data->settings, PREF_CHANGE_DATE_ADJUST_TIME, change_type == GTH_CHANGE_ADJUST_TIME);
113 	if (change_type == GTH_CHANGE_ADJUST_TIME)
114 		g_settings_set_int (data->settings, PREF_CHANGE_DATE_TIME_ADJUSTMENT, time_adjustment);
115 
116 	/* exec the task */
117 
118 	task = gth_change_date_task_new (gth_browser_get_location (data->browser),
119 					 data->file_list,
120 					 change_fields,
121 					 change_type,
122 					 date_time,
123 					 time_adjustment);
124 	gth_browser_exec_task (data->browser, task, GTH_TASK_FLAGS_DEFAULT);
125 	gtk_widget_destroy (data->dialog);
126 
127 	g_object_unref (task);
128 	gth_datetime_free (date_time);
129 }
130 
131 
132 static void
update_sensitivity(DialogData * data)133 update_sensitivity (DialogData *data)
134 {
135 	gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog),
136 					   GTK_RESPONSE_OK,
137 					   (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton"))
138 					    || IS_ACTIVE (GET_WIDGET ("change_comment_checkbutton"))));
139 	gtk_widget_set_sensitive (data->date_selector, IS_ACTIVE (GET_WIDGET ("to_following_date_radiobutton")));
140 	gtk_widget_set_sensitive (GET_WIDGET ("time_box"), IS_ACTIVE (GET_WIDGET ("adjust_time_radiobutton")));
141 
142 	if (IS_ACTIVE (GET_WIDGET ("change_last_modified_checkbutton"))) {
143 		gtk_widget_set_sensitive (GET_WIDGET ("to_last_modified_date_radiobutton"), FALSE);
144 		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_last_modified_date_radiobutton"))))
145 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_following_date_radiobutton")), TRUE);
146 	}
147 	else
148 		gtk_widget_set_sensitive (GET_WIDGET ("to_last_modified_date_radiobutton"), TRUE);
149 }
150 
151 
152 static void
radio_button_clicked(GtkWidget * button,DialogData * data)153 radio_button_clicked (GtkWidget  *button,
154 		      DialogData *data)
155 {
156 	update_sensitivity (data);
157 }
158 
159 
160 void
dlg_change_date(GthBrowser * browser,GList * file_list)161 dlg_change_date (GthBrowser *browser,
162 		 GList      *file_list)
163 {
164 	DialogData  *data;
165 	GTimeVal     timeval;
166 	GthDateTime *datetime;
167 
168 	data = g_new0 (DialogData, 1);
169 	data->browser = browser;
170 	data->file_list = _g_object_list_ref (file_list);
171 	data->builder = _gtk_builder_new_from_file ("change-date.ui", "change_date");
172 	data->settings = g_settings_new (GTHUMB_CHANGE_DATE_SCHEMA);
173 
174 	/* Get the widgets. */
175 
176 	data->dialog = g_object_new (GTK_TYPE_DIALOG,
177 				     "title", _("Change Date"),
178 				     "transient-for", GTK_WINDOW (browser),
179 				     "modal", FALSE,
180 				     "destroy-with-parent", FALSE,
181 				     "use-header-bar", _gtk_settings_get_dialogs_use_header (),
182 				     NULL);
183 	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (data->dialog))),
184 			   _gtk_builder_get_widget (data->builder, "dialog_content"));
185 	gtk_dialog_add_buttons (GTK_DIALOG (data->dialog),
186 				_GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL,
187 				_GTK_LABEL_EXECUTE, GTK_RESPONSE_OK,
188 				NULL);
189 	_gtk_dialog_add_class_to_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, GTK_STYLE_CLASS_SUGGESTED_ACTION);
190 
191 	data->date_selector = gth_time_selector_new ();
192 	gth_time_selector_show_time (GTH_TIME_SELECTOR (data->date_selector), TRUE, TRUE);
193 	gtk_widget_show (data->date_selector);
194 	gtk_box_pack_start (GTK_BOX (GET_WIDGET ("date_selector_box")), data->date_selector, TRUE, TRUE, 0);
195 
196 	/* Set widgets data. */
197 
198 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("change_last_modified_checkbutton")),
199 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_SET_LAST_MODIFIED_DATE));
200 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("change_comment_checkbutton")),
201 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_SET_COMMENT_DATE));
202 
203 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_following_date_radiobutton")),
204 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_TO_FOLLOWING_DATE));
205 
206 	datetime = gth_datetime_new ();
207 	g_get_current_time (&timeval);
208 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_following_date_radiobutton")))) {
209 		char *s;
210 		s = g_settings_get_string (data->settings, PREF_CHANGE_DATE_DATE);
211 		if (strcmp (s, "") != 0)
212 			gth_datetime_from_exif_date (datetime, s);
213 		else
214 			gth_datetime_from_timeval (datetime, &timeval);
215 		g_free (s);
216 	}
217 	else
218 		gth_datetime_from_timeval (datetime, &timeval);
219 	gth_time_selector_set_value (GTH_TIME_SELECTOR (data->date_selector), datetime);
220 	gth_datetime_free (datetime);
221 
222 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_last_modified_date_radiobutton")),
223 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_TO_FILE_MODIFIED_DATE));
224 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_creation_date_radiobutton")),
225 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_TO_FILE_CREATION_DATE));
226 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("to_photo_original_date_radiobutton")),
227 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_TO_PHOTO_ORIGINAL_DATE));
228 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("adjust_time_radiobutton")),
229 				      g_settings_get_boolean (data->settings, PREF_CHANGE_DATE_ADJUST_TIME));
230 	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("adjust_time_radiobutton")))) {
231 		int adjustement;
232 		int sign;
233 		int hours;
234 		int minutes;
235 		int seconds;
236 
237 		adjustement = g_settings_get_int (data->settings, PREF_CHANGE_DATE_TIME_ADJUSTMENT);
238 		if (adjustement < 0) {
239 			sign = -1;
240 			adjustement = - adjustement;
241 		}
242 		else
243 			sign = 1;
244 
245 		hours = adjustement / 3600;
246 		adjustement = adjustement % 3600;
247 
248 		minutes = adjustement / 60;
249 		adjustement = adjustement % 60;
250 
251 		seconds = adjustement;
252 
253 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_h_spinbutton")), hours);
254 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_m_spinbutton")), minutes);
255 		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("adjust_time_s_spinbutton")), seconds);
256 		gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("adjust_sign_combobox")), (sign >= 0) ? 0 : 1);
257 	}
258 
259 	update_sensitivity (data);
260 
261 	/* Set the signals handlers. */
262 
263 	g_signal_connect (G_OBJECT (data->dialog),
264 			  "destroy",
265 			  G_CALLBACK (dialog_destroy_cb),
266 			  data);
267 	g_signal_connect_swapped (gtk_dialog_get_widget_for_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_CANCEL),
268 				  "clicked",
269 				  G_CALLBACK (gtk_widget_destroy),
270 				  G_OBJECT (data->dialog));
271 	g_signal_connect (gtk_dialog_get_widget_for_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK),
272 			  "clicked",
273 			  G_CALLBACK (ok_button_clicked),
274 			  data);
275 	g_signal_connect (GET_WIDGET ("change_last_modified_checkbutton"),
276 			  "clicked",
277 			  G_CALLBACK (radio_button_clicked),
278 			  data);
279 	g_signal_connect (GET_WIDGET ("change_comment_checkbutton"),
280 			  "clicked",
281 			  G_CALLBACK (radio_button_clicked),
282 			  data);
283 	g_signal_connect (GET_WIDGET ("to_following_date_radiobutton"),
284 			  "clicked",
285 			  G_CALLBACK (radio_button_clicked),
286 			  data);
287 	g_signal_connect (GET_WIDGET ("to_last_modified_date_radiobutton"),
288 			  "clicked",
289 			  G_CALLBACK (radio_button_clicked),
290 			  data);
291 	g_signal_connect (GET_WIDGET ("to_creation_date_radiobutton"),
292 			  "clicked",
293 			  G_CALLBACK (radio_button_clicked),
294 			  data);
295 	g_signal_connect (GET_WIDGET ("to_photo_original_date_radiobutton"),
296 			  "clicked",
297 			  G_CALLBACK (radio_button_clicked),
298 			  data);
299 	g_signal_connect (GET_WIDGET ("adjust_time_radiobutton"),
300 			  "clicked",
301 			  G_CALLBACK (radio_button_clicked),
302 			  data);
303 
304 	/* run dialog. */
305 
306 	gtk_widget_show (data->dialog);
307 }
308