/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Pix * * 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, see . */ #include #include #include "gth-import-enum-types.h" #include "gth-import-preferences-dialog.h" #include "preferences.h" #include "utils.h" #define EXAMPLE_FILE_DATE "2005-03-09T13:23:51Z" #define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x))) static char * Importer_Date_Formats[] = { "%Y-%m-%d", "%Y-%m", "%Y", "%Y/%m/%d", "%Y/%m", NULL }; static GthTemplateCode Subfolder_Special_Codes[] = { { GTH_TEMPLATE_CODE_TYPE_DATE, N_("File date"), 'D' }, { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Current date"), 'T' }, { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Event description"), 'E' }, }; /* Signals */ enum { DESTINATION_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; struct _GthImportPreferencesDialogPrivate { GtkBuilder *builder; GSettings *settings; char *event; }; G_DEFINE_TYPE_WITH_CODE (GthImportPreferencesDialog, gth_import_preferences_dialog, GTK_TYPE_DIALOG, G_ADD_PRIVATE (GthImportPreferencesDialog)) static void gth_import_preferences_dialog_finalize (GObject *object) { GthImportPreferencesDialog *self; self = GTH_IMPORT_PREFERENCES_DIALOG (object); _g_object_unref (self->priv->settings); _g_object_unref (self->priv->builder); g_free (self->priv->event); G_OBJECT_CLASS (gth_import_preferences_dialog_parent_class)->finalize (object); } static void gth_import_preferences_dialog_class_init (GthImportPreferencesDialogClass *klass) { GObjectClass *object_class; object_class = (GObjectClass*) klass; object_class->finalize = gth_import_preferences_dialog_finalize; /* signals */ signals[DESTINATION_CHANGED] = g_signal_new ("destination-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GthImportPreferencesDialogClass, destination_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void save_options (GthImportPreferencesDialog *self) { GFile *destination; destination = gth_import_preferences_dialog_get_destination (self); if (destination != NULL) { char *uri; uri = g_file_get_uri (destination); g_settings_set_string (self->priv->settings, PREF_IMPORTER_DESTINATION, uri); g_free (uri); } if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("automatic_subfolder_checkbutton")))) { const char *subfolder_template = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("subfolder_template_entry"))); g_settings_set_string (self->priv->settings, PREF_IMPORTER_SUBFOLDER_TEMPLATE, subfolder_template); } else g_settings_set_string (self->priv->settings, PREF_IMPORTER_SUBFOLDER_TEMPLATE, ""); _g_object_unref (destination); } static void save_and_hide (GthImportPreferencesDialog *self) { save_options (self); gtk_widget_hide (GTK_WIDGET (self)); } static gboolean preferences_dialog_delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) { save_and_hide ((GthImportPreferencesDialog *) user_data); return TRUE; } static GthFileData * create_example_file_data (void) { GFile *file; GFileInfo *info; GthFileData *file_data; GthMetadata *metadata; file = g_file_new_for_uri ("file://home/user/document.txt"); info = g_file_info_new (); file_data = gth_file_data_new (file, info); metadata = g_object_new (GTH_TYPE_METADATA, "raw", "2005:03:09 13:23:51", "formatted", "2005:03:09 13:23:51", NULL); g_file_info_set_attribute_object (info, "Embedded::Photo::DateTimeOriginal", G_OBJECT (metadata)); g_object_unref (metadata); g_object_unref (info); g_object_unref (file); return file_data; } static void update_destination (GthImportPreferencesDialog *self) { GFile *destination; destination = gth_import_preferences_dialog_get_destination (self); if (destination == NULL) { gtk_label_set_text (GTK_LABEL (GET_WIDGET ("example_label")), ""); } else { GString *example; char *destination_name; GFile *subfolder; example = g_string_new (""); destination_name = g_file_get_parse_name (destination); _g_string_append_markup_escaped (example, "%s", destination_name); subfolder = gth_import_preferences_dialog_get_subfolder_example (self); if (subfolder != NULL) { char *subfolder_name = g_file_get_parse_name (subfolder); if (! _g_str_empty (subfolder_name) && ! _g_str_equal (subfolder_name, "/")) { const char *name = g_str_has_suffix (destination_name, "/") ? subfolder_name + 1 : subfolder_name; _g_string_append_markup_escaped (example, "%s", name); } g_free (subfolder_name); g_object_unref (subfolder); } gtk_label_set_markup (GTK_LABEL (GET_WIDGET ("example_label")), example->str); g_free (destination_name); g_string_free (example, TRUE); g_object_unref (destination); } g_signal_emit (self, signals[DESTINATION_CHANGED], 0); } static void destination_selection_changed_cb (GtkWidget *widget, gpointer *user_data) { update_destination ((GthImportPreferencesDialog *) user_data); } static void automatic_subfolder_checkbutton_toggled_cb (GtkToggleButton *togglebutton, gpointer user_data) { GthImportPreferencesDialog *self = user_data; gboolean active; active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("automatic_subfolder_checkbutton"))); gtk_widget_set_visible (GET_WIDGET ("subfolder_section_box"), active); if (active) gtk_widget_grab_focus (GET_WIDGET ("subfolder_template_entry")); update_destination (self); } static void subfolder_template_entry_changed_cb (GtkEditable *editable, gpointer *user_data) { update_destination ((GthImportPreferencesDialog *) user_data); } static gboolean template_eval_cb (TemplateFlags flags, gunichar parent_code, gunichar code, char **args, GString *result, gpointer user_data) { GthImportPreferencesDialog *self = user_data; gboolean preview; char *text = NULL; GDateTime *timestamp; preview = flags & TEMPLATE_FLAGS_PREVIEW; if ((parent_code == 'D') || (parent_code == 'T')) { /* strftime code, return the code itself. */ _g_string_append_template_code (result, code, args); return FALSE; } if (preview && (code != 0)) g_string_append (result, ""); /**/ switch (code) { case 'D': /* File date */ timestamp = g_date_time_new_from_iso8601 (EXAMPLE_FILE_DATE, NULL); text = g_date_time_format (timestamp, (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT); g_date_time_unref (timestamp); break; case 'T': /* Timestamp */ timestamp = g_date_time_new_now_local (); text = g_date_time_format (timestamp, (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT); g_date_time_unref (timestamp); break; case 'E': /* Event description */ if (self->priv->event != NULL) g_string_append (result, self->priv->event); break; default: break; } if (text != NULL) { g_string_append (result, text); g_free (text); } if (preview && (code != 0)) g_string_append (result, ""); return FALSE; } static void edit_subfolder_template_button_clicked_cb (GtkButton *button, gpointer user_data) { GthImportPreferencesDialog *self = user_data; GtkWidget *dialog; dialog = gth_template_editor_dialog_new (Subfolder_Special_Codes, G_N_ELEMENTS (Subfolder_Special_Codes), 0, _("Edit Template"), GTK_WINDOW (self)); gth_template_editor_dialog_set_preview_cb (GTH_TEMPLATE_EDITOR_DIALOG (dialog), template_eval_cb, self); gth_template_editor_dialog_set_date_formats (GTH_TEMPLATE_EDITOR_DIALOG (dialog), Importer_Date_Formats); gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog), gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("subfolder_template_entry")))); g_signal_connect (dialog, "response", G_CALLBACK (gth_template_editor_dialog_default_response), GET_WIDGET ("subfolder_template_entry")); gtk_widget_show (dialog); } static void dialog_response_cb (GtkDialog *dialog, int response_id, gpointer user_data) { GthImportPreferencesDialog *self = user_data; if ((response_id == GTK_RESPONSE_DELETE_EVENT) || (response_id == GTK_RESPONSE_CLOSE)) save_and_hide (self); } static void gth_import_preferences_dialog_init (GthImportPreferencesDialog *self) { GtkWidget *content; GFile *destination; char *subfolder_template; self->priv = gth_import_preferences_dialog_get_instance_private (self); self->priv->builder = _gtk_builder_new_from_file ("import-preferences.ui", "importer"); self->priv->settings = g_settings_new (PIX_IMPORTER_SCHEMA); content = _gtk_builder_get_widget (self->priv->builder, "import_preferences"); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), content, TRUE, TRUE, 0); gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CLOSE, GTK_RESPONSE_CLOSE); /* set widget data */ destination = gth_import_preferences_get_destination (); gtk_file_chooser_set_file (GTK_FILE_CHOOSER (GET_WIDGET ("destination_filechooserbutton")), destination, NULL); subfolder_template = g_settings_get_string (self->priv->settings, PREF_IMPORTER_SUBFOLDER_TEMPLATE); if (subfolder_template != NULL) { gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("subfolder_template_entry")), subfolder_template); if (! _g_str_empty (subfolder_template)) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("automatic_subfolder_checkbutton")), TRUE); automatic_subfolder_checkbutton_toggled_cb (NULL, self); } g_free (subfolder_template); } update_destination (self); g_signal_connect (GET_WIDGET ("destination_filechooserbutton"), "selection_changed", G_CALLBACK (destination_selection_changed_cb), self); g_signal_connect (self, "delete-event", G_CALLBACK (preferences_dialog_delete_event_cb), self); g_signal_connect (GET_WIDGET ("automatic_subfolder_checkbutton"), "toggled", G_CALLBACK (automatic_subfolder_checkbutton_toggled_cb), self); g_signal_connect (GET_WIDGET ("subfolder_template_entry"), "changed", G_CALLBACK (subfolder_template_entry_changed_cb), self); g_signal_connect (GET_WIDGET ("edit_subfolder_template_button"), "clicked", G_CALLBACK (edit_subfolder_template_button_clicked_cb), self); g_signal_connect (self, "response", G_CALLBACK (dialog_response_cb), self); g_object_unref (destination); } GtkWidget * gth_import_preferences_dialog_new (void) { return (GtkWidget *) g_object_new (GTH_TYPE_IMPORT_PREFERENCES_DIALOG, "title", _("Preferences"), "resizable", FALSE, "modal", TRUE, "use-header-bar", _gtk_settings_get_dialogs_use_header (), NULL); } void gth_import_preferences_dialog_set_event (GthImportPreferencesDialog *self, const char *event) { g_free (self->priv->event); self->priv->event = g_strdup (event); g_signal_emit (self, signals[DESTINATION_CHANGED], 0); } GFile * gth_import_preferences_dialog_get_destination (GthImportPreferencesDialog *self) { return gtk_file_chooser_get_file (GTK_FILE_CHOOSER (GET_WIDGET ("destination_filechooserbutton"))); } GFile * gth_import_preferences_dialog_get_subfolder_example (GthImportPreferencesDialog *self) { GFile *destination; GthFileData *example_file_data; const char *subfolder_template; GTimeVal timestamp; GFile *destination_example; destination = g_file_new_for_path("/"); example_file_data = create_example_file_data (); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("automatic_subfolder_checkbutton")))) subfolder_template = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("subfolder_template_entry"))); else subfolder_template = NULL; g_get_current_time (×tamp); destination_example = gth_import_utils_get_file_destination (example_file_data, destination, subfolder_template, self->priv->event, timestamp); g_object_unref (example_file_data); g_object_unref (destination); return destination_example; }