[ekiga/ds-gtk-application] Actor: Added a new and simpler Action/Actor mechanism.



commit fcfb3998d89e9f4106ddc4cad0828f4a93e4c305
Author: Damien Sandras <dsandras beip be>
Date:   Sat Sep 13 16:55:17 2014 +0200

    Actor: Added a new and simpler Action/Actor mechanism.
    
    This allows exposing Actions to the UI when they are not specifically
    part of the generic API.
    
    An object able to execute Actions is an Actor. An Actor is exposing its
    own Actions which can also be pulled from an ActionProvider (e.g. the
    CallCore could provide call Actions to a Contact).

 lib/Makefile.am                       |   10 +-
 lib/engine/action/action-provider.cpp |   52 ++++++++
 lib/engine/action/action-provider.h   |   87 +++++++++++++
 lib/engine/action/action.cpp          |   26 +++--
 lib/engine/action/action.h            |   36 ++++--
 lib/engine/action/actor.cpp           |   70 ++++++++---
 lib/engine/action/actor.h             |   69 ++++++++---
 lib/engine/action/data-action.h       |  219 ---------------------------------
 lib/engine/action/data-actor.h        |  117 ------------------
 9 files changed, 292 insertions(+), 394 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bca9d93..13b4449 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -230,10 +230,10 @@ libekiga_la_SOURCES += \
 libekiga_la_SOURCES += \
        engine/action/action.h \
        engine/action/action.cpp \
+       engine/action/action-provider.h \
+       engine/action/action-provider.cpp \
        engine/action/actor.h \
-       engine/action/actor.cpp \
-       engine/action/data-action.h \
-       engine/action/data-actor.h
+       engine/action/actor.cpp
 
 ##
 #  Sources of the addressbook stack
@@ -368,8 +368,8 @@ libekiga_la_SOURCES += \
        engine/gui/gtk-core/menu-builder-gtk.cpp \
        engine/gui/gtk-core/form-dialog-gtk.h \
        engine/gui/gtk-core/form-dialog-gtk.cpp \
-       engine/gui/gtk-core/actor-menu.h \
-       engine/gui/gtk-core/actor-menu.cpp \
+       engine/gui/gtk-core/gactor-menu.h \
+       engine/gui/gtk-core/gactor-menu.cpp \
        engine/gui/gtk-core/optional-buttons-gtk.h \
        engine/gui/gtk-core/optional-buttons-gtk.cpp \
        engine/gui/gtk-core/codecsbox.cpp \
