• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mcallegari / qlcplus / 21760395819

06 Feb 2026 05:52PM UTC coverage: 33.994% (-0.08%) from 34.078%
21760395819

push

github

mcallegari
Back to 5.2.1 debug

17635 of 51877 relevant lines covered (33.99%)

19809.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.47
/engine/src/keypadparser.cpp
1
/*
2
  Q Light Controller Plus
3
  keypadparser.cpp
4

5
  Copyright (c) Massimo Callegari
6

7
  Licensed under the Apache License, Version 2.0 (the "License");
8
  you may not use this file except in compliance with the License.
9
  You may obtain a copy of the License at
10

11
      http://www.apache.org/licenses/LICENSE-2.0.txt
12

13
  Unless required by applicable law or agreed to in writing, software
14
  distributed under the License is distributed on an "AS IS" BASIS,
15
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
  See the License for the specific language governing permissions and
17
  limitations under the License.
18
*/
19

20
#include <cmath>
21

22
#include "keypadparser.h"
23
#include "qlcmacros.h"
24
#include "universe.h"
25

26
KeyPadParser::KeyPadParser()
1✔
27
{
28
}
1✔
29

30
QList<SceneValue> KeyPadParser::parseCommand(Doc *doc, QString command,
12✔
31
                                             QByteArray &uniData)
