Blame gladeui/glade-app.c

Packit 1e8aac
/*
Packit 1e8aac
 * Copyright (C) 2001 Ximian, Inc.
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
Packit 1e8aac
 * published by the Free Software Foundation; either version 2 of the
Packit 1e8aac
 * License, or (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
 * Authors:
Packit 1e8aac
 *   Naba Kumar <naba@gnome.org>
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include <config.h>
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * SECTION:glade-app
Packit 1e8aac
 * @Short_Description: The central control point of the Glade core.
Packit 1e8aac
 *
Packit 1e8aac
 * This main control object is where we try to draw the line between
Packit 1e8aac
 * what is the Glade core and what is the main application. The main
Packit 1e8aac
 * application must derive from the GladeApp object and create an instance
Packit 1e8aac
 * to initialize the Glade core.
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include "glade.h"
Packit 1e8aac
#include "glade-debug.h"
Packit 1e8aac
#include "glade-cursor.h"
Packit 1e8aac
#include "glade-catalog.h"
Packit 1e8aac
#include "glade-design-view.h"
Packit 1e8aac
#include "glade-design-layout.h"
Packit 1e8aac
#include "glade-marshallers.h"
Packit 1e8aac
#include "glade-accumulators.h"
Packit 1e8aac
Packit 1e8aac
#include <string.h>
Packit 1e8aac
#include <glib.h>
Packit 1e8aac
#include <glib/gstdio.h>
Packit 1e8aac
#include <glib/gi18n-lib.h>
Packit 1e8aac
#include <gdk/gdkkeysyms.h>
Packit 1e8aac
#include <gtk/gtk.h>
Packit 1e8aac
Packit 1e8aac
#ifdef MAC_INTEGRATION
Packit 1e8aac
#  include <gtkosxapplication.h>
Packit 1e8aac
#endif
Packit 1e8aac
Packit 1e8aac
#define GLADE_CONFIG_FILENAME "glade.conf"
Packit 1e8aac
Packit 1e8aac
enum
Packit 1e8aac
{
Packit 1e8aac
  DOC_SEARCH,
Packit 1e8aac
  SIGNAL_EDITOR_CREATED,
Packit 1e8aac
  WIDGET_ADAPTOR_REGISTERED,
Packit 1e8aac
  LAST_SIGNAL
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
struct _GladeAppPrivate
Packit 1e8aac
{
Packit 1e8aac
  GtkWidget *window;
Packit 1e8aac
Packit 1e8aac
  GladeClipboard *clipboard;    /* See glade-clipboard */
Packit 1e8aac
  GList *catalogs;              /* See glade-catalog */
Packit 1e8aac
Packit 1e8aac
  GList *projects;              /* The list of Projects */
Packit 1e8aac
Packit 1e8aac
  GKeyFile *config;             /* The configuration file */
Packit 1e8aac
Packit 1e8aac
  GtkAccelGroup *accel_group;   /* Default acceleration group for this app */
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
static guint glade_app_signals[LAST_SIGNAL] = { 0 };
Packit 1e8aac
Packit 1e8aac
/* installation paths */
Packit 1e8aac
static gchar *catalogs_dir = NULL;
Packit 1e8aac
static gchar *modules_dir = NULL;
Packit 1e8aac
static gchar *pixmaps_dir = NULL;
Packit 1e8aac
static gchar *locale_dir = NULL;
Packit 1e8aac
static gchar *bin_dir = NULL;
Packit 1e8aac
static gchar *lib_dir = NULL;
Packit 1e8aac
Packit 1e8aac
static GladeApp *singleton_app = NULL;
Packit 1e8aac
static gboolean check_initialised = FALSE;
Packit 1e8aac
Packit 1e8aac
G_DEFINE_TYPE_WITH_PRIVATE (GladeApp, glade_app, G_TYPE_OBJECT);
Packit 1e8aac
Packit 1e8aac
/*****************************************************************
Packit 1e8aac
 *                    GObjectClass                               *
Packit 1e8aac
 *****************************************************************/
Packit 1e8aac
static GObject *
Packit 1e8aac
glade_app_constructor (GType                  type,
Packit 1e8aac
                       guint                  n_construct_properties,
Packit 1e8aac
                       GObjectConstructParam *construct_properties)
