Sfoglia il codice sorgente

Make ctkComplementMapper more generic, rename into ctkBooleanMapper

Julien Finet 13 anni fa
parent
commit
145a0a72fe

+ 3 - 3
Libs/Core/CMakeLists.txt

@@ -30,14 +30,14 @@ set(KIT_SRCS
   ctkAbstractQObjectFactory.tpp
   ctkAbstractLibraryFactory.h
   ctkAbstractLibraryFactory.tpp
+  ctkBooleanMapper.cpp
+  ctkBooleanMapper.h
   ctkCallback.cpp
   ctkCallback.h
   ctkCheckableModelHelper.cpp
   ctkCheckableModelHelper.h
   ctkCommandLineParser.cpp
   ctkCommandLineParser.h
-  ctkComplementMapper.cpp
-  ctkComplementMapper.h
   ctkDependencyGraph.cpp
   ctkDependencyGraph.h
   ctkErrorLogModel.cpp
@@ -83,10 +83,10 @@ endif()
 
 # Headers that should run through moc
 set(KIT_MOC_SRCS
+  ctkBooleanMapper.h
   ctkCallback.h
   ctkCheckableModelHelper.h
   ctkCommandLineParser.h
-  ctkComplementMapper.h
   ctkErrorLogFDMessageHandler_p.h
   ctkErrorLogModel.h
   ctkLogger.h

+ 3 - 3
Libs/Core/Testing/Cpp/CMakeLists.txt

@@ -22,10 +22,10 @@ set(KITTests_SRCS
   ctkAbstractObjectFactoryTest1.cpp
   ctkAbstractPluginFactoryTest1.cpp
   ctkAbstractQObjectFactoryTest1.cpp
+  ctkBooleanMapperTest.cpp
   ctkCallbackTest1.cpp
   ctkCheckableModelHelperTest1.cpp
   ctkCommandLineParserTest1.cpp
-  ctkComplementMapperTest.cpp
   ctkErrorLogModelTest1.cpp
   ctkErrorLogModelEntryGroupingTest1.cpp
   ctkErrorLogModelTerminalOutputTest1.cpp
@@ -99,7 +99,7 @@ set(Tests_Helpers_MOC_SRCS
 set(Tests_Helpers_MOC_CPP)
 QT4_WRAP_CPP(Tests_Helpers_MOC_CPP ${Tests_Helpers_MOC_SRCS})
 QT4_GENERATE_MOCS(
-  ctkComplementMapperTest.cpp
+  ctkBooleanMapperTest.cpp
   )
 
 if(HAVE_BFD)
@@ -128,10 +128,10 @@ SIMPLE_TEST( ctkAbstractQObjectFactoryTest1 )
 if(HAVE_BFD)
   SIMPLE_TEST( ctkBinaryFileDescriptorTest1 $<TARGET_FILE:ctkBinaryFileDescriptorTestHelper> )
 endif()
+SIMPLE_TEST( ctkBooleanMapperTest )
 SIMPLE_TEST( ctkCallbackTest1 )
 SIMPLE_TEST( ctkCheckableModelHelperTest1 )
 SIMPLE_TEST( ctkCommandLineParserTest1 )
-SIMPLE_TEST( ctkComplementMapperTest )
 SIMPLE_TEST( ctkDependencyGraphTest1 )
 SIMPLE_TEST( ctkDependencyGraphTest2 )
 SIMPLE_TEST( ctkErrorLogModelTest1 )

+ 61 - 24
Libs/Core/Testing/Cpp/ctkComplementMapperTest.cpp

@@ -22,7 +22,7 @@
 #include <QSignalSpy>
 
 // CTK includes
-#include "ctkComplementMapper.h"
+#include "ctkBooleanMapper.h"
 #include "ctkTest.h"
 
 // ----------------------------------------------------------------------------
@@ -49,21 +49,22 @@ private:
 };
 
 // ----------------------------------------------------------------------------
-class ctkComplementMapperTester: public QObject
+class ctkBooleanMapperTester: public QObject
 {
   Q_OBJECT
 private Q_SLOTS:
   void testValue();
-  void testValueComplement();
+  void testComplement();
+  void testValueAsInt();
   void testSignals();
 };
 
 // ----------------------------------------------------------------------------
-void ctkComplementMapperTester::testValue()
+void ctkBooleanMapperTester::testValue()
 {
   ctkObjectWithBoolProp object;
-  ctkComplementMapper* complementMapper =
-    new ctkComplementMapper(&object, "checked", SIGNAL(toggled(bool)));
+  ctkBooleanMapper* complementMapper =
+    new ctkBooleanMapper(&object, "checked", SIGNAL(toggled(bool)));
 
   QCOMPARE(object.checked(), false);
   QCOMPARE(complementMapper->value(), false);
@@ -86,57 +87,93 @@ void ctkComplementMapperTester::testValue()
 }
 
 // ----------------------------------------------------------------------------
-void ctkComplementMapperTester::testValueComplement()
+void ctkBooleanMapperTester::testComplement()
 {
   ctkObjectWithBoolProp object;
-  ctkComplementMapper* complementMapper =
-    new ctkComplementMapper(&object, "checked", SIGNAL(toggled(bool)));
+  ctkBooleanMapper* complementMapper =
+    new ctkBooleanMapper(&object, "checked", SIGNAL(toggled(bool)));
 
   QCOMPARE(object.checked(), false);
-  QCOMPARE(complementMapper->valueComplement(), true);
+  QCOMPARE(complementMapper->complement(), true);
 
   object.setChecked(true);
   QCOMPARE(object.checked(), true);
-  QCOMPARE(complementMapper->valueComplement(), false);
+  QCOMPARE(complementMapper->complement(), false);
 
-  complementMapper->setValueComplement(true);
+  complementMapper->setComplement(true);
   QCOMPARE(object.checked(), false);
-  QCOMPARE(complementMapper->valueComplement(), true);
+  QCOMPARE(complementMapper->complement(), true);
+}
+
+
+// ----------------------------------------------------------------------------
+void ctkBooleanMapperTester::testValueAsInt()
+{
+  ctkObjectWithBoolProp object;
+  ctkBooleanMapper* complementMapper =
+    new ctkBooleanMapper(&object, "checked", SIGNAL(toggled(bool)));
+  complementMapper->setTrueValue(QVariant(-1));
+  complementMapper->setFalseValue(QVariant(19));
+
+  QCOMPARE(object.checked(), false);
+  QCOMPARE(complementMapper->valueAsInt(), 19);
+
+  object.setChecked(true);
+  QCOMPARE(object.checked(), true);
+  QCOMPARE(complementMapper->valueAsInt(), -1);
+
+  object.setChecked(false);
+  QCOMPARE(object.checked(), false);
+  QCOMPARE(complementMapper->valueAsInt(), 19);
+
+  complementMapper->setValueAsInt(-1);
+  QCOMPARE(object.checked(), true);
+  QCOMPARE(complementMapper->valueAsInt(), -1);
+
+  complementMapper->setValueAsInt(19);
+  QCOMPARE(object.checked(), false);
+  QCOMPARE(complementMapper->valueAsInt(), 19);
 }
 
 // ----------------------------------------------------------------------------
-void ctkComplementMapperTester::testSignals()
+void ctkBooleanMapperTester::testSignals()
 {
   ctkObjectWithBoolProp object;
-  ctkComplementMapper* complementMapper =
-    new ctkComplementMapper(&object, "checked", SIGNAL(toggled(bool)));
+  ctkBooleanMapper* complementMapper =
+    new ctkBooleanMapper(&object, "checked", SIGNAL(toggled(bool)));
 
   QSignalSpy spyToggled(&object, SIGNAL(toggled(bool)));
   QSignalSpy spyValueChanged(complementMapper, SIGNAL(valueChanged(bool)));
-  QSignalSpy spyValueComplementChanged(complementMapper,
-                                       SIGNAL(valueComplementChanged(bool)));
+  QSignalSpy spyComplementChanged(complementMapper,
+                                  SIGNAL(complementChanged(bool)));
+  QSignalSpy spyValueAsIntChanged(complementMapper,
+                                  SIGNAL(valueAsIntChanged(int)));
 
   object.setChecked(true);
   QCOMPARE(spyToggled.count(), 1);
   QCOMPARE(spyValueChanged.count(), 1);
-  QCOMPARE(spyValueComplementChanged.count(), 1);
+  QCOMPARE(spyComplementChanged.count(), 1);
+  QCOMPARE(spyValueAsIntChanged.count(), 1);
 
   spyToggled.clear();
   spyValueChanged.clear();
-  spyValueComplementChanged.clear();
+  spyComplementChanged.clear();
+  spyValueAsIntChanged.clear();
 
   // no op
   complementMapper->setValue(complementMapper->value());
   QCOMPARE(spyToggled.count(), 0);
   QCOMPARE(spyValueChanged.count(), 0);
-  QCOMPARE(spyValueComplementChanged.count(), 0);
+  QCOMPARE(spyComplementChanged.count(), 0);
+  QCOMPARE(spyValueAsIntChanged.count(), 0);
 
   complementMapper->toggle();
   QCOMPARE(spyToggled.count(), 1);
   QCOMPARE(spyValueChanged.count(), 1);
-  QCOMPARE(spyValueComplementChanged.count(), 1);
+  QCOMPARE(spyComplementChanged.count(), 1);
+  QCOMPARE(spyValueAsIntChanged.count(), 1);
 }
 
 // ----------------------------------------------------------------------------
-CTK_TEST_MAIN(ctkComplementMapperTest)
-#include "moc_ctkComplementMapperTest.cpp"
+CTK_TEST_MAIN(ctkBooleanMapperTest)
+#include "moc_ctkBooleanMapperTest.cpp"

+ 190 - 0
Libs/Core/ctkBooleanMapper.cpp

@@ -0,0 +1,190 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+
+// CTK includes
+#include "ctkBooleanMapper.h"
+
+//-----------------------------------------------------------------------------
+class ctkBooleanMapperPrivate
+{
+public:
+  ctkBooleanMapperPrivate();
+  QByteArray PropertyName;
+  QVariant TrueValue;
+  QVariant FalseValue;
+};
+
+// --------------------------------------------------------------------------
+ctkBooleanMapperPrivate::ctkBooleanMapperPrivate()
+{
+  this->TrueValue = QVariant(true);
+  this->FalseValue = QVariant(false);
+}
+
+// --------------------------------------------------------------------------
+// ctkBooleanMapper methods
+
+// --------------------------------------------------------------------------
+ctkBooleanMapper::ctkBooleanMapper(
+  QObject* targetObject, const QByteArray& property, const char* signal)
+  : QObject(targetObject)
+  , d_ptr(new ctkBooleanMapperPrivate)
+{
+  Q_ASSERT(property.isEmpty() != true);
+  Q_ASSERT(targetObject != 0);
+  Q_D(ctkBooleanMapper);
+  d->PropertyName = property;
+  if (signal)
+    {
+    connect(targetObject, signal, this, SLOT(emitValueChanged()));
+    }
+}
+
+// --------------------------------------------------------------------------
+ctkBooleanMapper::~ctkBooleanMapper()
+{
+}
+
+// --------------------------------------------------------------------------
+QByteArray ctkBooleanMapper::propertyName()const
+{
+  Q_D(const ctkBooleanMapper);
+  return d->PropertyName;
+}
+
+// --------------------------------------------------------------------------
+QObject* ctkBooleanMapper::targetObject()const
+{
+  return this->parent();
+}
+
+// --------------------------------------------------------------------------
+QVariant ctkBooleanMapper::trueValue()const
+{
+  Q_D(const ctkBooleanMapper);
+  return d->TrueValue;
+}
+
+// --------------------------------------------------------------------------
+QVariant ctkBooleanMapper::falseValue()const
+{
+  Q_D(const ctkBooleanMapper);
+  return d->FalseValue;
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setTrueValue(const QVariant& trueValue)
+{
+  Q_D(ctkBooleanMapper);
+  if (d->TrueValue == trueValue)
+    {
+    return;
+    }
+  d->TrueValue = trueValue;
+  this->emitValueAsChanged();
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setFalseValue(const QVariant& falseValue)
+{
+  Q_D(ctkBooleanMapper);
+  if (d->FalseValue == falseValue)
+    {
+    return;
+    }
+  d->FalseValue = falseValue;
+  this->emitValueAsChanged();
+}
+
+// --------------------------------------------------------------------------
+bool ctkBooleanMapper::value()const
+{
+  return this->targetObject()->property(this->propertyName()).toBool();
+}
+
+// --------------------------------------------------------------------------
+bool ctkBooleanMapper::complement()const
+{
+  return !this->value();
+}
+
+// --------------------------------------------------------------------------
+int ctkBooleanMapper::valueAsInt()const
+{
+  Q_D(const ctkBooleanMapper);
+  return this->value() ? d->TrueValue.toInt() : d->FalseValue.toInt();
+}
+
+// --------------------------------------------------------------------------
+QString ctkBooleanMapper::valueAsString()const
+{
+  Q_D(const ctkBooleanMapper);
+  return this->value() ? d->TrueValue.toString() : d->FalseValue.toString();
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setValue(bool value)
+{
+  this->targetObject()->setProperty(this->propertyName(), QVariant(value));
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setComplement(bool value)
+{
+  this->setValue(!value);
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setValueAsInt(int intValue)
+{
+  Q_D(ctkBooleanMapper);
+  this->setValue( QVariant(intValue) == d->TrueValue);
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::setValueAsString(const QString& stringValue)
+{
+  Q_D(ctkBooleanMapper);
+  this->setValue( QVariant(stringValue) == d->TrueValue );
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::toggle()
+{
+  this->setValue(this->complement());
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::emitValueChanged()
+{
+  emit valueChanged(this->value());
+  emit complementChanged(this->complement());
+  this->emitValueAsChanged();
+}
+
+// --------------------------------------------------------------------------
+void ctkBooleanMapper::emitValueAsChanged()
+{
+  emit valueAsIntChanged(this->valueAsInt());
+  emit valueAsStringChanged(this->valueAsString());
+}
+

+ 40 - 17
Libs/Core/ctkComplementMapper.h

@@ -18,26 +18,27 @@
 
 =========================================================================*/
 
-#ifndef __ctkComplementMapper_h
-#define __ctkComplementMapper_h
+#ifndef __ctkBooleanMapper_h
+#define __ctkBooleanMapper_h
 
 // Qt includes
 #include <QObject>
+#include <QVariant>
 
 // CTK includes
 #include "ctkCoreExport.h"
-class ctkComplementMapperPrivate;
+class ctkBooleanMapperPrivate;
 
 //---------------------------------------------------------------------------
 /// \ingroup Core
 /// QCheckBox* checkBox = new QCheckBox;
-/// ctkComplementMapper* inverter =
-///   new ctkComplementMapper("checked", SIGNAL("toggled(bool)"), checkBox);
+/// ctkBooleanMapper* inverter =
+///   new ctkBooleanMapper("checked", SIGNAL("toggled(bool)"), checkBox);
 /// inverter->setComplementValue(true);
 /// // -> checkBox->checked() == false
 /// inverter->setValue(false);
 /// // -> checkBox->checked() == false
-class CTK_CORE_EXPORT ctkComplementMapper : public QObject
+class CTK_CORE_EXPORT ctkBooleanMapper : public QObject
 {
   Q_OBJECT
   /// This property contains the name of the object mapped property.
@@ -45,20 +46,28 @@ class CTK_CORE_EXPORT ctkComplementMapper : public QObject
 
   /// This property holds the mapped property.
   /// It is the value of the mapped object property
-  Q_PROPERTY(bool value READ value WRITE setValue NOTIFY valueComplementChanged STORED false);
+  Q_PROPERTY(bool value READ value WRITE setValue NOTIFY complementChanged STORED false);
 
   /// This property is the complement of the mapped property.
   /// false if \a value is true and true if \a value is false
-  Q_PROPERTY(bool valueComplement READ valueComplement WRITE setValueComplement NOTIFY valueComplementChanged STORED false)
+  Q_PROPERTY(bool complement READ complement WRITE setComplement NOTIFY complementChanged STORED false)
 
+  Q_PROPERTY(int valueAsInt READ valueAsInt WRITE setValueAsInt NOTIFY valueAsIntChanged STORED false )
+  Q_PROPERTY(QString valueAsString READ valueAsString WRITE setValueAsString NOTIFY valueAsStringChanged STORED false )
+
+  /// 1 by default
+  Q_PROPERTY(QVariant trueValue READ trueValue WRITE setTrueValue )
+
+  /// 0 by default
+  Q_PROPERTY(QVariant falseValue READ falseValue WRITE setFalseValue )
 public:
   /// Map the property \a property of the object.
   /// The mapper becomes a child of \a object and will be destructed when
   /// \a object is destructed.
   /// property and object must be valid and non empty. If signal is 0,
-  /// \a valueChanged(bool) and \a valueComplementChanged(bool) won't be fired.
-  ctkComplementMapper(QObject* targetObject, const QByteArray& propertyName, const char* signal);
-  virtual ~ctkComplementMapper();
+  /// \a valueChanged(bool) and \a complementChanged(bool) won't be fired.
+  ctkBooleanMapper(QObject* targetObject, const QByteArray& propertyName, const char* signal);
+  virtual ~ctkBooleanMapper();
 
   QByteArray propertyName()const;
 
@@ -66,26 +75,40 @@ public:
   QObject* targetObject()const;
 
   bool value()const;
-  bool valueComplement()const;
+  bool complement()const;
+  int valueAsInt()const;
+  QString valueAsString()const;
+
+  QVariant trueValue()const;
+  QVariant falseValue()const;
+
+  void setTrueValue(const QVariant& value);
+  void setFalseValue(const QVariant& value);
 
 public Q_SLOTS:
   void setValue(bool value);
-  void setValueComplement(bool valueComplement);
+  void setComplement(bool complement);
+  void setValueAsInt(int value);
+  void setValueAsString(const QString& value);
 
   void toggle();
 
 Q_SIGNALS:
   void valueChanged(bool value);
-  void valueComplementChanged(bool valueComplement);
+  void complementChanged(bool complement);
+  void valueAsIntChanged(int value);
+  void valueAsStringChanged(const QString& value);
 
 protected Q_SLOTS:
   void emitValueChanged();
+  void emitValueAsChanged();
+
 protected:
-  QScopedPointer<ctkComplementMapperPrivate> d_ptr;
+  QScopedPointer<ctkBooleanMapperPrivate> d_ptr;
 
 private:
-  Q_DECLARE_PRIVATE(ctkComplementMapper);
-  Q_DISABLE_COPY(ctkComplementMapper);
+  Q_DECLARE_PRIVATE(ctkBooleanMapper);
+  Q_DISABLE_COPY(ctkBooleanMapper);
 };
 
 #endif

+ 0 - 107
Libs/Core/ctkComplementMapper.cpp

@@ -1,107 +0,0 @@
-/*=========================================================================
-
-  Library:   CTK
-
-  Copyright (c) Kitware Inc.
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0.txt
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-
-=========================================================================*/
-
-// Qt includes
-#include <QVariant>
-
-// CTK includes
-#include "ctkComplementMapper.h"
-
-//-----------------------------------------------------------------------------
-class ctkComplementMapperPrivate
-{
-public:
-  QByteArray PropertyName;
-};
-
-// --------------------------------------------------------------------------
-// ctkComplementMapper methods
-
-// --------------------------------------------------------------------------
-ctkComplementMapper::ctkComplementMapper(
-  QObject* targetObject, const QByteArray& property, const char* signal)
-  : QObject(targetObject)
-  , d_ptr(new ctkComplementMapperPrivate)
-{
-  Q_ASSERT(property.isEmpty() != true);
-  Q_ASSERT(targetObject != 0);
-  Q_D(ctkComplementMapper);
-  d->PropertyName = property;
-  if (signal)
-    {
-    connect(targetObject, signal, this, SLOT(emitValueChanged()));
-    }
-}
-
-// --------------------------------------------------------------------------
-ctkComplementMapper::~ctkComplementMapper()
-{
-}
-
-// --------------------------------------------------------------------------
-QByteArray ctkComplementMapper::propertyName()const
-{
-  Q_D(const ctkComplementMapper);
-  return d->PropertyName;
-}
-
-// --------------------------------------------------------------------------
-QObject* ctkComplementMapper::targetObject()const
-{
-  return this->parent();
-}
-
-// --------------------------------------------------------------------------
-bool ctkComplementMapper::value()const
-{
-  return this->targetObject()->property(this->propertyName()).toBool();
-}
-
-// --------------------------------------------------------------------------
-bool ctkComplementMapper::valueComplement()const
-{
-  return !this->value();
-}
-
-// --------------------------------------------------------------------------
-void ctkComplementMapper::setValue(bool value)
-{
-  this->targetObject()->setProperty(this->propertyName(), QVariant(value));
-}
-
-// --------------------------------------------------------------------------
-void ctkComplementMapper::setValueComplement(bool value)
-{
-  this->setValue(!value);
-}
-
-// --------------------------------------------------------------------------
-void ctkComplementMapper::toggle()
-{
-  this->setValue(this->valueComplement());
-}
-
-// --------------------------------------------------------------------------
-void ctkComplementMapper::emitValueChanged()
-{
-  emit valueChanged(this->value());
-  emit valueComplementChanged(this->valueComplement());
-}
-

+ 4 - 4
Libs/Widgets/Testing/Cpp/ctkSettingsPanelTest1.cpp

@@ -27,7 +27,7 @@
 #include <QVariant>
 
 // CTK includes
-#include "ctkComplementMapper.h"
+#include "ctkBooleanMapper.h"
 #include "ctkSettingsPanel.h"
 
 // STD includes
@@ -240,9 +240,9 @@ int ctkSettingsPanelTest1(int argc, char * argv [] )
 
   box->setChecked(false);
   settingsPanel.registerProperty("key complement",
-                                 new ctkComplementMapper(box, "checked", SIGNAL(toggled(bool))),
-                                 "valueComplement",
-                                  SIGNAL(valueComplementChanged(bool)));
+                                 new ctkBooleanMapper(box, "checked", SIGNAL(toggled(bool))),
+                                 "complement",
+                                  SIGNAL(complementChanged(bool)));
 
   // Check settings value after a property is registered
   boxVal = settings.value("key complement");

+ 4 - 4
Libs/Widgets/ctkSettingsPanel.h

@@ -56,13 +56,13 @@ public:
   /// The current value of the property is later used when
   /// restoreDefaultSettings() is called.
   /// If you want to register the logical complement of a boolean property
-  /// you can use ctkComplementMapper:
+  /// you can use ctkBooleanMapper:
   /// <code>
   /// panel->registerProperty("unchecked",
-  ///                         new ctkComplementMapper(checkBox, "checked", SIGNAL(toggled(bool))),
-  ///                         "valueComplement", SIGNAL(valueComplementChanged(bool)));
+  ///                         new ctkBooleanMapper(checkBox, "checked", SIGNAL(toggled(bool))),
+  ///                         "complement", SIGNAL(complementChanged(bool)));
   /// </code>
-  /// \sa Q_PROPERTY(), \sa ctkComplementMapper
+  /// \sa Q_PROPERTY(), \sa ctkBooleanMapper
   void registerProperty(const QString& key,
                         QObject* object,
                         const QString& property,