[glom] Store example files in a GResource.



commit 9cd1b6dab94191abbb9392304e867bddb2bba766
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Oct 21 14:15:21 2013 +0200

    Store example files in a GResource.
    
    * ui/glom.gresource.xml: Rename this to ui/glom-ui.gresource.xml
      so we can also have:
    * examples/glom-examples.gresource.xml.
    * Makefile.am:
    * Makefile_glom.am: Generate the gresource source file.
    * glom/dialog_existing_or_new.[h|cc]: Get the example files
      from the globally-registered GResource.
    This avoid the need to check multiple locations, and avoids the risk
    of not checking all possible locations, when distros move the files
    around. And this simplifies packaging by not needing the example
    files to be installed separately.

 Makefile.am                                      |   13 ---
 Makefile_glom.am                                 |   20 ++++--
 examples/glom-examples.gresource.xml             |   17 ++++
 glom/dialog_existing_or_new.cc                   |   92 +++++++++++-----------
 glom/dialog_existing_or_new.h                    |    6 +-
 ui/{glom.gresource.xml => glom-ui.gresource.xml} |    0
 6 files changed, 79 insertions(+), 69 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0e070f6..22fe1ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,8 +59,6 @@ include Makefile_libglom.am
 
 glom_defines = \
 -DGLOM_DATADIR=\""$(datadir)"\" \
--DGLOM_DOCDIR_EXAMPLES=\""$(docdir)/examples"\" \
--DGLOM_DOCDIR_EXAMPLES_NOTINSTALLED=\""$(abs_top_srcdir)/examples"\" \
 -DGLOM_LOCALEDIR=\""$(glom_localedir)"\" \
 -DGLOM_PKGDATADIR=\""$(pkgdatadir)"\" \
 -DGLOM_PKGDATADIR_NOTINSTALLED=\""$(top_srcdir)/ui"\"
@@ -165,17 +163,6 @@ dist_glade_developer_DATA = ui/developer/dialog_add_related_table.glade \
 xsltdir = $(pkgdatadir)/xslt
 dist_xslt_DATA = xslt/print_report_to_html.xsl
 
-exampledir = $(docdir)/examples
-example_files = \
-       examples/example_film_manager.glom      \
-       examples/example_lesson_planner.glom    \
-       examples/example_music_collection.glom  \
-       examples/example_project_manager.glom   \
-       examples/example_smallbusiness.glom
-dist_example_DATA = \
-       $(example_files) \
-       examples/README
-
 # Get the base filenames only, without the extension: 
 example_files_names ?= $(patsubst %.glom,%,$(notdir $(example_files)))
 
diff --git a/Makefile_glom.am b/Makefile_glom.am
index 55c2462..4eae916 100644
--- a/Makefile_glom.am
+++ b/Makefile_glom.am
@@ -28,15 +28,23 @@ bin_PROGRAMS += glom/glom
 
 glom_glom_CPPFLAGS = $(glom_includes) $(GLOM_CFLAGS) $(PYTHON_CPPFLAGS) $(BOOST_PYTHON_CFLAGS) 
$(GCOV_CFLAGS) $(glom_defines)
 
-# Generate the GResource source file:
+# Generate the GResource source file for .glade files:
 # TODO: Do not use all .glade files in the client-only build.
-glom_resource_file = ui/glom.gresource.xml
-BUILT_SOURCES = ui/glom-resources.c
-ui/glom-resources.c: $(glom_resource_file) $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies 
$(glom_resource_file))
-       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-source 
$(glom_resource_file)
+glom_ui_resource_file = ui/glom-ui.gresource.xml
+BUILT_SOURCES = ui/glom-ui-resources.c
+ui/glom-ui-resources.c: $(glom_ui_resource_file) $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies 
$(glom_ui_resource_file))
+       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-source 
$(glom_ui_resource_file)
+
+# Generate the GResource source file for example .glom files:
+# TODO: Do not use all .glade files in the client-only build.
+glom_examples_resource_file = examples/glom-examples.gresource.xml
+BUILT_SOURCES += examples/glom-examples-resources.c
+examples/glom-examples-resources.c: $(glom_examples_resource_file) $(shell $(GLIB_COMPILE_RESOURCES) 
--generate-dependencies $(glom_examples_resource_file))
+       $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-source 
$(glom_examples_resource_file)
 
 EXTRA_DIST = \
-       $(glom_resource_file)
+       $(glom_ui_resource_file)\
+       $(glom_examples_resource_file)
 
 glom_eggspreadtable_files =  \
   glom/utility_widgets/eggspreadtable/eggmarshalers.c \
diff --git a/examples/glom-examples.gresource.xml b/examples/glom-examples.gresource.xml
new file mode 100644
index 0000000..819d1be
--- /dev/null
+++ b/examples/glom-examples.gresource.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/glom">
+    <file preprocess="xml-stripblanks" compressed="true">examples/example_film_manager.glom</file>
+    <file preprocess="xml-stripblanks" compressed="true">examples/example_lesson_planner.glom</file>
+    <file preprocess="xml-stripblanks" compressed="true">examples/example_music_collection.glom</file>
+    <file preprocess="xml-stripblanks" compressed="true">examples/example_project_manager.glom</file>
+    <file preprocess="xml-stripblanks" compressed="true">examples/example_smallbusiness.glom</file>
+  </gresource>
+</gresources>
+
+
+
+
+ 
+
+
diff --git a/glom/dialog_existing_or_new.cc b/glom/dialog_existing_or_new.cc
index 430f847..221ca43 100644
--- a/glom/dialog_existing_or_new.cc
+++ b/glom/dialog_existing_or_new.cc
@@ -29,6 +29,7 @@
 #include <gtkmm/recentmanager.h>
 #include <gtkmm/filechooserdialog.h>
 #include <glibmm/miscutils.h>
+#include <glibmm/vectorutils.h>
 
 #ifdef G_OS_WIN32
 #include <glibmm/fileutils.h>
