diff --git a/core/include/Data/ArrayData.h b/core/include/Data/ArrayData.h new file mode 100644 index 0000000..b08f0c2 --- /dev/null +++ b/core/include/Data/ArrayData.h @@ -0,0 +1,56 @@ +#ifndef SCIQLOP_ARRAYDATA_H +#define SCIQLOP_ARRAYDATA_H + +#include + +/** + * @brief The ArrayData class represents a dataset for a data series. + * + * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim + * template-parameter. + * + * @tparam Dim the dimension of the ArrayData (one or two) + * @sa IDataSeries + */ +template +class ArrayData { +public: + /** + * Ctor for a unidimensional ArrayData + * @param nbColumns the number of values the ArrayData will hold + */ + template > + explicit ArrayData(int nbColumns) : m_Data{1, QVector{}} + { + m_Data[0].resize(nbColumns); + } + + /** + * Sets a data at a specified index. The index has to be valid to be effective + * @param index the index to which the data will be set + * @param data the data to set + * @remarks this method is only available for a unidimensional ArrayData + */ + template > + void setData(int index, double data) noexcept + { + if (index >= 0 && index < m_Data.at(0).size()) { + m_Data[0].replace(index, data); + } + } + + /** + * @return the data as a vector + * @remarks this method is only available for a unidimensional ArrayData + */ + template > + QVector data() const noexcept + { + return m_Data.at(0); + } + +private: + QVector > m_Data; +}; + +#endif // SCIQLOP_ARRAYDATA_H diff --git a/core/include/Data/DataProviderParameters.h b/core/include/Data/DataProviderParameters.h new file mode 100644 index 0000000..496f171 --- /dev/null +++ b/core/include/Data/DataProviderParameters.h @@ -0,0 +1,16 @@ +#ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H +#define SCIQLOP_DATAPROVIDERPARAMETERS_H + +/** + * @brief The DataProviderParameters struct holds the information needed to retrieve data from a + * data provider + * @sa IDataProvider + */ +struct DataProviderParameters { + /// Start time + double m_TStart; + /// End time + double m_TEnd; +}; + +#endif // SCIQLOP_DATAPROVIDERPARAMETERS_H diff --git a/core/include/Data/DataSeries.h b/core/include/Data/DataSeries.h new file mode 100644 index 0000000..f4315f0 --- /dev/null +++ b/core/include/Data/DataSeries.h @@ -0,0 +1,50 @@ +#ifndef SCIQLOP_DATASERIES_H +#define SCIQLOP_DATASERIES_H + +#include +#include + +#include + +/** + * @brief The DataSeries class is the base (abstract) implementation of IDataSeries. + * + * It proposes to set a dimension for the values ​​data + * + * @tparam Dim The dimension of the values data + * + */ +template +class DataSeries : public IDataSeries { +public: + /// @sa IDataSeries::xAxisData() + std::shared_ptr > xAxisData() override { return m_XAxisData; } + + /// @sa IDataSeries::xAxisUnit() + QString xAxisUnit() const override { return m_XAxisUnit; } + + /// @return the values dataset + std::shared_ptr > valuesData() const { return m_ValuesData; } + + /// @sa IDataSeries::valuesUnit() + QString valuesUnit() const override { return m_ValuesUnit; } + +protected: + /// Protected ctor (DataSeries is abstract) + explicit DataSeries(std::shared_ptr > xAxisData, const QString &xAxisUnit, + std::shared_ptr > valuesData, const QString &valuesUnit) + : m_XAxisData{xAxisData}, + m_XAxisUnit{xAxisUnit}, + m_ValuesData{valuesData}, + m_ValuesUnit{valuesUnit} + { + } + +private: + std::shared_ptr > m_XAxisData; + QString m_XAxisUnit; + std::shared_ptr > m_ValuesData; + QString m_ValuesUnit; +}; + +#endif // SCIQLOP_DATASERIES_H diff --git a/core/include/Data/IDataProvider.h b/core/include/Data/IDataProvider.h new file mode 100644 index 0000000..0b83f2b --- /dev/null +++ b/core/include/Data/IDataProvider.h @@ -0,0 +1,25 @@ +#ifndef SCIQLOP_IDATAPROVIDER_H +#define SCIQLOP_IDATAPROVIDER_H + +#include + +class DataProviderParameters; +class IDataSeries; + +/** + * @brief The IDataProvider interface aims to declare a data provider. + * + * A data provider is an entity that generates data and returns it according to various parameters + * (time interval, product to retrieve the data, etc.) + * + * @sa IDataSeries + */ +class IDataProvider { +public: + virtual ~IDataProvider() noexcept = default; + + virtual std::unique_ptr + retrieveData(const DataProviderParameters ¶meters) const = 0; +}; + +#endif // SCIQLOP_IDATAPROVIDER_H diff --git a/core/include/Data/IDataSeries.h b/core/include/Data/IDataSeries.h new file mode 100644 index 0000000..0278a8e --- /dev/null +++ b/core/include/Data/IDataSeries.h @@ -0,0 +1,37 @@ +#ifndef SCIQLOP_IDATASERIES_H +#define SCIQLOP_IDATASERIES_H + +#include + +#include + +template +class ArrayData; + +/** + * @brief The IDataSeries aims to declare a data series. + * + * A data series is an entity that contains at least : + * - one dataset representing the x-axis + * - one dataset representing the values + * + * Each dataset is represented by an ArrayData, and is associated with a unit. + * + * An ArrayData can be unidimensional or two-dimensional, depending on the implementation of the + * IDataSeries. The x-axis dataset is always unidimensional. + * + * @sa ArrayData + */ +class IDataSeries { +public: + virtual ~IDataSeries() noexcept = default; + + /// Returns the x-axis dataset + virtual std::shared_ptr > xAxisData() = 0; + + virtual QString xAxisUnit() const = 0; + + virtual QString valuesUnit() const = 0; +}; + +#endif // SCIQLOP_IDATASERIES_H diff --git a/core/include/Data/ScalarSeries.h b/core/include/Data/ScalarSeries.h new file mode 100644 index 0000000..5dd39b0 --- /dev/null +++ b/core/include/Data/ScalarSeries.h @@ -0,0 +1,28 @@ +#ifndef SCIQLOP_SCALARSERIES_H +#define SCIQLOP_SCALARSERIES_H + +#include + +/** + * @brief The ScalarSeries class is the implementation for a data series representing a scalar. + */ +class ScalarSeries : public DataSeries<1> { +public: + /** + * Ctor + * @param size the number of data the series will hold + * @param xAxisUnit x-axis unit + * @param valuesUnit values unit + */ + explicit ScalarSeries(int size, const QString &xAxisUnit, const QString &valuesUnit); + + /** + * Sets data for a specific index. The index has to be valid to be effective + * @param index the index to which the data will be set + * @param x the x-axis data + * @param value the value data + */ + void setData(int index, double x, double value) noexcept; +}; + +#endif // SCIQLOP_SCALARSERIES_H diff --git a/core/include/DataSource/DataSourceController.h b/core/include/DataSource/DataSourceController.h index 6d3df61..13c2192 100644 --- a/core/include/DataSource/DataSourceController.h +++ b/core/include/DataSource/DataSourceController.h @@ -10,6 +10,7 @@ Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController) class DataSourceItem; +class IDataProvider; /** * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This @@ -42,6 +43,17 @@ public: void setDataSourceItem(const QUuid &dataSourceUid, std::unique_ptr dataSourceItem) noexcept; + /** + * Sets the data provider used to retrieve data from of a data source. The controller takes + * ownership of the provider. + * @param dataSourceUid the unique id with which the data source has been registered into the + * controller. If it is invalid, the method has no effect. + * @param dataProvider the provider of the data source + * @sa registerDataSource() + */ + void setDataProvider(const QUuid &dataSourceUid, + std::unique_ptr dataProvider) noexcept; + public slots: /// Manage init/end of the controller void initialize(); diff --git a/core/src/Data/ScalarSeries.cpp b/core/src/Data/ScalarSeries.cpp new file mode 100644 index 0000000..f3f4fc2 --- /dev/null +++ b/core/src/Data/ScalarSeries.cpp @@ -0,0 +1,13 @@ +#include + +ScalarSeries::ScalarSeries(int size, const QString &xAxisUnit, const QString &valuesUnit) + : DataSeries{std::make_shared >(size), xAxisUnit, + std::make_shared >(size), valuesUnit} +{ +} + +void ScalarSeries::setData(int index, double x, double value) noexcept +{ + xAxisData()->setData(index, x); + valuesData()->setData(index, value); +} diff --git a/core/src/DataSource/DataSourceController.cpp b/core/src/DataSource/DataSourceController.cpp index c8066c1..aeed99e 100644 --- a/core/src/DataSource/DataSourceController.cpp +++ b/core/src/DataSource/DataSourceController.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include #include @@ -16,6 +18,8 @@ public: QHash m_DataSources; /// Data sources structures std::map > m_DataSourceItems; + /// Data providers registered + std::map > m_DataProviders; }; DataSourceController::DataSourceController(QObject *parent) @@ -59,6 +63,19 @@ void DataSourceController::setDataSourceItem( } } +void DataSourceController::setDataProvider(const QUuid &dataSourceUid, + std::unique_ptr dataProvider) noexcept +{ + if (impl->m_DataSources.contains(dataSourceUid)) { + impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider))); + } + else { + qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data " + "source has been registered with the uid") + .arg(dataSourceUid.toString()); + } +} + void DataSourceController::initialize() { qCDebug(LOG_DataSourceController()) << tr("DataSourceController init") diff --git a/core/vera-exclusions/exclusions.txt b/core/vera-exclusions/exclusions.txt index 7b0007c..d4b3912 100644 --- a/core/vera-exclusions/exclusions.txt +++ b/core/vera-exclusions/exclusions.txt @@ -4,3 +4,7 @@ Common/spimpl\.h:\d+:.* # Ignore false positive relative to two class definitions in a same file DataSourceItem\.h:\d+:.*IPSIS_S01.* +# Ignore false positive relative to a template class +ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (D) +ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim) diff --git a/plugins/mockplugin/include/CosinusProvider.h b/plugins/mockplugin/include/CosinusProvider.h new file mode 100644 index 0000000..cc48a53 --- /dev/null +++ b/plugins/mockplugin/include/CosinusProvider.h @@ -0,0 +1,16 @@ +#ifndef SCIQLOP_COSINUSPROVIDER_H +#define SCIQLOP_COSINUSPROVIDER_H + +#include + +/** + * @brief The CosinusProvider class is an example of how a data provider can generate data + */ +class CosinusProvider : public IDataProvider { +public: + /// @sa IDataProvider::retrieveData() + std::unique_ptr + retrieveData(const DataProviderParameters ¶meters) const override; +}; + +#endif // SCIQLOP_COSINUSPROVIDER_H diff --git a/plugins/mockplugin/include/MockPlugin.h b/plugins/mockplugin/include/MockPlugin.h index 7d18987..889705e 100644 --- a/plugins/mockplugin/include/MockPlugin.h +++ b/plugins/mockplugin/include/MockPlugin.h @@ -18,10 +18,6 @@ class MockPlugin : public QObject, public IPlugin { public: /// @sa IPlugin::initialize() void initialize() override; - -private: - /// Creates the data source item relative to the plugin - std::unique_ptr createDataSourceItem() const noexcept; }; #endif // SCIQLOP_MOCKPLUGIN_H diff --git a/plugins/mockplugin/src/CosinusProvider.cpp b/plugins/mockplugin/src/CosinusProvider.cpp new file mode 100644 index 0000000..b6e4e12 --- /dev/null +++ b/plugins/mockplugin/src/CosinusProvider.cpp @@ -0,0 +1,28 @@ +#include "CosinusProvider.h" + +#include +#include + +std::unique_ptr +CosinusProvider::retrieveData(const DataProviderParameters ¶meters) const +{ + // Gets the timerange from the parameters + auto start = parameters.m_TStart; + auto end = parameters.m_TEnd; + + // We assure that timerange is valid + if (end < start) { + std::swap(start, end); + } + + // Generates scalar series containing cosinus values (one value per second) + auto scalarSeries + = std::make_unique(end - start, QStringLiteral("t"), QStringLiteral("")); + + for (auto time = start; time < end; ++time) { + auto dataIndex = time - start; + scalarSeries->setData(dataIndex, time, std::cos(time)); + } + + return scalarSeries; +} diff --git a/plugins/mockplugin/src/MockPlugin.cpp b/plugins/mockplugin/src/MockPlugin.cpp index 599ad04..526a2fc 100644 --- a/plugins/mockplugin/src/MockPlugin.cpp +++ b/plugins/mockplugin/src/MockPlugin.cpp @@ -1,4 +1,5 @@ -#include +#include "MockPlugin.h" +#include "CosinusProvider.h" #include #include @@ -12,23 +13,14 @@ namespace { /// Name of the data source const auto DATA_SOURCE_NAME = QStringLiteral("MMS"); -} // namespace - -void MockPlugin::initialize() +/// Creates the data provider relative to the plugin +std::unique_ptr createDataProvider() noexcept { - if (auto app = sqpApp) { - // Registers to the data source controller - auto &dataSourceController = app->dataSourceController(); - auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME); - - dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem()); - } - else { - qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application"); - } + return std::make_unique(); } -std::unique_ptr MockPlugin::createDataSourceItem() const noexcept +/// Creates the data source item relative to the plugin +std::unique_ptr createDataSourceItem() noexcept { // Magnetic field products auto fgmProduct = std::make_unique(DataSourceItemType::PRODUCT, @@ -51,5 +43,25 @@ std::unique_ptr MockPlugin::createDataSourceItem() const noexcep root->appendChild(std::move(magneticFieldFolder)); root->appendChild(std::move(electricFieldFolder)); - return std::move(root); + return root; +} + +} // namespace + +void MockPlugin::initialize() +{ + if (auto app = sqpApp) { + // Registers to the data source controller + auto &dataSourceController = app->dataSourceController(); + auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME); + + // Sets data source tree + dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem()); + + // Sets data provider + dataSourceController.setDataProvider(dataSourceUid, createDataProvider()); + } + else { + qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application"); + } }