Revert "Revert "Make GladeProject change gtk target to 3.0 and warn the user if there are""

This reverts commit 5f7a5f2a4e00820fc41442bb28ff864a9a0034ee.
This commit is contained in:
Juan Pablo Ugarte 2011-09-28 17:51:34 -03:00
parent 568454ae35
commit 802fd1926a
9 changed files with 566 additions and 77 deletions

View File

@ -1,3 +1,19 @@
2011-09-19 Juan Pablo Ugarte <juanpablougarte@gmail.com>
* gladeui/glade-object-stub.[ch]: Added new object type used to remember
unknown objects in xml files.
* gladeui/glade-utils.c: made glade_util_ui_message () accept markup strings.
* gladeui/glade-xml-utils.[ch]: added new function glade_xml_node_copy()
* gladeui/glade-widget.c:
o glade_widget_read() create object stub if class is unknown.
o glade_widget_write() used saved xml to dump stub objects.
* glade/gladeui/glade-project.c: make GladeProject remember unknown catalogs
to avoid loosing requirements when loading/saving a file with unknown objects.
2011-09-19 Ignacio Casal Quinteiro <icq@gnome.org>
* configure.ac, plugins/python/glade-python.c:

View File

@ -49,6 +49,7 @@ EXTRA_DIST = glade-marshallers.list gladeui.rc.in icon-naming-spec.c glade-previ
# The glade core library
libgladeui_2_la_SOURCES = \
glade-debug.c \
glade-object-stub.c \
glade-xml-utils.c \
glade-catalog.c \
glade-widget-adaptor.c \
@ -144,6 +145,7 @@ libgladeuiinclude_HEADERS = \
noinst_HEADERS = \
glade-marshallers.h \
glade-design-layout.h \
glade-object-stub.h \
glade-popup.h \
glade-accumulators.h \
glade-design-private.h \

224
gladeui/glade-object-stub.c Normal file
View File

@ -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));
}

View File

@ -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_ */

View File

