package DragWidget;

use strict;
use warnings;

use QtCore4;
use QtGui4;
use QtCore4::isa qw( Qt::Frame );

# [0]
sub NEW {
    my ( $class, $parent ) = @_;
    $class->SUPER::NEW( $parent );

    this->setMinimumSize(200, 200);
    this->setFrameStyle(Qt::Frame::Sunken() | Qt::Frame::StyledPanel());
    this->setAcceptDrops(1);

    my $boatIcon = Qt::Label(this);
    $boatIcon->setPixmap(Qt::Pixmap('images/boat.png'));
    $boatIcon->move(20, 20);
    $boatIcon->show();
    $boatIcon->setAttribute(Qt::WA_DeleteOnClose());

    my $carIcon = Qt::Label(this);
    $carIcon->setPixmap(Qt::Pixmap('images/car.png'));
    $carIcon->move(120, 20);
    $carIcon->show();
    $carIcon->setAttribute(Qt::WA_DeleteOnClose());

    my $houseIcon = Qt::Label(this);
    $houseIcon->setPixmap(Qt::Pixmap('images/house.png'));
    $houseIcon->move(20, 120);
    $houseIcon->show();
    $houseIcon->setAttribute(Qt::WA_DeleteOnClose());
}
# [0]

sub dragEnterEvent {
    my ($event) = @_;
    if ($event->mimeData()->hasFormat('application/x-dnditemdata')) {
        my $source = $event->source();
        if (defined $source && $source == this) {
            $event->setDropAction(Qt::MoveAction());
            $event->accept();
        } else {
            $event->acceptProposedAction();
        }
    } else {
        $event->ignore();
    }
}

sub dragMoveEvent {
    my ($event) = @_;
    if ($event->mimeData()->hasFormat('application/x-dnditemdata')) {
        my $source = $event->source();
        if (defined $source && $source == this) {
            $event->setDropAction(Qt::MoveAction());
            $event->accept();
        } else {
            $event->acceptProposedAction();
        }
    } else {
        $event->ignore();
    }
}

sub dropEvent {
    my ($event) = @_;
    if ($event->mimeData()->hasFormat('application/x-dnditemdata')) {
        my $itemData = $event->mimeData()->data('application/x-dnditemdata');
        my $dataStream = Qt::DataStream($itemData, Qt::IODevice::ReadOnly());
        
        my $pixmap = Qt::Pixmap();
        my $offset = Qt::Point();
        {
            no warnings qw(void); # For bitshift warning
            $dataStream >> $pixmap >> $offset;
        }

        my $newIcon = Qt::Label(this);
        $newIcon->setPixmap($pixmap);
        $newIcon->move($event->pos() - $offset);
        $newIcon->show();
        $newIcon->setAttribute(Qt::WA_DeleteOnClose());

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

# [1]
sub mousePressEvent {
    my ($event) = @_;
    my $child = this->childAt($event->pos());
    if (!$child) {
        return;
    }

    my $pixmap = $child->pixmap();

    my $itemData = Qt::ByteArray();
    my $dataStream = Qt::DataStream($itemData, Qt::IODevice::WriteOnly());
    {
        no warnings qw(void); # For bitshift warning
        $dataStream << $pixmap << Qt::Point($event->pos() - $child->pos());
    }
# [1]

# [2]
    my $mimeData = Qt::MimeData();
    $mimeData->setData('application/x-dnditemdata', $itemData);
# [2]
        
# [3]
    my $drag = Qt::Drag(this);
    $drag->setMimeData($mimeData);
    $drag->setPixmap($pixmap);
    $drag->setHotSpot($event->pos() - $child->pos());
# [3]

    # XXX Fix this.  Shared memory on the Pixmap causes $tempPixmap and $pixmap
    # to point to the same data.  The C++ code paints on the tempPixmap instead
    # of the pixmap.
    my $tempPixmap = Qt::Pixmap($pixmap);
    my $painter = Qt::Painter();
    $painter->begin($pixmap);
    $painter->fillRect($tempPixmap->rect(), Qt::Color(127,127,127,127));
    $painter->end();

    $child->setPixmap($pixmap);

    my $result = $drag->exec(Qt::CopyAction() | Qt::MoveAction(), Qt::CopyAction());
    if ($result == Qt::MoveAction()) {
        $child->close();
    }
    else {
        $child->show();
        $child->setPixmap($tempPixmap);
    }
}

1;