Skip to content

Commit

Permalink
more
Browse files Browse the repository at this point in the history
  • Loading branch information
boutinb committed Nov 7, 2024
1 parent 1d4277d commit e49fdff
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 123 deletions.
4 changes: 4 additions & 0 deletions QMLComponents/analysisform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ void AnalysisForm::runScriptRequestDone(const QString& result, const QString& co
clearFormErrors();
if (_rSyntax->parseRSyntaxOptions(options))
{
blockValueChangeSignal(true);
_analysis->clearOptions();
bindTo(Json::nullValue);
bindTo(options);
blockValueChangeSignal(false, false);
_analysis->boundValueChangedHandler();
}
}
Expand Down
53 changes: 7 additions & 46 deletions QMLComponents/boundcontrols/boundcontrolbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,12 @@ void BoundControlBase::_readTableValue(const Json::Value &value, const std::stri
{
for (const Json::Value& row : value)
{
std::vector<std::string> term;
const Json::Value& keyValue = row[key];
if (keyValue.isArray())
{
for (const Json::Value& component : keyValue)
term.push_back(component.asString());
}
else if (keyValue.isString())
term.push_back(keyValue.asString());
else
Log::log() << "Key (" << key << ") bind value is not an array or a string in " << getName() << ": " << value.toStyledString() << std::endl;
Json::Value keyValue = row[key];

Term term = Term::readTerm(keyValue);
if (term.size() > 0)
{
terms.add(Term(term));
terms.add(term);

QMap<QString, Json::Value> controlMap;
for (auto itr = row.begin(); itr != row.end(); ++itr)
Expand All @@ -145,52 +136,22 @@ void BoundControlBase::_readTableValue(const Json::Value &value, const std::stri
controlMap[tq(name)] = *itr;
}

allControlValues[Term(term).asQString()] = controlMap;
allControlValues[term.asQString()] = controlMap;
}
}
}

Json::Value BoundControlBase::_getTableValueOption(const Terms& terms, const ListModel::RowControlsValues& componentValuesMap, const std::string& key, bool hasInteraction, bool keyHasVariables) const
Json::Value BoundControlBase::_getTableValueOption(const Terms& terms, const ListModel::RowControlsValues& componentValuesMap, const std::string& key, bool hasInteraction, bool keyHasVariables)
{
Json::Value result(Json::arrayValue);

for (const Term& term : terms)
{
QMap<QString, Json::Value> componentValues = componentValuesMap[term.asQString()];

Json::Value rowValues(Json::objectValue),
keyValue; // depending of keyHasVariables & hasInteraction, keyValue can be an object, an array or a string

if (keyHasVariables)
{
// If the key of the row contains variables, set 'value' and 'types'
Json::Value jsonValue, jsonTypes;

if (hasInteraction)
{
for (const std::string& comp : term.scomponents())
jsonValue.append(comp);
for (columnType type : term.types())
jsonTypes.append(columnTypeToString(type));
}
else
{
jsonValue = term.asString();
jsonTypes = columnTypeToString(term.type());
}
keyValue["value"] = jsonValue;
keyValue["types"] = jsonTypes;
}
else
{
if (hasInteraction)
for (const std::string& comp : term.scomponents())
keyValue.append(comp);
else
keyValue = term.asString();
}
Json::Value rowValues(Json::objectValue);

rowValues[key] = keyValue;
rowValues[key] = term.toJson(hasInteraction, keyHasVariables);

QMapIterator<QString, Json::Value> it2(componentValues);
while (it2.hasNext())
Expand Down
2 changes: 1 addition & 1 deletion QMLComponents/boundcontrols/boundcontrolbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class BoundControlBase : public BoundControl
std::string getName() const;
void handleComputedColumn(const Json::Value& value);

Json::Value _getTableValueOption(const Terms& terms, const ListModel::RowControlsValues& componentValuesMap, const std::string& key, bool hasInteraction, bool keyHasVariables) const;
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);
Expand Down
22 changes: 13 additions & 9 deletions QMLComponents/boundcontrols/boundcontrolterms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,30 +180,34 @@ bool BoundControlTerms::isJsonValid(const Json::Value &optionValue) const
(typesPart.isArray() || typesPart.isString());
}

Json::Value BoundControlTerms::_makeOption(const Terms& terms, const ListModel::RowControlsValues& controlValues) const
Json::Value BoundControlTerms::makeOption(const Terms& terms, const ListModel::RowControlsValues& controlValues, const std::string& optionKey, bool containsInteractions, bool hasRowComponent, bool isSingleRow)
{
Json::Value result(Json::objectValue);

Json::Value optionValue,
optionTypes = _termsModel->getVariableTypes(terms);
Json::Value optionValue;

if (_listView->hasRowComponent() || _listView->containsInteractions())
optionValue = _getTableValueOption(terms, controlValues, _optionKey, _listView->containsInteractions(), false);
else if (_isSingleRow)
if (hasRowComponent || containsInteractions)
optionValue = _getTableValueOption(terms, controlValues, optionKey, containsInteractions, false);
else if (isSingleRow)
optionValue = terms.size() > 0 ? terms[0].asString() : "";
else
for (const Term& term : terms)
optionValue.append(term.asString());

result["value"] = optionValue;
result["types"] = optionTypes;
result["types"] = terms.types();

if (_listView->hasRowComponent() || _listView->containsInteractions())
result["optionKey"] = _optionKey;
if (hasRowComponent || containsInteractions)
result["optionKey"] = optionKey;

return result;
}

Json::Value BoundControlTerms::_makeOption(const Terms& terms, const ListModel::RowControlsValues& controlValues) const
{
return makeOption(terms, controlValues, _optionKey, _listView->containsInteractions(), _listView->hasRowComponent(), _isSingleRow);
}

void BoundControlTerms::resetBoundValue()
{
setBoundValue(_makeOption(_termsModel->terms(), _termsModel->getTermsWithComponentValues()));
Expand Down
2 changes: 2 additions & 0 deletions QMLComponents/boundcontrols/boundcontrolterms.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class BoundControlTerms : public BoundControlBase
Json::Value addTermsToOption(const Json::Value &option, const Terms &terms, const ListModel::RowControlsValues &extraTermsMap = {}) const;
bool areTermsInOption(const Json::Value& option, Terms& terms) const;

static Json::Value makeOption(const Terms& terms, const ListModel::RowControlsValues& controlValues, const std::string& optionKey, bool containsInteractions, bool hasRowComponent, bool isSingleRow);

private:
Terms _getTermsFromOptions(const Json::Value& option) const;
Json::Value _adjustBindingValue(const Json::Value &value) const;
Expand Down
6 changes: 1 addition & 5 deletions QMLComponents/controls/componentslistbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,8 @@ QList<QVariant> ComponentsListBase::controlNameXOffsetMap() const
return result;
}

Json::Value ComponentsListBase::getJsonFromComponentValues(const ListModel::RowControlsValues &termsWithComponentValues)
Json::Value ComponentsListBase::getJsonFromComponentValues(const Terms& terms, const ListModel::RowControlsValues &termsWithComponentValues)
{
Terms terms;
for (const QString& term : termsWithComponentValues.keys())
terms.add(Term::readTerm(term));

return _getTableValueOption(terms, termsWithComponentValues, fq(_optionKey), containsInteractions(), containsVariables());
}

Expand Down
2 changes: 1 addition & 1 deletion QMLComponents/controls/componentslistbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class ComponentsListBase : public JASPListControl, public BoundControlBase
QList<QVariant> controlNameXOffsetMap() const;
QList<QVariant> headerLabels() const { return _headerLabels; }

Json::Value getJsonFromComponentValues(const ListModel::RowControlsValues& termsWithComponentValues);
Json::Value getJsonFromComponentValues(const Terms& terms, const ListModel::RowControlsValues& termsWithComponentValues);

signals:
void addItem();
Expand Down
39 changes: 4 additions & 35 deletions QMLComponents/models/listmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,41 +794,10 @@ void ListModel::_replaceTerm(int index, const Term &term)
setUpRowControls();
}

