summaryrefslogtreecommitdiffstats
path: root/src/qml/qmleffectmanifestparametersmodel.cpp
blob: 4bcfb6ba5a6246ee6c3089524d65bfd9c7305d0c (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "qml/qmleffectmanifestparametersmodel.h"

#include <QModelIndex>

#include "effects/effectmanifest.h"

namespace mixxx {
namespace qml {
namespace {
const QHash<int, QByteArray> kRoleNames = {
        {QmlEffectManifestParametersModel::IdRole, "id"},
        {QmlEffectManifestParametersModel::NameRole, "name"},
        {QmlEffectManifestParametersModel::ShortNameRole, "shortName"},
        {QmlEffectManifestParametersModel::DescriptionRole, "description"},
        {QmlEffectManifestParametersModel::ControlHintRole, "controlHint"},
        {QmlEffectManifestParametersModel::ControlKeyRole, "controlKey"},
};
}

QmlEffectManifestParametersModel::QmlEffectManifestParametersModel(
        EffectManifestPointer pEffectManifest,
        QObject* parent)
        : QAbstractListModel(parent), m_pEffectManifest(pEffectManifest) {
}

QVariant QmlEffectManifestParametersModel::data(const QModelIndex& index, int role) const {
    const QList<EffectManifestParameterPointer>& parameters = m_pEffectManifest->parameters();
    if (index.row() >= parameters.size()) {
        return QVariant();
    }

    const EffectManifestParameterPointer pParameter = parameters.at(index.row());
    switch (role) {
    case QmlEffectManifestParametersModel::IdRole:
        return pParameter->id();
    case QmlEffectManifestParametersModel::NameRole:
        return pParameter->name();
    case QmlEffectManifestParametersModel::ShortNameRole:
        return pParameter->shortName();
    case QmlEffectManifestParametersModel::DescriptionRole:
        return pParameter->description();
    case QmlEffectManifestParametersModel::ControlHintRole:
        // TODO: Remove this cast, instead expose the enum directly using
        // Q_ENUM after #2618 has been merged.
        return static_cast<int>(pParameter->controlHint());
    case QmlEffectManifestParametersModel::ControlKeyRole: {
        // FIXME: Unfortunately our effect parameter controls are messed up.
        // Even though we only have a single, ordered list of parameters, our
        // COs splits up this list into two distinct list (`parameter_N` and
        // `button_parameter_M`), and their indices don't match up with the
        // original list.
        //
        // For example, if you have 4 parameters (A: Knob, B: Button, C: Knob,
        // D: Knob), one would expect the following control keys:
        //    parameter1 -> A
        //    button_parameter2 -> B
        //    parameter3 -> C
        //    parameter4 -> D
        //
        // But in reality, this will lead to the following control keys:
        //    parameter1 -> A
        //    button_parameter1 -> B
        //    parameter2 -> C
        //    parameter3 -> D
        //
        // This  makes it extremely hard to show the parameters in the correct
        // order, because you also need to know how many parameters of the same
        // type are in that list.
        //
        // Due to backwards compatibility, we cannot fix this. This attempts to
        // solve this problem by letting the user fetch the appropriate key
        // from the model.
        if (pParameter->controlHint() == EffectManifestParameter::ControlHint::UNKNOWN) {
            return QString();
        }
        const bool isButton = pParameter->controlHint() ==
                EffectManifestParameter::ControlHint::TOGGLE_STEPPING;
        int keyNumber = 1;
        for (int i = 0; i < index.row(); i++) {
            const EffectManifestParameterPointer pPrevParameter = parameters.at(i);
            if (pPrevParameter->controlHint() == EffectManifestParameter::ControlHint::UNKNOWN) {
                continue;
            }
            if (isButton ==
                    (pPrevParameter->controlHint() ==
                            EffectManifestParameter::ControlHint::
                                    TOGGLE_STEPPING)) {
                keyNumber++;
            }
        }

        return (isButton ? QStringLiteral("button_parameter%1")
                         : QStringLiteral("parameter%1"))
                .arg(QString::number(keyNumber));
    }
    default:
        return QVariant();
    }
}

int QmlEffectManifestParametersModel::rowCount(const QModelIndex& parent) const {
    if (parent.isValid()) {
        return 0;
    }

    // Add +1 because we also include "no effect" in the model
    return m_pEffectManifest->parameters().size();
}

QHash<int, QByteArray> QmlEffectManifestParametersModel::roleNames() const {
    return kRoleNames;
}

QVariant QmlEffectManifestParametersModel::get(int row) const {
    QModelIndex idx = index(row, 0);
    QVariantMap dataMap;
    for (auto it = kRoleNames.constBegin(); it != kRoleNames.constEnd(); it++) {
        dataMap.insert(it.value(), data(idx, it.key()));
    }
    return dataMap;
}

} // namespace qml
} // namespace mixxx