[gthumb] importer: use the template editor to specify the subfolder template



commit f6a4673650bb7e81b810e27ac4bf473c7fa456a9
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Wed Jun 2 12:47:43 2021 +0200

    importer: use the template editor to specify the subfolder template

 .../gschemas/org.gnome.gthumb.importer.gschema.xml |  11 +-
 extensions/importer/data/ui/import-preferences.ui  | 568 +++++----------------
 .../importer/gth-import-destination-button.c       |  30 +-
 .../importer/gth-import-preferences-dialog.c       | 370 +++++++-------
 .../importer/gth-import-preferences-dialog.h       |   2 +-
 extensions/importer/preferences.h                  |   5 +-
 extensions/importer/utils.c                        | 152 +++---
 extensions/importer/utils.h                        |  26 +-
 8 files changed, 404 insertions(+), 760 deletions(-)
---
diff --git a/data/gschemas/org.gnome.gthumb.importer.gschema.xml 
b/data/gschemas/org.gnome.gthumb.importer.gschema.xml
index df8460f6..9bff2d9b 100644
--- a/data/gschemas/org.gnome.gthumb.importer.gschema.xml
+++ b/data/gschemas/org.gnome.gthumb.importer.gschema.xml
@@ -22,16 +22,7 @@
     <key name="destination" type="s">
       <default>''</default>
     </key>
-    <key name="subfolder-type" enum="org.gnome.gthumb.GthSubfolderType">
-      <default>'none'</default>
-    </key>
-    <key name="subfolder-format" enum="org.gnome.gthumb.GthSubfolderFormat">
-      <default>'yyyymmdd'</default>
-    </key>
-    <key name="subfolder-single" type="b">
-      <default>false</default>
-    </key>
-    <key name="subfolder-custom-format" type="s">
+    <key name="subfolder-template" type="s">
       <default>''</default>
     </key>
     <key name="warn-delete-unsupported" type="b">
diff --git a/extensions/importer/data/ui/import-preferences.ui 
b/extensions/importer/data/ui/import-preferences.ui
index d63c39a5..34cf82ae 100644
--- a/extensions/importer/data/ui/import-preferences.ui
+++ b/extensions/importer/data/ui/import-preferences.ui
@@ -1,73 +1,51 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.0 -->
+<!-- Generated with glade 3.38.2 -->
 <interface>
-  <requires lib="gtk+" version="3.0"/>
+  <requires lib="gtk+" version="3.16"/>
   <object class="GtkBox" id="import_preferences">
     <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="border_width">15</property>
+    <property name="can-focus">False</property>
+    <property name="border-width">15</property>
     <property name="orientation">vertical</property>
-    <property name="spacing">12</property>
+    <property name="spacing">24</property>
     <child>
-      <object class="GtkFrame" id="frame1">
+      <object class="GtkBox">
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="label_xalign">0</property>
-        <property name="shadow_type">none</property>
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
         <child>
-          <object class="GtkAlignment" id="alignment2">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="top_padding">6</property>
-            <property name="left_padding">12</property>
-            <child>
-              <object class="GtkBox" id="vbox4">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkBox" id="hbox2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkFileChooserButton" id="destination_filechooserbutton">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="action">select-folder</property>
-                        <property name="local_only">False</property>
-                        <property name="title" translatable="yes"/>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child type="label">
           <object class="GtkLabel" id="destination_label">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can-focus">False</property>
             <property name="label" translatable="yes">_Destination</property>
-            <property name="use_markup">True</property>
-            <property name="use_underline">True</property>
-            <property name="mnemonic_widget">destination_filechooserbutton</property>
+            <property name="use-underline">True</property>
+            <property name="mnemonic-widget">destination_filechooserbutton</property>
+            <property name="xalign">0</property>
             <attributes>
               <attribute name="weight" value="bold"/>
             </attributes>
           </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFileChooserButton" id="destination_filechooserbutton">
+            <property name="width-request">450</property>
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="action">select-folder</property>
+            <property name="local-only">False</property>
+            <property name="title" translatable="yes"/>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
         </child>
       </object>
       <packing>
@@ -77,66 +55,59 @@
       </packing>
     </child>
     <child>
-      <object class="GtkBox" id="vbox6">
+      <object class="GtkCheckButton" id="automatic_subfolder_checkbutton">
+        <property name="label" translatable="yes">_Automatic subfolder</property>
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <property name="can-focus">True</property>
+        <property name="receives-default">False</property>
+        <property name="halign">start</property>
+        <property name="use-underline">True</property>
+        <property name="draw-indicator">True</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="subfolder_section_box">
+        <property name="can-focus">False</property>
+        <property name="margin-start">24</property>
         <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
         <child>
