Merge remote-tracking branch 'upstream/master' into qt5
This commit is contained in:
commit
16b4f9a991
|
@ -104,6 +104,7 @@ message SongMetadata {
|
||||||
TRUEAUDIO = 11;
|
TRUEAUDIO = 11;
|
||||||
CDDA = 12;
|
CDDA = 12;
|
||||||
OGGOPUS = 13;
|
OGGOPUS = 13;
|
||||||
|
WAVPACK = 14;
|
||||||
STREAM = 99;
|
STREAM = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include <unsynchronizedlyricsframe.h>
|
#include <unsynchronizedlyricsframe.h>
|
||||||
#include <vorbisfile.h>
|
#include <vorbisfile.h>
|
||||||
#include <wavfile.h>
|
#include <wavfile.h>
|
||||||
|
#include <wavpackfile.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -659,6 +660,8 @@ pb::tagreader::SongMetadata_Type TagReader::GuessFileType(
|
||||||
return pb::tagreader::SongMetadata_Type_WAV;
|
return pb::tagreader::SongMetadata_Type_WAV;
|
||||||
if (dynamic_cast<TagLib::TrueAudio::File*>(fileref->file()))
|
if (dynamic_cast<TagLib::TrueAudio::File*>(fileref->file()))
|
||||||
return pb::tagreader::SongMetadata_Type_TRUEAUDIO;
|
return pb::tagreader::SongMetadata_Type_TRUEAUDIO;
|
||||||
|
if (dynamic_cast<TagLib::WavPack::File*>(fileref->file()))
|
||||||
|
return pb::tagreader::SongMetadata_Type_WAVPACK;
|
||||||
|
|
||||||
return pb::tagreader::SongMetadata_Type_UNKNOWN;
|
return pb::tagreader::SongMetadata_Type_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ message SongMetadata {
|
||||||
TRUEAUDIO = 11;
|
TRUEAUDIO = 11;
|
||||||
CDDA = 12;
|
CDDA = 12;
|
||||||
OGGOPUS = 13;
|
OGGOPUS = 13;
|
||||||
|
WAVPACK = 14;
|
||||||
STREAM = 99;
|
STREAM = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,12 @@ class MimeData : public QMimeData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MimeData(bool clear = false, bool play_now = false, bool enqueue = false,
|
MimeData(bool clear = false, bool play_now = false, bool enqueue = false,
|
||||||
bool open_in_new_playlist = false)
|
bool enqueue_next_now = false, bool open_in_new_playlist = false)
|
||||||
: override_user_settings_(false),
|
: override_user_settings_(false),
|
||||||
clear_first_(clear),
|
clear_first_(clear),
|
||||||
play_now_(play_now),
|
play_now_(play_now),
|
||||||
enqueue_now_(enqueue),
|
enqueue_now_(enqueue),
|
||||||
|
enqueue_next_now_(enqueue_next_now),
|
||||||
open_in_new_playlist_(open_in_new_playlist),
|
open_in_new_playlist_(open_in_new_playlist),
|
||||||
name_for_new_playlist_(QString()),
|
name_for_new_playlist_(QString()),
|
||||||
from_doubleclick_(false) {}
|
from_doubleclick_(false) {}
|
||||||
|
@ -53,6 +54,10 @@ class MimeData : public QMimeData {
|
||||||
// If this is set then the items are added to the queue after being inserted.
|
// If this is set then the items are added to the queue after being inserted.
|
||||||
bool enqueue_now_;
|
bool enqueue_now_;
|
||||||
|
|
||||||
|
// If this is set then the items are added to the beginning of the queue after
|
||||||
|
// being inserted.
|
||||||
|
bool enqueue_next_now_;
|
||||||
|
|
||||||
// If this is set then the items are inserted into a newly created playlist.
|
// If this is set then the items are inserted into a newly created playlist.
|
||||||
bool open_in_new_playlist_;
|
bool open_in_new_playlist_;
|
||||||
|
|
||||||
|
|
|
@ -427,6 +427,8 @@ QString Song::TextForFiletype(FileType type) {
|
||||||
return QObject::tr("AIFF");
|
return QObject::tr("AIFF");
|
||||||
case Song::Type_Wav:
|
case Song::Type_Wav:
|
||||||
return QObject::tr("Wav");
|
return QObject::tr("Wav");
|
||||||
|
case Song::Type_WavPack:
|
||||||
|
return QObject::tr("WavPack");
|
||||||
case Song::Type_TrueAudio:
|
case Song::Type_TrueAudio:
|
||||||
return QObject::tr("TrueAudio");
|
return QObject::tr("TrueAudio");
|
||||||
case Song::Type_Cdda:
|
case Song::Type_Cdda:
|
||||||
|
@ -447,6 +449,7 @@ bool Song::IsFileLossless() const {
|
||||||
case Song::Type_Flac:
|
case Song::Type_Flac:
|
||||||
case Song::Type_OggFlac:
|
case Song::Type_OggFlac:
|
||||||
case Song::Type_Wav:
|
case Song::Type_Wav:
|
||||||
|
case Song::Type_WavPack:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -673,7 +676,8 @@ void Song::InitFromFilePartial(const QString& filename) {
|
||||||
if (suffix == "mp3" || suffix == "ogg" || suffix == "flac" ||
|
if (suffix == "mp3" || suffix == "ogg" || suffix == "flac" ||
|
||||||
suffix == "mpc" || suffix == "m4a" || suffix == "aac" ||
|
suffix == "mpc" || suffix == "m4a" || suffix == "aac" ||
|
||||||
suffix == "wma" || suffix == "mp4" || suffix == "spx" ||
|
suffix == "wma" || suffix == "mp4" || suffix == "spx" ||
|
||||||
suffix == "wav" || suffix == "opus" || suffix == "m4b") {
|
suffix == "wav" || suffix == "opus" || suffix == "m4b" ||
|
||||||
|
suffix == "wv") {
|
||||||
d->valid_ = true;
|
d->valid_ = true;
|
||||||
} else {
|
} else {
|
||||||
d->valid_ = false;
|
d->valid_ = false;
|
||||||
|
|
|
@ -101,6 +101,7 @@ class Song {
|
||||||
Type_TrueAudio = 11,
|
Type_TrueAudio = 11,
|
||||||
Type_Cdda = 12,
|
Type_Cdda = 12,
|
||||||
Type_OggOpus = 13,
|
Type_OggOpus = 13,
|
||||||
|
Type_WavPack = 14,
|
||||||
Type_Stream = 99,
|
Type_Stream = 99,
|
||||||
};
|
};
|
||||||
static QString TextForFiletype(FileType type);
|
static QString TextForFiletype(FileType type);
|
||||||
|
|
|
@ -60,6 +60,7 @@ void LastFmCoverProvider::QueryFinished(QNetworkReply* reply, int id) {
|
||||||
result.description =
|
result.description =
|
||||||
element["artist"].text() + " - " + element["name"].text();
|
element["artist"].text() + " - " + element["name"].text();
|
||||||
result.image_url = QUrl(element["image size=extralarge"].text());
|
result.image_url = QUrl(element["image size=extralarge"].text());
|
||||||
|
if (result.image_url.isEmpty()) continue;
|
||||||
results << result;
|
results << result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -39,7 +39,7 @@ const char* DigitallyImportedClient::kAuthUrl =
|
||||||
"http://api.audioaddict.com/v1/%1/members/authenticate";
|
"http://api.audioaddict.com/v1/%1/members/authenticate";
|
||||||
|
|
||||||
const char* DigitallyImportedClient::kChannelListUrl =
|
const char* DigitallyImportedClient::kChannelListUrl =
|
||||||
"http://api.v2.audioaddict.com/v1/%1/mobile/"
|
"http://api.audioaddict.com/v1/%1/mobile/"
|
||||||
"batch_update?asset_group_key=mobile_icons&stream_set_key=";
|
"batch_update?asset_group_key=mobile_icons&stream_set_key=";
|
||||||
|
|
||||||
DigitallyImportedClient::DigitallyImportedClient(const QString& service_name,
|
DigitallyImportedClient::DigitallyImportedClient(const QString& service_name,
|
||||||
|
|
|
@ -221,7 +221,7 @@ bool SpotifyBlobDownloader::CheckSignature(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (std::exception e) {
|
} catch (std::exception& e) {
|
||||||
// This should only happen if we fail to parse our own key.
|
// This should only happen if we fail to parse our own key.
|
||||||
qLog(Debug) << "Verifying spotify blob signature failed:" << e.what();
|
qLog(Debug) << "Verifying spotify blob signature failed:" << e.what();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -964,7 +964,7 @@ void LibraryBackend::UpdateManualAlbumArt(const QString& artist,
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
if (!albumartist.isNull()) {
|
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||||
query.AddWhere("albumartist", albumartist);
|
query.AddWhere("albumartist", albumartist);
|
||||||
} else if (!artist.isNull()) {
|
} else if (!artist.isNull()) {
|
||||||
query.AddWhere("artist", artist);
|
query.AddWhere("artist", artist);
|
||||||
|
@ -984,7 +984,7 @@ void LibraryBackend::UpdateManualAlbumArt(const QString& artist,
|
||||||
QString(
|
QString(
|
||||||
"UPDATE %1 SET art_manual = :art"
|
"UPDATE %1 SET art_manual = :art"
|
||||||
" WHERE album = :album AND unavailable = 0").arg(songs_table_));
|
" WHERE album = :album AND unavailable = 0").arg(songs_table_));
|
||||||
if (!albumartist.isNull()) {
|
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||||
sql += " AND albumartist = :albumartist";
|
sql += " AND albumartist = :albumartist";
|
||||||
} else if (!artist.isNull()) {
|
} else if (!artist.isNull()) {
|
||||||
sql += " AND artist = :artist";
|
sql += " AND artist = :artist";
|
||||||
|
@ -994,7 +994,7 @@ void LibraryBackend::UpdateManualAlbumArt(const QString& artist,
|
||||||
q.prepare(sql);
|
q.prepare(sql);
|
||||||
q.bindValue(":art", art);
|
q.bindValue(":art", art);
|
||||||
q.bindValue(":album", album);
|
q.bindValue(":album", album);
|
||||||
if (!albumartist.isNull()) {
|
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||||
q.bindValue(":albumartist", albumartist);
|
q.bindValue(":albumartist", albumartist);
|
||||||
} else if (!artist.isNull()) {
|
} else if (!artist.isNull()) {
|
||||||
q.bindValue(":artist", artist);
|
q.bindValue(":artist", artist);
|
||||||
|
|
|
@ -392,6 +392,9 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||||
add_to_playlist_enqueue_ = context_menu_->addAction(
|
add_to_playlist_enqueue_ = context_menu_->addAction(
|
||||||
IconLoader::Load("go-next", IconLoader::Base), tr("Queue track"), this,
|
IconLoader::Load("go-next", IconLoader::Base), tr("Queue track"), this,
|
||||||
SLOT(AddToPlaylistEnqueue()));
|
SLOT(AddToPlaylistEnqueue()));
|
||||||
|
add_to_playlist_enqueue_next_ = context_menu_->addAction(
|
||||||
|
IconLoader::Load("go-next", IconLoader::Base), tr("Play next"), this,
|
||||||
|
SLOT(AddToPlaylistEnqueueNext()));
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
search_for_this_ = context_menu_->addAction(
|
search_for_this_ = context_menu_->addAction(
|
||||||
IconLoader::Load("system-search", IconLoader::Base),
|
IconLoader::Load("system-search", IconLoader::Base),
|
||||||
|
@ -616,6 +619,14 @@ void LibraryView::AddToPlaylistEnqueue() {
|
||||||
emit AddToPlaylistSignal(data);
|
emit AddToPlaylistSignal(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryView::AddToPlaylistEnqueueNext() {
|
||||||
|
QMimeData* data = model()->mimeData(selectedIndexes());
|
||||||
|
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||||
|
mime_data->enqueue_next_now_ = true;
|
||||||
|
}
|
||||||
|
emit AddToPlaylistSignal(data);
|
||||||
|
}
|
||||||
|
|
||||||
void LibraryView::OpenInNewPlaylist() {
|
void LibraryView::OpenInNewPlaylist() {
|
||||||
QMimeData* data = model()->mimeData(selectedIndexes());
|
QMimeData* data = model()->mimeData(selectedIndexes());
|
||||||
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||||
|
|
|
@ -92,6 +92,7 @@ signals:
|
||||||
void Load();
|
void Load();
|
||||||
void AddToPlaylist();
|
void AddToPlaylist();
|
||||||
void AddToPlaylistEnqueue();
|
void AddToPlaylistEnqueue();
|
||||||
|
void AddToPlaylistEnqueueNext();
|
||||||
void OpenInNewPlaylist();
|
void OpenInNewPlaylist();
|
||||||
void Organise();
|
void Organise();
|
||||||
void CopyToDevice();
|
void CopyToDevice();
|
||||||
|
@ -131,6 +132,7 @@ signals:
|
||||||
QAction* load_;
|
QAction* load_;
|
||||||
QAction* add_to_playlist_;
|
QAction* add_to_playlist_;
|
||||||
QAction* add_to_playlist_enqueue_;
|
QAction* add_to_playlist_enqueue_;
|
||||||
|
QAction* add_to_playlist_enqueue_next_;
|
||||||
QAction* open_in_new_playlist_;
|
QAction* open_in_new_playlist_;
|
||||||
QAction* organise_;
|
QAction* organise_;
|
||||||
QAction* copy_to_device_;
|
QAction* copy_to_device_;
|
||||||
|
|
|
@ -151,14 +151,14 @@ Playlist::~Playlist() {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Playlist::InsertSongItems(const SongList& songs, int pos, bool play_now,
|
void Playlist::InsertSongItems(const SongList& songs, int pos, bool play_now,
|
||||||
bool enqueue) {
|
bool enqueue, bool enqueue_next) {
|
||||||
PlaylistItemList items;
|
PlaylistItemList items;
|
||||||
|
|
||||||
for (const Song& song : songs) {
|
for (const Song& song : songs) {
|
||||||
items << PlaylistItemPtr(new T(song));
|
items << PlaylistItemPtr(new T(song));
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertItems(items, pos, play_now, enqueue);
|
InsertItems(items, pos, play_now, enqueue, enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant Playlist::headerData(int section, Qt::Orientation, int role) const {
|
QVariant Playlist::headerData(int section, Qt::Orientation, int role) const {
|
||||||
|
@ -702,7 +702,7 @@ void Playlist::InsertDynamicItems(int count) {
|
||||||
connect(inserter, SIGNAL(PlayRequested(QModelIndex)),
|
connect(inserter, SIGNAL(PlayRequested(QModelIndex)),
|
||||||
SIGNAL(PlayRequested(QModelIndex)));
|
SIGNAL(PlayRequested(QModelIndex)));
|
||||||
|
|
||||||
inserter->Load(this, -1, false, false, dynamic_playlist_, count);
|
inserter->Load(this, -1, false, false, false, dynamic_playlist_, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags Playlist::flags(const QModelIndex& index) const {
|
Qt::ItemFlags Playlist::flags(const QModelIndex& index) const {
|
||||||
|
@ -732,12 +732,14 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
||||||
|
|
||||||
bool play_now = false;
|
bool play_now = false;
|
||||||
bool enqueue_now = false;
|
bool enqueue_now = false;
|
||||||
|
bool enqueue_next_now = false;
|
||||||
if (const MimeData* mime_data = qobject_cast<const MimeData*>(data)) {
|
if (const MimeData* mime_data = qobject_cast<const MimeData*>(data)) {
|
||||||
if (mime_data->clear_first_) {
|
if (mime_data->clear_first_) {
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
play_now = mime_data->play_now_;
|
play_now = mime_data->play_now_;
|
||||||
enqueue_now = mime_data->enqueue_now_;
|
enqueue_now = mime_data->enqueue_now_;
|
||||||
|
enqueue_next_now = mime_data->enqueue_next_now_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const SongMimeData* song_data = qobject_cast<const SongMimeData*>(data)) {
|
if (const SongMimeData* song_data = qobject_cast<const SongMimeData*>(data)) {
|
||||||
|
@ -747,33 +749,35 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
||||||
if (song_data->backend &&
|
if (song_data->backend &&
|
||||||
song_data->backend->songs_table() == Library::kSongsTable)
|
song_data->backend->songs_table() == Library::kSongsTable)
|
||||||
InsertSongItems<LibraryPlaylistItem>(song_data->songs, row, play_now,
|
InsertSongItems<LibraryPlaylistItem>(song_data->songs, row, play_now,
|
||||||
enqueue_now);
|
enqueue_now, enqueue_next_now);
|
||||||
else if (song_data->backend &&
|
else if (song_data->backend &&
|
||||||
song_data->backend->songs_table() == MagnatuneService::kSongsTable)
|
song_data->backend->songs_table() == MagnatuneService::kSongsTable)
|
||||||
InsertSongItems<MagnatunePlaylistItem>(song_data->songs, row, play_now,
|
InsertSongItems<MagnatunePlaylistItem>(song_data->songs, row, play_now,
|
||||||
enqueue_now);
|
enqueue_now, enqueue_next_now);
|
||||||
else if (song_data->backend &&
|
else if (song_data->backend &&
|
||||||
song_data->backend->songs_table() == JamendoService::kSongsTable)
|
song_data->backend->songs_table() == JamendoService::kSongsTable)
|
||||||
InsertSongItems<JamendoPlaylistItem>(song_data->songs, row, play_now,
|
InsertSongItems<JamendoPlaylistItem>(song_data->songs, row, play_now,
|
||||||
enqueue_now);
|
enqueue_now, enqueue_next_now);
|
||||||
else
|
else
|
||||||
InsertSongItems<SongPlaylistItem>(song_data->songs, row, play_now,
|
InsertSongItems<SongPlaylistItem>(song_data->songs, row, play_now,
|
||||||
enqueue_now);
|
enqueue_now, enqueue_next_now);
|
||||||
} else if (const InternetMimeData* internet_data =
|
} else if (const InternetMimeData* internet_data =
|
||||||
qobject_cast<const InternetMimeData*>(data)) {
|
qobject_cast<const InternetMimeData*>(data)) {
|
||||||
// Dragged from the Internet pane
|
// Dragged from the Internet pane
|
||||||
InsertInternetItems(internet_data->model, internet_data->indexes, row,
|
InsertInternetItems(internet_data->model, internet_data->indexes, row,
|
||||||
play_now, enqueue_now);
|
play_now, enqueue_now, enqueue_next_now);
|
||||||
} else if (const InternetSongMimeData* internet_song_data =
|
} else if (const InternetSongMimeData* internet_song_data =
|
||||||
qobject_cast<const InternetSongMimeData*>(data)) {
|
qobject_cast<const InternetSongMimeData*>(data)) {
|
||||||
InsertInternetItems(internet_song_data->service, internet_song_data->songs,
|
InsertInternetItems(internet_song_data->service, internet_song_data->songs,
|
||||||
row, play_now, enqueue_now);
|
row, play_now, enqueue_now, enqueue_next_now);
|
||||||
} else if (const GeneratorMimeData* generator_data =
|
} else if (const GeneratorMimeData* generator_data =
|
||||||
qobject_cast<const GeneratorMimeData*>(data)) {
|
qobject_cast<const GeneratorMimeData*>(data)) {
|
||||||
InsertSmartPlaylist(generator_data->generator_, row, play_now, enqueue_now);
|
InsertSmartPlaylist(generator_data->generator_, row, play_now, enqueue_now,
|
||||||
|
enqueue_next_now);
|
||||||
} else if (const PlaylistItemMimeData* item_data =
|
} else if (const PlaylistItemMimeData* item_data =
|
||||||
qobject_cast<const PlaylistItemMimeData*>(data)) {
|
qobject_cast<const PlaylistItemMimeData*>(data)) {
|
||||||
InsertItems(item_data->items_, row, play_now, enqueue_now);
|
InsertItems(item_data->items_, row, play_now, enqueue_now,
|
||||||
|
enqueue_next_now);
|
||||||
} else if (data->hasFormat(kRowsMimetype)) {
|
} else if (data->hasFormat(kRowsMimetype)) {
|
||||||
// Dragged from the playlist
|
// Dragged from the playlist
|
||||||
// Rearranging it is tricky...
|
// Rearranging it is tricky...
|
||||||
|
@ -808,7 +812,7 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
||||||
if (items.count() > kUndoItemLimit) {
|
if (items.count() > kUndoItemLimit) {
|
||||||
// Too big to keep in the undo stack. Also clear the stack because it
|
// Too big to keep in the undo stack. Also clear the stack because it
|
||||||
// might have been invalidated.
|
// might have been invalidated.
|
||||||
InsertItemsWithoutUndo(items, row, false);
|
InsertItemsWithoutUndo(items, row, false, false);
|
||||||
undo_stack_->clear();
|
undo_stack_->clear();
|
||||||
} else {
|
} else {
|
||||||
undo_stack_->push(
|
undo_stack_->push(
|
||||||
|
@ -827,26 +831,27 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action,
|
||||||
SongLoaderInserter* inserter = new SongLoaderInserter(
|
SongLoaderInserter* inserter = new SongLoaderInserter(
|
||||||
task_manager_, library_, backend_->app()->player());
|
task_manager_, library_, backend_->app()->player());
|
||||||
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||||
inserter->LoadAudioCD(this, row, play_now, enqueue_now);
|
inserter->LoadAudioCD(this, row, play_now, enqueue_now, enqueue_next_now);
|
||||||
} 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(), row, play_now, enqueue_now);
|
InsertUrls(data->urls(), row, play_now, enqueue_now, enqueue_next_now);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertUrls(const QList<QUrl>& urls, int pos, bool play_now,
|
void Playlist::InsertUrls(const QList<QUrl>& urls, int pos, bool play_now,
|
||||||
bool enqueue) {
|
bool enqueue, bool enqueue_next) {
|
||||||
SongLoaderInserter* inserter = new SongLoaderInserter(
|
SongLoaderInserter* inserter = new SongLoaderInserter(
|
||||||
task_manager_, library_, backend_->app()->player());
|
task_manager_, library_, backend_->app()->player());
|
||||||
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||||
|
|
||||||
inserter->Load(this, pos, play_now, enqueue, urls);
|
inserter->Load(this, pos, play_now, enqueue, enqueue_next, urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertSmartPlaylist(GeneratorPtr generator, int pos,
|
void Playlist::InsertSmartPlaylist(GeneratorPtr generator, int pos,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue,
|
||||||
|
bool enqueue_next) {
|
||||||
// Hack: If the generator hasn't got a library set then use the main one
|
// Hack: If the generator hasn't got a library set then use the main one
|
||||||
if (!generator->library()) {
|
if (!generator->library()) {
|
||||||
generator->set_library(library_);
|
generator->set_library(library_);
|
||||||
|
@ -856,7 +861,7 @@ void Playlist::InsertSmartPlaylist(GeneratorPtr generator, int pos,
|
||||||
new GeneratorInserter(task_manager_, library_, this);
|
new GeneratorInserter(task_manager_, library_, this);
|
||||||
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
connect(inserter, SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||||
|
|
||||||
inserter->Load(this, pos, play_now, enqueue, generator);
|
inserter->Load(this, pos, play_now, enqueue, enqueue_next, generator);
|
||||||
|
|
||||||
if (generator->is_dynamic()) {
|
if (generator->is_dynamic()) {
|
||||||
TurnOnDynamicPlaylist(generator);
|
TurnOnDynamicPlaylist(generator);
|
||||||
|
@ -975,7 +980,7 @@ void Playlist::MoveItemsWithoutUndo(int start, const QList<int>& dest_rows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertItems(const PlaylistItemList& itemsIn, int pos,
|
void Playlist::InsertItems(const PlaylistItemList& itemsIn, int pos,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue, bool enqueue_next) {
|
||||||
if (itemsIn.isEmpty()) return;
|
if (itemsIn.isEmpty()) return;
|
||||||
|
|
||||||
PlaylistItemList items = itemsIn;
|
PlaylistItemList items = itemsIn;
|
||||||
|
@ -1025,18 +1030,18 @@ void Playlist::InsertItems(const PlaylistItemList& itemsIn, int pos,
|
||||||
if (items.count() > kUndoItemLimit) {
|
if (items.count() > kUndoItemLimit) {
|
||||||
// Too big to keep in the undo stack. Also clear the stack because it
|
// Too big to keep in the undo stack. Also clear the stack because it
|
||||||
// might have been invalidated.
|
// might have been invalidated.
|
||||||
InsertItemsWithoutUndo(items, pos, enqueue);
|
InsertItemsWithoutUndo(items, pos, enqueue, enqueue_next);
|
||||||
undo_stack_->clear();
|
undo_stack_->clear();
|
||||||
} else {
|
} else {
|
||||||
undo_stack_->push(
|
undo_stack_->push(new PlaylistUndoCommands::InsertItems(
|
||||||
new PlaylistUndoCommands::InsertItems(this, items, pos, enqueue));
|
this, items, pos, enqueue, enqueue_next));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (play_now) emit PlayRequested(index(start, 0));
|
if (play_now) emit PlayRequested(index(start, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
void Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
||||||
bool enqueue) {
|
bool enqueue, bool enqueue_next) {
|
||||||
if (items.isEmpty()) return;
|
if (items.isEmpty()) return;
|
||||||
|
|
||||||
const int start = pos == -1 ? items_.count() : pos;
|
const int start = pos == -1 ? items_.count() : pos;
|
||||||
|
@ -1071,22 +1076,33 @@ void Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
||||||
queue_->ToggleTracks(indexes);
|
queue_->ToggleTracks(indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enqueue_next) {
|
||||||
|
QModelIndexList indexes;
|
||||||
|
for (int i = start; i <= end; ++i) {
|
||||||
|
indexes << index(i, 0);
|
||||||
|
}
|
||||||
|
queue_->InsertFirst(indexes);
|
||||||
|
}
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
ReshuffleIndices();
|
ReshuffleIndices();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertLibraryItems(const SongList& songs, int pos, bool play_now,
|
void Playlist::InsertLibraryItems(const SongList& songs, int pos, bool play_now,
|
||||||
bool enqueue) {
|
bool enqueue, bool enqueue_next) {
|
||||||
InsertSongItems<LibraryPlaylistItem>(songs, pos, play_now, enqueue);
|
InsertSongItems<LibraryPlaylistItem>(songs, pos, play_now, enqueue,
|
||||||
|
enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertSongs(const SongList& songs, int pos, bool play_now,
|
void Playlist::InsertSongs(const SongList& songs, int pos, bool play_now,
|
||||||
bool enqueue) {
|
bool enqueue, bool enqueue_next) {
|
||||||
InsertSongItems<SongPlaylistItem>(songs, pos, play_now, enqueue);
|
InsertSongItems<SongPlaylistItem>(songs, pos, play_now, enqueue,
|
||||||
|
enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertSongsOrLibraryItems(const SongList& songs, int pos,
|
void Playlist::InsertSongsOrLibraryItems(const SongList& songs, int pos,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue,
|
||||||
|
bool enqueue_next) {
|
||||||
PlaylistItemList items;
|
PlaylistItemList items;
|
||||||
for (const Song& song : songs) {
|
for (const Song& song : songs) {
|
||||||
if (song.is_library_song()) {
|
if (song.is_library_song()) {
|
||||||
|
@ -1095,12 +1111,13 @@ void Playlist::InsertSongsOrLibraryItems(const SongList& songs, int pos,
|
||||||
items << PlaylistItemPtr(new SongPlaylistItem(song));
|
items << PlaylistItemPtr(new SongPlaylistItem(song));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InsertItems(items, pos, play_now, enqueue);
|
InsertItems(items, pos, play_now, enqueue, enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertInternetItems(const InternetModel* model,
|
void Playlist::InsertInternetItems(const InternetModel* model,
|
||||||
const QModelIndexList& items, int pos,
|
const QModelIndexList& items, int pos,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue,
|
||||||
|
bool enqueue_next) {
|
||||||
PlaylistItemList playlist_items;
|
PlaylistItemList playlist_items;
|
||||||
QList<QUrl> song_urls;
|
QList<QUrl> song_urls;
|
||||||
|
|
||||||
|
@ -1119,23 +1136,24 @@ void Playlist::InsertInternetItems(const InternetModel* model,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!song_urls.isEmpty()) {
|
if (!song_urls.isEmpty()) {
|
||||||
InsertUrls(song_urls, pos, play_now, enqueue);
|
InsertUrls(song_urls, pos, play_now, enqueue, enqueue_next);
|
||||||
play_now = false;
|
play_now = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertItems(playlist_items, pos, play_now, enqueue);
|
InsertItems(playlist_items, pos, play_now, enqueue, enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertInternetItems(InternetService* service,
|
void Playlist::InsertInternetItems(InternetService* service,
|
||||||
const SongList& songs, int pos,
|
const SongList& songs, int pos,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue,
|
||||||
|
bool enqueue_next) {
|
||||||
PlaylistItemList playlist_items;
|
PlaylistItemList playlist_items;
|
||||||
for (const Song& song : songs) {
|
for (const Song& song : songs) {
|
||||||
playlist_items << shared_ptr<PlaylistItem>(
|
playlist_items << shared_ptr<PlaylistItem>(
|
||||||
new InternetPlaylistItem(service, song));
|
new InternetPlaylistItem(service, song));
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertItems(playlist_items, pos, play_now, enqueue);
|
InsertItems(playlist_items, pos, play_now, enqueue, enqueue_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::UpdateItems(const SongList& songs) {
|
void Playlist::UpdateItems(const SongList& songs) {
|
||||||
|
|
|
@ -235,18 +235,22 @@ class Playlist : public QAbstractListModel {
|
||||||
|
|
||||||
// Changing the playlist
|
// Changing the playlist
|
||||||
void InsertItems(const PlaylistItemList& items, int pos = -1,
|
void InsertItems(const PlaylistItemList& items, int pos = -1,
|
||||||
bool play_now = false, bool enqueue = false);
|
bool play_now = false, bool enqueue = false,
|
||||||
|
bool enqueue_next = false);
|
||||||
void InsertLibraryItems(const SongList& items, int pos = -1,
|
void InsertLibraryItems(const SongList& items, int pos = -1,
|
||||||
bool play_now = false, bool enqueue = false);
|
bool play_now = false, bool enqueue = false,
|
||||||
|
bool enqueue_next = false);
|
||||||
void InsertSongs(const SongList& items, int pos = -1, bool play_now = false,
|
void InsertSongs(const SongList& items, int pos = -1, bool play_now = false,
|
||||||
bool enqueue = false);
|
bool enqueue = false, bool enqueue_next = false);
|
||||||
void InsertSongsOrLibraryItems(const SongList& items, int pos = -1,
|
void InsertSongsOrLibraryItems(const SongList& items, int pos = -1,
|
||||||
bool play_now = false, bool enqueue = false);
|
bool play_now = false, bool enqueue = false,
|
||||||
|
bool enqueue_next = false);
|
||||||
void InsertSmartPlaylist(smart_playlists::GeneratorPtr gen, int pos = -1,
|
void InsertSmartPlaylist(smart_playlists::GeneratorPtr gen, int pos = -1,
|
||||||
bool play_now = false, bool enqueue = false);
|
bool play_now = false, bool enqueue = false,
|
||||||
|
bool enqueue_next = false);
|
||||||
void InsertInternetItems(InternetService* service, const SongList& songs,
|
void InsertInternetItems(InternetService* service, const SongList& songs,
|
||||||
int pos = -1, bool play_now = false,
|
int pos = -1, bool play_now = false,
|
||||||
bool enqueue = false);
|
bool enqueue = false, bool enqueue_next = false);
|
||||||
void ReshuffleIndices();
|
void ReshuffleIndices();
|
||||||
|
|
||||||
// If this playlist contains the current item, this method will apply the
|
// If this playlist contains the current item, this method will apply the
|
||||||
|
@ -335,7 +339,7 @@ class Playlist : public QAbstractListModel {
|
||||||
void SetColumnAlignment(const ColumnAlignmentMap& alignment);
|
void SetColumnAlignment(const ColumnAlignmentMap& alignment);
|
||||||
|
|
||||||
void InsertUrls(const QList<QUrl>& urls, int pos = -1, bool play_now = false,
|
void InsertUrls(const QList<QUrl>& urls, int pos = -1, bool play_now = false,
|
||||||
bool enqueue = false);
|
bool enqueue = false, bool enqueue_next = false);
|
||||||
// Removes items with given indices from the playlist. This operation is not
|
// Removes items with given indices from the playlist. This operation is not
|
||||||
// undoable.
|
// undoable.
|
||||||
void RemoveItemsWithoutUndo(const QList<int>& indices);
|
void RemoveItemsWithoutUndo(const QList<int>& indices);
|
||||||
|
@ -366,18 +370,18 @@ signals:
|
||||||
|
|
||||||
void InsertInternetItems(const InternetModel* model,
|
void InsertInternetItems(const InternetModel* model,
|
||||||
const QModelIndexList& items, int pos, bool play_now,
|
const QModelIndexList& items, int pos, bool play_now,
|
||||||
bool enqueue);
|
bool enqueue, bool enqueue_next = false);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void InsertSongItems(const SongList& songs, int pos, bool play_now,
|
void InsertSongItems(const SongList& songs, int pos, bool play_now,
|
||||||
bool enqueue);
|
bool enqueue, bool enqueue_next = false);
|
||||||
|
|
||||||
void InsertDynamicItems(int count);
|
void InsertDynamicItems(int count);
|
||||||
|
|
||||||
// Modify the playlist without changing the undo stack. These are used by
|
// Modify the playlist without changing the undo stack. These are used by
|
||||||
// our friends in PlaylistUndoCommands
|
// our friends in PlaylistUndoCommands
|
||||||
void InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
void InsertItemsWithoutUndo(const PlaylistItemList& items, int pos,
|
||||||
bool enqueue = false);
|
bool enqueue = false, bool enqueue_next = false);
|
||||||
PlaylistItemList RemoveItemsWithoutUndo(int pos, int count);
|
PlaylistItemList RemoveItemsWithoutUndo(int pos, int count);
|
||||||
void MoveItemsWithoutUndo(const QList<int>& source_rows, int pos);
|
void MoveItemsWithoutUndo(const QList<int>& source_rows, int pos);
|
||||||
void MoveItemWithoutUndo(int source, int dest);
|
void MoveItemWithoutUndo(int source, int dest);
|
||||||
|
|
|
@ -23,13 +23,17 @@ namespace PlaylistUndoCommands {
|
||||||
Base::Base(Playlist* playlist) : QUndoCommand(0), playlist_(playlist) {}
|
Base::Base(Playlist* playlist) : QUndoCommand(0), playlist_(playlist) {}
|
||||||
|
|
||||||
InsertItems::InsertItems(Playlist* playlist, const PlaylistItemList& items,
|
InsertItems::InsertItems(Playlist* playlist, const PlaylistItemList& items,
|
||||||
int pos, bool enqueue)
|
int pos, bool enqueue, bool enqueue_next)
|
||||||
: Base(playlist), items_(items), pos_(pos), enqueue_(enqueue) {
|
: Base(playlist),
|
||||||
|
items_(items),
|
||||||
|
pos_(pos),
|
||||||
|
enqueue_(enqueue),
|
||||||
|
enqueue_next_(enqueue_next) {
|
||||||
setText(tr("add %n songs", "", items_.count()));
|
setText(tr("add %n songs", "", items_.count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertItems::redo() {
|
void InsertItems::redo() {
|
||||||
playlist_->InsertItemsWithoutUndo(items_, pos_, enqueue_);
|
playlist_->InsertItemsWithoutUndo(items_, pos_, enqueue_, enqueue_next_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertItems::undo() {
|
void InsertItems::undo() {
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Base : public QUndoCommand {
|
||||||
class InsertItems : public Base {
|
class InsertItems : public Base {
|
||||||
public:
|
public:
|
||||||
InsertItems(Playlist* playlist, const PlaylistItemList& items, int pos,
|
InsertItems(Playlist* playlist, const PlaylistItemList& items, int pos,
|
||||||
bool enqueue = false);
|
bool enqueue = false, bool enqueue_next = false);
|
||||||
|
|
||||||
void undo();
|
void undo();
|
||||||
void redo();
|
void redo();
|
||||||
|
@ -56,6 +56,7 @@ class InsertItems : public Base {
|
||||||
PlaylistItemList items_;
|
PlaylistItemList items_;
|
||||||
int pos_;
|
int pos_;
|
||||||
bool enqueue_;
|
bool enqueue_;
|
||||||
|
bool enqueue_next_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveItems : public Base {
|
class RemoveItems : public Base {
|
||||||
|
|
|
@ -113,6 +113,7 @@ PlaylistView::PlaylistView(QWidget* parent)
|
||||||
upgrading_from_qheaderview_(false),
|
upgrading_from_qheaderview_(false),
|
||||||
read_only_settings_(true),
|
read_only_settings_(true),
|
||||||
upgrading_from_version_(-1),
|
upgrading_from_version_(-1),
|
||||||
|
background_initialized_(false),
|
||||||
background_image_type_(Default),
|
background_image_type_(Default),
|
||||||
blur_radius_(kDefaultBlurRadius),
|
blur_radius_(kDefaultBlurRadius),
|
||||||
opacity_level_(kDefaultOpacityLevel),
|
opacity_level_(kDefaultOpacityLevel),
|
||||||
|
@ -1128,10 +1129,12 @@ void PlaylistView::ReloadSettings() {
|
||||||
// set_background_image when it is not needed, as this will cause the fading
|
// set_background_image when it is not needed, as this will cause the fading
|
||||||
// animation to start again. This also avoid to do useless
|
// animation to start again. This also avoid to do useless
|
||||||
// "force_background_redraw".
|
// "force_background_redraw".
|
||||||
if (background_image_filename != background_image_filename_ ||
|
if (background_initialized_ == false ||
|
||||||
|
background_image_filename != background_image_filename_ ||
|
||||||
background_type != background_image_type_ ||
|
background_type != background_image_type_ ||
|
||||||
blur_radius_ != blur_radius || opacity_level_ != opacity_level) {
|
blur_radius_ != blur_radius || opacity_level_ != opacity_level) {
|
||||||
// Store background properties
|
// Store background properties
|
||||||
|
background_initialized_ = true;
|
||||||
background_image_type_ = background_type;
|
background_image_type_ = background_type;
|
||||||
background_image_filename_ = background_image_filename;
|
background_image_filename_ = background_image_filename;
|
||||||
blur_radius_ = blur_radius;
|
blur_radius_ = blur_radius;
|
||||||
|
|
|
@ -195,15 +195,17 @@ signals:
|
||||||
bool read_only_settings_;
|
bool read_only_settings_;
|
||||||
int upgrading_from_version_;
|
int upgrading_from_version_;
|
||||||
|
|
||||||
|
bool background_initialized_;
|
||||||
BackgroundImageType background_image_type_;
|
BackgroundImageType background_image_type_;
|
||||||
|
// Used if background image is a filemane
|
||||||
|
QString background_image_filename_;
|
||||||
// Stores the background image to be displayed. As we want this image to be
|
// Stores the background image to be displayed. As we want this image to be
|
||||||
// particular (in terms of format, opacity), you should probably use
|
// particular (in terms of format, opacity), you should probably use
|
||||||
// set_background_image_type instead of modifying background_image_ directly
|
// set_background_image_type instead of modifying background_image_ directly
|
||||||
QImage background_image_;
|
QImage background_image_;
|
||||||
int blur_radius_;
|
int blur_radius_;
|
||||||
int opacity_level_;
|
int opacity_level_;
|
||||||
// Used if background image is a filemane
|
|
||||||
QString background_image_filename_;
|
|
||||||
QImage current_song_cover_art_;
|
QImage current_song_cover_art_;
|
||||||
QPixmap cached_scaled_background_image_;
|
QPixmap cached_scaled_background_image_;
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,29 @@ void Queue::ToggleTracks(const QModelIndexList& source_indexes) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Queue::InsertFirst(const QModelIndexList& source_indexes) {
|
||||||
|
for (const QModelIndex& source_index : source_indexes) {
|
||||||
|
QModelIndex proxy_index = mapFromSource(source_index);
|
||||||
|
if (proxy_index.isValid()) {
|
||||||
|
// Already in the queue, so remove it to be reinserted later
|
||||||
|
const int row = proxy_index.row();
|
||||||
|
beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
source_indexes_.removeAt(row);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int rows = source_indexes.count();
|
||||||
|
// Enqueue the tracks at the beginning
|
||||||
|
beginInsertRows(QModelIndex(), 0, rows - 1);
|
||||||
|
int offset = 0;
|
||||||
|
for (const QModelIndex& source_index : source_indexes) {
|
||||||
|
source_indexes_.insert(offset, QPersistentModelIndex(source_index));
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
int Queue::PositionOf(const QModelIndex& source_index) const {
|
int Queue::PositionOf(const QModelIndex& source_index) const {
|
||||||
return mapFromSource(source_index).row();
|
return mapFromSource(source_index).row();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Queue : public QAbstractProxyModel {
|
||||||
// Modify the queue
|
// Modify the queue
|
||||||
int TakeNext();
|
int TakeNext();
|
||||||
void ToggleTracks(const QModelIndexList& source_indexes);
|
void ToggleTracks(const QModelIndexList& source_indexes);
|
||||||
|
void InsertFirst(const QModelIndexList& source_indexes);
|
||||||
void Clear();
|
void Clear();
|
||||||
void Move(const QList<int>& proxy_rows, int pos);
|
void Move(const QList<int>& proxy_rows, int pos);
|
||||||
void MoveUp(int row);
|
void MoveUp(int row);
|
||||||
|
|
|
@ -37,11 +37,13 @@ SongLoaderInserter::SongLoaderInserter(TaskManager* task_manager,
|
||||||
SongLoaderInserter::~SongLoaderInserter() { qDeleteAll(pending_); }
|
SongLoaderInserter::~SongLoaderInserter() { qDeleteAll(pending_); }
|
||||||
|
|
||||||
void SongLoaderInserter::Load(Playlist* destination, int row, bool play_now,
|
void SongLoaderInserter::Load(Playlist* destination, int row, bool play_now,
|
||||||
bool enqueue, const QList<QUrl>& urls) {
|
bool enqueue, bool enqueue_next,
|
||||||
|
const QList<QUrl>& urls) {
|
||||||
destination_ = destination;
|
destination_ = destination;
|
||||||
row_ = row;
|
row_ = row;
|
||||||
play_now_ = play_now;
|
play_now_ = play_now;
|
||||||
enqueue_ = enqueue;
|
enqueue_ = enqueue;
|
||||||
|
enqueue_next_ = enqueue_next;
|
||||||
|
|
||||||
connect(destination, SIGNAL(destroyed()), SLOT(DestinationDestroyed()));
|
connect(destination, SIGNAL(destroyed()), SLOT(DestinationDestroyed()));
|
||||||
connect(this, SIGNAL(PreloadFinished()), SLOT(InsertSongs()));
|
connect(this, SIGNAL(PreloadFinished()), SLOT(InsertSongs()));
|
||||||
|
@ -78,11 +80,13 @@ void SongLoaderInserter::Load(Playlist* destination, int row, bool play_now,
|
||||||
// In the meantime, MusicBrainz will be queried to get songs' metadata.
|
// In the meantime, MusicBrainz will be queried to get songs' metadata.
|
||||||
// AudioCDTagsLoaded will be called next, and playlist's items will be updated.
|
// AudioCDTagsLoaded will be called next, and playlist's items will be updated.
|
||||||
void SongLoaderInserter::LoadAudioCD(Playlist* destination, int row,
|
void SongLoaderInserter::LoadAudioCD(Playlist* destination, int row,
|
||||||
bool play_now, bool enqueue) {
|
bool play_now, bool enqueue,
|
||||||
|
bool enqueue_next) {
|
||||||
destination_ = destination;
|
destination_ = destination;
|
||||||
row_ = row;
|
row_ = row;
|
||||||
play_now_ = play_now;
|
play_now_ = play_now;
|
||||||
enqueue_ = enqueue;
|
enqueue_ = enqueue;
|
||||||
|
enqueue_next_ = enqueue_next;
|
||||||
|
|
||||||
SongLoader* loader = new SongLoader(library_, player_, this);
|
SongLoader* loader = new SongLoader(library_, player_, this);
|
||||||
NewClosure(loader, SIGNAL(AudioCDTracksLoaded()),
|
NewClosure(loader, SIGNAL(AudioCDTracksLoaded()),
|
||||||
|
@ -119,7 +123,8 @@ void SongLoaderInserter::InsertSongs() {
|
||||||
// Insert songs (that haven't been completely loaded) to allow user to see
|
// Insert songs (that haven't been completely loaded) to allow user to see
|
||||||
// and play them while not loaded completely
|
// and play them while not loaded completely
|
||||||
if (destination_) {
|
if (destination_) {
|
||||||
destination_->InsertSongsOrLibraryItems(songs_, row_, play_now_, enqueue_);
|
destination_->InsertSongsOrLibraryItems(songs_, row_, play_now_, enqueue_,
|
||||||
|
enqueue_next_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,11 @@ class SongLoaderInserter : public QObject {
|
||||||
~SongLoaderInserter();
|
~SongLoaderInserter();
|
||||||
|
|
||||||
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
||||||
const QList<QUrl>& urls);
|
bool enqueue_next, const QList<QUrl>& urls);
|
||||||
void LoadAudioCD(Playlist* destination, int row, bool play_now, bool enqueue);
|
void LoadAudioCD(Playlist* destination, int row, bool play_now, bool enqueue,
|
||||||
|
bool enqueue_now);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Error(const QString& message);
|
void Error(const QString& message);
|
||||||
void PreloadFinished();
|
void PreloadFinished();
|
||||||
void EffectiveLoadFinished(const SongList& songs);
|
void EffectiveLoadFinished(const SongList& songs);
|
||||||
|
@ -64,6 +65,7 @@ signals:
|
||||||
int row_;
|
int row_;
|
||||||
bool play_now_;
|
bool play_now_;
|
||||||
bool enqueue_;
|
bool enqueue_;
|
||||||
|
bool enqueue_next_;
|
||||||
|
|
||||||
SongList songs_;
|
SongList songs_;
|
||||||
|
|
||||||
|
|
|
@ -43,14 +43,15 @@ static PlaylistItemList Generate(GeneratorPtr generator, int dynamic_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneratorInserter::Load(Playlist* destination, int row, bool play_now,
|
void GeneratorInserter::Load(Playlist* destination, int row, bool play_now,
|
||||||
bool enqueue, GeneratorPtr generator,
|
bool enqueue, bool enqueue_next,
|
||||||
int dynamic_count) {
|
GeneratorPtr generator, int dynamic_count) {
|
||||||
task_id_ = task_manager_->StartTask(tr("Loading smart playlist"));
|
task_id_ = task_manager_->StartTask(tr("Loading smart playlist"));
|
||||||
|
|
||||||
destination_ = destination;
|
destination_ = destination;
|
||||||
row_ = row;
|
row_ = row;
|
||||||
play_now_ = play_now;
|
play_now_ = play_now;
|
||||||
enqueue_ = enqueue;
|
enqueue_ = enqueue;
|
||||||
|
enqueue_next_ = enqueue_next;
|
||||||
is_dynamic_ = generator->is_dynamic();
|
is_dynamic_ = generator->is_dynamic();
|
||||||
|
|
||||||
connect(generator.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
connect(generator.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||||
|
|
|
@ -41,9 +41,9 @@ class GeneratorInserter : public QObject {
|
||||||
QObject* parent);
|
QObject* parent);
|
||||||
|
|
||||||
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
||||||
GeneratorPtr generator, int dynamic_count = 0);
|
bool enqueue_next, GeneratorPtr generator, int dynamic_count = 0);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Error(const QString& message);
|
void Error(const QString& message);
|
||||||
void PlayRequested(const QModelIndex& index);
|
void PlayRequested(const QModelIndex& index);
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ signals:
|
||||||
int row_;
|
int row_;
|
||||||
bool play_now_;
|
bool play_now_;
|
||||||
bool enqueue_;
|
bool enqueue_;
|
||||||
|
bool enqueue_next_;
|
||||||
bool is_dynamic_;
|
bool is_dynamic_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -752,7 +752,7 @@ void AlbumCoverManager::LoadSelectedToPlaylist() {
|
||||||
void AlbumCoverManager::SaveAndSetCover(QListWidgetItem* item,
|
void AlbumCoverManager::SaveAndSetCover(QListWidgetItem* item,
|
||||||
const QImage& image) {
|
const QImage& image) {
|
||||||
const QString artist = item->data(Role_ArtistName).toString();
|
const QString artist = item->data(Role_ArtistName).toString();
|
||||||
const QString albumartist = item->data(Role_ArtistName).toString();
|
const QString albumartist = item->data(Role_AlbumArtistName).toString();
|
||||||
const QString album = item->data(Role_AlbumName).toString();
|
const QString album = item->data(Role_AlbumName).toString();
|
||||||
|
|
||||||
QString path =
|
QString path =
|
||||||
|
|
|
@ -677,6 +677,10 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||||
playlist_queue_ = playlist_menu_->addAction("", this, SLOT(PlaylistQueue()));
|
playlist_queue_ = playlist_menu_->addAction("", this, SLOT(PlaylistQueue()));
|
||||||
playlist_queue_->setShortcut(QKeySequence("Ctrl+D"));
|
playlist_queue_->setShortcut(QKeySequence("Ctrl+D"));
|
||||||
ui_->playlist->addAction(playlist_queue_);
|
ui_->playlist->addAction(playlist_queue_);
|
||||||
|
playlist_queue_play_next_ =
|
||||||
|
playlist_menu_->addAction("", this, SLOT(PlaylistQueuePlayNext()));
|
||||||
|
playlist_queue_play_next_->setShortcut(QKeySequence("Ctrl+Shift+D"));
|
||||||
|
ui_->playlist->addAction(playlist_queue_play_next_);
|
||||||
playlist_skip_ = playlist_menu_->addAction("", this, SLOT(PlaylistSkip()));
|
playlist_skip_ = playlist_menu_->addAction("", this, SLOT(PlaylistSkip()));
|
||||||
ui_->playlist->addAction(playlist_skip_);
|
ui_->playlist->addAction(playlist_skip_);
|
||||||
playlist_menu_->addSeparator();
|
playlist_menu_->addSeparator();
|
||||||
|
@ -1411,7 +1415,7 @@ void MainWindow::closeEvent(QCloseEvent* event) {
|
||||||
event->accept();
|
event->accept();
|
||||||
SetHiddenInTray(true);
|
SetHiddenInTray(true);
|
||||||
} else {
|
} else {
|
||||||
QApplication::quit();
|
Exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1759,6 +1763,11 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos,
|
||||||
else
|
else
|
||||||
playlist_queue_->setText(tr("Toggle queue status"));
|
playlist_queue_->setText(tr("Toggle queue status"));
|
||||||
|
|
||||||
|
if (all > 1)
|
||||||
|
playlist_queue_play_next_->setText(tr("Play selected tracks next"));
|
||||||
|
else
|
||||||
|
playlist_queue_play_next_->setText(tr("Play next"));
|
||||||
|
|
||||||
if (in_skipped == 1 && not_in_skipped == 0)
|
if (in_skipped == 1 && not_in_skipped == 0)
|
||||||
playlist_skip_->setText(tr("Unskip track"));
|
playlist_skip_->setText(tr("Unskip track"));
|
||||||
else if (in_skipped > 1 && not_in_skipped == 0)
|
else if (in_skipped > 1 && not_in_skipped == 0)
|
||||||
|
@ -1773,6 +1782,9 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos,
|
||||||
else
|
else
|
||||||
playlist_queue_->setIcon(IconLoader::Load("go-next", IconLoader::Base));
|
playlist_queue_->setIcon(IconLoader::Load("go-next", IconLoader::Base));
|
||||||
|
|
||||||
|
playlist_queue_play_next_->setIcon(
|
||||||
|
IconLoader::Load("go-next", IconLoader::Base));
|
||||||
|
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
ui_->action_selection_set_value->setVisible(false);
|
ui_->action_selection_set_value->setVisible(false);
|
||||||
ui_->action_edit_value->setVisible(false);
|
ui_->action_edit_value->setVisible(false);
|
||||||
|
@ -2493,6 +2505,17 @@ void MainWindow::PlaylistQueue() {
|
||||||
app_->playlist_manager()->current()->queue()->ToggleTracks(indexes);
|
app_->playlist_manager()->current()->queue()->ToggleTracks(indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::PlaylistQueuePlayNext() {
|
||||||
|
QModelIndexList indexes;
|
||||||
|
for (const QModelIndex& proxy_index :
|
||||||
|
ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||||
|
indexes << app_->playlist_manager()->current()->proxy()->mapToSource(
|
||||||
|
proxy_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
app_->playlist_manager()->current()->queue()->InsertFirst(indexes);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistSkip() {
|
void MainWindow::PlaylistSkip() {
|
||||||
QModelIndexList indexes;
|
QModelIndexList indexes;
|
||||||
for (const QModelIndex& proxy_index :
|
for (const QModelIndex& proxy_index :
|
||||||
|
|
|
@ -162,6 +162,7 @@ signals:
|
||||||
void PlaylistPlay();
|
void PlaylistPlay();
|
||||||
void PlaylistStopAfter();
|
void PlaylistStopAfter();
|
||||||
void PlaylistQueue();
|
void PlaylistQueue();
|
||||||
|
void PlaylistQueuePlayNext();
|
||||||
void PlaylistSkip();
|
void PlaylistSkip();
|
||||||
void PlaylistRemoveCurrent();
|
void PlaylistRemoveCurrent();
|
||||||
void PlaylistEditFinished(const QModelIndex& index);
|
void PlaylistEditFinished(const QModelIndex& index);
|
||||||
|
@ -361,6 +362,7 @@ signals:
|
||||||
QAction* playlist_delete_;
|
QAction* playlist_delete_;
|
||||||
QAction* playlist_open_in_browser_;
|
QAction* playlist_open_in_browser_;
|
||||||
QAction* playlist_queue_;
|
QAction* playlist_queue_;
|
||||||
|
QAction* playlist_queue_play_next_;
|
||||||
QAction* playlist_skip_;
|
QAction* playlist_skip_;
|
||||||
QAction* playlist_add_to_another_;
|
QAction* playlist_add_to_another_;
|
||||||
QList<QAction*> playlistitem_actions_;
|
QList<QAction*> playlistitem_actions_;
|
||||||
|
|
|
@ -105,7 +105,11 @@ void TrackSliderSlider::enterEvent(QEvent* e) {
|
||||||
|
|
||||||
void TrackSliderSlider::leaveEvent(QEvent* e) {
|
void TrackSliderSlider::leaveEvent(QEvent* e) {
|
||||||
QSlider::leaveEvent(e);
|
QSlider::leaveEvent(e);
|
||||||
popup_->hide();
|
// On some (but not all) systems, displaying the TrackSliderPopup
|
||||||
|
// generates a leaveEvent. Ensure that this leaveEvent is genuine.
|
||||||
|
if (!geometry().contains(mapFromGlobal(QCursor::pos()))) {
|
||||||
|
popup_->hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackSliderSlider::keyPressEvent(QKeyEvent* event) {
|
void TrackSliderSlider::keyPressEvent(QKeyEvent* event) {
|
||||||
|
|
Loading…
Reference in New Issue