[gthumb] template editor: added preview, edit quoted text in another dialog
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] template editor: added preview, edit quoted text in another dialog
- Date: Sat, 19 Jun 2021 18:10:34 +0000 (UTC)
commit 7e15a036fea9ccb9b6b6b89299a36d31c0ea1b18
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sun May 16 12:47:53 2021 +0200
template editor: added preview, edit quoted text in another dialog
data/ui/code-selector.ui | 288 ++++++++++++++++--------
data/ui/meson.build | 3 +-
data/ui/template-editor-dialog.ui | 48 ++++
gthumb/gth-template-editor-dialog.c | 434 ++++++++++++++++++++++++++++--------
gthumb/gth-template-editor-dialog.h | 21 +-
gthumb/gth-template-selector.c | 385 +++++++++++++++++++++++++-------
gthumb/gth-template-selector.h | 32 ++-
gthumb/resources/gthumb.css | 9 +
8 files changed, 929 insertions(+), 291 deletions(-)
---
diff --git a/data/ui/code-selector.ui b/data/ui/code-selector.ui
index 739d8fb4..289fca59 100644
--- a/data/ui/code-selector.ui
+++ b/data/ui/code-selector.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
+<!-- Generated with glade 3.38.2 -->
<interface>
- <requires lib="gtk+" version="3.10"/>
+ <requires lib="gtk+" version="3.16"/>
<object class="GtkTreeStore" id="attribute_treestore">
<columns>
<!-- column-name id -->
@@ -24,8 +24,8 @@
<property name="lower">1</property>
<property name="upper">1000</property>
<property name="value">1</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
</object>
<object class="GtkListStore" id="type_liststore">
<columns>
@@ -36,14 +36,16 @@
</columns>
</object>
<object class="GtkBox" id="code_selector">
+ <property name="width-request">800</property>
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">2</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border-width">2</property>
<property name="spacing">6</property>
<child>
<object class="GtkComboBox" id="type_combobox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="model">type_liststore</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
@@ -59,38 +61,44 @@
</packing>
</child>
<child>
- <object class="GtkNotebook" id="type_notebook">
+ <object class="GtkStack" id="type_stack">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
+ <property name="can-focus">False</property>
+ <property name="hhomogeneous">False</property>
+ <property name="vhomogeneous">False</property>
<child>
- <object class="GtkEntry" id="text_entry">
+ <object class="GtkLabel" id="space_label">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
+ <property name="can-focus">False</property>
</object>
+ <packing>
+ <property name="name">space</property>
+ </packing>
</child>
- <child type="tab">
- <object class="GtkLabel" id="label1">
+ <child>
+ <object class="GtkEntry" id="text_entry">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">True</property>
+ <property name="invisible-char">●</property>
</object>
<packing>
- <property name="tab_fill">False</property>
+ <property name="name">text</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="hbox3">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkSpinButton" id="enumerator_digits_spinbutton">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
+ <property name="can-focus">True</property>
+ <property name="invisible-char">●</property>
+ <property name="text" translatable="yes">1</property>
<property name="adjustment">enumerator_digits_adjustment</property>
+ <property name="value">1</property>
</object>
<packing>
<property name="expand">False</property>
@@ -101,7 +109,7 @@
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="label" translatable="yes">digits</property>
</object>
<packing>
@@ -112,63 +120,43 @@
</child>
</object>
<packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
+ <property name="name">enumerator</property>
+ <property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox" id="hbox1">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<child>
- <placeholder/>
+ <object class="GtkLabel" id="example_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <attributes>
+ <attribute name="style" value="oblique"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
</child>
</object>
<packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="position">2</property>
- <property name="tab_fill">False</property>
+ <property name="name">simple</property>
+ <property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkBox" id="hbox4">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="label5">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">format:</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
<child>
<object class="GtkComboBox" id="date_format_combobox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="model">date_format_liststore</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
@@ -180,40 +168,31 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">1</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="custom_date_format_entry">
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
- <property name="secondary_icon_name">edit-delete-symbolic</property>
+ <property name="can-focus">True</property>
+ <property name="invisible-char">●</property>
+ <property name="secondary-icon-name">edit-delete-symbolic</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
<packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label6">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="position">3</property>
- <property name="tab_fill">False</property>
+ <property name="name">date</property>
+ <property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="attribute_combobox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="model">attribute_treestore</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext3"/>
@@ -223,17 +202,136 @@
</child>
</object>
<packing>
- <property name="position">4</property>
+ <property name="name">file_attribute</property>
+ <property name="position">5</property>
</packing>
</child>
- <child type="tab">
- <object class="GtkLabel" id="label7">
+ <child>
+ <object class="GtkBox">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="prompt_entry">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="width-chars">0</property>
+ <property name="placeholder-text" translatable="yes">Description</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkEntry" id="default_value_entry">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="width-chars">0</property>
+ <property name="secondary-icon-tooltip-markup" translatable="yes">Edit</property>
+ <property name="placeholder-text" translatable="yes">Default value</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="edit_default_value_button">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">document-edit-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
<packing>
- <property name="position">4</property>
- <property name="tab_fill">False</property>
+ <property name="name">ask_value</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkEntry" id="quoted_entry">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="width-chars">20</property>
+ <property name="placeholder-text" translatable="yes">Default value</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="edit_quoted_text_button">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">document-edit-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">quoted</property>
+ <property name="position">7</property>
</packing>
</child>
</object>
@@ -246,19 +344,19 @@
<child>
<object class="GtkBox" id="hbox2">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="remove_button">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">remove</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="tooltip-text" translatable="yes">remove</property>
<child>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">list-remove-symbolic</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">list-remove-symbolic</property>
</object>
</child>
</object>
@@ -271,14 +369,14 @@
<child>
<object class="GtkButton" id="add_button">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="tooltip_text" translatable="yes">add</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="tooltip-text" translatable="yes">add</property>
<child>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">list-add-symbolic</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">list-add-symbolic</property>
</object>
</child>
</object>
diff --git a/data/ui/meson.build b/data/ui/meson.build
index 07b50881..a6b9dbd8 100644
--- a/data/ui/meson.build
+++ b/data/ui/meson.build
@@ -11,6 +11,7 @@ ui_files = files(
'personalize-filters.ui',
'preferences.ui',
'shortcuts-preferences.ui',
- 'sort-order.ui'
+ 'sort-order.ui',
+ 'template-editor-dialog.ui'
)
install_data(ui_files, install_dir : ui_install_dir)
diff --git a/data/ui/template-editor-dialog.ui b/data/ui/template-editor-dialog.ui
new file mode 100644
index 00000000..6a9d9661
--- /dev/null
+++ b/data/ui/template-editor-dialog.ui
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface>
+ <requires lib="gtk+" version="3.24"/>
+ <object class="GtkBox" id="content">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">15</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="preview_label">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="wrap">True</property>
+ <property name="selectable">True</property>
+ <property name="width-chars">0</property>
+ <property name="max-width-chars">30</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <style>
+ <class name="terminal"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="selectors">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/gthumb/gth-template-editor-dialog.c b/gthumb/gth-template-editor-dialog.c
index 779b37a7..291770e9 100644
--- a/gthumb/gth-template-editor-dialog.c
+++ b/gthumb/gth-template-editor-dialog.c
@@ -22,19 +22,27 @@
#include <config.h>
#include <stdlib.h>
#include <gtk/gtk.h>
+#include "glib-utils.h"
#include "gtk-utils.h"
#include "gth-template-editor-dialog.h"
#include "gth-template-selector.h"
+#include "str-utils.h"
+#define UPDATE_PREVIEW_DELAY 100
#define GET_WIDGET(name) _gtk_builder_get_widget (self->priv->builder, (name))
struct _GthTemplateEditorDialogPrivate {
- GtkWidget *content;
- GRegex *re;
- GthTemplateCode *allowed_codes;
- int n_codes;
+ GtkBuilder *builder;
+ GtkWidget *selectors;
+ GtkWidget *preview;
+ GthTemplateCode *allowed_codes;
+ int n_codes;
+ gulong update_id;
+ TemplatePreviewFunc preview_func;
+ gpointer preview_data;
+ TemplateFlags template_flags;
};
@@ -47,12 +55,14 @@ G_DEFINE_TYPE_WITH_CODE (GthTemplateEditorDialog,
static void
gth_template_editor_dialog_finalize (GObject *object)
{
- GthTemplateEditorDialog *dialog;
+ GthTemplateEditorDialog *self = GTH_TEMPLATE_EDITOR_DIALOG (object);
- dialog = GTH_TEMPLATE_EDITOR_DIALOG (object);
-
- if (dialog->priv->re != NULL)
- g_regex_unref (dialog->priv->re);
+ if (self->priv->update_id != 0) {
+ g_source_remove (self->priv->update_id);
+ self->priv->update_id = 0;
+ }
+ _g_object_unref (self->priv->builder);
+ g_free (self->priv->allowed_codes);
G_OBJECT_CLASS (gth_template_editor_dialog_parent_class)->finalize (object);
}
@@ -69,13 +79,16 @@ gth_template_editor_dialog_class_init (GthTemplateEditorDialogClass *class)
static void
-gth_template_editor_dialog_init (GthTemplateEditorDialog *dialog)
+gth_template_editor_dialog_init (GthTemplateEditorDialog *self)
{
- dialog->priv = gth_template_editor_dialog_get_instance_private (dialog);
- dialog->priv->content = NULL;
- dialog->priv->re = NULL;
- dialog->priv->allowed_codes = NULL;
- dialog->priv->n_codes = 0;
+ self->priv = gth_template_editor_dialog_get_instance_private (self);
+ self->priv->selectors = NULL;
+ self->priv->allowed_codes = NULL;
+ self->priv->n_codes = 0;
+ self->priv->update_id = 0;
+ self->priv->preview_func = NULL;
+ self->priv->preview_data = NULL;
+ self->priv->template_flags = 0;
}
@@ -86,15 +99,167 @@ _gth_template_editor_update_sensitivity (GthTemplateEditorDialog *self)
gboolean many_selectors;
GList *scan;
- children = gtk_container_get_children (GTK_CONTAINER (self->priv->content));
+ children = gtk_container_get_children (GTK_CONTAINER (self->priv->selectors));
many_selectors = (children != NULL) && (children->next != NULL);
for (scan = children; scan; scan = scan->next)
- gth_template_selector_can_remove (GTH_TEMPLATE_SELECTOR (children->data), many_selectors);
+ gth_template_selector_can_remove (GTH_TEMPLATE_SELECTOR (scan->data), many_selectors);
g_list_free (children);
}
+static char *
+_get_preview_from_template (GthTemplateEditorDialog *self,
+ const char *template,
+ gboolean highlight_code)
+{
+ GString *preview;
+ char **template_v;
+ int i, j;
+ GTimeVal timeval;
+
+ if (template == NULL)
+ return g_strdup ("");
+
+ preview = g_string_new ("");
+ template_v = _g_template_tokenize (template, self->priv->template_flags);
+ for (i = 0; template_v[i] != NULL; i++) {
+ const char *token = template_v[i];
+ GthTemplateCode *code = NULL;
+
+ for (j = 0; (code == NULL) && (j < self->priv->n_codes); j++) {
+ GthTemplateCode *allowed_code = self->priv->allowed_codes + j;
+
+ switch (allowed_code->type) {
+ case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
+ if (token[0] == '#')
+ code = allowed_code;
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_TEXT:
+ case GTH_TEMPLATE_CODE_TYPE_SPACE:
+ /* ignore */
+ break;
+
+ default:
+ if (_g_template_token_is (token, allowed_code->code))
+ code = allowed_code;
+ break;
+ }
+ }
+
+ if (code != NULL) {
+ char **args;
+ char *text;
+
+ if (highlight_code)
+ g_string_append (preview, "<span foreground=\"#4696f8\">");
+
+ args = _g_template_get_token_args (template_v[i]);
+
+ switch (code->type) {
+ case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
+ text = _g_template_replace_enumerator (token, 1);
+ _g_string_append_markup_escaped (preview, "%s", text);
+ g_free (text);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_DATE:
+ g_get_current_time (&timeval);
+ text = _g_time_val_strftime (&timeval, (args[0] != NULL) ? args[0] :
DEFAULT_STRFTIME_FORMAT);
+ _g_string_append_markup_escaped (preview, "%s", text);
+ g_free (text);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE:
+ if (args[0] != NULL)
+ _g_string_append_markup_escaped (preview, "{ %s }", args[0]);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ASK_VALUE:
+ if ((args[0] != NULL) && (args[1] != NULL)) {
+ text = _get_preview_from_template (self, args[1], FALSE);
+ g_string_append (preview, text);
+ g_free (text);
+ }
+ else if (args[0] != NULL)
+ _g_string_append_markup_escaped (preview, "{ %s }", args[0]);
+ else
+ g_string_append_unichar (preview, code->code);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_QUOTED:
+ text = _get_preview_from_template (self, args[0], FALSE);
+ g_string_append_printf (preview, "'%s'", text);
+ g_free (text);
+ break;
+
+ default:
+ _g_string_append_markup_escaped (preview, "%s", token);
+ break;
+ }
+
+ if (highlight_code)
+ g_string_append (preview, "</span>");
+
+ g_strfreev (args);
+ }
+ else
+ _g_string_append_markup_escaped (preview, "%s", token);
+ }
+
+ g_strfreev (template_v);
+
+ return g_string_free (preview, FALSE);
+}
+
+
+static void
+_gth_template_editor_update_preview (GthTemplateEditorDialog *self)
+{
+ char *template;
+ char *preview;
+
+ template = gth_template_editor_dialog_get_template (self);
+ if (self->priv->preview_func != NULL)
+ preview = self->priv->preview_func (template,
+ self->priv->template_flags,
+ self->priv->preview_data);
+ else
+ preview = _get_preview_from_template (self, template, TRUE);
+
+ gtk_label_set_markup (GTK_LABEL (self->priv->preview), preview);
+
+ g_free (preview);
+ g_free (template);
+}
+
+
+static gboolean
+update_preview_cb (gpointer user_data)
+{
+ GthTemplateEditorDialog *self = user_data;
+
+ if (self->priv->update_id != 0) {
+ g_source_remove (self->priv->update_id);
+ self->priv->update_id = 0;
+ }
+
+ _gth_template_editor_update_preview (self);
+
+ return FALSE;
+}
+
+
+static void
+_gth_template_editor_queue_update_preview (GthTemplateEditorDialog *self)
+{
+ if (self->priv->update_id != 0)
+ g_source_remove (self->priv->update_id);
+ self->priv->update_id = g_timeout_add (UPDATE_PREVIEW_DELAY, update_preview_cb, self);
+}
+
+
static GtkWidget * _gth_template_editor_create_selector (GthTemplateEditorDialog *self);
@@ -105,9 +270,14 @@ selector_add_template_cb (GthTemplateSelector *selector,
GtkWidget *child;
child = _gth_template_editor_create_selector (self);
- gtk_box_pack_start (GTK_BOX (self->priv->content), child, FALSE, FALSE, 0);
- gtk_box_reorder_child (GTK_BOX (self->priv->content), child, _gtk_container_get_pos (GTK_CONTAINER
(self->priv->content), GTK_WIDGET (selector)) + 1);
+ gtk_box_pack_start (GTK_BOX (self->priv->selectors), child, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (self->priv->selectors),
+ child,
+ _gtk_container_get_pos (GTK_CONTAINER (self->priv->selectors),
+ GTK_WIDGET (selector)) + 1);
_gth_template_editor_update_sensitivity (self);
+ _gth_template_editor_queue_update_preview (self);
+ gth_template_selector_focus (GTH_TEMPLATE_SELECTOR (child));
}
@@ -117,6 +287,72 @@ selector_remove_template_cb (GthTemplateSelector *selector,
{
gtk_widget_destroy (GTK_WIDGET (selector));
_gth_template_editor_update_sensitivity (self);
+ _gth_template_editor_queue_update_preview (self);
+}
+
+
+static void
+selector_editor_dialog_response_cb (GtkDialog *dialog,
+ int response_id,
+ gpointer user_data)
+{
+ GtkEntry *entry = user_data;
+ char *value;
+
+ switch (response_id) {
+ case GTK_RESPONSE_OK:
+ value = gth_template_editor_dialog_get_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog));
+ if (value != NULL) {
+ gtk_entry_set_text (entry, value);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+
+ g_free (value);
+ }
+ break;
+
+ default:
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ }
+}
+
+
+static void
+selector_edit_template_cb (GthTemplateSelector *selector,
+ GtkEntry *entry,
+ GthTemplateEditorDialog *self)
+{
+ GthTemplateCode *code;
+ GtkWidget *dialog;
+
+ code = gth_template_selector_get_code (selector);
+ if (code == NULL)
+ return;
+
+ dialog = gth_template_editor_dialog_new (self->priv->allowed_codes,
+ self->priv->n_codes,
+ self->priv->template_flags | TEMPLATE_FLAGS_PARTIAL,
+ gtk_window_get_title (GTK_WINDOW (self)),
+ GTK_WINDOW (self));
+ gth_template_editor_dialog_set_preview_func (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+ self->priv->preview_func,
+ self->priv->preview_data);
+ gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+ gtk_entry_get_text (entry));
+
+ g_signal_connect (dialog,
+ "response",
+ G_CALLBACK (selector_editor_dialog_response_cb),
+ entry);
+ gtk_widget_show (dialog);
+}
+
+
+static void
+selector_changed_cb (GthTemplateSelector *selector,
+ GthTemplateEditorDialog *self)
+{
+ _gth_template_editor_queue_update_preview (self);
}
@@ -126,6 +362,7 @@ _gth_template_editor_create_selector (GthTemplateEditorDialog *self)
GtkWidget *child;
child = gth_template_selector_new (self->priv->allowed_codes, self->priv->n_codes);
+ gth_template_selector_set_value (GTH_TEMPLATE_SELECTOR (child), "");
gtk_widget_show (child);
g_signal_connect (child,
@@ -136,6 +373,14 @@ _gth_template_editor_create_selector (GthTemplateEditorDialog *self)
"remove_template",
G_CALLBACK (selector_remove_template_cb),
self);
+ g_signal_connect (child,
+ "edit_template",
+ G_CALLBACK (selector_edit_template_cb),
+ self);
+ g_signal_connect (child,
+ "changed",
+ G_CALLBACK (selector_changed_cb),
+ self);
return child;
}
@@ -145,94 +390,85 @@ static void
gth_template_editor_dialog_construct (GthTemplateEditorDialog *self,
GthTemplateCode *allowed_codes,
int n_codes,
+ TemplateFlags template_flags,
const char *title,
GtkWindow *parent)
{
- GtkWidget *child;
- GString *regexp;
- GString *special_codes;
- int i;
-
- self->priv->allowed_codes = allowed_codes;
- self->priv->n_codes = n_codes;
+ GtkWidget *content;
+ int i, j;
+ gboolean has_enumerator;
- if (title != NULL)
- gtk_window_set_title (GTK_WINDOW (self), title);
- if (parent != NULL)
- gtk_window_set_transient_for (GTK_WINDOW (self), parent);
- gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
- gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 5);
- gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+ self->priv->n_codes = n_codes + 2;
+ self->priv->allowed_codes = g_new0 (GthTemplateCode, self->priv->n_codes);
- gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
- gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_OK, GTK_RESPONSE_OK);
+ j = 0;
- _gtk_dialog_add_class_to_response (GTK_DIALOG (self), GTK_RESPONSE_OK,
GTK_STYLE_CLASS_SUGGESTED_ACTION);
+ self->priv->allowed_codes[j].type = GTH_TEMPLATE_CODE_TYPE_TEXT;
+ self->priv->allowed_codes[j].description = N_("Text");
+ j++;
- self->priv->content = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
- gtk_container_set_border_width (GTK_CONTAINER (self->priv->content), 5);
- gtk_widget_show (self->priv->content);
- gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), self->priv->content,
TRUE, TRUE, 0);
+ self->priv->allowed_codes[j].type = GTH_TEMPLATE_CODE_TYPE_SPACE;
+ /* Translators: The space character not the Astronomy space. */
+ self->priv->allowed_codes[j].description = N_("Space");
+ j++;
- child = _gth_template_editor_create_selector (self);
- gtk_box_pack_start (GTK_BOX (self->priv->content), child, FALSE, FALSE, 0);
+ has_enumerator = FALSE;
+ for (i = 0; i < n_codes; i++) {
+ if ((allowed_codes[i].type == GTH_TEMPLATE_CODE_TYPE_TEXT)
+ || (allowed_codes[i].type == GTH_TEMPLATE_CODE_TYPE_SPACE))
+ {
+ self->priv->n_codes--;
+ continue;
+ }
- _gth_template_editor_update_sensitivity (self);
+ self->priv->allowed_codes[j] = allowed_codes[i];
+ if (self->priv->allowed_codes[j].type == GTH_TEMPLATE_CODE_TYPE_ENUMERATOR)
+ has_enumerator = TRUE;
- /* build the regular expression to compile the template */
+ j++;
+ }
- regexp = g_string_new ("");
- special_codes = g_string_new ("");
+ self->priv->template_flags = template_flags;
+ if (! has_enumerator)
+ self->priv->template_flags |= TEMPLATE_FLAGS_NO_ENUMERATOR;
- for (i = 0; i < n_codes; i++) {
- GthTemplateCode *code = &allowed_codes[i];
-
- switch (code->type) {
- case GTH_TEMPLATE_CODE_TYPE_TEXT:
- break;
- case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
- if (regexp->len > 0)
- g_string_append (regexp, "|");
- g_string_append (regexp, "(");
- g_string_append_c (regexp, code->code);
- g_string_append (regexp, "+)");
- break;
- case GTH_TEMPLATE_CODE_TYPE_SIMPLE:
- case GTH_TEMPLATE_CODE_TYPE_DATE:
- case GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE:
- g_string_append_c (special_codes, code->code);
- break;
- }
+ if (title != NULL)
+ gtk_window_set_title (GTK_WINDOW (self), title);
+ if (parent != NULL) {
+ gtk_window_set_transient_for (GTK_WINDOW (self), parent);
+ _gtk_dialog_add_to_window_group (GTK_DIALOG (self));
+ gtk_window_set_modal (GTK_WINDOW (self), TRUE);
}
+ gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
- if (special_codes->len > 0) {
- /* special code with a custom format */
+ gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_OK, GTK_RESPONSE_OK);
- if (regexp->len > 0)
- g_string_append (regexp, "|");
- g_string_append (regexp, "(%[");
- g_string_append (regexp, special_codes->str);
- g_string_append (regexp, "]{[^}]+\\})");
+ _gtk_dialog_add_class_to_response (GTK_DIALOG (self), GTK_RESPONSE_OK,
GTK_STYLE_CLASS_SUGGESTED_ACTION);
- /* special codes without a custom format */
+ self->priv->builder = _gtk_builder_new_from_file ("template-editor-dialog.ui", NULL);
- g_string_append (regexp, "|");
- g_string_append (regexp, "(%[");
- g_string_append (regexp, special_codes->str);
- g_string_append (regexp, "])");
+ content = _gtk_builder_get_widget (self->priv->builder, "content");
+ gtk_widget_show (content);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), content, TRUE, TRUE,
0);
- }
+ self->priv->preview = _gtk_builder_get_widget (self->priv->builder, "preview_label");
+ self->priv->selectors = _gtk_builder_get_widget (self->priv->builder, "selectors");
- self->priv->re = g_regex_new (regexp->str, 0, 0, NULL);
+ gtk_box_pack_start (GTK_BOX (self->priv->selectors),
+ _gth_template_editor_create_selector (self),
+ FALSE,
+ FALSE,
+ 0);
- g_string_free (special_codes, TRUE);
- g_string_free (regexp, TRUE);
+ _gth_template_editor_update_sensitivity (self);
}
GtkWidget *
gth_template_editor_dialog_new (GthTemplateCode *allowed_codes,
int n_codes,
+ TemplateFlags template_flags,
const char *title,
GtkWindow *parent)
{
@@ -241,7 +477,7 @@ gth_template_editor_dialog_new (GthTemplateCode *allowed_codes,
self = g_object_new (GTH_TYPE_TEMPLATE_EDITOR_DIALOG,
"use-header-bar", _gtk_settings_get_dialogs_use_header (),
NULL);
- gth_template_editor_dialog_construct (self, allowed_codes, n_codes, title, parent);
+ gth_template_editor_dialog_construct (self, allowed_codes, n_codes, template_flags, title, parent);
return (GtkWidget *) self;
}
@@ -254,9 +490,9 @@ gth_template_editor_dialog_set_template (GthTemplateEditorDialog *self,
char **template_v;
int i;
- _gtk_container_remove_children (GTK_CONTAINER (self->priv->content), NULL, NULL);
+ _gtk_container_remove_children (GTK_CONTAINER (self->priv->selectors), NULL, NULL);
- template_v = g_regex_split (self->priv->re, template, 0);
+ template_v = _g_template_tokenize (template, self->priv->template_flags);
for (i = 0; template_v[i] != NULL; i++) {
GtkWidget *child;
@@ -264,31 +500,41 @@ gth_template_editor_dialog_set_template (GthTemplateEditorDialog *self,
continue;
child = _gth_template_editor_create_selector (self);
- gtk_box_pack_start (GTK_BOX (self->priv->content), child, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (self->priv->selectors), child, FALSE, FALSE, 0);
gth_template_selector_set_value (GTH_TEMPLATE_SELECTOR (child), template_v[i]);
}
+ if (template_v[0] == NULL) {
+ GtkWidget *child;
+
+ /* Empty template. */
+
+ child = _gth_template_editor_create_selector (self);
+ gtk_box_pack_start (GTK_BOX (self->priv->selectors), child, FALSE, FALSE, 0);
+ gth_template_selector_set_value (GTH_TEMPLATE_SELECTOR (child), "");
+ }
+
_gth_template_editor_update_sensitivity (self);
+ _gth_template_editor_update_preview (self);
g_strfreev (template_v);
}
char *
-gth_template_editor_dialog_get_template (GthTemplateEditorDialog *self,
- GError **error)
+gth_template_editor_dialog_get_template (GthTemplateEditorDialog *self)
{
GString *template;
GList *children;
GList *scan;
template = g_string_new ("");
- children = gtk_container_get_children (GTK_CONTAINER (self->priv->content));
+ children = gtk_container_get_children (GTK_CONTAINER (self->priv->selectors));
for (scan = children; scan; scan = scan->next) {
GtkWidget *child = scan->data;
char *value;
- value = gth_template_selector_get_value (GTH_TEMPLATE_SELECTOR (child), NULL);
+ value = gth_template_selector_get_value (GTH_TEMPLATE_SELECTOR (child));
if (value != NULL) {
g_string_append (template, value);
g_free (value);
@@ -299,3 +545,13 @@ gth_template_editor_dialog_get_template (GthTemplateEditorDialog *self,
return g_string_free (template, FALSE);
}
+
+
+void
+gth_template_editor_dialog_set_preview_func (GthTemplateEditorDialog *self,
+ TemplatePreviewFunc func,
+ gpointer user_data)
+{
+ self->priv->preview_func = func;
+ self->priv->preview_data = user_data;
+}
diff --git a/gthumb/gth-template-editor-dialog.h b/gthumb/gth-template-editor-dialog.h
index e6890ffd..7e7b37f6 100644
--- a/gthumb/gth-template-editor-dialog.h
+++ b/gthumb/gth-template-editor-dialog.h
@@ -47,15 +47,18 @@ struct _GthTemplateEditorDialogClass {
GtkDialogClass parent_class;
};
-GType gth_template_editor_dialog_get_type (void);
-GtkWidget * gth_template_editor_dialog_new (GthTemplateCode *allowed_codes,
- int n_codes,
- const char *title,
- GtkWindow *parent);
-void gth_template_editor_dialog_set_template (GthTemplateEditorDialog *self,
- const char *value);
-char * gth_template_editor_dialog_get_template (GthTemplateEditorDialog *self,
- GError **error);
+GType gth_template_editor_dialog_get_type (void);
+GtkWidget * gth_template_editor_dialog_new (GthTemplateCode *allowed_codes,
+ int n_codes,
+ TemplateFlags template_flags,
+ const char *title,
+ GtkWindow *parent);
+void gth_template_editor_dialog_set_template (GthTemplateEditorDialog *self,
+ const char *value);
+char * gth_template_editor_dialog_get_template (GthTemplateEditorDialog *self);
+void gth_template_editor_dialog_set_preview_func (GthTemplateEditorDialog *self,
+ TemplatePreviewFunc func,
+ gpointer user_data);
G_END_DECLS
diff --git a/gthumb/gth-template-selector.c b/gthumb/gth-template-selector.c
index 958a7ac8..df9c75bb 100644
--- a/gthumb/gth-template-selector.c
+++ b/gthumb/gth-template-selector.c
@@ -29,7 +29,6 @@
#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
-
enum {
TYPE_DATA_COLUMN,
TYPE_NAME_COLUMN,
@@ -52,6 +51,8 @@ enum {
enum {
ADD_TEMPLATE,
REMOVE_TEMPLATE,
+ EDIT_TEMPLATE,
+ CHANGED,
LAST_SIGNAL
};
@@ -60,6 +61,16 @@ struct _GthTemplateSelectorPrivate {
GtkBuilder *builder;
};
+static char *TypeName[] = {
+ "space",
+ "text",
+ "enumerator",
+ "simple",
+ "date",
+ "file_attribute",
+ "ask_value",
+ "quoted"
+};
G_DEFINE_TYPE_WITH_CODE (GthTemplateSelector,
gth_template_selector,
@@ -67,7 +78,18 @@ G_DEFINE_TYPE_WITH_CODE (GthTemplateSelector,
G_ADD_PRIVATE (GthTemplateSelector))
-static char * Date_Formats[] = { "%Y-%m-%d--%H.%M.%S", "%Y-%m-%d", "%x %X", "%x", NULL };
+static char * Date_Formats[] = {
+ "%Y-%m-%d--%H.%M.%S",
+ "%x %X",
+ "%Y%m%d%H%M%S",
+ "%Y-%m-%d",
+ "%x",
+ "%Y%m%d",
+ "%H.%M.%S",
+ "%X",
+ "%H%M%S",
+ NULL
+};
static guint gth_template_selector_signals[LAST_SIGNAL] = { 0 };
@@ -109,6 +131,25 @@ gth_template_selector_class_init (GthTemplateSelectorClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
+ gth_template_selector_signals[EDIT_TEMPLATE] =
+ g_signal_new ("edit-template",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthTemplateSelectorClass, edit_template),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_ENTRY);
+ gth_template_selector_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthTemplateSelectorClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
}
@@ -138,22 +179,38 @@ remove_button_clicked_cb (GtkButton *button,
}
+static void
+edit_quoted_text_button_clicked_cb (GtkButton *button,
+ GthTemplateSelector *self)
+{
+ GtkWidget *entry = GET_WIDGET ("quoted_entry");
+
+ gtk_widget_grab_focus (entry);
+ g_signal_emit (self, gth_template_selector_signals[EDIT_TEMPLATE], 0, entry);
+}
+
+
+static void
+_gth_template_selector_changed (GthTemplateSelector *self)
+{
+ g_signal_emit (self, gth_template_selector_signals[CHANGED], 0);
+}
+
+
static void
type_combobox_changed_cb (GtkComboBox *combo_box,
GthTemplateSelector *self)
{
- GtkTreeIter iter;
GthTemplateCode *code;
- if (! gtk_combo_box_get_active_iter (combo_box, &iter))
+ code = gth_template_selector_get_code (self);
+ if (code == NULL)
return;
- gtk_tree_model_get (GTK_TREE_MODEL (GET_WIDGET ("type_liststore")),
- &iter,
- TYPE_DATA_COLUMN, &code,
- -1);
+ gtk_stack_set_visible_child_name (GTK_STACK (GET_WIDGET ("type_stack")), TypeName[code->type]);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("type_notebook")), code->type);
+ gth_template_selector_focus (self);
+ _gth_template_selector_changed (self);
}
@@ -173,6 +230,8 @@ date_format_combobox_changed_cb (GtkComboBox *combo_box,
gtk_widget_show (GET_WIDGET ("date_format_combobox"));
gtk_widget_hide (GET_WIDGET ("custom_date_format_entry"));
}
+
+ _gth_template_selector_changed (self);
}
@@ -184,8 +243,37 @@ custom_date_format_entry_icon_release_cb (GtkEntry *entry,
{
GthTemplateSelector *self = user_data;
- if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
+ if (icon_pos == GTK_ENTRY_ICON_SECONDARY) {
gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("date_format_combobox")), 0);
+ _gth_template_selector_changed (self);
+ }
+}
+
+
+static void
+editable_changed_cb (GtkEditable *editable,
+ gpointer user_data)
+{
+ _gth_template_selector_changed (GTH_TEMPLATE_SELECTOR (user_data));
+}
+
+
+static void
+attribute_combobox_changed_cb (GtkComboBox *combo_box,
+ gpointer user_data)
+{
+ _gth_template_selector_changed (GTH_TEMPLATE_SELECTOR (user_data));
+}
+
+
+static void
+edit_default_value_button_clicked_cb (GtkButton *button,
+ GthTemplateSelector *self)
+{
+ GtkWidget *entry = GET_WIDGET ("default_value_entry");
+
+ gtk_widget_grab_focus (entry);
+ g_signal_emit (self, gth_template_selector_signals[EDIT_TEMPLATE], 0, entry);
}
@@ -223,7 +311,7 @@ gth_template_selector_construct (GthTemplateSelector *self,
-1);
}
- gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("type_notebook")),
GTH_TEMPLATE_CODE_TYPE_SIMPLE);
+ gtk_stack_set_visible_child_name (GTK_STACK (GET_WIDGET ("type_stack")),
TypeName[GTH_TEMPLATE_CODE_TYPE_SIMPLE]);
/* date formats */
@@ -328,6 +416,42 @@ gth_template_selector_construct (GthTemplateSelector *self,
"icon-release",
G_CALLBACK (custom_date_format_entry_icon_release_cb),
self);
+ g_signal_connect (GET_WIDGET ("custom_date_format_entry"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("edit_quoted_text_button"),
+ "clicked",
+ G_CALLBACK (edit_quoted_text_button_clicked_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("quoted_entry"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("text_entry"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("enumerator_digits_spinbutton"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("attribute_combobox"),
+ "changed",
+ G_CALLBACK (attribute_combobox_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("prompt_entry"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("default_value_entry"),
+ "changed",
+ G_CALLBACK (editable_changed_cb),
+ self);
+ g_signal_connect (GET_WIDGET ("edit_default_value_button"),
+ "clicked",
+ G_CALLBACK (edit_default_value_button_clicked_cb),
+ self);
}
@@ -344,26 +468,6 @@ gth_template_selector_new (GthTemplateCode *allowed_codes,
}
-static char *
-get_format_from_value (const char *value)
-{
- char *format = NULL;
- GRegex *re;
- char **a;
- int i;
-
- re = g_regex_new ("%.\\{([^}]+)\\}", 0, 0, NULL);
- a = g_regex_split (re, value, 0);
- for (i = 1; i < g_strv_length (a); i += 2)
- format = g_strstrip (g_strdup (a[i]));
-
- g_strfreev (a);
- g_regex_unref (re);
-
- return format;
-}
-
-
static gboolean
_gtk_tree_model_get_iter_from_attribute_id (GtkTreeModel *tree_model,
GtkTreeIter *root,
@@ -404,15 +508,14 @@ void
gth_template_selector_set_value (GthTemplateSelector *self,
const char *value)
{
- GthTemplateCode *code = NULL;
- GtkTreeModel *tree_model;
- GtkTreeIter iter;
- GtkTreeIter text_iter;
- gboolean allows_text = FALSE;
- int i;
- gboolean predefined_format;
- char *format;
- char *attribute_id;
+ GthTemplateCode *code = NULL;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ GtkTreeIter text_iter, space_iter;
+ int i;
+ gboolean predefined_format;
+ char **args;
+ char *arg;
tree_model = (GtkTreeModel *) GET_WIDGET ("type_liststore");
if (gtk_tree_model_get_iter_first (tree_model, &iter)) {
@@ -424,38 +527,46 @@ gth_template_selector_set_value (GthTemplateSelector *self,
TYPE_DATA_COLUMN, &iter_code,
-1);
- if (iter_code->type == GTH_TEMPLATE_CODE_TYPE_TEXT) {
- allows_text = TRUE;
+ switch (iter_code->type) {
+ case GTH_TEMPLATE_CODE_TYPE_TEXT:
text_iter = iter;
- }
+ break;
- if ((value[0] == '%')
- && ((iter_code->type == GTH_TEMPLATE_CODE_TYPE_SIMPLE)
- || (iter_code->type == GTH_TEMPLATE_CODE_TYPE_DATE)
- || (iter_code->type == GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE))
- && (value[1] == iter_code->code))
- {
- code = iter_code;
- }
- else if ((iter_code->type == GTH_TEMPLATE_CODE_TYPE_ENUMERATOR) && (value[0] ==
iter_code->code)) {
- code = iter_code;
+ case GTH_TEMPLATE_CODE_TYPE_SPACE:
+ space_iter = iter;
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
+ if (g_str_has_prefix (value, "#"))
+ code = iter_code;
+ break;
+
+ default:
+ if (_g_template_token_is (value, iter_code->code))
+ code = iter_code;
+ break;
}
}
while ((code == NULL) && gtk_tree_model_iter_next (tree_model, &iter));
}
- if ((code == NULL) && ! allows_text)
- return;
-
- if ((code == NULL) && allows_text) {
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")), &text_iter);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("type_notebook")),
GTH_TEMPLATE_CODE_TYPE_TEXT);
- gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("text_entry")), value);
+ if (code == NULL) {
+ if (_g_str_equal (value, " ")) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")),
&space_iter);
+ gtk_stack_set_visible_child_name (GTK_STACK (GET_WIDGET ("type_stack")),
TypeName[GTH_TEMPLATE_CODE_TYPE_SPACE]);
+ }
+ else {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")),
&text_iter);
+ gtk_stack_set_visible_child_name (GTK_STACK (GET_WIDGET ("type_stack")),
TypeName[GTH_TEMPLATE_CODE_TYPE_TEXT]);
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("text_entry")), value);
+ }
return;
}
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")), &iter);
- gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("type_notebook")), code->type);
+ gtk_stack_set_visible_child_name (GTK_STACK (GET_WIDGET ("type_stack")), TypeName[code->type]);
+
+ args = _g_template_get_token_args (value);
switch (code->type) {
case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
@@ -464,11 +575,11 @@ gth_template_selector_set_value (GthTemplateSelector *self,
case GTH_TEMPLATE_CODE_TYPE_DATE:
predefined_format = FALSE;
- format = get_format_from_value (value);
- if (format == NULL)
- format = g_strdup (DEFAULT_STRFTIME_FORMAT);
+ arg = g_strdup (args[0]);
+ if (arg == NULL)
+ arg = g_strdup (DEFAULT_STRFTIME_FORMAT);
for (i = 0; Date_Formats[i] != NULL; i++) {
- if (g_str_equal (format, Date_Formats[i])) {
+ if (g_str_equal (arg, Date_Formats[i])) {
gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET
("date_format_combobox")), i);
predefined_format = TRUE;
break;
@@ -476,67 +587,78 @@ gth_template_selector_set_value (GthTemplateSelector *self,
}
if (! predefined_format) {
gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("date_format_combobox")),
G_N_ELEMENTS (Date_Formats) - 1);
- gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("custom_date_format_entry")), format);
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("custom_date_format_entry")), arg);
}
- g_free (format);
+ g_free (arg);
break;
case GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE:
- attribute_id = get_format_from_value (value);
- if (attribute_id != NULL) {
+ if (args[0] != NULL) {
GtkTreeModel *tree_model;
GtkTreeIter iter;
tree_model = (GtkTreeModel *) GET_WIDGET ("attribute_treestore");
- if (_gtk_tree_model_get_iter_from_attribute_id (tree_model, NULL, attribute_id,
&iter))
+ if (_gtk_tree_model_get_iter_from_attribute_id (tree_model, NULL, args[0], &iter))
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (GET_WIDGET
("attribute_combobox")), &iter);
}
- g_free (attribute_id);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ASK_VALUE:
+ if (args[0] != NULL)
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("prompt_entry")), args[0]);
+ if (args[1] != NULL)
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("default_value_entry")), args[1]);
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_QUOTED:
+ if (args[0] != NULL)
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("quoted_entry")), args[0]);
break;
default:
break;
}
+
+ g_strfreev (args);
}
char *
-gth_template_selector_get_value (GthTemplateSelector *self,
- GError **error)
+gth_template_selector_get_value (GthTemplateSelector *self)
{
+ GthTemplateCode *code;
GString *value;
GtkTreeIter iter;
- GthTemplateCode *code;
int i;
- if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")), &iter))
+ code = gth_template_selector_get_code (self);
+ if (code == NULL)
return NULL;
- gtk_tree_model_get (GTK_TREE_MODEL (GET_WIDGET ("type_liststore")),
- &iter,
- TYPE_DATA_COLUMN, &code,
- -1);
-
value = g_string_new ("");
switch (code->type) {
+ case GTH_TEMPLATE_CODE_TYPE_SPACE:
+ g_string_append_c (value, ' ');
+ break;
+
case GTH_TEMPLATE_CODE_TYPE_TEXT:
g_string_append (value, gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("text_entry"))));
break;
case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
for (i = 0; i < gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (GET_WIDGET
("enumerator_digits_spinbutton"))); i++)
- g_string_append_c (value, code->code);
+ g_string_append_c (value, '#');
break;
case GTH_TEMPLATE_CODE_TYPE_SIMPLE:
- g_string_append (value, "%");
- g_string_append_c (value, code->code);
+ g_string_append_c (value, '%');
+ g_string_append_unichar (value, code->code);
break;
case GTH_TEMPLATE_CODE_TYPE_DATE:
- g_string_append (value, "%");
- g_string_append_c (value, code->code);
+ g_string_append_c (value, '%');
+ g_string_append_unichar (value, code->code);
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("date_format_combobox")),
&iter)) {
char *format;
@@ -564,12 +686,27 @@ gth_template_selector_get_value (GthTemplateSelector *self,
ATTRIBUTE_ID_COLUMN, &attribute_id,
-1);
if ((attribute_id != NULL) && (strcmp (attribute_id, "") != 0)) {
- g_string_append_printf (value, "%%%c{ %s }", code->code, attribute_id);
+ g_string_append_c (value, '%');
+ g_string_append_unichar (value, code->code);
+ g_string_append_printf (value, "{ %s }", attribute_id);
}
g_free (attribute_id);
}
break;
+
+ case GTH_TEMPLATE_CODE_TYPE_QUOTED:
+ g_string_append_c (value, '%');
+ g_string_append_unichar (value, code->code);
+ g_string_append_printf (value, "{ %s }", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET
("quoted_entry"))));
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ASK_VALUE:
+ g_string_append_c (value, '%');
+ g_string_append_unichar (value, code->code);
+ g_string_append_printf (value, "{ %s }", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET
("prompt_entry"))));
+ g_string_append_printf (value, "{ %s }", gtk_entry_get_text (GTK_ENTRY (GET_WIDGET
("default_value_entry"))));
+ break;
}
return g_string_free (value, FALSE);
@@ -582,3 +719,79 @@ gth_template_selector_can_remove (GthTemplateSelector *self,
{
gtk_widget_set_sensitive (GET_WIDGET ("remove_button"), value);
}
+
+
+void
+gth_template_selector_set_quoted (GthTemplateSelector *self,
+ const char *value)
+{
+ gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("quoted_entry")), value);
+ _gth_template_selector_changed (self);
+}
+
+
+void
+gth_template_selector_focus (GthTemplateSelector *self)
+{
+ GthTemplateCode *code;
+ GtkWidget *focused = NULL;
+
+ code = gth_template_selector_get_code (self);
+ if (code == NULL)
+ return;
+
+ focused = GET_WIDGET ("type_combobox");
+
+ switch (code->type) {
+ case GTH_TEMPLATE_CODE_TYPE_SPACE:
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_TEXT:
+ focused = GET_WIDGET ("text_entry");
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ENUMERATOR:
+ focused = GET_WIDGET ("enumerator_digits_spinbutton");
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_SIMPLE:
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_DATE:
+ focused = GET_WIDGET ("date_format_combobox");
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE:
+ focused = GET_WIDGET ("attribute_combobox");
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_QUOTED:
+ focused = GET_WIDGET ("quoted_entry");
+ break;
+
+ case GTH_TEMPLATE_CODE_TYPE_ASK_VALUE:
+ focused = GET_WIDGET ("prompt_entry");
+ break;
+ }
+
+ if (focused != NULL)
+ gtk_widget_grab_focus (focused);
+}
+
+
+GthTemplateCode *
+gth_template_selector_get_code (GthTemplateSelector *self)
+{
+ GtkTreeIter iter;
+ GthTemplateCode *code = NULL;
+
+ if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (GET_WIDGET ("type_combobox")), &iter))
+ return NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (GET_WIDGET ("type_liststore")),
+ &iter,
+ TYPE_DATA_COLUMN, &code,
+ -1);
+
+ return code;
+}
diff --git a/gthumb/gth-template-selector.h b/gthumb/gth-template-selector.h
index 9e0490aa..e7d151b6 100644
--- a/gthumb/gth-template-selector.h
+++ b/gthumb/gth-template-selector.h
@@ -27,17 +27,21 @@
G_BEGIN_DECLS
typedef enum {
+ GTH_TEMPLATE_CODE_TYPE_SPACE,
GTH_TEMPLATE_CODE_TYPE_TEXT,
GTH_TEMPLATE_CODE_TYPE_ENUMERATOR,
GTH_TEMPLATE_CODE_TYPE_SIMPLE,
GTH_TEMPLATE_CODE_TYPE_DATE,
- GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE
+ GTH_TEMPLATE_CODE_TYPE_FILE_ATTRIBUTE,
+ GTH_TEMPLATE_CODE_TYPE_ASK_VALUE,
+ GTH_TEMPLATE_CODE_TYPE_QUOTED
} GthTemplateCodeType;
typedef struct {
GthTemplateCodeType type;
char *description;
- char code;
+ gunichar code;
+ int n_args;
} GthTemplateCode;
#define GTH_TYPE_TEMPLATE_SELECTOR (gth_template_selector_get_type ())
@@ -61,17 +65,23 @@ struct _GthTemplateSelectorClass {
void (*add_template) (GthTemplateSelector *selector);
void (*remove_template) (GthTemplateSelector *selector);
+ void (*edit_template) (GthTemplateSelector *selector,
+ GtkEntry *entry);
+ void (*changed) (GthTemplateSelector *selector);
};
-GType gth_template_selector_get_type (void);
-GtkWidget * gth_template_selector_new (GthTemplateCode *allowed_codes,
- int n_codes);
-void gth_template_selector_set_value (GthTemplateSelector *selector,
- const char *value);
-char * gth_template_selector_get_value (GthTemplateSelector *selector,
- GError **error);
-void gth_template_selector_can_remove (GthTemplateSelector *selector,
- gboolean value);
+GType gth_template_selector_get_type (void);
+GtkWidget * gth_template_selector_new (GthTemplateCode *allowed_codes,
+ int n_codes);
+void gth_template_selector_set_value (GthTemplateSelector *selector,
+ const char *value);
+char * gth_template_selector_get_value (GthTemplateSelector *selector);
+void gth_template_selector_can_remove (GthTemplateSelector *selector,
+ gboolean value);
+void gth_template_selector_set_quoted (GthTemplateSelector *selector,
+ const char *value);
+void gth_template_selector_focus (GthTemplateSelector *selector);
+GthTemplateCode * gth_template_selector_get_code (GthTemplateSelector *selector);
G_END_DECLS
diff --git a/gthumb/resources/gthumb.css b/gthumb/resources/gthumb.css
index 66f9b122..980517f2 100644
--- a/gthumb/resources/gthumb.css
+++ b/gthumb/resources/gthumb.css
@@ -174,3 +174,12 @@ GthToolbox .header-bar,
.revert-shortcut-button {
padding: 0;
}
+
+/* -- terminal-like label, used for the template preview -- */
+
+.terminal {
+ background-color: #000;
+ color: #fff;
+ padding: 20px;
+ font-family: monospace;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]