Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. why QDrag->exec() is crashing on MAC but not on windows version?
QtWS25 Last Chance

why QDrag->exec() is crashing on MAC but not on windows version?

Scheduled Pinned Locked Moved Unsolved General and Desktop
drag&dropdragleaveeventdrag and dropc++exec
8 Posts 3 Posters 1.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Y Offline
    Y Offline
    Yash001
    wrote on 28 Jun 2019, 21:13 last edited by Yash001
    #1

    I am using drag and drop event in Qt. On windows platform Qt with visual studio 2017. On Mac platform I am using Qt creator.

    on windows platform it is work perfectly. But on Mac it is crashing.

    I am creating the widget with help of CreateBuildExpElementWidget function, which is also install the event filter on that widget.

    QWidget* BuilderWidget::CreateBuildExpElementWidget(const BuilderContainer &bc, QUuid id) {
    	if (bc.type != BuilderContainer::ELEMENT) {
    		LOG() << "It is not an ELEMENT!";
    		return 0;
    	}
    
    	auto *w = OBJ_NAME(new QFrame(this), "node-builder-element");
    	
    
    	auto lay = NO_SPACING(NO_MARGIN(new QVBoxLayout(w)));
    
    	QSpinBox *mult;
    	QLabel *imageLbl;
    	QLabel *commentLbl;
    
    	lay->addWidget(imageLbl = OBJ_NAME(new QLabel, "node-builder-label"));
    	lay->addWidget(commentLbl = OBJ_NAME(new QLabel(bc.elem.name), "node-builder-label"));
    	lay->addWidget(mult = OBJ_NAME(new QSpinBox(), "node-builder-multiplier-single"));
    
    	commentLbl->setWordWrap(true);
    	commentLbl->hide();
    
    	QPixmap pixmap = bc.elem.ptr->GetImage();
    
    	auto imageLblSizeHint = imageLbl->sizeHint() * 0.95;
    
    	if( (pixmap.height() > imageLblSizeHint.height()) || (pixmap.width() > imageLblSizeHint.width()) ) {
    		pixmap = pixmap.scaled(imageLblSizeHint, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    	}
    
    	imageLbl->setPixmap(pixmap);
    	
    	mult->setMinimum(1);
    	mult->setMaximum(99999);
    	mult->setValue(bc.repeats);
    	mult->setSuffix("x");
    	mult->setToolTip("Number of the element repeats");
    
    	w->setAttribute(Qt::WA_Hover, true);
    	w->installEventFilter(new ElementEventFilter(w, this, imageLbl, commentLbl));
    
    	auto disconnector = new Disconnector(mult);
    	
    	*disconnector <<
    	connect(mult, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int val) {
    		SetRepeats(id, val);
    	});
    
    	return w;
    }
    

    ElementEvents

    class ElementEventFilter : public QObject {
    public:
    	ElementEventFilter(QObject *parent, BuilderWidget *bw, QWidget *image, QWidget *comment) :
    		QObject(parent), _bw(bw), pressed(false), dragged(false), entered(false), _image(image), _comment(comment) {}
    
    	bool eventFilter(QObject *obj, QEvent *e) {
    		bool ret = false;
    		
    		switch (e->type()) {
    		case QEvent::MouseButtonPress:
    			if (!IsIgnoreArea(obj, e)) {
    				pressed = true;
    				dragged = false;
    				pressButton = ((QMouseEvent*)e)->button();
    				pressPoint = ((QMouseEvent*)e)->pos();
    
    				ret = true;
    			}
    
    			break;
    
    		case QEvent::MouseMove:
    			if (pressed && !dragged) {
    				QPoint pos = ((QMouseEvent*)e)->pos();
    				QLine moveVector(pressPoint, pos);
    				auto length = qSqrt(moveVector.dx() * moveVector.dx() + moveVector.dy() * moveVector.dy());
    				if (length > 3) {
    					dragged = true;
    					ret = ProcessDrag(obj, e);
    				}
    			}
    			break;
    
    		case QEvent::MouseButtonRelease:
    			if (pressed && !dragged) {
    				ret = ProcessSelection(obj, e);
    			}
    			pressed = false;
    			dragged = false;
    			break;
    
    		case QEvent::HoverEnter:
    			entered = true;
    			break;
    
    		case QEvent::HoverMove:
    			if (entered) {
    				if (IsIgnoreArea(obj, e)) {
    					_comment->hide();
    					_image->show();
    				}
    				else {
    					_image->hide();
    					_comment->show();
    				}
    				ret = true;
    			}
    			break;
    
    		case QEvent::HoverLeave:
    			entered = false;
    			_comment->hide();
    			_image->show();
    			break;
    		}
    
    		return ret;
    	}
    
    private:
    	bool IsIgnoreArea(QObject *obj, QEvent *e) {
    		auto w = qobject_cast<QWidget*>(obj);
    		if (!w) {
    			return true;
    		}
    
    		auto me = (QMouseEvent*)e;
    
    		auto marg = w->contentsMargins();
    		QPoint bottomRight = QPoint(w->width(), w->height());
    		bottomRight -= QPoint(marg.right() - 3, marg.bottom() - 3);
    
    		QPoint topLeft = QPoint(marg.left() - 3, marg.top() - 3);
    
    		if (!QRect(topLeft, bottomRight).contains(me->pos())) {
    			return true;
    		}
    
    		return false;
    	}
    	bool ProcessSelection(QObject *obj, QEvent *e) {
    
    		auto w = qobject_cast<QWidget*>(obj);
    		if (!w) {
    			return false;
    		}
    		
    		if (IsIgnoreArea(obj, e)) {
    			return false;
    		}
    		
    		emit _bw->ElementSelected(w);
    		return true;
    	}
    	bool ProcessDrag(QObject *obj, QEvent *e) {
    	
    		QWidget *w = qobject_cast<QWidget*>(obj);
    		if (!w) {
    			return false;
    		}
    		
    		QMouseEvent *me = (QMouseEvent*)e;
    
    		if (IsIgnoreArea(obj, e)) {
    			return false;
    		}
    		
    		if (pressButton == Qt::LeftButton) {
    			auto margins = w->contentsMargins();
    			auto rect = w->rect();
    
    			QPoint startPoint;
    			startPoint.setX(margins.left() - 1);
    			startPoint.setY(margins.top() - 1);
    			QPoint endPoint;
    			endPoint.setX(rect.width() - margins.right() + 1);
    			endPoint.setY(rect.height() - margins.bottom());
    
    			QUuid id = _bw->GetId(w);
    
    			auto mime = new QMimeData;
    			mime->setData(CONTAINER_MIME_TYPE, id.toByteArray());
    
    			auto pixmap = w->grab(QRect(startPoint, endPoint));
    			pixmap = pixmap.scaledToHeight((endPoint.y() - startPoint.y()) / 2, Qt::SmoothTransformation);
    
    			QDrag *drag = new QDrag(obj);
    			drag->setMimeData(mime);
    			drag->setPixmap(pixmap);
    			drag->setHotSpot((pressPoint - QPoint(margins.left(), margins.top())) / 2);
    			
    			Qt::DropAction dropAction = drag->exec(Qt::MoveAction, Qt::MoveAction);
    
    			return true;
    		}
    
    		return false;
    	}
    
    	QPoint pressPoint;
    	Qt::MouseButton pressButton;
    	bool pressed;
    	bool dragged;
    	bool entered;
    
    	QWidget *_image;
    	QWidget *_comment;
    
    	BuilderWidget *_bw;
    };
    

    call to CreateBuildExpElementWidget and put it in container.

    void BuilderWidget::InitWidgets() {
    	for (auto it = container.elements.begin(); it != container.elements.end(); ++it) {
    		switch (it->type) {
    			case BuilderContainer::ELEMENT:
    				if (!it->w) {
    					it->w = CreateBuildExpElementWidget(*it, it->id);
    					it->w->hide();
    				}
    				break;
    		}
    	}
    }
    

    handle the drop event and delete the original widget with help DeleteContainer function.

    void BuilderWidget::dropEvent(QDropEvent *e) {
    	if (e->mimeData()->hasFormat(CONTAINER_MIME_TYPE)) {
    		if (!background.currentArea) {
    			return;
    		}
    
    		auto area = background.currentArea;
    		auto byteArray = e->mimeData()->data(CONTAINER_MIME_TYPE);
    		auto id = QUuid(byteArray);
    		BuilderContainer toMove;
    		BuilderContainer *origin = 0;
    
    		for (auto it = container.elements.begin(); it != container.elements.end(); ++it) {
    			if (it->id == id) {
    				toMove = *it;
    				origin = &(*it);
    				break;
    			}
    		}
    		if (!origin) {
    			return;
    		}
    
    		
    		toMove.id = QUuid::createUuid();
    		toMove.w = 0;
    
    		if (area->list) {
    			if ( (area->list == &container.elements) || (toMove.type == BuilderContainer::ELEMENT) ) {
    				area->list->insert(area->before, toMove);
    			}	
    		}
    		
    
    		InitWidgets();
    		DeleteContainer(origin);
    	}
    
    	background.currentArea = 0;
    	this->update();
    }
    

    DeleteContainer Function.

    void BuilderWidget::DeleteContainer(BuilderContainer *bcPtr) {
       if (!bcPtr) {
       	return;
       }
       
       auto toDeleteBc = bcPtr;
    
       HandleSelection(0);
       
       for (int i = 0; i < container.elements.count(); ++i) {
       	auto &currentBc(container.elements[i]);
       	
       	if (&currentBc == toDeleteBc) {
       		
       		currentBc.w->hide(); 
       		currentBc.w->deleteLater();
       		container.elements.removeAt(i);
       		break;
       	}
       }
    
    }
    

    Qt::DropAction dropAction = drag->exec(Qt::MoveAction, Qt::MoveAction); this line is crashing software on MAC platform. If I comment out currentBc.w->deleteLater(); inside the DeleteContainer function then it is work fine.

    what is wrong am I doing?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on 28 Jun 2019, 21:16 last edited by
      #2

      Hi,

      What version of Qt are you using ?
      What version of macOS are you running ?
      Can you provide a complete minimal example that reproduce that behaviour ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      Y 2 Replies Last reply 2 Jul 2019, 21:42
      0
      • SGaistS SGaist
        28 Jun 2019, 21:16

        Hi,

        What version of Qt are you using ?
        What version of macOS are you running ?
        Can you provide a complete minimal example that reproduce that behaviour ?

        Y Offline
        Y Offline
        Yash001
        wrote on 2 Jul 2019, 21:42 last edited by Yash001 7 Feb 2019, 21:52
        #3

        @SGaist

        @SGaist said in why QDrag->exec() is crashing on MAC but not on windows version?:

        What version of Qt are you using ?

        I am using Qt 5.13.0.

        @SGaist said in why QDrag->exec() is crashing on MAC but not on windows version?:

        What version of macOS are you running ?

        macOS version 10.13.6

        @SGaist said in why QDrag->exec() is crashing on MAC but not on windows version?:

        Can you provide a complete minimal example that reproduce that behavior ?

        Here The complete project for reproduce same behavior

        image file element1.png, element2.png
        1_1562102685775_element2.png 0_1562102685774_element1.png

        File name: ReplicaOfProject.pro

        #-------------------------------------------------
        #
        # Project created by QtCreator 2019-05-29T12:19:35
        #
        #-------------------------------------------------
        
        QT       += core gui
        
        greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
        
        TARGET = ReplicaOfProject
        TEMPLATE = app
        
        # The following define makes your compiler emit warnings if you use
        # any feature of Qt which has been marked as deprecated (the exact warnings
        # depend on your compiler). Please consult the documentation of the
        # deprecated API in order to know how to port your code away from it.
        DEFINES += QT_DEPRECATED_WARNINGS
        
        # You can also make your code fail to compile if you use deprecated APIs.
        # In order to do so, uncomment the following line.
        # You can also select to disable deprecated APIs only up to a certain version of Qt.
        #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
        
        CONFIG += c++11
        
        SOURCES += \
                BuilderWidget.cpp \
                Mainwindow.cpp \
                MainwindowUI.cpp \
                main.cpp
        
        HEADERS += \
            BuilderWidget.h \
            Mainwindow.h \
            MainwindowUI.h \
            UIEventFilters.hpp \
            UIHelper.hpp
        RESOURCES += \
            gui.qrc
        # Default rules for deployment.
        qnx: target.path = /tmp/$${TARGET}/bin
        else: unix:!android: target.path = /opt/$${TARGET}/bin
        !isEmpty(target.path): INSTALLS += target
        
        

        Filename: main.cpp

        #include "Mainwindow.h"
        #include <QApplication>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            MainWindow w;
            w.show();
        
            return a.exec();
        }
        
        

        Filename: BuilderWidget.h

        #ifndef BUILDERWIDGET_H
        #define BUILDERWIDGET_H
        
        #define ELEMENT_MIME_TYPE	"image/element"
        
        #include <QFrame>
        
        #include <QVBoxLayout>
        #include "QDebug"
        #include "quuid.h"
        #include "qlabel.h"
        #include "qlist.h"
        
        
        #include <QDragEnterEvent>
        #include <QDragLeaveEvent>
        #include <QDragMoveEvent>
        #include <QDropEvent>
        #include <QResizeEvent>
        #include <QDrag>
        #include <QMimeData>
        
        #include "UIHelper.hpp"
        #include "UIEventFilters.hpp"
        
        
        
        
        
        
        class BuilderWidget : public QFrame
        {
            Q_OBJECT
        
            typedef struct{
                QWidget *w = nullptr;
                QUuid id;
                QString imagePath;
            }BuilderContainer;
        
            struct {
                    QVBoxLayout *elementsLay = nullptr;
                    QWidget *selectOverlay = nullptr;
                } ui;
        
            void InitWidgets();
            void PlaceWidgets();
            QWidget* CreateBuildExpElementWidget(const BuilderContainer&);
        public:
            explicit BuilderWidget(QWidget *parent = nullptr);
            QUuid GetId(QWidget*);
            QList<BuilderContainer> container;
        protected:
            void dropEvent(QDropEvent *e);
            void dragEnterEvent(QDragEnterEvent *e);
            void dragLeaveEvent(QDragLeaveEvent *e);
            void dragMoveEvent(QDragMoveEvent *e);
        
        signals:
        
        public slots:
            void DeleteContainer(BuilderContainer*);
        };
        
        #endif // BUILDERWIDGET_H
        
        

        FileName: BuilderWidget.cpp

        #include "BuilderWidget.h"
        #define BUILDER_ELEMENT_SPACING		2
        
        BuilderWidget::BuilderWidget(QWidget *parent) : QFrame(parent)
        {
            OBJ_NAME(this, "build-exp-holder");
            this->setAcceptDrops(true);
        
        }
        QWidget* BuilderWidget::CreateBuildExpElementWidget(const BuilderContainer &bc) {
            auto label = OBJ_NAME(new QLabel, "element-builder");
        
            QPixmap pixmap(bc.imagePath);
            label->setPixmap(pixmap);
        
        
            label->setAttribute(Qt::WA_Hover, true);
            label->installEventFilter(new ElementEventFilter(label->parent(), this, label, bc.id));
        
            return label;
        
        }
        
        void BuilderWidget::DeleteContainer(BuilderContainer *bcPtr) {
            if (!bcPtr) {
                    return;
             }
            auto toDeleteBc = bcPtr;
        
            for (int i = 0; i < container.count(); ++i) {
                auto &currentBc(container[i]);
                if (&currentBc == toDeleteBc) {
                    currentBc.w->deleteLater();
                    container.removeAt(i);
                    break;
                }
            }
        
             return;
        }
        
        void BuilderWidget::InitWidgets() {
            for (auto it = container.begin(); it != container.end(); ++it) {
        
                if (!it->w) {
                        it->w = CreateBuildExpElementWidget(*it);
                        it->w->hide();
                 }
        
            }
        
        }
        void BuilderWidget::PlaceWidgets() {
            if (!ui.elementsLay) {
                    ui.elementsLay = NO_MARGIN(new QVBoxLayout(this));
                    ui.elementsLay->setSpacing(BUILDER_ELEMENT_SPACING);
                }
                while (ui.elementsLay->count()) {
                    auto item = ui.elementsLay->itemAt(0);
                    ui.elementsLay->removeItem(item);
        
                    delete item;
                }
        
            for (auto it = container.begin(); it != container.end(); ++it) {
                auto elemLay = NO_SPACING(NO_MARGIN(new QHBoxLayout));
        
                elemLay->addStretch(1);
                elemLay->addWidget(it->w);
                elemLay->addStretch(1);
        
                ui.elementsLay->addLayout(elemLay);
        
                if (it->w->isHidden()) {
                    it->w->show();
                }
            }
        
        
            this->update();
        }
        void BuilderWidget::dropEvent(QDropEvent *e) {
        
            if (e->mimeData()->hasFormat(ELEMENT_MIME_TYPE)) {
        
                auto byteArray = e->mimeData()->data(ELEMENT_MIME_TYPE);
                auto id = QUuid(byteArray);
        
                BuilderContainer toMove;
                BuilderContainer *origin = nullptr;
        
                for (auto it = container.begin(); it != container.end(); ++it) {
                    if (it->id == id) {
                        toMove = *it;
                        origin = &(*it);
                        break;
                     }
                }
                if (!origin){
                    toMove.imagePath = byteArray;
                }
                toMove.id = QUuid::createUuid();
                toMove.w = nullptr;
        
                container << toMove;
                InitWidgets();
        
                if (origin){
                    DeleteContainer(origin);
                }
                PlaceWidgets();
            }
        
            this->update();
        }
        void BuilderWidget::dragEnterEvent(QDragEnterEvent *e) {
        
            if (e->mimeData()->hasFormat(ELEMENT_MIME_TYPE)) {
                e->accept();
            }
            else {
                e->ignore();
            }
            this->update();
        }
        void BuilderWidget::dragLeaveEvent(QDragLeaveEvent *e) {
            this->update();
        }
        void BuilderWidget::dragMoveEvent(QDragMoveEvent *e) {
            do {
                if (!(e->mimeData()->hasFormat(ELEMENT_MIME_TYPE)) ) {
                    break;
                }
                auto pos = e->pos();
        
        
                e->accept();
                this->update();
        
                return;
            } while (0);
        
        
            e->ignore();
            this->update();
        }
        
        

        FileName: Mainwindow.h

        #ifndef MAINWINDOW_H
        #define MAINWINDOW_H
        
        #include <QMainWindow>
        #include "qfile.h"
        #include "qapplication.h"
        #include "qdesktopwidget.h"
        
        #include "UIEventFilters.hpp"
        
        class MainWindowUI;
        
        class MainWindow : public QMainWindow
        {
            Q_OBJECT
        
        public:
            MainWindow(QWidget *parent = nullptr);
            ~MainWindow();
        private:
            MainWindowUI *ui;
        
            void ApplyStyle();
        };
        
        #endif // MAINWINDOW_H
        
        

        Filename: Mainwindow.cpp

        #include "Mainwindow.h"
        #include "MainwindowUI.h"
        
        MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent),ui(new MainWindowUI(this))
        {
            ui->CreateUI();
            ApplyStyle();
        }
        
        MainWindow::~MainWindow()
        {
        
        }
        
        void MainWindow::ApplyStyle() {
        
            QFile f(":/GUI/GUI.css");
            if (!f.open(QIODevice::ReadOnly))
                return;
        
            QString newStyleSheet = f.readAll();
        
            qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(newStyleSheet);
        
            f.close();
        }
        

        Filename: MainwindowUI.h

        #ifndef MAINWINDOWUI_H
        #define MAINWINDOWUI_H
        #include "Mainwindow.h"
        
        class MainWindowUI : public QObject
        {
            Q_OBJECT
        public:
            MainWindowUI(MainWindow *Parent);
            void CreateUI();
            void CraeteCentralWidget();
            QWidget* GetMainTabWidget();
            QWidget* CreateElementsListWidget();
            QWidget* CreateDragPlace();
        signals:
        
        public slots:
        
        private:
            MainWindow *m_mainWindow;
        };
        
        #endif // MAINWINDOWUI_H
        
        

        Filename: MainwindowUI.cpp

        #include "MainwindowUI.h"
        #include "UIHelper.hpp"
        #include "QListView"
        #include "QStandardItemModel"
        #include "qdebug.h"
        #include "QMimeData"
        #include "qdrag.h"
        
        
        #include "builderwidget.h"
        #define ELEMENT_MIME_TYPE	"image/element"
        
        MainWindowUI::MainWindowUI(MainWindow *parent) : m_mainWindow(parent)
        {
        
        }
        
        
        void MainWindowUI::CreateUI(){
            CraeteCentralWidget();
        }
        void MainWindowUI::CraeteCentralWidget(){
            QWidget *centralWidget = OBJ_NAME(WDG(), "central-widget");
            QGridLayout *centralLayout = NO_SPACING(NO_MARGIN(new QGridLayout(centralWidget)));
            m_mainWindow->setCentralWidget(centralWidget);
            centralLayout->addWidget(GetMainTabWidget(), 1, 0);
        
        }
        QWidget* MainWindowUI::GetMainTabWidget() {
            static QWidget *w = nullptr;
        
            if (w) {
                return w;
            }
            w = WDG();
        
           auto lay = NO_SPACING(NO_MARGIN(new QHBoxLayout(w)));
           lay->addWidget(CreateElementsListWidget());
           lay->addWidget(CreateDragPlace());
            return w;
         }
        
        QWidget* MainWindowUI::CreateElementsListWidget(){
            static QWidget *w = nullptr;
        
            if (w) {
                return w;
            }
        
            w = OBJ_NAME(WDG(), "node-list-owner");
           auto lay = NO_SPACING(NO_MARGIN(new QVBoxLayout(w)));
        
           auto elementsListHolder = OBJ_NAME(new QFrame(), "elements-list-holder");
           auto elementsListHolderLay = new QGridLayout(elementsListHolder);
        
        
           QStringList elemets = {":/GUI/element1.png",":/GUI/element2.png"};
        
        
           foreach(auto elem, elemets) {
                auto label = OBJ_NAME(new QLabel, "element-builder");
                QPixmap pixmap(elem);
                label->setPixmap(pixmap);
        
                label->installEventFilter(new UniversalEventFilter(label, [=](QObject *obj, QEvent *e) {
        
        
                                if (e->type() == QEvent::Enter) {
        
                                    QWidget *w = qobject_cast<QWidget*>(obj);
        
                                    if (!w) {
                                        return false;
                                    }
        
                                    auto marg = w->contentsMargins();
        
                                    auto additionalHeight = (w->height() - marg.bottom() - marg.top()) * 0.25;
        
                                    QPoint topLeft = QPoint(marg.left() - 1, marg.top() - 3);
                                    QPoint bottomRight = QPoint(w->width(), w->height() + additionalHeight);
        
                                    bottomRight -= QPoint(marg.right(), marg.bottom());
        
        
        
        
                                    //auto  overlay  = OBJ_NAME(new QFrame(w), "hover-element-overlay");
                                    auto  overlay  = OBJ_NAME(label , "hover-element-overlay");
        
                                    overlay->setGeometry(QRect(topLeft + w->pos(), bottomRight + w->pos()));
        
        
                                    static bool dragInAction;
                                    dragInAction = false;
                                    overlay->installEventFilter(new UniversalEventFilter(overlay, [=](QObject *obj, QEvent *e) {
                                        if (e->type() == QEvent::MouseButtonPress) {
                                            QWidget *w = qobject_cast<QWidget*>(obj);
                                            if (!w) {
                                                return false;
                                            }
        
                                            QMouseEvent *me = (QMouseEvent*)e;
        
                                            if (me->button() == Qt::LeftButton) {
                                                auto margins = w->contentsMargins();
                                                auto rect = w->rect();
        
                                                QPoint startPoint;
                                                startPoint.setX(margins.left() - 1);
                                                startPoint.setY(margins.top() - 1);
                                                QPoint endPoint;
                                                endPoint.setX(rect.width() - margins.right());
                                                endPoint.setY(rect.height() - margins.bottom());
        
                                               auto byteArray = QByteArray().append(elem);
        
                                                auto mime = new QMimeData;
                                                mime->setData(ELEMENT_MIME_TYPE, byteArray);
        
                                                auto pixmap = w->grab(QRect(startPoint, endPoint));
                                                pixmap = pixmap.scaledToHeight((endPoint.y() - startPoint.y()) / 2, Qt::SmoothTransformation);
        
                                                QDrag *drag = new QDrag(obj);
                                                drag->setMimeData(mime);
                                                drag->setPixmap(pixmap);
                                                drag->setHotSpot((me->pos() - QPoint(margins.left(), margins.top())) / 2);
        
                                                dragInAction = true;
                                                Qt::DropAction dropAction = drag->exec(Qt::CopyAction, Qt::CopyAction);
                                                dragInAction = false;
        
                                                return true;
                                            }
                                            return false;
                                        }
                                        if (e->type() == QEvent::Enter) {
                                            return true;
                                        }
                                        if (e->type() == QEvent::Leave) {
                                            if (dragInAction) {
                                                return false;
                                            }
        
        
                                            return true;
                                        }
                                        return false;
                                    }));
        
        
                                    return true;
                                    }
        
        
                                    return false;
                        }));
        
        
        
        
                static int column = 0;
                if (!column) {
                    elementsListHolderLay->addWidget(label, 0, column);
                    column++;
                }else{
                    elementsListHolderLay->addWidget(label, 0,column);
                    column = 0;
                }
            }
        
        
            lay->addWidget(elementsListHolder);
            lay->addStretch();
            return w;
        }
        QWidget* MainWindowUI::CreateDragPlace(){
            static QWidget *w = nullptr;
        
            if (w) {
                return w;
            }
        
            w = OBJ_NAME(WDG(), "Drag-place-widget");
             auto lay = NO_SPACING(NO_MARGIN(new QVBoxLayout(w)));
        
             lay->addWidget(new BuilderWidget(m_mainWindow));
        
            return w;
        
        }
        
        

        FileName: UIEventFilters.hpp

        #pragma once
        
        #define ELEMENT_MIME_TYPE	"image/element"
        #include "BuilderWidget.h"
        #include <QEvent>
        #include <QMouseEvent>
        
        #include <QObject>
        #include <QWidget>
        #include <QScrollArea>
        #include <QScrollBar>
        #include <qtooltip.h>
        #include <QSortFilterProxyModel>
        #include <QGraphicsDropShadowEffect>
        #include <QXmlStreamReader>
        
        #include <QtMath>
        
        
        
        #include <functional>
        
        #define EXPERIMENT_VIEW_ALL_CATEGORY	"View All"
        
        
        
        class UniversalEventFilter : public QObject {
        public:
        	UniversalEventFilter(QObject *parent, std::function<bool(QObject*, QEvent*)> lambda) :
        		QObject(parent), _lambda(lambda) {}
        
        	bool eventFilter(QObject *obj, QEvent *e) {
        		return _lambda(obj, e);
        		
        	}
        private:
        	std::function<bool(QObject*, QEvent*)> _lambda;
        };
        
        class BuilderWidget;
        class ElementEventFilter : public QObject {
        public:
            ElementEventFilter(QObject *parent, BuilderWidget *bw, QWidget *image,QUuid _id) :
                QObject(parent), _bw(bw), pressed(false), dragged(false), entered(false), _image(image),id(_id) {}
        
            bool eventFilter(QObject *obj, QEvent *e) {
                bool ret = false;
        
                switch (e->type()) {
                case QEvent::MouseButtonPress:
                    if (!IsIgnoreArea(obj, e)) {
                        pressed = true;
                        dragged = false;
                        pressButton = (static_cast<QMouseEvent*>(e))->button();
                        pressPoint = (static_cast<QMouseEvent*>(e))->pos();
        
                        ret = true;
                    }
        
                    break;
        
                case QEvent::MouseMove:
                    if (pressed && !dragged) {
                        QPoint pos = (static_cast<QMouseEvent*>(e))->pos();
                        QLine moveVector(pressPoint, pos);
                        auto length = qSqrt(moveVector.dx() * moveVector.dx() + moveVector.dy() * moveVector.dy());
                        if (length > 3) {
                            dragged = true;
                            ret = ProcessDrag(obj, e);
                        }
                    }
                    break;
        
                case QEvent::MouseButtonRelease:
                    if (pressed && !dragged) {
                        ret = ProcessSelection(obj, e);
                    }
                    pressed = false;
                    dragged = false;
                    break;
        
                case QEvent::HoverEnter:
                    entered = true;
                    break;
        
                case QEvent::HoverLeave:
                    entered = false;
        
                    _image->show();
                    break;
                default:
                    break;
                }
        
                return ret;
            }
        
        private:
            bool IsIgnoreArea(QObject *obj, QEvent *e) {
                auto w = qobject_cast<QWidget*>(obj);
                if (!w) {
                    return true;
                }
        
                auto me = static_cast<QMouseEvent*>(e);
        
                auto marg = w->contentsMargins();
                QPoint bottomRight = QPoint(w->width(), w->height());
                bottomRight -= QPoint(marg.right() - 3, marg.bottom() - 3);
        
                QPoint topLeft = QPoint(marg.left() - 3, marg.top() - 3);
        
                if (!QRect(topLeft, bottomRight).contains(me->pos())) {
                    return true;
                }
        
                return false;
            }
            bool ProcessSelection(QObject *obj, QEvent *e) {
        
                auto w = qobject_cast<QWidget*>(obj);
                if (!w) {
                    return false;
                }
        
                if (IsIgnoreArea(obj, e)) {
                    return false;
                }
        
        
                return true;
            }
            bool ProcessDrag(QObject *obj, QEvent *e) {
        
                QWidget *w = qobject_cast<QWidget*>(obj);
                if (!w) {
                    return false;
                }
        
                //auto me = static_cast<QMouseEvent*>(e);
        
                if (IsIgnoreArea(obj, e)) {
                    return false;
                }
        
                if (pressButton == Qt::LeftButton) {
                    auto margins = w->contentsMargins();
                    auto rect = w->rect();
        
                    QPoint startPoint;
                    startPoint.setX(margins.left() - 1);
                    startPoint.setY(margins.top() - 1);
                    QPoint endPoint;
                    endPoint.setX(rect.width() - margins.right() + 1);
                    endPoint.setY(rect.height() - margins.bottom());
        
        
                    auto mime = new QMimeData;
                    mime->setData(ELEMENT_MIME_TYPE, id.toByteArray());
        
                    auto pixmap = w->grab(QRect(startPoint, endPoint));
                    pixmap = pixmap.scaledToHeight((endPoint.y() - startPoint.y()) / 2, Qt::SmoothTransformation);
        
                    QDrag *drag = new QDrag(obj);
                    drag->setMimeData(mime);
                    drag->setPixmap(pixmap);
                    drag->setHotSpot((pressPoint - QPoint(margins.left(), margins.top())) / 2);
        
                    Qt::DropAction dropAction = drag->exec(Qt::MoveAction, Qt::MoveAction);
        
                    return true;
                }
        
                return false;
            }
        
            QPoint pressPoint;
            Qt::MouseButton pressButton;
            bool pressed;
            bool dragged;
            bool entered;
        
            QWidget *_image;
            QUuid id;
            BuilderWidget *_bw;
        };
        
        
        

        FileName: UIHelper.hpp

        #pragma once
        
        #include <QObject>
        
        #include <QLayout>
        #include <QGridLayout>
        #include <QHBoxLayout>
        #include <QVBoxLayout>
        
        #include <QLabel>
        #include <QComboBox>
        #include <QLineEdit>
        #include <QTextEdit>
        #include <QPushButton>
        #include <QRadioButton>
        
        template<typename WidgetType>
        WidgetType* SetObjectName(WidgetType *w, const QString &name) {
        	w->setObjectName(name);
        	return w;
        }
        template<typename WidgetType>
        WidgetType* SetObjectProperty(WidgetType *w, const char *name, const QString &value) {
        	w->setProperty(name, value);
        	return w;
        }
        template<typename LayoutType>
        LayoutType* SetZeroMargin(LayoutType *l) {
        	l->setContentsMargins(0, 0, 0, 0);
        	return l;
        }
        template<typename LayoutType>
        LayoutType* SetZeroSpacing(LayoutType *l) {
        	l->setSpacing(0);
        	return l;
        }
        
        #define TR(...)         QObject::tr(__VA_ARGS__)
        //#define QObject::connect(...)    QObject::connect(__VA_ARGS__)
        
        
        
        #define WDG()			new QWidget
        #define LBL(str)		new QLabel(TR(str))
        #define CMB()			new QComboBox
        #define LED()			new QLineEdit
        #define TED()			new QTextEdit
        #define PBT(str)		new QPushButton(TR(str))
        #define RBT(str)		new QRadioButton(TR(str))
        
        
        
        #define OBJ_NAME(qobject, qstring)	SetObjectName(qobject, qstring)
        #define OBJ_PROP(w, name, val)		SetObjectProperty(w, name, val)
        
        #define NO_MARGIN(qlayout)	SetZeroMargin(qlayout)
        #define NO_SPACING(qlayout)	SetZeroSpacing(qlayout)
        

        Filename: GUI.css

        QMainWindow {
                min-width: 1366px;
                min-height: 768px;
        }
        #node-list-owner{
        border: 2px solid;
        }
        
        

        FileName: gui.qrc

        <RCC>
            <qresource prefix="/GUI">
                <file>GUI.css</file>
                <file>element1.png</file>
                <file>element2.png</file>
            </qresource>
            <qresource prefix="/"/>
        </RCC>
        
        

        Reproducing step:

        0_1562103581237_Reproduce By Following.PNG

        Here the MAC version of software is crashing at drag#2.
        software is crash at line Qt::DropAction dropAction = drag->exec(Qt::MoveAction, Qt::MoveAction); in UIEventFilters.hpp file.

        if I will comment out line currentBc.w->deleteLater(); in BuilderWidget::DeleteContainer(BuilderContainer *bcPtr) function then it is not crashing.

        What are the change I need to make?

        Just for futures use: is It any way to upload .cpp and .h file in Qt form?

        1 Reply Last reply
        0
        • Y Offline
          Y Offline
          Yash001
          wrote on 3 Jul 2019, 18:11 last edited by
          #4
          This post is deleted!
          1 Reply Last reply
          0
          • SGaistS SGaist
            28 Jun 2019, 21:16

            Hi,

            What version of Qt are you using ?
            What version of macOS are you running ?
            Can you provide a complete minimal example that reproduce that behaviour ?

            Y Offline
            Y Offline
            Yash001
            wrote on 3 Jul 2019, 21:09 last edited by
            #5

            @SGaist any suggestion for avoiding crash while using QDrag->exec() in MAC software?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on 10 Jul 2019, 06:32 last edited by
              #6

              I don't have an answer currently because your example is clearly not minimal. I can confirm it crashes even with a more recent version of Qt. However, the code is pretty convoluted especially for doing drag and drop.

              I think there's room for simplification that would likely end up in a cleaner and easier to understand code base.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • S Offline
                S Offline
                Sebastien Leon
                wrote on 12 Sept 2019, 08:05 last edited by
                #7

                Hello Yash001
                I get similar issue with my code and manage to fix it by patching Qt... I'm wondering if the same fix would fix your issue too...
                (because I send the fix to Qt to commit, but as I can not reproduce the issue on a minimal project, they say the problem doesn't exist and they do not really want to accept my patch. So it is better if several of us report the same issue)
                On our side, the issue was raised only when we use tablet pen + drag & drop. I do not know if it is the same problem for you... (if you were using our mouse, it is more likely that our patch will not fix your issue)
                You can download the patch here :
                http://download.pointcarre.com/dev/Qt5.12.4Fix.zip
                Please let me know if it fix your issue...
                Best regards
                Sebastien

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 12 Sept 2019, 09:34 last edited by
                  #8

                  Hi @Sebastien-Leon and welcome to devnet,

                  Can you post the link to the bug report / gerrit review you made ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved