[gtkmm] Gtk::Builder: Don't get gtkmm-derived GTypes while parsing <columns>



commit af2b13ab5ce5d316af0b0c19a299feba49d5f946
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu Mar 12 15:25:16 2015 +0100

    Gtk::Builder: Don't get gtkmm-derived GTypes while parsing <columns>
    
    * gtk/src/builder.[ccg|hg]: Add set_no_gtkmm_derived_types(), to be called
    from Buildable_Class.
    get_type_from_name_vfunc_callback(): Check if Buildable_Class has requested
    that gtkmm-derived types shall not be searched for.
    * gtk/src/buildable.[ccg|hg]: Add Buildable_Class::
    custom_tag_start_vfunc_callback() and custom_tag_end_vfunc_callback().
    Ask the Builder not to search for gtkmm-derived types while a TreeModel
    parses a <columns> element in the XML file. Bug #742637.

 gtk/src/buildable.ccg |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/src/buildable.hg  |   27 ++++++++++++++++++-
 gtk/src/builder.ccg   |   30 ++++++++++++++++++---
 gtk/src/builder.hg    |    4 +++
 4 files changed, 126 insertions(+), 5 deletions(-)
---
diff --git a/gtk/src/buildable.ccg b/gtk/src/buildable.ccg
index f10e0ef..9067fb1 100644
--- a/gtk/src/buildable.ccg
+++ b/gtk/src/buildable.ccg
@@ -16,4 +16,74 @@
  */
 
 #include <gtk/gtk.h>
+#include <gtkmm/builder.h>
+#include <cstring>
 
+namespace Gtk
+{
+
+//static
+gboolean Buildable_Class::custom_tag_start_vfunc_callback(
+  GtkBuildable* buildable,
+  GtkBuilder* builder,
+  GObject* child,
+  const gchar* tagname,
+  GMarkupParser* parser,
+  gpointer* data)
+{
+  // If it's a TreeModel (such as ListStore or TreeStore) and it's the start
+  // of a <columns> element, inform the Builder that the get_type_from_name()
+  // vfunc shall not search for gtkmm-derived types.
+  // See https://bugzilla.gnome.org/show_bug.cgi?id=742637
+  if (GTK_IS_TREE_MODEL(buildable) && std::strcmp(tagname, "columns") == 0)
+  {
+    Builder* const cpp_builder = dynamic_cast<Builder*>(
+      Glib::ObjectBase::_get_current_wrapper((GObject*)builder));
+    if (cpp_builder)
+      cpp_builder->set_no_gtkmm_derived_types(true);
+  }
+
+  BaseClassType* const base = static_cast<BaseClassType*>(
+    g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C 
interface).
+      g_type_interface_peek(G_OBJECT_GET_CLASS(buildable), CppObjectType::get_type()) // Get the interface.
+    )
+  );
+
+  // Call the original underlying C function:
+  if (base && base->custom_tag_start)
+    return (*base->custom_tag_start)(buildable, builder, child, tagname, parser, data);
+  return false;
+}
+
+//static
+void Buildable_Class::custom_tag_end_vfunc_callback(
+  GtkBuildable* buildable,
+  GtkBuilder* builder,
+  GObject* child,
+  const gchar* tagname,
+  gpointer* data)
+{
+  BaseClassType* const base = static_cast<BaseClassType*>(
+    g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C 
interface).
+      g_type_interface_peek(G_OBJECT_GET_CLASS(buildable), CppObjectType::get_type()) // Get the interface.
+    )
+  );
+
+  // Call the original underlying C function:
+  if (base && base->custom_tag_end)
+    (*base->custom_tag_end)(buildable, builder, child, tagname, data);
+
+  // If it's a TreeModel (such as ListStore or TreeStore) and it's the end
+  // of a </columns> element, inform the Builder that the get_type_from_name()
+  // vfunc shall resume search for gtkmm-derived types.
+  // See https://bugzilla.gnome.org/show_bug.cgi?id=742637
+  if (GTK_IS_TREE_MODEL(buildable) && std::strcmp(tagname, "columns") == 0)
+  {
+    Builder* const cpp_builder = dynamic_cast<Builder*>(
+      Glib::ObjectBase::_get_current_wrapper((GObject*)builder));
+    if (cpp_builder)
+      cpp_builder->set_no_gtkmm_derived_types(false);
+  }
+}
+
+} // namespace Gtk
diff --git a/gtk/src/buildable.hg b/gtk/src/buildable.hg
index aa99e2a..a5e2444 100644
--- a/gtk/src/buildable.hg
+++ b/gtk/src/buildable.hg
@@ -83,7 +83,32 @@ public:
 */
 
   //TODO: Properties, signals, vfuncs.
