~bcurtiswx/ubuntu/precise/empathy/3.4.2.1-0ubuntu1

« back to all changes in this revision

Viewing changes to libempathy-gtk/gossip-status-presets.c

  • Committer: Bazaar Package Importer
  • Author(s): Sjoerd Simons
  • Date: 2007-05-20 15:31:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070520153142-r3auwguxdgxhktqb
Tags: upstream-0.4
ImportĀ upstreamĀ versionĀ 0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
3
 * Copyright (C) 2005-2007 Imendio AB
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License as
 
7
 * published by the Free Software Foundation; either version 2 of the
 
8
 * License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public
 
16
 * License along with this program; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 *
 
20
 * Author: Martyn Russell <martyn@imendio.com>
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <sys/types.h>
 
26
#include <sys/stat.h>
 
27
#include <string.h>
 
28
 
 
29
#include <glib.h>
 
30
#include <glib/gi18n.h>
 
31
 
 
32
#include <libxml/parser.h>
 
33
#include <libxml/tree.h>
 
34
 
 
35
#include <libempathy/gossip-debug.h>
 
36
#include <libempathy/gossip-utils.h>
 
37
 
 
38
#include "gossip-status-presets.h"
 
39
 
 
40
#define DEBUG_DOMAIN "StatusPresets"
 
41
 
 
42
#define STATUS_PRESETS_XML_FILENAME "status-presets.xml"
 
43
#define STATUS_PRESETS_DTD_FILENAME "gossip-status-presets.dtd"
 
44
#define STATUS_PRESETS_MAX_EACH     15
 
45
 
 
46
typedef struct {
 
47
        gchar      *status;
 
48
        McPresence  state;
 
49
} StatusPreset;
 
50
 
 
51
static StatusPreset *status_preset_new          (McPresence    state,
 
52
                                                 const gchar  *status);
 
53
static void     status_preset_free              (StatusPreset *status);
 
54
static void     status_presets_file_parse       (const gchar  *filename);
 
55
const gchar *   status_presets_get_state_as_str (McPresence    state);
 
56
static gboolean status_presets_file_save        (void);
 
57
static void     status_presets_set_default      (McPresence    state,
 
58
                                                 const gchar  *status);
 
59
 
 
60
static GList        *presets = NULL;
 
61
static StatusPreset *default_preset = NULL;
 
62
 
 
63
static StatusPreset *
 
64
status_preset_new (McPresence   state,
 
65
                   const gchar *status)
 
66
{
 
67
        StatusPreset *preset;
 
68
 
 
69
        preset = g_new0 (StatusPreset, 1);
 
70
 
 
71
        preset->status = g_strdup (status);
 
72
        preset->state = state;
 
73
 
 
74
        return preset;
 
75
}
 
76
 
 
77
static void
 
78
status_preset_free (StatusPreset *preset)
 
79
{
 
80
        g_free (preset->status);
 
81
        g_free (preset);
 
82
}
 
83
 
 
84
static void
 
85
status_presets_file_parse (const gchar *filename)
 
