QT_GUI_IM_5_9 - 8BitsCoding/RobotMentor GitHub Wiki

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QSplitter>
#include "container.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QSplitter * splitter = new QSplitter(this);

    splitter->addWidget(new Container(this));

    splitter->addWidget(new Container(this));

    ui->verticalLayout->addWidget(splitter);
}

Widget::~Widget()
{
    delete ui;
}
#ifndef PIXMAPMIME_H
#define PIXMAPMIME_H

#include <QMimeData>
#include <QPixmap>

class PixmapMime : public QMimeData
{
    Q_OBJECT
public:
    explicit PixmapMime(QPixmap pix,QPoint offset,QString description);

    QPixmap pix() const;

    QPoint offset() const;

signals:

public slots:
private:
    QPixmap mPix;
    QPoint mOffset;
    QString description;
    QStringList mimeFormats;

    // QMimeData interface
public:
    QStringList formats() const override;

protected:
    QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const override;
};

#endif // PIXMAPMIME_H
#include "pixmapmime.h"

PixmapMime::PixmapMime(QPixmap pix,QPoint offset,QString description)  :
    mPix(pix),mOffset(offset),description(description)
{
    mimeFormats << "text/html" << "text/plain";
}

QPixmap PixmapMime::pix() const
{
    return mPix;
}

QPoint PixmapMime::offset() const
{
    return mOffset;
}

QStringList PixmapMime::formats() const
{
    return  mimeFormats;
}

QVariant PixmapMime::retrieveData(const QString &mimetype, QVariant::Type preferredType) const
{

    if(mimetype == "text/plain"){
        return  description;
    }else if(mimetype == "text/html"){
        QString htmlString ;
        htmlString.append( "<html><p>" );
        htmlString.append(description) ;
        htmlString.append("</p></html>");

        return  htmlString;

    }else {
        return  QMimeData::retrieveData(mimetype,preferredType);

    }
}
#ifndef CONTAINER_H
#define CONTAINER_H

#include <QWidget>

class Container : public QWidget
{
    Q_OBJECT
public:
    explicit Container(QWidget *parent = nullptr);

signals:

public slots:

    // QWidget interface
protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dragMoveEvent(QDragMoveEvent *event) override;
    void dragLeaveEvent(QDragLeaveEvent *event) override;
    void dropEvent(QDropEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private:
    QPoint startPos;
};

#endif // CONTAINER_H
#include "container.h"
#include <QLabel>
#include <QPainter>
#include <QMouseEvent>
#include <QApplication>
#include <QDataStream>
#include <QMimeData>
#include <QDrag>
#include <QDebug>
#include "pixmapmime.h"

Container::Container(QWidget *parent) : QWidget(parent)
{
    setMinimumSize(150,150);

    setAcceptDrops(true);

    QLabel * qtIcon = new QLabel(this);
    qtIcon->setPixmap(QPixmap(":/images/qt.png"));
    qtIcon->move(20,20);
    qtIcon->show();
    qtIcon->setAttribute(Qt::WA_DeleteOnClose);

    QLabel * cppIcon = new QLabel(this);
    cppIcon->setPixmap(QPixmap(":/images/cpp.png"));
    cppIcon->move(150,20);
    cppIcon->show();
    cppIcon->setAttribute(Qt::WA_DeleteOnClose);

    QLabel * terminalIcon = new QLabel(this);
    terminalIcon->setPixmap(QPixmap(":/images/terminal.png"));
    terminalIcon->move(20,150);
    terminalIcon->show();
    terminalIcon->setAttribute(Qt::WA_DeleteOnClose);

}

void Container::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        startPos = event->pos();
    QWidget::mousePressEvent(event);
}

void Container::mouseMoveEvent(QMouseEvent *event)
{

    if (event->buttons() & Qt::LeftButton) {

        int distance = (event->pos() - startPos).manhattanLength();

        if (distance >= QApplication::startDragDistance())
        {

            QLabel * child = static_cast<QLabel *>(childAt(event->pos()));

            if(!child)
                return;

            QPixmap mPixmap = * child->pixmap();

/*
            QByteArray ba;

            QDataStream dataStream(&ba,QIODevice::WriteOnly);

            dataStream << mPixmap << QPoint(event->pos() - child->pos());
            QMimeData * mimeData = new QMimeData;
            mimeData->setData("application/x-qtcustomitem",ba);
            */

            PixmapMime * mimeData = new PixmapMime(mPixmap,
                       QPoint(event->pos() - child->pos()),
                                               "Item icon");

            QDrag * drag = new QDrag(this);
            drag->setMimeData(mimeData);
            drag->setPixmap(mPixmap);


            drag->setHotSpot(event->pos() - child->pos());


            //Blur the original label
            QPixmap tempPix = mPixmap;
            QPainter painter(&tempPix);
            painter.fillRect(tempPix.rect(),QColor(127, 127, 127, 127));

            child->setPixmap(tempPix);


            //Call to drag->exec() is blocking
            if(drag->exec(Qt::MoveAction | Qt::CopyAction,Qt::CopyAction) == Qt::MoveAction){
                //Move data
                qDebug()<< "Moving data";
                child->close();
            }else{
                //Copy action
                child->setPixmap(mPixmap);
                qDebug() << "Copying data";
            }
        }


    }

}

void Container::dragEnterEvent(QDragEnterEvent *event)
{
    if (qobject_cast<const PixmapMime *>(event->mimeData())) {
        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
            //event->ignore();
        } else {
            event->acceptProposedAction();
        }

    }else{
        event->ignore();
    }

}

void Container::dragMoveEvent(QDragMoveEvent *event)
{
    if (qobject_cast<const PixmapMime *>(event->mimeData())) {
        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
            //event->ignore();
        } else {
            event->acceptProposedAction();
        }

    }else{
        event->ignore();
    }
}

void Container::dragLeaveEvent(QDragLeaveEvent *event)
{
    QWidget::dragLeaveEvent(event);
}

void Container::dropEvent(QDropEvent *event)
{

    const PixmapMime * mimeData =
       qobject_cast<const PixmapMime *> (event->mimeData());

    if(mimeData){
        QPixmap mPixmap = mimeData->pix();
        QPoint offset = mimeData->offset();

        QLabel * newLabel = new QLabel(this);
        newLabel->setPixmap(mPixmap);
        newLabel->move(event->pos() - offset);
        newLabel->show();
        newLabel->setAttribute(Qt::WA_DeleteOnClose);


        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
            //event->ignore();
        } else {
            event->acceptProposedAction();
        }

    }

    else{
        event->ignore();
    }






    /*
    if (event->mimeData()->hasFormat("application/x-qtcustomitem")) {



//        QByteArray ba = event->mimeData()->data("application/x-qtcustomitem");
//        QDataStream dataStream(&ba,QIODevice::ReadOnly);

//        QPixmap mPixmap;
//        QPoint offset;

//        dataStream >> mPixmap >> offset;







        QLabel * newLabel = new QLabel(this);
        newLabel->setPixmap(mPixmap);
        newLabel->move(event->pos() - offset);
        newLabel->show();
        newLabel->setAttribute(Qt::WA_DeleteOnClose);

        if (event->source() == this) {
            event->setDropAction(Qt::MoveAction);
            event->accept();
            //event->ignore();
        } else {
            event->acceptProposedAction();
        }

    }else{
        event->ignore();
    }

    */

}

void Container::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.drawRoundRect(0,5,width()-10, height()-10,3,3);

    QWidget::paintEvent(event);

}
⚠️ **GitHub.com Fallback** ⚠️