1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00

Feature plugins framework: presets

This commit is contained in:
f4exb 2020-09-24 05:38:05 +02:00
parent 5f43ace810
commit cd5a4db876
42 changed files with 2242 additions and 26 deletions

View File

@ -6,6 +6,7 @@ set(simpleptt_SOURCES
simplepttplugin.cpp
simplepttworker.cpp
simplepttreport.cpp
simplepttwebapiadapter.cpp
)
set(simpleptt_HEADERS
@ -14,6 +15,7 @@ set(simpleptt_HEADERS
simplepttplugin.h
simplepttworker.h
simplepttreport.h
simplepttwebapiadapter.h
)
include_directories(

View File

@ -24,6 +24,7 @@
#endif
#include "simpleptt.h"
#include "simplepttplugin.h"
#include "simplepttwebapiadapter.h"
const PluginDescriptor SimplePTTPlugin::m_pluginDescriptor = {
SimplePTT::m_featureId,
@ -72,3 +73,8 @@ Feature* SimplePTTPlugin::createFeature(WebAPIAdapterInterface* webAPIAdapterInt
{
return new SimplePTT(webAPIAdapterInterface);
}
FeatureWebAPIAdapter* SimplePTTPlugin::createFeatureWebAPIAdapter() const
{
return new SimplePTTWebAPIAdapter();
}

View File

@ -36,6 +36,7 @@ public:
virtual PluginInstanceGUI* createFeatureGUI(FeatureUISet *featureUISet, Feature *feature) const;
virtual Feature* createFeature(WebAPIAdapterInterface *webAPIAdapterInterface) const;
virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "SWGFeatureSettings.h"
#include "simpleptt.h"
#include "simplepttwebapiadapter.h"
SimplePTTWebAPIAdapter::SimplePTTWebAPIAdapter()
{}
SimplePTTWebAPIAdapter::~SimplePTTWebAPIAdapter()
{}
int SimplePTTWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setSimplePttSettings(new SWGSDRangel::SWGSimplePTTSettings());
response.getSimplePttSettings()->init();
SimplePTT::webapiFormatFeatureSettings(response, m_settings);
return 200;
}
int SimplePTTWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) errorMessage;
SimplePTT::webapiUpdateFeatureSettings(m_settings, featureSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_SIMPLEPTT_WEBAPIADAPTER_H
#define INCLUDE_SIMPLEPTT_WEBAPIADAPTER_H
#include "feature/featurewebapiadapter.h"
#include "simplepttsettings.h"
/**
* Standalone API adapter only for the settings
*/
class SimplePTTWebAPIAdapter : public FeatureWebAPIAdapter {
public:
SimplePTTWebAPIAdapter();
virtual ~SimplePTTWebAPIAdapter();
virtual QByteArray serialize() const { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage);
private:
SimplePTTSettings m_settings;
};
#endif // INCLUDE_SIMPLEPTT_WEBAPIADAPTER_H

View File

@ -138,9 +138,11 @@ set(sdrbase_SOURCES
device/deviceutils.cpp
feature/feature.cpp
feature/featureutils.cpp
limerfe/limerfeusbcalib.cpp
settings/featuresetpreset.cpp
settings/preferences.cpp
settings/preset.cpp
settings/mainsettings.cpp
@ -292,6 +294,7 @@ set(sdrbase_HEADERS
device/deviceutils.h
feature/feature.h
feature/featureutils.h
limerfe/limerfeusbcalib.h
@ -300,6 +303,7 @@ set(sdrbase_HEADERS
plugin/pluginapi.h
plugin/pluginmanager.h
settings/featuresetpreset.h
settings/preferences.h
settings/preset.h
settings/mainsettings.h

View File

@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "featureutils.h"
bool FeatureUtils::compareFeatureURIs(const QString& registeredFeatureURI, const QString& xFeatureURI)
{
return registeredFeatureURI == getRegisteredFeatureURI(xFeatureURI);
}
QString FeatureUtils::getRegisteredFeatureURI(const QString& xFeatureURI)
{
return xFeatureURI;
}

View File

@ -0,0 +1,31 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_FEATURE_FEATUREUTILS_H_
#define SDRBASE_FEATURE_FEATUREUTILS_H_
#include <QString>
#include "export.h"
class SDRBASE_API FeatureUtils
{
public:
static bool compareFeatureURIs(const QString& registeredFeatureURI, const QString& xFeatureURI);
static QString getRegisteredFeatureURI(const QString& xFeatureURI);
};
#endif // SDRBASE_FEATURE_FEATUREUTILS_H_

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// Interface for static web API adapters used for preset serialization and //
// deserialization //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_FEATURE_FEATUREWEBAPIADAPER_H_
#define SDRBASE_FEATURE_FEATUREWEBAPIADAPER_H_
#include <QByteArray>
#include <QStringList>
#include "export.h"
namespace SWGSDRangel
{
class SWGFeatureSettings;
}
class SDRBASE_API FeatureWebAPIAdapter
{
public:
FeatureWebAPIAdapter() {}
virtual ~FeatureWebAPIAdapter() {}
virtual QByteArray serialize() const = 0;
virtual bool deserialize(const QByteArray& data) = 0;
/**
* API adapter for the channel settings GET requests
*/
virtual int webapiSettingsGet(
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) response;
errorMessage = "Not implemented"; return 501;
}
/**
* API adapter for the channel settings PUT and PATCH requests
*/
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& featureSettingsKeys,
SWGSDRangel::SWGFeatureSettings& response,
QString& errorMessage)
{
(void) force;
(void) featureSettingsKeys;
(void) response;
errorMessage = "Not implemented"; return 501;
}
};
#endif // SDRBASE_FEATURE_FEATUREWEBAPIADAPER_H_

View File

@ -33,6 +33,7 @@ class MIMOChannel;
class ChannelAPI;
class ChannelWebAPIAdapter;
class DeviceWebAPIAdapter;
class FeatureWebAPIAdapter;
class Feature;
class SDRBASE_API PluginInterface {
@ -198,6 +199,13 @@ public:
return nullptr;
}
// any feature
virtual FeatureWebAPIAdapter* createFeatureWebAPIAdapter() const
{
return nullptr;
}
// any device
virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices)

View File

@ -360,3 +360,15 @@ const PluginInterface *PluginManager::getDevicePluginInterface(const QString& de
return nullptr;
}
const PluginInterface *PluginManager::getFeaturePluginInterface(const QString& featureIdURI) const
{
for (PluginAPI::FeatureRegistrations::const_iterator it = m_featureRegistrations.begin(); it != m_featureRegistrations.end(); ++it)
{
if (it->m_featureIdURI == featureIdURI) {
return it->m_plugin;
}
}
return nullptr;
}

View File

@ -30,7 +30,6 @@
class QComboBox;
class QPluginLoader;
class Preset;
class Message;
class MessageQueue;
class DeviceAPI;
@ -95,6 +94,7 @@ public:
const PluginInterface *getChannelPluginInterface(const QString& channelIdURI) const;
const PluginInterface *getDevicePluginInterface(const QString& deviceId) const;
const PluginInterface *getFeaturePluginInterface(const QString& featureIdURI) const;
static const QString& getFileInputDeviceId() { return m_fileInputDeviceTypeID; }
static const QString& getFileOutputDeviceId() { return m_fileOutputDeviceTypeID; }

View File

@ -38945,7 +38945,11 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
<<<<<<< ours
Generated 2020-09-28T13:50:10.100+02:00
=======
Generated 2020-09-23T23:57:22.462+02:00
>>>>>>> theirs
</div>
</div>
</div>

View File

@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "util/simpleserializer.h"
#include "featuresetpreset.h"
FeatureSetPreset::FeatureSetPreset()
{
resetToDefaults();
}
FeatureSetPreset::FeatureSetPreset(const FeatureSetPreset& other) :
m_group(other.m_group),
m_description(other.m_description),
m_featureConfigs(other.m_featureConfigs)
{}
void FeatureSetPreset::resetToDefaults()
{
m_group = "default";
m_description = "no name";
m_featureConfigs.clear();
}
QByteArray FeatureSetPreset::serialize() const
{
SimpleSerializer s(1);
s.writeString(1, m_group);
s.writeString(2, m_description);
s.writeS32(100, m_featureConfigs.size());
for(int i = 0; i < m_featureConfigs.size(); i++)
{
s.writeString(101 + i * 2, m_featureConfigs[i].m_featureIdURI);
s.writeBlob(102 + i * 2, m_featureConfigs[i].m_config);
}
return s.final();
}
bool FeatureSetPreset::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
bool tmpBool;
int tmp;
d.readString(1, &m_group, "default");
d.readString(2, &m_description, "no name");
qint32 featureCount;
d.readS32(100, &featureCount, 0);
m_featureConfigs.clear();
for (int i = 0; i < featureCount; i++)
{
QString feature;
QByteArray config;
d.readString(101 + i * 2, &feature, "unknown-feature");
d.readBlob(102 + i * 2, &config);
m_featureConfigs.append(FeatureConfig(feature, config));
}
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,81 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_SETTINGS_FEATURESETSETTINGS_H_
#define SDRBASE_SETTINGS_FEATURESETSETTINGS_H_
#include <QString>
#include <QByteArray>
#include <QList>
#include <QMetaType>
#include "export.h"
class SDRBASE_API FeatureSetPreset {
public:
struct FeatureConfig {
QString m_featureIdURI; //!< Channel type ID in URI form
QByteArray m_config;
FeatureConfig(const QString& featureIdURI, const QByteArray& config) :
m_featureIdURI(featureIdURI),
m_config(config)
{ }
};
typedef QList<FeatureConfig> FeatureConfigs;
FeatureSetPreset();
FeatureSetPreset(const FeatureSetPreset& other);
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void setGroup(const QString& group) { m_group = group; }
const QString& getGroup() const { return m_group; }
void setDescription(const QString& description) { m_description = description; }
const QString& getDescription() const { return m_description; }
void clearFeatures() { m_featureConfigs.clear(); }
void addFeature(const QString& feature, const QByteArray& config) { m_featureConfigs.append(FeatureConfig(feature, config)); }
int getFeatureCount() const { return m_featureConfigs.count(); }
const FeatureConfig& getFeatureConfig(int index) const { return m_featureConfigs.at(index); }
static bool presetCompare(const FeatureSetPreset *p1, FeatureSetPreset *p2)
{
if (p1->m_group != p2->m_group)
{
return p1->m_group < p2->m_group;
}
else
{
return p1->m_description < p2->m_description;
}
}
private:
// group and preset description
QString m_group;
QString m_description;
// features and configurations
FeatureConfigs m_featureConfigs;
};
Q_DECLARE_METATYPE(const FeatureSetPreset*)
Q_DECLARE_METATYPE(FeatureSetPreset*)
#endif // SDRBASE_SETTINGS_FEATURESETSETTINGS_H_

View File

@ -19,15 +19,20 @@ MainSettings::MainSettings() :
MainSettings::~MainSettings()
{
for(int i = 0; i < m_presets.count(); ++i)
for (int i = 0; i < m_presets.count(); ++i)
{
delete m_presets[i];
}
for(int i = 0; i < m_commands.count(); ++i)
for (int i = 0; i < m_commands.count(); ++i)
{
delete m_commands[i];
}
for (int i = 0; i < m_featureSetPresets.count(); ++i)
{
delete m_featureSetPresets[i];
}
}
QString MainSettings::getFileLocation() const
@ -42,12 +47,13 @@ int MainSettings::getFileFormat() const
return (int) s.format();
}
void MainSettings::load(PluginManager *pluginManager)
void MainSettings::load()
{
QSettings s;
m_preferences.deserialize(qUncompress(QByteArray::fromBase64(s.value("preferences").toByteArray())));
m_workingPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current").toByteArray())));
m_workingFeatureSetPreset.deserialize(qUncompress(QByteArray::fromBase64(s.value("current-featureset").toByteArray())));
if (m_audioDeviceManager) {
m_audioDeviceManager->deserialize(qUncompress(QByteArray::fromBase64(s.value("audio").toByteArray())));
@ -59,14 +65,14 @@ void MainSettings::load(PluginManager *pluginManager)
QStringList groups = s.childGroups();
for(int i = 0; i < groups.size(); ++i)
for (int i = 0; i < groups.size(); ++i)
{
if (groups[i].startsWith("preset"))
{
s.beginGroup(groups[i]);
Preset* preset = new Preset;
if(preset->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray()))))
if (preset->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray()))))
{
m_presets.append(preset);
}
@ -82,7 +88,7 @@ void MainSettings::load(PluginManager *pluginManager)
s.beginGroup(groups[i]);
Command* command = new Command;
if(command->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray()))))
if (command->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray()))))
{
m_commands.append(command);
}
@ -91,6 +97,22 @@ void MainSettings::load(PluginManager *pluginManager)
delete command;
}
s.endGroup();
}
else if (groups[i].startsWith("featureset"))
{
s.beginGroup(groups[i]);
FeatureSetPreset* featureSetPreset = new FeatureSetPreset;
if (featureSetPreset->deserialize(qUncompress(QByteArray::fromBase64(s.value("data").toByteArray()))))
{
m_featureSetPresets.append(featureSetPreset);
}
else
{
delete featureSetPreset;
}
s.endGroup();
}
}
@ -99,12 +121,13 @@ void MainSettings::load(PluginManager *pluginManager)
m_limeRFEUSBCalib.deserialize(qUncompress(QByteArray::fromBase64(s.value("limeRFEUSBCalib").toByteArray())));
}
void MainSettings::save(PluginManager *pluginManager) const
void MainSettings::save() const
{
QSettings s;
s.setValue("preferences", qCompress(m_preferences.serialize()).toBase64());
s.setValue("current", qCompress(m_workingPreset.serialize()).toBase64());
s.setValue("current-featureset", qCompress(m_workingFeatureSetPreset.serialize()).toBase64());
if (m_audioDeviceManager) {
s.setValue("audio", qCompress(m_audioDeviceManager->serialize()).toBase64());
@ -140,6 +163,14 @@ void MainSettings::save(PluginManager *pluginManager) const
s.endGroup();
}
for (int i = 0; i < m_featureSetPresets.count(); ++i)
{
QString group = QString("featureset-%1").arg(i + 1);
s.beginGroup(group);
s.setValue("data", qCompress(m_featureSetPresets[i]->serialize()).toBase64());
s.endGroup();
}
s.setValue("hwDeviceUserArgs", qCompress(m_hardwareDeviceUserArgs.serialize()).toBase64());
s.setValue("limeRFEUSBCalib", qCompress(m_limeRFEUSBCalib.serialize()).toBase64());
}
@ -149,14 +180,18 @@ void MainSettings::initialize()
resetToDefaults();
clearCommands();
clearPresets();
clearFeatureSetPresets();
}
void MainSettings::resetToDefaults()
{
m_preferences.resetToDefaults();
m_workingPreset.resetToDefaults();
m_workingFeatureSetPreset.resetToDefaults();
}
// DeviceSet presets
Preset* MainSettings::newPreset(const QString& group, const QString& description)
{
Preset* preset = new Preset();
@ -230,7 +265,7 @@ const Preset* MainSettings::getPreset(const QString& groupName, quint64 centerFr
}
}
return 0;
return nullptr;
}
void MainSettings::clearPresets()
@ -242,6 +277,8 @@ void MainSettings::clearPresets()
m_presets.clear();
}
// Commands
void MainSettings::addCommand(Command *command)
{
m_commands.append(command);
@ -299,7 +336,7 @@ const Command* MainSettings::getCommand(const QString& groupName, const QString&
}
}
return 0;
return nullptr;
}
void MainSettings::clearCommands()
@ -310,3 +347,83 @@ void MainSettings::clearCommands()
m_commands.clear();
}
// FeatureSet presets
FeatureSetPreset* MainSettings::newFeatureSetPreset(const QString& group, const QString& description)
{
FeatureSetPreset* preset = new FeatureSetPreset();
preset->setGroup(group);
preset->setDescription(description);
addFeatureSetPreset(preset);
return preset;
}
void MainSettings::addFeatureSetPreset(FeatureSetPreset *preset)
{
m_featureSetPresets.append(preset);
}
void MainSettings::deleteFeatureSetPreset(const FeatureSetPreset* preset)
{
m_featureSetPresets.removeAll((FeatureSetPreset*) preset);
delete (FeatureSetPreset*) preset;
}
void MainSettings::deleteFeatureSetPresetGroup(const QString& groupName)
{
FeatureSetPresets::iterator it = m_featureSetPresets.begin();
while (it != m_featureSetPresets.end())
{
if ((*it)->getGroup() == groupName) {
it = m_featureSetPresets.erase(it);
} else {
++it;
}
}
}
void MainSettings::sortFeatureSetPresets()
{
std::sort(m_featureSetPresets.begin(), m_featureSetPresets.end(), FeatureSetPreset::presetCompare);
}
void MainSettings::renameFeatureSetPresetGroup(const QString& oldGroupName, const QString& newGroupName)
{
int nbPresets = getFeatureSetPresetCount();
for (int i = 0; i < nbPresets; i++)
{
if (getPreset(i)->getGroup() == oldGroupName)
{
FeatureSetPreset *preset_mod = const_cast<FeatureSetPreset*>(getFeatureSetPreset(i));
preset_mod->setGroup(newGroupName);
}
}
}
const FeatureSetPreset* MainSettings::getFeatureSetPreset(const QString& groupName, const QString& description) const
{
int nbPresets = getFeatureSetPresetCount();
for (int i = 0; i < nbPresets; i++)
{
if ((getFeatureSetPreset(i)->getGroup() == groupName) &&
(getFeatureSetPreset(i)->getDescription() == description))
{
return getFeatureSetPreset(i);
}
}
return nullptr;
}
void MainSettings::clearFeatureSetPresets()
{
foreach (FeatureSetPreset *preset, m_featureSetPresets) {
delete preset;
}
m_featureSetPresets.clear();
}

