[glibmm] DBusConnection: Add [register|unregister]_subtree() methods.



commit d823608687dd1303f78f165e0f8e47de366a60a5
Author: José Alburquerque <jaalburqu svn gnome org>
Date:   Thu Jan 6 15:17:55 2011 -0500

    DBusConnection: Add [register|unregister]_subtree() methods.
    
    	* gio/src/dbusconnection.{ccg,hg}: Add the new methods along with a
    	corresponding class (like the one for register_object()).  Added
    	method docs.  Modified the registration methods so that the vtable is
    	passed and not a struct containing the slots.  Please note that this
    	API feels like it could be made better before glibmm goes stable.  In
    	particular, it might be nice and (maybe even possible) to not require
    	that the *VTable instances be global.

 ChangeLog                  |   12 ++
 gio/src/dbusconnection.ccg |  209 +++++++++++++++++++++++++++--------
 gio/src/dbusconnection.hg  |  261 ++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 418 insertions(+), 64 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9a95590..dc7d096 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-01-06  José Alburquerque  <jaalburqu svn gnome org>
+
+	DBusConnection: Add [register|unregister]_subtree() methods.
+
+	* gio/src/dbusconnection.{ccg,hg}: Add the new methods along with a
+	corresponding class (like the one for register_object()).  Added
+	method docs.  Modified the registration methods so that the vtable is
+	passed and not a struct containing the slots.  Please note that this
+	API feels like it could be made better before glibmm goes stable.  In
+	particular, it might be nice and (maybe even possible) to not require
+	that the *VTable instances be global.
+
 2011-01-06  Murray Cumming  <murrayc murrayc com>
 
 	SocketService, ThreadedSocketService: Correct ref-counting for signals.
