Blame gladeui/glade-inspector.c

Packit 1e8aac
/*
Packit 1e8aac
 * glade-inspector.h
Packit 1e8aac
 *
Packit 1e8aac
 * Copyright (C) 2001 Ximian, Inc.
Packit 1e8aac
 * Copyright (C) 2007 Vincent Geddes
Packit 1e8aac
 *
Packit 1e8aac
 * Authors:
Packit 1e8aac
 *   Chema Celorio
Packit 1e8aac
 *   Tristan Van Berkom <tvb@gnome.org>
Packit 1e8aac
 *   Vincent Geddes <vincent.geddes@gmail.com>
Packit 1e8aac
 *
Packit 1e8aac
 * This program is free software; you can redistribute it and/or modify
Packit 1e8aac
 * it under the terms of the GNU General Public License as published by
Packit 1e8aac
 * the Free Software Foundation; either version 2 of the License, or
Packit 1e8aac
 * (at your option) any later version.
Packit 1e8aac
 *
Packit 1e8aac
 * This program is distributed in the hope that it will be useful,
Packit 1e8aac
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1e8aac
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 1e8aac
 * GNU General Public License for more details.
Packit 1e8aac
 *
Packit 1e8aac
 * You should have received a copy of the GNU General Public License
Packit 1e8aac
 * along with this program; if not, write to the Free Software
Packit 1e8aac
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include <config.h>
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * SECTION:glade-inspector
Packit 1e8aac
 * @Short_Description: A widget for inspecting objects in a #GladeProject.
Packit 1e8aac
 *
Packit 1e8aac
 * A #GladeInspector is a widget for inspecting the objects that make up a user interface. 
Packit 1e8aac
 *
Packit 1e8aac
 * An inspector is created by calling either glade_inspector_new() or glade_inspector_new_with_project(). 
Packit 1e8aac
 * The current project been inspected can be changed by calling glade_inspector_set_project().
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include "glade.h"
Packit 1e8aac
#include "glade-widget.h"
Packit 1e8aac
#include "glade-project.h"
Packit 1e8aac
#include "glade-widget-adaptor.h"
Packit 1e8aac
#include "glade-inspector.h"
Packit 1e8aac
#include "glade-popup.h"
Packit 1e8aac
#include "glade-app.h"
Packit 1e8aac
#include "glade-dnd.h"
Packit 1e8aac
Packit 1e8aac
#include <string.h>
Packit 1e8aac
#include <glib/gi18n-lib.h>
Packit 1e8aac
#if GTK_CHECK_VERSION (2, 21, 8)
Packit 1e8aac
#include <gdk/gdkkeysyms-compat.h>
Packit 1e8aac
#else
Packit 1e8aac
#include <gdk/gdkkeysyms.h>
Packit 1e8aac
#endif
Packit 1e8aac
Packit 1e8aac
#define GLADE_INSPECTOR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object),\
Packit 1e8aac
					    GLADE_TYPE_INSPECTOR,                 \
Packit 1e8aac
			 		    GladeInspectorPrivate))
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void     search_entry_text_inserted_cb (GtkEntry       *entry,
Packit 1e8aac
					       const gchar    *text,
Packit 1e8aac
					       gint            length,
Packit 1e8aac
					       gint           *position,
Packit 1e8aac
					       GladeInspector *inspector);
Packit 1e8aac
static void     search_entry_text_deleted_cb  (GtkEditable    *editable,
Packit 1e8aac
					       gint            start_pos,
Packit 1e8aac
					       gint            end_pos,
Packit 1e8aac
					       GladeInspector *inspector);
Packit 1e8aac
Packit 1e8aac
enum
Packit 1e8aac
{
Packit 1e8aac
  PROP_0,
Packit 1e8aac
  PROP_PROJECT,
Packit 1e8aac
  N_PROPERTIES
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
enum
Packit 1e8aac
{
Packit 1e8aac
  SELECTION_CHANGED,
Packit 1e8aac
  ITEM_ACTIVATED,
Packit 1e8aac
  LAST_SIGNAL
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
struct _GladeInspectorPrivate
Packit 1e8aac
{
Packit 1e8aac
  GtkWidget *view;
Packit 1e8aac
  GtkTreeModel *filter;
Packit 1e8aac
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  GtkWidget *entry;
Packit 1e8aac
  guint idle_complete;
Packit 1e8aac
  gboolean search_disabled;
Packit 1e8aac
  gchar *completion_text;
Packit 1e8aac
  gchar *completion_text_fold;
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
static GParamSpec *properties[N_PROPERTIES];
Packit 1e8aac
static guint glade_inspector_signals[LAST_SIGNAL] = { 0 };
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void glade_inspector_dispose (GObject *object);
Packit 1e8aac
static void glade_inspector_finalize (GObject *object);
Packit 1e8aac
static void add_columns (GtkTreeView *inspector);
Packit 1e8aac
static void item_activated_cb (GtkTreeView       *view,
Packit 1e8aac
                               GtkTreePath       *path,
Packit 1e8aac
                               GtkTreeViewColumn *column,
Packit 1e8aac
                               GladeInspector    *inspector);
Packit 1e8aac
static void selection_changed_cb (GtkTreeSelection *selection,
Packit 1e8aac
                                  GladeInspector   *inspector);
Packit 1e8aac
static gint button_press_cb (GtkWidget      *widget,
Packit 1e8aac
                             GdkEventButton *event,
Packit 1e8aac
                             GladeInspector *inspector);
Packit 1e8aac
Packit 1e8aac
G_DEFINE_TYPE_WITH_PRIVATE (GladeInspector, glade_inspector, GTK_TYPE_BOX)
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_set_property (GObject      *object,
Packit 1e8aac
			      guint         property_id,
Packit 1e8aac
			      const GValue *value,
Packit 1e8aac
                              GParamSpec   *pspec)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector = GLADE_INSPECTOR (object);
Packit 1e8aac
Packit 1e8aac
  switch (property_id)
Packit 1e8aac
    {
Packit 1e8aac
      case PROP_PROJECT:
Packit 1e8aac
        glade_inspector_set_project (inspector, g_value_get_object (value));
Packit 1e8aac
        break;
Packit 1e8aac
      default:
Packit 1e8aac
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 1e8aac
        break;
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_get_property (GObject    *object,
Packit 1e8aac
                              guint       property_id,
Packit 1e8aac
                              GValue     *value,
Packit 1e8aac
                              GParamSpec *pspec)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector = GLADE_INSPECTOR (object);
Packit 1e8aac
Packit 1e8aac
  switch (property_id)
Packit 1e8aac
    {
Packit 1e8aac
      case PROP_PROJECT:
Packit 1e8aac
        g_value_set_object (value, glade_inspector_get_project (inspector));
Packit 1e8aac
        break;
Packit 1e8aac
      default:
Packit 1e8aac
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 1e8aac
        break;
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_class_init (GladeInspectorClass *klass)
Packit 1e8aac
{
Packit 1e8aac
  GObjectClass *object_class;
Packit 1e8aac
Packit 1e8aac
  object_class = G_OBJECT_CLASS (klass);
Packit 1e8aac
Packit 1e8aac
  object_class->dispose = glade_inspector_dispose;
Packit 1e8aac
  object_class->finalize = glade_inspector_finalize;
Packit 1e8aac
  object_class->set_property = glade_inspector_set_property;
Packit 1e8aac
  object_class->get_property = glade_inspector_get_property;
Packit 1e8aac
Packit 1e8aac
  /**
Packit 1e8aac
   * GladeInspector::selection-changed:
Packit 1e8aac
   * @inspector: the object which received the signal
Packit 1e8aac
   *
Packit 1e8aac
   * Emitted when the selection changes in the GladeInspector.
Packit 1e8aac
   */
