libqi-api  2.4.3.28
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proxyproperty.hpp
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QI_TYPE_PROXYPROPERTY_HPP_
8 #define _QI_TYPE_PROXYPROPERTY_HPP_
9 
10 #include <qi/log.hpp>
11 #include <qi/property.hpp>
12 #include <qi/anyfunction.hpp>
13 
14 
15 namespace qi
16 {
21  template<typename T>
22  class ProxyProperty: public Property<T>
23  {
24  public:
27  /* The signal bounce code is completely duplicated from SignalProxy.
28  * Unfortunately factoring this is not trivial:
29  * onSubscribe needs to be passed to Signal constructor, and we want to keep
30  * it that way.
31  */
32  ProxyProperty(AnyObject object, const std::string& propertyName)
33  {
34  setup(object, propertyName);
35  }
36  void setup(AnyObject object, const std::string& propertyName);
38  void onSubscribe(bool enable, GenericObject* object, const std::string& propertyName, SignalLink link);
40  void triggerOverride(const GenericFunctionParameters& params, MetaCallType, GenericObject* object, const std::string& propertyName);
41  private:
42  T getter(GenericObject* object, const std::string& propertyName);
43  bool setter(T&, const T&, GenericObject* object, const std::string& propertyName);
44  };
45 
46  template<typename T>
47  void makeProxyProperty(Property<T>& target, AnyObject object, const std::string& signalName)
48  {
49  ProxyProperty<T>& proxy = static_cast<ProxyProperty<T> &>(target);
50  proxy.setup(object, signalName);
51  }
52  template<typename T>
53  void makeProxyProperty(ProxyProperty<T>& target, AnyObject object, const std::string& signalName)
54  {
55  target.setup(object, signalName);
56  }
57 
58  template<typename T>
60  {
61  SignalType::disconnectAll();
62  }
63 
64  template<typename T>
65  void ProxyProperty<T>::setup(AnyObject object, const std::string& propertyName)
66  {
67  // signal part
69  object.asGenericObject(), propertyName, SignalBase::invalidSignalLink));
71  object.asGenericObject(), propertyName));
72 
73  // property part
74  this->_getter = boost::bind(&ProxyProperty<T>::getter, this, object.asGenericObject(), propertyName);
75  this->_setter = boost::bind(&ProxyProperty<T>::setter, this, _1, _2, object.asGenericObject(), propertyName);
76  }
77 
78  template<typename T>
79  void ProxyProperty<T>::onSubscribe(bool enable, GenericObject* object, const std::string& propertyName, SignalLink link)
80  {
81  if (enable)
82  {
83  link = object->connect(propertyName,
86  ));
87  }
88  else
89  {
90  bool ok = !object->disconnect(link).hasError();
91  if (!ok)
92  qiLogError("qitype.proxysignal") << "Failed to disconnect from parent signal";
94  }
95  // rebind onSubscribe since link changed
97  object, propertyName, link));
98  }
99 
100  template<typename T>
102  {
103  // Receive notify from backend, trigger on our signal, bypassing our trigger overload
104  SignalType::callSubscribers(args);
105  return AnyReference(typeOf<void>());
106  }
107 
108  template<typename T>
110  GenericObject* object, const std::string& propertyName)
111  {
112  // Just forward to backend, which will notify us in bouceEvent(),
113  // and then we will notify our local Subscribers
114  object->metaPost(propertyName, params);
115  }
116  template<typename T>
117  T ProxyProperty<T>::getter(GenericObject* object, const std::string& propertyName)
118  {
119  return object->property<T>(propertyName);
120  }
121  template<typename T>
122  bool ProxyProperty<T>::setter(T& target, const T& v, GenericObject* object, const std::string& propertyName)
123  {
124  // no need to fill target it's never used since we have a getter
125  object->setProperty(propertyName, v).value(); // throw on remote error
126  // Prevent local subscribers from being called
127  return false;
128  }
129 }
130 #endif // _QITYPE_PROXYPROPERTY_HPP_
boost::function< RF > bind(const AF &fun,...)
void setup(AnyObject object, const std::string &propertyName)
static const SignalLink invalidSignalLink
Definition: signal.hpp:103
AnyReference bounceEvent(const AnyReferenceVector args)
void setOnSubscribers(OnSubscribers onSubscribers)
void setTriggerOverride(Trigger trigger)
void onSubscribe(bool enable, GenericObject *object, const std::string &propertyName, SignalLink link)
void triggerOverride(const GenericFunctionParameters &params, MetaCallType, GenericObject *object, const std::string &propertyName)
#define qiLogError(...)
Log in error mode.
Definition: log.hpp:113
std::vector< AnyReference > AnyReferenceVector
MetaCallType
Definition: typeobject.hpp:19
static AnyFunction fromDynamicFunction(DynamicFunction f)
virtual AnyValue value() const
Definition: property.hpp:85
Convenient log macro.
void makeProxyProperty(Property< T > &target, AnyObject object, const std::string &signalName)
qi::uint64_t SignalLink
Definition: signal.hpp:33
SignalF< void(const T &)> SignalType
ProxyProperty(AnyObject object, const std::string &propertyName)