Skip to content

Commit fd1bb18

Browse files
committed
Initialize controls only if their dependencies are already initialized
1 parent a4ac478 commit fd1bb18

14 files changed

+187
-184
lines changed

QMLComponents/analysisform.cpp

+4-12
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,6 @@ void AnalysisForm::_setUp()
275275

276276
for (JASPControl* control : controls)
277277
{
278-
BoundControl* boundControl = control->boundControl();
279-
if (boundControl) boundControl->setDefaultBoundValue(boundControl->createJson()); // The default value is known only when all controls are setup
280278
_dependsOrderedCtrls.push_back(control);
281279
connect(control, &JASPControl::helpMDChanged, this, &AnalysisForm::helpMDChanged);
282280
}
@@ -363,7 +361,6 @@ void AnalysisForm::bindTo(const Json::Value & defaultOptions)
363361

364362
for (JASPControl* control : _dependsOrderedCtrls)
365363
{
366-
bool hasOption = false;
367364
BoundControl* boundControl = control->boundControl();
368365
JASPListControl* listControl = dynamic_cast<JASPListControl *>(control);
369366

@@ -385,27 +382,22 @@ void AnalysisForm::bindTo(const Json::Value & defaultOptions)
385382
}
386383
}
387384

385+
Json::Value optionValue = Json::nullValue;
388386
if (boundControl)
389387
{
390388
std::string name = control->name().toStdString();
391-
Json::Value optionValue = defaultOptions.size() != 0 ? defaultOptions[name] : Json::nullValue;
389+
if (defaultOptions.isMember(name))
390+
optionValue = defaultOptions[name];
392391

393392
if (optionValue != Json::nullValue && !boundControl->isJsonValid(optionValue))
394393
{
395394
optionValue = Json::nullValue;
396395
control->setHasWarning(true);
397396
controlsJsonWrong.insert(name);
398397
}
399-
400-
if (optionValue == Json::nullValue)
401-
optionValue = boundControl->createJson();
402-
else
403-
hasOption = true;
404-
405-
boundControl->bindTo(optionValue);
406398
}
407399

408-
control->setInitialized(hasOption);
400+
control->setInitialized(optionValue);
409401
}
410402

411403
for (ListModelAvailableInterface* availableModel : availableModelsToBeReset)

QMLComponents/controls/comboboxbase.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ComboBoxBase::ComboBoxBase(QQuickItem* parent)
3030

3131
void ComboBoxBase::bindTo(const Json::Value& value)
3232
{
33-
// Do not call BoundControlBase::bindTo now because the value might be changed to the default value.
33+
_model->resetTermsFromSources();
3434

3535
std::vector<std::string> values = _model->getValues();
3636
std::string selectedValue = value.asString();

QMLComponents/controls/jaspcontrol.cpp

+39-11
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ void JASPControl::_resetBindingValue()
157157
// If a control gets a value from a JASP file, this value may differ from its default value sets by a QML binding:
158158
// this QML binding may then change the value during the initialization of the form.
159159
// In this case, restore the original value.
160-
if (isBound() && hasUserInteractiveValue() && initializedFromJaspFile() && form() && !form()->initialized())
160+
if (isBound() && hasUserInteractiveValue() && initializedWithValue() && form() && !form()->initialized())
161161
boundControl()->resetBoundValue();
162162
}
163163

@@ -742,16 +742,6 @@ QString JASPControl::humanFriendlyLabel() const
742742

743743
return label;
744744

745-
}
746-
747-
void JASPControl::setInitialized(bool byFile)
748-
{
749-
if (!_initialized)
750-
{
751-
_initialized = true;
752-
_initializedFromJaspFile = byFile;
753-
emit initializedChanged();
754-
}
755745
}
756746

757747
QVector<JASPControl::ParentKey> JASPControl::getParentKeys()
@@ -821,3 +811,41 @@ void JASPControl::addExplicitDependency()
821811
{
822812
_addExplicitDependency(_explicitDepends);
823813
}
814+
815+
bool JASPControl::dependingControlsAreInitialized()
816+
{
817+
bool dependenciesAreInitialized = true;
818+
819+
for (JASPControl* c : _depends)
820+
{
821+
if (!c->initialized())
822+
dependenciesAreInitialized = false;
823+
}
824+
return dependenciesAreInitialized;
825+
}
826+
827+
void JASPControl::setInitialized(const Json::Value &value)
828+
{
829+
if (dependingControlsAreInitialized())
830+
_setInitialized(value);
831+
else
832+
{
833+
for (JASPControl* c : _depends)
834+
if (!c->initialized())
835+
connect(c, &JASPControl::initializedChanged, [this, value]() { if (dependingControlsAreInitialized()) _setInitialized(value); });
836+
}
837+
}
838+
839+
void JASPControl::_setInitialized(const Json::Value &value)
840+
{
841+
BoundControl* bControl = boundControl();
842+
if (bControl)
843+
{
844+
bControl->setDefaultBoundValue(bControl->createJson());
845+
bControl->bindTo(value == Json::nullValue ? bControl->createJson() : value);
846+
}
847+
848+
_initialized = true;
849+
_initializedWithValue = (value != Json::nullValue);
850+
emit initializedChanged();
851+
}

