~ubuntu-branches/ubuntu/precise/empathy/precise

« back to all changes in this revision

Viewing changes to libempathy/empathy-status-presets.c

Tags: upstream-0.21.90
ImportĀ upstreamĀ versionĀ 0.21.90

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 <telepathy-glib/util.h>
 
36
 
 
37
#include "empathy-debug.h"
 
38
#include "empathy-utils.h"
 
39
#include "empathy-status-presets.h"
 
40
 
 
41
#define DEBUG_DOMAIN "StatusPresets"
 
42
 
 
43
#define STATUS_PRESETS_XML_FILENAME "status-presets.xml"
 
44
#define STATUS_PRESETS_DTD_FILENAME "empathy-status-presets.dtd"
 
45
#define STATUS_PRESETS_MAX_EACH     15
 
46
 
 
47
typedef struct {
 
48
        gchar      *status;
 
49
        McPresence  state;
 
50
} StatusPreset;
 
51
 
 
52
static StatusPreset *status_preset_new          (McPresence    state,
 
53
                                                 const gchar  *status);
 
54
static void     status_preset_free              (StatusPreset *status);
 
55
static void     status_presets_file_parse       (const gchar  *filename);
 
56
const gchar *   status_presets_get_state_as_str (McPresence    state);
 
57
static gboolean status_presets_file_save        (void);
 
58
static void     status_presets_set_default      (McPresence    state,
 
59
                                                 const gchar  *status);
 
60
 
 
61
static GList        *presets = NULL;
 
62
static StatusPreset *default_preset = NULL;
 
63
 
 
64
static StatusPreset *
 
65
status_preset_new (McPresence   state,
 
66
                   const gchar *status)
 
67
{
 
68
        StatusPreset *preset;
 
69
 
 
70
        preset = g_new0 (StatusPreset, 1);
 
71
 
 
72
        preset->status = g_strdup (status);
 
73
        preset->state = state;
 
74
 
 
75
        return preset;
 
76
}
 
77
 
 
78
static void
 
79
status_preset_free (StatusPreset *preset)
 
80
{
 
81
        g_free (preset->status);
 
82
        g_free (preset);
 
83
}
 
84
 
 
85
static void
 
86
status_presets_file_parse (const gchar *filename)
 
87
{
 
88
        xmlParserCtxtPtr ctxt;
 
89
        xmlDocPtr        doc;
 
90
        xmlNodePtr       presets_node;
 
91
        xmlNodePtr       node;
 
92
 
 
93
        empathy_debug (DEBUG_DOMAIN, "Attempting to parse file:'%s'...", filename);
 
94
 
 
95
        ctxt = xmlNewParserCtxt ();
 
96
 
 
97
        /* Parse and validate the file. */
 
98
        doc = xmlCtxtReadFile (ctxt, filename, NULL, 0);
 
99
        if (!doc) {
 
100
                g_warning ("Failed to parse file:'%s'", filename);
 
101
                xmlFreeParserCtxt (ctxt);
 
102
                return;
 
103
        }
 
104
 
 
105
        if (!empathy_xml_validate (doc, STATUS_PRESETS_DTD_FILENAME)) {
 
106
                g_warning ("Failed to validate file:'%s'", filename);
 
107
                xmlFreeDoc(doc);
 
108
                xmlFreeParserCtxt (ctxt);
 
109
                return;
 
110
        }
 
111
 
 
112
        /* The root node, presets. */
 
113
        presets_node = xmlDocGetRootElement (doc);
 
114
 
 
115
        node = presets_node->children;
 
116
        while (node) {
 
117
                if (strcmp ((gchar *) node->name, "status") == 0 ||
 
118
                    strcmp ((gchar *) node->name, "default") == 0) {
 
119
                        McPresence    state;
 
120
                        gchar        *status;
 
121
                        gchar        *state_str;
 
122
                        StatusPreset *preset;
 
123
                        gboolean      is_default = FALSE;
 
124
 
 
125
                        if (strcmp ((gchar *) node->name, "default") == 0) {
 
126
                                is_default = TRUE;
 
127
                        }
 
128
 
 
129
                        status = (gchar *) xmlNodeGetContent (node);
 
130
                        state_str = (gchar *) xmlGetProp (node, "presence");
 
131
 
 
132
                        if (state_str) {
 
133
                                state = empathy_presence_from_str (state_str);
 
134
 
 
135
                                if (is_default) {
 
136
                                        empathy_debug (DEBUG_DOMAIN,
 
137
                                                      "Default status preset state is:'%s', status:'%s'",
 
138
                                                      state_str, status);
 
139
 
 
140
                                        status_presets_set_default (state, status);
 
141
                                } else {
 
142
                                        preset = status_preset_new (state, status);
 
143
                                        presets = g_list_append (presets, preset);
 
144
                                }
 
145
                        }
 
146
 
 
147
                        xmlFree (status);
 
148
                        xmlFree (state_str);
 
149
                }
 
150
 
 
151
                node = node->next;
 
152
        }
 
153
 
 
154
        /* Use the default if not set */
 
155
        if (!default_preset) {
 
156
                status_presets_set_default (MC_PRESENCE_OFFLINE, NULL);
 
157
        }
 
158
 
 
159
        empathy_debug (DEBUG_DOMAIN, "Parsed %d status presets", g_list_length (presets));
 
160
 
 
161
        xmlFreeDoc (doc);
 
162
        xmlFreeParserCtxt (ctxt);
 
163
}
 
