mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
1503 lines
46 KiB
C++
1503 lines
46 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
#include "vtkSMSettings.h"
|
|
|
|
#include "vtkMultiProcessController.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkProcessModule.h"
|
|
#include "vtkPVXMLElement.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkSMDoubleVectorProperty.h"
|
|
#include "vtkSMEnumerationDomain.h"
|
|
#include "vtkSMIdTypeVectorProperty.h"
|
|
#include "vtkSMInputProperty.h"
|
|
#include "vtkSMIntVectorProperty.h"
|
|
#include "vtkSMProperty.h"
|
|
#include "vtkSMPropertyIterator.h"
|
|
#include "vtkSMProxy.h"
|
|
#include "vtkSMProxyListDomain.h"
|
|
#include "vtkSMStringVectorProperty.h"
|
|
#include "vtkStringList.h"
|
|
|
|
#include <sstream>
|
|
#include <vtksys/SystemTools.hxx>
|
|
#include "vtk_jsoncpp.h"
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <cfloat>
|
|
|
|
#define vtkSMSettingsDebugMacro(x)\
|
|
{ if (vtksys::SystemTools::GetEnv("PV_SETTINGS_DEBUG")) { \
|
|
std::ostringstream vtkerror; \
|
|
vtkerror << x << endl; \
|
|
vtkOutputWindowDisplayText(vtkerror.str().c_str());} }
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
namespace {
|
|
class SettingsCollection {
|
|
public:
|
|
Json::Value Value;
|
|
double Priority;
|
|
};
|
|
|
|
bool SortByPriority(const SettingsCollection & r1,
|
|
const SettingsCollection & r2)
|
|
{
|
|
return (r1.Priority > r2.Priority);
|
|
}
|
|
|
|
} // end anonymous namespace
|
|
|
|
class vtkSMSettings::vtkSMSettingsInternal {
|
|
public:
|
|
std::vector< SettingsCollection > SettingCollections;
|
|
bool SettingCollectionsAreSorted;
|
|
bool IsModified;
|
|
|
|
void Modified()
|
|
{
|
|
this->IsModified = true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Sort setting collections by priority, from highest to lowest
|
|
void SortSettingCollections()
|
|
{
|
|
// Sort the settings roots by priority (highest to lowest)
|
|
std::stable_sort(this->SettingCollections.begin(), this->SettingCollections.end(), SortByPriority);
|
|
this->SettingCollectionsAreSorted = true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Splits a JSON path into branch and leaf components. This is needed
|
|
// to build trees with the JsonCpp library.
|
|
static void SeparateBranchFromLeaf(const char* jsonPath, std::string & root, std::string & leaf)
|
|
{
|
|
root.clear();
|
|
leaf.clear();
|
|
|
|
// Chop off leaf setting
|
|
std::string jsonPathString(jsonPath);
|
|
size_t lastPeriod = jsonPathString.find_last_of('.');
|
|
root = jsonPathString.substr(0, lastPeriod);
|
|
leaf = jsonPathString.substr(lastPeriod+1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// See if given setting is defined
|
|
bool HasSetting(const char* settingName)
|
|
{
|
|
Json::Value value = this->GetSetting(settingName);
|
|
|
|
return !value.isNull();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description: Get a Json::Value given a setting name. Returns the
|
|
// highest-priority setting defined in the setting collections, and
|
|
// null if it isn't defined in any of the collections.
|
|
//
|
|
// String format is:
|
|
// "." => root node
|
|
// ".[n]" => elements at index 'n' of root node (an array value)
|
|
// ".name" => member named 'name' of root node (an object value)
|
|
// ".name1.name2.name3"
|
|
// ".[0][1][2].name1[3]"
|
|
const Json::Value & GetSetting(const char* settingName)
|
|
{
|
|
return this->GetSettingAtOrBelowPriority(settingName, VTK_DOUBLE_MAX);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const Json::Value & GetSettingBelowPriority(const char* settingName, double priority)
|
|
{
|
|
this->SortCollectionsIfNeeded();
|
|
|
|
// Iterate over settings, checking higher priority settings first
|
|
for (size_t i = 0; i < this->SettingCollections.size(); ++i)
|
|
{
|
|
if (this->SettingCollections[i].Priority >= priority)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Json::Path settingPath(settingName);
|
|
const Json::Value & setting = settingPath.resolve(this->SettingCollections[i].Value);
|
|
if (!setting.isNull())
|
|
{
|
|
return setting;
|
|
}
|
|
}
|
|
|
|
return Json::Value::nullRef;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const Json::Value & GetSettingAtOrBelowPriority(const char* settingName, double priority)
|
|
{
|
|
this->SortCollectionsIfNeeded();
|
|
|
|
// Iterate over settings, checking higher priority settings first
|
|
for (size_t i = 0; i < this->SettingCollections.size(); ++i)
|
|
{
|
|
if (this->SettingCollections[i].Priority > priority)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Json::Path settingPath(settingName);
|
|
const Json::Value & setting = settingPath.resolve(this->SettingCollections[i].Value);
|
|
if (!setting.isNull())
|
|
{
|
|
return setting;
|
|
}
|
|
}
|
|
|
|
return Json::Value::nullRef;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template< typename T >
|
|
bool GetSetting(const char* settingName, std::vector<T> & values)
|
|
{
|
|
values.clear();
|
|
|
|
Json::Value setting = this->GetSetting(settingName);
|
|
if (!setting)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (setting.isObject())
|
|
{
|
|
return false;
|
|
}
|
|
else if (setting.isArray())
|
|
{
|
|
for (Json::Value::ArrayIndex i = 0; i < setting.size(); ++i)
|
|
{
|
|
T value;
|
|
this->ConvertJsonValue(setting[i], value);
|
|
values.push_back(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
T value;
|
|
bool success = this->ConvertJsonValue(setting, value);
|
|
if (success)
|
|
{
|
|
values.push_back(value);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool GetPropertySetting(const char* settingName,
|
|
vtkSMIntVectorProperty* property)
|
|
{
|
|
if (!property)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
vtkSMDomain* domain = property->FindDomain("vtkSMEnumerationDomain");
|
|
vtkSMEnumerationDomain* enumDomain = vtkSMEnumerationDomain::SafeDownCast(domain);
|
|
if (enumDomain)
|
|
{
|
|
// The enumeration property could be either text or value
|
|
const Json::Value & jsonValue = this->GetSetting(settingName);
|
|
int enumValue;
|
|
bool hasInt = this->ConvertJsonValue(jsonValue, enumValue);
|
|
if (hasInt)
|
|
{
|
|
property->SetElement(0, enumValue);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
std::string stringValue;
|
|
bool hasString = this->ConvertJsonValue(jsonValue, stringValue);
|
|
if (hasString && enumDomain->HasEntryText(stringValue.c_str()))
|
|
{
|
|
enumValue = enumDomain->GetEntryValueForText(stringValue.c_str());
|
|
property->SetElement(0, enumValue);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
std::vector<int> vector;
|
|
if (!this->GetSetting(settingName, vector) ||
|
|
vector.size() != property->GetNumberOfElements())
|
|
{
|
|
return false;
|
|
}
|
|
if (property->GetRepeatable())
|
|
{
|
|
property->SetNumberOfElements(static_cast<unsigned int>(vector.size()));
|
|
}
|
|
|
|
property->SetElements(&vector[0]);
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool GetPropertySetting(const char* settingName,
|
|
vtkSMDoubleVectorProperty* property)
|
|
{
|
|
std::vector<double> vector;
|
|
if (!property || !this->GetSetting(settingName, vector))
|
|
{
|
|
return false;
|
|
}
|
|
else if (property->GetRepeatable())
|
|
{
|
|
property->SetNumberOfElements(static_cast<unsigned int>(vector.size()));
|
|
}
|
|
else if (vector.size() != property->GetNumberOfElements())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
property->SetElements(&vector[0]);
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool GetPropertySetting(const char* settingName,
|
|
vtkSMStringVectorProperty* property)
|
|
{
|
|
std::vector<std::string> vector;
|
|
if (!property || !this->GetSetting(settingName, vector))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
vtkSmartPointer<vtkStringList> stringList = vtkSmartPointer<vtkStringList>::New();
|
|
for (size_t i = 0; i < vector.size(); ++i)
|
|
{
|
|
vtkStdString vtk_string(vector[i]);
|
|
stringList->AddString(vtk_string);
|
|
}
|
|
|
|
if (property->GetRepeatable())
|
|
{
|
|
property->SetNumberOfElements(static_cast<unsigned int>(vector.size()));
|
|
}
|
|
else if (vector.size() != property->GetNumberOfElements())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
property->SetElements(stringList);
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool GetPropertySetting(const char* settingName, vtkSMInputProperty* property)
|
|
{
|
|
vtkSMDomain * domain = property->GetDomain( "proxy_list" );
|
|
vtkSMProxyListDomain * proxyListDomain = NULL;
|
|
if ((proxyListDomain = vtkSMProxyListDomain::SafeDownCast(domain)))
|
|
{
|
|
// Now check whether this proxy is the one we want
|
|
std::string sourceSettingString(settingName);
|
|
sourceSettingString.append(".Selected");
|
|
|
|
std::string sourceName;
|
|
if (this->HasSetting(sourceSettingString.c_str()))
|
|
{
|
|
std::vector<std::string> selectedString;
|
|
this->GetSetting(sourceSettingString.c_str(), selectedString);
|
|
if (selectedString.size() > 0)
|
|
{
|
|
sourceName = selectedString[0];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (unsigned int ip = 0; ip < proxyListDomain->GetNumberOfProxies(); ++ip)
|
|
{
|
|
vtkSMProxy* listProxy = proxyListDomain->GetProxy(ip);
|
|
if (listProxy)
|
|
{
|
|
// Recurse on the proxy
|
|
bool success = this->GetProxySettings(settingName, listProxy);
|
|
if (!success)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Now check whether it was selected
|
|
if (listProxy->GetXMLName() == sourceName)
|
|
{
|
|
// \TODO - probably not exactly what we need to do
|
|
property->SetInputConnection(0, listProxy, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool GetProxySettings(const char* settingPrefix, vtkSMProxy* proxy)
|
|
{
|
|
if (!proxy)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool overallSuccess = true;
|
|
|
|
vtkSMPropertyIterator * iter = proxy->NewPropertyIterator();
|
|
for (iter->Begin(); !iter->IsAtEnd(); iter->Next())
|
|
{
|
|
vtkSMProperty* property = iter->GetProperty();
|
|
if (!property)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Check to see if we save only to QSettings or to both QSettings
|
|
// and the JSON file.
|
|
if (property->GetHints())
|
|
{
|
|
vtkPVXMLElement* saveInQSettingsHint = property->GetHints()->FindNestedElementByName("SaveInQSettings");
|
|
if (saveInQSettingsHint)
|
|
{
|
|
int bothSettings = 0;
|
|
saveInQSettingsHint->GetScalarAttribute("both", &bothSettings);
|
|
if (!bothSettings)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char* proxyName = proxy->GetXMLName();
|
|
const char* propertyName = iter->GetKey();
|
|
if (proxyName &&
|
|
propertyName &&
|
|
!property->GetNoCustomDefault())
|
|
{
|
|
// Build the JSON reference string
|
|
std::ostringstream settingStringStream;
|
|
settingStringStream << settingPrefix
|
|
<< "." << proxyName
|
|
<< "." << propertyName;
|
|
|
|
const std::string settingString = settingStringStream.str();
|
|
const char* settingName = settingString.c_str();
|
|
if (this->HasSetting(settingName))
|
|
{
|
|
bool success = false;
|
|
if (vtkSMIntVectorProperty* intVectorProperty =
|
|
vtkSMIntVectorProperty::SafeDownCast(property))
|
|
{
|
|
success = this->GetPropertySetting(settingName, intVectorProperty);
|
|
}
|
|
else if (vtkSMDoubleVectorProperty* doubleVectorProperty =
|
|
vtkSMDoubleVectorProperty::SafeDownCast(property))
|
|
{
|
|
success = this->GetPropertySetting(settingName, doubleVectorProperty);
|
|
}
|
|
else if (vtkSMStringVectorProperty* stringVectorProperty =
|
|
vtkSMStringVectorProperty::SafeDownCast(property))
|
|
{
|
|
success = this->GetPropertySetting(settingName, stringVectorProperty);
|
|
}
|
|
else if (vtkSMInputProperty* inputProperty =
|
|
vtkSMInputProperty::SafeDownCast(property))
|
|
{
|
|
success = this->GetPropertySetting(settingName, inputProperty);
|
|
}
|
|
else
|
|
{
|
|
overallSuccess = false;
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
overallSuccess = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
iter->Delete();
|
|
|
|
return overallSuccess;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template< typename T >
|
|
void SetSetting(const char* settingName, const std::vector< T > & values)
|
|
{
|
|
this->CreateCollectionIfNeeded();
|
|
this->SortCollectionsIfNeeded();
|
|
|
|
// Just set settings in the highest-priority settings group for now.
|
|
std::string root, leaf;
|
|
this->SeparateBranchFromLeaf(settingName, root, leaf);
|
|
|
|
std::vector< T > previousValues;
|
|
this->GetSetting(settingName, previousValues);
|
|
|
|
Json::Path settingPath(root.c_str());
|
|
Json::Value & jsonValue = settingPath.make(this->SettingCollections[0].Value);
|
|
jsonValue[leaf] = Json::Value::nullRef;
|
|
|
|
if (values.size() > 1)
|
|
{
|
|
jsonValue[leaf].resize(
|
|
static_cast<Json::Value::ArrayIndex>(values.size()));
|
|
|
|
for (size_t i = 0; i < values.size(); ++i)
|
|
{
|
|
if (i >= previousValues.size() || previousValues[i] != values[i])
|
|
{
|
|
this->Modified();
|
|
}
|
|
jsonValue[leaf][static_cast<Json::Value::ArrayIndex>(i)] = values[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (previousValues.size() < 1 || previousValues[0] != values[0])
|
|
{
|
|
jsonValue[leaf] = values[0];
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool SetPropertySetting(const char* settingName,
|
|
vtkSMIntVectorProperty* property)
|
|
{
|
|
Json::Path valuePath(settingName);
|
|
Json::Value & jsonValue = valuePath.make(this->SettingCollections[0].Value);
|
|
if (property->GetNumberOfElements() == 1)
|
|
{
|
|
if (jsonValue.isArray())
|
|
{
|
|
// Reset to null so that we aren't setting a value on a Json::Value array
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
if (jsonValue.isNull() || jsonValue.asInt() != property->GetElement(0))
|
|
{
|
|
jsonValue = property->GetElement(0);
|
|
this->Modified();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!jsonValue.isArray() && !jsonValue.isNull())
|
|
{
|
|
// Reset to null so that the jsonValue.resize() operation works
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
jsonValue.resize(property->GetNumberOfElements());
|
|
for (unsigned int i = 0; i < property->GetNumberOfElements(); ++i)
|
|
{
|
|
if (jsonValue[i].isNull() || jsonValue[i].asInt() != property->GetElement(i))
|
|
{
|
|
jsonValue[i] = property->GetElement(i);
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool SetPropertySetting(const char* settingName,
|
|
vtkSMDoubleVectorProperty* property)
|
|
{
|
|
Json::Path valuePath(settingName);
|
|
Json::Value & jsonValue = valuePath.make(this->SettingCollections[0].Value);
|
|
if (property->GetNumberOfElements() == 1)
|
|
{
|
|
if (jsonValue.isArray())
|
|
{
|
|
// Reset to null so that we aren't setting a value on a Json::Value array
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
if (jsonValue.isNull() || jsonValue.asDouble() != property->GetElement(0))
|
|
{
|
|
jsonValue = property->GetElement(0);
|
|
this->Modified();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!jsonValue.isArray() && !jsonValue.isNull())
|
|
{
|
|
// Reset to null so that the jsonValue.resize() operation works
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
jsonValue.resize(property->GetNumberOfElements());
|
|
for (unsigned int i = 0; i < property->GetNumberOfElements(); ++i)
|
|
{
|
|
if (jsonValue[i].isNull() || jsonValue[i].asDouble() != property->GetElement(i))
|
|
{
|
|
jsonValue[i] = property->GetElement(i);
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool SetPropertySetting(const char* settingName,
|
|
vtkSMStringVectorProperty* property)
|
|
{
|
|
Json::Path valuePath(settingName);
|
|
Json::Value & jsonValue = valuePath.make(this->SettingCollections[0].Value);
|
|
if (property->GetNumberOfElements() == 1)
|
|
{
|
|
if (jsonValue.isArray())
|
|
{
|
|
// Reset to null so that we aren't setting a value on a Json::Value array
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
if (jsonValue.isNull() || strcmp(jsonValue.asCString(), property->GetElement(0)) != 0)
|
|
{
|
|
jsonValue = property->GetElement(0);
|
|
this->Modified();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!jsonValue.isArray() && !jsonValue.isNull())
|
|
{
|
|
// Reset to null so that the jsonValue.resize() operation works
|
|
jsonValue = Json::Value::null;
|
|
this->Modified();
|
|
}
|
|
|
|
jsonValue.resize(property->GetNumberOfElements());
|
|
for (unsigned int i = 0; i < property->GetNumberOfElements(); ++i)
|
|
{
|
|
if (jsonValue[i].isNull() || strcmp(jsonValue[i].asCString(), property->GetElement(i)) != 0)
|
|
{
|
|
jsonValue[i] = property->GetElement(i);
|
|
this->Modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Set a property setting in the highest-priority collection.
|
|
bool SetPropertySetting(const char* settingName, vtkSMProperty* property)
|
|
{
|
|
this->CreateCollectionIfNeeded();
|
|
this->SortCollectionsIfNeeded();
|
|
|
|
if (vtkSMIntVectorProperty* intVectorProperty =
|
|
vtkSMIntVectorProperty::SafeDownCast(property))
|
|
{
|
|
return this->SetPropertySetting(settingName, intVectorProperty);
|
|
}
|
|
else if (vtkSMDoubleVectorProperty* doubleVectorProperty =
|
|
vtkSMDoubleVectorProperty::SafeDownCast(property))
|
|
{
|
|
return this->SetPropertySetting(settingName, doubleVectorProperty);
|
|
}
|
|
else if (vtkSMStringVectorProperty* stringVectorProperty =
|
|
vtkSMStringVectorProperty::SafeDownCast(property))
|
|
{
|
|
return this->SetPropertySetting(settingName, stringVectorProperty);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Set proxy settings to the highest-priority collection.
|
|
bool SetProxySettings(vtkSMProxy* proxy,
|
|
vtkSMPropertyIterator* propertyIt,
|
|
bool skipPropertiesWithDynamicDomains)
|
|
{
|
|
if (!proxy)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string jsonPrefix(".");
|
|
jsonPrefix.append(proxy->GetXMLGroup());
|
|
|
|
return this->SetProxySettings(jsonPrefix.c_str(), proxy, propertyIt,
|
|
skipPropertiesWithDynamicDomains);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Set proxy settings in the highest-priority collection under
|
|
// the setting prefix.
|
|
bool SetProxySettings(const char* settingPrefix, vtkSMProxy* proxy,
|
|
vtkSMPropertyIterator* propertyIt,
|
|
bool skipPropertiesWithDynamicDomains)
|
|
{
|
|
if (!proxy)
|
|
{
|
|
return false;
|
|
}
|
|
this->CreateCollectionIfNeeded();
|
|
this->SortCollectionsIfNeeded();
|
|
|
|
double highestPriority = this->SettingCollections[0].Priority;
|
|
|
|
// Get reference to JSON value
|
|
const char* proxyName = proxy->GetXMLName();
|
|
std::ostringstream settingStringStream;
|
|
settingStringStream << settingPrefix << "." << proxyName;
|
|
std::string settingString(settingStringStream.str());
|
|
const char* settingCString = settingString.c_str();
|
|
|
|
Json::Path valuePath(settingCString);
|
|
Json::Value & proxyValue = valuePath.make(this->SettingCollections[0].Value);
|
|
|
|
bool propertySet = false;
|
|
vtkSmartPointer<vtkSMPropertyIterator> iter;
|
|
if (propertyIt)
|
|
{
|
|
iter = propertyIt;
|
|
}
|
|
else
|
|
{
|
|
iter.TakeReference(proxy->NewPropertyIterator());
|
|
}
|
|
for (iter->Begin(); !iter->IsAtEnd(); iter->Next())
|
|
{
|
|
vtkSMProperty* property = iter->GetProperty();
|
|
if (!property) continue;
|
|
|
|
// Check to see if we save only to QSettings or to both QSettings
|
|
// and the JSON file.
|
|
if (property->GetHints())
|
|
{
|
|
vtkPVXMLElement* saveInQSettingsHint = property->GetHints()->FindNestedElementByName("SaveInQSettings");
|
|
if (saveInQSettingsHint)
|
|
{
|
|
int bothSettings = 0;
|
|
saveInQSettingsHint->GetScalarAttribute("both", &bothSettings);
|
|
if (!bothSettings)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char* propertyName = iter->GetKey();
|
|
std::ostringstream propertySettingStringStream;
|
|
propertySettingStringStream << settingStringStream.str() << "."
|
|
<< propertyName;
|
|
std::string propertySettingString(propertySettingStringStream.str());
|
|
const char* propertySettingCString = propertySettingString.c_str();
|
|
|
|
if (strcmp(property->GetPanelVisibility(), "never") == 0 ||
|
|
property->GetInformationOnly() ||
|
|
property->GetIsInternal() ||
|
|
property->GetNoCustomDefault())
|
|
{
|
|
continue;
|
|
}
|
|
else if (skipPropertiesWithDynamicDomains &&
|
|
property->HasDomainsWithRequiredProperties())
|
|
{
|
|
// skip properties that have domains that change at runtime. Such
|
|
// properties are typically serialized in state files not in settings.
|
|
continue;
|
|
}
|
|
else if (property->IsValueDefault())
|
|
{
|
|
// Remove existing JSON entry only if there is no
|
|
// lower-priority setting. That's because if there is a
|
|
// lower-priority setting that is not default, we want to be
|
|
// able to set the value back to the default in the higher
|
|
// priority setting collection.
|
|
const Json::Value & lowerPriorityValue = this->GetSettingBelowPriority(propertySettingCString,
|
|
highestPriority);
|
|
if (lowerPriorityValue.isNull())
|
|
{
|
|
if (!proxyValue.removeMember(property->GetXMLName()).isNull())
|
|
{
|
|
this->Modified();
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (this->SetPropertySetting(propertySettingCString, property))
|
|
{
|
|
propertySet = true;
|
|
}
|
|
}
|
|
|
|
// If no property was set, remove the proxy entry.
|
|
if (!propertySet)
|
|
{
|
|
Json::Path parentPath(settingPrefix);
|
|
Json::Value & parentValue = parentPath.make(this->SettingCollections[0].Value);
|
|
parentValue.removeMember(proxyName);
|
|
|
|
if (parentValue.empty())
|
|
{
|
|
std::string parentRoot, parentLeaf;
|
|
SeparateBranchFromLeaf(settingPrefix, parentRoot, parentLeaf);
|
|
parentRoot.append(".");
|
|
// Need special handling when parent root is "." because
|
|
// Json::Path::make() doesn't appear to handle it correctly.
|
|
if (parentRoot == ".")
|
|
{
|
|
this->SettingCollections[0].Value.removeMember(parentLeaf);
|
|
}
|
|
else
|
|
{
|
|
Json::Path parentRootPath(parentRoot);
|
|
Json::Value & parentRootValue = parentRootPath.make(this->SettingCollections[0].Value);
|
|
parentRootValue.removeMember(parentLeaf);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool ConvertJsonValue(const Json::Value & jsonValue, int & value)
|
|
{
|
|
if (!jsonValue.isNumeric())
|
|
{
|
|
return false;
|
|
}
|
|
value = jsonValue.asInt();
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool ConvertJsonValue(const Json::Value & jsonValue, double & value)
|
|
{
|
|
if (!jsonValue.isNumeric())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
value = jsonValue.asDouble();
|
|
}
|
|
catch (...)
|
|
{
|
|
vtkGenericWarningMacro(<< "Could not convert \n" << jsonValue.toStyledString());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool ConvertJsonValue(const Json::Value & jsonValue, std::string & value)
|
|
{
|
|
if (!jsonValue.isString())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
value = jsonValue.asString();
|
|
}
|
|
catch (...)
|
|
{
|
|
vtkGenericWarningMacro(<< "Could not convert \n" << jsonValue.toStyledString());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Ensure that at least one collection exists so that when settings are set,
|
|
// there is a place to store them. If a collection needs to be created, its
|
|
// priority is set to DOUBLE_MAX.
|
|
void CreateCollectionIfNeeded()
|
|
{
|
|
if (this->SettingCollections.size() == 0)
|
|
{
|
|
SettingsCollection newCollection;
|
|
newCollection.Priority = VTK_DOUBLE_MAX;
|
|
this->SettingCollections.push_back(newCollection);
|
|
this->IsModified = true;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Sort the collections if needed
|
|
void SortCollectionsIfNeeded()
|
|
{
|
|
if (!this->SettingCollectionsAreSorted)
|
|
{
|
|
this->SortSettingCollections();
|
|
this->SettingCollectionsAreSorted = true;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkStandardNewMacro(vtkSMSettings);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSMSettings::vtkSMSettings()
|
|
{
|
|
this->Internal = new vtkSMSettingsInternal();
|
|
this->Internal->SettingCollectionsAreSorted = false;
|
|
this->Internal->IsModified = false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSMSettings::~vtkSMSettings()
|
|
{
|
|
delete this->Internal;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSMSettings* vtkSMSettings::GetInstance()
|
|
{
|
|
static vtkSmartPointer<vtkSMSettings> Instance;
|
|
if (Instance.GetPointer() == NULL)
|
|
{
|
|
vtkSMSettings* settings = vtkSMSettings::New();
|
|
Instance = settings;
|
|
settings->FastDelete();
|
|
}
|
|
|
|
return Instance;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::AddCollectionFromString(const std::string & settings,
|
|
double priority)
|
|
{
|
|
SettingsCollection collection;
|
|
collection.Priority = priority;
|
|
|
|
vtkSMSettingsDebugMacro("Loading settings JSON string '" << settings << "'");
|
|
|
|
// If the settings string is empty, the JSON parser can't handle it.
|
|
// Replace the empty string with {}
|
|
std::string processedSettings(settings);
|
|
if (processedSettings == "")
|
|
{
|
|
processedSettings.append("{}");
|
|
}
|
|
|
|
// Parse the user settings
|
|
Json::Reader reader;
|
|
bool success = reader.parse(processedSettings, collection.Value, true);
|
|
if (success)
|
|
{
|
|
this->Internal->SettingCollections.push_back(collection);
|
|
this->Internal->SettingCollectionsAreSorted = false;
|
|
vtkSMSettingsDebugMacro("Successfully parsed settings string");
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro(<< "Failed to parse settings from JSON" << endl
|
|
<< processedSettings << endl);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::AddCollectionFromFile(const std::string & fileName,
|
|
double priority)
|
|
{
|
|
std::string settingsFileName(fileName);
|
|
std::ifstream settingsFile(settingsFileName.c_str(), ios::in | ios::binary | ios::ate);
|
|
vtkSMSettingsDebugMacro("Attempting to load settings file '" << fileName << "'");
|
|
if (settingsFile.is_open())
|
|
{
|
|
std::streampos size = settingsFile.tellg();
|
|
settingsFile.seekg(0, ios::beg);
|
|
int stringSize = size;
|
|
char * settingsString = new char[stringSize+1];
|
|
settingsFile.read(settingsString, stringSize);
|
|
settingsString[stringSize] = '\0';
|
|
settingsFile.close();
|
|
|
|
bool success = this->AddCollectionFromString(std::string(settingsString),
|
|
priority);
|
|
delete[] settingsString;
|
|
|
|
vtkSMSettingsDebugMacro("Loading settings file '" << fileName << "' " << (success ? "succeeded" : "failed"));
|
|
|
|
return success;
|
|
}
|
|
else
|
|
{
|
|
vtkSMSettingsDebugMacro("Could not open settings file '" << fileName << "'");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::ClearAllSettings()
|
|
{
|
|
this->Internal->SettingCollections.clear();
|
|
this->Internal->SettingCollectionsAreSorted = false;
|
|
this->Internal->IsModified = false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::DistributeSettings()
|
|
{
|
|
vtkProcessModule *pm = vtkProcessModule::GetProcessModule();
|
|
if (pm->GetProcessType() == vtkProcessModule::PROCESS_BATCH &&
|
|
pm->GetSymmetricMPIMode() &&
|
|
(pm->GetNumberOfLocalPartitions() > 1))
|
|
{
|
|
// Broadcast settings to satellite nodes
|
|
vtkMultiProcessController * controller = pm->GetGlobalController();
|
|
|
|
unsigned int numberOfSettingCollections;
|
|
if (controller->GetLocalProcessId() == 0)
|
|
{
|
|
// Send the number of JSON settings roots
|
|
numberOfSettingCollections = static_cast<unsigned int>(this->Internal->SettingCollections.size());
|
|
controller->Broadcast(&numberOfSettingCollections, 1, 0);
|
|
|
|
for (size_t i = 0; i < numberOfSettingCollections; ++i)
|
|
{
|
|
std::string settingsString = this->Internal->SettingCollections[i].Value.toStyledString();
|
|
unsigned int stringSize = static_cast<unsigned int>(settingsString.size())+1;
|
|
controller->Broadcast(&stringSize, 1, 0);
|
|
if (stringSize > 0)
|
|
{
|
|
controller->Broadcast(const_cast<char*>(settingsString.c_str()), stringSize, 0);
|
|
controller->Broadcast(&this->Internal->SettingCollections[i].Priority, 1, 0);
|
|
}
|
|
}
|
|
}
|
|
else // Satellites
|
|
{
|
|
// Get the number of JSON settings roots
|
|
controller->Broadcast(&numberOfSettingCollections, 1, 0);
|
|
|
|
for (unsigned int i = 0; i < numberOfSettingCollections; ++i)
|
|
{
|
|
unsigned int stringSize = 0;
|
|
controller->Broadcast(&stringSize, 1, 0);
|
|
if (stringSize > 0)
|
|
{
|
|
char* settingsString = new char[stringSize];
|
|
controller->Broadcast(settingsString, stringSize, 0);
|
|
double priority = 0.0;
|
|
controller->Broadcast(&priority, 1, 0);
|
|
this->AddCollectionFromString(std::string(settingsString), priority);
|
|
delete[] settingsString;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::SaveSettingsToFile(const std::string & filePath)
|
|
{
|
|
if (this->Internal->SettingCollections.size() == 0 ||
|
|
!this->Internal->IsModified)
|
|
{
|
|
// No settings to save, so we'll always succeed.
|
|
vtkSMSettingsDebugMacro("No settings to save");
|
|
return true;
|
|
}
|
|
|
|
// Get directory component of filePath and create it if it doesn't exist.
|
|
std::string directory =
|
|
vtksys::SystemTools::GetParentDirectory(filePath.c_str());
|
|
bool createdDirectory = vtksys::SystemTools::MakeDirectory(directory.c_str());
|
|
if (!createdDirectory)
|
|
{
|
|
vtkErrorMacro(<< "Directory '" << directory << "' does not exist and could "
|
|
<< "not be created.");
|
|
return false;
|
|
}
|
|
|
|
vtkSMSettingsDebugMacro("Opening settings file '" << filePath << "' for writing");
|
|
std::ofstream settingsFile(filePath.c_str(), ios::out | ios::binary );
|
|
if (settingsFile.is_open())
|
|
{
|
|
std::string output = this->Internal->SettingCollections[0].Value.toStyledString();
|
|
settingsFile << output;
|
|
|
|
this->Internal->IsModified = false;
|
|
|
|
vtkSMSettingsDebugMacro("Succeeded writing settings file '" << filePath << "'");
|
|
return true;
|
|
}
|
|
|
|
vtkSMSettingsDebugMacro("Failed writing settings file '" << filePath << "'");
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::HasSetting(const char* settingName)
|
|
{
|
|
return this->Internal->HasSetting(settingName);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
unsigned int vtkSMSettings::GetSettingNumberOfElements(const char* settingName)
|
|
{
|
|
Json::Value value = this->Internal->GetSetting(settingName);
|
|
if (value.isArray())
|
|
{
|
|
return value.size();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSMSettings::GetSettingAsInt(const char* settingName,
|
|
int defaultValue)
|
|
{
|
|
return this->GetSettingAsInt(settingName, 0, defaultValue);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkSMSettings::GetSettingAsDouble(const char* settingName,
|
|
double defaultValue)
|
|
{
|
|
return this->GetSettingAsDouble(settingName, 0, defaultValue);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
std::string vtkSMSettings::GetSettingAsString(const char* settingName,
|
|
const std::string & defaultValue)
|
|
{
|
|
return this->GetSettingAsString(settingName, 0, defaultValue);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSMSettings::GetSettingAsInt(const char* settingName,
|
|
unsigned int index,
|
|
int defaultValue)
|
|
{
|
|
std::vector<int> values;
|
|
bool success = this->Internal->GetSetting(settingName, values);
|
|
|
|
if (success && index < values.size())
|
|
{
|
|
return values[index];
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
double vtkSMSettings::GetSettingAsDouble(const char* settingName,
|
|
unsigned int index,
|
|
double defaultValue)
|
|
{
|
|
std::vector<double> values;
|
|
bool success = this->Internal->GetSetting(settingName, values);
|
|
|
|
if (success && index < values.size())
|
|
{
|
|
return values[index];
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
std::string vtkSMSettings::GetSettingAsString(const char* settingName,
|
|
unsigned int index,
|
|
const std::string & defaultValue)
|
|
{
|
|
std::vector<std::string> values;
|
|
bool success = this->Internal->GetSetting(settingName, values);
|
|
|
|
if (success && index < values.size())
|
|
{
|
|
return values[index];
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
std::string vtkSMSettings::GetSettingDescription(const char *settingName)
|
|
{
|
|
Json::Value value = this->Internal->GetSetting(settingName);
|
|
if (!value)
|
|
{
|
|
return std::string();
|
|
}
|
|
|
|
if (value.hasComment(Json::commentBefore))
|
|
{
|
|
return value.getComment(Json::commentBefore);
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::GetProxySettings(vtkSMProxy* proxy)
|
|
{
|
|
if (!proxy)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string jsonPrefix(".");
|
|
jsonPrefix.append(proxy->GetXMLGroup());
|
|
|
|
return this->GetProxySettings(jsonPrefix.c_str(), proxy);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::GetProxySettings(const char* prefix, vtkSMProxy* proxy)
|
|
{
|
|
if (!proxy)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return this->Internal->GetProxySettings(prefix, proxy);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, int value)
|
|
{
|
|
this->SetSetting(settingName, 0, value);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, double value)
|
|
{
|
|
this->SetSetting(settingName, 0, value);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, const std::string & value)
|
|
{
|
|
this->SetSetting(settingName, 0, value);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, unsigned int index, int value)
|
|
{
|
|
std::vector<int> values;
|
|
this->Internal->GetSetting(settingName, values);
|
|
if (values.size() <= index)
|
|
{
|
|
values.resize(index+1, 0);
|
|
}
|
|
|
|
values[index] = value;
|
|
this->Internal->SetSetting(settingName, values);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, unsigned int index, double value)
|
|
{
|
|
std::vector<double> values;
|
|
this->Internal->GetSetting(settingName, values);
|
|
if (values.size() <= index)
|
|
{
|
|
values.resize(index+1, 0);
|
|
}
|
|
|
|
values[index] = value;
|
|
this->Internal->SetSetting(settingName, values);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSetting(const char* settingName, unsigned int index, const std::string & value)
|
|
{
|
|
std::vector<std::string> values;
|
|
this->Internal->GetSetting(settingName, values);
|
|
if (values.size() <= index)
|
|
{
|
|
values.resize(index+1, "");
|
|
}
|
|
|
|
values[index] = value;
|
|
this->Internal->SetSetting(settingName, values);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetProxySettings(
|
|
vtkSMProxy* proxy, vtkSMPropertyIterator* propertyIt,
|
|
bool skipPropertiesWithDynamicDomains)
|
|
{
|
|
this->Internal->SetProxySettings(proxy, propertyIt, skipPropertiesWithDynamicDomains);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetProxySettings(const char* prefix,
|
|
vtkSMProxy* proxy, vtkSMPropertyIterator* propertyIt,
|
|
bool skipPropertiesWithDynamicDomains)
|
|
{
|
|
this->Internal->SetProxySettings(prefix, proxy, propertyIt, skipPropertiesWithDynamicDomains);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::SetSettingDescription(const char* settingName, const char* description)
|
|
{
|
|
Json::Path settingPath(settingName);
|
|
Json::Value & settingValue = settingPath.make(this->Internal->SettingCollections[0].Value);
|
|
settingValue.setComment(std::string(description), Json::commentBefore);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class T>
|
|
Json::Value vtkConvertXMLElementToJSON(
|
|
vtkSMVectorProperty* vp,
|
|
const std::vector<vtkSmartPointer<vtkPVXMLElement> >& elements)
|
|
{
|
|
// Since we need to handle enumeration domain :/.
|
|
vtkSMEnumerationDomain* enumDomain = vtkSMEnumerationDomain::SafeDownCast(
|
|
vp->FindDomain("vtkSMEnumerationDomain"));
|
|
Json::Value value(Json::arrayValue);
|
|
for (size_t cc=0; cc < elements.size(); ++cc)
|
|
{
|
|
T xmlValue;
|
|
elements[cc]->GetScalarAttribute("value", &xmlValue);
|
|
const char* txt = enumDomain? enumDomain->GetEntryTextForValue(xmlValue) : NULL;
|
|
if (txt)
|
|
{
|
|
value[static_cast<unsigned int>(cc)] = Json::Value(txt);
|
|
}
|
|
else
|
|
{
|
|
value[static_cast<unsigned int>(cc)] = Json::Value(xmlValue);
|
|
}
|
|
}
|
|
if (vp->GetNumberOfElements()==1 && vp->GetRepeatCommand()==0 && value.size()==1)
|
|
{
|
|
return value[0];
|
|
}
|
|
return value
|
|
;
|
|
}
|
|
|
|
template <>
|
|
Json::Value vtkConvertXMLElementToJSON<vtkStdString>(
|
|
vtkSMVectorProperty* vp,
|
|
const std::vector<vtkSmartPointer<vtkPVXMLElement> >& elements)
|
|
{
|
|
Json::Value value(Json::arrayValue);
|
|
for (size_t cc=0; cc < elements.size(); ++cc)
|
|
{
|
|
value[static_cast<unsigned int>(cc)] = Json::Value(elements[cc]->GetAttribute("value"));
|
|
}
|
|
if (vp->GetNumberOfElements()==1 && vp->GetRepeatCommand()==0 && value.size()==1)
|
|
{
|
|
return value[0];
|
|
}
|
|
return value;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
Json::Value vtkSMSettings::SerializeAsJSON(
|
|
vtkSMProxy* proxy, vtkSMPropertyIterator* iter/*=NULL*/)
|
|
{
|
|
if (proxy == NULL)
|
|
{
|
|
return Json::Value();
|
|
}
|
|
vtkSmartPointer<vtkPVXMLElement> xml;
|
|
xml.TakeReference(proxy->SaveXMLState(/*parent=*/NULL, iter));
|
|
Json::Value root(Json::objectValue);
|
|
for (unsigned int cc=0, max=xml->GetNumberOfNestedElements(); cc < max; ++cc)
|
|
{
|
|
vtkPVXMLElement* propXML = xml->GetNestedElement(cc);
|
|
if (propXML && propXML->GetName() && strcmp(propXML->GetName(), "Property") == 0)
|
|
{
|
|
const char* pname = propXML->GetAttribute("name");
|
|
int number_of_elements = 0;
|
|
if (!pname || !propXML->GetScalarAttribute("number_of_elements", &number_of_elements))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
vtkSMProperty* prop = proxy->GetProperty(pname);
|
|
if (prop == NULL || prop->GetInformationOnly())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// parse "Element".
|
|
std::vector<vtkSmartPointer<vtkPVXMLElement> > valueElements;
|
|
valueElements.resize(number_of_elements);
|
|
for (unsigned int kk=0, maxkk=propXML->GetNumberOfNestedElements(); kk<maxkk; ++kk)
|
|
{
|
|
int index = 0;
|
|
vtkPVXMLElement* elemXML = propXML->GetNestedElement(kk);
|
|
if (elemXML && elemXML->GetName() && strcmp(elemXML->GetName(), "Element") == 0 &&
|
|
elemXML->GetScalarAttribute("index", &index) &&
|
|
index >= 0 &&
|
|
index <= number_of_elements)
|
|
{
|
|
valueElements[index] = elemXML;
|
|
}
|
|
}
|
|
vtkSMVectorPropertyTemplateMacro(prop,
|
|
root[pname] = vtkConvertXMLElementToJSON<SM_TT>(
|
|
vtkSMVectorProperty::SafeDownCast(prop), valueElements);
|
|
);
|
|
}
|
|
}
|
|
return root;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMSettings::DeserializeFromJSON(
|
|
vtkSMProxy* proxy, const Json::Value& value)
|
|
{
|
|
if (!proxy || !value)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!value.isObject())
|
|
{
|
|
vtkGenericWarningMacro("Invalid JSON type. Expected an 'object'.");
|
|
return false;
|
|
}
|
|
|
|
vtkNew<vtkPVXMLElement> xml;
|
|
xml->SetName("Proxy");
|
|
xml->AddAttribute("group", proxy->GetXMLGroup());
|
|
xml->AddAttribute("name", proxy->GetXMLName());
|
|
for (Json::Value::const_iterator iter = value.begin(); iter != value.end(); ++iter)
|
|
{
|
|
vtkSMProperty* prop = proxy->GetProperty(iter.name().c_str());
|
|
if (!prop)
|
|
{
|
|
continue;
|
|
}
|
|
// Since we need to handle enumeration domain :/.
|
|
vtkSMEnumerationDomain* enumDomain = vtkSMEnumerationDomain::SafeDownCast(
|
|
prop->FindDomain("vtkSMEnumerationDomain"));
|
|
|
|
vtkNew<vtkPVXMLElement> propXML;
|
|
propXML->SetName("Property");
|
|
propXML->AddAttribute("name", iter.name().c_str());
|
|
if ((*iter).isArray() || (*iter).isObject())
|
|
{
|
|
propXML->AddAttribute("number_of_elements", static_cast<int>((*iter).size()));
|
|
int index = 0;
|
|
for (Json::Value::const_iterator elemIter = (*iter).begin(); elemIter != (*iter).end(); ++elemIter, ++index)
|
|
{
|
|
vtkNew<vtkPVXMLElement> elemXML;
|
|
elemXML->SetName("Element");
|
|
elemXML->AddAttribute("index", index);
|
|
std::string elemValue = (*elemIter).asString();
|
|
if (enumDomain && enumDomain->HasEntryText(elemValue.c_str()))
|
|
{
|
|
std::ostringstream stream;
|
|
stream << enumDomain->GetEntryValueForText(elemValue.c_str());
|
|
elemValue = stream.str();
|
|
}
|
|
elemXML->AddAttribute("value", elemValue.c_str());
|
|
propXML->AddNestedElement(elemXML.GetPointer());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
propXML->AddAttribute("number_of_elements", "1");
|
|
vtkNew<vtkPVXMLElement> elemXML;
|
|
elemXML->SetName("Element");
|
|
elemXML->AddAttribute("index", "0");
|
|
std::string elemValue = (*iter).asString();
|
|
if (enumDomain && enumDomain->HasEntryText(elemValue.c_str()))
|
|
{
|
|
std::ostringstream stream;
|
|
stream << enumDomain->GetEntryValueForText(elemValue.c_str());
|
|
elemValue = stream.str();
|
|
}
|
|
elemXML->AddAttribute("value", elemValue.c_str());
|
|
propXML->AddNestedElement(elemXML.GetPointer());
|
|
}
|
|
xml->AddNestedElement(propXML.GetPointer());
|
|
}
|
|
return (proxy->LoadXMLState(xml.GetPointer(), NULL) != 0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMSettings::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
os << indent << "SettingCollections:\n";
|
|
for (size_t i = 0; i < this->Internal->SettingCollections.size(); ++i)
|
|
{
|
|
os << indent << indent << "Root " << i << ":\n";
|
|
os << indent << indent << indent << "Priority: "
|
|
<< this->Internal->SettingCollections[i].Priority << "\n";
|
|
std::stringstream ss(this->Internal->SettingCollections[i].Value.toStyledString());
|
|
std::string line;
|
|
while (std::getline(ss, line))
|
|
{
|
|
os << indent << indent << indent << line << "\n";
|
|
}
|
|
}
|
|
}
|