[gthumb] contact sheet: use the template editor



commit b3088b9630b81bebd59b696d591f47c5efc122b4
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Fri May 21 08:02:40 2021 +0200

    contact sheet: use the template editor

 .../org.gnome.gthumb.contact-sheet.gschema.xml     |   2 +-
 extensions/contact_sheet/data/ui/contact-sheet.ui  | 812 +++++++++------------
 extensions/contact_sheet/data/ui/image-wall.ui     | 401 +++++-----
 extensions/contact_sheet/dlg-contact-sheet.c       | 180 ++++-
 extensions/contact_sheet/dlg-image-wall.c          |  31 +
 .../contact_sheet/gth-contact-sheet-creator.c      | 184 +++--
 .../contact_sheet/gth-contact-sheet-creator.h      |   2 +
 7 files changed, 825 insertions(+), 787 deletions(-)
---
diff --git a/data/gschemas/org.gnome.gthumb.contact-sheet.gschema.xml 
b/data/gschemas/org.gnome.gthumb.contact-sheet.gschema.xml
index 3eb1abf6..e4dfea25 100644
--- a/data/gschemas/org.gnome.gthumb.contact-sheet.gschema.xml
+++ b/data/gschemas/org.gnome.gthumb.contact-sheet.gschema.xml
@@ -25,7 +25,7 @@
 
   <schema id="org.gnome.gthumb.contact-sheet.contact-sheet" 
path="/org/gnome/gthumb/contact-sheet/contact-sheet/" gettext-domain="gthumb">
     <key name="header" type="s">
-      <default>''</default>
+      <default>'%L'</default>
     </key>
     <key name="footer" type="s">
       <default>''</default>
diff --git a/extensions/contact_sheet/data/ui/contact-sheet.ui 
b/extensions/contact_sheet/data/ui/contact-sheet.ui
index d25dc912..9443a779 100644
--- a/extensions/contact_sheet/data/ui/contact-sheet.ui
+++ b/extensions/contact_sheet/data/ui/contact-sheet.ui
@@ -1,11 +1,11 @@
 <?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"/>
   <object class="GtkAdjustment" id="cols_adjustment">
     <property name="upper">100</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="filetype_liststore">
     <columns>
@@ -17,8 +17,8 @@
   </object>
   <object class="GtkAdjustment" id="rows_adjustment">
     <property name="upper">100</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="sort_liststore">
     <columns>
@@ -48,253 +48,163 @@
   </object>
   <object class="GtkBox" id="dialog_content">
     <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">5</property>
     <child>
       <object class="GtkNotebook" id="notebook1">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
+        <property name="can-focus">True</property>
         <property name="vexpand">True</property>
-        <property name="border_width">6</property>
+        <property name="border-width">6</property>
         <child>
           <object class="GtkVBox" id="vbox1">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">12</property>
-            <property name="spacing">6</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">12</property>
+            <property name="spacing">12</property>
             <child>
               <object class="GtkFrame" id="frame7">
                 <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="label-xalign">0</property>
+                <property name="shadow-type">none</property>
                 <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">12</property>
+                    <property name="can-focus">False</property>
+                    <property name="top-padding">6</property>
+                    <property name="left-padding">12</property>
                     <child>
                       <object class="GtkTable" id="table2">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="n_rows">3</property>
-                        <property name="n_columns">2</property>
-                        <property name="column_spacing">6</property>
-                        <property name="row_spacing">6</property>
+                        <property name="can-focus">False</property>
+                        <property name="n-rows">2</property>
+                        <property name="n-columns">2</property>
+                        <property name="column-spacing">6</property>
+                        <property name="row-spacing">6</property>
                         <child>
-                          <placeholder/>
+                          <object class="GtkLabel" id="label122">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="label" translatable="yes">_Footer:</property>
+                            <property name="use-underline">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="top-attach">1</property>
+                            <property name="bottom-attach">2</property>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options"/>
+                          </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="page_footer_help_table">
-                            <property name="can_focus">False</property>
-                            <property name="n_rows">4</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">12</property>
-                            <property name="row_spacing">6</property>
-                            <child>
-                              <object class="GtkLabel" id="label7">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label">%p</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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label8">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label">%n</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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label10">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">The current page number</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>
-                                <property name="y_options">GTK_FILL</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 total number of 
pages</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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
+                          <object class="GtkLabel" id="label86">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="label" translatable="yes">_Header:</property>
+                            <property name="use-underline">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options"/>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
                             <child>
-                              <object class="GtkLabel" id="label14">
+                              <object class="GtkEntry" id="footer_entry">
                                 <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>
+                                <property name="can-focus">True</property>
+                                <property name="invisible-char">●</property>
+                                <property name="activates-default">True</property>
+                                <property name="secondary-icon-tooltip-markup" 
translatable="yes">Help</property>
                               </object>
                               <packing>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label15">
+                              <object class="GtkButton" id="edit_footer_button">
                                 <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>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">True</property>
+                                <property name="tooltip-text" translatable="yes">Edit template</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="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="y_options">GTK_FILL</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="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="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
                             <child>
-                              <object class="GtkLabel" id="label16">
+                              <object class="GtkEntry" id="header_entry">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes" comments="translate only the text 
in the curly brackets">%D{ format }</property>
-                                <property name="xalign">0</property>
-                                <attributes>
-                                  <attribute name="size" value="8000"/>
-                                </attributes>
+                                <property name="can-focus">True</property>
+                                <property name="invisible-char">●</property>
+                                <property name="activates-default">True</property>
                               </object>
                               <packing>
-                                <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkLabel" id="label17">
+                              <object class="GtkButton" id="edit_header_button">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">The current date</property>
-                                <property name="xalign">0</property>
-                                <attributes>
-                                  <attribute name="size" value="8000"/>
-                                </attributes>
+                                <property name="can-focus">True</property>
+                                <property name="receives-default">True</property>
+                                <property name="tooltip-text" translatable="yes">Edit template</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="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
-                                <property name="y_options">GTK_FILL</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="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="top_attach">2</property>
-                            <property name="bottom_attach">3</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="footer_entry">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">●</property>
-                            <property name="activates_default">True</property>
-                            <property name="secondary_icon_name">help-browser-symbolic</property>
-                            <property name="secondary_icon_tooltip_text">Help</property>
-                          </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>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label122">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">_Footer:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">footer_entry</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options"/>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="header_entry">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="invisible_char">●</property>
-                            <property name="activates_default">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label86">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label" translatable="yes">_Header:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">header_entry</property>
-                            <property name="xalign">0</property>
-                          </object>
-                          <packing>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options"/>
+                            <property name="left-attach">1</property>
+                            <property name="right-attach">2</property>
                           </packing>
                         </child>
                       </object>
@@ -304,9 +214,9 @@
                 <child type="label">
                   <object class="GtkLabel" id="label30">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">Contact Sheet</property>
-                    <property name="use_markup">True</property>
+                    <property name="use-markup">True</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
@@ -322,88 +232,118 @@
             <child>
               <object class="GtkFrame" id="frame1">
                 <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="label-xalign">0</property>
