[gtkmm] Gtk::Builder: Don't get gtkmm-derived GTypes while parsing <columns>
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm] Gtk::Builder: Don't get gtkmm-derived GTypes while parsing <columns>
- Date: Thu, 12 Mar 2015 14:27:43 +0000 (UTC)
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]