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
|
// Get the list of rows that were moved
|
||||||
QList<int> source_rows;
|
QList<int> source_rows;
|
||||||
|
Playlist* source_playlist = NULL;
|
||||||
|
|
||||||
QDataStream stream(data->data(kRowsMimetype));
|
QDataStream stream(data->data(kRowsMimetype));
|
||||||
|
stream >> source_playlist;
|
||||||
stream >> source_rows;
|
stream >> source_rows;
|
||||||
qStableSort(source_rows); // Make sure we take them in order
|
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()) {
|
} else if (data->hasUrls()) {
|
||||||
// URL list dragged from the file list or some other app
|
// URL list dragged from the file list or some other app
|
||||||
InsertUrls(data->urls(), false, row);
|
InsertUrls(data->urls(), false, row);
|
||||||
@ -708,6 +728,7 @@ QMimeData* Playlist::mimeData(const QModelIndexList& indexes) const {
|
|||||||
QBuffer buf;
|
QBuffer buf;
|
||||||
buf.open(QIODevice::WriteOnly);
|
buf.open(QIODevice::WriteOnly);
|
||||||
QDataStream stream(&buf);
|
QDataStream stream(&buf);
|
||||||
|
stream << this;
|
||||||
stream << rows;
|
stream << rows;
|
||||||
buf.close();
|
buf.close();
|
||||||
|
|
||||||
@ -1099,3 +1120,13 @@ void Playlist::QueueLayoutChanged() {
|
|||||||
emit dataChanged(index, index);
|
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_;
|
QUndoStack* undo_stack_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QDataStream& operator <<(QDataStream&, const Playlist*);
|
||||||
|
QDataStream& operator >>(QDataStream&, Playlist*&);
|
||||||
|
|
||||||
#endif // PLAYLIST_H
|
#endif // PLAYLIST_H
|
||||||
|
@ -110,6 +110,7 @@ void PlaylistContainer::ClearFilter() {
|
|||||||
|
|
||||||
void PlaylistContainer::SetManager(PlaylistManager *manager) {
|
void PlaylistContainer::SetManager(PlaylistManager *manager) {
|
||||||
manager_ = manager;
|
manager_ = manager;
|
||||||
|
ui_->tab_bar->SetManager(manager);
|
||||||
|
|
||||||
connect(ui_->tab_bar, SIGNAL(CurrentIdChanged(int)),
|
connect(ui_->tab_bar, SIGNAL(CurrentIdChanged(int)),
|
||||||
manager, SLOT(SetCurrentPlaylist(int)));
|
manager, SLOT(SetCurrentPlaylist(int)));
|
||||||
|
@ -14,19 +14,27 @@
|
|||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "playlist.h"
|
||||||
|
#include "playlistmanager.h"
|
||||||
#include "playlisttabbar.h"
|
#include "playlisttabbar.h"
|
||||||
|
#include "songmimedata.h"
|
||||||
|
#include "radio/radiomimedata.h"
|
||||||
#include "ui/iconloader.h"
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
#include <QContextMenuEvent>
|
#include <QContextMenuEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
PlaylistTabBar::PlaylistTabBar(QWidget *parent)
|
PlaylistTabBar::PlaylistTabBar(QWidget *parent)
|
||||||
: QTabBar(parent),
|
: QTabBar(parent),
|
||||||
|
manager_(NULL),
|
||||||
menu_(new QMenu(this)),
|
menu_(new QMenu(this)),
|
||||||
menu_index_(-1),
|
menu_index_(-1),
|
||||||
suppress_current_changed_(false)
|
suppress_current_changed_(false)
|
||||||
{
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
remove_ = menu_->addAction(IconLoader::Load("list-remove"), tr("Remove playlist"), this, SLOT(Remove()));
|
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()));
|
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()));
|
save_ = menu_->addAction(IconLoader::Load("document-save"), tr("Save playlist..."), this, SLOT(Save()));
|
||||||
@ -44,6 +52,10 @@ void PlaylistTabBar::SetActions(
|
|||||||
new_ = new_playlist;
|
new_ = new_playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlaylistTabBar::SetManager(PlaylistManager *manager) {
|
||||||
|
manager_ = manager;
|
||||||
|
}
|
||||||
|
|
||||||
void PlaylistTabBar::contextMenuEvent(QContextMenuEvent* e) {
|
void PlaylistTabBar::contextMenuEvent(QContextMenuEvent* e) {
|
||||||
menu_index_ = tabAt(e->pos());
|
menu_index_ = tabAt(e->pos());
|
||||||
rename_->setEnabled(menu_index_ != -1);
|
rename_->setEnabled(menu_index_ != -1);
|
||||||
@ -156,3 +168,52 @@ void PlaylistTabBar::TabMoved() {
|
|||||||
}
|
}
|
||||||
emit PlaylistOrderChanged(ids);
|
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
|
#ifndef PLAYLISTTABBAR_H
|
||||||
#define PLAYLISTTABBAR_H
|
#define PLAYLISTTABBAR_H
|
||||||
|
|
||||||
|
#include <QBasicTimer>
|
||||||
#include <QTabBar>
|
#include <QTabBar>
|
||||||
|
|
||||||
|
class PlaylistManager;
|
||||||
|
|
||||||
class QMenu;
|
class QMenu;
|
||||||
|
|
||||||
class PlaylistTabBar : public QTabBar {
|
class PlaylistTabBar : public QTabBar {
|
||||||
@ -27,7 +30,10 @@ class PlaylistTabBar : public QTabBar {
|
|||||||
public:
|
public:
|
||||||
PlaylistTabBar(QWidget *parent = 0);
|
PlaylistTabBar(QWidget *parent = 0);
|
||||||
|
|
||||||
|
static const int kDragHoverTimeout = 500;
|
||||||
|
|
||||||
void SetActions(QAction* new_playlist, QAction* load_playlist);
|
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
|
// We use IDs to refer to tabs so the tabs can be moved around (and their
|
||||||
// indexes change).
|
// indexes change).
|
||||||
@ -49,6 +55,16 @@ signals:
|
|||||||
void Save(int id);
|
void Save(int id);
|
||||||
void PlaylistOrderChanged(const QList<int>& ids);
|
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:
|
private slots:
|
||||||
void CurrentIndexChanged(int index);
|
void CurrentIndexChanged(int index);
|
||||||
void Rename();
|
void Rename();
|
||||||
@ -56,12 +72,9 @@ private slots:
|
|||||||
void TabMoved();
|
void TabMoved();
|
||||||
void Save();
|
void Save();
|
||||||
|
|
||||||
protected:
|
|
||||||
void contextMenuEvent(QContextMenuEvent* e);
|
|
||||||
void mouseReleaseEvent(QMouseEvent* e);
|
|
||||||
void mouseDoubleClickEvent(QMouseEvent* e);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PlaylistManager* manager_;
|
||||||
|
|
||||||
QMenu* menu_;
|
QMenu* menu_;
|
||||||
int menu_index_;
|
int menu_index_;
|
||||||
QAction* new_;
|
QAction* new_;
|
||||||
@ -69,6 +82,9 @@ private:
|
|||||||
QAction* remove_;
|
QAction* remove_;
|
||||||
QAction* save_;
|
QAction* save_;
|
||||||
|
|
||||||
|
QBasicTimer drag_hover_timer_;
|
||||||
|
int drag_hover_tab_;
|
||||||
|
|
||||||
bool suppress_current_changed_;
|
bool suppress_current_changed_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user