ekiga r7221 - trunk/lib/engine/components/resource-list



Author: jpuydt
Date: Wed Oct 15 12:48:01 2008
New Revision: 7221
URL: http://svn.gnome.org/viewvc/ekiga?rev=7221&view=rev

Log:
Reworked the resource-list code : does the same thing as before, but should be more extensible (entry-ref and external, for example)

Added:
   trunk/lib/engine/components/resource-list/rl-entry-ref.cpp
   trunk/lib/engine/components/resource-list/rl-entry-ref.h
      - copied, changed from r7220, /trunk/lib/engine/components/resource-list/rl-presentity.h
   trunk/lib/engine/components/resource-list/rl-entry.cpp
   trunk/lib/engine/components/resource-list/rl-entry.h
      - copied, changed from r7220, /trunk/lib/engine/components/resource-list/rl-presentity.h
   trunk/lib/engine/components/resource-list/rl-list.cpp
   trunk/lib/engine/components/resource-list/rl-list.h
      - copied, changed from r7220, /trunk/lib/engine/components/resource-list/rl-heap.h
Removed:
   trunk/lib/engine/components/resource-list/rl-presentity.cpp
   trunk/lib/engine/components/resource-list/rl-presentity.h
Modified:
   trunk/lib/engine/components/resource-list/Makefile.am
   trunk/lib/engine/components/resource-list/rl-heap.cpp
   trunk/lib/engine/components/resource-list/rl-heap.h

Modified: trunk/lib/engine/components/resource-list/Makefile.am
==============================================================================
--- trunk/lib/engine/components/resource-list/Makefile.am	(original)
+++ trunk/lib/engine/components/resource-list/Makefile.am	Wed Oct 15 12:48:01 2008
@@ -6,6 +6,7 @@
 
 INCLUDES = 						\
 	-I$(top_srcdir)/lib/gmconf			\
+	-I$(top_srcdir)/lib/gmref			\
 	-I$(top_srcdir)/lib/engine/framework		\
 	-I$(top_srcdir)/lib/engine/presence/skel	\
 	-I$(top_srcdir)/lib/engine/account/skel		\
@@ -14,8 +15,12 @@
 libgmresource_list_la_SOURCES = \
 	$(resource_list_dir)/resource-list-main.h \
 	$(resource_list_dir)/resource-list-main.cpp \
-	$(resource_list_dir)/rl-presentity.h \
-	$(resource_list_dir)/rl-presentity.cpp \
+	$(resource_list_dir)/rl-entry.h \
+	$(resource_list_dir)/rl-entry.cpp \
+	$(resource_list_dir)/rl-entry-ref.h \
+	$(resource_list_dir)/rl-entry-ref.cpp \
+	$(resource_list_dir)/rl-list.h \
+	$(resource_list_dir)/rl-list.cpp \
 	$(resource_list_dir)/rl-heap.h \
 	$(resource_list_dir)/rl-heap.cpp \
 	$(resource_list_dir)/rl-cluster.h \

Added: trunk/lib/engine/components/resource-list/rl-entry-ref.cpp
==============================================================================
--- (empty file)
+++ trunk/lib/engine/components/resource-list/rl-entry-ref.cpp	Wed Oct 15 12:48:01 2008
@@ -0,0 +1,152 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         rl-entry-ref.cpp -  description
+ *                         ------------------------------------------
+ *   begin                : written in 2008 by Julien Puydt
+ *   copyright            : (c) 2008 by Julien Puydt
+ *   description          : resource-list entry-ref class
+ *
+ */
+
+#include "config.h"
+
+#include "rl-entry-ref.h"
+
+#include "presence-core.h"
+
+RL::EntryRef::EntryRef (Ekiga::ServiceCore& core_,
+			const std::string path_,
+			int pos,
+			const std::string group,
+			xmlNodePtr node_):
+  core(core_), path(path_), position(pos), doc(NULL), node(node_),
+  link_doc(NULL), link_node(NULL), name_node(NULL),
+  presence("unknown"), status(_("Click to fetch"))
+{
+  groups.insert (group);
+
+  for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
+
+
+    if (child->type == XML_ELEMENT_NODE
+	&& child->name != NULL
+	&& xmlStrEqual (BAD_CAST "display-name", child->name)) {
+
+      name_node = child;
+    }
+  }
+}
+
+RL::EntryRef::~EntryRef ()
+{
+  if (doc != NULL)
+    xmlFreeDoc (doc);
+}
+
+bool
+RL::EntryRef::is_positional () const
+{
+  return true; // FIXME
+}
+
+const std::string
+RL::EntryRef::get_uri () const
+{
+  std::string result;
+  xmlChar* str = xmlGetProp (node, BAD_CAST "uri");
+
+  if (str != NULL) {
+
+    result = ((const char*)str);
+    xmlFree (str);
+  }
+
+  return result;
+}
+
+
+void
+RL::EntryRef::set_presence (const std::string presence_)
+{
+  presence = presence_;
+  updated.emit ();
+}
+
+void
+RL::EntryRef::set_status (const std::string status_)
+{
+  status = status_;
+  updated.emit ();
+}
+
+const std::string
+RL::EntryRef::get_name () const
+{
+  std::string result;
+
+  if (link_node != NULL) {
+
+    xmlChar* str = xmlNodeGetContent (node);
+
+    if (str != NULL) {
+
+      result = ((const char*)str);
+      xmlFree (str);
+    }
+  } else
+    result = _("Distant contact");
+
+  return result;
+}
+
+bool
+RL::EntryRef::populate_menu (Ekiga::MenuBuilder& builder)
+{
+  bool populated = false;
+  Ekiga::PresenceCore* presence_core
+    = dynamic_cast<Ekiga::PresenceCore*>(core.get ("presence-core"));
+  std::string uri(get_uri ());
+
+  builder.add_action ("refresh", _("_Refresh"),
+		      sigc::mem_fun (this, &RL::EntryRef::refresh));
+
+  if ( !uri.empty ())
+    populated =
+      presence_core->populate_presentity_menu (*this, uri, builder)
+      || populated;
+
+  return populated;
+}
+
+void
+RL::EntryRef::refresh ()
+{
+  std::cout << "FIXME: should refresh on " << path << std::endl;
+}

Copied: trunk/lib/engine/components/resource-list/rl-entry-ref.h (from r7220, /trunk/lib/engine/components/resource-list/rl-presentity.h)
==============================================================================
--- /trunk/lib/engine/components/resource-list/rl-presentity.h	(original)
+++ trunk/lib/engine/components/resource-list/rl-entry-ref.h	Wed Oct 15 12:48:01 2008
@@ -1,4 +1,5 @@
 
+
 /* Ekiga -- A VoIP and Video-Conferencing application
  * Copyright (C) 2000-2008 Damien Sandras
  *
@@ -27,36 +28,55 @@
 
 
 /*
- *                         rl-presentity.h  -  description
+ *                         rl-entry-ref.h  -  description
  *                         ------------------------------------------
  *   begin                : written in 2008 by Julien Puydt
  *   copyright            : (c) 2008 by Julien Puydt
- *   description          : resource-list presentity interface
+ *   description          : resource-list entry-ref class
  *
  */
 
-#ifndef __RL_PRESENTITY_H__
-#define __RL_PRESENTITY_H__
+#ifndef __RL_ENTRY_REF_H__
+#define __RL_ENTRY_REF_H__
+
+#include "gmref.h"
 
 #include "services.h"
 #include "presentity.h"
 
+#include <libxml/tree.h>
+
 namespace RL {
 
-  class Presentity: public Ekiga::Presentity
+  class EntryRef:
+    public GmRefCounted,
+    public Ekiga::Presentity
   {
   public:
 
-    Presentity (Ekiga::ServiceCore& core_,
-		std::string name_,
-		std::string uri_);
+    EntryRef (Ekiga::ServiceCore& core_,
+	      const std::string path_,
+	      int pos,
+	      const std::string group,
+	      xmlNodePtr node_);
+
+    ~EntryRef ();
+
+    /* the part of the interface which helps the list manage this element */
+
+    bool is_positional () const;
 
-    ~Presentity ();
+    /* needed so presence can be pushed into this presentity */
+
+    const std::string get_uri () const;
+
+    void set_presence (const std::string presence_);
+
+    void set_status (const std::string status_);
 
-    void add_group (std::string group);
+    /* Ekiga::Presentity interface */
 
-    const std::string get_name () const
-    { return name; }
+    const std::string get_name () const;
 
     const std::string get_presence () const
     { return presence; }
@@ -72,21 +92,25 @@
 
     bool populate_menu (Ekiga::MenuBuilder& builder);
 
-    const std::string get_uri () const
-    { return uri; }
+  private:
+    Ekiga::ServiceCore& core;
 
-    void set_presence (const std::string presence_);
+    std::string path;
+    int position;
 
-    void set_status (const std::string status_);
+    std::set<std::string> groups;
 
-  private:
-    Ekiga::ServiceCore& core;
+    xmlDocPtr doc;
+    xmlNodePtr node;
+
+    xmlDocPtr link_doc;
+    xmlNodePtr link_node;
+    xmlNodePtr name_node;
 
-    std::string name;
-    std::string uri;
     std::string presence;
     std::string status;
-    std::set<std::string> groups;
+
+    void refresh ();
   };
 };
 

Added: trunk/lib/engine/components/resource-list/rl-entry.cpp
==============================================================================
--- (empty file)
+++ trunk/lib/engine/components/resource-list/rl-entry.cpp	Wed Oct 15 12:48:01 2008
@@ -0,0 +1,162 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         rl-entry.cpp -  description
+ *                         ------------------------------------------
+ *   begin                : written in 2008 by Julien Puydt
+ *   copyright            : (c) 2008 by Julien Puydt
+ *   description          : resource-list entry class
+ *
+ */
+
+
+#include <libxml/debugXML.h>
+
+#include "config.h"
+
+#include "rl-entry.h"
+
+#include "presence-core.h"
+
+RL::Entry::Entry (Ekiga::ServiceCore& core_,
+		  const std::string path_,
+		  int pos,
+		  const std::string group,
+		  xmlNodePtr node_):
+  core(core_), path(path_), position(pos), doc(NULL),
+  node(node_), name_node(NULL),
+  presence("unknown"), status("")
+{
+  groups.insert (group);
+
+  refresh ();
+}
+
+RL::Entry::~Entry ()
+{
+  if (doc != NULL)
+    xmlFreeDoc (doc);
+}
+
+bool
+RL::Entry::is_positional () const
+{
+  return get_uri ().empty ();
+}
+
+const std::string
+RL::Entry::get_uri () const
+{
+  std::string result;
+  xmlChar* str = xmlGetProp (node, (const xmlChar*) "uri");
+
+  if (str != NULL) {
+
+    result = ((const char*)str);
+    xmlFree (str);
+  }
+
+  return result;
+}
+
+
+void
+RL::Entry::set_presence (const std::string presence_)
+{
+  presence = presence_;
+  updated.emit ();
+}
+
+void
+RL::Entry::set_status (const std::string status_)
+{
+  status = status_;
+  updated.emit ();
+}
+
+const std::string
+RL::Entry::get_name () const
+{
+  std::string result;
+  xmlChar* str = xmlNodeGetContent (name_node);
+
+  if (str != NULL) {
+
+    result = ((const char*)str);
+    xmlFree (str);
+  }
+
+  return result;
+}
+
+bool
+RL::Entry::populate_menu (Ekiga::MenuBuilder& builder)
+{
+  bool populated = false;
+  Ekiga::PresenceCore* presence_core
+    = dynamic_cast<Ekiga::PresenceCore*>(core.get ("presence-core"));
+  std::string uri(get_uri ());
+
+  builder.add_action ("refresh", _("_Refresh"),
+		      sigc::mem_fun (this, &RL::Entry::refresh));
+
+  if ( !uri.empty ())
+    populated =
+      presence_core->populate_presentity_menu (*this, uri, builder)
+      || populated;
+
+  return populated;
+}
+
+void
+RL::Entry::refresh ()
+{
+  if (node != NULL)
+    parse ();
+  else {
+
+    /* FIXME: here we should fetch the document, then parse it
+     */
+  }
+}
+
+void
+RL::Entry::parse ()
+{
+  for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
+
+
+    if (child->type == XML_ELEMENT_NODE
+	&& child->name != NULL
+	&& xmlStrEqual (BAD_CAST "display-name", child->name)) {
+
+      name_node = child;
+    }
+  }
+}

Copied: trunk/lib/engine/components/resource-list/rl-entry.h (from r7220, /trunk/lib/engine/components/resource-list/rl-presentity.h)
==============================================================================
--- /trunk/lib/engine/components/resource-list/rl-presentity.h	(original)
+++ trunk/lib/engine/components/resource-list/rl-entry.h	Wed Oct 15 12:48:01 2008
@@ -27,36 +27,55 @@
 
 
 /*
- *                         rl-presentity.h  -  description
+ *                         rl-entry.h  -  description
  *                         ------------------------------------------
  *   begin                : written in 2008 by Julien Puydt
  *   copyright            : (c) 2008 by Julien Puydt
- *   description          : resource-list presentity interface
+ *   description          : resource-list entry class
  *
  */
 
-#ifndef __RL_PRESENTITY_H__
-#define __RL_PRESENTITY_H__
+#ifndef __RL_ENTRY_H__
+#define __RL_ENTRY_H__
+
+#include "gmref.h"
 
 #include "services.h"
 #include "presentity.h"
 
+#include <libxml/tree.h>
+
 namespace RL {
 
-  class Presentity: public Ekiga::Presentity
+  class Entry:
+    public GmRefCounted,
+    public Ekiga::Presentity
   {
   public:
 
-    Presentity (Ekiga::ServiceCore& core_,
-		std::string name_,
-		std::string uri_);
+    Entry (Ekiga::ServiceCore& core_,
+	   const std::string path_,
+	   int pos,
+	   const std::string group,
+	   xmlNodePtr node_);
+
+    ~Entry ();
+
+    /* the part of the interface which helps the list manage this element */
+
+    bool is_positional () const;
 
-    ~Presentity ();
+    /* needed so presence can be pushed into this presentity */
+
+    const std::string get_uri () const;
+
+    void set_presence (const std::string presence_);
+
+    void set_status (const std::string status_);
 
-    void add_group (std::string group);
+    /* Ekiga::Presentity interface */
 
-    const std::string get_name () const
-    { return name; }
+    const std::string get_name () const;
 
     const std::string get_presence () const
     { return presence; }
@@ -72,21 +91,23 @@
 
     bool populate_menu (Ekiga::MenuBuilder& builder);
 
-    const std::string get_uri () const
-    { return uri; }
+  private:
+    Ekiga::ServiceCore& core;
 
-    void set_presence (const std::string presence_);
+    std::string path;
+    int position;
 
-    void set_status (const std::string status_);
+    std::set<std::string> groups;
 
-  private:
-    Ekiga::ServiceCore& core;
+    xmlDocPtr doc;
+    xmlNodePtr node;
+    xmlNodePtr name_node;
 
-    std::string name;
-    std::string uri;
     std::string presence;
     std::string status;
-    std::set<std::string> groups;
+
+    void refresh ();
+    void parse ();
   };
 };
 