-          <object class="GtkCheckButton" id="autosubfolder_checkbutton">
+          <object class="GtkBox">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">False</property>
-            <property name="xalign">0.5</property>
-            <property name="draw_indicator">True</property>
+            <property name="can-focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
             <child>
-              <object class="GtkLabel" id="label2">
+              <object class="GtkLabel" id="label12">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">_Automatic subfolder</property>
-                <property name="use_underline">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">_Template:</property>
+                <property name="use-underline">True</property>
+                <property name="mnemonic-widget">subfolder_template_entry</property>
+                <property name="xalign">0</property>
                 <attributes>
                   <attribute name="weight" value="bold"/>
                 </attributes>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
             </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="alignment1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="top_padding">6</property>
-            <property name="left_padding">14</property>
             <child>
-              <object class="GtkBox" id="subfolder_type_box1">
+              <object class="GtkBox">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">6</property>
+                <property name="can-focus">False</property>
                 <child>
-                  <object class="GtkBox" id="vbox2">
+                  <object class="GtkEntry" id="subfolder_template_entry">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="orientation">vertical</property>
-                    <child>
-                      <object class="GtkBox" id="subfolder_type_box">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="spacing">6</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
+                    <property name="can-focus">True</property>
                   </object>
                   <packing>
                     <property name="expand">True</property>
@@ -145,394 +116,93 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkBox" id="vbox1">
+                  <object class="GtkButton" id="edit_subfolder_template_button">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="orientation">vertical</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
                     <child>
-                      <object class="GtkNotebook" id="subfolder_options_notebook">
+                      <object class="GtkImage">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="show_tabs">False</property>
-                        <property name="show_border">False</property>
-                        <child>
-                          <object class="GtkCheckButton" id="single_subfolder_checkbutton">
-                            <property name="label" translatable="yes">as _single subfolder</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="use_underline">True</property>
-                            <property name="xalign">0.5</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                        </child>
-                        <child type="tab">
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="custom_format_entry">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">●</property>
-                            <property name="secondary_icon_name">help-browser-symbolic</property>
-                            <property name="secondary_icon_tooltip_text">Help</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child type="tab">
-                          <placeholder/>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child type="tab">
-                          <placeholder/>
-                        </child>
+                        <property name="can-focus">False</property>
+                        <property name="icon-name">document-edit-symbolic</property>
                       </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="expand">True</property>
+                    <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">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">0</property>
           </packing>
         </child>
         <child>
-          <object class="GtkAlignment" id="template_help_alignment">
-            <property name="can_focus">False</property>
-            <property name="top_padding">6</property>
-            <property name="left_padding">28</property>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
             <child>
-              <object class="GtkBox" id="hbox1">
+              <object class="GtkLabel" id="label1">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <child>
-                  <object class="GtkTable" id="template_help_table">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="n_rows">8</property>
-                    <property name="n_columns">2</property>
-                    <property name="column_spacing">12</property>
-                    <property name="row_spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="label6">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%E</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label11">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The event description</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label14">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Special code</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label15">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Description</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label4">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%Y</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label5">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%m</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label7">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%d</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label8">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%H</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label9">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%M</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label10">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label">%S</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label12">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The year</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">2</property>
-                        <property name="bottom_attach">3</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label13">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The month</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">3</property>
-                        <property name="bottom_attach">4</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label16">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The day of the month</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">4</property>
-                        <property name="bottom_attach">5</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label17">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The hour</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">5</property>
-                        <property name="bottom_attach">6</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label18">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The minutes</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">6</property>
-                        <property name="bottom_attach">7</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="label19">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">The seconds</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="size" value="8000"/>
-                        </attributes>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="top_attach">7</property>
-                        <property name="bottom_attach">8</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Example:</property>
+                <property name="use-underline">True</property>
+                <property name="mnemonic-widget">destination_filechooserbutton</property>
+                <property name="xalign">0</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
             </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkAlignment" id="alignment3">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="top_padding">6</property>
-            <property name="left_padding">14</property>
             <child>
               <object class="GtkLabel" id="example_label">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label">example: file:///home/paolo/images/2009/08/12</property>
+                <property name="can-focus">False</property>
+                <property name="label">/home/paolo/images/</property>
                 <property name="xalign">0</property>
