1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2012, 2016 Free Software Foundation
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "psppire-dialog-action.h"
21 #include "psppire-dialog.h"
24 #include "psppire-data-window.h"
25 #include "builder-wrapper.h"
27 static void psppire_dialog_action_init (PsppireDialogAction *act);
28 static void psppire_dialog_action_class_init (PsppireDialogActionClass *class);
30 static GObjectClass * parent_class = NULL;
34 __get_name (GAction *act)
36 return G_OBJECT_TYPE_NAME (act);
39 static const GVariantType *
40 __get_state_type (GAction *act)
47 __get_state (GAction *act)
53 static const GVariantType *
54 __get_parameter_type (GAction *act)
56 return PSPPIRE_DIALOG_ACTION (act)->parameter_type;
60 __get_enabled (GAction *act)
65 static void psppire_dialog_action_activate (PsppireDialogAction *act, GVariant *parameter);
68 psppire_dialog_action_activate_null (PsppireDialogAction *act)
70 psppire_dialog_action_activate (act, NULL);
75 __activate (GAction *action, GVariant *parameter)
77 psppire_dialog_action_activate (PSPPIRE_DIALOG_ACTION (action), parameter);
82 action_model_init (GActionInterface *iface)
84 iface->get_name = __get_name;
85 iface->get_state_type = __get_state_type;
86 iface->get_state = __get_state;
87 iface->get_parameter_type = __get_parameter_type;
88 iface->get_enabled = __get_enabled;
89 iface->activate = __activate;
94 psppire_dialog_action_get_type (void)
96 static GType de_type = 0;
100 static const GTypeInfo de_info =
102 sizeof (PsppireDialogActionClass),
103 NULL, /* base_init */
104 NULL, /* base_finalize */
105 (GClassInitFunc) psppire_dialog_action_class_init,
106 NULL, /* class_finalize */
107 NULL, /* class_data */
108 sizeof (PsppireDialogAction),
110 (GInstanceInitFunc) psppire_dialog_action_init,
114 static const GInterfaceInfo ga_info = {
115 (GInterfaceInitFunc) action_model_init,
121 de_type = g_type_register_static (G_TYPE_OBJECT, "PsppireDialogAction",
122 &de_info, G_TYPE_FLAG_ABSTRACT);
124 g_type_add_interface_static (de_type, G_TYPE_ACTION, &ga_info);
144 psppire_dialog_action_set_property (GObject *object,
149 PsppireDialogAction *act = PSPPIRE_DIALOG_ACTION (object);
155 GObject *p = g_value_get_object (value);
156 act->toplevel = GTK_WIDGET (p);
160 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
167 psppire_dialog_action_get_property (GObject *object,
172 PsppireDialogAction *dialog_action = PSPPIRE_DIALOG_ACTION (object);
177 g_value_take_object (value, dialog_action->toplevel);
180 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
188 on_destroy_dataset (GObject *w)
190 GHashTable *t = g_object_get_data (w, "thing-table");
191 GSList *dl = g_object_get_data (w, "widget-list");
193 g_slist_free_full (dl, (GDestroyNotify) gtk_widget_destroy);
194 g_hash_table_unref (t);
197 /* Each toplevel widget - that is the data window, which generally has a 1-1 association
198 with a dataset - has an associated GHashTable.
200 This GHashTable is keyed by the address of a PsppireDialogAction, and its values
201 are user determined pointers (typically a GtkBuilder*).
203 This is useful for storing the state of dialogs so they can persist between invocations.
206 psppire_dialog_action_get_hash_table (PsppireDialogAction *act)
208 GHashTable *t = g_object_get_data (G_OBJECT (act->toplevel), "thing-table");
211 t = g_hash_table_new_full (g_direct_hash, g_direct_equal, 0, g_object_unref);
212 g_object_set_data (G_OBJECT (act->toplevel), "thing-table", t);
213 g_object_set_data (G_OBJECT (act->toplevel), "widget-list", NULL);
214 g_signal_connect (act->toplevel, "destroy", G_CALLBACK (on_destroy_dataset), NULL);
221 psppire_dialog_action_get_xml (PsppireDialogAction *da)
223 GHashTable *thing = psppire_dialog_action_get_hash_table (da);
224 GtkBuilder *xml = g_hash_table_lookup (thing, da);
230 psppire_dialog_action_activate (PsppireDialogAction *act, GVariant *parameter)
234 PsppireDialogActionClass *class = PSPPIRE_DIALOG_ACTION_GET_CLASS (act);
236 act->dict = PSPPIRE_DATA_WINDOW(act->toplevel)->dict;
238 GSList *wl = g_object_get_data (G_OBJECT (act->toplevel), "widget-list");
239 wl = g_slist_prepend (wl, act->dialog);
240 g_object_set_data (G_OBJECT (act->toplevel), "widget-list", wl);
242 if (class->initial_activate)
244 GHashTable *thing = psppire_dialog_action_get_hash_table (act);
245 GtkBuilder *xml = g_hash_table_lookup (thing, act);
248 xml = class->initial_activate (act, parameter);
249 g_hash_table_insert (thing, act, xml);
255 GHashTable *thing = psppire_dialog_action_get_hash_table (act);
256 GtkBuilder *xml = g_hash_table_lookup (thing, act);
258 class->activate (act, parameter);
261 gtk_window_set_transient_for (GTK_WINDOW (act->dialog),
262 GTK_WINDOW (act->toplevel));
266 g_object_set (act->source, "model", act->dict, NULL);
267 gtk_widget_grab_focus (act->source);
271 psppire_dialog_reload (PSPPIRE_DIALOG (act->dialog));
273 act->activated = TRUE;
275 response = psppire_dialog_run (PSPPIRE_DIALOG (act->dialog));
277 if (class->generate_syntax)
281 case GTK_RESPONSE_OK:
282 g_free (execute_syntax_string (PSPPIRE_DATA_WINDOW (act->toplevel),
283 class->generate_syntax (act)));
285 case PSPPIRE_RESPONSE_PASTE:
286 g_free (paste_syntax_to_window (class->generate_syntax (act)));
295 psppire_dialog_action_class_init (PsppireDialogActionClass *class)
297 GObjectClass *object_class = G_OBJECT_CLASS (class);
299 parent_class = g_type_class_peek_parent (class);
301 GParamSpec *toplevel_spec =
302 g_param_spec_object ("top-level",
304 "The top level widget to which this dialog action belongs",
306 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
308 object_class->set_property = psppire_dialog_action_set_property;
309 object_class->get_property = psppire_dialog_action_get_property;
311 class->generate_syntax = NULL;
313 g_object_class_install_property (object_class,
317 g_object_class_override_property (object_class, PROP_NAME, "name");
318 g_object_class_override_property (object_class, PROP_ENABLED, "enabled");
319 g_object_class_override_property (object_class, PROP_STATE, "state");
320 g_object_class_override_property (object_class, PROP_STATE_TYPE, "state-type");
321 g_object_class_override_property (object_class, PROP_PARAMETER_TYPE, "parameter-type");
326 psppire_dialog_action_init (PsppireDialogAction *act)
328 act->toplevel = NULL;
330 act->activated = FALSE;
331 act->parameter_type = NULL;
335 psppire_dialog_action_set_valid_predicate (PsppireDialogAction *act,
336 ContentsAreValid dialog_state_valid)
338 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (act->dialog),
339 dialog_state_valid, act);
343 psppire_dialog_action_set_refresh (PsppireDialogAction *pda,
344 PsppireDialogActionRefresh refresh)
346 g_signal_connect_swapped (pda->dialog, "refresh", G_CALLBACK (refresh), pda);