Blame src/glade-window.c

Packit 1e8aac
/*
Packit 1e8aac
 * Copyright (C) 2001 Ximian, Inc.
Packit 1e8aac
 * Copyright (C) 2007 Vincent Geddes.
Packit 1e8aac
 * Copyright (C) 2012-2018 Juan Pablo Ugarte.
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
 *   Chema Celorio <chema@celorio.com>
Packit 1e8aac
 *   Paolo Borelli <pborelli@katamail.com>
Packit 1e8aac
 *   Vincent Geddes <vgeddes@gnome.org>
Packit 1e8aac
 *   Juan Pablo Ugarte <juanpablougarte@gmail.com>
Packit 1e8aac
 */
Packit 1e8aac
Packit 1e8aac
#include <config.h>
Packit 1e8aac
Packit 1e8aac
#include "glade-window.h"
Packit 1e8aac
#include "glade-resources.h"
Packit 1e8aac
#include "glade-preferences.h"
Packit 1e8aac
#include "glade-registration.h"
Packit 1e8aac
#include "glade-intro.h"
Packit 1e8aac
Packit 1e8aac
#include <gladeui/glade.h>
Packit 1e8aac
#include <gladeui/glade-popup.h>
Packit 1e8aac
#include <gladeui/glade-inspector.h>
Packit 1e8aac
#include <gladeui/glade-adaptor-chooser.h>
Packit 1e8aac
Packit 1e8aac
#include <gladeui/glade-project.h>
Packit 1e8aac
Packit 1e8aac
#include <string.h>
Packit 1e8aac
#include <glib/gstdio.h>
Packit 1e8aac
#include <glib/gi18n.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
Packit 1e8aac
#define ACTION_GROUP_STATIC             "GladeStatic"
Packit 1e8aac
#define ACTION_GROUP_PROJECT            "GladeProject"
Packit 1e8aac
#define ACTION_GROUP_PROJECTS_LIST_MENU "GladeProjectsList"
Packit 1e8aac
Packit 1e8aac
#define READONLY_INDICATOR (_("[Read Only]"))
Packit 1e8aac
Packit 1e8aac
#define URL_DEVELOPER_MANUAL "http://library.gnome.org/devel/gladeui/"
Packit 1e8aac
Packit 1e8aac
#define CONFIG_GROUP_WINDOWS        "Glade Windows"
Packit 1e8aac
#define GLADE_WINDOW_DEFAULT_WIDTH  720
Packit 1e8aac
#define GLADE_WINDOW_DEFAULT_HEIGHT 540
Packit 1e8aac
#define CONFIG_KEY_X                "x"
Packit 1e8aac
#define CONFIG_KEY_Y                "y"
Packit 1e8aac
#define CONFIG_KEY_WIDTH            "width"
Packit 1e8aac
#define CONFIG_KEY_HEIGHT           "height"
Packit 1e8aac
#define CONFIG_KEY_MAXIMIZED        "maximized"
Packit 1e8aac
Packit 1e8aac
#define CONFIG_GROUP_LOAD_SAVE      "Load and Save"
Packit 1e8aac
#define CONFIG_KEY_BACKUP           "backup"
Packit 1e8aac
#define CONFIG_KEY_AUTOSAVE         "autosave"
Packit 1e8aac
#define CONFIG_KEY_AUTOSAVE_SECONDS "autosave-seconds"
Packit 1e8aac
Packit 1e8aac
#define CONFIG_INTRO_GROUP          "Intro"
Packit 1e8aac
#define CONFIG_INTRO_DONE           "intro-done"
Packit 1e8aac
Packit 1e8aac
#define GLADE_WINDOW_ACTIVE_VIEW(w) ((GladeDesignView *) gtk_stack_get_visible_child (w->priv->view_stack))
Packit 1e8aac
Packit 1e8aac
struct _GladeWindowPrivate
Packit 1e8aac
{
Packit 1e8aac
  GladeApp *app;
Packit 1e8aac
Packit 1e8aac
  GtkStack *stack;
Packit 1e8aac
  GtkStack *view_stack;
Packit 1e8aac
Packit 1e8aac
  GtkHeaderBar *headerbar;
Packit 1e8aac
  GtkWidget *project_switcher ;
Packit 1e8aac
  GtkWindow *about_dialog;
Packit 1e8aac
  GladePreferences *preferences;
Packit 1e8aac
Packit 1e8aac
  GtkWidget *start_page;
Packit 1e8aac
  GtkLabel  *version_label;
Packit 1e8aac
  GtkWidget *intro_button;
Packit 1e8aac
Packit 1e8aac
  GladeAdaptorChooser *adaptor_chooser;
Packit 1e8aac
  GtkStack *inspectors_stack;           /* Cached per project inspectors */
Packit 1e8aac
Packit 1e8aac
  GladeEditor  *editor;                 /* The editor */
Packit 1e8aac
Packit 1e8aac
  GtkWidget *statusbar;                 /* A pointer to the status bar. */
Packit 1e8aac
  guint statusbar_context_id;           /* The context id of general messages */
Packit 1e8aac
  guint statusbar_menu_context_id;      /* The context id of the menu bar */
Packit 1e8aac
  guint statusbar_actions_context_id;   /* The context id of actions messages */
Packit 1e8aac
Packit 1e8aac
  GActionGroup *actions;
Packit 1e8aac
Packit 1e8aac
  GtkRecentManager *recent_manager;
Packit 1e8aac
  GtkWidget *recent_menu;
Packit 1e8aac
Packit 1e8aac
  gchar *default_path;          /* the default path for open/save operations */
Packit 1e8aac
Packit 1e8aac
  GtkWidget *undo_button;       /* undo/redo button, right click for history */
Packit 1e8aac
  GtkWidget *redo_button;
Packit 1e8aac
Packit 1e8aac
  GtkWidget *toolbar;           /* Actions are added to the toolbar */
Packit 1e8aac
  gint actions_start;           /* start of action items */
Packit 1e8aac
Packit 1e8aac
  GtkWidget *center_paned;
Packit 1e8aac
  GtkWidget *left_paned;
Packit 1e8aac
  GtkWidget *open_button_box;   /* gtk_button_box_set_layout() set homogeneous to TRUE, and we do not want that in this case  */
Packit 1e8aac
  GtkWidget *save_button_box;
Packit 1e8aac
Packit 1e8aac
  GtkWidget *registration;      /* Registration and user survey dialog */
Packit 1e8aac
Packit 1e8aac
  GladeIntro *intro;
Packit 1e8aac
  GType new_type;
Packit 1e8aac
Packit 1e8aac
  GdkRectangle position;
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
static void check_reload_project (GladeWindow *window, GladeProject *project);
Packit 1e8aac
Packit 1e8aac
G_DEFINE_TYPE_WITH_PRIVATE (GladeWindow, glade_window, GTK_TYPE_WINDOW)
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
refresh_title (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  if (GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
      gchar *title, *name = NULL;
Packit 1e8aac
      GList *p;
Packit 1e8aac
Packit 1e8aac
      gtk_header_bar_set_custom_title (window->priv->headerbar, NULL);
Packit 1e8aac
Packit 1e8aac
      name = glade_project_get_name (project);
Packit 1e8aac
Packit 1e8aac
      if (glade_project_get_modified (project))
Packit 1e8aac
        name = g_strdup_printf ("*%s", name);
Packit 1e8aac
      else
Packit 1e8aac
        name = g_strdup (name);
Packit 1e8aac
Packit 1e8aac
      if (glade_project_get_readonly (project) != FALSE)
Packit 1e8aac
        title = g_strdup_printf ("%s %s", name, READONLY_INDICATOR);
Packit 1e8aac
      else
Packit 1e8aac
        title = g_strdup_printf ("%s", name);
Packit 1e8aac
Packit 1e8aac
      gtk_header_bar_set_title (window->priv->headerbar, title);
Packit 1e8aac
      g_free (title);
Packit 1e8aac
      g_free (name);
Packit 1e8aac
Packit 1e8aac
      if ((p = glade_app_get_projects ()) && g_list_next (p))
Packit 1e8aac
        gtk_header_bar_set_custom_title (window->priv->headerbar, window->priv->project_switcher);
Packit 1e8aac
      else
Packit 1e8aac
        {
Packit 1e8aac
          const gchar *path;
Packit 1e8aac
Packit 1e8aac
          /* Show path */
Packit 1e8aac
          if (project && (path = glade_project_get_path (project)))
Packit 1e8aac
            {
Packit 1e8aac
              gchar *dirname = g_path_get_dirname (path);
Packit 1e8aac
              const gchar *home = g_get_home_dir ();
Packit 1e8aac
Packit 1e8aac
              if (g_str_has_prefix (dirname, home))
Packit 1e8aac
                {
Packit 1e8aac
                  char *subtitle = &dirname[g_utf8_strlen (home, -1) - 1];
Packit 1e8aac
                  subtitle[0] = '~';
Packit 1e8aac
                  gtk_header_bar_set_subtitle (window->priv->headerbar, subtitle);
Packit 1e8aac
                }
Packit 1e8aac
              else
Packit 1e8aac
                gtk_header_bar_set_subtitle (window->priv->headerbar, dirname);
Packit 1e8aac
Packit 1e8aac
              g_free (dirname);
Packit 1e8aac
            }
Packit 1e8aac
          else
Packit 1e8aac
            gtk_header_bar_set_subtitle (window->priv->headerbar, NULL);
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      gtk_header_bar_set_custom_title (window->priv->headerbar, NULL);
Packit 1e8aac
      gtk_header_bar_set_title (window->priv->headerbar, _("User Interface Designer"));
Packit 1e8aac
      gtk_header_bar_set_subtitle (window->priv->headerbar, NULL);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static const gchar *
Packit 1e8aac
get_default_path (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  return window->priv->default_path;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
update_default_path (GladeWindow *window, const gchar *filename)
Packit 1e8aac
{
Packit 1e8aac
  gchar *path;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (filename != NULL);
Packit 1e8aac
Packit 1e8aac
  path = g_path_get_dirname (filename);
Packit 1e8aac
Packit 1e8aac
  g_free (window->priv->default_path);
Packit 1e8aac
  window->priv->default_path = g_strdup (path);
Packit 1e8aac
Packit 1e8aac
  g_free (path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
activate_action (GtkToolButton *toolbutton, GladeWidgetAction *action)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidget   *widget;
Packit 1e8aac
  GWActionClass *aclass = glade_widget_action_get_class (action);
Packit 1e8aac
Packit 1e8aac
  if ((widget = g_object_get_data (G_OBJECT (toolbutton), "glade-widget")))
Packit 1e8aac
    glade_widget_adaptor_action_activate (glade_widget_get_adaptor (widget),
Packit 1e8aac
                                          glade_widget_get_object (widget), 
Packit 1e8aac
                                          aclass->path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
action_notify_sensitive (GObject *gobject, GParamSpec *arg1, GtkWidget *item)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidgetAction *action = GLADE_WIDGET_ACTION (gobject);
Packit 1e8aac
  gtk_widget_set_sensitive (item, glade_widget_action_get_sensitive (action));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
action_disconnect (gpointer data, GClosure *closure)
Packit 1e8aac
{
Packit 1e8aac
  g_signal_handlers_disconnect_matched (data, G_SIGNAL_MATCH_FUNC,
Packit 1e8aac
                                        0, 0, NULL,
Packit 1e8aac
                                        action_notify_sensitive, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
clean_actions (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GtkContainer *container = GTK_CONTAINER (window->priv->toolbar);
Packit 1e8aac
  GtkToolbar *bar = GTK_TOOLBAR (window->priv->toolbar);
Packit 1e8aac
  GtkToolItem *item;
Packit 1e8aac
Packit 1e8aac
  if (window->priv->actions_start)
Packit 1e8aac
    {
Packit 1e8aac
      while ((item =
Packit 1e8aac
              gtk_toolbar_get_nth_item (bar, window->priv->actions_start)))
Packit 1e8aac
        gtk_container_remove (container, GTK_WIDGET (item));
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
add_actions (GladeWindow *window, GladeWidget *widget, GList *actions)
Packit 1e8aac
{
Packit 1e8aac
  GtkToolbar *bar = GTK_TOOLBAR (window->priv->toolbar);
Packit 1e8aac
  GtkToolItem *item = gtk_separator_tool_item_new ();
Packit 1e8aac
  gint n = 0;
Packit 1e8aac
  GList *l;
Packit 1e8aac
Packit 1e8aac
  gtk_toolbar_insert (bar, item, -1);
Packit 1e8aac
  gtk_widget_show (GTK_WIDGET (item));
Packit 1e8aac
Packit 1e8aac
  if (window->priv->actions_start == 0)
Packit 1e8aac
    window->priv->actions_start = gtk_toolbar_get_item_index (bar, item);
Packit 1e8aac
Packit 1e8aac
  for (l = actions; l; l = g_list_next (l))
Packit 1e8aac
    {
Packit 1e8aac
      GladeWidgetAction *action = l->data;
Packit 1e8aac
      GWActionClass     *aclass = glade_widget_action_get_class (action);
Packit 1e8aac
Packit 1e8aac
      if (!aclass->important || !glade_widget_action_get_visible (action))
Packit 1e8aac
        continue;
Packit 1e8aac
Packit 1e8aac
      if (glade_widget_action_get_children (action))
Packit 1e8aac
        {
Packit 1e8aac
          g_warning ("Trying to add a group action to the toolbar is unsupported");
Packit 1e8aac
          continue;
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      item = gtk_tool_button_new (NULL, aclass->label);
Packit 1e8aac
      gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item),
Packit 1e8aac
                                     (aclass->stock) ? aclass->stock : "system-run");
Packit 1e8aac
Packit 1e8aac
      if (aclass->label)
Packit 1e8aac
        gtk_widget_set_tooltip_text (GTK_WIDGET (item), aclass->label);
Packit 1e8aac
Packit 1e8aac
      g_object_set_data (G_OBJECT (item), "glade-widget", widget);
Packit 1e8aac
Packit 1e8aac
      /* We use destroy_data to keep track of notify::sensitive callbacks
Packit 1e8aac
       * on the action object and disconnect them when the toolbar item
Packit 1e8aac
       * gets destroyed.
Packit 1e8aac
       */
Packit 1e8aac
      g_signal_connect_data (item, "clicked",
Packit 1e8aac
                             G_CALLBACK (activate_action),
Packit 1e8aac
                             action, action_disconnect, 0);
Packit 1e8aac
Packit 1e8aac
      gtk_widget_set_sensitive (GTK_WIDGET (item), 
Packit 1e8aac
                                glade_widget_action_get_sensitive (action));
Packit 1e8aac
Packit 1e8aac
      g_signal_connect (action, "notify::sensitive",
Packit 1e8aac
                        G_CALLBACK (activate_action), GTK_WIDGET (item));
Packit 1e8aac
Packit 1e8aac
      gtk_toolbar_insert (bar, item, -1);
Packit 1e8aac
      gtk_tool_item_set_homogeneous (item, FALSE);
Packit 1e8aac
      gtk_widget_show_all (GTK_WIDGET (item));
Packit 1e8aac
      n++;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (n == 0)
Packit 1e8aac
    clean_actions (window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static GladeProject *
Packit 1e8aac
get_active_project (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  if (GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  return NULL;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_selection_changed_cb (GladeProject *project, GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *active_project;
Packit 1e8aac
  GladeWidget  *glade_widget = NULL;
Packit 1e8aac
  GList        *list;
Packit 1e8aac
  gint          num;
Packit 1e8aac
Packit 1e8aac
  active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  /* This is sometimes called with a NULL project (to make the label
Packit 1e8aac
   * insensitive with no projects loaded)
Packit 1e8aac
   */
Packit 1e8aac
  g_return_if_fail (GLADE_IS_WINDOW (window));
Packit 1e8aac
Packit 1e8aac
  /* Only update the toolbar & workspace if the selection has changed on
Packit 1e8aac
   * the currently active project.
Packit 1e8aac
   */
Packit 1e8aac
  if (project == active_project)
Packit 1e8aac
    {
Packit 1e8aac
      list = glade_project_selection_get (project);
Packit 1e8aac
      num = g_list_length (list);
Packit 1e8aac
Packit 1e8aac
      if (num == 1 && !GLADE_IS_PLACEHOLDER (list->data))
Packit 1e8aac
        {
Packit 1e8aac
          glade_widget = glade_widget_get_from_gobject (G_OBJECT (list->data));
Packit 1e8aac
Packit 1e8aac
          clean_actions (window);
Packit 1e8aac
          if (glade_widget_get_actions (glade_widget))
Packit 1e8aac
            add_actions (window, glade_widget, glade_widget_get_actions (glade_widget));
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  glade_editor_load_widget (window->priv->editor, glade_widget);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
refresh_stack_title_for_project (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GList *children, *l;
Packit 1e8aac
Packit 1e8aac
  children = gtk_container_get_children (GTK_CONTAINER (window->priv->view_stack));
Packit 1e8aac
  for (l = children; l; l = l->next)
Packit 1e8aac
    {
Packit 1e8aac
      GtkWidget *view = l->data;
Packit 1e8aac
Packit 1e8aac
      if (project == glade_design_view_get_project (GLADE_DESIGN_VIEW (view)))
Packit 1e8aac
        {
Packit 1e8aac
          gchar *name = glade_project_get_name (project);
Packit 1e8aac
          gchar *str;
Packit 1e8aac
Packit 1e8aac
          /* remove extension */
Packit 1e8aac
          if ((str = g_utf8_strrchr (name, -1, '.')))
Packit 1e8aac
            *str = '\0';
Packit 1e8aac
Packit 1e8aac
          if (glade_project_get_modified (project))
Packit 1e8aac
            str = g_strdup_printf ("*%s", name);
Packit 1e8aac
          else
Packit 1e8aac
            str = g_strdup (name);
Packit 1e8aac
Packit 1e8aac
          gtk_container_child_set (GTK_CONTAINER (window->priv->view_stack), view,
Packit 1e8aac
                                   "title", str, NULL);
Packit 1e8aac
          g_free (name);
Packit 1e8aac
          g_free (str);
Packit 1e8aac
Packit 1e8aac
          break;
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
  g_list_free (children);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_targets_changed_cb (GladeProject *project, GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  refresh_stack_title_for_project (window, project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
actions_set_enabled (GladeWindow *window, const gchar *name, gboolean enabled)
Packit 1e8aac
{
Packit 1e8aac
  GAction *action = g_action_map_lookup_action (G_ACTION_MAP (window->priv->actions), name);
Packit 1e8aac
  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enabled);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_actions_set_enabled (GladeWindow *window, gboolean enabled)
Packit 1e8aac
{
Packit 1e8aac
  actions_set_enabled (window, "close", enabled);
Packit 1e8aac
  actions_set_enabled (window, "save", enabled);
Packit 1e8aac
  actions_set_enabled (window, "save_as", enabled);
Packit 1e8aac
  actions_set_enabled (window, "properties", enabled);
Packit 1e8aac
  actions_set_enabled (window, "undo", enabled);
Packit 1e8aac
  actions_set_enabled (window, "redo", enabled);
Packit 1e8aac
  actions_set_enabled (window, "cut", enabled);
Packit 1e8aac
  actions_set_enabled (window, "copy", enabled);
Packit 1e8aac
  actions_set_enabled (window, "delete", enabled);
Packit 1e8aac
  actions_set_enabled (window, "previous", enabled);
Packit 1e8aac
  actions_set_enabled (window, "next", enabled);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
pointer_mode_actions_set_enabled (GladeWindow *window, gboolean enabled)
Packit 1e8aac
{
Packit 1e8aac
  actions_set_enabled (window, "select", enabled);
Packit 1e8aac
  actions_set_enabled (window, "drag_resize", enabled);
Packit 1e8aac
  actions_set_enabled (window, "margin_edit", enabled);
Packit 1e8aac
  actions_set_enabled (window, "align_edit", enabled);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
refresh_undo_redo (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeCommand *undo = NULL, *redo = NULL;
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  const gchar *desc;
Packit 1e8aac
  gchar *tooltip;
Packit 1e8aac
Packit 1e8aac
  if (project != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      undo = glade_project_next_undo_item (project);
Packit 1e8aac
      redo = glade_project_next_redo_item (project);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Refresh Undo */
Packit 1e8aac
  actions_set_enabled (window, "undo", undo != NULL);
Packit 1e8aac
  desc = undo ? glade_command_description (undo) : _("the last action");
Packit 1e8aac
  tooltip = g_strdup_printf (_("Undo: %s"), desc);
Packit 1e8aac
  gtk_widget_set_tooltip_text (priv->undo_button, tooltip);
Packit 1e8aac
  g_free (tooltip);
Packit 1e8aac
Packit 1e8aac
  /* Refresh Redo */
Packit 1e8aac
  actions_set_enabled (window, "redo", redo != NULL);
Packit 1e8aac
  desc = redo ? glade_command_description (redo) : _("the last action");
Packit 1e8aac
  tooltip = g_strdup_printf (_("Redo: %s"), desc);
Packit 1e8aac
  gtk_widget_set_tooltip_text (priv->redo_button, tooltip);
Packit 1e8aac
  g_free (tooltip);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
cancel_autosave (gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  guint autosave_id = GPOINTER_TO_UINT (data);
Packit 1e8aac
Packit 1e8aac
  g_source_remove (autosave_id);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
autosave_project (gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project = (GladeProject *)data;
Packit 1e8aac
  GladeWindow *window = GLADE_WINDOW (glade_app_get_window ());
Packit 1e8aac
  gchar *display_name;
Packit 1e8aac
Packit 1e8aac
  display_name = glade_project_get_name (project);
Packit 1e8aac
Packit 1e8aac
  if (glade_project_autosave (project, NULL))
Packit 1e8aac
    glade_util_flash_message (window->priv->statusbar,
Packit 1e8aac
                              window->priv->statusbar_actions_context_id,
Packit 1e8aac
                              _("Autosaving '%s'"), display_name);
Packit 1e8aac
  else
Packit 1e8aac
    /* This is problematic, should we be more intrusive and popup a dialog ? */
Packit 1e8aac
    glade_util_flash_message (window->priv->statusbar,
Packit 1e8aac
                              window->priv->statusbar_actions_context_id,
Packit 1e8aac
                              _("Error autosaving '%s'"), display_name);
Packit 1e8aac
Packit 1e8aac
  g_free (display_name);
Packit 1e8aac
Packit 1e8aac
  /* This will remove the source id */
Packit 1e8aac
  g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_queue_autosave (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  if (glade_project_get_path (project) != NULL &&
Packit 1e8aac
      glade_project_get_modified (project) &&
Packit 1e8aac
      glade_preferences_autosave (window->priv->preferences))
Packit 1e8aac
    {
Packit 1e8aac
      guint autosave_id =
Packit 1e8aac
        g_timeout_add_seconds (glade_preferences_autosave_seconds (window->priv->preferences),
Packit 1e8aac
                               autosave_project, project);
Packit 1e8aac
Packit 1e8aac
      g_object_set_data_full (G_OBJECT (project), "glade-autosave-id",
Packit 1e8aac
                              GUINT_TO_POINTER (autosave_id), cancel_autosave);
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
      g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_cancel_autosave (GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  g_object_set_data (G_OBJECT (project), "glade-autosave-id", NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_changed_cb (GladeProject *project,
Packit 1e8aac
                    GladeCommand *command,
Packit 1e8aac
                    gboolean      execute,
Packit 1e8aac
                    GladeWindow  *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (project == active_project)
Packit 1e8aac
    refresh_undo_redo (window, project);
Packit 1e8aac
Packit 1e8aac
  project_queue_autosave (window, project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
project_notify_handler_cb (GladeProject *project,
Packit 1e8aac
                           GParamSpec *spec,
Packit 1e8aac
                           GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (strcmp (spec->name, "path") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      refresh_title (window);
Packit 1e8aac
      refresh_stack_title_for_project (window, project);
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (spec->name, "format") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      refresh_stack_title_for_project (window, project);
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (spec->name, "modified") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      refresh_title (window);
Packit 1e8aac
      refresh_stack_title_for_project (window, project);
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (spec->name, "read-only") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      refresh_stack_title_for_project (window, project);
Packit 1e8aac
Packit 1e8aac
      actions_set_enabled (window, "save", !glade_project_get_readonly (project));
Packit 1e8aac
    }
Packit 1e8aac
  else if (strcmp (spec->name, "has-selection") == 0 && (project == active_project))
Packit 1e8aac
    {
Packit 1e8aac
      gboolean has_selection = glade_project_get_has_selection (project);
Packit 1e8aac
      actions_set_enabled (window, "cut", has_selection);
Packit 1e8aac
      actions_set_enabled (window, "copy", has_selection);
Packit 1e8aac
      actions_set_enabled (window, "delete", has_selection);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
clipboard_notify_handler_cb (GladeClipboard *clipboard,
Packit 1e8aac
                             GParamSpec     *spec,
Packit 1e8aac
                             GladeWindow    *window)
Packit 1e8aac
{
Packit 1e8aac
  if (strcmp (spec->name, "has-selection") == 0)
Packit 1e8aac
    {
Packit 1e8aac
      actions_set_enabled (window, "paste",
Packit 1e8aac
                           glade_clipboard_get_has_selection (clipboard));
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_pointer_mode_changed (GladeProject *project,
Packit 1e8aac
                         GParamSpec   *pspec,
Packit 1e8aac
                         GladeWindow  *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (!active_project)
Packit 1e8aac
    {
Packit 1e8aac
      pointer_mode_actions_set_enabled (window, FALSE);
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
  else if (active_project != project)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  if (glade_project_get_pointer_mode (project) == GLADE_POINTER_ADD_WIDGET)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  pointer_mode_actions_set_enabled (window, TRUE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
set_sensitivity_according_to_project (GladeWindow  *window,
Packit 1e8aac
                                      GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  gboolean has_selection = glade_project_get_has_selection (project);
Packit 1e8aac
Packit 1e8aac
  actions_set_enabled (window, "cut", has_selection);
Packit 1e8aac
  actions_set_enabled (window, "copy", has_selection);
Packit 1e8aac
  actions_set_enabled (window, "delete", has_selection);
Packit 1e8aac
Packit 1e8aac
  actions_set_enabled (window, "save",
Packit 1e8aac
                       !glade_project_get_readonly (project));
Packit 1e8aac
Packit 1e8aac
  actions_set_enabled (window, "paste",
Packit 1e8aac
                       glade_clipboard_get_has_selection (glade_app_get_clipboard ()));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gchar *
Packit 1e8aac
get_uri_from_project_path (const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  GError *error = NULL;
Packit 1e8aac
  gchar *uri = NULL;
Packit 1e8aac
Packit 1e8aac
  if (g_path_is_absolute (path))
Packit 1e8aac
    uri = g_filename_to_uri (path, NULL, &error);
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      gchar *cwd = g_get_current_dir ();
Packit 1e8aac
      gchar *fullpath = g_build_filename (cwd, path, NULL);
Packit 1e8aac
      uri = g_filename_to_uri (fullpath, NULL, &error);
Packit 1e8aac
      g_free (cwd);
Packit 1e8aac
      g_free (fullpath);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (error)
Packit 1e8aac
    {
Packit 1e8aac
      g_warning ("Could not convert local path \"%s\" to a uri: %s", path, error->message);
Packit 1e8aac
      g_error_free (error);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return uri;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
recent_add (GladeWindow *window, const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  gchar *uri = get_uri_from_project_path (path);
Packit 1e8aac
  GtkRecentData *recent_data;
Packit 1e8aac
Packit 1e8aac
  if (!uri)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  recent_data = g_slice_new (GtkRecentData);
Packit 1e8aac
Packit 1e8aac
  recent_data->display_name = NULL;
Packit 1e8aac
  recent_data->description = NULL;
Packit 1e8aac
  recent_data->mime_type = "application/x-glade";
Packit 1e8aac
  recent_data->app_name = (gchar *) g_get_application_name ();
Packit 1e8aac
  recent_data->app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
Packit 1e8aac
  recent_data->groups = NULL;
Packit 1e8aac
  recent_data->is_private = FALSE;
Packit 1e8aac
Packit 1e8aac
  gtk_recent_manager_add_full (window->priv->recent_manager, uri, recent_data);
Packit 1e8aac
Packit 1e8aac
  g_free (uri);
Packit 1e8aac
  g_free (recent_data->app_exec);
Packit 1e8aac
  g_slice_free (GtkRecentData, recent_data);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
recent_remove (GladeWindow * window, const gchar * path)
Packit 1e8aac
{
Packit 1e8aac
  gchar *uri = get_uri_from_project_path (path);
Packit 1e8aac
Packit 1e8aac
  if (!uri)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  gtk_recent_manager_remove_item (window->priv->recent_manager, uri, NULL);
Packit 1e8aac
Packit 1e8aac
  g_free (uri);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/* switch to a project and check if we need to reload it.
Packit 1e8aac
 *
Packit 1e8aac
 */
Packit 1e8aac
static void
Packit 1e8aac
switch_to_project (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  GtkWidget *view;
Packit 1e8aac
Packit 1e8aac
  view = GTK_WIDGET (glade_design_view_get_from_project (project));
Packit 1e8aac
  gtk_stack_set_visible_child (priv->view_stack, view);
Packit 1e8aac
Packit 1e8aac
  check_reload_project (window, project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_open_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GtkWidget *filechooser;
Packit 1e8aac
  gchar *path = NULL, *default_path;
Packit 1e8aac
Packit 1e8aac
  filechooser = glade_util_file_dialog_new (_("Open\342\200\246"), NULL,
Packit 1e8aac
                                            GTK_WINDOW (window),
Packit 1e8aac
                                            GLADE_FILE_DIALOG_ACTION_OPEN);
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
  default_path = g_strdup (get_default_path (window));
Packit 1e8aac
  if (default_path != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
Packit 1e8aac
                                           default_path);
Packit 1e8aac
      g_free (default_path);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_OK)
Packit 1e8aac
    path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
Packit 1e8aac
Packit 1e8aac
  gtk_widget_destroy (filechooser);
Packit 1e8aac
Packit 1e8aac
  if (!path)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  glade_window_open_project (window, path);
Packit 1e8aac
  g_free (path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
check_loading_project_for_save (GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  if (glade_project_is_loading (project))
Packit 1e8aac
    {
Packit 1e8aac
      gchar *name = glade_project_get_name (project);
Packit 1e8aac
Packit 1e8aac
      glade_util_ui_message (glade_app_get_window (),
Packit 1e8aac
                             GLADE_UI_INFO, NULL,
Packit 1e8aac
                             _("Project %s is still loading."), name);
Packit 1e8aac
      g_free (name);
Packit 1e8aac
      return TRUE;
Packit 1e8aac
    }
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
do_save (GladeWindow *window, GladeProject *project, const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  GError *error = NULL;
Packit 1e8aac
  GladeVerifyFlags verify_flags = 0;
Packit 1e8aac
  gchar *display_path = g_strdup (path);
Packit 1e8aac
Packit 1e8aac
  if (glade_preferences_backup (window->priv->preferences) &&
Packit 1e8aac
      !glade_project_backup (project, path, NULL))
Packit 1e8aac
    {
Packit 1e8aac
      if (!glade_util_ui_message (GTK_WIDGET (window),
Packit 1e8aac
                                  GLADE_UI_ARE_YOU_SURE, NULL,
Packit 1e8aac
                                  _("Failed to backup existing file, continue saving?")))
Packit 1e8aac
        {
Packit 1e8aac
          g_free (display_path);
Packit 1e8aac
          return FALSE;
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (glade_preferences_warn_versioning (window->priv->preferences))
Packit 1e8aac
    verify_flags |= GLADE_VERIFY_VERSIONS;
Packit 1e8aac
  if (glade_preferences_warn_deprecations (window->priv->preferences))
Packit 1e8aac
    verify_flags |= GLADE_VERIFY_DEPRECATIONS;
Packit 1e8aac
  if (glade_preferences_warn_unrecognized (window->priv->preferences))
Packit 1e8aac
    verify_flags |= GLADE_VERIFY_UNRECOGNIZED;
Packit 1e8aac
Packit 1e8aac
  if (!glade_project_save_verify (project, path, verify_flags, &error))
Packit 1e8aac
    {
Packit 1e8aac
      if (error)
Packit 1e8aac
        {
Packit 1e8aac
          /* Reset path so future saves will prompt the file chooser */
Packit 1e8aac
          glade_project_reset_path (project);
Packit 1e8aac
Packit 1e8aac
          glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_ERROR, NULL,
Packit 1e8aac
                                 _("Failed to save %s: %s"),
Packit 1e8aac
                                 display_path, error->message);
Packit 1e8aac
          g_error_free (error);
Packit 1e8aac
        }
Packit 1e8aac
      g_free (display_path);
Packit 1e8aac
      return FALSE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Cancel any queued autosave when explicitly saving */
Packit 1e8aac
  project_cancel_autosave (project);
Packit 1e8aac
Packit 1e8aac
  g_free (display_path);
Packit 1e8aac
  return TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
save (GladeWindow *window, GladeProject *project, const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  gchar *display_name;
Packit 1e8aac
  time_t mtime;
Packit 1e8aac
  GtkWidget *dialog;
Packit 1e8aac
  GtkWidget *button;
Packit 1e8aac
  gint response;
Packit 1e8aac
Packit 1e8aac
  if (check_loading_project_for_save (project))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* check for external modification to the project file */
Packit 1e8aac
  if (glade_project_get_path (project))
Packit 1e8aac
    {
Packit 1e8aac
      mtime = glade_util_get_file_mtime (glade_project_get_path (project), NULL);
Packit 1e8aac
Packit 1e8aac
      if (mtime > glade_project_get_file_mtime (project))
Packit 1e8aac
        {
Packit 1e8aac
Packit 1e8aac
          dialog = gtk_message_dialog_new (GTK_WINDOW (window),
Packit 1e8aac
                                           GTK_DIALOG_MODAL,
Packit 1e8aac
                                           GTK_MESSAGE_WARNING,
Packit 1e8aac
                                           GTK_BUTTONS_NONE,
Packit 1e8aac
                                           _("The file %s has been modified since reading it"),
Packit 1e8aac
                                           glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
          gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit 1e8aac
                                                    _("If you save it, all the external changes could be lost. "
Packit 1e8aac
                                                    "Save it anyway?"));
Packit 1e8aac
Packit 1e8aac
          gtk_window_set_title (GTK_WINDOW (dialog), "");
Packit 1e8aac
Packit 1e8aac
          button = gtk_button_new_with_mnemonic (_("_Save Anyway"));
Packit 1e8aac
          gtk_button_set_image (GTK_BUTTON (button),
Packit 1e8aac
                                gtk_image_new_from_icon_name ("document-save",
Packit 1e8aac
                                                                      GTK_ICON_SIZE_BUTTON));
Packit 1e8aac
          gtk_widget_show (button);
Packit 1e8aac
Packit 1e8aac
          gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
Packit 1e8aac
                                        GTK_RESPONSE_ACCEPT);
Packit 1e8aac
          gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Don't Save"),
Packit 1e8aac
                                 GTK_RESPONSE_REJECT);
Packit 1e8aac
Packit 1e8aac
          gtk_dialog_set_default_response (GTK_DIALOG (dialog),
Packit 1e8aac
                                           GTK_RESPONSE_REJECT);
Packit 1e8aac
Packit 1e8aac
          response = gtk_dialog_run (GTK_DIALOG (dialog));
Packit 1e8aac
Packit 1e8aac
          gtk_widget_destroy (dialog);
Packit 1e8aac
Packit 1e8aac
          if (response == GTK_RESPONSE_REJECT)
Packit 1e8aac
            return;
Packit 1e8aac
      }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Interestingly; we cannot use `path' after glade_project_reset_path
Packit 1e8aac
   * because we are getting called with glade_project_get_path (project) as an argument.
Packit 1e8aac
   */
Packit 1e8aac
  if (!do_save (window, project, path))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* Get display_name here, it could have changed with "Save As..." */
Packit 1e8aac
  display_name = glade_project_get_name (project);
Packit 1e8aac
Packit 1e8aac
  recent_add (window, glade_project_get_path (project));
Packit 1e8aac
  update_default_path (window, glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
  /* refresh names */
Packit 1e8aac
  refresh_title (window);
Packit 1e8aac
  refresh_stack_title_for_project (window, project);
Packit 1e8aac
Packit 1e8aac
  glade_util_flash_message (window->priv->statusbar,
Packit 1e8aac
                            window->priv->statusbar_actions_context_id,
Packit 1e8aac
                            _("Project '%s' saved"), display_name);
Packit 1e8aac
Packit 1e8aac
  g_free (display_name);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
path_has_extension (const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  gchar *basename = g_path_get_basename (path);
Packit 1e8aac
  gboolean retval = g_utf8_strrchr (basename, -1, '.') != NULL;
Packit 1e8aac
  g_free (basename);
Packit 1e8aac
  return retval;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
save_as (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project, *another_project;
Packit 1e8aac
  GtkWidget *filechooser;
Packit 1e8aac
  GtkWidget *dialog;
Packit 1e8aac
  gchar *path = NULL;
Packit 1e8aac
  gchar *project_name;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  if (project == NULL)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  if (check_loading_project_for_save (project))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  filechooser = glade_util_file_dialog_new (_("Save As\342\200\246"), project,
Packit 1e8aac
                                            GTK_WINDOW (window),
Packit 1e8aac
                                            GLADE_FILE_DIALOG_ACTION_SAVE);
Packit 1e8aac
Packit 1e8aac
  if (glade_project_get_path (project))
Packit 1e8aac
    {
Packit 1e8aac
      gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser),
Packit 1e8aac
                                     glade_project_get_path (project));
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      gchar *default_path = g_strdup (get_default_path (window));
Packit 1e8aac
      if (default_path != NULL)
Packit 1e8aac
        {
Packit 1e8aac
          gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (filechooser),
Packit 1e8aac
                                               default_path);
Packit 1e8aac
          g_free (default_path);
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      project_name = glade_project_get_name (project);
Packit 1e8aac
      gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filechooser),
Packit 1e8aac
                                         project_name);
Packit 1e8aac
      g_free (project_name);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  while (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_OK)
Packit 1e8aac
    {
Packit 1e8aac
      path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
Packit 1e8aac
Packit 1e8aac
      /* Check if selected filename has an extension or not */
Packit 1e8aac
      if (!path_has_extension (path))
Packit 1e8aac
        {
Packit 1e8aac
          gchar *real_path = g_strconcat (path, ".glade", NULL);
Packit 1e8aac
Packit 1e8aac
          g_free (path);
Packit 1e8aac
          path = real_path;
Packit 1e8aac
Packit 1e8aac
          /* We added .glade extension!,
Packit 1e8aac
           * check if file exist to avoid overwriting a file without asking
Packit 1e8aac
           */
Packit 1e8aac
          if (g_file_test (path, G_FILE_TEST_EXISTS))
Packit 1e8aac
            {
Packit 1e8aac
              /* Set existing filename and let filechooser ask about overwriting */
Packit 1e8aac
              gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser), path);
Packit 1e8aac
              g_free (path);
Packit 1e8aac
              path = NULL;
Packit 1e8aac
              continue;
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
      break;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  gtk_widget_destroy (filechooser);
Packit 1e8aac
Packit 1e8aac
  if (!path)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  /* checks if selected path is actually writable */
Packit 1e8aac
  if (glade_util_file_is_writeable (path) == FALSE)
Packit 1e8aac
    {
Packit 1e8aac
      dialog = gtk_message_dialog_new (GTK_WINDOW (window),
Packit 1e8aac
                                       GTK_DIALOG_MODAL,
Packit 1e8aac
                                       GTK_MESSAGE_ERROR,
Packit 1e8aac
                                       GTK_BUTTONS_OK,
Packit 1e8aac
                                       _("Could not save the file %s"),
Packit 1e8aac
                                       path);
Packit 1e8aac
Packit 1e8aac
      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit 1e8aac
                                                _("You do not have the permissions "
Packit 1e8aac
                                                  "necessary to save the file."));
Packit 1e8aac
Packit 1e8aac
      gtk_window_set_title (GTK_WINDOW (dialog), "");
Packit 1e8aac
Packit 1e8aac
      g_signal_connect_swapped (dialog, "response",
Packit 1e8aac
                                G_CALLBACK (gtk_widget_destroy), dialog);
Packit 1e8aac
Packit 1e8aac
      gtk_widget_show (dialog);
Packit 1e8aac
      g_free (path);
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* checks if another open project is using selected path */
Packit 1e8aac
  if ((another_project = glade_app_get_project_by_path (path)) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      if (project != another_project)
Packit 1e8aac
        {
Packit 1e8aac
Packit 1e8aac
          glade_util_ui_message (GTK_WIDGET (window),
Packit 1e8aac
                                 GLADE_UI_ERROR, NULL,
Packit 1e8aac
                                 _
Packit 1e8aac
                                 ("Could not save file %s. Another project with that path is open."),
Packit 1e8aac
                                 path);
Packit 1e8aac
Packit 1e8aac
          g_free (path);
Packit 1e8aac
          return;
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  save (window, project, path);
Packit 1e8aac
Packit 1e8aac
  g_free (path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_save_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  if (project == NULL)
Packit 1e8aac
    {
Packit 1e8aac
      /* Just in case the menu-item or button is not insensitive */
Packit 1e8aac
      glade_util_ui_message (GTK_WIDGET (window), GLADE_UI_WARN, NULL,
Packit 1e8aac
                             _("No open projects to save"));
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (glade_project_get_path (project) != NULL)
Packit 1e8aac
    {
Packit 1e8aac
      save (window, project, glade_project_get_path (project));
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* If instead we dont have a path yet, fire up a file selector */
Packit 1e8aac
  save_as (window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_save_as_action_activate (GSimpleAction *action,
Packit 1e8aac
                            GVariant      *parameter,
Packit 1e8aac
                            gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  save_as (window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
confirm_close_project (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GtkWidget *dialog;
Packit 1e8aac
  gboolean close = FALSE;
Packit 1e8aac
  gchar *msg, *project_name = NULL;
Packit 1e8aac
  gint ret;
Packit 1e8aac
Packit 1e8aac
  project_name = glade_project_get_name (project);
Packit 1e8aac
Packit 1e8aac
  msg = g_strdup_printf (_("Save changes to project \"%s\" before closing?"),
Packit 1e8aac
                         project_name);
Packit 1e8aac
Packit 1e8aac
  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
Packit 1e8aac
                                   GTK_DIALOG_MODAL,
Packit 1e8aac
                                   GTK_MESSAGE_WARNING,
Packit 1e8aac
                                   GTK_BUTTONS_NONE, "%s", msg);
Packit 1e8aac
  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit 1e8aac
                                            "%s", _("Your changes will be lost if you don't save them."));
Packit 1e8aac
  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
Packit 1e8aac
Packit 1e8aac
  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
Packit 1e8aac
                          _("Close _without Saving"), GTK_RESPONSE_NO,
Packit 1e8aac
                          _("_Cancel"), GTK_RESPONSE_CANCEL,
Packit 1e8aac
                          _("_Save"), GTK_RESPONSE_YES,
Packit 1e8aac
                          NULL);
Packit 1e8aac
Packit 1e8aac
#ifdef G_OS_WIN32
Packit 1e8aac
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
Packit 1e8aac
                                           GTK_RESPONSE_YES,
Packit 1e8aac
                                           GTK_RESPONSE_CANCEL,
Packit 1e8aac
                                           GTK_RESPONSE_NO, -1);
Packit 1e8aac
#endif
Packit 1e8aac
Packit 1e8aac
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
Packit 1e8aac
Packit 1e8aac
  ret = gtk_dialog_run (GTK_DIALOG (dialog));
Packit 1e8aac
  switch (ret)
Packit 1e8aac
    {
Packit 1e8aac
      case GTK_RESPONSE_YES:
Packit 1e8aac
        /* if YES we save the project: note we cannot use save_cb
Packit 1e8aac
         * since it saves the current project, while the modified
Packit 1e8aac
         * project we are saving may be not the current one.
Packit 1e8aac
         */
Packit 1e8aac
        if (glade_project_get_path (project) != NULL)
Packit 1e8aac
          {
Packit 1e8aac
            close = do_save (window, project, glade_project_get_path (project));
Packit 1e8aac
          }
Packit 1e8aac
        else
Packit 1e8aac
          {
Packit 1e8aac
            GtkWidget *filechooser;
Packit 1e8aac
            gchar *path = NULL;
Packit 1e8aac
            gchar *default_path;
Packit 1e8aac
Packit 1e8aac
            filechooser =
Packit 1e8aac
                glade_util_file_dialog_new (_("Save\342\200\246"), project,
Packit 1e8aac
                                            GTK_WINDOW (window),
Packit 1e8aac
                                            GLADE_FILE_DIALOG_ACTION_SAVE);
Packit 1e8aac
Packit 1e8aac
            default_path = g_strdup (get_default_path (window));
Packit 1e8aac
            if (default_path != NULL)
Packit 1e8aac
              {
Packit 1e8aac
                gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER
Packit 1e8aac
                                                     (filechooser),
Packit 1e8aac
                                                     default_path);
Packit 1e8aac
                g_free (default_path);
Packit 1e8aac
              }
Packit 1e8aac
Packit 1e8aac
            gtk_file_chooser_set_current_name
Packit 1e8aac
                (GTK_FILE_CHOOSER (filechooser), project_name);
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
            if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_OK)
Packit 1e8aac
              path =
Packit 1e8aac
                  gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
Packit 1e8aac
                                                 (filechooser));
Packit 1e8aac
Packit 1e8aac
            gtk_widget_destroy (filechooser);
Packit 1e8aac
Packit 1e8aac
            if (!path)
Packit 1e8aac
              break;
Packit 1e8aac
Packit 1e8aac
            save (window, project, path);
Packit 1e8aac
Packit 1e8aac
            g_free (path);
Packit 1e8aac
Packit 1e8aac
            close = FALSE;
Packit 1e8aac
          }
Packit 1e8aac
        break;
Packit 1e8aac
      case GTK_RESPONSE_NO:
Packit 1e8aac
        close = TRUE;
Packit 1e8aac
        break;
Packit 1e8aac
      case GTK_RESPONSE_CANCEL:
Packit 1e8aac
      case GTK_RESPONSE_DELETE_EVENT:
Packit 1e8aac
        close = FALSE;
Packit 1e8aac
        break;
Packit 1e8aac
      default:
Packit 1e8aac
        g_assert_not_reached ();
Packit 1e8aac
        close = FALSE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (msg);
Packit 1e8aac
  g_free (project_name);
Packit 1e8aac
  gtk_widget_destroy (dialog);
Packit 1e8aac
Packit 1e8aac
  return close;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
close_project (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  GladeDesignView *view = glade_design_view_get_from_project (project);
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
Packit 1e8aac
  /* Cancel any queued autosave activity */
Packit 1e8aac
  project_cancel_autosave (project);
Packit 1e8aac
Packit 1e8aac
  if (glade_project_is_loading (project))
Packit 1e8aac
    {
Packit 1e8aac
      glade_project_cancel_load (project);
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (project, project_notify_handler_cb, window);
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (project, project_selection_changed_cb, window);
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (project, project_targets_changed_cb, window);
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (project, project_changed_cb, window);
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (project, on_pointer_mode_changed, window);
Packit 1e8aac
Packit 1e8aac
  /* remove inspector first */
Packit 1e8aac
  gtk_container_remove (GTK_CONTAINER (priv->inspectors_stack),
Packit 1e8aac
                        g_object_get_data (G_OBJECT (view), "glade-window-view-inspector"));
Packit 1e8aac
Packit 1e8aac
  /* then the main view */
Packit 1e8aac
  gtk_container_remove (GTK_CONTAINER (priv->view_stack), GTK_WIDGET (view));
Packit 1e8aac
Packit 1e8aac
  clean_actions (window);
Packit 1e8aac
Packit 1e8aac
  /* Refresh the editor and some of the actions */
Packit 1e8aac
  project_selection_changed_cb (project, window);
Packit 1e8aac
Packit 1e8aac
  on_pointer_mode_changed (project, NULL, window);
Packit 1e8aac
Packit 1e8aac
  glade_app_remove_project (project);
Packit 1e8aac
Packit 1e8aac
  refresh_title (window);
Packit 1e8aac
Packit 1e8aac
  if (!glade_app_get_projects ())
Packit 1e8aac
    gtk_stack_set_visible_child (priv->stack, priv->start_page);
Packit 1e8aac
Packit 1e8aac
  if (GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    set_sensitivity_according_to_project (window,
Packit 1e8aac
                                          glade_design_view_get_project
Packit 1e8aac
                                          (GLADE_WINDOW_ACTIVE_VIEW (window)));
Packit 1e8aac
  else
Packit 1e8aac
    project_actions_set_enabled (window, FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_close_action_activate (GSimpleAction *action,
Packit 1e8aac
                          GVariant      *parameter,
Packit 1e8aac
                          gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeDesignView *view;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
  gboolean close;
Packit 1e8aac
Packit 1e8aac
  view = GLADE_WINDOW_ACTIVE_VIEW (window);
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (view);
Packit 1e8aac
Packit 1e8aac
  if (view == NULL)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  if (glade_project_get_modified (project))
Packit 1e8aac
    {
Packit 1e8aac
      close = confirm_close_project (window, project);
Packit 1e8aac
      if (!close)
Packit 1e8aac
        return;
Packit 1e8aac
    }
Packit 1e8aac
  close_project (window, project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_copy_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  if (!GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  glade_project_copy_selection (project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_cut_action_activate (GSimpleAction *action,
Packit 1e8aac
                        GVariant      *parameter,
Packit 1e8aac
                        gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  if (!GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  glade_project_command_cut (project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_paste_action_activate (GSimpleAction *action,
Packit 1e8aac
                          GVariant      *parameter,
Packit 1e8aac
                          gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GtkWidget *placeholder;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  if (!GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
  placeholder = glade_util_get_placeholder_from_pointer (GTK_CONTAINER (window));
Packit 1e8aac
Packit 1e8aac
  /* If this action is activated with a key binging (ctrl-v) the widget will be
Packit 1e8aac
   * pasted over the placeholder below the default pointer.
Packit 1e8aac
   */
Packit 1e8aac
  glade_project_command_paste (project, placeholder ? GLADE_PLACEHOLDER (placeholder) : NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_delete_action_activate (GSimpleAction *action,
Packit 1e8aac
                           GVariant      *parameter,
Packit 1e8aac
                           gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  if (!GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  glade_project_command_delete (project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
stack_visible_child_next_prev (GladeWindow *window, gboolean next)
Packit 1e8aac
{
Packit 1e8aac
  GladeDesignView *view;
Packit 1e8aac
  GList *children, *node;
Packit 1e8aac
Packit 1e8aac
  if (!(view = GLADE_WINDOW_ACTIVE_VIEW (window)))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  children = gtk_container_get_children (GTK_CONTAINER (window->priv->view_stack));
Packit 1e8aac
Packit 1e8aac
  if ((node = g_list_find (children, view)) &&
Packit 1e8aac
      ((next && node->next) || (!next && node->prev)))
Packit 1e8aac
    gtk_stack_set_visible_child (window->priv->view_stack,
Packit 1e8aac
                                 (next) ? node->next->data : node->prev->data);
Packit 1e8aac
Packit 1e8aac
  g_list_free (children);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_previous_action_activate (GSimpleAction *action,
Packit 1e8aac
                             GVariant      *parameter,
Packit 1e8aac
                             gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  stack_visible_child_next_prev (window, FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_next_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  stack_visible_child_next_prev (window, TRUE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_properties_action_activate (GSimpleAction *action,
Packit 1e8aac
                               GVariant      *parameter,
Packit 1e8aac
                               gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  if (!GLADE_WINDOW_ACTIVE_VIEW (window))
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  project = glade_design_view_get_project (GLADE_WINDOW_ACTIVE_VIEW (window));
Packit 1e8aac
Packit 1e8aac
  glade_project_properties (project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_undo_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (!active_project)
Packit 1e8aac
    {
Packit 1e8aac
      g_warning ("undo should not be sensitive: we don't have a project");
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  glade_project_undo (active_project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_redo_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeProject *active_project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (!active_project)
Packit 1e8aac
    {
Packit 1e8aac
      g_warning ("redo should not be sensitive: we don't have a project");
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  glade_project_redo (active_project);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
doc_search_cb (GladeEditor *editor,
Packit 1e8aac
               const gchar *book,
Packit 1e8aac
               const gchar *page,
Packit 1e8aac
               const gchar *search,
Packit 1e8aac
               GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  glade_util_search_devhelp (book, page, search);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_stack_visible_child_notify (GObject    *gobject,
Packit 1e8aac
                               GParamSpec *pspec,
Packit 1e8aac
                               GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeDesignView *view = GLADE_WINDOW_ACTIVE_VIEW (window);
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
Packit 1e8aac
  if (view)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *project = glade_design_view_get_project (view);
Packit 1e8aac
Packit 1e8aac
      /* switch to the project's inspector */
Packit 1e8aac
      gtk_stack_set_visible_child (priv->inspectors_stack,
Packit 1e8aac
                                   g_object_get_data (G_OBJECT (view), "glade-window-view-inspector"));
Packit 1e8aac
Packit 1e8aac
      glade_adaptor_chooser_set_project (priv->adaptor_chooser, project);
Packit 1e8aac
Packit 1e8aac
      set_sensitivity_according_to_project (window, project);
Packit 1e8aac
Packit 1e8aac
      refresh_undo_redo (window, project);
Packit 1e8aac
Packit 1e8aac
      /* Refresh the editor and some of the actions */
Packit 1e8aac
      project_selection_changed_cb (project, window);
Packit 1e8aac
Packit 1e8aac
      on_pointer_mode_changed (project, NULL, window);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_open_recent_action_item_activated (GtkRecentChooser *chooser,
Packit 1e8aac
                                      GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  gchar *uri, *path;
Packit 1e8aac
  GError *error = NULL;
Packit 1e8aac
Packit 1e8aac
  uri = gtk_recent_chooser_get_current_uri (chooser);
Packit 1e8aac
Packit 1e8aac
  path = g_filename_from_uri (uri, NULL, NULL);
Packit 1e8aac
  if (error)
Packit 1e8aac
    {
Packit 1e8aac
      g_warning ("Could not convert uri \"%s\" to a local path: %s", uri,
Packit 1e8aac
                 error->message);
Packit 1e8aac
      g_error_free (error);
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  glade_window_open_project (window, path);
Packit 1e8aac
Packit 1e8aac
  g_free (uri);
Packit 1e8aac
  g_free (path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_reference_action_activate (GSimpleAction *action,
Packit 1e8aac
                              GVariant      *parameter,
Packit 1e8aac
                              gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  if (glade_util_have_devhelp ())
Packit 1e8aac
    {
Packit 1e8aac
      glade_util_search_devhelp ("gladeui", NULL, NULL);
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* fallback to displaying online developer manual */
Packit 1e8aac
  glade_util_url_show (URL_DEVELOPER_MANUAL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_preferences_action_activate (GSimpleAction *action,
Packit 1e8aac
                                GVariant      *parameter,
Packit 1e8aac
                                gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  gtk_widget_show (GTK_WIDGET (window->priv->preferences));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_about_action_activate (GSimpleAction *action,
Packit 1e8aac
                          GVariant      *parameter,
Packit 1e8aac
                          gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
Packit 1e8aac
  gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (priv->about_dialog), PACKAGE_VERSION);
Packit 1e8aac
Packit 1e8aac
  gtk_window_present (priv->about_dialog);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
enum
Packit 1e8aac
{
Packit 1e8aac
  TARGET_URI_LIST
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
static GtkTargetEntry drop_types[] = {
Packit 1e8aac
  {"text/uri-list", 0, TARGET_URI_LIST}
Packit 1e8aac
};
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
drag_data_received (GtkWidget *widget,
Packit 1e8aac
                    GdkDragContext *context,
Packit 1e8aac
                    gint x, gint y,
Packit 1e8aac
                    GtkSelectionData *selection_data,
Packit 1e8aac
                    guint info,
Packit 1e8aac
                    guint time,
Packit 1e8aac
                    GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  gchar **uris, **str;
Packit 1e8aac
  const guchar *data;
Packit 1e8aac
Packit 1e8aac
  if (info != TARGET_URI_LIST)
Packit 1e8aac
    return;
Packit 1e8aac
Packit 1e8aac
  data = gtk_selection_data_get_data (selection_data);
Packit 1e8aac
Packit 1e8aac
  uris = g_uri_list_extract_uris ((gchar *) data);
Packit 1e8aac
Packit 1e8aac
  for (str = uris; *str; str++)
Packit 1e8aac
    {
Packit 1e8aac
      GError *error = NULL;
Packit 1e8aac
      gchar *path = g_filename_from_uri (*str, NULL, &error);
Packit 1e8aac
Packit 1e8aac
      if (path)
Packit 1e8aac
        {
Packit 1e8aac
          glade_window_open_project (window, path);
Packit 1e8aac
        }
Packit 1e8aac
      else
Packit 1e8aac
        {
Packit 1e8aac
          g_warning ("Could not convert uri to local path: %s", error->message);
Packit 1e8aac
Packit 1e8aac
          g_error_free (error);
Packit 1e8aac
        }
Packit 1e8aac
      g_free (path);
Packit 1e8aac
    }
Packit 1e8aac
  g_strfreev (uris);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
delete_event (GtkWindow *w, GdkEvent *event, GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  g_action_group_activate_action (window->priv->actions, "quit", NULL);
Packit 1e8aac
Packit 1e8aac
  /* return TRUE to stop other handlers */
Packit 1e8aac
  return TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
add_project (GladeWindow *window, GladeProject *project, gboolean for_file)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  GtkWidget *view, *inspector;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (GLADE_IS_PROJECT (project));
Packit 1e8aac
Packit 1e8aac
  /* Create a new view for project */
Packit 1e8aac
  view = glade_design_view_new (project);
Packit 1e8aac
Packit 1e8aac
  gtk_stack_set_visible_child (priv->stack, priv->center_paned);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::modified",
Packit 1e8aac
                    G_CALLBACK (project_notify_handler_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::path",
Packit 1e8aac
                    G_CALLBACK (project_notify_handler_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::format",
Packit 1e8aac
                    G_CALLBACK (project_notify_handler_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::has-selection",
Packit 1e8aac
                    G_CALLBACK (project_notify_handler_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::read-only",
Packit 1e8aac
                    G_CALLBACK (project_notify_handler_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "notify::pointer-mode",
Packit 1e8aac
                    G_CALLBACK (on_pointer_mode_changed), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "selection-changed",
Packit 1e8aac
                    G_CALLBACK (project_selection_changed_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "targets-changed",
Packit 1e8aac
                    G_CALLBACK (project_targets_changed_cb), window);
Packit 1e8aac
  g_signal_connect (G_OBJECT (project), "changed",
Packit 1e8aac
                    G_CALLBACK (project_changed_cb), window);
Packit 1e8aac
Packit 1e8aac
  /* create inspector */
Packit 1e8aac
  inspector = glade_inspector_new ();
Packit 1e8aac
  g_object_set_data (G_OBJECT (view), "glade-window-view-inspector", inspector);
Packit 1e8aac
  glade_inspector_set_project (GLADE_INSPECTOR (inspector), project);
Packit 1e8aac
  gtk_container_add (GTK_CONTAINER (priv->inspectors_stack), inspector);
Packit 1e8aac
  gtk_widget_show (inspector);
Packit 1e8aac
Packit 1e8aac
  set_sensitivity_according_to_project (window, project);
Packit 1e8aac
Packit 1e8aac
  project_actions_set_enabled (window, TRUE);
Packit 1e8aac
Packit 1e8aac
  /* Pass ownership of the project to the app */
Packit 1e8aac
  glade_app_add_project (project);
Packit 1e8aac
  g_object_unref (project);
Packit 1e8aac
Packit 1e8aac
  /* Add view to stack */
Packit 1e8aac
  gtk_container_add (GTK_CONTAINER (priv->view_stack), view);
Packit 1e8aac
  gtk_widget_show (view);
Packit 1e8aac
  gtk_stack_set_visible_child (priv->view_stack, view);
Packit 1e8aac
Packit 1e8aac
  refresh_stack_title_for_project (window, project);
Packit 1e8aac
  refresh_title (window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_registration_action_activate (GSimpleAction *action,
Packit 1e8aac
                                 GVariant      *parameter,
Packit 1e8aac
                                 gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  gtk_window_present (GTK_WINDOW (window->priv->registration));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
on_undo_button_button_press_event (GtkWidget   *widget,
Packit 1e8aac
                                   GdkEvent    *event,
Packit 1e8aac
                                   GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (project && event->button.button == 3)
Packit 1e8aac
    gtk_menu_popup_at_widget (GTK_MENU (glade_project_undo_items (project)),
Packit 1e8aac
                              widget,
Packit 1e8aac
                              GDK_GRAVITY_NORTH_WEST,
Packit 1e8aac
                              GDK_GRAVITY_SOUTH_WEST,
Packit 1e8aac
                              event);
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
on_redo_button_button_press_event (GtkWidget   *widget,
Packit 1e8aac
                                   GdkEvent    *event,
Packit 1e8aac
                                   GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project = get_active_project (window);
Packit 1e8aac
Packit 1e8aac
  if (project && event->button.button == 3)
Packit 1e8aac
    gtk_menu_popup_at_widget (GTK_MENU (glade_project_redo_items (project)),
Packit 1e8aac
                              widget,
Packit 1e8aac
                              GDK_GRAVITY_NORTH_WEST,
Packit 1e8aac
                              GDK_GRAVITY_SOUTH_WEST,
Packit 1e8aac
                              event);
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_window_new_project (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (GLADE_IS_WINDOW (window));
Packit 1e8aac
Packit 1e8aac
  project = glade_project_new ();
Packit 1e8aac
  if (!project)
Packit 1e8aac
    {
Packit 1e8aac
      glade_util_ui_message (GTK_WIDGET (window),
Packit 1e8aac
                             GLADE_UI_ERROR, NULL,
Packit 1e8aac
                             _("Could not create a new project."));
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
  add_project (window, project, FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_new_action_activate (GSimpleAction *action,
Packit 1e8aac
                        GVariant      *parameter,
Packit 1e8aac
                        gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  glade_window_new_project (data);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
open_project (GladeWindow *window, const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  project = glade_project_new ();
Packit 1e8aac
Packit 1e8aac
  add_project (window, project, TRUE);
Packit 1e8aac
  update_default_path (window, path);
Packit 1e8aac
Packit 1e8aac
  if (!glade_project_load_from_file (project, path))
Packit 1e8aac
    {
Packit 1e8aac
      close_project (window, project);
Packit 1e8aac
Packit 1e8aac
      recent_remove (window, path);
Packit 1e8aac
      return FALSE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* increase project popularity */
Packit 1e8aac
  recent_add (window, glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
  return TRUE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
check_reload_project (GladeWindow *window, GladeProject *project)
Packit 1e8aac
{
Packit 1e8aac
  gchar *path;
Packit 1e8aac
  GtkWidget *dialog;
Packit 1e8aac
  GtkWidget *button;
Packit 1e8aac
  gint response;
Packit 1e8aac
Packit 1e8aac
  /* Reopen the project if it has external modifications.
Packit 1e8aac
   * Prompt for permission to reopen.
Packit 1e8aac
   */
Packit 1e8aac
  if ((glade_util_get_file_mtime (glade_project_get_path (project), NULL)
Packit 1e8aac
       <= glade_project_get_file_mtime (project)))
Packit 1e8aac
    {
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (glade_project_get_modified (project))
Packit 1e8aac
    {
Packit 1e8aac
      dialog = gtk_message_dialog_new (GTK_WINDOW (window),
Packit 1e8aac
                                       GTK_DIALOG_MODAL,
Packit 1e8aac
                                       GTK_MESSAGE_WARNING,
Packit 1e8aac
                                       GTK_BUTTONS_NONE,
Packit 1e8aac
                                       _("The project %s has unsaved changes"),
Packit 1e8aac
                                       glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit 1e8aac
                                                _
Packit 1e8aac
                                                ("If you reload it, all unsaved changes "
Packit 1e8aac
                                                 "could be lost. Reload it anyway?"));
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      dialog = gtk_message_dialog_new (GTK_WINDOW (window),
Packit 1e8aac
                                       GTK_DIALOG_MODAL,
Packit 1e8aac
                                       GTK_MESSAGE_WARNING,
Packit 1e8aac
                                       GTK_BUTTONS_NONE,
Packit 1e8aac
                                       _
Packit 1e8aac
                                       ("The project file %s has been externally modified"),
Packit 1e8aac
                                       glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit 1e8aac
                                                _
Packit 1e8aac
                                                ("Do you want to reload the project?"));
Packit 1e8aac
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  gtk_window_set_title (GTK_WINDOW (dialog), "");
Packit 1e8aac
Packit 1e8aac
  button = gtk_button_new_with_mnemonic (_("_Reload"));
Packit 1e8aac
  gtk_button_set_image (GTK_BUTTON (button),
Packit 1e8aac
                        gtk_image_new_from_icon_name ("view-refresh",
Packit 1e8aac
                                                      GTK_ICON_SIZE_BUTTON));
Packit 1e8aac
  gtk_widget_show (button);
Packit 1e8aac
Packit 1e8aac
  gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Cancel"), GTK_RESPONSE_REJECT);
Packit 1e8aac
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
Packit 1e8aac
                                GTK_RESPONSE_ACCEPT);
Packit 1e8aac
Packit 1e8aac
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
Packit 1e8aac
Packit 1e8aac
  response = gtk_dialog_run (GTK_DIALOG (dialog));
Packit 1e8aac
Packit 1e8aac
  gtk_widget_destroy (dialog);
Packit 1e8aac
Packit 1e8aac
  if (response == GTK_RESPONSE_REJECT)
Packit 1e8aac
    {
Packit 1e8aac
      return;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  /* Reopen */
Packit 1e8aac
  path = g_strdup (glade_project_get_path (project));
Packit 1e8aac
Packit 1e8aac
  close_project (window, project);
Packit 1e8aac
  open_project (window, path);
Packit 1e8aac
  g_free (path);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
/**
Packit 1e8aac
 * glade_window_open_project:
Packit 1e8aac
 * @window: a #GladeWindow
Packit 1e8aac
 * @path: the filesystem path of the project
Packit 1e8aac
 *
Packit 1e8aac
 * Opens a project file. If the project is already open, switch to that
Packit 1e8aac
 * project.
Packit 1e8aac
 *
Packit 1e8aac
 * Returns: #TRUE if the project was opened
Packit 1e8aac
 */
Packit 1e8aac
gboolean
Packit 1e8aac
glade_window_open_project (GladeWindow *window, const gchar *path)
Packit 1e8aac
{
Packit 1e8aac
  GladeProject *project;
Packit 1e8aac
Packit 1e8aac
  g_return_val_if_fail (GLADE_IS_WINDOW (window), FALSE);
Packit 1e8aac
  g_return_val_if_fail (path != NULL, FALSE);
Packit 1e8aac
Packit 1e8aac
  /* dont allow a project to be opened twice */
Packit 1e8aac
  project = glade_app_get_project_by_path (path);
Packit 1e8aac
  if (project)
Packit 1e8aac
    {
Packit 1e8aac
      /* just switch to the project */
Packit 1e8aac
      switch_to_project (window, project);
Packit 1e8aac
      return TRUE;
Packit 1e8aac
    }
Packit 1e8aac
  else
Packit 1e8aac
    {
Packit 1e8aac
      return open_project (window, path);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_dispose (GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = GLADE_WINDOW (object);
Packit 1e8aac
Packit 1e8aac
  g_clear_object (&window->priv->app);
Packit 1e8aac
  g_clear_object (&window->priv->registration);
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_window_parent_class)->dispose (object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_finalize (GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  g_free (GLADE_WINDOW (object)->priv->default_path);
Packit 1e8aac
Packit 1e8aac
  G_OBJECT_CLASS (glade_window_parent_class)->finalize (object);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
glade_window_configure_event (GtkWidget *widget, GdkEventConfigure *event)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = GLADE_WINDOW (widget);
Packit 1e8aac
  gboolean retval;
Packit 1e8aac
Packit 1e8aac
  gboolean is_maximized;
Packit 1e8aac
  GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
Packit 1e8aac
  is_maximized = gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_MAXIMIZED;
Packit 1e8aac
Packit 1e8aac
  if (!is_maximized)
Packit 1e8aac
    {
Packit 1e8aac
      window->priv->position.width = event->width;
Packit 1e8aac
      window->priv->position.height = event->height;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  retval =
Packit 1e8aac
      GTK_WIDGET_CLASS (glade_window_parent_class)->configure_event (widget,
Packit 1e8aac
                                                                     event);
Packit 1e8aac
Packit 1e8aac
  if (!is_maximized)
Packit 1e8aac
    {
Packit 1e8aac
      gtk_window_get_position (GTK_WINDOW (widget),
Packit 1e8aac
                               &window->priv->position.x,
Packit 1e8aac
                               &window->priv->position.y);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  return retval;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
key_file_set_window_position (GKeyFile *config,
Packit 1e8aac
                              GdkRectangle *position,
Packit 1e8aac
                              const char *id,
Packit 1e8aac
                              gboolean maximized)
Packit 1e8aac
{
Packit 1e8aac
  char *key_x, *key_y, *key_width, *key_height, *key_maximized;
Packit 1e8aac
Packit 1e8aac
  key_x = g_strdup_printf ("%s-" CONFIG_KEY_X, id);
Packit 1e8aac
  key_y = g_strdup_printf ("%s-" CONFIG_KEY_Y, id);
Packit 1e8aac
  key_width = g_strdup_printf ("%s-" CONFIG_KEY_WIDTH, id);
Packit 1e8aac
  key_height = g_strdup_printf ("%s-" CONFIG_KEY_HEIGHT, id);
Packit 1e8aac
  key_maximized = g_strdup_printf ("%s-" CONFIG_KEY_MAXIMIZED, id);
Packit 1e8aac
Packit 1e8aac
  if (position->x > G_MININT)
Packit 1e8aac
    g_key_file_set_integer (config, CONFIG_GROUP_WINDOWS, key_x, position->x);
Packit 1e8aac
  if (position->y > G_MININT)
Packit 1e8aac
    g_key_file_set_integer (config, CONFIG_GROUP_WINDOWS, key_y, position->y);
Packit 1e8aac
Packit 1e8aac
  g_key_file_set_integer (config, CONFIG_GROUP_WINDOWS,
Packit 1e8aac
                          key_width, position->width);
Packit 1e8aac
  g_key_file_set_integer (config, CONFIG_GROUP_WINDOWS,
Packit 1e8aac
                          key_height, position->height);
Packit 1e8aac
Packit 1e8aac
  g_key_file_set_boolean (config, CONFIG_GROUP_WINDOWS,
Packit 1e8aac
                          key_maximized, maximized);
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
  g_free (key_maximized);
Packit 1e8aac
  g_free (key_height);
Packit 1e8aac
  g_free (key_width);
Packit 1e8aac
  g_free (key_y);
Packit 1e8aac
  g_free (key_x);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
save_windows_config (GladeWindow *window, GKeyFile *config)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  GdkWindow *gdk_window;
Packit 1e8aac
  gboolean maximized;
Packit 1e8aac
Packit 1e8aac
  gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
Packit 1e8aac
  maximized = gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_MAXIMIZED;
Packit 1e8aac
Packit 1e8aac
  key_file_set_window_position (config, &priv->position, "main", maximized);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
save_paned_position (GKeyFile *config, GtkWidget *paned, const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
  g_key_file_set_integer (config, name, "position",
Packit 1e8aac
                          gtk_paned_get_position (GTK_PANED (paned)));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_config_save (GladeWindow * window)
Packit 1e8aac
{
Packit 1e8aac
  GKeyFile *config = glade_app_get_config ();
Packit 1e8aac
Packit 1e8aac
  save_windows_config (window, config);
Packit 1e8aac
Packit 1e8aac
  /* Save main window paned positions */
Packit 1e8aac
  save_paned_position (config, window->priv->center_paned, "center_pane");
Packit 1e8aac
  save_paned_position (config, window->priv->left_paned, "left_pane");
Packit 1e8aac
Packit 1e8aac
  glade_preferences_save (window->priv->preferences, config);
Packit 1e8aac
Packit 1e8aac
  glade_app_config_save ();
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static int
Packit 1e8aac
key_file_get_int (GKeyFile *config,
Packit 1e8aac
                  const char *group,
Packit 1e8aac
                  const char *key,
Packit 1e8aac
                  int default_value)
Packit 1e8aac
{
Packit 1e8aac
  if (g_key_file_has_key (config, group, key, NULL))
Packit 1e8aac
    return g_key_file_get_integer (config, group, key, NULL);
Packit 1e8aac
  else
Packit 1e8aac
    return default_value;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
key_file_get_window_position (GKeyFile *config,
Packit 1e8aac
                              const char *id,
Packit 1e8aac
                              GdkRectangle *pos,
Packit 1e8aac
                              gboolean *maximized)
Packit 1e8aac
{
Packit 1e8aac
  char *key_x, *key_y, *key_width, *key_height, *key_maximized;
Packit 1e8aac
Packit 1e8aac
  key_x = g_strdup_printf ("%s-" CONFIG_KEY_X, id);
Packit 1e8aac
  key_y = g_strdup_printf ("%s-" CONFIG_KEY_Y, id);
Packit 1e8aac
  key_width = g_strdup_printf ("%s-" CONFIG_KEY_WIDTH, id);
Packit 1e8aac
  key_height = g_strdup_printf ("%s-" CONFIG_KEY_HEIGHT, id);
Packit 1e8aac
  key_maximized = g_strdup_printf ("%s-" CONFIG_KEY_MAXIMIZED, id);
Packit 1e8aac
Packit 1e8aac
  pos->x = key_file_get_int (config, CONFIG_GROUP_WINDOWS, key_x, pos->x);
Packit 1e8aac
  pos->y = key_file_get_int (config, CONFIG_GROUP_WINDOWS, key_y, pos->y);
Packit 1e8aac
  pos->width =
Packit 1e8aac
      key_file_get_int (config, CONFIG_GROUP_WINDOWS, key_width, pos->width);
Packit 1e8aac
  pos->height =
Packit 1e8aac
      key_file_get_int (config, CONFIG_GROUP_WINDOWS, key_height, pos->height);
Packit 1e8aac
Packit 1e8aac
  if (maximized)
Packit 1e8aac
    {
Packit 1e8aac
      if (g_key_file_has_key
Packit 1e8aac
          (config, CONFIG_GROUP_WINDOWS, key_maximized, NULL))
Packit 1e8aac
        *maximized =
Packit 1e8aac
            g_key_file_get_boolean (config, CONFIG_GROUP_WINDOWS, key_maximized,
Packit 1e8aac
                                    NULL);
Packit 1e8aac
      else
Packit 1e8aac
        *maximized = FALSE;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  g_free (key_x);
Packit 1e8aac
  g_free (key_y);
Packit 1e8aac
  g_free (key_width);
Packit 1e8aac
  g_free (key_height);
Packit 1e8aac
  g_free (key_maximized);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
load_paned_position (GKeyFile *config,
Packit 1e8aac
                     GtkWidget *pane,
Packit 1e8aac
                     const gchar *name,
Packit 1e8aac
                     gint default_position)
Packit 1e8aac
{
Packit 1e8aac
  gtk_paned_set_position (GTK_PANED (pane),
Packit 1e8aac
                          key_file_get_int (config, name, "position",
Packit 1e8aac
                                            default_position));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
fix_paned_positions_idle (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  /* When initially maximized/fullscreened we need to deffer this operation 
Packit 1e8aac
   */
Packit 1e8aac
  GKeyFile *config = glade_app_get_config ();
Packit 1e8aac
Packit 1e8aac
  load_paned_position (config, window->priv->left_paned, "left_pane", 200);
Packit 1e8aac
  load_paned_position (config, window->priv->center_paned, "center_pane", 400);
Packit 1e8aac
Packit 1e8aac
  return FALSE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_set_initial_size (GladeWindow *window, GKeyFile *config)
Packit 1e8aac
{
Packit 1e8aac
  GdkRectangle position = {
Packit 1e8aac
    G_MININT, G_MININT, GLADE_WINDOW_DEFAULT_WIDTH, GLADE_WINDOW_DEFAULT_HEIGHT
Packit 1e8aac
  };
Packit 1e8aac
Packit 1e8aac
  gboolean maximized;
Packit 1e8aac
Packit 1e8aac
  key_file_get_window_position (config, "main", &position, &maximized);
Packit 1e8aac
  if (maximized)
Packit 1e8aac
    {
Packit 1e8aac
      gtk_window_maximize (GTK_WINDOW (window));
Packit 1e8aac
      g_timeout_add (200, (GSourceFunc) fix_paned_positions_idle, window);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  if (position.width <= 0 || position.height <= 0)
Packit 1e8aac
    {
Packit 1e8aac
      position.width = GLADE_WINDOW_DEFAULT_WIDTH;
Packit 1e8aac
      position.height = GLADE_WINDOW_DEFAULT_HEIGHT;
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  gtk_window_set_default_size (GTK_WINDOW (window), position.width,
Packit 1e8aac
                               position.height);
Packit 1e8aac
Packit 1e8aac
  if (position.x > G_MININT && position.y > G_MININT)
Packit 1e8aac
    gtk_window_move (GTK_WINDOW (window), position.x, position.y);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_config_load (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GKeyFile *config = glade_app_get_config ();
Packit 1e8aac
Packit 1e8aac
  /* Initial main dimensions */
Packit 1e8aac
  glade_window_set_initial_size (window, config);
Packit 1e8aac
Packit 1e8aac
  /* Paned positions */
Packit 1e8aac
  load_paned_position (config, window->priv->left_paned, "left_pane", 200);
Packit 1e8aac
  load_paned_position (config, window->priv->center_paned, "center_pane", 400);
Packit 1e8aac
Packit 1e8aac
  /* Intro button */
Packit 1e8aac
  if (g_key_file_get_boolean (config, CONFIG_INTRO_GROUP, CONFIG_INTRO_DONE, FALSE))
Packit 1e8aac
    gtk_widget_hide (window->priv->intro_button);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_quit_action_activate (GSimpleAction *action,
Packit 1e8aac
                         GVariant      *parameter,
Packit 1e8aac
                         gpointer       data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  GList *list, *projects;
Packit 1e8aac
Packit 1e8aac
  projects = g_list_copy (glade_app_get_projects ());
Packit 1e8aac
Packit 1e8aac
  for (list = projects; list; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *project = GLADE_PROJECT (list->data);
Packit 1e8aac
Packit 1e8aac
      if (glade_project_get_modified (project))
Packit 1e8aac
        {
Packit 1e8aac
          gboolean quit = confirm_close_project (window, project);
Packit 1e8aac
          if (!quit)
Packit 1e8aac
            {
Packit 1e8aac
              g_list_free (projects);
Packit 1e8aac
              return;
Packit 1e8aac
            }
Packit 1e8aac
        }
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  for (list = projects; list; list = list->next)
Packit 1e8aac
    {
Packit 1e8aac
      GladeProject *project = GLADE_PROJECT (glade_app_get_projects ()->data);
Packit 1e8aac
      close_project (window, project);
Packit 1e8aac
    }
Packit 1e8aac
Packit 1e8aac
  glade_window_config_save (window);
Packit 1e8aac
Packit 1e8aac
  g_list_free (projects);
Packit 1e8aac
Packit 1e8aac
  gtk_main_quit ();
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_pointer_select_action_activate (GSimpleAction *action, GVariant *p, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  glade_project_set_pointer_mode (get_active_project (data), GLADE_POINTER_SELECT);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_pointer_align_edit_action_activate (GSimpleAction *action, GVariant *p, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  glade_project_set_pointer_mode (get_active_project (data), GLADE_POINTER_ALIGN_EDIT);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_pointer_drag_resize_action_activate (GSimpleAction *action, GVariant *p, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  glade_project_set_pointer_mode (get_active_project (data), GLADE_POINTER_DRAG_RESIZE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_pointer_margin_edit_action_activate (GSimpleAction *action, GVariant *p, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  glade_project_set_pointer_mode (get_active_project (data), GLADE_POINTER_MARGIN_EDIT);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_intro_action_activate (GSimpleAction *action, GVariant *p, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindow *window = data;
Packit 1e8aac
  gtk_widget_show (window->priv->intro_button);
Packit 1e8aac
  glade_intro_play (window->priv->intro);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_init (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv;
Packit 1e8aac
Packit 1e8aac
  window->priv = priv = glade_window_get_instance_private (window);
Packit 1e8aac
Packit 1e8aac
  priv->default_path = NULL;
Packit 1e8aac
Packit 1e8aac
  /* Init preferences first, this has to be done before anything initializes
Packit 1e8aac
   * the real GladeApp, so that catalog paths are loaded correctly before we
Packit 1e8aac
   * continue.
Packit 1e8aac
   *
Packit 1e8aac
   * This should be fixed so that dynamic addition of catalogs at runtime
Packit 1e8aac
   * is supported.
Packit 1e8aac
   */
Packit 1e8aac
  priv->preferences = (GladePreferences *)glade_preferences_new ();
Packit 1e8aac
  glade_preferences_load (window->priv->preferences, glade_app_get_config ());
Packit 1e8aac
Packit 1e8aac
  /* We need this for the icons to be available */
Packit 1e8aac
  glade_init ();
Packit 1e8aac
Packit 1e8aac
  gtk_widget_init_template (GTK_WIDGET (window));
Packit 1e8aac
Packit 1e8aac
  gtk_box_set_homogeneous (GTK_BOX (priv->open_button_box), FALSE);
Packit 1e8aac
  gtk_box_set_homogeneous (GTK_BOX (priv->save_button_box), FALSE);
Packit 1e8aac
Packit 1e8aac
  priv->registration = glade_registration_new ();
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_action_handler (GladeWindow *window, const gchar *name)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  GAction *action;
Packit 1e8aac
Packit 1e8aac
  if ((action = g_action_map_lookup_action (G_ACTION_MAP (priv->actions), name)))
Packit 1e8aac
    g_action_activate (action, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
switch_foreach (GtkWidget *widget, gpointer data)
Packit 1e8aac
{
Packit 1e8aac
  GtkWidget *parent = gtk_widget_get_parent (widget);
Packit 1e8aac
  gint pos;
Packit 1e8aac
Packit 1e8aac
  gtk_container_child_get (GTK_CONTAINER(parent), widget, "position", &pos, NULL);
Packit 1e8aac
Packit 1e8aac
  if (pos == GPOINTER_TO_INT (data))
Packit 1e8aac
    gtk_stack_set_visible_child (GTK_STACK (parent), widget);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_switch_handler (GladeWindow *window, gint index)
Packit 1e8aac
{
Packit 1e8aac
  gtk_container_foreach (GTK_CONTAINER (window->priv->view_stack),
Packit 1e8aac
                         switch_foreach, GINT_TO_POINTER (index));
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static gboolean
Packit 1e8aac
intro_continue (gpointer intro)
Packit 1e8aac
{
Packit 1e8aac
  glade_intro_play (intro);
Packit 1e8aac
  return G_SOURCE_REMOVE;
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_intro_project_add_widget (GladeProject *project,
Packit 1e8aac
                             GladeWidget  *widget,
Packit 1e8aac
                             GladeWindow  *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (widget);
Packit 1e8aac
Packit 1e8aac
  if (glade_widget_adaptor_get_object_type (adaptor) == window->priv->new_type)
Packit 1e8aac
    {
Packit 1e8aac
      g_idle_add (intro_continue, window->priv->intro);
Packit 1e8aac
Packit 1e8aac
      if (window->priv->new_type == GTK_TYPE_BUTTON)
Packit 1e8aac
        g_signal_handlers_disconnect_by_func (project, on_intro_project_add_widget, window);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_user_new_action_activate (GSimpleAction *simple,
Packit 1e8aac
                             GVariant      *parameter,
Packit 1e8aac
                             GladeWindow   *window)
Packit 1e8aac
{
Packit 1e8aac
  g_signal_connect (get_active_project (window), "add-widget",
Packit 1e8aac
                    G_CALLBACK (on_intro_project_add_widget),
Packit 1e8aac
                    window);
Packit 1e8aac
Packit 1e8aac
  glade_intro_play (window->priv->intro);
Packit 1e8aac
Packit 1e8aac
  g_signal_handlers_disconnect_by_func (simple, on_user_new_action_activate, window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_intro_show_node (GladeIntro  *intro,
Packit 1e8aac
                    const gchar *node,
Packit 1e8aac
                    GtkWidget   *widget,
Packit 1e8aac
                    GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  if (!g_strcmp0 (node, "new-project"))
Packit 1e8aac
    {
Packit 1e8aac
      /* Create two new project to make the project switcher visible */
Packit 1e8aac
      g_action_group_activate_action (window->priv->actions, "new", NULL);
Packit 1e8aac
      g_action_group_activate_action (window->priv->actions, "new", NULL);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "add-project"))
Packit 1e8aac
    {
Packit 1e8aac
      GAction *new_action = g_action_map_lookup_action (G_ACTION_MAP (priv->actions), "new");
Packit 1e8aac
Packit 1e8aac
      g_signal_connect (new_action, "activate",
Packit 1e8aac
                        G_CALLBACK (on_user_new_action_activate),
Packit 1e8aac
                        window);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "add-window"))
Packit 1e8aac
    {
Packit 1e8aac
      window->priv->new_type = GTK_TYPE_WINDOW;
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "add-grid"))
Packit 1e8aac
    {
Packit 1e8aac
      window->priv->new_type = GTK_TYPE_GRID;
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "add-button"))
Packit 1e8aac
    {
Packit 1e8aac
      window->priv->new_type = GTK_TYPE_BUTTON;
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "search") ||
Packit 1e8aac
           !g_strcmp0 (node, "others"))
Packit 1e8aac
    {
Packit 1e8aac
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "gtk"))
Packit 1e8aac
    {
Packit 1e8aac
      GList *children;
Packit 1e8aac
Packit 1e8aac
      if ((children = gtk_container_get_children (GTK_CONTAINER (widget))))
Packit 1e8aac
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (children->data), TRUE);
Packit 1e8aac
Packit 1e8aac
      g_list_free (children);
Packit 1e8aac
    }
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
on_intro_hide_node (GladeIntro  *intro,
Packit 1e8aac
                    const gchar *node,
Packit 1e8aac
                    GtkWidget   *widget,
Packit 1e8aac
                    GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  if (!g_strcmp0 (node, "search") ||
Packit 1e8aac
      !g_strcmp0 (node, "others"))
Packit 1e8aac
    {
Packit 1e8aac
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "gtk"))
Packit 1e8aac
    {
Packit 1e8aac
      GList *children;
Packit 1e8aac
Packit 1e8aac
      if ((children = gtk_container_get_children (GTK_CONTAINER (widget))))
Packit 1e8aac
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (children->data), FALSE);
Packit 1e8aac
Packit 1e8aac
      g_list_free (children);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "done"))
Packit 1e8aac
    {
Packit 1e8aac
      gtk_widget_hide (window->priv->intro_button);
Packit 1e8aac
      g_key_file_set_boolean (glade_app_get_config (),
Packit 1e8aac
                              CONFIG_INTRO_GROUP,
Packit 1e8aac
                              CONFIG_INTRO_DONE,
Packit 1e8aac
                              TRUE);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!g_strcmp0 (node, "add-project") ||
Packit 1e8aac
           !g_strcmp0 (node, "add-window") ||
Packit 1e8aac
           !g_strcmp0 (node, "add-grid") ||
Packit 1e8aac
           !g_strcmp0 (node, "add-button"))
Packit 1e8aac
    glade_intro_pause (window->priv->intro);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
#define ADD_NODE(n,w,P,d,t) glade_intro_script_add (window->priv->intro, n, w, t, GLADE_INTRO_##P, d)
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_populate_intro (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  ADD_NODE (NULL, "intro-button",  BOTTOM, 5, _("Hello, I will show you what's new in Glade"));
Packit 1e8aac
  ADD_NODE (NULL, "headerbar",     BOTTOM, 6, _("The menubar and toolbar were merged in the headerbar"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL, "open-button",   BOTTOM, 3, _("You can open a project"));
Packit 1e8aac
  ADD_NODE (NULL, "recent-button", BOTTOM, 2, _("find recently used"));
Packit 1e8aac
  ADD_NODE (NULL, "new-button",    BOTTOM, 2, _("or create a new one"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE ("new-project", NULL,       NONE, .75, NULL);
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL, "undo-button",       BOTTOM, 2, _("Undo"));
Packit 1e8aac
  ADD_NODE (NULL, "redo-button",       BOTTOM, 2, _("Redo"));
Packit 1e8aac
  ADD_NODE (NULL, "project-switcher",  BOTTOM, 3, _("Project switcher"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL, "save-button",       BOTTOM, 4, _("and Save button are directly accessible in the headerbar"));
Packit 1e8aac
  ADD_NODE (NULL, "save-as-button",    BOTTOM, 2, _("just like Save As"));
Packit 1e8aac
  ADD_NODE (NULL, "properties-button", BOTTOM, 2, _("project properties"));
Packit 1e8aac
  ADD_NODE (NULL, "menu-button",       BOTTOM, 3, _("and less commonly used actions"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL, "inspector", CENTER, 3, _("The object inspector took the palette's place"));
Packit 1e8aac
  ADD_NODE (NULL, "editor",    CENTER, 3, _("To free up space for the property editor"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL,      "adaptor-chooser",       BOTTOM, 4, _("The palette was replaced with a new object chooser"));
Packit 1e8aac
  ADD_NODE ("search",  "adaptor-search-button", RIGHT,  3, _("Where you can search all supported classes"));
Packit 1e8aac
  ADD_NODE ("gtk",     "adaptor-gtk-buttonbox", BOTTOM, 2.5, _("investigate GTK+ object groups"));
Packit 1e8aac
  ADD_NODE ("others",  "adaptor-others-button", RIGHT,  4, _("and find classes introduced by other libraries"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL, "intro-button", BOTTOM, 6, _("OK, now that we are done with the overview, let's start with the new workflow"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE ("add-project", "intro-button", BOTTOM, 4, _("First of all, create a new project"));
Packit 1e8aac
  ADD_NODE ("add-window",  "intro-button", BOTTOM, 6, _("OK, now add a GtkWindow using the new widget chooser or by double clicking on the workspace"));
Packit 1e8aac
  ADD_NODE (NULL,          "intro-button", BOTTOM, 2, _("Excellent!"));
Packit 1e8aac
  ADD_NODE (NULL,          "intro-button", BOTTOM, 5, _("BTW, did you know you can double click on any placeholder to create widgets?"));
Packit 1e8aac
  ADD_NODE ("add-grid",    "intro-button", BOTTOM, 3, _("Try adding a grid"));
Packit 1e8aac
  ADD_NODE ("add-button",  "intro-button", BOTTOM, 3, _("and a button"));
Packit 1e8aac
Packit 1e8aac
  ADD_NODE (NULL,   "intro-button",  BOTTOM, 3, _("Quite easy! Isn't it?"));
Packit 1e8aac
  ADD_NODE ("done", "intro-button",  BOTTOM, 2, _("Enjoy!"));
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (window->priv->intro, "show-node",
Packit 1e8aac
                    G_CALLBACK (on_intro_show_node),
Packit 1e8aac
                    window);
Packit 1e8aac
  g_signal_connect (window->priv->intro, "hide-node",
Packit 1e8aac
                    G_CALLBACK (on_intro_hide_node),
Packit 1e8aac
                    window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_constructed (GObject *object)
Packit 1e8aac
{
Packit 1e8aac
  static GActionEntry actions[] = {
Packit 1e8aac
    { "open",         on_open_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "new",          on_new_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "registration", on_registration_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "intro",        on_intro_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "reference",    on_reference_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "preferences",  on_preferences_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "about",        on_about_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "quit",         on_quit_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    /* Project actions */
Packit 1e8aac
    { "close",        on_close_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "save",         on_save_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "save_as",      on_save_as_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "properties",   on_properties_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "undo",         on_undo_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "redo",         on_redo_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "cut",          on_cut_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "copy",         on_copy_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "paste",        on_paste_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "delete",       on_delete_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "previous",     on_previous_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "next",         on_next_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    /* Pointer mode actions */
Packit 1e8aac
    { "select",       on_pointer_select_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "drag_resize",  on_pointer_drag_resize_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "margin_edit",  on_pointer_margin_edit_action_activate, NULL, NULL, NULL },
Packit 1e8aac
    { "align_edit",   on_pointer_align_edit_action_activate, NULL, NULL, NULL },
Packit 1e8aac
  };
Packit 1e8aac
  GladeWindow *window = GLADE_WINDOW (object);
Packit 1e8aac
  GladeWindowPrivate *priv = window->priv;
Packit 1e8aac
  gchar *version;
Packit 1e8aac
Packit 1e8aac
  /* Chain up... */
Packit 1e8aac
  G_OBJECT_CLASS (glade_window_parent_class)->constructed (object);
Packit 1e8aac
Packit 1e8aac
  /* Init Glade version */
Packit 1e8aac
  version = g_strdup_printf ("%d.%d.%d", GLADE_MAJOR_VERSION, GLADE_MINOR_VERSION, GLADE_MICRO_VERSION);
Packit 1e8aac
  gtk_label_set_text (priv->version_label, version);
Packit 1e8aac
  g_free (version);
Packit 1e8aac
Packit 1e8aac
  /* recent files */
Packit 1e8aac
  priv->recent_manager = gtk_recent_manager_get_default ();
Packit 1e8aac
Packit 1e8aac
  /* Setup Actions */
Packit 1e8aac
  priv->actions = (GActionGroup *) g_simple_action_group_new ();
Packit 1e8aac
  g_action_map_add_action_entries (G_ACTION_MAP (priv->actions), actions, G_N_ELEMENTS (actions), window);
Packit 1e8aac
  gtk_widget_insert_action_group (GTK_WIDGET (window), "app", priv->actions);
Packit 1e8aac
Packit 1e8aac
  /* status bar */
Packit 1e8aac
  priv->statusbar_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar), "general");
Packit 1e8aac
  priv->statusbar_menu_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar), "menu");
Packit 1e8aac
  priv->statusbar_actions_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (priv->statusbar), "actions");
Packit 1e8aac
Packit 1e8aac
  /* support for opening a file by dragging onto the project window */
Packit 1e8aac
  gtk_drag_dest_set (GTK_WIDGET (window),
Packit 1e8aac
                     GTK_DEST_DEFAULT_ALL,
Packit 1e8aac
                     drop_types, G_N_ELEMENTS (drop_types),
Packit 1e8aac
                     GDK_ACTION_COPY | GDK_ACTION_MOVE);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (G_OBJECT (window), "drag-data-received",
Packit 1e8aac
                    G_CALLBACK (drag_data_received), window);
Packit 1e8aac
Packit 1e8aac
  g_signal_connect (G_OBJECT (window), "delete-event",
Packit 1e8aac
                    G_CALLBACK (delete_event), window);
Packit 1e8aac
Packit 1e8aac
  /* GtkWindow events */
Packit 1e8aac
  g_signal_connect (G_OBJECT (window), "key-press-event",
Packit 1e8aac
                    G_CALLBACK (glade_utils_hijack_key_press), window);
Packit 1e8aac
Packit 1e8aac
  /* Load configuration, we need the list of extra catalog paths before creating
Packit 1e8aac
   * the GladeApp
Packit 1e8aac
   */
Packit 1e8aac
  glade_window_config_load (window);
Packit 1e8aac
Packit 1e8aac
  /* Create GladeApp singleton, this will load all catalogs */
Packit 1e8aac
  priv->app = glade_app_new ();
Packit 1e8aac
  glade_app_set_window (GTK_WIDGET (window));
Packit 1e8aac
Packit 1e8aac
  /* Clipboard signals */
Packit 1e8aac
  g_signal_connect (G_OBJECT (glade_app_get_clipboard ()),
Packit 1e8aac
                    "notify::has-selection",
Packit 1e8aac
                    G_CALLBACK (clipboard_notify_handler_cb), window);
Packit 1e8aac
Packit 1e8aac
  priv->intro = glade_intro_new (GTK_WINDOW (window));
Packit 1e8aac
  glade_window_populate_intro (window);
Packit 1e8aac
Packit 1e8aac
  refresh_title (window);
Packit 1e8aac
  project_actions_set_enabled (window, FALSE);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
#define DEFINE_ACTION_SIGNAL(klass, name, handler,...) \
Packit 1e8aac
  g_signal_new_class_handler (name, \
Packit 1e8aac
                              G_TYPE_FROM_CLASS (klass), \
Packit 1e8aac
                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, \
Packit 1e8aac
                              G_CALLBACK (handler), \
Packit 1e8aac
                              NULL, NULL, NULL, \
Packit 1e8aac
                              G_TYPE_NONE, __VA_ARGS__)
Packit 1e8aac
Packit 1e8aac
static void
Packit 1e8aac
glade_window_class_init (GladeWindowClass *klass)
Packit 1e8aac
{
Packit 1e8aac
  GObjectClass *object_class;
Packit 1e8aac
  GtkWidgetClass *widget_class;
Packit 1e8aac
  GtkCssProvider *provider;
Packit 1e8aac
Packit 1e8aac
  object_class = G_OBJECT_CLASS (klass);
Packit 1e8aac
  widget_class = GTK_WIDGET_CLASS (klass);
Packit 1e8aac
Packit 1e8aac
  object_class->constructed = glade_window_constructed;
Packit 1e8aac
  object_class->dispose = glade_window_dispose;
Packit 1e8aac
  object_class->finalize = glade_window_finalize;
Packit 1e8aac
Packit 1e8aac
  widget_class->configure_event = glade_window_configure_event;
Packit 1e8aac
Packit 1e8aac
  DEFINE_ACTION_SIGNAL (klass, "glade-action", glade_window_action_handler, 1, G_TYPE_STRING);
Packit 1e8aac
  DEFINE_ACTION_SIGNAL (klass, "glade-switch", glade_window_switch_handler, 1, G_TYPE_INT);
Packit 1e8aac
Packit 1e8aac
  gtk_widget_class_set_css_name (widget_class, "GladeWindow");
Packit 1e8aac
Packit 1e8aac
  provider = gtk_css_provider_new ();
Packit 1e8aac
  gtk_css_provider_load_from_resource (provider, "/org/gnome/glade/glade-window.css");
Packit 1e8aac
  gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
Packit 1e8aac
                                             GTK_STYLE_PROVIDER (provider),
Packit 1e8aac
                                             GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
Packit 1e8aac
  g_object_unref (provider);
Packit 1e8aac
Packit 1e8aac
  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/glade/glade.glade");
Packit 1e8aac
Packit 1e8aac
  /* Internal children */
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, adaptor_chooser);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, headerbar);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, project_switcher);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, about_dialog);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, start_page);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, version_label);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, intro_button);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, center_paned);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, left_paned);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, open_button_box);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, save_button_box);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, stack);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, view_stack);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, inspectors_stack);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, editor);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, statusbar);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, toolbar);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, undo_button);
Packit 1e8aac
  gtk_widget_class_bind_template_child_private (widget_class, GladeWindow, redo_button);
Packit 1e8aac
Packit 1e8aac
  /* Callbacks */
Packit 1e8aac
  gtk_widget_class_bind_template_callback (widget_class, on_stack_visible_child_notify);
Packit 1e8aac
  gtk_widget_class_bind_template_callback (widget_class, on_open_recent_action_item_activated);
Packit 1e8aac
  gtk_widget_class_bind_template_callback (widget_class, on_undo_button_button_press_event);
Packit 1e8aac
  gtk_widget_class_bind_template_callback (widget_class, on_redo_button_button_press_event);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
Packit 1e8aac
GtkWidget *
Packit 1e8aac
glade_window_new (void)
Packit 1e8aac
{
Packit 1e8aac
  return g_object_new (GLADE_TYPE_WINDOW, NULL);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_window_check_devhelp (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  g_return_if_fail (GLADE_IS_WINDOW (window));
Packit 1e8aac
Packit 1e8aac
  if (glade_util_have_devhelp ())
Packit 1e8aac
    g_signal_connect (glade_app_get (), "doc-search", G_CALLBACK (doc_search_cb), window);
Packit 1e8aac
}
Packit 1e8aac
Packit 1e8aac
void
Packit 1e8aac
glade_window_registration_notify_user (GladeWindow *window)
Packit 1e8aac
{
Packit 1e8aac
  gboolean skip_reminder, completed;
Packit 1e8aac
  GladeWindowPrivate *priv;
Packit 1e8aac
Packit 1e8aac
  g_return_if_fail (GLADE_IS_WINDOW (window));
Packit 1e8aac
  priv = window->priv;
Packit 1e8aac
Packit 1e8aac
  g_object_get (priv->registration,
Packit 1e8aac
                "completed", &completed,
Packit 1e8aac
                "skip-reminder", &skip_reminder,
Packit 1e8aac
                NULL);
Packit 1e8aac
Packit 1e8aac
  if (!completed && !skip_reminder)
Packit 1e8aac
    {
Packit 1e8aac
      GtkWidget *dialog, *check;
Packit 1e8aac
Packit 1e8aac
      dialog = gtk_message_dialog_new (GTK_WINDOW (glade_app_get_window ()),
Packit 1e8aac
                                       GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 1e8aac
                                       GTK_MESSAGE_QUESTION,
Packit 1e8aac
                                       GTK_BUTTONS_YES_NO,
Packit 1e8aac
                                       "%s",
Packit 1e8aac
                                       /* translators: Primary message of a dialog used to notify the user about the survey */
Packit 1e8aac
                                       _("We are conducting a user survey\n would you like to take it now?"));
Packit 1e8aac
Packit 1e8aac
      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
Packit 1e8aac
                                                /* translators: Secondary text of a dialog used to notify the user about the survey */
Packit 1e8aac
                                                _("If not, you can always find it in the Help menu."));
Packit 1e8aac
Packit 1e8aac
      check = gtk_check_button_new_with_mnemonic (_("_Do not show this dialog again"));
Packit 1e8aac
      gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
Packit 1e8aac
                        check, FALSE, FALSE, 0);
Packit 1e8aac
      gtk_widget_set_halign (check, GTK_ALIGN_START);
Packit 1e8aac
      gtk_widget_set_margin_start (check, 6);
Packit 1e8aac
      gtk_widget_show (check);
Packit 1e8aac
Packit 1e8aac
      if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES)
Packit 1e8aac
          gtk_window_present (GTK_WINDOW (priv->registration));
Packit 1e8aac
Packit 1e8aac
      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)))
Packit 1e8aac
        {
Packit 1e8aac
          g_object_set (priv->registration, "skip-reminder", TRUE, NULL);
Packit 1e8aac
          glade_app_config_save ();
Packit 1e8aac
        }
Packit 1e8aac
Packit 1e8aac
      gtk_widget_destroy (dialog);
Packit 1e8aac
    }
Packit 1e8aac
  else if (!completed)
Packit 1e8aac
    glade_util_flash_message (priv->statusbar, priv->statusbar_context_id, "%s",
Packit 1e8aac
                              /* translators: Text to show in the statusbar if the user did not completed the survey and choose not to show the notification dialog again */
Packit 1e8aac
                              _("Go to Help -> Registration & User Survey and complete our survey!"));
Packit 1e8aac
}