-                <attributes>
-                  <attribute name="size" value="8500"/>
-                </attributes>
+                <style>
+                  <class name="terminal"/>
+                </style>
               </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
             </child>
           </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">3</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
       <packing>
-        <property name="expand">True</property>
+        <property name="expand">False</property>
         <property name="fill">True</property>
-        <property name="position">1</property>
+        <property name="position">2</property>
       </packing>
     </child>
   </object>
diff --git a/extensions/importer/gth-import-destination-button.c 
b/extensions/importer/gth-import-destination-button.c
index e4d59906..f675ef0a 100644
--- a/extensions/importer/gth-import-destination-button.c
+++ b/extensions/importer/gth-import-destination-button.c
@@ -84,31 +84,29 @@ preferences_dialog_destination_changed_cb (GthImportPreferencesDialog *dialog,
                                           GthImportDestinationButton *self)
 {
        GFile *destination;
-       GFile *destination_example;
+       GFile *subfolder_example;
 
        destination = gth_import_preferences_dialog_get_destination (dialog);
-       destination_example = gth_import_preferences_dialog_get_destination_example (dialog);
-       if ((destination != NULL) && (destination_example != NULL)) {
-               char *name;
+       subfolder_example = gth_import_preferences_dialog_get_subfolder_example (dialog);
+       if (destination != NULL) {
+               char *destination_name;
+               char *subfolder_name;
 
-               name = g_file_get_parse_name (destination);
                gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->destination_icon), "folder-symbolic", 
GTK_ICON_SIZE_MENU);
-               gtk_label_set_text (GTK_LABEL (self->priv->destination_label), name);
-               g_free (name);
 
-               name = g_file_get_relative_path (destination, destination_example);
-               if ((name != NULL) && (strcmp (name, "") != 0)) {
-                       char *example_path;
+               destination_name = g_file_get_parse_name (destination);
+               gtk_label_set_text (GTK_LABEL (self->priv->destination_label), destination_name);
 
-                       example_path = g_strconcat (G_DIR_SEPARATOR_S, name, NULL);
-                       gtk_label_set_text (GTK_LABEL (self->priv->subfolder_label), example_path);
-
-                       g_free (example_path);
+               subfolder_name = g_file_get_parse_name (subfolder_example);
+               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;
+                       gtk_label_set_text (GTK_LABEL (self->priv->subfolder_label), name);
                }
                else
                        gtk_label_set_text (GTK_LABEL (self->priv->subfolder_label), "");
 
-               g_free (name);
+               g_free (subfolder_name);
+               g_free (destination_name);
        }
        else {
                gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->destination_icon), "dialog-error", 
GTK_ICON_SIZE_MENU);
@@ -116,7 +114,7 @@ preferences_dialog_destination_changed_cb (GthImportPreferencesDialog *dialog,
                gtk_label_set_text (GTK_LABEL (self->priv->subfolder_label), "");
        }
 
-       _g_object_unref (destination_example);
+       _g_object_unref (subfolder_example);
        _g_object_unref (destination);
 }
 
diff --git a/extensions/importer/gth-import-preferences-dialog.c 
b/extensions/importer/gth-import-preferences-dialog.c
index 44d1e48c..8767a392 100644
--- a/extensions/importer/gth-import-preferences-dialog.c
+++ b/extensions/importer/gth-import-preferences-dialog.c
@@ -27,9 +27,27 @@
 #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,
@@ -43,10 +61,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 struct _GthImportPreferencesDialogPrivate {
        GtkBuilder *builder;
        GSettings  *settings;
-       GtkWidget  *subfolder_type_list;
-       GtkWidget  *subfolder_format_list;
        char       *event;
-       gboolean    help_visible;
 };
 
 
@@ -93,24 +108,10 @@ gth_import_preferences_dialog_class_init (GthImportPreferencesDialogClass *klass
 }
 
 
