Drag&drop, working towards making it accept drop events
Still work in progress
This commit is contained in:
parent
f933d66e55
commit
b427f9e094
4 changed files with 95 additions and 15 deletions
|
@ -126,10 +126,26 @@ void BlockGrid::paintEvent (QPaintEvent* event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockGrid::dragEnterEvent(QDragEnterEvent* event) {
|
||||||
|
m_block_dnd.drag_enter_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockGrid::dropEvent(QDropEvent* event) {
|
||||||
|
m_block_dnd.drop_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
void BlockGrid::mousePressEvent(QMouseEvent* event) {
|
void BlockGrid::mousePressEvent(QMouseEvent* event) {
|
||||||
m_block_dnd.mouse_press_event(event);
|
m_block_dnd.mouse_press_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockGrid::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
m_block_dnd.mouse_release_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockGrid::mouseMoveEvent(QMouseEvent* event) {
|
||||||
|
m_block_dnd.mouse_move_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
void BlockGrid::advance_frame() {
|
void BlockGrid::advance_frame() {
|
||||||
for (auto& ico : m_icons) {
|
for (auto& ico : m_icons) {
|
||||||
ico.advance_frame();
|
ico.advance_frame();
|
||||||
|
|
|
@ -46,7 +46,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent (QPaintEvent* event) override;
|
void paintEvent (QPaintEvent* event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
|
void dropEvent(QDropEvent* event) override;
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void advance_frame();
|
void advance_frame();
|
||||||
|
|
|
@ -22,9 +22,13 @@
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QDrag>
|
#include <QDrag>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QWidget>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
# include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace duck::widget::detail {
|
namespace duck::widget::detail {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -32,38 +36,74 @@ constexpr char g_drag_mime[] = "application/x-dndblock";
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
BlockDragAndDrop::BlockDragAndDrop (
|
BlockDragAndDrop::BlockDragAndDrop (
|
||||||
QObject* parent,
|
QWidget* parent,
|
||||||
PointToIndexFunc&& func,
|
PointToIndexFunc&& func,
|
||||||
std::function<std::size_t()>&& get_block_count,
|
std::function<std::size_t()>&& get_icon_count,
|
||||||
std::function<const QPixmap&(std::size_t)>&& get_pixmap
|
std::function<const QPixmap&(std::size_t)>&& get_pixmap
|
||||||
) :
|
) :
|
||||||
m_point_to_index(std::move(func)),
|
m_point_to_index(std::move(func)),
|
||||||
m_get_block_count(std::move(get_block_count)),
|
m_get_icon_count(std::move(get_icon_count)),
|
||||||
m_get_pixmap(std::move(get_pixmap)),
|
m_get_pixmap(std::move(get_pixmap)),
|
||||||
m_parent(parent)
|
m_parent(parent)
|
||||||
{
|
{
|
||||||
assert(m_parent);
|
assert(m_parent);
|
||||||
|
m_parent->setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockDragAndDrop::mouse_press_event (const QMouseEvent* event) {
|
void BlockDragAndDrop::mouse_press_event (const QMouseEvent* event) {
|
||||||
const auto [icon_index, block_origin] = m_point_to_index(event->position().toPoint());
|
if (event->button() & Qt::LeftButton) {
|
||||||
if (icon_index < 0)
|
assert(not m_dragging);
|
||||||
return;
|
|
||||||
const auto icon_index_uns = static_cast<std::size_t>(icon_index);
|
const auto [block_index, block_origin] = m_point_to_index(event->position().toPoint());
|
||||||
if (icon_index_uns >= m_get_block_count())
|
if (block_index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto icon_index = static_cast<std::size_t>(block_index);
|
||||||
|
if (icon_index >= m_get_icon_count())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_start_pos = event->position().toPoint();
|
||||||
|
m_dragging = true;
|
||||||
|
m_block_index = block_index;
|
||||||
|
m_hot_spot = m_start_pos - block_origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDragAndDrop::mouse_release_event(const QMouseEvent* event) {
|
||||||
|
if (event->button() & Qt::LeftButton) {
|
||||||
|
m_dragging = false;
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
std::cout << "Mouse button released before block's drag&drop\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDragAndDrop::mouse_move_event (const QMouseEvent* event) {
|
||||||
|
if (not m_dragging)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (not (event->buttons() & Qt::LeftButton))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((event->position().toPoint() - m_start_pos).manhattanLength() < QApplication::startDragDistance())
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
std::cout << "mouse_move_event() drag&drop started\n";
|
||||||
|
#endif
|
||||||
QByteArray item_data;
|
QByteArray item_data;
|
||||||
QDataStream data_stream(&item_data, QIODevice::WriteOnly);
|
QDataStream data_stream(&item_data, QIODevice::WriteOnly);
|
||||||
data_stream << m_get_pixmap(icon_index_uns);
|
data_stream << m_get_pixmap(m_block_index);
|
||||||
|
|
||||||
std::unique_ptr<QMimeData> mime_data(new QMimeData);
|
std::unique_ptr<QMimeData> mime_data(new QMimeData);
|
||||||
mime_data->setData(g_drag_mime, item_data);
|
mime_data->setData(g_drag_mime, item_data);
|
||||||
|
|
||||||
|
assert(m_block_index >= 0);
|
||||||
|
const auto icon_index = static_cast<unsigned int>(m_block_index);
|
||||||
QDrag* const drag(new QDrag(m_parent));
|
QDrag* const drag(new QDrag(m_parent));
|
||||||
drag->setMimeData(mime_data.release());
|
drag->setMimeData(mime_data.release());
|
||||||
drag->setPixmap(m_get_pixmap(icon_index_uns));
|
drag->setPixmap(m_get_pixmap(icon_index));
|
||||||
drag->setHotSpot(event->position().toPoint() - block_origin);
|
drag->setHotSpot(m_hot_spot);
|
||||||
|
|
||||||
switch (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction)) {
|
switch (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction)) {
|
||||||
case Qt::MoveAction:
|
case Qt::MoveAction:
|
||||||
|
@ -73,5 +113,14 @@ void BlockDragAndDrop::mouse_press_event (const QMouseEvent* event) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
m_dragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDragAndDrop::drag_enter_event(QDragEnterEvent* event) {
|
||||||
|
if (not m_dragging and event->mimeData()->hasFormat(g_drag_mime))
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDragAndDrop::drop_event(QDropEvent* event) {
|
||||||
}
|
}
|
||||||
} //namespace duck::widget::detail
|
} //namespace duck::widget::detail
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
|
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QPixmap;
|
class QPixmap;
|
||||||
|
class QWidget;
|
||||||
|
class QDragEnterEvent;
|
||||||
|
class QDropEvent;
|
||||||
|
|
||||||
namespace duck::widget::detail {
|
namespace duck::widget::detail {
|
||||||
class BlockDragAndDrop {
|
class BlockDragAndDrop {
|
||||||
|
@ -30,19 +33,27 @@ public:
|
||||||
typedef std::function<std::pair<int,QPoint>(QPoint)> PointToIndexFunc;
|
typedef std::function<std::pair<int,QPoint>(QPoint)> PointToIndexFunc;
|
||||||
|
|
||||||
BlockDragAndDrop (
|
BlockDragAndDrop (
|
||||||
QObject* parent,
|
QWidget* parent,
|
||||||
PointToIndexFunc&& func,
|
PointToIndexFunc&& func,
|
||||||
std::function<std::size_t()>&& get_block_count,
|
std::function<std::size_t()>&& get_icon_count,
|
||||||
std::function<const QPixmap&(std::size_t)>&& get_pixmap
|
std::function<const QPixmap&(std::size_t)>&& get_pixmap
|
||||||
);
|
);
|
||||||
|
|
||||||
void mouse_press_event (const QMouseEvent* event);
|
void mouse_press_event (const QMouseEvent* event);
|
||||||
|
void mouse_release_event (const QMouseEvent* event);
|
||||||
|
void mouse_move_event (const QMouseEvent* event);
|
||||||
|
void drag_enter_event(QDragEnterEvent* event);
|
||||||
|
void drop_event(QDropEvent* event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PointToIndexFunc m_point_to_index;
|
PointToIndexFunc m_point_to_index;
|
||||||
std::function<std::size_t()> m_get_block_count;
|
std::function<std::size_t()> m_get_icon_count;
|
||||||
std::function<const QPixmap&(std::size_t)> m_get_pixmap;
|
std::function<const QPixmap&(std::size_t)> m_get_pixmap;
|
||||||
QObject* m_parent;
|
QWidget* m_parent;
|
||||||
|
QPoint m_start_pos;
|
||||||
|
QPoint m_hot_spot;
|
||||||
|
int m_block_index;
|
||||||
|
bool m_dragging {false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace duck::widget::detail
|
} //namespace duck::widget::detail
|
||||||
|
|
Loading…
Add table
Reference in a new issue