diff --git a/src/qt/meson.build b/src/qt/meson.build index d70af1f..3b49f93 100644 --- a/src/qt/meson.build +++ b/src/qt/meson.build @@ -35,6 +35,7 @@ executable(app_name, project_config_file, gitrev_config_file, 'widgets/block_grid.cpp', + 'widgets/detail/block_drag_and_drop.cpp', 'make_qt_animation.cpp', 'animated_pixmap.cpp', include_directories: inc, diff --git a/src/qt/widgets/block_grid.cpp b/src/qt/widgets/block_grid.cpp index 61a00a8..2e130c3 100644 --- a/src/qt/widgets/block_grid.cpp +++ b/src/qt/widgets/block_grid.cpp @@ -21,11 +21,6 @@ #include #include #include -#include -#include -#include -#include -#include #include namespace duck::widget { @@ -48,8 +43,14 @@ namespace { BlockGrid::BlockGrid (QWidget* parent, unsigned int rows, unsigned int columns, float fps) : QWidget(parent), - m_anim_timer(new QTimer(this)), + m_block_dnd( + this, + {[this](QPoint pt){return locate_icon_index_at(pt);}}, + {[this](){return m_icons.size();}}, + {[this](std::size_t index)->const QPixmap&{return m_icons[index].current_frame();}} + ), m_icon_size(-1, -1), + m_anim_timer(new QTimer(this)), m_rows(rows), m_columns(columns) { @@ -126,34 +127,7 @@ void BlockGrid::paintEvent (QPaintEvent* event) { } void BlockGrid::mousePressEvent(QMouseEvent* event) { - const auto [icon_index, block_origin] = locate_icon_index_at(event->position().toPoint()); - if (icon_index < 0) - return; - - const auto icon_index_uns = static_cast(icon_index); - if (icon_index_uns >= m_icons.size()) - return; - - QByteArray item_data; - QDataStream data_stream(&item_data, QIODevice::WriteOnly); - data_stream << m_icons[icon_index_uns].current_frame(); - - std::unique_ptr mime_data(new QMimeData); - mime_data->setData("application/x-dndblock", item_data); - - QDrag* const drag(new QDrag(this)); - drag->setMimeData(mime_data.release()); - drag->setPixmap(m_icons[icon_index_uns].current_frame()); - drag->setHotSpot(event->position().toPoint() - block_origin); - - switch (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction)) { - case Qt::MoveAction: - break; - case Qt::CopyAction: - break; - default: - break; - } + m_block_dnd.mouse_press_event(event); } void BlockGrid::advance_frame() { diff --git a/src/qt/widgets/block_grid.hpp b/src/qt/widgets/block_grid.hpp index 20a890c..a43363f 100644 --- a/src/qt/widgets/block_grid.hpp +++ b/src/qt/widgets/block_grid.hpp @@ -18,6 +18,7 @@ #pragma once #include "../animated_pixmap.hpp" +#include "detail/block_drag_and_drop.hpp" #include #include #include @@ -55,10 +56,11 @@ private: unsigned int columns() const; std::pair locate_icon_index_at (QPoint pt) const; + detail::BlockDragAndDrop m_block_dnd; std::vector m_icons; + QSize m_icon_size; QTimer* m_anim_timer; std::unique_ptr m_empty_icon; - QSize m_icon_size; unsigned int m_rows; unsigned int m_columns; }; diff --git a/src/qt/widgets/detail/block_drag_and_drop.cpp b/src/qt/widgets/detail/block_drag_and_drop.cpp new file mode 100644 index 0000000..5f1b6c0 --- /dev/null +++ b/src/qt/widgets/detail/block_drag_and_drop.cpp @@ -0,0 +1,77 @@ +/* Copyright 2020-2025, Michele Santullo + * This file is part of memoserv. + * + * Memoserv is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Memoserv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Memoserv. If not, see . + */ + +#include "block_drag_and_drop.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace duck::widget::detail { +namespace { +constexpr char g_drag_mime[] = "application/x-dndblock"; +} //unnamed namespace + +BlockDragAndDrop::BlockDragAndDrop ( + QObject* parent, + PointToIndexFunc&& func, + std::function&& get_block_count, + std::function&& get_pixmap +) : + m_point_to_index(std::move(func)), + m_get_block_count(std::move(get_block_count)), + m_get_pixmap(std::move(get_pixmap)), + m_parent(parent) +{ + assert(m_parent); +} + +void BlockDragAndDrop::mouse_press_event (const QMouseEvent* event) { + const auto [icon_index, block_origin] = m_point_to_index(event->position().toPoint()); + if (icon_index < 0) + return; + const auto icon_index_uns = static_cast(icon_index); + if (icon_index_uns >= m_get_block_count()) + return; + + QByteArray item_data; + QDataStream data_stream(&item_data, QIODevice::WriteOnly); + data_stream << m_get_pixmap(icon_index_uns); + + std::unique_ptr mime_data(new QMimeData); + mime_data->setData(g_drag_mime, item_data); + + QDrag* const drag(new QDrag(m_parent)); + drag->setMimeData(mime_data.release()); + drag->setPixmap(m_get_pixmap(icon_index_uns)); + drag->setHotSpot(event->position().toPoint() - block_origin); + + switch (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction)) { + case Qt::MoveAction: + break; + case Qt::CopyAction: + break; + default: + break; + } +} +} //namespace duck::widget::detail diff --git a/src/qt/widgets/detail/block_drag_and_drop.hpp b/src/qt/widgets/detail/block_drag_and_drop.hpp new file mode 100644 index 0000000..ddf451c --- /dev/null +++ b/src/qt/widgets/detail/block_drag_and_drop.hpp @@ -0,0 +1,48 @@ +/* Copyright 2020-2025, Michele Santullo + * This file is part of memoserv. + * + * Memoserv is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Memoserv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Memoserv. If not, see . + */ + +#pragma once + +#include +#include +#include + +class QMouseEvent; +class QPixmap; + +namespace duck::widget::detail { +class BlockDragAndDrop { +public: + typedef std::function(QPoint)> PointToIndexFunc; + + BlockDragAndDrop ( + QObject* parent, + PointToIndexFunc&& func, + std::function&& get_block_count, + std::function&& get_pixmap + ); + + void mouse_press_event (const QMouseEvent* event); + +private: + PointToIndexFunc m_point_to_index; + std::function m_get_block_count; + std::function m_get_pixmap; + QObject* m_parent; +}; + +} //namespace duck::widget::detail