-static GthSubfolderType
-get_subfolder_type (GthImportPreferencesDialog *self)
-{
-       if (! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("autosubfolder_checkbutton"))))
-               return GTH_SUBFOLDER_TYPE_NONE;
-       else
-               return gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->subfolder_type_list)) + 1;
-}
-
-
 static void
 save_options (GthImportPreferencesDialog *self)
 {
-       GFile              *destination;
-       gboolean            single_subfolder;
-       GthSubfolderType    subfolder_type;
-       GthSubfolderFormat  subfolder_format;
-       const char         *custom_format;
+       GFile *destination;
 
        destination = gth_import_preferences_dialog_get_destination (self);
        if (destination != NULL) {
@@ -122,17 +123,12 @@ save_options (GthImportPreferencesDialog *self)
                g_free (uri);
        }
 
-       single_subfolder = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET 
("single_subfolder_checkbutton")));
-       g_settings_set_boolean (self->priv->settings, PREF_IMPORTER_SUBFOLDER_SINGLE, single_subfolder);
-
-       subfolder_type = get_subfolder_type (self);
-       g_settings_set_enum (self->priv->settings, PREF_IMPORTER_SUBFOLDER_TYPE, subfolder_type);
-
-       subfolder_format = gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->subfolder_format_list));
-       g_settings_set_enum (self->priv->settings, PREF_IMPORTER_SUBFOLDER_FORMAT, subfolder_format);
-
-       custom_format = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("custom_format_entry")));
-       g_settings_set_string (self->priv->settings, PREF_IMPORTER_SUBFOLDER_CUSTOM_FORMAT, custom_format);
+       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);
 }
@@ -185,109 +181,161 @@ create_example_file_data (void)
 static void
 update_destination (GthImportPreferencesDialog *self)
 {
-       GFile              *destination_example;
-       char               *uri;
-       char               *example;
-       GthSubfolderType    subfolder_type;
-       GthSubfolderFormat  subfolder_format;
-
-       destination_example = gth_import_preferences_dialog_get_destination_example (self);
-       if (destination_example == NULL)
-               return;
-
-       uri = g_file_get_parse_name (destination_example);
-       example = g_strdup_printf (_("example: %s"), uri);
-       gtk_label_set_text (GTK_LABEL (GET_WIDGET ("example_label")), example);
-
-       subfolder_type = get_subfolder_type (self);
-       gtk_widget_set_sensitive (GET_WIDGET ("single_subfolder_checkbutton"), subfolder_type != 
GTH_SUBFOLDER_TYPE_NONE);
-       gtk_widget_set_sensitive (self->priv->subfolder_type_list, subfolder_type != GTH_SUBFOLDER_TYPE_NONE);
-       gtk_widget_set_sensitive (self->priv->subfolder_format_list, subfolder_type != 
GTH_SUBFOLDER_TYPE_NONE);
-       gtk_widget_set_sensitive (GET_WIDGET ("subfolder_options_notebook"), subfolder_type != 
GTH_SUBFOLDER_TYPE_NONE);
+       GFile *destination;
 
-       subfolder_format = gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->subfolder_format_list));
-       gtk_notebook_set_current_page (GTK_NOTEBOOK (GET_WIDGET ("subfolder_options_notebook")), 
(subfolder_format == GTH_SUBFOLDER_FORMAT_CUSTOM) ? 1 : 0);
+       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, "<span 
foreground=\"#4696f8\">%s</span>", 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);
-
-       g_free (example);
-       g_free (uri);
-       g_object_unref (destination_example);
 }
 
 
-static gboolean
-preferences_dialog_map_event_cb (GtkWidget *widget,
-                                GdkEvent  *event,
-                                gpointer   user_data)
+static void
+destination_selection_changed_cb (GtkWidget *widget,
+                                 gpointer  *user_data)
 {
        update_destination ((GthImportPreferencesDialog *) user_data);
-       return FALSE;
 }
 
 
 static void
-subfolder_type_list_changed_cb (GtkWidget *widget,
-                               gpointer   user_data)
+automatic_subfolder_checkbutton_toggled_cb (GtkToggleButton *togglebutton,
+                                           gpointer         user_data)
 {
-       update_destination ((GthImportPreferencesDialog *) 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_format_list_changed_cb (GtkWidget *widget,
-                                 gpointer   user_data)
+subfolder_template_entry_changed_cb (GtkEditable *editable,
+                                    gpointer    *user_data)
 {
        update_destination ((GthImportPreferencesDialog *) user_data);
 }
 
 
-static void
-destination_selection_changed_cb (GtkWidget *widget,
-                                 gpointer  *user_data)
+static gboolean
+template_eval_cb (TemplateFlags   flags,
+                 gunichar        parent_code,
+                 gunichar        code,
+                 char          **args,
+                 GString        *result,
+                 gpointer        user_data)
 {
-       update_destination ((GthImportPreferencesDialog *) user_data);
-}
+       GthImportPreferencesDialog *self = user_data;
+       gboolean                    preview;
+       char                       *text = NULL;
+       GDateTime                  *timestamp;
 
+       preview = flags & TEMPLATE_FLAGS_PREVIEW;
 
-static void
-subfolder_hierarchy_checkbutton_toggled_cb (GtkWidget *widget,
-                                           gpointer  *user_data)
-{
-       update_destination ((GthImportPreferencesDialog *) user_data);
-}
+       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, "<span foreground=\"#4696f8\">");
+
+       /**/
+
+       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;
+       }
 