86
{
 
87
        xmlParserCtxtPtr ctxt;
 
88
        xmlDocPtr        doc;
 
89
        xmlNodePtr       presets_node;
 
90
        xmlNodePtr       node;
 
91
 
 
92
        gossip_debug (DEBUG_DOMAIN, "Attempting to parse file:'%s'...", filename);
 
93
 
 
94
        ctxt = xmlNewParserCtxt ();
 
95
 
 
96
        /* Parse and validate the file. */
 
97
        doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
 
98
        if (!doc) {
 
99
                g_warning ("Failed to parse file:'%s'", filename);
 
100
                xmlFreeParserCtxt (ctxt);
 
101
                return;
 
102
        }
 
103
 
 
104
        if (!gossip_xml_validate (doc, STATUS_PRESETS_DTD_FILENAME)) {
 
105
                g_warning ("Failed to validate file:'%s'", filename);
 
106
                xmlFreeDoc(doc);
 
107
                xmlFreeParserCtxt (ctxt);
 
108
                return;
 
109
        }
 
110
 
 
111
        /* The root node, presets. */
 
112
        presets_node = xmlDocGetRootElement (doc);
 
113
 
 
114
        node = presets_node->children;
 
115
        while (node) {
 
116
                if (strcmp ((gchar *) node->name, "status") == 0 ||
 
117
                    strcmp ((gchar *) node->name, "default") == 0) {
 
118
                        McPresence    state;
 
119
                        gchar        *status;
 
120
                        gchar        *state_str;
 
121
                        StatusPreset *preset;
 
122
                        gboolean      is_default = FALSE;
 
123
 
 
124
                        if (strcmp ((gchar *) node->name, "default") == 0) {
 
125
                                is_default = TRUE;
 
126
                        }
 
127
 
 
128
                        status = (gchar *) xmlNodeGetContent (node);
 
129
                        state_str = (gchar *) xmlGetProp (node, "presence");
 
130
 
 
131
                        if (state_str) {
 
132
                                state = gossip_presence_state_from_str (state_str);
 
133
 
 
134
                                if (is_default) {
 
135
                                        gossip_debug (DEBUG_DOMAIN,
 
136
                                                      "Default status preset state is:'%s', status:'%s'",
 
137
                                                      state_str, status);
 
138
 
 
139
                                        status_presets_set_default (state, status);
 
140
                                } else {
 
141
                                        preset = status_preset_new (state, status);
 
142
                                        presets = g_list_append (presets, preset);
 
143
                                }
 
144
                        }
 
145
 
 
146
                        xmlFree (status);
 
147
                        xmlFree (state_str);
 
148
                }
 
149
 
 
150
                node = node->next;
 
151
        }
 
152
 
 
153
        /* Use the default if not set */
 
154
        if (!default_preset) {
 
155
                status_presets_set_default (MC_PRESENCE_OFFLINE, NULL);
 
156
        }
 
157
 
 
158
        gossip_debug (DEBUG_DOMAIN, "Parsed %d status presets", g_list_length (presets));
 
159
 
 
160
        xmlFreeDoc (doc);
 
161
        xmlFreeParserCtxt (ctxt);
 
162
}
 
163
 
 
164
void
 
165
gossip_status_presets_get_all (void)
 
166
{
 
167
        gchar *dir;
 
168
        gchar *file_with_path;
 
169
 
 
170
        /* If already set up clean up first. */
 
171
        if (presets) {
 
172
                g_list_foreach (presets, (GFunc) status_preset_free, NULL);
 
173
                g_list_free (presets);
 
174
                presets = NULL;
 
175
        }
 
176
 
 
177
        dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
 
178
        g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
179
        file_with_path = g_build_filename (dir, STATUS_PRESETS_XML_FILENAME, NULL);
 
180
        g_free (dir);
 
181
 
 
182
        if (g_file_test (file_with_path, G_FILE_TEST_EXISTS)) {
 
183
                status_presets_file_parse (file_with_path);
 
184
        }
 
185
 
 
186
        g_free (file_with_path);
 
187
}
 
188
 
 
189
static gboolean
 
190
status_presets_file_save (void)
 
191
{
 
192
        xmlDocPtr   doc;
 
193
        xmlNodePtr  root;
 
194
        GList      *l;
 
195
        gchar      *dir;
 
196
        gchar      *file;
 
197
        gint        count[LAST_MC_PRESENCE];
 
198
        gint        i;
 
199
 
 
200
        for (i = 0; i < LAST_MC_PRESENCE; i++) {
 
201
                count[i] = 0;
 
202
        }
 
203
 
 
204
        dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
 
205
        g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
206
        file = g_build_filename (dir, STATUS_PRESETS_XML_FILENAME, NULL);
 
207
        g_free (dir);
 
208
 
 
209
        doc = xmlNewDoc ("1.0");
 
210
        root = xmlNewNode (NULL, "presets");
 
211
        xmlDocSetRootElement (doc, root);
 
212
 
 
213
        if (default_preset) {
 
214
                xmlNodePtr  subnode;
 
215
                xmlChar    *state;
 
216
 
 
217
                state = (gchar*) gossip_presence_state_to_str (default_preset->state);
 
218
 
 
219
                subnode = xmlNewTextChild (root, NULL, "default",
 
220
                                           default_preset->status);
 
221
                xmlNewProp (subnode, "presence", state);
 
222
        }
 
223
 
 
224
        for (l = presets; l; l = l->next) {
 
225
                StatusPreset *sp;
 
226
                xmlNodePtr    subnode;
 
227
                xmlChar      *state;
 
228
 
 
229
                sp = l->data;
 
230
                state = (gchar*) gossip_presence_state_to_str (sp->state);
 
231
 
 
232
                count[sp->state]++;
 
233
                if (count[sp->state] > STATUS_PRESETS_MAX_EACH) {
 
234
                        continue;
 
235
                }
 
236
 
 
237
                subnode = xmlNewTextChild (root, NULL,
 
238
                                           "status", sp->status);
 
239
                xmlNewProp (subnode, "presence", state);
 
240
        }
 
241
 
 
242
        /* Make sure the XML is indented properly */
 
243
        xmlIndentTreeOutput = 1;
 
244
 
 
245
        gossip_debug (DEBUG_DOMAIN, "Saving file:'%s'", file);
 
246
        xmlSaveFormatFileEnc (file, doc, "utf-8", 1);
 
247
        xmlFreeDoc (doc);
 
248
 
 
249
        g_free (file);
 
250
 
 
251
        return TRUE;
 
252
}
 
