removed PrefixPath debug line
[opentx.git] / companion / src / flashfirmwaredialog.cpp
blob1e8dd4e8d93bd097a6ed98a7bd13fc74f937cede
1 #include "flashfirmwaredialog.h"
2 #include "ui_flashfirmwaredialog.h"
3 #include "appdata.h"
4 #include "converteeprom.h"
5 #include "eeprominterface.h"
6 #include "firmwareinterface.h"
7 #include "process_flash.h"
8 #include "helpers.h"
9 #include "hexinterface.h"
10 #include "progressdialog.h"
11 #include "radiointerface.h"
12 #include "splashlibrary.h"
13 #include "progresswidget.h"
15 #if defined WIN32 || !defined __GNUC__
16 #include <windows.h>
17 #define sleep(x) Sleep(x*1000)
18 #else
19 #include <unistd.h>
20 #endif
22 FlashFirmwareDialog::FlashFirmwareDialog(QWidget *parent):
23 QDialog(parent),
24 ui(new Ui::FlashFirmwareDialog),
25 fwName(g.profile[g.id()].fwName())
27 ui->setupUi(this);
29 if (!g.profile[g.id()].splashFile().isEmpty()){
30 imageSource = PROFILE;
31 imageFile = g.profile[g.id()].splashFile();
32 ui->useProfileSplash->setChecked(true);
34 else {
35 imageSource = FIRMWARE;
36 imageFile = "";
37 ui->useProfileSplash->setDisabled(true);
40 if (IS_TARANIS(GetEepromInterface()->getBoard())) {
41 // No backup on Taranis ... could be done if in massstorage
42 ui->backupEEprom->hide();
43 ui->backupEEprom->setCheckState(Qt::Unchecked);
45 else {
46 ui->backupEEprom->setCheckState(g.backupOnFlash() ? Qt::Checked : Qt::Unchecked);
49 QString backupPath = g.profile[g.id()].pBackupDir();
50 if (backupPath.isEmpty()) {
51 backupPath=g.backupDir();
53 if (backupPath.isEmpty() || !QDir(backupPath).exists()) {
54 ui->backupEEprom->setEnabled(false);
57 ui->checkHardwareCompatibility->setChecked(g.checkHardwareCompatibility());
59 updateUI();
61 resize(0, 0); // TODO needed?
64 FlashFirmwareDialog::~FlashFirmwareDialog()
66 delete ui;
69 void FlashFirmwareDialog::updateUI()
71 ui->firmwareFilename->setText(fwName);
72 ui->burnButton->setEnabled(QFile(fwName).exists());
74 FirmwareInterface firmware(fwName);
75 if (firmware.isValid()) {
76 ui->firmwareInfoFrame->show();
77 ui->date->setText(firmware.getDate() + " " + firmware.getTime());
78 ui->version->setText(firmware.getVersion());
79 ui->variant->setText(firmware.getEEpromId());
80 ui->date->setEnabled(true);
81 ui->version->setEnabled(true);
82 ui->variant->setEnabled(true);
83 if (firmware.hasSplash()) {
84 ui->splashFrame->show();
85 ui->splash->setFixedSize(firmware.getSplashWidth(), firmware.getSplashHeight());
87 else {
88 ui->splashFrame->hide();
91 else {
92 imageSource = FIRMWARE;
93 ui->firmwareInfoFrame->hide();
94 ui->splashFrame->hide();
97 QImage image;
98 switch(imageSource) {
99 case FIRMWARE:
100 ui->useFirmwareSplash->setChecked(true);
101 image = firmware.getSplash();
102 break;
103 case PROFILE:
104 ui->useProfileSplash->setChecked(true);
105 image.load(g.profile[g.id()].splashFile());
106 break;
107 case LIBRARY:
108 ui->useLibrarySplash->setChecked(true);
109 image.load(imageFile);
110 break;
111 case EXTERNAL:
112 ui->useExternalSplash->setChecked(true);
113 image.load(imageFile);
114 break;
117 if (!image.isNull()) {
118 ui->splash->setPixmap(makePixMap(image, g.profile[g.id()].fwType()));
122 void FlashFirmwareDialog::on_firmwareLoad_clicked()
124 QString fileName = QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g.flashDir(), FLASH_FILES_FILTER);
125 if (!fileName.isEmpty()) {
126 fwName = fileName;
127 if (!fwName.isEmpty() && !FirmwareInterface(fwName).isValid()) {
128 QMessageBox::warning(this, tr("Warning"), tr("%1 may not be a valid firmware file").arg(fwName));
130 updateUI();
134 void FlashFirmwareDialog::on_useFirmwareSplash_clicked()
136 FirmwareInterface firmware(fwName);
137 if (!firmware.isValid()) {
138 QMessageBox::warning(this, tr("Error"), tr( "The firmware file is not valid." ));
140 else if (!firmware.hasSplash()) {
141 QMessageBox::warning(this, tr("Error"), tr( "There is no start screen image in the firmware file." ));
143 else {
144 imageSource = FIRMWARE;
146 updateUI();
149 void FlashFirmwareDialog::on_useProfileSplash_clicked()
151 QString fileName = g.profile[g.id()].splashFile();
152 if (!fileName.isEmpty()) {
153 QImage image(fileName);
154 if (image.isNull()) {
155 QMessageBox::critical(this, tr("Error"), tr("Profile image %1 is invalid.").arg(fileName));
157 else {
158 imageSource = PROFILE;
161 updateUI();
164 void FlashFirmwareDialog::on_useExternalSplash_clicked()
166 QString supportedImageFormats;
167 for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
168 supportedImageFormats += QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex];
170 QString fileName = QFileDialog::getOpenFileName(this, tr("Open image file to use as radio start screen"), g.imagesDir(), tr("Images (%1)").arg(supportedImageFormats));
171 if (!fileName.isEmpty()){
172 g.imagesDir( QFileInfo(fileName).dir().absolutePath() );
173 QImage image(fileName);
174 if (image.isNull()) {
175 QMessageBox::critical(this, tr("Error"), tr("Image could not be loaded from %1").arg(fileName));
177 else{
178 imageSource = EXTERNAL;
179 imageFile = fileName;
182 updateUI();
185 void FlashFirmwareDialog::on_useLibrarySplash_clicked()
187 QString fileName;
188 splashLibrary *ld = new splashLibrary(this, &fileName);
189 ld->exec();
190 if (!fileName.isEmpty()) {
191 QImage image(fileName);
192 if (image.isNull()) {
193 QMessageBox::critical(this, tr("Error"), tr("The library image could not be loaded"));
195 else {
196 imageSource = LIBRARY;
197 imageFile = fileName;
200 updateUI();
203 void FlashFirmwareDialog::on_burnButton_clicked()
205 g.flashDir(QFileInfo(fwName).dir().absolutePath());
206 g.checkHardwareCompatibility(ui->checkHardwareCompatibility->isChecked());
207 g.backupOnFlash(ui->backupEEprom->isChecked());
209 qDebug() << "FlashFirmwareDialog: flashing" << fwName;
211 if (imageSource != FIRMWARE) {
212 // load the splash image
213 const QPixmap * pixmap = ui->splash->pixmap();
214 QImage image;
215 if (pixmap) {
216 image = pixmap->toImage().scaled(ui->splash->width(), ui->splash->height());
218 if (image.isNull()) {
219 QMessageBox::critical(this, tr("Warning"), tr("Splash image not found"));
220 return;
222 // write the customized firmware
223 QString tempFile;
224 if (getFileType(fwName) == FILE_TYPE_HEX)
225 tempFile = generateProcessUniqueTempFileName("flash.hex");
226 else
227 tempFile = generateProcessUniqueTempFileName("flash.bin");
228 qDebug() << "FlashFirmwareDialog: patching" << fwName << "with custom splash screen and saving to" << tempFile;
229 FirmwareInterface firmware(fwName);
230 firmware.setSplash(image);
231 if (firmware.save(tempFile) <= 0) {
232 QMessageBox::critical(this, tr("Warning"), tr("Cannot save customized firmware"));
233 return;
235 startFlash(tempFile);
237 else {
238 startFlash(fwName);
242 void FlashFirmwareDialog::on_cancelButton_clicked()
244 close();
247 void FlashFirmwareDialog::shrink()
249 resize(0, 0);
252 void FlashFirmwareDialog::startFlash(const QString &filename)
254 bool backup = g.backupOnFlash();
256 close();
258 ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
260 // check hardware compatibility if requested
261 if (g.checkHardwareCompatibility()) {
262 QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin");
263 if (!readFirmware(tempFirmware, progressDialog.progress())) {
264 QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
265 return;
267 FirmwareInterface previousFirmware(tempFirmware);
268 qunlink(tempFirmware);
269 FirmwareInterface newFirmware(filename);
270 qDebug() << "startFlash: checking firmware compatibility between " << tempFirmware << "and" << filename;
271 if (!newFirmware.isHardwareCompatible(previousFirmware)) {
272 QMessageBox::warning(this, tr("Firmware check failed"), tr("New firmware is not compatible with the one currently installed!"));
273 if (isTempFileName(filename)) {
274 qDebug() << "startFlash: removing temporary file" << filename;
275 qunlink(filename);
277 return;
281 // backup if requested
282 bool result = true;
283 QString backupFilename;
284 QString backupPath;
285 if (backup) {
286 backupPath = g.profile[g.id()].pBackupDir();
287 if (backupPath.isEmpty()) {
288 backupPath=g.backupDir();
290 backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
291 result = readEeprom(backupFilename, progressDialog.progress());
292 sleep(2);
295 // flash
296 result = (result && writeFirmware(filename, progressDialog.progress()));
298 // restore if backup requested
299 if (backup && result) {
300 sleep(2);
301 QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
302 if (!convertEEprom(backupFilename, restoreFilename, filename)) {
303 QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
304 restoreFilename = backupFilename;
306 if (!writeEeprom(restoreFilename, progressDialog.progress())) {
307 QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
311 progressDialog.progress()->setInfo(tr("Flashing done"));
312 progressDialog.exec();
314 if (isTempFileName(filename)) {
315 qDebug() << "startFlash: removing temporary file" << filename;
316 qunlink(filename);