summaryrefslogtreecommitdiffstats
path: root/src/control/controlobjectscript.cpp
blob: b7cbfd0194a24bfc67f97d462ed73f9320218706 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <QtDebug>

#include "control/controlobjectscript.h"

ControlObjectScript::ControlObjectScript(const ConfigKey& key, QObject* pParent)
        : ControlProxy(key, pParent, ControlFlag::NoAssertIfMissing) {
}

bool ControlObjectScript::addScriptConnection(const ScriptConnection& conn) {
    if (m_scriptConnections.isEmpty()) {
        // Only connect the slots when they are actually needed
        // by script connections.
        connect(m_pControl.data(),
                &ControlDoublePrivate::valueChanged,
                this,
                &ControlObjectScript::slotValueChanged,
                Qt::QueuedConnection);
        connect(this,
                &ControlObjectScript::trigger,
                this,
                &ControlObjectScript::slotValueChanged,
                Qt::QueuedConnection);
    }

    for (const auto& priorConnection : qAsConst(m_scriptConnections)) {
        if (conn == priorConnection) {
            qWarning() << "Connection " + conn.id.toString() +
                          " already connected to (" +
                          conn.key.group + ", " + conn.key.item +
                          "). Ignoring attempt to connect again.";
            return false;
        }
    }

    m_scriptConnections.append(conn);
    controllerDebug("Connected (" +
                    conn.key.group + ", " + conn.key.item +
                    ") to connection " + conn.id.toString());
    return true;
}

bool ControlObjectScript::removeScriptConnection(const ScriptConnection& conn) {
    bool success = m_scriptConnections.removeOne(conn);
    if (success) {
        controllerDebug("Disconnected (" +
                        conn.key.group + ", " + conn.key.item +
                        ") from connection " + conn.id.toString());
    } else {
        qWarning() << "Failed to disconnect (" +
                      conn.key.group + ", " + conn.key.item +
                      ") from connection " + conn.id.toString();
    }
    if (m_scriptConnections.isEmpty()) {
        // no ScriptConnections left, so disconnect signals
        disconnect(m_pControl.data(),
                &ControlDoublePrivate::valueChanged,
                this,
                &ControlObjectScript::slotValueChanged);
        disconnect(this,
                &ControlObjectScript::trigger,
                this,
                &ControlObjectScript::slotValueChanged);
    }
    return success;
}

void ControlObjectScript::disconnectAllConnectionsToFunction(const QJSValue& function) {
    // Make a local copy of m_scriptConnections because items are removed within the loop.
    const QList<ScriptConnection> connections = m_scriptConnections;
    for (const auto& conn: connections) {
        if (conn.callback.strictlyEquals(function)) {
            removeScriptConnection(conn);
        }
    }
}

void ControlObjectScript::slotValueChanged(double value, QObject*) {
    // Make a local copy of m_connectedScriptFunctions first.
    // This allows a script to disconnect a callback from inside the
    // the callback. Otherwise the this may crash since the disconnect call
    // happens during conn.function.call() in the middle of the loop below.
    const QList<ScriptConnection> connections = m_scriptConnections;
    for (auto&& conn: connections) {
        conn.executeCallback(value);
    }
}