/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2012 Free Software Foundation
+ Copyright (C) 2012, 2016 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "executor.h"
#include "helper.h"
#include "psppire-data-window.h"
+#include "builder-wrapper.h"
static void psppire_dialog_action_init (PsppireDialogAction *act);
static void psppire_dialog_action_class_init (PsppireDialogActionClass *class);
-G_DEFINE_ABSTRACT_TYPE (PsppireDialogAction, psppire_dialog_action, GTK_TYPE_ACTION);
+static GObjectClass * parent_class = NULL;
+
+
+static const gchar *
+__get_name (GAction *act)
+{
+ return G_OBJECT_TYPE_NAME (act);
+}
+
+static const GVariantType *
+__get_state_type (GAction *act)
+{
+ return NULL;
+}
+
+
+static GVariant *
+__get_state (GAction *act)
+{
+ return NULL;
+}
+
+
+static const GVariantType *
+__get_parameter_type (GAction *act)
+{
+ return PSPPIRE_DIALOG_ACTION (act)->parameter_type;
+}
+
+static gboolean
+__get_enabled (GAction *act)
+{
+ return TRUE;
+}
+
+static void psppire_dialog_action_activate (PsppireDialogAction *act, GVariant *parameter);
+
+void
+psppire_dialog_action_activate_null (PsppireDialogAction *act)
+{
+ psppire_dialog_action_activate (act, NULL);
+}
+
+
+static void
+__activate (GAction *action, GVariant *parameter)
+{
+ psppire_dialog_action_activate (PSPPIRE_DIALOG_ACTION (action), parameter);
+}
+
+
+static void
+action_model_init (GActionInterface *iface)
+{
+ iface->get_name = __get_name;
+ iface->get_state_type = __get_state_type;
+ iface->get_state = __get_state;
+ iface->get_parameter_type = __get_parameter_type;
+ iface->get_enabled = __get_enabled;
+ iface->activate = __activate;
+}
+
+
+GType
+psppire_dialog_action_get_type (void)
+{
+ static GType de_type = 0;
+
+ if (!de_type)
+ {
+ static const GTypeInfo de_info =
+ {
+ sizeof (PsppireDialogActionClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) psppire_dialog_action_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PsppireDialogAction),
+ 0,
+ (GInstanceInitFunc) psppire_dialog_action_init,
+ };
+
+
+ static const GInterfaceInfo ga_info = {
+ (GInterfaceInitFunc) action_model_init,
+ NULL,
+ NULL
+ };
+
+
+ de_type = g_type_register_static (G_TYPE_OBJECT, "PsppireDialogAction",
+ &de_info, G_TYPE_FLAG_ABSTRACT);
+
+ g_type_add_interface_static (de_type, G_TYPE_ACTION, &ga_info);
+ }
+
+ return de_type;
+}
+
/* Properties */
enum
{
PROP_0,
- PROP_MANAGER,
PROP_TOPLEVEL,
+ PROP_NAME,
+ PROP_ENABLED,
+ PROP_STATE,
+ PROP_STATE_TYPE,
+ PROP_PARAMETER_TYPE
};
static void
switch (prop_id)
{
- case PROP_MANAGER:
+ case PROP_TOPLEVEL:
{
-
GObject *p = g_value_get_object (value);
- act->uim = GTK_UI_MANAGER (p);
+ act->toplevel = GTK_WIDGET (p);
}
break;
default:
switch (prop_id)
{
- case PROP_MANAGER:
- g_value_take_object (value, dialog_action->uim);
- break;
- case PROP_TOPLEVEL:
+ case PROP_TOPLEVEL:
g_value_take_object (value, dialog_action->toplevel);
break;
default:
}
+
+static void
+on_destroy_dataset (GObject *w)
+{
+ GHashTable *t = g_object_get_data (w, "thing-table");
+ GSList *dl = g_object_get_data (w, "widget-list");
+
+ g_slist_free_full (dl, (GDestroyNotify) gtk_widget_destroy);
+ g_hash_table_unref (t);
+}
+
+/* Each toplevel widget - that is the data window, which generally has a 1-1 association
+ with a dataset - has an associated GHashTable.
+
+ This GHashTable is keyed by the address of a PsppireDialogAction, and its values
+ are user determined pointers (typically a GtkBuilder*).
+
+ This is useful for storing the state of dialogs so they can persist between invocations.
+*/
+GHashTable *
+psppire_dialog_action_get_hash_table (PsppireDialogAction *act)
+{
+ GHashTable *t = g_object_get_data (G_OBJECT (act->toplevel), "thing-table");
+ if (t == NULL)
+ {
+ t = g_hash_table_new_full (g_direct_hash, g_direct_equal, 0, g_object_unref);
+ g_object_set_data (G_OBJECT (act->toplevel), "thing-table", t);
+ g_object_set_data (G_OBJECT (act->toplevel), "widget-list", NULL);
+ g_signal_connect (act->toplevel, "destroy", G_CALLBACK (on_destroy_dataset), NULL);
+ }
+
+ return t;
+}
+
+GtkBuilder *
+psppire_dialog_action_get_xml (PsppireDialogAction *da)
+{
+ GHashTable *thing = psppire_dialog_action_get_hash_table (da);
+ GtkBuilder *xml = g_hash_table_lookup (thing, da);
+ return xml;
+}
+
+
static void
-psppire_dialog_action_activate (PsppireDialogAction *act)
+psppire_dialog_action_activate (PsppireDialogAction *act, GVariant *parameter)
{
gint response;
PsppireDialogActionClass *class = PSPPIRE_DIALOG_ACTION_GET_CLASS (act);
- GSList *sl = gtk_ui_manager_get_toplevels (act->uim, GTK_UI_MANAGER_MENUBAR | GTK_UI_MANAGER_TOOLBAR);
- g_return_if_fail (sl);
+ act->dict = PSPPIRE_DATA_WINDOW(act->toplevel)->dict;
- act->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (sl->data));
- g_slist_free (sl);
+ GSList *wl = g_object_get_data (G_OBJECT (act->toplevel), "widget-list");
+ wl = g_slist_prepend (wl, act->dialog);
+ g_object_set_data (G_OBJECT (act->toplevel), "widget-list", wl);
- act->dict = PSPPIRE_DATA_WINDOW(act->toplevel)->dict;
-
- g_object_set (act->source, "model", act->dict, NULL);
+ if (class->initial_activate)
+ {
+ GHashTable *thing = psppire_dialog_action_get_hash_table (act);
+ GtkBuilder *xml = g_hash_table_lookup (thing, act);
+ if (xml == NULL)
+ {
+ xml = class->initial_activate (act, parameter);
+ g_hash_table_insert (thing, act, xml);
+ }
+ }
+
+ if (class->activate)
+ {
+ GHashTable *thing = psppire_dialog_action_get_hash_table (act);
+ GtkBuilder *xml = g_hash_table_lookup (thing, act);
+ if (xml != NULL)
+ class->activate (act, parameter);
+ }
- gtk_window_set_transient_for (GTK_WINDOW (act->dialog), GTK_WINDOW (act->toplevel));
+ gtk_window_set_transient_for (GTK_WINDOW (act->dialog),
+ GTK_WINDOW (act->toplevel));
+
+ if (act->source)
+ {
+ g_object_set (act->source, "model", act->dict, NULL);
+ gtk_widget_grab_focus (act->source);
+ }
+ if (!act->activated)
+ psppire_dialog_reload (PSPPIRE_DIALOG (act->dialog));
- if (GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate)
- GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate ( GTK_ACTION (act));
+ act->activated = TRUE;
response = psppire_dialog_run (PSPPIRE_DIALOG (act->dialog));
break;
}
}
-
- gtk_widget_destroy (act->dialog);
}
static void
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
- GParamSpec *manager_spec =
- g_param_spec_object ("manager",
- "Manager",
- "The GtkUIManager which created this object",
- GTK_TYPE_UI_MANAGER,
- G_PARAM_READWRITE);
+ parent_class = g_type_class_peek_parent (class);
GParamSpec *toplevel_spec =
g_param_spec_object ("top-level",
"Top Level",
"The top level widget to which this dialog action belongs",
GTK_TYPE_WINDOW,
- G_PARAM_READABLE);
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
object_class->set_property = psppire_dialog_action_set_property;
object_class->get_property = psppire_dialog_action_get_property;
class->generate_syntax = NULL;
- class->activate = psppire_dialog_action_activate;
-
- g_object_class_install_property (object_class,
- PROP_MANAGER,
- manager_spec);
-
g_object_class_install_property (object_class,
PROP_TOPLEVEL,
toplevel_spec);
+
+ g_object_class_override_property (object_class, PROP_NAME, "name");
+ g_object_class_override_property (object_class, PROP_ENABLED, "enabled");
+ g_object_class_override_property (object_class, PROP_STATE, "state");
+ g_object_class_override_property (object_class, PROP_STATE_TYPE, "state-type");
+ g_object_class_override_property (object_class, PROP_PARAMETER_TYPE, "parameter-type");
}
{
act->toplevel = NULL;
act->dict = NULL;
+ act->activated = FALSE;
+ act->parameter_type = NULL;
}
-
void
-psppire_dialog_action_set_valid_predicate (PsppireDialogAction *act,
+psppire_dialog_action_set_valid_predicate (PsppireDialogAction *act,
ContentsAreValid dialog_state_valid)
{
psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (act->dialog),
}
void
-psppire_dialog_action_set_refresh (PsppireDialogAction *pda,
+psppire_dialog_action_set_refresh (PsppireDialogAction *pda,
PsppireDialogActionRefresh refresh)
{
g_signal_connect_swapped (pda->dialog, "refresh", G_CALLBACK (refresh), pda);
}
-