5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "categorized.h"
22 #include "firmwares/opentx/opentxinterface.h"
24 bool CategorizedStorageFormat::load(RadioData
& radioData
)
26 QByteArray radioSettingsBuffer
;
27 if (!loadFile(radioSettingsBuffer
, "RADIO/radio.bin")) {
28 setError(tr("Can't extract RADIO/radio.bin"));
32 OpenTxEepromInterface
* loadInterface
= loadRadioSettingsFromByteArray(radioData
.generalSettings
, radioSettingsBuffer
);
37 board
= loadInterface
->getBoard();
39 QByteArray modelsListBuffer
;
40 if (!loadFile(modelsListBuffer
, "RADIO/models.txt")) {
41 setError(tr("Can't extract RADIO/models.txt"));
45 QList
<QByteArray
> lines
= modelsListBuffer
.split('\n');
47 int categoryIndex
= -1;
48 foreach (const QByteArray
& lineArray
, lines
) {
49 QString line
= QString(lineArray
).trimmed();
50 if (line
.isEmpty()) continue;
51 // qDebug() << "parsing line" << line;
53 if (line
.startsWith('[') && line
.endsWith(']')) {
54 // ignore categories for boards that do not support them
55 if (getCurrentFirmware()->getCapability(HasModelCategories
)) {
56 QString name
= line
.mid(1, line
.size() - 2);
57 CategoryData
category(qPrintable(name
));
58 radioData
.categories
.push_back(category
);
60 qDebug() << "added category" << name
;
65 // determine if we have a model number
66 QStringList parts
= line
.split(QRegExp("\\s+"), QString::SkipEmptyParts
);
67 if (parts
.size() == 2) {
69 int modelNumber
= parts
[0].toInt();
70 if (modelNumber
> 0 && modelNumber
> modelIndex
&& modelNumber
< getCurrentFirmware()->getCapability(Models
)) {
71 modelIndex
= modelNumber
;
72 qDebug() << "advanced model number to" << modelIndex
;
75 if (modelNumber
!= modelIndex
) qDebug() << "Invalid model number" << parts
[0];
79 if (parts
.size() == 1) {
80 // parse model file name and load
81 QString fileName
= parts
[0];
82 qDebug() << "Loading model from file" << fileName
<< "into slot" << modelIndex
;
83 QByteArray modelBuffer
;
84 if (!loadFile(modelBuffer
, QString("MODELS/%1").arg(fileName
))) {
85 setError(tr("Can't extract %1").arg(fileName
));
88 if ((int)radioData
.models
.size() <= modelIndex
) {
89 radioData
.models
.resize(modelIndex
+ 1);
91 if (!loadModelFromByteArray(radioData
.models
[modelIndex
], modelBuffer
)) {
92 setError(tr("Error loading models"));
95 strncpy(radioData
.models
[modelIndex
].filename
, qPrintable(fileName
), sizeof(radioData
.models
[modelIndex
].filename
));
96 if (IS_HORUS(board
) && !strcmp(radioData
.generalSettings
.currModelFilename
, qPrintable(fileName
))) {
97 radioData
.generalSettings
.currModelIndex
= modelIndex
;
98 qDebug() << "currModelIndex =" << modelIndex
;
100 if (getCurrentFirmware()->getCapability(HasModelCategories
)) {
101 radioData
.models
[modelIndex
].category
= categoryIndex
;
103 radioData
.models
[modelIndex
].used
= true;
109 // TODO add to parsing report
110 qDebug() << "Invalid line" <<line
;
116 bool CategorizedStorageFormat::write(const RadioData
& radioData
)
118 QByteArray modelsList
; // models.txt
119 QByteArray radioSettingsData
; // radio.bin
120 size_t numModels
= radioData
.models
.size();
121 size_t numCategories
= radioData
.categories
.size();
122 std::vector
<std::vector
<QString
>> sortedModels(numCategories
);
124 writeRadioSettingsToByteArray(radioData
.generalSettings
, radioSettingsData
);
125 if (!writeFile(radioSettingsData
, "RADIO/radio.bin")) {
129 for (size_t m
=0; m
<numModels
; m
++) {
130 const ModelData
& model
= radioData
.models
[m
];
131 if (model
.isEmpty()) continue;
133 QString modelFilename
= QString("MODELS/%1").arg(model
.filename
);
134 QByteArray modelData
;
135 writeModelToByteArray(model
, modelData
);
136 if (!writeFile(modelData
, modelFilename
)) {
140 // For firmware that doesn't support categories, we can just construct
141 // models.txt as we iterate thru the models vector. For firmware that does
142 // support categories, we have a bit of work to do in order to sort the
143 // models first by category index, so we use the sortedModels data
144 // structure to do that.
145 if (!getCurrentFirmware()->getCapability(HasModelCategories
)) {
146 // Use format with model number and file name. This is needed because
147 // radios without category support can have unused model slots
148 modelsList
.append(QString("%1 %2\n").arg(m
).arg(model
.filename
));
150 sortedModels
[model
.category
].push_back(QString("%1\n").arg(model
.filename
));
154 if (getCurrentFirmware()->getCapability(HasModelCategories
)) {
155 for (size_t c
=0; c
<numCategories
; c
++) {
156 modelsList
.append(QString().sprintf("[%s]\n", radioData
.categories
[c
].name
));
157 numModels
= sortedModels
[c
].size();
158 for (size_t m
=0; m
<numModels
; m
++) {
159 modelsList
.append(sortedModels
[c
][m
]);
164 if (!writeFile(modelsList
, "RADIO/models.txt")) {