diff --git a/app/meson.build b/app/meson.build index 7a56baa..49466a0 100644 --- a/app/meson.build +++ b/app/meson.build @@ -28,9 +28,10 @@ else endif app_libs = [] - +cpp_args = [] if 'static' == get_option('default_library') app_libs = [ sciqlop_amdaplugin, sciqlop_mockplugin] + cpp_args += ['-DQT_STATICPLUGIN'] endif sciqlop_app = executable('sciqlop', @@ -39,7 +40,7 @@ sciqlop_app = executable('sciqlop', rc, include_directories : [ app_inc], link_with: app_libs, + cpp_args: cpp_args, dependencies : [sciqlop_gui, sciqlop_core], install : true ) - diff --git a/build_cfg/linux/appImage.sh b/build_cfg/linux/appImage.sh index 3435b6d..aa1405c 100644 --- a/build_cfg/linux/appImage.sh +++ b/build_cfg/linux/appImage.sh @@ -5,7 +5,6 @@ meson --prefix=/usr .. ninja DESTDIR=AppDir ninja install mv AppDir/usr/lib64 AppDir/usr/lib -mv AppDir/usr/lib/*plugin.so AppDir/usr/bin/ wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage chmod +x linuxdeployqt-continuous-x86_64.AppImage && ./linuxdeployqt-continuous-x86_64.AppImage --appimage-extract LD_LIBRARY_PATH=AppDir/usr/lib64/ ./squashfs-root/AppRun AppDir/usr/share/applications/*.desktop -appimage diff --git a/gui/src/Visualization/VisualizationDragDropContainer.cpp b/gui/src/Visualization/VisualizationDragDropContainer.cpp index b79b8b9..648a215 100644 --- a/gui/src/Visualization/VisualizationDragDropContainer.cpp +++ b/gui/src/Visualization/VisualizationDragDropContainer.cpp @@ -1,496 +1,554 @@ -#include "Visualization/VisualizationDragDropContainer.h" -#include "DragAndDrop/DragDropGuiController.h" -#include "SqpApplication.h" -#include "Visualization/VisualizationDragWidget.h" - -#include "Common/VisualizationDef.h" - -#include -#include -#include - -#include -#include - -Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer") - -auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels - -struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate { - - QVBoxLayout *m_Layout; - QHash m_AcceptedMimeTypes; - QString m_PlaceHolderText; - DragDropGuiController::PlaceHolderType m_PlaceHolderType; - - VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun - = [](auto mimeData) { return true; }; - VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun - = [](auto dragWidget, auto mimeData) { return true; }; - - int m_MinContainerHeight = 0; - - explicit VisualizationDragDropContainerPrivate(QWidget *widget) - : m_PlaceHolderType(DragDropGuiController::PlaceHolderType::Graph) - { - m_Layout = new QVBoxLayout(widget); - m_Layout->setContentsMargins(0, 0, 0, 0); - } - - bool acceptMimeData(const QMimeData *data) const - { - auto accepted = false; - for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); - ++it) { - const auto &type = it.key(); - const auto &behavior = it.value(); - - if (data->hasFormat(type)) { - if (behavior != DropBehavior::Forbidden) { - accepted = true; - } - else { - accepted = false; - break; - } - } - } - - if (accepted) { - accepted = m_AcceptMimeDataFun(data); - } - - return accepted; - } - - bool allowMergeForMimeData(const QMimeData *data) const - { - auto result = false; - for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); - ++it) { - - if (data->hasFormat(it.key()) - && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged - || it.value() - == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) { - result = true; - } - else if (data->hasFormat(it.key()) - && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) { - // Merge is forbidden if the mime data contain an acceptable type which cannot be - // merged - result = false; - break; - } - } - - return result; - } - - bool allowInsertForMimeData(const QMimeData *data) const - { - for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); - ++it) { - if (data->hasFormat(it.key()) - && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted - || it.value() - == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) { - return true; - } - } - - return false; - } - - bool hasPlaceHolder() const - { - return sqpApp->dragDropGuiController().placeHolder().parentWidget() - == m_Layout->parentWidget(); - } - - VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const - { - VisualizationDragWidget *dragWidget = nullptr; - - for (auto child : parent->children()) { - auto widget = qobject_cast(child); - if (widget && widget->isVisible()) { - if (widget->frameGeometry().contains(pos)) { - dragWidget = widget; - break; - } - } - } - - return dragWidget; - } - - bool cursorIsInContainer(QWidget *container) const - { - auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos()); - return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container - && sqpApp->dragDropGuiController().placeHolder().isAncestorOf(widgetUnderMouse); - } - - int countDragWidget(const QWidget *parent, bool onlyVisible = false) const - { - auto nbGraph = 0; - for (auto child : parent->children()) { - if (qobject_cast(child)) { - if (!onlyVisible || qobject_cast(child)->isVisible()) { - nbGraph += 1; - } - } - } - - return nbGraph; - } - - bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert, - bool canMerge, const VisualizationDragDropContainer *container); -}; - -VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent) - : QFrame{parent}, - impl{spimpl::make_unique_impl(this)} -{ - setAcceptDrops(true); -} - -void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget) -{ - impl->m_Layout->addWidget(dragWidget); - disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); - connect(dragWidget, &VisualizationDragWidget::dragDetected, this, - &VisualizationDragDropContainer::startDrag); -} - -void VisualizationDragDropContainer::insertDragWidget(int index, - VisualizationDragWidget *dragWidget) -{ - impl->m_Layout->insertWidget(index, dragWidget); - disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); - connect(dragWidget, &VisualizationDragWidget::dragDetected, this, - &VisualizationDragDropContainer::startDrag); -} - -void VisualizationDragDropContainer::setMimeType( - const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior) -{ - impl->m_AcceptedMimeTypes[mimeType] = behavior; -} - -int VisualizationDragDropContainer::countDragWidget() const -{ - return impl->countDragWidget(this); -} - -void VisualizationDragDropContainer::setAcceptMimeDataFunction( - VisualizationDragDropContainer::AcceptMimeDataFunction fun) -{ - impl->m_AcceptMimeDataFun = fun; -} - -void VisualizationDragDropContainer::setAcceptDragWidgetFunction( - VisualizationDragDropContainer::AcceptDragWidgetFunction fun) -{ - impl->m_AcceptDragWidgetFun = fun; -} - -void VisualizationDragDropContainer::setPlaceHolderType(DragDropGuiController::PlaceHolderType type, - const QString &placeHolderText) -{ - impl->m_PlaceHolderType = type; - impl->m_PlaceHolderText = placeHolderText; -} - -void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget, - const QPoint &dragPosition) -{ - auto &helper = sqpApp->dragDropGuiController(); - helper.resetDragAndDrop(); - - // Note: The management of the drag object is done by Qt - auto drag = new QDrag{dragWidget}; - - auto mimeData = dragWidget->mimeData(dragPosition); - drag->setMimeData(mimeData); - - auto pixmap = dragWidget->customDragPixmap(dragPosition); - if (pixmap.isNull()) { - pixmap = QPixmap{dragWidget->size()}; - dragWidget->render(&pixmap); - } - - drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH, - Qt::KeepAspectRatio, Qt::SmoothTransformation)); - - auto image = pixmap.toImage(); - mimeData->setImageData(image); - mimeData->setUrls({helper.imageTemporaryUrl(image)}); - - if (impl->m_Layout->indexOf(dragWidget) >= 0) { - - if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) { - helper.setCurrentDragWidget(dragWidget); - - if (impl->cursorIsInContainer(this)) { - auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget); - helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType, - impl->m_PlaceHolderText); - dragWidget->setVisible(false); - } - else { - // The drag starts directly outside the drop zone - // do not add the placeHolder - } - } - - drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction); - - helper.doCloseWidgets(); - } - else { - qCWarning(LOG_VisualizationDragDropContainer()) - << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified " - "VisualizationDragWidget is not found in this container."); - } -} - -void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event) -{ - if (impl->acceptMimeData(event->mimeData())) { - event->acceptProposedAction(); - - auto &helper = sqpApp->dragDropGuiController(); - - if (!impl->hasPlaceHolder()) { - auto dragWidget = helper.getCurrentDragWidget(); - - if (dragWidget) { - // If the drag&drop is internal to the visualization, entering the container hide - // the dragWidget which was made visible by the dragLeaveEvent - auto parentWidget - = qobject_cast(dragWidget->parentWidget()); - if (parentWidget) { - dragWidget->setVisible(false); - } - } - - auto canMerge = impl->allowMergeForMimeData(event->mimeData()); - auto canInsert = impl->allowInsertForMimeData(event->mimeData()); - if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, - this)) { - event->ignore(); - } - } - else { - // do nothing - } - } - else { - event->ignore(); - } - - QWidget::dragEnterEvent(event); -} - -void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event) -{ - Q_UNUSED(event); - - auto &helper = sqpApp->dragDropGuiController(); - - if (!impl->cursorIsInContainer(this)) { - helper.removePlaceHolder(); - helper.setHightlightedDragWidget(nullptr); - impl->m_MinContainerHeight = 0; - - auto dragWidget = helper.getCurrentDragWidget(); - if (dragWidget) { - // dragWidget has a value only if the drag is started from the visualization - // In that case, shows the drag widget at its original place - // So the drag widget doesn't stay hidden if the drop occurs outside the visualization - // drop zone (It is not possible to catch a drop event outside of the application) - - if (dragWidget) { - dragWidget->setVisible(true); - } - } - } - else { - // Leave event probably received for a child widget. - // Do nothing. - // Note: The DragLeave event, doesn't have any mean to determine who sent it. - } - - QWidget::dragLeaveEvent(event); -} - -void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event) -{ - if (impl->acceptMimeData(event->mimeData())) { - auto canMerge = impl->allowMergeForMimeData(event->mimeData()); - auto canInsert = impl->allowInsertForMimeData(event->mimeData()); - impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this); - } - else { - event->ignore(); - } - - QWidget::dragMoveEvent(event); -} - -void VisualizationDragDropContainer::dropEvent(QDropEvent *event) -{ - auto &helper = sqpApp->dragDropGuiController(); - - if (impl->acceptMimeData(event->mimeData())) { - auto dragWidget = helper.getCurrentDragWidget(); - if (impl->hasPlaceHolder()) { - // drop where the placeHolder is located - - auto canInsert = impl->allowInsertForMimeData(event->mimeData()); - if (canInsert) { - auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder()); - - if (dragWidget) { - auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget); - if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) { - // Correction of the index if the drop occurs in the same container - // and if the drag is started from the visualization (in that case, the - // dragWidget is hidden) - droppedIndex -= 1; - } - - dragWidget->setVisible(true); - } - - event->acceptProposedAction(); - - helper.removePlaceHolder(); - - emit dropOccuredInContainer(droppedIndex, event->mimeData()); - } - else { - qCWarning(LOG_VisualizationDragDropContainer()) << tr( - "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but " - "the insertion is forbidden."); - Q_ASSERT(false); - } - } - else if (helper.getHightlightedDragWidget()) { - // drop on the highlighted widget - - auto canMerge = impl->allowMergeForMimeData(event->mimeData()); - if (canMerge) { - event->acceptProposedAction(); - emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData()); - } - else { - qCWarning(LOG_VisualizationDragDropContainer()) - << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but " - "the merge is forbidden."); - Q_ASSERT(false); - } - } - } - else { - event->ignore(); - } - - sqpApp->dragDropGuiController().setHightlightedDragWidget(nullptr); - impl->m_MinContainerHeight = 0; - - QWidget::dropEvent(event); -} - - -bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition( - const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge, - const VisualizationDragDropContainer *container) -{ - auto &helper = sqpApp->dragDropGuiController(); - - auto absPos = container->mapToGlobal(pos); - auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos)); - - if (countDragWidget(container, true) == 0) { - // Drop on an empty container, just add the placeHolder at the top - helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText); - } - else if (!isOnPlaceHolder) { - auto nbDragWidget = countDragWidget(container); - if (nbDragWidget > 0) { - - if (m_MinContainerHeight == 0) { - m_MinContainerHeight = container->size().height(); - } - - m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height()); - auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT); - - auto posY = pos.y(); - auto dropIndex = floor(posY / graphHeight); - auto zoneSize = graphHeight / 4.0; - - - auto isOnTop = posY < dropIndex * graphHeight + zoneSize; - auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize; - - auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder())); - - auto dragWidgetHovered = getChildDragWidgetAt(container, pos); - - auto acceptMerge = m_AcceptDragWidgetFun(dragWidgetHovered, mimeData); - - if (canInsert && (isOnTop || isOnBottom || !canMerge || !acceptMerge)) { - if (posY > (dropIndex + 1) * graphHeight - graphHeight / 2.0) { - dropIndex += 1; - } - - if (helper.getCurrentDragWidget()) { - auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget()); - if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) { - // Correction of the index if the drop occurs in the same container - // and if the drag is started from the visualization (in that case, the - // dragWidget is hidden) - dropIndex += 1; - } - } - - if (dropIndex != placeHolderIndex) { - helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType, - m_PlaceHolderText); - } - - helper.setHightlightedDragWidget(nullptr); - } - else if (canMerge && dragWidgetHovered) { - // drop on the middle -> merge - if (hasPlaceHolder()) { - helper.removePlaceHolder(); - } - - helper.setHightlightedDragWidget(dragWidgetHovered); - } - else { - qCWarning(LOG_VisualizationDragDropContainer()) - << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop " - "action."); - } - } - else { - qCInfo(LOG_VisualizationDragDropContainer()) - << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget " - "found in the " - "container"); - } - } - else { - // the mouse is hover the placeHolder - // Do nothing - } - - return true; -} +#include "Visualization/VisualizationDragDropContainer.h" +#include "DragAndDrop/DragDropGuiController.h" +#include "SqpApplication.h" +#include "Visualization/VisualizationDragWidget.h" + +#include "Common/VisualizationDef.h" + +#include +#include +#include + +#include +#include + +Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer") + +auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels + +struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate +{ + + QVBoxLayout* m_Layout; + QHash m_AcceptedMimeTypes; + QString m_PlaceHolderText; + DragDropGuiController::PlaceHolderType m_PlaceHolderType; + + VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun + = [](auto mimeData) { return true; }; + VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun + = [](auto dragWidget, auto mimeData) { return true; }; + + int m_MinContainerHeight = 0; + + explicit VisualizationDragDropContainerPrivate(QWidget* widget) + : m_PlaceHolderType(DragDropGuiController::PlaceHolderType::Graph) + { + m_Layout = new QVBoxLayout(widget); + m_Layout->setContentsMargins(0, 0, 0, 0); + } + + bool acceptMimeData(const QMimeData* data) const + { + auto accepted = false; + for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); ++it) + { + const auto& type = it.key(); + const auto& behavior = it.value(); + + if (data->hasFormat(type)) + { + if (behavior != DropBehavior::Forbidden) + { + accepted = true; + } + else + { + accepted = false; + break; + } + } + } + + if (accepted) + { + accepted = m_AcceptMimeDataFun(data); + } + + return accepted; + } + + bool allowMergeForMimeData(const QMimeData* data) const + { + auto result = false; + for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); ++it) + { + + if (data->hasFormat(it.key()) + && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged + || it.value() + == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) + { + result = true; + } + else if (data->hasFormat(it.key()) + && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) + { + // Merge is forbidden if the mime data contain an acceptable type which cannot be + // merged + result = false; + break; + } + } + + return result; + } + + bool allowInsertForMimeData(const QMimeData* data) const + { + for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd(); ++it) + { + if (data->hasFormat(it.key()) + && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted + || it.value() + == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) + { + return true; + } + } + + return false; + } + + bool hasPlaceHolder() const + { + return sqpApp->dragDropGuiController().placeHolder().parentWidget() + == m_Layout->parentWidget(); + } + + VisualizationDragWidget* getChildDragWidgetAt(const QWidget* parent, const QPoint& pos) const + { + VisualizationDragWidget* dragWidget = nullptr; + + for (auto child : parent->children()) + { + auto widget = qobject_cast(child); + if (widget && widget->isVisible()) + { + if (widget->frameGeometry().contains(pos)) + { + dragWidget = widget; + break; + } + } + } + + return dragWidget; + } + + bool cursorIsInContainer(QWidget* container) const + { + auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos()); + return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container + && sqpApp->dragDropGuiController().placeHolder().isAncestorOf(widgetUnderMouse); + } + + int countDragWidget(const QWidget* parent, bool onlyVisible = false) const + { + auto nbGraph = 0; + for (auto child : parent->children()) + { + if (qobject_cast(child)) + { + if (!onlyVisible || qobject_cast(child)->isVisible()) + { + nbGraph += 1; + } + } + } + + return nbGraph; + } + + bool findPlaceHolderPosition(const QPoint& pos, const QMimeData* mimeData, bool canInsert, + bool canMerge, const VisualizationDragDropContainer* container); +}; + +VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget* parent) + : QFrame { parent } + , impl { spimpl::make_unique_impl(this) } +{ + setAcceptDrops(true); +} + +void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget* dragWidget) +{ + impl->m_Layout->addWidget(dragWidget); + disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); + connect(dragWidget, &VisualizationDragWidget::dragDetected, this, + &VisualizationDragDropContainer::startDrag); +} + +void VisualizationDragDropContainer::insertDragWidget( + int index, VisualizationDragWidget* dragWidget) +{ + impl->m_Layout->insertWidget(index, dragWidget); + disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr); + connect(dragWidget, &VisualizationDragWidget::dragDetected, this, + &VisualizationDragDropContainer::startDrag); +} + +void VisualizationDragDropContainer::setMimeType( + const QString& mimeType, VisualizationDragDropContainer::DropBehavior behavior) +{ + impl->m_AcceptedMimeTypes[mimeType] = behavior; +} + +int VisualizationDragDropContainer::countDragWidget() const +{ + return impl->countDragWidget(this); +} + +void VisualizationDragDropContainer::setAcceptMimeDataFunction( + VisualizationDragDropContainer::AcceptMimeDataFunction fun) +{ + impl->m_AcceptMimeDataFun = fun; +} + +void VisualizationDragDropContainer::setAcceptDragWidgetFunction( + VisualizationDragDropContainer::AcceptDragWidgetFunction fun) +{ + impl->m_AcceptDragWidgetFun = fun; +} + +void VisualizationDragDropContainer::setPlaceHolderType( + DragDropGuiController::PlaceHolderType type, const QString& placeHolderText) +{ + impl->m_PlaceHolderType = type; + impl->m_PlaceHolderText = placeHolderText; +} + +void VisualizationDragDropContainer::startDrag( + VisualizationDragWidget* dragWidget, const QPoint& dragPosition) +{ + auto& helper = sqpApp->dragDropGuiController(); + helper.resetDragAndDrop(); + + // Note: The management of the drag object is done by Qt + auto drag = new QDrag { dragWidget }; + + auto mimeData = dragWidget->mimeData(dragPosition); + drag->setMimeData(mimeData); + + auto pixmap = dragWidget->customDragPixmap(dragPosition); + if (pixmap.isNull()) + { + pixmap = QPixmap { dragWidget->size() }; + dragWidget->render(&pixmap); + } + + drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH, + Qt::KeepAspectRatio, Qt::SmoothTransformation)); + + auto image = pixmap.toImage(); + mimeData->setImageData(image); + mimeData->setUrls({ helper.imageTemporaryUrl(image) }); + + if (impl->m_Layout->indexOf(dragWidget) >= 0) + { + + if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) + { + helper.setCurrentDragWidget(dragWidget); + + if (impl->cursorIsInContainer(this)) + { + auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget); + helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType, + impl->m_PlaceHolderText); + dragWidget->setVisible(false); + } + else + { + // The drag starts directly outside the drop zone + // do not add the placeHolder + } + } + + drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction); + + helper.doCloseWidgets(); + } + else + { + qCWarning(LOG_VisualizationDragDropContainer()) + << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified " + "VisualizationDragWidget is not found in this container."); + } +} + +void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent* event) +{ + if (impl->acceptMimeData(event->mimeData())) + { + event->acceptProposedAction(); + + auto& helper = sqpApp->dragDropGuiController(); + + if (!impl->hasPlaceHolder()) + { + auto dragWidget = helper.getCurrentDragWidget(); + + if (dragWidget) + { + // If the drag&drop is internal to the visualization, entering the container hide + // the dragWidget which was made visible by the dragLeaveEvent + auto parentWidget + = qobject_cast(dragWidget->parentWidget()); + if (parentWidget) + { + dragWidget->setVisible(false); + } + } + + auto canMerge = impl->allowMergeForMimeData(event->mimeData()); + auto canInsert = impl->allowInsertForMimeData(event->mimeData()); + if (!impl->findPlaceHolderPosition( + event->pos(), event->mimeData(), canInsert, canMerge, this)) + { + event->ignore(); + } + } + else + { + // do nothing + } + } + else + { + event->ignore(); + } + + QWidget::dragEnterEvent(event); +} + +void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent* event) +{ + Q_UNUSED(event); + + auto& helper = sqpApp->dragDropGuiController(); + + if (!impl->cursorIsInContainer(this)) + { + helper.removePlaceHolder(); + helper.setHightlightedDragWidget(nullptr); + impl->m_MinContainerHeight = 0; + + auto dragWidget = helper.getCurrentDragWidget(); + if (dragWidget) + { + // dragWidget has a value only if the drag is started from the visualization + // In that case, shows the drag widget at its original place + // So the drag widget doesn't stay hidden if the drop occurs outside the visualization + // drop zone (It is not possible to catch a drop event outside of the application) + + if (dragWidget) + { + dragWidget->setVisible(true); + } + } + } + else + { + // Leave event probably received for a child widget. + // Do nothing. + // Note: The DragLeave event, doesn't have any mean to determine who sent it. + } + + QWidget::dragLeaveEvent(event); +} + +void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent* event) +{ + if (impl->acceptMimeData(event->mimeData())) + { + event->acceptProposedAction(); + auto canMerge = impl->allowMergeForMimeData(event->mimeData()); + auto canInsert = impl->allowInsertForMimeData(event->mimeData()); + impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this); + } + else + { + event->ignore(); + } + + QWidget::dragMoveEvent(event); +} + +void VisualizationDragDropContainer::dropEvent(QDropEvent* event) +{ + auto& helper = sqpApp->dragDropGuiController(); + + if (impl->acceptMimeData(event->mimeData())) + { + auto dragWidget = helper.getCurrentDragWidget(); + if (impl->hasPlaceHolder()) + { + // drop where the placeHolder is located + + auto canInsert = impl->allowInsertForMimeData(event->mimeData()); + if (canInsert) + { + auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder()); + + if (dragWidget) + { + auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget); + if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) + { + // Correction of the index if the drop occurs in the same container + // and if the drag is started from the visualization (in that case, the + // dragWidget is hidden) + droppedIndex -= 1; + } + + dragWidget->setVisible(true); + } + + event->acceptProposedAction(); + + helper.removePlaceHolder(); + + emit dropOccuredInContainer(droppedIndex, event->mimeData()); + } + else + { + qCWarning(LOG_VisualizationDragDropContainer()) << tr( + "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but " + "the insertion is forbidden."); + Q_ASSERT(false); + } + } + else if (helper.getHightlightedDragWidget()) + { + // drop on the highlighted widget + + auto canMerge = impl->allowMergeForMimeData(event->mimeData()); + if (canMerge) + { + event->acceptProposedAction(); + emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData()); + } + else + { + qCWarning(LOG_VisualizationDragDropContainer()) + << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but " + "the merge is forbidden."); + Q_ASSERT(false); + } + } + } + else + { + event->ignore(); + } + + sqpApp->dragDropGuiController().setHightlightedDragWidget(nullptr); + impl->m_MinContainerHeight = 0; + + QWidget::dropEvent(event); +} + + +bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition( + const QPoint& pos, const QMimeData* mimeData, bool canInsert, bool canMerge, + const VisualizationDragDropContainer* container) +{ + auto& helper = sqpApp->dragDropGuiController(); + + auto absPos = container->mapToGlobal(pos); + auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos)); + + if (countDragWidget(container, true) == 0) + { + // Drop on an empty container, just add the placeHolder at the top + helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText); + } + else if (!isOnPlaceHolder) + { + auto nbDragWidget = countDragWidget(container); + if (nbDragWidget > 0) + { + + if (m_MinContainerHeight == 0) + { + m_MinContainerHeight = container->size().height(); + } + + m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height()); + auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT); + + auto posY = pos.y(); + auto dropIndex = floor(posY / graphHeight); + auto zoneSize = graphHeight / 4.0; + + + auto isOnTop = posY < dropIndex * graphHeight + zoneSize; + auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize; + + auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder())); + + auto dragWidgetHovered = getChildDragWidgetAt(container, pos); + + auto acceptMerge = m_AcceptDragWidgetFun(dragWidgetHovered, mimeData); + + if (canInsert && (isOnTop || isOnBottom || !canMerge || !acceptMerge)) + { + if (posY > (dropIndex + 1) * graphHeight - graphHeight / 2.0) + { + dropIndex += 1; + } + + if (helper.getCurrentDragWidget()) + { + auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget()); + if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) + { + // Correction of the index if the drop occurs in the same container + // and if the drag is started from the visualization (in that case, the + // dragWidget is hidden) + dropIndex += 1; + } + } + + if (dropIndex != placeHolderIndex) + { + helper.insertPlaceHolder( + m_Layout, dropIndex, m_PlaceHolderType, m_PlaceHolderText); + } + + helper.setHightlightedDragWidget(nullptr); + } + else if (canMerge && dragWidgetHovered) + { + // drop on the middle -> merge + if (hasPlaceHolder()) + { + helper.removePlaceHolder(); + } + + helper.setHightlightedDragWidget(dragWidgetHovered); + } + else + { + qCWarning(LOG_VisualizationDragDropContainer()) + << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop " + "action."); + } + } + else + { + qCInfo(LOG_VisualizationDragDropContainer()) + << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget " + "found in the " + "container"); + } + } + else + { + // the mouse is hover the placeHolder + // Do nothing + } + + return true; +} diff --git a/meson.build b/meson.build index 29e80d4..68659a9 100644 --- a/meson.build +++ b/meson.build @@ -47,4 +47,4 @@ if cppcheck.found() command : [cppcheck, '--enable=all', '--project=' + join_paths(meson.build_root(), 'compile_commands.json')] ) -endif +endif \ No newline at end of file diff --git a/plugins/amda/meson.build b/plugins/amda/meson.build index 0b6d2f7..4fe9d66 100644 --- a/plugins/amda/meson.build +++ b/plugins/amda/meson.build @@ -30,13 +30,21 @@ amdaplugin_prep_files = qt5.preprocess(moc_headers : amdaplugin_moc_headers, qresources : amdaplugin_resources_files, ui_files : amdaplugin_ui_files) +cpp_args = ['-DAMDA_LIB','-DQT_PLUGIN'] +message('======================='+get_option('default_library')+'==========================') +if(get_option('default_library') == 'static') + message('building amda plugin as static lib') + cpp_args += ['-DQT_STATICPLUGIN'] +endif + sciqlop_amdaplugin = library('amdaplugin', amdaplugin_sources, amdaplugin_prep_files, - cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'], + cpp_args : cpp_args, include_directories : [amdaplugin_inc], dependencies : [sciqlop_core, sciqlop_gui], - install : true + install : true, + install_dir : join_paths(get_option('libdir'), 'SciQLop') ) diff --git a/plugins/mockplugin/meson.build b/plugins/mockplugin/meson.build index daa88ca..4b8cb8b 100644 --- a/plugins/mockplugin/meson.build +++ b/plugins/mockplugin/meson.build @@ -22,11 +22,17 @@ gen = generator(moc, mockplugin_moc_files = gen.process(mockplugin_moc_headers) +cpp_args = ['-DMOCKPLUGIN_LIB','-DQT_PLUGIN'] +if(get_option('default_library')=='static') + cpp_args += ['-DQT_STATICPLUGIN'] +endif + sciqlop_mockplugin = library('mockplugin', mockplugin_sources, mockplugin_moc_files, - cpp_args : '-DMOCKPLUGIN_LIB', + cpp_args : cpp_args, include_directories : [mockplugin_inc], dependencies : [sciqlop_core, sciqlop_gui], - install : true + install : true, + install_dir : join_paths(get_option('libdir'), 'SciQLop') )