+                <property name="shadow-type">none</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>
+                    <property name="can-focus">False</property>
+                    <property name="top-padding">6</property>
+                    <property name="left-padding">12</property>
                     <child>
                       <object class="GtkVBox" id="vbox5">
                         <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="GtkTable" id="table4">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="n_rows">3</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">6</property>
-                            <property name="row_spacing">6</property>
-                            <child>
-                              <placeholder/>
-                            </child>
+                            <property name="can-focus">False</property>
+                            <property name="n-rows">2</property>
+                            <property name="n-columns">2</property>
+                            <property name="column-spacing">6</property>
+                            <property name="row-spacing">6</property>
                             <child>
                               <object class="GtkLabel" id="label84">
                                 <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_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>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_FILL</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="x-options">GTK_FILL</property>
+                                <property name="y-options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkFileChooserButton" id="destination_filechooserbutton">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                                <property name="can-focus">False</property>
                                 <property name="action">select-folder</property>
-                                <property name="local_only">False</property>
+                                <property name="local-only">False</property>
                                 <property name="title" translatable="yes">Choose destination 
folder</property>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left-attach">1</property>
+                                <property name="right-attach">2</property>
+                                <property name="y-options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label54">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                                <property name="can-focus">False</property>
                                 <property name="label" translatable="yes">File_name:</property>
-                                <property name="use_underline">True</property>
-                                <property name="mnemonic_widget">template_entry</property>
+                                <property name="use-underline">True</property>
                                 <property name="xalign">0</property>
                               </object>
                               <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_FILL</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="top-attach">1</property>
+                                <property name="bottom-attach">2</property>
+                                <property name="x-options">GTK_FILL</property>
+                                <property name="y-options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkHBox" id="hbox47">
                                 <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="template_entry">
+                                  <object class="GtkBox">
                                     <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="invisible_char">●</property>
-                                    <property name="activates_default">True</property>
-                                    <property name="text">###</property>
-                                    <property name="secondary_icon_name">help-browser-symbolic</property>
+                                    <property name="can-focus">False</property>
+                                    <child>
+                                      <object class="GtkEntry" id="template_entry">
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="invisible-char">●</property>
+                                        <property name="activates-default">True</property>
+                                        <property name="text">###</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_filename_button">
+                                        <property name="name">edit_footer_button</property>
+                                        <property name="visible">True</property>
+                                        <property name="can-focus">True</property>
+                                        <property name="receives-default">True</property>
+                                        <property name="tooltip-text" translatable="yes">Edit 
template</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>
@@ -414,7 +354,7 @@
                                 <child>
                                   <object class="GtkComboBox" id="filetype_combobox">
                                     <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
+                                    <property name="can-focus">False</property>
                                     <property name="model">filetype_liststore</property>
                                     <property name="active">0</property>
                                     <child>
@@ -432,93 +372,11 @@
                                 </child>
                               </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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkTable" id="template_help_table">
-                                <property name="can_focus">False</property>
-                                <property name="n_rows">2</property>
-                                <property name="n_columns">2</property>
-                                <property name="column_spacing">12</property>
-                                <property name="row_spacing">6</property>
-                                <child>
-                                  <object class="GtkLabel" id="label32">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label">#</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>
-                                    <property name="y_options">GTK_FILL</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label34">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <property name="label" translatable="yes">New enumerator digit</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>
-                                    <property name="y_options">GTK_FILL</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label36">
-                                    <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>
-                                  <packing>
-                                    <property name="y_options">GTK_FILL</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkLabel" id="label37">
-                                    <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>
-                                    <property name="y_options">GTK_FILL</property>
-                                  </packing>
-                                </child>
-                              </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>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left-attach">1</property>
+                                <property name="right-attach">2</property>
+                                <property name="top-attach">1</property>
+                                <property name="bottom-attach">2</property>
+                                <property name="y-options">GTK_FILL</property>
                               </packing>
                             </child>
                           </object>
@@ -531,13 +389,13 @@
                         <child>
                           <object class="GtkCheckButton" id="image_map_checkbutton">
                             <property name="label" translatable="yes">Create _HTML image map</property>
-                            <property name="use_action_appearance">False</property>
+                            <property name="use-action-appearance">False</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="can-focus">True</property>
+                            <property name="receives-default">False</property>
+                            <property name="use-underline">True</property>
                             <property name="xalign">0</property>
-                            <property name="draw_indicator">True</property>
+                            <property name="draw-indicator">True</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -552,9 +410,9 @@
                 <child type="label">
                   <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">Saving</property>
-                    <property name="use_markup">True</property>
+                    <property name="use-markup">True</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
@@ -572,35 +430,35 @@
         <child type="tab">
           <object class="GtkLabel" id="label1">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can-focus">False</property>
             <property name="label" translatable="yes">General</property>
           </object>
           <packing>
-            <property name="tab_fill">False</property>
+            <property name="tab-fill">False</property>
           </packing>
         </child>
         <child>
           <object class="GtkHBox" id="hbox1">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">12</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">12</property>
             <property name="spacing">6</property>
             <child>
               <object class="GtkScrolledWindow" id="theme_scrolledwindow">
-                <property name="width_request">530</property>
-                <property name="height_request">320</property>
+                <property name="width-request">530</property>
+                <property name="height-request">320</property>
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="shadow_type">in</property>
+                <property name="can-focus">True</property>
+                <property name="shadow-type">in</property>
                 <child>
                   <object class="GtkIconView" id="theme_iconview">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
+                    <property name="can-focus">True</property>
                     <property name="margin">6</property>
-                    <property name="selection_mode">browse</property>
+                    <property name="selection-mode">browse</property>
                     <property name="model">theme_liststore</property>
-                    <property name="row_spacing">0</property>
-                    <property name="column_spacing">0</property>
+                    <property name="row-spacing">0</property>
+                    <property name="column-spacing">0</property>
                     <child>
                       <object class="GtkCellRendererPixbuf" id="cellrenderertext3"/>
                       <attributes>
@@ -628,20 +486,20 @@
             <child>
               <object class="GtkVBox" id="vbox2">
                 <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="add_theme_button">
-                    <property name="use_action_appearance">False</property>
+                    <property name="use-action-appearance">False</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Create a new theme</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="tooltip-text" translatable="yes">Create a new theme</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>
@@ -653,16 +511,16 @@
                 </child>
                 <child>
                   <object class="GtkButton" id="edit_theme_button">
-                    <property name="use_action_appearance">False</property>
+                    <property name="use-action-appearance">False</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Edit the selected theme</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="tooltip-text" translatable="yes">Edit the selected theme</property>
                     <child>
                       <object class="GtkImage" id="image3">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="icon_name">document-properties-symbolic</property>
+                        <property name="can-focus">False</property>
+                        <property name="icon-name">document-properties-symbolic</property>
                       </object>
                     </child>
                   </object>
@@ -674,16 +532,16 @@
                 </child>
                 <child>
                   <object class="GtkButton" id="delete_theme_button">
