X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-dialog-action.c;h=9eeed98d8dd608fe8b101159017cd5a1ea269ad6;hb=e5ed663e9f1998c1c2409a668288d4e5d496beda;hp=1a19ebb9a57ad3fce50e073b3a56d57f5618afa5;hpb=a2727738806fde48b6f360182f12bd44e1a468db;p=pspp diff --git a/src/ui/gui/psppire-dialog-action.c b/src/ui/gui/psppire-dialog-action.c index 1a19ebb9a5..9eeed98d8d 100644 --- a/src/ui/gui/psppire-dialog-action.c +++ b/src/ui/gui/psppire-dialog-action.c @@ -1,5 +1,5 @@ /* 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 @@ -22,18 +22,122 @@ #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 @@ -46,11 +150,10 @@ psppire_dialog_action_set_property (GObject *object, 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: @@ -70,10 +173,7 @@ psppire_dialog_action_get_property (GObject *object, 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: @@ -83,28 +183,94 @@ psppire_dialog_action_get_property (GObject *object, } + +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)); @@ -123,8 +289,6 @@ psppire_dialog_action_activate (PsppireDialogAction *act) break; } } - - gtk_widget_destroy (act->dialog); } static void @@ -132,34 +296,29 @@ psppire_dialog_action_class_init (PsppireDialogActionClass *class) { 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"); } @@ -168,11 +327,12 @@ psppire_dialog_action_init (PsppireDialogAction *act) { 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), @@ -180,9 +340,8 @@ psppire_dialog_action_set_valid_predicate (PsppireDialogAction *act, } 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); } -