/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #include #include "libgnome/libgnomeP.h" #include "gnome-dock-layout.h" #include "gnome-mdi-session.h" static GPtrArray * config_get_list (const gchar *); static void config_set_list (const gchar *, GList *, gpointer (*)(gpointer)); static void restore_window_child (GnomeMDI *, GHashTable *, GHashTable *, GHashTable *, GHashTable *, GHashTable *, glong, glong, gboolean *, gint, gint, gint, gint); static void restore_window (GnomeMDI *, const gchar *, GPtrArray *, GHashTable *, GHashTable *, GHashTable *, GHashTable *, GHashTable *, glong); static void set_active_window (GnomeMDI *, GHashTable *, glong); static gpointer view_window_func (gpointer); static gchar * gnome_mdi_child_get_config_string (GnomeMDIChild *child) { if(GNOME_MDI_CHILD_CLASS(GTK_OBJECT(child)->klass)->get_config_string) return GNOME_MDI_CHILD_CLASS(GTK_OBJECT(child)->klass)->get_config_string(child, NULL); return NULL; } static GPtrArray * config_get_list (const gchar *key) { GPtrArray *array; gchar *string, *pos; string = gnome_config_get_string (key); if (!string) return NULL; array = g_ptr_array_new (); pos = string; while (*pos) { glong value; gchar *tmp; tmp = strchr (pos, ':'); if (tmp) *tmp = '\0'; if (sscanf (pos, "%lx", &value) == 1) g_ptr_array_add (array, (gpointer) value); if (tmp) pos = tmp+1; else break; } g_free (string); return array; } static void config_set_list (const gchar *key, GList *list, gpointer (*func)(gpointer)) { gchar value [BUFSIZ]; value [0] = '\0'; while (list) { char buffer [BUFSIZ]; gpointer data; data = func ? func (list->data) : list->data; g_snprintf (buffer, sizeof(buffer), "%lx", (glong) data); if (*value) strcat (value, ":"); strcat (value, buffer); list = g_list_next (list); } gnome_config_set_string (key, value); } static void restore_window_child (GnomeMDI *mdi, GHashTable *child_hash, GHashTable *child_windows, GHashTable *child_views, GHashTable *view_hash, GHashTable *window_hash, glong window, glong child, gboolean *init, gint x, gint y, gint width, gint height) { GPtrArray *windows, *views; GnomeMDIChild *mdi_child; guint k; windows = g_hash_table_lookup (child_windows, (gpointer) child); if (!windows) return; views = g_hash_table_lookup (child_views, (gpointer) child); if (!views) return; mdi_child = g_hash_table_lookup (child_hash, (gpointer) child); if (!mdi_child) return; for (k = 0; k < windows->len; k++) { if (windows->pdata [k] != (gpointer) window) continue; if (*init) gnome_mdi_add_view (mdi, mdi_child); else { gnome_mdi_add_toplevel_view (mdi, mdi_child); gtk_widget_set_usize (GTK_WIDGET (mdi->active_window), width, height); gtk_widget_set_uposition (GTK_WIDGET (mdi->active_window), x, y); *init = TRUE; g_hash_table_insert (window_hash, (gpointer) window, mdi->active_window); } g_hash_table_insert (view_hash, views->pdata [k], mdi->active_view); } } static void restore_window (GnomeMDI *mdi, const gchar *section, GPtrArray *child_list, GHashTable *child_hash, GHashTable *child_windows, GHashTable *child_views, GHashTable *view_hash, GHashTable *window_hash, glong window) { gboolean init = FALSE; gchar key [BUFSIZ], *string; gint ret, x, y, w, h; guint j; g_snprintf (key, sizeof(key), "%s/mdi_window_%lx", section, window); string = gnome_config_get_string (key); if (!string) return; ret = sscanf (string, "%d/%d/%d/%d", &x, &y, &w, &h); g_free (string); if (ret != 4) return; for (j = 0; j < child_list->len; j++) restore_window_child (mdi, child_hash, child_windows, child_views, view_hash, window_hash, window, (glong) child_list->pdata [j], &init, x, y, w, h); g_snprintf (key, sizeof(key), "%s/mdi_window_layout_%lx", section, window); string = gnome_config_get_string (key); if (!string) return; #if 0 { GnomeApp *app = mdi->active_window; GnomeDockLayout *layout; printf("app->layout == %08lx\n", app->layout); /* this should be a nasty hack before dock-layout gets a bit better don't even know if it works, though ;) */ layout = gnome_dock_get_layout(GNOME_DOCK(app->dock)); gnome_dock_layout_parse_string(mdi->active_window->layout, string); gtk_container_forall(GTK_CONTAINER(app->dock), remove_items, app->dock); gnome_dock_add_from_layout(GNOME_DOCK(app->dock), layout); gtk_object_unref(GTK_OBJECT(layout)); } #endif } static void set_active_window (GnomeMDI *mdi, GHashTable *window_hash, glong active_window) { GnomeApp *app; GtkWidget *view; app = g_hash_table_lookup (window_hash, (gpointer) active_window); if (!app) return; view = gnome_mdi_get_view_from_window (mdi, app); if (!view) return; gnome_mdi_set_active_view (mdi, view); } /** * gnome_mdi_restore_state: * @mdi: A pointer to a GnomeMDI object. * @section: Name of the section to restore MDI state from. * @create_child_func: A function that recreates a child from its config string. * * Description: * Restores the MDI state. Children are recreated with @create_child_func that * restores information about a child from a config string that was provided * during saving state by the child. * * Return value: * TRUE if state was successfully restored, FALSE otherwise. **/ gboolean gnome_mdi_restore_state (GnomeMDI *mdi, const gchar *section, GnomeMDIChildCreator create_child_func) { gchar key [BUFSIZ], *string; GPtrArray *window_list, *child_list; GHashTable *child_hash, *child_windows; GHashTable *child_views, *view_hash, *window_hash; glong active_view = 0, active_window = 0; guint i; gint mode; g_snprintf (key, sizeof(key), "%s/mdi_mode=-1", section); mode = gnome_config_get_int (key); if (gnome_config_get_int (key) == -1) return FALSE; gnome_mdi_set_mode (mdi, mode); child_hash = g_hash_table_new (NULL, NULL); child_windows = g_hash_table_new (NULL, NULL); child_views = g_hash_table_new (NULL, NULL); view_hash = g_hash_table_new (NULL, NULL); window_hash = g_hash_table_new (NULL, NULL); /* Walk the list of windows. */ g_snprintf (key, sizeof(key), "%s/mdi_windows", section); window_list = config_get_list (key); /* Walk the list of children. */ g_snprintf (key, sizeof(key), "%s/mdi_children", section); child_list = config_get_list (key); /* Get the active view. */ g_snprintf (key, sizeof(key), "%s/mdi_active_view", section); string = gnome_config_get_string (key); if (string) { sscanf (string, "%lx", &active_view); g_free (string); } /* Get the active window. */ g_snprintf (key, sizeof(key), "%s/mdi_active_window", section); string = gnome_config_get_string (key); if (string) { sscanf (string, "%lx", &active_window); g_free (string); } /* Read child descriptions. */ for (i = 0; i < child_list->len; i++) { glong child = (glong) child_list->pdata [i]; GPtrArray *windows, *views; GnomeMDIChild *mdi_child; g_snprintf (key, sizeof(key), "%s/mdi_child_config_%lx", section, child); string = gnome_config_get_string (key); if (!string) continue; mdi_child = create_child_func (string); g_free (string); gnome_mdi_add_child (mdi, mdi_child); g_hash_table_insert (child_hash, (gpointer)child, mdi_child); g_snprintf (key, sizeof(key), "%s/mdi_child_windows_%lx", section, child); windows = config_get_list (key); g_hash_table_insert (child_windows, (gpointer) child, windows); g_snprintf (key, sizeof(key), "%s/mdi_child_views_%lx", section, child); views = config_get_list (key); g_hash_table_insert (child_views, (gpointer) child, views); } /* Read window descriptions. */ for (i = 0; i < window_list->len; i++) restore_window (mdi, section, child_list, child_hash, child_windows, child_views, view_hash, window_hash, (glong) window_list->pdata [i]); /* For each window, set its active view. */ for (i = 0; i < window_list->len; i++) { GtkWidget *real_view; glong view; gint ret; g_snprintf (key, sizeof(key), "%s/mdi_window_view_%lx", section, (long) window_list->pdata [i]); string = gnome_config_get_string (key); if (!string) continue; ret = sscanf (string, "%lx", &view); g_free (string); if (ret != 1) continue; real_view = g_hash_table_lookup (view_hash, (gpointer) view); if (!real_view) continue; gnome_mdi_set_active_view (mdi, real_view); } /* Finally, set the active window. */ set_active_window (mdi, window_hash, active_window); /* Free allocated memory. */ for (i = 0; i < child_list->len; i++) { glong child = (glong) child_list->pdata [i]; GPtrArray *windows, *views; windows = g_hash_table_lookup (child_windows, (gpointer) child); if (windows) g_ptr_array_free (windows, FALSE); views = g_hash_table_lookup (child_views, (gpointer) child); if (views) g_ptr_array_free (views, FALSE); } g_hash_table_destroy (child_hash); g_hash_table_destroy (child_windows); g_hash_table_destroy (child_views); g_hash_table_destroy (view_hash); g_hash_table_destroy (window_hash); return TRUE; } static gpointer view_window_func (gpointer data) { return gnome_mdi_get_app_from_view(GTK_WIDGET(data)); } /** * gnome_mdi_save_state: * @mdi: A pointer to a GnomeMDI object. * @section: Name of the section that the MDI config should be saved to. * * Description: * Saves MDI state to the application's config file in section @section. **/ void gnome_mdi_save_state (GnomeMDI *mdi, const gchar *section) { gchar key [BUFSIZ], value [BUFSIZ]; GList *child, *window; gint x, y, w, h; gnome_config_clean_section (section); /* save MDI mode */ g_snprintf (key, sizeof(key), "%s/mdi_mode", section); gnome_config_set_int (key, mdi->mode); /* Write list of children. */ g_snprintf (key, sizeof(key), "%s/mdi_children", section); config_set_list (key, mdi->children, NULL); /* Write list of windows. */ g_snprintf (key, sizeof(key), "%s/mdi_windows", section); config_set_list (key, mdi->windows, NULL); /* Save active window. */ g_snprintf (key, sizeof(key), "%s/mdi_active_window", section); g_snprintf (value, sizeof(value), "%lx", (glong) mdi->active_window); gnome_config_set_string (key, value); /* Save active view. */ g_snprintf (key, sizeof(key), "%s/mdi_active_view", section); g_snprintf (value, sizeof(value), "%lx", (glong) mdi->active_view); gnome_config_set_string (key, value); /* Walk list of children. */ child = mdi->children; while (child) { GnomeMDIChild *mdi_child; gchar *string; mdi_child = GNOME_MDI_CHILD (child->data); /* Save child configuration. */ string = gnome_mdi_child_get_config_string(mdi_child); if (string) { g_snprintf (key, sizeof(key), "%s/mdi_child_config_%lx", section, (long) mdi_child); gnome_config_set_string (key, string); g_free (string); } /* Save list of views this child has. */ g_snprintf (key, sizeof(key), "%s/mdi_child_windows_%lx", section, (long) mdi_child); config_set_list (key, mdi_child->views, view_window_func); g_snprintf (key, sizeof(key), "%s/mdi_child_views_%lx", section, (long) mdi_child); config_set_list (key, mdi_child->views, NULL); child = g_list_next (child); } /* Save list of toplevel windows. */ window = mdi->windows; while (window) { GnomeApp *app; GnomeDockLayout *layout; GtkWidget *view; gchar *string; app = GNOME_APP (window->data); gdk_window_get_geometry (GTK_WIDGET (app)->window, &x, &y, &w, &h, NULL); gdk_window_get_origin (GTK_WIDGET (app)->window, &x, &y); g_snprintf (key, sizeof(key), "%s/mdi_window_%lx", section, (long) app); g_snprintf (value, sizeof(value), "%d/%d/%d/%d", x, y, w, h); gnome_config_set_string (key, value); view = gnome_mdi_get_view_from_window (mdi, app); g_snprintf (key, sizeof(key), "%s/mdi_window_view_%lx", section, (long) app); g_snprintf (value, sizeof(value), "%lx", (long) view); gnome_config_set_string (key, value); g_snprintf(key, sizeof(key), "%s/mdi_window_layout_%lx", section, (long) app); layout = gnome_dock_get_layout (GNOME_DOCK (app->dock)); string = gnome_dock_layout_create_string (layout); gtk_object_unref (GTK_OBJECT (layout)); gnome_config_set_string(key, string); g_free(string); window = g_list_next (window); } }