-                    <property name="use_action_appearance">False</property>
+                    <property name="use-action-appearance">False</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="tooltip_text" translatable="yes">Delete the selected theme</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="tooltip-text" translatable="yes">Delete the selected theme</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>
@@ -708,60 +566,60 @@
         <child type="tab">
           <object class="GtkLabel">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can-focus">False</property>
             <property name="label" translatable="yes">Theme</property>
           </object>
           <packing>
             <property name="position">1</property>
-            <property name="tab_fill">False</property>
+            <property name="tab-fill">False</property>
           </packing>
         </child>
         <child>
           <object class="GtkVBox" id="vbox3">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">12</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">12</property>
             <property name="spacing">12</property>
             <child>
               <object class="GtkTable" id="table3">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">3</property>
-                <property name="n_columns">3</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">6</property>
+                <property name="can-focus">False</property>
+                <property name="n-rows">3</property>
+                <property name="n-columns">3</property>
+                <property name="column-spacing">6</property>
+                <property name="row-spacing">6</property>
                 <child>
                   <placeholder/>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label18">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">Columns:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">cols_spinbutton</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">cols_spinbutton</property>
                     <property name="xalign">0</property>
                   </object>
                   <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="top-attach">1</property>
+                    <property name="bottom-attach">2</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkHBox" 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="cols_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">0</property>
                         <property name="adjustment">cols_adjustment</property>
-                        <property name="climb_rate">1</property>
+                        <property name="climb-rate">1</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -771,27 +629,27 @@
                     </child>
                   </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>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="left-attach">1</property>
+                    <property name="right-attach">2</property>
+                    <property name="top-attach">1</property>
+                    <property name="bottom-attach">2</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkHBox" 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="GtkSpinButton" id="images_per_index_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">0</property>
                         <property name="adjustment">rows_adjustment</property>
-                        <property name="climb_rate">1</property>
+                        <property name="climb-rate">1</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -801,59 +659,59 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="left-attach">1</property>
+                    <property name="right-attach">2</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="label28">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">Images per page:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">images_per_index_spinbutton</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">images_per_index_spinbutton</property>
                     <property name="xalign">0</property>
                   </object>
                   <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="single_index_checkbutton">
                     <property name="label" translatable="yes">All images on a single page</property>
-                    <property name="use_action_appearance">False</property>
+                    <property name="use-action-appearance">False</property>
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">False</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
                     <property name="xalign">0</property>
-                    <property name="draw_indicator">True</property>
+                    <property name="draw-indicator">True</property>
                   </object>
                   <packing>
-                    <property name="left_attach">2</property>
-                    <property name="right_attach">3</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="left-attach">2</property>
+                    <property name="right-attach">3</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkCheckButton" id="same_size_checkbutton">
                     <property name="label" translatable="yes">_All pages with the same size</property>
-                    <property name="use_action_appearance">False</property>
+                    <property name="use-action-appearance">False</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="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="use-underline">True</property>
                     <property name="xalign">0</property>
-                    <property name="draw_indicator">True</property>
+                    <property name="draw-indicator">True</property>
                   </object>
                   <packing>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"/>
+                    <property name="right-attach">3</property>
+                    <property name="top-attach">2</property>
+                    <property name="bottom-attach">3</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options"/>
                   </packing>
                 </child>
               </object>
@@ -871,51 +729,51 @@
         <child type="tab">
           <object class="GtkLabel" id="label2">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can-focus">False</property>
             <property name="label" translatable="yes">Layout</property>
           </object>
           <packing>
             <property name="position">2</property>
-            <property name="tab_fill">False</property>
+            <property name="tab-fill">False</property>
           </packing>
         </child>
         <child>
           <object class="GtkVBox" id="vbox4">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="border_width">12</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">12</property>
             <property name="spacing">6</property>
             <child>
               <object class="GtkTable" id="table1">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="n_rows">2</property>
-                <property name="n_columns">2</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">6</property>
+                <property name="can-focus">False</property>
+                <property name="n-rows">2</property>
+                <property name="n-columns">2</property>
+                <property name="column-spacing">6</property>
+                <property name="row-spacing">6</property>
                 <child>
                   <object class="GtkLabel" id="label112">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">S_ort:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">sort_combobox</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">sort_combobox</property>
                     <property name="xalign">0</property>
                   </object>
                   <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"/>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options"/>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkHBox" id="hbox62">
                     <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="GtkComboBox" id="sort_combobox">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="model">sort_liststore</property>
                         <child>
                           <object class="GtkCellRendererText" id="cellrenderertext2"/>
@@ -933,13 +791,13 @@
                     <child>
                       <object class="GtkCheckButton" id="reverse_order_checkbutton">
                         <property name="label" translatable="yes">Re_verse order</property>
-                        <property name="use_action_appearance">False</property>
+                        <property name="use-action-appearance">False</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="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="use-underline">True</property>
                         <property name="xalign">0</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="draw-indicator">True</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -949,37 +807,37 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="left-attach">1</property>
+                    <property name="right-attach">2</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkLabel" id="size_label">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">_Size:</property>
-                    <property name="use_underline">True</property>
+                    <property name="use-underline">True</property>
                     <property name="justify">center</property>
-                    <property name="mnemonic_widget">thumbnail_size_combobox</property>
+                    <property name="mnemonic-widget">thumbnail_size_combobox</property>
                     <property name="xalign">0</property>
                   </object>
                   <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="top-attach">1</property>
+                    <property name="bottom-attach">2</property>
+                    <property name="x-options">GTK_FILL</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
                 <child>
                   <object class="GtkHBox" 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="GtkComboBox" id="thumbnail_size_combobox">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="model">thumbnail_size_liststore</property>
                         <child>
                           <object class="GtkCellRendererText" id="cellrenderertext5"/>
@@ -997,13 +855,13 @@
                     <child>
                       <object class="GtkCheckButton" id="squared_thumbnail_checkbutton">
                         <property name="label" translatable="yes">Sq_uared</property>
-                        <property name="use_action_appearance">False</property>
+                        <property name="use-action-appearance">False</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="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="use-underline">True</property>
                         <property name="xalign">0</property>
-                        <property name="draw_indicator">True</property>
+                        <property name="draw-indicator">True</property>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -1013,11 +871,11 @@
                     </child>
                   </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>
-                    <property name="y_options">GTK_FILL</property>
+                    <property name="left-attach">1</property>
+                    <property name="right-attach">2</property>
+                    <property name="top-attach">1</property>
+                    <property name="bottom-attach">2</property>
+                    <property name="y-options">GTK_FILL</property>
                   </packing>
                 </child>
               </object>
@@ -1030,11 +888,11 @@
             <child>
               <object class="GtkVBox" id="vbox6">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <child>
                   <object class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="label" translatable="yes">Caption:</property>
                     <property name="xalign">0</property>
                   </object>
@@ -1047,8 +905,8 @@
                 <child>
                   <object class="GtkScrolledWindow" id="thumbnail_caption_scrolledwindow">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="shadow_type">in</property>
