[latexila/wip/templates-revamp] TemplatesDefault and TemplatesPersonal classes



commit 321c3f46318c8ffce1a5b603255387be585110f7
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Apr 18 19:02:10 2015 +0200

    TemplatesDefault and TemplatesPersonal classes
    
    Slightly better code design.
    
    Before, LatexilaTemplates (the model) contained functions for the view,
    returning a GtkTreeView. Then for some functions the GtkTreePath must
    come from the good view; just the fact that it must be documented is a
    smell for a bad design. Now a GtkTreePath argument to a GtkListStore
    subclass makes perfect sense, and doesn't need extra documentation.

 docs/reference/Makefile.am                    |    3 +-
 docs/reference/latexila-docs.xml              |    3 +-
 docs/reference/latexila-sections.txt          |   31 +-
 po/POTFILES.in                                |    4 +-
 src/liblatexila/Makefile.am                   |    8 +-
 src/liblatexila/latexila-templates-common.c   |  132 ++++++
 src/liblatexila/latexila-templates-common.h   |   58 +++
 src/liblatexila/latexila-templates-default.c  |  248 ++++++++++
 src/liblatexila/latexila-templates-default.h  |   38 ++
 src/liblatexila/latexila-templates-dialogs.c  |   42 +-
 src/liblatexila/latexila-templates-personal.c |  241 ++++++++++
 src/liblatexila/latexila-templates-personal.h |   38 ++
 src/liblatexila/latexila-templates.c          |  619 -------------------------
 src/liblatexila/latexila-templates.h          |   44 --
 src/main_window_file.vala                     |    2 +-
 15 files changed, 811 insertions(+), 700 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 7f86569..1b33c0d 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -53,7 +53,8 @@ EXTRA_HFILES =
 # Header files or dirs to ignore when scanning. Use base file/dir names
 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
 IGNORE_HFILES =                                        \
-       latexila-enum-types.h
+       latexila-enum-types.h                   \
+       latexila-templates-common.h
 
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/docs/reference/latexila-docs.xml b/docs/reference/latexila-docs.xml
index 271077d..7f47169 100644
--- a/docs/reference/latexila-docs.xml
+++ b/docs/reference/latexila-docs.xml
@@ -22,8 +22,9 @@
     <xi:include href="xml/post-processor-latex.xml"/>
     <xi:include href="xml/post-processor-latexmk.xml"/>
     <xi:include href="xml/synctex.xml"/>
-    <xi:include href="xml/templates.xml"/>
     <xi:include href="xml/templates-dialogs.xml"/>
+    <xi:include href="xml/templates-default.xml"/>
+    <xi:include href="xml/templates-personal.xml"/>
     <xi:include href="xml/utils.xml"/>
   </chapter>
 
diff --git a/docs/reference/latexila-sections.txt b/docs/reference/latexila-sections.txt
index 4efdfcf..8e8ad02 100644
--- a/docs/reference/latexila-sections.txt
+++ b/docs/reference/latexila-sections.txt
@@ -230,22 +230,29 @@ latexila_synctex_get_type
 </SECTION>
 
 <SECTION>
-<FILE>templates</FILE>
-<TITLE>LatexilaTemplates</TITLE>
-LatexilaTemplates
-latexila_templates_get_instance
-latexila_templates_get_default_templates_view
-latexila_templates_get_personal_templates_view
-latexila_templates_get_default_template_contents
-latexila_templates_get_personal_template_contents
+<FILE>templates-dialogs</FILE>
+<TITLE>LatexilaTemplatesDialogs</TITLE>
+latexila_templates_dialogs_open
+</SECTION>
+
+<SECTION>
+<FILE>templates-default</FILE>
+<TITLE>LatexilaTemplatesDefault</TITLE>
+LatexilaTemplatesDefault
+latexila_templates_default_get_instance
+latexila_templates_default_get_contents
 <SUBSECTION Standard>
-LATEXILA_TYPE_TEMPLATES
+LATEXILA_TYPE_TEMPLATES_DEFAULT
 </SECTION>
 
 <SECTION>
