Commit 9de9e61b authored by Tristan Van Berkom's avatar Tristan Van Berkom

2010-01-29 Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com>

	* gladeui/Makefile.am:
	  Added new files needed for object separation and updated protocol for the preview feature.

	* gladeui/glade-preview-tokens.h:
	  Stores commom code between glade-preview and glade-previewer.

	* gladeui/glade-preview-tokens.h:
	  Updated protocol. Updated license to LGPL.

	* gladeui/glade-project.c, gladeui/glade-preview.[ch]:
	  Object separation for Glade_preview. Updated license of gladeui/glade-preview.[ch] to LGPL.
	  Updated protocol for glade-previewer.
parent c028fefa
2010-01-29 Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com>
* gladeui/Makefile.am:
Added new files needed for object separation and updated protocol for the preview feature.
* gladeui/glade-preview-tokens.h:
Stores commom code between glade-preview and glade-previewer.
* gladeui/glade-preview-tokens.h:
Updated protocol. Updated license to LGPL.
* gladeui/glade-project.c, gladeui/glade-preview.[ch]:
Object separation for Glade_preview. Updated license of gladeui/glade-preview.[ch] to LGPL.
Updated protocol for glade-previewer.
2011-02-08 Juan Pablo Ugarte <juanpablougarte@gmail.com>
* gladeui/glade-design-layout.c:
......
......@@ -40,7 +40,7 @@ common_defines = \
-DGLADE_MODULESDIR="\"$(pkglibdir)/modules\"" \
-DGLADE_PIXMAPSDIR="\"$(pkgdatadir)/pixmaps\"" \
-DGLADE_LOCALEDIR="\"$(datadir)/locale\""\
-DGLADE_BINDIR="\"$(bindir)\""
-DGLADE_BINDIR="\"$(bindir)\""
BUILT_SOURCES = glade-marshallers.c glade-marshallers.h
......@@ -86,7 +86,8 @@ libgladeui_2_la_SOURCES = \
glade-name-context.c \
glade-displayable-values.c \
glade-signal-model.c \
glade-cell-renderer-icon.c
glade-cell-renderer-icon.c \
glade-preview.c
libgladeui_2_la_CPPFLAGS = \
$(common_defines) \
......@@ -145,7 +146,8 @@ noinst_HEADERS = \
glade-popup.h \
glade-cursor.h \
glade-accumulators.h \
glade-design-private.h
glade-design-private.h \
glade-preview-tokens.h
if PLATFORM_WIN32
libgladeui_2_la_LDFLAGS += -no-undefined
......
......@@ -2,7 +2,7 @@
* Copyright (C) 2010 Marco Diego Aurélio Mesquita
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
......@@ -11,7 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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.
*
......@@ -19,7 +19,6 @@
* Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com>
*/
#include <config.h>
#include <stdlib.h>
......@@ -32,6 +31,8 @@
#include <locale.h>
#include <glib/gi18n-lib.h>
#include "glade-preview-tokens.h"
static void
display_help_and_quit (const GOptionEntry * entries)
{
......@@ -168,10 +169,11 @@ get_toplevel (gchar * name, gchar * string, gsize length)
}
g_object_unref (builder);
return toplevel;
}
static void
static GtkWidget *
preview_widget (gchar * name, gchar * buffer, gsize length)
{
GtkWidget *widget;
......@@ -200,6 +202,8 @@ preview_widget (gchar * name, gchar * buffer, gsize length)
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show_all (window);
return widget;
}
static GIOChannel *
......@@ -259,7 +263,7 @@ read_buffer (GIOChannel * source)
}
/* Check for quit token */
if (g_strcmp0 ("<quit>", token) == 0)
if (g_strcmp0 (QUIT_TOKEN, token) == 0)
{
g_free (token);
return NULL;
......@@ -287,11 +291,115 @@ read_buffer (GIOChannel * source)
return buffer;
}
static void
copy_window_properties (GtkWindow *old_window, GtkWindow *new_window)
{
GParamSpec **properties_list;
guint i, n_properties;
gint width, height;
GValue copy_value = { 0,};
if (!old_window || !new_window) return;
properties_list = g_object_class_list_properties
(G_OBJECT_GET_CLASS (G_OBJECT (new_window)),
&n_properties);
for (i = 0; i < n_properties; i++)
{
if (!((properties_list[i]->flags & G_PARAM_READABLE) &&
(properties_list[i]->flags & G_PARAM_WRITABLE) &&
(!(properties_list[i]->flags & G_PARAM_CONSTRUCT_ONLY))
)) continue;
/* We won't set some properties */
if (g_strcmp0 ("parent", properties_list[i]->name) == 0) continue;
if (g_strcmp0 ("visible", properties_list[i]->name) == 0) continue;
g_value_init (&copy_value, properties_list[i]->value_type);
g_object_get_property (G_OBJECT (new_window),
properties_list[i]->name,
&copy_value);
g_object_set_property (G_OBJECT (old_window),
properties_list[i]->name,
&copy_value);
g_value_unset (&copy_value);
}
/* Special code to copy default size */
if (gtk_window_get_resizable (old_window))
{
gtk_window_get_default_size (new_window, &width, &height);
if ((width > 0) && (height > 0))
gtk_window_resize (old_window, width, height);
}
if (properties_list) g_free (properties_list);
}
static void
update_window (GtkWindow *old_window, GtkWindow *new_window)
{
GtkWidget *window_child;
GtkWidget *old_window_child;
if (!old_window || !new_window) return;
/* ref the new window child */
window_child = gtk_bin_get_child (GTK_BIN (new_window));
if (window_child)
{
g_object_ref (window_child);
/* remove window child */
gtk_container_remove (GTK_CONTAINER (new_window), window_child);
}
/* gtk_widget_destroy the *running preview's* window child */
old_window_child = gtk_bin_get_child (GTK_BIN (old_window));
if (old_window_child)
gtk_widget_destroy (old_window_child);
/* apply properties from the new window to the
* old window (using GObjectapis)*/
copy_window_properties (old_window, new_window);
/* add new preview's window child to the old preview's window */
if (window_child)
{
gtk_container_add (GTK_CONTAINER (old_window), window_child);
/* unref the newly added child (which we added a ref to before) */
g_object_unref (window_child);
}
}
static void
update_window_child (GtkWindow *old_window, GtkWidget *new_widget)
{
GtkWidget *old_window_child;
if (!old_window) return;
/* gtk_widget_destroy the *running preview's* window child */
old_window_child = gtk_bin_get_child (GTK_BIN (old_window));
if (old_window_child)
gtk_widget_destroy (old_window_child);
/* add new widget as child to the old preview's window */
if (new_widget)
gtk_container_add (GTK_CONTAINER (old_window), new_widget);
}
static gboolean
on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
{
gchar *buffer;
gsize length;
static GtkWidget *preview_window = NULL;
GtkWidget *new_widget;
gchar **split_buffer = NULL;
gchar *toplevel_name = (gchar *) data;
......@@ -310,8 +418,43 @@ on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
length = strlen (buffer);
preview_widget (toplevel_name, buffer, length);
g_free (buffer);
/* if it is the first time this is called */
if (!preview_window)
{
preview_window = preview_widget (toplevel_name, buffer, length);
}
else
{
/* We have an update */
split_buffer = g_strsplit_set (buffer + UPDATE_TOKEN_SIZE, "\n", 2);
g_free (buffer);
if (!split_buffer) return FALSE;
toplevel_name = split_buffer[0];
buffer = split_buffer[1];
length = strlen (buffer);
new_widget = get_toplevel (toplevel_name, buffer, length);
if (GTK_IS_WINDOW (new_widget))
update_window (GTK_WINDOW (preview_window),
GTK_WINDOW (new_widget));
else update_window_child (GTK_WINDOW (preview_window), new_widget);
}
if (!split_buffer)
{
/* This means we're not in an update, we should free the buffer. */
g_free (buffer);
}
else
{
/* This means we've had an update, buffer was already freed. */
g_free (split_buffer[0]);
g_free (split_buffer[1]);
g_free (split_buffer);
}
return TRUE;
}
......
......@@ -45,6 +45,8 @@
#include "glade-marshallers.h"
#include "glade-catalog.h"
#include "glade-preview.h"
#include "glade-project.h"
#include "glade-command.h"
#include "glade-name-context.h"
......@@ -139,8 +141,8 @@ struct _GladeProjectPrivate
GtkWidget *relative_path_entry;
GtkWidget *full_path_button;
/* Store preview processes, so we can kill them on close */
GHashTable *preview_channels;
/* Store previews, so we can kill them on close */
GHashTable *previews;
/* For the loading progress bars ("load-progress" signal) */
gint progress_step;
......@@ -166,13 +168,6 @@ typedef struct
gchar *filename;
} StockFilePair;
typedef struct
{
GIOChannel *channel;
guint watch;
} ChannelWatchPair;
GType
glade_pointer_mode_get_type (void)
{
......@@ -294,6 +289,13 @@ glade_project_dispose (GObject * object)
/* Emit close signal */
g_signal_emit (object, glade_project_signals[CLOSE], 0);
/* Destroy running previews */
if (project->priv->previews)
{
g_hash_table_destroy (project->priv->previews);
project->priv->previews = NULL;
}
if (project->priv->selection_changed_id > 0)
project->priv->selection_changed_id =
(g_source_remove (project->priv->selection_changed_id), 0);
......@@ -645,66 +647,32 @@ glade_project_push_undo_impl (GladeProject * project, GladeCommand * cmd)
}
static void
glade_project_preview_exits (GPid pid, gint status, gpointer data)
glade_project_preview_exits (GladePreview *preview, GladeProject *project)
{
GladeProject *project = (GladeProject *) data;
ChannelWatchPair *channel_watch;
GIOChannel *channel;
gchar *pidstr = g_strdup_printf ("%d", pid);
gchar *pidstr;
channel_watch = g_hash_table_lookup (project->priv->preview_channels, pidstr);
channel = channel_watch->channel;
g_io_channel_unref (channel);
g_hash_table_remove (project->priv->preview_channels, pidstr);
pidstr = g_strdup_printf ("%d", glade_preview_get_pid (preview));
preview = g_hash_table_lookup (project->priv->previews, pidstr);
if (preview)
g_hash_table_remove (project->priv->previews, pidstr);
g_free (pidstr);
g_free (channel_watch);
}
static void
glade_project_kill_previews (gpointer key, gpointer value, gpointer user_data)
glade_project_destroy_preview (gpointer data)
{
const gchar *quit = "<quit>";
GIOChannel *channel;
ChannelWatchPair *channel_watch = (ChannelWatchPair *) value;
GError *error = NULL;
gsize size;
channel = channel_watch->channel;
/* Removing watch, since the child will commit suicide */
g_source_remove (channel_watch->watch);
g_io_channel_write_chars (channel, quit, strlen (quit), &size, &error);
if (size != strlen (quit) && error != NULL)
{
g_printerr ("Error passing quit signal trough pipe: %s", error->message);
g_error_free (error);
}
g_io_channel_flush (channel, &error);
if (error != NULL)
{
g_printerr ("Error flushing channel: %s", error->message);
g_error_free (error);
}
GladePreview *preview = GLADE_PREVIEW (data);
GladeWidget *gwidget;
g_io_channel_shutdown (channel, TRUE, &error);
if (error != NULL)
{
g_printerr ("Error shutting down channel: %s", error->message);
g_error_free (error);
}
g_io_channel_unref (channel);
g_free (channel_watch);
}
gwidget = glade_preview_get_widget (preview);
g_object_set_data (G_OBJECT (gwidget), "preview", NULL);
static void
glade_project_close_impl (GladeProject * project)
{
g_hash_table_foreach (project->priv->preview_channels,
glade_project_kill_previews, project);
g_hash_table_unref (project->priv->preview_channels);
g_signal_handlers_disconnect_by_func (preview,
G_CALLBACK (glade_project_preview_exits),
g_object_get_data (G_OBJECT (preview), "project"));
g_object_unref (preview);
}
static void
......@@ -748,8 +716,11 @@ glade_project_init (GladeProject * project)
priv->first_modification = NULL;
priv->first_modification_is_na = FALSE;
priv->preview_channels =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
priv->previews = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
glade_project_destroy_preview);
priv->widget_names = glade_name_context_new ();
priv->accel_group = NULL;
......@@ -810,7 +781,7 @@ glade_project_class_init (GladeProjectClass * klass)
klass->widget_name_changed = NULL;
klass->selection_changed = NULL;
klass->close = glade_project_close_impl;
klass->close = NULL;
klass->changed = glade_project_changed_impl;
/**
......@@ -1894,95 +1865,6 @@ glade_project_save (GladeProject * project, const gchar * path, GError ** error)
return ret > 0;
}
static GPid
glade_project_launch_preview (GladeProject * project, gchar * buffer,
GtkWidget * widget)
{
GPid pid;
GError *error = NULL;
gchar *argv[4];
gint child_stdin;
GIOChannel *output;
guint watch;
ChannelWatchPair *channel_watch;
GladeWidget *glade_widget;
#ifdef WINDOWS
argv[0] =
g_build_filename (glade_app_get_bin_dir (), "glade-previewer.exe", NULL);
#else
argv[0] =
g_build_filename (glade_app_get_bin_dir (), "glade-previewer", NULL);
#endif
argv[1] = "--listen";
if (widget != NULL)
{
glade_widget = glade_widget_get_from_gobject (G_OBJECT (widget));
argv[2] = g_strdup_printf ("--toplevel=%s", glade_widget_get_name (glade_widget));
argv[3] = NULL;
}
if (g_spawn_async_with_pipes (NULL,
argv,
NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
&pid, &child_stdin, NULL, NULL,
&error) == FALSE)
{
g_printerr (_("Error launching previewer: %s\n"), error->message);
glade_util_ui_message (glade_app_get_window (),
GLADE_UI_ERROR, NULL,
_("Failed to launch preview: %s.\n"),
error->message);
g_error_free (error);
pid = 0;
goto end;
}
/* Store watch so we can remove it later */
watch = g_child_watch_add (pid, glade_project_preview_exits, project);
#ifdef WINDOWS
output = g_io_channel_win32_new_fd (child_stdin);
#else
output = g_io_channel_unix_new (child_stdin);
#endif
gsize bytes_written;
g_io_channel_write_chars (output, buffer, strlen (buffer), &bytes_written,
&error);
if (bytes_written != strlen (buffer) && error != NULL)
{
g_printerr ("Error passing UI trough pipe: %s", error->message);
g_error_free (error);
}
g_io_channel_flush (output, &error);
if (error != NULL)
{
g_printerr ("Error flushing UI trough pipe: %s", error->message);
g_error_free (error);
}
if (widget != NULL)
g_free (argv[2]);
/* Adding channel to list of channels */
channel_watch = g_new (ChannelWatchPair, 1);
channel_watch->channel = output;
channel_watch->watch = watch;
g_hash_table_insert (project->priv->preview_channels,
g_strdup_printf ("%d", pid), channel_watch);
end:
g_free (argv[0]);
return pid;
}
/**
* glade_project_preview:
* @project: a #GladeProject
......@@ -1997,8 +1879,8 @@ void
glade_project_preview (GladeProject * project, GladeWidget * gwidget)
{
GladeXmlContext *context;
gchar *text;
GtkWidget *widget;
gchar *text, *pidstr;
GladePreview *preview = NULL;
g_return_if_fail (GLADE_IS_PROJECT (project));
......@@ -2009,9 +1891,36 @@ glade_project_preview (GladeProject * project, GladeWidget * gwidget)
gwidget = glade_widget_get_toplevel (gwidget);
if (!GTK_IS_WIDGET (glade_widget_get_object (gwidget)))
return;
widget = GTK_WIDGET (glade_widget_get_object (gwidget));
glade_project_launch_preview (project, text, widget);
if ((pidstr = g_object_get_data (G_OBJECT (gwidget), "preview")) != NULL)
preview = g_hash_table_lookup (project->priv->previews, pidstr);
if (!preview)
{
preview = glade_preview_launch (gwidget, text);
/* Leave project data on the preview */
g_object_set_data (G_OBJECT (preview), "project", project);
/* Leave preview data on the widget */
g_object_set_data_full (G_OBJECT (gwidget),
"preview",
g_strdup_printf ("%d", glade_preview_get_pid (preview)),
g_free);
g_signal_connect (preview, "exits",
G_CALLBACK (glade_project_preview_exits),
project);
/* Add preview to list of previews */
g_hash_table_insert (project->priv->previews,
g_strdup_printf("%d", glade_preview_get_pid (preview)),
preview);
}
else
{
glade_preview_update (preview, text);
}
g_free (text);
}
......@@ -2021,15 +1930,16 @@ glade_project_preview (GladeProject * project, GladeWidget * gwidget)
*******************************************************************/
/* translators: reffers to a widget in toolkit version '%s %d.%d' and a project targeting toolkit version '%s %d.%d' */
#define WIDGET_VERSION_CONFLICT_MSGFMT _("This widget was introduced in %s %d.%d while project targets %s %d.%d")
#define WIDGET_VERSION_CONFLICT_MSGFMT _("This widget was introduced in %s %d.%d " \
"while project targets %s %d.%d")
/* translators: reffers to a widget '[%s]' introduced in toolkit version '%s %d.%d' */
#define WIDGET_VERSION_CONFLICT_FMT _("[%s] Object class '%s' was introduced in %s %d.%d\n")
#define WIDGET_VERSION_CONFLICT_FMT _("[%s] Object class '%s' was introduced in %s %d.%d\n")
#define WIDGET_DEPRECATED_MSG _("This widget is deprecated")
#define WIDGET_DEPRECATED_MSG _("This widget is deprecated")
/* translators: reffers to a widget '[%s]' loaded from toolkit version '%s %d.%d' */
#define WIDGET_DEPRECATED_FMT _("[%s] Object class '%s' from %s %d.%d is deprecated\n")
#define WIDGET_DEPRECATED_FMT _("[%s] Object class '%s' from %s %d.%d is deprecated\n")
/* Defined here for pretty translator comments (bug in intl tools, for some reason
......@@ -2039,22 +1949,25 @@ glade_project_preview (GladeProject * project, GladeWidget * gwidget)
/* translators: reffers to a property in toolkit version '%s %d.%d'
* and a project targeting toolkit version '%s %d.%d' */
#define PROP_VERSION_CONFLICT_MSGFMT _("This property was introduced in %s %d.%d while project targets %s %d.%d")
#define PROP_VERSION_CONFLICT_MSGFMT _("This property was introduced in %s %d.%d " \
"while project targets %s %d.%d")
/* translators: reffers to a property '%s' of widget '[%s]' in toolkit version '%s %d.%d' */
#define PROP_VERSION_CONFLICT_FMT _("[%s] Property '%s' of object class '%s' was introduced in %s %d.%d\n")
#define PROP_VERSION_CONFLICT_FMT _("[%s] Property '%s' of object class '%s' " \
"was introduced in %s %d.%d\n")
/* translators: reffers to a property '%s' of widget '[%s]' in toolkit version '%s %d.%d' */
#define PACK_PROP_VERSION_CONFLICT_FMT _("[%s] Packing property '%s' of object class '%s' " \
"was introduced in %s %d.%d\n")
#define PACK_PROP_VERSION_CONFLICT_FMT _("[%s] Packing property '%s' of object class '%s' " \
"was introduced in %s %d.%d\n")
/* translators: reffers to a signal '%s' of widget '[%s]' in toolkit version '%s %d.%d' */
#define SIGNAL_VERSION_CONFLICT_FMT _("[%s] Signal '%s' of object class '%s' was introduced in %s %d.%d\n")
#define SIGNAL_VERSION_CONFLICT_FMT _("[%s] Signal '%s' of object class '%s' " \
"was introduced in %s %d.%d\n")
/* translators: reffers to a signal in toolkit version '%s %d.%d'
* and a project targeting toolkit version '%s %d.%d' */
#define SIGNAL_VERSION_CONFLICT_MSGFMT _("This signal was introduced in %s %d.%d while project targets %s %d.%d")
#define SIGNAL_VERSION_CONFLICT_MSGFMT _("This signal was introduced in %s %d.%d " \
"while project targets %s %d.%d")
static void
......@@ -2906,6 +2819,7 @@ glade_project_remove_object (GladeProject * project, GObject * object)
{
GladeWidget *gwidget;
GList *list, *children;
gchar *preview_pid;
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (G_IS_OBJECT (object));
......@@ -2942,6 +2856,9 @@ glade_project_remove_object (GladeProject * project, GObject * object)
project->priv->tree = g_list_remove (project->priv->tree, object);
project->priv->objects = g_list_remove (project->priv->objects, object);
if ((preview_pid = g_object_get_data (G_OBJECT (gwidget), "preview")))
g_hash_table_remove (project->priv->previews, preview_pid);
/* Unset the project pointer on the GladeWidget */
glade_widget_set_project (gwidget, NULL);
glade_widget_set_in_project (gwidget, FALSE);
......@@ -2965,7 +2882,6 @@ glade_project_set_target_version (GladeProject * project,
g_hash_table_insert (project->priv->target_versions_minor,
g_strdup (catalog), GINT_TO_POINTER ((int) minor));
/* Update prefs dialog from here... */
if (project->priv->target_radios &&
(radios =
......@@ -3745,7 +3661,6 @@ resource_full_path_set (GtkFileChooserButton * button, GladeProject * project)
glade_project_set_resource_path (project, text);
}
static void
update_prefs_for_resource_path (GladeProject * project)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment