1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 2003 Lars Clausen
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 2 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, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* persistence.c -- functions that handle persistent stores, such as
20 * window positions and sizes, font menu, document history etc.
28 #include <sys/types.h>
33 #include "persistence.h"
35 #include "dia_xml_libxml.h"
39 #include <libxml/tree.h>
41 /* Hash table from window role (string) to PersistentWindow structure.
43 static GHashTable
*persistent_windows
;
45 /* Returns the name used for a window in persistence.
48 persistence_get_window_name(GtkWindow
*window
)
50 gchar
*name
= gtk_window_get_role(window
);
52 printf("Internal: Window %s has no role.\n", gtk_window_get_title(window
));
59 find_node_named (xmlNodePtr p
, const char *name
)
61 while (p
&& 0 != strcmp(p
->name
, name
))
67 persistence_load_window(xmlNodePtr node
)
70 PersistentWindow
*wininfo
= g_new0(PersistentWindow
, 1);
73 attr
= composite_find_attribute(node
, "role");
75 name
= data_string(attribute_first_data(attr
));
81 attr
= composite_find_attribute(node
, "xpos");
83 wininfo
->x
= data_int(attribute_first_data(attr
));
84 attr
= composite_find_attribute(node
, "ypos");
86 wininfo
->y
= data_int(attribute_first_data(attr
));
87 attr
= composite_find_attribute(node
, "width");
89 wininfo
->width
= data_int(attribute_first_data(attr
));
90 attr
= composite_find_attribute(node
, "height");
92 wininfo
->height
= data_int(attribute_first_data(attr
));
93 attr
= composite_find_attribute(node
, "isopen");
95 wininfo
->isopen
= data_boolean(attribute_first_data(attr
));
97 if (persistent_windows
== NULL
) {
98 persistent_windows
= g_hash_table_new(g_str_hash
, g_str_equal
);
100 /* Do anything to avoid dups? */
102 g_hash_table_insert(persistent_windows
, name
, wininfo
);
105 /* Load all persistent data. */
110 gchar
*filename
= dia_config_filename("persistence");
113 if (!g_file_test(filename
, G_FILE_TEST_IS_REGULAR
)) return;
115 doc
= xmlDiaParseFile(filename
);
117 if (doc
->xmlRootNode
!= NULL
) {
118 xmlNsPtr
namespace = xmlSearchNs(doc
, doc
->xmlRootNode
, "dia");
119 if (!strcmp (doc
->xmlRootNode
->name
, "persistence") &&
121 xmlNodePtr window_node
;
122 window_node
= find_node_named(doc
->xmlRootNode
->xmlChildrenNode
,
124 while (window_node
!= NULL
) {
125 persistence_load_window(window_node
);
126 window_node
= window_node
->next
;
136 persistence_store_window_info(GtkWindow
*window
, PersistentWindow
*wininfo
,
139 /* Drawable means visible & mapped, what we usually think of as open. */
141 gtk_window_get_position(window
, &wininfo
->x
, &wininfo
->y
);
142 gtk_window_get_size(window
, &wininfo
->width
, &wininfo
->height
);
143 wininfo
->isopen
= TRUE
;
145 wininfo
->isopen
= FALSE
;
150 persistence_update_window(GtkWindow
*window
, GdkEvent
*event
, gpointer data
)
152 gchar
*name
= persistence_get_window_name(window
);
153 PersistentWindow
*wininfo
;
156 if (name
== NULL
) return FALSE
;
157 if (persistent_windows
== NULL
) {
158 persistent_windows
= g_hash_table_new(g_str_hash
, g_str_equal
);
160 wininfo
= (PersistentWindow
*)g_hash_table_lookup(persistent_windows
, name
);
162 /* Can't tell the window state from the window itself yet. */
163 isclosed
= (event
->type
== GDK_UNMAP
);
164 if (wininfo
!= NULL
) {
165 persistence_store_window_info(window
, wininfo
, isclosed
);
167 wininfo
= g_new0(PersistentWindow
, 1);
168 persistence_store_window_info(window
, wininfo
, isclosed
);
169 g_hash_table_insert(persistent_windows
, name
, wininfo
);
171 if (wininfo
->window
!= NULL
&& wininfo
->window
!= window
) {
172 g_object_unref(wininfo
->window
);
173 wininfo
->window
= NULL
;
175 if (wininfo
->window
== NULL
) {
176 wininfo
->window
= window
;
177 g_object_ref(window
);
182 /* Call this function after the window has a role assigned to use any
183 * persistence information about the window.
186 persistence_register_window(GtkWindow
*window
)
188 gchar
*name
= persistence_get_window_name(window
);
189 PersistentWindow
*wininfo
;
191 if (name
== NULL
) return;
192 if (persistent_windows
== NULL
) {
193 persistent_windows
= g_hash_table_new(g_str_hash
, g_str_equal
);
195 wininfo
= (PersistentWindow
*)g_hash_table_lookup(persistent_windows
, name
);
196 if (wininfo
!= NULL
) {
197 gtk_window_move(window
, wininfo
->x
, wininfo
->y
);
198 gtk_window_resize(window
, wininfo
->width
, wininfo
->height
);
199 if (wininfo
->isopen
) gtk_widget_show(window
);
201 wininfo
= g_new0(PersistentWindow
, 1);
202 gtk_window_get_position(window
, &wininfo
->x
, &wininfo
->y
);
203 gtk_window_get_size(window
, &wininfo
->width
, &wininfo
->height
);
204 /* Drawable means visible & mapped, what we usually think of as open. */
205 wininfo
->isopen
= GTK_WIDGET_DRAWABLE(GTK_WIDGET(window
));
206 g_hash_table_insert(persistent_windows
, name
, wininfo
);
208 if (wininfo
->window
!= NULL
&& wininfo
->window
!= window
) {
209 g_object_unref(wininfo
->window
);
210 wininfo
->window
= NULL
;
212 if (wininfo
->window
== NULL
) {
213 wininfo
->window
= window
;
214 g_object_ref(window
);
217 g_signal_connect(GTK_OBJECT(window
), "configure-event",
218 G_CALLBACK(persistence_update_window
), NULL
);
220 g_signal_connect(GTK_OBJECT(window
), "unmap-event",
221 G_CALLBACK(persistence_update_window
), NULL
);
224 /** Call this function at start-up to have a window creation function
225 * called if the window should be opened at startup.
226 * If no persistence information is available for the given role,
228 * @arg role The role of the window, as will be set by gtk_window_set_role()
229 * @arg createfunc A 0-argument function that creates the window. This
230 * function will be called if the persistence information indicates that the
231 * window should be open. The function should create and show the window.
234 persistence_register_window_create(gchar
*role
, NullaryFunc
*func
)
236 PersistentWindow
*wininfo
;
238 if (role
== NULL
) return;
239 if (persistent_windows
== NULL
) return;
240 wininfo
= (PersistentWindow
*)g_hash_table_lookup(persistent_windows
, role
);
241 if (wininfo
!= NULL
) {
246 /* Save the position of a window */
248 persistence_save_window(gpointer key
, gpointer value
, gpointer data
)
250 xmlNodePtr tree
= (xmlNodePtr
)data
;
251 PersistentWindow
*window_pos
= (PersistentWindow
*)value
;
255 window
= (ObjectNode
)xmlNewChild(tree
, NULL
, "window", NULL
);
257 data_add_string(new_attribute(window
, "role"), key
);
258 data_add_int(new_attribute(window
, "xpos"), window_pos
->x
);
259 data_add_int(new_attribute(window
, "ypos"), window_pos
->y
);
260 data_add_int(new_attribute(window
, "width"), window_pos
->width
);
261 data_add_int(new_attribute(window
, "height"), window_pos
->height
);
262 data_add_boolean(new_attribute(window
, "isopen"), window_pos
->isopen
);
266 /* Save all persistent data. */
272 gchar
*filename
= dia_config_filename("persistence");
274 doc
= xmlNewDoc("1.0");
275 doc
->encoding
= xmlStrdup("UTF-8");
276 doc
->xmlRootNode
= xmlNewDocNode(doc
, NULL
, "persistence", NULL
);
278 name_space
= xmlNewNs(doc
->xmlRootNode
,
279 "http://www.lysator.liu.se/~alla/dia/",
281 xmlSetNs(doc
->xmlRootNode
, name_space
);
283 /* Save any persistent window positions */
284 if (persistent_windows
!= NULL
&&
285 g_hash_table_size(persistent_windows
) != 0) {
286 g_hash_table_foreach(persistent_windows
, persistence_save_window
,
290 xmlDiaSaveFile(filename
, doc
);