DragDropGuiController.cpp
331 lines
| 10.6 KiB
| text/x-c
|
CppLexer
r1075 | #include "DragAndDrop/DragDropGuiController.h" | |||
r885 | #include "DragAndDrop/DragDropScroller.h" | |||
r886 | #include "DragAndDrop/DragDropTabSwitcher.h" | |||
r837 | #include "SqpApplication.h" | |||
r850 | #include "Visualization/VisualizationDragDropContainer.h" | |||
r844 | #include "Visualization/VisualizationDragWidget.h" | |||
r850 | #include "Visualization/VisualizationWidget.h" | |||
#include "Visualization/operations/FindVariableOperation.h" | ||||
r1287 | #include "DataSource/DataSourceController.h" | |||
r1348 | #include "Variable/VariableController2.h" | |||
r850 | ||||
#include "Common/MimeTypesDef.h" | ||||
#include "Common/VisualizationDef.h" | ||||
r837 | ||||
r844 | #include <QDir> | |||
r881 | #include <QLabel> | |||
r885 | #include <QUrl> | |||
r844 | #include <QVBoxLayout> | |||
r837 | ||||
r840 | ||||
r1075 | Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController") | |||
r850 | ||||
r837 | ||||
r1420 | struct DragDropGuiController::DragDropGuiControllerPrivate | |||
{ | ||||
r837 | ||||
r1420 | VisualizationDragWidget* m_CurrentDragWidget = nullptr; | |||
r844 | std::unique_ptr<QWidget> m_PlaceHolder = nullptr; | |||
r1420 | QLabel* m_PlaceHolderLabel; | |||
QWidget* m_PlaceBackground; | ||||
r844 | std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr; | |||
r886 | std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr; | |||
r844 | QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using | |||
// QTemporaryFile to have a name which is not generated. | ||||
r837 | ||||
r1420 | VisualizationDragWidget* m_HighlightedDragWidget = nullptr; | |||
r873 | ||||
r874 | QMetaObject::Connection m_DragWidgetDestroyedConnection; | |||
QMetaObject::Connection m_HighlightedWidgetDestroyedConnection; | ||||
r1420 | QList<QWidget*> m_WidgetToClose; | |||
Thibaud Rabillard
|
r911 | |||
r1075 | explicit DragDropGuiControllerPrivate() | |||
r1420 | : m_PlaceHolder { std::make_unique<QWidget>() } | |||
, m_DragDropScroller { std::make_unique<DragDropScroller>() } | ||||
, m_DragDropTabSwitcher { std::make_unique<DragDropTabSwitcher>() } | ||||
r837 | { | |||
r1420 | auto layout = new QVBoxLayout { m_PlaceHolder.get() }; | |||
r881 | layout->setSpacing(0); | |||
layout->setContentsMargins(0, 0, 0, 0); | ||||
r1420 | m_PlaceHolderLabel = new QLabel { "", m_PlaceHolder.get() }; | |||
r881 | m_PlaceHolderLabel->setMinimumHeight(25); | |||
layout->addWidget(m_PlaceHolderLabel); | ||||
r1420 | m_PlaceBackground = new QWidget { m_PlaceHolder.get() }; | |||
r881 | m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |||
layout->addWidget(m_PlaceBackground); | ||||
sqpApp->installEventFilter(m_DragDropScroller.get()); | ||||
r886 | sqpApp->installEventFilter(m_DragDropTabSwitcher.get()); | |||
r837 | ||||
r876 | m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png"); | |||
r837 | } | |||
r1420 | void preparePlaceHolder( | |||
DragDropGuiController::PlaceHolderType type, const QString& topLabelText) const | ||||
r837 | { | |||
r1420 | if (m_CurrentDragWidget) | |||
{ | ||||
r844 | m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size()); | |||
m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy()); | ||||
r837 | } | |||
r1420 | else | |||
{ | ||||
r850 | // Configuration of the placeHolder when there is no dragWidget | |||
// (for instance with a drag from a variable) | ||||
r851 | m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT); | |||
r850 | m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); | |||
r837 | } | |||
r881 | ||||
r1420 | switch (type) | |||
{ | ||||
r1075 | case DragDropGuiController::PlaceHolderType::Graph: | |||
r881 | m_PlaceBackground->setStyleSheet( | |||
"background-color: #BBD5EE; border: 1px solid #2A7FD4"); | ||||
break; | ||||
r1075 | case DragDropGuiController::PlaceHolderType::Zone: | |||
case DragDropGuiController::PlaceHolderType::Default: | ||||
r881 | m_PlaceBackground->setStyleSheet( | |||
"background-color: #BBD5EE; border: 2px solid #2A7FD4"); | ||||
m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4"); | ||||
break; | ||||
} | ||||
m_PlaceHolderLabel->setText(topLabelText); | ||||
m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty()); | ||||
r837 | } | |||
}; | ||||
r1075 | DragDropGuiController::DragDropGuiController() | |||
r1420 | : impl { spimpl::make_unique_impl<DragDropGuiControllerPrivate>() } | |||
r912 | { | |||
} | ||||
r837 | ||||
r1075 | DragDropGuiController::~DragDropGuiController() | |||
r837 | { | |||
r844 | QFile::remove(impl->m_ImageTempUrl); | |||
r837 | } | |||
r1075 | void DragDropGuiController::resetDragAndDrop() | |||
r850 | { | |||
setCurrentDragWidget(nullptr); | ||||
r873 | impl->m_HighlightedDragWidget = nullptr; | |||
r850 | } | |||
r1420 | void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget* dragWidget) | |||
r837 | { | |||
r1420 | if (impl->m_CurrentDragWidget) | |||
{ | ||||
r874 | ||||
QObject::disconnect(impl->m_DragWidgetDestroyedConnection); | ||||
} | ||||
r1420 | if (dragWidget) | |||
{ | ||||
r874 | // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed | |||
r1420 | impl->m_DragWidgetDestroyedConnection = QObject::connect(dragWidget, | |||
&VisualizationDragWidget::destroyed, [this]() { impl->m_CurrentDragWidget = nullptr; }); | ||||
r874 | } | |||
r844 | impl->m_CurrentDragWidget = dragWidget; | |||
r837 | } | |||
r1420 | VisualizationDragWidget* DragDropGuiController::getCurrentDragWidget() const | |||
r837 | { | |||
r844 | return impl->m_CurrentDragWidget; | |||
r837 | } | |||
r1420 | QWidget& DragDropGuiController::placeHolder() const | |||
r837 | { | |||
r844 | return *impl->m_PlaceHolder; | |||
r837 | } | |||
r1420 | void DragDropGuiController::insertPlaceHolder( | |||
QVBoxLayout* layout, int index, PlaceHolderType type, const QString& topLabelText) | ||||
r837 | { | |||
removePlaceHolder(); | ||||
r881 | impl->preparePlaceHolder(type, topLabelText); | |||
r844 | layout->insertWidget(index, impl->m_PlaceHolder.get()); | |||
impl->m_PlaceHolder->show(); | ||||
r837 | } | |||
r1075 | void DragDropGuiController::removePlaceHolder() | |||
r837 | { | |||
r844 | auto parentWidget = impl->m_PlaceHolder->parentWidget(); | |||
r1420 | if (parentWidget) | |||
{ | ||||
r844 | parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get()); | |||
impl->m_PlaceHolder->setParent(nullptr); | ||||
impl->m_PlaceHolder->hide(); | ||||
r837 | } | |||
} | ||||
r1075 | bool DragDropGuiController::isPlaceHolderSet() const | |||
r837 | { | |||
r844 | return impl->m_PlaceHolder->parentWidget(); | |||
r837 | } | |||
r1420 | void DragDropGuiController::addDragDropScrollArea(QScrollArea* scrollArea) | |||
r840 | { | |||
r844 | impl->m_DragDropScroller->addScrollArea(scrollArea); | |||
r840 | } | |||
r1420 | void DragDropGuiController::removeDragDropScrollArea(QScrollArea* scrollArea) | |||
r840 | { | |||
r844 | impl->m_DragDropScroller->removeScrollArea(scrollArea); | |||
r840 | } | |||
r1420 | void DragDropGuiController::addDragDropTabBar(QTabBar* tabBar) | |||
r886 | { | |||
impl->m_DragDropTabSwitcher->addTabBar(tabBar); | ||||
} | ||||
r1420 | void DragDropGuiController::removeDragDropTabBar(QTabBar* tabBar) | |||
r886 | { | |||
impl->m_DragDropTabSwitcher->removeTabBar(tabBar); | ||||
} | ||||
r1420 | QUrl DragDropGuiController::imageTemporaryUrl(const QImage& image) const | |||
r837 | { | |||
r844 | image.save(impl->m_ImageTempUrl); | |||
return QUrl::fromLocalFile(impl->m_ImageTempUrl); | ||||
r837 | } | |||
r850 | ||||
r1420 | void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget* dragWidget) | |||
r873 | { | |||
r1420 | if (impl->m_HighlightedDragWidget) | |||
{ | ||||
r873 | impl->m_HighlightedDragWidget->highlightForMerge(false); | |||
r874 | QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection); | |||
r873 | } | |||
r1420 | if (dragWidget) | |||
{ | ||||
r874 | dragWidget->highlightForMerge(true); | |||
// ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed | ||||
impl->m_DragWidgetDestroyedConnection | ||||
= QObject::connect(dragWidget, &VisualizationDragWidget::destroyed, | ||||
r1420 | [this]() { impl->m_HighlightedDragWidget = nullptr; }); | |||
r873 | } | |||
r874 | ||||
impl->m_HighlightedDragWidget = dragWidget; | ||||
r873 | } | |||
r1420 | VisualizationDragWidget* DragDropGuiController::getHightlightedDragWidget() const | |||
r875 | { | |||
return impl->m_HighlightedDragWidget; | ||||
} | ||||
r1420 | void DragDropGuiController::delayedCloseWidget(QWidget* widget) | |||
Thibaud Rabillard
|
r911 | { | ||
widget->hide(); | ||||
impl->m_WidgetToClose << widget; | ||||
} | ||||
r1075 | void DragDropGuiController::doCloseWidgets() | |||
Thibaud Rabillard
|
r911 | { | ||
r1420 | for (auto widget : impl->m_WidgetToClose) | |||
{ | ||||
Thibaud Rabillard
|
r911 | widget->close(); | ||
} | ||||
impl->m_WidgetToClose.clear(); | ||||
} | ||||
r1075 | bool DragDropGuiController::checkMimeDataForVisualization( | |||
r1420 | const QMimeData* mimeData, VisualizationDragDropContainer* dropContainer) | |||
r850 | { | |||
r1420 | if (!mimeData || !dropContainer) | |||
{ | ||||
r1075 | qCWarning(LOG_DragDropGuiController()) << QObject::tr( | |||
"DragDropGuiController::checkMimeDataForVisualization, invalid input parameters."); | ||||
r868 | Q_ASSERT(false); | |||
r876 | return false; | |||
r868 | } | |||
r876 | auto result = false; | |||
r850 | ||||
r1420 | if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) | |||
{ | ||||
r1348 | auto variables = sqpApp->variableController().variables( | |||
r1422 | Variable2::IDs(mimeData->data(MIME_TYPE_VARIABLE_LIST))); | |||
r850 | ||||
r1420 | if (variables.size() == 1) | |||
{ | ||||
r850 | ||||
r1348 | auto variable = variables[0]; | |||
r1420 | if (variable->data() != nullptr) | |||
{ | ||||
r876 | ||||
// Check that the variable is not already in a graph | ||||
r850 | ||||
r876 | auto parent = dropContainer->parentWidget(); | |||
r1420 | while (parent && qobject_cast<VisualizationWidget*>(parent) == nullptr) | |||
{ | ||||
r876 | parent = parent->parentWidget(); // Search for the top level VisualizationWidget | |||
} | ||||
r850 | ||||
r1420 | if (parent) | |||
{ | ||||
auto visualizationWidget = static_cast<VisualizationWidget*>(parent); | ||||
r876 | ||||
r1420 | FindVariableOperation findVariableOperation { variable }; | |||
r876 | visualizationWidget->accept(&findVariableOperation); | |||
auto variableContainers = findVariableOperation.result(); | ||||
r1420 | if (variableContainers.empty()) | |||
{ | ||||
r876 | result = true; | |||
} | ||||
r1420 | else | |||
{ | ||||
r876 | // result = false: the variable already exist in the visualisation | |||
} | ||||
} | ||||
r1420 | else | |||
{ | ||||
r1075 | qCWarning(LOG_DragDropGuiController()) << QObject::tr( | |||
"DragDropGuiController::checkMimeDataForVisualization, the parent " | ||||
r876 | "VisualizationWidget cannot be found. Cannot check if the variable is " | |||
"already used or not."); | ||||
r850 | } | |||
} | ||||
r1420 | else | |||
{ | ||||
r876 | // result = false: the variable is not fully loaded | |||
r850 | } | |||
} | ||||
r1420 | else | |||
{ | ||||
r876 | // result = false: cannot drop multiple variables in the visualisation | |||
r850 | } | |||
} | ||||
r1420 | else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) | |||
{ | ||||
r1287 | auto productDataList = sqpApp->dataSourceController().productsDataForMimeData( | |||
mimeData->data(MIME_TYPE_PRODUCT_LIST)); | ||||
r1420 | if (productDataList.count() == 1) | |||
{ | ||||
r1287 | result = true; | |||
} | ||||
r1420 | else | |||
{ | ||||
r1287 | // result = false: cannot drop multiple products in the visualisation | |||
} | ||||
} | ||||
r1420 | else | |||
{ | ||||
r876 | // Other MIME data | |||
// no special rules, accepted by default | ||||
result = true; | ||||
} | ||||
r850 | ||||
r1287 | ||||
r850 | return result; | |||
} | ||||