diff --git a/lib/engine/action/action-provider.cpp b/lib/engine/action/action-provider.cpp
new file mode 100644
index 0000000..c79a878
--- /dev/null
+++ b/lib/engine/action/action-provider.cpp
@@ -0,0 +1,52 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * 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.
+ */
+
+
+/*
+ *                         action-provider.cpp  -  description
+ *                         -----------------------------------
+ *   begin                : written in February 2014 by Damien Sandras
+ *   copyright            : (c) 2014 by Damien Sandras
+ *   description          : An engine action provider.
+ *
+ */
+
+#include "action-provider.h"
+
+using namespace Ekiga;
+
+void
+URIActionProviderStore::pull_actions (ActionStore & store,
+                                      const std::string & name,
+                                      const std::string & uri)
+{
+  ActionStore provider_store;
+  for (URIActionProviderStore::iterator it = begin (); it != end (); it++) {
+    (*it)->pull_actions (provider_store, name, uri);
+    store.merge (provider_store);
+  }
+}
diff --git a/lib/engine/action/action-provider.h b/lib/engine/action/action-provider.h
new file mode 100644
index 0000000..9aba843
--- /dev/null
+++ b/lib/engine/action/action-provider.h
@@ -0,0 +1,87 @@
+
+/* Ekiga -- A VoIP and Video-Conferencing application
+ * Copyright (C) 2000-2014 Damien Sandras <dsandras seconix com>
+ *
+ * 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.
+ */
+
+
+/*
+ *                         action-provider.h  -  description
+ *                         ---------------------------------
+ *   begin                : written in February 2014 by Damien Sandras
+ *   copyright            : (c) 2014 by Damien Sandras
+ *   description          : An engine action provider.
+ *
+ */
+
+#ifndef __ACTION_PROVIDER_H__
+#define __ACTION_PROVIDER_H__
+
+#include <string>
+
+#include "scoped-connections.h"
+
+#include "action.h"
+
+namespace Ekiga {
+
+  /**
+   * @defgroup actions ActionProvider
+   * @{
+   */
+
+  /* An ActionProvider is an object able to provide Actions to
+   * Actors.
+   */
+  class ActionProvider
+  {
+  public:
+    virtual void pull_actions (ActionStore & /*store*/) {};
+  };
+  typedef boost::shared_ptr< ActionProvider > ActionProviderPtr;
+
+  class URIActionProvider : public ActionProvider
+  {
+  public:
+    virtual void pull_actions (ActionStore & /*store*/,
+                               const std::string & /*display_name*/,
+                               const std::string & /*uri*/) = 0;
+  };
+  typedef boost::shared_ptr< URIActionProvider > URIActionProviderPtr;
+
+  class URIActionProviderStore : public std::list< URIActionProviderPtr >
+  {
+  public:
+    virtual void pull_actions (ActionStore & /*store*/,
+                               const std::string & /*display_name*/,
+                               const std::string & /*uri*/);
+  };
+
+
+  /**
+   * @}
+   */
+}
+
+#endif
diff --git a/lib/engine/action/action.cpp b/lib/engine/action/action.cpp
index 5af12af..e7808c5 100644
--- a/lib/engine/action/action.cpp
+++ b/lib/engine/action/action.cpp
@@ -45,9 +45,9 @@ Action::Action (const std::string & _name,
 {
   name = _name;
   description = _description;
-  enabled = true;
+  action_enabled = true;
 
-  activated.connect (boost::bind (&Action::on_activated, this));
+  conns.add (activated.connect (boost::bind (&Action::on_activated, this)));
 }
 
 
@@ -58,14 +58,18 @@ Action::Action (const std::string & _name,
   name = _name;
   description = _description;
   callback = _callback;
-  enabled = true;
+  action_enabled = true;
 
-  activated.connect (boost::bind (&Action::on_activated, this));
+  conns.add (activated.connect (boost::bind (&Action::on_activated, this)));
 }
 
 
+Action::~Action ()
+{
+}
+
 const std::string &
-Action::get_name ()
+Action::get_name () const
 {
   return name;
 }
@@ -73,7 +77,7 @@ Action::get_name ()
 
 
 const std::string &
-Action::get_description ()
+Action::get_description () const
 {
   return description;
 }
@@ -90,21 +94,23 @@ Action::activate ()
 void
 Action::enable ()
 {
-  enabled = true;
+  action_enabled = true;
+  enabled ();
 }
 
 
 void
 Action::disable ()
 {
-  enabled = false;
+  action_enabled = false;
+  disabled ();
 }
 
 
 bool
-Action::is_enabled ()
+Action::is_enabled () const
 {
-  return enabled;
+  return action_enabled;
 }
 
 
diff --git a/lib/engine/action/action.h b/lib/engine/action/action.h
index 3e189df..833639e 100644
--- a/lib/engine/action/action.h
+++ b/lib/engine/action/action.h
@@ -41,7 +41,12 @@
 #include <boost/signals2.hpp>
 #include <boost/function.hpp>
 #include <boost/smart_ptr.hpp>
-#include <map>
+
+#include <list>
+#include <string>
+
+#include "scoped-connections.h"
+
 
 namespace Ekiga {
 
@@ -60,7 +65,7 @@ namespace Ekiga {
    * objects might allow processing more actions than the parent object.
    *
    * The Action object interface allows such derived objects to expose their
-   * own specific actions to be globally in such a way that they are usable
+   * own specific actions in such a way that they are usable
    * through the user interface without requiring dynamic casts in the UI code
    * to be able to use the full derived object API.
    *
@@ -80,6 +85,8 @@ namespace Ekiga {
    */
   class Action
   {
+    friend class Actor;
+
   public:
 
     /** Create an Action given a name and a description.
@@ -102,17 +109,23 @@ namespace Ekiga {
             const std::string & _description,
             boost::function0<void> _callback);
 
+    /** Destructor.
+     *
+     * Does nothing special.
+     */
+    ~Action ();
+
 
     /** Return the Action name.
      * @return the Action name (please read 'CONVENTION').
      */
-    const std::string & get_name ();
+    const std::string & get_name () const;
 
 
     /** Return the Action description.
      * @return the Action description.
      */
-    const std::string & get_description ();
+    const std::string & get_description () const;
 
 
     /** Activate the Action.
@@ -139,15 +152,21 @@ namespace Ekiga {
     /** Return the Action state.
      * @return true if the Action is enabled, false otherwise.
      */
-    bool is_enabled ();
+    bool is_enabled () const;
 
 
   protected:
 
     std::string name;
     std::string description;
+    bool action_enabled;
     boost::function0<void> callback;
 
+    /** Those signals are emitted when the Action is enabled/disabled.
+     */
+    boost::signals2::signal<void(void)> enabled;
+    boost::signals2::signal<void(void)> disabled;
+
 
   private:
 
@@ -162,15 +181,14 @@ namespace Ekiga {
      */
     boost::signals2::signal<void(void)> activated;
 
-    bool enabled;
+    Ekiga::scoped_connections conns;
   };
 
-  typedef boost::shared_ptr<Action> ActionPtr;
-  typedef std::map< std::string, ActionPtr > ActionMap;
+  typedef boost::shared_ptr< Action > ActionPtr;
+  typedef std::list< ActionPtr > ActionStore;
 
   /**
    * @}
    */
 }
-
 #endif
diff --git a/lib/engine/action/actor.cpp b/lib/engine/action/actor.cpp
index 61cec3d..75dd0a6 100644
--- a/lib/engine/action/actor.cpp
+++ b/lib/engine/action/actor.cpp
@@ -43,32 +43,72 @@ using namespace Ekiga;
 void
 Actor::add_action (ActionPtr action)
 {
-  actions.insert (std::make_pair (action->get_name (), action));
-  action_names.push_back (action->get_name ());
+  remove_action (action->get_name ()); // Remove any other action with the same name.
+
+  actions.push_back (action);
+
+  conns.add (action->enabled.connect (boost::bind (boost::ref (action_enabled), action->get_name ())));
+  conns.add (action->disabled.connect (boost::bind (boost::ref (action_enabled), action->get_name ())));
+
+  action_added (action->get_name ());
 }
 
 
 void
-Actor::enable_action (const std::string & name)
+Actor::add_action (const ActionStore & _actions)
 {
-  ActionMap::iterator it;
-  it = actions.find (name);
+  for (ActionStore::const_iterator it = _actions.begin (); it != _actions.end () ; ++it)
+    add_action (*it);
+}
+
 
-  if (it != actions.end ()) {
-    it->second->enable ();
-    action_enabled (name);
+bool
+Actor::remove_action (const std::string & name)
+{
+  for (ActionStore::iterator it = actions.begin (); it != actions.end () ; ++it) {
+    if ((*it)->get_name () == name) {
+      action_removed (name);
+      actions.erase (it);
+      return true;
+    }
   }
+  return false;
 }
 
 
 void
-Actor::disable_action (const std::string & name)
+Actor::remove_actions ()
 {
-  ActionMap::iterator it;
-  it = actions.find (name);
-
-  if (it != actions.end ()) {
-    it->second->disable ();
-    action_disabled (name);
+  for (ActionStore::iterator it = actions.begin (); it != actions.end () ; ++it) {
+    action_removed ((*it)->get_name ());
   }
+  actions.clear ();
+}
+
+
+Actor::const_iterator
+Actor::begin () const
+{
+  return actions.begin ();
+}
+
+
+Actor::const_iterator
+Actor::end () const
+{
+  return actions.end ();
+}
+
+
+Actor::iterator
+Actor::begin ()
+{
+  return actions.begin ();
+}
+
+
+Actor::iterator
+Actor::end ()
+{
+  return actions.end ();
 }
diff --git a/lib/engine/action/actor.h b/lib/engine/action/actor.h
index 7d96444..63c64fd 100644
--- a/lib/engine/action/actor.h
+++ b/lib/engine/action/actor.h
@@ -38,9 +38,11 @@
 #ifndef __ACTOR_H__
 #define __ACTOR_H__
 
-#include <string>
 
 #include "action.h"
+#include "scoped-connections.h"
+
+#include <string>
 
 namespace Ekiga {
 
@@ -52,16 +54,19 @@ namespace Ekiga {
 
   /* An actor is an object able to execute Actions.
    *
-   * Actor can register actions through the add_action method.
-   * acting.
+   * An Actor can register actions through the add_action method.
+   * It can remove them using the remove_action and remove_actions methods.
+   *
    */
   class Actor
   {
-    friend class ActorMenu;
+    friend class GActorMenu;
+    typedef ActionStore::const_iterator const_iterator;
+    typedef ActionStore::iterator iterator;
 
   public:
 
-    /** Register an action on the given Actor.
+    /** Add an action to the given Actor.
      *
      * Actions that are not "added" using this method will not be usable
      * from menus.
@@ -71,37 +76,63 @@ namespace Ekiga {
     virtual void add_action (ActionPtr action);
 
 
-    /** Enable a specific action on the given Actor.
+    /** Add actions from an ActionStore to the given Actor.
+     *
+     * Actions that are not "added" using this method will not be usable
+     * from menus.
      *
-     * @param The Action name.
+     * @param An ActionStore.
      */
-    void enable_action (const std::string & name);
+    virtual void add_action (const ActionStore & actions);
 
 
-    /** Disable a specific action on the given Actor.
+    /** Remove an action from the given Actor.
      *
-     * @param The Action name.
+     * @param An Action name.
+     * @return true if the Action was successfully removed, false otherwise.
      */
-    void disable_action (const std::string & name);
+    virtual bool remove_action (const std::string & name);
 
 
-  protected:
+    /** Remove all actions from the given Actor.
+     *
+     */
+    virtual void remove_actions ();
 
-    /** This method must be called by each Actor to register Actions.
+
+    /** Iterators (able to iterate through actions)
      */
-    virtual void register_actions () = 0;
+    const_iterator begin () const;
+    const_iterator end () const;
+    iterator begin ();
+    iterator end ();
 
 
-    /** Those signals are emitted when an Action is enabled/disabled
-     *  in the ActionMap.
+    /**
+     * Those signals are emitted when an Action is enabled/disabled
+     * in the ActionMap.
      */
     boost::signals2::signal<void(const std::string &)> action_enabled;
     boost::signals2::signal<void(const std::string &)> action_disabled;
 
-    ActionMap actions;
-    std::list<std::string> action_names;
-  };
 
+    /**
+     * Those signals are emitted when an Action is added/removed
+     * to/from the ActionMap.
+     */
+    boost::signals2::signal<void(const std::string &)> action_added;
+    boost::signals2::signal<void(const std::string &)> action_removed;
+
+
+  protected:
+
+    /**
+     * This is the Actor ActionStore.
+     * It contains all actions supported by the current Actor.
+     */
+    ActionStore actions;
+    Ekiga::scoped_connections conns;
+  };
   typedef boost::shared_ptr< Actor > ActorPtr;
 
   /**


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