-static void
-autosubfolder_checkbutton_toggled_cb (GtkToggleButton *togglebutton,
-                                     gpointer        *user_data)
-{
-       update_destination ((GthImportPreferencesDialog *) user_data);
-}
+       if (text != NULL) {
+               g_string_append (result, text);
+               g_free (text);
+       }
 
+       if (preview && (code != 0))
+               g_string_append (result, "</span>");
 
-static void
-custom_format_entry_changed_cb (GtkEditable *editable,
-                               gpointer    *user_data)
-{
-       update_destination ((GthImportPreferencesDialog *) user_data);
+       return FALSE;
 }
 
 
 static void
-custom_format_entry_icon_press_cb (GtkEntry             *entry,
-                                  GtkEntryIconPosition  icon_pos,
-                                  GdkEvent             *event,
-                                  gpointer              user_data)
+edit_subfolder_template_button_clicked_cb (GtkButton *button,
+                                          gpointer   user_data)
 {
        GthImportPreferencesDialog *self = user_data;
-
-       self->priv->help_visible = ! self->priv->help_visible;
-
-       if (self->priv->help_visible)
-               gtk_widget_show (GET_WIDGET ("template_help_alignment"));
-       else
-               gtk_widget_hide (GET_WIDGET ("template_help_alignment"));
+       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);
 }
 
 
@@ -308,98 +356,54 @@ gth_import_preferences_dialog_init (GthImportPreferencesDialog *self)
 {
        GtkWidget        *content;
        GFile            *destination;
-       GthSubfolderType  subfolder_type;
-       char             *custom_format;
+       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 (GTHUMB_IMPORTER_SCHEMA);
-       self->priv->help_visible = FALSE;
 
        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);
-
-       /* subfolder type  */
-
-       self->priv->subfolder_type_list = _gtk_combo_box_new_with_texts (_("File date"),
-                                                                        _("Current date"),
-                                                                        NULL);
-       gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->subfolder_type_list), 0);
-       gtk_widget_show (self->priv->subfolder_type_list);
-       gtk_box_pack_start (GTK_BOX (GET_WIDGET ("subfolder_type_box")), self->priv->subfolder_type_list, 
TRUE, TRUE, 0);
-       /*gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("subfolder_label")), 
self->priv->subfolder_type_list);*/
-
-       /* subfolder format */
-
-       self->priv->subfolder_format_list = _gtk_combo_box_new_with_texts (_("year-month-day"),
-                                                                          _("year-month"),
-                                                                          _("year"),
-                                                                          _("custom format"),
-                                                                          NULL);
-       gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->subfolder_format_list), 0);
-       gtk_widget_show (self->priv->subfolder_format_list);
-       gtk_box_pack_start (GTK_BOX (GET_WIDGET ("subfolder_type_box")), self->priv->subfolder_format_list, 
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_current_folder_file (GTK_FILE_CHOOSER (GET_WIDGET 
("destination_filechooserbutton")),
-                                                 destination,
-                                                 NULL);
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("single_subfolder_checkbutton")),
-                                     g_settings_get_boolean (self->priv->settings, 
PREF_IMPORTER_SUBFOLDER_SINGLE));
-       subfolder_type = g_settings_get_enum (self->priv->settings, PREF_IMPORTER_SUBFOLDER_TYPE);
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("autosubfolder_checkbutton")), 
subfolder_type != GTH_SUBFOLDER_TYPE_NONE);
-       gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->subfolder_type_list),
-                                 (subfolder_type == 0) ? 0 : subfolder_type - 1);
-       gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->subfolder_format_list),
-                                 g_settings_get_enum (self->priv->settings, PREF_IMPORTER_SUBFOLDER_FORMAT));
-
-       custom_format = g_settings_get_string (self->priv->settings, PREF_IMPORTER_SUBFOLDER_CUSTOM_FORMAT);
-       if (custom_format != NULL) {
-               gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("custom_format_entry")), custom_format);
-               g_free (custom_format);
+       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 (self->priv->subfolder_type_list,
-                         "changed",
-                         G_CALLBACK (subfolder_type_list_changed_cb),
-                         self);
-       g_signal_connect (self->priv->subfolder_format_list,
-                         "changed",
-                         G_CALLBACK (subfolder_format_list_changed_cb),
-                         self);
        g_signal_connect (GET_WIDGET ("destination_filechooserbutton"),
                          "selection_changed",
                          G_CALLBACK (destination_selection_changed_cb),
                          self);
