diff --git a/CMakeLists.txt b/CMakeLists.txt index de29f99..3ee82ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ FILE (GLOB_RECURSE core_SRCS ./include/Common/Numeric.h ./include/Common/deprecate.h ./include/Common/containers.h + ./include/Common/debug.h ./include/Plugin/IPlugin.h ./include/Data/ArrayDataIterator.h ./include/Data/VariableRequest.h diff --git a/include/Common/debug.h b/include/Common/debug.h new file mode 100644 index 0000000..059649f --- /dev/null +++ b/include/Common/debug.h @@ -0,0 +1,9 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef SCIQLOP_CRASH_ON_ERROR + #define SCIQLOP_ERROR(x) assert(false) +#else + #define SCIQLOP_ERROR(x) +#endif +#endif diff --git a/include/Data/IDataProvider.h b/include/Data/IDataProvider.h index 1535e40..ba4e869 100644 --- a/include/Data/IDataProvider.h +++ b/include/Data/IDataProvider.h @@ -46,7 +46,12 @@ public: = 0; ) - virtual QUuid getData(const DataProviderParameters ¶meters){return QUuid::createUuid();} + // Synchronous call -> asyncGetData may be written for asynchronous get + virtual IDataSeries* getData(const DataProviderParameters ¶meters) + { + Q_UNUSED(parameters); + return nullptr; + } DEPRECATE( @@ -56,7 +61,7 @@ public: virtual void requestDataAborting(QUuid acqIdentifier) = 0; ) - virtual void abort(QUuid requestID){} + virtual void abort(QUuid requestID){Q_UNUSED(requestID);} signals: DEPRECATE( diff --git a/include/Variable/Variable.h b/include/Variable/Variable.h index 30fc2a3..ef0cdf5 100644 --- a/include/Variable/Variable.h +++ b/include/Variable/Variable.h @@ -9,7 +9,9 @@ #include #include +#include +#include #include #include @@ -70,7 +72,10 @@ public: QVector provideNotInCacheRangeList(const DateTimeRange &range) const noexcept; QVector provideInCacheRangeList(const DateTimeRange &range) const noexcept; +DEPRECATE( void mergeDataSeries(std::shared_ptr dataSeries) noexcept; + ) + void mergeDataSeries(IDataSeries* dataSeries) noexcept; static QVector provideNotInCacheRangeList(const DateTimeRange &oldRange, const DateTimeRange &nextRange); @@ -78,6 +83,7 @@ public: static QVector provideInCacheRangeList(const DateTimeRange &oldRange, const DateTimeRange &nextRange); + QUuid ID(){return _uuid;} signals: void updated(); /// Signal emitted when when the data series of the variable is loaded for the first time @@ -86,6 +92,7 @@ signals: private: class VariablePrivate; spimpl::unique_impl_ptr impl; + QUuid _uuid; }; // Required for using shared_ptr in signals/slots diff --git a/include/Variable/VariableController2.h b/include/Variable/VariableController2.h index 2352aa3..a11f4ac 100644 --- a/include/Variable/VariableController2.h +++ b/include/Variable/VariableController2.h @@ -1,26 +1,36 @@ -#include #include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include "Data/DateTimeRange.h" -#include -#include -#include -class VariableController2Private; -class VariableController2 +class VariableController2: public QObject { + class VariableController2Private; + Q_OBJECT + spimpl::unique_impl_ptr impl; public: explicit VariableController2(); std::shared_ptr createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr provider, const DateTimeRange &range); - void changeRange(QUuid variable, DateTimeRange r); - void asyncChangeRange(QUuid variable, DateTimeRange r); + + void deleteVariable(std::shared_ptr variable); + void changeRange(std::shared_ptr variable, DateTimeRange r); + void asyncChangeRange(std::shared_ptr variable, DateTimeRange r); + const std::set > &variables(); + +signals: + void variableAdded(std::shared_ptr); + void variableDeleted(std::shared_ptr); }; diff --git a/src/Variable/Variable.cpp b/src/Variable/Variable.cpp index 036e244..06b5397 100644 --- a/src/Variable/Variable.cpp +++ b/src/Variable/Variable.cpp @@ -6,6 +6,7 @@ #include #include #include +#include Q_LOGGING_CATEGORY(LOG_Variable, "Variable") @@ -106,12 +107,14 @@ struct Variable::VariablePrivate { }; Variable::Variable(const QString &name, const QVariantHash &metadata) - : impl{spimpl::make_unique_impl(name, metadata)} + : impl{spimpl::make_unique_impl(name, metadata)}, + _uuid{QUuid::createUuid()} { } Variable::Variable(const Variable &other) - : impl{spimpl::make_unique_impl(*other.impl)} + : impl{spimpl::make_unique_impl(*other.impl)}, + _uuid{QUuid::createUuid()} //is a clone but must have a != uuid { } @@ -206,6 +209,34 @@ void Variable::mergeDataSeries(std::shared_ptr dataSeries) noexcept } } +void Variable::mergeDataSeries(IDataSeries *dataSeries) noexcept +{ + if (dataSeries==nullptr) { + SCIQLOP_ERROR("Given IDataSeries is nullptr"); + return; + } + + auto dataInit = false; + // @TODO move to impl to Pimpl this is what it stands for... + // Add or merge the data + impl->lockWrite(); + if (!impl->m_DataSeries) { + //@TODO find a better way + impl->m_DataSeries = dataSeries->clone(); + dataInit = true; + delete dataSeries; + } + else { + impl->m_DataSeries->merge(dataSeries); + } + impl->purgeDataSeries(); + impl->unlock(); + + if (dataInit) { + emit dataInitialized(); + } +} + std::shared_ptr Variable::dataSeries() const noexcept { diff --git a/src/Variable/VariableController2.cpp b/src/Variable/VariableController2.cpp index 5aa7acf..10f5c8a 100644 --- a/src/Variable/VariableController2.cpp +++ b/src/Variable/VariableController2.cpp @@ -1,17 +1,56 @@ #include "Variable/VariableController2.h" +#include +#include +#include - -class VariableController2Private +class VariableController2::VariableController2Private { - + std::set> _variables; + QMap> _providers; public: VariableController2Private(QObject* parent=Q_NULLPTR) - {} + { + Q_UNUSED(parent); + } + ~VariableController2Private() = default; + std::shared_ptr createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr provider, const DateTimeRange &range) { - return std::make_shared(name,metadata); + auto newVar = std::make_shared(name,metadata); + this->_variables.insert(newVar); + this->_providers[newVar->ID()] = provider; + return newVar; + } + + void deleteVariable(std::shared_ptr variable) + { + if(this->_providers.contains(variable->ID())) + this->_providers.remove(variable->ID()); + if(SciQLop::containers::contains(this->_variables, variable)) + this->_variables.erase(variable); + } + + void changeRange(std::shared_ptr variable, DateTimeRange r) + { + if(_providers.contains(variable->ID())) + { + auto provider = _providers[variable->ID()]; + auto data = provider->getData(DataProviderParameters{{r},variable->metadata()}); + variable->mergeDataSeries(data); + } + else + { + SCIQLOP_ERROR("No provider found for given variable"); + } + } + + + const std::set>& variables() + { + return _variables; } + }; VariableController2::VariableController2() @@ -20,6 +59,25 @@ VariableController2::VariableController2() std::shared_ptr VariableController2::createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr provider, const DateTimeRange &range) { - return impl->createVariable(name, metadata, provider, range); + auto var = impl->createVariable(name, metadata, provider, range); + emit variableAdded(var); + impl->changeRange(var,range); + return var; +} + +void VariableController2::deleteVariable(std::shared_ptr variable) +{ + impl->deleteVariable(variable); + emit variableDeleted(variable); +} + +void VariableController2::changeRange(std::shared_ptr variable, DateTimeRange r) +{ + impl->changeRange(variable, r); +} + +const std::set > &VariableController2::variables() +{ + return impl->variables(); } diff --git a/tests/Variable/TestVariableController2.cpp b/tests/Variable/TestVariableController2.cpp index f900346..4235d87 100644 --- a/tests/Variable/TestVariableController2.cpp +++ b/tests/Variable/TestVariableController2.cpp @@ -1,9 +1,51 @@ +#include #include #include +#include +#include +#include +#include +#include +#include +class FakeProvider: public IDataProvider +{ +public: + FakeProvider() = default; -class TestVariableController2 : public QObject + std::shared_ptr clone() const override{ return std::make_shared(); } + + IDataSeries* getData(const DataProviderParameters ¶meters) override + { + auto tstart = parameters.m_Times[0].m_TStart; + auto tend = parameters.m_Times[0].m_TEnd; + std::vector x; + std::vector y; + for(auto i = tstart;i){callbackCalled=true;}); + auto provider = std::make_shared(); + QVERIFY(!callbackCalled); + auto var1 = vc.createVariable("var1",{},provider,DateTimeRange()); + QVERIFY(SciQLop::containers::contains(vc.variables(), var1)); + QVERIFY(callbackCalled); + } + + void testDeleteVariable() + { + VariableController2 vc; + bool callbackCalled = false; + connect(&vc,&VariableController2::variableDeleted, [&callbackCalled](std::shared_ptr){callbackCalled=true;}); + auto provider = std::make_shared(); + auto var1 = vc.createVariable("var1",{},provider,DateTimeRange()); + QVERIFY(SciQLop::containers::contains(vc.variables(), var1)); + QVERIFY(!callbackCalled); + vc.deleteVariable(var1); + QVERIFY(!SciQLop::containers::contains(vc.variables(), var1)); + QVERIFY(callbackCalled); + } + + void testGetData() { - QCOMPARE(1+1, 2); + VariableController2 vc; + auto provider = std::make_shared(); + auto range1 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00), + QDate(2018,8,7),QTime(16,00)); + auto range2 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(12,00), + QDate(2018,8,7),QTime(18,00)); + auto var1 = vc.createVariable("var1", {}, provider, range1); + QCOMPARE(var1->nbPoints(), int(range1.delta())); + vc.changeRange(var1, range2); + QCOMPARE(var1->nbPoints(), int(range2.delta())); + } private: