##// END OF EJS Templates
Parser refactoring (3)...
Parser refactoring (3) Implements properties reading and properties checking Implementation takes some of the basic parser, which will be deleted at the end

File last commit:

r912:9102bdac4611
r935:b93a3fb4e7f2
Show More
VisualizationDragDropContainer.cpp
453 lines | 16.1 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")
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;
DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
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)
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 {
Drag of the time widget on a graph
r885 for (const auto &type : m_AcceptedMimeTypes.keys()) {
drop of variables in the visualization
r852 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
New visualization classes for the drag&drop
r841 return true;
Format changes
r847 }
New visualization classes for the drag&drop
r841 }
return false;
}
Drag of the time widget on a graph
r885 bool allowMergeForMimeData(const QMimeData *data) const
New visualization classes for the drag&drop
r841 {
Drag of the time widget on a graph
r885 bool 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)) {
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 {
Improves reliability
r880 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
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 }
Drag of the time widget on a graph
r885 void VisualizationDragDropContainer::addAcceptedMimeType(
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 drag->setHotSpot(dragPosition);
auto mimeData = dragWidget->mimeData();
drag->setMimeData(mimeData);
auto pixmap = QPixmap(dragWidget->size());
dragWidget->render(&pixmap);
drag->setPixmap(pixmap);
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);
auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
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
}
}