Packit 1e8aac
{
Packit 1e8aac
  GObject *object;
Packit 1e8aac
Packit 1e8aac
  /* singleton */
Packit 1e8aac
  if (!singleton_app)
Packit 1e8aac
    {
Packit 1e8aac
      object = G_OBJECT_CLASS (glade_app_parent_class)->constructor (type,
Packit 1e8aac
                                                                     n_construct_properties,
Packit 1e8aac
                                                                     construct_properties);
Packit 1e8aac
      singleton_app = GLADE_APP (object);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      g_object_ref (singleton_app);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return G_OBJECT (singleton_app);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_app_dispose (GObject *app)
Packit 1e8aac
{
Packit 1e8aac
  GladeAppPrivate *priv = GLADE_APP (app)->priv;
Packit 1e8aac
Packit 1e8aac
  if (priv->clipboard)
Packit 1e8aac
    {
Packit 1e8aac
      g_object_unref (priv->clipboard);
Packit 1e8aac
      priv->clipboard = NULL;
Packit 1e8aac
    }
Packit 1e8aac
  /* FIXME: Remove projects */
Packit 1e8aac
Packit 1e8aac
  if (priv->config)
Packit 1e8aac
    {
Packit 1e8aac
      g_key_file_free (priv->config);
Packit 1e8aac
      priv->config = NULL;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_app_parent_class)->dispose (app);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_app_finalize (GObject *app)
Packit 1e8aac
{
Packit 1e8aac
  g_free (catalogs_dir);
Packit 1e8aac
  g_free (modules_dir);
Packit 1e8aac
  g_free (pixmaps_dir);
Packit 1e8aac
  g_free (locale_dir);
Packit 1e8aac
  g_free (bin_dir);
Packit 1e8aac
  g_free (lib_dir);
Packit 1e8aac
Packit 1e8aac
  singleton_app = NULL;
Packit 1e8aac
  check_initialised = FALSE;
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_app_parent_class)->finalize (app);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/* build package paths at runtime */
Packit 1e8aac
static void
Packit 1e8aac
build_package_paths (void)
Packit 1e8aac
{
Packit 1e8aac
  const gchar *path;
Packit 1e8aac
Packit 1e8aac
  path = g_getenv (GLADE_ENV_PIXMAP_DIR);
Packit 1e8aac
  if (path)
Packit 1e8aac
    pixmaps_dir = g_strdup (path);
Packit 1e8aac
Packit 1e8aac
#if defined (G_OS_WIN32) || (defined (MAC_INTEGRATION) && defined (MAC_BUNDLE))
Packit 1e8aac
  gchar *prefix;
Packit 1e8aac
Packit 1e8aac
# ifdef G_OS_WIN32
Packit 1e8aac
  prefix = g_win32_get_package_installation_directory_of_module (NULL);
Packit 1e8aac
Packit 1e8aac
# else // defined (MAC_INTEGRATION) && defined (MAC_BUNDLE)
Packit 1e8aac
  prefix = quartz_application_get_resource_path ();
Packit 1e8aac
Packit 1e8aac
# endif
Packit 1e8aac
Packit 1e8aac
  if (!pixmaps_dir)
Packit 1e8aac
    pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL);
Packit 1e8aac
Packit 1e8aac
  catalogs_dir = g_build_filename (prefix, "share", PACKAGE, "catalogs", NULL);
Packit 1e8aac
  modules_dir = g_build_filename (prefix, "lib", PACKAGE, "modules", NULL);
Packit 1e8aac
  locale_dir = g_build_filename (prefix, "share", "locale", NULL);
Packit 1e8aac
  bin_dir = g_build_filename (prefix, "bin", NULL);
Packit 1e8aac
  lib_dir = g_build_filename (prefix, "lib", NULL);
Packit 1e8aac
Packit 1e8aac
  g_free (prefix);
Packit 1e8aac
#else
Packit 1e8aac
  catalogs_dir = g_strdup (GLADE_CATALOGSDIR);
Packit 1e8aac
  modules_dir = g_strdup (GLADE_MODULESDIR);
Packit 1e8aac
Packit 1e8aac
  if (!pixmaps_dir)
Packit 1e8aac
    pixmaps_dir = g_strdup (GLADE_PIXMAPSDIR);
Packit 1e8aac
  locale_dir = g_strdup (GLADE_LOCALEDIR);
Packit 1e8aac
  bin_dir = g_strdup (GLADE_BINDIR);
Packit 1e8aac
  lib_dir = g_strdup (GLADE_LIBDIR);
Packit 1e8aac
#endif
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/* initialization function for libgladeui (not GladeApp) */
Packit 1e8aac
static void
Packit 1e8aac
glade_init_check (void)
Packit 1e8aac
{
Packit 1e8aac
  if (check_initialised)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  glade_init_debug_flags ();
Packit 1e8aac
Packit 1e8aac
  /* Make sure path accessors work on osx */
Packit 1e8aac
  build_package_paths ();
Packit 1e8aac
Packit 1e8aac
  bindtextdomain (GETTEXT_PACKAGE, locale_dir);
Packit 1e8aac
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Packit 1e8aac
Packit 1e8aac
  check_initialised = TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/*****************************************************************
Packit 1e8aac
 *                    GladeAppClass                              *
Packit 1e8aac
 *****************************************************************/
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_catalogs_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return catalogs_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_modules_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return modules_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_pixmaps_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return pixmaps_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_locale_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return locale_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_bin_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return bin_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
const gchar *
Packit 1e8aac
glade_app_get_lib_dir (void)
Packit 1e8aac
{
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  return lib_dir;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
pointer_mode_register_icon (const gchar     *icon_name,
Packit 1e8aac
                            gint             real_size,
Packit 1e8aac
                            GladePointerMode mode,
Packit 1e8aac
                            GtkIconSize      size)
Packit 1e8aac
{
Packit 1e8aac
  GdkPixbuf *pixbuf;
Packit 1e8aac
Packit 1e8aac
  if ((pixbuf = glade_utils_pointer_mode_render_icon (mode, size)))
Packit 1e8aac
    {
Packit 1e8aac
      gtk_icon_theme_add_builtin_icon (icon_name, real_size, pixbuf);
Packit 1e8aac
      g_object_unref (pixbuf);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
register_icon (const gchar    *new_icon_name,
Packit 1e8aac
               gint            size,
Packit 1e8aac
               const gchar    *icon_name,
Packit 1e8aac
               const gchar    *file_name)
Packit 1e8aac
{
Packit 1e8aac
  GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
Packit 1e8aac
  GdkPixbuf *pixbuf;
Packit 1e8aac
  GtkIconInfo *info;
Packit 1e8aac
Packit 1e8aac
  if ((info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size, 0)))
Packit 1e8aac
    {
Packit 1e8aac
      pixbuf = gtk_icon_info_load_icon (info, NULL);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      gchar *path = g_build_filename (glade_app_get_pixmaps_dir (), file_name, NULL);
Packit 1e8aac
      pixbuf = gdk_pixbuf_new_from_file (path, NULL);
Packit 1e8aac
      g_free (path);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (pixbuf)
Packit 1e8aac
    {
Packit 1e8aac
      gtk_icon_theme_add_builtin_icon (new_icon_name, size, pixbuf);
Packit 1e8aac
      g_object_unref (pixbuf);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/*
Packit 1e8aac
 * glade_app_register_icon_names:
Packit 1e8aac
 * @size: icon size
Packit 1e8aac
 *
Packit 1e8aac
 * Register a new icon name for most of GladePointerMode.
Packit 1e8aac
 * After calling this function "glade-selector", "glade-drag-resize",
Packit 1e8aac
 * "glade-margin-edit" and "glade-align-edit" icon names will be available.
Packit 1e8aac
 */ 
Packit 1e8aac
static void
Packit 1e8aac
glade_app_register_icon_names (GtkIconSize size)
Packit 1e8aac
{
Packit 1e8aac
  gint w, h, real_size;
Packit 1e8aac
Packit 1e8aac
  if (gtk_icon_size_lookup (size, &w, &h) == FALSE)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  real_size = MIN (w, h);
Packit 1e8aac
Packit 1e8aac
  pointer_mode_register_icon ("glade-selector", real_size, GLADE_POINTER_SELECT, size);
Packit 1e8aac
  pointer_mode_register_icon ("glade-drag-resize", real_size, GLADE_POINTER_DRAG_RESIZE, size);
Packit 1e8aac
  pointer_mode_register_icon ("glade-margin-edit", real_size, GLADE_POINTER_MARGIN_EDIT, size);
Packit 1e8aac
  pointer_mode_register_icon ("glade-align-edit", real_size, GLADE_POINTER_ALIGN_EDIT, size);
Packit 1e8aac
Packit 1e8aac
  register_icon ("glade-devhelp", real_size,
Packit 1e8aac
                 GLADE_DEVHELP_ICON_NAME,
Packit 1e8aac
                 GLADE_DEVHELP_FALLBACK_ICON_FILE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_init:
Packit 1e8aac
 * 
Packit 1e8aac
 * Initialization function for libgladeui (not #GladeApp)
Packit 1e8aac
 * It builds paths, bind text domain, and register icons
Packit 1e8aac
 */
Packit 1e8aac
void
Packit 1e8aac
glade_init (void)
Packit 1e8aac
{
Packit 1e8aac
  static gboolean init = FALSE;
Packit 1e8aac
Packit 1e8aac
  if (init) return;
Packit 1e8aac
  
Packit 1e8aac
  glade_init_check ();
Packit 1e8aac
Packit 1e8aac
  /* Register icons needed by the UI */
Packit 1e8aac
  glade_app_register_icon_names (GTK_ICON_SIZE_LARGE_TOOLBAR);
Packit 1e8aac
  
Packit 1e8aac
  init = TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_app_init (GladeApp *app)
Packit 1e8aac
{
Packit 1e8aac
  static gboolean initialized = FALSE;
Packit 1e8aac
  GladeAppPrivate *priv = app->priv = glade_app_get_instance_private (app);
Packit 1e8aac
Packit 1e8aac
  singleton_app = app;
Packit 1e8aac
Packit 1e8aac
  glade_init ();
Packit 1e8aac
Packit 1e8aac
  if (!initialized)
Packit 1e8aac
    {
Packit 1e8aac
      GtkIconTheme *default_icon_theme = gtk_icon_theme_get_default ();
Packit 1e8aac
      const gchar *path;
Packit 1e8aac
Packit 1e8aac
      gtk_icon_theme_append_search_path (default_icon_theme, pixmaps_dir);
Packit 1e8aac
Packit 1e8aac
      /* Handle extra icon theme paths. Needed for tests to work */
Packit 1e8aac
      if ((path = g_getenv (GLADE_ENV_ICON_THEME_PATH)))
Packit 1e8aac
        {
Packit 1e8aac
          gchar **tokens = g_strsplit (path, ":", -1);
Packit 1e8aac
          gint i;
Packit 1e8aac
Packit 1e8aac
          for (i = 0; tokens[i]; i++)
Packit 1e8aac
            gtk_icon_theme_append_search_path (default_icon_theme, tokens[i]);
Packit 1e8aac
Packit 1e8aac
          g_strfreev (tokens);
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      glade_cursor_init ();
Packit 1e8aac
Packit 1e8aac
      initialized = TRUE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  priv->accel_group = NULL;
Packit 1e8aac
Packit 1e8aac
  /* Initialize app objects */
Packit 1e8aac
  priv->catalogs = (GList *) glade_catalog_load_all ();
Packit 1e8aac
Packit 1e8aac
  /* Create clipboard */
Packit 1e8aac
  priv->clipboard = glade_clipboard_new ();
Packit 1e8aac
Packit 1e8aac
  /* Load the configuration file */
Packit 1e8aac
  priv->config = g_key_file_ref (glade_app_get_config ());
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_app_event_handler (GdkEvent *event, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  if (glade_app_do_event (event)) return;
Packit 1e8aac
Packit 1e8aac
  gtk_main_do_event (event);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_app_class_init (GladeAppClass *klass)
Packit 1e8aac
{
Packit 1e8aac
  GObjectClass *object_class;
Packit 1e8aac
	
Packit 1e8aac
  object_class = G_OBJECT_CLASS (klass);
Packit 1e8aac
Packit 1e8aac
  object_class->constructor = glade_app_constructor;
Packit 1e8aac
  object_class->dispose = glade_app_dispose;
Packit 1e8aac
  object_class->finalize = glade_app_finalize;
Packit 1e8aac
Packit 1e8aac
  /**
Packit 1e8aac
   * GladeApp::doc-search:
Packit 1e8aac
   * @gladeeditor: the #GladeEditor which received the signal.
Packit 1e8aac
   * @arg1: the (#gchar *) book to search or %NULL
Packit 1e8aac
   * @arg2: the (#gchar *) page to search or %NULL
Packit 1e8aac
   * @arg3: the (#gchar *) search string or %NULL
Packit 1e8aac
   *
Packit 1e8aac
   * Emitted when the glade core requests that a doc-search be performed.
Packit 1e8aac
   */
Packit 1e8aac
  glade_app_signals[DOC_SEARCH] =
Packit 1e8aac
      g_signal_new ("doc-search",
Packit 1e8aac
                    G_TYPE_FROM_CLASS (object_class),
Packit 1e8aac
                    G_SIGNAL_RUN_LAST, 0, NULL, NULL,
Packit 1e8aac
                    _glade_marshal_VOID__STRING_STRING_STRING,
Packit 1e8aac
                    G_TYPE_NONE, 3,
Packit 1e8aac
                    G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
Packit 1e8aac
Packit 1e8aac
  /**
Packit 1e8aac
   * GladeApp::signal-editor-created:
Packit 1e8aac
   * @gladeapp: the #GladeApp which received the signal.
Packit 1e8aac
   * @signal_editor: the new #GladeSignalEditor.
Packit 1e8aac
   *
Packit 1e8aac
   * Emitted when a new signal editor created.
Packit 1e8aac
   * A tree view is created in the default handler.
Packit 1e8aac
   * Connect your handler before the default handler for setting a custom column or renderer
Packit 1e8aac
   * and after it for connecting to the tree view signals
Packit 1e8aac
   */
Packit 1e8aac
  glade_app_signals[SIGNAL_EDITOR_CREATED] =
Packit 1e8aac
    g_signal_new ("signal-editor-created",
Packit 1e8aac
                  G_TYPE_FROM_CLASS (object_class),
Packit 1e8aac
                  G_SIGNAL_RUN_LAST,
Packit 1e8aac
                  0, NULL, NULL,
Packit 1e8aac
                  _glade_marshal_VOID__OBJECT,
Packit 1e8aac
                  G_TYPE_NONE, 1, G_TYPE_OBJECT);  
Packit 1e8aac
Packit 1e8aac
  /**
Packit 1e8aac
   * GladeApp::widget-adaptor-registered:
Packit 1e8aac
   * @gladeapp: the #GladeApp which received the signal.
Packit 1e8aac
   * @adaptor: the newlly registered #GladeWidgetAdaptor.
Packit 1e8aac
   *
Packit 1e8aac
   * Emitted when a new widget adaptor is registered.
Packit 1e8aac
   */
Packit 1e8aac
  glade_app_signals[WIDGET_ADAPTOR_REGISTERED] =
Packit 1e8aac
    g_signal_new ("widget-adaptor-registered",
Packit 1e8aac
                  G_TYPE_FROM_CLASS (object_class),
Packit 1e8aac
                  G_SIGNAL_RUN_LAST,
Packit 1e8aac
                  0, NULL, NULL,
Packit 1e8aac
                  _glade_marshal_VOID__OBJECT,
Packit 1e8aac
                  G_TYPE_NONE, 1, G_TYPE_OBJECT);
Packit 1e8aac
Packit 1e8aac
  gdk_event_handler_set (glade_app_event_handler, NULL, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/*****************************************************************
Packit 1e8aac
 *                       Public API                              *
Packit 1e8aac
 *****************************************************************/
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_app_do_event:
Packit 1e8aac
 * @event: the event to process.
Packit 1e8aac
 *
Packit 1e8aac
 * This function has to be called in an event handler for widget selection to work.
Packit 1e8aac
 * See gdk_event_handler_set()
Packit 1e8aac
 *
Packit 1e8aac
 * Returns: true if the event was handled.
Packit 1e8aac
 */ 
Packit 1e8aac
gboolean
Packit 1e8aac
glade_app_do_event (GdkEvent *event)
Packit 1e8aac
{
Packit 1e8aac
  GdkWindow *window = event->any.window;
Packit 1e8aac
  GtkWidget *layout;
Packit 1e8aac
  gpointer widget;
Packit 1e8aac
Packit 1e8aac
  if (window == NULL) return FALSE;
Packit 1e8aac
    
Packit 1e8aac
  gdk_window_get_user_data (window, &widget);
Packit 1e8aac
Packit 1e8aac
  /* As a slight optimization we could replace gtk_widget_get_ancestor()
Packit 1e8aac
   * with a custom function that only iterates trought parents with windows.
Packit 1e8aac
   */
Packit 1e8aac
  if (widget && IS_GLADE_WIDGET_EVENT (event->type) &&
Packit 1e8aac
      (layout = gtk_widget_get_ancestor (widget, GLADE_TYPE_DESIGN_LAYOUT)))
Packit 1e8aac
    return _glade_design_layout_do_event (GLADE_DESIGN_LAYOUT (layout), event);
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_app_config_save
Packit 1e8aac
 *
Packit 1e8aac
 * Saves the GKeyFile to "g_get_user_config_dir()/GLADE_CONFIG_FILENAME"
Packit 1e8aac
 *
Packit 1e8aac
 * Return 0 on success.
Packit 1e8aac
 */
Packit 1e8aac
gint
Packit 1e8aac
glade_app_config_save ()
Packit 1e8aac
{
Packit 1e8aac
  GIOChannel *channel;
Packit 1e8aac
  GIOStatus status;
Packit 1e8aac
  gchar *data = NULL, *filename;
Packit 1e8aac
  const gchar *config_dir = g_get_user_config_dir ();
Packit 1e8aac
  GError *error = NULL;
Packit 1e8aac
  gsize size, written, bytes_written = 0;
Packit 1e8aac
  static gboolean error_shown = FALSE;
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
Packit 1e8aac
  /* If we had any errors; wait untill next session to retry.
Packit 1e8aac
   */
Packit 1e8aac
  if (error_shown)
Packit 1e8aac
    return -1;
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  /* Just in case... try to create the config directory */
Packit 1e8aac
  if (g_file_test (config_dir, G_FILE_TEST_IS_DIR) == FALSE)
Packit 1e8aac
    {
Packit 1e8aac
      if (g_file_test (config_dir, G_FILE_TEST_EXISTS))
Packit 1e8aac
        {
Packit 1e8aac
          /* Config dir exists but is not a directory */
Packit 1e8aac
          glade_util_ui_message
Packit 1e8aac
              (glade_app_get_window (),
Packit 1e8aac
               GLADE_UI_ERROR, NULL,
Packit 1e8aac
               _("Trying to save private data to %s directory "
Packit 1e8aac
                 "but it is a regular file.\n"
Packit 1e8aac
                 "No private data will be saved in this session"), config_dir);
Packit 1e8aac
          error_shown = TRUE;
Packit 1e8aac
          return -1;
Packit 1e8aac
        }
Packit 1e8aac
      else if (g_mkdir (config_dir, S_IRWXU) != 0)
Packit 1e8aac
        {
Packit 1e8aac
          /* Doesnt exist; failed to create */
Packit 1e8aac
          glade_util_ui_message
Packit 1e8aac
              (glade_app_get_window (),
Packit 1e8aac
               GLADE_UI_ERROR, NULL,
Packit 1e8aac
               _("Failed to create directory %s to save private data.\n"
Packit 1e8aac
                 "No private data will be saved in this session"), config_dir);
Packit 1e8aac
          error_shown = TRUE;
Packit 1e8aac
          return -1;
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  filename = g_build_filename (config_dir, GLADE_CONFIG_FILENAME, NULL);
Packit 1e8aac
Packit 1e8aac
  if ((channel = g_io_channel_new_file (filename, "w", &error)) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      if ((data =
Packit 1e8aac
           g_key_file_to_data (app->priv->config, &size, &error)) != NULL)
Packit 1e8aac
        {
Packit 1e8aac
Packit 1e8aac
          /* Implement loop here */
Packit 1e8aac
          while ((status = g_io_channel_write_chars (channel, data + bytes_written,     /* Offset of write */
Packit 1e8aac
                                                     size - bytes_written,      /* Size left to write */
Packit 1e8aac
                                                     &written,
Packit 1e8aac
                                                     &error)) !=
Packit 1e8aac
                 G_IO_STATUS_ERROR && (bytes_written + written) < size)
Packit 1e8aac
            bytes_written += written;
Packit 1e8aac
Packit 1e8aac
          if (status == G_IO_STATUS_ERROR)
Packit 1e8aac
            {
Packit 1e8aac
              glade_util_ui_message
Packit 1e8aac
                  (glade_app_get_window (),
Packit 1e8aac
                   GLADE_UI_ERROR, NULL,
Packit 1e8aac
                   _("Error writing private data to %s (%s).\n"
Packit 1e8aac
                     "No private data will be saved in this session"),
Packit 1e8aac
                   filename, error->message);
Packit 1e8aac
              error_shown = TRUE;
Packit 1e8aac
            }
Packit 1e8aac
          g_free (data);
Packit 1e8aac
        }
Packit 1e8aac
      else
Packit 1e8aac
        {
Packit 1e8aac
          glade_util_ui_message
Packit 1e8aac
              (glade_app_get_window (),
Packit 1e8aac
               GLADE_UI_ERROR, NULL,
Packit 1e8aac
               _("Error serializing configuration data to save (%s).\n"
Packit 1e8aac
                 "No private data will be saved in this session"),
Packit 1e8aac
               error->message);
Packit 1e8aac
          error_shown = TRUE;
Packit 1e8aac
        }
Packit 1e8aac
      g_io_channel_shutdown (channel, TRUE, NULL);
Packit 1e8aac
      g_io_channel_unref (channel);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      glade_util_ui_message
Packit 1e8aac
          (glade_app_get_window (),
Packit 1e8aac
           GLADE_UI_ERROR, NULL,
Packit 1e8aac
           _("Error opening %s to write private data (%s).\n"
Packit 1e8aac
             "No private data will be saved in this session"),
Packit 1e8aac
           filename, error->message);
Packit 1e8aac
      error_shown = TRUE;
Packit 1e8aac
    }
Packit 1e8aac
  g_free (filename);
Packit 1e8aac
Packit 1e8aac
  if (error)
Packit 1e8aac
    {
Packit 1e8aac
      g_error_free (error);
Packit 1e8aac
      return -1;
Packit 1e8aac
    }
Packit 1e8aac
  return 0;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeApp *
Packit 1e8aac
glade_app_get (void)
Packit 1e8aac
{
Packit 1e8aac
  if (!singleton_app)
Packit 1e8aac
    {
Packit 1e8aac
      singleton_app = glade_app_new ();
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return singleton_app;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_app_set_window (GtkWidget *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  app->priv->window = window;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeCatalog *
Packit 1e8aac
glade_app_get_catalog (const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
  GList *list;
Packit 1e8aac
  GladeCatalog *catalog;
Packit 1e8aac
Packit 1e8aac
  g_return_val_if_fail (name && name[0], NULL);
Packit 1e8aac
Packit 1e8aac
  for (list = app->priv->catalogs; list; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      catalog = list->data;
Packit 1e8aac
      if (!strcmp (glade_catalog_get_name (catalog), name))
Packit 1e8aac
        return catalog;
Packit 1e8aac
    }
Packit 1e8aac
  return NULL;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gboolean
Packit 1e8aac
glade_app_get_catalog_version (const gchar *name, gint *major, gint *minor)
Packit 1e8aac
{
Packit 1e8aac
  GladeCatalog *catalog = glade_app_get_catalog (name);
Packit 1e8aac
Packit 1e8aac
  g_return_val_if_fail (catalog != NULL, FALSE);
Packit 1e8aac
Packit 1e8aac
  if (major)
Packit 1e8aac
    *major = glade_catalog_get_major_version (catalog);
Packit 1e8aac
  if (minor)
Packit 1e8aac
    *minor = glade_catalog_get_minor_version (catalog);
Packit 1e8aac
Packit 1e8aac
  return TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GList *
Packit 1e8aac
glade_app_get_catalogs (void)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  return app->priv->catalogs;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
GtkWidget *
Packit 1e8aac
glade_app_get_window (void)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
  return app->priv->window;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeClipboard *
Packit 1e8aac
glade_app_get_clipboard (void)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
  return app->priv->clipboard;
Packit 1e8aac
}
Packit 1e8aac
/**
Packit 1e8aac
 * glade_app_get_catalogs:
Packit 1e8aac
 *
Packit 1e8aac
 * Return value: (element-type GladeCatalog): catalogs
Packit 1e8aac
 */
Packit 1e8aac
GList *
Packit 1e8aac
glade_app_get_projects (void)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app = glade_app_get ();
Packit 1e8aac
  return app->priv->projects;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GKeyFile *
Packit 1e8aac
glade_app_get_config (void)
Packit 1e8aac
{
Packit 1e8aac
  static GKeyFile *config = NULL;
Packit 1e8aac
Packit 1e8aac
  if (config == NULL)
Packit 1e8aac
    {
Packit 1e8aac
      gchar *filename = g_build_filename (g_get_user_config_dir (),
Packit 1e8aac
                                          GLADE_CONFIG_FILENAME, NULL);
Packit 1e8aac
      config = g_key_file_new ();
Packit 1e8aac
      g_key_file_load_from_file (config, filename, G_KEY_FILE_NONE, NULL);
Packit 1e8aac
      g_free (filename);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return config;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
gboolean
Packit 1e8aac
glade_app_is_project_loaded (const gchar *project_path)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
  GList *list;
Packit 1e8aac
  gboolean loaded = FALSE;
Packit 1e8aac
Packit 1e8aac
  if (project_path == NULL)
Packit 1e8aac
    return FALSE;
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  for (list = app->priv->projects; list; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *cur_project = GLADE_PROJECT (list->data);
Packit 1e8aac
Packit 1e8aac
      if ((loaded = glade_project_get_path (cur_project) &&
Packit 1e8aac
           (strcmp (glade_project_get_path (cur_project), project_path) == 0)))
Packit 1e8aac
        break;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return loaded;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_app_get_project_by_path:
Packit 1e8aac
 * @project_path: The path of an open project
Packit 1e8aac
 *
Packit 1e8aac
 * Finds an open project with @path
Packit 1e8aac
 *
Packit 1e8aac
 * Returns: A #GladeProject, or NULL if no such open project was found
Packit 1e8aac
 */
Packit 1e8aac
GladeProject *
Packit 1e8aac
glade_app_get_project_by_path (const gchar *project_path)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
  GList *l;
Packit 1e8aac
  gchar *canonical_path;
Packit 1e8aac
Packit 1e8aac
  if (project_path == NULL)
Packit 1e8aac
    return NULL;
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  canonical_path = glade_util_canonical_path (project_path);
Packit 1e8aac
Packit 1e8aac
  for (l = app->priv->projects; l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *project = (GladeProject *) l->data;
Packit 1e8aac
Packit 1e8aac
      if (glade_project_get_path (project) &&
Packit 1e8aac
          strcmp (canonical_path, glade_project_get_path (project)) == 0)
Packit 1e8aac
        {
Packit 1e8aac
          g_free (canonical_path);
Packit 1e8aac
          return project;
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (canonical_path);
Packit 1e8aac
Packit 1e8aac
  return NULL;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_app_add_project (GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (GLADE_IS_PROJECT (project));
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  /* If the project was previously loaded, don't re-load */
Packit 1e8aac
  if (g_list_find (app->priv->projects, project) != NULL)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* Take a reference for GladeApp here... */
Packit 1e8aac
  app->priv->projects = g_list_append (app->priv->projects, g_object_ref (project));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_app_remove_project (GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
  g_return_if_fail (GLADE_IS_PROJECT (project));
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  app->priv->projects = g_list_remove (app->priv->projects, project);
Packit 1e8aac
Packit 1e8aac
  /* Its safe to just release the project as the project emits a
Packit 1e8aac
   * "close" signal and everyone is responsable for cleaning up at
Packit 1e8aac
   * that point.
Packit 1e8aac
   */
Packit 1e8aac
  g_object_unref (project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/*
Packit 1e8aac
 * glade_app_set_accel_group:
Packit 1e8aac
 *
Packit 1e8aac
 * Sets @accel_group to app.
Packit 1e8aac
 * The acceleration group will made available for editor dialog windows
Packit 1e8aac
 * from the plugin backend.
Packit 1e8aac
 */
Packit 1e8aac
void
Packit 1e8aac
glade_app_set_accel_group (GtkAccelGroup *accel_group)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
  g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  app->priv->accel_group = accel_group;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GtkAccelGroup *
Packit 1e8aac
glade_app_get_accel_group (void)
Packit 1e8aac
{
Packit 1e8aac
  return glade_app_get ()->priv->accel_group;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
GladeApp *
Packit 1e8aac
glade_app_new (void)
Packit 1e8aac
{
Packit 1e8aac
  return g_object_new (GLADE_TYPE_APP, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_app_search_docs (const gchar *book,
Packit 1e8aac
		       const gchar *page, 
Packit 1e8aac
		       const gchar *search)
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
Packit 1e8aac
  app = glade_app_get ();
Packit 1e8aac
Packit 1e8aac
  g_signal_emit (G_OBJECT (app), glade_app_signals[DOC_SEARCH], 0, 
Packit 1e8aac
		 book, page, search);
Packit 1e8aac
}