From 3563e917c6369b5291afd9a0f410fe608523b61c Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Mon, 26 Sep 2022 08:55:16 +1000 Subject: [PATCH] feat(cpn): Enhancements to update component runtime options (#2324) * enh(cpn): Save update component asset options and manage in app settings * Add option to delete decompress folders independent of delete download folder * Fix sdsync to point to last update folder * Update options dlg to allow choosing release channel and saving settings as defaults * Rename params * Asset options dialog shared between settings and update run. Add to Save as defaults --- companion/src/apppreferencesdialog.cpp | 60 ++- companion/src/apppreferencesdialog.h | 1 + companion/src/apppreferencesdialog.ui | 13 +- companion/src/mainwindow.cpp | 16 +- companion/src/mainwindow.h | 2 +- companion/src/storage/appdata.cpp | 119 ++++- companion/src/storage/appdata.h | 47 +- companion/src/updates/repomodels.cpp | 67 ++- companion/src/updates/repomodels.h | 24 +- companion/src/updates/updatecompanion.cpp | 41 +- companion/src/updates/updatecompanion.h | 2 + companion/src/updates/updatefirmware.cpp | 43 +- companion/src/updates/updatefirmware.h | 2 + companion/src/updates/updateinterface.cpp | 430 ++++++++++-------- companion/src/updates/updateinterface.h | 92 ++-- companion/src/updates/updatemultiprotocol.cpp | 35 +- companion/src/updates/updatemultiprotocol.h | 3 + companion/src/updates/updateoptionsdialog.cpp | 163 ++++--- companion/src/updates/updateoptionsdialog.h | 14 +- companion/src/updates/updateoptionsdialog.ui | 86 ++-- companion/src/updates/updates.cpp | 53 ++- companion/src/updates/updates.h | 5 +- companion/src/updates/updatesdcard.cpp | 28 +- companion/src/updates/updatesdcard.h | 2 + companion/src/updates/updatesdialog.cpp | 132 ++++-- companion/src/updates/updatesdialog.h | 12 +- companion/src/updates/updatesdialog.ui | 15 +- companion/src/updates/updatesounds.cpp | 36 +- companion/src/updates/updatesounds.h | 2 + companion/src/updates/updatethemes.cpp | 23 +- companion/src/updates/updatethemes.h | 3 + 31 files changed, 1016 insertions(+), 555 deletions(-) diff --git a/companion/src/apppreferencesdialog.cpp b/companion/src/apppreferencesdialog.cpp index f68f4929f..d9e309a53 100644 --- a/companion/src/apppreferencesdialog.cpp +++ b/companion/src/apppreferencesdialog.cpp @@ -30,6 +30,7 @@ #include "moduledata.h" #include "compounditemmodels.h" #include "updates/updateinterface.h" +#include "updates/updateoptionsdialog.h" #include @@ -103,6 +104,27 @@ void AppPreferencesDialog::accept() // Updates tab + if (ui->leDownloadDir->text().isEmpty()) { + QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Download folder path missing!")); + return; + } + + if (ui->leDecompressDir->text().isEmpty()) { + QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Decompress folder path missing!")); + return; + } + + if (ui->leUpdateDir->text().isEmpty()) { + QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Update folder path missing!")); + return; + } + + if (!ui->chkDecompressDirUseDwnld->isChecked() && + ui->leDecompressDir->text().trimmed() == ui->leDownloadDir->text().trimmed()) { + QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update Settings: Decompress and download folders have the same path!")); + return; + } + g.updateCheckFreq(AppData::UpdateCheckFreq(ui->cboUpdateCheckFreq->currentIndex())); g.downloadDir(ui->leDownloadDir->text()); @@ -113,6 +135,7 @@ void AppPreferencesDialog::accept() g.updateDir(ui->leUpdateDir->text()); g.updDelDownloads(ui->chkDelDownloads->isChecked()); + g.updDelDecompress(ui->chkDelDecompress->isChecked()); g.updLogLevel(ui->cboLogLevel->currentIndex()); QMapIterator it(factories->sortedComponentsList()); @@ -321,13 +344,10 @@ void AppPreferencesDialog::initSettings() connect(ui->btnResetUpdatesToDefaults, &QPushButton::clicked, [=]() { if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Reset all update settings to defaults. Are you sure?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { - for (int i = 0; i < MAX_COMPONENTS; i++) { - if (g.component[i].existsOnDisk()) - g.getComponent(i).resetAll(); - } g.resetUpdatesSettings(); QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Update settings have been reset. Please close and restart Companion to avoid unexpected behaviour!")); + loadUpdatesTab(); } }); @@ -336,11 +356,19 @@ void AppPreferencesDialog::initSettings() ui->leDecompressDir->setText(g.decompressDir()); ui->leDecompressDir->setEnabled(true); ui->btnDecompressSelect->setEnabled(true); + ui->chkDelDownloads->setEnabled(true); } else { ui->leDecompressDir->setText(g.downloadDir()); ui->leDecompressDir->setEnabled(false); ui->btnDecompressSelect->setEnabled(false); + if (ui->chkDelDecompress->isChecked()) { + ui->chkDelDownloads->setEnabled(true); + } + else { + ui->chkDelDownloads->setEnabled(false); + ui->chkDelDownloads->setChecked(false); + } } }); @@ -378,6 +406,18 @@ void AppPreferencesDialog::initSettings() } }); + connect(ui->chkDelDecompress, &QCheckBox::stateChanged, [=](const int checked) { + if (!checked) { + if (ui->chkDecompressDirUseDwnld->isChecked()) { + ui->chkDelDownloads->setEnabled(false); + ui->chkDelDownloads->setChecked(false); + } + } + else { + ui->chkDelDownloads->setEnabled(true); + } + }); + int row = 0; int col = 0; @@ -391,6 +431,8 @@ void AppPreferencesDialog::initSettings() QLabel *h2 = new QLabel(tr("Release channel")); grid->addWidget(h2, row, col++); + col++; // options button + QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ); grid->addItem(spacer, row, col++); @@ -413,6 +455,14 @@ void AppPreferencesDialog::initSettings() cboReleaseChannel[i] = new QComboBox(); cboReleaseChannel[i]->addItems(ComponentData::releaseChannelsList()); grid->addWidget(cboReleaseChannel[i], row, col++); + + btnComponentOptions[i] = new QPushButton(tr("Options")); + connect(btnComponentOptions[i], &QPushButton::clicked, [=]() { + UpdateOptionsDialog *dlg = new UpdateOptionsDialog(this, factories, i, false); + dlg->exec(); + dlg->deleteLater(); + }); + grid->addWidget(btnComponentOptions[i], row, col++); } ui->grpComponents->setLayout(grid); @@ -425,6 +475,8 @@ void AppPreferencesDialog::initSettings() void AppPreferencesDialog::loadUpdatesTab() { ui->cboUpdateCheckFreq->setCurrentIndex(g.updateCheckFreq()); + ui->chkDelDownloads->setChecked(g.updDelDownloads()); + ui->chkDelDecompress->setChecked(g.updDelDecompress()); ui->leDownloadDir->setText(g.downloadDir()); // trigger toggled signal by changing design value and then setting to saved value ui->chkDecompressDirUseDwnld->setChecked(!ui->chkDecompressDirUseDwnld->isChecked()); diff --git a/companion/src/apppreferencesdialog.h b/companion/src/apppreferencesdialog.h index 9b6e82331..c307bf337 100644 --- a/companion/src/apppreferencesdialog.h +++ b/companion/src/apppreferencesdialog.h @@ -92,6 +92,7 @@ class AppPreferencesDialog : public QDialog QLabel *lblName[MAX_COMPONENTS]; QCheckBox *chkCheckForUpdate[MAX_COMPONENTS]; QComboBox *cboReleaseChannel[MAX_COMPONENTS]; + QPushButton *btnComponentOptions[MAX_COMPONENTS]; void loadUpdatesTab(); diff --git a/companion/src/apppreferencesdialog.ui b/companion/src/apppreferencesdialog.ui index 6580f1376..eca37e07c 100644 --- a/companion/src/apppreferencesdialog.ui +++ b/companion/src/apppreferencesdialog.ui @@ -1531,15 +1531,22 @@ Mode 4: - + - + Options - Delete downloads after update + Delete downloads + + + + + + + Delete decompressions diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 81f0a6167..ef9453672 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -237,20 +237,24 @@ void MainWindow::onLanguageChanged(QAction * act) void MainWindow::autoCheckForUpdates() { + statusBar()->showMessage(tr("Checking for updates...")); doUpdates(true, false); + statusBar()->clearMessage(); } void MainWindow::manualCheckForUpdates() { - doUpdates(true, true); + statusBar()->showMessage(tr("Checking for updates...")); + doUpdates(true); + statusBar()->clearMessage(); } void MainWindow::downloads() { - doUpdates(false, true); + doUpdates(false); } -void MainWindow::doUpdates(bool check, bool manual) +void MainWindow::doUpdates(bool check, bool interactive) { Updates *upd = new Updates(this, updateFactories); @@ -259,9 +263,9 @@ void MainWindow::doUpdates(bool check, bool manual) }); if (check) - upd->checkForUpdates(manual); + upd->autoUpdates(interactive); else - upd->doUpdates(); + upd->manualUpdates(); delete upd; } @@ -471,7 +475,7 @@ void MainWindow::sdsync(bool postUpdate) } if (postUpdate) - syncOpts.folderA = g.updateDir(); + syncOpts.folderA = g.lastUpdateDir(); if (syncOpts.folderA.isEmpty()) syncOpts.folderA = g.profile[g.id()].sdPath(); diff --git a/companion/src/mainwindow.h b/companion/src/mainwindow.h index 219a4cc3f..8ed31dc3a 100644 --- a/companion/src/mainwindow.h +++ b/companion/src/mainwindow.h @@ -113,7 +113,7 @@ class MainWindow : public QMainWindow void autoCheckForUpdates(); void manualCheckForUpdates(); void downloads(); - void doUpdates(bool check, bool manual); + void doUpdates(bool check, bool interactive = true); void openFile(const QString & fileName, bool updateLastUsedDir = false); diff --git a/companion/src/storage/appdata.cpp b/companion/src/storage/appdata.cpp index 56df7da65..83a1afa2d 100644 --- a/companion/src/storage/appdata.cpp +++ b/companion/src/storage/appdata.cpp @@ -19,6 +19,7 @@ */ #include "appdata.h" +#include "updates/updateoptionsdialog.h" #include #include @@ -289,6 +290,32 @@ void Profile::resetFwVariables() } +// ** ComponentAssetData class******************** + +ComponentAssetData::ComponentAssetData() : CompStoreObj(), index(-1) +{ + CompStoreObj::addObjectMapping(propertyGroup(), this); +} + +// The default copy operator can not be used since the index variable would be destroyed +ComponentAssetData & ComponentAssetData::operator= (const ComponentAssetData & rhs) +{ + for (int i = metaObject()->propertyOffset(), e = metaObject()->propertyCount(); i < e; ++i) { + const QMetaProperty & prop = metaObject()->property(i); + if (!prop.isValid() || !prop.isWritable()) { + qWarning() << "Could not copy property" << QString(prop.name()) << "isValid:" << prop.isValid() << "isWritable:" << prop.isWritable(); + continue; + } + prop.write(this, prop.read(&rhs)); + } + return *this; +} + +bool ComponentAssetData::existsOnDisk() +{ + return (m_settings.contains(settingsPath() % "desc")); +} + // ** ComponentData class******************** ComponentData::ComponentData() : CompStoreObj(), index(-1) @@ -318,11 +345,32 @@ bool ComponentData::existsOnDisk() void ComponentData::clearRelease() { - release(CompStoreObj::propertyDefaultValue(this, "release").toString()); - id(CompStoreObj::propertyDefaultValue(this, "id").toInt()); - prerelease(CompStoreObj::propertyDefaultValue(this, "prerelease").toBool()); - date(CompStoreObj::propertyDefaultValue(this, "date").toString()); - version(CompStoreObj::propertyDefaultValue(this, "version").toString()); + releaseReset(); + idReset(); + prereleaseReset(); + dateReset(); + versionReset(); +} + +ComponentAssetData & ComponentData::getAsset(int index) +{ + if (index > -1 && index < MAX_COMPONENT_ASSETS) + return asset[index]; + return asset[0]; +} + +const ComponentAssetData & ComponentData::getAsset(int index) const +{ + if (index > -1 && index < MAX_COMPONENT_ASSETS) + return asset[index]; + return asset[0]; +} + +void ComponentData::initAllAssets() +{ + for (int i = 0; i < MAX_COMPONENT_ASSETS; i++) { + asset[i].resetAll(); + } } // ** AppData class******************** @@ -345,16 +393,20 @@ AppData::AppData() : qWarning() << "Could not create settings backup path" << CPN_SETTINGS_BACKUP_DIR; // Configure the profiles - for (int i=0; i -1 && m_releaseChannel != (int)g.component[m_settingsIdx].releaseChannel()) - return true; - else - return false; + if (m_releaseChannel != channel) { + m_releaseChannel = channel; + update(); + } } void ReleasesItemModel::parseMetaData(const int mdt, QJsonDocument * jsonDoc) { json = jsonDoc; - if (m_settingsIdx > -1) - m_releaseChannel = g.component[m_settingsIdx].releaseChannel(); - switch (mdt) { case MDT_Release: parseRelease(); @@ -105,6 +103,7 @@ void ReleasesItemModel::parseReleases() } sort(0, Qt::DescendingOrder); + m_refreshRequired = false; } void ReleasesItemModel::parseJsonObject(const QJsonObject & obj) @@ -136,19 +135,31 @@ void ReleasesItemModel::parseJsonObject(const QJsonObject & obj) item->setData(QDateTime::fromString(obj.value("created_at").toString(), Qt::ISODate), UpdatesItemModel::IMDR_Date); } - item->setData(isReleaseAvailable(tag, prerelease), UpdatesItemModel::IMDR_Available); + setDynamicItemData(item); appendRow(item); } -bool ReleasesItemModel::isReleaseAvailable(const QString tagname, const bool prerelease) +void ReleasesItemModel::setDynamicItemData(QStandardItem * item) { - if (prerelease) { + item->setData(isReleaseAvailable(item), UpdatesItemModel::IMDR_Available); +} + +void ReleasesItemModel::update() +{ + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i)); +} + +bool ReleasesItemModel::isReleaseAvailable(QStandardItem * item) +{ + if (item->data(IMDR_Prerelease).toBool()) { if (m_releaseChannel == ComponentData::RELEASE_CHANNEL_STABLE) { //qDebug() << "Release channel stable" << tagname << "is pre-release" ; return false; } - else if (m_releaseChannel == ComponentData::RELEASE_CHANNEL_PRERELEASE && tagname.toLower() == m_nightlyName) { + else if (m_releaseChannel == ComponentData::RELEASE_CHANNEL_PRERELEASE && + item->data(IMDR_Tag).toString().toLower() == m_nightlyName) { //qDebug() << "Release channel pre-release" << tagname << "is nightly" ; return false; } @@ -382,7 +393,6 @@ QStringList UpdatesFilteredItemModel::list() return strl; } - /* ReleasesFilteredItemModel */ @@ -427,8 +437,8 @@ bool AssetsFilteredItemModel::setCopyFilter(const int id, const QString filter) ReleasesMetaData */ -ReleasesMetaData::ReleasesMetaData(QWidget * parent) : - QWidget(parent), +ReleasesMetaData::ReleasesMetaData(QObject * parent) : + QObject(parent), m_repo(""), m_id(0) { @@ -438,10 +448,7 @@ ReleasesMetaData::ReleasesMetaData(QWidget * parent) : bool ReleasesMetaData::refreshRequired() { - if (m_id != 0) - return itemModel->releaseChannelChanged(); - - return true; + return m_id == 0 ? true : itemModel->refreshRequired(); } int ReleasesMetaData::getSetId() @@ -462,12 +469,28 @@ int ReleasesMetaData::getSetId(QVariant value, Qt::MatchFlags flags, int role) return m_id; } +QString ReleasesMetaData::name() +{ + if (m_id) + return filteredItemModel->name(m_id); + + return ""; +} + +QString ReleasesMetaData::version() +{ + if (m_id) + return filteredItemModel->version(m_id); + + return "0"; +} + /* AssetsMetaData */ -AssetsMetaData::AssetsMetaData(QWidget * parent) : - QWidget(parent) +AssetsMetaData::AssetsMetaData(QObject * parent) : + QObject(parent) { itemModel = new AssetsItemModel(); filteredItemModel = new AssetsFilteredItemModel(itemModel); diff --git a/companion/src/updates/repomodels.h b/companion/src/updates/repomodels.h index c2ed3d180..dffbc4cc5 100644 --- a/companion/src/updates/repomodels.h +++ b/companion/src/updates/repomodels.h @@ -22,7 +22,6 @@ #pragma once #include -#include #include #include @@ -86,17 +85,21 @@ class ReleasesItemModel : public UpdatesItemModel void setNightlyName(const QString name) { m_nightlyName = name.toLower(); } void setSettingsIndex(const int index) { m_settingsIdx = index; } + void setReleaseChannel(const int channel); void parseMetaData(const int mdt, QJsonDocument * json); int settingsIndex() { return m_settingsIdx; } - bool releaseChannelChanged(); + bool refreshRequired() { return m_refreshRequired; } private: int m_settingsIdx; QString m_nightlyName; int m_releaseChannel; + bool m_refreshRequired; - bool isReleaseAvailable(const QString tagname, const bool prerelease); + void setDynamicItemData(QStandardItem * item); + void update(); + bool isReleaseAvailable(QStandardItem * item); void parseRelease(); void parseReleases(); @@ -199,18 +202,19 @@ class AssetsFilteredItemModel : public UpdatesFilteredItemModel private: }; -class ReleasesMetaData : public QWidget +class ReleasesMetaData : public QObject { Q_OBJECT public: - explicit ReleasesMetaData(QWidget * parent); + explicit ReleasesMetaData(QObject * parent); virtual ~ReleasesMetaData() {}; bool refreshRequired(); void setRepo(QString repo) { m_repo = repo; } void setNightlyName(QString name) { itemModel->setNightlyName(name); } - void setSettingsIndex(int index) { itemModel->setSettingsIndex(index); } + void setSettingsIndex(const int index) { itemModel->setSettingsIndex(index); } + void setReleaseChannel(const int channel) { itemModel->setReleaseChannel(channel); } void setId(int id) { m_id = id; } int id() { return m_id; } @@ -226,9 +230,9 @@ class ReleasesMetaData : public QWidget void dumpContentsFiltered() { filteredItemModel->dumpContents(); } QString date() { return filteredItemModel->date(m_id); } - QString name() { return filteredItemModel->name(m_id); } + QString name(); bool prerelease() { return filteredItemModel->prerelease(m_id); } - QString version() { return filteredItemModel->version(m_id); } + QString version(); QString urlReleases() { return QString("%1/releases").arg(m_repo); } QString urlReleaseLatest() { return QString("%1/latest").arg(urlReleases()); } @@ -241,11 +245,11 @@ class ReleasesMetaData : public QWidget int m_id; }; -class AssetsMetaData : public QWidget +class AssetsMetaData : public QObject { Q_OBJECT public: - explicit AssetsMetaData(QWidget * parent); + explicit AssetsMetaData(QObject * parent); virtual ~AssetsMetaData() {}; void setRepo(QString repo) { m_repo = repo; } diff --git a/companion/src/updates/updatecompanion.cpp b/companion/src/updates/updatecompanion.cpp index feffc0a91..de2ef7772 100644 --- a/companion/src/updates/updatecompanion.cpp +++ b/companion/src/updates/updatecompanion.cpp @@ -20,7 +20,6 @@ */ #include "updatecompanion.h" -#include "appdata.h" #include #include @@ -59,14 +58,25 @@ UpdateCompanion::UpdateCompanion(QWidget * parent) : setName(tr("Companion")); setRepo(QString(GH_REPOS_EDGETX).append("/edgetx")); setReleasesNightlyName("nightly"); +} - dfltParams->data.flags = (UPDFLG_Common | UPDFLG_Locked | UPDFLG_AsyncInstall) & ~UPDFLG_CopyDest; +void UpdateCompanion::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = QString("%1").arg(QString(OS_FILEPATTERN)); - ap.maxExpected = 1; - ap.flags = dfltParams->data.flags; + g.component[settingsIndex()].initAllAssets(); + + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + + cad.desc("installer"); + cad.processes((UPDFLG_Common_Asset | UPDFLG_AsyncInstall) & ~UPDFLG_CopyDest); + cad.flags(cad.processes() | UPDFLG_CopyFiles | UPDFLG_Locked); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter(QString("%1").arg(QString(OS_FILEPATTERN))); + cad.maxExpected(1); + + qDebug() << "Asset settings initialised"; } bool UpdateCompanion::asyncInstall() @@ -110,7 +120,7 @@ bool UpdateCompanion::asyncInstall() #if defined(__linux__) || defined(__linux) QFile f(installerPath); if (!f.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner)) { - QMessageBox::critical(parentWidget(), CPN_STR_APP_NAME, tr("Unable to set file permissions on the AppImage")); + QMessageBox::critical(progress, CPN_STR_APP_NAME, tr("Unable to set file permissions on the AppImage")); return false; } @@ -123,24 +133,24 @@ bool UpdateCompanion::asyncInstall() if (dest.exists()) { if (!dest.remove()) { - QMessageBox::critical(parentWidget(), CPN_STR_APP_NAME, tr("Unable to delete file %1").arg(fileName)); + QMessageBox::critical(progress, CPN_STR_APP_NAME, tr("Unable to delete file %1").arg(fileName)); return false; } } if (!QFile::copy(installerPath, fileName)) { - QMessageBox::critical(parentWidget(), CPN_STR_APP_NAME, tr("Unable to copy file to %1").arg(fileName)); + QMessageBox::critical(progress, CPN_STR_APP_NAME, tr("Unable to copy file to %1").arg(fileName)); return false; } - if (QMessageBox::question(parentWidget(), CPN_STR_APP_NAME, "Restart Companion?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + if (QMessageBox::question(progress, CPN_STR_APP_NAME, "Restart Companion?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { QProcess::startDetached(fileName); qApp->exit(); } #else - int ret = QMessageBox::question(parentWidget(), CPN_STR_APP_NAME, OS_INSTALL_QUESTION, QMessageBox::Yes | QMessageBox::No); + int ret = QMessageBox::question(progress, CPN_STR_APP_NAME, OS_INSTALL_QUESTION, QMessageBox::Yes | QMessageBox::No); if (ret == QMessageBox::Yes) { if (QDesktopServices::openUrl(QUrl::fromLocalFile(installerPath))) @@ -152,7 +162,7 @@ bool UpdateCompanion::asyncInstall() return true; #else - QMessageBox::warning(parentWidget(), CPN_STR_APP_NAME, OS_INSTALL_MSG); + QMessageBox::warning(progress, CPN_STR_APP_NAME, OS_INSTALL_MSG); return true; #endif // OS_SUPPORTED_INSTALLER } @@ -162,9 +172,8 @@ const QString UpdateCompanion::currentRelease() #if defined(VERSION_TAG) return UpdateInterface::latestRelease(); #else - dfltParams->data.currentRelease = QString("EdgeTX v%1.%2 (Custom)").arg(VERSION_MAJOR).arg(VERSION_MINOR); - runParams->data.currentRelease = dfltParams->data.currentRelease; - return dfltParams->data.currentRelease; + params->currentRelease = QString("EdgeTX v%1.%2 (Custom)").arg(VERSION_MAJOR).arg(VERSION_MINOR); + return params->currentRelease; #endif } diff --git a/companion/src/updates/updatecompanion.h b/companion/src/updates/updatecompanion.h index a1b488326..b7fad86e2 100644 --- a/companion/src/updates/updatecompanion.h +++ b/companion/src/updates/updatecompanion.h @@ -33,6 +33,8 @@ class UpdateCompanion : public UpdateInterface virtual ~UpdateCompanion() {} protected: + virtual void initAssetSettings() override; + virtual bool asyncInstall() override; virtual const QString currentRelease() override; virtual const QString currentVersion() override; diff --git a/companion/src/updates/updatefirmware.cpp b/companion/src/updates/updatefirmware.cpp index be1f319c2..e66cd9b15 100644 --- a/companion/src/updates/updatefirmware.cpp +++ b/companion/src/updates/updatefirmware.cpp @@ -20,7 +20,6 @@ */ #include "updatefirmware.h" -#include "appdata.h" #include "flashfirmwaredialog.h" UpdateFirmware::UpdateFirmware(QWidget * parent) : @@ -29,17 +28,28 @@ UpdateFirmware::UpdateFirmware(QWidget * parent) : setName(tr("Firmware")); setRepo(QString(GH_REPOS_EDGETX).append("/edgetx")); setReleasesNightlyName("nightly"); +} - dfltParams->data.flags = UPDFLG_Common | UPDFLG_Locked | UPDFLG_AsyncInstall; +void UpdateFirmware::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = "edgetx-firmware"; - ap.maxExpected = 1; - ap.flags = dfltParams->data.flags | UPDFLG_CopyFiles; - ap.destSubDir = "FIRMWARE"; - ap.copyFilterType = UpdateParameters::UFT_Expression; - ap.copyFilter = QString("^%FWFLAVOUR%-.*\\.bin$"); + g.component[settingsIndex()].initAllAssets(); + + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + + cad.desc("binary"); + cad.processes(UPDFLG_Common_Asset | UPDFLG_AsyncInstall); + cad.flags(cad.processes() | UPDFLG_CopyFiles | UPDFLG_Locked); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter("edgetx-firmware"); + cad.maxExpected(1); + cad.destSubDir("FIRMWARE"); + cad.copyFilterType(UpdateParameters::UFT_Expression); + cad.copyFilter("^%FWFLAVOUR%-.*\\.bin$"); + + qDebug() << "Asset settings initialised"; } bool UpdateFirmware::asyncInstall() @@ -54,8 +64,11 @@ bool UpdateFirmware::asyncInstall() assets->setFilterFlags(UPDFLG_AsyncInstall); //reportProgress(tr("Asset filter applied: %1 Assets found: %2").arg(updateFlagsToString(UPDFLG_AsyncInstall)).arg(assets->count()), QtDebugMsg); - if (assets->count() != 1) { - reportProgress(tr("Expected 1 asset for install but none found"), QtCriticalMsg); + if (assets->count() < 1) + return true; + + if (assets->count() != params->assets.at(0).maxExpected) { + reportProgress(tr("Expected %1 asset for install but %2 found").arg(params->assets.at(0).maxExpected).arg(assets->count()), QtCriticalMsg); return false; } @@ -64,9 +77,9 @@ bool UpdateFirmware::asyncInstall() if (!assets->subDirectory().isEmpty()) destPath.append("/" % assets->subDirectory()); - const UpdateParameters::AssetParams &ap = runParams->data.assets.at(0); + const UpdateParameters::AssetParams &ap = params->assets.at(0); - QString pattern(runParams->buildFilterPattern(ap.copyFilterType, ap.copyFilter)); + QString pattern(params->buildFilterPattern(ap.copyFilterType, ap.copyFilter)); QRegularExpression filter(pattern, QRegularExpression::CaseInsensitiveOption); QDirIterator it(destPath); @@ -92,7 +105,7 @@ bool UpdateFirmware::asyncInstall() g.currentProfile().fwName(destPath); - int ret = QMessageBox::question(this, CPN_STR_APP_NAME, tr("Write the updated firmware to the radio now ?"), QMessageBox::Yes | QMessageBox::No); + int ret = QMessageBox::question(progress, CPN_STR_APP_NAME, tr("Write the updated firmware to the radio now ?"), QMessageBox::Yes | QMessageBox::No); if (ret == QMessageBox::Yes) { FlashFirmwareDialog *dlg = new FlashFirmwareDialog(this); dlg->exec(); diff --git a/companion/src/updates/updatefirmware.h b/companion/src/updates/updatefirmware.h index b96d24143..0446aa439 100644 --- a/companion/src/updates/updatefirmware.h +++ b/companion/src/updates/updatefirmware.h @@ -33,5 +33,7 @@ class UpdateFirmware : public UpdateInterface virtual ~UpdateFirmware() {} protected: + virtual void initAssetSettings() override; + virtual bool asyncInstall() override; }; diff --git a/companion/src/updates/updateinterface.cpp b/companion/src/updates/updateinterface.cpp index f6dbe201b..fd2f01bd3 100644 --- a/companion/src/updates/updateinterface.cpp +++ b/companion/src/updates/updateinterface.cpp @@ -20,7 +20,6 @@ */ #include "updateinterface.h" -#include "appdata.h" #include "minizinterface.h" #include "helpers.h" #include "updatefirmware.h" @@ -44,64 +43,34 @@ */ -UpdateParameters::UpdateParameters(QWidget * parent) : - QWidget(parent) +UpdateParameters::UpdateParameters(QObject * parent) : + QObject(parent) { - data.flags = 0; - data.decompressDirUseDwnld = true; - data.updateDirUseSD = true; -} - -UpdateParameters& UpdateParameters::operator=(const UpdateParameters& source) -{ - // Perform a deep copy - - // check for self-assignment - - - if (this != &source) { - data.flags = source.data.flags; - data.fwFlavour = source.data.fwFlavour; - data.language = source.data.language; - data.currentRelease = source.data.currentRelease; - data.updateRelease = source.data.updateRelease; - data.downloadDir = source.data.downloadDir; - data.decompressDirUseDwnld = source.data.decompressDirUseDwnld; - data.decompressDir = source.data.decompressDir; - data.updateDirUseSD = source.data.updateDirUseSD; - data.updateDir = source.data.updateDir; - - while (!data.assets.isEmpty()) { - data.assets.removeLast(); - } - - for (int i = 0; i < source.data.assets.size(); i++) { - data.assets.append(source.data.assets[i]); - } - } - - return *this; + logLevel = 0; + flags = 0; + decompressDirUseDwnld = true; + updateDirUseSD = true; } UpdateParameters::AssetParams & UpdateParameters::addAsset() { AssetParams ap; + ap.processes = 0; ap.flags = 0; ap.filterType = UFT_None; - ap.maxExpected = -1; + ap.maxExpected = 0; ap.copyFilterType = UFT_None; + assets.append(ap); - data.assets.append(ap); - - return data.assets[data.assets.size() - 1]; + return assets[assets.size() - 1]; } QString UpdateParameters::buildFilterPattern(const UpdateFilterType filterType, const QString & filter) { QString pattern(filter); - pattern.replace("%FWFLAVOUR%", data.fwFlavour); - pattern.replace("%LANGUAGE%", data.language); + pattern.replace("%FWFLAVOUR%", fwFlavour); + pattern.replace("%LANGUAGE%", language); switch ((int)filterType) { case UFT_Exact: @@ -144,23 +113,20 @@ QString UpdateParameters::updateFilterTypeToString(UpdateFilterType uft) UpdateInterface::UpdateInterface(QWidget * parent) : QWidget(parent), + progress(nullptr), + resultsPerPage(-1), reply(nullptr), buffer(new QByteArray()), - file(nullptr) + file(nullptr), + m_settingsIdx(-1) { - progress = nullptr; - m_settingsIdx = -1; - QNetworkProxyFactory::setUseSystemConfiguration(true); releases = new ReleasesMetaData(this); assets = new AssetsMetaData(this); - dfltParams = new UpdateParameters(this); - runParams = new UpdateParameters(this); + params = new UpdateParameters(this); setReleasesNightlyName(""); - dfltParams->data.flags = UPDFLG_Common; - resultsPerPage = -1; } UpdateInterface::~UpdateInterface() @@ -172,22 +138,16 @@ UpdateInterface::~UpdateInterface() delete file; delete releases; delete assets; - delete dfltParams; - delete runParams; + delete params; } -bool UpdateInterface::manualUpdate(ProgressWidget * progress) +bool UpdateInterface::update(ProgressWidget * progress) { + if (!(params->flags & UPDFLG_Update)) + return true; + this->progress = progress; - if (runParams->data.flags & UPDFLG_Update) - return update(); - - return true; -} - -bool UpdateInterface::update() -{ if (progress) { progress->setInfo(tr("Processing updates for: %1").arg(name)); progress->setValue(0); @@ -196,22 +156,22 @@ bool UpdateInterface::update() reportProgress(tr("Processing updates for: %1").arg(name), QtInfoMsg); - if ((runParams->data.flags & UPDFLG_Preparation) && !preparation()) { + if (!preparation()) { reportProgress(tr("%1 preparation failed").arg(name), QtCriticalMsg); return false; } - if ((runParams->data.flags & UPDFLG_Download) && !download()) { + if (!download()) { reportProgress(tr("%1 download failed").arg(name), QtCriticalMsg); return false; } - if ((runParams->data.flags & UPDFLG_Decompress) && !decompress()) { + if (!decompress()) { reportProgress(tr("%1 decompress failed").arg(name), QtCriticalMsg); return false; } - if ((runParams->data.flags & UPDFLG_CopyDest) && !copyToDestination()) { + if (!copyToDestination()) { reportProgress(tr("%1 copy to destination failed").arg(name), QtCriticalMsg); return false; } @@ -222,12 +182,12 @@ bool UpdateInterface::update() return false; } - if ((runParams->data.flags & UPDFLG_AsyncInstall) && !asyncInstall()) { + if (!asyncInstall()) { reportProgress(tr("%1 start async failed").arg(name), QtCriticalMsg); return false; } - if ((runParams->data.flags & UPDFLG_Housekeeping) && !housekeeping()) { + if (!housekeeping()) { reportProgress(tr("%1 housekeeping failed").arg(name), QtCriticalMsg); return false; } @@ -235,7 +195,7 @@ bool UpdateInterface::update() reportProgress(tr("%1 update successful").arg(name), QtInfoMsg); if (!progress) - QMessageBox::information(this, CPN_STR_APP_NAME, tr("%1 update successful").arg(name)); + QMessageBox::information(progress, CPN_STR_APP_NAME, tr("%1 update successful").arg(name)); return true; } @@ -302,7 +262,9 @@ QString UpdateInterface::semanticVersion(QString version) void UpdateInterface::reportProgress(const QString & text, const int type) { - if (logLevel == QtDebugMsg || (logLevel == QtInfoMsg && type > QtDebugMsg) || (type < QtInfoMsg && type >= logLevel)) { + if (params->logLevel == QtDebugMsg || + (params->logLevel == QtInfoMsg && type > QtDebugMsg) || + (type < QtInfoMsg && type >= params->logLevel)) { if (progress) progress->addMessage(text, type); else @@ -323,13 +285,13 @@ void UpdateInterface::progressMessage(const QString & text) void UpdateInterface::criticalMsg(const QString & msg) { - QMessageBox::critical(nullptr, tr("Update Interface"), msg); + QMessageBox::critical(progress, tr("Update Interface"), msg); } void UpdateInterface::setName(QString name) { this->name = name; - setSettingsIdx(); + setSettingsIndex(); currentRelease(); } @@ -339,7 +301,7 @@ void UpdateInterface::setRepo(QString repo) assets->setRepo(repo); } -void UpdateInterface::setSettingsIdx() +void UpdateInterface::setSettingsIndex() { int i = g.getComponentIndex(name); @@ -358,6 +320,50 @@ void UpdateInterface::setSettingsIdx() m_settingsIdx = i; releases->setSettingsIndex(m_settingsIdx); + if (isValidSettingsIndex() && !g.component[m_settingsIdx].asset[0].existsOnDisk()) + initAssetSettings(); +} + +void UpdateInterface::loadAssetSettings() +{ + if (!isValidSettingsIndex()) + return; + + params->assets.clear(); + + for (int i = 0; i < MAX_COMPONENT_ASSETS && g.component[m_settingsIdx].asset[i].existsOnDisk(); i++) { + UpdateParameters::AssetParams &ap = params->addAsset(); + ComponentAssetData &cad = g.component[m_settingsIdx].asset[i]; + + ap.processes = cad.processes(); + ap.flags = cad.flags(); + ap.filterType = (UpdateParameters::UpdateFilterType)cad.filterType(); + ap.filter = cad.filter(); + ap.maxExpected = cad.maxExpected(); + ap.destSubDir = cad.destSubDir(); + ap.copyFilterType = (UpdateParameters::UpdateFilterType)cad.copyFilterType(); + ap.copyFilter = cad.copyFilter(); + } +} + +void UpdateInterface::saveAssetSettings() +{ + if (!isValidSettingsIndex()) + return; + + for (int i = 0; i < MAX_COMPONENT_ASSETS && g.component[m_settingsIdx].asset[i].existsOnDisk(); i++) { + const UpdateParameters::AssetParams &ap = params->assets.at(i); + ComponentAssetData &cad = g.component[m_settingsIdx].asset[i]; + + // ap.processes do not overwrite as read only + cad.flags(ap.flags); + cad.filterType(ap.filterType); + cad.filter(ap.filter); + cad.maxExpected(ap.maxExpected); + cad.destSubDir(ap.destSubDir); + cad.copyFilterType(ap.copyFilterType); + cad.copyFilter(ap.copyFilter); + } } bool UpdateInterface::isUpdateable() @@ -365,72 +371,90 @@ bool UpdateInterface::isUpdateable() return g.component[m_settingsIdx].checkForUpdate(); } -void UpdateInterface::resetRunEnvironment() +void UpdateInterface::resetEnvironment() { + // reset from previous run if any + params->flags &= ~UPDFLG_Update; progress = nullptr; - logLevel = g.updLogLevel(); - initFlavourLanguage(dfltParams); - initParamFolders(dfltParams); - - *runParams = *dfltParams; - runParams->data.flags &= ~UPDFLG_Update; + params->logLevel = g.updLogLevel(); + setReleaseChannel(g.component[m_settingsIdx].releaseChannel()); + params->updateRelease = ""; + setFlavourLanguage(); + loadAssetSettings(); + setParamFolders(); if (g.updDelDownloads()) - runParams->data.flags |= UpdateInterface::UPDFLG_DelDownloads; + params->flags |= UpdateInterface::UPDFLG_DelDownloads; else - runParams->data.flags &= ~UpdateInterface::UPDFLG_DelDownloads; + params->flags &= ~UpdateInterface::UPDFLG_DelDownloads; + + if (g.updDelDecompress()) + params->flags |= UpdateInterface::UPDFLG_DelDecompress; + else + params->flags &= ~UpdateInterface::UPDFLG_DelDecompress; } -void UpdateInterface::initFlavourLanguage(UpdateParameters * params) +void UpdateInterface::setReleaseChannel(int channel) +{ + params->releaseChannel = channel; + releases->setReleaseChannel(channel); +} + +void UpdateInterface::setFlavourLanguage() { const Firmware * baseFw = getCurrentFirmware()->getFirmwareBase(); const QStringList currVariant = getCurrentFirmware()->getId().split('-'); - params->data.fwFlavour = ""; + params->fwFlavour = ""; if (currVariant.size() > 1) { - params->data.fwFlavour = currVariant.at(1); - params->data.fwFlavour = params->data.fwFlavour.replace('+', 'p'); + params->fwFlavour = currVariant.at(1); + params->fwFlavour = params->fwFlavour.replace('+', 'p'); } - params->data.language = ""; + params->language = ""; for (const char *lang : baseFw->languageList()) { if (currVariant.last() == lang) { - params->data.language = currVariant.last(); + params->language = currVariant.last(); break; } } } -void UpdateInterface::initParamFolders(UpdateParameters * params) +void UpdateInterface::setParamFolders() { if (g.downloadDir().trimmed().isEmpty()) g.downloadDirReset(true); - params->data.downloadDir = g.downloadDir().trimmed(); + params->downloadDir = g.downloadDir().trimmed(); - params->data.decompressDirUseDwnld = g.decompressDirUseDwnld(); + params->decompressDirUseDwnld = g.decompressDirUseDwnld(); - if (params->data.decompressDirUseDwnld) - params->data.decompressDir = params->data.downloadDir; + if (params->decompressDirUseDwnld) + params->decompressDir = params->downloadDir; else { if (g.decompressDir().trimmed().isEmpty()) g.decompressDirReset(true); - params->data.decompressDir = g.decompressDir().trimmed(); + params->decompressDir = g.decompressDir().trimmed(); } - params->data.updateDirUseSD = g.updateDirUseSD(); + if (g.currentProfile().sdPath().trimmed().isEmpty()) + params->updateDirUseSD = false; + else + params->updateDirUseSD = g.updateDirUseSD(); - if (params->data.updateDirUseSD && (!g.currentProfile().sdPath().trimmed().isEmpty())) - params->data.updateDir = g.currentProfile().sdPath().trimmed(); + if (params->updateDirUseSD) { + params->sdDir = g.currentProfile().sdPath().trimmed(); + params->updateDir = params->sdDir; + } else { if (g.updateDir().trimmed().isEmpty()) g.updateDirReset(true); - params->data.updateDir = g.updateDir().trimmed(); + params->updateDir = g.updateDir().trimmed(); } } @@ -442,34 +466,22 @@ void UpdateInterface::clearRelease() const QString UpdateInterface::currentRelease() { - dfltParams->data.currentRelease = g.component[m_settingsIdx].release(); - runParams->data.currentRelease = dfltParams->data.currentRelease; - return dfltParams->data.currentRelease; + params->currentRelease = g.component[m_settingsIdx].release(); + return params->currentRelease; } -const QString UpdateInterface::latestRelease() +QString UpdateInterface::latestRelease() { - if (repoReleasesMetaData()) { - releases->getSetId(); - if (releases->id()) - dfltParams->data.updateRelease = releases->name(); - else - dfltParams->data.updateRelease = ""; - } - - return dfltParams->data.updateRelease; + repoReleasesMetaData(); + return releases->name(); } const QString UpdateInterface::updateRelease() { - if (runParams->data.updateRelease.isEmpty()) { - if (dfltParams->data.updateRelease.isEmpty()) - latestRelease(); + if (params->updateRelease.isEmpty()) + params->updateRelease = latestRelease(); - runParams->data.updateRelease = dfltParams->data.updateRelease; - } - - return runParams->data.updateRelease; + return params->updateRelease; } const bool UpdateInterface::isUpdateAvailable() @@ -498,11 +510,7 @@ const bool UpdateInterface::isLatestVersion(const QString & installed, const QSt const bool UpdateInterface::isLatestRelease() { - // subsequent processes rely on this call being successful so advise nothing to do - if (!repoReleasesMetaData()) { - return true; - } - + repoReleasesMetaData(); QString currentVer = currentVersion(); QString latestVer = releases->version(); // nightlies often have the same version so also check id @@ -576,21 +584,21 @@ bool UpdateInterface::setRunFolders() } } - downloadDir = QString("%1/%2/%3").arg(runParams->data.downloadDir).arg(name).arg(fldr); + downloadDir = QString("%1/%2/%3").arg(params->downloadDir).arg(name).arg(fldr); if (!checkCreateDirectory(downloadDir, UPDFLG_Download)) return false; //reportProgress(tr("Download directory: %1").arg(downloadDir), QtDebugMsg); - decompressDir = QString("%1/%2/%3").arg(runParams->data.decompressDir).arg(name).arg(fldr); + decompressDir = QString("%1/%2/%3").arg(params->decompressDir).arg(name).arg(fldr); if (!checkCreateDirectory(decompressDir, UPDFLG_Decompress)) return false; //reportProgress(tr("Decompress directory: %1").arg(decompressDir), QtDebugMsg); - updateDir = runParams->data.updateDir; + updateDir = params->updateDir; if (!checkCreateDirectory(updateDir, UPDFLG_CopyDest)) return false; @@ -602,7 +610,7 @@ bool UpdateInterface::setRunFolders() bool UpdateInterface::checkCreateDirectory(const QString & dir, const UpdateFlags flag) { - if (runParams->data.flags & flag) { + if (params->flags & flag) { if (dir.isEmpty()) { reportProgress(tr("%1 directory not configured in application settings!").arg(updateFlagsToString(flag)), QtCriticalMsg); return false; @@ -826,17 +834,17 @@ bool UpdateInterface::convertDownloadToJson(QJsonDocument * json) bool UpdateInterface::getSetAssets(const UpdateParameters::AssetParams & ap) { - QString pattern(runParams->buildFilterPattern(ap.filterType, ap.filter)); + QString pattern(params->buildFilterPattern(ap.filterType, ap.filter)); assets->setFilterPattern(pattern); - //reportProgress(tr("Asset filter applied: %1").arg(pattern), QtDebugMsg); + reportProgress(tr("Asset filter: %1").arg(pattern), QtDebugMsg); - if (assets->count() < 0) { - reportProgress(tr("No assets not found in release '%1' using filter pattern '%2'").arg(releases->name().arg(pattern)), QtCriticalMsg); + if (assets->count() < 1) { + reportProgress(tr("No assets found in release '%1' using filter '%2'").arg(releases->name()).arg(pattern), QtCriticalMsg); return false; } - else if (ap.maxExpected > -1 && assets->count() > ap.maxExpected) { - reportProgress(tr("%1 assets found when %2 expected in release '%3' using filter pattern '%4'") - .arg(assets->count()).arg(ap.maxExpected).arg(releases->name().arg(pattern)), QtCriticalMsg); + else if (ap.maxExpected > 0 && assets->count() > ap.maxExpected) { + reportProgress(tr("%1 assets found when %2 expected in release '%3' using filter '%4'") + .arg(assets->count() + 1).arg(ap.maxExpected).arg(releases->name().arg(pattern)), QtCriticalMsg); return false; } @@ -854,7 +862,7 @@ bool UpdateInterface::getSetAssets(const UpdateParameters::AssetParams & ap) return false; } - if (!assets->setCopyFilter(runParams->buildFilterPattern(ap.copyFilterType, ap.copyFilter))) { + if (!assets->setCopyFilter(params->buildFilterPattern(ap.copyFilterType, ap.copyFilter))) { reportProgress(tr("Unable to set copy filter for asset %1").arg(assets->filename()), QtCriticalMsg); return false; } @@ -894,21 +902,23 @@ void UpdateInterface::downloadBinaryToFile(const QString & url, const QString & if (f.exists()) { reportProgress(tr("File exists: %1").arg(filename), QtDebugMsg); - int reply = QMessageBox::question(this, CPN_STR_APP_NAME, tr("File %1 exists. Download again?").arg(filename), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); - if (reply == QMessageBox::Cancel) { - //reportProgress(tr("User action: Cancel"), QtDebugMsg); - downloadSuccess = false; - return; - } - else if (reply == QMessageBox::No) { - //reportProgress(tr("User action: Use previous download"), QtDebugMsg); - downloadSuccess = true; - return; - } - else { - ; - //reportProgress(tr("User action: Download again"), QtDebugMsg); + if (progress) { + int reply = QMessageBox::question(progress, CPN_STR_APP_NAME, tr("File %1 exists. Download again?").arg(filename), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::No); + if (reply == QMessageBox::Cancel) { + //reportProgress(tr("User action: Cancel"), QtDebugMsg); + downloadSuccess = false; + return; + } + else if (reply == QMessageBox::No) { + //reportProgress(tr("User action: Use previous download"), QtDebugMsg); + downloadSuccess = true; + return; + } + else { + ; + //reportProgress(tr("User action: Download again"), QtDebugMsg); + } } } else if (!QDir().mkpath(f.path())) { @@ -964,7 +974,7 @@ bool UpdateInterface::decompressArchive(const QString & archivePath, const QStri dest.append(QFileInfo(archivePath).completeBaseName()); - MinizInterface mIface(progress, MinizInterface::PCM_SIZE, logLevel); + MinizInterface mIface(progress, MinizInterface::PCM_SIZE, params->logLevel); if (!mIface.unzipArchiveToPath(archivePath, dest)) { reportProgress(tr("Failed to decompress %1").arg(archivePath), QtCriticalMsg); @@ -1238,8 +1248,8 @@ bool UpdateInterface::preparation() if (progress) progress->setValue(++cnt); - if (!releases->getSetId(runParams->data.updateRelease)) { - reportProgress(tr("Set release id from update release name failed"), QtCriticalMsg); + if (!releases->getSetId(params->updateRelease)) { + reportProgress(tr("Set release id from update release '%1' failed").arg(params->updateRelease), QtCriticalMsg); return false; } @@ -1265,8 +1275,8 @@ bool UpdateInterface::flagAssets() { progressMessage(tr("Flagging assets")); - for (int i = 0; i < runParams->data.assets.size(); i++) { - const UpdateParameters::AssetParams & ap = runParams->data.assets.at(i); + for (int i = 0; i < params->assets.size(); i++) { + const UpdateParameters::AssetParams & ap = params->assets.at(i); if (!getSetAssets(ap)) return false; } @@ -1323,7 +1333,9 @@ bool UpdateInterface::housekeeping() if (progress) progress->setValue(++cnt); - if (runParams->data.flags & UPDFLG_DelDownloads) { + g.lastUpdateDir(params->updateDir); // used by sdsync + + if (params->flags & UPDFLG_DelDownloads) { reportProgress(tr("Delete download directory: %1").arg(downloadDir), QtDebugMsg); QDir d(downloadDir); if (!d.removeRecursively()) @@ -1333,11 +1345,24 @@ bool UpdateInterface::housekeeping() if (progress) progress->setValue(++cnt); - if (!g.decompressDirUseDwnld() && (runParams->data.flags & UPDFLG_DelDownloads)) { - reportProgress(tr("Delete decompress directory: %1").arg(decompressDir), QtDebugMsg); - QDir d(decompressDir); - if (!d.removeRecursively()) - reportProgress(tr("Failed to delete decompress folder %1").arg(decompressDir), QtCriticalMsg); + if (params->flags & UPDFLG_DelDecompress) { + if (!params->decompressDirUseDwnld) { + reportProgress(tr("Delete decompress directory: %1").arg(decompressDir), QtDebugMsg); + QDir d(decompressDir); + if (!d.removeRecursively()) + reportProgress(tr("Failed to delete decompress folder %1").arg(decompressDir), QtCriticalMsg); + } + else if (!(params->flags & UPDFLG_DelDownloads)) { + assets->setFilterFlags(UPDFLG_Decompress); + for (int i = 0; i < assets->count(); i++) { + assets->getSetId(i); + QString path = QString("%1/A%2/%3").arg(decompressDir).arg(assets->id()).arg(QFileInfo(assets->filename()).completeBaseName()); + reportProgress(tr("Delete decompress folder: %1").arg(path), QtDebugMsg); + //QDir d(path); + if (!QDir(path).removeRecursively()) + reportProgress(tr("Failed to delete decompress folder %1").arg(path), QtCriticalMsg); + } + } } if (progress) @@ -1346,6 +1371,7 @@ bool UpdateInterface::housekeeping() return true; } +// as unique per component override if used bool UpdateInterface::asyncInstall() { return true; @@ -1403,11 +1429,31 @@ void UpdateFactories::unregisterUpdateFactories() delete factory; } -const UpdateParameters * const UpdateFactories::getDefaultParams(const QString & name) +void UpdateFactories::initAssetSettings(const QString & name) { foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { if (name == factory->name()) { - return factory->instance()->getDefaultParams(); + factory->instance()->initAssetSettings(); + break; + } + } +} + +void UpdateFactories::saveAssetSettings(const QString & name) +{ + foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { + if (name == factory->name()) { + factory->instance()->saveAssetSettings(); + break; + } + } +} + +UpdateParameters * const UpdateFactories::getParams(const QString & name) +{ + foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { + if (name == factory->name()) { + return factory->instance()->getParams(); break; } } @@ -1415,32 +1461,20 @@ const UpdateParameters * const UpdateFactories::getDefaultParams(const QString & return nullptr; } -UpdateParameters * const UpdateFactories::getRunParams(const QString & name) +void UpdateFactories::resetEnvironment(const QString & name) { foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { if (name == factory->name()) { - return factory->instance()->getRunParams(); - break; - } - } - - return nullptr; -} - -void UpdateFactories::resetRunEnvironment(const QString & name) -{ - foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { - if (name == factory->name()) { - factory->instance()->resetRunEnvironment(); + factory->instance()->resetEnvironment(); break; } } } -void UpdateFactories::resetAllRunEnvironments() +void UpdateFactories::resetAllEnvironments() { foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { - factory->instance()->resetRunEnvironment(); + resetEnvironment(factory->name()); } } @@ -1461,7 +1495,7 @@ const QMap UpdateFactories::sortedComponentsList(bool updateableOn foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { if (updateableOnly && !factory->instance()->isUpdateable()) continue; - map.insert(factory->name(), factory->instance()->settingsIdx()); + map.insert(factory->name(), factory->instance()->settingsIndex()); } return map; @@ -1477,6 +1511,16 @@ void UpdateFactories::clearRelease(const QString & name) } } +void UpdateFactories::setReleaseChannel(const QString & name, int channel) +{ + foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { + if (name == factory->name()) { + factory->instance()->setReleaseChannel(channel); + break; + } + } +} + const QString UpdateFactories::currentRelease(const QString & name) { QString ret; @@ -1547,20 +1591,34 @@ const QStringList UpdateFactories::releases(const QString & name) return ret; } -bool UpdateFactories::manualUpdate(ProgressWidget * progress) +bool UpdateFactories::update(const QString & name, ProgressWidget * progress) { - bool ok = false; + bool ret = false; foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { - ok = factory->instance()->manualUpdate(progress); - if (!ok) + if (name == factory->name()) { + ret = factory->instance()->update(progress); + break; + } + } + + return ret; +} + +bool UpdateFactories::updateAll(ProgressWidget * progress) +{ + bool ret = false; + + foreach (UpdateFactoryInterface * factory, registeredUpdateFactories) { + ret = update(factory->name(), progress); + if (!ret) break; } - return ok; + return ret; } -const bool UpdateFactories::isUpdatesAvailable(QStringList & names) +const bool UpdateFactories::isUpdateAvailable(QStringList & names) { bool ret = false; names.clear(); diff --git a/companion/src/updates/updateinterface.h b/companion/src/updates/updateinterface.h index d09924d62..37493a908 100644 --- a/companion/src/updates/updateinterface.h +++ b/companion/src/updates/updateinterface.h @@ -24,13 +24,13 @@ #include "repomodels.h" #include "constants.h" #include "progresswidget.h" +#include "appdata.h" #include -#include #include #include -class UpdateParameters : public QWidget +class UpdateParameters : public QObject { Q_OBJECT @@ -49,6 +49,7 @@ class UpdateParameters : public QWidget static QString updateFilterTypeToString(UpdateFilterType uft); struct AssetParams { + int processes; int flags; UpdateFilterType filterType; QString filter; @@ -58,34 +59,31 @@ class UpdateParameters : public QWidget QString copyFilter; }; - struct GeneralParams { - int flags; - QString fwFlavour; - QString language; - QString currentRelease; - QString updateRelease; - QString downloadDir; - bool decompressDirUseDwnld; - QString decompressDir; - bool updateDirUseSD; - QString updateDir; - QVector assets; - }; + int flags; + int logLevel; + QString fwFlavour; + QString language; + int releaseChannel; + QString currentRelease; + QString updateRelease; + QString downloadDir; + bool decompressDirUseDwnld; + QString decompressDir; + QString sdDir; + bool updateDirUseSD; + QString updateDir; + QVector assets; - GeneralParams data; - - UpdateParameters(QWidget * parent); + UpdateParameters(QObject * parent); virtual ~UpdateParameters() {} AssetParams & addAsset(); QString buildFilterPattern(const UpdateFilterType filterType, const QString & filter); - - UpdateParameters& operator=(const UpdateParameters& source); }; class UpdateInterface : public QWidget { - Q_OBJECT + Q_OBJECT public: @@ -110,7 +108,9 @@ class UpdateInterface : public QWidget UPDFLG_Housekeeping = 1 << 9, UPDFLG_AsyncInstall = 1 << 10, UPDFLG_DelDownloads = 1 << 11, - UPDFLG_Common = UPDFLG_Preparation | UPDFLG_Download | UPDFLG_Decompress | UPDFLG_CopyDest | UPDFLG_Housekeeping, + UPDFLG_DelDecompress = 1 << 12, + UPDFLG_Common_Asset = UPDFLG_Download | UPDFLG_Decompress | UPDFLG_CopyDest, + UPDFLG_Common = UPDFLG_Common_Asset | UPDFLG_Preparation | UPDFLG_Housekeeping, }; Q_ENUM(UpdateFlags) @@ -124,8 +124,7 @@ class UpdateInterface : public QWidget ReleasesMetaData *releases; AssetsMetaData *assets; - UpdateParameters *dfltParams; - UpdateParameters *runParams; + UpdateParameters *params; ProgressWidget *progress; QString name; @@ -133,11 +132,13 @@ class UpdateInterface : public QWidget QString downloadDir; QString decompressDir; QString updateDir; - int logLevel; - virtual bool manualUpdate(ProgressWidget * progress = nullptr); + virtual bool update(ProgressWidget * progress = nullptr); + + virtual void initAssetSettings() = 0; + virtual void loadAssetSettings(); + virtual void saveAssetSettings(); - virtual bool update(); virtual bool preparation(); virtual bool flagAssets(); virtual bool download(); @@ -153,7 +154,7 @@ class UpdateInterface : public QWidget virtual const QString updateRelease(); virtual const bool isLatestRelease(); virtual const bool isLatestVersion(const QString & current, const QString & latest); - virtual const QString latestRelease(); + virtual QString latestRelease(); void clearRelease(); const QStringList getReleases(); @@ -161,12 +162,12 @@ class UpdateInterface : public QWidget void setRepo(QString repo); void setResultsPerPage(int cnt) { resultsPerPage = cnt; } void setReleasesNightlyName(QString name) { releases->setNightlyName(name); } + void setReleaseChannel(int channel); - void initParamFolders(UpdateParameters * params); - const UpdateParameters * const getDefaultParams() { return dfltParams; } - UpdateParameters * getRunParams() { return runParams; } - void resetRunEnvironment(); - void setRunUpdate() { runParams->data.flags |= UPDFLG_Update; } + void setParamFolders(); + UpdateParameters * getParams() { return params; } + void resetEnvironment(); + void setRunUpdate() { params->flags |= UPDFLG_Update; } bool isUpdateable(); bool repoReleasesMetaData(); @@ -200,8 +201,9 @@ class UpdateInterface : public QWidget void criticalMsg(const QString & msg); static QString downloadDataTypeToString(DownloadDataType val); static QString updateFlagsToString(UpdateFlags val); - void initFlavourLanguage(UpdateParameters * params); - int settingsIdx() { return m_settingsIdx; } + void setFlavourLanguage(); + int settingsIndex() { return m_settingsIdx; } + bool isValidSettingsIndex() { return m_settingsIdx > -1 && m_settingsIdx < MAX_COMPONENTS; } private slots: void onDownloadFinished(QNetworkReply * reply, DownloadDataType ddt, int subtype); @@ -219,7 +221,7 @@ class UpdateInterface : public QWidget static QString semanticVersion(QString version); - void setSettingsIdx(); + void setSettingsIndex(); bool setRunFolders(); bool checkCreateDirectory(const QString & dirSetting, const UpdateFlags flag); @@ -258,7 +260,7 @@ class UpdateFactory : public UpdateFactoryInterface class UpdateFactories : public QWidget { - Q_OBJECT + Q_OBJECT public: explicit UpdateFactories(QWidget * parent = nullptr); @@ -268,22 +270,26 @@ class UpdateFactories : public QWidget void registerUpdateFactories(); void unregisterUpdateFactories(); - const UpdateParameters * const getDefaultParams(const QString & name); - UpdateParameters * const getRunParams(const QString & name); - void resetRunEnvironment(const QString & name); - void resetAllRunEnvironments(); + void initAssetSettings(const QString & name); + void saveAssetSettings(const QString & name); + + UpdateParameters * const getParams(const QString & name); + void resetEnvironment(const QString & name); + void resetAllEnvironments(); void setRunUpdate(const QString & name); const QMap sortedComponentsList(bool updateableOnly = false); void clearRelease(const QString & name); + void setReleaseChannel(const QString & name, int channel); const QString currentRelease(const QString & name); const QString updateRelease(const QString & name); const bool isLatestRelease(const QString & name); const QString latestRelease(const QString & name); const QStringList releases(const QString & name); - bool manualUpdate(ProgressWidget * progress = nullptr); - const bool isUpdatesAvailable(QStringList & names); + bool update(const QString & name, ProgressWidget * progress = nullptr); + bool updateAll(ProgressWidget * progress = nullptr); + const bool isUpdateAvailable(QStringList & names); private: QVector registeredUpdateFactories; diff --git a/companion/src/updates/updatemultiprotocol.cpp b/companion/src/updates/updatemultiprotocol.cpp index b9c9b1c44..10a16fe55 100644 --- a/companion/src/updates/updatemultiprotocol.cpp +++ b/companion/src/updates/updatemultiprotocol.cpp @@ -27,20 +27,33 @@ UpdateMultiProtocol::UpdateMultiProtocol(QWidget * parent) : setName(tr("Multiprotocol")); setRepo(QString(GITHUB_API_REPOS).append("/pascallanger/DIY-Multiprotocol-TX-Module")); setResultsPerPage(50); // GitHub REST API default 30 +} +void UpdateMultiProtocol::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; + + g.component[settingsIndex()].initAllAssets(); + { - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = "MultiLuaScripts"; - ap.maxExpected = 1; - ap.flags = dfltParams->data.flags | UPDFLG_Locked | UPDFLG_CopyStructure; + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + cad.desc("scripts"); + cad.processes(UPDFLG_Common_Asset); + cad.flags(cad.processes() | UPDFLG_CopyStructure); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter("MultiLuaScripts"); + cad.maxExpected(1); } - { - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Expression; - ap.filter = "^mm-stm-serial-.*\\.bin$"; - ap.flags = (dfltParams->data.flags | UPDFLG_CopyFiles) &~ UPDFLG_Decompress; - ap.destSubDir = "FIRMWARE"; + ComponentAssetData &cad = g.component[settingsIndex()].asset[1]; + cad.desc("binaries"); + cad.processes(UPDFLG_Common_Asset &~ UPDFLG_Decompress); + cad.flags(cad.processes() | UPDFLG_CopyFiles); + cad.filterType(UpdateParameters::UFT_Expression); + cad.filter("^mm-stm-serial-.*\\.bin$"); + cad.destSubDir("FIRMWARE"); } + + qDebug() << "Asset settings initialised"; } diff --git a/companion/src/updates/updatemultiprotocol.h b/companion/src/updates/updatemultiprotocol.h index 91c42e2e4..4e036b891 100644 --- a/companion/src/updates/updatemultiprotocol.h +++ b/companion/src/updates/updatemultiprotocol.h @@ -34,4 +34,7 @@ class UpdateMultiProtocol : public UpdateInterface explicit UpdateMultiProtocol(QWidget * parent); virtual ~UpdateMultiProtocol() {} + protected: + virtual void initAssetSettings() override; + }; diff --git a/companion/src/updates/updateoptionsdialog.cpp b/companion/src/updates/updateoptionsdialog.cpp index d2183e149..01f0e6155 100644 --- a/companion/src/updates/updateoptionsdialog.cpp +++ b/companion/src/updates/updateoptionsdialog.cpp @@ -30,40 +30,42 @@ #include #include -UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * factories, const int idx) : +UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * factories, const int idx, const bool isRun) : QDialog(parent), ui(new Ui::UpdateOptionsDialog), factories(factories), idx(idx), name(g.component[idx].name()), - dfltParams(factories->getDefaultParams(name)), - runParams(factories->getRunParams(name)) + isRun(isRun) { ui->setupUi(this); + if (!isRun) factories->resetEnvironment(name); + + params = factories->getParams(name); + setWindowTitle(tr("%1 %2").arg(name).arg(tr("Options"))); - ui->leCurrent->setText(dfltParams->data.currentRelease); + ui->txtCurrentRelease->setText(factories->currentRelease(name)); - connect(ui->btnForget, &QPushButton::clicked, [=]() { - if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear current release information.\nWarning: There is no undo! Are you sure?"), + connect(ui->btnClearRelease, &QPushButton::clicked, [=]() { + if (QMessageBox::question(this, CPN_STR_APP_NAME, tr("Clear current release information. Are you sure?"), QMessageBox::Yes |QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { factories->clearRelease(name); - ui->leCurrent->setText(dfltParams->data.currentRelease); + ui->txtCurrentRelease->setText(factories->currentRelease(name)); emit changed(idx); + } }); - ui->cboReleases->addItems(factories->releases(name)); - - int i = -1; - QVBoxLayout *grpAssetsLayout = new QVBoxLayout(); - foreach (const UpdateParameters::AssetParams &ap, dfltParams->data.assets) { + for (int i = 0; i < params->assets.size(); i++) { + const UpdateParameters::AssetParams & ap = params->assets.at(i); + + int processes = ap.processes; int flags = ap.flags; const bool locked = flags & UpdateInterface::UPDFLG_Locked; - i++; QHBoxLayout *layout1 = new QHBoxLayout(); @@ -111,17 +113,25 @@ UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * fac QHBoxLayout *layout2 = new QHBoxLayout(); + layout2->addWidget(new QLabel(tr("Max.Expected"))); + + QSpinBox *sbMaxExpected = new QSpinBox(); + sbMaxExpected->setEnabled(!locked); + sbMaxExpected->setSpecialValueText(tr("No Limit")); + sbMaxExpects << sbMaxExpected; + layout2->addWidget(sbMaxExpected); + QCheckBox *chkDownload = new QCheckBox(tr("Download")); chkDownloads << chkDownload; layout2->addWidget(chkDownload); QCheckBox *chkDecompress = new QCheckBox(tr("Decompress")); - chkDecompress->setEnabled(flags & UpdateInterface::UPDFLG_Decompress); + chkDecompress->setEnabled(processes & UpdateInterface::UPDFLG_Decompress); chkDecompresses << chkDecompress; layout2->addWidget(chkDecompress); QCheckBox *chkInstall = new QCheckBox(tr("Install")); - chkInstall->setEnabled(flags & UpdateInterface::UPDFLG_AsyncInstall); + chkInstall->setEnabled(processes & UpdateInterface::UPDFLG_AsyncInstall); chkInstalls << chkInstall; layout2->addWidget(chkInstall); @@ -133,23 +143,23 @@ UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * fac QGridLayout *layout3 = new QGridLayout(); QCheckBox *chkCopy = new QCheckBox(tr("Copy")); - chkCopy->setEnabled(flags & UpdateInterface::UPDFLG_CopyDest); + chkCopy->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest); chkCopies << chkCopy; layout3->addWidget(chkCopy, 0, 0); QLabel *lblCopyFilter = new QLabel(tr("Filter")); - lblCopyFilter->setEnabled(flags & UpdateInterface::UPDFLG_CopyDest); + lblCopyFilter->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest); lblCopyFilters << lblCopyFilter; layout3->addWidget(lblCopyFilter, 0, 1); QComboBox *cboCopyFilterType = new QComboBox(); - cboCopyFilterType->setEnabled(!locked); + cboCopyFilterType->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest && (!locked)); cboCopyFilterType->addItems(UpdateParameters::updateFilterTypeList()); cboCopyFilterTypes << cboCopyFilterType; layout3->addWidget(cboCopyFilterType, 0, 2); QLineEdit *leCopyFilter = new QLineEdit(); - leCopyFilter->setEnabled(flags & UpdateInterface::UPDFLG_CopyDest && (!locked)); + leCopyFilter->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest && (!locked)); leCopyFilters << leCopyFilter; layout3->addWidget(leCopyFilter, 0, 3); @@ -168,21 +178,77 @@ UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * fac }); QLabel *lblSubFolder = new QLabel(tr("Sub folder")); - lblSubFolder->setEnabled(flags & UpdateInterface::UPDFLG_CopyDest); + lblSubFolder->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest); lblSubFolders << lblSubFolder; layout3->addWidget(lblSubFolder, 1, 1); QLineEdit *leSubFolder = new QLineEdit(); - leSubFolder->setEnabled(flags & UpdateInterface::UPDFLG_CopyDest && (!locked)); + leSubFolder->setEnabled(processes & UpdateInterface::UPDFLG_CopyDest && (!locked)); leSubFolders << leSubFolder; layout3->addWidget(leSubFolder, 1, 2, 1, 2); + connect(chkDownload, &QCheckBox::stateChanged, [=](const int checked) { + if (!checked) { + chkDecompress->setChecked(false); + chkCopy->setChecked(false); + chkInstall->setChecked(false); + } + else { + chkDecompress->setChecked(processes & UpdateInterface::UPDFLG_Decompress); + chkCopy->setChecked(processes & UpdateInterface::UPDFLG_CopyDest); + chkInstall->setChecked(processes & UpdateInterface::UPDFLG_AsyncInstall); + } + }); + + connect(chkDecompress, &QCheckBox::stateChanged, [=](const int checked) { + if (!checked) { + chkCopy->setChecked(false); + chkInstall->setChecked(false); + } + else { + chkCopy->setChecked(processes & UpdateInterface::UPDFLG_CopyDest); + chkInstall->setChecked(processes & UpdateInterface::UPDFLG_AsyncInstall); + } + }); + + connect(chkCopy, &QCheckBox::stateChanged, [=](const int checked) { + cboCopyFilterType->setEnabled(checked ? (processes & UpdateInterface::UPDFLG_CopyDest) && (!locked) : checked); + leCopyFilter->setEnabled(checked ? (processes & UpdateInterface::UPDFLG_CopyDest) && (!locked) : checked); + leSubFolder->setEnabled(checked ? (processes & UpdateInterface::UPDFLG_CopyDest) && (!locked) : checked); + if (!checked) { + chkInstall->setChecked(false); + } + else { + chkInstall->setChecked(processes & UpdateInterface::UPDFLG_AsyncInstall); + } + }); + grpAssetsLayout->addLayout(layout3); } ui->grpAssets->setLayout(grpAssetsLayout); connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() { + for (int i = 0; i < params->assets.size(); i++) { + UpdateParameters::AssetParams & ap = params->assets[i]; + + int flags = ap.flags; + + if (!(flags & UpdateInterface::UPDFLG_Locked)) { + ap.filterType = (UpdateParameters::UpdateFilterType)cboAssetFilterTypes.at(i)->currentIndex(); + ap.filter = leAssetFilters.at(i)->text(); + ap.maxExpected = sbMaxExpects.at(i)->value(); + ap.copyFilterType = (UpdateParameters::UpdateFilterType)cboCopyFilterTypes.at(i)->currentIndex(); + ap.copyFilter = leCopyFilters.at(i)->text(); + ap.destSubDir = leSubFolders.at(i)->text(); + } + + chkDownloads.at(i)->isChecked() ? flags |= UpdateInterface::UPDFLG_Download : flags &= ~UpdateInterface::UPDFLG_Download; + chkDecompresses.at(i)->isChecked() ? flags |= UpdateInterface::UPDFLG_Decompress : flags &= ~UpdateInterface::UPDFLG_Decompress; + chkInstalls.at(i)->isChecked() ? flags |= UpdateInterface::UPDFLG_AsyncInstall : flags &= ~UpdateInterface::UPDFLG_AsyncInstall; + chkCopies.at(i)->isChecked() ? flags |= UpdateInterface::UPDFLG_CopyDest : flags &= ~UpdateInterface::UPDFLG_CopyDest; + ap.flags = flags; + } QDialog::accept(); }); @@ -190,38 +256,6 @@ UpdateOptionsDialog::UpdateOptionsDialog(QWidget * parent, UpdateFactories * fac QDialog::reject(); }); - connect(ui->buttonBox, &QDialogButtonBox::clicked, [=](QAbstractButton * button) { - if (ui->buttonBox->standardButton(button) == QDialogButtonBox::RestoreDefaults) { - factories->resetRunEnvironment(name); - update(); - } - //else if (ui->buttonBox->standardButton(button) == QDialogButtonBox::Cancel) { - // QDialog::reject(); - //} - else if (ui->buttonBox->standardButton(button) == QDialogButtonBox::Ok) { - runParams->data.updateRelease = ui->cboReleases->currentText(); - - for (int i = 0; i < runParams->data.assets.size(); i++) { - UpdateParameters::AssetParams &ap = runParams->data.assets[i]; - - if (!(ap.flags & UpdateInterface::UPDFLG_Locked)) { - ap.filterType = (UpdateParameters::UpdateFilterType)cboAssetFilterTypes.at(i)->currentIndex(); - ap.filter = leAssetFilters.at(i)->text(); - ap.copyFilterType = (UpdateParameters::UpdateFilterType)cboCopyFilterTypes.at(i)->currentIndex(); - ap.copyFilter = leCopyFilters.at(i)->text(); - ap.destSubDir = leSubFolders.at(i)->text(); - } - - chkDownloads.at(i)->isChecked() ? ap.flags |= UpdateInterface::UPDFLG_Download : ap.flags &= ~UpdateInterface::UPDFLG_Download; - chkDecompresses.at(i)->isChecked() ? ap.flags |= UpdateInterface::UPDFLG_Decompress :ap.flags &= ~UpdateInterface::UPDFLG_Decompress; - chkInstalls.at(i)->isChecked() ? ap.flags |= UpdateInterface::UPDFLG_AsyncInstall : ap.flags &= ~UpdateInterface::UPDFLG_AsyncInstall; - chkCopies.at(i)->isChecked() ? ap.flags |= UpdateInterface::UPDFLG_CopyDest : ap.flags &= ~UpdateInterface::UPDFLG_CopyDest; - } - - emit changed(idx); - } - }); - update(); QTimer::singleShot(50, this, [=]() { @@ -236,23 +270,24 @@ UpdateOptionsDialog::~UpdateOptionsDialog() void UpdateOptionsDialog::update() { - ui->cboReleases->setCurrentText(runParams->data.updateRelease); - - int i = 0; - - foreach (const UpdateParameters::AssetParams &ap, runParams->data.assets) { - cboAssetFilterTypes.at(i)->setCurrentIndex((int)ap.filterType); + for (int i = 0; i < params->assets.size(); i++) { + const UpdateParameters::AssetParams & ap = params->assets.at(i); + cboAssetFilterTypes.at(i)->setCurrentIndex(ap.filterType); leAssetFilters.at(i)->setText(ap.filter); - chkDownloads.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_Download); - chkDecompresses.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_Decompress); - chkInstalls.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_AsyncInstall); + sbMaxExpects.at(i)->setValue(ap.maxExpected); + chkDownloads.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_Download); + + chkDecompresses.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_Decompress); + + chkCopies.at(i)->setChecked(!chkCopies.at(i)->isChecked()); chkCopies.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_CopyDest); - cboCopyFilterTypes.at(i)->setCurrentIndex((int)ap.copyFilterType); + cboCopyFilterTypes.at(i)->setCurrentIndex(-1); + cboCopyFilterTypes.at(i)->setCurrentIndex(ap.copyFilterType); leCopyFilters.at(i)->setText(ap.copyFilter); leSubFolders.at(i)->setText(ap.destSubDir); - i++; + chkInstalls.at(i)->setChecked(ap.flags & UpdateInterface::UPDFLG_AsyncInstall); } } diff --git a/companion/src/updates/updateoptionsdialog.h b/companion/src/updates/updateoptionsdialog.h index 24c38aa14..2a3aa4160 100644 --- a/companion/src/updates/updateoptionsdialog.h +++ b/companion/src/updates/updateoptionsdialog.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace Ui { class UpdateOptionsDialog; @@ -41,7 +42,7 @@ class UpdateOptionsDialog : public QDialog Q_OBJECT public: - UpdateOptionsDialog(QWidget * parent, UpdateFactories * factories, const int idx); + UpdateOptionsDialog(QWidget * parent, UpdateFactories * factories, const int idx, const bool isRun); virtual ~UpdateOptionsDialog(); signals: @@ -52,21 +53,22 @@ class UpdateOptionsDialog : public QDialog private: Ui::UpdateOptionsDialog *ui; - const UpdateFactories *factories; + UpdateFactories *factories; const int idx; const QString name; - const UpdateParameters *dfltParams; - UpdateParameters *runParams; + const bool isRun; + UpdateParameters *params; QVector cboAssetFilterTypes; QVector leAssetFilters; + QVector sbMaxExpects; QVector chkDownloads; QVector chkDecompresses; QVector chkInstalls; QVector chkCopies; - QVector lblCopyFilters; + QVector lblCopyFilters; QVector cboCopyFilterTypes; QVector leCopyFilters; - QVector lblSubFolders; + QVector lblSubFolders; QVector leSubFolders; }; diff --git a/companion/src/updates/updateoptionsdialog.ui b/companion/src/updates/updateoptionsdialog.ui index 048aad91f..df84fc506 100644 --- a/companion/src/updates/updateoptionsdialog.ui +++ b/companion/src/updates/updateoptionsdialog.ui @@ -7,7 +7,7 @@ 0 0 530 - 200 + 129 @@ -21,53 +21,41 @@ - - - Release - - - - - - - 0 - 0 - - - - Clear the last updated release information - - - Forget - - - - - - - - - - Current - - - - - - - Update to - - - - - - - true - - - - - + + + + + Current Release: + + + + + + + + 0 + 0 + + + + unknown + + + + + + + + 0 + 0 + + + + Clear + + + + @@ -116,7 +104,7 @@ Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults + QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/companion/src/updates/updates.cpp b/companion/src/updates/updates.cpp index 709296974..f18449596 100644 --- a/companion/src/updates/updates.cpp +++ b/companion/src/updates/updates.cpp @@ -39,9 +39,9 @@ Updates::~Updates() { } -void Updates::checkForUpdates(bool manual) +void Updates::autoUpdates(bool interactive) { - if (!manual) { + if (!interactive) { if (g.updateCheckFreq() == AppData::UPDATE_CHECK_MANUAL) return; @@ -65,45 +65,56 @@ void Updates::checkForUpdates(bool manual) g.lastUpdateCheck(QDateTime::currentDateTime().toString(Qt::ISODate)); + factories->resetAllEnvironments(); + QStringList list; - if (!factories->isUpdatesAvailable(list)) { - if (manual) + if (!factories->isUpdateAvailable(list)) { + if (interactive) QMessageBox::information(parentWidget(), CPN_STR_APP_NAME, tr("No updates available at this time")); return; } if (QMessageBox::question(parentWidget(), CPN_STR_APP_NAME % ": " % tr("Checking for Updates"), - tr("Updates available for:\n %1\n\nUpdate now?").arg(list.join("\n ")), - (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes) { - doUpdates(); + tr("Updates available for:\n - %1\n\nProcess now?").arg(list.join("\n - ")), + (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::No) { + return; } + + for (int i = 0; i < list.count(); i++) { + factories->setRunUpdate(list.at(i)); + factories->updateRelease(list.at(i)); + } + + runUpdate(); } -void Updates::doUpdates() +void Updates::manualUpdates() { if (factories->sortedComponentsList(true).isEmpty()) { QMessageBox::warning(this, CPN_STR_APP_NAME, tr("No components have been flagged to check in Update Settings!")); return; } - factories->resetAllRunEnvironments(); + factories->resetAllEnvironments(); UpdatesDialog *dlg = new UpdatesDialog(this, factories); + dlg->deleteLater(); + if (dlg->exec()) + runUpdate(); +} + +void Updates::runUpdate() +{ bool ok = false; - - if (dlg->exec()) { - ProgressDialog progressDialog(this, tr("Update Components"), CompanionIcon("fuses.png"), true); - progressDialog.progress()->lock(true); - progressDialog.progress()->setInfo(tr("Starting...")); - ok = factories->manualUpdate(progressDialog.progress()); - progressDialog.progress()->lock(false); - progressDialog.progress()->setInfo(tr("Finished %1").arg(ok ? tr("successfully") : tr("with errors"))); - progressDialog.exec(); - } - - delete dlg; + ProgressDialog progressDialog(this, tr("Update Components"), CompanionIcon("fuses.png"), true); + progressDialog.progress()->lock(true); + progressDialog.progress()->setInfo(tr("Starting...")); + ok = factories->updateAll(progressDialog.progress()); + progressDialog.progress()->lock(false); + progressDialog.progress()->setInfo(tr("Finished %1").arg(ok ? tr("successfully") : tr("with errors"))); + progressDialog.exec(); if (ok) checkRunSDSync(); diff --git a/companion/src/updates/updates.h b/companion/src/updates/updates.h index 49d6a3899..bde995509 100644 --- a/companion/src/updates/updates.h +++ b/companion/src/updates/updates.h @@ -34,8 +34,8 @@ class Updates : public QWidget explicit Updates(QWidget * parent, UpdateFactories * updateFactories); virtual ~Updates(); - void checkForUpdates(bool manual); - void doUpdates(); + void autoUpdates(bool interactive); + void manualUpdates(); signals: void runSDSync(); @@ -43,5 +43,6 @@ class Updates : public QWidget private: UpdateFactories *factories; + void runUpdate(); void checkRunSDSync(); }; diff --git a/companion/src/updates/updatesdcard.cpp b/companion/src/updates/updatesdcard.cpp index 49e2dd08a..d7c1d9de4 100644 --- a/companion/src/updates/updatesdcard.cpp +++ b/companion/src/updates/updatesdcard.cpp @@ -28,14 +28,24 @@ UpdateSDCard::UpdateSDCard(QWidget * parent) : { setName(tr("SD Card")); setRepo(QString(GH_REPOS_EDGETX).append("/edgetx-sdcard")); +} - dfltParams->data.flags = UPDFLG_Common | UPDFLG_Locked; +void UpdateSDCard::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = QString("%FWFLAVOUR%-"); - ap.maxExpected = 1; - ap.flags = dfltParams->data.flags | UPDFLG_CopyStructure; + g.component[settingsIndex()].initAllAssets(); + + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + cad.desc("files"); + cad.processes(UPDFLG_Common_Asset); + cad.flags(cad.processes() | UPDFLG_Locked | UPDFLG_CopyStructure); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter("%FWFLAVOUR%-"); + cad.maxExpected(1); + + qDebug() << "Asset settings initialised"; } bool UpdateSDCard::flagAssets() @@ -60,9 +70,9 @@ bool UpdateSDCard::flagAssets() return false; } - const UpdateParameters::AssetParams & ap = runParams->data.assets.at(0); + const UpdateParameters::AssetParams & ap = params->assets.at(0); - QRegularExpression filter(runParams->buildFilterPattern(ap.filterType, ap.filter), QRegularExpression::CaseInsensitiveOption); + QRegularExpression filter(params->buildFilterPattern(ap.filterType, ap.filter), QRegularExpression::CaseInsensitiveOption); bool found = false; QString sdimage; @@ -91,7 +101,7 @@ bool UpdateSDCard::flagAssets() delete json; if (!found) { - reportProgress(tr("Radio flavour %1 not listed in %2").arg(runParams->data.fwFlavour).arg(mappingfile), QtCriticalMsg); + reportProgress(tr("Radio flavour %1 not listed in %2").arg(params->fwFlavour).arg(mappingfile), QtCriticalMsg); return false; } diff --git a/companion/src/updates/updatesdcard.h b/companion/src/updates/updatesdcard.h index c3674f6c2..926ef1f25 100644 --- a/companion/src/updates/updatesdcard.h +++ b/companion/src/updates/updatesdcard.h @@ -33,5 +33,7 @@ class UpdateSDCard : public UpdateInterface virtual ~UpdateSDCard() {} protected: + virtual void initAssetSettings() override; + virtual bool flagAssets() override; }; diff --git a/companion/src/updates/updatesdialog.cpp b/companion/src/updates/updatesdialog.cpp index 5412731c7..c40a34dbd 100644 --- a/companion/src/updates/updatesdialog.cpp +++ b/companion/src/updates/updatesdialog.cpp @@ -24,7 +24,6 @@ #include "updateoptionsdialog.h" #include -#include #include #include #include @@ -32,7 +31,8 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : QDialog(parent), ui(new Ui::UpdatesDialog), - factories(factories) + factories(factories), + sortedCompList(factories->sortedComponentsList(true)) { // downloading the release meta data takes a few seconds for each component so display progress QDialog *status = new QDialog(parent); @@ -46,6 +46,8 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : ui->setupUi(this); + ui->chkDelDownloads->setChecked(g.updDelDownloads()); + ui->chkDelDecompress->setChecked(g.updDelDecompress()); ui->leDownloadDir->setText(g.downloadDir()); connect(ui->chkDecompressDirUseDwnld, &QCheckBox::stateChanged, [=](const int checked) { @@ -53,15 +55,24 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : ui->leDecompressDir->setText(g.decompressDir()); ui->leDecompressDir->setEnabled(true); ui->btnDecompressSelect->setEnabled(true); + ui->chkDelDownloads->setEnabled(true); } else { ui->leDecompressDir->setText(g.downloadDir()); ui->leDecompressDir->setEnabled(false); ui->btnDecompressSelect->setEnabled(false); + if (ui->chkDelDecompress->isChecked()) { + ui->chkDelDownloads->setEnabled(true); + } + else { + ui->chkDelDownloads->setEnabled(false); + ui->chkDelDownloads->setChecked(false); + } } }); - ui->chkDecompressDirUseDwnld->setChecked(!g.decompressDirUseDwnld()); + // trigger toggled signal by changing design value and then setting to saved value + ui->chkDecompressDirUseDwnld->setChecked(!ui->chkDecompressDirUseDwnld->isChecked()); ui->chkDecompressDirUseDwnld->setChecked(g.decompressDirUseDwnld()); connect(ui->chkUpdateDirUseSD, &QCheckBox::stateChanged, [=](const int checked) { @@ -82,11 +93,6 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : else ui->chkUpdateDirUseSD->setEnabled(true); - if (g.updateDirUseSD() && g.currentProfile().sdPath().trimmed().isEmpty()) { - g.updateDirUseSD(false); - g.updateDirReset(); - } - if (g.updateDirUseSD()) { // trigger toggled signal by changing design value and then setting to saved value ui->chkUpdateDirUseSD->setChecked(!ui->chkUpdateDirUseSD->isChecked()); @@ -116,6 +122,18 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : } }); + connect(ui->chkDelDecompress, &QCheckBox::stateChanged, [=](const int checked) { + if (!checked) { + if (ui->chkDecompressDirUseDwnld->isChecked()) { + ui->chkDelDownloads->setEnabled(false); + ui->chkDelDownloads->setChecked(false); + } + } + else { + ui->chkDelDownloads->setEnabled(true); + } + }); + int row = 0; int col = 0; @@ -130,18 +148,18 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : QLabel *h3 = new QLabel(tr("Channel")); grid->addWidget(h3, row, col++); - QLabel *h4 = new QLabel(tr("Current Release")); + QLabel *h4 = new QLabel(tr("Current")); grid->addWidget(h4, row, col++); - QLabel *h5 = new QLabel(tr("Update Release")); + QLabel *h5 = new QLabel(tr("Update to")); grid->addWidget(h5, row, col++); - col++; // options button + col++; // options QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ); grid->addItem(spacer, row, col++); - QMapIterator it(factories->sortedComponentsList(true)); + QMapIterator it(sortedCompList); while (it.hasNext()) { it.next(); @@ -162,23 +180,32 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : QLabel *lblName = new QLabel(name); grid->addWidget(lblName, row, col++); - QLabel *lblRC = new QLabel(ComponentData::releaseChannelsList().at(g.component[i].releaseChannel())); - grid->addWidget(lblRC, row, col++); + cboRelChannel[i] = new QComboBox(); + cboRelChannel[i]->addItems(ComponentData::releaseChannelsList()); + cboRelChannel[i]->setCurrentIndex(g.component[i].releaseChannel()); + grid->addWidget(cboRelChannel[i], row, col++); lblCurrentRel[i] = new QLabel(factories->currentRelease(name)); grid->addWidget(lblCurrentRel[i], row, col++); - lblUpdateRel[i] = new QLabel(factories->updateRelease(name)); - grid->addWidget(lblUpdateRel[i], row, col++); + cboUpdateRel[i] = new QComboBox(); + cboUpdateRel[i]->addItems(factories->releases(name)); + grid->addWidget(cboUpdateRel[i], row, col++); + + connect(cboRelChannel[i], QOverload::of(&QComboBox::currentIndexChanged), [=] (const int index) { + factories->setReleaseChannel(name, index); + cboUpdateRel[i]->clear(); + cboUpdateRel[i]->addItems(factories->releases(name)); + }); btnOptions[i] = new QPushButton(tr("Options")); connect(btnOptions[i], &QPushButton::clicked, [=]() { - UpdateOptionsDialog *dlg = new UpdateOptionsDialog(this, factories, i); + UpdateOptionsDialog *dlg = new UpdateOptionsDialog(this, factories, i, true); connect(dlg, &UpdateOptionsDialog::changed, [=](const int i) { QString name = g.component[i].name(); chkUpdate[i]->setChecked(!factories->isLatestRelease(name)); lblCurrentRel[i]->setText(factories->currentRelease(name)); - lblUpdateRel[i]->setText(factories->updateRelease(name)); + cboUpdateRel[i]->setCurrentText(factories->updateRelease(name)); }); dlg->exec(); dlg->deleteLater(); @@ -189,7 +216,11 @@ UpdatesDialog::UpdatesDialog(QWidget * parent, UpdateFactories * factories) : ui->grpComponents->setLayout(grid); - ui->chkDelDownloads->setChecked(g.updDelDownloads()); + QPushButton *btnSaveAsDefaults = new QPushButton(tr("Save as Defaults")); + ui->buttonBox->addButton(btnSaveAsDefaults, QDialogButtonBox::ActionRole); + connect(btnSaveAsDefaults, &QPushButton::clicked, [=]() { + saveAsDefaults(); + }); connect(ui->buttonBox, &QDialogButtonBox::rejected, [=]() { QDialog::reject(); @@ -227,30 +258,39 @@ void UpdatesDialog::accept() return; } - QMapIterator it(factories->sortedComponentsList()); + if (!ui->chkDecompressDirUseDwnld->isChecked() && + ui->leDecompressDir->text().trimmed() == ui->leDownloadDir->text().trimmed()) { + QMessageBox::warning(this, CPN_STR_APP_NAME, tr("Decompress and download folders have the same path!")); + return; + } int cnt = 0; + QMapIterator it(sortedCompList); + while (it.hasNext()) { it.next(); int i = it.value(); - if (g.component[i].checkForUpdate()) { - if (chkUpdate[i]->isChecked()) { - cnt++; - const QString name = it.key(); - UpdateParameters *runParams = factories->getRunParams(name); - runParams->data.flags |= UpdateInterface::UPDFLG_Update; - runParams->data.downloadDir = ui->leDownloadDir->text(); - runParams->data.decompressDirUseDwnld = ui->chkDecompressDirUseDwnld->isChecked(); - runParams->data.decompressDir = ui->leDecompressDir->text(); - runParams->data.updateDirUseSD = ui->chkUpdateDirUseSD->isChecked(); - runParams->data.updateDir = ui->leUpdateDir->text(); - if (ui->chkDelDownloads->isChecked()) - runParams->data.flags |= UpdateInterface::UPDFLG_DelDownloads; - else - runParams->data.flags &= ~UpdateInterface::UPDFLG_DelDownloads; - } + if (chkUpdate[i]->isChecked()) { + cnt++; + const QString name = it.key(); + UpdateParameters *params = factories->getParams(name); + params->updateRelease = cboUpdateRel[i]->currentText(); + params->flags |= UpdateInterface::UPDFLG_Update; + params->downloadDir = ui->leDownloadDir->text(); + params->decompressDirUseDwnld = ui->chkDecompressDirUseDwnld->isChecked(); + params->decompressDir = ui->leDecompressDir->text(); + params->updateDirUseSD = ui->chkUpdateDirUseSD->isChecked(); + params->updateDir = ui->leUpdateDir->text(); + if (ui->chkDelDownloads->isChecked()) + params->flags |= UpdateInterface::UPDFLG_DelDownloads; + else + params->flags &= ~UpdateInterface::UPDFLG_DelDownloads; + if (ui->chkDelDecompress->isChecked()) + params->flags |= UpdateInterface::UPDFLG_DelDecompress; + else + params->flags &= ~UpdateInterface::UPDFLG_DelDecompress; } } @@ -261,3 +301,23 @@ void UpdatesDialog::accept() QDialog::accept(); } + +void UpdatesDialog::saveAsDefaults() +{ + g.downloadDir(ui->leDownloadDir->text()); + g.decompressDirUseDwnld(ui->chkDecompressDirUseDwnld->isChecked()); + g.decompressDir(ui->leDecompressDir->text()); + g.updateDirUseSD(ui->chkUpdateDirUseSD->isChecked()); + g.updateDir(ui->leUpdateDir->text()); + g.updDelDownloads(ui->chkDelDownloads->isChecked()); + g.updDelDecompress(ui->chkDelDecompress->isChecked()); + + QMapIterator it(sortedCompList); + + while (it.hasNext()) { + it.next(); + int i = it.value(); + g.component[i].releaseChannel((ComponentData::ReleaseChannel)cboRelChannel[i]->currentIndex()); + factories->saveAssetSettings(it.key()); + } +} diff --git a/companion/src/updates/updatesdialog.h b/companion/src/updates/updatesdialog.h index 4f70233ad..8feebc4b8 100644 --- a/companion/src/updates/updatesdialog.h +++ b/companion/src/updates/updatesdialog.h @@ -27,7 +27,10 @@ #include #include #include +#include #include +#include +#include namespace Ui { class UpdatesDialog; @@ -49,10 +52,15 @@ class UpdatesDialog : public QDialog private: Ui::UpdatesDialog *ui; UpdateFactories *factories; + UpdateParameters *runParams; + + QMap sortedCompList; QCheckBox *chkUpdate[MAX_COMPONENTS]; + QComboBox *cboRelChannel[MAX_COMPONENTS]; QLabel *lblCurrentRel[MAX_COMPONENTS]; - QLabel *lblUpdateRel[MAX_COMPONENTS]; + QComboBox *cboUpdateRel[MAX_COMPONENTS]; QPushButton *btnOptions[MAX_COMPONENTS]; -}; + void saveAsDefaults(); +}; diff --git a/companion/src/updates/updatesdialog.ui b/companion/src/updates/updatesdialog.ui index cba2c3344..3d7d35aa2 100644 --- a/companion/src/updates/updatesdialog.ui +++ b/companion/src/updates/updatesdialog.ui @@ -10,7 +10,7 @@ 0 0 595 - 345 + 385 @@ -137,15 +137,22 @@ - + - + Options - Delete downloads after update + Delete downloads + + + + + + + Delete decompressions diff --git a/companion/src/updates/updatesounds.cpp b/companion/src/updates/updatesounds.cpp index 9aed82403..41ab70352 100644 --- a/companion/src/updates/updatesounds.cpp +++ b/companion/src/updates/updatesounds.cpp @@ -32,11 +32,6 @@ UpdateSounds::UpdateSounds(QWidget * parent) : { setName(tr("Sounds")); setRepo(QString(GH_REPOS_EDGETX).append("/edgetx-sdcard-sounds")); - - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = QString("edgetx-sdcard-sounds-%LANGUAGE%-"); - ap.flags = dfltParams->data.flags | UPDFLG_CopyStructure; } UpdateSounds::~UpdateSounds() @@ -44,6 +39,23 @@ UpdateSounds::~UpdateSounds() delete langPacks; } +void UpdateSounds::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; + + g.component[settingsIndex()].initAllAssets(); + + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + cad.desc("sounds"); + cad.processes(UPDFLG_Common_Asset); + cad.flags(cad.processes() | UPDFLG_CopyStructure); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter("edgetx-sdcard-sounds-%LANGUAGE%-"); + + qDebug() << "Asset settings initialised"; +} + bool UpdateSounds::flagAssets() { progressMessage(tr("Processing available sounds")); @@ -52,12 +64,12 @@ bool UpdateSounds::flagAssets() assets->setFilterPattern(pattern); if (assets->count() < 0) { - reportProgress(tr("Asset not found in release '%1' using filter pattern '%2'").arg(releases->name().arg(pattern)), QtCriticalMsg); + reportProgress(tr("Asset not found in release '%1' using filter pattern '%2'").arg(releases->name()).arg(pattern), QtCriticalMsg); return false; } else if (assets->count() > 1) { reportProgress(tr("%1 assets found when %2 expected in release '%3' using filter pattern '%4'") - .arg(assets->count()).arg(1).arg(releases->name().arg(pattern)), QtCriticalMsg); + .arg(assets->count()).arg(1).arg(releases->name()).arg(pattern), QtCriticalMsg); return false; } @@ -97,7 +109,7 @@ bool UpdateSounds::flagAssets() lang = langVariant.split("-").at(0); } - if (lang == runParams->data.language) { + if (lang == params->language) { QStandardItem * item = new QStandardItem(); if (!obj.value("language").isUndefined()) @@ -118,7 +130,7 @@ bool UpdateSounds::flagAssets() delete json; if (langPacks->rowCount() < 1) { - reportProgress(tr("Language %1 not listed in %2").arg(runParams->data.language).arg(pattern), QtCriticalMsg); + reportProgress(tr("Language %1 not listed in %2").arg(params->language).arg(pattern), QtCriticalMsg); return false; } @@ -130,7 +142,7 @@ bool UpdateSounds::flagAssets() QItemSelectionModel *selItems = dlg->selectedItems(); if (!ok || !selItems->hasSelection()) { - QMessageBox::warning(this, CPN_STR_APP_NAME, tr("No language packs have been selected. Sounds update will be skipped!")); + QMessageBox::warning(progress, CPN_STR_APP_NAME, tr("No language packs have been selected. Sounds update will be skipped!")); dlg->deleteLater(); return true; } @@ -156,7 +168,7 @@ bool UpdateSounds::flagLanguageAsset(QString lang) { progressMessage(tr("Flagging assets")); - runParams->data.language = lang; - UpdateParameters::AssetParams ap = runParams->data.assets[0]; + params->language = lang; + UpdateParameters::AssetParams ap = params->assets[0]; return getSetAssets(ap); } diff --git a/companion/src/updates/updatesounds.h b/companion/src/updates/updatesounds.h index 789fa622f..b4ab4595c 100644 --- a/companion/src/updates/updatesounds.h +++ b/companion/src/updates/updatesounds.h @@ -35,6 +35,8 @@ class UpdateSounds : public UpdateInterface virtual ~UpdateSounds(); protected: + virtual void initAssetSettings() override; + virtual bool flagAssets() override; private: diff --git a/companion/src/updates/updatethemes.cpp b/companion/src/updates/updatethemes.cpp index 05a86ac4d..a4d6a2bbd 100644 --- a/companion/src/updates/updatethemes.cpp +++ b/companion/src/updates/updatethemes.cpp @@ -20,17 +20,28 @@ */ #include "updatethemes.h" -#include "eeprominterface.h" UpdateThemes::UpdateThemes(QWidget * parent) : UpdateInterface(parent) { setName(tr("Themes")); setRepo(QString(GH_REPOS_EDGETX).append("/themes")); +} - UpdateParameters::AssetParams &ap = dfltParams->addAsset(); - ap.filterType = UpdateParameters::UFT_Startswith; - ap.filter = "edgetx-themes"; - ap.maxExpected = 1; - ap.flags = dfltParams->data.flags | UPDFLG_CopyStructure; +void UpdateThemes::initAssetSettings() +{ + if (!isValidSettingsIndex()) + return; + + g.component[settingsIndex()].initAllAssets(); + + ComponentAssetData &cad = g.component[settingsIndex()].asset[0]; + cad.desc("files"); + cad.processes(UPDFLG_Common_Asset); + cad.flags(cad.processes() | UPDFLG_CopyStructure); + cad.filterType(UpdateParameters::UFT_Startswith); + cad.filter("edgetx-themes"); + cad.maxExpected(1); + + qDebug() << "Asset settings initialised"; } diff --git a/companion/src/updates/updatethemes.h b/companion/src/updates/updatethemes.h index f09e78d98..329a6e8b1 100644 --- a/companion/src/updates/updatethemes.h +++ b/companion/src/updates/updatethemes.h @@ -32,4 +32,7 @@ class UpdateThemes : public UpdateInterface explicit UpdateThemes(QWidget * parent); virtual ~UpdateThemes() {} + protected: + virtual void initAssetSettings() override; + };