diff --git a/app/src/MainWindow.cpp b/app/src/MainWindow.cpp index e9ecc3b..4e11f1c 100644 --- a/app/src/MainWindow.cpp +++ b/app/src/MainWindow.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include //#include @@ -75,89 +77,96 @@ MainWindow::MainWindow(QWidget *parent) m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); - // NOTE: These lambda could be factorized. Be careful of theirs parameters - // Lambda that defines what's happened when clicking on the leftSidePaneInspector open button - auto openLeftInspector = [this](bool checked) { - // Update of the last opened geometry - if (checked) { - impl->m_LastOpenLeftInspectorSize = m_Ui->leftMainInspectorWidget->size(); - } + auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane(); + auto openLeftInspectorAction = new QAction{QIcon{ + ":/icones/previous.png", + }, + tr("Show/hide the left inspector"), this}; - auto startSize = impl->m_LastOpenLeftInspectorSize; - auto endSize = startSize; - endSize.setWidth(0); - auto currentSizes = m_Ui->splitter->sizes(); - if (checked) { - // adjust sizes individually here, e.g. - currentSizes[LEFTMAININSPECTORWIDGETSPLITTERINDEX] - -= impl->m_LastOpenLeftInspectorSize.width(); - currentSizes[VIEWPLITTERINDEX] += impl->m_LastOpenLeftInspectorSize.width(); - m_Ui->splitter->setSizes(currentSizes); - } - else { - // adjust sizes individually here, e.g. - currentSizes[LEFTMAININSPECTORWIDGETSPLITTERINDEX] - += impl->m_LastOpenLeftInspectorSize.width(); - currentSizes[VIEWPLITTERINDEX] -= impl->m_LastOpenLeftInspectorSize.width(); - m_Ui->splitter->setSizes(currentSizes); - } + auto spacerLeftTop = new QWidget{}; + spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - }; + auto spacerLeftBottom = new QWidget{}; + spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + leftSidePane->addWidget(spacerLeftTop); + leftSidePane->addAction(openLeftInspectorAction); + leftSidePane->addWidget(spacerLeftBottom); + + + auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane(); + auto openRightInspectorAction = new QAction{QIcon{ + ":/icones/next.png", + }, + tr("Show/hide the right inspector"), this}; + + auto spacerRightTop = new QWidget{}; + spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + auto spacerRightBottom = new QWidget{}; + spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + rightSidePane->addWidget(spacerRightTop); + rightSidePane->addAction(openRightInspectorAction); + rightSidePane->addWidget(spacerRightBottom); + + openLeftInspectorAction->setCheckable(true); + openRightInspectorAction->setCheckable(true); + + auto openInspector = [this](bool checked, bool right, auto action) { + + action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"}); - // Lambda that defines what's happened when clicking on the SidePaneInspector open button - auto openRightInspector = [this](bool checked) { + auto &lastInspectorSize + = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; + + auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() + : m_Ui->leftMainInspectorWidget->size(); // Update of the last opened geometry if (checked) { - impl->m_LastOpenRightInspectorSize = m_Ui->rightMainInspectorWidget->size(); + lastInspectorSize = nextInspectorSize; } - auto startSize = impl->m_LastOpenRightInspectorSize; + auto startSize = lastInspectorSize; auto endSize = startSize; endSize.setWidth(0); + auto splitterInspectorIndex + = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; + auto currentSizes = m_Ui->splitter->sizes(); if (checked) { // adjust sizes individually here, e.g. - currentSizes[RIGHTMAININSPECTORWIDGETSPLITTERINDEX] - -= impl->m_LastOpenRightInspectorSize.width(); - currentSizes[VIEWPLITTERINDEX] += impl->m_LastOpenRightInspectorSize.width(); + currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); + currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); m_Ui->splitter->setSizes(currentSizes); } else { // adjust sizes individually here, e.g. - currentSizes[RIGHTMAININSPECTORWIDGETSPLITTERINDEX] - += impl->m_LastOpenRightInspectorSize.width(); - currentSizes[VIEWPLITTERINDEX] -= impl->m_LastOpenRightInspectorSize.width(); + currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); + currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); m_Ui->splitter->setSizes(currentSizes); } }; - QToolBar *leftSidePane = m_Ui->leftInspectorSidePane->sidePane(); - auto openLeftInspectorAction = leftSidePane->addAction( - QIcon{ - ":/icones/openInspector.png", - }, - tr("Show/hide the left inspector"), openLeftInspector); - - openLeftInspectorAction->setCheckable(true); - - auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane(); - auto openRightInspectorAction = rightSidePane->addAction( - QIcon{ - ":/icones/openInspector.png", - }, - tr("Show/hide the right inspector"), openRightInspector); - - openRightInspectorAction->setCheckable(true); + connect(openLeftInspectorAction, &QAction::triggered, + [openInspector, openLeftInspectorAction](bool checked) { + openInspector(checked, false, openLeftInspectorAction); + }); + connect(openRightInspectorAction, &QAction::triggered, + [openInspector, openRightInspectorAction](bool checked) { + openInspector(checked, true, openRightInspectorAction); + }); this->menuBar()->addAction(tr("File")); auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); - mainToolBar->addAction(QStringLiteral("A1")); + + mainToolBar->addWidget(new TimeWidget{}); // Widgets / controllers connections connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)), 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/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index bfeefc6..007c5c0 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -19,14 +19,14 @@ struct VariableController::VariableControllerPrivate { VariableController::VariableController(QObject *parent) : QObject{parent}, impl{spimpl::make_unique_impl()} { - qCDebug(LOG_VariableController()) - << tr("VariableController construction") << QThread::currentThread(); + qCDebug(LOG_VariableController()) << tr("VariableController construction") + << QThread::currentThread(); } VariableController::~VariableController() { - qCDebug(LOG_VariableController()) - << tr("VariableController destruction") << QThread::currentThread(); + qCDebug(LOG_VariableController()) << tr("VariableController destruction") + << QThread::currentThread(); this->waitForFinish(); } 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/gui/include/TimeWidget/TimeWidget.h b/gui/include/TimeWidget/TimeWidget.h new file mode 100644 index 0000000..014bea1 --- /dev/null +++ b/gui/include/TimeWidget/TimeWidget.h @@ -0,0 +1,21 @@ +#ifndef SCIQLOP_TIMEWIDGET_H +#define SCIQLOP_TIMEWIDGET_H + +#include + +namespace Ui { +class TimeWidget; +} // Ui + +class TimeWidget : public QWidget { + Q_OBJECT + +public: + explicit TimeWidget(QWidget *parent = 0); + virtual ~TimeWidget(); + +private: + Ui::TimeWidget *ui; +}; + +#endif // SCIQLOP_ SQPSIDEPANE_H diff --git a/gui/resources/icones/next.png b/gui/resources/icones/next.png new file mode 100644 index 0000000000000000000000000000000000000000..b70248b705e281885153a05ade514e565a13560b GIT binary patch literal 4413 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 literal 0 Hc$@?U+#X$GB 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 literal 0 Hc$@ icones/openInspector.png + icones/next.png + icones/previous.png diff --git a/gui/src/SidePane/SqpSidePane.cpp b/gui/src/SidePane/SqpSidePane.cpp index 72e6ea9..ac7494f 100644 --- a/gui/src/SidePane/SqpSidePane.cpp +++ b/gui/src/SidePane/SqpSidePane.cpp @@ -34,13 +34,6 @@ SqpSidePane::SqpSidePane(QWidget *parent) : QWidget{parent}, ui{new Ui::SqpSideP this->layout()->addWidget(m_SidePaneToolbar); m_SidePaneToolbar->setStyleSheet(SQPSIDEPANESTYLESHEET); - - this->setStyleSheet( - " QWidget {" - "background: red;" - - "border: 1px;" - " }"); } SqpSidePane::~SqpSidePane() diff --git a/gui/src/TimeWidget/TimeWidget.cpp b/gui/src/TimeWidget/TimeWidget.cpp new file mode 100644 index 0000000..69cdd16 --- /dev/null +++ b/gui/src/TimeWidget/TimeWidget.cpp @@ -0,0 +1,12 @@ +#include "TimeWidget/TimeWidget.h" +#include "ui_TimeWidget.h" + +TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget} +{ + ui->setupUi(this); +} + +TimeWidget::~TimeWidget() +{ + delete ui; +} diff --git a/gui/ui/Sidepane/SqpSidePane.ui b/gui/ui/SidePane/SqpSidePane.ui similarity index 100% rename from gui/ui/Sidepane/SqpSidePane.ui rename to gui/ui/SidePane/SqpSidePane.ui diff --git a/gui/ui/TimeWidget/TimeWidget.ui b/gui/ui/TimeWidget/TimeWidget.ui new file mode 100644 index 0000000..67cc2c2 --- /dev/null +++ b/gui/ui/TimeWidget/TimeWidget.ui @@ -0,0 +1,85 @@ + + + TimeWidget + + + + 0 + 0 + 716 + 48 + + + + + 0 + 0 + + + + Form + + + + + + + 0 + 0 + + + + TStart : + + + + + + + + 0 + 0 + + + + dd/MM/yyyy HH:mm:ss:zzz + + + true + + + + + + + + 0 + 0 + + + + TEnd : + + + + + + + + 0 + 0 + + + + dd/MM/yyyy HH:mm:ss:zzz + + + true + + + + + + + + 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..8240f30 --- /dev/null +++ b/plugins/mockplugin/src/CosinusProvider.cpp @@ -0,0 +1,30 @@ +#include "CosinusProvider.h" + +#include +#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("")); + + auto dataIndex = 0; + for (auto time = start; time < end; ++time, ++dataIndex) { + 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"); + } }