diff --git a/companion/src/companion.cpp b/companion/src/companion.cpp index 358f84f5b..ee70dad24 100644 --- a/companion/src/companion.cpp +++ b/companion/src/companion.cpp @@ -232,6 +232,18 @@ int main(int argc, char *argv[]) registerOpenTxFirmwares(); SimulatorLoader::registerSimulators(); + QTemporaryDir tempDir(QDir::tempPath() % "/etx-cpn-XXXXXX"); + + if (!tempDir.isValid()) { + qDebug() << "Unable to create application temporary directory"; + gAppTempPath = ""; + } else { + gAppTempPath = tempDir.path(); + + if (!QDir(gAppTempPath).mkdir("IMAGES")) + qDebug() << "Unable to create images cache directory:" << Helpers::getImagesCacheDir(); + } + Profile & profile = g.currentProfile(); if (profile.fwType().isEmpty()){ profile.fwType(Firmware::getDefaultVariant()->getId()); diff --git a/companion/src/firmwares/edgetx/edgetxinterface.cpp b/companion/src/firmwares/edgetx/edgetxinterface.cpp index c089c9b2b..5c46a3ba8 100644 --- a/companion/src/firmwares/edgetx/edgetxinterface.cpp +++ b/companion/src/firmwares/edgetx/edgetxinterface.cpp @@ -78,7 +78,7 @@ static void writeYamlToByteArray(const YAML::Node& node, QByteArray& data, bool data_ostream << node; data = QByteArray::fromStdString(data_ostream.str()); - qDebug() << "Saving YAML:"; + //qDebug() << "Saving YAML:"; if(addChecksum) { uint16_t checksum = 0xFFFF; @@ -88,7 +88,7 @@ static void writeYamlToByteArray(const YAML::Node& node, QByteArray& data, bool data.prepend(checksum_ostream.str().c_str()); } - qDebug() << data.toStdString().c_str(); + //qDebug() << data.toStdString().c_str(); } bool loadLabelsListFromYaml(RadioData::ModelLabels& labels, diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index fe1f25041..2b4015650 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -2334,3 +2334,42 @@ void ModelData::initTopBar() zone.widgetName = "Internal GPS"; } } + +QString ModelData::getImageFilename() const +{ + if (!isBitmapEmpty()) { + QString extn; + + if (!getCurrentFirmware()->getCapability(ModelImageKeepExtn)) + extn = "." % getDefaultImageFileExtn(); + + return QString(bitmap).append(extn); + } else { + return QString(); + } +} + +QString ModelData::getImageFileExtn() const +{ + if (getCurrentFirmware()->getCapability(ModelImageKeepExtn)) { + QStringList strl = QString(bitmap).split("."); + return strl.count() > 1 ? strl.at(strl.count() - 1) : ""; + } else { + return getDefaultImageFileExtn(); + } +} + +QString ModelData::getDefaultImageFileExtn() +{ + QString ret; + + if (!getCurrentFirmware()->getCapability(ModelImageKeepExtn)) + ret = getCurrentFirmware()->getCapabilityStr(ModelImageFilters).replace("*.", ""); + + return ret; +} + +bool ModelData::isBitmapEmpty() const +{ + return bitmap[0] == '\0'; +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index cc7e51b55..e6ab58617 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -293,6 +293,10 @@ class ModelData { const Board::SwitchType getSwitchType(int sw, const GeneralSettings & gs) const; QString getChecklistFilename() const; + QString getImageFilename() const; + QString getImageFileExtn() const; + static QString getDefaultImageFileExtn(); + bool isBitmapEmpty() const; enum ReferenceUpdateAction { REF_UPD_ACT_CLEAR, diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 2784280a3..3756928c6 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -107,7 +107,8 @@ int OpenTxFirmware::getCapability(::Capability capability) case HasMixerNames: return (IS_TARANIS_X9(board) ? 8 : 6); case HasModelImage: - return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_FAMILY_HORUS_OR_T16(board)); + return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || + IS_FAMILY_HORUS_OR_T16(board) || Boards::getCapability(board, Board::HasColorLcd)); case HasModelLabels: return IS_FAMILY_HORUS_OR_T16(board); case HasModelsList: diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 7c61e3718..5c0439e6f 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -44,6 +44,8 @@ #include #include +QString gAppTempPath; + using namespace Helpers; Stopwatch gStopwatch("global"); @@ -366,6 +368,34 @@ QString Helpers::concatPath(QString & str1, const QString & str2, bool onlyonese return (str1 % ((!str1.endsWith("/") || !onlyonesep) ? "/" : "") % str2); } +QString Helpers::getImagesCacheDir() +{ + if (gAppTempPath.isEmpty()) + return QString(); + + return QDir(gAppTempPath).filePath("IMAGES"); +} + +QString Helpers::getImagePath(const QString & filename) +{ + if (filename.isEmpty()) + return QString(); + + QString srcpath(Helpers::getImagesCacheDir() % "/" % filename); + + if (srcpath.isEmpty() || !QFileInfo::exists(srcpath) || QFileInfo(srcpath).isDir()) { + srcpath = g.currentProfile().sdPath() % "/IMAGES/" % filename; + + if (!QFileInfo::exists(srcpath) || QFileInfo(srcpath).isDir()) { + qDebug() << filename << "not found in image cache or sd path."; + srcpath = ""; + } + } + + return srcpath; +} + + #ifdef __APPLE__ // Flag when simulator is running static bool simulatorRunning = false; diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 56552b085..45e9cd83c 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -34,6 +34,7 @@ #include extern const QColor colors[CPN_MAX_CURVES]; +extern QString gAppTempPath; #define TMR_NUM_OPTION (TMRMODE_COUNT+2*9+2*getCurrentFirmware()->getCapability(LogicalSwitches)-1) @@ -118,6 +119,8 @@ namespace Helpers QString concatPath(const QString & str1, const QString & str2, bool onlyonesep = true); QString concatPath(const QString & str1, QString & str2, bool onlyonesep = true); QString concatPath(QString & str1, const QString & str2, bool onlyonesep = true); + QString getImagesCacheDir(); + QString getImagePath(const QString & filename); } // namespace Helpers // TODO : move globals to Helpers namespace diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index ac9b39ae3..0394869e3 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -83,46 +83,23 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge else { ui->imagePreview->setFixedSize(QSize(64, 32)); } + QStringList items; items.append(""); - QString path = g.profile[g.id()].sdPath(); - path.append("/IMAGES/"); - QDir qd(path); - if (qd.exists()) { - QStringList filters = firmware->getCapabilityStr(ModelImageFilters).split("|"); - foreach ( QString file, qd.entryList(filters, QDir::Files) ) { - QFileInfo fi(file); - QString temp; - if (firmware->getCapability(ModelImageKeepExtn)) - temp = fi.fileName(); - else - temp = fi.completeBaseName(); - if (!items.contains(temp) && temp.length() <= firmware->getCapability(ModelImageNameLen)) - items.append(temp); - } - } - if (!items.contains(model.bitmap)) { + loadImageList(items, Helpers::getImagesCacheDir()); + loadImageList(items, g.currentProfile().sdPath() % "/IMAGES/"); + + if (!items.contains(model.bitmap)) items.append(model.bitmap); - } + items.sort(Qt::CaseInsensitive); + foreach (QString file, items) { ui->image->addItem(file); + if (file == model.bitmap) { ui->image->setCurrentIndex(ui->image->count() - 1); - if (!file.isEmpty()) { - QString fileName = path; - fileName.append(model.bitmap); - if (!firmware->getCapability(ModelImageKeepExtn)) { - QString extn = firmware->getCapabilityStr(ModelImageFilters); - if (extn.size() > 0) - extn.remove(0, 1); // remove * - fileName.append(extn); - } - QImage image(fileName); - if (!image.isNull()) { - ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(ui->imagePreview->size()))); - } - } + loadImagePreview(); } } } @@ -392,25 +369,7 @@ void SetupPanel::on_image_currentIndexChanged(int index) if (!lock) { memset(model->bitmap, 0, CPN_MAX_BITMAP_LEN); strncpy(model->bitmap, ui->image->currentText().toLatin1(), CPN_MAX_BITMAP_LEN); - if (model->bitmap[0] != '\0') { - QString path = g.profile[g.id()].sdPath(); - path.append("/IMAGES/"); - path.append(model->bitmap); - if (!firmware->getCapability(ModelImageKeepExtn)) { - QString extn = firmware->getCapabilityStr(ModelImageFilters); - if (extn.size() > 0) - extn.remove(0, 1); // remove * - path.append(extn); - } - QImage image(path); - if (!image.isNull()) - ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(ui->imagePreview->size()))); - else - ui->imagePreview->clear(); - } - else { - ui->imagePreview->clear(); - } + loadImagePreview(); emit modified(); } } @@ -829,3 +788,37 @@ void SetupPanel::onFunctionSwitchesUpdateItemModels() updateStartupSwitches(); sharedItemModels->update(AbstractItemModel::IMUE_FunctionSwitches); } + +void SetupPanel::loadImageList(QStringList &list, const QString & path) +{ + QDir d(path); + const int maxnamelen = firmware->getCapability(ModelImageNameLen); + const bool keepextn = firmware->getCapability(ModelImageKeepExtn); + + if (d.exists()) { + QStringList filters = firmware->getCapabilityStr(ModelImageFilters).split("|"); + + foreach ( QString file, d.entryList(filters, QDir::Files) ) { + QFileInfo fi(file); + QString temp = keepextn ? fi.fileName() : fi.completeBaseName(); + + if (!list.contains(temp) && temp.length() <= maxnamelen) + list.append(temp); + } + } +} + +void SetupPanel::loadImagePreview() +{ + if (!model->isBitmapEmpty()) { + QImage image; + QString filename(model->getImageFilename()); + QString path(Helpers::getImagePath(filename)); + + if (!path.isEmpty() && image.load(path)) + ui->imagePreview->setPixmap(QPixmap::fromImage(image.scaled(ui->imagePreview->size()))); + else + ui->imagePreview->clear(); + + } +} diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 7d1e583c0..ba69e2038 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -115,4 +115,6 @@ class SetupPanel : public ModelPanel void connectItemModelEvents(const FilteredItemModel * itemModel); CompoundItemModelFactory * panelItemModels; FilteredItemModelFactory * panelFilteredModels; + void loadImageList(QStringList &list, const QString & dir); + void loadImagePreview(); }; diff --git a/companion/src/simulator.cpp b/companion/src/simulator.cpp index c354873e9..ba1cfc193 100644 --- a/companion/src/simulator.cpp +++ b/companion/src/simulator.cpp @@ -45,6 +45,7 @@ #include "translations.h" #include "version.h" #include "boardfactories.h" +#include "helpers.h" using namespace Simulator; @@ -367,6 +368,21 @@ int main(int argc, char *argv[]) Firmware::setCurrentVariant(Firmware::getFirmwareForId(simOptions.firmwareId)); //qDebug() << "current firmware:" << getCurrentFirmware()->getId(); + QString imgDir = Helpers::getImagesCacheDir(); + QDir dir(imgDir); + + if (dir.exists()) { + if (!dir.removeRecursively()) + qDebug() << "Unable to delete images cache directory" << imgDir; + else + qDebug() << "Deleted images cache directory" << imgDir; + } + + if (!QDir::temp().mkpath(imgDir)) + qDebug() << "Unable to create images cache directory" << imgDir; + else + qDebug() << "Created images cache directory" << imgDir; + int result = 0; SimulatorMainWindow * mainWindow = new SimulatorMainWindow(nullptr, simOptions.simulatorId, (simOptions.flags ? simOptions.flags : SIMULATOR_FLAGS_STANDALONE)); if ((result = mainWindow->getExitStatus(&resultMsg))) { diff --git a/companion/src/storage/etx.cpp b/companion/src/storage/etx.cpp index f0c8985ed..504c2655a 100644 --- a/companion/src/storage/etx.cpp +++ b/companion/src/storage/etx.cpp @@ -20,6 +20,8 @@ */ #include "etx.h" +#include "helpers.h" + #include #define MZ_ALLOCATION_SIZE (32*1024) @@ -94,14 +96,8 @@ bool EtxFormat::loadFile(QByteArray & filedata, const QString & filename, bool o { size_t size; void * data = mz_zip_reader_extract_file_to_heap(&zip_archive, qPrintable(filename), &size, 0); - if (!data) { - if (optional) { - //qDebug() << "File not found:" << filename; - return true; - } else { - return false; - } - } + + if (!data) return optional; qDebug() << QString("Extracted file %1, size=%2").arg(filename).arg(size); filedata.clear(); @@ -110,16 +106,77 @@ bool EtxFormat::loadFile(QByteArray & filedata, const QString & filename, bool o return true; } -bool EtxFormat::writeFile(const QByteArray & filedata, const QString & filename) +bool EtxFormat::loadImageFile(const QString & filename, bool optional) { - 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 EdgeTX archive").arg(filename)); + QString srcpath("IMAGES/" % filename); + size_t size; + void * data = mz_zip_reader_extract_file_to_heap(&zip_archive, qPrintable(srcpath), &size, 0); + + if (!data) return optional; + + QByteArray ba; + ba.append((char *)data, size); + mz_free(data); + + QFile imgfile(Helpers::getImagesCacheDir() % "/" % filename); + + if (imgfile.open(QIODevice::WriteOnly)) { + if (imgfile.write(ba) != (qint64)size) { + qDebug() << "Image data written does not match expected"; + return false; + } + + imgfile.close(); + } else { + setError(tr("Unable to write %1 to cache").arg(filename)); return false; } + qDebug() << QString("Extracted file %1, size=%2").arg(srcpath).arg(size); 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)); + return false; + } + + qDebug() << "File" << filename << "written, size:" << filedata.size(); + return true; +} + +bool EtxFormat::writeImageFile(const QString & filename) +{ + QString srcpath(Helpers::getImagePath(filename)); + + if (!srcpath.isEmpty()) { + QByteArray ba; + QFile imgfile(srcpath); + + if (imgfile.open(QIODevice::ReadOnly)) { + ba.append(imgfile.readAll()); + imgfile.close(); + } else { + setError(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)); + return false; + } + + qDebug() << "File" << destpath << "written, size:" << ba.size(); + return true; + } + + return false; +} + bool EtxFormat::getFileList(std::list& filelist) { int count = (int)mz_zip_reader_get_num_files(&zip_archive); diff --git a/companion/src/storage/etx.h b/companion/src/storage/etx.h index 7092ea1e2..c071b1af6 100644 --- a/companion/src/storage/etx.h +++ b/companion/src/storage/etx.h @@ -41,7 +41,9 @@ class EtxFormat : public LabelsStorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false); + virtual bool loadImageFile(const QString & fileName, bool optional = false); virtual bool writeFile(const QByteArray & fileData, const QString & fileName); + virtual bool writeImageFile(const QString & fileName); virtual bool getFileList(std::list& filelist); virtual bool deleteFile(const QString & fileName) { return false; } diff --git a/companion/src/storage/labeled.cpp b/companion/src/storage/labeled.cpp index a9dffc28f..27a35938b 100644 --- a/companion/src/storage/labeled.cpp +++ b/companion/src/storage/labeled.cpp @@ -71,6 +71,7 @@ bool LabelsStorageFormat::load(RadioData & radioData) QByteArray labelslistBuffer; int sortOrder = 0; + if (loadFile(labelslistBuffer, "MODELS/labels.yml")) { try { if (!loadLabelsListFromYaml(radioData.labels, sortOrder, modelFiles, labelslistBuffer)) { @@ -108,6 +109,8 @@ bool LabelsStorageFormat::load(RadioData & radioData) if (hasLabels) radioData.models.resize(modelFiles.size()); + QList modelImages; + for (const auto& mc : modelFiles) { qDebug() << "Filename: " << mc.filename.c_str(); @@ -127,6 +130,7 @@ bool LabelsStorageFormat::load(RadioData & radioData) QByteArray modelBuffer; QString filename = "MODELS/" + QString::fromStdString(mc.filename); + if (!loadFile(modelBuffer, filename)) { setError(tr("Cannot extract ") + filename); return false; @@ -150,6 +154,14 @@ bool LabelsStorageFormat::load(RadioData & radioData) if (!loadChecklist(model)) return false; + if (!model.isBitmapEmpty()) { + const QString fname(model.getImageFilename()); + + if (!modelImages.contains(fname)) { + modelImages.append(fname); + } + } + model.modelIndex = modelIdx; strncpy(model.filename, mc.filename.c_str(), sizeof(model.filename)-1); @@ -160,6 +172,11 @@ bool LabelsStorageFormat::load(RadioData & radioData) modelIdx++; } + for (const auto &fname : modelImages) { + if (!loadImageFile(fname, true)) + return false; + } + // Add the labels in the models if (hasLabels) { radioData.addLabelsFromModels(); @@ -232,8 +249,9 @@ bool LabelsStorageFormat::write(RadioData & radioData) } EtxModelfiles modelFiles; - for (const auto& model : radioData.models) { + QList modelImages; + for (const auto& model : radioData.models) { if (model.isEmpty()) continue; @@ -251,10 +269,23 @@ bool LabelsStorageFormat::write(RadioData & radioData) if (!writeFile(modelData, modelFilename)) return false; + if (!model.isBitmapEmpty()) { + const QString fname(model.getImageFilename()); + + if (!modelImages.contains(fname)) { + modelImages.append(fname); + } + } + if (!writeChecklist(model)) return false; } + for (const auto &fname : modelImages) { + if (!writeImageFile(fname)) + return false; + } + if (hasLabels) { QByteArray labelsListBuffer; if (!writeLabelsListToYaml(radioData, labelsListBuffer) || !writeFile(labelsListBuffer, "MODELS/labels.yml")) @@ -279,11 +310,10 @@ bool LabelsStorageFormat::loadChecklist(ModelData & model) bool LabelsStorageFormat::writeChecklist(const ModelData & model) { - const QString fname("MODELS/" + model.getChecklistFilename()); - - // not every model has a checklist if (!model.checklistData.isEmpty()) { + const QString fname("MODELS/" + model.getChecklistFilename()); //qDebug() << "Writing checklist file:" << fname; + if (!writeFile(model.checklistData, fname)) { setError(tr("Cannot write ") + fname); return false; diff --git a/companion/src/storage/labeled.h b/companion/src/storage/labeled.h index 41ba159c3..8432993aa 100644 --- a/companion/src/storage/labeled.h +++ b/companion/src/storage/labeled.h @@ -46,7 +46,9 @@ class LabelsStorageFormat : public StorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false) = 0; + virtual bool loadImageFile(const QString & fileName, bool optional = false) = 0; virtual bool writeFile(const QByteArray & fileData, const QString & fileName) = 0; + virtual bool writeImageFile(const QString & fileName) = 0; virtual bool getFileList(std::list& filelist) = 0; virtual bool deleteFile(const QString & fileName) = 0; diff --git a/companion/src/storage/sdcard.cpp b/companion/src/storage/sdcard.cpp index 1d4f49b24..f73e4bb41 100644 --- a/companion/src/storage/sdcard.cpp +++ b/companion/src/storage/sdcard.cpp @@ -20,6 +20,8 @@ */ #include "sdcard.h" +#include "helpers.h" + #include #include @@ -28,6 +30,7 @@ bool SdcardFormat::write(RadioData & radioData) QDir dir(filename); dir.mkdir("RADIO"); dir.mkdir("MODELS"); + dir.mkdir("IMAGES"); return LabelsStorageFormat::write(radioData); } @@ -35,6 +38,7 @@ bool SdcardFormat::loadFile(QByteArray & filedata, const QString & filename, boo { QString path = this->filename + "/" + filename; QFile file(path); + if (!file.exists()) { if (optional) { //qDebug() << "File not found:" << filename; @@ -45,11 +49,47 @@ bool SdcardFormat::loadFile(QByteArray & filedata, const QString & filename, boo } if (!file.open(QFile::ReadOnly)) { - setError(tr("Error opening file %1:\n%2.").arg(path).arg(file.errorString())); + setError(tr("Error opening file %1:\n%2.").arg(filename).arg(file.errorString())); return false; } + filedata = file.readAll(); - qDebug() << "File" << path << "read, size:" << filedata.size(); + qDebug() << "File" << filename << "read, size:" << filedata.size(); + return true; +} + +bool SdcardFormat::loadImageFile(const QString & filename, bool optional) +{ + QString srcpath = this->filename + "/IMAGES/" + filename; + QFile file(srcpath); + + if (!file.exists()) return optional; + + if (QDir(Helpers::getImagesCacheDir()).exists()) { + QString destpath(Helpers::getImagesCacheDir() % "/" % filename); + QFile destfile(destpath); + + // QFile::copy fails if destination file exists + if (destfile.exists()) { + if (destfile.remove()) { + qDebug() << "Deleted file from image cache" << filename; + } else { + qDebug() << "Unable to delete cached" << filename; + return false; + } + } + + if (file.copy(Helpers::getImagesCacheDir() % "/" % filename)) { + qDebug() << "Cached image" << filename; + } else { + qDebug() << "Failed to cache image" << filename; + return false; + } + } else { + qDebug() << "Failed to cache" << filename << ". Cache directory" << Helpers::getImagesCacheDir() + << "does not exist."; + } + return true; } @@ -57,25 +97,59 @@ bool SdcardFormat::writeFile(const QByteArray & data, const QString & filename) { QString path = this->filename + "/" + 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())); return false; } + file.write(data.data(), data.size()); file.close(); qDebug() << "File" << path << "written, size:" << data.size(); return true; } +bool SdcardFormat::writeImageFile(const QString & filename) +{ + QString srcpath(Helpers::getImagePath(filename)); + + if (!srcpath.isEmpty()) { + QFileInfo srcinfo(srcpath); + QString destpath(this->filename + "/IMAGES/" + filename); + QFileInfo destinfo(destpath); + + if (destinfo.exists()) { + // for performance reasons avoid overwriting the same image + if (destinfo.size() == srcinfo.size()) { + qDebug() << "Image file" << filename << "skipped as same size"; + return true; + } + } + + if (!QFile(srcpath).copy(destpath)) { + setError(tr("Error writing image file: %1").arg(filename)); + return false; + } + + qDebug() << "File" << destpath << "written, size:" << srcinfo.size(); + return true; + } + + return false; +} + bool SdcardFormat::getFileList(std::list& filelist) { QDir dir(filename); + if (!dir.cd("MODELS")) return false; QStringList ql = dir.entryList(); + for (const auto& str : ql) { filelist.push_back("MODELS/" + str.toStdString()); } + return true; } @@ -92,6 +166,11 @@ bool SdcardFormat::deleteFile(const QString & filename) return true; } +/* + + class SdcardStorageFactory +*/ + bool SdcardStorageFactory::probe(const QString & path) { return QDir(path).exists(); diff --git a/companion/src/storage/sdcard.h b/companion/src/storage/sdcard.h index 1cff37b2f..26bb9f812 100644 --- a/companion/src/storage/sdcard.h +++ b/companion/src/storage/sdcard.h @@ -40,7 +40,9 @@ class SdcardFormat : public LabelsStorageFormat protected: virtual bool loadFile(QByteArray & fileData, const QString & fileName, bool optional = false); + virtual bool loadImageFile(const QString & fileName, bool optional = false); virtual bool writeFile(const QByteArray & fileData, const QString & fileName); + virtual bool writeImageFile(const QString & fileName); virtual bool getFileList(std::list& filelist); virtual bool deleteFile(const QString & fileName); };