-<FILE>templates-dialogs</FILE>
-<TITLE>LatexilaTemplatesDialogs</TITLE>
-latexila_templates_dialogs_open
+<FILE>templates-personal</FILE>
+<TITLE>LatexilaTemplatesPersonal</TITLE>
+LatexilaTemplatesPersonal
+latexila_templates_personal_get_instance
+latexila_templates_personal_get_contents
+<SUBSECTION Standard>
+LATEXILA_TYPE_TEMPLATES_PERSONAL
 </SECTION>
 
 <SECTION>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bb6c33a..5dfe577 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -36,8 +36,10 @@ src/liblatexila/latexila-post-processor.c
 src/liblatexila/latexila-post-processor-latex.c
 src/liblatexila/latexila-post-processor-latexmk.c
 src/liblatexila/latexila-synctex.c
+src/liblatexila/latexila-templates-common.c
+src/liblatexila/latexila-templates-default.c
 src/liblatexila/latexila-templates-dialogs.c
-src/liblatexila/latexila-templates.c
+src/liblatexila/latexila-templates-personal.c
 src/liblatexila/latexila-utils.c
 src/main.vala
 src/main_window_build_tools.vala
diff --git a/src/liblatexila/Makefile.am b/src/liblatexila/Makefile.am
index aef1085..7a85fa4 100644
--- a/src/liblatexila/Makefile.am
+++ b/src/liblatexila/Makefile.am
@@ -23,8 +23,10 @@ liblatexila_headers =                                \
        latexila-post-processor-latex.h         \
        latexila-post-processor-latexmk.h       \
        latexila-synctex.h                      \
-       latexila-templates.h                    \
+       latexila-templates-common.h             \
+       latexila-templates-default.h            \
        latexila-templates-dialogs.h            \
+       latexila-templates-personal.h           \
        latexila-types.h                        \
        latexila-utils.h
 
@@ -40,8 +42,10 @@ liblatexila_sources =                                \
        latexila-post-processor-latex.c         \
        latexila-post-processor-latexmk.c       \
        latexila-synctex.c                      \
-       latexila-templates.c                    \
+       latexila-templates-common.c             \
+       latexila-templates-default.c            \
        latexila-templates-dialogs.c            \
+       latexila-templates-personal.c           \
        latexila-utils.c
 
 liblatexila_built_sources =    \