164
 
 
165
void
 
166
empathy_status_presets_get_all (void)
 
167
{
 
168
        gchar *dir;
 
169
        gchar *file_with_path;
 
170
 
 
171
        /* If already set up clean up first. */
 
172
        if (presets) {
 
173
                g_list_foreach (presets, (GFunc) status_preset_free, NULL);
 
174
                g_list_free (presets);
 
175
                presets = NULL;
 
176
        }
 
177
 
 
178
        dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
 
179
        g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
180
        file_with_path = g_build_filename (dir, STATUS_PRESETS_XML_FILENAME, NULL);
 
181
        g_free (dir);
 
182
 
 
183
        if (g_file_test (file_with_path, G_FILE_TEST_EXISTS)) {
 
184
                status_presets_file_parse (file_with_path);
 
185
        }
 
186
 
 
187
        g_free (file_with_path);
 
188
}
 
189
 
 
190
static gboolean
 
191
status_presets_file_save (void)
 
192
{
 
193
        xmlDocPtr   doc;
 
194
        xmlNodePtr  root;
 
195
        GList      *l;
 
196
        gchar      *dir;
 
197
        gchar      *file;
 
198
        gint        count[LAST_MC_PRESENCE];
 
199
        gint        i;
 
200
 
 
201
        for (i = 0; i < LAST_MC_PRESENCE; i++) {
 
202
                count[i] = 0;
 
203
        }
 
204
 
 
205
        dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
 
206
        g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
 
207
        file = g_build_filename (dir, STATUS_PRESETS_XML_FILENAME, NULL);
 
208
        g_free (dir);
 
209
 
 
210
        doc = xmlNewDoc ("1.0");
 
211
        root = xmlNewNode (NULL, "presets");
 
212
        xmlDocSetRootElement (doc, root);
 
213
 
 
214
        if (default_preset) {
 
215
                xmlNodePtr  subnode;
 
216
                xmlChar    *state;
 
217
 
 
218
                state = (gchar*) empathy_presence_to_str (default_preset->state);
 
219
 
 
220
                subnode = xmlNewTextChild (root, NULL, "default",
 
221
                                           default_preset->status);
 
222
                xmlNewProp (subnode, "presence", state);
 
223
        }
 
224
 
 
225
        for (l = presets; l; l = l->next) {
 
226
                StatusPreset *sp;
 
227
                xmlNodePtr    subnode;
 
228
                xmlChar      *state;
 
229
 
 
230
                sp = l->data;
 
231
                state = (gchar*) empathy_presence_to_str (sp->state);
 
232
 
 
233
                count[sp->state]++;
 
234
                if (count[sp->state] > STATUS_PRESETS_MAX_EACH) {
 
235
                        continue;
 
236
                }
 
237
 
 
238
                subnode = xmlNewTextChild (root, NULL,
 
239
                                           "status", sp->status);
 
240
                xmlNewProp (subnode, "presence", state);
 
241
        }
 
242
 
 
243
        /* Make sure the XML is indented properly */
 
244
        xmlIndentTreeOutput = 1;
 
245
 
 
246
        empathy_debug (DEBUG_DOMAIN, "Saving file:'%s'", file);
 
247
        xmlSaveFormatFileEnc (file, doc, "utf-8", 1);
 
248
        xmlFreeDoc (doc);
 
249
 
 
250
        g_free (file);
 
251
 
 
252
        return TRUE;
 
253
}
 
254
 
 
255
GList *
 
256
empathy_status_presets_get (McPresence state,
 
257
                           gint       max_number)
 