@@ -246,25 +247,8 @@ Dialog_ExistingOrNew::Dialog_ExistingOrNew(BaseObjectType* cobject, const Glib::
 
  // Load example files:
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-
-#ifdef G_OS_WIN32
-  gchar* dir = g_win32_get_package_installation_directory_of_module(0);
-  std::string path = Glib::build_filename(dir, "share" G_DIR_SEPARATOR_S "doc"
-                                                       G_DIR_SEPARATOR_S "glom"
-                                                       G_DIR_SEPARATOR_S "examples");
-  g_free(dir);
-
-  if(!Glib::file_test(path, Glib::FILE_TEST_EXISTS))
-    path = GLOM_DOCDIR_EXAMPLES;
-#else
-  const char path[] = GLOM_DOCDIR_EXAMPLES;
-#endif //G_OS_WIN32
-
-  //Show the installed example files,
-  //falling back to the ones from the local source tree if none are installed:
-  if(!list_examples_at_path(path))
-    list_examples_at_path(GLOM_DOCDIR_EXAMPLES_NOTINSTALLED);
-
+  //Show the bundled (in a GResource) example files,
+  list_examples();
 #endif //!GLOM_ENABLE_CLIENT_ONLY
 
   //Make sure the first item is visible:
@@ -275,33 +259,45 @@ Dialog_ExistingOrNew::Dialog_ExistingOrNew(BaseObjectType* cobject, const Glib::
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-bool Dialog_ExistingOrNew::list_examples_at_path(const std::string& path)
+bool Dialog_ExistingOrNew::list_examples()
 {
   //std::cout << "debug: " << G_STRFUNC << ": path=" << path << std::endl;
 
-  Glib::RefPtr<Gio::File> examples_dir = Gio::File::create_for_path(path);
-  Glib::RefPtr<Gio::FileInfo> info;
+  const char* examples_dir = "/org/gnome/glom/examples/";
 
   try
   {
-    Glib::RefPtr<Gio::FileEnumerator> examples = 
examples_dir->enumerate_children(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE","G_FILE_ATTRIBUTE_STANDARD_NAME);
+    //TODO: Add to glibmm? const type_vec_strings examples = Gio::Resource::enumerate_children(examples_dir);
+    GError* gerror = 0;
+    char** cexamples = g_resources_enumerate_children(examples_dir, G_RESOURCE_LOOKUP_FLAGS_NONE, &gerror);
+    if(gerror)
+    {
+      Glib::Error::throw_exception(gerror);
+    }
+
+    typedef std::vector<Glib::ustring> type_vec_strings;
+    const type_vec_strings examples = 
+      Glib::ArrayHandler<Glib::ustring>::array_to_vector(cexamples, Glib::OWNERSHIP_DEEP);
+
     bool example_found = false;
-    while( (info = examples->next_file()) )
+    for(type_vec_strings::const_iterator iter = examples.begin(); iter != examples.end(); ++iter)
     {
-      const Glib::ustring title = get_title_from_example(info, examples_dir);
+      const std::string example_name = *iter;
+
+      const std::string full_path = Glib::build_filename(examples_dir, example_name);
+      const Glib::ustring title = get_title_from_example(full_path);
       if(!title.empty())
       {
-        append_example(title, Gio::File::create_for_path(Glib::build_filename(examples_dir->get_path(), 
info->get_name())));
+        append_example(title, full_path);
        example_found = true;
       }
     }
 
-    // TODO: Monitor example directory for new/removed files?
     return example_found;
   }
   catch(const Glib::Exception& ex)
   {
-    std::cerr << "Could not enumerate examples at path=" << path << ", Error=" << ex.what() << std::endl;
+    std::cerr << "Could not enumerate examples. Error=" << ex.what() << std::endl;
   }
 
   return false;
@@ -661,27 +657,29 @@ void Dialog_ExistingOrNew::update_ui_sensitivity()
 }
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-Glib::ustring Dialog_ExistingOrNew::get_title_from_example(const Glib::RefPtr<Gio::FileInfo>& info, const 
Glib::RefPtr<Gio::File>& examples_dir)
+Glib::ustring Dialog_ExistingOrNew::get_title_from_example(const std::string& resource_name)
 {
   try
   {
-    // Load file.
-    const Glib::ustring content_type = 
info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
-    const Glib::ustring mime_type = Gio::content_type_get_mime_type(content_type);
-
-    if(mime_type == "application/x-glom")
+    GError* gerror = 0;
+    GInputStream* cstream =
+      g_resources_open_stream(resource_name.c_str(),
+        G_RESOURCE_LOOKUP_FLAGS_NONE, &gerror);
+    if(gerror)
     {
-      const Glib::RefPtr<Gio::File> current_example =
-        Gio::File::create_for_path(Glib::build_filename(examples_dir->get_path(), info->get_name()));
-      Glib::RefPtr<Gio::FileInputStream> stream = current_example->read();
-      m_current_buffer.reset(new buffer);
-      const int bytes_read = stream->read(m_current_buffer->buf, buffer::SIZE);
-      const std::string data(m_current_buffer->buf, bytes_read);
-      // TODO: Check that data is valid UTF-8, the last character might be truncated
-
-      Parser parser;
-      return (Glib::ustring(parser.get_example_title(data)));
+      Glib::Error::throw_exception(gerror);
     }
+    
+    Glib::RefPtr<Gio::InputStream> stream = Glib::wrap(cstream);
+
+    //TODO: Really do this asynchronously?
+    m_current_buffer.reset(new buffer);
+    const int bytes_read = stream->read(m_current_buffer->buf, buffer::SIZE);
+    const std::string data(m_current_buffer->buf, bytes_read);
+    // TODO: Check that data is valid UTF-8, the last character might be truncated
+
+    Parser parser;
+    return (Glib::ustring(parser.get_example_title(data)));
   }
   catch(const Glib::Exception& exception)
   {
@@ -694,7 +692,7 @@ Glib::ustring Dialog_ExistingOrNew::get_title_from_example(const Glib::RefPtr<Gi
   return Glib::ustring();
 }
 
-void Dialog_ExistingOrNew::append_example(const Glib::ustring& title, const Glib::RefPtr<Gio::File>& file)
+void Dialog_ExistingOrNew::append_example(const Glib::ustring& title, const std::string& resource_name)
 {
   if(!m_new_model)
   {
@@ -715,7 +713,7 @@ void Dialog_ExistingOrNew::append_example(const Glib::ustring& title, const Glib
     // Add to list.
     Gtk::TreeModel::iterator iter = m_new_model->append(m_iter_new_template->children());
     (*iter)[m_new_columns.m_col_title] = title;
-    (*iter)[m_new_columns.m_col_template_uri] = file->get_uri();
+    (*iter)[m_new_columns.m_col_template_uri] = "resource://" + resource_name; //GFile understands this for 
actual files, though not directories.
 
     if(is_first_item)
     {
@@ -728,7 +726,7 @@ void Dialog_ExistingOrNew::append_example(const Glib::ustring& title, const Glib
   }
   catch(const Glib::Exception& ex)
   {
-    std::cerr << "Could not read example: " << file->get_path() << ": " << ex.what() << std::endl;
+    std::cerr << "Could not read example: " << resource_name << ": " << ex.what() << std::endl;
   }
 }
 #endif /* !GLOM_ENABLE_CLIENT_ONLY */
diff --git a/glom/dialog_existing_or_new.h b/glom/dialog_existing_or_new.h
index 812af21..d954664 100644
--- a/glom/dialog_existing_or_new.h
+++ b/glom/dialog_existing_or_new.h
@@ -94,9 +94,9 @@ private:
   void on_new_button_clicked(const Gtk::TreeModel::Path& path);
 
   
-  bool list_examples_at_path(const std::string& path);
-  Glib::ustring get_title_from_example(const Glib::RefPtr<Gio::FileInfo>& info, const 
Glib::RefPtr<Gio::File>& examples_dir);
-  void append_example(const Glib::ustring& title, const Glib::RefPtr<Gio::File>& file);
+  bool list_examples();
+  Glib::ustring get_title_from_example(const std::string& resource_name);
+  void append_example(const Glib::ustring& title, const std::string& resource_name);
 #endif /* !GLOM_ENABLE_CLIENT_ONLY */
     
 #ifndef G_OS_WIN32
diff --git a/ui/glom.gresource.xml b/ui/glom-ui.gresource.xml
similarity index 100%
rename from ui/glom.gresource.xml
rename to ui/glom-ui.gresource.xml


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