View File

@ -6,6 +6,7 @@
#include "limerfe/limerfeusbcalib.h"
#include "preferences.h"
#include "preset.h"
#include "featuresetpreset.h"
#include "export.h"
#include "plugin/pluginmanager.h"
@ -19,8 +20,8 @@ public:
MainSettings();
~MainSettings();
void load(PluginManager *pluginManager);
void save(PluginManager *pluginManager) const;
void load();
void save() const;
void resetToDefaults();
void initialize();
@ -40,6 +41,8 @@ public:
void renamePresetGroup(const QString& oldGroupName, const QString& newGroupName);
void deletePresetGroup(const QString& groupName);
void clearPresets();
const Preset& getWorkingPresetConst() const { return m_workingPreset; }
Preset* getWorkingPreset() { return &m_workingPreset; }
void addCommand(Command *command);
void deleteCommand(const Command* command);
@ -51,8 +54,20 @@ public:
void deleteCommandGroup(const QString& groupName);
void clearCommands();
const Preset& getWorkingPresetConst() const { return m_workingPreset; }
Preset* getWorkingPreset() { return &m_workingPreset; }
FeatureSetPreset* newFeatureSetPreset(const QString& group, const QString& description);
void addFeatureSetPreset(FeatureSetPreset *preset);
void deleteFeatureSetPreset(const FeatureSetPreset* preset);
int getFeatureSetPresetCount() const { return m_featureSetPresets.count(); }
const FeatureSetPreset* getFeatureSetPreset(int index) const { return m_featureSetPresets[index]; }
const FeatureSetPreset* getFeatureSetPreset(const QString& groupName, const QString& description) const;
void sortFeatureSetPresets();
void renameFeatureSetPresetGroup(const QString& oldGroupName, const QString& newGroupName);
void deleteFeatureSetPresetGroup(const QString& groupName);
void clearFeatureSetPresets();
const FeatureSetPreset& getWorkingFeatureSetPresetConst() const { return m_workingFeatureSetPreset; }
FeatureSetPreset* getWorkingFeatureSetPreset() { return &m_workingFeatureSetPreset; }
QList<FeatureSetPreset*> *getFeatureSetPresets() { return &m_featureSetPresets; }
int getSourceIndex() const { return m_preferences.getSourceIndex(); }
void setSourceIndex(int value) { m_preferences.setSourceIndex(value); }
const QString& getSourceDeviceId() const { return m_preferences.getSourceDevice(); }
@ -82,10 +97,13 @@ protected:
Preferences m_preferences;
AudioDeviceManager *m_audioDeviceManager;
Preset m_workingPreset;
FeatureSetPreset m_workingFeatureSetPreset;
typedef QList<Preset*> Presets;
Presets m_presets;
typedef QList<Command*> Commands;
Commands m_commands;
typedef QList<FeatureSetPreset*> FeatureSetPresets;
FeatureSetPresets m_featureSetPresets;
DeviceUserArgs m_hardwareDeviceUserArgs;
LimeRFEUSBCalib m_limeRFEUSBCalib;
AMBEEngine *m_ambeEngine;

View File

