Fix inconsistency between adding items via drag'n'drop and using the '>>' actions

This commit is contained in:
craig
2012-01-03 19:54:13 +00:00
committed by craig
parent d4bb8f5281
commit 1872cef46f
18 changed files with 141 additions and 166 deletions

View File

@@ -5,6 +5,8 @@
3. Add option to group single track artist/albums under
'Various Artists'/'Single Tracks'/'Artist - Track'
4. Improve time slider accuracu, by checking the time elapsed at each interval.
5. Fix inconsistency between adding items via drag'n'drop and using the '>>'
actions.
0.1.2
-----

View File

@@ -104,26 +104,19 @@ void AlbumsPage::setItemSize()
void AlbumsPage::addSelectionToPlaylist(const QString &name)
{
QStringList files;
const QModelIndexList selected = view->selectedIndexes();
if (0==selected.size()) {
return;
}
QModelIndexList mapped;
foreach (const QModelIndex &idx, selected) {
AlbumsModel::Item *item=static_cast<AlbumsModel::Item *>(proxy.mapToSource(idx).internalPointer());
if (item->isAlbum()) {
foreach (const AlbumsModel::SongItem *s, static_cast<AlbumsModel::AlbumItem*>(item)->songs) {
files << s->file;
}
} else {
files << static_cast<AlbumsModel::SongItem*>(item)->file;
}
mapped.append(proxy.mapToSource(idx));
}
QStringList files=model.filenames(mapped);
if (!files.isEmpty()) {
if (name.isEmpty()) {
emit add(files);

View File

@@ -111,31 +111,19 @@ void FolderPage::itemDoubleClicked(const QModelIndex &)
void FolderPage::addSelectionToPlaylist(const QString &name)
{
// Get selected view indexes
QModelIndexList selected = view->selectedIndexes();
QStringList files;
const QModelIndexList selected = view->selectedIndexes();
foreach (const QModelIndex idx, selected) {
DirViewItem *item = static_cast<DirViewItem *>(proxy.mapToSource(idx).internalPointer());
QStringList tmp;
switch (item->type()) {
case DirViewItem::Type_Dir:
tmp = walk(idx);
for (int i = 0; i < tmp.size(); i++) {
if (!files.contains(tmp.at(i)))
files << tmp.at(i);
}
break;
case DirViewItem::Type_File:
if (!files.contains(item->fullName()))
files << item->fullName();
break;
default:
break;
}
if (0==selected.size()) {
return;
}
QModelIndexList mapped;
foreach (const QModelIndex &idx, selected) {
mapped.append(proxy.mapToSource(idx));
}
QStringList files=model.filenames(mapped);
if (!files.isEmpty()) {
if (name.isEmpty()) {
emit add(files);

View File

@@ -104,59 +104,19 @@ void LibraryPage::clear()
void LibraryPage::addSelectionToPlaylist(const QString &name)
{
QStringList files;
MusicLibraryItem *item;
MusicLibraryItemSong *songItem;
QModelIndexList selected = view->selectedIndexes();
const QModelIndexList selected = view->selectedIndexes();
// Loop over the selection. Only add files.
foreach (const QModelIndex &idx, selected) {
item = static_cast<MusicLibraryItem *>(proxy.mapToSource(idx).internalPointer());
switch (item->type()) {
case MusicLibraryItem::Type_Artist: {
for (quint32 i = 0; ; i++) {
const QModelIndex album = idx.child(i , 0);
if (!album.isValid())
break;
for (quint32 j = 0; ; j++) {
const QModelIndex track = album.child(j, 0);
if (!track.isValid())
break;
const QModelIndex mappedSongIndex = proxy.mapToSource(track);
songItem = static_cast<MusicLibraryItemSong *>(mappedSongIndex.internalPointer());
const QString fileName = songItem->file();
if (!fileName.isEmpty() && !files.contains(fileName))
files.append(fileName);
}
}
break;
}
case MusicLibraryItem::Type_Album: {
for (quint32 i = 0; ; i++) {
QModelIndex track = idx.child(i, 0);
if (!track.isValid())
break;
const QModelIndex mappedSongIndex = proxy.mapToSource(track);
songItem = static_cast<MusicLibraryItemSong *>(mappedSongIndex.internalPointer());
const QString fileName = songItem->file();
if (!fileName.isEmpty() && !files.contains(fileName))
files.append(fileName);
}
break;
}
case MusicLibraryItem::Type_Song: {
const QString fileName = static_cast<MusicLibraryItemSong *>(item)->file();
if (!fileName.isEmpty() && !files.contains(fileName))
files.append(fileName);
break;
}
default:
break;
}
if (0==selected.size()) {
return;
}
QModelIndexList mapped;
foreach (const QModelIndex &idx, selected) {
mapped.append(proxy.mapToSource(idx));
}
QStringList files=model.filenames(mapped);
if (!files.isEmpty()) {
if (name.isEmpty()) {
emit add(files);

View File

@@ -37,16 +37,6 @@
#include <QtGui/QMessageBox>
#endif
// Play Queue - for some reason, expects the list in reverse order...
static QStringList reverseList(const QStringList &orig)
{
QStringList rev;
foreach (const QString &s, orig) {
rev.prepend(s);
}
return rev;
}
PlaylistsPage::PlaylistsPage(MainWindow *p)
: QWidget(p)
{
@@ -254,10 +244,12 @@ void PlaylistsPage::itemDoubleClicked(const QModelIndex &index)
void PlaylistsPage::addItemsToPlayQueue(const QModelIndexList &indexes)
{
QStringList filenames;
if (0==indexes.size()) {
return;
}
// If we only have 1 item selected, see if it is a playlist. If so, we might be able to
// jsut ask MPD to load it...
// just ask MPD to load it...
if (1==indexes.count()) {
QModelIndex idx=proxy.mapToSource(*(indexes.begin()));
PlaylistsModel::Item *item=static_cast<PlaylistsModel::Item *>(idx.internalPointer());
@@ -267,36 +259,28 @@ void PlaylistsPage::addItemsToPlayQueue(const QModelIndexList &indexes)
foreach (const PlaylistsModel::SongItem *s, static_cast<PlaylistsModel::PlaylistItem*>(item)->songs) {
if (s->file.startsWith("http:/")) {
loadable=false; // Can't just load playlist, might need to parse HTTP...
break;
}
filenames << s->file;
}
if (loadable) {
emit loadPlaylist(static_cast<PlaylistsModel::PlaylistItem*>(item)->name);;
} else {
emit add(reverseList(filenames));
emit loadPlaylist(static_cast<PlaylistsModel::PlaylistItem*>(item)->name);
return;
}
view->clearSelection();
return;
}
}
QSet<PlaylistsModel::Item *> selectedPlaylists;
foreach(QModelIndex index, indexes) {
QModelIndex idx=proxy.mapToSource(index);
PlaylistsModel::Item *item=static_cast<PlaylistsModel::Item *>(idx.internalPointer());
if (item->isPlaylist()) {
selectedPlaylists.insert(item);
foreach (const PlaylistsModel::SongItem *s, static_cast<PlaylistsModel::PlaylistItem*>(item)->songs) {
filenames << s->file;
}
} else if (!selectedPlaylists.contains(static_cast<PlaylistsModel::SongItem*>(item)->parent)) {
filenames << static_cast<PlaylistsModel::SongItem*>(item)->file;
}
QModelIndexList mapped;
foreach (const QModelIndex &idx, indexes) {
mapped.append(proxy.mapToSource(idx));
}
QStringList files=PlaylistsModel::self()->filenames(mapped);
if (!files.isEmpty()) {
emit add(files);
view->clearSelection();
}
view->clearSelection();
emit add(reverseList(filenames));
}
void PlaylistsPage::selectionChanged()

View File

@@ -138,18 +138,15 @@ void StreamsPage::addItemsToPlayQueue(const QModelIndexList &indexes)
return;
}
QStringList streams;
QModelIndexList mapped;
foreach (const QModelIndex &idx, indexes) {
QString stream=model.data(proxy.mapToSource(idx), Qt::ToolTipRole).toString();
if (!streams.contains(stream)) {
streams << stream;
}
mapped.append(proxy.mapToSource(idx));
}
if (!streams.isEmpty()) {
emit add(streams);
QStringList files=model.filenames(mapped);
if (!files.isEmpty()) {
emit add(files);
view->clearSelection();
}
}

View File

@@ -299,25 +299,29 @@ Qt::ItemFlags AlbumsModel::flags(const QModelIndex &index) const
return Qt::NoItemFlags;
}
QMimeData * AlbumsModel::mimeData(const QModelIndexList &indexes) const
QStringList AlbumsModel::filenames(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QStringList filenames;
QStringList fnames;
foreach(QModelIndex index, indexes) {
Item *item=static_cast<Item *>(index.internalPointer());
if (item->isAlbum()) {
foreach (const SongItem *s, static_cast<AlbumItem*>(item)->songs) {
if (!filenames.contains(s->file)) {
filenames << s->file;
if (!fnames.contains(s->file)) {
fnames << s->file;
}
}
} else if (!filenames.contains(static_cast<SongItem*>(item)->file)) {
filenames << static_cast<SongItem*>(item)->file;
} else if (!fnames.contains(static_cast<SongItem*>(item)->file)) {
fnames << static_cast<SongItem*>(item)->file;
}
}
return fnames;
}
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames);
QMimeData * AlbumsModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames(indexes));
return mimeData;
}

View File

@@ -93,6 +93,7 @@ public:
QModelIndex index(int row, int column, const QModelIndex &parent) const;
QVariant data(const QModelIndex &, int) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QStringList filenames(const QModelIndexList &indexes) const;
QMimeData * mimeData(const QModelIndexList &indexes) const;
void update(const MusicLibraryItemRoot *root);
void clear();

View File

@@ -180,17 +180,21 @@ Qt::ItemFlags dirViewModel::flags(const QModelIndex &index) const
return Qt::ItemIsDropEnabled;
}
QMimeData *dirViewModel::mimeData(const QModelIndexList &indexes) const
QStringList dirViewModel::filenames(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QStringList filenames;
QStringList fnames;
foreach(QModelIndex index, indexes) {
DirViewItem *item = static_cast<DirViewItem *>(index.internalPointer());
recurseDirItems(*item, filenames);
recurseDirItems(*item, fnames);
}
return fnames;
}
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames);
QMimeData *dirViewModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames(indexes));
return mimeData;
}

View File

@@ -45,6 +45,7 @@ public:
int columnCount(const QModelIndex &) const;
QVariant data(const QModelIndex &, int) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QStringList filenames(const QModelIndexList &indexes) const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
void clear();

View File

@@ -512,16 +512,9 @@ Qt::ItemFlags MusicLibraryModel::flags(const QModelIndex &index) const
return Qt::ItemIsDropEnabled;
}
/**
* Convert the data at indexes into mimedata ready for transport
*
* @param indexes The indexes to pack into mimedata
* @return The mimedata
*/
QMimeData *MusicLibraryModel::mimeData(const QModelIndexList &indexes) const
QStringList MusicLibraryModel::filenames(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QStringList filenames;
QStringList fnames;
foreach(QModelIndex index, indexes) {
MusicLibraryItem *item = static_cast<MusicLibraryItem *>(index.internalPointer());
@@ -531,8 +524,8 @@ QMimeData *MusicLibraryModel::mimeData(const QModelIndexList &indexes) const
for (int i = 0; i < item->childCount(); i++) {
QStringList sorted=static_cast<MusicLibraryItemAlbum*>(item->child(i))->sortedTracks();
foreach (const QString &f, sorted) {
if(!filenames.contains(f)) {
filenames << f;
if(!fnames.contains(f)) {
fnames << f;
}
}
}
@@ -540,22 +533,33 @@ QMimeData *MusicLibraryModel::mimeData(const QModelIndexList &indexes) const
case MusicLibraryItem::Type_Album: {
QStringList sorted=static_cast<MusicLibraryItemAlbum*>(item)->sortedTracks();
foreach (const QString &f, sorted) {
if(!filenames.contains(f)) {
filenames << f;
if(!fnames.contains(f)) {
fnames << f;
}
}
break;
}
case MusicLibraryItem::Type_Song:
if (item->type() == MusicLibraryItem::Type_Song && !filenames.contains(static_cast<MusicLibraryItemSong*>(item)->file())) {
filenames << static_cast<MusicLibraryItemSong*>(item)->file();
if (item->type() == MusicLibraryItem::Type_Song && !fnames.contains(static_cast<MusicLibraryItemSong*>(item)->file())) {
fnames << static_cast<MusicLibraryItemSong*>(item)->file();
}
break;
default:
break;
}
}
return fnames;
}
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames);
/**
* Convert the data at indexes into mimedata ready for transport
*
* @param indexes The indexes to pack into mimedata
* @return The mimedata
*/
QMimeData *MusicLibraryModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames(indexes));
return mimeData;
}

View File

@@ -51,6 +51,7 @@ public:
int columnCount(const QModelIndex &) const;
QVariant data(const QModelIndex &, int) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QStringList filenames(const QModelIndexList &indexes) const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
const MusicLibraryItemRoot * root() const { return rootItem; }

View File

@@ -240,6 +240,26 @@ Qt::DropActions PlaylistsModel::supportedDropActions() const
return Qt::CopyAction | Qt::MoveAction;
}
QStringList PlaylistsModel::filenames(const QModelIndexList &indexes) const
{
QStringList fnames;
QSet<Item *> selectedPlaylists;
foreach(QModelIndex index, indexes) {
Item *item=static_cast<Item *>(index.internalPointer());
if (item->isPlaylist()) {
selectedPlaylists.insert(item);
foreach (const SongItem *s, static_cast<PlaylistItem*>(item)->songs) {
fnames << s->file;
}
} else if (!selectedPlaylists.contains(static_cast<SongItem*>(item)->parent)) {
fnames << static_cast<SongItem*>(item)->file;
}
}
return fnames;
}
static const QLatin1String constPlaylistNameMimeType("cantata/playlistnames");
static const QLatin1String constPositionsMimeType("cantata/positions");

View File

@@ -80,6 +80,7 @@ public:
QVariant data(const QModelIndex &, int) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
Qt::DropActions supportedDropActions() const;
QStringList filenames(const QModelIndexList &indexes) const;
QMimeData * mimeData(const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int /*col*/, const QModelIndex &parent);
QStringList mimeTypes() const;

View File

@@ -40,6 +40,15 @@
#include "mpdstatus.h"
#include "streamfetcher.h"
static QStringList reverseList(const QStringList &orig)
{
QStringList rev;
foreach (const QString &s, orig) {
rev.prepend(s);
}
return rev;
}
const QLatin1String PlayQueueModel::constMoveMimeType("cantata/move");
const QLatin1String PlayQueueModel::constFileNameMimeType("cantata/filename");
@@ -55,14 +64,14 @@ void PlayQueueModel::encode(QMimeData &mimeData, const QString &mime, const QStr
mimeData.setData(mime, encodedData);
}
QStringList PlayQueueModel::decode(const QMimeData &mimeData, const QString &mime, bool rev)
QStringList PlayQueueModel::decode(const QMimeData &mimeData, const QString &mime)
{
QByteArray encodedData=mimeData.data(mime);
QTextStream stream(&encodedData, QIODevice::ReadOnly);
QStringList rv;
while (!stream.atEnd()) {
rev ? rv.prepend(stream.readLine().remove('\n')) : rv.append(stream.readLine().remove('\n'));
rv.append(stream.readLine().remove('\n'));
}
return rv;
}
@@ -294,7 +303,7 @@ bool PlayQueueModel::dropMimeData(const QMimeData *data,
return true;
} else if (data->hasFormat(constFileNameMimeType)) {
//Act on moves from the music library and dir view
addItems(decode(*data, constFileNameMimeType, true), row);
addItems(reverseList(decode(*data, constFileNameMimeType)), row);
return true;
}

View File

@@ -59,7 +59,7 @@ public:
static const QLatin1String constFileNameMimeType;
static void encode(QMimeData &mimeData, const QString &mime, const QStringList &values);
static QStringList decode(const QMimeData &mimeData, const QString &mime, bool rev=false);
static QStringList decode(const QMimeData &mimeData, const QString &mime);
PlayQueueModel(QObject *parent = 0);
~PlayQueueModel();

View File

@@ -457,10 +457,9 @@ Qt::ItemFlags StreamsModel::flags(const QModelIndex &index) const
return Qt::NoItemFlags;
}
QMimeData * StreamsModel::mimeData(const QModelIndexList &indexes) const
QStringList StreamsModel::filenames(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QStringList filenames;
QStringList fnames;
QSet<Item *> selectedCategories;
foreach(QModelIndex index, indexes) {
Item *item=static_cast<Item *>(index.internalPointer());
@@ -469,19 +468,25 @@ QMimeData * StreamsModel::mimeData(const QModelIndexList &indexes) const
selectedCategories.insert(item);
foreach (const StreamItem *s, static_cast<CategoryItem*>(item)->streams) {
QString f=s->url.toString();
if (!filenames.contains(f)) {
filenames << f;
if (!fnames.contains(f)) {
fnames << f;
}
}
} else if (!selectedCategories.contains(static_cast<StreamItem*>(item)->parent)) {
QString f=static_cast<StreamItem*>(item)->url.toString();
if (!filenames.contains(f)) {
filenames << f;
if (!fnames.contains(f)) {
fnames << f;
}
}
}
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames);
return fnames;
}
QMimeData * StreamsModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
PlayQueueModel::encode(*mimeData, PlayQueueModel::constFileNameMimeType, filenames(indexes));
return mimeData;
}

View File

@@ -82,6 +82,7 @@ public:
QString name(const QString &cat, const QString &url) { return name(getCategory(cat), url); }
bool entryExists(const QString &cat, const QString &name, const QUrl &url=QUrl()) { return entryExists(getCategory(cat), name, url); }
Qt::ItemFlags flags(const QModelIndex &index) const;
QStringList filenames(const QModelIndexList &indexes) const;
QMimeData * mimeData(const QModelIndexList &indexes) const;
void mark(const QList<int> &rows, bool f);