diff options
author | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-09-20 11:08:39 -0300 |
---|---|---|
committer | Juan Pablo Ugarte <juanpablougarte@gmail.com> | 2013-09-20 11:08:39 -0300 |
commit | a6e497dd91bb33cefa2682f70144d8d0a66a26b4 (patch) | |
tree | c38f3373256de16771b3fa386536e5e19b8938fa | |
parent | fb4735ecdea307a7284bddde6c72bfd0f31c51c2 (diff) | |
download | glade-a6e497dd91bb33cefa2682f70144d8d0a66a26b4.tar.gz |
Backported feature to make GladeProject remember unknown object classes
-rw-r--r-- | gladeui/Makefile.am | 7 | ||||
-rw-r--r-- | gladeui/glade-object-stub.c | 224 | ||||
-rw-r--r-- | gladeui/glade-object-stub.h | 57 | ||||
-rw-r--r-- | gladeui/glade-project.c | 105 | ||||
-rw-r--r-- | gladeui/glade-utils.c | 15 | ||||
-rw-r--r-- | gladeui/glade-widget.c | 43 | ||||
-rw-r--r-- | gladeui/glade-xml-utils.c | 13 | ||||
-rw-r--r-- | gladeui/glade-xml-utils.h | 1 |
8 files changed, 410 insertions, 55 deletions
diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am index b4741b2f..1e4e5b81 100644 --- a/gladeui/Makefile.am +++ b/gladeui/Makefile.am @@ -25,6 +25,7 @@ libgladeui_1_la_SOURCES = \ glade-placeholder.c \ glade-custom.c \ glade-inspector.c \ + glade-object-stub.c \ glade-xml-utils.c \ glade-palette.c \ glade-design-layout.c \ @@ -117,6 +118,12 @@ libgladeuiinclude_HEADERS = \ glade-cell-renderer-icon.h +noinst_HEADERS = \ + glade-marshallers.h \ + glade-design-layout.h \ + glade-object-stub.h \ + glade-popup.h \ + glade-accumulators.h if PLATFORM_WIN32 libgladeui_1_la_LDFLAGS += -no-undefined diff --git a/gladeui/glade-object-stub.c b/gladeui/glade-object-stub.c new file mode 100644 index 00000000..e15ce322 --- /dev/null +++ b/gladeui/glade-object-stub.c @@ -0,0 +1,224 @@ +/* + * glade-object-stub.c + * + * Copyright (C) 2011 Juan Pablo Ugarte + * + * Author: Juan Pablo Ugarte <juanpablougarte@gmail.com> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <config.h> + +#include <glib/gi18n-lib.h> +#include "glade-object-stub.h" +#include "glade-project.h" + +struct _GladeObjectStubPrivate +{ + GtkLabel *label; + + gchar *type; + GladeXmlNode *node; +}; + +#define GLADE_OBJECT_STUB_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GLADE_TYPE_OBJECT_STUB, GladeObjectStubPrivate)) + +enum +{ + PROP_0, + + PROP_OBJECT_TYPE, + PROP_XML_NODE +}; + + +G_DEFINE_TYPE (GladeObjectStub, glade_object_stub, GTK_TYPE_INFO_BAR); + +#define RESPONSE_DELETE 1 +#define RESPONSE_DELETE_ALL 2 + +static void +on_infobar_response (GladeObjectStub *stub, gint response_id) +{ + GladeWidget *gwidget = glade_widget_get_from_gobject (stub); + + if (response_id == RESPONSE_DELETE) + { + GList widgets = {0, }; + widgets.data = gwidget; + glade_command_delete (&widgets); + } + else if (response_id == RESPONSE_DELETE_ALL) + { + GladeProject *project = glade_widget_get_project (gwidget); + GList *stubs = NULL; + const GList *l; + + for (l = glade_project_get_objects (project); l; l = g_list_next (l)) + { + if (GLADE_IS_OBJECT_STUB (l->data)) + { + GladeWidget *gobj = glade_widget_get_from_gobject (l->data); + stubs = g_list_prepend (stubs, gobj); + } + } + + glade_command_delete (stubs); + g_list_free (stubs); + } +} + +static void +glade_object_stub_init (GladeObjectStub *object) +{ + GladeObjectStubPrivate *priv = GLADE_OBJECT_STUB_PRIVATE (object); + GtkWidget *label = gtk_label_new (NULL); + + object->priv = priv; + priv->type = NULL; + priv->node = NULL; + + priv->label = GTK_LABEL (label); + gtk_label_set_line_wrap (priv->label, TRUE); + + gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (object))), label); + + gtk_info_bar_add_button (GTK_INFO_BAR (object), + _("Delete"), RESPONSE_DELETE); + gtk_info_bar_add_button (GTK_INFO_BAR (object), + _("Delete All"), RESPONSE_DELETE_ALL); + + g_signal_connect (object, "response", G_CALLBACK (on_infobar_response), NULL); +} + +static void +glade_object_stub_finalize (GObject *object) +{ + GladeObjectStubPrivate *priv = GLADE_OBJECT_STUB (object)->priv; + + g_free (priv->type); + + if (priv->node) glade_xml_node_delete (priv->node); + + G_OBJECT_CLASS (glade_object_stub_parent_class)->finalize (object); +} + +static void +glade_object_stub_refresh_text (GladeObjectStub *stub) +{ + GladeObjectStubPrivate *priv = stub->priv; + gchar *markup; + + if (priv->type == NULL) return; + + markup = g_markup_printf_escaped ("<b>FIXME:</b> Unable to create object with type %s", priv->type); + + gtk_label_set_markup (priv->label, markup); + gtk_info_bar_set_message_type (GTK_INFO_BAR (stub), GTK_MESSAGE_WARNING); + g_free (markup); +} + +static void +glade_object_stub_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GladeObjectStubPrivate *priv; + GladeObjectStub *stub; + + g_return_if_fail (GLADE_IS_OBJECT_STUB (object)); + + stub = GLADE_OBJECT_STUB (object); + priv = stub->priv; + + switch (prop_id) + { + case PROP_OBJECT_TYPE: + g_free (priv->type); + priv->type = g_value_dup_string (value); + glade_object_stub_refresh_text (stub); + break; + case PROP_XML_NODE: + if (priv->node) glade_xml_node_delete (priv->node); + priv->node = g_value_dup_boxed (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +glade_object_stub_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GladeObjectStubPrivate *priv; + + g_return_if_fail (GLADE_IS_OBJECT_STUB (object)); + + priv = GLADE_OBJECT_STUB (object)->priv; + + switch (prop_id) + { + case PROP_OBJECT_TYPE: + g_value_set_string (value, priv->type); + break; + case PROP_XML_NODE: + g_value_set_boxed (value, priv->node); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GType +glade_xml_node_get_type (void) +{ + static GType type = 0; + + if (type) return type; + + type = g_boxed_type_register_static ("GladeXmlNode", + (GBoxedCopyFunc) glade_xml_node_copy, + (GBoxedFreeFunc) glade_xml_node_delete); + return type; +} + +static void +glade_object_stub_class_init (GladeObjectStubClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GladeObjectStubPrivate)); + + object_class->finalize = glade_object_stub_finalize; + object_class->set_property = glade_object_stub_set_property; + object_class->get_property = glade_object_stub_get_property; + + g_object_class_install_property (object_class, + PROP_OBJECT_TYPE, + g_param_spec_string ("object-type", + "Object Type", + "The object type this stub replaces", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_XML_NODE, + g_param_spec_boxed ("xml-node", + "XML node", + "The XML representation of the original object this is replacing", + glade_xml_node_get_type (), + G_PARAM_READWRITE)); +} diff --git a/gladeui/glade-object-stub.h b/gladeui/glade-object-stub.h new file mode 100644 index 00000000..42369b4e --- /dev/null +++ b/gladeui/glade-object-stub.h @@ -0,0 +1,57 @@ +/* + * glade-object-stub.h + * + * Copyright (C) 2011 Juan Pablo Ugarte + * + * Author: Juan Pablo Ugarte <juanpablougarte@gmail.com> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _GLADE_OBJECT_STUB_H_ +#define _GLADE_OBJECT_STUB_H_ + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define GLADE_TYPE_OBJECT_STUB (glade_object_stub_get_type ()) +#define GLADE_OBJECT_STUB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_OBJECT_STUB, GladeObjectStub)) +#define GLADE_OBJECT_STUB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_OBJECT_STUB, GladeObjectStubClass)) +#define GLADE_IS_OBJECT_STUB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_OBJECT_STUB)) +#define GLADE_IS_OBJECT_STUB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_OBJECT_STUB)) +#define GLADE_OBJECT_STUB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_OBJECT_STUB, GladeObjectStubClass)) + +typedef struct _GladeObjectStubClass GladeObjectStubClass; +typedef struct _GladeObjectStub GladeObjectStub; +typedef struct _GladeObjectStubPrivate GladeObjectStubPrivate; + +struct _GladeObjectStubClass +{ + GtkInfoBarClass parent_class; +}; + +struct _GladeObjectStub +{ + GtkInfoBar parent_instance; + GladeObjectStubPrivate *priv; +}; + +GType glade_object_stub_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* _GLADE_OBJECT_STUB_H_ */ diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c index 4ac349ae..850e7bfa 100644 --- a/gladeui/glade-project.c +++ b/gladeui/glade-project.c @@ -49,7 +49,7 @@ #include "glade-project.h" #include "glade-command.h" #include "glade-name-context.h" - +#include "glade-object-stub.h" #define VALID_ITER(project, iter) ((iter)!= NULL && G_IS_OBJECT ((iter)->user_data) && ((GladeProject*)(project))->priv->stamp == (iter)->stamp) @@ -142,6 +142,8 @@ struct _GladeProjectPrivate * (full or relative path, null means project directory). */ + GList *unknown_catalogs; /* List of CatalogInfo catalogs */ + /* Control on the preferences dialog to update buttons etc when properties change */ GtkWidget *prefs_dialog; GtkWidget *glade_radio; @@ -162,6 +164,12 @@ struct _GladeProjectPrivate gboolean load_cancel; }; +typedef struct +{ + gchar *catalog; + gint position; +} CatalogInfo; + typedef struct { GladeWidget *toplevel; GladeNameContext *names; @@ -355,6 +363,21 @@ glade_project_finalize (GObject *object) } g_list_free (project->priv->toplevels); + if (project->priv->unknown_catalogs) + { + GList *l; + + for (l = project->priv->unknown_catalogs; l; l = g_list_next (l)) + { + CatalogInfo *data = l->data; + g_free (data->catalog); + g_free (data); + } + + g_list_free (project->priv->unknown_catalogs); + project->priv->unknown_catalogs = NULL; + } + G_OBJECT_CLASS (glade_project_parent_class)->finalize (object); } @@ -631,6 +654,7 @@ glade_project_init (GladeProject *project) priv->prev_redo_item = NULL; priv->first_modification = NULL; priv->first_modification_is_na = FALSE; + priv->unknown_catalogs = NULL; priv->toplevel_names = glade_name_context_new (); priv->naming_policy = GLADE_POLICY_PROJECT_WIDE; @@ -1036,6 +1060,7 @@ glade_project_read_requires (GladeProject *project, gchar *required_lib = NULL; gboolean loadable = TRUE; guint16 major, minor; + gint position = 0; for (node = glade_xml_node_get_children_with_comments (root_node); node; node = glade_xml_node_next_with_comments (node)) @@ -1062,6 +1087,17 @@ glade_project_read_requires (GladeProject *project, */ if (!glade_catalog_is_loaded (required_lib)) { + CatalogInfo *data = g_new0(CatalogInfo, 1); + + data->catalog = required_lib; + data->position = position; + + /* Keep a list of unknown catalogs to avoid loosing the requirement */ + project->priv->unknown_catalogs = g_list_append (project->priv->unknown_catalogs, + data); + /* Also keep the version */ + glade_project_set_target_version (project, required_lib, major, minor); + if (!loadable) g_string_append (string, ", "); @@ -1075,9 +1111,10 @@ glade_project_read_requires (GladeProject *project, glade_project_set_target_version (project, required_lib, major, minor); + g_free (required_lib); } - - g_free (required_lib); + + position++; } if (!loadable) @@ -1468,12 +1505,7 @@ glade_project_load_internal (GladeProject *project) /* XXX Need to load project->priv->comment ! */ glade_project_read_comment (project, doc); - if (glade_project_read_requires (project, root, project->priv->path, &has_gtk_dep) == FALSE) - { - project->priv->loading = FALSE; - glade_xml_context_free (context); - return FALSE; - } + glade_project_read_requires (project, root, project->priv->path, &has_gtk_dep); glade_project_read_naming_policy (project, root); @@ -2270,25 +2302,37 @@ static gboolean glade_project_verify (GladeProject *project, gboolean saving) { - GString *string = g_string_new (NULL); - GladeWidget *widget; - GList *list; - gboolean ret = TRUE; - gchar *path_name; - - for (list = project->priv->objects; list; list = list->next) - { - widget = glade_widget_get_from_gobject (list->data); - - path_name = glade_widget_generate_path_name (widget); + GString *string = g_string_new (NULL); + GList *list; + gboolean ret = TRUE; + + for (list = project->priv->objects; list; list = list->next) + { + GladeWidget *widget = glade_widget_get_from_gobject (list->data); + + if (GLADE_IS_OBJECT_STUB (list->data)) + { + gchar *type; + g_object_get (list->data, "object-type", &type, NULL); + + /* translators: reffers to an unknow object named '%s' of type '%s' */ + g_string_append_printf (string, _("Unknow object %s with type %s\n"), + glade_widget_get_name (widget), type); + g_free (type); + } + else + { + gchar *path_name = glade_widget_generate_path_name (widget); - glade_project_verify_adaptor (project, widget->adaptor, - path_name, string, saving, FALSE, NULL); - glade_project_verify_properties_internal (widget, path_name, string, FALSE); - glade_project_verify_signals (widget, path_name, string, FALSE); + glade_project_verify_adaptor (project, glade_widget_get_adaptor (widget), + path_name, string, saving, FALSE, NULL); + glade_project_verify_properties_internal (widget, path_name, string, + FALSE); + glade_project_verify_signals (widget, path_name, string, FALSE); - g_free (path_name); - } + g_free (path_name); + } + } if (string->len > 0) { @@ -3498,7 +3542,14 @@ glade_project_required_libs (GladeProject *project) if (!required) required = g_list_prepend (required, g_strdup ("gtk+")); - return g_list_reverse (required); + for (l = project->priv->unknown_catalogs; l; l = g_list_next (l)) + { + CatalogInfo *data = l->data; + /* Keep position to make sure we do not create a diff when saving */ + required = g_list_insert (required, g_strdup (data->catalog), data->position); + } + + return required; } /** diff --git a/gladeui/glade-utils.c b/gladeui/glade-utils.c index 00324658..ae52501c 100644 --- a/gladeui/glade-utils.c +++ b/gladeui/glade-utils.c @@ -250,16 +250,17 @@ glade_util_ui_message (GtkWidget *parent, dialog = gtk_message_dialog_new (GTK_WINDOW (parent), GTK_DIALOG_DESTROY_WITH_PARENT, - message_type, - buttons_type, - "%s", - string); + message_type, buttons_type, NULL); - gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE); + gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), string); if (widget) - gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), - widget, TRUE, TRUE, 2); + { + gtk_box_pack_end (GTK_BOX + (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), + widget, TRUE, TRUE, 2); + gtk_widget_show (widget); + } response = gtk_dialog_run (GTK_DIALOG (dialog)); diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c index 7ca924cc..d8045bef 100644 --- a/gladeui/glade-widget.c +++ b/gladeui/glade-widget.c @@ -56,8 +56,7 @@ #include "glade-app.h" #include "glade-design-view.h" #include "glade-widget-action.h" - - +#include "glade-object-stub.h" static void glade_widget_set_adaptor (GladeWidget *widget, GladeWidgetAdaptor *adaptor); @@ -3876,26 +3875,22 @@ glade_widget_read (GladeProject *project, widget, node); } - else if (adaptor) + else { - if (G_TYPE_IS_ABSTRACT (adaptor->type)) - glade_util_ui_message (glade_app_get_window (), - GLADE_UI_WARN, NULL, - "Unable to load widget %s with abstract class %s", - id, klass); - else - glade_util_ui_message (glade_app_get_window (), - GLADE_UI_WARN, NULL, - "Unable to load widget %s of class %s", - id, klass); - + GObject *stub = g_object_new (GLADE_TYPE_OBJECT_STUB, + "object-type", klass, + "xml-node", node, + NULL); + + widget = glade_widget_adaptor_create_widget (glade_widget_adaptor_get_by_type (GTK_TYPE_HBOX), + FALSE, + "parent", parent, + "project", project, + "reason", GLADE_CREATE_LOAD, + "object", stub, + "name", id, + NULL); } - else - glade_util_ui_message (glade_app_get_window (), - GLADE_UI_WARN, NULL, - "Unable to load widget %s of unknown class %s", - id, klass); - g_free (id); } g_free (klass); @@ -4034,6 +4029,14 @@ glade_widget_write (GladeWidget *widget, GList *l, *list; GladeProjectFormat fmt = glade_project_get_format (widget->project); + /* Check if its an unknown object, and use saved xml if so */ + if (GLADE_IS_OBJECT_STUB (widget->object)) + { + g_object_get (widget->object, "xml-node", &widget_node, NULL); + glade_xml_node_append_child (node, widget_node); + return; + } + widget_node = glade_xml_node_new (context, GLADE_XML_TAG_WIDGET (fmt)); glade_xml_node_append_child (node, widget_node); diff --git a/gladeui/glade-xml-utils.c b/gladeui/glade-xml-utils.c index 8958fe8e..a6642e24 100644 --- a/gladeui/glade-xml-utils.c +++ b/gladeui/glade-xml-utils.c @@ -751,7 +751,18 @@ glade_xml_node_new_comment (GladeXmlContext *context, const gchar *comment) return (GladeXmlNode *) xmlNewDocComment ((xmlDocPtr) context->doc, BAD_CAST(comment)); } - +GladeXmlNode * +glade_xml_node_copy (GladeXmlNode *node) +{ + if (node) + { + xmlNodePtr xnode = (xmlNodePtr) node; + return (GladeXmlNode *) xmlDocCopyNode (xnode, NULL, 1); + } + else + return NULL; +} + void glade_xml_node_delete (GladeXmlNode *node) { diff --git a/gladeui/glade-xml-utils.h b/gladeui/glade-xml-utils.h index 9fda0c8f..d52a8e08 100644 --- a/gladeui/glade-xml-utils.h +++ b/gladeui/glade-xml-utils.h @@ -251,6 +251,7 @@ void glade_xml_node_set_property_boolean (GladeXmlNode *node_in, const gchar *na /* Node operations */ GladeXmlNode * glade_xml_node_new (GladeXmlContext *context, const gchar *name); GladeXmlNode * glade_xml_node_new_comment (GladeXmlContext *context, const gchar *comment); +GladeXmlNode * glade_xml_node_copy (GladeXmlNode *node); void glade_xml_node_delete (GladeXmlNode *node); GladeXmlNode * glade_xml_node_get_children (GladeXmlNode *node); GladeXmlNode * glade_xml_node_get_parent (GladeXmlNode *node_in); |