@ -22,6 +22,8 @@
#include "channel/channelutils.h"
#include "device/devicewebapiadapter.h"
#include "device/deviceutils.h"
#include "feature/featurewebapiadapter.h"
#include "feature/featureutils.h"
#include "dsp/glspectrumsettings.h"
#include "webapiadapterbase.h"
@ -31,6 +33,8 @@ WebAPIAdapterBase::WebAPIAdapterBase()
WebAPIAdapterBase::~WebAPIAdapterBase()
{
m_webAPIChannelAdapters.flush();
m_webAPIFeatureAdapters.flush();
m_webAPIDeviceAdapters.flush();
}
void WebAPIAdapterBase::webapiFormatPreferences(
@ -90,6 +94,37 @@ void WebAPIAdapterBase::webapiUpdatePreferences(
}
}
void WebAPIAdapterBase::webapiFormatFeatureSetPreset(
SWGSDRangel::SWGFeatureSetPreset *apiPreset,
const FeatureSetPreset& preset
)
{
apiPreset->init();
apiPreset->setGroup(new QString(preset.getGroup()));
apiPreset->setDescription(new QString(preset.getDescription()));
int nbFeatures = preset.getFeatureCount();
for (int i = 0; i < nbFeatures; i++)
{
const FeatureSetPreset::FeatureConfig& featureConfig = preset.getFeatureConfig(i);
QList<SWGSDRangel::SWGFeatureConfig *> *swgFeatureConfigs = apiPreset->getFeatureConfigs();
swgFeatureConfigs->append(new SWGSDRangel::SWGFeatureConfig);
swgFeatureConfigs->back()->init();
swgFeatureConfigs->back()->setFeatureIdUri(new QString(featureConfig.m_featureIdURI));
const QByteArray& featureSettings = featureConfig.m_config;
SWGSDRangel::SWGFeatureSettings *swgFeatureSettings = swgFeatureConfigs->back()->getConfig();
swgFeatureSettings->init();
FeatureWebAPIAdapter *featureWebAPIAdapter = m_webAPIFeatureAdapters.getFeatureWebAPIAdapter(featureConfig.m_featureIdURI, m_pluginManager);
if (featureWebAPIAdapter)
{
featureWebAPIAdapter->deserialize(featureSettings);
QString errorMessage;
featureWebAPIAdapter->webapiSettingsGet(*swgFeatureSettings, errorMessage);
}
}
}
void WebAPIAdapterBase::webapiFormatPreset(
SWGSDRangel::SWGPreset *apiPreset,
const Preset& preset
@ -179,6 +214,65 @@ void WebAPIAdapterBase::webapiFormatPreset(
apiPreset->setLayout(new QString(preset.getLayout().toBase64().toStdString().c_str()));
}
void WebAPIAdapterBase::webapiUpdateFeatureSetPreset(
bool force,
SWGSDRangel::SWGFeatureSetPreset *apiPreset,
const WebAPIAdapterInterface::FeatureSetPresetKeys& presetKeys,
FeatureSetPreset *preset
)
{
if (presetKeys.m_keys.contains("description")) {
preset->setDescription(*apiPreset->getDescription());
}
if (presetKeys.m_keys.contains("group")) {
preset->setGroup(*apiPreset->getGroup());
}
if (force) { // PUT replaces feature list possibly erasing it if no features are given
preset->clearFeatures();
}
QList<WebAPIAdapterInterface::FeatureKeys>::const_iterator featureKeysIt = presetKeys.m_featureKeys.begin();
int i = 0;
QString errorMessage;
for (; featureKeysIt != presetKeys.m_featureKeys.end(); ++featureKeysIt, i++)
{
SWGSDRangel::SWGFeatureConfig *swgFeatureConfig = apiPreset->getFeatureConfigs()->at(i);
if (!swgFeatureConfig) { // safety measure but should not happen
continue;
}
if (featureKeysIt->m_keys.contains("featureIdURI"))
{
QString *featureIdURI = swgFeatureConfig->getFeatureIdUri();
if (!featureIdURI) {
continue;
}
FeatureWebAPIAdapter *featureWebAPIAdapter = m_webAPIFeatureAdapters.getFeatureWebAPIAdapter(*featureIdURI, m_pluginManager);
if (!featureWebAPIAdapter) {
continue;
}
SWGSDRangel::SWGFeatureSettings *featureSettings = swgFeatureConfig->getConfig();
featureWebAPIAdapter->webapiSettingsPutPatch(
true, // features are always appended
featureKeysIt->m_featureKeys,
*featureSettings,
errorMessage
);
QByteArray config = featureWebAPIAdapter->serialize();
preset->addFeature(*featureIdURI, config);
}
}
}
void WebAPIAdapterBase::webapiUpdatePreset(
bool force,
SWGSDRangel::SWGPreset *apiPreset,
@ -489,3 +583,39 @@ void WebAPIAdapterBase::WebAPIDeviceAdapters::flush()
m_webAPIDeviceAdapters.clear();
}
FeatureWebAPIAdapter *WebAPIAdapterBase::WebAPIFeatureAdapters::getFeatureWebAPIAdapter(const QString& featureURI, const PluginManager *pluginManager)
{
QString registeredFeatureURI = FeatureUtils::getRegisteredFeatureURI(featureURI);
QMap<QString, FeatureWebAPIAdapter*>::iterator it = m_webAPIFeatureAdapters.find(registeredFeatureURI);
if (it == m_webAPIFeatureAdapters.end())
{
const PluginInterface *pluginInterface = pluginManager->getFeaturePluginInterface(registeredFeatureURI);
if (pluginInterface)
{
FeatureWebAPIAdapter *featureAPI = pluginInterface->createFeatureWebAPIAdapter();
m_webAPIFeatureAdapters.insert(registeredFeatureURI, featureAPI);
return featureAPI;
}
else
{
m_webAPIFeatureAdapters.insert(registeredFeatureURI, nullptr);
return nullptr;
}
}
else
{
return *it;
}
}
void WebAPIAdapterBase::WebAPIFeatureAdapters::flush()
{
foreach(FeatureWebAPIAdapter *featureAPI, m_webAPIFeatureAdapters) {
delete featureAPI;
}
m_webAPIFeatureAdapters.clear();
}

View File

@ -24,9 +24,11 @@
#include "export.h"
#include "SWGPreferences.h"
#include "SWGPreset.h"
#include "SWGFeatureSetPreset.h"
#include "SWGCommand.h"
#include "settings/preferences.h"
#include "settings/preset.h"
#include "settings/featuresetpreset.h"
#include "settings/mainsettings.h"
#include "commands/command.h"
#include "webapiadapterinterface.h"
@ -54,6 +56,10 @@ public:
SWGSDRangel::SWGPreset *apiPreset,
const Preset& preset
);
void webapiFormatFeatureSetPreset(
SWGSDRangel::SWGFeatureSetPreset *apiPreset,
const FeatureSetPreset& preset
);
static void webapiFormatCommand(
SWGSDRangel::SWGCommand *apiCommand,
const Command& command
@ -72,6 +78,12 @@ public:
const WebAPIAdapterInterface::PresetKeys& presetKeys,
Preset *preset
);
void webapiUpdateFeatureSetPreset(
bool force,
SWGSDRangel::SWGFeatureSetPreset *apiPreset,
const WebAPIAdapterInterface::FeatureSetPresetKeys& presetKeys,
FeatureSetPreset *preset
);
static void webapiUpdateCommand(
SWGSDRangel::SWGCommand *apiCommand,
const WebAPIAdapterInterface::CommandKeys& commandKeys,
@ -97,9 +109,19 @@ private:
QMap<QString, DeviceWebAPIAdapter*> m_webAPIDeviceAdapters;
};
class WebAPIFeatureAdapters
{
public:
FeatureWebAPIAdapter *getFeatureWebAPIAdapter(const QString& featureURI, const PluginManager *pluginManager);
void flush();
private:
QMap<QString, FeatureWebAPIAdapter*> m_webAPIFeatureAdapters;
};
const PluginManager *m_pluginManager;
WebAPIChannelAdapters m_webAPIChannelAdapters;
WebAPIDeviceAdapters m_webAPIDeviceAdapters;
WebAPIFeatureAdapters m_webAPIFeatureAdapters;
};
#endif // SDRBASE_WEBAPI_WEBAPIADAPTERBASE_H_

View File

@ -110,10 +110,34 @@ void WebAPIAdapterInterface::ConfigKeys::debug() const
qDebug(" }");
}
qDebug("featuresets:");
foreach(FeatureSetPresetKeys presetKeys, m_featureSetPresetKeys)
{
qDebug(" {");
foreach(QString presetKey, presetKeys.m_keys) {
qDebug(" %s", qPrintable(presetKey));
}
qDebug(" featureConfigs");
foreach(FeatureKeys featureKeys, presetKeys.m_featureKeys)
{
qDebug(" {");
qDebug(" config:");
foreach(QString featureKey, featureKeys.m_featureKeys) {
qDebug(" %s", qPrintable(featureKey));
}
qDebug(" }");
}
qDebug(" }");
}
qDebug("workingPreset:");
foreach(QString presetKey, m_workingPresetKeys.m_keys) {
qDebug(" %s", qPrintable(presetKey));
}
qDebug("workingFeatureSetPreset:");
foreach(QString presetKey, m_workingFeatureSetPresetKeys.m_keys) {
qDebug(" %s", qPrintable(presetKey));
}
qDebug(" spectrumConfig:");
foreach(QString spectrumKey, m_workingPresetKeys.m_spectrumKeys) {
qDebug(" %s", qPrintable(spectrumKey));

View File

@ -82,6 +82,11 @@ public:
QStringList m_keys;
QStringList m_deviceKeys;
};
struct FeatureKeys
{
QStringList m_keys;
QStringList m_featureKeys;
};
struct PresetKeys
{
QStringList m_keys;
@ -89,6 +94,12 @@ public:
QList<ChannelKeys> m_channelsKeys;
QList<DeviceKeys> m_devicesKeys;
};
struct FeatureSetPresetKeys
{
QStringList m_keys;
QList<FeatureKeys> m_featureKeys;
QList<DeviceKeys> m_devicesKeys;
};
struct CommandKeys
{
QStringList m_keys;
@ -97,7 +108,9 @@ public:
{
QStringList m_preferencesKeys;
PresetKeys m_workingPresetKeys;
FeatureSetPresetKeys m_workingFeatureSetPresetKeys;
QList<PresetKeys> m_presetKeys;
QList<FeatureSetPresetKeys> m_featureSetPresetKeys;
QList<CommandKeys> m_commandKeys;
void debug() const;
};

View File

@ -51,6 +51,10 @@
#include "SWGChannelActions.h"
#include "SWGSuccessResponse.h"
#include "SWGErrorResponse.h"
#include "SWGFeatureSetList.h"
#include "SWGFeatureSettings.h"
#include "SWGFeatureReport.h"
#include "SWGFeatureActions.h"
const QMap<QString, QString> WebAPIRequestMapper::m_channelURIToSettingsKey = {
{"sdrangel.channel.amdemod", "AMDemodSettings"},
@ -229,6 +233,10 @@ const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToSettingsKey=
const QMap<QString, QString> WebAPIRequestMapper::m_mimoDeviceHwIdToActionsKey= {
};
const QMap<QString, QString> WebAPIRequestMapper::m_featureURIToSettingsKey = {
{"sdrangel.feature.simpleptt", "SimplePTTSettings"}
};
WebAPIRequestMapper::WebAPIRequestMapper(QObject* parent) :
HttpRequestHandler(parent),
m_adapter(0)
@ -2882,7 +2890,10 @@ bool WebAPIRequestMapper::validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings&
return true;
}
bool WebAPIRequestMapper::validateConfig(SWGSDRangel::SWGInstanceConfigResponse& config, QJsonObject& jsonObject, WebAPIAdapterInterface::ConfigKeys& configKeys)
bool WebAPIRequestMapper::validateConfig(
SWGSDRangel::SWGInstanceConfigResponse& config,
QJsonObject& jsonObject,
WebAPIAdapterInterface::ConfigKeys& configKeys)
{
if (jsonObject.contains("preferences"))
{
@ -2927,6 +2938,23 @@ bool WebAPIRequestMapper::validateConfig(SWGSDRangel::SWGInstanceConfigResponse&
}
}
if (jsonObject.contains("featuresetpresets"))
{
QList<SWGSDRangel::SWGFeatureSetPreset *> *featureSetPresets = new QList<SWGSDRangel::SWGFeatureSetPreset *>();
config.setFeaturesetpresets(featureSetPresets);
QJsonArray presetsJson = jsonObject["featuresetpresets"].toArray();
QJsonArray::const_iterator featureSetPresetsIt = presetsJson.begin();
for (; featureSetPresetsIt != presetsJson.end(); ++featureSetPresetsIt)
{
QJsonObject presetJson = featureSetPresetsIt->toObject();
SWGSDRangel::SWGFeatureSetPreset *featureSetPreset = new SWGSDRangel::SWGFeatureSetPreset();
featureSetPresets->append(featureSetPreset);
configKeys.m_featureSetPresetKeys.append(WebAPIAdapterInterface::FeatureSetPresetKeys());
appendFeatureSetPresetKeys(featureSetPreset, presetJson, configKeys.m_featureSetPresetKeys.back());
}
}
if (jsonObject.contains("workingPreset"))
{
SWGSDRangel::SWGPreset *preset = new SWGSDRangel::SWGPreset();
@ -2935,6 +2963,58 @@ bool WebAPIRequestMapper::validateConfig(SWGSDRangel::SWGInstanceConfigResponse&
appendPresetKeys(preset, presetJson, configKeys.m_workingPresetKeys);
}
if (jsonObject.contains("workingFeatureSetPreset"))
{
SWGSDRangel::SWGFeatureSetPreset *preset = new SWGSDRangel::SWGFeatureSetPreset();
config.setWorkingFeatureSetPreset(preset);
QJsonObject presetJson = jsonObject["workingFeatureSetPreset"].toObject();
appendFeatureSetPresetKeys(preset, presetJson, configKeys.m_workingFeatureSetPresetKeys);
}
return true;
}
bool WebAPIRequestMapper::appendFeatureSetPresetKeys(
SWGSDRangel::SWGFeatureSetPreset *preset,
const QJsonObject& presetJson,
WebAPIAdapterInterface::FeatureSetPresetKeys& featureSetPresetKeys
)
{
if (presetJson.contains("description"))
{
preset->setDescription(new QString(presetJson["description"].toString()));
featureSetPresetKeys.m_keys.append("description");
}
if (presetJson.contains("group"))
{
preset->setGroup(new QString(presetJson["group"].toString()));
featureSetPresetKeys.m_keys.append("group");
}
if (presetJson.contains("featureConfigs"))
{
QJsonArray featuresJson = presetJson["featureConfigs"].toArray();
QJsonArray::const_iterator featuresIt = featuresJson.begin();
QList<SWGSDRangel::SWGFeatureConfig*> *features = new QList<SWGSDRangel::SWGFeatureConfig*>();
preset->setFeatureConfigs(features);
for (; featuresIt != featuresJson.end(); ++featuresIt)
{
QJsonObject featureJson = featuresIt->toObject();
SWGSDRangel::SWGFeatureConfig *featureConfig = new SWGSDRangel::SWGFeatureConfig();
featureSetPresetKeys.m_featureKeys.append(WebAPIAdapterInterface::FeatureKeys());
if (appendPresetFeatureKeys(featureConfig, featureJson, featureSetPresetKeys.m_featureKeys.back()))
{
features->append(featureConfig);
}
else
{
delete featureConfig;
featureSetPresetKeys.m_featureKeys.takeLast(); // remove channel keys
}
}
}
return true;
}
@ -3042,6 +3122,40 @@ bool WebAPIRequestMapper::appendPresetKeys(
return true;
}
bool WebAPIRequestMapper::appendPresetFeatureKeys(
SWGSDRangel::SWGFeatureConfig *feature,
const QJsonObject& featureSettingsJson,
WebAPIAdapterInterface::FeatureKeys& featureKeys
)
{
if (featureSettingsJson.contains("featureIdURI"))
{
QString *featureURI = new QString(featureSettingsJson["featureIdURI"].toString());
feature->setFeatureIdUri(featureURI);
featureKeys.m_keys.append("featureIdURI");
if (featureSettingsJson.contains("config") && m_featureURIToSettingsKey.contains(*featureURI))
{
SWGSDRangel::SWGFeatureSettings *featureSettings = new SWGSDRangel::SWGFeatureSettings();
feature->setConfig(featureSettings);
return getFeatureSettings(
m_channelURIToSettingsKey[*featureURI],
featureSettings,
featureSettingsJson["config"].toObject(),
featureKeys.m_featureKeys
);
}
else
{
return false;
}
}
else
{
return false;
}
}
bool WebAPIRequestMapper::appendPresetChannelKeys(
SWGSDRangel::SWGChannelConfig *channel,
const QJsonObject& channelSettingsJson,
@ -3522,6 +3636,70 @@ bool WebAPIRequestMapper::getDeviceActions(
}
bool WebAPIRequestMapper::getFeatureSettings(
const QString& featureSettingsKey,
SWGSDRangel::SWGFeatureSettings *featureSettings,
const QJsonObject& featureSettingsJson,
QStringList& featureSettingsKeys
)
{
QStringList featureKeys = featureSettingsJson.keys();
if (featureKeys.contains(featureSettingsKey) && featureSettingsJson[featureSettingsKey].isObject())
{
QJsonObject settingsJsonObject = featureSettingsJson[featureSettingsKey].toObject();
featureSettingsKeys = settingsJsonObject.keys();
if (featureSettingsKey == "SimplePTTSettings")
{
featureSettings->setSimplePttSettings(new SWGSDRangel::SWGSimplePTTSettings());
featureSettings->getSimplePttSettings()->fromJsonObject(settingsJsonObject);
}
else
{
return false;
}
return true;
}
else
{
return false;
}
}
bool WebAPIRequestMapper::getFeatureActions(
const QString& featureActionsKey,
SWGSDRangel::SWGFeatureActions *featureActions,
const QJsonObject& featureActionsJson,
QStringList& featureActionsKeys
)
{
QStringList featureKeys = featureActionsJson.keys();
if (featureKeys.contains(featureActionsKey) && featureActionsJson[featureActionsKey].isObject())
{
QJsonObject actionsJsonObject = featureActionsJson[featureActionsKey].toObject();
featureActionsKeys = actionsJsonObject.keys();
if (featureActionsKey == "SimplePTTActions")
{
featureActions->setSimplePttActions(new SWGSDRangel::SWGSimplePTTActions());
featureActions->getSimplePttActions()->fromJsonObject(actionsJsonObject);
}
else
{
return false;
}
return true;
}
else
{
return false;
}
}
void WebAPIRequestMapper::appendSettingsSubKeys(
const QJsonObject& parentSettingsJsonObject,
QJsonObject& childSettingsJsonObject,

View File

@ -37,6 +37,9 @@ namespace SWGSDRangel
class SWGPreset;
class SWGChannelConfig;
class SWGDeviceConfig;
class SWGFeatureConfig;
class SWGFeatureActions;
class SWGFeatureSetPreset;
}
class SDRBASE_API WebAPIRequestMapper : public qtwebapp::HttpRequestHandler {
@ -104,11 +107,23 @@ private:
bool validateLimeRFEConfig(SWGSDRangel::SWGLimeRFESettings& limeRFESettings, QJsonObject& jsonObject, QStringList& limeRFESettingsKeys);
bool validateConfig(SWGSDRangel::SWGInstanceConfigResponse& config, QJsonObject& jsonObject, WebAPIAdapterInterface::ConfigKeys& configKeys);
bool appendFeatureSetPresetKeys(
SWGSDRangel::SWGFeatureSetPreset *preset,
const QJsonObject& presetJson,
WebAPIAdapterInterface::FeatureSetPresetKeys& featureSetPresetKeys
);
bool appendPresetKeys(
SWGSDRangel::SWGPreset *preset,
const QJsonObject& presetJson,
WebAPIAdapterInterface::PresetKeys& presetKeys);
bool appendPresetFeatureKeys(
SWGSDRangel::SWGFeatureConfig *feature,
const QJsonObject& featureSettingsJson,
WebAPIAdapterInterface::FeatureKeys& featureKeys
);
bool appendPresetChannelKeys(
SWGSDRangel::SWGChannelConfig *channel,
const QJsonObject& channelSettngsJson,
@ -160,6 +175,20 @@ private:
const QString& parentKey,
QStringList& keyList);
bool getFeatureSettings(
const QString& featureSettingsKey,
SWGSDRangel::SWGFeatureSettings *featureSettings,
const QJsonObject& featureSettingsJson,
QStringList& featureSettingsKeys
);
bool getFeatureActions(
const QString& featureActionsKey,
SWGSDRangel::SWGFeatureActions *featureActions,
const QJsonObject& featureActionsJson,
QStringList& featureSettingsKeys
);
bool parseJsonBody(QString& jsonStr, QJsonObject& jsonObject, qtwebapp::HttpResponse& response);
void resetDeviceSettings(SWGSDRangel::SWGDeviceSettings& deviceSettings);
@ -194,6 +223,9 @@ private:
static const QMap<QString, QString> m_sourceDeviceHwIdToActionsKey;
static const QMap<QString, QString> m_sinkDeviceHwIdToActionsKey;
static const QMap<QString, QString> m_mimoDeviceHwIdToActionsKey;
static const QMap<QString, QString> m_featureTypeToSettingsKey;
static const QMap<QString, QString> m_featureTypeToActionsKey;
static const QMap<QString, QString> m_featureURIToSettingsKey;
};
#endif /* SDRBASE_WEBAPI_WEBAPIREQUESTMAPPER_H_ */

View File

@ -34,6 +34,7 @@ set(sdrgui_SOURCES
gui/fmpreemphasisdialog.cpp
gui/featureadddialog.cpp
gui/featuresdock.cpp
gui/featurepresetsdialog.cpp
gui/featurewindow.cpp
gui/glscope.cpp
gui/glscopegui.cpp
@ -115,6 +116,7 @@ set(sdrgui_HEADERS
gui/fmpreemphasisdialog.h
gui/featureadddialog.h
gui/featuresdock.h
gui/featurepresetsdialog.h
gui/featurewindow.h
gui/glscope.h
gui/glscopegui.h

View File

@ -17,6 +17,9 @@
#include "gui/featurewindow.h"
#include "plugin/plugininstancegui.h"
#include "plugin/pluginapi.h"
#include "settings/featuresetpreset.h"
#include "feature/featureutils.h"
#include "featureuiset.h"
@ -63,6 +66,16 @@ void FeatureUISet::renameFeatureInstances()
}
}
// sort by name
bool FeatureUISet::FeatureInstanceRegistration::operator<(const FeatureInstanceRegistration& other) const
{
if (m_gui && other.m_gui) {
return m_gui->getName() < other.m_gui->getName();
} else {
return false;
}
}
void FeatureUISet::freeFeatures()
{
for(int i = 0; i < m_featureInstanceRegistrations.count(); i++)
@ -101,3 +114,66 @@ Feature *FeatureUISet::getFeatureAt(int featureIndex)
return nullptr;
}
}
void FeatureUISet::loadFeatureSetSettings(const FeatureSetPreset *preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter)
{
qDebug("FeatureUISet::loadFeatureSetSettings: Loading preset [%s | %s]", qPrintable(preset->getGroup()), qPrintable(preset->getDescription()));
// Available feature plugins
PluginAPI::FeatureRegistrations *featureRegistrations = pluginAPI->getFeatureRegistrations();
// copy currently open features and clear list
FeatureInstanceRegistrations openFeatures = m_featureInstanceRegistrations;
m_featureInstanceRegistrations.clear();
for (int i = 0; i < openFeatures.count(); i++)
{
qDebug("FeatureUISet::loadFeatureSetSettings: destroying old feature [%s]", qPrintable(openFeatures[i].m_featureName));
openFeatures[i].m_gui->destroy();
}
qDebug("FeatureUISet::loadFeatureSetSettings: %d feature(s) in preset", preset->getFeatureCount());
for (int i = 0; i < preset->getFeatureCount(); i++)
{
const FeatureSetPreset::FeatureConfig& featureConfig = preset->getFeatureConfig(i);
FeatureInstanceRegistration reg;
// create feature instance
for(int i = 0; i < featureRegistrations->count(); i++)
{
if (FeatureUtils::compareFeatureURIs((*featureRegistrations)[i].m_featureIdURI, featureConfig.m_featureIdURI))
{
qDebug("FeatureUISet::loadFeatureSetSettings: creating new feature [%s] from config [%s]",
qPrintable((*featureRegistrations)[i].m_featureIdURI),
qPrintable(featureConfig.m_featureIdURI));
Feature *feature =
(*featureRegistrations)[i].m_plugin->createFeature(apiAdapter);
PluginInstanceGUI *featureGUI =
(*featureRegistrations)[i].m_plugin->createFeatureGUI(this, feature);
reg = FeatureInstanceRegistration(featureConfig.m_featureIdURI, featureGUI, feature);
break;
}
}
if (reg.m_gui)
{
qDebug("FeatureUISet::loadFeatureSetSettings: deserializing feature [%s]", qPrintable(featureConfig.m_featureIdURI));
reg.m_gui->deserialize(featureConfig.m_config);
}
}
renameFeatureInstances();
}
void FeatureUISet::saveFeatureSetSettings(FeatureSetPreset *preset)
{
std::sort(m_featureInstanceRegistrations.begin(), m_featureInstanceRegistrations.end()); // sort by increasing delta frequency and type
for (int i = 0; i < m_featureInstanceRegistrations.count(); i++)
{
qDebug("FeatureUISet::saveFeatureSetSettings: saving feature [%s]", qPrintable(m_featureInstanceRegistrations[i].m_featureName));
preset->addFeature(m_featureInstanceRegistrations[i].m_featureName, m_featureInstanceRegistrations[i].m_gui->serialize());
}
}

View File

@ -26,7 +26,10 @@
class QWidget;
class FeatureWindow;
class PluginInstanceGUI;
class PluginAPI;
class Feature;
class FeatureSetPreset;
class WebAPIAdapterInterface;
class SDRGUI_API FeatureUISet
{
@ -42,6 +45,8 @@ public:
void deleteFeature(int featureIndex);
const Feature *getFeatureAt(int featureIndex) const;
Feature *getFeatureAt(int featureIndex);
void loadFeatureSetSettings(const FeatureSetPreset* preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter);
void saveFeatureSetSettings(FeatureSetPreset* preset);
FeatureWindow *m_featureWindow;

View File

@ -0,0 +1,413 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QMessageBox>
#include <QDebug>
#include "gui/addpresetdialog.h"
#include "feature/featureuiset.h"
#include "featurepresetsdialog.h"
#include "settings/featuresetpreset.h"
#include "ui_featurepresetsdialog.h"
FeaturePresetsDialog::FeaturePresetsDialog(QWidget* parent) :
QDialog(parent),
ui(new Ui::FeaturePresetsDialog),
m_featureSetPresets(nullptr)
{
ui->setupUi(this);
}
FeaturePresetsDialog::~FeaturePresetsDialog()
{
delete ui;
}
void FeaturePresetsDialog::populateTree()
{
if (!m_featureSetPresets) {
return;
}
QList<FeatureSetPreset*>::const_iterator it = m_featureSetPresets->begin();
int middleIndex = m_featureSetPresets->size() / 2;
QTreeWidgetItem *treeItem;
ui->presetsTree->clear();
for (int i = 0; it != m_featureSetPresets->end(); ++it, i++)
{
treeItem = addPresetToTree(*it);
if (i == middleIndex) {
ui->presetsTree->setCurrentItem(treeItem);
}
}
updatePresetControls();
}
QTreeWidgetItem* FeaturePresetsDialog::addPresetToTree(const FeatureSetPreset* preset)
{
QTreeWidgetItem* group = nullptr;
for (int i = 0; i < ui->presetsTree->topLevelItemCount(); i++)
{
if (ui->presetsTree->topLevelItem(i)->text(0) == preset->getGroup())
{
group = ui->presetsTree->topLevelItem(i);
break;
}
}
if (!group)
{
QStringList sl;
sl.append(preset->getGroup());
group = new QTreeWidgetItem(ui->presetsTree, sl, PGroup);
group->setFirstColumnSpanned(true);
group->setExpanded(true);
ui->presetsTree->sortByColumn(0, Qt::AscendingOrder);
}
QStringList sl;
sl.append(preset->getDescription());
QTreeWidgetItem* item = new QTreeWidgetItem(group, sl, PItem); // description column
item->setTextAlignment(0, Qt::AlignLeft);
item->setData(0, Qt::UserRole, QVariant::fromValue(preset));
updatePresetControls();
return item;
}
void FeaturePresetsDialog::updatePresetControls()
{
ui->presetsTree->resizeColumnToContents(0);
if (ui->presetsTree->currentItem())
{
ui->presetDelete->setEnabled(true);
ui->presetLoad->setEnabled(true);
}
else
{
ui->presetDelete->setEnabled(false);
ui->presetLoad->setEnabled(false);
}
}
void FeaturePresetsDialog::on_presetSave_clicked()
{
QStringList groups;
QString group;
QString description = "";
for (int i = 0; i < ui->presetsTree->topLevelItemCount(); i++) {
groups.append(ui->presetsTree->topLevelItem(i)->text(0));
}
QTreeWidgetItem* item = ui->presetsTree->currentItem();
if (item)
{
if (item->type() == PGroup)
{
group = item->text(0);
}
else if (item->type() == PItem)
{
group = item->parent()->text(0);
description = item->text(0);
}
}
AddPresetDialog dlg(groups, group, this);
if (description.length() > 0) {
dlg.setDescription(description);
}
if (dlg.exec() == QDialog::Accepted)
{
FeatureSetPreset* preset = newFeatureSetPreset(dlg.group(), dlg.description());
savePresetSettings(preset);
ui->presetsTree->setCurrentItem(addPresetToTree(preset));
}
sortFeatureSetPresets();
}
void FeaturePresetsDialog::on_presetUpdate_clicked()
{
QTreeWidgetItem* item = ui->presetsTree->currentItem();
const FeatureSetPreset* changedPreset = nullptr;
if (item)
{
if( item->type() == PItem)
{
const FeatureSetPreset* preset = qvariant_cast<const FeatureSetPreset*>(item->data(0, Qt::UserRole));
if (preset)
{
FeatureSetPreset* preset_mod = const_cast<FeatureSetPreset*>(preset);
savePresetSettings(preset_mod);
changedPreset = preset;
}
}
}
sortFeatureSetPresets();
ui->presetsTree->clear();
for (int i = 0; i < m_featureSetPresets->size(); ++i)
{
QTreeWidgetItem *item_x = addPresetToTree(m_featureSetPresets->at(i));
const FeatureSetPreset* preset_x = qvariant_cast<const FeatureSetPreset*>(item_x->data(0, Qt::UserRole));
if (changedPreset && (preset_x == changedPreset)) { // set cursor on changed preset
ui->presetsTree->setCurrentItem(item_x);
}
}
}
void FeaturePresetsDialog::on_settingsSave_clicked()
{
}
void FeaturePresetsDialog::on_presetEdit_clicked()
{
QTreeWidgetItem* item = ui->presetsTree->currentItem();
QStringList groups;
bool change = false;
const FeatureSetPreset *changedPreset = nullptr;
QString newGroupName;
for (int i = 0; i < ui->presetsTree->topLevelItemCount(); i++) {
groups.append(ui->presetsTree->topLevelItem(i)->text(0));
}
if (item)
{
if (item->type() == PItem)
{
const FeatureSetPreset* preset = qvariant_cast<const FeatureSetPreset*>(item->data(0, Qt::UserRole));
AddPresetDialog dlg(groups, preset->getGroup(), this);
dlg.setDescription(preset->getDescription());
if (dlg.exec() == QDialog::Accepted)
{
FeatureSetPreset* preset_mod = const_cast<FeatureSetPreset*>(preset);
preset_mod->setGroup(dlg.group());
preset_mod->setDescription(dlg.description());
change = true;
changedPreset = preset;
}
}
else if (item->type() == PGroup)
{
AddPresetDialog dlg(groups, item->text(0), this);
dlg.showGroupOnly();
dlg.setDialogTitle("Edit preset group");
if (dlg.exec() == QDialog::Accepted)
{
renamePresetGroup(item->text(0), dlg.group());
newGroupName = dlg.group();
change = true;
}
}
}
if (change)
{
sortFeatureSetPresets();
ui->presetsTree->clear();
for (int i = 0; i < m_featureSetPresets->size(); ++i)
{
QTreeWidgetItem *item_x = addPresetToTree(m_featureSetPresets->at(i));
const FeatureSetPreset* preset_x = qvariant_cast<const FeatureSetPreset*>(item_x->data(0, Qt::UserRole));
if (changedPreset && (preset_x == changedPreset)) { // set cursor on changed preset
ui->presetsTree->setCurrentItem(item_x);
}
}
if (!changedPreset) // on group name change set cursor on the group that has been changed
{
for(int i = 0; i < ui->presetsTree->topLevelItemCount(); i++)
{
QTreeWidgetItem* item = ui->presetsTree->topLevelItem(i);
if (item->text(0) == newGroupName) {
ui->presetsTree->setCurrentItem(item);
}
}
}
}
}
void FeaturePresetsDialog::on_presetDelete_clicked()
{
QTreeWidgetItem* item = ui->presetsTree->currentItem();
if (item == 0)
{
updatePresetControls();
return;
}
else
{
if (item->type() == PItem)
{
const FeatureSetPreset* preset = qvariant_cast<const FeatureSetPreset*>(item->data(0, Qt::UserRole));
if (preset)
{
if(QMessageBox::question(this, tr("Delete Preset"), tr("Do you want to delete preset '%1'?").arg(preset->getDescription()), QMessageBox::No | QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
delete item;
deletePreset(preset);
}
}
}
else if (item->type() == PGroup)
{
if (QMessageBox::question(this,
tr("Delete preset group"),
tr("Do you want to delete preset group '%1'?")
.arg(item->text(0)), QMessageBox::No | QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
{
deletePresetGroup(item->text(0));
ui->presetsTree->clear();
for (int i = 0; i < m_featureSetPresets->size(); ++i) {
addPresetToTree(m_featureSetPresets->at(i));
}
}
}
}
}
void FeaturePresetsDialog::on_presetLoad_clicked()
{
qDebug() << "FeaturePresetsDialog::on_presetLoad_clicked";
QTreeWidgetItem* item = ui->presetsTree->currentItem();
if (!item)
{
qDebug("FeaturePresetsDialog::on_presetLoad_clicked: item null");
updatePresetControls();
return;
}
const FeatureSetPreset* preset = qvariant_cast<const FeatureSetPreset*>(item->data(0, Qt::UserRole));
if (!preset)
{
qDebug("FeatureSetPreset::on_presetLoad_clicked: preset null");
return;
}
loadPresetSettings(preset);
}
void FeaturePresetsDialog::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
(void) current;
(void) previous;
updatePresetControls();
}
void FeaturePresetsDialog::on_presetTree_itemActivated(QTreeWidgetItem *item, int column)
{
(void) item;
(void) column;
on_presetLoad_clicked();
}
FeatureSetPreset* FeaturePresetsDialog::newFeatureSetPreset(const QString& group, const QString& description)
{
FeatureSetPreset* preset = new FeatureSetPreset();
preset->setGroup(group);
preset->setDescription(description);
addFeatureSetPreset(preset);
return preset;
}
void FeaturePresetsDialog::addFeatureSetPreset(FeatureSetPreset *preset)
{
m_featureSetPresets->append(preset);
}
void FeaturePresetsDialog::savePresetSettings(FeatureSetPreset* preset)
{
qDebug("FeaturePresetsDialog::savePresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
preset->clearFeatures();
m_featureUISet->saveFeatureSetSettings(preset);
}
void FeaturePresetsDialog::loadPresetSettings(const FeatureSetPreset* preset)
{
qDebug("FeaturePresetsDialog::loadPresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
m_featureUISet->loadFeatureSetSettings(preset, m_pluginAPI, m_apiAdapter);
}
void FeaturePresetsDialog::sortFeatureSetPresets()
{
std::sort(m_featureSetPresets->begin(), m_featureSetPresets->end(), FeatureSetPreset::presetCompare);
}
void FeaturePresetsDialog::renamePresetGroup(const QString& oldGroupName, const QString& newGroupName)
{
for (int i = 0; i < m_featureSetPresets->size(); i++)
{
if (m_featureSetPresets->at(i)->getGroup() == oldGroupName)
{
FeatureSetPreset *preset_mod = const_cast<FeatureSetPreset*>(m_featureSetPresets->at(i));
preset_mod->setGroup(newGroupName);
}
}
}
void FeaturePresetsDialog::deletePreset(const FeatureSetPreset* preset)
{
m_featureSetPresets->removeAll((FeatureSetPreset*) preset);
delete (FeatureSetPreset*) preset;
}
void FeaturePresetsDialog::deletePresetGroup(const QString& groupName)
{
QList<FeatureSetPreset*>::iterator it = m_featureSetPresets->begin();
while (it != m_featureSetPresets->end())
{
if ((*it)->getGroup() == groupName) {
it = m_featureSetPresets->erase(it);
} else {
++it;
}
}
}

View File

@ -0,0 +1,82 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2020 F4EXB //
// written by Edouard Griffiths //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRGUI_GUI_FEATUREPRESETDIALOG_H_
#define SDRGUI_GUI_FEATUREPRESETDIALOG_H_
#include <QDialog>
#include <QList>
#include <QTreeWidgetItem>
#include "export.h"
class FeatureSetPreset;
class FeatureUISet;
class WebAPIAdapterInterface;
class PluginAPI;
namespace Ui {
class FeaturePresetsDialog;
}
class SDRGUI_API FeaturePresetsDialog : public QDialog {
Q_OBJECT
public:
explicit FeaturePresetsDialog(QWidget* parent = nullptr);
~FeaturePresetsDialog();
void setPresets(QList<FeatureSetPreset*>* presets) { m_featureSetPresets = presets; }
void setFeatureUISet(FeatureUISet *featureUISet) { m_featureUISet = featureUISet; }
void setPluginAPI(PluginAPI *pluginAPI) { m_pluginAPI = pluginAPI; }
void setWebAPIAdapter(WebAPIAdapterInterface *apiAdapter) { m_apiAdapter = apiAdapter; }
void populateTree();
private:
enum {
PGroup,
PItem
};
Ui::FeaturePresetsDialog* ui;
QList<FeatureSetPreset*> *m_featureSetPresets;
FeatureUISet *m_featureUISet;
PluginAPI *m_pluginAPI;
WebAPIAdapterInterface *m_apiAdapter;
QTreeWidgetItem* addPresetToTree(const FeatureSetPreset* preset);
void updatePresetControls();
FeatureSetPreset* newFeatureSetPreset(const QString& group, const QString& description);
void addFeatureSetPreset(FeatureSetPreset *preset);
void savePresetSettings(FeatureSetPreset* preset);
void loadPresetSettings(const FeatureSetPreset* preset);
void sortFeatureSetPresets();
void renamePresetGroup(const QString& oldGroupName, const QString& newGroupName);
void deletePreset(const FeatureSetPreset* preset);
void deletePresetGroup(const QString& groupName);
private slots:
void on_presetSave_clicked();
void on_presetUpdate_clicked();
void on_settingsSave_clicked();
void on_presetEdit_clicked();
void on_presetDelete_clicked();
void on_presetLoad_clicked();
void on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void on_presetTree_itemActivated(QTreeWidgetItem *item, int column);
};
#endif // SDRGUI_GUI_FEATUREPRESETDIALOG_H_

View File

@ -0,0 +1,261 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FeaturePresetsDialog</class>
<widget class="QDialog" name="FeaturePresetsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>392</width>
<height>414</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Feature presets</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>40</x>
<y>380</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>392</width>
<height>310</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="presetsTree">
<property name="indentation">
<number>5</number>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="columnCount">
<number>1</number>
</property>
<attribute name="headerMinimumSectionSize">
<number>5</number>
</attribute>
<column>
<property name="text">
<string>Description</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>330</y>
<width>392</width>
<height>34</height>
</rect>
</property>
<layout class="QHBoxLayout" name="presetsControl">
<item>
<widget class="QToolButton" name="presetSave">
<property name="toolTip">
<string>Save current settings as new preset</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/create.png</normaloff>:/create.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="presetUpdate">
<property name="toolTip">
<string>Update selected preset with current settings</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="settingsSave">
<property name="toolTip">
<string>Save the current settings (inc. presets)</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/save.png</normaloff>:/save.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="presetEdit">
<property name="toolTip">
<string>Edit preset details</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/edit.png</normaloff>:/edit.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="presetDelete">
<property name="toolTip">
<string>Delete selected preset</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="presetLoad">
<property name="toolTip">
<string>Load selected preset</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
<normaloff>:/load.png</normaloff>:/load.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="../resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FeaturePresetsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FeaturePresetsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -41,6 +41,12 @@ FeaturesDock::FeaturesDock(QWidget *parent, Qt::WindowFlags flags) :
m_addFeatureButton->setToolTip("Add features");
m_addFeatureButton->setFixedSize(16, 16);
m_presetsButton = new QPushButton();
QIcon presetsIcon(":/star.png");
m_presetsButton->setIcon(presetsIcon);
m_presetsButton->setToolTip("Feature presets");
m_presetsButton->setFixedSize(16, 16);
m_normalButton = new QPushButton();
QIcon normalIcon = style()->standardIcon(QStyle::SP_TitleBarNormalButton, 0, this);
m_normalButton->setIcon(normalIcon);
@ -52,6 +58,7 @@ FeaturesDock::FeaturesDock(QWidget *parent, Qt::WindowFlags flags) :
m_closeButton->setFixedSize(12, 12);
m_titleBarLayout->addWidget(m_addFeatureButton);
m_titleBarLayout->addWidget(m_presetsButton);
m_titleBarLayout->addWidget(m_titleLabel);
m_titleBarLayout->addWidget(m_normalButton);
m_titleBarLayout->addWidget(m_closeButton);
@ -64,6 +71,13 @@ FeaturesDock::FeaturesDock(QWidget *parent, Qt::WindowFlags flags) :
&FeaturesDock::addFeatureDialog
);
QObject::connect(
m_presetsButton,
&QPushButton::clicked,
this,
&FeaturesDock::presetsDialog
);
QObject::connect(
m_normalButton,
&QPushButton::clicked,
@ -99,7 +113,12 @@ void FeaturesDock::toggleFloating()
void FeaturesDock::addFeatureDialog()
{
m_featureAddDialog.exec();
}
void FeaturesDock::presetsDialog()
{
m_featurePresetsDialog.populateTree();
m_featurePresetsDialog.exec();
}
void FeaturesDock::addFeatureEmitted(int featureIndex)

View File

@ -22,6 +22,7 @@
#include <QDockWidget>
#include "featureadddialog.h"
#include "featurepresetsdialog.h"
class QHBoxLayout;
class QLabel;
@ -38,18 +39,26 @@ public:
void resetAvailableFeatures() { m_featureAddDialog.resetFeatureNames(); }
void addAvailableFeatures(const QStringList& featureNames) { m_featureAddDialog.addFeatureNames(featureNames); }
void setPresets(QList<FeatureSetPreset*>* presets) { m_featurePresetsDialog.setPresets(presets); }
void setFeatureUISet(FeatureUISet *featureUISet) { m_featurePresetsDialog.setFeatureUISet(featureUISet); }
void setPluginAPI(PluginAPI *pluginAPI) { m_featurePresetsDialog.setPluginAPI(pluginAPI); }
void setWebAPIAdapter(WebAPIAdapterInterface *apiAdapter) { m_featurePresetsDialog.setWebAPIAdapter(apiAdapter); }
private:
QPushButton *m_addFeatureButton;
QPushButton *m_presetsButton;
QWidget *m_titleBar;
QHBoxLayout *m_titleBarLayout;
QLabel *m_titleLabel;
QPushButton *m_normalButton;
QPushButton *m_closeButton;
FeatureAddDialog m_featureAddDialog;
FeaturePresetsDialog m_featurePresetsDialog;
private slots:
void toggleFloating();
void addFeatureDialog();
void presetsDialog();
void addFeatureEmitted(int featureIndex);
signals:

View File

@ -88,6 +88,9 @@
MESSAGE_CLASS_DEFINITION(MainWindow::MsgLoadPreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgSavePreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgDeletePreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgLoadFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgSaveFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgDeleteFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgAddDeviceSet, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgRemoveLastDeviceSet, Message)
MESSAGE_CLASS_DEFINITION(MainWindow::MsgSetDevice, Message)
@ -207,6 +210,9 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
m_pluginManager->listFeatures(featureNames);
ui->featureDock->addAvailableFeatures(featureNames);
addFeatureSet();
ui->featureDock->setFeatureUISet(m_featureUIs[0]);
ui->featureDock->setPresets(m_settings.getFeatureSetPresets());
ui->featureDock->setPluginAPI(m_pluginManager->getPluginAPI());
splash->showStatusMessage("load file input...", Qt::white);
qDebug() << "MainWindow::MainWindow: select SampleSource from settings or default (file input)...";
@ -220,6 +226,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
qDebug() << "MainWindow::MainWindow: load current preset settings...";
loadPresetSettings(m_settings.getWorkingPreset(), 0);
loadFeatureSetPresetSettings(m_settings.getWorkingFeatureSetPreset(), 0);
splash->showStatusMessage("update preset controls...", Qt::white);
qDebug() << "MainWindow::MainWindow: update preset controls...";
@ -244,6 +251,7 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse
#endif
m_apiAdapter = new WebAPIAdapterGUI(*this);
ui->featureDock->setWebAPIAdapter(m_apiAdapter);
m_requestMapper = new WebAPIRequestMapper(this);
m_requestMapper->setAdapter(m_apiAdapter);
m_apiHost = parser.getServerAddress();
@ -650,7 +658,7 @@ void MainWindow::loadSettings()
{
qDebug() << "MainWindow::loadSettings";
m_settings.load(m_pluginManager);
m_settings.load();
m_settings.sortPresets();
int middleIndex = m_settings.getPresetCount() / 2;
QTreeWidgetItem *treeItem;
@ -742,6 +750,33 @@ void MainWindow::savePresetSettings(Preset* preset, int tabIndex)
preset->setLayout(saveState());
}
void MainWindow::loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex)
{
qDebug("MainWindow::loadFeatureSetPresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
if (featureSetIndex >= 0)
{
FeatureUISet *featureSetUI = m_featureUIs[featureSetIndex];
featureSetUI->loadFeatureSetSettings(preset, m_pluginManager->getPluginAPI(), m_apiAdapter);
}
}
void MainWindow::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex)
{
qDebug("MainWindow::saveFeatureSetPresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
// Save from currently selected source tab
//int currentSourceTabIndex = ui->tabInputsView->currentIndex();
FeatureUISet *featureUI = m_featureUIs[featureSetIndex];
preset->clearFeatures();
featureUI->saveFeatureSetSettings(preset);
}
void MainWindow::saveCommandSettings()
{
}
@ -767,7 +802,8 @@ void MainWindow::closeEvent(QCloseEvent *closeEvent)
qDebug("MainWindow::closeEvent");
savePresetSettings(m_settings.getWorkingPreset(), 0);
m_settings.save(m_pluginManager);
saveFeatureSetPresetSettings(m_settings.getWorkingFeatureSetPreset(), 0);
m_settings.save();
while (m_deviceUIs.size() > 0)
{
@ -871,6 +907,7 @@ QTreeWidgetItem* MainWindow::addCommandToTree(const Command* command)
void MainWindow::applySettings()
{
loadPresetSettings(m_settings.getWorkingPreset(), 0);
loadFeatureSetPresetSettings(m_settings.getWorkingFeatureSetPreset(), 0);
m_settings.sortPresets();
int middleIndex = m_settings.getPresetCount() / 2;
@ -910,7 +947,21 @@ bool MainWindow::handleMessage(const Message& cmd)
savePresetSettings(notif.getPreset(), notif.getDeviceSetIndex());
if (notif.isNewPreset()) { ui->presetTree->setCurrentItem(addPresetToTree(notif.getPreset())); }
m_settings.sortPresets();
m_settings.save(m_pluginManager);
m_settings.save();
return true;
}
else if (MsgLoadFeatureSetPreset::match(cmd))
{
MsgLoadFeatureSetPreset& notif = (MsgLoadFeatureSetPreset&) cmd;
loadFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
return true;
}
else if (MsgSaveFeatureSetPreset::match(cmd))
{
MsgSaveFeatureSetPreset& notif = (MsgSaveFeatureSetPreset&) cmd;
saveFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
m_settings.sortFeatureSetPresets();
m_settings.save();
return true;
}
else if (MsgDeletePreset::match(cmd))
@ -1252,7 +1303,7 @@ void MainWindow::on_commandOutput_clicked()
void MainWindow::on_commandsSave_clicked()
{
saveCommandSettings();
m_settings.save(m_pluginManager);
m_settings.save();
}
void MainWindow::commandKeysConnect(QObject *object, const char *slot)
@ -1509,7 +1560,8 @@ void MainWindow::on_presetImport_clicked()
void MainWindow::on_settingsSave_clicked()
{
savePresetSettings(m_settings.getWorkingPreset(), ui->tabInputsView->currentIndex());
m_settings.save(m_pluginManager);
saveFeatureSetPresetSettings(m_settings.getWorkingFeatureSetPreset(), ui->tabFeatures->currentIndex());
m_settings.save();
}
void MainWindow::on_presetLoad_clicked()

View File

@ -52,6 +52,7 @@ class WebAPIServer;
class WebAPIAdapterGUI;
class Preset;
class Command;
class FeatureSetPreset;
class CommandKeyReceiver;
namespace qtwebapp {
@ -178,6 +179,75 @@ private:
{ }
};
class MsgLoadFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
const FeatureSetPreset *getPreset() const { return m_preset; }
int getFeatureSetIndex() const { return m_featureSetIndex; }
static MsgLoadFeatureSetPreset* create(const FeatureSetPreset *preset, int featureSetIndex)
{
return new MsgLoadFeatureSetPreset(preset, featureSetIndex);
}
private:
const FeatureSetPreset *m_preset;
int m_featureSetIndex;
MsgLoadFeatureSetPreset(const FeatureSetPreset *preset, int featureSetIndex) :
Message(),
m_preset(preset),
m_featureSetIndex(featureSetIndex)
{ }
};
class MsgSaveFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
FeatureSetPreset *getPreset() const { return m_preset; }
int getFeatureSetIndex() const { return m_featureSetIndex; }
bool isNewPreset() const { return m_newPreset; }
static MsgSaveFeatureSetPreset* create(FeatureSetPreset *preset, int featureSetIndex, bool newPreset)
{
return new MsgSaveFeatureSetPreset(preset, featureSetIndex, newPreset);
}
private:
FeatureSetPreset *m_preset;
int m_featureSetIndex;
bool m_newPreset;
MsgSaveFeatureSetPreset(FeatureSetPreset *preset, int featureSetIndex, bool newPreset) :
Message(),
m_preset(preset),
m_featureSetIndex(featureSetIndex),
m_newPreset(newPreset)
{ }
};
class MsgDeleteFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
const FeatureSetPreset *getPreset() const { return m_preset; }
static MsgDeleteFeatureSetPreset* create(const FeatureSetPreset *preset)
{
return new MsgDeleteFeatureSetPreset(preset);
}
private:
const FeatureSetPreset *m_preset;
MsgDeleteFeatureSetPreset(const FeatureSetPreset *preset) :
Message(),
m_preset(preset)
{ }
};
class MsgAddDeviceSet : public Message {
MESSAGE_CLASS_DECLARATION
@ -397,6 +467,8 @@ private:
void loadSettings();
void loadPresetSettings(const Preset* preset, int tabIndex);
void savePresetSettings(Preset* preset, int tabIndex);
void loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex);
void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex);
void saveCommandSettings();
void createStatusBar();

View File

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>star.png</file>
<file>swap.png</file>
<file>gridpolar.png</file>
<file>gridrect.png</file>

BIN
sdrgui/resources/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -145,6 +145,8 @@ int WebAPIAdapterGUI::instanceConfigGet(
WebAPIAdapterBase::webapiFormatPreferences(preferences, m_mainWindow.getMainSettings().getPreferences());
SWGSDRangel::SWGPreset *workingPreset = response.getWorkingPreset();
webAPIAdapterBase.webapiFormatPreset(workingPreset, m_mainWindow.getMainSettings().getWorkingPresetConst());
SWGSDRangel::SWGFeatureSetPreset *workingFeatureSetPreset = response.getWorkingFeatureSetPreset();
webAPIAdapterBase.webapiFormatFeatureSetPreset(workingFeatureSetPreset, m_mainWindow.getMainSettings().getWorkingFeatureSetPresetConst());
int nbPresets = m_mainWindow.m_settings.getPresetCount();
QList<SWGSDRangel::SWGPreset*> *swgPresets = response.getPresets();
@ -166,6 +168,16 @@ int WebAPIAdapterGUI::instanceConfigGet(
WebAPIAdapterBase::webapiFormatCommand(swgCommands->back(), *command);
}
int nbFeatureSetPresets = m_mainWindow.m_settings.getFeatureSetPresetCount();
QList<SWGSDRangel::SWGFeatureSetPreset*> *swgFeatureSetPresets = response.getFeaturesetpresets();
for (int i = 0; i < nbFeatureSetPresets; i++)
{
const FeatureSetPreset *preset = m_mainWindow.m_settings.getFeatureSetPreset(i);
swgFeatureSetPresets->append(new SWGSDRangel::SWGFeatureSetPreset);
webAPIAdapterBase.webapiFormatFeatureSetPreset(swgFeatureSetPresets->back(), *preset);
}
return 200;
}
@ -190,6 +202,9 @@ int WebAPIAdapterGUI::instanceConfigPutPatch(
Preset *workingPreset = m_mainWindow.m_settings.getWorkingPreset();
webAPIAdapterBase.webapiUpdatePreset(force, query.getWorkingPreset(), configKeys.m_workingPresetKeys, workingPreset);
FeatureSetPreset *workingFeatureSetPreset = m_mainWindow.m_settings.getWorkingFeatureSetPreset();
webAPIAdapterBase.webapiUpdateFeatureSetPreset(force, query.getWorkingFeatureSetPreset(), configKeys.m_workingFeatureSetPresetKeys, workingFeatureSetPreset);
QList<PresetKeys>::const_iterator presetKeysIt = configKeys.m_presetKeys.begin();
int i = 0;
for (; presetKeysIt != configKeys.m_presetKeys.end(); ++presetKeysIt, i++)
@ -210,6 +225,16 @@ int WebAPIAdapterGUI::instanceConfigPutPatch(
m_mainWindow.m_settings.addCommand(newCommand);
}
QList<FeatureSetPresetKeys>::const_iterator featureSetPresetKeysIt = configKeys.m_featureSetPresetKeys.begin();
i = 0;
for (; featureSetPresetKeysIt != configKeys.m_featureSetPresetKeys.end(); ++featureSetPresetKeysIt, i++)
{
FeatureSetPreset *newPreset = new FeatureSetPreset(); // created with default values
SWGSDRangel::SWGFeatureSetPreset *swgPreset = query.getFeaturesetpresets()->at(i);
webAPIAdapterBase.webapiUpdateFeatureSetPreset(force, swgPreset, *featureSetPresetKeysIt, newPreset);
m_mainWindow.m_settings.addFeatureSetPreset(newPreset);
}
MainWindow::MsgApplySettings *msg = MainWindow::MsgApplySettings::create();
m_mainWindow.m_inputMessageQueue.push(msg);

View File

@ -19,6 +19,9 @@
#include "plugin/pluginapi.h"
#include "feature/feature.h"
#include "feature/featureutils.h"
#include "settings/featuresetpreset.h"
#include "featureset.h"
FeatureSet::FeatureSet(int tabIndex)
@ -61,6 +64,16 @@ void FeatureSet::renameFeatureInstances()
}
}
// sort by name
bool FeatureSet::FeatureInstanceRegistration::operator<(const FeatureInstanceRegistration& other) const
{
if (m_feature && other.m_feature) {
return m_feature->getName() < other.m_feature->getName();
} else {
return false;
}
}
void FeatureSet::freeFeatures()
{
for(int i = 0; i < m_featureInstanceRegistrations.count(); i++)
@ -100,3 +113,64 @@ Feature *FeatureSet::getFeatureAt(int featureIndex)
return nullptr;
}
}
void FeatureSet::loadFeatureSetSettings(const FeatureSetPreset *preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter)
{
qDebug("FeatureSet::loadFeatureSetSettings: Loading preset [%s | %s]", qPrintable(preset->getGroup()), qPrintable(preset->getDescription()));
// Available feature plugins
PluginAPI::FeatureRegistrations *featureRegistrations = pluginAPI->getFeatureRegistrations();
// copy currently open features and clear list
FeatureInstanceRegistrations openFeatures = m_featureInstanceRegistrations;
m_featureInstanceRegistrations.clear();
for (int i = 0; i < openFeatures.count(); i++)
{
qDebug("FeatureSet::loadFeatureSetSettings: destroying old feature [%s]", qPrintable(openFeatures[i].m_featureName));
openFeatures[i].m_feature->destroy();
}
qDebug("FeatureSet::loadFeatureSetSettings: %d feature(s) in preset", preset->getFeatureCount());
for (int i = 0; i < preset->getFeatureCount(); i++)
{
const FeatureSetPreset::FeatureConfig& featureConfig = preset->getFeatureConfig(i);
FeatureInstanceRegistration reg;
// create feature instance
for(int i = 0; i < featureRegistrations->count(); i++)
{
if (FeatureUtils::compareFeatureURIs((*featureRegistrations)[i].m_featureIdURI, featureConfig.m_featureIdURI))
{
qDebug("FeatureSet::loadFeatureSetSettings: creating new feature [%s] from config [%s]",
qPrintable((*featureRegistrations)[i].m_featureIdURI),
qPrintable(featureConfig.m_featureIdURI));
Feature *feature =
(*featureRegistrations)[i].m_plugin->createFeature(apiAdapter);
reg = FeatureInstanceRegistration(featureConfig.m_featureIdURI, feature);
break;
}
}
if (reg.m_feature)
{
qDebug("FeatureSet::loadFeatureSetSettings: deserializing feature [%s]", qPrintable(featureConfig.m_featureIdURI));
reg.m_feature->deserialize(featureConfig.m_config);
}
}
renameFeatureInstances();
}
void FeatureSet::saveFeatureSetSettings(FeatureSetPreset *preset)
{
std::sort(m_featureInstanceRegistrations.begin(), m_featureInstanceRegistrations.end()); // sort by increasing delta frequency and type
for (int i = 0; i < m_featureInstanceRegistrations.count(); i++)
{
qDebug("FeatureSet::saveFeatureSetSettings: saving feature [%s]", qPrintable(m_featureInstanceRegistrations[i].m_featureName));
preset->addFeature(m_featureInstanceRegistrations[i].m_featureName, m_featureInstanceRegistrations[i].m_feature->serialize());
}
}

View File

@ -25,6 +25,7 @@
class PluginAPI;
class Feature;
class FeatureSetPreset;
class WebAPIAdapterInterface;
class SDRGUI_API FeatureSet
@ -40,6 +41,8 @@ public:
void deleteFeature(int featureIndex);
const Feature *getFeatureAt(int featureIndex) const;
Feature *getFeatureAt(int featureIndex);
void loadFeatureSetSettings(const FeatureSetPreset* preset, PluginAPI *pluginAPI, WebAPIAdapterInterface *apiAdapter);
void saveFeatureSetSettings(FeatureSetPreset* preset);
private:
struct FeatureInstanceRegistration

View File

@ -41,6 +41,9 @@ MESSAGE_CLASS_DEFINITION(MainCore::MsgDeleteInstance, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgLoadPreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgSavePreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgDeletePreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgLoadFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgSaveFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgDeleteFeatureSetPreset, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgAddDeviceSet, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgRemoveLastDeviceSet, Message)
MESSAGE_CLASS_DEFINITION(MainCore::MsgSetDevice, Message)
@ -102,7 +105,7 @@ MainCore::~MainCore()
}
m_apiServer->stop();
m_settings.save(m_pluginManager);
m_settings.save();
delete m_apiServer;
delete m_requestMapper;
delete m_apiAdapter;
@ -136,7 +139,7 @@ bool MainCore::handleMessage(const Message& cmd)
MsgSavePreset& notif = (MsgSavePreset&) cmd;
savePresetSettings(notif.getPreset(), notif.getDeviceSetIndex());
m_settings.sortPresets();
m_settings.save(m_pluginManager);
m_settings.save();
return true;
}
else if (MsgDeletePreset::match(cmd))
@ -147,6 +150,28 @@ bool MainCore::handleMessage(const Message& cmd)
m_settings.deletePreset(presetToDelete);
return true;
}
else if (MsgLoadFeatureSetPreset::match(cmd))
{
MsgLoadFeatureSetPreset& notif = (MsgLoadFeatureSetPreset&) cmd;
loadFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
return true;
}
else if (MsgSaveFeatureSetPreset::match(cmd))
{
MsgSaveFeatureSetPreset& notif = (MsgSaveFeatureSetPreset&) cmd;
saveFeatureSetPresetSettings(notif.getPreset(), notif.getFeatureSetIndex());
m_settings.sortPresets();
m_settings.save();
return true;
}
else if (MsgDeleteFeatureSetPreset::match(cmd))
{
MsgDeleteFeatureSetPreset& notif = (MsgDeleteFeatureSetPreset&) cmd;
const FeatureSetPreset *presetToDelete = notif.getPreset();
// remove preset from settings
m_settings.deleteFeatureSetPreset(presetToDelete);
return true;
}
else if (MsgAddDeviceSet::match(cmd))
{
MsgAddDeviceSet& notif = (MsgAddDeviceSet&) cmd;
@ -233,7 +258,7 @@ void MainCore::loadSettings()
{
qDebug() << "MainCore::loadSettings";
m_settings.load(m_pluginManager);
m_settings.load();
m_settings.sortPresets();
setLoggingOptions();
}
@ -733,3 +758,29 @@ void MainCore::savePresetSettings(Preset* preset, int tabIndex)
}
}
void MainCore::loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex)
{
qDebug("MainCore::loadFeatureSetPresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
if (featureSetIndex >= 0)
{
FeatureSet *featureSet = m_featureSets[featureSetIndex];
featureSet->loadFeatureSetSettings(preset, m_pluginManager->getPluginAPI(), m_apiAdapter);
}
}
void MainCore::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex)
{
qDebug("MainCore::saveFeatureSetPresetSettings: preset [%s | %s]",
qPrintable(preset->getGroup()),
qPrintable(preset->getDescription()));
// Save from currently selected source tab
//int currentSourceTabIndex = ui->tabInputsView->currentIndex();
FeatureSet *featureSet = m_featureSets[featureSetIndex];
preset->clearFeatures();
featureSet->saveFeatureSetSettings(preset);
}

View File

@ -149,6 +149,74 @@ private:
{ }
};
class MsgLoadFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
const FeatureSetPreset *getPreset() const { return m_preset; }
int getFeatureSetIndex() const { return m_featureSetIndex; }
static MsgLoadFeatureSetPreset* create(const FeatureSetPreset *preset, int featureSetIndex) {
return new MsgLoadFeatureSetPreset(preset, featureSetIndex);
}
private:
const FeatureSetPreset *m_preset;
int m_featureSetIndex;
MsgLoadFeatureSetPreset(const FeatureSetPreset *preset, int featureSetIndex) :
Message(),
m_preset(preset),
m_featureSetIndex(featureSetIndex)
{ }
};
class MsgSaveFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
FeatureSetPreset *getPreset() const { return m_preset; }
int getFeatureSetIndex() const { return m_featureSetIndex; }
bool isNewPreset() const { return m_newPreset; }
static MsgSaveFeatureSetPreset* create(FeatureSetPreset *preset, int featureSetIndex, bool newPreset)
{
return new MsgSaveFeatureSetPreset(preset, featureSetIndex, newPreset);
}
private:
FeatureSetPreset *m_preset;
int m_featureSetIndex;
bool m_newPreset;
MsgSaveFeatureSetPreset(FeatureSetPreset *preset, int featureSetIndex, bool newPreset) :
Message(),
m_preset(preset),
m_featureSetIndex(featureSetIndex),
m_newPreset(newPreset)
{ }
};
class MsgDeleteFeatureSetPreset : public Message {
MESSAGE_CLASS_DECLARATION
public:
const FeatureSetPreset *getPreset() const { return m_preset; }
static MsgDeleteFeatureSetPreset* create(const FeatureSetPreset *preset)
{
return new MsgDeleteFeatureSetPreset(preset);
}
private:
const FeatureSetPreset *m_preset;
MsgDeleteFeatureSetPreset(const FeatureSetPreset *preset) :
Message(),
m_preset(preset)
{ }
};
class MsgDeleteInstance : public Message {
MESSAGE_CLASS_DECLARATION
@ -356,6 +424,8 @@ private:
void applySettings();
void loadPresetSettings(const Preset* preset, int tabIndex);
void savePresetSettings(Preset* preset, int tabIndex);
void loadFeatureSetPresetSettings(const FeatureSetPreset* preset, int featureSetIndex);
void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex);
void setLoggingOptions();
bool handleMessage(const Message& cmd);