-       g_signal_connect (GET_WIDGET ("single_subfolder_checkbutton"),
-                         "toggled",
-                         G_CALLBACK (subfolder_hierarchy_checkbutton_toggled_cb),
-                         self);
-       g_signal_connect (self,
-                         "map-event",
-                         G_CALLBACK (preferences_dialog_map_event_cb),
-                         self);
        g_signal_connect (self,
                          "delete-event",
                          G_CALLBACK (preferences_dialog_delete_event_cb),
                          self);
-       g_signal_connect (GET_WIDGET ("autosubfolder_checkbutton"),
+       g_signal_connect (GET_WIDGET ("automatic_subfolder_checkbutton"),
                          "toggled",
-                         G_CALLBACK (autosubfolder_checkbutton_toggled_cb),
+                         G_CALLBACK (automatic_subfolder_checkbutton_toggled_cb),
                          self);
-       g_signal_connect (GET_WIDGET ("custom_format_entry"),
+       g_signal_connect (GET_WIDGET ("subfolder_template_entry"),
                          "changed",
-                         G_CALLBACK (custom_format_entry_changed_cb),
+                         G_CALLBACK (subfolder_template_entry_changed_cb),
                          self);
-       g_signal_connect (GET_WIDGET ("custom_format_entry"),
-                         "icon-press",
-                         G_CALLBACK (custom_format_entry_icon_press_cb),
+       g_signal_connect (GET_WIDGET ("edit_subfolder_template_button"),
+                         "clicked",
+                         G_CALLBACK (edit_subfolder_template_button_clicked_cb),
                          self);
        g_signal_connect (self,
                          "response",
@@ -441,39 +445,29 @@ gth_import_preferences_dialog_get_destination (GthImportPreferencesDialog *self)
 
 
 GFile *
-gth_import_preferences_dialog_get_destination_example (GthImportPreferencesDialog *self)
+gth_import_preferences_dialog_get_subfolder_example (GthImportPreferencesDialog *self)
 {
-       GFile              *destination;
-       GthSubfolderType    subfolder_type;
-       GthSubfolderFormat  subfolder_format;
-       gboolean            single_subfolder;
-       const char         *custom_format;
-       GthFileData        *example_data;
-       GTimeVal            timeval;
-       GFile              *destination_example;
+       GFile       *destination;
+       GthFileData *example_file_data;
+       const char  *subfolder_template;
+       GTimeVal     timestamp;
+       GFile       *destination_example;
 
-       destination = gth_import_preferences_dialog_get_destination (self);
-       if (destination == NULL)
-               return NULL;
-
-       subfolder_type = get_subfolder_type (self);
-       subfolder_format = gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->subfolder_format_list));
-       single_subfolder = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET 
("single_subfolder_checkbutton")));
-       custom_format = gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("custom_format_entry")));
+       destination = g_file_new_for_path("/");
 
-       example_data = create_example_file_data ();
-       g_get_current_time (&timeval);
-
-       destination_example = gth_import_utils_get_file_destination (example_data,
+       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 (&timestamp);
+       destination_example = gth_import_utils_get_file_destination (example_file_data,
                                                                     destination,
-                                                                    subfolder_type,
-                                                                    subfolder_format,
-                                                                    single_subfolder,
-                                                                    custom_format,
+                                                                    subfolder_template,
                                                                     self->priv->event,
-                                                                    timeval);
+                                                                    timestamp);
 
-       g_object_unref (example_data);
+       g_object_unref (example_file_data);
        g_object_unref (destination);
 
        return destination_example;
diff --git a/extensions/importer/gth-import-preferences-dialog.h 
b/extensions/importer/gth-import-preferences-dialog.h
index d53eac31..31440de9 100644
--- a/extensions/importer/gth-import-preferences-dialog.h
+++ b/extensions/importer/gth-import-preferences-dialog.h
@@ -58,7 +58,7 @@ void         gth_import_preferences_dialog_set_event (GthImportPreferencesDialog
                                                      const char                 *event);
 GFile *      gth_import_preferences_dialog_get_destination
                                                     (GthImportPreferencesDialog *self);