@ -50,7 +50,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)
@ -131,6 +131,8 @@ struct _GladeProjectPrivate
* (full or relative path, null means project directory).
*/
GList *unknown_catalogs; /* List of CatalogInfo catalogs */
/* Control on the properties dialog to update buttons etc when properties change */
GtkWidget *prefs_dialog;
GtkWidget *project_wide_radio;
@ -164,11 +166,11 @@ struct _GladeProjectPrivate
guint pointer_mode : 2; /* The currently effective GladePointerMode */
};
typedef struct
typedef struct
{
gchar *stock;
gchar *filename;
} StockFilePair;
gchar *catalog;
gint position;
} CatalogInfo;
GType
glade_pointer_mode_get_type (void)
@ -286,29 +288,30 @@ static void
glade_project_dispose (GObject *object)
{
GladeProject *project = GLADE_PROJECT (object);
GladeProjectPrivate *priv = project->priv;
GList *list, *tree;
/* Emit close signal */
g_signal_emit (object, glade_project_signals[CLOSE], 0);
/* Destroy running previews */
if (project->priv->previews)
if (priv->previews)
{
g_hash_table_destroy (project->priv->previews);
project->priv->previews = NULL;
g_hash_table_destroy (priv->previews);
priv->previews = NULL;
}
if (project->priv->selection_changed_id > 0)
project->priv->selection_changed_id =
(g_source_remove (project->priv->selection_changed_id), 0);
if (priv->selection_changed_id > 0)
priv->selection_changed_id =
(g_source_remove (priv->selection_changed_id), 0);
glade_project_selection_clear (project, TRUE);
glade_project_list_unref (project->priv->undo_stack);
project->priv->undo_stack = NULL;
glade_project_list_unref (priv->undo_stack);
priv->undo_stack = NULL;
/* Remove objects from the project */
tree = g_list_copy (project->priv->tree);
tree = g_list_copy (priv->tree);
for (list = tree; list; list = list->next)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (list->data);
@ -317,14 +320,29 @@ glade_project_dispose (GObject *object)
}
g_list_free (tree);
while (project->priv->tree)
glade_project_remove_object (project, project->priv->tree->data);
while (priv->tree)
glade_project_remove_object (project, priv->tree->data);
while (project->priv->objects)
glade_project_remove_object (project, project->priv->objects->data);
while (priv->objects)
glade_project_remove_object (project, priv->objects->data);
g_assert (project->priv->tree == NULL);
g_assert (project->priv->objects == NULL);
g_assert (priv->tree == NULL);
g_assert (priv->objects == NULL);
if (priv->unknown_catalogs)
{
GList *l;
for (l = priv->unknown_catalogs; l; l = g_list_next (l))
{
CatalogInfo *data = l->data;
g_free (data->catalog);
g_free (data);
}
g_list_free (priv->unknown_catalogs);
priv->unknown_catalogs = NULL;
}
G_OBJECT_CLASS (glade_project_parent_class)->dispose (object);
}
@ -715,6 +733,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->previews = g_hash_table_new_full (g_str_hash,
g_str_equal,
@ -1104,6 +1123,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))
@ -1131,6 +1151,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, ", ");
@ -1144,9 +1175,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)
@ -1433,9 +1465,94 @@ glade_project_push_progress (GladeProject *project)
project->priv->progress_full, project->priv->progress_step);
}
/* translators: reffers to project name '%s' that targets gtk version '%d.%d' */
#define PROJECT_TARGET_DIALOG_TITLE_FMT _("%s targets Gtk+ %d.%d")
static void
glade_project_check_target_version (GladeProject *project)
{
GladeProjectPrivate *priv;
GHashTable *unknown_classes;
gint unknown_objects;
gint major, minor;
GtkWidget *dialog;
GString *text;
GList *l;
glade_project_get_target_version (project, "gtk+", &major, &minor);
/* Glade >= 3.10 only targets Gtk 3 */
if (major >= 3) return;
priv = project->priv;
unknown_classes = g_hash_table_new (g_str_hash, g_str_equal);
unknown_objects = 0;
for (l = priv->objects; l; l = g_list_next (l))
{
if (GLADE_IS_OBJECT_STUB (l->data))
{
gchar *type;
g_object_get (l->data, "object-type", &type, NULL);
g_hash_table_insert (unknown_classes, type, NULL);
unknown_objects++;
}
}
if (unknown_objects)
{
GList *classes = g_hash_table_get_keys (unknown_classes);
if (unknown_objects == 1)
{
text = g_string_new (_("Specially because there is an object that can not be build with type "));
}
else
{
text = g_string_new ("");
g_string_printf (text, _("Specially because there are %d objects that can not be build with types "),
unknown_objects);
}
for (l = classes; l; l = g_list_next (l))
{
if (g_list_previous (l))
g_string_append (text, (g_list_next (l)) ? ", " : _(" and "));
g_string_append (text, l->data);
}
g_list_free (classes);
}
else
text = NULL;
dialog = gtk_message_dialog_new (GTK_WINDOW (glade_app_get_window ()),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
PROJECT_TARGET_DIALOG_TITLE_FMT,
glade_project_get_name (project),
major, minor);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("But this version of Glade is for GTK+ 3 only.\n"
"Make sure you can run this project with Glade 3.8 with no deprecated widgets first.\n"
"%s"), (text) ? text->str : "");
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
glade_project_set_target_version (project, "gtk+", 3, 0);
g_hash_table_destroy (unknown_classes);
if (text) g_string_free (text, TRUE);
}
static gboolean
glade_project_load_internal (GladeProject *project)
{
GladeProjectPrivate *priv = project->priv;
GladeXmlContext *context;
GladeXmlDoc *doc;
GladeXmlNode *root;
@ -1444,20 +1561,20 @@ glade_project_load_internal (GladeProject *project)
gboolean has_gtk_dep = FALSE;
gint count;
project->priv->selection = NULL;
project->priv->objects = NULL;
project->priv->loading = TRUE;
priv->selection = NULL;
priv->objects = NULL;
priv->loading = TRUE;
/* get the context & root node of the catalog file */
if (!(context =
glade_xml_context_new_from_path (project->priv->path, NULL, NULL)))
glade_xml_context_new_from_path (priv->path, NULL, NULL)))
{
g_warning ("Couldn't open glade file [%s].", project->priv->path);
project->priv->loading = FALSE;
g_warning ("Couldn't open glade file [%s].", priv->path);
priv->loading = FALSE;
return FALSE;
}
project->priv->mtime = glade_util_get_file_mtime (project->priv->path, NULL);
priv->mtime = glade_util_get_file_mtime (priv->path, NULL);
doc = glade_xml_context_get_doc (context);
root = glade_xml_doc_get_root (doc);
@ -1465,9 +1582,9 @@ glade_project_load_internal (GladeProject *project)
if (!glade_xml_node_verify_silent (root, GLADE_XML_TAG_PROJECT))
{
g_warning ("Couldnt recognize GtkBuilder xml, skipping %s",
project->priv->path);
priv->path);
glade_xml_context_free (context);
project->priv->loading = FALSE;
priv->loading = FALSE;
return FALSE;
}
@ -1477,21 +1594,18 @@ 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;
}
/* Read requieres, and do not abort load if there are missing catalog since
* GladeObjectStub is created to keep the original xml for unknown object classes
*/
glade_project_read_requires (project, root, priv->path, &has_gtk_dep);
glade_project_read_resource_path (project, root);
/* Launch a dialog if it's going to take enough time to be
* worth showing at all */
count = glade_project_count_xml_objects (project, root, 0);
project->priv->progress_full = count;
project->priv->progress_step = 0;
priv->progress_full = count;
priv->progress_step = 0;
for (node = glade_xml_node_get_children (root);
node; node = glade_xml_node_next (node))
@ -1503,23 +1617,23 @@ glade_project_load_internal (GladeProject *project)
if ((widget = glade_widget_read (project, NULL, node, NULL)) != NULL)
glade_project_add_object (project, glade_widget_get_object (widget));
if (project->priv->load_cancel)
if (priv->load_cancel)
break;
}
/* Finished with the xml context */
glade_xml_context_free (context);
if (project->priv->load_cancel)
if (priv->load_cancel)
{
project->priv->loading = FALSE;
priv->loading = FALSE;
return FALSE;
}
if (!has_gtk_dep)
glade_project_introspect_gtk_version (project);
if (glade_util_file_is_writeable (project->priv->path) == FALSE)
if (glade_util_file_is_writeable (priv->path) == FALSE)
glade_project_set_readonly (project, TRUE);
/* Now we have to loop over all the object properties
@ -1530,8 +1644,8 @@ glade_project_load_internal (GladeProject *project)
/* Reset project status here too so that you get a clean
* slate after calling glade_project_open().
*/
project->priv->modified = FALSE;
project->priv->loading = FALSE;
priv->modified = FALSE;
priv->loading = FALSE;
/* Emit "parse-finished" signal */
g_signal_emit (project, glade_project_signals[PARSE_FINISHED], 0);
@ -1540,6 +1654,8 @@ glade_project_load_internal (GladeProject *project)
*/
glade_project_verify_project_for_ui (project);
glade_project_check_target_version (project);
return TRUE;
}
@ -2221,24 +2337,35 @@ 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);
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);
path_name = glade_widget_generate_path_name (widget);
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);
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)
@ -3248,7 +3375,16 @@ glade_project_required_libs (GladeProject *project)
if (!required)
required = g_list_prepend (required, g_strdup ("gtk+"));
return g_list_reverse (required);
required = 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;
}
/**
@ -4551,8 +4687,8 @@ gtk_tree_model_iface_init (GtkTreeModelIface *iface)
void
glade_project_copy_selection (GladeProject *project)
{
GList *widgets = NULL, *list;
GladeWidget *widget;
GList *widgets = NULL, *list;
gboolean has_unknown = FALSE;
g_return_if_fail (GLADE_IS_PROJECT (project));
@ -4568,12 +4704,19 @@ glade_project_copy_selection (GladeProject *project)
for (list = project->priv->selection; list && list->data; list = list->next)
{
widget = glade_widget_get_from_gobject (list->data);
widget = glade_widget_dup (widget, FALSE);
widgets = g_list_prepend (widgets, widget);
if (GLADE_IS_OBJECT_STUB (list->data))
has_unknown = TRUE;
else
{
GladeWidget *widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, glade_widget_dup (widget, FALSE));
}
}
if (has_unknown)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("Unknown widgets ignored."));
glade_clipboard_add (glade_app_get_clipboard (), widgets);
g_list_free (widgets);
}
@ -4582,7 +4725,7 @@ void
glade_project_command_cut (GladeProject *project)
{
GList *widgets = NULL, *list;
GladeWidget *widget;
gboolean has_unknown = FALSE;
gboolean failed = FALSE;
g_return_if_fail (GLADE_IS_PROJECT (project));
@ -4592,12 +4735,20 @@ glade_project_command_cut (GladeProject *project)
for (list = project->priv->selection; list && list->data; list = list->next)
{
widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, widget);
if (GLADE_IS_OBJECT_STUB (list->data))
has_unknown = TRUE;
else
{
GladeWidget *widget = glade_widget_get_from_gobject (list->data);
widgets = g_list_prepend (widgets, widget);
}
}
if (failed == FALSE && widgets != NULL)
glade_command_cut (widgets);
else if (has_unknown)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("Unknown widgets ignored."));
else if (widgets == NULL)
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_INFO, NULL, _("No widget selected."));

View File

@ -249,15 +249,18 @@ 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);
gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
message_type, buttons_type, NULL);
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));
gtk_widget_destroy (dialog);

View File

@ -56,7 +56,7 @@
#include "glade-design-view.h"
#include "glade-widget-action.h"
#include "glade-signal-model.h"
#include "glade-object-stub.h"
static void glade_widget_set_adaptor (GladeWidget * widget,
GladeWidgetAdaptor * adaptor);
@ -3779,7 +3779,22 @@ glade_widget_read (GladeProject * project,
}
glade_widget_adaptor_read_widget (adaptor, widget, node);
}
else
{
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_WIDGET),
FALSE,
"parent", parent,
"project", project,
"reason", GLADE_CREATE_LOAD,
"object", stub,
"name", id,
NULL);
}
g_free (id);
}
@ -3903,9 +3918,18 @@ void
glade_widget_write (GladeWidget * widget,
GladeXmlContext * context, GladeXmlNode * node)
{
GObject *object = glade_widget_get_object (widget);
GladeXmlNode *widget_node;
GList *l, *list;
/* Check if its an unknown object, and use saved xml if so */
if (GLADE_IS_OBJECT_STUB (object))
{
g_object_get (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);
glade_xml_node_append_child (node, widget_node);

View File

@ -750,6 +750,17 @@ glade_xml_node_new_comment (GladeXmlContext * context, const gchar * comment)
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)

View File

@ -219,6 +219,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);