feat(cpn): add detailed progress to read and write radio (#7450)
This commit is contained in:
@@ -569,26 +569,43 @@ bool readSettings(const QString &filename, ProgressWidget *progress)
|
||||
bool readSettingsSDCard(const QString &filename, ProgressWidget *progress,
|
||||
bool fromRadio)
|
||||
{
|
||||
if (progress) {
|
||||
progress->setValue(0);
|
||||
progress->setMaximum(100);
|
||||
progress->updateInfoAndMessages(TR("Initialising..."));
|
||||
}
|
||||
|
||||
QString radioPath;
|
||||
|
||||
if (fromRadio) {
|
||||
radioPath = findMassStoragePath("RADIO", true, progress);
|
||||
qDebug() << "Searching for SD card, found" << radioPath;
|
||||
} else {
|
||||
radioPath = g.currentProfile().sdPath();
|
||||
|
||||
if (!QFile::exists(radioPath % "/RADIO"))
|
||||
radioPath.clear();
|
||||
}
|
||||
|
||||
if (radioPath.isEmpty()) {
|
||||
QMessageBox::critical(progress, CPN_STR_TTL_ERROR, TR("Unable to find SD card!"));
|
||||
const QString msg(TR("Unable to find SD card!"));
|
||||
if (progress)
|
||||
progress->addMessage(msg, QtFatalMsg);
|
||||
else
|
||||
QMessageBox::critical(nullptr, CPN_STR_TTL_ERROR, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (progress)
|
||||
progress->setInfo(TR("Loading models and settings"));
|
||||
|
||||
RadioData radioData;
|
||||
Storage inputStorage(radioPath);
|
||||
inputStorage.setProgress(progress);
|
||||
|
||||
if (!inputStorage.load(radioData)) {
|
||||
QString errorMsg = inputStorage.error();
|
||||
|
||||
if (errorMsg.isEmpty())
|
||||
errorMsg = TR("Failed to read Models and Settings from")
|
||||
% QDir::toNativeSeparators(radioPath);
|
||||
@@ -597,10 +614,15 @@ bool readSettingsSDCard(const QString &filename, ProgressWidget *progress,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (progress)
|
||||
progress->addMessage(TR("Writing models and settings to temporary file..."));
|
||||
|
||||
Storage outputStorage(filename);
|
||||
outputStorage.setProgress(progress);
|
||||
|
||||
if (!outputStorage.write(radioData)) {
|
||||
QMessageBox::critical(progress, CPN_STR_TTL_ERROR,
|
||||
TR("Failed to write Models and Setting file") % " "
|
||||
TR("Failed to write Models and Setting to") % " "
|
||||
% QDir::toNativeSeparators(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -525,23 +525,13 @@ void MainWindow::customizeSplash()
|
||||
|
||||
void MainWindow::writeSettings()
|
||||
{
|
||||
StatusDialog *status = new StatusDialog(this, tr("Writing models and settings to radio"), tr("In progress..."), 400);
|
||||
|
||||
if (activeMdiChild())
|
||||
activeMdiChild()->writeSettings(status);
|
||||
|
||||
delete status;
|
||||
activeMdiChild()->writeModelsSettings();
|
||||
}
|
||||
|
||||
void MainWindow::readSettings()
|
||||
{
|
||||
Board::Type board = getCurrentBoard();
|
||||
QString tempFile;
|
||||
if (Boards::getCapability(board, Board::HasSDCard))
|
||||
tempFile = generateProcessUniqueTempFileName("temp.etx");
|
||||
else
|
||||
tempFile = generateProcessUniqueTempFileName("temp.bin");
|
||||
|
||||
QString tempFile(generateProcessUniqueTempFileName("temp.etx"));
|
||||
qDebug() << "Reading models and settings into temp file: " << tempFile;
|
||||
|
||||
if (readSettingsFromRadio(tempFile)) {
|
||||
@@ -568,16 +558,21 @@ bool MainWindow::readFirmwareFromRadio(const QString & filename)
|
||||
|
||||
bool MainWindow::readSettingsFromRadio(const QString & filename)
|
||||
{
|
||||
ProgressDialog progressDialog(this, tr("Read Models and Settings from Radio"), CompanionIcon("read_eeprom.png"));
|
||||
bool result = ::readSettings(filename, progressDialog.progress());
|
||||
if (!result) {
|
||||
if (!progressDialog.isEmpty()) {
|
||||
progressDialog.exec();
|
||||
}
|
||||
}
|
||||
else {
|
||||
statusBar()->showMessage(tr("Models and Settings read"), 2000);
|
||||
}
|
||||
ProgressDialog dlg(this, tr("Read Models and Settings from Radio"), CompanionIcon("read_eeprom.png"));
|
||||
ProgressWidget * progress = dlg.progress();
|
||||
progress->lock(false);
|
||||
dlg.setProcessStarted();
|
||||
progress->setInfo(tr("Initialising"));
|
||||
|
||||
bool result = ::readSettings(filename, progress);
|
||||
|
||||
dlg.setProcessStopped();
|
||||
progress->setValue(progress->maximum());
|
||||
progress->updateInfoAndMessages(tr("Finished %1").arg(result ? tr("successfully") : tr("with errors")));
|
||||
progress->refresh();
|
||||
QApplication::processEvents();
|
||||
dlg.exec();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1488,52 +1483,30 @@ void MainWindow::chooseProfile()
|
||||
|
||||
void MainWindow::readSettingsSDPath()
|
||||
{
|
||||
ProgressDialog progressDialog(this, tr("Read Models and Settings from Profile SD Path"), CompanionIcon("read_eeprom.png"));
|
||||
QString tempFile;
|
||||
tempFile = generateProcessUniqueTempFileName("temp.etx");
|
||||
qDebug() << "Reading models and settings from SD path into temp file: " << tempFile;
|
||||
|
||||
if (readSettingsFromSDPath(tempFile)) {
|
||||
bool result = ::readSettingsSDCard(tempFile, progressDialog.progress(), false);
|
||||
|
||||
if (!result) {
|
||||
if (!progressDialog.isEmpty())
|
||||
progressDialog.exec();
|
||||
} else {
|
||||
statusBar()->showMessage(tr("Models and Settings read"), 2000);
|
||||
MdiChild * child = createMdiChild();
|
||||
child->newFile();
|
||||
child->loadFile(tempFile, false);
|
||||
child->show();
|
||||
qunlink(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::readSettingsFromSDPath(const QString & filename)
|
||||
{
|
||||
ProgressDialog progressDialog(this, tr("Read Models and Settings from SD path"), CompanionIcon("read_eeprom.png"));
|
||||
bool result = ::readSettingsSDCard(filename, progressDialog.progress(), false);
|
||||
if (!result) {
|
||||
if (!progressDialog.isEmpty()) {
|
||||
progressDialog.exec();
|
||||
}
|
||||
}
|
||||
else {
|
||||
statusBar()->showMessage(tr("Models and Settings read"), 2000);
|
||||
}
|
||||
return result;
|
||||
qunlink(tempFile);
|
||||
}
|
||||
|
||||
void MainWindow::writeSettingsSDPath()
|
||||
{
|
||||
if (activeMdiChild()) {
|
||||
int cnt = activeMdiChild()->invalidModels();
|
||||
|
||||
if (cnt) {
|
||||
QMessageBox::critical(this, tr("Write Models and Settings to SD Path"),
|
||||
tr("Operation aborted: %1 models have errors that may affect operation.\n%2")
|
||||
.arg(cnt)
|
||||
.arg(activeMdiChild()->modelErrorsList().join("\n")));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
StatusDialog *status = new StatusDialog(this, tr("Writing models and settings to SD path"), tr("In progress..."), 400);
|
||||
activeMdiChild()->writeSettings(status, false);
|
||||
delete status;
|
||||
}
|
||||
if (activeMdiChild())
|
||||
activeMdiChild()->writeModelsSettings(false);
|
||||
}
|
||||
|
||||
bool MainWindow::isSDPathValid()
|
||||
|
||||
@@ -154,7 +154,6 @@ class MainWindow : public QMainWindow
|
||||
|
||||
bool readSettingsFromRadio(const QString & filename);
|
||||
bool readFirmwareFromRadio(const QString & filename);
|
||||
bool readSettingsFromSDPath(const QString & filename);
|
||||
|
||||
bool checkProfileRadioExists(int profId);
|
||||
|
||||
|
||||
+53
-18
@@ -34,6 +34,8 @@
|
||||
#include "filtereditemmodels.h"
|
||||
#include "labels.h"
|
||||
#include "firmwares/edgetx/edgetxinterface.h"
|
||||
#include "progress/progressdialog.h"
|
||||
#include "progress/progresswidget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ExportableTableView>
|
||||
@@ -1424,11 +1426,19 @@ bool MdiChild::saveAs(bool isNew)
|
||||
return saveFile(fileName, true);
|
||||
}
|
||||
|
||||
bool MdiChild::saveFile(const QString & filename, bool setCurrent)
|
||||
bool MdiChild::saveFile(const QString & filename, bool setCurrent, bool toRadio)
|
||||
{
|
||||
radioData.fixModelFilenames();
|
||||
Storage storage(filename);
|
||||
bool result = storage.write(radioData);
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (toRadio)
|
||||
result = saveFileProgress(filename);
|
||||
else {
|
||||
Storage storage(filename);
|
||||
result = storage.write(radioData);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
@@ -1451,6 +1461,29 @@ bool MdiChild::saveFile(const QString & filename, bool setCurrent)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdiChild::saveFileProgress(const QString & filename)
|
||||
{
|
||||
ProgressDialog dlg(parentWidget(), tr("Write Models and Settings"),
|
||||
CompanionIcon("write_eeprom.png"));
|
||||
|
||||
ProgressWidget * progress = dlg.progress();
|
||||
progress->lock(false);
|
||||
dlg.setProcessStarted();
|
||||
progress->updateInfoAndMessages(tr("Initialising"));
|
||||
|
||||
Storage storage(filename);
|
||||
storage.setProgress(progress);
|
||||
bool result = storage.write(radioData);
|
||||
|
||||
dlg.setProcessStopped();
|
||||
progress->updateInfoAndMessages(tr("Finished %1").arg(result ? tr("successfully") : tr("with errors")));
|
||||
progress->setValue(progress->maximum());
|
||||
progress->refresh();
|
||||
QApplication::processEvents();
|
||||
dlg.exec();
|
||||
return result;
|
||||
}
|
||||
|
||||
void MdiChild::closeFile(bool force)
|
||||
{
|
||||
forceCloseFlag = force;
|
||||
@@ -1573,7 +1606,7 @@ int MdiChild::askQuestion(const QString & msg, QMessageBox::StandardButtons butt
|
||||
return QMessageBox::question(this, CPN_STR_APP_NAME, msg, buttons, defaultButton);
|
||||
}
|
||||
|
||||
void MdiChild::writeSettings(StatusDialog * status, bool toRadio)
|
||||
void MdiChild::writeModelsSettings(bool toRadio)
|
||||
{
|
||||
// safeguard as the menu actions are enabled
|
||||
int cnt = radioData.invalidModels();
|
||||
@@ -1605,25 +1638,27 @@ void MdiChild::writeSettings(StatusDialog * status, bool toRadio)
|
||||
|
||||
if (toRadio) {
|
||||
radioPath = findMassStoragePath("RADIO", true);
|
||||
qDebug() << "Searching for SD card, found" << radioPath;
|
||||
if (radioPath.isEmpty()) {
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Unable to find radio SD card!"));
|
||||
return;
|
||||
}
|
||||
qDebug() << "SD card found" << radioPath;
|
||||
} else {
|
||||
radioPath = g.currentProfile().sdPath();
|
||||
if (!QFile(radioPath % "/RADIO").exists())
|
||||
radioPath.clear();
|
||||
if (!QFile(radioPath % "/RADIO").exists()) {
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Unable to find SD path '%1'!")
|
||||
.arg(QDir::toNativeSeparators(radioPath % "/RADIO")));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (radioPath.isEmpty()) {
|
||||
qDebug() << "Radio SD card not found";
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Unable to find SD card!"));
|
||||
return;
|
||||
}
|
||||
bool ret = saveFile(radioPath, false, toRadio);
|
||||
|
||||
if (saveFile(radioPath, false)) {
|
||||
status->hide();
|
||||
QMessageBox::information(this, CPN_STR_TTL_INFO, tr("Models and settings written"));
|
||||
} else {
|
||||
status->hide();
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Error writing models and settings!"));
|
||||
if (!toRadio) {
|
||||
if (ret)
|
||||
QMessageBox::information(this, CPN_STR_TTL_INFO, tr("Models and settings written"));
|
||||
else
|
||||
QMessageBox::critical(this, CPN_STR_TTL_ERROR, tr("Error writing models and settings!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,9 +114,10 @@ class MdiChild : public QWidget
|
||||
bool loadFile(const QString & fileName, bool resetCurrentFile=true);
|
||||
bool save();
|
||||
bool saveAs(bool isNew=false);
|
||||
bool saveFile(const QString & fileName, bool setCurrent=true);
|
||||
bool saveFile(const QString & fileName, bool setCurrent = true, bool toRadio = false);
|
||||
bool saveFileProgress(const QString & fileName);
|
||||
void closeFile(bool force = false);
|
||||
void writeSettings(StatusDialog * status, bool toRadio = true);
|
||||
void writeModelsSettings(bool toRadio = true);
|
||||
void print(int model=-1, const QString & filename="");
|
||||
void onFirmwareChanged();
|
||||
|
||||
|
||||
@@ -820,5 +820,6 @@ void SetupPanel::loadImagePreview()
|
||||
else
|
||||
ui->imagePreview->clear();
|
||||
|
||||
}
|
||||
} else
|
||||
ui->imagePreview->clear();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ ProgressWidget::ProgressWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ProgressWidget),
|
||||
m_forceOpen(false),
|
||||
m_hasDetails(false)
|
||||
m_hasDetails(false),
|
||||
m_logLevel(QtInfoMsg)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->info->hide();
|
||||
@@ -52,6 +53,7 @@ ProgressWidget::ProgressWidget(QWidget *parent) :
|
||||
newFont.setPointSize(9);
|
||||
#endif
|
||||
ui->textEdit->setFont(newFont);
|
||||
QTimer::singleShot(0, [this]() { this->refresh(); });
|
||||
}
|
||||
|
||||
ProgressWidget::~ProgressWidget()
|
||||
@@ -67,6 +69,7 @@ void ProgressWidget::stop()
|
||||
void ProgressWidget::clearDetails() const
|
||||
{
|
||||
ui->textEdit->clear();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void ProgressWidget::forceOpen()
|
||||
@@ -74,17 +77,20 @@ void ProgressWidget::forceOpen()
|
||||
m_forceOpen = true;
|
||||
ui->checkBox->hide();
|
||||
toggleDetails();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void ProgressWidget::setInfo(const QString &text)
|
||||
{
|
||||
ui->info->show();
|
||||
ui->info->setText(text);
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void ProgressWidget::setMaximum(int value)
|
||||
{
|
||||
ui->progressBar->setMaximum(value);
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
int ProgressWidget::maximum()
|
||||
@@ -95,6 +101,7 @@ int ProgressWidget::maximum()
|
||||
void ProgressWidget::setValue(int value)
|
||||
{
|
||||
ui->progressBar->setValue(value);
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void ProgressWidget::addText(const QString &text, const bool richText, const bool updateLast)
|
||||
@@ -143,6 +150,15 @@ void ProgressWidget::addHtml(const QString & text, const bool updateLast)
|
||||
|
||||
void ProgressWidget::addMessage(const QString & text, const int & type, const bool richText, const bool updateLast)
|
||||
{
|
||||
// The allowed predicate only lets QtInfoMsg through when m_logLevel is QtDebugMsg or QtInfoMsg;
|
||||
// when m_logLevel is QtWarningMsg, QtCriticalMsg, or QtFatalMsg, QtInfoMsg is always filtered out
|
||||
const bool allowed = (m_logLevel == QtDebugMsg) ||
|
||||
(m_logLevel == QtInfoMsg && type > QtDebugMsg) ||
|
||||
(type < QtInfoMsg && type >= m_logLevel);
|
||||
|
||||
if (!allowed)
|
||||
return;
|
||||
|
||||
QString color;
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
@@ -171,6 +187,8 @@ void ProgressWidget::addMessage(const QString & text, const int & type, const bo
|
||||
else {
|
||||
addHtml(QString("<font color=%1>").arg(color) % text % "</font><br>", updateLast);
|
||||
}
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
QString ProgressWidget::getText() const
|
||||
@@ -233,6 +251,7 @@ void ProgressWidget::refresh()
|
||||
ui->info->update();
|
||||
ui->progressBar->update();
|
||||
ui->textEdit->update();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
void ProgressWidget::updateInfoAndMessages(const QString & text, const int & type, const bool richText)
|
||||
|
||||
@@ -57,6 +57,7 @@ class ProgressWidget : public QWidget
|
||||
void refresh();
|
||||
void updateInfoAndMessages(const QString & text, const int & type = QtInfoMsg, const bool richText = false);
|
||||
void updateLastMessage(const QString & text, const int & type = QtInfoMsg, const bool richText = false);
|
||||
void setLoggingLevel(const int & level = QtInfoMsg) { m_logLevel = level; }
|
||||
|
||||
signals:
|
||||
void detailsToggled();
|
||||
@@ -72,4 +73,5 @@ class ProgressWidget : public QWidget
|
||||
Ui::ProgressWidget *ui;
|
||||
bool m_forceOpen;
|
||||
bool m_hasDetails;
|
||||
int m_logLevel;
|
||||
};
|
||||
|
||||
@@ -31,18 +31,17 @@ bool EtxFormat::load(RadioData & radioData)
|
||||
QFile file(filename);
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
setError(tr("Error opening file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
fatalMsg(tr("Error opening file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray archiveContents = file.readAll();
|
||||
|
||||
qDebug() << "File" << filename << "read, size:" << archiveContents.size();
|
||||
|
||||
// qDebug() << "File" << filename << "read, size:" << archiveContents.size();
|
||||
// open zip file
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
|
||||
if (!mz_zip_reader_init_mem(&zip_archive, archiveContents.data(), archiveContents.size(), 0)) {
|
||||
qDebug() << tr("Error opening EdgeTX archive %1").arg(filename);
|
||||
fatalMsg(tr("Error opening EdgeTX archive %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -53,37 +52,41 @@ bool EtxFormat::load(RadioData & radioData)
|
||||
|
||||
bool EtxFormat::write(RadioData & radioData)
|
||||
{
|
||||
qDebug() << "Saving to archive" << filename;
|
||||
// qDebug() << "Saving to archive" << filename;
|
||||
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
if (!mz_zip_writer_init_heap(&zip_archive, 0, MZ_ALLOCATION_SIZE)) {
|
||||
setError(tr("Error initializing EdgeTX archive writer"));
|
||||
fatalMsg(tr("Error initializing EdgeTX archive writer"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = LabelsStorageFormat::write(radioData);
|
||||
|
||||
if (result) {
|
||||
// finalize archive and get contents
|
||||
char * archiveContents;
|
||||
size_t archiveSize;
|
||||
|
||||
if (mz_zip_writer_finalize_heap_archive(&zip_archive, (void **)&archiveContents, &archiveSize)) {
|
||||
qDebug() << "Archive size" << archiveSize;
|
||||
// qDebug() << "Archive size" << archiveSize;
|
||||
// write contents to file
|
||||
QFile file(filename);
|
||||
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
qint64 len = file.write(archiveContents, archiveSize);
|
||||
|
||||
if (len != (qint64)archiveSize) {
|
||||
setError(tr("Error writing file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
fatalMsg(tr("Error writing file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
setError(tr("Error creating EdgeTX file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
fatalMsg(tr("Error creating EdgeTX file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
setError(tr("Error creating EdgeTX archive"));
|
||||
fatalMsg(tr("Error creating EdgeTX archive"));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +102,7 @@ bool EtxFormat::loadFile(QByteArray & filedata, const QString & filename, bool o
|
||||
|
||||
if (!data) return optional;
|
||||
|
||||
qDebug() << QString("Extracted file %1, size=%2").arg(filename).arg(size);
|
||||
//qDebug() << QString("Extracted file %1, size=%2").arg(filename).arg(size);
|
||||
filedata.clear();
|
||||
filedata.append((char *)data, size);
|
||||
mz_free(data);
|
||||
@@ -122,28 +125,28 @@ bool EtxFormat::loadImageFile(const QString & filename, bool optional)
|
||||
|
||||
if (imgfile.open(QIODevice::WriteOnly)) {
|
||||
if (imgfile.write(ba) != (qint64)size) {
|
||||
qDebug() << "Image data written does not match expected";
|
||||
fatalMsg(tr("Image data written does not match expected"));
|
||||
return false;
|
||||
}
|
||||
|
||||
imgfile.close();
|
||||
} else {
|
||||
setError(tr("Unable to write %1 to cache").arg(filename));
|
||||
fatalMsg(tr("Unable to write %1 to cache").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << QString("Extracted file %1, size=%2").arg(srcpath).arg(size);
|
||||
statusMsg(tr("Extracted image: %1").arg(srcpath));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EtxFormat::writeFile(const QByteArray & filedata, const QString & filename)
|
||||
{
|
||||
if (!mz_zip_writer_add_mem(&zip_archive, filename.toStdString().c_str(), filedata.data(), filedata.size(), MZ_DEFAULT_LEVEL)) {
|
||||
setError(tr("Error adding %1 to archive").arg(filename));
|
||||
fatalMsg(tr("Error adding %1 to archive").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "File" << filename << "written, size:" << filedata.size();
|
||||
//qDebug() << "File" << filename << "written, size:" << filedata.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -159,21 +162,22 @@ bool EtxFormat::writeImageFile(const QString & filename)
|
||||
ba.append(imgfile.readAll());
|
||||
imgfile.close();
|
||||
} else {
|
||||
setError(tr("Unable to open image %1").arg(filename));
|
||||
fatalMsg(tr("Unable to open image %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString destpath("IMAGES/" % filename);
|
||||
|
||||
if (!mz_zip_writer_add_mem(&zip_archive, destpath.toStdString().c_str(), ba.data(), ba.size(), MZ_DEFAULT_LEVEL)) {
|
||||
setError(tr("Error adding file %1").arg(destpath));
|
||||
fatalMsg(tr("Error adding file: %1").arg(destpath));
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "File" << destpath << "written, size:" << ba.size();
|
||||
statusMsg(tr("File written: %1").arg(filename));
|
||||
return true;
|
||||
}
|
||||
|
||||
fatalMsg(tr("No application image cache"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -183,6 +187,7 @@ bool EtxFormat::getFileList(std::list<std::string>& filelist)
|
||||
if (count == 0) return false;
|
||||
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat)) continue;
|
||||
if (mz_zip_reader_is_file_a_directory(&zip_archive, i)) continue;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "labeled.h"
|
||||
#include "firmwares/opentx/opentxinterface.h"
|
||||
#include "firmwares/edgetx/edgetxinterface.h"
|
||||
#include "progressdialog.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
@@ -35,7 +36,14 @@ StorageType LabelsStorageFormat::probeFormat()
|
||||
|
||||
bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
{
|
||||
int steps = 2; // initialisation and load radio.yml
|
||||
bool hasLabels = getCurrentFirmware()->getCapability(HasModelLabels);
|
||||
|
||||
if (hasLabels)
|
||||
steps++;
|
||||
|
||||
StorageType st = getStorageType(filename);
|
||||
|
||||
if (st == STORAGE_TYPE_UNKNOWN)
|
||||
st = probeFormat();
|
||||
|
||||
@@ -49,43 +57,18 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
qDebug() << tr("Cannot find %1/MODELS/models.yml").arg(filename);
|
||||
else
|
||||
qDebug() << tr("Found %1/MODELS/models.yml").arg(filename);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!QFile(filename).exists())
|
||||
qDebug() << tr("Cannot find %1").arg(filename);
|
||||
else
|
||||
qDebug() << tr("Found %1").arg(filename);
|
||||
}
|
||||
|
||||
if (!loadRadioSettings(radioData.generalSettings))
|
||||
return false;
|
||||
|
||||
board = (Board::Type)radioData.generalSettings.variant;
|
||||
|
||||
// get models
|
||||
// Scan for all models
|
||||
EtxModelfiles modelFiles;
|
||||
|
||||
// Labels - Read the labels from labels.yml file
|
||||
// - Always scan for /MODELS/modelXX.yml
|
||||
// - Update possible labels with all found in models too
|
||||
statusMsg(tr("Scanning for models..."));
|
||||
|
||||
QByteArray labelslistBuffer;
|
||||
int sortOrder = 0;
|
||||
|
||||
if (loadFile(labelslistBuffer, "MODELS/labels.yml")) {
|
||||
try {
|
||||
if (!loadLabelsListFromYaml(radioData.labels, sortOrder, modelFiles, labelslistBuffer)) {
|
||||
setError(tr("Can't load MODELS/labels.yml"));
|
||||
}
|
||||
} catch(const std::runtime_error& e) {
|
||||
setError(tr("Can't load MODELS/labels.yml") + ":\n" + QString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
// Save Sort Order
|
||||
radioData.sortOrder = sortOrder;
|
||||
|
||||
// Scan for all models
|
||||
std::list<std::string> filelist;
|
||||
if (!getFileList(filelist))
|
||||
return false;
|
||||
@@ -103,8 +86,39 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
}
|
||||
}
|
||||
|
||||
progressSetMaximum(steps + modelFiles.size());
|
||||
steps = 0;
|
||||
progressSetValue(++steps);
|
||||
|
||||
if (!loadRadioSettings(radioData.generalSettings))
|
||||
return false;
|
||||
|
||||
board = (Board::Type)radioData.generalSettings.variant;
|
||||
|
||||
// Labels - Read the labels from labels.yml file
|
||||
// - Always scan for /MODELS/modelXX.yml
|
||||
// - Update possible labels with all found in models too
|
||||
progressSetValue(++steps);
|
||||
|
||||
QByteArray labelslistBuffer;
|
||||
int sortOrder = 0;
|
||||
|
||||
if (hasLabels && loadFile(labelslistBuffer, "MODELS/labels.yml", true)) {
|
||||
try {
|
||||
if (!loadLabelsListFromYaml(radioData.labels, sortOrder, modelFiles, labelslistBuffer)) {
|
||||
fatalMsg(tr("Can't load MODELS/labels.yml"));
|
||||
}
|
||||
} catch(const std::runtime_error& e) {
|
||||
fatalMsg(tr("Can't load MODELS/labels.yml") + ":\n" + QString(e.what()));
|
||||
}
|
||||
|
||||
progressSetValue(++steps);
|
||||
}
|
||||
|
||||
// Save Sort Order
|
||||
radioData.sortOrder = sortOrder;
|
||||
|
||||
int modelIdx = 0;
|
||||
bool hasLabels = getCurrentFirmware()->getCapability(HasModelLabels);
|
||||
|
||||
if (hasLabels)
|
||||
radioData.models.resize(modelFiles.size());
|
||||
@@ -118,12 +132,13 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
if (mc.modelIdx >= 0 && mc.modelIdx < (int)radioData.models.size()) {
|
||||
modelIdx = mc.modelIdx;
|
||||
if (!radioData.models[modelIdx].isEmpty()) {
|
||||
qDebug() << QString("Warning: file %1 skipped as slot %2 already used").arg(mc.filename.c_str()).arg(mc.modelIdx + 1);
|
||||
statusMsg(tr("Warning: file %1 skipped as slot %2 already used")
|
||||
.arg(mc.filename.c_str()).arg(mc.modelIdx + 1), QtWarningMsg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << QString("Warning: file %1 skipped as slot %2 not available").arg(mc.filename.c_str()).arg(mc.modelIdx + 1);
|
||||
} else {
|
||||
statusMsg(tr("Warning: file %1 skipped as slot %2 not available")
|
||||
.arg(mc.filename.c_str()).arg(mc.modelIdx + 1), QtWarningMsg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +147,7 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
QString filename = "MODELS/" + QString::fromStdString(mc.filename);
|
||||
|
||||
if (!loadFile(modelBuffer, filename)) {
|
||||
setError(tr("Cannot extract ") + filename);
|
||||
fatalMsg(tr("Cannot load %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -143,11 +158,11 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
|
||||
try {
|
||||
if (!loadModelFromYaml(model,modelBuffer)) {
|
||||
setError(tr("Cannot load ") + filename);
|
||||
fatalMsg(tr("Cannot convert to yaml %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
} catch(const std::runtime_error& e) {
|
||||
setError(tr("Cannot load ") + filename + ":\n" + QString(e.what()));
|
||||
fatalMsg(tr("Cannot convert to yaml %1:\n%2").arg(filename).arg(QString(e.what())));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -170,8 +185,12 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
|
||||
model.used = true;
|
||||
modelIdx++;
|
||||
progressSetValue(++steps);
|
||||
statusMsg(tr("Loaded: %1").arg(filename));
|
||||
}
|
||||
|
||||
statusMsg(tr("Loading model images..."));
|
||||
|
||||
for (const auto &fname : modelImages) {
|
||||
if (!loadImageFile(fname, true))
|
||||
return false;
|
||||
@@ -179,6 +198,7 @@ bool LabelsStorageFormat::load(RadioData & radioData)
|
||||
|
||||
// Add the labels in the models
|
||||
if (hasLabels) {
|
||||
statusMsg(tr("Loading labels..."));
|
||||
radioData.addLabelsFromModels();
|
||||
|
||||
// If no labels, add a Favorites
|
||||
@@ -199,8 +219,57 @@ bool LabelsStorageFormat::write(RadioData & radioData)
|
||||
// Also some are at a point in time eg calibration and
|
||||
// therefore not restored to the radio from say an etx file
|
||||
|
||||
progressSetValue(0);
|
||||
progressSetMaximum(100);
|
||||
|
||||
// retrieve models list + delete models + calib + write settings
|
||||
int steps = 4;
|
||||
|
||||
bool hasLabels = getCurrentFirmware()->getCapability(HasModelLabels);
|
||||
steps += (int)hasLabels;
|
||||
|
||||
for (const auto& model : radioData.models) {
|
||||
if (!model.isEmpty())
|
||||
steps += 2; // assume yaml and image for every model
|
||||
}
|
||||
|
||||
progressSetMaximum(steps);
|
||||
steps = 0;
|
||||
|
||||
std::list<std::string> filelist;
|
||||
getFileList(filelist);
|
||||
|
||||
if (filelist.size()) {
|
||||
// Delete all old modelxx.yml from radio MODELS folder before writing new modelxx.yml files
|
||||
progressSetInfoAndMsg(tr("Deleting existing models..."));
|
||||
|
||||
progressSetValue(++steps);
|
||||
const std::regex yml_regex("MODELS/(model([0-9]+)\\.yml)", std::regex_constants::icase);
|
||||
|
||||
for (const auto& f : filelist) {
|
||||
std::smatch match;
|
||||
if (std::regex_match(f, match, yml_regex)) {
|
||||
if (match.size() == 3) {
|
||||
if (!deleteFile(QString(f.c_str()))) {
|
||||
fatalMsg(tr("Unable to delete file: %1").arg(QDir::toNativeSeparators(QString(f.c_str()))));
|
||||
return false;
|
||||
} else {
|
||||
statusMsg(tr("Deleted file: %1").arg(QString(f.c_str())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progressSetValue(++steps);
|
||||
|
||||
// may not exist on a new sd card or path
|
||||
if (QFile(filename + "/RADIO/radio.yml").exists()) {
|
||||
const QString settingsPath("RADIO/radio.yml");
|
||||
const QString fullSettingsPath(filename % "/" % settingsPath);
|
||||
const QString displaySettingsPath(QDir::toNativeSeparators(fullSettingsPath));
|
||||
|
||||
if (QFile(fullSettingsPath).exists()) {
|
||||
progressSetInfoAndMsg(tr("Preserve radio calibration..."));
|
||||
GeneralSettings gsCur;
|
||||
|
||||
if (loadRadioSettings(gsCur)) {
|
||||
@@ -210,44 +279,32 @@ bool LabelsStorageFormat::write(RadioData & radioData)
|
||||
for (int i = 0; i < CPN_MAX_INPUTS; i++) {
|
||||
gsNew.inputConfig[i].calib = gsCur.inputConfig[i].calib;
|
||||
}
|
||||
|
||||
qDebug() << "Hardware specific settings preserved";
|
||||
} else {
|
||||
setError("Error reading current settings from radio");
|
||||
fatalMsg(tr("Error reading radio calibration from %1")
|
||||
.arg(displaySettingsPath));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Radio calibration not found" << displaySettingsPath;
|
||||
}
|
||||
|
||||
progressSetValue(++steps);
|
||||
progressSetInfoAndMsg(tr("Writing radio settings..."));
|
||||
|
||||
QByteArray radioSettingsBuffer;
|
||||
if (!writeRadioSettingsToYaml(radioData.generalSettings, radioSettingsBuffer))
|
||||
return false;
|
||||
|
||||
if (!writeFile(radioSettingsBuffer, "RADIO/radio.yml"))
|
||||
return false;
|
||||
|
||||
bool hasLabels = getCurrentFirmware()->getCapability(HasModelLabels);
|
||||
|
||||
// fetch "MODELS/modelXX.yml"
|
||||
std::list<std::string> filelist;
|
||||
if (!getFileList(filelist)) {
|
||||
setError(tr("Cannot list files"));
|
||||
if (!writeRadioSettingsToYaml(radioData.generalSettings, radioSettingsBuffer)) {
|
||||
fatalMsg(tr("Error converting radio settings to yaml"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete all old modelxx.yml from radio MODELS folder before writing new modelxx.yml files
|
||||
const std::regex yml_regex("MODELS/(model([0-9s]+)\\.yml)", std::regex_constants::icase);
|
||||
for (const auto& f : filelist) {
|
||||
std::smatch match;
|
||||
if (std::regex_match(f, match, yml_regex)) {
|
||||
if (match.size() == 3) {
|
||||
if (!deleteFile(QString(f.c_str()))) {
|
||||
setError(tr("Error deleting files"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!writeFile(radioSettingsBuffer, settingsPath)) {
|
||||
fatalMsg(tr("Error writing: %1").arg(displaySettingsPath));
|
||||
return false;
|
||||
}
|
||||
|
||||
progressSetValue(++steps);
|
||||
progressSetInfoAndMsg(tr("Writing models..."));
|
||||
|
||||
EtxModelfiles modelFiles;
|
||||
QList<QString> modelImages;
|
||||
|
||||
@@ -256,6 +313,7 @@ bool LabelsStorageFormat::write(RadioData & radioData)
|
||||
continue;
|
||||
|
||||
QString modelFilename;
|
||||
|
||||
if (hasLabels) {
|
||||
std::string ymlFilename = patchFilenameToYaml(model.filename);
|
||||
modelFilename = QString("MODELS/%1").arg(QString::fromStdString(ymlFilename));
|
||||
@@ -265,9 +323,15 @@ bool LabelsStorageFormat::write(RadioData & radioData)
|
||||
}
|
||||
|
||||
QByteArray modelData;
|
||||
writeModelToYaml(model, modelData);
|
||||
if (!writeFile(modelData, modelFilename))
|
||||
if (!writeModelToYaml(model, modelData)) {
|
||||
fatalMsg(tr("Error converting model to yaml: %1").arg(model.name));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writeFile(modelData, modelFilename)) {
|
||||
fatalMsg(tr("Error writing: %1").arg(QDir::toNativeSeparators(filename % "/" % modelFilename)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!model.isBitmapEmpty()) {
|
||||
const QString fname(model.getImageFilename());
|
||||
@@ -279,19 +343,37 @@ bool LabelsStorageFormat::write(RadioData & radioData)
|
||||
|
||||
if (!writeChecklist(model))
|
||||
return false;
|
||||
|
||||
statusMsg(tr("Model written: %1").arg(model.name));
|
||||
progressSetValue(++steps);
|
||||
}
|
||||
|
||||
progressSetInfoAndMsg(tr("Writing model images..."));
|
||||
|
||||
for (const auto &fname : modelImages) {
|
||||
if (!writeImageFile(fname))
|
||||
return false;
|
||||
else
|
||||
progressSetValue(++steps);
|
||||
}
|
||||
|
||||
if (hasLabels) {
|
||||
progressSetInfoAndMsg(tr("Writing labels..."));
|
||||
|
||||
QByteArray labelsListBuffer;
|
||||
if (!writeLabelsListToYaml(radioData, labelsListBuffer) || !writeFile(labelsListBuffer, "MODELS/labels.yml"))
|
||||
if (!writeLabelsListToYaml(radioData, labelsListBuffer)) {
|
||||
fatalMsg(tr("Error converting labels to yaml"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString labelsPath("MODELS/labels.yml");
|
||||
if (!writeFile(labelsListBuffer, labelsPath)) {
|
||||
fatalMsg(tr("Error writing: %1").arg(QDir::toNativeSeparators(filename % "/" % labelsPath)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
progressSetValue(++steps);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -300,10 +382,8 @@ bool LabelsStorageFormat::loadChecklist(ModelData & model)
|
||||
const QString fname("MODELS/" + model.getChecklistFilename());
|
||||
//qDebug() << "Searching for checklist file:" << fname;
|
||||
|
||||
if (!loadFile(model.checklistData, fname, true)) {
|
||||
setError(tr("Cannot load ") + fname);
|
||||
if (!loadFile(model.checklistData, fname, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -314,10 +394,8 @@ bool LabelsStorageFormat::writeChecklist(const ModelData & model)
|
||||
const QString fname("MODELS/" + model.getChecklistFilename());
|
||||
//qDebug() << "Writing checklist file:" << fname;
|
||||
|
||||
if (!writeFile(model.checklistData, fname)) {
|
||||
setError(tr("Cannot write ") + fname);
|
||||
if (!writeFile(model.checklistData, fname))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -331,17 +409,17 @@ bool LabelsStorageFormat::loadRadioSettings(GeneralSettings & generalSettings)
|
||||
const QString filePath(QDir::toNativeSeparators(filename + "/" + file));
|
||||
|
||||
if (!loadFile(radioSettingsBuffer, file)) {
|
||||
setError(tr("Cannot extract %1").arg(filePath));
|
||||
fatalMsg(tr("Cannot read %1").arg(filePath));
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!loadRadioSettingsFromYaml(generalSettings, radioSettingsBuffer)) {
|
||||
setError(tr("Cannot load %1").arg(filePath));
|
||||
fatalMsg(tr("Cannot convert to yaml %1").arg(filePath));
|
||||
return false;
|
||||
}
|
||||
} catch(const std::runtime_error& e) {
|
||||
setError(tr("Cannot load %1").arg(filePath) + ":\n" + QString(e.what()));
|
||||
fatalMsg(tr("Cannot convert to yaml %1:\n%2").arg(filePath).arg(QString(e.what())));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,25 +36,25 @@ bool SdcardFormat::write(RadioData & radioData)
|
||||
|
||||
bool SdcardFormat::loadFile(QByteArray & filedata, const QString & filename, bool optional)
|
||||
{
|
||||
filedata.clear(); // in case buffer is being reused
|
||||
QString path = this->filename + "/" + filename;
|
||||
QFile file(path);
|
||||
|
||||
if (!file.exists()) {
|
||||
if (optional) {
|
||||
//qDebug() << "File not found:" << filename;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!file.exists()) return optional;
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
setError(tr("Error opening file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
fatalMsg(tr("Error opening file %1:\n%2.").arg(filename).arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
filedata = file.readAll();
|
||||
qDebug() << "File" << filename << "read, size:" << filedata.size();
|
||||
|
||||
if (filedata.isEmpty()) {
|
||||
fatalMsg(tr("File empty: %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
statusMsg(tr("File loaded: %1").arg(filename));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -72,22 +72,22 @@ bool SdcardFormat::loadImageFile(const QString & filename, bool optional)
|
||||
// QFile::copy fails if destination file exists
|
||||
if (destfile.exists()) {
|
||||
if (destfile.remove()) {
|
||||
qDebug() << "Deleted file from image cache" << filename;
|
||||
//qDebug() << "Deleted file from image cache" << filename;
|
||||
} else {
|
||||
qDebug() << "Unable to delete cached" << filename;
|
||||
fatalMsg(tr("Unable to delete cached").arg(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (file.copy(Helpers::getImagesCacheDir() % "/" % filename)) {
|
||||
qDebug() << "Cached image" << filename;
|
||||
// qDebug() << "Cached image" << filename;
|
||||
} else {
|
||||
qDebug() << "Failed to cache image" << filename;
|
||||
fatalMsg(tr("Failed to cache image: %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Failed to cache" << filename << ". Cache directory" << Helpers::getImagesCacheDir()
|
||||
<< "does not exist.";
|
||||
fatalMsg(tr("No application image cache"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -99,13 +99,19 @@ bool SdcardFormat::writeFile(const QByteArray & data, const QString & filename)
|
||||
QFile file(path);
|
||||
|
||||
if (!file.open(QFile::WriteOnly)) {
|
||||
setError(tr("Error opening file %1 in write mode:\n%2.").arg(path).arg(file.errorString()));
|
||||
fatalMsg(tr("Error opening file %1 in write mode:\n%2.").arg(path).arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(data.data(), data.size());
|
||||
qint64 writesz = file.write(data.data(), data.size());
|
||||
file.close();
|
||||
qDebug() << "File" << path << "written, size:" << data.size();
|
||||
|
||||
if (writesz != data.size()) {
|
||||
fatalMsg(tr("Error writing file %1: wrote %2 of %3 bytes").arg(path).arg(writesz).arg(data.size()));
|
||||
return false;
|
||||
}
|
||||
|
||||
statusMsg(tr("File written: %1").arg(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -121,20 +127,26 @@ bool SdcardFormat::writeImageFile(const QString & filename)
|
||||
if (destinfo.exists()) {
|
||||
// for performance reasons avoid overwriting the same image
|
||||
if (destinfo.size() == srcinfo.size()) {
|
||||
qDebug() << "Image file" << filename << "skipped as same size";
|
||||
statusMsg(tr("Duplicate image file: %1 skipped").arg(filename));
|
||||
return true;
|
||||
}
|
||||
// Size differs, remove the existing file before copying
|
||||
if (!QFile::remove(destpath)) {
|
||||
fatalMsg(tr("Error removing existing image file: %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!QFile(srcpath).copy(destpath)) {
|
||||
setError(tr("Error writing image file: %1").arg(filename));
|
||||
fatalMsg(tr("Error writing image file: %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "File" << destpath << "written, size:" << srcinfo.size();
|
||||
statusMsg(tr("Image written: %1").arg(filename));
|
||||
return true;
|
||||
}
|
||||
|
||||
fatalMsg(tr("No application image cache"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,11 +170,11 @@ bool SdcardFormat::deleteFile(const QString & filename)
|
||||
QString path = this->filename + "/" + filename;
|
||||
|
||||
if (!QFile::remove(path)) {
|
||||
setError(tr("Error deleting file %1").arg(path));
|
||||
fatalMsg(tr("Error deleting file: %1").arg(path));
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "File" << path << "deleted";
|
||||
statusMsg(tr("Deleted file: %1").arg(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,50 @@ void unregisterStorageFactories()
|
||||
delete factory;
|
||||
}
|
||||
|
||||
|
||||
void StorageFormat::statusMsg(const QString & text, const int & type,
|
||||
const bool richText, const bool updateLast)
|
||||
{
|
||||
if (_progress)
|
||||
_progress->addMessage(text, type, richText, updateLast);
|
||||
|
||||
if (type == QtCriticalMsg || type == QtFatalMsg)
|
||||
setError(text);
|
||||
else if (type == QtWarningMsg)
|
||||
setWarning(text);
|
||||
}
|
||||
|
||||
void StorageFormat::fatalMsg(const QString & text, const bool richText)
|
||||
{
|
||||
statusMsg(text, QtFatalMsg, richText);
|
||||
}
|
||||
|
||||
void StorageFormat::progressSetInfoAndMsg(const QString & text, const int & type, const bool richText)
|
||||
{
|
||||
progressSetInfo(text);
|
||||
statusMsg(text, type, richText);
|
||||
}
|
||||
|
||||
void StorageFormat::progressSetInfo(const QString & msg)
|
||||
{
|
||||
if (_progress) _progress->setInfo(msg);
|
||||
}
|
||||
|
||||
void StorageFormat::progressSetLock(const bool lock)
|
||||
{
|
||||
if (_progress) _progress->lock(lock);
|
||||
}
|
||||
|
||||
void StorageFormat::progressSetMaximum(const int max)
|
||||
{
|
||||
if (_progress) _progress->setMaximum(max);
|
||||
}
|
||||
|
||||
void StorageFormat::progressSetValue(const int val)
|
||||
{
|
||||
if (_progress) _progress->setValue(val);
|
||||
}
|
||||
|
||||
bool Storage::load(RadioData & radioData)
|
||||
{
|
||||
if (!fileExists())
|
||||
@@ -69,6 +113,8 @@ bool Storage::load(RadioData & radioData)
|
||||
StorageFormat *format = getStorageFormat();
|
||||
|
||||
if (format) {
|
||||
format->setProgress(_progress);
|
||||
|
||||
if (format->load(radioData)) {
|
||||
board = format->getBoard();
|
||||
setWarning(format->warning());
|
||||
@@ -89,6 +135,7 @@ bool Storage::write(RadioData & radioData)
|
||||
StorageFormat *format = getStorageFormat();
|
||||
|
||||
if (format) {
|
||||
format->setProgress(_progress);
|
||||
ret = format->write(radioData);
|
||||
delete format;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "radiodata.h"
|
||||
#include "progressdialog.h"
|
||||
#include "progresswidget.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QString>
|
||||
@@ -46,7 +48,8 @@ class StorageFormat
|
||||
StorageFormat(const QString & filename, uint8_t version=0):
|
||||
filename(filename),
|
||||
version(version),
|
||||
board(Board::BOARD_UNKNOWN)
|
||||
board(Board::BOARD_UNKNOWN),
|
||||
_progress(nullptr)
|
||||
{
|
||||
}
|
||||
virtual ~StorageFormat() {}
|
||||
@@ -55,6 +58,8 @@ class StorageFormat
|
||||
virtual bool write(RadioData & radioData) = 0;
|
||||
virtual bool writeModel(const RadioData & radioData, const int modelIndex) { return false; }
|
||||
|
||||
void setProgress(ProgressWidget * progress) { _progress = progress; }
|
||||
|
||||
QString error() {
|
||||
return _error;
|
||||
}
|
||||
@@ -83,11 +88,21 @@ class StorageFormat
|
||||
_warning = warning;
|
||||
}
|
||||
|
||||
void statusMsg(const QString & text, const int & type = QtInfoMsg,
|
||||
const bool richText = false, const bool updateLast = false);
|
||||
void fatalMsg(const QString & text, const bool richText = false);
|
||||
void progressSetInfoAndMsg(const QString & text, const int & type = QtInfoMsg, const bool richText = false);
|
||||
void progressSetInfo(const QString & msg);
|
||||
void progressSetLock(const bool lock);
|
||||
void progressSetMaximum(const int max);
|
||||
void progressSetValue(const int val);
|
||||
|
||||
QString filename;
|
||||
uint8_t version;
|
||||
QString _error;
|
||||
QString _warning;
|
||||
Board::Type board;
|
||||
ProgressWidget * _progress;
|
||||
};
|
||||
|
||||
class StorageFactory
|
||||
|
||||
Reference in New Issue
Block a user