-GFile *      gth_import_preferences_dialog_get_destination_example
+GFile *      gth_import_preferences_dialog_get_subfolder_example
                                                     (GthImportPreferencesDialog *self);
 
 G_END_DECLS
diff --git a/extensions/importer/preferences.h b/extensions/importer/preferences.h
index ac35a42f..13c718eb 100644
--- a/extensions/importer/preferences.h
+++ b/extensions/importer/preferences.h
@@ -33,10 +33,7 @@ G_BEGIN_DECLS
 /* keys: viewer */
 
 #define PREF_IMPORTER_DESTINATION              "destination"
-#define PREF_IMPORTER_SUBFOLDER_TYPE           "subfolder-type"
-#define PREF_IMPORTER_SUBFOLDER_FORMAT         "subfolder-format"
-#define PREF_IMPORTER_SUBFOLDER_SINGLE         "subfolder-single"
-#define PREF_IMPORTER_SUBFOLDER_CUSTOM_FORMAT  "subfolder-custom-format"
+#define PREF_IMPORTER_SUBFOLDER_TEMPLATE       "subfolder-template"
 #define PREF_IMPORTER_WARN_DELETE_UNSUPPORTED  "warn-delete-unsupported"
 
 G_END_DECLS
diff --git a/extensions/importer/utils.c b/extensions/importer/utils.c
index bff19781..63179730 100644
--- a/extensions/importer/utils.c
+++ b/extensions/importer/utils.c
@@ -46,89 +46,99 @@ gth_import_preferences_get_destination (void)
 }
 
 
