VisualizationZoneWidget.cpp
516 lines
| 20.1 KiB
| text/x-c
|
CppLexer
r95 | #include "Visualization/VisualizationZoneWidget.h" | |||
r444 | ||||
|
r207 | #include "Visualization/IVisualizationWidgetVisitor.h" | ||
|
r730 | #include "Visualization/QCustomPlotSynchronizer.h" | ||
r444 | #include "Visualization/VisualizationGraphWidget.h" | |||
r852 | #include "Visualization/VisualizationWidget.h" | |||
r58 | #include "ui_VisualizationZoneWidget.h" | |||
r850 | #include "Common/MimeTypesDef.h" | |||
r853 | #include "Common/VisualizationDef.h" | |||
r539 | #include <Data/SqpRange.h> | |||
r884 | #include <Time/TimeController.h> | |||
r548 | #include <Variable/Variable.h> | |||
r539 | #include <Variable/VariableController.h> | |||
r118 | ||||
r852 | #include <Visualization/operations/FindVariableOperation.h> | |||
r847 | #include <DragDropHelper.h> | |||
r539 | #include <QUuid> | |||
|
r265 | #include <SqpApplication.h> | ||
r621 | #include <cmath> | |||
|
r265 | |||
r842 | #include <QLayout> | |||
|
r219 | Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget") | ||
|
r200 | namespace { | ||
|
r307 | |||
|
r200 | /// Generates a default name for a new graph, according to the number of graphs already displayed in | ||
/// the zone | ||||
QString defaultGraphName(const QLayout &layout) | ||||
{ | ||||
auto count = 0; | ||||
for (auto i = 0; i < layout.count(); ++i) { | ||||
if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) { | ||||
count++; | ||||
} | ||||
} | ||||
return QObject::tr("Graph %1").arg(count + 1); | ||||
} | ||||
|
r738 | /** | ||
* Applies a function to all graphs of the zone represented by its layout | ||||
* @param layout the layout that contains graphs | ||||
* @param fun the function to apply to each graph | ||||
*/ | ||||
template <typename Fun> | ||||
void processGraphs(QLayout &layout, Fun fun) | ||||
{ | ||||
for (auto i = 0; i < layout.count(); ++i) { | ||||
if (auto item = layout.itemAt(i)) { | ||||
if (auto visualizationGraphWidget | ||||
= dynamic_cast<VisualizationGraphWidget *>(item->widget())) { | ||||
fun(*visualizationGraphWidget); | ||||
} | ||||
} | ||||
} | ||||
} | ||||
|
r200 | } // namespace | ||
r539 | struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate { | |||
|
r730 | explicit VisualizationZoneWidgetPrivate() | ||
: m_SynchronisationGroupId{QUuid::createUuid()}, | ||||
m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()} | ||||
{ | ||||
} | ||||
r539 | QUuid m_SynchronisationGroupId; | |||
|
r730 | std::unique_ptr<IGraphSynchronizer> m_Synchronizer; | ||
r852 | ||||
r884 | // Returns the first graph in the zone or nullptr if there is no graph inside | |||
VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const | ||||
{ | ||||
VisualizationGraphWidget *firstGraph = nullptr; | ||||
auto layout = zoneWidget->ui->dragDropContainer->layout(); | ||||
if (layout->count() > 0) { | ||||
if (auto visualizationGraphWidget | ||||
= qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) { | ||||
firstGraph = visualizationGraphWidget; | ||||
} | ||||
} | ||||
return firstGraph; | ||||
} | ||||
r852 | void dropGraph(int index, VisualizationZoneWidget *zoneWidget); | |||
void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index, | ||||
VisualizationZoneWidget *zoneWidget); | ||||
r539 | }; | |||
|
r197 | VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent) | ||
r842 | : VisualizationDragWidget{parent}, | |||
r539 | ui{new Ui::VisualizationZoneWidget}, | |||
impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()} | ||||
r58 | { | |||
ui->setupUi(this); | ||||
|
r197 | |||
ui->zoneNameLabel->setText(name); | ||||
|
r265 | |||
r887 | ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph); | |||
r885 | ui->dragDropContainer->addAcceptedMimeType( | |||
MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted); | ||||
ui->dragDropContainer->addAcceptedMimeType( | ||||
MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged); | ||||
ui->dragDropContainer->addAcceptedMimeType( | ||||
MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged); | ||||
r852 | ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) { | |||
return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData, | ||||
ui->dragDropContainer); | ||||
}); | ||||
r881 | ||||
connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this, | ||||
r847 | &VisualizationZoneWidget::dropMimeData); | |||
r881 | connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this, | |||
&VisualizationZoneWidget::dropMimeDataOnGraph); | ||||
r842 | ||||
|
r265 | // 'Close' options : widget is deleted when closed | ||
setAttribute(Qt::WA_DeleteOnClose); | ||||
connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close); | ||||
ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); | ||||
r539 | ||||
// Synchronisation id | ||||
QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId", | ||||
Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId)); | ||||
r58 | } | |||
VisualizationZoneWidget::~VisualizationZoneWidget() | ||||
{ | ||||
delete ui; | ||||
} | ||||
r118 | ||||
void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget) | ||||
{ | ||||
|
r730 | // Synchronize new graph with others in the zone | ||
impl->m_Synchronizer->addGraph(*graphWidget); | ||||
r842 | ui->dragDropContainer->addDragWidget(graphWidget); | |||
} | ||||
void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget) | ||||
{ | ||||
// Synchronize new graph with others in the zone | ||||
impl->m_Synchronizer->addGraph(*graphWidget); | ||||
ui->dragDropContainer->insertDragWidget(index, graphWidget); | ||||
r118 | } | |||
|
r200 | VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable) | ||
r842 | { | |||
return createGraph(variable, -1); | ||||
} | ||||
r847 | VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable, | |||
int index) | ||||
r118 | { | |||
r847 | auto graphWidget | |||
= new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this}; | ||||
|
r307 | |||
r444 | ||||
|
r307 | // Set graph properties | ||
graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); | ||||
graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT); | ||||
|
r200 | |||
r444 | // Lambda to synchronize zone widget | |||
r545 | auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange, | |||
r539 | const SqpRange &oldGraphRange) { | |||
r545 | auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange); | |||
r842 | auto frameLayout = ui->dragDropContainer->layout(); | |||
r444 | for (auto i = 0; i < frameLayout->count(); ++i) { | |||
auto graphChild | ||||
= dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget()); | ||||
if (graphChild && (graphChild != graphWidget)) { | ||||
auto graphChildRange = graphChild->graphRange(); | ||||
switch (zoomType) { | ||||
r539 | case AcquisitionZoomType::ZoomIn: { | |||
r545 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; | |||
auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; | ||||
r444 | graphChildRange.m_TStart += deltaLeft; | |||
graphChildRange.m_TEnd -= deltaRight; | ||||
r627 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn"); | |||
r848 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft") | |||
<< deltaLeft; | ||||
qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight") | ||||
<< deltaRight; | ||||
r627 | qCDebug(LOG_VisualizationZoneWidget()) | |||
r545 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; | |||
r445 | ||||
r444 | break; | |||
} | ||||
r539 | case AcquisitionZoomType::ZoomOut: { | |||
r627 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut"); | |||
r545 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; | |||
auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; | ||||
r848 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft") | |||
<< deltaLeft; | ||||
qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight") | ||||
<< deltaRight; | ||||
r627 | qCDebug(LOG_VisualizationZoneWidget()) | |||
r545 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; | |||
r444 | graphChildRange.m_TStart -= deltaLeft; | |||
graphChildRange.m_TEnd += deltaRight; | ||||
break; | ||||
} | ||||
r539 | case AcquisitionZoomType::PanRight: { | |||
r627 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight"); | |||
r814 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; | |||
r545 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; | |||
r814 | graphChildRange.m_TStart += deltaLeft; | |||
r444 | graphChildRange.m_TEnd += deltaRight; | |||
r627 | qCDebug(LOG_VisualizationZoneWidget()) | |||
r545 | << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart; | |||
r444 | break; | |||
} | ||||
r539 | case AcquisitionZoomType::PanLeft: { | |||
r627 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft"); | |||
r545 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; | |||
r814 | auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; | |||
r444 | graphChildRange.m_TStart -= deltaLeft; | |||
r814 | graphChildRange.m_TEnd -= deltaRight; | |||
r444 | break; | |||
} | ||||
r539 | case AcquisitionZoomType::Unknown: { | |||
r627 | qCDebug(LOG_VisualizationZoneWidget()) | |||
r444 | << tr("Impossible to synchronize: zoom type unknown"); | |||
break; | ||||
} | ||||
default: | ||||
qCCritical(LOG_VisualizationZoneWidget()) | ||||
<< tr("Impossible to synchronize: zoom type not take into account"); | ||||
// No action | ||||
break; | ||||
} | ||||
r539 | graphChild->enableAcquisition(false); | |||
r848 | qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ") | |||
<< graphChild->graphRange(); | ||||
qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ") | ||||
<< graphChildRange; | ||||
r627 | qCDebug(LOG_VisualizationZoneWidget()) | |||
r445 | << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart; | |||
graphChild->setGraphRange(graphChildRange); | ||||
r539 | graphChild->enableAcquisition(true); | |||
r444 | } | |||
} | ||||
}; | ||||
// connection for synchronization | ||||
connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget); | ||||
r540 | connect(graphWidget, &VisualizationGraphWidget::variableAdded, this, | |||
&VisualizationZoneWidget::onVariableAdded); | ||||
|
r737 | connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this, | ||
&VisualizationZoneWidget::onVariableAboutToBeRemoved); | ||||
r540 | ||||
r548 | auto range = SqpRange{}; | |||
r884 | if (auto firstGraph = impl->firstGraph(this)) { | |||
r548 | // Case of a new graph in a existant zone | |||
r884 | range = firstGraph->graphRange(); | |||
r548 | } | |||
else { | ||||
// Case of a new graph as the first of the zone | ||||
range = variable->range(); | ||||
} | ||||
r842 | this->insertGraph(index, graphWidget); | |||
r540 | ||||
r548 | graphWidget->addVariable(variable, range); | |||
|
r615 | |||
// get y using variable range | ||||
if (auto dataSeries = variable->dataSeries()) { | ||||
r636 | dataSeries->lockRead(); | |||
r637 | auto valuesBounds | |||
r847 | = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd); | |||
|
r615 | auto end = dataSeries->cend(); | ||
if (valuesBounds.first != end && valuesBounds.second != end) { | ||||
auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; }; | ||||
auto minValue = rangeValue(valuesBounds.first->minValue()); | ||||
auto maxValue = rangeValue(valuesBounds.second->maxValue()); | ||||
graphWidget->setYRange(SqpRange{minValue, maxValue}); | ||||
} | ||||
r636 | dataSeries->unlock(); | |||
|
r615 | } | ||
r444 | ||||
r118 | return graphWidget; | |||
} | ||||
r847 | VisualizationGraphWidget * | |||
VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index) | ||||
r842 | { | |||
r847 | if (variables.isEmpty()) { | |||
r842 | return nullptr; | |||
r847 | } | |||
r842 | ||||
auto graphWidget = createGraph(variables.first(), index); | ||||
r847 | for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) { | |||
r842 | graphWidget->addVariable(*variableIt, graphWidget->graphRange()); | |||
} | ||||
return graphWidget; | ||||
} | ||||
|
r207 | void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor) | ||
r118 | { | |||
|
r208 | if (visitor) { | ||
visitor->visitEnter(this); | ||||
|
r738 | // Apply visitor to graph children: widgets different from graphs are not visited (no | ||
// action) | ||||
processGraphs( | ||||
r842 | *ui->dragDropContainer->layout(), | |||
|
r738 | [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); }); | ||
|
r208 | |||
visitor->visitLeave(this); | ||||
} | ||||
|
r219 | else { | ||
qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null"); | ||||
} | ||||
r118 | } | |||
|
r209 | bool VisualizationZoneWidget::canDrop(const Variable &variable) const | ||
{ | ||||
// A tab can always accomodate a variable | ||||
Q_UNUSED(variable); | ||||
return true; | ||||
} | ||||
|
r327 | bool VisualizationZoneWidget::contains(const Variable &variable) const | ||
{ | ||||
Q_UNUSED(variable); | ||||
return false; | ||||
} | ||||
r119 | QString VisualizationZoneWidget::name() const | |||
r118 | { | |||
|
r197 | return ui->zoneNameLabel->text(); | ||
r118 | } | |||
r540 | ||||
r842 | QMimeData *VisualizationZoneWidget::mimeData() const | |||
{ | ||||
r849 | auto mimeData = new QMimeData; | |||
r876 | mimeData->setData(MIME_TYPE_ZONE, QByteArray{}); | |||
r842 | ||||
return mimeData; | ||||
} | ||||
bool VisualizationZoneWidget::isDragAllowed() const | ||||
{ | ||||
return true; | ||||
} | ||||
|
r738 | void VisualizationZoneWidget::closeEvent(QCloseEvent *event) | ||
{ | ||||
// Closes graphs in the zone | ||||
r842 | processGraphs(*ui->dragDropContainer->layout(), | |||
|
r738 | [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); }); | ||
|
r739 | // Delete synchronization group from variable controller | ||
QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId", | ||||
Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId)); | ||||
|
r738 | QWidget::closeEvent(event); | ||
} | ||||
r540 | void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable) | |||
{ | ||||
QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized", | ||||
Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable), | ||||
Q_ARG(QUuid, impl->m_SynchronisationGroupId)); | ||||
} | ||||
|
r737 | |||
void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable) | ||||
{ | ||||
QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection, | ||||
Q_ARG(std::shared_ptr<Variable>, variable), | ||||
Q_ARG(QUuid, impl->m_SynchronisationGroupId)); | ||||
} | ||||
r842 | ||||
void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData) | ||||
{ | ||||
r850 | if (mimeData->hasFormat(MIME_TYPE_GRAPH)) { | |||
r852 | impl->dropGraph(index, this); | |||
} | ||||
else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) { | ||||
auto variables = sqpApp->variableController().variablesForMimeData( | ||||
mimeData->data(MIME_TYPE_VARIABLE_LIST)); | ||||
impl->dropVariables(variables, index, this); | ||||
} | ||||
else { | ||||
qCWarning(LOG_VisualizationZoneWidget()) | ||||
<< tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received."); | ||||
} | ||||
} | ||||
r881 | void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, | |||
const QMimeData *mimeData) | ||||
{ | ||||
auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget); | ||||
if (!graphWidget) { | ||||
qCWarning(LOG_VisualizationZoneWidget()) | ||||
<< tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, " | ||||
"drop aborted"); | ||||
Q_ASSERT(false); | ||||
return; | ||||
} | ||||
if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) { | ||||
auto variables = sqpApp->variableController().variablesForMimeData( | ||||
mimeData->data(MIME_TYPE_VARIABLE_LIST)); | ||||
for (const auto &var : variables) { | ||||
graphWidget->addVariable(var, graphWidget->graphRange()); | ||||
} | ||||
} | ||||
r885 | else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) { | |||
auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE)); | ||||
graphWidget->setGraphRange(range); | ||||
} | ||||
r881 | else { | |||
qCWarning(LOG_VisualizationZoneWidget()) | ||||
<< tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received."); | ||||
} | ||||
} | ||||
r852 | void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph( | |||
int index, VisualizationZoneWidget *zoneWidget) | ||||
{ | ||||
auto &helper = sqpApp->dragDropHelper(); | ||||
auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget()); | ||||
if (!graphWidget) { | ||||
qCWarning(LOG_VisualizationZoneWidget()) | ||||
<< tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not " | ||||
"found or invalid."); | ||||
Q_ASSERT(false); | ||||
return; | ||||
} | ||||
auto parentDragDropContainer | ||||
= qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget()); | ||||
if (!parentDragDropContainer) { | ||||
qCWarning(LOG_VisualizationZoneWidget()) | ||||
<< tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of " | ||||
"the dropped graph is not found."); | ||||
Q_ASSERT(false); | ||||
return; | ||||
} | ||||
const auto &variables = graphWidget->variables(); | ||||
r844 | ||||
r852 | if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) { | |||
// The drop didn't occur in the same zone | ||||
// Abort the requests for the variables (if any) | ||||
// Commented, because it's not sure if it's needed or not | ||||
// for (const auto& var : variables) | ||||
//{ | ||||
// sqpApp->variableController().onAbortProgressRequested(var); | ||||
//} | ||||
auto previousParentZoneWidget = graphWidget->parentZoneWidget(); | ||||
auto nbGraph = parentDragDropContainer->countDragWidget(); | ||||
if (nbGraph == 1) { | ||||
// This is the only graph in the previous zone, close the zone | ||||
previousParentZoneWidget->close(); | ||||
r844 | } | |||
r847 | else { | |||
r852 | // Close the graph | |||
graphWidget->close(); | ||||
} | ||||
// Creates the new graph in the zone | ||||
zoneWidget->createGraph(variables, index); | ||||
} | ||||
else { | ||||
// The drop occurred in the same zone or the graph is empty | ||||
// Simple move of the graph, no variable operation associated | ||||
parentDragDropContainer->layout()->removeWidget(graphWidget); | ||||
if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) { | ||||
// The graph is empty and dropped in a different zone. | ||||
// Take the range of the first graph in the zone (if existing). | ||||
auto layout = zoneWidget->ui->dragDropContainer->layout(); | ||||
if (layout->count() > 0) { | ||||
if (auto visualizationGraphWidget | ||||
= qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) { | ||||
graphWidget->setGraphRange(visualizationGraphWidget->graphRange()); | ||||
r844 | } | |||
} | ||||
r852 | } | |||
zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget); | ||||
} | ||||
} | ||||
void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables( | ||||
const QList<std::shared_ptr<Variable> > &variables, int index, | ||||
VisualizationZoneWidget *zoneWidget) | ||||
{ | ||||
r876 | // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and | |||
// compatible variable here | ||||
if (variables.count() > 1) { | ||||
r852 | qCWarning(LOG_VisualizationZoneWidget()) | |||
r876 | << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation " | |||
"aborted."); | ||||
r852 | return; | |||
} | ||||
r877 | zoneWidget->createGraph(variables, index); | |||
r842 | } | |||