##// END OF EJS Templates
Several additions for Catalogue GUI...
Several additions for Catalogue GUI Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>

File last commit:

r44:79fb0ced05d7
r55:6b6bb3a15bf8
Show More
Variable.cpp
225 lines | 6.5 KiB | text/x-c | CppLexer
#include <optional>
#include <QMutex>
#include <QReadWriteLock>
#include <QThread>
#include "Variable/Variable.h"
#include <Data/IDataSeries.h>
#include <Data/DateTimeRange.h>
#include <Common/debug.h>
Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
/**
* Searches in metadata for a value that can be converted to DataSeriesType
* @param metadata the metadata where to search
* @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
* @sa DataSeriesType
*/
static DataSeriesType findDataSeriesType(const QVariantHash &metadata)
{
auto dataSeriesType = DataSeriesType::UNKNOWN;
// Go through the metadata and stop at the first value that could be converted to DataSeriesType
for (auto it = metadata.cbegin(), end = metadata.cend();
it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
}
return dataSeriesType;
}
#define VP_PROPERTY(property,getter,setter,type) \
type getter() noexcept\
{\
QReadLocker lock{&m_Lock};\
return property;\
}\
void setter(const type& getter) noexcept\
{\
QWriteLocker lock{&m_Lock};\
property = getter;\
}\
type property;\
#define V_FW_GETTER_SETTER(getter,setter, type)\
type Variable::getter() const noexcept \
{\
return impl->getter();\
}\
void Variable::setter(const type& getter) noexcept \
{\
impl->setter(getter);\
emit updated(this->ID());\
}\
struct Variable::VariablePrivate {
explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
: m_Name{name},
m_Range{INVALID_RANGE},
m_CacheRange{INVALID_RANGE},
m_Metadata{metadata},
m_DataSeries{nullptr},
m_RealRange{INVALID_RANGE},
m_NbPoints{0},
m_Type{findDataSeriesType(m_Metadata)}
{
}
VariablePrivate(const VariablePrivate &other)
: m_Name{other.m_Name},
m_Range{other.m_Range},
m_CacheRange{other.m_CacheRange},
m_Metadata{other.m_Metadata},
m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
m_RealRange{other.m_RealRange},
m_NbPoints{other.m_NbPoints},
m_Type{findDataSeriesType(m_Metadata)}
{
}
void lockRead() { m_Lock.lockForRead(); }
void lockWrite() { m_Lock.lockForWrite(); }
void unlock() { m_Lock.unlock(); }
void purgeDataSeries()
{
if (m_DataSeries) {
m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
}
updateRealRange();
updateNbPoints();
}
void mergeDataSeries(const std::vector<IDataSeries*>& dataseries, bool overwrite=false)
{
QWriteLocker lock{&m_Lock};
for(auto ds:dataseries)
{
if(!overwrite & bool(m_DataSeries))
m_DataSeries->merge(ds);
else
m_DataSeries = ds->clone();
}
}
void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
/// Updates real range according to current variable range and data series
void updateRealRange()
{
if (m_DataSeries) {
auto lock = m_DataSeries->getReadLock();
auto end = m_DataSeries->cend();
auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()};
else
m_RealRange = std::nullopt;
}
else {
m_RealRange = std::nullopt;
}
}
VP_PROPERTY(m_Name, name, setName, QString)
VP_PROPERTY(m_Range, range, setRange, DateTimeRange)
VP_PROPERTY(m_CacheRange, cacheRange, setCacheRange, DateTimeRange)
VP_PROPERTY(m_Metadata, metadata, setMetadata, QVariantHash)
VP_PROPERTY(m_DataSeries, dataSeries, setDataSeries, std::shared_ptr<IDataSeries>)
VP_PROPERTY(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
unsigned int m_NbPoints;
VP_PROPERTY(m_Type, type, setType, DataSeriesType)
QReadWriteLock m_Lock;
};
Variable::Variable(const QString &name, const QVariantHash &metadata)
: impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
_uuid{QUuid::createUuid()}
{
}
Variable::Variable(const Variable &other)
: impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
_uuid{QUuid::createUuid()} //is a clone but must have a != uuid
{
}
std::shared_ptr<Variable> Variable::clone() const
{
return std::make_shared<Variable>(*this);
}
V_FW_GETTER_SETTER(name,setName,QString)
DateTimeRange Variable::range() const noexcept
{
return impl->range();
}
void Variable::setRange(const DateTimeRange &range, bool notify) noexcept
{
impl->setRange(range);
impl->updateRealRange();
if(notify)
emit this->updated(this->ID());
}
V_FW_GETTER_SETTER(cacheRange, setCacheRange, DateTimeRange)
unsigned int Variable::nbPoints() const noexcept
{
return impl->m_NbPoints;
}
std::optional<DateTimeRange> Variable::realRange() const noexcept
{
return impl->realRange();
}
void Variable::updateData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
{
{
QWriteLocker lock{&m_lock};
impl->mergeDataSeries(dataSeries);
impl->setRange(newRange);
impl->setCacheRange(newCacheRange);
impl->purgeDataSeries();
}
if(notify)
emit updated(this->ID());
}
void Variable::setData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
{
{
QWriteLocker lock{&m_lock};
impl->mergeDataSeries(dataSeries, true);
impl->setRange(newRange);
impl->setCacheRange(newCacheRange);
impl->purgeDataSeries();
}
if(notify)
emit updated(this->ID());
}
std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
{
return impl->dataSeries();
}
DataSeriesType Variable::type() const noexcept
{
return impl->type();
}
QVariantHash Variable::metadata() const noexcept
{
impl->lockRead();
auto metadata = impl->m_Metadata;
impl->unlock();
return metadata;
}