Modified: trunk/lib/engine/components/resource-list/rl-heap.cpp
==============================================================================
--- trunk/lib/engine/components/resource-list/rl-heap.cpp	(original)
+++ trunk/lib/engine/components/resource-list/rl-heap.cpp	Wed Oct 15 12:48:01 2008
@@ -37,7 +37,7 @@
 
 #include "config.h"
 
-#include <iostream>
+#include <glib.h>
 
 #include "robust-xml.h"
 
@@ -46,7 +46,7 @@
 RL::Heap::Heap (Ekiga::ServiceCore& core_,
 		xmlNodePtr node_):
   core(core_), node(node_), uri(NULL),
-  username(NULL), password(NULL), name(NULL)
+  username(NULL), password(NULL), name(NULL), doc(NULL)
 {
   for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
 
@@ -75,7 +75,7 @@
   if (password == NULL)
     password = xmlNewChild (node, NULL, BAD_CAST "password", BAD_CAST "");
 
-  update ();
+  refresh ();
 }
 
 RL::Heap::Heap (Ekiga::ServiceCore& core_,
@@ -108,11 +108,13 @@
 			BAD_CAST "name",
 			BAD_CAST robust_xmlEscape (node->doc,
 						   _("Unnamed")).c_str ());
-  update ();
+  refresh ();
 }
 
 RL::Heap::~Heap ()
 {
+  if (doc != NULL)
+    xmlFreeDoc (doc);
 }
 
 const std::string
@@ -121,7 +123,7 @@
   std::string result;
   xmlChar* str = xmlNodeGetContent (name);
   if (str != NULL)
-    result = (const gchar*)str;
+    result = (const char*)str;
   else
     result = _("Unnamed");
 
@@ -136,7 +138,7 @@
   std::string result;
   xmlChar* str = xmlNodeGetContent (uri);
   if (str != NULL)
-    result = (const gchar*)str;
+    result = (const char*)str;
   else
     result = "";
 
@@ -145,6 +147,16 @@
   return result;
 }
 
+void
+RL::Heap::visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor)
+{
+  bool go_on = true;
+
+  for (std::list<gmref_ptr<List> >::iterator iter = lists.begin ();
+       go_on && iter != lists.end ();
+       ++iter)
+    go_on = (*iter)->visit_presentities (visitor);
+}
 
 bool
 RL::Heap::populate_menu (Ekiga::MenuBuilder& /*builder*/)
@@ -166,27 +178,38 @@
 }
 
 void