+
+#m4begin
+dnl //Custom-coded vfuncs:
+dnl
+  _PUSH(SECTION_CC_PRE_INCLUDES)
+    // Needed before gtkmm/private/buildable_p.h is included.
+    typedef struct _GtkBuilder GtkBuilder;
+  _SECTION(SECTION_PCC_CLASS_INIT_VFUNCS)
+    klass->custom_tag_start = &custom_tag_start_vfunc_callback;
+    klass->custom_tag_end = &custom_tag_end_vfunc_callback;
+  _SECTION(SECTION_PH_VFUNCS)
+    static gboolean custom_tag_start_vfunc_callback(
+      GtkBuildable* buildable,
+      GtkBuilder* builder,
+      GObject* child,
+      const gchar* tagname,
+      GMarkupParser* parser,
+      gpointer* data);
+    static void custom_tag_end_vfunc_callback(
+      GtkBuildable* buildable,
+      GtkBuilder* builder,
+      GObject* child,
+      const gchar* tagname,
+      gpointer* data);
+  _POP()
+#m4end
 };
 
 } // namespace Gtk
-
diff --git a/gtk/src/builder.ccg b/gtk/src/builder.ccg
index 1f8dd31..c8e36fb 100644
--- a/gtk/src/builder.ccg
+++ b/gtk/src/builder.ccg
@@ -20,6 +20,12 @@
 
 #include <gtk/gtk.h>
 
+namespace
+{
+
+//TODO: When we can break ABI, replace this GQuark by member data in Gtk::Builder.
+GQuark quark_no_gtkmm_derived_types = g_quark_from_static_string("gtkmm__Builder::no_gtkmm_derived_types");
+
 // Allow GtkBuilder to instantiate a gtkmm derived GType instead of the regular
 // GTK+ GType, so we can, for instance, use our vfuncs and default signal handlers.
 static GType
@@ -28,11 +34,19 @@ get_type_from_name_vfunc_callback(GtkBuilder* self, const char* type_name)
   if (!type_name)
     return G_TYPE_INVALID;
 
-  // See if there is a gtkmm version of the gclass:
-  Glib::ustring classname_prefixed ("gtkmm__"); // gtkmm uses a prefix
-  classname_prefixed += type_name;
+  GType gtype = G_TYPE_INVALID;
+
+  // If a TreeModel (such as ListStore or TreeStore) is being built,
+  // Buildable_Class may have requested no search for gtkmm-derived types.
+  // See https://bugzilla.gnome.org/show_bug.cgi?id=742637
+  if (!g_object_get_qdata((GObject*)self, quark_no_gtkmm_derived_types))
+  {
+    // See if there is a gtkmm version of the gclass:
+    Glib::ustring classname_prefixed ("gtkmm__"); // gtkmm uses a prefix
+    classname_prefixed += type_name;
 
-  GType gtype = g_type_from_name(classname_prefixed.c_str());
+    gtype = g_type_from_name(classname_prefixed.c_str());
+  }
 
   if (gtype == G_TYPE_INVALID) // If it's not a registered typename
   {
@@ -51,9 +65,17 @@ get_type_from_name_vfunc_callback(GtkBuilder* self, const char* type_name)
   return gtype;
 }
 
+} // anonymous namespace
+
 namespace Gtk
 {
 
+// Called from Buildable
+void Builder::set_no_gtkmm_derived_types(bool status)
+{
+  g_object_set_qdata((GObject*)gobj(), quark_no_gtkmm_derived_types, (gpointer)status);
+}
+
 // static
 Glib::RefPtr<Builder> Builder::create_from_file(const std::string& filename)
 {
diff --git a/gtk/src/builder.hg b/gtk/src/builder.hg
index 06a1954..715a024 100644
--- a/gtk/src/builder.hg
+++ b/gtk/src/builder.hg
@@ -571,6 +571,10 @@ protected:
   Gtk::Widget* get_widget_checked(const Glib::ustring& name, GType type);
   GtkWidget* get_cwidget(const Glib::ustring& name);
 
+private:
+  void set_no_gtkmm_derived_types(bool status);
+  friend class Buildable_Class;
+
 #m4begin
 dnl Custom-coded vfunc:
 dnl


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