No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Chris Lahey <clahey@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <libxml/parser.h>
31 #include <libxml/xmlmemory.h>
32
33 #include <libedataserver/libedataserver.h>
34
35 #include "e-util/e-util.h"
36 #include "libevolution-utils/e-xml-utils.h"
37
38 #include "e-table-state.h"
39
40 #define STATE_VERSION 0.1
41
42 G_DEFINE_TYPE (ETableState, e_table_state, G_TYPE_OBJECT)
43
44 static void
45 etst_dispose (GObject *object)
46 {
47 ETableState *etst = E_TABLE_STATE (object);
48
49 if (etst->sort_info) {
50 g_object_unref (etst->sort_info);
51 etst->sort_info = NULL;
52 }
53
54 G_OBJECT_CLASS (e_table_state_parent_class)->dispose (object);
55 }
56
57 static void
58 etst_finalize (GObject *object)
59 {
60 ETableState *etst = E_TABLE_STATE (object);
61
62 if (etst->columns) {
63 g_free (etst->columns);
64 etst->columns = NULL;
65 }
66
67 if (etst->expansions) {
68 g_free (etst->expansions);
69 etst->expansions = NULL;
70 }
71
72 G_OBJECT_CLASS (e_table_state_parent_class)->finalize (object);
73 }
74
75 static void
76 e_table_state_class_init (ETableStateClass *class)
77 {
78 GObjectClass *object_class = G_OBJECT_CLASS (class);
79
80 object_class->dispose = etst_dispose;
81 object_class->finalize = etst_finalize;
82 }
83
84 static void
85 e_table_state_init (ETableState *state)
86 {
87 state->columns = NULL;
88 state->expansions = NULL;
89 state->sort_info = e_table_sort_info_new ();
90 }
91
92 ETableState *
93 e_table_state_new (void)
94 {
95 return g_object_new (E_TYPE_TABLE_STATE, NULL);
96 }
97
98 ETableState *
99 e_table_state_vanilla (gint col_count)
100 {
101 GString *str;
102 gint i;
103 ETableState *res;
104
105 str = g_string_new ("<ETableState>\n");
106 for (i = 0; i < col_count; i++)
107 g_string_append_printf (str, " <column source=\"%d\"/>\n", i);
108 g_string_append (str, " <grouping></grouping>\n");
109 g_string_append (str, "</ETableState>\n");
110
111 res = e_table_state_new ();
112 e_table_state_load_from_string (res, str->str);
113
114 g_string_free (str, TRUE);
115 return res;
116 }
117
118 gboolean
119 e_table_state_load_from_file (ETableState *state,
120 const gchar *filename)
121 {
122 xmlDoc *doc;
123
124 g_return_val_if_fail (E_IS_TABLE_STATE (state), FALSE);
125 g_return_val_if_fail (filename != NULL, FALSE);
126
127 doc = e_xml_parse_file (filename);
128 if (doc) {
129 xmlNode *node = xmlDocGetRootElement (doc);
130 e_table_state_load_from_node (state, node);
131 xmlFreeDoc (doc);
132 return TRUE;
133 }
134 return FALSE;
135 }
136
137 void
138 e_table_state_load_from_string (ETableState *state,
139 const gchar *xml)
140 {
141 xmlDoc *doc;
142
143 g_return_if_fail (E_IS_TABLE_STATE (state));
144 g_return_if_fail (xml != NULL);
145
146 doc = xmlParseMemory ((gchar *) xml, strlen (xml));
147 if (doc) {
148 xmlNode *node = xmlDocGetRootElement (doc);
149 e_table_state_load_from_node (state, node);
150 xmlFreeDoc (doc);
151 }
152 }
153
154 typedef struct {
155 gint column;
156 gdouble expansion;
157 } int_and_double;
158
159 void
160 e_table_state_load_from_node (ETableState *state,
161 const xmlNode *node)
162 {
163 xmlNode *children;
164 GList *list = NULL, *iterator;
165 gdouble state_version;
166 gint i;
167 gboolean can_group = TRUE;
168
169 g_return_if_fail (E_IS_TABLE_STATE (state));
170 g_return_if_fail (node != NULL);
171
172 state_version = e_xml_get_double_prop_by_name_with_default (
173 node, (const guchar *)"state-version", STATE_VERSION);
174
175 if (state->sort_info) {
176 can_group = e_table_sort_info_get_can_group (state->sort_info);
177 g_object_unref (state->sort_info);
178 }
179
180 state->sort_info = NULL;
181 children = node->xmlChildrenNode;
182 for (; children; children = children->next) {
183 if (!strcmp ((gchar *) children->name, "column")) {
184 int_and_double *column_info = g_new (int_and_double, 1);
185
186 column_info->column = e_xml_get_integer_prop_by_name (
187 children, (const guchar *)"source");
188 column_info->expansion =
189 e_xml_get_double_prop_by_name_with_default (
190 children, (const guchar *)"expansion", 1);
191
192 list = g_list_append (list, column_info);
193 } else if (state->sort_info == NULL &&
194 !strcmp ((gchar *) children->name, "grouping")) {
195 state->sort_info = e_table_sort_info_new ();
196 e_table_sort_info_load_from_node (
197 state->sort_info, children, state_version);
198 }
199 }
200 g_free (state->columns);
201 g_free (state->expansions);
202 state->col_count = g_list_length (list);
203 state->columns = g_new (int, state->col_count);
204 state->expansions = g_new (double, state->col_count);
205
206 if (!state->sort_info)
207 state->sort_info = e_table_sort_info_new ();
208 e_table_sort_info_set_can_group (state->sort_info, can_group);
209
210 for (iterator = list, i = 0; iterator; i++) {
211 int_and_double *column_info = iterator->data;
212
213 state->columns[i] = column_info->column;
214 state->expansions[i] = column_info->expansion;
215 g_free (column_info);
216 iterator = g_list_next (iterator);
217 }
218 g_list_free (list);
219 }
220
221 void
222 e_table_state_save_to_file (ETableState *state,
223 const gchar *filename)
224 {
225 xmlDoc *doc;
226
227 if ((doc = xmlNewDoc ((const guchar *)"1.0")) == NULL)
228 return;
229
230 xmlDocSetRootElement (doc, e_table_state_save_to_node (state, NULL));
231
232 e_xml_save_file (filename, doc);
233
234 xmlFreeDoc (doc);
235 }
236
237 gchar *
238 e_table_state_save_to_string (ETableState *state)
239 {
240 gchar *ret_val;
241 xmlChar *string;
242 gint length;
243 xmlDoc *doc;
244
245 g_return_val_if_fail (E_IS_TABLE_STATE (state), NULL);
246
247 doc = xmlNewDoc ((const guchar *)"1.0");
248 xmlDocSetRootElement (doc, e_table_state_save_to_node (state, NULL));
249 xmlDocDumpMemory (doc, &string, &length);
250 xmlFreeDoc (doc);
251
252 ret_val = g_strdup ((gchar *) string);
253 xmlFree (string);
254 return ret_val;
255 }
256
257 xmlNode *
258 e_table_state_save_to_node (ETableState *state,
259 xmlNode *parent)
260 {
261 gint i;
262 xmlNode *node;
263
264 g_return_val_if_fail (E_IS_TABLE_STATE (state), NULL);
265
266 if (parent)
267 node = xmlNewChild (
268 parent, NULL, (const guchar *) "ETableState", NULL);
269 else
270 node = xmlNewNode (NULL, (const guchar *) "ETableState");
271
272 e_xml_set_double_prop_by_name (
273 node, (const guchar *)"state-version", STATE_VERSION);
274
275 for (i = 0; i < state->col_count; i++) {
276 gint column = state->columns[i];
277 gdouble expansion = state->expansions[i];
278 xmlNode *new_node;
279
280 new_node = xmlNewChild (
281 node, NULL, (const guchar *) "column", NULL);
282 e_xml_set_integer_prop_by_name (
283 new_node, (const guchar *) "source", column);
284 if (expansion >= -1)
285 e_xml_set_double_prop_by_name (
286 new_node, (const guchar *)
287 "expansion", expansion);
288 }
289
290 e_table_sort_info_save_to_node (state->sort_info, node);
291
292 return node;
293 }
294
295 /**
296 * e_table_state_duplicate:
297 * @state: The ETableState to duplicate
298 *
299 * This creates a copy of the %ETableState @state
300 *
301 * Returns: The duplicated %ETableState.
302 */
303 ETableState *
304 e_table_state_duplicate (ETableState *state)
305 {
306 ETableState *new_state;
307 gchar *copy;
308
309 g_return_val_if_fail (E_IS_TABLE_STATE (state), NULL);
310
311 new_state = e_table_state_new ();
312 copy = e_table_state_save_to_string (state);
313 e_table_state_load_from_string (new_state, copy);
314 g_free (copy);
315
316 e_table_sort_info_set_can_group
317 (new_state->sort_info,
318 e_table_sort_info_get_can_group (state->sort_info));
319
320 return new_state;
321 }