253
 
 
254
GList *
 
255
gossip_status_presets_get (McPresence state,
 
256
                           gint       max_number)
 
257
{
 
258
        GList *list = NULL;
 
259
        GList *l;
 
260
        gint   i;
 
261
 
 
262
        i = 0;
 
263
        for (l = presets; l; l = l->next) {
 
264
                StatusPreset *sp;
 
265
 
 
266
                sp = l->data;
 
267
 
 
268
                if (sp->state != state) {
 
269
                        continue;
 
270
                }
 
271
 
 
272
                list = g_list_append (list, sp->status);
 
273
                i++;
 
274
 
 
275
                if (max_number != -1 && i >= max_number) {
 
276
                        break;
 
277
                }
 
278
        }
 
279
 
 
280
        return list;
 
281
}
 
282
 
 
283
void
 
284
gossip_status_presets_set_last (McPresence   state,
 
285
                                const gchar *status)
 
286
{
 
287
        GList        *l;
 
288
        StatusPreset *preset;
 
289
        gint          num;
 
290
 
 
291
        /* Remove any duplicate. */
 
292
        for (l = presets; l; l = l->next) {
 
293
                preset = l->data;
 
294
 
 
295
                if (state == preset->state) {
 
296
                        if (strcmp (status, preset->status) == 0) {
 
297
                                status_preset_free (preset);
 
298
                                presets = g_list_delete_link (presets, l);
 
299
                                break;
 
300
                        }
 
301
                }
 
302
        }
 
303
 
 
304
        preset = status_preset_new (state, status);
 
305
        presets = g_list_prepend (presets, preset);
 
306
 
 
307
        num = 0;
 
308
        for (l = presets; l; l = l->next) {
 
309
                preset = l->data;
 
310
 
 
311
                if (state != preset->state) {
 
312
                        continue;
 
313
                }
 
314
 
 
315
                num++;
 
316
 
 
317
                if (num > STATUS_PRESETS_MAX_EACH) {
 
318
                        status_preset_free (preset);
 
319
                        presets = g_list_delete_link (presets, l);
 
320
                        break;
 
321
                }
 
322
        }
 
323
 
 
324
        status_presets_file_save ();
 
325
}
 
326
 
 
327
void
 
328
gossip_status_presets_reset (void)
 
329
{
 
330
        g_list_foreach (presets, (GFunc) status_preset_free, NULL);
 
331
        g_list_free (presets);
 
332
 
 
333
        presets = NULL;
 
334
 
 
335
        status_presets_set_default (MC_PRESENCE_AVAILABLE, NULL);
 
336
 
 
337
        status_presets_file_save ();
 
338
}
 
339
 
 
340
McPresence
 
341
gossip_status_presets_get_default_state (void)
 
342
{
 
343
        if (!default_preset) {
 
344
                return MC_PRESENCE_OFFLINE;
 
345
        }
 
346
 
 
347
        return default_preset->state;
 
348
}
 
349
 
 
350
const gchar *
 
351
gossip_status_presets_get_default_status (void)
 
352
{
 
353
        if (!default_preset ||
 
354
            !default_preset->status) {
 
355
                return NULL;
 
356
        }
 
357
 
 
358
        return default_preset->status;
 
359
}
 
360
 
 
361
static void
 
362
status_presets_set_default (McPresence   state,
 
363
                            const gchar *status)
 
364
{
 
365
        if (default_preset) {
 
366
                status_preset_free (default_preset);
 
367
        }
 
368
 
 
369
        default_preset = status_preset_new (state, status);
 
370
}
 
371
 
 
372
void
 
373
gossip_status_presets_set_default (McPresence   state,
 
374
                                   const gchar *status)
 
375
{
 
376
        status_presets_set_default (state, status);
 
377
        status_presets_file_save ();
 
378
}
 
379
 
 
380
void
 
381
gossip_status_presets_clear_default (void)
 
382
{
 
383
        if (default_preset) {
 
384
                status_preset_free (default_preset);
 
385
                default_preset = NULL;
 
386
        }
 
387
 
 
388
        status_presets_file_save ();
 
389
}