258
{
 
259
        GList *list = NULL;
 
260
        GList *l;
 
261
        gint   i;
 
262
 
 
263
        i = 0;
 
264
        for (l = presets; l; l = l->next) {
 
265
                StatusPreset *sp;
 
266
 
 
267
                sp = l->data;
 
268
 
 
269
                if (sp->state != state) {
 
270
                        continue;
 
271
                }
 
272
 
 
273
                list = g_list_append (list, sp->status);
 
274
                i++;
 
275
 
 
276
                if (max_number != -1 && i >= max_number) {
 
277
                        break;
 
278
                }
 
279
        }
 
280
 
 
281
        return list;
 
282
}
 
283
 
 
284
void
 
285
empathy_status_presets_set_last (McPresence   state,
 
286
                                const gchar *status)
 
287
{
 
288
        GList        *l;
 
289
        StatusPreset *preset;
 
290
        gint          num;
 
291
 
 
292
        /* Check if duplicate */
 
293
        for (l = presets; l; l = l->next) {
 
294
                preset = l->data;
 
295
 
 
296
                if (state == preset->state &&
 
297
                    !tp_strdiff (status, preset->status)) {
 
298
                        return;
 
299
                }
 
300
        }
 
301
 
 
302
        preset = status_preset_new (state, status);
 
303
        presets = g_list_prepend (presets, preset);
 
304
 
 
305
        num = 0;
 
306
        for (l = presets; l; l = l->next) {
 
307
                preset = l->data;
 
308
 
 
309
                if (state != preset->state) {
 
310
                        continue;
 
311
                }
 
312
 
 
313
                num++;
 
314
 
 
315
                if (num > STATUS_PRESETS_MAX_EACH) {
 
316
                        status_preset_free (preset);
 
317
                        presets = g_list_delete_link (presets, l);
 
318
                        break;
 
319
                }
 
320
        }
 
321
 
 
322
        status_presets_file_save ();
 
323
}
 
324
 
 
325
void
 
326
empathy_status_presets_remove (McPresence   state,
 
327
                               const gchar *status)
 
328
{
 
329
        StatusPreset *preset;
 
330
        GList        *l;
 
331
 
 
332
        for (l = presets; l; l = l->next) {
 
333
                preset = l->data;
 
334
 
 
335
                if (state == preset->state &&
 
336
                    !tp_strdiff (status, preset->status)) {
 
337
                        status_preset_free (preset);
 
338
                        presets = g_list_delete_link (presets, l);
 
339
                        status_presets_file_save ();
 
340
                        break;
 
341
                }
 
342
        }
 
343
}
 
344
 
 
345
void
 
346
empathy_status_presets_reset (void)
 
347
{
 
348
        g_list_foreach (presets, (GFunc) status_preset_free, NULL);
 
349
        g_list_free (presets);
 
350
 
 
351
        presets = NULL;
 
352
 
 
353
        status_presets_set_default (MC_PRESENCE_AVAILABLE, NULL);
 
354
 
 
355
        status_presets_file_save ();
 
356
}
 
357
 
 
358
McPresence
 
359
empathy_status_presets_get_default_state (void)
 
360
{
 
361
        if (!default_preset) {
 
362
                return MC_PRESENCE_OFFLINE;
 
363
        }
 
364
 
 
365
        return default_preset->state;
 
366
}
 
367
 
 
368
const gchar *
 
369
empathy_status_presets_get_default_status (void)
 
370
{
 
371
        if (!default_preset ||
 
372
            !default_preset->status) {
 
373
                return NULL;
 
374
        }
 
375
 
 
376
        return default_preset->status;
 
377
}
 
378
 
 
379
static void
 
380
status_presets_set_default (McPresence   state,
 
381
                            const gchar *status)
 
382
{
 
383
        if (default_preset) {
 
384
                status_preset_free (default_preset);
 
385
        }
 
386
 
 
387
        default_preset = status_preset_new (state, status);
 
388
}
 
389
 
 
390
void
 
391
empathy_status_presets_set_default (McPresence   state,
 
392
                                   const gchar *status)
 
393
{
 
394
        status_presets_set_default (state, status);
 
395
        status_presets_file_save ();
 
396
}
 
397
 
 
398
void
 
399
empathy_status_presets_clear_default (void)
 
400
{
 
401
        if (default_preset) {
 
402
                status_preset_free (default_preset);
 
403
                default_preset = NULL;
 
404
        }
 
405
 
 
406
        status_presets_file_save ();
 
407
}