+                    <property name="can-focus">True</property>
+                    <property name="shadow-type">in</property>
                     <child>
                       <placeholder/>
                     </child>
@@ -1074,12 +932,12 @@
         <child type="tab">
           <object class="GtkLabel">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can-focus">False</property>
             <property name="label" translatable="yes">Thumbnails</property>
           </object>
           <packing>
             <property name="position">3</property>
-            <property name="tab_fill">False</property>
+            <property name="tab-fill">False</property>
           </packing>
         </child>
       </object>
diff --git a/extensions/contact_sheet/data/ui/image-wall.ui b/extensions/contact_sheet/data/ui/image-wall.ui
index 58acb4ad..b95e0ba5 100644
--- a/extensions/contact_sheet/data/ui/image-wall.ui
+++ b/extensions/contact_sheet/data/ui/image-wall.ui
@@ -1,11 +1,11 @@
 <?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"/>
   <object class="GtkAdjustment" id="cols_adjustment">
     <property name="upper">100</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="filetype_liststore">
     <columns>
@@ -17,8 +17,8 @@
   </object>
   <object class="GtkAdjustment" id="rows_adjustment">
     <property name="upper">100</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="sort_liststore">
     <columns>
@@ -38,102 +38,131 @@
   </object>
   <object class="GtkBox" id="dialog_content">
     <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">5</property>
     <child>
       <object class="GtkBox" id="vbox1">
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="border_width">6</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">6</property>
+        <property name="spacing">12</property>
         <child>
           <object class="GtkFrame" id="frame1">
             <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="label-xalign">0</property>
+            <property name="shadow-type">none</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>
+                <property name="can-focus">False</property>
+                <property name="top-padding">6</property>
+                <property name="left-padding">12</property>
                 <child>
                   <object class="GtkBox" id="vbox5">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can-focus">False</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkTable" id="table4">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="n_rows">3</property>
-                        <property name="n_columns">2</property>
-                        <property name="column_spacing">6</property>
-                        <property name="row_spacing">6</property>
-                        <child>
-                          <placeholder/>
-                        </child>
+                        <property name="can-focus">False</property>
+                        <property name="n-rows">2</property>
+                        <property name="n-columns">2</property>
+                        <property name="column-spacing">6</property>
+                        <property name="row-spacing">6</property>
                         <child>
                           <object class="GtkLabel" id="label84">
                             <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_underline">True</property>
+                            <property name="use-underline">True</property>
                             <property name="xalign">0</property>
                           </object>
                           <packing>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkFileChooserButton" id="destination_filechooserbutton">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can-focus">False</property>
                             <property name="action">select-folder</property>
-                            <property name="local_only">False</property>
+                            <property name="local-only">False</property>
                             <property name="title" translatable="yes">Choose destination folder</property>
                           </object>
                           <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="left-attach">1</property>
+                            <property name="right-attach">2</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkLabel" id="label54">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can-focus">False</property>
                             <property name="label" translatable="yes">File_name:</property>
-                            <property name="use_underline">True</property>
-                            <property name="mnemonic_widget">template_entry</property>
+                            <property name="use-underline">True</property>
                             <property name="xalign">0</property>
                           </object>
                           <packing>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="top-attach">1</property>
+                            <property name="bottom-attach">2</property>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkBox" id="hbox47">
                             <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="template_entry">
+                              <object class="GtkBox">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">●</property>
-                                <property name="activates_default">True</property>
-                                <property name="text">###</property>
-                                <property name="secondary_icon_name">help-browser-symbolic</property>
+                                <property name="can-focus">False</property>
+                                <child>
+                                  <object class="GtkEntry" id="template_entry">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="invisible-char">●</property>
+                                    <property name="activates-default">True</property>
+                                    <property name="text">###</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_template_entry_button">
+                                    <property name="visible">True</property>
+                                    <property name="can-focus">True</property>
+                                    <property name="receives-default">True</property>
+                                    <property name="tooltip-text" translatable="yes">Edit template</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>
@@ -144,7 +173,7 @@
                             <child>
                               <object class="GtkComboBox" id="filetype_combobox">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                                <property name="can-focus">False</property>
                                 <property name="model">filetype_liststore</property>
                                 <property name="active">0</property>
                                 <child>
@@ -162,93 +191,11 @@
                             </child>
                           </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>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkTable" id="template_help_table">
-                            <property name="can_focus">False</property>
-                            <property name="n_rows">2</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">12</property>
-                            <property name="row_spacing">6</property>
-                            <child>
-                              <object class="GtkLabel" id="label32">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label">#</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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label34">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes">New enumerator digit</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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label36">
-                                <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>
-                              <packing>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label37">
-                                <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>
-                                <property name="y_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                          </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>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="left-attach">1</property>
+                            <property name="right-attach">2</property>
+                            <property name="top-attach">1</property>
+                            <property name="bottom-attach">2</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                       </object>
@@ -265,9 +212,9 @@
             <child type="label">
               <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">Saving</property>
-                <property name="use_markup">True</property>
+                <property name="use-markup">True</property>
                 <attributes>
                   <attribute name="weight" value="bold"/>
                 </attributes>
@@ -283,52 +230,52 @@
         <child>
           <object class="GtkFrame" id="frame3">
             <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="label-xalign">0</property>
+            <property name="shadow-type">none</property>
             <child>
               <object class="GtkAlignment" id="alignment5">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="top_padding">6</property>
-                <property name="left_padding">12</property>
+                <property name="can-focus">False</property>
+                <property name="top-padding">6</property>
+                <property name="left-padding">12</property>
                 <child>
                   <object class="GtkTable" id="table3">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="n_rows">2</property>
-                    <property name="n_columns">3</property>
-                    <property name="column_spacing">6</property>
-                    <property name="row_spacing">6</property>
+                    <property name="can-focus">False</property>
+                    <property name="n-rows">2</property>
+                    <property name="n-columns">3</property>
+                    <property name="column-spacing">6</property>
+                    <property name="row-spacing">6</property>
                     <child>
                       <placeholder/>
                     </child>
                     <child>
                       <object class="GtkLabel" id="label18">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="label" translatable="yes">Columns:</property>
                         <property name="xalign">0</property>
                       </object>
                       <packing>
-                        <property name="top_attach">1</property>
-                        <property name="bottom_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_FILL</property>
+                        <property name="y-options">GTK_FILL</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="cols_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="adjustment">cols_adjustment</property>
-                            <property name="climb_rate">1</property>
+                            <property name="climb-rate">1</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -338,26 +285,26 @@
                         </child>
                       </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>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
+                        <property name="left-attach">1</property>
+                        <property name="right-attach">2</property>
+                        <property name="top-attach">1</property>
+                        <property name="bottom-attach">2</property>
+                        <property name="x-options">GTK_FILL</property>
+                        <property name="y-options">GTK_FILL</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="GtkSpinButton" id="images_per_index_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="adjustment">rows_adjustment</property>
-                            <property name="climb_rate">1</property>
+                            <property name="climb-rate">1</property>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -367,40 +314,40 @@
                         </child>
                       </object>
                       <packing>