Json::Value ListModel::getVariableTypes(const Terms& terms, bool onlyChanged) const
{
Json::Value types(Json::arrayValue);

auto changedType = [&, onlyChanged] (const QString& term, columnType type) -> Json::Value
{
if (onlyChanged && (_listView->hasMandatoryType() || (columnType)requestInfo(VariableInfo::VariableType, term).toInt() == type))
return Json::nullValue;
else
return columnTypeToString(type);
};

for (const Term& term : terms)
{
if (term.components().size() == 1)
types.append(changedType(term.asQString(), term.type()));
else
{
Json::Value componentTypes(Json::arrayValue);
columnTypeVec termTypes = term.types();
int i = 0;
for (const QString component : term.components())
{
componentTypes.append(changedType(component, termTypes.size() > i ? termTypes[i] : columnType::unknown));
i++;
}
types.append(componentTypes);
}
}

return types;
}


Json::Value ListModel::getVariableTypes(bool onlyChanged) const
{
return getVariableTypes(terms(), onlyChanged);
if (onlyChanged && _listView->hasMandatoryType())
return Json::nullValue;

return _terms.types(onlyChanged, this);
}
1 change: 0 additions & 1 deletion QMLComponents/models/listmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class ListModel : public QAbstractTableModel, public VariableInfoConsumer
void setVariableType(int index, columnType type);
columnType getVariableType( const QString& name) const;
Json::Value getVariableTypes(bool onlyChanged = false) const;
Json::Value getVariableTypes(const Terms& terms, bool onlyChanged = false) const;
columnType getVariableRealType(const QString& name) const;
QString getVariablePreview( const QString& name) const;
QStringList getUsedTypes() const;
Expand Down
63 changes: 63 additions & 0 deletions QMLComponents/models/term.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,66 @@ Term Term::readTerm(QString str)
{
return Term(str.split(separator));
}