+typedef struct {
+       GthFileData *file_data;
+       const char  *event_name;
+       GTimeVal     import_time;
+       GTimeVal     file_time;
+} TemplateData;
+
+
+static gboolean
+template_eval_cb (TemplateFlags   flags,
+                 gunichar        parent_code,
+                 gunichar        code,
+                 char          **args,
+                 GString        *result,
+                 gpointer        user_data)
+{
+       TemplateData *template_data = user_data;
+       char         *text = NULL;
+
+       if ((parent_code == 'D') || (parent_code == 'T')) {
+               /* strftime code, return the code itself. */
+               _g_string_append_template_code (result, code, args);
+               return FALSE;
+       }
+
+       switch (code) {
+       case 'D': /* File date */
+               text = _g_time_val_strftime (&template_data->file_time,
+                                            (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT);
+               break;
+
+       case 'T': /* Timestamp */
+               text = _g_time_val_strftime (&template_data->import_time,
+                                            (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT);
+               break;
+
+       case 'E': /* Event description */
+               if (template_data->event_name != NULL)
+                       g_string_append (result, template_data->event_name);
+               break;
+
+       default:
+               break;
+       }
+
+       if (text != NULL) {
+               g_string_append (result, text);
+               g_free (text);
+       }
+
+       return FALSE;
+}
+
+
 GFile *
-gth_import_utils_get_file_destination (GthFileData        *file_data,
-                                      GFile              *destination,
-                                      GthSubfolderType    subfolder_type,
-                                      GthSubfolderFormat  subfolder_format,
-                                      gboolean            single_subfolder,
-                                      const char         *custom_format,
-                                      const char         *event_name,
-                                      GTimeVal            import_start_time)
+gth_import_utils_get_file_destination (GthFileData *file_data,
+                                      GFile       *destination,
+                                      const char  *subfolder_template,
+                                      const char  *event_name,
+                                      GTimeVal     import_time)
 {
-       GTimeVal  timeval;
-       char     *child;
-       GFile    *file_destination;
+       TemplateData  template_data;
+       char         *subfolder;
+       GFile        *file_destination;
+
+       template_data.file_data = file_data;
+       template_data.event_name = event_name;
+       template_data.import_time = import_time;
 
-       if (subfolder_type == GTH_SUBFOLDER_TYPE_FILE_DATE) {
+       {
                GthMetadata *metadata;
 
                metadata = (GthMetadata *) g_file_info_get_attribute_object (file_data->info, 
"Embedded::Photo::DateTimeOriginal");
                if (metadata != NULL)
-                       _g_time_val_from_exif_date (gth_metadata_get_raw (metadata), &timeval);
+                       _g_time_val_from_exif_date (gth_metadata_get_raw (metadata), 
&template_data.file_time);
                else
-                       g_file_info_get_modification_time (file_data->info, &timeval);
+                       g_file_info_get_modification_time (file_data->info, &template_data.file_time);
 
-               if (timeval.tv_sec == 0)
-                       subfolder_type = GTH_SUBFOLDER_TYPE_CURRENT_DATE;
+               if (template_data.file_time.tv_sec == 0)
+                       template_data.file_time = import_time;
        }
 
-       if (subfolder_type == GTH_SUBFOLDER_TYPE_CURRENT_DATE)
-               timeval = import_start_time;
-
-       switch (subfolder_type) {
-       case GTH_SUBFOLDER_TYPE_FILE_DATE:
-       case GTH_SUBFOLDER_TYPE_CURRENT_DATE:
-               if (subfolder_format != GTH_SUBFOLDER_FORMAT_CUSTOM) {
-                       GDate  *date;
-                       char  **parts;
-
-                       date = g_date_new ();
-                       g_date_set_time_val (date, &timeval);
-
-                       parts = g_new0 (char *, 4);
-                       parts[0] = g_strdup_printf ("%04d", g_date_get_year (date));
-                       if (subfolder_format != GTH_SUBFOLDER_FORMAT_YYYY) {
-                               parts[1] = g_strdup_printf ("%02d", g_date_get_month (date));
-                               if (subfolder_format != GTH_SUBFOLDER_FORMAT_YYYYMM)
-                                       parts[2] = g_strdup_printf ("%02d", g_date_get_day (date));
-                       }
-
-                       if (single_subfolder)
-                               child = g_strjoinv ("-", parts);
-                       else
-                               child = g_strjoinv ("/", parts);
-
-                       g_strfreev (parts);
-                       g_date_free (date);
-               }
-               else {
-                       char *format = NULL;
-
-                       if (event_name != NULL) {
-                               GRegex *re;
-
-                               re = g_regex_new ("%E", 0, 0, NULL);
-                               format = g_regex_replace_literal (re, custom_format, -1, 0, event_name, 0, 
NULL);
-
-                               g_regex_unref (re);
-                       }
-                       if (format == NULL)
-                               format = g_strdup (custom_format);
-                       child = _g_time_val_strftime (&timeval, format);
-
-                       g_free (format);
-               }
-               break;
-
-       case GTH_SUBFOLDER_TYPE_NONE:
-       default:
-               child = NULL;
-               break;
+       subfolder = _g_template_eval (subfolder_template,
+                                     TEMPLATE_FLAGS_NO_ENUMERATOR,
+                                     template_eval_cb,
+                                     &template_data);
+       if (subfolder != NULL) {
+               file_destination = _g_file_append_path (destination, subfolder);
+               g_free (subfolder);
        }
-       file_destination = _g_file_append_path (destination, child);
-
-       g_free (child);
+       else
+               file_destination = g_file_dup (destination);
 
        return file_destination;
+
 }
diff --git a/extensions/importer/utils.h b/extensions/importer/utils.h
index 61c0fe19..14e53d09 100644
--- a/extensions/importer/utils.h
+++ b/extensions/importer/utils.h
@@ -26,28 +26,12 @@ G_BEGIN_DECLS
 
 #include <gthumb.h>
 
-typedef enum {
-       GTH_SUBFOLDER_TYPE_NONE = 0,
-        GTH_SUBFOLDER_TYPE_FILE_DATE,
-       GTH_SUBFOLDER_TYPE_CURRENT_DATE,
-} GthSubfolderType;
-
-typedef enum {
-       GTH_SUBFOLDER_FORMAT_YYYYMMDD,
-       GTH_SUBFOLDER_FORMAT_YYYYMM,
-       GTH_SUBFOLDER_FORMAT_YYYY,
-       GTH_SUBFOLDER_FORMAT_CUSTOM
-} GthSubfolderFormat;
-
 GFile *   gth_import_preferences_get_destination  (void);
-GFile *   gth_import_utils_get_file_destination   (GthFileData        *file_data,
-                                                  GFile              *destination,
-                                                  GthSubfolderType    subfolder_type,
-                                                  GthSubfolderFormat  subfolder_format,
-                                                  gboolean            single_subfolder,
-                                                  const char         *custom_format,
-                                                  const char         *event_name,
-                                                  GTimeVal            import_start_time);
+GFile *   gth_import_utils_get_file_destination   (GthFileData *file_data,
+                                                  GFile       *destination,
+                                                  const char  *subfolder_template,
+                                                  const char  *event_name,
+                                                  GTimeVal     import_start_time);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]