-                        <property name="left_attach">1</property>
-                        <property name="right_attach">2</property>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
+                        <property name="left-attach">1</property>
+                        <property name="right-attach">2</property>
+                        <property name="x-options">GTK_FILL</property>
+                        <property name="y-options">GTK_FILL</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkLabel" id="label28">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
+                        <property name="can-focus">False</property>
                         <property name="label" translatable="yes">Images per page:</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">images_per_index_spinbutton</property>
+                        <property name="use-underline">True</property>
+                        <property name="mnemonic-widget">images_per_index_spinbutton</property>
                         <property name="xalign">0</property>
                       </object>
                       <packing>
-                        <property name="x_options">GTK_FILL</property>
-                        <property name="y_options">GTK_FILL</property>
+                        <property name="x-options">GTK_FILL</property>
+                        <property name="y-options">GTK_FILL</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkCheckButton" id="single_index_checkbutton">
                         <property name="label" translatable="yes">All images on a single page</property>
-                        <property name="use_action_appearance">False</property>
+                        <property name="use-action-appearance">False</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</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="draw-indicator">True</property>
                       </object>
                       <packing>
-                        <property name="left_attach">2</property>
-                        <property name="right_attach">3</property>
-                        <property name="y_options">GTK_FILL</property>
+                        <property name="left-attach">2</property>
+                        <property name="right-attach">3</property>
+                        <property name="y-options">GTK_FILL</property>
                       </packing>
                     </child>
                   </object>
@@ -410,9 +357,9 @@
             <child type="label">
               <object class="GtkLabel" id="label6">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="label" translatable="yes">Layout</property>
-                <property name="use_markup">True</property>
+                <property name="use-markup">True</property>
                 <attributes>
                   <attribute name="weight" value="bold"/>
                 </attributes>
@@ -428,51 +375,51 @@
         <child>
           <object class="GtkFrame" id="frame4">
             <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="label-xalign">0</property>
+            <property name="shadow-type">none</property>
             <child>
               <object class="GtkAlignment" id="alignment6">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="top_padding">6</property>
-                <property name="left_padding">12</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="can-focus">False</property>
                     <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkTable" id="table1">
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="n_rows">2</property>
-                        <property name="n_columns">2</property>
-                        <property name="column_spacing">6</property>
-                        <property name="row_spacing">6</property>
+                        <property name="can-focus">False</property>
+                        <property name="n-rows">2</property>
+                        <property name="n-columns">2</property>
+                        <property name="column-spacing">6</property>
+                        <property name="row-spacing">6</property>
                         <child>
                           <object class="GtkLabel" id="label112">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can-focus">False</property>
                             <property name="label" translatable="yes">S_ort:</property>
-                            <property name="use_underline">True</property>
+                            <property name="use-underline">True</property>
                             <property name="xalign">0</property>
                           </object>
                           <packing>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options"/>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options"/>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkBox" id="hbox62">
                             <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="GtkComboBox" id="sort_combobox">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                                <property name="can-focus">False</property>
                                 <property name="model">sort_liststore</property>
                                 <child>
                                   <object class="GtkCellRendererText" id="cellrenderertext2"/>
@@ -490,13 +437,13 @@
                             <child>
                               <object class="GtkCheckButton" id="reverse_order_checkbutton">
                                 <property name="label" translatable="yes">Re_verse order</property>
-                                <property name="use_action_appearance">False</property>
+                                <property name="use-action-appearance">False</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="can-focus">True</property>
+                                <property name="receives-default">False</property>
+                                <property name="use-underline">True</property>
                                 <property name="xalign">0</property>
-                                <property name="draw_indicator">True</property>
+                                <property name="draw-indicator">True</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -506,36 +453,36 @@
                             </child>
                           </object>
                           <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="left-attach">1</property>
+                            <property name="right-attach">2</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                         <child>
                           <object class="GtkLabel" id="size_label">
                             <property name="visible">True</property>
-                            <property name="can_focus">False</property>
+                            <property name="can-focus">False</property>
                             <property name="label" translatable="yes">_Size:</property>
-                            <property name="use_underline">True</property>
+                            <property name="use-underline">True</property>
                             <property name="justify">center</property>
                             <property name="xalign">0</property>
                           </object>
                           <packing>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="top-attach">1</property>
+                            <property name="bottom-attach">2</property>
+                            <property name="x-options">GTK_FILL</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                         <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="GtkComboBox" id="thumbnail_size_combobox">
                                 <property name="visible">True</property>
-                                <property name="can_focus">False</property>
+                                <property name="can-focus">False</property>
                                 <property name="model">thumbnail_size_liststore</property>
                                 <child>
                                   <object class="GtkCellRendererText" id="cellrenderertext5"/>
@@ -552,11 +499,11 @@
                             </child>
                           </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>
-                            <property name="y_options">GTK_FILL</property>
+                            <property name="left-attach">1</property>
+                            <property name="right-attach">2</property>
+                            <property name="top-attach">1</property>
+                            <property name="bottom-attach">2</property>
+                            <property name="y-options">GTK_FILL</property>
                           </packing>
                         </child>
                       </object>
@@ -573,9 +520,9 @@
             <child type="label">
               <object class="GtkLabel" id="label5">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can-focus">False</property>
                 <property name="label" translatable="yes">Thumbnails</property>
-                <property name="use_markup">True</property>
+                <property name="use-markup">True</property>
                 <attributes>
                   <attribute name="weight" value="bold"/>
                 </attributes>
diff --git a/extensions/contact_sheet/dlg-contact-sheet.c b/extensions/contact_sheet/dlg-contact-sheet.c
index 8a624e96..9faf6cdd 100644
--- a/extensions/contact_sheet/dlg-contact-sheet.c
+++ b/extensions/contact_sheet/dlg-contact-sheet.c
@@ -31,6 +31,18 @@
 #define STRING_IS_VOID(x) (((x) == NULL) || (*(x) == 0))
 #define PREVIEW_SIZE 112
 