Term Term::readTerm(const Json::Value &json, columnType defaultType)
{
Json::Value jsonValue = json;
std::vector<std::string> components;
columnTypeVec types;

if (json.isObject() && json.isMember("value") && json.isMember("types"))
{
jsonValue = json["value"];
Json::Value jsonType = json["types"];

if (jsonType.isArray())
{
for (const Json::Value& type : jsonType)
types.push_back(columnTypeFromString(type.asString(), columnType::unknown));
}
else if (jsonType.isString())
types.push_back(columnTypeFromString(jsonType.asString(), columnType::unknown));
}

if (jsonValue.isArray())
{
for (const Json::Value& component : jsonValue)
components.push_back(component.asString());
}
else if (jsonValue.isString())
components.push_back(jsonValue.asString());

while (types.size() < components.size())
types.push_back(defaultType);

return Term(components, types);
}

Json::Value Term::toJson(bool useArray, bool useValueAndType) const
{
useArray = useArray || _components.size();
Json::Value result, value, types;

if (useArray)
{
for (const QString& component : _components)
value.append(fq(component));
for (columnType type : _types)
types.append(columnTypeToString(type));
}
else
{
value = asString();
types = columnTypeToString(type());
}

if (useValueAndType)
{
result["value"] = value;
result["types"] = types;
}
else
result = value;

return result;
}
4 changes: 4 additions & 0 deletions QMLComponents/models/term.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <QString>
#include <QStringList>
#include "columntype.h"
#include <json/json.h>

///
/// A term is a basic element of a VariablesList
Expand Down Expand Up @@ -76,6 +77,9 @@ class Term
static const char* separator;
static Term readTerm(std::string str);
static Term readTerm(QString str);
static Term readTerm(const Json::Value& json, columnType defaultType = columnType::unknown);

Json::Value toJson(bool useArray = true, bool useValueAndType = true) const;

private:
void initFrom(const QStringList components, const columnTypeVec& type);
Expand Down
32 changes: 32 additions & 0 deletions QMLComponents/models/terms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <QIODevice>
#include <QSet>
#include "utilities/qutils.h"
#include "variableinfo.h"

using namespace std;

Expand Down Expand Up @@ -530,7 +531,38 @@ void Terms::setUndraggableTerms(const Terms& undraggableTerms)
_terms = newTerms;
}

Json::Value Terms::types(bool onlyChanged, const VariableInfoConsumer* info) const
{
Json::Value types(Json::arrayValue);

auto changedType = [&, onlyChanged, info] (const QString& term, columnType type) -> Json::Value
{
if (onlyChanged && info && (columnType)info->requestInfo(VariableInfo::VariableType, term).toInt() == type)
return Json::nullValue;
else
return columnTypeToString(type);
};

for (const Term& term : _terms)
{
if (term.components().size() == 1)
types.append(changedType(term.asQString(), term.type()));
else
{
Json::Value componentTypes(Json::arrayValue);
columnTypeVec termTypes = term.types();
int i = 0;
for (const QString component : term.components())
{
componentTypes.append(changedType(component, termTypes.size() > i ? termTypes[i] : columnType::unknown));
i++;
}
types.append(componentTypes);
}
}

return types;
}

void Terms::set(const QByteArray & array, bool isUnique)
{
Expand Down
4 changes: 4 additions & 0 deletions QMLComponents/models/terms.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "term.h"
#include "controls/jaspcontrol.h"

class VariableInfoConsumer;

///
/// Terms is a list of Term. They are used in VariablesList
/// Some extra functionalities are added to deal with terms with interactions, in order for example to remove all terms that contain some component
Expand Down Expand Up @@ -124,6 +126,8 @@ class Terms
void setDraggable(bool draggable);
void setUndraggableTerms(const Terms& undraggableTerms);

Json::Value types(bool onlyChanged = false, const VariableInfoConsumer* info = nullptr) const;

private:

int rankOf(const QString &component) const;
Expand Down
2 changes: 1 addition & 1 deletion QMLComponents/rsyntax/formulaparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ bool FormulaParser::parse(const Json::Value& formula, bool isLhs, ParsedTerms& p

QString FormulaParser::transformToFormulaTerm(const Term &term, const Json::Value& changedType, char join, bool addQuotes)
{
static QRegularExpression rx("^[a-zA-Z0-9_]+$");
static QRegularExpression rx("^[a-zA-Z0-9_\\.]+$");
QString result;
const QStringList& components = term.components();
int i = 0;
Expand Down
Loading

0 comments on commit e49fdff

Please sign in to comment.