Преглед изворни кода

ctkSettings - Properly handle empty QStringList

The method Property::setValue was checking the return value of QObject::setProperty.
Nevertheless, if an empty QStringList is stored in the settings and read back,
 the associated QVariant will be invalid.

In that specific case, if the type of the associated property is QStringList
and it the value to set is Invalid, we ensure an empty QStringList is set.

A QtBug has also been reported. See http://bugreports.qt.nokia.com/browse/QTBUG-19823
Jean-Christophe Fillion-Robin пре 14 година
родитељ
комит
866f87e35b
2 измењених фајлова са 40 додато и 6 уклоњено
  1. 5 0
      Libs/Widgets/Testing/Cpp/CMakeLists.txt
  2. 35 6
      Libs/Widgets/ctkSettingsPanel.cpp

+ 5 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -48,6 +48,7 @@ SET(TEST_SOURCES
   ctkDateRangeWidgetTest1.cpp
   ctkScreenshotDialogTest1.cpp
   ctkSettingsPanelTest1.cpp
+  ctkSettingsPanelTest2.cpp
   ctkSettingsTest1.cpp
   ctkSettingsDialogTest1.cpp
   ctkSliderWidgetTest1.cpp
@@ -82,11 +83,14 @@ SET(Tests_SRCS
   ctkExampleDerivedWorkflowWidgetStep.h
   ctkExampleWorkflowWidgetStepUsingSignalsAndSlots.cpp
   ctkExampleWorkflowWidgetStepUsingSignalsAndSlots.h
+  ctkSettingsPanelTest2Helper.cpp
+  ctkSettingsPanelTest2Helper.h
   )
 
 SET(Tests_MOC_SRCS
   ctkExampleDerivedWorkflowWidgetStep.h
   ctkExampleWorkflowWidgetStepUsingSignalsAndSlots.h
+  ctkSettingsPanelTest2Helper.h
   )
 
 SET(Tests_MOC_CPP)
@@ -159,6 +163,7 @@ SIMPLE_TEST( ctkRangeWidgetTest2 )
 SIMPLE_TEST( ctkScreenshotDialogTest1 )
 SIMPLE_TEST( ctkSettingsDialogTest1 )
 SIMPLE_TEST( ctkSettingsPanelTest1 )
+SIMPLE_TEST( ctkSettingsPanelTest2 )
 SIMPLE_TEST( ctkSettingsTest1 )
 SIMPLE_TEST( ctkSliderWidgetTest1 )
 SIMPLE_TEST( ctkToolTipTrapperTest1 )

+ 35 - 6
Libs/Widgets/ctkSettingsPanel.cpp

@@ -20,6 +20,7 @@
 
 // Qt includes
 #include <QDebug>
+#include <QMetaProperty>
 #include <QSettings>
 #include <QSignalMapper>
 
@@ -29,6 +30,10 @@
 
 static ctkLogger logger("org.commontk.libs.widgets.ctkSettingsPanel");
 
+namespace
+{
+
+// --------------------------------------------------------------------------
 struct PropertyType
 {
   PropertyType();
@@ -39,6 +44,8 @@ struct PropertyType
 
   QVariant value()const;
   bool setValue(const QVariant& value);
+
+  QMetaProperty metaProperty();
 };
 
 // --------------------------------------------------------------------------
@@ -66,10 +73,34 @@ bool PropertyType::setValue(const QVariant& val)
     Q_ASSERT(this->Object && !this->Property.isEmpty());
     return false;
     }
-  // the following returns true if the property has been added using Q_PROPERTY
-  // false otherwise (and the property is then a dynamic property)
-  return this->Object->setProperty(this->Property.toLatin1(), val);
+  QVariant value(val);
+  // HACK - See http://bugreports.qt.nokia.com/browse/QTBUG-19823
+  if (qstrcmp(this->metaProperty().typeName(), "QStringList") == 0 && !value.isValid())
+    {
+    value = QVariant(QStringList());
+    }
+  bool success = this->Object->setProperty(this->Property.toLatin1(), value);
+  Q_ASSERT(success);
+  return success;
+}
+
+// --------------------------------------------------------------------------
+QMetaProperty PropertyType::metaProperty()
+{
+  Q_ASSERT(this->Object);
+  for(int i=0; i < this->Object->metaObject()->propertyCount(); ++i)
+    {
+    this->Object->metaObject()->property(i);
+    if (this->Object->metaObject()->property(i).name() == this->Property)
+      {
+      return this->Object->metaObject()->property(i);
+      }
+    }
+  return QMetaProperty();
 }
+
+} // end of anonymous namespace
+
 //-----------------------------------------------------------------------------
 class ctkSettingsPanelPrivate
 {
@@ -155,9 +186,7 @@ void ctkSettingsPanel::updateProperties()
       QVariant value = d->Settings->value(key);
       PropertyType& prop = d->Properties[key];
       // Update object registered using registerProperty()
-      bool res = prop.setValue(value);
-      Q_ASSERT(res);
-      Q_UNUSED(res);
+      prop.setValue(value);
       prop.PreviousValue = value;
       }
     else