Rename psppire_dialog_action_get_pointer -> psppire_dialog_action_get_hash_table
[pspp] / src / ui / gui / psppire-dialog-action.c
index 1a19ebb9a57ad3fce50e073b3a56d57f5618afa5..70b89ea2867c2d2b8378bfde2a7f8a83ad394c84 100644 (file)
@@ -83,6 +83,54 @@ psppire_dialog_action_get_property (GObject    *object,
 }
 
 
+static void
+set_toplevel (PsppireDialogAction *act)
+{
+  if (act->toplevel)
+    return;
+
+  GSList *sl = gtk_ui_manager_get_toplevels (act->uim, GTK_UI_MANAGER_MENUBAR | GTK_UI_MANAGER_TOOLBAR);
+  g_return_if_fail (sl);
+  
+  act->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (sl->data));
+  g_slist_free (sl);
+}
+
+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)
+{
+  set_toplevel (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;
+}
+
 static void
 psppire_dialog_action_activate (PsppireDialogAction *act)
 {
@@ -90,22 +138,28 @@ psppire_dialog_action_activate (PsppireDialogAction *act)
 
   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);
+  gboolean first_time = ! act->toplevel;
 
-  act->toplevel = gtk_widget_get_toplevel (GTK_WIDGET (sl->data));
-  g_slist_free (sl);
+  set_toplevel (act);
 
   act->dict = PSPPIRE_DATA_WINDOW(act->toplevel)->dict;
   
   g_object_set (act->source, "model", act->dict, NULL);
-  
-  gtk_window_set_transient_for (GTK_WINDOW (act->dialog), GTK_WINDOW (act->toplevel));
 
+  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);
+
+  gtk_window_set_transient_for (GTK_WINDOW (act->dialog), GTK_WINDOW (act->toplevel));
 
   if (GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate)
     GTK_ACTION_CLASS (psppire_dialog_action_parent_class)->activate ( GTK_ACTION (act));
 
+  gtk_widget_grab_focus (act->source);
+
+  if (first_time)
+    psppire_dialog_reload (PSPPIRE_DIALOG (act->dialog));
+
   response = psppire_dialog_run (PSPPIRE_DIALOG (act->dialog));
 
   if ( class->generate_syntax )
@@ -123,8 +177,6 @@ psppire_dialog_action_activate (PsppireDialogAction *act)
          break;
        }
     }
-
-  gtk_widget_destroy (act->dialog);
 }
 
 static void
@@ -186,3 +238,10 @@ psppire_dialog_action_set_refresh (PsppireDialogAction *pda,
   g_signal_connect_swapped (pda->dialog, "refresh", G_CALLBACK (refresh),  pda);
 }
 
+
+void 
+psppire_dialog_action_set_activation (gpointer class, activation activate)
+{
+  GTK_ACTION_CLASS (class)->activate = activate;
+}
+