diff --git a/src/playlist/playlistlistcontainer.cpp b/src/playlist/playlistlistcontainer.cpp index 3ba55bdd..65bfb527 100644 --- a/src/playlist/playlistlistcontainer.cpp +++ b/src/playlist/playlistlistcontainer.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "core/application.h" #include "core/iconloader.h" @@ -110,6 +111,7 @@ PlaylistListContainer::PlaylistListContainer(QWidget *parent) QObject::connect(ui_->tree, &PlaylistListView::ItemsSelectedChanged, this, &PlaylistListContainer::ItemsSelectedChanged); QObject::connect(ui_->tree, &PlaylistListView::doubleClicked, this, &PlaylistListContainer::ItemDoubleClicked); + QObject::connect(ui_->tree, &PlaylistListView::ItemMimeDataDroppedSignal, this, &PlaylistListContainer::ItemMimeDataDropped); model_->invisibleRootItem()->setData(PlaylistListModel::Type_Folder, PlaylistListModel::Role_Type); @@ -348,6 +350,19 @@ void PlaylistListContainer::ItemDoubleClicked(const QModelIndex &proxy_idx) { } +void PlaylistListContainer::ItemMimeDataDropped(const QModelIndex &proxy_idx, const QMimeData *q_mimedata) { + + const QModelIndex idx = proxy_->mapToSource(proxy_idx); + if (!idx.isValid()) return; + + // Drop playlist rows if type is playlist and it's not active, to prevent selfcopy + int playlis_id = idx.data(PlaylistListModel::Role_PlaylistId).toInt(); + if (idx.data(PlaylistListModel::Role_Type).toInt() == PlaylistListModel::Type_Playlist && playlis_id != app_->playlist_manager()->active_id()) { + app_->playlist_manager()->playlist(playlis_id)->dropMimeData(q_mimedata, Qt::CopyAction, -1, 0, QModelIndex()); + } + +} + void PlaylistListContainer::CopyToDevice() { #ifndef Q_OS_WIN diff --git a/src/playlist/playlistlistcontainer.h b/src/playlist/playlistlistcontainer.h index 0193af3a..062c0d31 100644 --- a/src/playlist/playlistlistcontainer.h +++ b/src/playlist/playlistlistcontainer.h @@ -63,6 +63,7 @@ class PlaylistListContainer : public QWidget { // From the UI void NewFolderClicked(); void ItemDoubleClicked(const QModelIndex &proxy_idx); + void ItemMimeDataDropped(const QModelIndex &proxy_idx, const QMimeData *q_mimedata); // From the model void PlaylistPathChanged(const int id, const QString &new_path); diff --git a/src/playlist/playlistlistview.cpp b/src/playlist/playlistlistview.cpp index 2ed71401..95eb01c4 100644 --- a/src/playlist/playlistlistview.cpp +++ b/src/playlist/playlistlistview.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include "widgets/autoexpandingtreeview.h" #include "playlistlistview.h" +#include "playlist.h" PlaylistListView::PlaylistListView(QWidget *parent) : AutoExpandingTreeView(parent) {} @@ -64,3 +66,72 @@ bool PlaylistListView::ItemsSelected() const { void PlaylistListView::selectionChanged(const QItemSelection&, const QItemSelection&) { emit ItemsSelectedChanged(selectionModel()->selectedRows().count() > 0); } + +void PlaylistListView::dragEnterEvent(QDragEnterEvent *e) { + + if (e->mimeData()->hasFormat(Playlist::kRowsMimetype)) { + e->acceptProposedAction(); + } + else { + AutoExpandingTreeView::dragEnterEvent(e); + } + +} + +void PlaylistListView::dragMoveEvent(QDragMoveEvent *e) { + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QModelIndex drag_hover_tab_ = indexAt(e->position().toPoint()); +#else + QModelIndex drag_hover_tab_ = indexAt(e->pos()); +#endif + + if (e->mimeData()->hasFormat(Playlist::kRowsMimetype)) { + if (drag_hover_tab_ != currentIndex()) { + e->setDropAction(Qt::CopyAction); + e->accept(visualRect(drag_hover_tab_)); + setCurrentIndex(drag_hover_tab_); + if (drag_hover_timer_.isActive()) { + drag_hover_timer_.stop(); + } + drag_hover_timer_.start(kDragHoverTimeout, this); + } + } + else { + AutoExpandingTreeView::dragMoveEvent(e); + } + +} + +void PlaylistListView::dragLeaveEvent(QDragLeaveEvent *e) { + + if (drag_hover_timer_.isActive()) { + drag_hover_timer_.stop(); + } + AutoExpandingTreeView::dragLeaveEvent(e); + +} + +void PlaylistListView::timerEvent(QTimerEvent *e) { + + QTreeView::timerEvent(e); + if (e->timerId() == drag_hover_timer_.timerId()) { + drag_hover_timer_.stop(); + emit doubleClicked(currentIndex()); + } + +} + +void PlaylistListView::dropEvent(QDropEvent *e) { + + if (e->mimeData()->hasFormat(Playlist::kRowsMimetype)) { + if (drag_hover_timer_.isActive()) { + drag_hover_timer_.stop(); + } + emit ItemMimeDataDroppedSignal(currentIndex(), e->mimeData()); + } + else { + AutoExpandingTreeView::dropEvent(e); + } + +} diff --git a/src/playlist/playlistlistview.h b/src/playlist/playlistlistview.h index ba768f84..89847f2e 100644 --- a/src/playlist/playlistlistview.h +++ b/src/playlist/playlistlistview.h @@ -24,6 +24,7 @@ #include "config.h" +#include #include #include #include @@ -31,6 +32,11 @@ #include "widgets/autoexpandingtreeview.h" class QPaintEvent; +class QDragEnterEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDropEvent; +class QTimerEvent; class PlaylistListView : public AutoExpandingTreeView { Q_OBJECT @@ -42,11 +48,23 @@ class PlaylistListView : public AutoExpandingTreeView { signals: void ItemsSelectedChanged(const bool); + void ItemMimeDataDroppedSignal(const QModelIndex &proxy_idx, const QMimeData *q_mimedata); protected: // QWidget void paintEvent(QPaintEvent *event) override; void selectionChanged(const QItemSelection&, const QItemSelection&) override; + + void dragEnterEvent(QDragEnterEvent *e) override; + void dragMoveEvent(QDragMoveEvent *e) override; + void dragLeaveEvent(QDragLeaveEvent *e) override; + void dropEvent(QDropEvent *e) override; + void timerEvent(QTimerEvent *e) override; + + private: + static const int kDragHoverTimeout = 500; + + QBasicTimer drag_hover_timer_; }; #endif // PLAYLISTVIEW_H