Packit 1e8aac
  glade_inspector_signals[SELECTION_CHANGED] =
Packit 1e8aac
      g_signal_new ("selection-changed",
Packit 1e8aac
                    G_TYPE_FROM_CLASS (object_class),
Packit 1e8aac
                    G_SIGNAL_RUN_LAST,
Packit 1e8aac
                    G_STRUCT_OFFSET (GladeInspectorClass, selection_changed),
Packit 1e8aac
                    NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
Packit 1e8aac
Packit 1e8aac
  /**
Packit 1e8aac
   * GladeInspector::item-activated:
Packit 1e8aac
   * @inspector: the object which received the signal
Packit 1e8aac
   *
Packit 1e8aac
   * Emitted when a item is activated in the GladeInspector.
Packit 1e8aac
   */
Packit 1e8aac
  glade_inspector_signals[ITEM_ACTIVATED] =
Packit 1e8aac
      g_signal_new ("item-activated",
Packit 1e8aac
                    G_TYPE_FROM_CLASS (object_class),
Packit 1e8aac
                    G_SIGNAL_RUN_LAST,
Packit 1e8aac
                    G_STRUCT_OFFSET (GladeInspectorClass, item_activated),
Packit 1e8aac
                    NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
Packit 1e8aac
Packit 1e8aac
  properties[PROP_PROJECT] =
Packit 1e8aac
    g_param_spec_object ("project",
Packit 1e8aac
                         _("Project"),
Packit 1e8aac
                         _("The project being inspected"),
Packit 1e8aac
                         GLADE_TYPE_PROJECT,
Packit 1e8aac
                         G_PARAM_READABLE | G_PARAM_WRITABLE);
Packit 1e8aac
  
Packit 1e8aac
  /* Install all properties */
Packit 1e8aac
  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
glade_inspector_visible_func (GtkTreeModel *model,
Packit 1e8aac
                              GtkTreeIter  *parent,
Packit 1e8aac
                              gpointer      data)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector = data;
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  GtkTreeIter iter;
Packit 1e8aac
Packit 1e8aac
  gboolean retval = FALSE;
Packit 1e8aac
Packit 1e8aac
  if (priv->search_disabled || priv->completion_text == NULL)
Packit 1e8aac
    return TRUE;
Packit 1e8aac
Packit 1e8aac
  if (gtk_tree_model_iter_children (model, &iter, parent))
Packit 1e8aac
    {
Packit 1e8aac
      do
Packit 1e8aac
        {
Packit 1e8aac
          retval = glade_inspector_visible_func (model, &iter, data);
Packit 1e8aac
        }
Packit 1e8aac
      while (gtk_tree_model_iter_next (model, &iter) && !retval);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (!retval)
Packit 1e8aac
    {
Packit 1e8aac
      gchar *widget_name, *haystack;
Packit 1e8aac
Packit 1e8aac
      gtk_tree_model_get (model, parent, GLADE_PROJECT_MODEL_COLUMN_NAME,
Packit 1e8aac
                          &widget_name, -1);
Packit 1e8aac
Packit 1e8aac
      haystack = g_utf8_casefold (widget_name, -1);
Packit 1e8aac
Packit 1e8aac
      retval = strstr (haystack, priv->completion_text_fold) != NULL;
Packit 1e8aac
Packit 1e8aac
      g_free (haystack);
Packit 1e8aac
      g_free (widget_name);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return retval;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_refilter (GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  if (!priv->search_disabled)
Packit 1e8aac
    {
Packit 1e8aac
      gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
Packit 1e8aac
      gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->view));
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
search_entry_changed_cb (GtkEntry *entry, GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  glade_inspector_refilter (inspector);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
typedef struct {
Packit 1e8aac
  const gchar    *text;
Packit 1e8aac
  gchar          *common_text;
Packit 1e8aac
  gchar          *first_match;
Packit 1e8aac
} CommonMatchData;
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
reduce_string (gchar *str1,
Packit 1e8aac
	       const gchar *str2)
Packit 1e8aac
{
Packit 1e8aac
  gint str1len = strlen (str1);
Packit 1e8aac
  gint i;
Packit 1e8aac
Packit 1e8aac
  for (i = 0; str2[i] != '\0'; i++)
Packit 1e8aac
    {
Packit 1e8aac
Packit 1e8aac
      if (str1[i] != str2[i] || i >= str1len)
Packit 1e8aac
	{
Packit 1e8aac
	  str1[i] = '\0';
Packit 1e8aac
	  break;
Packit 1e8aac
	}
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (str2[i] == '\0')
Packit 1e8aac
    str1[i] = '\0';
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
search_common_matches (GtkTreeModel    *model,
Packit 1e8aac
		       GtkTreePath     *path,
Packit 1e8aac
		       GtkTreeIter     *iter,
Packit 1e8aac
		       CommonMatchData *data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget;
Packit 1e8aac
  const gchar *name;
Packit 1e8aac
  GObject *obj;
Packit 1e8aac
  gboolean match;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_get (model, iter, GLADE_PROJECT_MODEL_COLUMN_OBJECT, &obj, -1);
Packit 1e8aac
  gwidget = glade_widget_get_from_gobject (obj);
Packit 1e8aac
Packit 1e8aac
  if (!glade_widget_has_name (gwidget))
Packit 1e8aac
    {
Packit 1e8aac
      g_object_unref (obj);
Packit 1e8aac
      return FALSE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  name  = glade_widget_get_name (gwidget);
Packit 1e8aac
  match = (strncmp (data->text, name, strlen (data->text)) == 0);
Packit 1e8aac
Packit 1e8aac
  if (match)
Packit 1e8aac
    {
Packit 1e8aac
      if (!data->first_match)
Packit 1e8aac
	data->first_match = g_strdup (name);
Packit 1e8aac
Packit 1e8aac
      if (data->common_text)
Packit 1e8aac
        reduce_string (data->common_text, name);
Packit 1e8aac
      else
Packit 1e8aac
	data->common_text = g_strdup (name);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_object_unref (obj);
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/* Returns the shortest common matching text from all
Packit 1e8aac
 * project widget names.
Packit 1e8aac
 *
Packit 1e8aac
 * If shortest_match is specified, it is given the first
Packit 1e8aac
 * full match for the 'search' text
Packit 1e8aac
 */
Packit 1e8aac
static gchar *
Packit 1e8aac
get_partial_match (GladeInspector *inspector,
Packit 1e8aac
		   const gchar    *search,
Packit 1e8aac
		   gchar         **first_match)
Packit 1e8aac
{
Packit 1e8aac
  GtkTreeModel     *model = GTK_TREE_MODEL (inspector->priv->project);
Packit 1e8aac
  CommonMatchData   data;
Packit 1e8aac
Packit 1e8aac
  data.text        = search;
Packit 1e8aac
  data.common_text = NULL;
Packit 1e8aac
  data.first_match = NULL;
Packit 1e8aac
  
Packit 1e8aac
  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)search_common_matches, &data);
Packit 1e8aac
Packit 1e8aac
  if (first_match)
Packit 1e8aac
    *first_match = data.first_match;
Packit 1e8aac
  else
Packit 1e8aac
    g_free (data.first_match);
Packit 1e8aac
Packit 1e8aac
  return data.common_text;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
inspector_set_completion_text (GladeInspector *inspector, const gchar *text)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  g_free (priv->completion_text);
Packit 1e8aac
  priv->completion_text = g_strdup (text);
Packit 1e8aac
  priv->completion_text_fold = text ? g_utf8_casefold (text, -1) : NULL;
Packit 1e8aac
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
search_complete_idle (GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
  gchar *completed;
Packit 1e8aac
  const gchar *str;
Packit 1e8aac
  gsize length;
Packit 1e8aac
Packit 1e8aac
  str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
Packit 1e8aac
Packit 1e8aac
  completed = get_partial_match (inspector, str, NULL);
Packit 1e8aac
  
Packit 1e8aac
  inspector_set_completion_text (inspector, str);
Packit 1e8aac
Packit 1e8aac
  if (completed)
Packit 1e8aac
    {
Packit 1e8aac
      length = strlen (str);
Packit 1e8aac
Packit 1e8aac
      g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
      g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
      gtk_entry_set_text (GTK_ENTRY (priv->entry), completed);
Packit 1e8aac
      gtk_editable_set_position (GTK_EDITABLE (priv->entry), length);
Packit 1e8aac
      gtk_editable_select_region (GTK_EDITABLE (priv->entry), length, -1);
Packit 1e8aac
      g_free (completed);
Packit 1e8aac
Packit 1e8aac
      g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
      g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  priv->idle_complete = 0;
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
search_entry_text_inserted_cb (GtkEntry       *entry,
Packit 1e8aac
                               const gchar    *text,
Packit 1e8aac
                               gint            length,
Packit 1e8aac
                               gint           *position,
Packit 1e8aac
                               GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  if (!priv->search_disabled && !priv->idle_complete)
Packit 1e8aac
    {
Packit 1e8aac
      priv->idle_complete =
Packit 1e8aac
          g_idle_add ((GSourceFunc) search_complete_idle, inspector);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
search_entry_text_deleted_cb (GtkEditable    *editable,
Packit 1e8aac
			      gint            start_pos,
Packit 1e8aac
			      gint            end_pos,
Packit 1e8aac
			      GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  if (!priv->search_disabled)
Packit 1e8aac
    {
Packit 1e8aac
      inspector_set_completion_text (inspector, gtk_entry_get_text (GTK_ENTRY (priv->entry)));
Packit 1e8aac
      glade_inspector_refilter (inspector);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
search_entry_key_press_event_cb (GtkEntry       *entry,
Packit 1e8aac
                                 GdkEventKey    *event,
Packit 1e8aac
                                 GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
  const gchar *str;
Packit 1e8aac
Packit 1e8aac
  str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
Packit 1e8aac
Packit 1e8aac
  if (event->keyval == GDK_KEY_Tab)
Packit 1e8aac
    {
Packit 1e8aac
      /* CNTL-Tab: An escape route to move focus */
Packit 1e8aac
      if (event->state & GDK_CONTROL_MASK)
Packit 1e8aac
        {
Packit 1e8aac
          gtk_widget_grab_focus (priv->view);
Packit 1e8aac
        }
Packit 1e8aac
      else /* Tab: Move cursor forward and refine the filter to include all text */
Packit 1e8aac
        {
Packit 1e8aac
          inspector_set_completion_text (inspector, str);
Packit 1e8aac
Packit 1e8aac
          gtk_editable_set_position (GTK_EDITABLE (entry), -1);
Packit 1e8aac
          gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
Packit 1e8aac
Packit 1e8aac
	  glade_inspector_refilter (inspector);
Packit 1e8aac
        }
Packit 1e8aac
      return TRUE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Enter/Return: Find the first complete match, refine filter to the complete match, and select the match  */
Packit 1e8aac
  if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter)
Packit 1e8aac
    {
Packit 1e8aac
      gchar *name, *full_match = NULL;
Packit 1e8aac
Packit 1e8aac
      if (str && (name = get_partial_match (inspector, str, &full_match)))
Packit 1e8aac
        {
Packit 1e8aac
	  GladeWidget *widget;
Packit 1e8aac
Packit 1e8aac
          inspector_set_completion_text (inspector, full_match);
Packit 1e8aac
	  g_free (name);
Packit 1e8aac
Packit 1e8aac
	  g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
	  g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
          gtk_entry_set_text (GTK_ENTRY (entry), priv->completion_text);
Packit 1e8aac
Packit 1e8aac
	  g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
	  g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
          gtk_editable_set_position (GTK_EDITABLE (entry), -1);
Packit 1e8aac
          gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
Packit 1e8aac
Packit 1e8aac
	  glade_inspector_refilter (inspector);
Packit 1e8aac
Packit 1e8aac
	  widget = glade_project_get_widget_by_name (priv->project, priv->completion_text);
Packit 1e8aac
	  if (widget)
Packit 1e8aac
	    glade_project_selection_set (priv->project, glade_widget_get_object (widget), TRUE);
Packit 1e8aac
        }
Packit 1e8aac
      return TRUE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Backspace: Attempt to move the cursor backwards and maintain the completed/selected portion */
Packit 1e8aac
  if (event->keyval == GDK_KEY_BackSpace)
Packit 1e8aac
    {
Packit 1e8aac
      if (!priv->search_disabled && !priv->idle_complete && str && str[0])
Packit 1e8aac
	{
Packit 1e8aac
	  /* Now, set the text to the current completion text -1 char, and recomplete */
Packit 1e8aac
	  if (priv->completion_text && priv->completion_text[0])
Packit 1e8aac
	    {
Packit 1e8aac
	      /* If we're not at the position of the length of the completion text, just carry on */
Packit 1e8aac
	      if (!gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry), NULL, NULL))
Packit 1e8aac
		return FALSE;
Packit 1e8aac
Packit 1e8aac
	      priv->completion_text[strlen (priv->completion_text) -1] = '\0';
Packit 1e8aac
Packit 1e8aac
	      g_signal_handlers_block_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
	      g_signal_handlers_block_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
	      gtk_entry_set_text (GTK_ENTRY (priv->entry), priv->completion_text);
Packit 1e8aac
	      gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
Packit 1e8aac
Packit 1e8aac
	      g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_inserted_cb, inspector);
Packit 1e8aac
	      g_signal_handlers_unblock_by_func (priv->entry, search_entry_text_deleted_cb, inspector);
Packit 1e8aac
Packit 1e8aac
	      priv->idle_complete =
Packit 1e8aac
		g_idle_add ((GSourceFunc) search_complete_idle, inspector);
Packit 1e8aac
Packit 1e8aac
	      return TRUE;
Packit 1e8aac
	    }
Packit 1e8aac
	}
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
search_entry_focus_in_cb (GtkWidget      *entry,
Packit 1e8aac
                          GdkEventFocus  *event,
Packit 1e8aac
                          GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  if (priv->search_disabled)
Packit 1e8aac
    priv->search_disabled = FALSE;
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
search_entry_focus_out_cb (GtkWidget      *entry,
Packit 1e8aac
                           GdkEventFocus  *event,
Packit 1e8aac
                           GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  priv->search_disabled = TRUE;
Packit 1e8aac
Packit 1e8aac
  inspector_set_completion_text (inspector, NULL);
Packit 1e8aac
Packit 1e8aac
  gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_init (GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspectorPrivate *priv;
Packit 1e8aac
  GtkWidget *sw;
Packit 1e8aac
  GtkTreeSelection *selection;
Packit 1e8aac
Packit 1e8aac
  inspector->priv = priv = glade_inspector_get_instance_private (inspector);
Packit 1e8aac
Packit 1e8aac
  gtk_orientable_set_orientation (GTK_ORIENTABLE (inspector),
Packit 1e8aac
				  GTK_ORIENTATION_VERTICAL);
Packit 1e8aac
Packit 1e8aac
  priv->project = NULL;
Packit 1e8aac
Packit 1e8aac
  priv->entry = gtk_entry_new ();
Packit 1e8aac
Packit 1e8aac
  gtk_entry_set_placeholder_text (GTK_ENTRY (priv->entry), _(" < Search Widgets >"));
Packit 1e8aac
  gtk_widget_show (priv->entry);
Packit 1e8aac
  gtk_box_pack_start (GTK_BOX (inspector), priv->entry, FALSE, FALSE, 2);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (priv->entry, "changed",
Packit 1e8aac
                    G_CALLBACK (search_entry_changed_cb), inspector);
Packit 1e8aac
  g_signal_connect (priv->entry, "key-press-event",
Packit 1e8aac
                    G_CALLBACK (search_entry_key_press_event_cb), inspector);
Packit 1e8aac
  g_signal_connect_after (priv->entry, "insert-text",
Packit 1e8aac
                          G_CALLBACK (search_entry_text_inserted_cb),
Packit 1e8aac
                          inspector);
Packit 1e8aac
  g_signal_connect_after (priv->entry, "delete-text",
Packit 1e8aac
                          G_CALLBACK (search_entry_text_deleted_cb),
Packit 1e8aac
                          inspector);
Packit 1e8aac
  g_signal_connect (priv->entry, "focus-in-event",
Packit 1e8aac
                    G_CALLBACK (search_entry_focus_in_cb), inspector);
Packit 1e8aac
  g_signal_connect (priv->entry, "focus-out-event",
Packit 1e8aac
                    G_CALLBACK (search_entry_focus_out_cb), inspector);
Packit 1e8aac
Packit 1e8aac
  priv->view = gtk_tree_view_new ();
Packit 1e8aac
  gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->view), FALSE);
Packit 1e8aac
  gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (priv->view), GTK_SCROLL_MINIMUM);
Packit 1e8aac
  add_columns (GTK_TREE_VIEW (priv->view));
Packit 1e8aac
Packit 1e8aac
  /* Set it as a drag source */
Packit 1e8aac
  gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->view),
Packit 1e8aac
                                          GDK_BUTTON1_MASK,
Packit 1e8aac
                                          _glade_dnd_get_target (), 1, 0);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (G_OBJECT (priv->view), "row-activated",
Packit 1e8aac
                    G_CALLBACK (item_activated_cb), inspector);
Packit 1e8aac
Packit 1e8aac
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->view));
Packit 1e8aac
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
Packit 1e8aac
  g_signal_connect (G_OBJECT (selection), "changed",
Packit 1e8aac
                    G_CALLBACK (selection_changed_cb), inspector);
Packit 1e8aac
Packit 1e8aac
  /* Expand All */
Packit 1e8aac
  gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->entry), GTK_ENTRY_ICON_SECONDARY, "go-down");
Packit 1e8aac
  gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->entry), GTK_ENTRY_ICON_SECONDARY, _("Expand all"));
Packit 1e8aac
  g_signal_connect_swapped (priv->entry, "icon-press", G_CALLBACK (gtk_tree_view_expand_all), priv->view);
Packit 1e8aac
Packit 1e8aac
  /* popup menu */
Packit 1e8aac
  g_signal_connect (G_OBJECT (priv->view), "button-press-event",
Packit 1e8aac
                    G_CALLBACK (button_press_cb), inspector);
Packit 1e8aac
Packit 1e8aac
  sw = gtk_scrolled_window_new (NULL, NULL);
Packit 1e8aac
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
Packit 1e8aac
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
Packit 1e8aac
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
Packit 1e8aac
  gtk_container_add (GTK_CONTAINER (sw), priv->view);
Packit 1e8aac
  gtk_box_pack_start (GTK_BOX (inspector), sw, TRUE, TRUE, 0);
Packit 1e8aac
Packit 1e8aac
  gtk_widget_show (priv->view);
Packit 1e8aac
  gtk_widget_show (sw);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_dispose (GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector = GLADE_INSPECTOR (object);
Packit 1e8aac
Packit 1e8aac
  glade_inspector_set_project (inspector, NULL);
Packit 1e8aac
Packit 1e8aac
  if (inspector->priv->idle_complete)
Packit 1e8aac
    {
Packit 1e8aac
      g_source_remove (inspector->priv->idle_complete);
Packit 1e8aac
      inspector->priv->idle_complete = 0;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_inspector_parent_class)->dispose (object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_finalize (GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector = GLADE_INSPECTOR (object);
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  g_free (priv->completion_text);
Packit 1e8aac
  g_free (priv->completion_text_fold);
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_inspector_parent_class)->finalize (object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_selection_changed_cb (GladeProject   *project,
Packit 1e8aac
                              GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *widget;
Packit 1e8aac
  GtkTreeSelection *selection;
Packit 1e8aac
  GtkTreeModel *model;
Packit 1e8aac
  GtkTreeIter *iter;
Packit 1e8aac
  GtkTreePath *path, *ancestor_path;
Packit 1e8aac
  GList *list;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (GLADE_IS_INSPECTOR (inspector));
Packit 1e8aac
  g_return_if_fail (GLADE_IS_PROJECT (project));
Packit 1e8aac
  g_return_if_fail (inspector->priv->project == project);
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_block_by_func (gtk_tree_view_get_selection
Packit 1e8aac
                                   (GTK_TREE_VIEW (inspector->priv->view)),
Packit 1e8aac
                                   G_CALLBACK (selection_changed_cb),
Packit 1e8aac
                                   inspector);
Packit 1e8aac
Packit 1e8aac
  selection =
Packit 1e8aac
      gtk_tree_view_get_selection (GTK_TREE_VIEW (inspector->priv->view));
Packit 1e8aac
  g_return_if_fail (selection != NULL);
Packit 1e8aac
Packit 1e8aac
  model = inspector->priv->filter;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_selection_unselect_all (selection);
Packit 1e8aac
Packit 1e8aac
  for (list = glade_project_selection_get (project);
Packit 1e8aac
       list && list->data; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      if ((widget =
Packit 1e8aac
           glade_widget_get_from_gobject (G_OBJECT (list->data))) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          if ((iter =
Packit 1e8aac
               glade_util_find_iter_by_widget (model, widget,
Packit 1e8aac
                                               GLADE_PROJECT_MODEL_COLUMN_OBJECT))
Packit 1e8aac
              != NULL)
Packit 1e8aac
            {
Packit 1e8aac
              path = gtk_tree_model_get_path (model, iter);
Packit 1e8aac
              ancestor_path = gtk_tree_path_copy (path);
Packit 1e8aac
Packit 1e8aac
              /* expand parent node */
Packit 1e8aac
              if (gtk_tree_path_up (ancestor_path))
Packit 1e8aac
                gtk_tree_view_expand_to_path
Packit 1e8aac
                    (GTK_TREE_VIEW (inspector->priv->view), ancestor_path);
Packit 1e8aac
Packit 1e8aac
              gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW
Packit 1e8aac
                                            (inspector->priv->view), path, NULL,
Packit 1e8aac
                                            TRUE, 0.5, 0);
Packit 1e8aac
Packit 1e8aac
              gtk_tree_selection_select_iter (selection, iter);
Packit 1e8aac
Packit 1e8aac
              gtk_tree_iter_free (iter);
Packit 1e8aac
              gtk_tree_path_free (path);
Packit 1e8aac
              gtk_tree_path_free (ancestor_path);
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_unblock_by_func (gtk_tree_view_get_selection
Packit 1e8aac
                                     (GTK_TREE_VIEW (inspector->priv->view)),
Packit 1e8aac
                                     G_CALLBACK (selection_changed_cb),
Packit 1e8aac
                                     inspector);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
selection_foreach_func (GtkTreeModel *model,
Packit 1e8aac
                        GtkTreePath  *path,
Packit 1e8aac
                        GtkTreeIter  *iter,
Packit 1e8aac
                        GList       **selection)
Packit 1e8aac
{
Packit 1e8aac
  GObject *object;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_get (model, iter, GLADE_PROJECT_MODEL_COLUMN_OBJECT, &object,
Packit 1e8aac
                      -1);
Packit 1e8aac
Packit 1e8aac
  if (object)
Packit 1e8aac
    {
Packit 1e8aac
      *selection = g_list_prepend (*selection, object);
Packit 1e8aac
      g_object_unref (object);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
selection_changed_cb (GtkTreeSelection *selection, GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GList *sel = NULL, *l;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_selection_selected_foreach (selection,
Packit 1e8aac
                                       (GtkTreeSelectionForeachFunc)
Packit 1e8aac
                                       selection_foreach_func, &sel;;
Packit 1e8aac
Packit 1e8aac
  /* We dont modify the project selection for a change that
Packit 1e8aac
   * leaves us with no selection. 
Packit 1e8aac
   *
Packit 1e8aac
   * This is typically because the user is changing the name
Packit 1e8aac
   * of a widget and the filter is active, the new name causes
Packit 1e8aac
   * the row to go out of the model and the selection to be
Packit 1e8aac
   * cleared, if we clear the selection we remove the editor
Packit 1e8aac
   * that the user is trying to type into.
Packit 1e8aac
   */
Packit 1e8aac
  if (!sel)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_block_by_func (inspector->priv->project,
Packit 1e8aac
                                   G_CALLBACK (project_selection_changed_cb),
Packit 1e8aac
                                   inspector);
Packit 1e8aac
Packit 1e8aac
  glade_project_selection_clear (inspector->priv->project, FALSE);
Packit 1e8aac
  for (l = sel; l; l = l->next)
Packit 1e8aac
    glade_project_selection_add (inspector->priv->project, G_OBJECT (l->data), FALSE);
Packit 1e8aac
  glade_project_selection_changed (inspector->priv->project);
Packit 1e8aac
  g_list_free (sel);
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_unblock_by_func (inspector->priv->project,
Packit 1e8aac
                                     G_CALLBACK (project_selection_changed_cb),
Packit 1e8aac
                                     inspector);
Packit 1e8aac
Packit 1e8aac
  g_signal_emit (inspector, glade_inspector_signals[SELECTION_CHANGED], 0);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
item_activated_cb (GtkTreeView       *view,
Packit 1e8aac
                   GtkTreePath       *path,
Packit 1e8aac
                   GtkTreeViewColumn *column,
Packit 1e8aac
                   GladeInspector    *inspector)
Packit 1e8aac
{
Packit 1e8aac
  g_signal_emit (inspector, glade_inspector_signals[ITEM_ACTIVATED], 0);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gint
Packit 1e8aac
button_press_cb (GtkWidget      *widget,
Packit 1e8aac
                 GdkEventButton *event,
Packit 1e8aac
                 GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GtkTreeView *view = GTK_TREE_VIEW (widget);
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
  GtkTreePath *path = NULL;
Packit 1e8aac
  gboolean handled = FALSE;
Packit 1e8aac
Packit 1e8aac
  /* Give some kind of access in case of missing right button */
Packit 1e8aac
  if (event->window == gtk_tree_view_get_bin_window (view) &&
Packit 1e8aac
      glade_popup_is_popup_event (event))
Packit 1e8aac
    {
Packit 1e8aac
      if (gtk_tree_view_get_path_at_pos (view, (gint) event->x, (gint) event->y,
Packit 1e8aac
                                         &path, NULL,
Packit 1e8aac
                                         NULL, NULL) && path != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          GtkTreeIter iter;
Packit 1e8aac
          GladeWidget *object = NULL;
Packit 1e8aac
          if (gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->project),
Packit 1e8aac
                                       &iter, path))
Packit 1e8aac
            {
Packit 1e8aac
              /* now we can obtain the widget from the iter.
Packit 1e8aac
               */
Packit 1e8aac
              gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
Packit 1e8aac
                                  GLADE_PROJECT_MODEL_COLUMN_OBJECT, &object,
Packit 1e8aac
                                  -1);
Packit 1e8aac
Packit 1e8aac
              if (widget != NULL)
Packit 1e8aac
                glade_popup_widget_pop (glade_widget_get_from_gobject (object),
Packit 1e8aac
                                        event, TRUE);
Packit 1e8aac
              else
Packit 1e8aac
                glade_popup_simple_pop (priv->project, event);
Packit 1e8aac
Packit 1e8aac
              handled = TRUE;
Packit 1e8aac
Packit 1e8aac
              gtk_tree_path_free (path);
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
      else
Packit 1e8aac
        {
Packit 1e8aac
          glade_popup_simple_pop (priv->project, event);
Packit 1e8aac
          handled = TRUE;
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
  return handled;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_warning_cell_data_func (GtkTreeViewColumn *column,
Packit 1e8aac
					GtkCellRenderer   *renderer,
Packit 1e8aac
					GtkTreeModel      *model,
Packit 1e8aac
					GtkTreeIter       *iter,
Packit 1e8aac
					gpointer           data)
Packit 1e8aac
{
Packit 1e8aac
  gchar *warning = NULL;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_get (model, iter,
Packit 1e8aac
		      GLADE_PROJECT_MODEL_COLUMN_WARNING, &warning,
Packit 1e8aac
		      -1);
Packit 1e8aac
Packit 1e8aac
  g_object_set (renderer, "visible", warning != NULL, NULL);
Packit 1e8aac
Packit 1e8aac
  g_free (warning);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_name_cell_data_func (GtkTreeViewColumn *column,
Packit 1e8aac
				     GtkCellRenderer   *renderer,
Packit 1e8aac
				     GtkTreeModel      *model,
Packit 1e8aac
				     GtkTreeIter       *iter,
Packit 1e8aac
				     gpointer           data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget *gwidget;
Packit 1e8aac
  GObject *obj;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_get (model, iter,
Packit 1e8aac
		      GLADE_PROJECT_MODEL_COLUMN_OBJECT, &obj,
Packit 1e8aac
		      -1);
Packit 1e8aac
Packit 1e8aac
  gwidget = glade_widget_get_from_gobject (obj);
Packit 1e8aac
Packit 1e8aac
  g_object_set (renderer, "text", 
Packit 1e8aac
		(glade_widget_has_name (gwidget)) ? 
Packit 1e8aac
		  glade_widget_get_display_name (gwidget) : NULL,
Packit 1e8aac
		NULL);
Packit 1e8aac
Packit 1e8aac
  g_object_unref (obj);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_inspector_detail_cell_data_func (GtkTreeViewColumn *column,
Packit 1e8aac
				       GtkCellRenderer   *renderer,
Packit 1e8aac
				       GtkTreeModel      *model,
Packit 1e8aac
				       GtkTreeIter       *iter,
Packit 1e8aac
				       gpointer           data)
Packit 1e8aac
{
Packit 1e8aac
  gchar *type_name = NULL, *detail = NULL;
Packit 1e8aac
Packit 1e8aac
  gtk_tree_model_get (model, iter,
Packit 1e8aac
		      GLADE_PROJECT_MODEL_COLUMN_TYPE_NAME, &type_name,
Packit 1e8aac
		      GLADE_PROJECT_MODEL_COLUMN_MISC, &detail,
Packit 1e8aac
		      -1);
Packit 1e8aac
Packit 1e8aac
  if (detail)
Packit 1e8aac
    {
Packit 1e8aac
      gchar *final = g_strconcat (type_name, "  ", detail, NULL);
Packit 1e8aac
Packit 1e8aac
      g_object_set (renderer, "text", final, NULL);
Packit 1e8aac
Packit 1e8aac
      g_free (final);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
      g_object_set (renderer, "text", type_name, NULL);
Packit 1e8aac
Packit 1e8aac
  g_free (type_name);
Packit 1e8aac
  g_free (detail);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
add_columns (GtkTreeView *view)
Packit 1e8aac
{
Packit 1e8aac
  GtkTreeViewColumn *column;
Packit 1e8aac
  GtkCellRenderer *renderer;
Packit 1e8aac
  GtkCellAreaBox *box;
Packit 1e8aac
Packit 1e8aac
  /* Use a GtkCellArea box to set the alignments manually */
Packit 1e8aac
  box = (GtkCellAreaBox *)gtk_cell_area_box_new ();
Packit 1e8aac
Packit 1e8aac
  column = gtk_tree_view_column_new_with_area (GTK_CELL_AREA (box));
Packit 1e8aac
  gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
Packit 1e8aac
  gtk_cell_area_box_set_spacing (GTK_CELL_AREA_BOX (box), 2);
Packit 1e8aac
Packit 1e8aac
  gtk_tree_view_set_tooltip_column (view, GLADE_PROJECT_MODEL_COLUMN_WARNING);
Packit 1e8aac
Packit 1e8aac
  /* Padding */
Packit 1e8aac
  renderer = gtk_cell_renderer_text_new ();
Packit 1e8aac
  g_object_set (G_OBJECT (renderer), "width", 4, NULL);
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
Packit 1e8aac
  /* Warning cell */
Packit 1e8aac
  renderer = gtk_cell_renderer_pixbuf_new ();
Packit 1e8aac
  g_object_set (renderer,
Packit 1e8aac
		"stock-id", "gtk-dialog-warning",
Packit 1e8aac
		"xpad", 2,
Packit 1e8aac
		NULL);
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
  gtk_tree_view_column_set_cell_data_func (column, renderer,
Packit 1e8aac
					   glade_inspector_warning_cell_data_func,
Packit 1e8aac
					   NULL, NULL);
Packit 1e8aac
Packit 1e8aac
  /* Class Icon */
Packit 1e8aac
  renderer = gtk_cell_renderer_pixbuf_new ();
Packit 1e8aac
  g_object_set (renderer,
Packit 1e8aac
		"xpad", 2,
Packit 1e8aac
		NULL);
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
  gtk_tree_view_column_set_attributes (column,
Packit 1e8aac
                                       renderer,
Packit 1e8aac
                                       "icon_name",
Packit 1e8aac
                                       GLADE_PROJECT_MODEL_COLUMN_ICON_NAME,
Packit 1e8aac
                                       NULL);
Packit 1e8aac
Packit 1e8aac
  /* Widget Name */
Packit 1e8aac
  renderer = gtk_cell_renderer_text_new ();
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
  gtk_tree_view_column_set_attributes (column,
Packit 1e8aac
                                       renderer,
Packit 1e8aac
                                       "text", GLADE_PROJECT_MODEL_COLUMN_NAME,
Packit 1e8aac
                                       NULL);
Packit 1e8aac
  gtk_tree_view_column_set_cell_data_func (column, renderer,
Packit 1e8aac
					   glade_inspector_name_cell_data_func,
Packit 1e8aac
					   NULL, NULL);
Packit 1e8aac
Packit 1e8aac
  /* Padding */
Packit 1e8aac
  renderer = gtk_cell_renderer_text_new ();
Packit 1e8aac
  g_object_set (G_OBJECT (renderer), "width", 8, NULL);
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
Packit 1e8aac
  /* Class name & detail */
Packit 1e8aac
  renderer = gtk_cell_renderer_text_new ();
Packit 1e8aac
  g_object_set (G_OBJECT (renderer),
Packit 1e8aac
                "style", PANGO_STYLE_ITALIC,
Packit 1e8aac
		"foreground", "Gray",
Packit 1e8aac
		"ellipsize", PANGO_ELLIPSIZE_END,
Packit 1e8aac
		NULL);
Packit 1e8aac
Packit 1e8aac
  gtk_cell_area_box_pack_start (box, renderer, FALSE, FALSE, FALSE);
Packit 1e8aac
  gtk_tree_view_column_set_cell_data_func (column, renderer,
Packit 1e8aac
					   glade_inspector_detail_cell_data_func,
Packit 1e8aac
					   NULL, NULL);
Packit 1e8aac
Packit 1e8aac
  gtk_tree_view_append_column (view, column);
Packit 1e8aac
  gtk_tree_view_set_headers_visible (view, FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
disconnect_project_signals (GladeInspector *inspector, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (G_OBJECT (project),
Packit 1e8aac
                                        G_CALLBACK
Packit 1e8aac
                                        (project_selection_changed_cb),
Packit 1e8aac
                                        inspector);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
connect_project_signals (GladeInspector *inspector, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "selection-changed",
Packit 1e8aac
                    G_CALLBACK (project_selection_changed_cb), inspector);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_inspector_set_project:
Packit 1e8aac
 * @inspector: a #GladeInspector
Packit 1e8aac
 * @project: a #GladeProject
Packit 1e8aac
 *
Packit 1e8aac
 * Sets the current project of @inspector to @project. To unset the current
Packit 1e8aac
 * project, pass %NULL for @project.
Packit 1e8aac
 */
Packit 1e8aac
void
Packit 1e8aac
glade_inspector_set_project (GladeInspector *inspector, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  g_return_if_fail (GLADE_IS_INSPECTOR (inspector));
Packit 1e8aac
  g_return_if_fail (GLADE_IS_PROJECT (project) || project == NULL);
Packit 1e8aac
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  if(priv->project == project)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  if (inspector->priv->project)
Packit 1e8aac
    {
Packit 1e8aac
      disconnect_project_signals (inspector, inspector->priv->project);
Packit 1e8aac
Packit 1e8aac
      /* Release our filter which releases the project */
Packit 1e8aac
      gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view), NULL);
Packit 1e8aac
      priv->filter = NULL;
Packit 1e8aac
      priv->project = NULL;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (project)
Packit 1e8aac
    {
Packit 1e8aac
      priv->project = project;
Packit 1e8aac
Packit 1e8aac
      /* The filter holds our reference to 'project' */
Packit 1e8aac
      priv->filter =
Packit 1e8aac
          gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->project), NULL);
Packit 1e8aac
Packit 1e8aac
      gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER
Packit 1e8aac
                                              (priv->filter),
Packit 1e8aac
                                              (GtkTreeModelFilterVisibleFunc)
Packit 1e8aac
                                              glade_inspector_visible_func,
Packit 1e8aac
                                              inspector, NULL);
Packit 1e8aac
Packit 1e8aac
      gtk_tree_view_set_model (GTK_TREE_VIEW (priv->view), priv->filter);
Packit 1e8aac
      g_object_unref (priv->filter);    /* pass ownership of the filter to the model */
Packit 1e8aac
Packit 1e8aac
      connect_project_signals (inspector, project);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_object_notify_by_pspec (G_OBJECT (inspector), properties[PROP_PROJECT]);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_inspector_get_project:
Packit 1e8aac
 * @inspector: a #GladeInspector
Packit 1e8aac
 * 
Packit 1e8aac
 * Note that the method does not ref the returned #GladeProject. 
Packit 1e8aac
 *
Packit 1e8aac
 * Returns: A #GladeProject
Packit 1e8aac
 */
Packit 1e8aac
GladeProject *
Packit 1e8aac
glade_inspector_get_project (GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  g_return_val_if_fail (GLADE_IS_INSPECTOR (inspector), NULL);
Packit 1e8aac
Packit 1e8aac
  return inspector->priv->project;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_inspector_get_selected_items:
Packit 1e8aac
 * @inspector: a #GladeInspector
Packit 1e8aac
 * 
Packit 1e8aac
 * Returns the selected items in the inspector. 
Packit 1e8aac
 *
Packit 1e8aac
 * Returns: A #GList
Packit 1e8aac
 */
Packit 1e8aac
GList *
Packit 1e8aac
glade_inspector_get_selected_items (GladeInspector *inspector)
Packit 1e8aac
{
Packit 1e8aac
  GtkTreeSelection *selection;
Packit 1e8aac
  GList *items = NULL, *paths;
Packit 1e8aac
  GladeInspectorPrivate *priv = inspector->priv;
Packit 1e8aac
Packit 1e8aac
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->view));
Packit 1e8aac
Packit 1e8aac
  for (paths = gtk_tree_selection_get_selected_rows (selection, NULL);
Packit 1e8aac
       paths != NULL; paths = g_list_next (paths->next))
Packit 1e8aac
    {
Packit 1e8aac
      GtkTreeIter filter_iter;
Packit 1e8aac
      GtkTreeIter iter;
Packit 1e8aac
      GtkTreePath *path = (GtkTreePath *) paths->data;
Packit 1e8aac
      GObject *object = NULL;
Packit 1e8aac
Packit 1e8aac
      gtk_tree_model_get_iter (priv->filter, &filter_iter, path);
Packit 1e8aac
      gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER
Packit 1e8aac
                                                        (priv->filter), &iter,
Packit 1e8aac
                                                        &filter_iter);
Packit 1e8aac
      gtk_tree_model_get (GTK_TREE_MODEL (priv->project), &iter,
Packit 1e8aac
                          GLADE_PROJECT_MODEL_COLUMN_OBJECT, &object, -1);
Packit 1e8aac
Packit 1e8aac
      g_object_unref (object);
Packit 1e8aac
      items = g_list_prepend (items, glade_widget_get_from_gobject (object));
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
Packit 1e8aac
  g_list_free (paths);
Packit 1e8aac
Packit 1e8aac
  return items;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_inspector_new:
Packit 1e8aac
 * 
Packit 1e8aac
 * Creates a new #GladeInspector
Packit 1e8aac
 * 
Packit 1e8aac
 * Returns: a new #GladeInspector
Packit 1e8aac
 */
Packit 1e8aac
GtkWidget *
Packit 1e8aac
glade_inspector_new (void)
Packit 1e8aac
{
Packit 1e8aac
  return g_object_new (GLADE_TYPE_INSPECTOR, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_inspector_new_with_project:
Packit 1e8aac
 * @project: a #GladeProject
Packit 1e8aac
 *
Packit 1e8aac
 * Creates a new #GladeInspector with @project
Packit 1e8aac
 * 
Packit 1e8aac
 * Returns: a new #GladeInspector
Packit 1e8aac
 */
Packit 1e8aac
GtkWidget *
Packit 1e8aac
glade_inspector_new_with_project (GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeInspector *inspector;
Packit 1e8aac
  g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
Packit 1e8aac
Packit 1e8aac
  inspector = g_object_new (GLADE_TYPE_INSPECTOR, "project", project, NULL);
Packit 1e8aac
Packit 1e8aac
  /* Make sure we expended to the right path */
Packit 1e8aac
  project_selection_changed_cb (project, inspector);
Packit 1e8aac
Packit 1e8aac
  return GTK_WIDGET (inspector);
Packit 1e8aac
}