From 73d2a50d0c6db13d95c14d504aadcd4f97836a7e 2017-12-21 14:54:15 From: Alexandre Leroux Date: 2017-12-21 14:54:15 Subject: [PATCH] Merge branch 'feature/AcqFixes' into develop --- diff --git a/core/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index 7e1e4b0..25ae998 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -136,6 +136,9 @@ struct VariableController::VariableControllerPrivate { void cancelVariableRequest(QUuid varRequestId); void executeVarRequest(std::shared_ptr var, VariableRequest &varRequest); + template + void desynchronize(VariableIterator variableIt, const QUuid &syncGroupId); + QMutex m_WorkingMutex; /// Variable model. The VariableController has the ownership VariableModel *m_VariableModel; @@ -258,8 +261,22 @@ void VariableController::deleteVariable(std::shared_ptr variable) noex // make some treatments before the deletion emit variableAboutToBeDeleted(variable); + auto variableIt = impl->m_VariableToIdentifierMap.find(variable); + Q_ASSERT(variableIt != impl->m_VariableToIdentifierMap.cend()); + + auto variableId = variableIt->second; + + // Removes variable's handler + impl->m_VarIdToVarRequestHandler.erase(variableId); + + // Desynchronizes variable (if the variable is in a sync group) + auto syncGroupIt = impl->m_VariableIdGroupIdMap.find(variableId); + if (syncGroupIt != impl->m_VariableIdGroupIdMap.cend()) { + impl->desynchronize(variableIt, syncGroupIt->second); + } + // Deletes identifier - impl->m_VariableToIdentifierMap.erase(variable); + impl->m_VariableToIdentifierMap.erase(variableIt); // Deletes provider auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable); @@ -545,23 +562,7 @@ void VariableController::desynchronize(std::shared_ptr variable, return; } - // Gets synchronization group - auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId); - if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) { - qCCritical(LOG_VariableController()) - << tr("Can't desynchronize variable %1: unknown synchronization group") - .arg(variable->name()); - return; - } - - auto variableId = variableIt->second; - - // Removes variable from synchronization group - auto synchronizationGroup = groupIt->second; - synchronizationGroup->removeVariableId(variableId); - - // Removes link between variable and synchronization group - impl->m_VariableIdGroupIdMap.erase(variableId); + impl->desynchronize(variableIt, synchronizationGroupId); } void VariableController::onRequestDataLoading(QVector > variables, @@ -933,6 +934,7 @@ void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varHandler->m_PendingVarRequest = VariableRequest{}; auto var = findVariable(itVarHandler->first); executeVarRequest(var, varHandler->m_RunningVarRequest); + updateVariables(varHandler->m_RunningVarRequest.m_VariableGroupId); break; } default: @@ -1032,7 +1034,14 @@ void VariableController::VariableControllerPrivate::executeVarRequest(std::share { qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest"); - auto varId = m_VariableToIdentifierMap.at(var); + auto varIdIt = m_VariableToIdentifierMap.find(var); + if (varIdIt == m_VariableToIdentifierMap.cend()) { + qCWarning(LOG_VariableController()) << tr( + "Can't execute request of a variable that is not registered (may has been deleted)"); + return; + } + + auto varId = varIdIt->second; auto varCacheRange = var->cacheRange(); auto varCacheRangeRequested = varRequest.m_CacheRangeRequested; @@ -1067,3 +1076,27 @@ void VariableController::VariableControllerPrivate::executeVarRequest(std::share var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested)); } } + +template +void VariableController::VariableControllerPrivate::desynchronize(VariableIterator variableIt, + const QUuid &syncGroupId) +{ + const auto &variable = variableIt->first; + const auto &variableId = variableIt->second; + + // Gets synchronization group + auto groupIt = m_GroupIdToVariableSynchronizationGroupMap.find(syncGroupId); + if (groupIt == m_GroupIdToVariableSynchronizationGroupMap.cend()) { + qCCritical(LOG_VariableController()) + << tr("Can't desynchronize variable %1: unknown synchronization group") + .arg(variable->name()); + return; + } + + // Removes variable from synchronization group + auto synchronizationGroup = groupIt->second; + synchronizationGroup->removeVariableId(variableId); + + // Removes link between variable and synchronization group + m_VariableIdGroupIdMap.erase(variableId); +} diff --git a/gui/include/Visualization/VisualizationGraphWidget.h b/gui/include/Visualization/VisualizationGraphWidget.h index 8f97ea9..efee1c9 100644 --- a/gui/include/Visualization/VisualizationGraphWidget.h +++ b/gui/include/Visualization/VisualizationGraphWidget.h @@ -25,6 +25,20 @@ namespace Ui { class VisualizationGraphWidget; } // namespace Ui +/// Defines options that can be associated with the graph +enum GraphFlag { + DisableAll = 0x0, ///< Disables acquisition and synchronization + EnableAcquisition = 0x1, ///< When this flag is set, the change of the graph's range leads to + /// the acquisition of data + EnableSynchronization = 0x2, ///< When this flag is set, the change of the graph's range causes + /// the call to the synchronization of the graphs contained in the + /// same zone of this graph + EnableAll = ~DisableAll ///< Enables acquisition and synchronization +}; + +Q_DECLARE_FLAGS(GraphFlags, GraphFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(GraphFlags) + class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget { Q_OBJECT @@ -41,8 +55,8 @@ public: /// Returns the main VisualizationWidget which contains the graph or nullptr VisualizationWidget *parentVisualizationWidget() const; - /// If acquisition isn't enable, requestDataLoading signal cannot be emit - void enableAcquisition(bool enable); + /// Sets graph options + void setFlags(GraphFlags flags); void addVariable(std::shared_ptr variable, SqpRange range); diff --git a/gui/src/Visualization/VisualizationGraphWidget.cpp b/gui/src/Visualization/VisualizationGraphWidget.cpp index b1e2048..85c81ff 100644 --- a/gui/src/Visualization/VisualizationGraphWidget.cpp +++ b/gui/src/Visualization/VisualizationGraphWidget.cpp @@ -59,7 +59,7 @@ struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { explicit VisualizationGraphWidgetPrivate(const QString &name) : m_Name{name}, - m_DoAcquisition{true}, + m_Flags{GraphFlag::EnableAll}, m_IsCalibration{false}, m_RenderingDelegate{nullptr} { @@ -77,7 +77,7 @@ struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { QString m_Name; // 1 variable -> n qcpplot std::map, PlottablesMap> m_VariableToPlotMultiMap; - bool m_DoAcquisition; + GraphFlags m_Flags; bool m_IsCalibration; /// Delegate used to attach rendering features to the plot std::unique_ptr m_RenderingDelegate; @@ -287,9 +287,9 @@ VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const return qobject_cast(parent); } -void VisualizationGraphWidget::enableAcquisition(bool enable) +void VisualizationGraphWidget::setFlags(GraphFlags flags) { - impl->m_DoAcquisition = enable; + impl->m_Flags = std::move(flags); } void VisualizationGraphWidget::addVariable(std::shared_ptr variable, SqpRange range) @@ -311,9 +311,9 @@ void VisualizationGraphWidget::addVariable(std::shared_ptr variable, S connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated())); - this->enableAcquisition(false); + this->setFlags(GraphFlag::DisableAll); this->setGraphRange(range); - this->enableAcquisition(true); + this->setFlags(GraphFlag::EnableAll); emit requestDataLoading(QVector >() << variable, range, false); @@ -696,12 +696,12 @@ void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange { qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged") << QThread::currentThread()->objectName() << "DoAcqui" - << impl->m_DoAcquisition; + << impl->m_Flags.testFlag(GraphFlag::EnableAcquisition); auto graphRange = SqpRange{t1.lower, t1.upper}; auto oldGraphRange = SqpRange{t2.lower, t2.upper}; - if (impl->m_DoAcquisition) { + if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) { QVector > variableUnderGraphVector; for (auto it = impl->m_VariableToPlotMultiMap.begin(), @@ -711,13 +711,13 @@ void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange } emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, !impl->m_IsCalibration); + } - if (!impl->m_IsCalibration) { - qCDebug(LOG_VisualizationGraphWidget()) - << tr("TORM: VisualizationGraphWidget::Synchronize notify !!") - << QThread::currentThread()->objectName() << graphRange << oldGraphRange; - emit synchronize(graphRange, oldGraphRange); - } + if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) { + qCDebug(LOG_VisualizationGraphWidget()) + << tr("TORM: VisualizationGraphWidget::Synchronize notify !!") + << QThread::currentThread()->objectName() << graphRange << oldGraphRange; + emit synchronize(graphRange, oldGraphRange); } auto pos = mapFromGlobal(QCursor::pos()); @@ -733,6 +733,9 @@ void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange else { qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget"; } + + // Quits calibration + impl->m_IsCalibration = false; } void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept @@ -917,8 +920,6 @@ void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept impl->endDrawingZone(this); - impl->m_IsCalibration = false; - // Selection / Deselection auto isSelectionZoneMode = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones; diff --git a/gui/src/Visualization/VisualizationZoneWidget.cpp b/gui/src/Visualization/VisualizationZoneWidget.cpp index 5f967a9..eb1222c 100644 --- a/gui/src/Visualization/VisualizationZoneWidget.cpp +++ b/gui/src/Visualization/VisualizationZoneWidget.cpp @@ -264,15 +264,15 @@ VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptrenableAcquisition(false); - qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ") - << graphChild->graphRange(); - qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ") - << graphChildRange; + graphChild->setFlags(GraphFlag::DisableAll); + qCDebug(LOG_VisualizationZoneWidget()) + << tr("TORM: Range before: ") << graphChild->graphRange(); + qCDebug(LOG_VisualizationZoneWidget()) + << tr("TORM: Range after : ") << graphChildRange; qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart; graphChild->setGraphRange(graphChildRange); - graphChild->enableAcquisition(true); + graphChild->setFlags(GraphFlag::EnableAll); } } }; diff --git a/gui/src/Visualization/operations/RescaleAxeOperation.cpp b/gui/src/Visualization/operations/RescaleAxeOperation.cpp index 543b26c..f9cd9ba 100644 --- a/gui/src/Visualization/operations/RescaleAxeOperation.cpp +++ b/gui/src/Visualization/operations/RescaleAxeOperation.cpp @@ -59,9 +59,11 @@ void RescaleAxeOperation::visit(VisualizationGraphWidget *graphWidget) if (graphWidget) { // If the widget contains the variable, rescale it if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) { - graphWidget->enableAcquisition(false); + // During rescale, acquisition for the graph is disabled but synchronization is still + // enabled + graphWidget->setFlags(GraphFlag::EnableSynchronization); graphWidget->setGraphRange(impl->m_Range); - graphWidget->enableAcquisition(true); + graphWidget->setFlags(GraphFlag::EnableAll); } } else { diff --git a/plugins/amda/tests/FuzzingDefs.cpp b/plugins/amda/tests/FuzzingDefs.cpp index d47bbd8..5d2502e 100644 --- a/plugins/amda/tests/FuzzingDefs.cpp +++ b/plugins/amda/tests/FuzzingDefs.cpp @@ -67,14 +67,18 @@ void FuzzingState::synchronizeVariable(VariableId variableId, SyncGroupId syncGr return; } - // Registers variable into sync group: if it's the first variable, sets the variable range as - // the sync group range + // Registers variable into sync group auto &syncGroup = m_SyncGroupsPool.at(syncGroupId); + auto &variableState = m_VariablesPool.at(variableId); syncGroup.m_Variables.insert(variableId); if (syncGroup.m_Variables.size() == 1) { - auto &variableState = m_VariablesPool.at(variableId); + // If it's the first variable, sets the variable range as the sync group range syncGroup.m_Range = variableState.m_Range; } + else { + // If a variable is added to an existing group, sets its range to the group's range + variableState.m_Range = syncGroup.m_Range; + } } void FuzzingState::desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId) @@ -97,13 +101,18 @@ void FuzzingState::updateRanges(VariableId variableId, const SqpRange &newRange) auto syncGroupId = this->syncGroupId(variableId); // Retrieves the variables to update: - // - if the variable is synchronized to others, updates all synchronized variables + // - if the variable is synchronized to others, updates the range of the group and of all + // synchronized variables // - otherwise, updates only the variable - auto variablesToUpdate = syncGroupId.isNull() ? std::set{variableId} - : m_SyncGroupsPool.at(syncGroupId).m_Variables; - - // Sets new range - for (const auto &variableId : variablesToUpdate) { + if (syncGroupId.isNull()) { m_VariablesPool.at(variableId).m_Range = newRange; } + else { + auto &syncGroup = m_SyncGroupsPool.at(syncGroupId); + syncGroup.m_Range = newRange; + + for (const auto &variableId : syncGroup.m_Variables) { + m_VariablesPool.at(variableId).m_Range = newRange; + } + } } diff --git a/plugins/amda/tests/FuzzingOperations.cpp b/plugins/amda/tests/FuzzingOperations.cpp index b947424..059c233 100644 --- a/plugins/amda/tests/FuzzingOperations.cpp +++ b/plugins/amda/tests/FuzzingOperations.cpp @@ -176,6 +176,9 @@ struct SynchronizeOperation : public IFuzzingOperation { // Updates state fuzzingState.synchronizeVariable(variableId, syncGroupId); + + variableController.onRequestDataLoading({variableState.m_Variable}, variableState.m_Range, + false); } }; @@ -197,7 +200,7 @@ struct DesynchronizeOperation : public IFuzzingOperation { qCInfo(LOG_FuzzingOperations()).noquote() << "Removing" << variableState.m_Variable->name() << "from synchronization group" << syncGroupId << "..."; - variableController.onAddSynchronized(variableState.m_Variable, syncGroupId); + variableController.desynchronize(variableState.m_Variable, syncGroupId); // Updates state fuzzingState.desynchronizeVariable(variableId, syncGroupId); diff --git a/plugins/amda/tests/FuzzingValidators.cpp b/plugins/amda/tests/FuzzingValidators.cpp index f4de229..069251d 100644 --- a/plugins/amda/tests/FuzzingValidators.cpp +++ b/plugins/amda/tests/FuzzingValidators.cpp @@ -96,7 +96,7 @@ public: auto dataHoleIt = std::adjacent_find( dataIts.first, dataIts.second, [](const auto &it1, const auto &it2) { /// @todo: validate resolution - return std::abs(it1.x() - it2.x()) > 2 * (LOCALHOST_SERVER_RESOLUTION - 1); + return std::abs(it1.x() - it2.x()) > 2 * LOCALHOST_SERVER_RESOLUTION; }); if (dataHoleIt != dataIts.second) { diff --git a/plugins/amda/tests/TestAmdaFuzzing.cpp b/plugins/amda/tests/TestAmdaFuzzing.cpp index 2dd6222..b2d299c 100644 --- a/plugins/amda/tests/TestAmdaFuzzing.cpp +++ b/plugins/amda/tests/TestAmdaFuzzing.cpp @@ -370,6 +370,10 @@ void TestAmdaFuzzing::testFuzzing() int main(int argc, char *argv[]) { + // Increases the test function timeout (which is 5 minutes by default) to 12 hours + // https://stackoverflow.com/questions/42655932/setting-timeout-to-qt-test + qputenv("QTEST_FUNCTION_TIMEOUT", QByteArray::number(12*60*60*1000)); + QLoggingCategory::setFilterRules( "*.warning=false\n" "*.info=false\n"