##// END OF EJS Templates
Creates method that computes thresholds of a SqpColorScale
Creates method that computes thresholds of a SqpColorScale

File last commit:

r1003:569b12637de1
r1059:63f62cbba482
Show More
VisualizationDragDropContainer.cpp
473 lines | 16.9 KiB | text/x-c | CppLexer
/ gui / src / Visualization / VisualizationDragDropContainer.cpp
New visualization classes for the drag&drop
r841 #include "Visualization/VisualizationDragDropContainer.h"
Moves the DragDropHelper file
r890 #include "DragAndDrop/DragDropHelper.h"
Format changes
r847 #include "SqpApplication.h"
#include "Visualization/VisualizationDragWidget.h"
New visualization classes for the drag&drop
r841
Move the GRAPH_MINIMUM_HEIGHT constant in a place accessible everywhere and use it in the drag&drop
r853 #include "Common/VisualizationDef.h"
New visualization classes for the drag&drop
r841 #include <QDrag>
#include <QDragEnterEvent>
Format changes
r847 #include <QVBoxLayout>
New visualization classes for the drag&drop
r841
MR for linux compilation
r848 #include <cmath>
New visualization classes for the drag&drop
r841 #include <memory>
drop of variables in the visualization
r852 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
Displays the miniature of the graph of the zone during a drag
r975 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
New visualization classes for the drag&drop
r841 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
Format changes
r847 QVBoxLayout *m_Layout;
Drag of the time widget on a graph
r885 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 QString m_PlaceHolderText;
Implements cursor mode
r1003 DragDropHelper::PlaceHolderType m_PlaceHolderType;
Drag of the time widget on a graph
r885
drop of variables in the visualization
r852 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
= [](auto mimeData) { return true; };
Drag of the time widget on a graph
r885
Improves visual effect of dropping a variable in a graph
r879 int m_MinContainerHeight = 0;
New visualization classes for the drag&drop
r841
Format changes
r847 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
Implements cursor mode
r1003 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
New visualization classes for the drag&drop
r841 {
Format changes
r847 m_Layout = new QVBoxLayout(widget);
m_Layout->setContentsMargins(0, 0, 0, 0);
New visualization classes for the drag&drop
r841 }
Format changes
r847 bool acceptMimeData(const QMimeData *data) const
New visualization classes for the drag&drop
r841 {
drop of zone on the time widget
r977 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;
}
Format changes
r847 }
New visualization classes for the drag&drop
r841 }
drop of zone on the time widget
r977 if (accepted) {
accepted = m_AcceptMimeDataFun(data);
}
return accepted;
New visualization classes for the drag&drop
r841 }
Drag of the time widget on a graph
r885 bool allowMergeForMimeData(const QMimeData *data) const
New visualization classes for the drag&drop
r841 {
code improvements
r980 auto result = false;
Drag of the time widget on a graph
r885 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)) {
New visualization classes for the drag&drop
r841 return true;
Format changes
r847 }
New visualization classes for the drag&drop
r841 }
return false;
}
bool hasPlaceHolder() const
{
Format changes
r847 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
New visualization classes for the drag&drop
r841 }
Improves visual effect of dropping a variable in a graph
r879 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
New visualization classes for the drag&drop
r841 {
Format changes
r847 VisualizationDragWidget *dragWidget = nullptr;
for (auto child : parent->children()) {
auto widget = qobject_cast<VisualizationDragWidget *>(child);
if (widget && widget->isVisible()) {
if (widget->frameGeometry().contains(pos)) {
New visualization classes for the drag&drop
r841 dragWidget = widget;
break;
}
}
}
return dragWidget;
}
Format changes
r847 bool cursorIsInContainer(QWidget *container) const
New visualization classes for the drag&drop
r841 {
fix some wrong drag&drop behavior appearing on mac
r979 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
&& sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
New visualization classes for the drag&drop
r841 }
Improves visual effect of dropping a variable in a graph
r879
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
Improves visual effect of dropping a variable in a graph
r879 {
auto nbGraph = 0;
for (auto child : parent->children()) {
if (qobject_cast<VisualizationDragWidget *>(child)) {
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
nbGraph += 1;
}
Improves visual effect of dropping a variable in a graph
r879 }
}
return nbGraph;
}
Drag of the time widget on a graph
r885 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
Improves visual effect of dropping a variable in a graph
r879 const VisualizationDragDropContainer *container);
New visualization classes for the drag&drop
r841 };
VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 : QFrame{parent},
Format changes
r847 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
New visualization classes for the drag&drop
r841 {
setAcceptDrops(true);
}
void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
{
Format changes
r847 impl->m_Layout->addWidget(dragWidget);
New visualization classes for the drag&drop
r841 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
Format changes
r847 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
&VisualizationDragDropContainer::startDrag);
New visualization classes for the drag&drop
r841 }
Format changes
r847 void VisualizationDragDropContainer::insertDragWidget(int index,
VisualizationDragWidget *dragWidget)
New visualization classes for the drag&drop
r841 {
Format changes
r847 impl->m_Layout->insertWidget(index, dragWidget);
New visualization classes for the drag&drop
r841 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
Format changes
r847 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
&VisualizationDragDropContainer::startDrag);
New visualization classes for the drag&drop
r841 }
drop of zone on the time widget
r977 void VisualizationDragDropContainer::setMimeType(
Drag of the time widget on a graph
r885 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
New visualization classes for the drag&drop
r841 {
Drag of the time widget on a graph
r885 impl->m_AcceptedMimeTypes[mimeType] = behavior;
New visualization classes for the drag&drop
r841 }
int VisualizationDragDropContainer::countDragWidget() const
{
Improves visual effect of dropping a variable in a graph
r879 return impl->countDragWidget(this);
New visualization classes for the drag&drop
r841 }
drop of variables in the visualization
r852 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
VisualizationDragDropContainer::AcceptMimeDataFunction fun)
{
impl->m_AcceptMimeDataFun = fun;
}
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
const QString &placeHolderText)
{
impl->m_PlaceHolderType = type;
impl->m_PlaceHolderText = placeHolderText;
}
Format changes
r847 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
const QPoint &dragPosition)
New visualization classes for the drag&drop
r841 {
Format changes
r847 auto &helper = sqpApp->dragDropHelper();
drop of variables in the visualization
r852 helper.resetDragAndDrop();
New visualization classes for the drag&drop
r841
Format changes
r847 // Note: The management of the drag object is done by Qt
Fixes for review
r849 auto drag = new QDrag{dragWidget};
New visualization classes for the drag&drop
r841
auto mimeData = dragWidget->mimeData();
drag->setMimeData(mimeData);
auto pixmap = QPixmap(dragWidget->size());
dragWidget->render(&pixmap);
Displays the miniature of the graph of the zone during a drag
r975 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
Qt::KeepAspectRatio, Qt::SmoothTransformation));
New visualization classes for the drag&drop
r841
auto image = pixmap.toImage();
mimeData->setImageData(image);
mimeData->setUrls({helper.imageTemporaryUrl(image)});
Format changes
r847 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
New visualization classes for the drag&drop
r841 helper.setCurrentDragWidget(dragWidget);
Format changes
r847 if (impl->cursorIsInContainer(this)) {
auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
impl->m_PlaceHolderText);
New visualization classes for the drag&drop
r841 dragWidget->setVisible(false);
}
Improves reliability
r880 else {
// The drag starts directly outside the drop zone
// do not add the placeHolder
}
New visualization classes for the drag&drop
r841
Thibaud Rabillard
Fix for D&D bug on mac
r912 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
helper.doCloseWidgets();
drop of variables in the visualization
r852 }
else {
qCWarning(LOG_VisualizationDragDropContainer())
<< tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
"VisualizationDragWidget is not found in this container.");
}
New visualization classes for the drag&drop
r841 }
void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
{
Format changes
r847 if (impl->acceptMimeData(event->mimeData())) {
New visualization classes for the drag&drop
r841 event->acceptProposedAction();
Format changes
r847 auto &helper = sqpApp->dragDropHelper();
New visualization classes for the drag&drop
r841
Format changes
r847 if (!impl->hasPlaceHolder()) {
New visualization classes for the drag&drop
r841 auto dragWidget = helper.getCurrentDragWidget();
drop of variables in the visualization
r852
if (dragWidget) {
// If the drag&drop is internal to the visualization, entering the container hide
Improves visual effect of dropping a variable in a graph
r879 // the dragWidget which was made visible by the dragLeaveEvent
drop of variables in the visualization
r852 auto parentWidget
= qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
if (parentWidget) {
dragWidget->setVisible(false);
}
New visualization classes for the drag&drop
r841 }
Drag of the time widget on a graph
r885 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
auto canInsert = impl->allowInsertForMimeData(event->mimeData());
impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
New visualization classes for the drag&drop
r841 }
drop of variables in the visualization
r852 else {
// do nothing
}
New visualization classes for the drag&drop
r841 }
Fixes for review
r849 else {
New visualization classes for the drag&drop
r841 event->ignore();
Fixes for review
r849 }
New visualization classes for the drag&drop
r841
QWidget::dragEnterEvent(event);
}
void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
{
Q_UNUSED(event);
Format changes
r847 auto &helper = sqpApp->dragDropHelper();
New visualization classes for the drag&drop
r841
Format changes
r847 if (!impl->cursorIsInContainer(this)) {
New visualization classes for the drag&drop
r841 helper.removePlaceHolder();
Improves visual effect of dropping a variable in a graph
r879 helper.setHightlightedDragWidget(nullptr);
impl->m_MinContainerHeight = 0;
New visualization classes for the drag&drop
r841
drop of variables in the visualization
r852 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
Format changes
r847 // 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)
New visualization classes for the drag&drop
r841
Format changes
r847 if (dragWidget) {
New visualization classes for the drag&drop
r841 dragWidget->setVisible(true);
}
}
}
drop of variables in the visualization
r852 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.
}
New visualization classes for the drag&drop
r841
QWidget::dragLeaveEvent(event);
}
void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
{
Format changes
r847 if (impl->acceptMimeData(event->mimeData())) {
Drag of the time widget on a graph
r885 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
auto canInsert = impl->allowInsertForMimeData(event->mimeData());
impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
New visualization classes for the drag&drop
r841 }
Fixes for review
r849 else {
New visualization classes for the drag&drop
r841 event->ignore();
Fixes for review
r849 }
New visualization classes for the drag&drop
r841
QWidget::dragMoveEvent(event);
}
void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
{
drop of variable inside an existing graph
r881 auto &helper = sqpApp->dragDropHelper();
Format changes
r847 if (impl->acceptMimeData(event->mimeData())) {
drop of variable inside an existing graph
r881 auto dragWidget = helper.getCurrentDragWidget();
drop of variables in the visualization
r852 if (impl->hasPlaceHolder()) {
drop of variable inside an existing graph
r881 // drop where the placeHolder is located
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
if (canInsert) {
auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 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;
}
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 dragWidget->setVisible(true);
}
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 event->acceptProposedAction();
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 helper.removePlaceHolder();
New visualization classes for the drag&drop
r841
Drag of the time widget on a graph
r885 emit dropOccuredInContainer(droppedIndex, event->mimeData());
}
else {
qCWarning(LOG_VisualizationDragDropContainer()) << tr(
"VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
"the insertion is forbidden.");
Q_ASSERT(false);
}
New visualization classes for the drag&drop
r841 }
drop of variable inside an existing graph
r881 else if (helper.getHightlightedDragWidget()) {
// drop on the highlighted widget
Drag of the time widget on a graph
r885 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
drop of variable inside an existing graph
r881 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);
}
drop of variables in the visualization
r852 }
New visualization classes for the drag&drop
r841 }
Fixes for review
r849 else {
New visualization classes for the drag&drop
r841 event->ignore();
Fixes for review
r849 }
New visualization classes for the drag&drop
r841
Improves visual effect of dropping a variable in a graph
r879 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
impl->m_MinContainerHeight = 0;
New visualization classes for the drag&drop
r841 QWidget::dropEvent(event);
}
Improves visual effect of dropping a variable in a graph
r879
void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
Drag of the time widget on a graph
r885 const QPoint &pos, bool canInsert, bool canMerge,
const VisualizationDragDropContainer *container)
Improves visual effect of dropping a variable in a graph
r879 {
auto &helper = sqpApp->dragDropHelper();
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 auto absPos = container->mapToGlobal(pos);
fix some wrong drag&drop behavior appearing on mac
r979 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886
if (countDragWidget(container, true) == 0) {
// Drop on an empty container, just add the placeHolder at the top
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 }
else if (!isOnPlaceHolder) {
Improves visual effect of dropping a variable in a graph
r879 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 = qMin(graphHeight / 4.0, 75.0);
auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
Drag of the time widget on a graph
r885 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
Improves visual effect of dropping a variable in a graph
r879 if (isOnBottom) {
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) {
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
m_PlaceHolderText);
Improves visual effect of dropping a variable in a graph
r879 }
helper.setHightlightedDragWidget(nullptr);
}
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 else if (canMerge && dragWidgetHovered) {
Improves visual effect of dropping a variable in a graph
r879 // drop on the middle -> merge
if (hasPlaceHolder()) {
helper.removePlaceHolder();
}
helper.setHightlightedDragWidget(dragWidgetHovered);
}
Drag of the time widget on a graph
r885 else {
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 qCWarning(LOG_VisualizationDragDropContainer())
<< tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
"action.");
Drag of the time widget on a graph
r885 }
Improves visual effect of dropping a variable in a graph
r879 }
else {
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 qCWarning(LOG_VisualizationDragDropContainer())
Add an empty area at the bottom of the tab where a new zone can be created from a drop. Differentiate graph and zone placeHolders.
r887 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
"found in the "
"container");
Improves visual effect of dropping a variable in a graph
r879 }
}
else {
Fix some glitches which occurred when dragging in the visualization something from the sides.
r886 // the mouse is hover the placeHolder
Improves visual effect of dropping a variable in a graph
r879 // Do nothing
}
}