-RL::Heap::update ()
+RL::Heap::refresh ()
 {
   XCAP::Core* xcap
     = dynamic_cast<XCAP::Core*>(core.get ("xcap-core"));
+
+  for (std::list<gmref_ptr<List> >::iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->flush ();
+  lists.clear ();
+
+  if (doc)
+    xmlFreeDoc (doc);
+  doc = NULL;
+
   xcap->read (get_uri (),
 	      sigc::mem_fun (this, &RL::Heap::on_document_received));
 }
 
 void
 RL::Heap::on_document_received (XCAP::Core::ResultType result,
-				std::string doc)
+				std::string value)
 {
   switch (result) {
 
   case XCAP::Core::SUCCESS:
 
-    parse_doc (doc);
+    parse_doc (value);
     break;
   case XCAP::Core::ERROR:
 
-    std::cout << "Error: " << doc << std::endl;
+    // FIXME: do something
     break;
   default:
     // shouldn't happen
@@ -197,136 +220,69 @@
 void
 RL::Heap::parse_doc (std::string raw)
 {
-  xmlDocPtr doc = xmlRecoverMemory (raw.c_str (), raw.length ());
+  doc = xmlRecoverMemory (raw.c_str (), raw.length ());
+
   xmlNodePtr root = xmlDocGetRootElement (doc);
 
   if (root == NULL) {
 
     // FIXME: warn the user somehow?
+    xmlFreeDoc (doc);
+    doc = NULL;
   } else {
 
+    int pos = 1;
     for (xmlNodePtr child = root->children; child != NULL; child = child->next)
       if (child->type == XML_ELEMENT_NODE
 	  && child->name != NULL
 	  && xmlStrEqual (BAD_CAST ("list"), child->name)) {
 
-	parse_list (child, NULL);
+	gmref_ptr<List> list(new List (core, get_uri (), pos, "", child));
+	list->entry_added.connect (sigc::mem_fun (this, &RL::Heap::on_entry_added));
+	list->entry_updated.connect (sigc::mem_fun (this, &RL::Heap::on_entry_updated));
+	list->entry_removed.connect (sigc::mem_fun (this, &RL::Heap::on_entry_removed));
+	list->publish ();
+	lists.push_back (list);
+	pos++;
+	continue;
       }
   }
-  xmlFreeDoc (doc);
 }
 
 void
-RL::Heap::parse_list (xmlNodePtr list,
-		      const gchar* base_name)
+RL::Heap::push_presence (const std::string uri_,
+			 const std::string presence)
 {
-  gchar* display_name = NULL;
-  gchar* unnamed = NULL;
-
-  if (base_name == NULL)
-    unnamed = g_strdup (_("Unnamed"));
-  else
-    unnamed = g_strdup_printf ("%s / %s",
-			       base_name, _("Unnamed"));
-
-  for (xmlNodePtr child = list->children;
-       child != NULL;
-       child = child->next) {
-
-    if (child->type == XML_ELEMENT_NODE
-	&& child->name != NULL) {
-
-      if (xmlStrEqual (BAD_CAST ("display-name"), child->name)) {
-
-	xmlChar* xml_str = xmlNodeGetContent (child);
-	if (xml_str != NULL && display_name == NULL) {
-
-	  if (base_name == NULL)
-	    display_name = g_strdup ((const gchar*)xml_str);
-	  else
-	    display_name = g_strdup_printf ("%s / %s",
-					    base_name, (const gchar*)xml_str);
-	}
-	xmlFree (xml_str);
-      }
-
-      if (xmlStrEqual (BAD_CAST ("list"), child->name)) {
-
-	if (display_name != NULL)
-	  parse_list (child, display_name);
-	else
-	  parse_list (child, unnamed);
-      }
-      if (xmlStrEqual (BAD_CAST ("entry"), child->name)) {
-
-	if (display_name != NULL)
-	  parse_entry (child, display_name);
-	else
-	  parse_entry (child, unnamed);
-      }
-    }
-  }
-
-  g_free (unnamed);
-  g_free (display_name);
+  for (std::list<gmref_ptr<List> >::iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->push_presence (uri_, presence);
 }
 
 void
-RL::Heap::parse_entry (xmlNodePtr entry,
-		       const gchar* group_name)
+RL::Heap::push_status (const std::string uri_,
+		       const std::string status)
 {
-  gchar* entry_uri = NULL;
-  std::string display_name = _("Unnamed");
-  Presentity* presentity = NULL;
-
-  {
-    xmlChar* str = xmlGetProp (entry, BAD_CAST "uri");
-    if (str != NULL) {
-
-      entry_uri = g_strdup ((const gchar*)str);
-      xmlFree (str);
-    }
-  }
-
-  for (xmlNodePtr child = entry->children; child != NULL; child = child->next)
-    if (child->type == XML_ELEMENT_NODE
-	&& child->name != NULL
-	&& xmlStrEqual (BAD_CAST ("display-name"), child->name)) {
-
-      xmlChar* xml_str = xmlNodeGetContent (child);
-      if (xml_str != NULL)
-	display_name = (const gchar*)xml_str;
-      xmlFree (xml_str);
-    }
-
-  if (entry_uri != NULL) {
+  for (std::list<gmref_ptr<List> >::iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->push_status (uri_, status);
+}
 
-    presentity = new Presentity (core, display_name, entry_uri);
-    if (group_name != NULL)
-      presentity->add_group (group_name);
-    add_presentity (*presentity);
-    g_free (entry_uri);
-  }
+void
+RL::Heap::on_entry_added (gmref_ptr<Entry> entry)
+{
+  presentity_added.emit (*entry);
 }
 
 void
-RL::Heap::push_presence (const std::string uri_,
-			 const std::string presence)
+RL::Heap::on_entry_updated (gmref_ptr<Entry> entry)
 {
-  for (iterator iter = begin ();
-       iter != end ();
-       ++iter)
-    if (iter->get_uri () == uri_)
-      iter->set_presence (presence);
+  presentity_updated.emit (*entry);
 }
 
 void
-RL::Heap::push_status (const std::string uri_,
-		       const std::string status)
+RL::Heap::on_entry_removed (gmref_ptr<Entry> entry)
 {
-  for (iterator iter = begin ();
-       iter != end ();
-       ++iter)
-    if (iter->get_uri () == uri_)
-      iter->set_status (status);
+  presentity_removed.emit (*entry);
 }

Modified: trunk/lib/engine/components/resource-list/rl-heap.h
==============================================================================
--- trunk/lib/engine/components/resource-list/rl-heap.h	(original)
+++ trunk/lib/engine/components/resource-list/rl-heap.h	Wed Oct 15 12:48:01 2008
@@ -38,17 +38,18 @@
 #ifndef __RL_HEAP_H__
 #define __RL_HEAP_H__
 
-#include "rl-presentity.h"
+#include "gmref.h"
 
-#include "heap-impl.h"
+#include "heap.h"
 #include "xcap.h"
 
-#include <glib.h>
 #include <libxml/tree.h>
 
+#include "rl-list.h"
+
 namespace RL {
 
-  class Heap: public Ekiga::HeapImpl<Presentity>
+  class Heap: public Ekiga::Heap
   {
   public:
 
@@ -65,6 +66,8 @@
 
     const std::string get_name () const;
 
+    void visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor);
+
     bool populate_menu (Ekiga::MenuBuilder& builder);
 
     bool populate_menu_for_group (std::string group,
@@ -90,20 +93,22 @@
     xmlNodePtr password;
     xmlNodePtr name;
 
+    xmlDocPtr doc;
+
+    std::list<gmref_ptr<List> > lists;
+
     const std::string get_uri () const;
 
-    void update ();
+    void refresh ();
 
     void on_document_received (XCAP::Core::ResultType result,
 			       std::string doc);
 
     void parse_doc (std::string doc);
 
-    void parse_list (xmlNodePtr list,
-		     const gchar* base_name);
-
-    void parse_entry (xmlNodePtr entry,
-		      const gchar* group_name);
+    void on_entry_added (gmref_ptr<Entry> entry);
+    void on_entry_updated (gmref_ptr<Entry> entry);
+    void on_entry_removed (gmref_ptr<Entry> entry);
   };
 };
 

Added: trunk/lib/engine/components/resource-list/rl-list.cpp
==============================================================================
--- (empty file)
+++ trunk/lib/engine/components/resource-list/rl-list.cpp	Wed Oct 15 12:48:01 2008
@@ -0,0 +1,434 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2008 Damien Sandras
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ * Ekiga is licensed under the GPL license and as a special exception,
+ * you have permission to link or otherwise combine this program with the
+ * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
+ * without applying the requirements of the GNU GPL to the OPAL, OpenH323
+ * and PWLIB programs, as long as you do follow the requirements of the
+ * GNU GPL for all the rest of the software thus combined.
+ */
+
+
+/*
+ *                         rl-list.cpp  -  description
+ *                         ------------------------------------------
+ *   begin                : written in 2008 by Julien Puydt
+ *   copyright            : (c) 2008 by Julien Puydt
+ *   description          : resource-list list class
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <iostream>
+
+#include "rl-list.h"
+
+class RL::ListImpl
+{
+public: // no need to make anything private
+
+  ListImpl (Ekiga::ServiceCore& core_,
+	    const std::string path_,
+	    int pos,
+	    const std::string group_,
+	    xmlNodePtr node_);
+
+  ~ListImpl ();
+
+  bool is_positional () const;
+
+  bool has_name (const std::string name) const;
+
+  void push_presence (const std::string uri_,
+		      const std::string presence);
+
+  void push_status (const std::string uri_,
+		    const std::string status);
+
+  void publish ();
+
+  std::string compute_path () const;
+
+  void flush ();
+
+  void refresh ();
+
+  void parse ();
+
+  /* data for itself */
+
+  Ekiga::ServiceCore& core;
+
+  std::string path;
+  int position;
+
+  std::string group;
+
+  xmlDocPtr doc;
+  xmlNodePtr node;
+
+  xmlNodePtr name_node;
+  std::string position_name;
+  std::string display_name;
+
+  /* make the world know what we have */
+  bool visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor);
+
+  sigc::signal<void, gmref_ptr<Entry> > entry_added;
+  sigc::signal<void, gmref_ptr<Entry> > entry_updated;
+  sigc::signal<void, gmref_ptr<Entry> > entry_removed;
+
+
+  /* data for its children */
+  typedef enum { LIST, ENTRY } ChildType;
+
+  std::list<ChildType> ordering;
+  std::list<gmref_ptr<List> > lists;
+  std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > > entries;
+};
+
+
+/* implementation of the List class */
+
+RL::List::List (Ekiga::ServiceCore& core_,
+		const std::string path_,
+		int pos,
+		const std::string group_,
+		xmlNodePtr node_)
+{
+  impl = new ListImpl (core_, path_, pos, group_, node_);
+  impl->entry_added.connect (entry_added.make_slot ());
+  impl->entry_updated.connect (entry_updated.make_slot ());
+  impl->entry_removed.connect (entry_removed.make_slot ());
+}
+
+RL::List::~List ()
+{
+  delete impl;
+}
+
+void
+RL::List::flush ()
+{
+  return impl->flush ();
+}
+
+void
+RL::List::publish ()
+{
+  return impl->publish ();
+}
+
+bool
+RL::List::is_positional () const
+{
+  return impl->is_positional ();
+}
+
+bool
+RL::List::has_name (const std::string name) const
+{
+  return impl->has_name (name);
+}
+
+void
+RL::List::push_presence (const std::string uri_,
+			 const std::string presence)
+{
+  impl->push_presence (uri_, presence);
+}
+
+void
+RL::List::push_status (const std::string uri_,
+		       const std::string status)
+{
+  impl->push_status (uri_, status);
+}
+
+bool
+RL::List::visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor)
+{
+  return impl->visit_presentities (visitor);
+}
+
+/* implementation of the ListImpl class */
+
+RL::ListImpl::ListImpl (Ekiga::ServiceCore& core_,
+			const std::string path_,
+			int pos,
+			const std::string group_,
+			xmlNodePtr node_):
+  core(core_), path(path_), position(pos), group(group_), doc(NULL), node(node_)
+{
+  {
+    gchar* raw = NULL;
+
+    if ( !group_.empty ()) {
+
+      raw = g_strdup_printf (_("%s / List #%d"),
+			     group_.c_str (), position);
+    } else {
+
+      raw = g_strdup_printf (_("List #%d"), position);
+    }
+    position_name = raw;
+    g_free (raw);
+
+  }
+
+  display_name = position_name; // refresh will set better
+
+  refresh ();
+}
+
+RL::ListImpl::~ListImpl ()
+{
+  if (doc != NULL)
+    xmlFreeDoc (doc);
+}
+
+bool
+RL::ListImpl::is_positional () const
+{
+  bool result = true;
+  xmlChar* str = xmlGetProp (node, BAD_CAST "name");
+
+  if (str != NULL) {
+
+    result = false;
+    xmlFree (str);
+  }
+
+  return result;
+}
+
+bool
+RL::ListImpl::has_name (const std::string name) const
+{
+  return (name == position_name) || (name == display_name);
+}
+
+void
+RL::ListImpl::flush ()
+{
+  ordering.clear ();
+
+  for (std::list<gmref_ptr<List> >::iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->flush ();
+  lists.clear ();
+
+  for (std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > >::iterator iter = entries.begin ();
+       iter != entries.end ();
+       ++iter) {
+
+    iter->first->removed.emit ();
+    for (std::list<sigc::connection>::iterator conn_iter
+	   = iter->second.begin ();
+	 conn_iter != iter->second.end ();
+	 ++conn_iter)
+      conn_iter->disconnect ();
+  }
+  entries.clear ();
+}
+
+void
+RL::ListImpl::publish ()
+{
+  std::list<gmref_ptr<List> >::const_iterator list_iter = lists.begin ();
+  std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > >::const_iterator entry_iter = entries.begin ();
+
+  for (std::list<ChildType>::const_iterator iter = ordering.begin ();
+       iter != ordering.end ();
+       ++iter) {
+
+    switch (*iter) {
+
+    case LIST:
+      (*list_iter)->publish ();
+      ++list_iter;
+      break;
+
+    case ENTRY:
+      entry_added.emit (entry_iter->first);
+      ++entry_iter;
+      break;
+
+    default:
+      break;// nothing
+    }
+  }
+}
+
+void
+RL::ListImpl::refresh ()
+{
+  flush ();
+
+  if (node)
+    parse ();
+  else {
+
+    /* FIXME:
+     * - fetch the document
+     * - call parse
+     */
+  }
+}
+
+void
+RL::ListImpl::parse ()
+{
+  std::string my_path = compute_path ();
+  int list_pos = 1;
+  int entry_pos = 1;
+
+  for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
+
+
+    if (child->type == XML_ELEMENT_NODE
+	&& child->name != NULL
+	&& xmlStrEqual (BAD_CAST "display-name", child->name)) {
+
+      xmlChar* str = xmlNodeGetContent (child);
+      name_node = child;
+      if (str != NULL) {
+
+	if ( !group.empty ())
+	  display_name = group + " / " + (const char*) str;
+	else
+	  display_name = (const char*) str;
+	xmlFree (str);
+      }
+      continue;
+    }
+
+    if (child->type == XML_ELEMENT_NODE
+	&& child->name != NULL
+	&& xmlStrEqual (BAD_CAST "list", child->name)) {
+
+      gmref_ptr<List> list = new List (core, my_path,
+				       list_pos, display_name, child);
+      list->entry_added.connect (entry_added.make_slot ());
+      lists.push_back (list);
+      ordering.push_back (LIST);
+      list_pos++;
+      continue;
+    }
+
+    if (child->type == XML_ELEMENT_NODE
+	&& child->name != NULL
+	&& xmlStrEqual (BAD_CAST "entry", child->name)) {
+
+      gmref_ptr<Entry> entry = new Entry (core, my_path,
+					  entry_pos, display_name, child);
+      std::list<sigc::connection> conns;
+      conns.push_back (entry->updated.connect (sigc::bind (entry_updated.make_slot (), entry)));
+      conns.push_back (entry->removed.connect (sigc::bind (entry_removed.make_slot (), entry)));
+      entries.push_back (std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > (entry, conns));
+      ordering.push_back (ENTRY);
+      entry_pos++;
+      continue;
+    }
+  }
+}
+
+std::string
+RL::ListImpl::compute_path () const
+{
+  std::string result;
+  gchar* raw = NULL;
+  xmlChar* str = xmlGetProp (node, BAD_CAST "name");
+
+  if (str != NULL) {
+
+    raw = g_strdup_printf ("%s/list[ name=\"%s\"]",
+			   path.c_str (), str);
+    xmlFree (str);
+  } else {
+
+    raw = g_strdup_printf ("%s/list[%d]", path.c_str (), position);
+  }
+
+  result = raw;
+
+  g_free (raw);
+
+  return result;
+}
+
+void
+RL::ListImpl::push_presence (const std::string uri_,
+			     const std::string presence)
+{
+  for (std::list<gmref_ptr<List> >::const_iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->push_presence (uri_, presence);
+
+  for (std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > >::const_iterator iter = entries.begin ();
+       iter != entries.end ();
+       ++iter) {
+
+    if (iter->first->get_uri () == uri_)
+      iter->first->set_presence (presence);
+  }
+}
+
+void
+RL::ListImpl::push_status (const std::string uri_,
+			   const std::string status)
+{
+  for (std::list<gmref_ptr<List> >::const_iterator iter = lists.begin ();
+       iter != lists.end ();
+       ++iter)
+    (*iter)->push_status (uri_, status);
+
+  for (std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > >::const_iterator iter = entries.begin ();
+       iter != entries.end ();
+       ++iter) {
+
+    if (iter->first->get_uri () == uri_)
+      iter->first->set_status (status);
+  }
+}
+
+bool
+RL::ListImpl::visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor)
+{
+  bool go_on = true;
+
+  for (std::list<gmref_ptr<List> >::const_iterator iter = lists.begin ();
+       go_on && iter != lists.end ();
+       ++iter)
+    go_on = (*iter)->visit_presentities (visitor);
+
+  for (std::list<std::pair<gmref_ptr<Entry>, std::list<sigc::connection> > >::const_iterator iter = entries.begin ();
+       go_on && iter != entries.end ();
+       ++iter) {
+
+    go_on = visitor (*(iter->first));
+  }
+
+  return go_on;
+}

Copied: trunk/lib/engine/components/resource-list/rl-list.h (from r7220, /trunk/lib/engine/components/resource-list/rl-heap.h)
==============================================================================
--- /trunk/lib/engine/components/resource-list/rl-heap.h	(original)
+++ trunk/lib/engine/components/resource-list/rl-list.h	Wed Oct 15 12:48:01 2008
@@ -1,4 +1,5 @@
 
+
 /* Ekiga -- A VoIP and Video-Conferencing application
  * Copyright (C) 2000-2008 Damien Sandras
  *
@@ -27,83 +28,76 @@
 
 
 /*
- *                         rl-heap.h  -  description
+ *                         rl-list.h  -  description
  *                         ------------------------------------------
  *   begin                : written in 2008 by Julien Puydt
  *   copyright            : (c) 2008 by Julien Puydt
- *   description          : resource-list heap declaration
+ *   description          : resource-list list class
  *
  */
 
-#ifndef __RL_HEAP_H__
-#define __RL_HEAP_H__
+#ifndef __RL_LIST_H__
+#define __RL_LIST_H__
 
-#include "rl-presentity.h"
+#include "gmref.h"
 
-#include "heap-impl.h"
-#include "xcap.h"
+#include "services.h"
 
-#include <glib.h>
 #include <libxml/tree.h>
 
-namespace RL {
+#include "rl-entry.h"
+
+namespace RL
+{
+  class ListImpl; // pimpling : both it and external need to know each other
 
-  class Heap: public Ekiga::HeapImpl<Presentity>
+  class List: public GmRefCounted
   {
   public:
 
-    Heap (Ekiga::ServiceCore& core_,
-	  xmlNodePtr node);
+    List (Ekiga::ServiceCore& core_,
+	  const std::string path_,
+	  int pos,
+	  const std::string group_,
+	  xmlNodePtr node_);
 
-    Heap (Ekiga::ServiceCore& core_,
-	  const std::string name_,
-	  const std::string uri_,
-	  const std::string username_,
-	  const std::string password_);
+    ~List ();
 
-    ~Heap ();
 
-    const std::string get_name () const;
+    /* the part of the interface which helps the list manage this element */
 
-    bool populate_menu (Ekiga::MenuBuilder& builder);
+    bool is_positional () const;
 
-    bool populate_menu_for_group (std::string group,
-				  Ekiga::MenuBuilder& builder);
+    bool has_name (const std::string name) const;
 
-    xmlNodePtr get_node () const;
+    /* we need to push presence&status down */
 
-    void push_presence (const std::string uri,
+    void push_presence (const std::string uri_,
 			const std::string presence);
 
-    void push_status (const std::string uri,
+    void push_status (const std::string uri_,
 		      const std::string status);
 
-    sigc::signal<void> trigger_saving;
-
-  private:
-
-    Ekiga::ServiceCore& core;
+    /* make the world know what we have */
+    bool visit_presentities (sigc::slot<bool, Ekiga::Presentity&> visitor);
 
-    xmlNodePtr node;
-    xmlNodePtr uri;
-    xmlNodePtr username;
-    xmlNodePtr password;
-    xmlNodePtr name;
+    sigc::signal<void, gmref_ptr<Entry> > entry_added;
+    sigc::signal<void, gmref_ptr<Entry> > entry_updated;
+    sigc::signal<void, gmref_ptr<Entry> > entry_removed;
+
+    /* this method orders the list to get rid of all its children */
+    void flush ();
+
+    /* this method makes the list publish what it has
+     * (it needs a method to be done, because we fetch on creation,
+     *  which means the owner may not have had the time to connect to
+     *  our signals yet)
+     */
+    void publish ();
 
-    const std::string get_uri () const;
-
-    void update ();
-
-    void on_document_received (XCAP::Core::ResultType result,
-			       std::string doc);
-
-    void parse_doc (std::string doc);
-
-    void parse_list (xmlNodePtr list,
-		     const gchar* base_name);
+  private:
 
-    void parse_entry (xmlNodePtr entry,
-		      const gchar* group_name);
+    ListImpl *impl;
   };
 };
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]