~ubuntu-branches/ubuntu/vivid/ekiga/vivid-proposed

« back to all changes in this revision

Viewing changes to plugins/resource-list/rl-presentity.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kilian Krause
  • Date: 2011-07-17 00:24:50 UTC
  • mfrom: (5.1.5 upstream) (7.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20110717002450-ytg3wsrc1ptd3153
Tags: 3.3.1-1
* New upstream release.
 - Required libpt-dev 2.10 and libopal-dev 3.10
* Fix debian/watch to catch new version
* Remove libnotify0.7.patch - included upstream
* Add libboost-dev and libboost-signals-dev to Build-Depends
* debian/rules: Don't install *.la files for new internal shared libs
* Fix Vcs URIs to point to correct desktop/experimental/ekiga tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Ekiga -- A VoIP and Video-Conferencing application
 
4
 * Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
 
5
 
 
6
 * This program is free software; you can  redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or (at
 
9
 * your option) any later version. This program is distributed in the hope
 
10
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
 
11
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
12
 * See the GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 *
 
18
 * Ekiga is licensed under the GPL license and as a special exception, you
 
19
 * have permission to link or otherwise combine this program with the
 
20
 * programs OPAL, OpenH323 and PWLIB, and distribute the combination, without
 
21
 * applying the requirements of the GNU GPL to the OPAL, OpenH323 and PWLIB
 
22
 * programs, as long as you do follow the requirements of the GNU GPL for all
 
23
 * the rest of the software thus combined.
 
24
 */
 
25
 
 
26
 
 
27
/*
 
28
 *                         rl-presentity.cpp  -  description
 
29
 *                         ------------------------------------------
 
30
 *   begin                : written in 2008 by Julien Puydt
 
31
 *   copyright            : (c) 2008 by Julien Puydt
 
32
 *   description          : implementation of a presentity in a resource-list
 
33
 *
 
34
 */
 
35
 
 
36
#include <algorithm>
 
37
#include <set>
 
38
 
 
39
#include <glib/gi18n.h>
 
40
 
 
41
#include "form-request-simple.h"
 
42
#include "robust-xml.h"
 
43
#include "xcap-core.h"
 
44
 
 
45
#include "rl-presentity.h"
 
46
 
 
47
/* at one point we will return a smart pointer on this... and if we don't use
 
48
 * a false smart pointer, we will crash : the reference count isn't embedded!
 
49
 */
 
50
struct null_deleter
 
51
{
 
52
    void operator()(void const *) const
 
53
    {
 
54
    }
 
55
};
 
56
 
 
57
 
 
58
RL::Presentity::Presentity (Ekiga::ServiceCore &services_,
 
59
                            boost::shared_ptr<XCAP::Path> path_,
 
60
                            boost::shared_ptr<xmlDoc> doc_,
 
61
                            xmlNodePtr node_,
 
62
                            bool writable_) :
 
63
  services(services_), doc(doc_), node(node_), writable(writable_),
 
64
  name_node(NULL), presence("unknown"), status("")
 
65
{
 
66
  boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
 
67
  xmlChar *xml_str = NULL;
 
68
  xmlNsPtr ns = xmlSearchNsByHref (doc.get (), node,
 
69
                                   BAD_CAST "http://www.ekiga.org");
 
70
 
 
71
  if (ns == NULL) {
 
72
 
 
73
    // FIXME: we should handle the case, even if it shouldn't happen
 
74
  }
 
75
 
 
76
  xml_str = xmlGetProp (node, BAD_CAST "uri");
 
77
  if (xml_str != NULL) {
 
78
 
 
79
    uri = (const char *)xml_str;
 
80
    path = path_->build_child_with_attribute ("entry", "uri", uri);
 
81
    xmlFree (xml_str);
 
82
  } else {
 
83
 
 
84
    // FIXME: we should handle the case, even if it shouldn't happen
 
85
 
 
86
  }
 
87
 
 
88
  for (xmlNodePtr child = node->children ;
 
89
       child != NULL ;
 
90
       child = child->next) {
 
91
 
 
92
    if (child->type == XML_ELEMENT_NODE
 
93
        && child->name != NULL) {
 
94
 
 
95
      if (xmlStrEqual (BAD_CAST ("display-name"), child->name)) {
 
96
 
 
97
        name_node = child;
 
98
        continue;
 
99
      }
 
100
      else if (xmlStrEqual (BAD_CAST ("group"), child->name)
 
101
               && child->ns == ns) {
 
102
 
 
103
        xml_str = xmlNodeGetContent (child);
 
104
        if (xml_str != NULL)
 
105
          group_nodes[(const char *)xml_str] = child;
 
106
        else
 
107
          group_nodes[""] = child;
 
108
        xmlFree (xml_str);
 
109
        continue;
 
110
      }
 
111
    }
 
112
  }
 
113
 
 
114
  for (std::map<std::string, xmlNodePtr>::const_iterator iter
 
115
         = group_nodes.begin ();
 
116
       iter != group_nodes.end ();
 
117
       iter++)
 
118
    groups.insert (iter->first);
 
119
 
 
120
  presence_core->fetch_presence (uri);
 
121
}
 
122
 
 
123
RL::Presentity::~Presentity ()
 
124
{
 
125
}
 
126
 
 
127
 
 
128
const std::string
 
129
RL::Presentity::get_name () const
 
130
{
 
131
  std::string result;
 
132
 
 
133
  if (name_node != NULL) {
 
134
 
 
135
    xmlChar* str = xmlNodeGetContent (name_node);
 
136
    if (str != NULL) {
 
137
 
 
138
      result = ((const char*)str);
 
139
      xmlFree (str);
 
140
    }
 
141
  } else {
 
142
 
 
143
    result = _("Unnamed");
 
144
  }
 
145
 
 
146
  return result;
 
147
}
 
148
 
 
149
 
 
150
const std::string
 
151
RL::Presentity::get_presence () const
 
152
{
 
153
  return presence;
 
154
}
 
155
 
 
156
 
 
157
const std::string
 
158
RL::Presentity::get_status () const
 
159
{
 
160
  return status;
 
161
}
 
162
 
 
163
 
 
164
const std::set<std::string>
 
165
RL::Presentity::get_groups () const
 
166
{
 
167
  return groups;
 
168
}
 
169
 
 
170
 
 
171
const std::string
 
172
RL::Presentity::get_uri () const
 
173
{
 
174
  return uri;
 
175
}
 
176
 
 
177
 
 
178
void
 
179
RL::Presentity::set_presence (const std::string _presence)
 
180
{
 
181
  presence = _presence;
 
182
  updated ();
 
183
}
 
184
 
 
185
void
 
186
RL::Presentity::set_status (const std::string _status)
 
187
{
 
188
  status = _status;
 
189
  updated ();
 
190
}
 
191
 
 
192
 
 
193
bool
 
194
RL::Presentity::has_uri (const std::string uri) const
 
195
{
 
196
  return uri == get_uri ();
 
197
}
 
198
 
 
199
bool
 
200
RL::Presentity::populate_menu (Ekiga::MenuBuilder &builder)
 
201
{
 
202
  bool populated = false;
 
203
  boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
 
204
 
 
205
  populated = presence_core->populate_presentity_menu (PresentityPtr (this, null_deleter ()), uri, builder);
 
206
 
 
207
  if (writable) {
 
208
 
 
209
    if (populated)
 
210
      builder.add_separator ();
 
211
 
 
212
    builder.add_action ("edit", _("_Edit"),
 
213
                        boost::bind (&RL::Presentity::edit_presentity, this));
 
214
    builder.add_action ("remove", _("_Remove"),
 
215
                        boost::bind (&RL::Presentity::remove, this));
 
216
  }
 
217
 
 
218
  return true;
 
219
}
 
220
 
 
221
 
 
222
void
 
223
RL::Presentity::edit_presentity ()
 
224
{
 
225
  boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&RL::Presentity::edit_presentity_form_submitted, this, _1, _2)));
 
226
 
 
227
  // FIXME: we should be able to know all groups in the heap
 
228
  std::set<std::string> all_groups = groups;
 
229
 
 
230
  request->title (_("Edit remote contact"));
 
231
  request->instructions (_("Please fill in this form to change an existing "
 
232
                           "contact on a remote server"));
 
233
  request->text ("name", _("Name:"), get_name (), std::string ());
 
234
  request->text ("uri", _("Address:"), uri, std::string ());
 
235
 
 
236
  request->editable_set ("groups", _("Choose groups:"),
 
237
                         groups, all_groups);
 
238
 
 
239
  questions (request);
 
240
}
 
241
 
 
242
 
 
243
void
 
244
RL::Presentity::edit_presentity_form_submitted (bool submitted,
 
245
                                                Ekiga::Form &result)
 
246
{
 
247
  if (!submitted)
 
248
    return;
 
249
 
 
250
  const std::string new_name = result.text ("name");
 
251
  const std::string new_uri = result.text ("uri");
 
252
  const std::set<std::string> new_groups = result.editable_set ("groups");
 
253
  std::map<std::string, xmlNodePtr> future_group_nodes;
 
254
  xmlNsPtr ns = xmlSearchNsByHref (node->doc, node,
 
255
                                   BAD_CAST "http://www.ekiga.org");
 
256
  bool reload = false;
 
257
 
 
258
  robust_xmlNodeSetContent (node, &name_node, "name", new_name);
 
259
 
 
260
  if (uri != new_uri) {
 
261
 
 
262
    xmlSetProp (node, (const xmlChar*)"uri", (const xmlChar*)uri.c_str ());
 
263
    boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
 
264
    presence_core->unfetch_presence (uri);
 
265
    reload = true;
 
266
  }
 
267
 
 
268
  for (std::map<std::string, xmlNodePtr>::const_iterator iter
 
269
         = group_nodes.begin ();
 
270
       iter != group_nodes.end () ;
 
271
       iter++) {
 
272
 
 
273
    if (new_groups.find (iter->first) == new_groups.end ()) {
 
274
 
 
275
      xmlUnlinkNode (iter->second);
 
276
      xmlFreeNode (iter->second);
 
277
    }
 
278
    else {
 
279
      future_group_nodes[iter->first] = iter->second;
 
280
    }
 
281
  }
 
282
 
 
283
  for (std::set<std::string>::const_iterator iter = new_groups.begin ();
 
284
       iter != new_groups.end ();
 
285
       iter++) {
 
286
 
 
287
    if (std::find (groups.begin (), groups.end (), *iter) == groups.end ())
 
288
      future_group_nodes[*iter] = xmlNewChild (node, ns,
 
289
                                               BAD_CAST "group",
 
290
                                               BAD_CAST robust_xmlEscape (node->doc, *iter).c_str ());
 
291
  }
 
292
 
 
293
  group_nodes = future_group_nodes;
 
294
  groups = new_groups;
 
295
 
 
296
  save (reload);
 
297
}
 
298
 
 
299
void
 
300
RL::Presentity::save (bool reload)
 
301
{
 
302
  xmlBufferPtr buffer = xmlBufferCreate ();
 
303
  int result = xmlNodeDump (buffer, node->doc, node, 0, 0);
 
304
 
 
305
  if (result >= 0) {
 
306
 
 
307
    boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
 
308
    xcap->write (path, "application/xcap-el+xml",
 
309
                 (const char*)xmlBufferContent (buffer),
 
310
                 boost::bind (&RL::Presentity::save_result, this, _1, reload));
 
311
  }
 
312
 
 
313
  xmlBufferFree (buffer);
 
314
 
 
315
}
 
316
 
 
317
void
 
318
RL::Presentity::remove ()
 
319
{
 
320
  xmlUnlinkNode (node);
 
321
  xmlFreeNode (node);
 
322
  boost::shared_ptr<Ekiga::PresenceCore> presence_core = services.get<Ekiga::PresenceCore> ("presence-core");
 
323
 
 
324
  presence_core->unfetch_presence (uri);
 
325
 
 
326
  boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
 
327
  xcap->erase (path,
 
328
               boost::bind (&RL::Presentity::erase_result, this, _1));
 
329
}
 
330
 
 
331
void
 
332
RL::Presentity::save_result (std::string error,
 
333
                             bool reload)
 
334
{
 
335
  if ( !error.empty ()) {
 
336
 
 
337
    // FIXME: do better
 
338
    std::cout << "XCAP error: " << error << std::endl;
 
339
    trigger_reload ();
 
340
  } else {
 
341
 
 
342
    if (reload)
 
343
      trigger_reload ();
 
344
    else
 
345
      updated ();
 
346
  }
 
347
}
 
348
 
 
349
void
 
350
RL::Presentity::erase_result (std::string error)
 
351
{
 
352
  if ( !error.empty ()) {
 
353
 
 
354
    // FIXME: do better
 
355
    std::cout << "XCAP error: " << error << std::endl;
 
356
  }
 
357
 
 
358
  trigger_reload ();
 
359
}