32
{
33
    QList<SceneValue> values;
12✔
34
    if (doc == NULL || command.isEmpty())
12✔
35
        return values;
×
36

37
    QStringList tokens = command.split(" ");
12✔
38

39
    int lastCommand = CommandNone;
12✔
40
    quint32 fromChannel = 0;
12✔
41
    quint32 toChannel = 0;
12✔
42
    quint32 byChannel = 1;
12✔
43
    bool channelSet = false;
12✔
44
    float fromValue = 0;
12✔
45
    float toValue = 0;
12✔
46
    int thruCount = 0;
12✔
47

48
    foreach (QString token, tokens)
62✔
49
    {
50
        if (token.isEmpty())
50✔
51
            continue;
×
52

53
        if (token == "AT")
50✔
54
        {
55
            lastCommand = CommandAT;
7✔
56
        }
57
        else if (token == "THRU")
43✔
58
        {
59
            lastCommand = CommandTHRU;
7✔
60
        }
61
        else if (token == "FULL")
36✔
62
        {
63
            toValue = 255;
3✔
64
            lastCommand = CommandFULL;
3✔
65
        }
66
        else if (token == "ZERO")
33✔
67
        {
68
            toValue = 0;
2✔
69
            lastCommand = CommandZERO;
2✔
70
        }
71
        else if (token == "BY")
31✔
72
        {
73
            lastCommand = CommandBY;
3✔
74
        }
75
        else if (token == "+")
28✔
76
        {
77
            lastCommand = CommandPlus;
×
78
        }
79
        else if (token == "-")
28✔
80
        {
81
            lastCommand = CommandMinus;
×
82
        }
83
        else if (token == "+%")
28✔
84
        {
85
            lastCommand = CommandPlusPercent;
1✔
86
        }
87
        else if (token == "-%")
27✔
88
        {
89
            lastCommand = CommandMinusPercent;
1✔
90
        }
91
        else if (token == "%")
26✔
92
        {
93
            if (lastCommand == CommandPlus)
×
94
                lastCommand = CommandPlusPercent;
×
95
            else if (lastCommand == CommandMinus)
×
96
                lastCommand = CommandMinusPercent;
×
97
        }
98
        else
99
        {
100
            // most likely a number
101
            bool ok = false;
26✔
102
            int number = token.toUInt(&ok);
26✔
103

104
            if (ok == false)
26✔
105
                continue;
×
106

107
            switch (lastCommand)
26✔
108
            {
109
                case CommandNone:
9✔
110
                    // no command: this is a channel number
111
                    if (number <= 0)
9✔
112
                        break;
×
113

114
                    fromChannel = number;
9✔
115
                    toChannel = fromChannel;
9✔
116
                    fromValue = uchar(uniData.at(number - 1));
9✔
117
                    toValue = fromValue;
9✔
118
                    channelSet = true;
9✔
119
                break;
9✔
120
                case CommandAT:
5✔
121
                    fromValue = float(number);
5✔
122
                    toValue = fromValue;
5✔
123
                break;
5✔
124
                case CommandTHRU:
7✔
125
                    if (thruCount == 0)
7✔
126
                        toChannel = number;
6✔
127
                    else
128
                        toValue = float(number);
1✔
129
                    thruCount++;
7✔
130
                break;
7✔
131
                case CommandFULL:
×
132
                    fromValue = 255;
×
133
                    toValue = 255;
×
134
                break;
×
135
                case CommandZERO:
×
136
                    fromValue = 0;
×
137
                    toValue = 0;
×
138
                break;
×
139
                case CommandBY:
3✔
140
                    byChannel = number;
3✔
141
                break;
3✔
142
                case CommandPlus:
×
143
                case CommandMinus:
144
                    toValue = number;
×
145
                break;
×
146
                case CommandPlusPercent:
2✔
147
                case CommandMinusPercent:
148
                    toValue = float(number) / 100.0;
2✔
149
                break;
2✔
150
            }
151
        }
152
    }
62✔
153

154
    /** handle the case where channel(s) are not specified.
155
     *  Compose a list of values based on the last channel list */
156

157
    if (channelSet == false)
12✔
158
    {
159
        if (m_channels.isEmpty())
3✔
160
            return values;
×
161

162
        for (int i = 0; i < m_channels.count(); i++)
27✔
163
        {
164
            SceneValue scv;
24✔
165

166
            scv.channel = m_channels.at(i);
24✔
167
            scv.value = toValue;
24✔
168
            values.append(scv);
24✔
169
        }
24✔
170

171
        return values;
3✔
172
    }
173
    else
174
    {
175
        m_channels.clear();
9✔
176
    }
177

178
    float valueDelta = 0;
9✔
179
    if (toValue != fromValue)
9✔
180
    {
181
        valueDelta = (float(toChannel) - float(fromChannel)) / float(byChannel);
5✔
182
        valueDelta = (float(toValue) - float(fromValue)) / valueDelta;
5✔
183
    }
184

185
    for (quint32 i = fromChannel - 1; i <= toChannel - 1; i += byChannel)
61✔
186
    {
187
        uchar uniValue = 0;
52✔
188
        SceneValue scv;
52✔
189

190
        if (i >= UNIVERSE_SIZE)
52✔
191
            continue;
×
192

193
        if (quint32(uniData.length()) > i)
52✔
194
            uniValue = uchar(uniData.at(i));
52✔
195

196
        scv.channel = i;
52✔
197
        if (lastCommand == CommandPlus)
52✔
198
            scv.value = CLAMP(uniValue + toValue, 0, 255);
×
199
        else if (lastCommand == CommandMinus)
52✔
200
            scv.value = CLAMP(uniValue - toValue, 0, 255);
×
201
        else if (lastCommand == CommandPlusPercent)
52✔
202
            scv.value = CLAMP(lrintf(uniValue * (1.0 + toValue)), 0, 255);
6✔
203
        else if (lastCommand == CommandMinusPercent)
46✔
204
            scv.value = CLAMP(lrintf(uniValue - (float(uniValue) * toValue)), 0, 255);
6✔
205
        else if (lastCommand == CommandZERO)
40✔
206
            scv.value = 0;
1✔
207
        else if (lastCommand == CommandFULL)
39✔
208
            scv.value = 255;
11✔
209
        else
210
            scv.value = uchar(fromValue);
28✔
211

212
        if (m_channels.contains(scv.channel) == false)
52✔
213
            m_channels.append(scv.channel);
52✔
214

215
        values.append(scv);
52✔
216
        fromValue += valueDelta;
52✔
217
    }
52✔
218

219
    return values;
9✔
220
}
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc