diff --git a/QMLComponents/boundcontrols/boundcontrolbase.cpp b/QMLComponents/boundcontrols/boundcontrolbase.cpp index 4060a48155..c0fa5c86f7 100644 --- a/QMLComponents/boundcontrols/boundcontrolbase.cpp +++ b/QMLComponents/boundcontrols/boundcontrolbase.cpp @@ -117,7 +117,7 @@ std::string BoundControlBase::getName() const return fq(_control->name()); } -void BoundControlBase::_readTableValue(const Json::Value &value, const std::string& key, bool hasMultipleTerms, Terms& terms, ListModel::RowControlsValues& allControlValues) +void BoundControlBase::_readTableValue(const Json::Value &value, const std::string& key, bool hasMultipleTerms, Terms& terms, ListModel::RowControlsValues& allControlValues, const Terms& sourceTerms) { for (const Json::Value& row : value) { @@ -126,6 +126,9 @@ void BoundControlBase::_readTableValue(const Json::Value &value, const std::stri Term term = Term::readTerm(keyValue); if (term.size() > 0) { + int termInd = sourceTerms.indexOf(term); + if (termInd >= 0) + term.setTypes(sourceTerms[termInd].types()); terms.add(term); QMap controlMap; diff --git a/QMLComponents/boundcontrols/boundcontrolbase.h b/QMLComponents/boundcontrols/boundcontrolbase.h index 4db22a19f8..e1dd63f1f0 100644 --- a/QMLComponents/boundcontrols/boundcontrolbase.h +++ b/QMLComponents/boundcontrols/boundcontrolbase.h @@ -51,7 +51,7 @@ class BoundControlBase : public BoundControl static Json::Value _getTableValueOption(const Terms& terms, const ListModel::RowControlsValues& componentValuesMap, const std::string& key, bool hasInteraction, bool keyHasVariables); void _setTableValue(const Terms& terms, const ListModel::RowControlsValues& componentValuesMap, const std::string& key, bool hasInteraction, bool keyHasVariables = false); - void _readTableValue(const Json::Value& value, const std::string& key, bool hasMultipleTerms, Terms& terms, ListModel::RowControlsValues& allControlValues); + void _readTableValue(const Json::Value& value, const std::string& key, bool hasMultipleTerms, Terms& terms, ListModel::RowControlsValues& allControlValues, const Terms& sourceTerms = Terms()); bool _isValueWithTypes(const Json::Value &value) const; JASPControl* _control = nullptr; diff --git a/QMLComponents/boundcontrols/boundcontrolterms.cpp b/QMLComponents/boundcontrols/boundcontrolterms.cpp index bc6b442e20..5592148178 100644 --- a/QMLComponents/boundcontrols/boundcontrolterms.cpp +++ b/QMLComponents/boundcontrols/boundcontrolterms.cpp @@ -127,43 +127,61 @@ void BoundControlTerms::bindTo(const Json::Value &value) Log::log() << "Control " << _control->name() << " is bound with a value that is neither an array, an object bor a string :" << valuePart.toStyledString() << std::endl; } - int i = 0; + int termId = 0; for (Term& term : terms) { - if (typesPart.size() > i) // If the type is given, use it + if (typesPart.size() > termId) // If the type is given, use it { - if (typesPart[i].isArray()) - { - columnTypeVec types; - for (const Json::Value& jsonType : typesPart[i]) + columnTypeVec types; + if (typesPart[termId].isArray()) + for (const Json::Value& jsonType : typesPart[termId]) types.push_back(columnTypeFromString(jsonType.asString(), columnType::unknown)); - term.setTypes(types); - } else - term.setType(columnTypeFromString(typesPart[i].asString(), columnType::unknown)); + types.push_back(columnTypeFromString(typesPart[termId].asString(), columnType::unknown)); + term.setTypes(types); } - else + termId++; + } + + // For backward compatibility, the types of the terms must be checked. + // Before 0.19.0, the types were not given: in this case the real type of the variable (if it is a variable) is retrieved from the dataset. + // In 0.19.1, the types were not given for terms with interaction: in this case, the variables of the interation term is + // most of the time also in the Variables List: the types of these variables must be stored and used for interaction term. This type might be not the one in the dataset, but a type changed by the user. + QMap variableTypeMap; + for (Term& term : terms) + { + if (term.size() == 1 && term.type() != columnType::unknown && _listView->isTypeAllowed(term.type())) + variableTypeMap[term.asQString()] = term.type(); + } + + for (Term& term : terms) + { + columnTypeVec types = term.types(), + checkedTypes; + int componentId = 0; + for (const QString& component : term.components()) { - if (term.type() == columnType::unknown) - { - // Backward compatibility: the type was not saved before 0.19, so get the real type and check whether it is allowed. If not, take the default - columnType type = _listView->model()->getVariableRealType(term.asQString()); - if (type != columnType::unknown && !_listView->isTypeAllowed(type)) - type = _listView->defaultType(); - term.setType(type); - } - typesPart.append(columnTypeToString(term.type())); + columnType type = types.size() > componentId ? types[componentId] : columnType::unknown; + if (type == columnType::unknown) + type = variableTypeMap.contains(component) ? variableTypeMap[component] : _listView->model()->getVariableRealType(component); + + // Ensure that the type is allowed (if it is unknown, this is not a variable, so don't check the type) + if (type != columnType::unknown && !_listView->isTypeAllowed(type)) + type = _listView->defaultType(); + + checkedTypes.push_back(type); + componentId++; } - i++; + + term.setTypes(checkedTypes); } Json::Value newValue = Json::objectValue; newValue["value"] = valuePart; - newValue["types"] = typesPart; + newValue["types"] = terms.types(); BoundControlBase::bindTo(newValue); _termsModel->initTerms(terms, allControlValues); - } Json::Value BoundControlTerms::createJson() const diff --git a/QMLComponents/controls/componentslistbase.cpp b/QMLComponents/controls/componentslistbase.cpp index 9adf8bd77f..e1237dffc5 100644 --- a/QMLComponents/controls/componentslistbase.cpp +++ b/QMLComponents/controls/componentslistbase.cpp @@ -47,7 +47,7 @@ void ComponentsListBase::bindTo(const Json::Value& value) Terms terms; ListModel::RowControlsValues allControlValues; - _readTableValue(value, keyName, containsInteractions(), terms, allControlValues); + _readTableValue(value, keyName, containsInteractions(), terms, allControlValues, _termsModel->getSourceTerms()); _termsModel->initTerms(terms, allControlValues); }