Support dragging and dropping between playlists

This commit is contained in:
David Sansome 2010-07-17 12:47:59 +00:00
parent 24134dd1ab
commit 40a2302311
5 changed files with 118 additions and 6 deletions

View File

@ -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;
}

View File

@ -240,4 +240,7 @@ class Playlist : public QAbstractListModel {
QUndoStack* undo_stack_;
};
QDataStream& operator <<(QDataStream&, const Playlist*);
QDataStream& operator >>(QDataStream&, Playlist*&);
#endif // PLAYLIST_H

View File

@ -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)));

View File

@ -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());
}

View File

@ -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_;
};