mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-01 20:06:53 +01:00
Support dragging and dropping between playlists
This commit is contained in:
parent
24134dd1ab
commit
40a2302311
@ -492,11 +492,31 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
||||
|
||||
// Get the list of rows that were moved
|
||||
QList<int> source_rows;
|
||||
Playlist* source_playlist = NULL;
|
||||
|
||||
QDataStream stream(data->data(kRowsMimetype));
|
||||
stream >> source_playlist;
|
||||
stream >> source_rows;
|
||||
qStableSort(source_rows); // Make sure we take them in order
|
||||
|
||||
undo_stack_->push(new PlaylistUndoCommands::MoveItems(this, source_rows, row));
|
||||
if (source_playlist == this) {
|
||||
// Dragged from this playlist - rearrange the items
|
||||
undo_stack_->push(new PlaylistUndoCommands::MoveItems(this, source_rows, row));
|
||||
} else {
|
||||
// Drag from a different playlist
|
||||
PlaylistItemList items;
|
||||
foreach (int row, source_rows)
|
||||
items << source_playlist->item_at(row);
|
||||
undo_stack_->push(new PlaylistUndoCommands::InsertItems(this, items, row));
|
||||
|
||||
// Remove the items from the source playlist if it was a move event
|
||||
if (action == Qt::MoveAction) {
|
||||
foreach (int row, source_rows) {
|
||||
source_playlist->undo_stack()->push(
|
||||
new PlaylistUndoCommands::RemoveItems(source_playlist, row, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (data->hasUrls()) {
|
||||
// URL list dragged from the file list or some other app
|
||||
InsertUrls(data->urls(), false, row);
|
||||
@ -708,6 +728,7 @@ QMimeData* Playlist::mimeData(const QModelIndexList& indexes) const {
|
||||
QBuffer buf;
|
||||
buf.open(QIODevice::WriteOnly);
|
||||
QDataStream stream(&buf);
|
||||
stream << this;
|
||||
stream << rows;
|
||||
buf.close();
|
||||
|
||||
@ -1099,3 +1120,13 @@ void Playlist::QueueLayoutChanged() {
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream& s, const Playlist* p) {
|
||||
s.writeRawData(reinterpret_cast<char*>(&p), sizeof(p));
|
||||
return s;
|
||||
}
|
||||
|
||||
QDataStream& operator >>(QDataStream& s, Playlist*& p) {
|
||||
s.readRawData(reinterpret_cast<char*>(&p), sizeof(p));
|
||||
return s;
|
||||
}
|
||||
|
@ -240,4 +240,7 @@ class Playlist : public QAbstractListModel {
|
||||
QUndoStack* undo_stack_;
|
||||
};
|
||||
|
||||
QDataStream& operator <<(QDataStream&, const Playlist*);
|
||||
QDataStream& operator >>(QDataStream&, Playlist*&);
|
||||
|
||||
#endif // PLAYLIST_H
|
||||
|
@ -110,6 +110,7 @@ void PlaylistContainer::ClearFilter() {
|
||||
|
||||
void PlaylistContainer::SetManager(PlaylistManager *manager) {
|
||||
manager_ = manager;
|
||||
ui_->tab_bar->SetManager(manager);
|
||||
|
||||
connect(ui_->tab_bar, SIGNAL(CurrentIdChanged(int)),
|
||||
manager, SLOT(SetCurrentPlaylist(int)));
|
||||
|
@ -14,19 +14,27 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "playlist.h"
|
||||
#include "playlistmanager.h"
|
||||
#include "playlisttabbar.h"
|
||||
#include "songmimedata.h"
|
||||
#include "radio/radiomimedata.h"
|
||||
#include "ui/iconloader.h"
|
||||
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMenu>
|
||||
#include <QInputDialog>
|
||||
#include <QtDebug>
|
||||
|
||||
PlaylistTabBar::PlaylistTabBar(QWidget *parent)
|
||||
: QTabBar(parent),
|
||||
manager_(NULL),
|
||||
menu_(new QMenu(this)),
|
||||
menu_index_(-1),
|
||||
suppress_current_changed_(false)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
|
||||
remove_ = menu_->addAction(IconLoader::Load("list-remove"), tr("Remove playlist"), this, SLOT(Remove()));
|
||||
rename_ = menu_->addAction(IconLoader::Load("edit-rename"), tr("Rename playlist..."), this, SLOT(Rename()));
|
||||
save_ = menu_->addAction(IconLoader::Load("document-save"), tr("Save playlist..."), this, SLOT(Save()));
|
||||
@ -44,6 +52,10 @@ void PlaylistTabBar::SetActions(
|
||||
new_ = new_playlist;
|
||||
}
|
||||
|
||||
void PlaylistTabBar::SetManager(PlaylistManager *manager) {
|
||||
manager_ = manager;
|
||||
}
|
||||
|
||||
void PlaylistTabBar::contextMenuEvent(QContextMenuEvent* e) {
|
||||
menu_index_ = tabAt(e->pos());
|
||||
rename_->setEnabled(menu_index_ != -1);
|
||||
@ -156,3 +168,52 @@ void PlaylistTabBar::TabMoved() {
|
||||
}
|
||||
emit PlaylistOrderChanged(ids);
|
||||
}
|
||||
|
||||
void PlaylistTabBar::dragEnterEvent(QDragEnterEvent* e) {
|
||||
if (e->mimeData()->hasUrls() ||
|
||||
e->mimeData()->hasFormat(Playlist::kRowsMimetype) ||
|
||||
qobject_cast<const SongMimeData*>(e->mimeData()) ||
|
||||
qobject_cast<const RadioMimeData*>(e->mimeData())) {
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistTabBar::dragMoveEvent(QDragMoveEvent* e) {
|
||||
drag_hover_tab_ = tabAt(e->pos());
|
||||
|
||||
if (drag_hover_tab_ == -1) {
|
||||
e->setDropAction(Qt::IgnoreAction);
|
||||
e->ignore();
|
||||
drag_hover_timer_.stop();
|
||||
} else {
|
||||
e->setDropAction(Qt::CopyAction);
|
||||
e->accept(tabRect(drag_hover_tab_));
|
||||
|
||||
if (!drag_hover_timer_.isActive())
|
||||
drag_hover_timer_.start(kDragHoverTimeout, this);
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistTabBar::dragLeaveEvent(QDragLeaveEvent*) {
|
||||
drag_hover_timer_.stop();
|
||||
}
|
||||
|
||||
void PlaylistTabBar::timerEvent(QTimerEvent* e) {
|
||||
QTabBar::timerEvent(e);
|
||||
|
||||
if (e->timerId() == drag_hover_timer_.timerId()) {
|
||||
drag_hover_timer_.stop();
|
||||
if (drag_hover_tab_ != -1)
|
||||
setCurrentIndex(drag_hover_tab_);
|
||||
}
|
||||
}
|
||||
|
||||
void PlaylistTabBar::dropEvent(QDropEvent* e) {
|
||||
if (drag_hover_tab_ == -1) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentIndex(drag_hover_tab_);
|
||||
manager_->current()->dropMimeData(e->mimeData(), e->proposedAction(), -1, 0, QModelIndex());
|
||||
}
|
||||
|
@ -17,8 +17,11 @@
|
||||
#ifndef PLAYLISTTABBAR_H
|
||||
#define PLAYLISTTABBAR_H
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QTabBar>
|
||||
|
||||
class PlaylistManager;
|
||||
|
||||
class QMenu;
|
||||
|
||||
class PlaylistTabBar : public QTabBar {
|
||||
@ -27,7 +30,10 @@ class PlaylistTabBar : public QTabBar {
|
||||
public:
|
||||
PlaylistTabBar(QWidget *parent = 0);
|
||||
|
||||
static const int kDragHoverTimeout = 500;
|
||||
|
||||
void SetActions(QAction* new_playlist, QAction* load_playlist);
|
||||
void SetManager(PlaylistManager* manager);
|
||||
|
||||
// We use IDs to refer to tabs so the tabs can be moved around (and their
|
||||
// indexes change).
|
||||
@ -49,6 +55,16 @@ signals:
|
||||
void Save(int id);
|
||||
void PlaylistOrderChanged(const QList<int>& ids);
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent* e);
|
||||
void mouseReleaseEvent(QMouseEvent* e);
|
||||
void mouseDoubleClickEvent(QMouseEvent* e);
|
||||
void dragEnterEvent(QDragEnterEvent* e);
|
||||
void dragMoveEvent(QDragMoveEvent* e);
|
||||
void dragLeaveEvent(QDragLeaveEvent* e);
|
||||
void dropEvent(QDropEvent* e);
|
||||
void timerEvent(QTimerEvent *);
|
||||
|
||||
private slots:
|
||||
void CurrentIndexChanged(int index);
|
||||
void Rename();
|
||||
@ -56,12 +72,9 @@ private slots:
|
||||
void TabMoved();
|
||||
void Save();
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent* e);
|
||||
void mouseReleaseEvent(QMouseEvent* e);
|
||||
void mouseDoubleClickEvent(QMouseEvent* e);
|
||||
|
||||
private:
|
||||
PlaylistManager* manager_;
|
||||
|
||||
QMenu* menu_;
|
||||
int menu_index_;
|
||||
QAction* new_;
|
||||
@ -69,6 +82,9 @@ private:
|
||||
QAction* remove_;
|
||||
QAction* save_;
|
||||
|
||||
QBasicTimer drag_hover_timer_;
|
||||
int drag_hover_tab_;
|
||||
|
||||
bool suppress_current_changed_;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user