psppire-dialog-action: Fix compilation error.
[pspp] / src / ui / gui / psppire-dialog-action.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2012, 2016  Free Software Foundation
3
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.
8
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.
13
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/>. */
16
17
18 #include <config.h>
19
20 #include "psppire-dialog-action.h"
21 #include "psppire-dialog.h"
22 #include "executor.h"
23 #include "helper.h"
24 #include "psppire-data-window.h"
25
26 static void psppire_dialog_action_init            (PsppireDialogAction      *act);
27 static void psppire_dialog_action_class_init      (PsppireDialogActionClass *class);
28
29 G_DEFINE_ABSTRACT_TYPE (PsppireDialogAction, psppire_dialog_action, GTK_TYPE_ACTION);
30
31 /* Properties */
32 enum
33 {
34   PROP_0,
35   PROP_MANAGER,
36   PROP_TOPLEVEL,
37 };
38
39 static void
40 psppire_dialog_action_set_property (GObject         *object,
41                                guint            prop_id,
42                                const GValue    *value,
43                                GParamSpec      *pspec)
44 {
45   PsppireDialogAction *act = PSPPIRE_DIALOG_ACTION (object);
46
47   switch (prop_id)
48     {
49     case PROP_MANAGER:
50       {
51
52         GObject *p = g_value_get_object (value);
53         act->uim = GTK_UI_MANAGER (p);
54       }
55       break;
56     default:
57       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
58       break;
59     };
60 }
61
62
63 static void
64 psppire_dialog_action_get_property (GObject    *object,
65                                guint            prop_id,
66                                GValue          *value,
67                                GParamSpec      *pspec)
68 {
69   PsppireDialogAction *dialog_action = PSPPIRE_DIALOG_ACTION (object);
70
71   switch (prop_id)
72     {
73     case PROP_MANAGER:
74       g_value_take_object (value, dialog_action->uim);
75       break;
76   case PROP_TOPLEVEL:
77       g_value_take_object (value, dialog_action->toplevel);
78       break;
79     default:
80       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
81       break;
82     };
83 }
84
85
86 static void
87 set_toplevel (PsppireDialogAction *act)
88 {
89   if (act->toplevel)
90     return;
91
92   GSList *sl = gtk_ui_manager_get_toplevels (act->uim, GTK_UI_MANAGER_MENUBAR | GTK_UI_MANAGER_TOOLBAR);
93   g_return_if_fail (sl);
94   
95   act->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (sl->data));
96   g_slist_free (sl);
97 }
98
99 static void
100 on_destroy_dataset (GObject *w)
101 {
102   GHashTable *t = g_object_get_data (w, "thing-table");
103   GSList *dl = g_object_get_data (w, "widget-list");
104   
105   g_slist_free_full (dl, (GDestroyNotify) gtk_widget_destroy);
106   g_hash_table_unref (t);
107 }
108
109 /* Each toplevel widget - that is the data window, which generally has a 1-1 association
110    with a dataset - has an associated GHashTable.
111    
112    This GHashTable is keyed by the address of a PsppireDialogAction, and its values
113    are user determined pointers (typically a GtkBuilder*).
114
115    This is useful for storing the state of dialogs so they can persist between invocations.
116 */
117 GHashTable *
118 psppire_dialog_action_get_hash_table (PsppireDialogAction *act)
119 {
120   set_toplevel (act);
121   
122   GHashTable *t = g_object_get_data (G_OBJECT (act->toplevel), "thing-table");
123   if (t == NULL)
124     {
125       t = g_hash_table_new_full (g_direct_hash, g_direct_equal, 0, g_object_unref);
126       g_object_set_data (G_OBJECT (act->toplevel), "thing-table", t);
127       g_object_set_data (G_OBJECT (act->toplevel), "widget-list", NULL);
128       g_signal_connect (act->toplevel, "destroy", G_CALLBACK (on_destroy_dataset), NULL);
129     }
130
131   return t;
132 }
133
134 static void
135 psppire_dialog_action_activate (PsppireDialogAction *act)
136 {
137   gint response;
138
139   PsppireDialogActionClass *class = PSPPIRE_DIALOG_ACTION_GET_CLASS (act);
140
141   gboolean first_time = ! act->toplevel;
142
143   set_toplevel (act);
144
145   act->dict = PSPPIRE_DATA_WINDOW(act->toplevel)->dict;
146   if (act->source)
147     g_object_set (act->source, "model", act->dict, NULL);
148
149   GSList *wl = g_object_get_data (G_OBJECT (act->toplevel), "widget-list");
150   wl = g_slist_prepend (wl, act->dialog);
151   g_object_set_data (G_OBJECT (act->toplevel), "widget-list", wl);
152
153   gtk_window_set_transient_for (GTK_WINDOW (act->dialog), GTK_WINDOW (act->toplevel));
154
155   if (GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate)
156     GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate ( GTK_ACTION (act));
157
158   if (act->source)
159     gtk_widget_grab_focus (act->source);
160
161   if (first_time)
162     psppire_dialog_reload (PSPPIRE_DIALOG (act->dialog));
163
164   response = psppire_dialog_run (PSPPIRE_DIALOG (act->dialog));
165
166   if ( class->generate_syntax )
167     {
168       switch (response)
169         {
170         case GTK_RESPONSE_OK:
171           g_free (execute_syntax_string (PSPPIRE_DATA_WINDOW (act->toplevel),
172                                          class->generate_syntax (act)));
173           break;
174         case PSPPIRE_RESPONSE_PASTE:
175           g_free (paste_syntax_to_window (class->generate_syntax (act)));
176           break;
177         default:
178           break;
179         }
180     }
181 }
182
183 static void
184 psppire_dialog_action_class_init (PsppireDialogActionClass *class)
185 {
186   GObjectClass *object_class = G_OBJECT_CLASS (class);
187
188   GParamSpec *manager_spec =
189     g_param_spec_object ("manager",
190                          "Manager",
191                          "The GtkUIManager which created this object",
192                          GTK_TYPE_UI_MANAGER,
193                          G_PARAM_READWRITE);
194
195   GParamSpec *toplevel_spec =
196     g_param_spec_object ("top-level",
197                          "Top Level",
198                          "The top level widget to which this dialog action belongs",
199                          GTK_TYPE_WINDOW,
200                          G_PARAM_READABLE);
201
202   object_class->set_property = psppire_dialog_action_set_property;
203   object_class->get_property = psppire_dialog_action_get_property;
204
205   class->generate_syntax = NULL;
206
207   class->activate = psppire_dialog_action_activate;
208
209   g_object_class_install_property (object_class,
210                                    PROP_MANAGER,
211                                    manager_spec);
212
213   g_object_class_install_property (object_class,
214                                    PROP_TOPLEVEL,
215                                    toplevel_spec);
216 }
217
218
219 static void
220 psppire_dialog_action_init (PsppireDialogAction *act)
221 {
222   act->toplevel = NULL;
223   act->dict = NULL;
224 }
225
226
227 void
228 psppire_dialog_action_set_valid_predicate (PsppireDialogAction *act, 
229                                            ContentsAreValid dialog_state_valid)
230 {
231   psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (act->dialog),
232                                       dialog_state_valid, act);
233 }
234
235 void
236 psppire_dialog_action_set_refresh (PsppireDialogAction *pda, 
237                                    PsppireDialogActionRefresh refresh)
238 {
239   g_signal_connect_swapped (pda->dialog, "refresh", G_CALLBACK (refresh),  pda);
240 }
241
242
243 void 
244 psppire_dialog_action_set_activation (gpointer class, activation activate)
245 {
246   GTK_ACTION_CLASS (class)->activate = (void (*)(GtkAction *)) activate;
247 }
248