[ekiga/ds-gtk-application] Roster: Added back the possibility to rename groups.



commit 4b54045e5946db43d707e80c43dbbdb38ab96c0c
Author: Damien Sandras <dsandras seconix com>
Date:   Sat Sep 27 14:56:05 2014 +0200

    Roster: Added back the possibility to rename groups.
    
    This involved several changes:
    1) Transformed EditableSet form elements into EditableLists. This allows
    keeping the notion of order. It also simplifies the code and improves
    efficiency.
    2) Added the possibility to call the corresponding action from the
    presentity itself.

 .../components/call-history/history-book.cpp       |    4 +-
 lib/engine/components/call-history/history-book.h  |    2 +-
 .../components/call-history/history-source.cpp     |    2 +-
 .../components/call-history/history-source.h       |    2 +-
 lib/engine/components/echo/echo-presentity.cpp     |    4 +-
 lib/engine/components/echo/echo-presentity.h       |    2 +-
 lib/engine/components/opal/opal-account.cpp        |   65 ++++---
 lib/engine/components/opal/opal-account.h          |   19 ++-
 lib/engine/components/opal/opal-bank.cpp           |   33 ++--
 lib/engine/components/opal/opal-bank.h             |    2 +-
 lib/engine/components/opal/opal-presentity.cpp     |   41 +++--
 lib/engine/components/opal/opal-presentity.h       |   15 +-
 lib/engine/components/opal/sip-chat-simple.cpp     |    2 +-
 lib/engine/framework/form-builder.cpp              |   41 ++--
 lib/engine/framework/form-builder.h                |   42 +++--
 lib/engine/framework/form-dumper.cpp               |   16 +-
 lib/engine/framework/form-dumper.h                 |   11 +-
 lib/engine/framework/form-visitor.h                |   12 +-
 lib/engine/framework/form.cpp                      |    6 +-
 lib/engine/framework/form.h                        |    4 +-
 lib/engine/gui/gtk-core/form-dialog-gtk.cpp        |  202 +++++++++++++-------
 lib/engine/gui/gtk-core/form-dialog-gtk.h          |   11 +-
 lib/engine/gui/gtk-frontend/heap-view.cpp          |   12 +-
 lib/engine/gui/gtk-frontend/roster-view-gtk.cpp    |   12 +-
 lib/engine/presence/presentity.h                   |    4 +-
 lib/engine/presence/proxy-presentity.cpp           |    2 +-
 lib/engine/presence/proxy-presentity.h             |    2 +-
 lib/engine/presence/uri-presentity.cpp             |    4 +-
 lib/engine/presence/uri-presentity.h               |    6 +-
 plugins/loudmouth/loudmouth-heap-roster.cpp        |   28 ++--
 plugins/loudmouth/loudmouth-heap-roster.h          |    2 +-
 31 files changed, 362 insertions(+), 248 deletions(-)
---
diff --git a/lib/engine/components/call-history/history-book.cpp 
b/lib/engine/components/call-history/history-book.cpp
index 9d6fb36..e436917 100644
--- a/lib/engine/components/call-history/history-book.cpp
+++ b/lib/engine/components/call-history/history-book.cpp
@@ -157,11 +157,11 @@ History::Book::populate_menu (Ekiga::MenuBuilder &builder)
   return true;
 }
 
-const std::set<std::string>
+const std::list<std::string>
 History::Book::existing_groups () const
 {
   // here it's more logical to lie
-  return std::set<std::string> ();
+  return std::list<std::string> ();
 }
 
 const std::string
diff --git a/lib/engine/components/call-history/history-book.h 
b/lib/engine/components/call-history/history-book.h
index 58e4759..1126fb7 100644
--- a/lib/engine/components/call-history/history-book.h
+++ b/lib/engine/components/call-history/history-book.h
@@ -72,7 +72,7 @@ namespace History
 
     bool populate_menu (Ekiga::MenuBuilder &);
 
-    const std::set<std::string> existing_groups () const;
+    const std::list<std::string> existing_groups () const;
 
     const std::string get_status () const;
 
diff --git a/lib/engine/components/call-history/history-source.cpp 
b/lib/engine/components/call-history/history-source.cpp
index d478a93..e126ea4 100644
--- a/lib/engine/components/call-history/history-source.cpp
+++ b/lib/engine/components/call-history/history-source.cpp
@@ -46,7 +46,7 @@ History::Source::~Source ()
 {
 }
 
-const std::set<std::string>
+const std::list<std::string>
 History::Source::existing_groups () const
 {
   return book->existing_groups ();
diff --git a/lib/engine/components/call-history/history-source.h 
b/lib/engine/components/call-history/history-source.h
index f5aa26a..6aa9f9f 100644
--- a/lib/engine/components/call-history/history-source.h
+++ b/lib/engine/components/call-history/history-source.h
@@ -68,7 +68,7 @@ namespace History
     const std::string get_description () const
     { return "\tStores the call history"; }
 
-    const std::set<std::string> existing_groups () const;
+    const std::list<std::string> existing_groups () const;
 
     BookPtr get_book () const;
 
diff --git a/lib/engine/components/echo/echo-presentity.cpp b/lib/engine/components/echo/echo-presentity.cpp
index 34aa0de..05e9532 100644
--- a/lib/engine/components/echo/echo-presentity.cpp
+++ b/lib/engine/components/echo/echo-presentity.cpp
@@ -66,10 +66,10 @@ Echo::Presentity::get_status () const
   return "ready";
 }
 
-const std::set<std::string>
+const std::list<std::string>
 Echo::Presentity::get_groups () const
 {
-  return std::set<std::string>();
+  return std::list<std::string>();
 }
 
 const std::string
diff --git a/lib/engine/components/echo/echo-presentity.h b/lib/engine/components/echo/echo-presentity.h
index 248f2de..f60a1ea 100644
--- a/lib/engine/components/echo/echo-presentity.h
+++ b/lib/engine/components/echo/echo-presentity.h
@@ -55,7 +55,7 @@ namespace Echo
 
     const std::string get_status () const;
 
-    const std::set<std::string> get_groups () const;
+    const std::list<std::string> get_groups () const;
 
     const std::string get_uri () const;
 
diff --git a/lib/engine/components/opal/opal-account.cpp b/lib/engine/components/opal/opal-account.cpp
index 668f00f..5bb99c3 100644
--- a/lib/engine/components/opal/opal-account.cpp
+++ b/lib/engine/components/opal/opal-account.cpp
@@ -144,7 +144,7 @@ Opal::Account::Account (boost::shared_ptr<Opal::Sip::EndPoint> _sip_endpoint,
                        boost::shared_ptr<Ekiga::PersonalDetails> _personal_details,
                        boost::shared_ptr<Ekiga::AudioOutputCore> _audiooutput_core,
                        boost::shared_ptr<CallManager> _call_manager,
-                       boost::function0<std::set<std::string> > _existing_groups,
+                       boost::function0<std::list<std::string> > _existing_groups,
                        xmlNodePtr _node):
   existing_groups(_existing_groups),
   node(_node),
@@ -179,7 +179,8 @@ Opal::Account::Account (boost::shared_ptr<Opal::Sip::EndPoint> _sip_endpoint,
       roster_node = child;
       for (xmlNodePtr presnode = roster_node->children; presnode != NULL; presnode = presnode->next) {
 
-       Opal::PresentityPtr pres(new Presentity (presence_core,
+       Opal::PresentityPtr pres(new Presentity (*this,
+                                                 presence_core,
                                                 existing_groups,
                                                 presnode));
 
@@ -229,15 +230,17 @@ Opal::Account::Account (boost::shared_ptr<Opal::Sip::EndPoint> _sip_endpoint,
 }
 
 
-std::set<std::string>
+std::list<std::string>
 Opal::Account::get_groups () const
 {
-  std::set<std::string> result;
+  std::list<std::string> result;
 
   for (Ekiga::RefLister< Presentity >::const_iterator iter = Ekiga::RefLister< Presentity >::begin (); iter 
!= Ekiga::RefLister< Presentity >::end (); ++iter) {
 
-    std::set<std::string> groups = (*iter)->get_groups ();
-    result.insert (groups.begin (), groups.end ());
+    std::list<std::string> groups = (*iter)->get_groups ();
+    result.merge (groups);
+    result.sort ();
+    result.unique ();
   }
 
   return result;
@@ -756,8 +759,9 @@ Opal::Account::add_contact ()
   if (!pcore)
     return;
 
-  boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new 
Ekiga::FormRequestSimple (boost::bind (&Opal::Account::on_add_contact_form_submitted, this, _1, _2)));
-  std::set<std::string> groups = existing_groups ();
+  boost::shared_ptr<Ekiga::FormRequestSimple> request =
+    boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind 
(&Opal::Account::on_add_contact_form_submitted, this, _1, _2)));
+  std::list<std::string> groups = existing_groups ();
 
   request->title (_("Add to account roster"));
   request->instructions (_("Please fill in this form to add a new contact "
@@ -766,9 +770,9 @@ Opal::Account::add_contact ()
 
   request->text ("uri", _("Address:"), "sip:", _("Address, e.g. sip:xyz ekiga net; if you do not specify the 
host part, e.g. sip:xyz, then you can choose it by right-clicking on the contact in roster")); // let's put a 
default
 
-  request->editable_set ("groups",
+  request->editable_list ("groups",
                         _("Put contact in groups:"),
-                        std::set<std::string>(), groups);
+                         std::list<std::string>(), groups);
 
   Ekiga::Heap::questions (request);
 }
@@ -786,7 +790,7 @@ Opal::Account::on_add_contact_form_submitted (bool submitted,
 
   const std::string name = result.text ("name");
   std::string uri;
-  const std::set<std::string> groups = result.editable_set ("groups");
+  const std::list<std::string> groups = result.editable_list ("groups");
 
   uri = result.text ("uri");
   uri = canonize_uri (uri);
@@ -797,7 +801,7 @@ Opal::Account::on_add_contact_form_submitted (bool submitted,
     xmlAddChild (roster_node, presnode);
     trigger_saving ();
 
-    Opal::PresentityPtr pres(new Presentity (presence_core, existing_groups, presnode));
+    Opal::PresentityPtr pres(new Presentity (*this, presence_core, existing_groups, presnode));
     pres->trigger_saving.connect (boost::ref (trigger_saving));
     pres->removed.connect (boost::bind (boost::ref (presentity_removed), pres));
     pres->updated.connect (boost::bind (boost::ref (presentity_updated), pres));
@@ -1275,20 +1279,21 @@ bool
 Opal::Account::populate_menu_for_group (const std::string name,
                                        Ekiga::MenuBuilder& builder)
 {
-  builder.add_action ("edit", _("Rename"),
-                     boost::bind (&Opal::Account::on_rename_group, this, name));
-  return true;
 }
 
 
 void
-Opal::Account::on_rename_group (std::string name)
+Opal::Account::on_rename_group (Opal::PresentityPtr pres)
 {
-  boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new 
Ekiga::FormRequestSimple (boost::bind (&Opal::Account::rename_group_form_submitted, this, name, _1, _2)));
+  boost::shared_ptr<Ekiga::FormRequestSimple> request =
+    boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind 
(&Opal::Account::on_rename_group_form_submitted,
+                                                                                            this, _1, _2, 
pres->get_groups ())));
 
   request->title (_("Rename group"));
-  request->instructions (_("Please edit this group name"));
-  request->text ("name", _("Name:"), name, std::string ());
+  request->instructions (_("You can rename groups by clicking on the corresponding entry and changing the 
group name"));
+  request->editable_list ("groups", _("Groups:"),
+                        pres->get_groups (), std::list<std::string>(),
+                         false, true);
 
   Ekiga::Heap::questions (request);
 }
@@ -1316,19 +1321,27 @@ struct rename_group_form_submitted_helper
 
 
 void
-Opal::Account::rename_group_form_submitted (std::string old_name,
-                                           bool submitted,
-                                           Ekiga::Form& result)
+Opal::Account::on_rename_group_form_submitted (bool submitted,
+                                               Ekiga::Form& result,
+                                               const std::list<std::string> & groups)
 {
   if (!submitted)
     return;
 
-  const std::string new_name = result.text ("name");
+  std::list <std::string> new_groups = result.editable_list ("groups");
+
+  std::list <std::string>::const_iterator nit = new_groups.begin ();
+  std::list <std::string>::const_iterator it = groups.begin ();
 
-  if ( !new_name.empty () && new_name != old_name) {
+  for (std::pair <std::list<std::string>::const_iterator, std::list<std::string>::const_iterator> i(it, nit);
+       i.first != groups.end ();
+       ++i.first, ++i.second) {
 
-    rename_group_form_submitted_helper helper (old_name, new_name);
-    visit_presentities (boost::ref (helper));
+    if (*i.first != *i.second) {
+
+      rename_group_form_submitted_helper helper (*i.first, *i.second);
+      visit_presentities (boost::ref (helper));
+    }
   }
 }
 
diff --git a/lib/engine/components/opal/opal-account.h b/lib/engine/components/opal/opal-account.h
index b4c325a..46211ce 100644
--- a/lib/engine/components/opal/opal-account.h
+++ b/lib/engine/components/opal/opal-account.h
@@ -50,6 +50,8 @@
 
 #include "bank-impl.h"
 
+#include "opal-presentity.h"
+
 namespace Opal
 {
   // forward declarations:
@@ -68,6 +70,7 @@ namespace Opal
     protected Ekiga::RefLister<Presentity>,
     public Ekiga::PresencePublisher
   {
+    friend class Opal::Presentity;
 public:
 
     typedef enum { SIP, Ekiga, DiamondCard, H323 } Type;
@@ -89,7 +92,7 @@ public:
             boost::shared_ptr<Ekiga::PersonalDetails> _personal_details,
             boost::shared_ptr<Ekiga::AudioOutputCore> _audiooutput_core,
             boost::shared_ptr<CallManager> _call_manager,
-            boost::function0<std::set<std::string> > _existing_groups,
+            boost::function0<std::list<std::string> > _existing_groups,
             xmlNodePtr node_);
 
     ~Account () {}
@@ -102,7 +105,7 @@ public:
 
     Type get_type () const;
 
-    std::set<std::string> get_groups () const;
+    std::list<std::string> get_groups () const;
 
     /** Returns the protocol name of the Opal::Account.
      * This function is purely virtual and should be implemented by the
@@ -192,6 +195,9 @@ public:
     boost::signals2::signal<void(std::string, std::string)> presence_received;
     boost::signals2::signal<void(std::string, std::string)> status_received;
 
+protected:
+    void on_rename_group (Opal::PresentityPtr pres);
+
 private:
     void fetch (const std::string uri) const;
     void unfetch (const std::string uri) const;
@@ -207,10 +213,9 @@ private:
     void on_consult (const std::string url);
     bool is_myself (const std::string uri) const;
 
-    void on_rename_group (const std::string name);
-    void rename_group_form_submitted (std::string old_name,
-                                     bool submitted,
-                                     Ekiga::Form& result);
+    void on_rename_group_form_submitted (bool submitted,
+                                         Ekiga::Form& result,
+                                         const std::list<std::string> & groups);
 
     Type type;
     mutable RegistrationState state;
@@ -229,7 +234,7 @@ private:
 
     PDECLARE_PresenceChangeNotifier (Account, OnPresenceChange);
 
-    boost::function0<std::set<std::string> > existing_groups;
+    boost::function0<std::list<std::string> > existing_groups;
     xmlNodePtr node;
     xmlNodePtr roster_node;
     OpalPresenceInfo::State personal_state;
diff --git a/lib/engine/components/opal/opal-bank.cpp b/lib/engine/components/opal/opal-bank.cpp
index 60fb27e..c470d33 100644
--- a/lib/engine/components/opal/opal-bank.cpp
+++ b/lib/engine/components/opal/opal-bank.cpp
@@ -77,12 +77,12 @@ Opal::Bank::Bank (Ekiga::ServiceCore& core):
   for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
 
     if (child->type == XML_ELEMENT_NODE
-       && child->name != NULL
-       && xmlStrEqual(BAD_CAST "account", child->name)) {
+        && child->name != NULL
+        && xmlStrEqual(BAD_CAST "account", child->name)) {
 
       boost::shared_ptr<Account> account(new Account (sip_endpoint, presence_core, notification_core,
-                                                     personal_details, audiooutput_core, opal_component,
-                                                     boost::bind(&Opal::Bank::existing_groups, this), 
child));
+                                                      personal_details, audiooutput_core, opal_component,
+                                                      boost::bind(&Opal::Bank::existing_groups, this), 
child));
 
       add_account (account);
       Ekiga::BankImpl<Account>::add_connection (account, account->presentity_added.connect (boost::bind 
(boost::ref(presentity_added), account, _1)));
@@ -126,7 +126,7 @@ bool
 Opal::Bank::populate_menu (Ekiga::MenuBuilder & builder)
 {
   builder.add_action ("add", _("_Add an Ekiga.net Account"),
-                     boost::bind (&Opal::Bank::new_account, this, Opal::Account::Ekiga, "", ""));
+                      boost::bind (&Opal::Bank::new_account, this, Opal::Account::Ekiga, "", ""));
   builder.add_action ("add", _("_Add an Ekiga Call Out Account"),
                      boost::bind (&Opal::Bank::new_account, this, Opal::Account::DiamondCard, "", ""));
   builder.add_action ("add", _("_Add a SIP Account"),
@@ -404,40 +404,43 @@ Opal::Bank::visit_heaps (boost::function1<bool, Ekiga::HeapPtr> visitor) const
 }
 
 
-const std::set<std::string>
+const std::list<std::string>
 Opal::Bank::existing_groups () const
 {
-  std::set<std::string> result;
+  std::list<std::string> result;
 
   for (const_iterator iter = begin ();
        iter != end ();
        ++iter) {
 
-    std::set<std::string> groups = (*iter)->get_groups ();
-    result.insert (groups.begin (), groups.end ());
+    std::list<std::string> groups = (*iter)->get_groups ();
+    result.merge (groups);
   }
 
-  result.insert (_("Family"));
-  result.insert (_("Friend"));
+  result.push_back (_("Family"));
+  result.push_back (_("Friend"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; associate means
      someone who is at the same "level" than you.
   */
-  result.insert (_("Associate"));
+  result.push_back (_("Associate"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; assistant means
      someone who is at a lower "level" than you.
   */
-  result.insert (_("Assistant"));
+  result.push_back (_("Assistant"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; supervisor means
      someone who is at a higher "level" than you.
   */
-  result.insert (_("Supervisor"));
+  result.push_back (_("Supervisor"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; self means yourself.
   */
-  result.insert (_("Self"));
+  result.push_back (_("Self"));
+
+  result.sort ();
+  result.unique ();
 
   return result;
 }
diff --git a/lib/engine/components/opal/opal-bank.h b/lib/engine/components/opal/opal-bank.h
index ff13131..544b614 100644
--- a/lib/engine/components/opal/opal-bank.h
+++ b/lib/engine/components/opal/opal-bank.h
@@ -112,7 +112,7 @@ public:
     /* this object is an Ekiga::Cluster */
     void visit_heaps (boost::function1<bool, Ekiga::HeapPtr> visitor) const;
 
-    const std::set<std::string> existing_groups () const;
+    const std::list<std::string> existing_groups () const;
 
 
     // FIXME: only here for the transition off gconf
diff --git a/lib/engine/components/opal/opal-presentity.cpp b/lib/engine/components/opal/opal-presentity.cpp
index 6afc46e..4fbeb12 100644
--- a/lib/engine/components/opal/opal-presentity.cpp
+++ b/lib/engine/components/opal/opal-presentity.cpp
@@ -41,6 +41,7 @@
 #include "robust-xml.h"
 
 #include "opal-presentity.h"
+#include "opal-account.h"
 
 
 // remove leading and trailing spaces and tabs (useful for copy/paste)
@@ -76,7 +77,7 @@ struct null_deleter
 xmlNodePtr
 Opal::Presentity::build_node (const std::string name,
                              const std::string uri,
-                             const std::set<std::string> groups)
+                             const std::list<std::string> groups)
 {
   xmlNodePtr node = xmlNewNode (NULL, BAD_CAST "entry");
   xmlSetProp (node, BAD_CAST "uri", BAD_CAST uri.c_str ());
@@ -84,7 +85,7 @@ Opal::Presentity::build_node (const std::string name,
               BAD_CAST "name",
               BAD_CAST robust_xmlEscape (node->doc,
                                          name).c_str ());
-  for (std::set<std::string>::const_iterator iter = groups.begin ();
+  for (std::list<std::string>::const_iterator iter = groups.begin ();
        iter != groups.end ();
        ++iter)
     xmlNewChild (node, NULL,
@@ -96,9 +97,11 @@ Opal::Presentity::build_node (const std::string name,
 }
 
 
-Opal::Presentity::Presentity (boost::weak_ptr<Ekiga::PresenceCore> presence_core_,
-                             boost::function0<std::set<std::string> > existing_groups_,
+Opal::Presentity::Presentity (const Opal::Account & account_,
+                              boost::weak_ptr<Ekiga::PresenceCore> presence_core_,
+                             boost::function0<std::list<std::string> > existing_groups_,
                              xmlNodePtr node_):
+  account(account_),
   presence_core(presence_core_),
   existing_groups(existing_groups_),
   node(node_),
@@ -109,8 +112,14 @@ Opal::Presentity::Presentity (boost::weak_ptr<Ekiga::PresenceCore> presence_core
   if (pcore)
     pcore->pull_actions (actions, get_name (), get_uri ());
 
-  add_action (Ekiga::ActionPtr (new Ekiga::Action ("edit", _("_Edit"), boost::bind 
(&Opal::Presentity::edit_presentity, this))));
-  add_action (Ekiga::ActionPtr (new Ekiga::Action ("remove", _("_Remove"), boost::bind 
(&Opal::Presentity::remove, this))));
+  add_action (Ekiga::ActionPtr (new Ekiga::Action ("edit", _("_Edit"),
+                                                   boost::bind (&Opal::Presentity::edit_presentity, this))));
+  add_action (Ekiga::ActionPtr (new Ekiga::Action ("remove", _("_Remove"),
+                                                   boost::bind (&Opal::Presentity::remove, this))));
+  add_action (Ekiga::ActionPtr (new Ekiga::Action ("rename", _("Rename _Groups"),
+                                                   boost::bind (&Opal::Account::on_rename_group,
+                                                                (Opal::Account *) &account,
+                                                                PresentityPtr (this)))));
 }
 
 
@@ -165,10 +174,10 @@ Opal::Presentity::get_status () const
 }
 
 
-const std::set<std::string>
+const std::list<std::string>
 Opal::Presentity::get_groups () const
 {
-  std::set<std::string> groups;
+  std::list<std::string> groups;
 
   for (xmlNodePtr child = node->children ;
        child != NULL ;
@@ -182,7 +191,7 @@ Opal::Presentity::get_groups () const
        xmlChar* xml_str = xmlNodeGetContent (child);
        if (xml_str != NULL) {
 
-         groups.insert ((const char*) xml_str);
+         groups.push_back ((const char*) xml_str);
          xmlFree (xml_str);
        }
       }
@@ -248,8 +257,8 @@ Opal::Presentity::edit_presentity ()
 
   std::string name = get_name ();
   std::string uri = get_uri ();
-  std::set<std::string> groups = get_groups ();
-  std::set<std::string> all_groups = existing_groups ();
+  std::list<std::string> groups = get_groups ();
+  std::list<std::string> all_groups = existing_groups ();
 
   request->title (_("Edit roster element"));
   request->instructions (_("Please fill in this form to change an existing "
@@ -257,7 +266,7 @@ Opal::Presentity::edit_presentity ()
   request->text ("name", _("Name:"), name, _("Name of the contact, as shown in your roster"));
   request->text ("uri", _("Address:"), uri, _("Address, e.g. sip:xyz ekiga net; if you do not specify the 
host part, e.g. sip:xyz, then you can choose it by right-clicking on the contact in roster"));
 
-  request->editable_set ("groups", _("Choose groups:"),
+  request->editable_list ("groups", _("Choose groups:"),
                         groups, all_groups);
 
   questions (request);
@@ -272,8 +281,8 @@ Opal::Presentity::edit_presentity_form_submitted (bool submitted,
     return;
 
   const std::string new_name = result.text ("name");
-  const std::set<std::string> groups = get_groups ();
-  const std::set<std::string> new_groups = result.editable_set ("groups");
+  const std::list<std::string> groups = get_groups ();
+  const std::list<std::string> new_groups = result.editable_list ("groups");
   std::string new_uri = result.text ("uri");
   const std::string uri = get_uri ();
   std::set<xmlNodePtr> nodes_to_remove;
@@ -314,7 +323,7 @@ Opal::Presentity::edit_presentity_form_submitted (bool submitted,
 
        if (xml_str != NULL) {
 
-         if (new_groups.find ((const char*) xml_str) == new_groups.end ()) {
+         if (std::find (new_groups.begin (), new_groups.end (), (const char*) xml_str) == new_groups.end ()) 
{
 
            nodes_to_remove.insert (child); // don't free what we loop on!
          }
@@ -334,7 +343,7 @@ Opal::Presentity::edit_presentity_form_submitted (bool submitted,
   }
 
   // the second loop looking for groups we weren't in but are now
-  for (std::set<std::string>::const_iterator iter = new_groups.begin ();
+  for (std::list<std::string>::const_iterator iter = new_groups.begin ();
        iter != new_groups.end ();
        iter++) {
 
diff --git a/lib/engine/components/opal/opal-presentity.h b/lib/engine/components/opal/opal-presentity.h
index ded3b04..abfce41 100644
--- a/lib/engine/components/opal/opal-presentity.h
+++ b/lib/engine/components/opal/opal-presentity.h
@@ -50,6 +50,7 @@
 
 namespace Opal
 {
+  class Account;
   class Cluster;
 
   /* This class implements and Ekiga::Presentity, stored as a node
@@ -66,10 +67,11 @@ namespace Opal
      * will then use to create a valid instance using the ctor */
     static xmlNodePtr build_node (const std::string name_,
                                  const std::string uri_,
-                                 const std::set<std::string> groups_);
+                                 const std::list<std::string> groups_);
 
-    Presentity (boost::weak_ptr<Ekiga::PresenceCore> presence_core_,
-               boost::function0<std::set<std::string> > existing_groups_,
+    Presentity (const Account & account,
+                boost::weak_ptr<Ekiga::PresenceCore> presence_core_,
+               boost::function0<std::list<std::string> > existing_groups_,
                xmlNodePtr node_);
 
     ~Presentity ();
@@ -82,7 +84,7 @@ namespace Opal
 
     const std::string get_status () const;
 
-    const std::set<std::string> get_groups () const;
+    const std::list<std::string> get_groups () const;
 
     const std::string get_uri () const;
 
@@ -113,7 +115,7 @@ namespace Opal
      * changes get written in the XML source document, and finally
      * emit 'removed' so the views (and the heap) forget about it as a
      * presentity.
-     * 
+     *
      */
     boost::signals2::signal<void(void)> trigger_saving;
     void remove ();
@@ -127,8 +129,9 @@ namespace Opal
     void edit_presentity_form_submitted (bool submitted,
                                         Ekiga::Form& result);
 
+    const Account & account;
     boost::weak_ptr<Ekiga::PresenceCore> presence_core;
-    boost::function0<std::set<std::string> > existing_groups;
+    boost::function0<std::list<std::string> > existing_groups;
     xmlNodePtr node;
 
     std::string presence;
diff --git a/lib/engine/components/opal/sip-chat-simple.cpp b/lib/engine/components/opal/sip-chat-simple.cpp
index 7af1bad..311cc1d 100644
--- a/lib/engine/components/opal/sip-chat-simple.cpp
+++ b/lib/engine/components/opal/sip-chat-simple.cpp
@@ -47,7 +47,7 @@ SIP::SimpleChat::SimpleChat (boost::shared_ptr<Ekiga::PresenceCore> core,
   personal_details(details), sender(sender_), uri(uri_)
 {
   presentity = boost::shared_ptr<Ekiga::URIPresentity> (new Ekiga::URIPresentity (core, name, uri,
-                                                                         std::set<std::string>()));
+                                                                                  std::list<std::string>()));
 }
 
 SIP::SimpleChat::~SimpleChat ()
diff --git a/lib/engine/framework/form-builder.cpp b/lib/engine/framework/form-builder.cpp
index b99aba7..5ab8438 100644
--- a/lib/engine/framework/form-builder.cpp
+++ b/lib/engine/framework/form-builder.cpp
@@ -50,7 +50,7 @@ Ekiga::FormBuilder::visit (Ekiga::FormVisitor &visitor) const
   std::list<struct MultiTextField>::const_iterator iter_multi_text = multi_texts.begin ();
   std::list<struct SingleChoiceField>::const_iterator iter_single_choice = single_choices.begin ();
   std::list<struct MultipleChoiceField>::const_iterator iter_multiple_choice = multiple_choices.begin ();
-  std::list<struct EditableSetField>::const_iterator iter_editable_set = editable_sets.begin ();
+  std::list<struct EditableListField>::const_iterator iter_editable_list = editable_lists.begin ();
 
   visitor.title (my_title);
   visitor.instructions (my_instructions);
@@ -127,12 +127,13 @@ Ekiga::FormBuilder::visit (Ekiga::FormVisitor &visitor) const
 
     case EDITABLE_SET:
 
-      visitor.editable_set (iter_editable_set->name,
-                           iter_editable_set->description,
-                           iter_editable_set->values,
-                           iter_editable_set->proposed_values,
-                           iter_editable_set->advanced);
-      iter_editable_set++;
+      visitor.editable_list (iter_editable_list->name,
+                           iter_editable_list->description,
+                           iter_editable_list->values,
+                           iter_editable_list->proposed_values,
+                            iter_editable_list->advanced,
+                            iter_editable_list->rename_only);
+      iter_editable_list++;
       break;
 
     default:
@@ -225,16 +226,16 @@ Ekiga::FormBuilder::multiple_choice (const std::string name) const
   return std::set<std::string>(); // shouldn't happen
 }
 
-const std::set<std::string>
-Ekiga::FormBuilder::editable_set (const std::string name) const
+const std::list<std::string>
+Ekiga::FormBuilder::editable_list (const std::string name) const
 {
-  for (std::list<struct EditableSetField>::const_iterator iter = editable_sets.begin ();
-       iter != editable_sets.end ();
+  for (std::list<struct EditableListField>::const_iterator iter = editable_lists.begin ();
+       iter != editable_lists.end ();
        iter++)
     if (iter->name == name)
       return iter->values;
 
-  return std::set<std::string>(); // shouldn't happen
+  return std::list<std::string>(); // shouldn't happen
 }
 
 void
@@ -337,13 +338,15 @@ Ekiga::FormBuilder::multiple_choice (const std::string name,
 }
 
 void
-Ekiga::FormBuilder::editable_set (const std::string name,
-                                 const std::string description,
-                                 const std::set<std::string> values,
-                                 const std::set<std::string> proposed_values,
-                                 bool advanced)
+Ekiga::FormBuilder::editable_list (const std::string name,
+                                   const std::string description,
+                                   const std::list<std::string> values,
+                                   const std::list<std::string> proposed_values,
+                                   bool advanced,
+                                   bool rename_only)
 {
-  editable_sets.push_back (EditableSetField (name, description, values,
-                                            proposed_values, advanced));
+  editable_lists.push_back (EditableListField (name, description, values,
+                                               proposed_values, advanced,
+                                               rename_only));
   ordering.push_back (EDITABLE_SET);
 }
diff --git a/lib/engine/framework/form-builder.h b/lib/engine/framework/form-builder.h
index 53e7733..68a517f 100644
--- a/lib/engine/framework/form-builder.h
+++ b/lib/engine/framework/form-builder.h
@@ -72,7 +72,7 @@ namespace Ekiga
 
     const std::set<std::string> multiple_choice (const std::string name) const;
 
-    const std::set<std::string> editable_set (const std::string name) const;
+    const std::list<std::string> editable_list (const std::string name) const;
 
     /* builder part */
 
@@ -122,11 +122,13 @@ namespace Ekiga
                          const std::map<std::string, std::string> choices,
                          bool advanced = false);
 
-    void editable_set (const std::string name,
-                      const std::string description,
-                      const std::set<std::string> values,
-                      const std::set<std::string> proposed_values,
-                      bool advanced = false);
+    void editable_list (const std::string name,
+                        const std::string description,
+                        const std::list<std::string> values,
+                        const std::list<std::string> proposed_values,
+                        bool advanced = false,
+                        bool rename_only = false);
+
   private:
 
     struct HiddenField
@@ -226,22 +228,28 @@ namespace Ekiga
       bool advanced;
     };
 
-    struct EditableSetField
+    struct EditableListField
     {
-      EditableSetField (const std::string _name,
-                       const std::string _description,
-                       const std::set<std::string> _values,
-                       const std::set<std::string> _proposed_values,
-                       bool _advanced):
-       name(_name), description(_description),
-       values(_values), proposed_values(_proposed_values), advanced(_advanced)
+      EditableListField (const std::string _name,
+                         const std::string _description,
+                         const std::list<std::string> _values,
+                         const std::list<std::string> _proposed_values,
+                         bool _advanced,
+                         bool _rename_only):
+       name(_name),
+        description(_description),
+       values(_values),
+        proposed_values(_proposed_values),
+        advanced(_advanced),
+        rename_only(_rename_only)
       {}
 
       const std::string name;
       const std::string description;
-      const std::set<std::string> values;
-      const std::set<std::string> proposed_values;
+      const std::list<std::string> values;
+      const std::list<std::string> proposed_values;
       bool advanced;
+      bool rename_only;
     };
 
     typedef enum {
@@ -268,7 +276,7 @@ namespace Ekiga
     std::list<struct MultiTextField> multi_texts;
     std::list<struct SingleChoiceField> single_choices;
     std::list<struct MultipleChoiceField> multiple_choices;
-    std::list<struct EditableSetField> editable_sets;
+    std::list<struct EditableListField> editable_lists;
   };
 
 /**
diff --git a/lib/engine/framework/form-dumper.cpp b/lib/engine/framework/form-dumper.cpp
index bcad301..e7e91e3 100644
--- a/lib/engine/framework/form-dumper.cpp
+++ b/lib/engine/framework/form-dumper.cpp
@@ -178,22 +178,24 @@ Ekiga::FormDumper::multiple_choice (const std::string name,
 }
 
 void
-Ekiga::FormDumper::editable_set (const std::string name,
-                                const std::string description,
-                                const std::set<std::string> values,
-                                const std::set<std::string> proposed_values,
-                                bool advanced)
+Ekiga::FormDumper::editable_list (const std::string name,
+                                  const std::string description,
+                                  const std::list<std::string> values,
+                                  const std::list<std::string> proposed_values,
+                                  bool advanced,
+                                  bool rename_only)
 {
   out << "Editable list " << name << ":" << std::endl
       << description
       << (advanced?"[advanced]":"")
+      << (rename_only?"[rename_only]":"")
       << "where current set is :" << std::endl;
-  for (std::set<std::string>::const_iterator iter = values.begin ();
+  for (std::list<std::string>::const_iterator iter = values.begin ();
        iter != values.end ();
        iter++)
     out << *iter << std::endl;
   out << "with proposed set of :" << std::endl;
-  for (std::set<std::string>::const_iterator iter = proposed_values.begin ();
+  for (std::list<std::string>::const_iterator iter = proposed_values.begin ();
        iter != proposed_values.end ();
        iter++)
     out << *iter << std::endl;
diff --git a/lib/engine/framework/form-dumper.h b/lib/engine/framework/form-dumper.h
index 0c1fd82..4e342ed 100644
--- a/lib/engine/framework/form-dumper.h
+++ b/lib/engine/framework/form-dumper.h
@@ -101,11 +101,12 @@ namespace Ekiga
                          const std::map<std::string, std::string> choices,
                          bool advanced);
 
-    void editable_set (const std::string name,
-                      const std::string description,
-                      const std::set<std::string> values,
-                      const std::set<std::string> proposed_values,
-                      bool advanced);
+    void editable_list (const std::string name,
+                        const std::string description,
+                        const std::list<std::string> values,
+                        const std::list<std::string> proposed_values,
+                        bool advanced,
+                        bool rename_only);
 
   private:
 
diff --git a/lib/engine/framework/form-visitor.h b/lib/engine/framework/form-visitor.h
index f613d44..193613a 100644
--- a/lib/engine/framework/form-visitor.h
+++ b/lib/engine/framework/form-visitor.h
@@ -38,6 +38,7 @@
 
 #include <map>
 #include <set>
+#include <list>
 #include <string>
 
 namespace Ekiga
@@ -106,11 +107,12 @@ namespace Ekiga
                                  const std::map<std::string,std::string> choices,
                                  bool advanced) = 0;
 
-    virtual void editable_set (const std::string name,
-                              const std::string description,
-                              const std::set<std::string> values,
-                              const std::set<std::string> proposed_values,
-                              bool advanced) = 0;
+    virtual void editable_list (const std::string name,
+                                const std::string description,
+                                const std::list<std::string> values,
+                                const std::list<std::string> proposed_values,
+                                bool advanced,
+                                bool rename_only) = 0;
   };
 
 /**
diff --git a/lib/engine/framework/form.cpp b/lib/engine/framework/form.cpp
index 7a5f843..48da40d 100644
--- a/lib/engine/framework/form.cpp
+++ b/lib/engine/framework/form.cpp
@@ -91,8 +91,8 @@ Ekiga::EmptyForm::multiple_choice (const std::string /*name*/) const
   return std::set<std::string>();
 }
 
-const std::set<std::string>
-Ekiga::EmptyForm::editable_set (const std::string /*name*/) const
+const std::list<std::string>
+Ekiga::EmptyForm::editable_list (const std::string /*name*/) const
 {
-  return std::set<std::string>();
+  return std::list<std::string>();
 }
diff --git a/lib/engine/framework/form.h b/lib/engine/framework/form.h
index a8bebb3..34f2383 100644
--- a/lib/engine/framework/form.h
+++ b/lib/engine/framework/form.h
@@ -68,7 +68,7 @@ namespace Ekiga
 
     virtual const std::set<std::string> multiple_choice (const std::string name) const = 0;
 
-    virtual const std::set<std::string> editable_set (const std::string name) const = 0;
+    virtual const std::list<std::string> editable_list (const std::string name) const = 0;
   };
 
 /**
@@ -99,7 +99,7 @@ namespace Ekiga
 
     const std::set<std::string> multiple_choice (const std::string name) const;
 
-    const std::set<std::string> editable_set (const std::string name) const;
+    const std::list<std::string> editable_list (const std::string name) const;
   };
 
 };
diff --git a/lib/engine/gui/gtk-core/form-dialog-gtk.cpp b/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
index b5c6c90..ded0f2b 100644
--- a/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
+++ b/lib/engine/gui/gtk-core/form-dialog-gtk.cpp
@@ -59,6 +59,7 @@ multiple_choice_choice_toggled_cb (GtkCellRendererToggle *cell,
 
 /** Called when the GtkEntry aiming at adding a new
  * value has been activated.
+ *
  * Checks if the proposed value is not already in
  * the list, add it to the values if it is not the
  * case.
@@ -67,21 +68,38 @@ multiple_choice_choice_toggled_cb (GtkCellRendererToggle *cell,
  * the list of values.
  */
 static void
-editable_set_add_value_activated_cb (GtkWidget *entry,
+editable_list_add_value_activated_cb (GtkWidget *entry,
                                     gpointer data);
 
 
+/** Called when an entry in the GtkListStore has been
+ * edited.
+ *
+ * Checks if the proposed value is not already in
+ * the list, modify the edited value if it is not the
+ * case.
+ *
+ * @param: data is a pointer to the GtkListStore presenting
+ * the list of values.
+ */
+static void
+editable_list_edit_value_cb (GtkCellRendererText *cell,
+                            gchar *path_string,
+                            gchar *value,
+                            gpointer data);
+
+
 /** Called when the GtkButton to add a value
  * has been clicked.
  *
  * Emit the 'activated' signal on the GtkEntry
- * to trigger editable_set_add_value_activated_cb.
+ * to trigger editable_list_add_value_activated_cb.
  *
  * @param: data is a pointer to the GtkEntry containing
  * the new value.
  */
 static void
-editable_set_add_value_clicked_cb (GtkWidget *button,
+editable_list_add_value_clicked_cb (GtkWidget *button,
                                   gpointer data);
 
 
@@ -94,7 +112,7 @@ editable_set_add_value_clicked_cb (GtkWidget *button,
  * the list of choices.
  */
 static void
-editable_set_choice_toggled_cb (GtkCellRendererToggle *cell,
+editable_list_choice_toggled_cb (GtkCellRendererToggle *cell,
                                gchar *path_str,
                                gpointer data);
 
@@ -440,18 +458,18 @@ private:
 };
 
 
-class EditableSetSubmitter: public Submitter
+class EditableListSubmitter: public Submitter
 {
 public:
 
-  EditableSetSubmitter (const std::string _name,
+  EditableListSubmitter (const std::string _name,
                        const std::string _description,
                        bool _advanced,
                        GtkWidget *_tree_view):
     name(_name), description(_description), advanced(_advanced), tree_view(_tree_view)
   { }
 
-  ~EditableSetSubmitter ()
+  ~EditableListSubmitter ()
   { }
 
   enum {
@@ -465,8 +483,8 @@ public:
   {
     GtkTreeModel *model = NULL;
     GtkTreeIter iter;
-    std::set<std::string> values;
-    std::set<std::string> proposed_values;
+    std::list<std::string> values;
+    std::list<std::string> proposed_values;
 
     model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
     if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) {
@@ -484,15 +502,15 @@ public:
        if (value) {
 
          if (active)
-           values.insert (value);
+           values.push_back (value);
          else
-           proposed_values.insert (value);
+           proposed_values.push_back (value);
          g_free (value);
        }
       } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter));
     }
 
-    builder.editable_set (name, description, values, proposed_values, advanced);
+    builder.editable_list (name, description, values, proposed_values, advanced);
   }
 
 private:
@@ -509,7 +527,7 @@ private:
  */
 
 static void
-editable_set_add_value_activated_cb (GtkWidget *entry,
+editable_list_add_value_activated_cb (GtkWidget *entry,
                                     gpointer data)
 {
   GtkTreeModel *model = NULL;
@@ -530,7 +548,7 @@ editable_set_add_value_activated_cb (GtkWidget *entry,
     do {
 
       gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
-                          EditableSetSubmitter::COLUMN_VALUE, &tree_value,
+                          EditableListSubmitter::COLUMN_VALUE, &tree_value,
                           -1);
       if (tree_value && !g_strcmp0 (tree_value, value)) {
         g_free (tree_value);
@@ -545,8 +563,8 @@ editable_set_add_value_activated_cb (GtkWidget *entry,
 
   gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                     EditableSetSubmitter::COLUMN_ACTIVE, TRUE,
-                      EditableSetSubmitter::COLUMN_VALUE, gtk_entry_get_text (GTK_ENTRY (entry)),
+                     EditableListSubmitter::COLUMN_ACTIVE, TRUE,
+                      EditableListSubmitter::COLUMN_VALUE, gtk_entry_get_text (GTK_ENTRY (entry)),
                       -1);
 
   gtk_entry_set_text (GTK_ENTRY (entry), "");
@@ -554,7 +572,45 @@ editable_set_add_value_activated_cb (GtkWidget *entry,
 
 
 static void
-editable_set_add_value_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
+editable_list_edit_value_cb (GtkCellRendererText *cell,
+                            gchar *path_string,
+                            gchar *value,
+                            gpointer data)
+{
+  GtkTreeModel *model = NULL;
+  GtkTreeIter iter;
+
+  gchar *tree_value = NULL;
+
+  if (!g_strcmp0 (value, ""))
+    return;
+
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (data));
+
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) {
+
+    do {
+
+      gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
+                          EditableListSubmitter::COLUMN_VALUE, &tree_value,
+                          -1);
+      if (tree_value && !g_strcmp0 (tree_value, value)) {
+        g_free (tree_value);
+        return;
+      }
+      g_free (tree_value);
+
+    } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter));
+  }
+
+  gtk_tree_model_get_iter_from_string (model, &iter, path_string); 
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                      EditableListSubmitter::COLUMN_VALUE, value, -1);
+}
+
+
+static void
+editable_list_add_value_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
                                   gpointer data)
 {
   if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (data)), ""))
@@ -563,7 +619,7 @@ editable_set_add_value_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
 
 
 static void
-editable_set_choice_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
+editable_list_choice_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
                                gchar *path_str,
                                gpointer data)
 {
@@ -579,10 +635,10 @@ editable_set_choice_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
   /* Update the tree model */
   gtk_tree_model_get_iter (model, &iter, path);
   gtk_tree_model_get (model, &iter,
-                     EditableSetSubmitter::COLUMN_ACTIVE, &fixed,
+                     EditableListSubmitter::COLUMN_ACTIVE, &fixed,
                      -1);
   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                      EditableSetSubmitter::COLUMN_ACTIVE, fixed^1,
+                      EditableListSubmitter::COLUMN_ACTIVE, fixed^1,
                      -1);
   gtk_tree_path_free (path);
 }
@@ -1162,11 +1218,12 @@ FormDialog::multiple_choice (const std::string name,
 }
 
 void
-FormDialog::editable_set (const std::string name,
-                         const std::string description,
-                         const std::set<std::string> values,
-                         const std::set<std::string> proposed_values,
-                         bool advanced)
+FormDialog::editable_list (const std::string name,
+                           const std::string description,
+                           const std::list<std::string> values,
+                           const std::list<std::string> proposed_values,
+                           bool advanced,
+                           bool rename_only)
 {
   GtkWidget *label = NULL;
   GtkWidget *scroll = NULL;
@@ -1183,7 +1240,7 @@ FormDialog::editable_set (const std::string name,
 
   gchar *label_text = NULL;
 
-  EditableSetSubmitter *submitter = NULL;
+  EditableListSubmitter *submitter = NULL;
 
   /* The label */
   label = gtk_label_new (NULL);
@@ -1193,7 +1250,7 @@ FormDialog::editable_set (const std::string name,
   g_free (label_text);
 
   /* The GtkListStore containing the values */
-  list_store = gtk_list_store_new (EditableSetSubmitter::COLUMN_NUMBER,
+  list_store = gtk_list_store_new (EditableListSubmitter::COLUMN_NUMBER,
                                   G_TYPE_BOOLEAN, G_TYPE_STRING);
   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
@@ -1210,43 +1267,47 @@ FormDialog::editable_set (const std::string name,
   gtk_container_add (GTK_CONTAINER (frame), scroll);
   gtk_container_add (GTK_CONTAINER (scroll), tree_view);
 
-  renderer = gtk_cell_renderer_toggle_new ();
-  column =
-    gtk_tree_view_column_new_with_attributes (NULL, renderer,
-                                              "active", EditableSetSubmitter::COLUMN_ACTIVE,
-                                              NULL);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
-  g_signal_connect (renderer, "toggled",
-                    G_CALLBACK (editable_set_choice_toggled_cb), list_store);
-
+  if (!rename_only) {
+    renderer = gtk_cell_renderer_toggle_new ();
+    column =
+      gtk_tree_view_column_new_with_attributes (NULL, renderer,
+                                                "active", EditableListSubmitter::COLUMN_ACTIVE,
+                                                NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+    g_signal_connect (renderer, "toggled",
+                      G_CALLBACK (editable_list_choice_toggled_cb), list_store);
+  }
   renderer = gtk_cell_renderer_text_new ();
+  if (rename_only)
+    g_object_set (renderer, "editable", TRUE, NULL);
   column =
     gtk_tree_view_column_new_with_attributes (NULL, renderer,
-                                              "text", EditableSetSubmitter::COLUMN_VALUE,
+                                              "text", EditableListSubmitter::COLUMN_VALUE,
                                               NULL);
   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
+  g_signal_connect (renderer, "edited", (GCallback) editable_list_edit_value_cb, tree_view);
 
-  for (std::set<std::string>::const_iterator set_iter = values.begin ();
-       set_iter != values.end ();
-       set_iter++) {
+  for (std::list<std::string>::const_iterator list_iter = values.begin ();
+       list_iter != values.end ();
+       list_iter++) {
 
     gtk_list_store_append (GTK_LIST_STORE (list_store), &iter);
     gtk_list_store_set (GTK_LIST_STORE (list_store), &iter,
-                       EditableSetSubmitter::COLUMN_ACTIVE, TRUE,
-                        EditableSetSubmitter::COLUMN_VALUE, set_iter->c_str (),
+                       EditableListSubmitter::COLUMN_ACTIVE, TRUE,
+                        EditableListSubmitter::COLUMN_VALUE, list_iter->c_str (),
                         -1);
   }
-  for (std::set<std::string>::const_iterator set_iter
+  for (std::list<std::string>::const_iterator list_iter
         = proposed_values.begin ();
-       set_iter != proposed_values.end ();
-       set_iter++) {
+       list_iter != proposed_values.end ();
+       list_iter++) {
 
-    if (values.find (*set_iter) == values.end ()) {
+    if (std::find(values.begin(), values.end(), *list_iter) == values.end ()) {
 
       gtk_list_store_append (GTK_LIST_STORE (list_store), &iter);
       gtk_list_store_set (GTK_LIST_STORE (list_store), &iter,
-                         EditableSetSubmitter::COLUMN_ACTIVE, FALSE,
-                         EditableSetSubmitter::COLUMN_VALUE, set_iter->c_str (),
+                         EditableListSubmitter::COLUMN_ACTIVE, FALSE,
+                         EditableListSubmitter::COLUMN_VALUE, list_iter->c_str (),
                          -1);
     }
   }
@@ -1273,34 +1334,37 @@ FormDialog::editable_set (const std::string name,
                     2, 1);
   }
 
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
-  entry = gtk_entry_new ();
-  button = gtk_button_new_with_label (_("Add Group"));
-  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 2);
-  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);
+  if (!rename_only) {
 
-  g_signal_connect (entry, "activate",
-                   (GCallback) editable_set_add_value_activated_cb,
-                   (gpointer) tree_view);
+    hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+    entry = gtk_entry_new ();
+    button = gtk_button_new_with_label (_("Add Group"));
+    gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);
 
-  g_signal_connect (button, "clicked",
-                   (GCallback) editable_set_add_value_clicked_cb,
-                   (gpointer) entry);
+    g_signal_connect (entry, "activate",
+                      (GCallback) editable_list_add_value_activated_cb,
+                      (gpointer) tree_view);
 
-  grow_fields (advanced);
-  if (advanced) {
+    g_signal_connect (button, "clicked",
+                      (GCallback) editable_list_add_value_clicked_cb,
+                      (gpointer) entry);
 
-    gtk_grid_attach (GTK_GRID (advanced_fields), hbox,
-                    0, advanced_rows - 1,
-                    2, 1);
-  } else {
+    grow_fields (advanced);
+    if (advanced) {
 
-    gtk_grid_attach (GTK_GRID (fields), hbox,
-                    0, rows - 1,
-                    2, 1);
+      gtk_grid_attach (GTK_GRID (advanced_fields), hbox,
+                       0, advanced_rows - 1,
+                       2, 1);
+    } else {
+
+      gtk_grid_attach (GTK_GRID (fields), hbox,
+                       0, rows - 1,
+                       2, 1);
+    }
   }
 
-  submitter = new EditableSetSubmitter (name, description, advanced, tree_view);
+  submitter = new EditableListSubmitter (name, description, advanced, tree_view);
   submitters.push_back (submitter);
 }
 
diff --git a/lib/engine/gui/gtk-core/form-dialog-gtk.h b/lib/engine/gui/gtk-core/form-dialog-gtk.h
index 10a3a5b..14b2e46 100644
--- a/lib/engine/gui/gtk-core/form-dialog-gtk.h
+++ b/lib/engine/gui/gtk-core/form-dialog-gtk.h
@@ -110,11 +110,12 @@ public:
                        const std::map<std::string, std::string> choices,
                        bool advanced);
 
-  void editable_set (const std::string name,
-                    const std::string description,
-                    const std::set<std::string> values,
-                    const std::set<std::string> proposed_values,
-                    bool advanced);
+  void editable_list (const std::string name,
+                      const std::string description,
+                      const std::list<std::string> values,
+                      const std::list<std::string> proposed_values,
+                      bool advanced,
+                      bool rename_only);
 
   /* those are public only to be called from C code */
 
diff --git a/lib/engine/gui/gtk-frontend/heap-view.cpp b/lib/engine/gui/gtk-frontend/heap-view.cpp
index 7112bbe..b9e1fde 100644
--- a/lib/engine/gui/gtk-frontend/heap-view.cpp
+++ b/lib/engine/gui/gtk-frontend/heap-view.cpp
@@ -231,14 +231,14 @@ on_presentity_added (HeapView* self,
 {
   GtkTreeIter group_iter;
   GtkTreeIter iter;
-  std::set<std::string> groups = presentity->get_groups ();
+  std::list<std::string> groups = presentity->get_groups ();
   GtkTreeSelection* selection = gtk_tree_view_get_selection (self->priv->view);
   bool should_emit = false;
 
   if (groups.empty ())
-    groups.insert (_("Unsorted"));
+    groups.push_back (_("Unsorted"));
 
-  for (std::set<std::string>::const_iterator group = groups.begin ();
+  for (std::list<std::string>::const_iterator group = groups.begin ();
        group != groups.end (); ++group) {
 
     find_iter_for_group (self, group->c_str (), &group_iter);
@@ -272,10 +272,10 @@ on_presentity_updated (HeapView* self,
   GtkTreeIter group_iter;
   GtkTreeIter iter;
   gchar* group_name = NULL;
-  std::set<std::string> groups = presentity->get_groups ();
+  std::list<std::string> groups = presentity->get_groups ();
 
   if (groups.empty ())
-    groups.insert (_("Unsorted"));
+    groups.push_back (_("Unsorted"));
 
   model = GTK_TREE_MODEL (self->priv->store);
 
@@ -287,7 +287,7 @@ on_presentity_updated (HeapView* self,
 
       if (group_name != NULL) {
 
-       if (groups.find (group_name) == groups.end ()) {
+       if (std::find (groups.begin (), groups.end (), group_name) == groups.end ()) {
 
          find_iter_for_presentity (self, presentity.get (), &group_iter, &iter);
          gtk_tree_store_remove (self->priv->store, &iter);
diff --git a/lib/engine/gui/gtk-frontend/roster-view-gtk.cpp b/lib/engine/gui/gtk-frontend/roster-view-gtk.cpp
index 085c478..8b89268 100644
--- a/lib/engine/gui/gtk-frontend/roster-view-gtk.cpp
+++ b/lib/engine/gui/gtk-frontend/roster-view-gtk.cpp
@@ -1062,7 +1062,7 @@ on_presentity_added (RosterViewGtk* self,
 {
   GdkRGBA color;
   GtkTreeIter heap_iter;
-  std::set<std::string> groups = presentity->get_groups ();
+  std::list<std::string> groups = presentity->get_groups ();
   GtkTreeSelection* selection = gtk_tree_view_get_selection (self->priv->tree_view);
   GtkTreeModelFilter* filtered_model = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model 
(self->priv->tree_view));
   GtkTreeIter group_iter;
@@ -1080,9 +1080,9 @@ on_presentity_added (RosterViewGtk* self,
   away = presentity->get_presence () == "away";
 
   if (groups.empty ())
-    groups.insert (_("Unsorted"));
+    groups.push_back (_("Unsorted"));
 
-  for (std::set<std::string>::const_iterator group = groups.begin ();
+  for (std::list<std::string>::const_iterator group = groups.begin ();
        group != groups.end ();
        group++) {
 
@@ -1172,12 +1172,12 @@ on_presentity_updated (RosterViewGtk* self,
   GtkTreeIter iter;
   gchar *group_name = NULL;
   int timeout = 0;
-  std::set<std::string> groups = presentity->get_groups ();
+  std::list<std::string> groups = presentity->get_groups ();
 
   model = GTK_TREE_MODEL (self->priv->store);
 
   if (groups.empty ())
-    groups.insert (_("Unsorted"));
+    groups.push_back (_("Unsorted"));
 
   // This makes sure we are in all groups where we should
   on_presentity_added (self, cluster, heap, presentity);
@@ -1194,7 +1194,7 @@ on_presentity_updated (RosterViewGtk* self,
                           -1);
       if (group_name != NULL) {
 
-        if (groups.find (group_name) == groups.end ()) {
+        if (std::find (groups.begin (), groups.end (), group_name) == groups.end ()) {
 
           roster_view_gtk_find_iter_for_presentity (self, &group_iter, presentity, &iter);
           gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
diff --git a/lib/engine/presence/presentity.h b/lib/engine/presence/presentity.h
index 5f0442b..1a49616 100644
--- a/lib/engine/presence/presentity.h
+++ b/lib/engine/presence/presentity.h
@@ -78,9 +78,9 @@ namespace Ekiga
     virtual const std::string get_status () const = 0;
 
     /** Returns the set of groups the Presentity belongs to.
-     * @return The Presentity's set of groups.
+     * @return The Presentity's list of groups.
      */
-    virtual const std::set<std::string> get_groups () const = 0;
+    virtual const std::list<std::string> get_groups () const = 0;
 
     /** Returns whether the Presentity has this uri.
      * @return Whether the Presentity has this uri.
diff --git a/lib/engine/presence/proxy-presentity.cpp b/lib/engine/presence/proxy-presentity.cpp
index d8d18a3..bd594d1 100644
--- a/lib/engine/presence/proxy-presentity.cpp
+++ b/lib/engine/presence/proxy-presentity.cpp
@@ -64,7 +64,7 @@ Ekiga::ProxyPresentity::get_status () const
   return presentity.get_status ();
 }
 
-const std::set<std::string>
+const std::list<std::string>
 Ekiga::ProxyPresentity::get_groups () const
 {
   return presentity.get_groups ();
diff --git a/lib/engine/presence/proxy-presentity.h b/lib/engine/presence/proxy-presentity.h
index 301133c..7c43031 100644
--- a/lib/engine/presence/proxy-presentity.h
+++ b/lib/engine/presence/proxy-presentity.h
@@ -80,7 +80,7 @@ namespace Ekiga
 
     const std::string get_status () const;
 
-    const std::set<std::string> get_groups () const;
+    const std::list<std::string> get_groups () const;
 
     bool has_uri (const std::string uri) const;
 
diff --git a/lib/engine/presence/uri-presentity.cpp b/lib/engine/presence/uri-presentity.cpp
index a80a7b1..17986e3 100644
--- a/lib/engine/presence/uri-presentity.cpp
+++ b/lib/engine/presence/uri-presentity.cpp
@@ -48,7 +48,7 @@ struct null_deleter
 Ekiga::URIPresentity::URIPresentity (boost::shared_ptr<Ekiga::PresenceCore> pcore,
                                     std::string name_,
                                     std::string uri_,
-                                    std::set<std::string> groups_):
+                                    std::list<std::string> groups_):
   presence_core(pcore), name(name_), uri(uri_), presence("unknown"), groups(groups_)
 {
   pcore->presence_received.connect (boost::bind (&Ekiga::URIPresentity::on_presence_received, this, _1, _2));
@@ -81,7 +81,7 @@ Ekiga::URIPresentity::get_status () const
   return status;
 }
 
-const std::set<std::string>
+const std::list<std::string>
 Ekiga::URIPresentity::get_groups () const
 {
   return groups;
diff --git a/lib/engine/presence/uri-presentity.h b/lib/engine/presence/uri-presentity.h
index 6434c23..8507773 100644
--- a/lib/engine/presence/uri-presentity.h
+++ b/lib/engine/presence/uri-presentity.h
@@ -70,7 +70,7 @@ namespace Ekiga
     URIPresentity (boost::shared_ptr<Ekiga::PresenceCore> _presence_core,
                   std::string name_,
                   std::string uri_,
-                  std::set<std::string> groups_);
+                  std::list<std::string> groups_);
 
     ~URIPresentity ();
 
@@ -84,7 +84,7 @@ namespace Ekiga
 
     const std::string get_status () const;
 
-    const std::set<std::string> get_groups () const;
+    const std::list<std::string> get_groups () const;
 
     bool has_uri (const std::string uri_) const;
 
@@ -102,7 +102,7 @@ namespace Ekiga
     std::string name;
     std::string uri;
     std::string presence;
-    std::set<std::string> groups;
+    std::list<std::string> groups;
     std::string status;
 
     void on_presence_received (std::string uri_,
diff --git a/plugins/loudmouth/loudmouth-heap-roster.cpp b/plugins/loudmouth/loudmouth-heap-roster.cpp
index 7cce94a..f0d0b07 100644
--- a/plugins/loudmouth/loudmouth-heap-roster.cpp
+++ b/plugins/loudmouth/loudmouth-heap-roster.cpp
@@ -338,7 +338,7 @@ LM::HeapRoster::add_item ()
   request->text ("name", _("Name:"), "", _("Name of the contact, as shown in your roster"));
   request->editable_set ("groups",
                         _("Put contact in groups:"),
-                        std::set<std::string>(), existing_groups ());
+                         std::list<std::string>(), existing_groups ());
 
   questions (request);
 }
@@ -352,7 +352,7 @@ LM::HeapRoster::add_item_form_submitted (bool submitted,
 
   const std::string jid = result.text ("jid");
   const std::string contact_name = result.text ("name");
-  const std::set<std::string> groups = result.editable_set ("groups");
+  const std::list<std::string> groups = result.editable_set ("groups");
 
   if ( !jid.empty ()) {
 
@@ -371,7 +371,7 @@ LM::HeapRoster::add_item_form_submitted (bool submitted,
                                      NULL);
     }
 
-    for (std::set<std::string>::const_iterator iter = groups.begin (); iter != groups.end (); ++iter) {
+    for (std::list<std::string>::const_iterator iter = groups.begin (); iter != groups.end (); ++iter) {
 
       gchar* escaped = g_markup_escape_text (iter->c_str (), -1);
       lm_message_node_add_child (node, "group", escaped);
@@ -459,50 +459,50 @@ LM::HeapRoster::on_chat_requested (PresentityPtr presentity)
 
 struct lm_existing_groups_helper
 {
-  std::set<std::string> groups;
+  std::list<std::string> groups;
 
   bool operator() (Ekiga::PresentityPtr presentity)
   {
-    const std::set<std::string> presentity_groups = presentity->get_groups ();
+    const std::list<std::string> presentity_groups = presentity->get_groups ();
 
-    groups.insert (presentity_groups.begin (),
+    groups.push_back (presentity_groups.begin (),
                   presentity_groups.end ());
 
     return true;
   }
 };
 
-const std::set<std::string>
+const std::list<std::string>
 LM::HeapRoster::existing_groups () const
 {
-  std::set<std::string> result;
+  std::list<std::string> result;
 
   {
     lm_existing_groups_helper helper;
     visit_presentities (boost::ref (helper));
     result = helper.groups;
   }
-  result.insert (_("Family"));
-  result.insert (_("Friend"));
+  result.push_back (_("Family"));
+  result.push_back (_("Friend"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; associate means
      someone who is at the same "level" than you.
   */
-  result.insert (_("Associate"));
+  result.push_back (_("Associate"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; assistant means
      someone who is at a lower "level" than you.
   */
-  result.insert (_("Assistant"));
+  result.push_back (_("Assistant"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; supervisor means
      someone who is at a higher "level" than you.
   */
-  result.insert (_("Supervisor"));
+  result.push_back (_("Supervisor"));
   /* Translator: http://www.ietf.org/rfc/rfc4480.txt proposes several
      relationships between you and your contact; self means yourself.
   */
-  result.insert (_("Self"));
+  result.push_back (_("Self"));
 
   return result;
 }
diff --git a/plugins/loudmouth/loudmouth-heap-roster.h b/plugins/loudmouth/loudmouth-heap-roster.h
index 1fee4f5..460ab24 100644
--- a/plugins/loudmouth/loudmouth-heap-roster.h
+++ b/plugins/loudmouth/loudmouth-heap-roster.h
@@ -120,7 +120,7 @@ namespace LM
     LmHandlerResult message_handler_roster (LmMessage* message);
     LmHandlerResult message_handler_muc (LmMessage* message);
 
-    const std::set<std::string> existing_groups () const;
+    const std::list<std::string> existing_groups () const;
 
     /* when adding an item, we first ask to add it to the roster,
      * then get notified that it was really added,


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