VariableController.cpp
508 lines
| 19.1 KiB
| text/x-c
|
CppLexer
r219 | #include <Variable/Variable.h> | |||
r495 | #include <Variable/VariableAcquisitionWorker.h> | |||
r209 | #include <Variable/VariableCacheController.h> | |||
r495 | #include <Variable/VariableCacheStrategy.h> | |||
Alexandre Leroux
|
r106 | #include <Variable/VariableController.h> | ||
Alexandre Leroux
|
r108 | #include <Variable/VariableModel.h> | ||
r495 | #include <Variable/VariableSynchronizationGroup.h> | |||
Alexandre Leroux
|
r106 | |||
Alexandre Leroux
|
r154 | #include <Data/DataProviderParameters.h> | ||
#include <Data/IDataProvider.h> | ||||
#include <Data/IDataSeries.h> | ||||
r179 | #include <Time/TimeController.h> | |||
Alexandre Leroux
|
r154 | |||
Alexandre Leroux
|
r106 | #include <QMutex> | ||
#include <QThread> | ||||
Alexandre Leroux
|
r347 | #include <QUuid> | ||
r281 | #include <QtCore/QItemSelectionModel> | |||
Alexandre Leroux
|
r106 | |||
r495 | #include <set> | |||
r209 | #include <unordered_map> | |||
Alexandre Leroux
|
r106 | Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController") | ||
r495 | namespace { | |||
SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &grapheRange, | ||||
const SqpRange &oldGraphRange) | ||||
{ | ||||
auto zoomType = VariableController::getZoomType(grapheRange, oldGraphRange); | ||||
auto varRangeRequested = varRange; | ||||
switch (zoomType) { | ||||
case AcquisitionZoomType::ZoomIn: { | ||||
auto deltaLeft = grapheRange.m_TStart - oldGraphRange.m_TStart; | ||||
auto deltaRight = oldGraphRange.m_TEnd - grapheRange.m_TEnd; | ||||
varRangeRequested.m_TStart += deltaLeft; | ||||
varRangeRequested.m_TEnd -= deltaRight; | ||||
break; | ||||
} | ||||
case AcquisitionZoomType::ZoomOut: { | ||||
auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart; | ||||
auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd; | ||||
varRangeRequested.m_TStart -= deltaLeft; | ||||
varRangeRequested.m_TEnd += deltaRight; | ||||
break; | ||||
} | ||||
case AcquisitionZoomType::PanRight: { | ||||
auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd; | ||||
varRangeRequested.m_TStart += deltaRight; | ||||
varRangeRequested.m_TEnd += deltaRight; | ||||
break; | ||||
} | ||||
case AcquisitionZoomType::PanLeft: { | ||||
auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart; | ||||
varRangeRequested.m_TStart -= deltaLeft; | ||||
varRangeRequested.m_TEnd -= deltaLeft; | ||||
break; | ||||
} | ||||
case AcquisitionZoomType::Unknown: { | ||||
qCCritical(LOG_VariableController()) | ||||
<< VariableController::tr("Impossible to synchronize: zoom type unknown"); | ||||
break; | ||||
} | ||||
default: | ||||
qCCritical(LOG_VariableController()) << VariableController::tr( | ||||
"Impossible to synchronize: zoom type not take into account"); | ||||
// No action | ||||
break; | ||||
} | ||||
return varRangeRequested; | ||||
} | ||||
} | ||||
Alexandre Leroux
|
r106 | struct VariableController::VariableControllerPrivate { | ||
Alexandre Leroux
|
r148 | explicit VariableControllerPrivate(VariableController *parent) | ||
r209 | : m_WorkingMutex{}, | |||
m_VariableModel{new VariableModel{parent}}, | ||||
r281 | m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}}, | |||
r495 | m_VariableCacheController{std::make_unique<VariableCacheController>()}, | |||
m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()}, | ||||
m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()} | ||||
{ | ||||
m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread); | ||||
m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread"); | ||||
} | ||||
virtual ~VariableControllerPrivate() | ||||
Alexandre Leroux
|
r106 | { | ||
r495 | qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction"); | |||
m_VariableAcquisitionWorkerThread.quit(); | ||||
m_VariableAcquisitionWorkerThread.wait(); | ||||
Alexandre Leroux
|
r106 | } | ||
r495 | ||||
void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested); | ||||
r486 | QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, | |||
const SqpRange &dateTime); | ||||
r485 | ||||
r495 | std::shared_ptr<Variable> findVariable(QUuid vIdentifier); | |||
std::shared_ptr<IDataSeries> | ||||
retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector); | ||||
void registerProvider(std::shared_ptr<IDataProvider> provider); | ||||
Alexandre Leroux
|
r106 | QMutex m_WorkingMutex; | ||
Alexandre Leroux
|
r148 | /// Variable model. The VariableController has the ownership | ||
VariableModel *m_VariableModel; | ||||
r281 | QItemSelectionModel *m_VariableSelectionModel; | |||
r179 | ||||
r209 | ||||
r181 | TimeController *m_TimeController{nullptr}; | |||
r209 | std::unique_ptr<VariableCacheController> m_VariableCacheController; | |||
r495 | std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy; | |||
std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker; | ||||
QThread m_VariableAcquisitionWorkerThread; | ||||
r219 | ||||
std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> > | ||||
m_VariableToProviderMap; | ||||
Alexandre Leroux
|
r386 | std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap; | ||
r495 | std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> > | |||
m_GroupIdToVariableSynchronizationGroupMap; | ||||
std::map<QUuid, QUuid> m_VariableIdGroupIdMap; | ||||
std::set<std::shared_ptr<IDataProvider> > m_ProviderSet; | ||||
Alexandre Leroux
|
r106 | }; | ||
r495 | ||||
Alexandre Leroux
|
r106 | VariableController::VariableController(QObject *parent) | ||
Alexandre Leroux
|
r148 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)} | ||
Alexandre Leroux
|
r106 | { | ||
r337 | qCDebug(LOG_VariableController()) << tr("VariableController construction") | |||
<< QThread::currentThread(); | ||||
r388 | ||||
connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this, | ||||
&VariableController::onAbortProgressRequested); | ||||
r495 | ||||
connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this, | ||||
&VariableController::onDataProvided); | ||||
connect(impl->m_VariableAcquisitionWorker.get(), | ||||
&VariableAcquisitionWorker::variableRequestInProgress, this, | ||||
&VariableController::onVariableRetrieveDataInProgress); | ||||
connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started, | ||||
impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize); | ||||
connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished, | ||||
impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize); | ||||
impl->m_VariableAcquisitionWorkerThread.start(); | ||||
Alexandre Leroux
|
r106 | } | ||
VariableController::~VariableController() | ||||
{ | ||||
r337 | qCDebug(LOG_VariableController()) << tr("VariableController destruction") | |||
<< QThread::currentThread(); | ||||
Alexandre Leroux
|
r106 | this->waitForFinish(); | ||
} | ||||
Alexandre Leroux
|
r154 | VariableModel *VariableController::variableModel() noexcept | ||
Alexandre Leroux
|
r108 | { | ||
Alexandre Leroux
|
r154 | return impl->m_VariableModel; | ||
Alexandre Leroux
|
r108 | } | ||
r281 | QItemSelectionModel *VariableController::variableSelectionModel() noexcept | |||
{ | ||||
return impl->m_VariableSelectionModel; | ||||
} | ||||
r179 | void VariableController::setTimeController(TimeController *timeController) noexcept | |||
{ | ||||
impl->m_TimeController = timeController; | ||||
} | ||||
Alexandre Leroux
|
r303 | void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept | ||
{ | ||||
if (!variable) { | ||||
qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null"; | ||||
return; | ||||
} | ||||
Alexandre Leroux
|
r309 | // Spreads in SciQlop that the variable will be deleted, so that potential receivers can | ||
// make some treatments before the deletion | ||||
emit variableAboutToBeDeleted(variable); | ||||
Alexandre Leroux
|
r304 | |||
Alexandre Leroux
|
r386 | // Deletes identifier | ||
impl->m_VariableToIdentifierMap.erase(variable); | ||||
Alexandre Leroux
|
r304 | // Deletes provider | ||
auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable); | ||||
qCDebug(LOG_VariableController()) | ||||
<< tr("Number of providers deleted for variable %1: %2") | ||||
.arg(variable->name(), QString::number(nbProvidersDeleted)); | ||||
Alexandre Leroux
|
r303 | |||
Alexandre Leroux
|
r305 | // Clears cache | ||
impl->m_VariableCacheController->clear(variable); | ||||
Alexandre Leroux
|
r306 | // Deletes from model | ||
impl->m_VariableModel->deleteVariable(variable); | ||||
} | ||||
Alexandre Leroux
|
r303 | |||
void VariableController::deleteVariables( | ||||
const QVector<std::shared_ptr<Variable> > &variables) noexcept | ||||
{ | ||||
for (auto variable : qAsConst(variables)) { | ||||
deleteVariable(variable); | ||||
} | ||||
} | ||||
r388 | void VariableController::abortProgress(std::shared_ptr<Variable> variable) | |||
{ | ||||
} | ||||
Alexandre Leroux
|
r377 | void VariableController::createVariable(const QString &name, const QVariantHash &metadata, | ||
Alexandre Leroux
|
r154 | std::shared_ptr<IDataProvider> provider) noexcept | ||
Alexandre Leroux
|
r143 | { | ||
r179 | ||||
if (!impl->m_TimeController) { | ||||
qCCritical(LOG_VariableController()) | ||||
<< tr("Impossible to create variable: The time controller is null"); | ||||
return; | ||||
} | ||||
r495 | auto range = impl->m_TimeController->dateTime(); | |||
Alexandre Leroux
|
r377 | |||
r495 | if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) { | |||
r359 | auto identifier = QUuid::createUuid(); | |||
r209 | ||||
r219 | // store the provider | |||
r495 | impl->registerProvider(provider); | |||
// Associate the provider | ||||
r219 | impl->m_VariableToProviderMap[newVariable] = provider; | |||
Alexandre Leroux
|
r386 | impl->m_VariableToIdentifierMap[newVariable] = identifier; | ||
r293 | ||||
r495 | impl->processRequest(newVariable, range); | |||
Alexandre Leroux
|
r154 | } | ||
Alexandre Leroux
|
r143 | } | ||
r471 | void VariableController::onDateTimeOnSelection(const SqpRange &dateTime) | |||
r281 | { | |||
r495 | // TODO check synchronisation | |||
r337 | qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection" | |||
<< QThread::currentThread()->objectName(); | ||||
r281 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); | |||
for (const auto &selectedRow : qAsConst(selectedRows)) { | ||||
if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) { | ||||
r495 | selectedVariable->setRange(dateTime); | |||
impl->processRequest(selectedVariable, dateTime); | ||||
r408 | ||||
// notify that rescale operation has to be done | ||||
r403 | emit rangeChanged(selectedVariable, dateTime); | |||
r281 | } | |||
} | ||||
} | ||||
r495 | void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested, | |||
const SqpRange &cacheRangeRequested, | ||||
QVector<AcquisitionDataPacket> dataAcquired) | ||||
r369 | { | |||
r495 | qCCritical(LOG_VariableController()) << tr("onDataProvided") << dataAcquired.isEmpty(); | |||
auto var = impl->findVariable(vIdentifier); | ||||
if (var != nullptr) { | ||||
var->setRange(rangeRequested); | ||||
var->setCacheRange(cacheRangeRequested); | ||||
qCCritical(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested; | ||||
qCCritical(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested; | ||||
auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired); | ||||
qCCritical(LOG_VariableController()) << tr("3: onDataProvided") | ||||
<< retrievedDataSeries->range(); | ||||
var->mergeDataSeries(retrievedDataSeries); | ||||
emit var->updated(); | ||||
} | ||||
else { | ||||
qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable"); | ||||
} | ||||
} | ||||
r369 | ||||
r495 | void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress) | |||
{ | ||||
auto var = impl->findVariable(identifier); | ||||
if (var != nullptr) { | ||||
impl->m_VariableModel->setDataProgress(var, progress); | ||||
} | ||||
else { | ||||
qCCritical(LOG_VariableController()) | ||||
<< tr("Impossible to notify progression of a null variable"); | ||||
r369 | } | |||
} | ||||
r388 | void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable) | |||
{ | ||||
qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested" | ||||
<< QThread::currentThread()->objectName(); | ||||
r389 | auto it = impl->m_VariableToIdentifierMap.find(variable); | |||
if (it != impl->m_VariableToIdentifierMap.cend()) { | ||||
r388 | impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second); | |||
} | ||||
else { | ||||
qCWarning(LOG_VariableController()) | ||||
<< tr("Aborting progression of inexistant variable detected !!!") | ||||
<< QThread::currentThread()->objectName(); | ||||
} | ||||
} | ||||
r495 | void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId) | |||
{ | ||||
auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>(); | ||||
impl->m_GroupIdToVariableSynchronizationGroupMap.insert( | ||||
std::make_pair(synchronizationGroupId, vSynchroGroup)); | ||||
} | ||||
void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId) | ||||
{ | ||||
impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId); | ||||
} | ||||
r219 | ||||
r495 | void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, | |||
const SqpRange &range, const SqpRange &oldRange, | ||||
bool synchronise) | ||||
r219 | { | |||
r495 | // NOTE: oldRange isn't really necessary since oldRange == variable->range(). | |||
r337 | qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading" | |||
<< QThread::currentThread()->objectName(); | ||||
r219 | // we want to load data of the variable for the dateTime. | |||
// First we check if the cache contains some of them. | ||||
// For the other, we ask the provider to give them. | ||||
r495 | foreach (auto var, variables) { | |||
qCInfo(LOG_VariableController()) << "processRequest for" << var->name(); | ||||
impl->processRequest(var, range); | ||||
} | ||||
r219 | ||||
r495 | if (synchronise) { | |||
// Get the group ids | ||||
qCInfo(LOG_VariableController()) | ||||
<< "VariableController::onRequestDataLoading for synchro var ENABLE"; | ||||
auto groupIds = std::set<QUuid>(); | ||||
foreach (auto var, variables) { | ||||
auto vToVIdit = impl->m_VariableToIdentifierMap.find(var); | ||||
if (vToVIdit != impl->m_VariableToIdentifierMap.cend()) { | ||||
auto vId = vToVIdit->second; | ||||
auto vIdToGIdit = impl->m_VariableIdGroupIdMap.find(vId); | ||||
if (vIdToGIdit != impl->m_VariableIdGroupIdMap.cend()) { | ||||
auto gId = vToVIdit->second; | ||||
if (groupIds.find(gId) == groupIds.cend()) { | ||||
groupIds.insert(gId); | ||||
} | ||||
} | ||||
} | ||||
r276 | } | |||
r495 | ||||
// We assume here all group ids exist | ||||
foreach (auto gId, groupIds) { | ||||
auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId); | ||||
auto vSyncIds = vSynchronizationGroup->getIds(); | ||||
for (auto vId : vSyncIds) { | ||||
auto var = impl->findVariable(vId); | ||||
if (var != nullptr) { | ||||
qCInfo(LOG_VariableController()) << "processRequest synchro for" << var->name(); | ||||
auto vSyncRangeRequested | ||||
= computeSynchroRangeRequested(var->range(), range, oldRange); | ||||
impl->processRequest(var, vSyncRangeRequested); | ||||
} | ||||
else { | ||||
qCCritical(LOG_VariableController()) | ||||
<< tr("Impossible to synchronize a null variable"); | ||||
} | ||||
} | ||||
r276 | } | |||
r219 | } | |||
} | ||||
Alexandre Leroux
|
r106 | void VariableController::initialize() | ||
{ | ||||
qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread(); | ||||
impl->m_WorkingMutex.lock(); | ||||
qCDebug(LOG_VariableController()) << tr("VariableController init END"); | ||||
} | ||||
void VariableController::finalize() | ||||
{ | ||||
impl->m_WorkingMutex.unlock(); | ||||
} | ||||
void VariableController::waitForFinish() | ||||
{ | ||||
QMutexLocker locker{&impl->m_WorkingMutex}; | ||||
} | ||||
r485 | ||||
r495 | AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange) | |||
{ | ||||
// t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd | ||||
auto zoomType = AcquisitionZoomType::Unknown; | ||||
if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) { | ||||
zoomType = AcquisitionZoomType::ZoomOut; | ||||
} | ||||
else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) { | ||||
zoomType = AcquisitionZoomType::PanRight; | ||||
} | ||||
else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) { | ||||
zoomType = AcquisitionZoomType::PanLeft; | ||||
} | ||||
else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) { | ||||
zoomType = AcquisitionZoomType::ZoomIn; | ||||
} | ||||
else { | ||||
qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected"; | ||||
} | ||||
return zoomType; | ||||
} | ||||
r485 | ||||
r495 | void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var, | |||
const SqpRange &rangeRequested) | ||||
r485 | { | |||
r495 | auto varRangesRequested | |||
= m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested); | ||||
auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second); | ||||
if (!notInCacheRangeList.empty()) { | ||||
// Display part of data which are already there | ||||
// Ask the provider for each data on the dateTimeListNotInCache | ||||
auto identifier = m_VariableToIdentifierMap.at(var); | ||||
auto varProvider = m_VariableToProviderMap.at(var); | ||||
if (varProvider != nullptr) { | ||||
m_VariableAcquisitionWorker->pushVariableRequest( | ||||
identifier, varRangesRequested.first, varRangesRequested.second, | ||||
DataProviderParameters{std::move(notInCacheRangeList), var->metadata()}, | ||||
varProvider); | ||||
r485 | } | |||
else { | ||||
r495 | qCCritical(LOG_VariableController()) | |||
<< "Impossible to provide data with a null provider"; | ||||
r485 | } | |||
} | ||||
r495 | else { | |||
var->setRange(rangeRequested); | ||||
var->setCacheRange(varRangesRequested.second); | ||||
var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second)); | ||||
emit var->updated(); | ||||
} | ||||
} | ||||
std::shared_ptr<Variable> | ||||
VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier) | ||||
{ | ||||
std::shared_ptr<Variable> var; | ||||
auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; }; | ||||
auto end = m_VariableToIdentifierMap.cend(); | ||||
auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply); | ||||
if (it != end) { | ||||
var = it->first; | ||||
} | ||||
else { | ||||
qCCritical(LOG_VariableController()) | ||||
<< tr("Impossible to find the variable with the identifier: ") << vIdentifier; | ||||
} | ||||
r485 | ||||
r495 | return var; | |||
} | ||||
std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries( | ||||
const QVector<AcquisitionDataPacket> acqDataPacketVector) | ||||
{ | ||||
qCInfo(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size") | ||||
<< acqDataPacketVector.size(); | ||||
std::shared_ptr<IDataSeries> dataSeries; | ||||
if (!acqDataPacketVector.isEmpty()) { | ||||
dataSeries = acqDataPacketVector[0].m_DateSeries; | ||||
for (int i = 1; i < acqDataPacketVector.size(); ++i) { | ||||
dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get()); | ||||
} | ||||
} | ||||
return dataSeries; | ||||
} | ||||
void VariableController::VariableControllerPrivate::registerProvider( | ||||
std::shared_ptr<IDataProvider> provider) | ||||
{ | ||||
if (m_ProviderSet.find(provider) == m_ProviderSet.end()) { | ||||
qCInfo(LOG_VariableController()) << tr("Registering of a new provider") | ||||
<< provider->objectName(); | ||||
m_ProviderSet.insert(provider); | ||||
connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(), | ||||
&VariableAcquisitionWorker::onVariableDataAcquired); | ||||
connect(provider.get(), &IDataProvider::dataProvidedProgress, | ||||
m_VariableAcquisitionWorker.get(), | ||||
&VariableAcquisitionWorker::onVariableRetrieveDataInProgress); | ||||
} | ||||
else { | ||||
qCInfo(LOG_VariableController()) << tr("Cannot register provider, it already exists "); | ||||
} | ||||
r485 | } | |||