Fix knob linking / refactor linking (#7883)

Closes #7869

This PR aims to fix linking bugs and it aims to make linking code faster. In the future I would like to replace controller and automation code with linked models, so it is essential for this feature to work as efficiently as possible.

Before this PR:

- AutomatableModels store a list of AutomatableModels that they are linked to.
- setValue() and other functions make recursive calls to themself resulting in the #7869 crash.
- Each AutomatableModel can unlink from other AutomatableModels, unlinking is the inverse operation to linking.

After this PR:

- AutomatableModels store a pointer to an other AutomatableModel making a linked list. The end is connected to the first element resulting in a "ring".
- setValue() and others are now recursion free, the code runs for every linked model, more efficiently than before.
- Each AutomatableModel can NOT unlink form other AutomatableModels, unlinking is NOT the inverse operation to linking. AutomatableModels can unlink themself from the linked list, they can not unlink themself from single models.

---------

Co-authored-by: allejok96 <allejok96@gmail.com>
This commit is contained in:
szeli1
2025-12-22 23:37:40 +01:00
committed by GitHub
parent c92741f567
commit 69f7c3243d
13 changed files with 338 additions and 221 deletions

View File

@@ -78,7 +78,7 @@ private slots: // tests
{
using namespace lmms;
BoolModel m1(false), m2(false);
BoolModel m1(true), m2(false);
QObject::connect(&m1, SIGNAL(dataChanged()),
this, SLOT(onM1Changed()));
@@ -86,17 +86,19 @@ private slots: // tests
this, SLOT(onM2Changed()));
resetChanged();
AutomatableModel::linkModels(&m1, &m1);
m1.linkToModel(&m1);
QVERIFY(!m1Changed); // cannot link to itself
QVERIFY(!m2Changed);
QVERIFY(m1.countLinks() == 0);
resetChanged();
AutomatableModel::linkModels(&m1, &m2);
QVERIFY(m1Changed); // since m1 takes the value of m2
m1.linkToModel(&m2);
QVERIFY(m1.value() == m2.value()); // since m1 takes the value of m2
QVERIFY(!m2Changed); // the second model is the source
QVERIFY(m1.countLinks() == 1);
resetChanged();
AutomatableModel::linkModels(&m1, &m2);
m1.linkToModel(&m2);
QVERIFY(!m1Changed); // it's already linked
QVERIFY(!m2Changed);
@@ -104,15 +106,15 @@ private slots: // tests
BoolModel m3(false);
m1.setValue(1.f);
m2.setValue(1.f);
AutomatableModel::linkModels(&m1, &m2);
m1.linkToModel(&m2);
QVERIFY(m1.value());
QVERIFY(m2.value());
QVERIFY(!m3.value());
AutomatableModel::linkModels(&m2, &m3); // drag m3, drop on m2
m2.linkToModel(&m3); // drag m3, drop on m2
// m2 should take m3's (0) value
// due to a bug(?), this does not happen
QVERIFY(m2.value());
QVERIFY(m2.value() == m3.value());
QVERIFY(!m3.value());
QVERIFY(m1.countLinks() == 2);
}
};