QMLComponents/controls/jaspcontrol.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class JASPControl : public QQuickItem
120120
bool indent() const { return _indent; }
121121
bool isDependency() const { return _isDependency; }
122122
bool initialized() const { return _initialized; }
123-
bool initializedFromJaspFile() const { return _initializedFromJaspFile; }
123+
bool initializedWithValue() const { return _initializedWithValue; }
124124
bool shouldShowFocus() const { return _shouldShowFocus; }
125125
bool shouldStealHover() const { return _shouldStealHover; }
126126
bool debug() const { return _debug; }
@@ -151,7 +151,7 @@ class JASPControl : public QQuickItem
151151
const QVariant& explicitDepends() const { return _explicitDepends; }
152152

153153
QString humanFriendlyLabel() const;
154-
void setInitialized(bool byFile = false);
154+
void setInitialized(const Json::Value& value = Json::nullValue);
155155

156156
QVector<JASPControl::ParentKey> getParentKeys();
157157

@@ -172,8 +172,6 @@ class JASPControl : public QQuickItem
172172

173173
virtual QString friendlyName() const;
174174
void addExplicitDependency();
175-
protected:
176-
Set _depends;
177175

178176
public slots:
179177
void setControlType( ControlType controlType) { _controlType = controlType; }
@@ -266,8 +264,11 @@ private slots:
266264
bool eventFilter(QObject *watched, QEvent *event) override;
267265
bool checkOptionName(const QString& name);
268266
void _addExplicitDependency(const QVariant& depends);
267+
bool dependingControlsAreInitialized();
268+
void _setInitialized(const Json::Value &value);
269269

270270
protected:
271+
Set _depends;
271272
ControlType _controlType;
272273
AnalysisForm* _form = nullptr;
273274
QString _name,
@@ -278,7 +279,7 @@ private slots:
278279
bool _isBound = true,
279280
_indent = false,
280281
_initialized = false,
281-
_initializedFromJaspFile = false,
282+
_initializedWithValue = false,
282283
_debug = false,
283284
_parentDebug = false,
284285
_hasError = false,

QMLComponents/controls/jasplistcontrol.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ void JASPListControl::_setupSources()
4848
{
4949
for (SourceItem* sourceItem : _sourceItems)
5050
{
51-
if (sourceItem->listModel())
51+
if (sourceItem->sourceListModel())
5252
{
53-
JASPListControl* sourceControl = sourceItem->listModel()->listView();
53+
JASPListControl* sourceControl = sourceItem->sourceListModel()->listView();
5454
disconnect(sourceControl, &JASPListControl::containsVariablesChanged, this, &JASPListControl::setContainsVariables);
5555
disconnect(sourceControl, &JASPListControl::containsInteractionsChanged, this, &JASPListControl::setContainsInteractions);
5656
}
@@ -62,9 +62,9 @@ void JASPListControl::_setupSources()
6262

6363
for (SourceItem* sourceItem : _sourceItems)
6464
{
65-
if (sourceItem->listModel())
65+
if (sourceItem->sourceListModel())
6666
{
67-
JASPListControl* sourceControl = sourceItem->listModel()->listView();
67+
JASPListControl* sourceControl = sourceItem->sourceListModel()->listView();
6868
connect(sourceControl, &JASPListControl::containsVariablesChanged, this, &JASPListControl::setContainsVariables);
6969
connect(sourceControl, &JASPListControl::containsInteractionsChanged, this, &JASPListControl::setContainsInteractions);
7070
}
@@ -86,10 +86,10 @@ void JASPListControl::setContainsVariables()
8686
{
8787
for (SourceItem* sourceItem : _sourceItems)
8888
{
89-
if (sourceItem->isColumnsModel()) containsVariables = true;
90-
else if (sourceItem->listModel())
89+
if (sourceItem->isAnalysisDataSet()) containsVariables = true;
90+
else if (sourceItem->sourceListModel())
9191
{
92-
if (sourceItem->listModel()->listView()->containsVariables() && sourceItem->controlName().isEmpty() && !sourceItem->modelUse().contains("levels"))
92+
if (sourceItem->sourceListModel()->listView()->containsVariables() && sourceItem->rowControlName().isEmpty() && !sourceItem->sourceFilter().contains("levels"))
9393
containsVariables = true;
9494
}
9595
}
@@ -120,9 +120,9 @@ void JASPListControl::setContainsInteractions()
120120
{
121121
for (SourceItem* sourceItem : _sourceItems)
122122
{
123-
if (sourceItem->listModel())
123+
if (sourceItem->sourceListModel())
124124
{
125-
JASPListControl* sourceControl = sourceItem->listModel()->listView();
125+
JASPListControl* sourceControl = sourceItem->sourceListModel()->listView();
126126
if (sourceControl->containsInteractions() || sourceItem->generateInteractions())
127127
containsInteractions = true;
128128
}

QMLComponents/controls/rowcontrols.cpp

+17-35
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,17 @@ void RowControls::init(int row, const Term& key, bool isNew)
4747
context->setContextProperty("rowIndex", row);
4848
context->setContextProperty("rowValue", key.asQString());
4949

50-
_rowObject = qobject_cast<QQuickItem*>(_rowComponent->create(context));
50+
_rowObject = qobject_cast<QQuickItem*>(_rowComponent->create(context)); // The _rowJASPControlMap will be filled during this step
5151
_rowObject->setParent(_parentModel);
5252
_context = context;
5353

54-
if (_rowObject) _setupControls();
54+
if (_rowObject) _initializeControls();
5555
else Log::log() << "Could not create control in ListView " << listView->name() << std::endl;
5656
}
5757

58-
void RowControls::_setupControls(bool reuseBoundValue)
58+
void RowControls::_initializeControls(bool useInitialValue)
5959
{
60-
// The controls (when created or reused) may need to be bound with some values:
61-
// either with the initial values (in _rowValues) or new values (by calling createJson)
62-
// And if a control depends on a source, its values must be refreshed by this source.
60+
// The controls (when created or reused) need to be initialized
6361
QList<JASPControl*> controls = _rowJASPControlMap.values();
6462
AnalysisForm* form = _parentModel->listView()->form();
6563

@@ -71,38 +69,22 @@ void RowControls::_setupControls(bool reuseBoundValue)
7169

7270
for (JASPControl* control : controls)
7371
{
74-
bool hasInitialValues = _initialValues.contains(control->name());
75-
BoundControl* boundItem = control->boundControl();
72+
JASPListControl* listView = dynamic_cast<JASPListControl*>(control);
73+
if (listView)
74+
for (SourceItem* source : listView->sourceItems())
75+
source->connectModels(); // If the source was disconnected, reconnect it.
7676

77-
if (boundItem)
78-
{
79-
// When a control is created before its parent, it has no bound value yet.
80-
// In this case we need to create a bound volue.
81-
bool hasNoBoundValue = boundItem->boundValue().isNull();
82-
if (!reuseBoundValue || hasNoBoundValue)
83-
{
84-
boundItem->setDefaultBoundValue(boundItem->createJson());
85-
boundItem->bindTo(hasInitialValues ? (_initialValues[control->name()]) : boundItem->createJson());
86-
// bindTo does not emit the signal that the bound value is changed.
87-
// But (at least) if it did not have any value, it should emit this signal.
88-
if (hasNoBoundValue) emit control->boundValueChanged(control);
89-
}
90-
}
91-
92-
if (!boundItem || !hasInitialValues || reuseBoundValue)
77+
Json::Value optionValue = Json::nullValue;
78+
BoundControl* boundItem = control->boundControl();
79+
if (boundItem && _initialValues.contains(control->name()))
9380
{
94-
JASPListControl* listView = dynamic_cast<JASPListControl*>(control);
95-
// If a ListView depends on a source, it has to be initialized by this source
96-
// For this just call the sourceTermsChanged handler.
97-
if (listView && listView->hasSource())
98-
{
99-
for (SourceItem* source : listView->sourceItems())
100-
source->connectModels(); // If the source was disconnected, reconnect it.
101-
listView->model()->sourceTermsReset();
102-
}
81+
// When a control is created before its parent, it has no value yet.
82+
// In this case use its initial value.
83+
if (useInitialValue || boundItem->boundValue().isNull())
84+
optionValue = _initialValues[control->name()];
10385
}
10486

105-
control->setInitialized();
87+
control->setInitialized(optionValue);
10688
}
10789

10890
if (form)
@@ -116,7 +98,7 @@ void RowControls::setContext(int row, const QString &key)
11698
_context->setContextProperty("rowValue", key);
11799
_context->setContextProperty("isNew", false);
118100

119-
_setupControls(true);
101+
_initializeControls(false);
120102
}
121103

122104
bool RowControls::addJASPControl(JASPControl *control)

QMLComponents/controls/rowcontrols.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Q_OBJECT
5252

5353
private:
5454

55-
void _setupControls(bool reuseBoundValue = false);
55+
void _initializeControls(bool useInitialValue = true);
5656

5757
ListModel* _parentModel;
5858
QQmlComponent* _rowComponent = nullptr;

0 commit comments

Comments
 (0)