View File

@ -144,6 +144,8 @@ int WebAPIAdapterSrv::instanceConfigGet(
WebAPIAdapterBase::webapiFormatPreferences(preferences, m_mainCore.getMainSettings().getPreferences());
SWGSDRangel::SWGPreset *workingPreset = response.getWorkingPreset();
webAPIAdapterBase.webapiFormatPreset(workingPreset, m_mainCore.getMainSettings().getWorkingPresetConst());
SWGSDRangel::SWGFeatureSetPreset *workingFeatureSetPreset = response.getWorkingFeatureSetPreset();
webAPIAdapterBase.webapiFormatFeatureSetPreset(workingFeatureSetPreset, m_mainCore.getMainSettings().getWorkingFeatureSetPresetConst());
int nbPresets = m_mainCore.m_settings.getPresetCount();
QList<SWGSDRangel::SWGPreset*> *swgPresets = response.getPresets();
@ -165,6 +167,16 @@ int WebAPIAdapterSrv::instanceConfigGet(
WebAPIAdapterBase::webapiFormatCommand(swgCommands->back(), *command);
}
int nbFeatureSetPresets = m_mainCore.m_settings.getFeatureSetPresetCount();
QList<SWGSDRangel::SWGFeatureSetPreset*> *swgFeatureSetPresets = response.getFeaturesetpresets();
for (int i = 0; i < nbFeatureSetPresets; i++)
{
const FeatureSetPreset *preset = m_mainCore.m_settings.getFeatureSetPreset(i);
swgFeatureSetPresets->append(new SWGSDRangel::SWGFeatureSetPreset);
webAPIAdapterBase.webapiFormatFeatureSetPreset(swgFeatureSetPresets->back(), *preset);
}
return 200;
}
@ -189,6 +201,9 @@ int WebAPIAdapterSrv::instanceConfigPutPatch(
Preset *workingPreset = m_mainCore.m_settings.getWorkingPreset();
webAPIAdapterBase.webapiUpdatePreset(force, query.getWorkingPreset(), configKeys.m_workingPresetKeys, workingPreset);
FeatureSetPreset *workingFeatureSetPreset = m_mainCore.m_settings.getWorkingFeatureSetPreset();
webAPIAdapterBase.webapiUpdateFeatureSetPreset(force, query.getWorkingFeatureSetPreset(), configKeys.m_workingFeatureSetPresetKeys, workingFeatureSetPreset);
QList<PresetKeys>::const_iterator presetKeysIt = configKeys.m_presetKeys.begin();
int i = 0;
for (; presetKeysIt != configKeys.m_presetKeys.end(); ++presetKeysIt, i++)
@ -209,6 +224,16 @@ int WebAPIAdapterSrv::instanceConfigPutPatch(
m_mainCore.m_settings.addCommand(newCommand);
}
QList<FeatureSetPresetKeys>::const_iterator featureSetPresetKeysIt = configKeys.m_featureSetPresetKeys.begin();
i = 0;
for (; featureSetPresetKeysIt != configKeys.m_featureSetPresetKeys.end(); ++featureSetPresetKeysIt, i++)
{
FeatureSetPreset *newPreset = new FeatureSetPreset(); // created with default values
SWGSDRangel::SWGFeatureSetPreset *swgPreset = query.getFeaturesetpresets()->at(i);
webAPIAdapterBase.webapiUpdateFeatureSetPreset(force, swgPreset, *featureSetPresetKeysIt, newPreset);
m_mainCore.m_settings.addFeatureSetPreset(newPreset);
}
MainCore::MsgApplySettings *msg = MainCore::MsgApplySettings::create();
m_mainCore.m_inputMessageQueue.push(msg);