+static GthTemplateCode Filename_Special_Codes[] = {
+       { GTH_TEMPLATE_CODE_TYPE_ENUMERATOR, N_("Enumerator") },
+       { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Current date"), 'D', 1 },
+};
+
+static GthTemplateCode Text_Special_Codes[] = {
+       { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Current page number"), 'p', 0 },
+       { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Total number of pages"), 'n', 0 },
+       { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Current date"), 'D', 1 },
+       { GTH_TEMPLATE_CODE_TYPE_SIMPLE, N_("Location"), 'L', 0 },
+};
+
 enum {
        THEME_COLUMN_THEME,
        THEME_COLUMN_DISPLAY_NAME,
@@ -53,13 +65,14 @@ enum {
 };
 
 typedef struct {
-       GthBrowser *browser;
-       GSettings  *settings;
-       GList      *file_list;
-       GtkBuilder *builder;
-       GtkWidget  *dialog;
-       GtkWidget  *thumbnail_caption_chooser;
-       gulong      theme_selection_changed_event;
+       GthBrowser  *browser;
+       GthFileData *location;
+       GSettings   *settings;
+       GList       *file_list;
+       GtkBuilder  *builder;
+       GtkWidget   *dialog;
+       GtkWidget   *thumbnail_caption_chooser;
+       gulong       theme_selection_changed_event;
 } DialogData;
 
 
@@ -87,6 +100,7 @@ destroy_cb (GtkWidget  *widget,
        _g_object_list_unref (data->file_list);
        g_object_unref (data->settings);
        g_object_unref (data->builder);
+       _g_object_unref (data->location);
        g_free (data);
 }
 
@@ -249,6 +263,7 @@ ok_clicked_cb (GtkWidget  *widget,
        gth_contact_sheet_creator_set_same_size (GTH_CONTACT_SHEET_CREATOR (task), same_size);
        gth_contact_sheet_creator_set_thumb_size (GTH_CONTACT_SHEET_CREATOR (task), squared_thumbnail, 
thumbnail_size, thumbnail_size);
        gth_contact_sheet_creator_set_thumbnail_caption (GTH_CONTACT_SHEET_CREATOR (task), thumbnail_caption);
+       gth_contact_sheet_creator_set_location_name (GTH_CONTACT_SHEET_CREATOR (task), 
g_file_info_get_edit_name (gth_browser_get_location_data (data->browser)->info));
 
        gth_browser_exec_task (data->browser, task, GTH_TASK_FLAGS_DEFAULT);
        close_dialog (data);
@@ -679,6 +694,133 @@ theme_iconview_selection_changed_cb (GtkIconView *iconview,
 }
 
 
+static gboolean
+text_preview_cb (TemplateFlags   flags,
+                gunichar        parent_code,
+                gunichar        code,
+                char          **args,
+                GString        *result,
+                gpointer        user_data)
+{
+       DialogData *data = user_data;
+       GDateTime  *timestamp;
+       char       *text;
+
+       if (parent_code == 'D') {
+               /* strftime code, return the code itself. */
+               _g_string_append_template_code (result, code, args);
+               return FALSE;
+       }
+
+       if (code != 0)
+               g_string_append (result, "<span foreground=\"#4696f8\">");
+
+       switch (code) {
+       case 'p':
+               g_string_append (result, "1");
+               break;
+
+       case 'n':
+               g_string_append (result, "5");
+               break;
+
+       case 'D':
+               timestamp = g_date_time_new_now_local ();
+               text = g_date_time_format (timestamp,
+                                          (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT);
+               g_string_append (result, text);
+
+               g_free (text);
+               g_date_time_unref (timestamp);
+               break;
+
+       case 'L':
+               g_string_append (result, g_file_info_get_edit_name (data->location->info));
+               break;
+
+       default:
+               break;
+       }
+
+       if (code != 0)
+               g_string_append (result, "</span>");
+
+       return FALSE;
+}
+
+
+static void
+edit_header_button_clicked_cb (GtkButton *button,
+                              gpointer   user_data)
+{
+       DialogData *data = user_data;
+       GtkWidget  *dialog;
+
+       dialog = gth_template_editor_dialog_new (Text_Special_Codes,
+                                                G_N_ELEMENTS (Text_Special_Codes),
+                                                0,
+                                                _("Edit Template"),
+                                                GTK_WINDOW (data->dialog));
+       gth_template_editor_dialog_set_preview_cb (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                  text_preview_cb,
+                                                  data);
+       gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                gtk_entry_get_text (GTK_ENTRY (GET_WIDGET 
("header_entry"))));
+       g_signal_connect (dialog,
+                         "response",
+                         G_CALLBACK (gth_template_editor_dialog_default_response),
+                         GET_WIDGET ("header_entry"));
+       gtk_widget_show (dialog);
+}
+
+
+static void
+edit_footer_button_clicked_cb (GtkButton *button,
+                              gpointer   user_data)
+{
+       DialogData *data = user_data;
+       GtkWidget  *dialog;
+
+       dialog = gth_template_editor_dialog_new (Text_Special_Codes,
+                                                G_N_ELEMENTS (Text_Special_Codes),
+                                                0,
+                                                _("Edit Template"),
+                                                GTK_WINDOW (data->dialog));
+       gth_template_editor_dialog_set_preview_cb (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                  text_preview_cb,
+                                                  data);
+       gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                gtk_entry_get_text (GTK_ENTRY (GET_WIDGET 
("footer_entry"))));
+       g_signal_connect (dialog,
+                         "response",
+                         G_CALLBACK (gth_template_editor_dialog_default_response),
+                         GET_WIDGET ("footer_entry"));
+       gtk_widget_show (dialog);
+}
+
+
+static void
+edit_filename_button_clicked_cb (GtkButton *button,
+                                gpointer   user_data)
+{
+       DialogData *data = user_data;
+       GtkWidget  *dialog;
+
+       dialog = gth_template_editor_dialog_new (Filename_Special_Codes,
+                                                G_N_ELEMENTS (Filename_Special_Codes),
+                                                0,
+                                                _("Edit Template"),
+                                                GTK_WINDOW (data->dialog));
+       gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                gtk_entry_get_text (GTK_ENTRY (GET_WIDGET 
("template_entry"))));
+       g_signal_connect (dialog,
+                         "response",
+                         G_CALLBACK (gth_template_editor_dialog_default_response),
+                         GET_WIDGET ("template_entry"));
+       gtk_widget_show (dialog);
+}
+
+
 void
 dlg_contact_sheet (GthBrowser *browser,
                   GList      *file_list)
@@ -690,7 +832,6 @@ dlg_contact_sheet (GthBrowser *browser,
        GList      *sort_types;
        GList      *scan;
        char       *caption;
-       GFile      *location;
        char       *s_value;
        char       *default_mime_type;
        GArray     *savers;
@@ -702,6 +843,7 @@ dlg_contact_sheet (GthBrowser *browser,
 
        data = g_new0 (DialogData, 1);
        data->browser = browser;
+       data->location = gth_file_data_dup (gth_browser_get_location_data (data->browser));
        data->file_list = _g_object_list_ref (file_list);
        data->builder = _gtk_builder_new_from_file ("contact-sheet.ui", "contact_sheet");
        data->settings = g_settings_new (GTHUMB_CONTACT_SHEET_SCHEMA);
@@ -730,16 +872,16 @@ dlg_contact_sheet (GthBrowser *browser,
 
        /* Set widgets data. */
 
-       gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("header_entry")),
-                           g_file_info_get_edit_name (gth_browser_get_location_data (browser)->info));
+       s_value = g_settings_get_string (data->settings, PREF_CONTACT_SHEET_HEADER);
+       gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("header_entry")), s_value);
+       g_free (s_value);
 
        s_value = g_settings_get_string (data->settings, PREF_CONTACT_SHEET_FOOTER);
        gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("footer_entry")), s_value);
        g_free (s_value);
 
-       location = gth_browser_get_location (data->browser);
-       if ((location != NULL) && g_file_has_uri_scheme (location, "file"))
-               s_value = g_file_get_uri (location);
+       if ((data->location != NULL) && g_file_has_uri_scheme (data->location->file, "file"))
+               s_value = g_file_get_uri (data->location->file);
        else
                s_value = _g_settings_get_uri (data->settings, PREF_CONTACT_SHEET_DESTINATION);
        if (s_value == NULL)
@@ -879,6 +1021,18 @@ dlg_contact_sheet (GthBrowser *browser,
                                          "selection-changed",
                                          G_CALLBACK (theme_iconview_selection_changed_cb),
                                          data);
+       g_signal_connect (GET_WIDGET ("edit_header_button"),
+                         "clicked",
+                         G_CALLBACK (edit_header_button_clicked_cb),
+                         data);
+       g_signal_connect (GET_WIDGET ("edit_footer_button"),
+                         "clicked",
+                         G_CALLBACK (edit_footer_button_clicked_cb),
+                         data);
+       g_signal_connect (GET_WIDGET ("edit_filename_button"),
+                         "clicked",
+                         G_CALLBACK (edit_filename_button_clicked_cb),
+                         data);
 
        /* Run dialog. */
 
diff --git a/extensions/contact_sheet/dlg-image-wall.c b/extensions/contact_sheet/dlg-image-wall.c
index 9a397e8a..c71b2cb0 100644
--- a/extensions/contact_sheet/dlg-image-wall.c
+++ b/extensions/contact_sheet/dlg-image-wall.c
@@ -30,6 +30,12 @@
 #define STRING_IS_VOID(x) (((x) == NULL) || (*(x) == 0))
 
 
+static GthTemplateCode Filename_Special_Codes[] = {
+       { GTH_TEMPLATE_CODE_TYPE_ENUMERATOR, N_("Enumerator") },
+       { GTH_TEMPLATE_CODE_TYPE_DATE, N_("Current date"), 'D', 1 },
+};
+
+
 enum {
        SORT_TYPE_COLUMN_DATA,
        SORT_TYPE_COLUMN_NAME
@@ -213,6 +219,27 @@ entry_help_icon_press_cb (GtkEntry             *entry,
 }
 
 
+static void
+edit_template_entry_button_clicked_cb (GtkWidget  *widget,
+                                      DialogData *data)
+{
+       GtkWidget *dialog;
+
+       dialog = gth_template_editor_dialog_new (Filename_Special_Codes,
+                                                G_N_ELEMENTS (Filename_Special_Codes),
+                                                0,
+                                                _("Edit Template"),
+                                                GTK_WINDOW (data->dialog));
+       gth_template_editor_dialog_set_template (GTH_TEMPLATE_EDITOR_DIALOG (dialog),
+                                                gtk_entry_get_text (GTK_ENTRY (GET_WIDGET 
("template_entry"))));
+       g_signal_connect (dialog,
+                         "response",
+                         G_CALLBACK (gth_template_editor_dialog_default_response),
+                         GET_WIDGET ("template_entry"));
+       gtk_widget_show (dialog);
+}
+
+
 void
 dlg_image_wall (GthBrowser *browser,
                GList      *file_list)
@@ -368,6 +395,10 @@ dlg_image_wall (GthBrowser *browser,
                                  "toggled",
                                  G_CALLBACK (update_sensitivity),
                                  data);
+       g_signal_connect (GET_WIDGET ("edit_template_entry_button"),
+                         "clicked",
+                         G_CALLBACK (edit_template_entry_button_clicked_cb),
+                         data);
 
        /* Run dialog. */
 
diff --git a/extensions/contact_sheet/gth-contact-sheet-creator.c 
b/extensions/contact_sheet/gth-contact-sheet-creator.c
index 980177b0..3388d9d4 100644
--- a/extensions/contact_sheet/gth-contact-sheet-creator.c
+++ b/extensions/contact_sheet/gth-contact-sheet-creator.c
@@ -89,6 +89,7 @@ struct _GthContactSheetCreatorPrivate {
        int                   thumb_width;
        int                   thumb_height;
        char                 *thumbnail_caption;
+       char                 *location_name;
 
        /* private data */
 
@@ -111,6 +112,7 @@ struct _GthContactSheetCreatorPrivate {
        int                   n_pages;
        char                **thumbnail_caption_v;
        char                **template_v;
+       GDateTime            *timestamp;
 };
 
 
@@ -231,44 +233,49 @@ get_page_height (GthContactSheetCreator *self,
 }
 
 
-static char *
-_g_get_name_from_template (char **utf8_template,
-                          int    n)
-{
-       GString *s;
-       int      i;
-       char    *result;
+typedef struct {
+       GthContactSheetCreator *creator;
+       int                     page;
+} TemplateData;
 
-       s = g_string_new (NULL);
 
-       for (i = 0; utf8_template[i] != NULL; i++) {
-               const char *chunk = utf8_template[i];
-               gunichar    ch = g_utf8_get_char (chunk);
+static gboolean
+filename_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 (ch != '#')
-                       g_string_append (s, chunk);
-               else {
-                       char *s_n;
-                       int   s_n_len;
-                       int   sharps_len = g_utf8_strlen (chunk, -1);
+       if (parent_code == 'D') {
+               /* strftime code, return the code itself. */
+               _g_string_append_template_code (result, code, args);
+               return FALSE;
+       }
 
-                       s_n = g_strdup_printf ("%d", n);
-                       s_n_len = strlen (s_n);
+       switch (code) {
+       case '#':
+               text = _g_template_replace_enumerator (args[0], template_data->page);
+               break;
 
-                       while (s_n_len < sharps_len) {
-                               g_string_append_c (s, '0');
-                               sharps_len--;
-                       }
+       case 'D':
+               text = g_date_time_format (template_data->creator->priv->timestamp,
+                                          (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT);
+               break;
 
-                       g_string_append (s, s_n);
-                       g_free (s_n);
-               }
+       default:
+               break;
        }
 
-       result = s->str;
-       g_string_free (s, FALSE);
+       if (text != NULL) {
+               g_string_append (result, text);
+               g_free (text);
+       }
 
-       return result;
+       return FALSE;
 }
 
 
@@ -276,13 +283,19 @@ static void
 begin_page (GthContactSheetCreator *self,
            int                     page_n)
 {
+       TemplateData     template_data;
        char            *name;
        char            *display_name;
        int              width;
        int              height;
        cairo_surface_t *surface;
 
-       name = _g_get_name_from_template (self->priv->template_v, page_n - 1);
+       template_data.creator = self;
+       template_data.page = page_n - 1;
+       name = _g_template_eval (self->priv->template,
+                                0,
+                                filename_template_eval_cb,
+                                &template_data);
        display_name = g_strdup_printf ("%s.%s", name, self->priv->file_extension);
        _g_object_unref (self->priv->destination_file);
        self->priv->destination_file = g_file_get_child_for_display_name (self->priv->destination, 
display_name, NULL);
@@ -448,7 +461,7 @@ end_page (GthContactSheetCreator  *self,
                                                       error))
                {
                        return FALSE;
-               }
+               }
 
                if (! g_output_stream_close (G_OUTPUT_STREAM (self->priv->imagemap_stream),
                                             gth_task_get_cancellable (GTH_TASK (self)),
@@ -466,35 +479,50 @@ end_page (GthContactSheetCreator  *self,
 /* -- get_text -- */
 
 
-typedef struct {
-       GthContactSheetCreator *self;
-       int                     page_n;
-} TemplateData;
-
-
 static gboolean
-text_eval_cb (const GMatchInfo *info,
-             GString          *res,
-             gpointer          data)
+text_template_eval_cb (TemplateFlags   flags,
+                      gunichar        parent_code,
+                      gunichar        code,
+                      char          **args,
+                      GString        *result,
+                      gpointer        user_data)
 {
-       TemplateData *template_data = data;
-       char         *r = NULL;
-       char         *match;
-
-       match = g_match_info_fetch (info, 0);
+       TemplateData *template_data = user_data;
+       char         *text = NULL;
 
-       if (strcmp (match, "%p") == 0) {
-               r = g_strdup_printf ("%d", template_data->page_n);
-       }
-       else if (strcmp (match, "%n") == 0) {
-               r = g_strdup_printf ("%d", template_data->self->priv->n_pages);
+       if (parent_code == 'D') {
+               /* strftime code, return the code itself. */
+               _g_string_append_template_code (result, code, args);
+               return FALSE;
        }
 
-       if (r != NULL)
-               g_string_append (res, r);
+       switch (code) {
+       case 'p':
+               text = g_strdup_printf ("%d", template_data->page);
+               break;
+
+       case 'n':
+               text = g_strdup_printf ("%d", template_data->creator->priv->n_pages);
+               break;
+
+       case 'D':
+               text = g_date_time_format (template_data->creator->priv->timestamp,
+                                          (args[0] != NULL) ? args[0] : DEFAULT_STRFTIME_FORMAT);
+               break;
+
+       case 'L':
+               if (template_data->creator->priv->location_name != NULL)
+                       g_string_append (result, template_data->creator->priv->location_name);
+               break;
 
-       g_free (r);
-       g_free (match);
+       default:
+               break;
+       }
+
+       if (text != NULL) {
+               g_string_append (result, text);
+               g_free (text);
+       }
 
        return FALSE;
 }
@@ -505,18 +533,14 @@ get_text (GthContactSheetCreator *self,
          const char             *text,
          int                     page_n)
 {
-       GRegex       *re;
-       TemplateData  template_data;
-       char         *new_text;
-
-       re = g_regex_new ("%[pn]", 0, 0, NULL);
-       template_data.self = self;
-       template_data.page_n = page_n;
-       new_text = g_regex_replace_eval (re, text, -1, 0, 0, text_eval_cb, &template_data, NULL);
-
-       g_regex_unref (re);
-
-       return new_text;
+       TemplateData template_data;
+
+       template_data.creator = self;
+       template_data.page = page_n;
+       return _g_template_eval (text,
+                                0,
+                                text_template_eval_cb,
+                                &template_data);
 }
 
 
@@ -656,6 +680,10 @@ export (GthContactSheetCreator *self)
        GList     *scan;
        GError    *error = NULL;
 
+       if (self->priv->timestamp != NULL)
+               g_date_time_unref (self->priv->timestamp);
+       self->priv->timestamp = g_date_time_new_now_local ();
+
        columns = ((self->priv->page_width - self->priv->theme->col_spacing) / (self->priv->thumb_width + 
(self->priv->theme->frame_hpadding * 2) + self->priv->theme->col_spacing));
        first_row = TRUE;
        begin_page (self, ++page_n);
@@ -816,8 +844,13 @@ export (GthContactSheetCreator *self)
                                            self->priv->destination,
                                            self->priv->created_files,
                                            GTH_MONITOR_EVENT_CREATED);
-               if (error == NULL)
-                       gth_browser_go_to (self->priv->browser, self->priv->destination, (GFile *) 
self->priv->created_files->data);
+               if (error == NULL) {
+                       GtkWidget *new_window;
+
+                       new_window = gth_browser_new ((GFile *) self->priv->created_files->data,
+                                                     NULL);
+                       gtk_window_present (GTK_WINDOW (new_window));
+               }
 
                _g_object_list_unref (self->priv->created_files);
                self->priv->created_files = NULL;
@@ -1089,6 +1122,9 @@ gth_contact_sheet_creator_finalize (GObject *object)
        g_free (self->priv->footer);
        g_free (self->priv->header);
        _g_object_list_unref (self->priv->gfile_list);
+       if (self->priv->timestamp != NULL)
+               g_date_time_unref (self->priv->timestamp);
+       g_free (self->priv->location_name);
 
        G_OBJECT_CLASS (gth_contact_sheet_creator_parent_class)->finalize (object);
 }
@@ -1142,6 +1178,8 @@ gth_contact_sheet_creator_init (GthContactSheetCreator *self)
        self->priv->thumb_width = DEFAULT_THUMB_SIZE;
        self->priv->thumb_height = DEFAULT_THUMB_SIZE;
        self->priv->thumbnail_caption = NULL;
+       self->priv->location_name = NULL;
+       self->priv->timestamp = NULL;
 }
 
 
@@ -1193,7 +1231,7 @@ gth_contact_sheet_creator_set_filename_template (GthContactSheetCreator *self,
        _g_str_set (&self->priv->template, filename_template);
        if (self->priv->template_v != NULL)
                g_strfreev (self->priv->template_v);
-       self->priv->template_v = _g_utf8_split_template (self->priv->template);
+       self->priv->template_v = _g_template_tokenize (self->priv->template, 0);
 }
 
 
@@ -1290,3 +1328,11 @@ gth_contact_sheet_creator_set_thumbnail_caption (GthContactSheetCreator *self,
        _g_str_set (&self->priv->thumbnail_caption, caption);
        self->priv->thumbnail_caption_v = g_strsplit (self->priv->thumbnail_caption, ",", -1);
 }
+
+
+void
+gth_contact_sheet_creator_set_location_name (GthContactSheetCreator *self,
+                                            const char             *name)
+{
+       _g_str_set (&self->priv->location_name, name);
+}
diff --git a/extensions/contact_sheet/gth-contact-sheet-creator.h 
b/extensions/contact_sheet/gth-contact-sheet-creator.h
index 2b011813..d38a0902 100644
--- a/extensions/contact_sheet/gth-contact-sheet-creator.h
+++ b/extensions/contact_sheet/gth-contact-sheet-creator.h
@@ -84,5 +84,7 @@ void       gth_contact_sheet_creator_set_thumb_size        (GthContactSheetCreat
                                                            int                       height);
 void       gth_contact_sheet_creator_set_thumbnail_caption (GthContactSheetCreator   *self,
                                                            const char               *caption);
+void       gth_contact_sheet_creator_set_location_name     (GthContactSheetCreator   *self,
+                                                           const char               *name);
 
 #endif /* GTH_CONTACT_SHEET_CREATOR_H */


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