/* -*- 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 . */ #include #include #include #include #include "dlg-rename-series.h" #include "gth-template-editor-dialog.h" #include "gth-template-selector.h" #include "gth-rename-task.h" #include "preferences.h" enum { SORT_DATA_COLUMN, SORT_NAME_COLUMN, SORT_NUM_COLUMNS }; enum { PREVIEW_OLD_NAME_COLUMN, PREVIEW_NEW_NAME_COLUMN, PREVIEW_NUM_COLUMNS }; #define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name)) #define DEFAULT_TEMPLATE "####%E" #define DEFAULT_START_AT 1 #define DEFAULT_SORT_BY "general::unsorted" #define DEFAULT_REVERSE_ORDER FALSE #define DEFAULT_CHANGE_CASE GTH_CHANGE_CASE_NONE #define UPDATE_DELAY 500 static GthTemplateCode Rename_Special_Codes[] = { { GTH_TEMPLATE_CODE_TYPE_TEXT, N_("Text"), 0 }, { GTH_TEMPLATE_CODE_TYPE_ENUMERATOR, N_("Enumerator"), '#' }, { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Original filename"), 'F' }, { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Original extension"), 'E' }, { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Original enumerator"), 'N' }, { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Modification date"), 'M' }, { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Digitalization date"), 'D' }, { GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE, N_("File attribute"), 'A' } }; typedef struct { GthBrowser *browser; GSettings *settings; GList *file_list; GList *file_data_list; GList *new_file_list; GList *new_names_list; gboolean single_file; gboolean first_update; GtkBuilder *builder; GtkWidget *dialog; GtkWidget *list_view; GtkWidget *sort_combobox; GtkWidget *change_case_combobox; GtkListStore *list_store; GtkListStore *sort_model; gboolean help_visible; char *required_attributes; guint update_id; gboolean template_changed; GList *tasks; gboolean closing; } DialogData; static void destroy_dialog (DialogData *data) { if (data->dialog != NULL) gtk_widget_destroy (data->dialog); data->dialog = NULL; gth_browser_set_dialog (data->browser, "rename_series", NULL); if (data->update_id != 0) { g_source_remove (data->update_id); data->update_id = 0; } g_free (data->required_attributes); g_object_unref (data->builder); _g_object_list_unref (data->file_data_list); _g_object_list_unref (data->file_list); _g_string_list_free (data->new_names_list); g_list_free (data->new_file_list); g_object_unref (data->settings); g_free (data); } typedef struct { const char *template; GthFileData *file_data; int n; GError **error; } TemplateData; static char * get_original_enum (GthFileData *file_data, char *match) { char *basename; GRegex *re; char **a; char *value = NULL; basename = g_file_get_basename (file_data->file); re = g_regex_new ("([0-9]+)", 0, 0, NULL); a = g_regex_split (re, basename, 0); if (g_strv_length (a) >= 2) value = g_strdup (g_strstrip (a[1])); g_strfreev (a); g_regex_unref (re); g_free (basename); return value; } static char * get_attribute_value (GthFileData *file_data, char *match) { GRegex *re; char **a; char *attribute = NULL; char *value = NULL; re = g_regex_new ("%A\\{([^}]+)\\}", 0, 0, NULL); a = g_regex_split (re, match, 0); if (g_strv_length (a) >= 2) attribute = g_strstrip (a[1]); if ((attribute != NULL) && (*attribute != '\0')) { value = gth_file_data_get_attribute_as_string (file_data, attribute); if (value != NULL) { char *tmp_value; tmp_value = _g_utf8_replace_pattern (value, "[\r\n]", " "); g_free (value); value = tmp_value; } } g_strfreev (a); g_regex_unref (re); return value; } static gboolean template_eval_cb (const GMatchInfo *info, GString *res, gpointer data) { TemplateData *template_data = data; char *r = NULL; char *match; match = g_match_info_fetch (info, 0); if (strncmp (match, "#", 1) == 0) { char *format; format = g_strdup_printf ("%%0%" G_GSIZE_FORMAT "d", strlen (match)); r = g_strdup_printf (format, template_data->n); g_free (format); } else if (strncmp (match, "%A", 2) == 0) { r = get_attribute_value (template_data->file_data, match); /*if (r == NULL) *template_data->error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_FAILED, _("Malformed template"));*/ } else if (strcmp (match, "%E") == 0) { char *uri; uri = g_file_get_uri (template_data->file_data->file); r = _g_uri_get_extension (uri); g_free (uri); } else if (strcmp (match, "%F") == 0) { char *basename; basename = g_file_get_basename (template_data->file_data->file); r = _g_path_remove_extension (basename); g_free (basename); } else if (strcmp (match, "%N") == 0) { r = get_original_enum (template_data->file_data, match); } else if ((strncmp (match, "%D", 2) == 0) || (strncmp (match, "%M", 2) == 0)) { gboolean value_available = FALSE; GTimeVal timeval; if (strncmp (match, "%D", 2) == 0) { value_available = gth_file_data_get_digitalization_time (template_data->file_data, &timeval); } else if (strncmp (match, "%M", 2) == 0) { timeval = *gth_file_data_get_modification_time (template_data->file_data); value_available = TRUE; } if (value_available) { GRegex *re; char **a; char *format = NULL; /* Get the date format */ re = g_regex_new ("%[A-Z]\\{([^}]+)\\}", 0, 0, NULL); a = g_regex_split (re, match, 0); if (g_strv_length (a) >= 2) format = g_strstrip (a[1]); r = _g_time_val_strftime (&timeval, format); g_strfreev (a); g_regex_unref (re); } } if (r != NULL) g_string_append (res, r); g_free (r); g_free (match); return FALSE; } static char * get_required_attributes (DialogData *data) { GtkTreeIter iter; GString *required_attributes; const char *template; required_attributes = g_string_new (GFILE_STANDARD_ATTRIBUTES); /* attributes required for sorting */ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (data->sort_combobox), &iter)) { GthFileDataSort *sort_type; gtk_tree_model_get (GTK_TREE_MODEL (data->sort_model), &iter, SORT_DATA_COLUMN, &sort_type, -1); if ((sort_type->required_attributes != NULL) && ! g_str_equal (sort_type->required_attributes, "")) { g_string_append (required_attributes, ","); g_string_append (required_attributes, sort_type->required_attributes); } } /* attributes required for renaming */ template = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("template_entry"))); if (g_strstr_len (template, -1, "%A") != NULL) { GRegex *re; char **a; int i; re = g_regex_new ("%A\\{([^}]+)\\}", 0, 0, NULL); a = g_regex_split (re, template, 0); for (i = 1; i < g_strv_length (a); i += 2) { char *id; id = g_strstrip (g_strdup (a[i])); g_string_append (required_attributes, ","); g_string_append (required_attributes, id); g_free (id); } g_strfreev (a); g_regex_unref (re); } if (g_strstr_len (template, -1, "%D") != NULL) { int i; for (i = 0; FileDataDigitalizationTags[i] != NULL; i++) { g_string_append (required_attributes, ","); g_string_append (required_attributes, FileDataDigitalizationTags[i]); } } if (g_strstr_len (template, -1, "%M") != NULL) { g_string_append (required_attributes, ","); g_string_append (required_attributes, G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC); } return g_string_free (required_attributes, FALSE); } /* update_file_list */ typedef struct { DialogData *data; ReadyFunc ready_func; GthTask *task; gulong task_completed_id; } UpdateData; static void update_data_free (UpdateData *update_data) { g_free(update_data); } static void update_preview_cb (GtkWidget *widget, DialogData *data); static void update_file_list__step2 (gpointer user_data) { UpdateData *update_data = user_data; DialogData *data = update_data->data; GtkTreeIter iter; int change_case; TemplateData *template_data; GRegex *re; GList *scan; GError *error = NULL; if (data->first_update) { if (data->file_data_list->next == NULL) { GthFileData *file_data = data->file_data_list->data; const char *edit_name; const char *end_pos; g_signal_handlers_block_by_func (GET_WIDGET ("template_entry"), update_preview_cb, data); gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("template_entry")), g_file_info_get_attribute_string (file_data->info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME)); g_signal_handlers_unblock_by_func (GET_WIDGET ("template_entry"), update_preview_cb, data); gtk_widget_grab_focus (GET_WIDGET ("template_entry")); edit_name = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("template_entry"))); end_pos = g_utf8_strrchr (edit_name, -1, '.'); if (end_pos != NULL) { glong nchars; nchars = g_utf8_strlen (edit_name, (gssize) (end_pos - edit_name)); gtk_editable_select_region (GTK_EDITABLE (GET_WIDGET ("template_entry")), 0, nchars); } } else { gtk_widget_grab_focus (GET_WIDGET ("template_entry")); gtk_editable_select_region (GTK_EDITABLE (GET_WIDGET ("template_entry")), 0, -1); } } data->first_update = FALSE; if (data->new_names_list != NULL) { _g_string_list_free (data->new_names_list); data->new_names_list = NULL; } if (data->new_file_list != NULL) { g_list_free (data->new_file_list); data->new_file_list = NULL; } data->new_file_list = g_list_copy (data->file_data_list); if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (data->sort_combobox), &iter)) { GthFileDataSort *sort_type; gtk_tree_model_get (GTK_TREE_MODEL (data->sort_model), &iter, SORT_DATA_COLUMN, &sort_type, -1); if (sort_type->cmp_func != NULL) data->new_file_list = g_list_sort (data->new_file_list, (GCompareFunc) sort_type->cmp_func); } if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("reverse_order_checkbutton")))) data->new_file_list = g_list_reverse (data->new_file_list); change_case = gtk_combo_box_get_active (GTK_COMBO_BOX (data->change_case_combobox)); template_data = g_new0 (TemplateData, 1); template_data->error = &error; template_data->n = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("start_at_spinbutton"))); template_data->template = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("template_entry"))); re = g_regex_new ("#+|%[ADEFMN](\\{[^}]+\\})?", 0, 0, NULL); for (scan = data->new_file_list; scan; scan = scan->next) { char *new_name; char *new_name2; template_data->file_data = scan->data; new_name = g_regex_replace_eval (re, template_data->template, -1, 0, 0, template_eval_cb, template_data, &error); if (error != NULL) break; switch (change_case) { case GTH_CHANGE_CASE_LOWER: new_name2 = g_utf8_strdown (new_name, -1); break; case GTH_CHANGE_CASE_UPPER: new_name2 = g_utf8_strup (new_name, -1); break; default: new_name2 = g_strdup (new_name); break; } data->new_names_list = g_list_prepend (data->new_names_list, new_name2); template_data->n = template_data->n + 1; g_free (new_name); } g_regex_unref (re); data->new_names_list = g_list_reverse (data->new_names_list); if (update_data->ready_func) update_data->ready_func (error, update_data->data); update_data_free (update_data); } static void load_file_data_task_completed_cb (GthTask *task, GError *error, gpointer user_data) { UpdateData *update_data = user_data; DialogData *data = update_data->data; gtk_widget_hide (GET_WIDGET ("task_box")); gtk_widget_set_sensitive (GET_WIDGET ("options_table"), TRUE); gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, TRUE); data->tasks = g_list_remove (data->tasks, update_data->task); g_object_unref (update_data->task); update_data->task = NULL; update_data->task_completed_id = 0; if (error != NULL) { if (! data->closing && update_data->ready_func) update_data->ready_func (error, update_data->data); update_data_free (update_data); if (data->tasks == NULL) destroy_dialog (data); return; } _g_object_list_unref (data->file_data_list); data->file_data_list = _g_object_list_ref (gth_load_file_data_task_get_result (GTH_LOAD_FILE_DATA_TASK (task))); data->template_changed = FALSE; update_file_list__step2 (update_data); } static void update_file_list (DialogData *data, ReadyFunc ready_func) { UpdateData *update_data; update_data = g_new (UpdateData, 1); update_data->data = data; update_data->ready_func = ready_func; if (data->template_changed) { char *required_attributes; gboolean reload_required; required_attributes = get_required_attributes (data); reload_required = attribute_list_reload_required (data->required_attributes, required_attributes); g_free (data->required_attributes); data->required_attributes = required_attributes; if (reload_required) { GtkWidget *child; gtk_widget_set_sensitive (GET_WIDGET ("options_table"), FALSE); gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, FALSE); gtk_widget_show (GET_WIDGET ("task_box")); update_data->task = gth_load_file_data_task_new (data->file_list, data->required_attributes); update_data->task_completed_id = g_signal_connect (update_data->task, "completed", G_CALLBACK (load_file_data_task_completed_cb), update_data); data->tasks = g_list_prepend (data->tasks, update_data->task); child = gth_task_progress_new (update_data->task); gtk_widget_show (child); gtk_box_pack_start (GTK_BOX (GET_WIDGET ("task_box")), child, TRUE, TRUE, 0); gth_task_exec (update_data->task, NULL); return; } } call_when_idle (update_file_list__step2, update_data); } static void ok_button_clicked__step2 (GError *error, gpointer user_data) { DialogData *data = user_data; GtkTreeIter iter; GList *old_files; GList *new_files; GList *scan1; GList *scan2; GthTask *task; if (error != NULL) { _gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->dialog), _("Could not rename the files"), error); return; } /* -- save preferences -- */ if (data->file_list->next != NULL) g_settings_set_string (data->settings, PREF_RENAME_SERIES_TEMPLATE, gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("template_entry")))); g_settings_set_int (data->settings, PREF_RENAME_SERIES_START_AT, gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET ("start_at_spinbutton")))); if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (data->sort_combobox), &iter)) { GthFileDataSort *sort_type; gtk_tree_model_get (GTK_TREE_MODEL (data->sort_model), &iter, SORT_DATA_COLUMN, &sort_type, -1); g_settings_set_string (data->settings, PREF_RENAME_SERIES_SORT_BY, sort_type->name); } g_settings_set_boolean (data->settings, PREF_RENAME_SERIES_REVERSE_ORDER, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("reverse_order_checkbutton")))); g_settings_set_enum (data->settings, PREF_RENAME_SERIES_CHANGE_CASE, gtk_combo_box_get_active (GTK_COMBO_BOX (data->change_case_combobox))); /* -- prepare and exec rename task -- */ old_files = NULL; new_files = NULL; for (scan1 = data->new_file_list, scan2 = data->new_names_list; scan1 && scan2; scan1 = scan1->next, scan2 = scan2->next) { GthFileData *file_data = scan1->data; char *new_name = scan2->data; GFile *parent; GFile *new_file; parent = g_file_get_parent (file_data->file); new_file = g_file_get_child (parent, new_name); old_files = g_list_prepend (old_files, g_object_ref (file_data->file)); new_files = g_list_prepend (new_files, new_file); g_object_unref (parent); } old_files = g_list_reverse (old_files); new_files = g_list_reverse (new_files); task = gth_rename_task_new (old_files, new_files); gth_browser_exec_task (data->browser, task, GTH_TASK_FLAGS_DEFAULT); g_object_unref (task); destroy_dialog (data); } static void ok_button_clicked (DialogData *data) { if (data->update_id != 0) { g_source_remove (data->update_id); data->update_id = 0; } update_file_list (data, ok_button_clicked__step2); } static void dialog_response_cb (GtkDialog *dialog, int response_id, gpointer user_data) { DialogData *data = user_data; switch (response_id) { case GTK_RESPONSE_DELETE_EVENT: case GTK_RESPONSE_CANCEL: if (data->tasks != NULL) { GList *tasks; data->closing = TRUE; tasks = g_list_copy (data->tasks); g_list_foreach (tasks, (GFunc) gth_task_cancel, NULL); g_list_free (tasks); } else destroy_dialog (data); break; case GTK_RESPONSE_OK: ok_button_clicked (data); break; default: break; } } static void error_dialog_response_cb (GtkDialog *dialog, int response, gpointer user_data) { DialogData *data = user_data; gtk_widget_destroy (GTK_WIDGET (dialog)); destroy_dialog (data); } static void update_preview__step2 (GError *error, gpointer user_data) { DialogData *data = user_data; GList *scan1, *scan2; if (error != NULL) { GtkWidget *d; d = _gtk_message_dialog_new (GTK_WINDOW (data->dialog), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, _GTK_ICON_NAME_DIALOG_ERROR, _("Could not rename the files"), error->message, _GTK_LABEL_OK, GTK_RESPONSE_OK, NULL); g_signal_connect (d, "response", G_CALLBACK (error_dialog_response_cb), data); gtk_window_present (GTK_WINDOW (d)); return; } /* -- update the list view -- */ gtk_list_store_clear (data->list_store); for (scan1 = data->new_file_list, scan2 = data->new_names_list; scan1 && scan2; scan1 = scan1->next, scan2 = scan2->next) { GthFileData *file_data1 = scan1->data; GthFileData *new_name = scan2->data; GtkTreeIter iter; gtk_list_store_append (data->list_store, &iter); gtk_list_store_set (data->list_store, &iter, PREVIEW_OLD_NAME_COLUMN, g_file_info_get_display_name (file_data1->info), PREVIEW_NEW_NAME_COLUMN, new_name, -1); } } static void dlg_rename_series_update_preview (DialogData *data) { update_file_list (data, update_preview__step2); } static void template_entry_icon_release_cb (GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, gpointer user_data) { DialogData *data = user_data; data->help_visible = ! data->help_visible; if (data->help_visible) gtk_widget_show (GET_WIDGET("template_help_table")); else gtk_widget_hide (GET_WIDGET("template_help_table")); } static gboolean update_preview_after_delay_cb (gpointer user_data) { DialogData *data = user_data; if (data->update_id != 0) { g_source_remove (data->update_id); data->update_id = 0; } dlg_rename_series_update_preview (data); return FALSE; } static void update_preview_cb (GtkWidget *widget, DialogData *data) { data->template_changed = TRUE; if (data->update_id != 0) g_source_remove (data->update_id); data->update_id = g_timeout_add (UPDATE_DELAY, update_preview_after_delay_cb, data); } static void template_editor_dialog_response_cb (GtkDialog *dialog, int response_id, gpointer user_data) { DialogData *data = user_data; char *template; GError *error = NULL; if (response_id != GTK_RESPONSE_OK) { gtk_widget_destroy (GTK_WIDGET (dialog)); return; } template = gth_template_editor_dialog_get_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog), &error); if (error != NULL) { _gtk_error_dialog_from_gerror_show (GTK_WINDOW (dialog), _("Could not save the template"), error); g_clear_error (&error); return; } gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("template_entry")), template); gtk_widget_destroy (GTK_WIDGET (dialog)); g_free (template); } static void edit_template_button_clicked_cb (GtkWidget *widget, DialogData *data) { GtkWidget *dialog; dialog = gth_template_editor_dialog_new (Rename_Special_Codes, 8, _("Edit Template"), GTK_WINDOW (data->dialog)); gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog), gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("template_entry")))); g_signal_connect (dialog, "response", G_CALLBACK (template_editor_dialog_response_cb), data); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_window_present (GTK_WINDOW (dialog)); } static void return_pressed_callback (GtkDialog *dialog, gpointer user_data) { ok_button_clicked (user_data); } void dlg_rename_series (GthBrowser *browser, GList *file_list) { DialogData *data; GtkCellRenderer *renderer; GtkTreeViewColumn *column; int i; GList *sort_types; GList *scan; int change_case; int start_at; char *sort_by; gboolean found; if (gth_browser_get_dialog (browser, "rename_series") != NULL) { gtk_window_present (GTK_WINDOW (gth_browser_get_dialog (browser, "rename_series"))); return; } data = g_new0 (DialogData, 1); data->browser = browser; data->builder = _gtk_builder_new_from_file ("rename-series.ui", "rename_series"); data->settings = g_settings_new (GTHUMB_RENAME_SERIES_SCHEMA); data->file_list = _g_file_list_dup (file_list); data->first_update = TRUE; data->template_changed = TRUE; data->closing = FALSE; /* Get the widgets. */ data->dialog = g_object_new (GTK_TYPE_DIALOG, "title", _("Rename"), "transient-for", GTK_WINDOW (browser), "modal", FALSE, "destroy-with-parent", FALSE, "use-header-bar", _gtk_settings_get_dialogs_use_header (), NULL); gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (data->dialog))), _gtk_builder_get_widget (data->builder, "dialog_content")); gtk_dialog_add_buttons (GTK_DIALOG (data->dialog), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL, _("_Rename"), GTK_RESPONSE_OK, NULL); _gtk_dialog_add_class_to_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, GTK_STYLE_CLASS_SUGGESTED_ACTION); gth_browser_set_dialog (browser, "rename_series", data->dialog); g_object_set_data (G_OBJECT (data->dialog), "dialog_data", data); /* Set widgets data. */ data->list_store = gtk_list_store_new (PREVIEW_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); data->list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (data->list_store)); g_object_unref (data->list_store); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); column = gtk_tree_view_column_new_with_attributes (_("Old Name"), renderer, "text", PREVIEW_OLD_NAME_COLUMN, NULL); gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (data->list_view), column); renderer = gtk_cell_renderer_text_new (); g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL); column = gtk_tree_view_column_new_with_attributes (_("New Name"), renderer, "text", PREVIEW_NEW_NAME_COLUMN, NULL); gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (data->list_view), column); gtk_widget_show (data->list_view); gtk_widget_set_vexpand (data->list_view, TRUE); gtk_container_add (GTK_CONTAINER (GET_WIDGET ("preview_scrolledwindow")), data->list_view); gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("preview_label")), data->list_view); if (data->file_list->next != NULL) gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("template_entry")), g_settings_get_string (data->settings, PREF_RENAME_SERIES_TEMPLATE)); start_at = g_settings_get_int (data->settings, PREF_RENAME_SERIES_START_AT); if (start_at < 0) start_at = DEFAULT_START_AT; gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("start_at_spinbutton")), start_at * 1.0); /* sort by */ data->sort_model = gtk_list_store_new (SORT_NUM_COLUMNS, G_TYPE_POINTER, G_TYPE_STRING); data->sort_combobox = gtk_combo_box_new_with_model (GTK_TREE_MODEL (data->sort_model)); g_object_unref (data->sort_model); renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (data->sort_combobox), renderer, TRUE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (data->sort_combobox), renderer, "text", SORT_NAME_COLUMN, NULL); sort_by = g_settings_get_string (data->settings, PREF_RENAME_SERIES_SORT_BY); found = FALSE; sort_types = gth_main_get_all_sort_types (); for (i = 0, scan = sort_types; scan; scan = scan->next, i++) { GthFileDataSort *sort_type = scan->data; GtkTreeIter iter; gtk_list_store_append (data->sort_model, &iter); gtk_list_store_set (data->sort_model, &iter, SORT_DATA_COLUMN, sort_type, SORT_NAME_COLUMN, sort_type->display_name, -1); if (strcmp (sort_by, sort_type->name) == 0) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->sort_combobox), &iter); found = TRUE; } } g_list_free (sort_types); g_free (sort_by); if (!found) gtk_combo_box_set_active (GTK_COMBO_BOX (data->sort_combobox), 0); gtk_widget_show (data->sort_combobox); gtk_box_pack_start (GTK_BOX (GET_WIDGET ("sort_by_box")), data->sort_combobox, FALSE, FALSE, 0); gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("sort_by_label")), data->sort_combobox); /* reverse order */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("reverse_order_checkbutton")), g_settings_get_boolean (data->settings, PREF_RENAME_SERIES_REVERSE_ORDER)); /* change case */ change_case = g_settings_get_enum (data->settings, PREF_RENAME_SERIES_CHANGE_CASE); if ((change_case < GTH_CHANGE_CASE_NONE) || (change_case > GTH_CHANGE_CASE_UPPER)) change_case = DEFAULT_CHANGE_CASE; data->change_case_combobox = _gtk_combo_box_new_with_texts (_("Keep original case"), _("Convert to lower-case"), _("Convert to upper-case"), NULL); gtk_combo_box_set_active (GTK_COMBO_BOX (data->change_case_combobox), change_case); gtk_widget_show (data->change_case_combobox); gtk_box_pack_start (GTK_BOX (GET_WIDGET ("change_case_box")), data->change_case_combobox, FALSE, FALSE, 0); gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("change_case_label")), data->change_case_combobox); /* Set the signals handlers. */ g_signal_connect (data->dialog, "delete-event", G_CALLBACK (gtk_true), NULL); g_signal_connect (data->dialog, "response", G_CALLBACK (dialog_response_cb), data); g_signal_connect (GET_WIDGET ("template_entry"), "icon-release", G_CALLBACK (template_entry_icon_release_cb), data); g_signal_connect (GET_WIDGET ("template_entry"), "changed", G_CALLBACK (update_preview_cb), data); g_signal_connect (GET_WIDGET("template_entry"), "activate", G_CALLBACK (return_pressed_callback), data); g_signal_connect (GET_WIDGET ("start_at_spinbutton"), "value_changed", G_CALLBACK (update_preview_cb), data); g_signal_connect (data->sort_combobox, "changed", G_CALLBACK (update_preview_cb), data); g_signal_connect (data->change_case_combobox, "changed", G_CALLBACK (update_preview_cb), data); g_signal_connect (GET_WIDGET ("reverse_order_checkbutton"), "toggled", G_CALLBACK (update_preview_cb), data); g_signal_connect (GET_WIDGET ("edit_template_button"), "clicked", G_CALLBACK (edit_template_button_clicked_cb), data); /* Run dialog. */ gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (browser)); gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE); gtk_widget_show (data->dialog); dlg_rename_series_update_preview (data); }