diff --git a/gio/src/dbusconnection.ccg b/gio/src/dbusconnection.ccg
index a415ad5..4f82cfa 100644
--- a/gio/src/dbusconnection.ccg
+++ b/gio/src/dbusconnection.ccg
@@ -26,15 +26,6 @@
 namespace
 {
 
-// struct to hold the slots in the DBusInterfaceVTable class.  This is used to
-// pass the slots to the callbacks and later destroy them.
-struct TypeDBusInterfaceVTableSlots
-{
-  Gio::DBusInterfaceVTable::SlotInterfaceMethodCall* slot_method_call;
-  Gio::DBusInterfaceVTable::SlotInterfaceGetProperty* slot_get_property;
-  Gio::DBusInterfaceVTable::SlotInterfaceSetProperty* slot_set_property;
-};
-
 extern "C"
 {
 
@@ -95,11 +86,11 @@ static void DBusInterfaceVTable_MethodCall_giomm_callback(
   const char* interface_name, const char* method_name, GVariant* parameters,
   GDBusMethodInvocation* invocation, void* user_data)
 {
-  TypeDBusInterfaceVTableSlots* the_slots =
-    static_cast<TypeDBusInterfaceVTableSlots*>(user_data);
+  Gio::DBusInterfaceVTable* vtable =
+    static_cast<Gio::DBusInterfaceVTable*>(user_data);
 
   Gio::DBusInterfaceVTable::SlotInterfaceMethodCall* the_slot =
-    the_slots->slot_method_call;
+    vtable->get_slot_method_call();
 
   try
   {
@@ -119,11 +110,11 @@ static GVariant* DBusInterfaceVTable_GetProperty_giomm_callback(
   const char* interface_name, const char* property_name, GError**,
   void* user_data)
 {
-  TypeDBusInterfaceVTableSlots* the_slots =
-    static_cast<TypeDBusInterfaceVTableSlots*>(user_data);
+  Gio::DBusInterfaceVTable* vtable =
+    static_cast<Gio::DBusInterfaceVTable*>(user_data);
 
   Gio::DBusInterfaceVTable::SlotInterfaceGetProperty* the_slot =
-    the_slots->slot_get_property;
+    vtable->get_slot_get_property();
 
   try
   {
@@ -147,11 +138,11 @@ static gboolean DBusInterfaceVTable_SetProperty_giomm_callback(
   const char* interface_name, const char* property_name, GVariant* value,
   GError**, void* user_data)
 {
-  TypeDBusInterfaceVTableSlots* the_slots =
-    static_cast<TypeDBusInterfaceVTableSlots*>(user_data);
+  Gio::DBusInterfaceVTable* vtable =
+    static_cast<Gio::DBusInterfaceVTable*>(user_data);
 
   Gio::DBusInterfaceVTable::SlotInterfaceSetProperty* the_slot =
-    the_slots->slot_set_property;
+    vtable->get_slot_set_property();
 
   try
   {
@@ -168,16 +159,105 @@ static gboolean DBusInterfaceVTable_SetProperty_giomm_callback(
   return false;
 }
 
-static void DBusInterfaceVTable_giomm_callback_destory(void* data)
+static char** DBusSubtreeVTable_Enumerate_giomm_callback(
+  GDBusConnection* connection, const char* sender, const char* object_path,
+  void* user_data)
+{
+  Gio::DBusSubtreeVTable* vtable =
+    static_cast<Gio::DBusSubtreeVTable*>(user_data);
+
+  Gio::DBusSubtreeVTable::SlotSubtreeEnumerate* the_slot =
+    vtable->get_slot_enumerate();
+
+  try
+  {
+    std::vector<Glib::ustring> result =
+      (*the_slot)(Glib::wrap(connection, true), Glib::ustring(sender),
+      Glib::ustring(object_path));
+
+    // This will be freed by the caller.
+    char** ret = g_new(char*, result.size());
+
+    for(std::vector<Glib::ustring>::size_type i = 0; i < result.size(); i++)
+    {
+      ret[i] = g_strdup(result[i].c_str());
+    }
+
+    return ret;
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  return 0;
+}
+
+static GDBusInterfaceInfo** DBusSubtreeVTable_Introspect_giomm_callback(
+  GDBusConnection* connection, const char* sender, const char* object_path,
+  const char* node, void* user_data)
 {
-  TypeDBusInterfaceVTableSlots* the_slots =
-    static_cast<TypeDBusInterfaceVTableSlots*>(data);
+  Gio::DBusSubtreeVTable* vtable =
+    static_cast<Gio::DBusSubtreeVTable*>(user_data);
+
+  Gio::DBusSubtreeVTable::SlotSubtreeIntrospect* the_slot =
+    vtable->get_slot_introspect();
+
+  try
+  {
+    std::vector< Glib::RefPtr<Gio::DBusInterfaceInfo> > result =
+      (*the_slot)(Glib::wrap(connection, true), Glib::ustring(sender),
+      Glib::ustring(object_path), Glib::ustring(node));
+
+    // This will be freed by the caller, along with unreferencing its members.
+    GDBusInterfaceInfo** info = g_new(GDBusInterfaceInfo*, result.size());
+
+    for(std::vector< Glib::RefPtr<Gio::DBusInterfaceInfo> >::size_type i = 0;
+      i < result.size(); i++)
+    {
+      info[i] = static_cast<GDBusInterfaceInfo*>(
+        g_object_ref(result[i]->gobj()));
+    }
 
-  delete the_slots->slot_method_call;
-  delete the_slots->slot_get_property;
-  delete the_slots->slot_set_property;
+    return info;
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
 
-  delete the_slots;
+  return 0;
+}
+
+static const GDBusInterfaceVTable* DBusSubtreeVTable_Dispatch_giomm_callback(
+  GDBusConnection* connection, const char* sender, const char* object_path,
+  const char* interface_name, const char* node, void** out_user_data,
+  void* user_data)
+{
+  Gio::DBusSubtreeVTable* vtable =
+    static_cast<Gio::DBusSubtreeVTable*>(user_data);
+
+  Gio::DBusSubtreeVTable::SlotSubtreeDispatch* the_slot =
+    vtable->get_slot_dispatch();
+
+  try
+  {
+    const Gio::DBusInterfaceVTable* vtable =
+      (*the_slot)(Glib::wrap(connection, true), Glib::ustring(sender),
+      Glib::ustring(object_path), Glib::ustring(interface_name),
+      Glib::ustring(node));
+
+    *out_user_data = const_cast<Gio::DBusInterfaceVTable*>(vtable);
+
+    return reinterpret_cast<GDBusInterfaceVTable*>(
+      const_cast<Gio::DBusInterfaceVTable*>(vtable));
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  return 0;
 }
 
 } // extern "C"
@@ -894,25 +974,34 @@ guint DBusConnection::add_filter(const SlotMessageFilter& slot)
 
 guint DBusConnection::register_object(const Glib::ustring& object_path,
   const Glib::RefPtr<DBusInterfaceInfo>& interface_info,
-  const DBusInterfaceVTable& vtable)
+  const DBusInterfaceVTable* vtable)
 {
-  TypeDBusInterfaceVTableSlots* the_slots = new TypeDBusInterfaceVTableSlots();
-
-  the_slots->slot_method_call = vtable.get_slot_method_call();
-  the_slots->slot_get_property = vtable.get_slot_get_property();
-  the_slots->slot_set_property = vtable.get_slot_set_property();
-
   GError* gerror = 0;
 
   guint const result = g_dbus_connection_register_object(gobj(),
     object_path.c_str(), Glib::unwrap(interface_info),
-    reinterpret_cast<GDBusInterfaceVTable*>(const_cast<DBusInterfaceVTable*>(&vtable)),
-    the_slots, &DBusInterfaceVTable_giomm_callback_destory, &gerror);
+    reinterpret_cast<GDBusInterfaceVTable*>(const_cast<DBusInterfaceVTable*>(vtable)),
+    const_cast<DBusInterfaceVTable*>(vtable), 0, &gerror);
 
   if(gerror)
     ::Glib::Error::throw_exception(gerror);
 
-  const_cast<DBusInterfaceVTable&>(vtable).signal_slots_registered();
+  return result;
+}
+
+guint DBusConnection::register_subtree(const Glib::ustring& object_path,
+  const DBusSubtreeVTable* vtable, DBusSubtreeFlags flags)
+{
+  GError* gerror = 0;
+
+  guint const result = g_dbus_connection_register_subtree(gobj(),
+    object_path.c_str(), 
+    reinterpret_cast<GDBusSubtreeVTable*>(const_cast<DBusSubtreeVTable*>(vtable)),
+    static_cast<GDBusSubtreeFlags>(flags),
+    const_cast<DBusSubtreeVTable*>(vtable), 0, &gerror);
+
+  if(gerror)
+    ::Glib::Error::throw_exception(gerror);
 
   return result;
 }
@@ -924,8 +1013,7 @@ DBusInterfaceVTable::DBusInterfaceVTable(
 )
 : slot_method_call(new SlotInterfaceMethodCall(slot_method_call)),
   slot_get_property(new SlotInterfaceGetProperty(slot_get_property)),
-  slot_set_property(new SlotInterfaceSetProperty(slot_set_property)),
-  slots_registered(false)
+  slot_set_property(new SlotInterfaceSetProperty(slot_set_property))
 {
   gobject_.method_call = &DBusInterfaceVTable_MethodCall_giomm_callback;
   gobject_.get_property = &DBusInterfaceVTable_GetProperty_giomm_callback;
@@ -934,12 +1022,9 @@ DBusInterfaceVTable::DBusInterfaceVTable(
 
 DBusInterfaceVTable::~DBusInterfaceVTable()
 {
-  if(!slots_registered)
-  {
-    delete slot_method_call;
-    delete slot_get_property;
-    delete slot_set_property;
-  }
+  delete slot_method_call;
+  delete slot_get_property;
+  delete slot_set_property;
 }
 
 DBusInterfaceVTable::SlotInterfaceMethodCall*
@@ -960,9 +1045,43 @@ DBusInterfaceVTable::SlotInterfaceSetProperty*
   return slot_set_property;
 }
 
-void DBusInterfaceVTable::signal_slots_registered()
+DBusSubtreeVTable::DBusSubtreeVTable(
+  const SlotSubtreeEnumerate& slot_enumerate,
+  const SlotSubtreeIntrospect& slot_introspect,
+  const SlotSubtreeDispatch& slot_dispatch
+)
+: slot_enumerate(new SlotSubtreeEnumerate(slot_enumerate)),
+  slot_introspect(new SlotSubtreeIntrospect(slot_introspect)),
+  slot_dispatch(new SlotSubtreeDispatch(slot_dispatch))
+{
+  gobject_.enumerate = &DBusSubtreeVTable_Enumerate_giomm_callback;
+  gobject_.introspect = &DBusSubtreeVTable_Introspect_giomm_callback;
+  gobject_.dispatch = &DBusSubtreeVTable_Dispatch_giomm_callback;
+}
+
+DBusSubtreeVTable::~DBusSubtreeVTable()
+{
+  delete slot_enumerate;
+  delete slot_introspect;
+  delete slot_dispatch;
+}
+
+DBusSubtreeVTable::SlotSubtreeEnumerate*
+  DBusSubtreeVTable::get_slot_enumerate() const
+{
+  return slot_enumerate;
+}
+
+DBusSubtreeVTable::SlotSubtreeIntrospect*
+  DBusSubtreeVTable::get_slot_introspect() const
+{
+  return slot_introspect;
+}
+
+DBusSubtreeVTable::SlotSubtreeDispatch*
+  DBusSubtreeVTable::get_slot_dispatch() const
 {
-  slots_registered = true;
+  return slot_dispatch;
 }
 
 } // namespace Gio
diff --git a/gio/src/dbusconnection.hg b/gio/src/dbusconnection.hg
index 5bb5210..24694bf 100644
--- a/gio/src/dbusconnection.hg
+++ b/gio/src/dbusconnection.hg
@@ -38,11 +38,13 @@ _WRAP_ENUM(DBusCallFlags, GDBusCallFlags, NO_GTYPE)
 _WRAP_ENUM(DBusConnectionFlags, GDBusConnectionFlags, NO_GTYPE)
 _WRAP_ENUM(DBusSendMessageFlags, GDBusSendMessageFlags, NO_GTYPE)
 _WRAP_ENUM(DBusSignalFlags, GDBusSignalFlags, NO_GTYPE)
+_WRAP_ENUM(DBusSubtreeFlags, GDBusSubtreeFlags, NO_GTYPE)
 
 class DBusAuthObserver;
 class DBusInterfaceInfo;
 class DBusInterfaceVTable;
 class DBusMethodInvocation;
+class DBusSubtreeVTable;
 
 /// @defgroup DBus D-Bus API
 
@@ -836,14 +838,94 @@ public:
 
   _WRAP_METHOD(void remove_filter(guint filter_id), g_dbus_connection_remove_filter)
 
-  /** TODO.
+  /** Registers slots for exported objects at @a object_path with the D-Bus
+   * interface that is described in @a interface_info.
+   *
+   * Calls to slots in @a vtable will happen in the thread-default main loop
+   * of the thread you are calling this method from.
+   *
+   * Note that all Glib::VariantBase values passed to functions in @a vtable
+   * will match the signature given in @a interface_info - if a remote caller
+   * passes incorrect values, the @c org.freedesktop.DBus.Error.InvalidArgs is
+   * returned to the remote caller.
+   *
+   * Additionally, if the remote caller attempts to invoke methods or access
+   * properties not mentioned in @a interface_info the
+   * @c org.freedesktop.DBus.Error.UnknownMethod resp.
+   * @c org.freedesktop.DBus.Error.InvalidArgs errors are returned to the
+   * caller.
+   *
+   * It is considered a programming error if the SlotDBusInterfaceGetProperty
+   * slot in @a vtable returns a Glib::VariantBase of incorrect type.
+   *
+   * If an existing slot is already registered at @a object_path and @a
+   * interface_name, then a Glib::Error is thrown.
+   *
+   * GDBus automatically implements the standard D-Bus interfaces
+   * org.freedesktop.DBus.Properties, org.freedesktop.DBus.Introspectable and
+   * org.freedesktop.Peer, so you don't have to implement those for the
+   * objects you export. You can implement org.freedesktop.DBus.Properties
+   * yourself, e.g. to handle getting and setting of properties
+   * asynchronously.
+   *
+   * @param object_path The object path to register at.  
+   * @param interface_info Introspection data for the interface.  
+   * @param vtable A GDBusInterfaceVTable to call into or NULL.  
+   * @return A registration id (never 0) that can be used with
+   * unregister_object() if no Glib::Error is thrown.
+   * @throw Glib::Error.
+   * @newin{2,28}
    */
   guint register_object(const Glib::ustring& object_path,
     const Glib::RefPtr<DBusInterfaceInfo>& interface_info,
-    const DBusInterfaceVTable& vtable);
+    const DBusInterfaceVTable* vtable);
   _IGNORE(g_dbus_connection_register_object)
 
   _WRAP_METHOD(bool unregister_object(guint registration_id), g_dbus_connection_unregister_object)
+
+  /** Registers a whole subtree of â??dynamicâ?? objects.
+   *
+   * Copies of the enumerate and introspection slots usted to create @a vtable
+   * are used to convey, to remote callers, what nodes exist in the subtree
+   * rooted by @a object_path.
+   *
+   * When handling remote calls into any node in the subtree, first the
+   * enumerate slot is used to check if the node exists. If the node
+   * exists or the Gio::DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag
+   * is set the introspection slot is used to check if the node supports the
+   * requested method. If so, the dispatch function is used to determine where
+   * to dispatch the call. The collected DBusInterfaceVTable will be used to
+   * call into the interface vtable for processing the request.
+   *
+   * All calls into user-provided code will be invoked in the thread-default
+   * main loop of the thread you are calling this method from.
+   *
+   * If an existing subtree is already registered at @a object_path or then
+   * a Glib::Error is thrown.
+   *
+   * Note that it is valid to register regular objects (using
+   * register_object()) in a subtree registered with register_subtree() - if
+   * so, the subtree handler is tried as the last resort. One way to think
+   * about a subtree handler is to consider it a â??fallback handlerâ?? for object
+   * paths not registered via register_object().
+   *
+   *
+   * @param object_path The object path to register the subtree at.  
+   * @param vtable A DBusSubtreeVTable to enumerate, introspect and dispatch
+   * nodes in the subtree.  
+   * @param flags Flags used to fine tune the behavior of the subtree.
+   * @return A subtree registration id (never 0) that can be used with
+   * unregister_subtree() if no Glib::Error is thrown.
+   *
+   * @newin{2,28}
+   */
+  guint register_subtree(const Glib::ustring& object_path,
+    const DBusSubtreeVTable* vtable,
+    DBusSubtreeFlags flags = Gio::DBUS_SUBTREE_FLAGS_NONE);
+  _IGNORE(g_dbus_connection_register_subtree)
+
+  _WRAP_METHOD(bool unregister_subtree(guint registration_id), g_dbus_connection_unregister_subtree)
+
 };
 
 /** DBusInterfaceVTable - A class used to represent a virtual table for
@@ -853,7 +935,14 @@ public:
  * simply register an object with the org.freedesktop.DBus.Properties D-Bus
  * interface using Gio::DBusConnection::register_object().
  *
- * Only one DBusInterfaceVTable instance may be used per registration.
+ * The only correct use of this class is to declare a global instance of it
+ * (or an instance local to the main function) and pass pointers to the
+ * instance to the methods that require such a parameter.  The instance can be
+ * used for multiple registrations and the memory it uses will be freed at the
+ * end of execution.  Any other use (like creating an instance local to a
+ * function and using that) may cause memory leaks or errors (if the instance
+ * is destroyed too early).
+ *
  * @newin{2,28}
  * @ingroup DBus
  */
@@ -870,7 +959,7 @@ public:
    * object_path, const Glib::ustring& interface_name, const Glib::ustring&
    * method_name, const Glib::VariantBase& parameters, const
    * Glib::RefPtr<Gio::DBusMethodInvocation>& invocation);
-   * @encode
+   * @endcode
    */
   typedef sigc::slot<
     void,
@@ -932,8 +1021,8 @@ public:
    */
   DBusInterfaceVTable(
    const SlotInterfaceMethodCall& slot_method_call,
-   const SlotInterfaceGetProperty& slot_get_property,
-   const SlotInterfaceSetProperty& slot_set_property
+   const SlotInterfaceGetProperty& slot_get_property = SlotInterfaceGetProperty(),
+   const SlotInterfaceSetProperty& slot_set_property = SlotInterfaceSetProperty()
   );
 
   /// Destructor.
@@ -953,7 +1042,15 @@ private:
   DBusInterfaceVTable(const DBusInterfaceVTable& other);
   DBusInterfaceVTable& operator=(const DBusInterfaceVTable& other);
 
-  friend class DBusConnection;
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // These are so the C callbacks and the
+  // Gio::DBusConnection::register_object() method can have access to the
+  // copies of the slots used for creation when registering.
+  SlotInterfaceMethodCall*      get_slot_method_call() const;
+  SlotInterfaceGetProperty*     get_slot_get_property() const;
+  SlotInterfaceSetProperty*     get_slot_set_property() const;
+#endif
 
 protected:
   // The underlying C instance.
@@ -963,22 +1060,148 @@ protected:
   SlotInterfaceMethodCall*      slot_method_call;
   SlotInterfaceGetProperty*     slot_get_property;
   SlotInterfaceSetProperty*     slot_set_property;
+};
+
+/** DBusSubtreeVTable - A class used to represent a virtual table for
+ * subtrees registered with Gio::DBusConnection::register_subtree().
+ *
+ * The only correct use of this class is to declare a global instance of it
+ * (or an instance local to the main function) and pass pointers to the
+ * instance to the methods that require such a parameter.  The instance can be
+ * used for multiple registrations and the memory it uses will be freed at the
+ * end of execution.  Any other use (like creating an instance local to a
+ * function and using that) may cause memory leaks or errors (if the instance
+ * is destroyed too early).
+ *
+ * @newin{2,28}
+ * @ingroup DBus
+ */
+class DBusSubtreeVTable
+{
+  _CLASS_GENERIC(DBusSubtreeVTable, GDBusSubtreeVTable)
+
+public:
+  /** The type for a slot which handles enumerating child nodes.
+   *
+   * This slot is called when generating introspection data and also when
+   * preparing to dispatch incoming messages in the event that the
+   * Gio::DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES flag is not
+   * specified (ie: to verify that the object path is valid).
+   *
+   * Hierarchies are not supported; the items that you return should not
+   * contain the '/' character.
+   *
+   * For example,
+   * @code
+   * std::vector<Glib::ustring> on_subtree_enumerate(const
+   * Glib::RefPtr<Gio::DBusConnection>& connection, const Glib::ustring&
+   * sender, const Glib::ustring& object_path);
+   * @endcode
+   */
+  typedef sigc::slot<
+    std::vector<Glib::ustring>,
+    const Glib::RefPtr<DBusConnection>&,
+    const Glib::ustring&,
+    const Glib::ustring&
+  > SlotSubtreeEnumerate;
 
-  // Boolean to signal whether the copies of the slots have been registered or
-  // not so the destructor can free them if they have not been registered.
-  bool slots_registered;
+  /** The type for a slot which handles introspecting a child node. 
+   *
+   * Subtrees are flat. @a node, if non-<tt>0</tt>, is always exactly one
+   * segment of the object path (ie: it never contains a slash).
+   *
+   * This function should return an empty vector to indicate that there is no
+   * object at this node.
+   *
+   * If this function returns a non-empty vector, the return value is expected
+   * to be a list of DBusInterfaceInfo structures describing the interfaces
+   * implemented by node.
+   *
+   * for example,
+   * @code
+   * std::vector< Glib::RefPtr<Gio::DBusInterFaceInfo> >
+   * on_subtree_introspect(const Glib::RefPtr<Gio::DBusConnection>&
+   * connection, const Glib::ustring& sender, const Glib::ustring&
+   * object_path, const Glib::ustring& node);
+   * @endcode
+   */
+  typedef sigc::slot<
+    std::vector< Glib::RefPtr<Gio::DBusInterfaceInfo> >,
+    const Glib::RefPtr<DBusConnection>&,
+    const Glib::ustring&,
+    const Glib::ustring&,
+    const Glib::ustring&
+  > SlotSubtreeIntrospect;
+
+  /** The type for a slot which handles dispatching a remote call on a child
+   * node.
+   *
+   * Subtrees are flat. @a node, if non-<tt>0</tt>, is always exactly one
+   * segment of the object path (ie: it never contains a slash).
+   *
+   * for example,
+   * @code
+   * const Gio::DBusInterfaceVTable* on_subtree_dispatch(const
+   * Glib::RefPtr<Gio::DBusConnection>& connection, const Glib::ustring&
+   * sender, const Glib::ustring& object_path, const Glib::ustring&
+   * interface_name, const Glib::ustring& node);
+   * @endcode
+   */
+  typedef sigc::slot<
+    const DBusInterfaceVTable*,
+    const Glib::RefPtr<DBusConnection>&,
+    const Glib::ustring&,
+    const Glib::ustring&,
+    const Glib::ustring&,
+    const Glib::ustring&
+  > SlotSubtreeDispatch;
+
+  /** Constructs a new DBusSubtreeVTable using specified slots.
+   * @param slot_enumerate The slot for handling incoming method calls.
+   * @param slot_introspect The slot for getting a property.
+   * @param slot_dispatch The slot for setting a property.
+   */
+  DBusSubtreeVTable(
+   const SlotSubtreeEnumerate& slot_enumerate,
+   const SlotSubtreeIntrospect& slot_introspect = SlotSubtreeIntrospect(),
+   const SlotSubtreeDispatch& slot_dispatch = SlotSubtreeDispatch()
+  );
+
+  /// Destructor.
+  virtual ~DBusSubtreeVTable();
+
+  /// Provides access to the underlying C object.
+  GDBusSubtreeVTable* gobj()
+    { return reinterpret_cast<GDBusSubtreeVTable*>(&gobject_); }
+
+  /// Provides access to the underlying C object.
+  const GDBusSubtreeVTable* gobj() const
+    { return reinterpret_cast<const GDBusSubtreeVTable*>(&gobject_); }
+
+
+private:
+  // Non-copyable.
+  DBusSubtreeVTable(const DBusSubtreeVTable& other);
+  DBusSubtreeVTable& operator=(const DBusSubtreeVTable& other);
+
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // These are so the C callbacks and the
+  // Gio::DBusConnection::register_subtreee() method can have access to the
+  // copies of the slots used for creation when registering.
+  SlotSubtreeEnumerate*         get_slot_enumerate() const;
+  SlotSubtreeIntrospect*        get_slot_introspect() const;
+  SlotSubtreeDispatch*          get_slot_dispatch() const;
+#endif
 
 protected:
-  // These are so the Gio::DBusConnection::register_object() method can have
-  // access to the copies of the slots used for creation when registering.
-  SlotInterfaceMethodCall*      get_slot_method_call() const;
-  SlotInterfaceGetProperty*     get_slot_get_property() const;
-  SlotInterfaceSetProperty*     get_slot_set_property() const;
+  // The underlying C instance.
+  GDBusSubtreeVTable          gobject_;
 
-  // This method is used to signal that the copies of the slots have been
-  // registered thus not needing to be freed when a created instance of this
-  // class is destroyed.
-  void signal_slots_registered();
+  // Pointers to copies of the slots used to create an instance.
+  SlotSubtreeEnumerate*         slot_enumerate;
+  SlotSubtreeIntrospect*        slot_introspect;
+  SlotSubtreeDispatch*          slot_dispatch;
 };
 
 } // namespace Gio



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