diff --git a/src/liblatexila/latexila-templates-common.c b/src/liblatexila/latexila-templates-common.c
new file mode 100644
index 0000000..8d45153
--- /dev/null
+++ b/src/liblatexila/latexila-templates-common.c
@@ -0,0 +1,132 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Common functions between default and personal templates. */
+
+#include "latexila-templates-common.h"
+
+void
+latexila_templates_init_store (GtkListStore *store)
+{
+  GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_FILE};
+
+  gtk_list_store_set_column_types (store,
+                                   LATEXILA_TEMPLATES_N_COLUMNS,
+                                   types);
+}
+
+/* For compatibility reasons. @config_icon_name is the string stored in the rc
+ * file, and the return value is the theme icon name used for the pixbuf. If we
+ * store directly the theme icon names in the rc file, old rc files must be
+ * modified via a script for example, but it's simpler like that.
+ * The config_icon_name can also be seen as the template _type_.
+ */
+static const gchar *
+get_pixbuf_icon_name (const gchar *config_icon_name)
+{
+  g_return_val_if_fail (config_icon_name != NULL, NULL);
+
+  if (g_str_equal (config_icon_name, "empty"))
+    return "text-x-preview";
+
+  if (g_str_equal (config_icon_name, "article"))
+    return "text-x-generic";
+
+  if (g_str_equal (config_icon_name, "report"))
+    return "x-office-document";
+
+  if (g_str_equal (config_icon_name, "book"))
+    return "accessories-dictionary";
+
+  if (g_str_equal (config_icon_name, "letter"))
+    return "emblem-mail";
+
+  if (g_str_equal (config_icon_name, "beamer"))
+    return "x-office-presentation";
+
+  g_return_val_if_reached (NULL);
+}
+
+void
+latexila_templates_add_template (GtkListStore *store,
+                                 const gchar  *name,
+                                 const gchar  *config_icon_name,
+                                 GFile        *file)
+{
+  GtkTreeIter iter;
+  const gchar *pixbuf_icon_name;
+
+  pixbuf_icon_name = get_pixbuf_icon_name (config_icon_name);
+
+  gtk_list_store_append (store, &iter);
+  gtk_list_store_set (store, &iter,
+                      LATEXILA_TEMPLATES_COLUMN_PIXBUF_ICON_NAME, pixbuf_icon_name,
+                      LATEXILA_TEMPLATES_COLUMN_CONFIG_ICON_NAME, config_icon_name,
+                      LATEXILA_TEMPLATES_COLUMN_NAME, name,
+                      LATEXILA_TEMPLATES_COLUMN_FILE, file,
+                      -1);
+}
+
+/**
+ * latexila_templates_get_view:
+ * @store: the #LatexilaTemplatesDefault or #LatexilaTemplatesPersonal instance.
+ *
+ * Returns: (transfer floating): a beautiful #GtkTreeView, just for you.
+ */
+GtkTreeView *
+latexila_templates_get_view (GtkListStore *store)
+{
+  GtkTreeView *view;
+  GtkTreeSelection *selection;
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+
+  view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)));
+  gtk_tree_view_set_headers_visible (view, FALSE);
+  gtk_widget_set_hexpand (GTK_WIDGET (view), TRUE);
+  gtk_widget_set_vexpand (GTK_WIDGET (view), TRUE);
+
+  selection = gtk_tree_view_get_selection (view);
+  gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+  /* Icon */
+  renderer = gtk_cell_renderer_pixbuf_new ();
+  g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+
+  column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                     renderer,
+                                                     "icon-name",
+                                                     LATEXILA_TEMPLATES_COLUMN_PIXBUF_ICON_NAME,
+                                                     NULL);
+
+  gtk_tree_view_append_column (view, column);
+
+  /* Name */
+  renderer = gtk_cell_renderer_text_new ();
+
+  column = gtk_tree_view_column_new_with_attributes (NULL,
+                                                     renderer,
+                                                     "text",
+                                                     LATEXILA_TEMPLATES_COLUMN_NAME,
+                                                     NULL);
+
+  gtk_tree_view_append_column (view, column);
+
+  return view;
+}
diff --git a/src/liblatexila/latexila-templates-common.h b/src/liblatexila/latexila-templates-common.h
new file mode 100644
index 0000000..e046cf9
--- /dev/null
+++ b/src/liblatexila/latexila-templates-common.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LATEXILA_TEMPLATES_COMMON_H__
+#define __LATEXILA_TEMPLATES_COMMON_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+enum _LatexilaTemplatesColumn
+{
+  LATEXILA_TEMPLATES_COLUMN_PIXBUF_ICON_NAME,
+
+  /* The string stored in the rc file (article, report, ...). For
+   * backward-compatibility reasons, this is not the same as PIXBUF_ICON_NAME.
+   */
+  LATEXILA_TEMPLATES_COLUMN_CONFIG_ICON_NAME,
+
+  LATEXILA_TEMPLATES_COLUMN_NAME,
+
+  /* The file where is stored the contents. For a default template this is an
+   * XML file, for a personal template this is a .tex file. A NULL file is
+   * valid for a default template, it means an empty template.
+   */
+  LATEXILA_TEMPLATES_COLUMN_FILE,
+
+  LATEXILA_TEMPLATES_N_COLUMNS
+};
+
+void            latexila_templates_init_store       (GtkListStore *store);
+
+void            latexila_templates_add_template     (GtkListStore *store,
+                                                     const gchar  *name,
+                                                     const gchar  *config_icon_name,
+                                                     GFile        *file);
+
+GtkTreeView *   latexila_templates_get_view         (GtkListStore *store);
+
+G_END_DECLS
+
+#endif /* __LATEXILA_TEMPLATES_COMMON_H__ */
diff --git a/src/liblatexila/latexila-templates-default.c b/src/liblatexila/latexila-templates-default.c
new file mode 100644
index 0000000..3e8df3b
--- /dev/null
+++ b/src/liblatexila/latexila-templates-default.c
@@ -0,0 +1,248 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:templates-default
+ * @title: LatexilaTemplatesDefault
+ * @short_description: Default templates
+ * @see_also: #LatexilaTemplatesPersonal
+ *
+ * #LatexilaTemplatesDefault is a singleton class that stores information about
+ * default templates. In LaTeXila, new documents are created from templates.
+ * There are a few default templates available, and personal templates can be
+ * created (see #LatexilaTemplatesPersonal).
+ *
+ * Each LaTeX user has probably different needs, and has a different set of
+ * templates. So it's better to keep a short list of default templates. It would
+ * be useless to have a hundred default templates, since anyway they would most
+ * probably not fit many users. For example each user has a different preamble,
+ * with different packages, configured differently, etc.
+ *
+ * In the git repository, default templates are located in the data/templates/
+ * directory. The templates are stored in XML format, with some chunks that are
+ * translatable or not. For example the babel package (or equivalent) is added
+ * to the preamble when LaTeXila is run in another language than English (and if
+ * a translation is available for that other language). Also, the letter
+ * template can be completely translated, using even a different document class
+ * that is more suitable for the target language.
+ */
+
+#include "config.h"
+#include "latexila-templates-default.h"
+#include <glib/gi18n.h>
+#include "latexila-templates-common.h"
+
+struct _LatexilaTemplatesDefault
+{
+  GtkListStore parent;
+};
+
+G_DEFINE_TYPE (LatexilaTemplatesDefault, latexila_templates_default, GTK_TYPE_LIST_STORE)
+
+static void
+latexila_templates_default_class_init (LatexilaTemplatesDefaultClass *klass)
+{
+}
+
+static void
+add_default_template (LatexilaTemplatesDefault *templates,
+                      const gchar              *name,
+                      const gchar              *config_icon_name,
+                      const gchar              *filename)
+{
+  gchar *path;
+  GFile *file;
+
+  path = g_build_filename (DATA_DIR, "templates", filename, NULL);
+  file = g_file_new_for_path (path);
+
+  latexila_templates_add_template (GTK_LIST_STORE (templates),
+                                   name,
+                                   config_icon_name,
+                                   file);
+
+  g_free (path);
+  g_object_unref (file);
+}
+
+static void
+latexila_templates_default_init (LatexilaTemplatesDefault *templates)
+{
+  latexila_templates_init_store (GTK_LIST_STORE (templates));
+
+  latexila_templates_add_template (GTK_LIST_STORE (templates),
+                                   _("Empty"),
+                                   "empty",
+                                   NULL);
+
+  add_default_template (templates, _("Article"), "article", "article.xml");
+  add_default_template (templates, _("Report"), "report", "report.xml");
+  add_default_template (templates, _("Book"), "book", "book.xml");
+  add_default_template (templates, _("Letter"), "letter", "letter.xml");
+  add_default_template (templates, _("Presentation"), "beamer", "beamer.xml");
+}
+
+/**
+ * latexila_templates_default_get_instance:
+ *
+ * Gets the instance of the #LatexilaTemplatesDefault singleton.
+ *
+ * Returns: (transfer none): the instance of #LatexilaTemplatesDefault.
+ */
+LatexilaTemplatesDefault *
+latexila_templates_default_get_instance (void)
+{
+  static LatexilaTemplatesDefault *instance = NULL;
+
+  if (instance == NULL)
+    instance = g_object_new (LATEXILA_TYPE_TEMPLATES_DEFAULT, NULL);
+
+  return instance;
+}
+
+static void
+parser_add_chunk (GString     *string,
+                  const gchar *chunk,
+                  gint         chunk_len)
+{
+  if (chunk == NULL)
+    return;
+
+  /* Remove the first '\n'. Without this, the XML files would be less well
+   * presented.
+   */
+  if (chunk[0] == '\n')
+    {
+      chunk = chunk + 1;
+
+      if (chunk_len != -1)
+        chunk_len--;
+    }
+
+  if (chunk_len != -1)
+    g_string_append_len (string, chunk, chunk_len);
+  else
+    g_string_append (string, chunk);
+}
+
+static void
+parser_text (GMarkupParseContext  *context,
+             const gchar          *text,
+             gsize                 text_len,
+             gpointer              user_data,
+             GError              **error)
+{
+  GString *template_contents = user_data;
+  const gchar *element;
+  gchar *text_nul_terminated = NULL;
+
+  element = g_markup_parse_context_get_element (context);
+
+  if (g_strcmp0 (element, "chunk") == 0)
+    {
+      parser_add_chunk (template_contents, text, text_len);
+    }
+
+  else if (g_strcmp0 (element, "translatableChunk") == 0)
+    {
+      const gchar *chunk;
+
+      text_nul_terminated = g_strndup (text, text_len);
+      chunk = _(text_nul_terminated);
+
+      parser_add_chunk (template_contents, chunk, -1);
+    }
+
+  else if (g_strcmp0 (element, "babel") == 0)
+    {
+      const gchar *translated_text;
+
+      text_nul_terminated = g_strndup (text, text_len);
+      translated_text = _(text_nul_terminated);
+
+      if (translated_text != text_nul_terminated)
+        parser_add_chunk (template_contents, translated_text, -1);
+    }
+
+  g_free (text_nul_terminated);
+}
+
+/**
+ * latexila_templates_default_get_contents:
+ * @templates: the #LatexilaTemplatesDefault instance.
+ * @path: the #GtkTreePath of a default template.
+ *
+ * Gets the contents of a default template.
+ *
+ * TODO load contents asynchronously.
+ *
+ * Returns: the default template's contents. Free with g_free().
+ */
+gchar *
+latexila_templates_default_get_contents (LatexilaTemplatesDefault *templates,
+                                         GtkTreePath              *path)
+{
+  GtkTreeIter iter;
+  GFile *xml_file;
+  gchar *xml_contents = NULL;
+  gsize xml_length;
+  GString *template_contents = NULL;
+  GMarkupParser parser = { NULL, NULL, parser_text, NULL, NULL };
+  GMarkupParseContext *context = NULL;
+  GError *error = NULL;
+
+  g_return_val_if_fail (LATEXILA_IS_TEMPLATES_DEFAULT (templates), NULL);
+
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (templates),
+                           &iter,
+                           path);
+
+  gtk_tree_model_get (GTK_TREE_MODEL (templates),
+                      &iter,
+                      LATEXILA_TEMPLATES_COLUMN_FILE, &xml_file,
+                      -1);
+
+  if (xml_file == NULL)
+    return g_strdup ("");
+
+  g_file_load_contents (xml_file, NULL, &xml_contents, &xml_length, NULL, &error);
+
+  template_contents = g_string_new (NULL);
+
+  if (error != NULL)
+    goto out;
+
+  context = g_markup_parse_context_new (&parser, 0, template_contents, NULL);
+  g_markup_parse_context_parse (context, xml_contents, xml_length, &error);
+
+out:
+  g_object_unref (xml_file);
+  g_free (xml_contents);
+
+  if (context != NULL)
+    g_markup_parse_context_unref (context);
+
+  if (error != NULL)
+    {
+      g_warning ("Error when loading default template contents: %s", error->message);
+      g_error_free (error);
+    }
+
+  return g_string_free (template_contents, FALSE);
+}
diff --git a/src/liblatexila/latexila-templates-default.h b/src/liblatexila/latexila-templates-default.h
new file mode 100644
index 0000000..a85e11e
--- /dev/null
+++ b/src/liblatexila/latexila-templates-default.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LATEXILA_TEMPLATES_DEFAULT_H__
+#define __LATEXILA_TEMPLATES_DEFAULT_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define LATEXILA_TYPE_TEMPLATES_DEFAULT latexila_templates_default_get_type ()
+G_DECLARE_FINAL_TYPE (LatexilaTemplatesDefault, latexila_templates_default, LATEXILA, TEMPLATES_DEFAULT, 
GtkListStore)
+
+LatexilaTemplatesDefault *
+              latexila_templates_default_get_instance           (void);
+
+gchar *       latexila_templates_default_get_contents           (LatexilaTemplatesDefault *templates,
+                                                                 GtkTreePath              *path);
+
+G_END_DECLS
+
+#endif /* __LATEXILA_TEMPLATES_DEFAULT_H__ */
diff --git a/src/liblatexila/latexila-templates-dialogs.c b/src/liblatexila/latexila-templates-dialogs.c
index 8259cff..062a684 100644
--- a/src/liblatexila/latexila-templates-dialogs.c
+++ b/src/liblatexila/latexila-templates-dialogs.c
@@ -19,13 +19,15 @@
 
 #include "latexila-templates-dialogs.h"
 #include <glib/gi18n.h>
-#include "latexila-templates.h"
+#include "latexila-templates-common.h"
+#include "latexila-templates-default.h"
+#include "latexila-templates-personal.h"
 #include "latexila-utils.h"
 
 static void
 init_open_dialog (GtkDialog   *dialog,
-                  GtkTreeView *default_templates,
-                  GtkTreeView *personal_templates)
+                  GtkTreeView *default_view,
+                  GtkTreeView *personal_view)
 {
   GtkContainer *hgrid;
   GtkWidget *scrolled_window;
@@ -43,7 +45,7 @@ init_open_dialog (GtkDialog   *dialog,
   gtk_widget_set_size_request (scrolled_window, 250, 200);
 
   gtk_container_add (GTK_CONTAINER (scrolled_window),
-                     GTK_WIDGET (default_templates));
+                     GTK_WIDGET (default_view));
 
   component = latexila_utils_get_dialog_component (_("Default Templates"), scrolled_window);
   gtk_container_add (hgrid, component);
@@ -55,7 +57,7 @@ init_open_dialog (GtkDialog   *dialog,
   gtk_widget_set_size_request (scrolled_window, 250, 200);
 
   gtk_container_add (GTK_CONTAINER (scrolled_window),
-                     GTK_WIDGET (personal_templates));
+                     GTK_WIDGET (personal_view));
 
   component = latexila_utils_get_dialog_component (_("Personal Templates"), scrolled_window);
   gtk_container_add (hgrid, component);
@@ -104,9 +106,10 @@ gchar *
 latexila_templates_dialogs_open (GtkWindow *parent_window)
 {
   GtkDialog *dialog;
-  LatexilaTemplates *templates;
-  GtkTreeView *default_templates;
-  GtkTreeView *personal_templates;
+  LatexilaTemplatesDefault *default_store;
+  LatexilaTemplatesPersonal *personal_store;
+  GtkTreeView *default_view;
+  GtkTreeView *personal_view;
   GtkTreeSelection *default_selection;
   GtkTreeSelection *personal_selection;
   gint response;
@@ -126,15 +129,17 @@ latexila_templates_dialogs_open (GtkWindow *parent_window)
 
   gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
 
-  templates = latexila_templates_get_instance ();
-  default_templates = latexila_templates_get_default_templates_view (templates);
-  personal_templates = latexila_templates_get_personal_templates_view (templates);
+  default_store = latexila_templates_default_get_instance ();
+  personal_store = latexila_templates_personal_get_instance ();
 
-  init_open_dialog (dialog, default_templates, personal_templates);
+  default_view = latexila_templates_get_view (GTK_LIST_STORE (default_store));
+  personal_view = latexila_templates_get_view (GTK_LIST_STORE (personal_store));
+
+  init_open_dialog (dialog, default_view, personal_view);
 
   /* Selection: at most one selected template in both GtkTreeViews. */
-  default_selection = gtk_tree_view_get_selection (default_templates);
-  personal_selection = gtk_tree_view_get_selection (personal_templates);
+  default_selection = gtk_tree_view_get_selection (default_view);
+  personal_selection = gtk_tree_view_get_selection (personal_view);
 
   g_signal_connect_object (default_selection,
                            "changed",
@@ -149,17 +154,16 @@ latexila_templates_dialogs_open (GtkWindow *parent_window)
                            0);
 
   /* Double-click */
-  g_signal_connect (default_templates,
+  g_signal_connect (default_view,
                     "row-activated",
                     G_CALLBACK (row_activated_cb),
                     dialog);
 
-  g_signal_connect (personal_templates,
+  g_signal_connect (personal_view,
                     "row-activated",
                     G_CALLBACK (row_activated_cb),
                     dialog);
 
-
   response = gtk_dialog_run (dialog);
 
   if (response == GTK_RESPONSE_OK)
@@ -173,7 +177,7 @@ latexila_templates_dialogs_open (GtkWindow *parent_window)
           g_assert (g_list_length (selected_rows) == 1);
 
           path = selected_rows->data;
-          contents = latexila_templates_get_default_template_contents (templates, path);
+          contents = latexila_templates_default_get_contents (default_store, path);
         }
 
       else if (gtk_tree_selection_count_selected_rows (personal_selection) > 0)
@@ -182,7 +186,7 @@ latexila_templates_dialogs_open (GtkWindow *parent_window)
           g_assert (g_list_length (selected_rows) == 1);
 
           path = selected_rows->data;
-          contents = latexila_templates_get_personal_template_contents (templates, path);
+          contents = latexila_templates_personal_get_contents (personal_store, path);
         }
 
       /* No templates selected. */
diff --git a/src/liblatexila/latexila-templates-personal.c b/src/liblatexila/latexila-templates-personal.c
new file mode 100644
index 0000000..c168c41
--- /dev/null
+++ b/src/liblatexila/latexila-templates-personal.c
@@ -0,0 +1,241 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:templates-personal
+ * @title: LatexilaTemplatesPersonal
+ * @short_description: Personal templates
+ * @see_also: #LatexilaTemplatesDefault
+ *
+ * #LatexilaTemplatesPersonal is a singleton class that stores information about
+ * pesonal templates.
+ *
+ * Personal templates are stored in the ~/.local/share/latexila/ directory.
+ * There is a templatesrc file that stores the list of names and icons. And the
+ * templates' contents are stored in 0.tex, 1.tex, 2.tex, etc, in the same order
+ * as in the templatesrc file.
+ */
+
+#include "config.h"
+#include "latexila-templates-personal.h"
+#include "latexila-templates-common.h"
+
+struct _LatexilaTemplatesPersonal
+{
+  GtkListStore parent;
+};
+
+G_DEFINE_TYPE (LatexilaTemplatesPersonal, latexila_templates_personal, GTK_TYPE_LIST_STORE)
+
+static void
+latexila_templates_personal_class_init (LatexilaTemplatesPersonalClass *klass)
+{
+}
+
+static GFile *
+get_rc_file (void)
+{
+  gchar *path;
+  GFile *rc_file;
+
+  path = g_build_filename (g_get_user_data_dir (), "latexila", "templatesrc", NULL);
+  rc_file = g_file_new_for_path (path);
+
+  g_free (path);
+  return rc_file;
+}
+
+static GFile *
+get_personal_template_file (gint template_num)
+{
+  gchar *filename;
+  gchar *path;
+  GFile *template_file;
+
+  filename = g_strdup_printf ("%d.tex", template_num);
+  path = g_build_filename (g_get_user_data_dir (), "latexila", filename, NULL);
+  template_file = g_file_new_for_path (path);
+
+  g_free (filename);
+  g_free (path);
+  return template_file;
+}
+
+static void
+rc_file_contents_loaded_cb (GFile                     *rc_file,
+                            GAsyncResult              *result,
+                            LatexilaTemplatesPersonal *templates)
+{
+  gchar *contents = NULL;
+  gsize length;
+  GKeyFile *key_file = NULL;
+  gchar **names = NULL;
+  gchar **icons = NULL;
+  gsize n_names;
+  gsize n_icons;
+  gint i;
+  GError *error = NULL;
+
+  g_file_load_contents_finish (rc_file, result, &contents, &length, NULL, &error);
+
+  if (error != NULL)
+    {
+      /* If the rc file doesn't exist, it means that there is no personal
+       * templates.
+       */
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          g_error_free (error);
+          error = NULL;
+        }
+
+      goto out;
+    }
+
+  key_file = g_key_file_new ();
+  g_key_file_load_from_data (key_file, contents, length, G_KEY_FILE_NONE, &error);
+
+  if (error != NULL)
+    goto out;
+
+  names = g_key_file_get_string_list (key_file, PACKAGE_NAME, "names", &n_names, &error);
+
+  if (error != NULL)
+    goto out;
+
+  icons = g_key_file_get_string_list (key_file, PACKAGE_NAME, "icons", &n_icons, &error);
+
+  if (error != NULL)
+    goto out;
+
+  g_return_if_fail (n_names == n_icons);
+
+  for (i = 0; i < n_names; i++)
+    {
+      GFile *template_file;
+
+      template_file = get_personal_template_file (i);
+
+      latexila_templates_add_template (GTK_LIST_STORE (templates),
+                                       names[i],
+                                       icons[i],
+                                       template_file);
+
+      g_object_unref (template_file);
+    }
+
+out:
+
+  if (error != NULL)
+    {
+      g_warning ("The loading of personal templates failed: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_free (contents);
+  g_strfreev (names);
+  g_strfreev (icons);
+
+  if (key_file != NULL)
+    g_key_file_unref (key_file);
+
+  /* Async operation finished. */
+  g_object_unref (templates);
+}
+
+static void
+latexila_templates_personal_init (LatexilaTemplatesPersonal *templates)
+{
+  GFile *rc_file;
+
+  latexila_templates_init_store (GTK_LIST_STORE (templates));
+
+  rc_file = get_rc_file ();
+
+  /* Prevent @templates from being destroyed during the async operation. */
+  g_object_ref (templates);
+
+  g_file_load_contents_async (rc_file,
+                              NULL,
+                              (GAsyncReadyCallback) rc_file_contents_loaded_cb,
+                              templates);
+}
+
+/**
+ * latexila_templates_personal_get_instance:
+ *
+ * Gets the instance of the #LatexilaTemplatesPersonal singleton.
+ *
+ * Returns: (transfer none): the instance of #LatexilaTemplatesPersonal.
+ */
+LatexilaTemplatesPersonal *
+latexila_templates_personal_get_instance (void)
+{
+  static LatexilaTemplatesPersonal *instance = NULL;
+
+  if (instance == NULL)
+    instance = g_object_new (LATEXILA_TYPE_TEMPLATES_PERSONAL, NULL);
+
+  return instance;
+}
+
+/**
+ * latexila_templates_personal_get_contents:
+ * @templates: the #LatexilaTemplatesPersonal instance.
+ * @path: the #GtkTreePath of a personal template.
+ *
+ * Gets the contents of a personal template.
+ *
+ * TODO load contents asynchronously, with a #GtkSourceFileLoader.
+ *
+ * Returns: the personal template's contents. Free with g_free().
+ */
+gchar *
+latexila_templates_personal_get_contents (LatexilaTemplatesPersonal *templates,
+                                          GtkTreePath               *path)
+{
+  GtkTreeIter iter;
+  GFile *file;
+  gchar *contents = NULL;
+  GError *error = NULL;
+
+  g_return_val_if_fail (LATEXILA_IS_TEMPLATES_PERSONAL (templates), NULL);
+
+  gtk_tree_model_get_iter (GTK_TREE_MODEL (templates),
+                           &iter,
+                           path);
+
+  gtk_tree_model_get (GTK_TREE_MODEL (templates),
+                      &iter,
+                      LATEXILA_TEMPLATES_COLUMN_FILE, &file,
+                      -1);
+
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+  g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
+
+  if (error != NULL)
+    {
+      g_warning ("Error when loading personal template contents: %s", error->message);
+      g_error_free (error);
+    }
+
+  g_object_unref (file);
+  return contents;
+}
diff --git a/src/liblatexila/latexila-templates-personal.h b/src/liblatexila/latexila-templates-personal.h
new file mode 100644
index 0000000..2bc0a51
--- /dev/null
+++ b/src/liblatexila/latexila-templates-personal.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LATEXILA_TEMPLATES_PERSONAL_H__
+#define __LATEXILA_TEMPLATES_PERSONAL_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define LATEXILA_TYPE_TEMPLATES_PERSONAL latexila_templates_personal_get_type ()
+G_DECLARE_FINAL_TYPE (LatexilaTemplatesPersonal, latexila_templates_personal, LATEXILA, TEMPLATES_PERSONAL, 
GtkListStore)
+
+LatexilaTemplatesPersonal *
+              latexila_templates_personal_get_instance          (void);
+
+gchar *       latexila_templates_personal_get_contents          (LatexilaTemplatesPersonal *templates,
+                                                                 GtkTreePath               *path);
+
+G_END_DECLS
+
+#endif /* __LATEXILA_TEMPLATES_PERSONAL_H__ */
diff --git a/src/main_window_file.vala b/src/main_window_file.vala
index 4360344..eb511f6 100644
--- a/src/main_window_file.vala
+++ b/src/main_window_file.vala
@@ -131,7 +131,7 @@ public class MainWindowFile
 
     public void on_file_new ()
     {
-        string contents = Latexila.Templates.dialogs_open (_main_window);
+        string contents = Latexila.templates_dialogs_open (_main_window);
 
         if (contents != null)
         {


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