Ipod Playlist Support (#220)
* Ipod Playlist Support Copy a whole playlist to the ipod and create an entry in Playlists on the iPod * Fix formatting and indentation Fix indenting and formatting to be consistent
This commit is contained in:
parent
4a934c9dab
commit
a32010e03b
|
@ -65,6 +65,7 @@ class MusicStorage {
|
|||
QString cover_source_;
|
||||
QString cover_dest_;
|
||||
ProgressFunction progress_;
|
||||
QString playlist_;
|
||||
};
|
||||
|
||||
struct DeleteJob {
|
||||
|
|
|
@ -188,6 +188,19 @@ bool GPodDevice::CopyToStorage(const CopyJob &job) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Put the track in the playlist, if one is specified
|
||||
if (!job.playlist_.isEmpty()) {
|
||||
// Does the playlist already exist?
|
||||
auto itdbPlaylist = itdb_playlist_by_name(db_, job.playlist_.toUtf8().data());
|
||||
if (itdbPlaylist == nullptr) {
|
||||
// Create the playlist
|
||||
itdbPlaylist = itdb_playlist_new(job.playlist_.toUtf8().data(), false);
|
||||
itdb_playlist_add(db_, itdbPlaylist, -1);
|
||||
}
|
||||
// Playlist should exist so add the track to the playlist
|
||||
itdb_playlist_add_track(itdbPlaylist, track, -1);
|
||||
}
|
||||
|
||||
AddTrackToModel(track, url_.path());
|
||||
|
||||
// Remove the original if it was requested
|
||||
|
|
|
@ -52,7 +52,7 @@ const int Organise::kBatchSize = 10;
|
|||
const int Organise::kTranscodeProgressInterval = 500;
|
||||
#endif
|
||||
|
||||
Organise::Organise(TaskManager *task_manager, std::shared_ptr<MusicStorage> destination, const OrganiseFormat &format, bool copy, bool overwrite, bool mark_as_listened, bool albumcover, const NewSongInfoList &songs_info, bool eject_after)
|
||||
Organise::Organise(TaskManager *task_manager, std::shared_ptr<MusicStorage> destination, const OrganiseFormat &format, bool copy, bool overwrite, bool mark_as_listened, bool albumcover, const NewSongInfoList &songs_info, bool eject_after, const QString &playlist)
|
||||
: thread_(nullptr),
|
||||
task_manager_(task_manager),
|
||||
#ifdef HAVE_GSTREAMER
|
||||
|
@ -66,10 +66,11 @@ Organise::Organise(TaskManager *task_manager, std::shared_ptr<MusicStorage> dest
|
|||
albumcover_(albumcover),
|
||||
eject_after_(eject_after),
|
||||
task_count_(songs_info.count()),
|
||||
playlist_(playlist),
|
||||
tasks_complete_(0),
|
||||
started_(false),
|
||||
task_id_(0),
|
||||
current_copy_progress_(0) {
|
||||
current_copy_progress_(0){
|
||||
|
||||
original_thread_ = thread();
|
||||
|
||||
|
@ -208,6 +209,7 @@ void Organise::ProcessSomeFiles() {
|
|||
job.mark_as_listened_ = mark_as_listened_;
|
||||
job.albumcover_ = albumcover_;
|
||||
job.remove_original_ = !copy_;
|
||||
job.playlist_ = playlist_;
|
||||
|
||||
if (task.song_info_.song_.art_manual_is_valid() && task.song_info_.song_.art_manual().path() != Song::kManuallyUnsetCover) {
|
||||
if (task.song_info_.song_.art_manual().isLocalFile() && QFile::exists(task.song_info_.song_.art_manual().toLocalFile())) {
|
||||
|
|
|
@ -61,7 +61,7 @@ class Organise : public QObject {
|
|||
};
|
||||
typedef QList<NewSongInfo> NewSongInfoList;
|
||||
|
||||
Organise(TaskManager *task_manager, std::shared_ptr<MusicStorage> destination, const OrganiseFormat &format, bool copy, bool overwrite, bool mark_as_listened, bool albumcover, const NewSongInfoList &songs, bool eject_after);
|
||||
Organise(TaskManager *task_manager, std::shared_ptr<MusicStorage> destination, const OrganiseFormat &format, bool copy, bool overwrite, bool mark_as_listened, bool albumcover, const NewSongInfoList &songs, bool eject_after, const QString &playlist = QString());
|
||||
~Organise();
|
||||
|
||||
static const int kBatchSize;
|
||||
|
@ -123,6 +123,7 @@ class Organise : public QObject {
|
|||
const bool albumcover_;
|
||||
const bool eject_after_;
|
||||
int task_count_;
|
||||
const QString playlist_;
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
QBasicTimer transcode_progress_timer_;
|
||||
|
|
|
@ -244,7 +244,12 @@ SongList OrganiseDialog::LoadSongsBlocking(const QStringList &filenames) {
|
|||
}
|
||||
|
||||
void OrganiseDialog::SetCopy(bool copy) {
|
||||
ui_->aftercopying->setCurrentIndex(copy ? 0 : 1);
|
||||
ui_->aftercopying->setCurrentIndex(copy ? 0 : 1);
|
||||
}
|
||||
|
||||
void OrganiseDialog::SetPlaylist(const QString &playlist)
|
||||
{
|
||||
playlist_ = playlist;
|
||||
}
|
||||
|
||||
void OrganiseDialog::InsertTag(const QString &tag) {
|
||||
|
@ -399,7 +404,7 @@ void OrganiseDialog::accept() {
|
|||
|
||||
// It deletes itself when it's finished.
|
||||
const bool copy = ui_->aftercopying->currentIndex() == 0;
|
||||
Organise *organise = new Organise(task_manager_, storage, format_, copy, ui_->overwrite->isChecked(), ui_->mark_as_listened->isChecked(), ui_->albumcover->isChecked(), new_songs_info_, ui_->eject_after->isChecked());
|
||||
Organise *organise = new Organise(task_manager_, storage, format_, copy, ui_->overwrite->isChecked(), ui_->mark_as_listened->isChecked(), ui_->albumcover->isChecked(), new_songs_info_, ui_->eject_after->isChecked(), playlist_);
|
||||
connect(organise, SIGNAL(Finished(QStringList, QStringList)), SLOT(OrganiseFinished(QStringList, QStringList)));
|
||||
connect(organise, SIGNAL(FileCopied(int)), this, SIGNAL(FileCopied(int)));
|
||||
if (backend_)
|
||||
|
|
|
@ -74,6 +74,8 @@ class OrganiseDialog : public QDialog {
|
|||
void SetCopy(bool copy);
|
||||
|
||||
static Organise::NewSongInfoList ComputeNewSongsFilenames(const SongList &songs, const OrganiseFormat &format);
|
||||
|
||||
void SetPlaylist(const QString &playlist);
|
||||
|
||||
signals:
|
||||
void FileCopied(int);
|
||||
|
@ -114,6 +116,7 @@ class OrganiseDialog : public QDialog {
|
|||
SongList songs_;
|
||||
Organise::NewSongInfoList new_songs_info_;
|
||||
quint64 total_size_;
|
||||
QString playlist_;
|
||||
|
||||
std::unique_ptr<OrganiseErrorDialog> error_dialog_;
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
#include "playlistlistmodel.h"
|
||||
#include "playlistmanager.h"
|
||||
#include "ui_playlistlistcontainer.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#ifndef Q_OS_WIN
|
||||
# include "device/devicemanager.h"
|
||||
# include "device/devicestatefiltermodel.h"
|
||||
#endif
|
||||
|
||||
class PlaylistListSortFilterModel : public QSortFilterProxyModel {
|
||||
public:
|
||||
|
@ -80,6 +85,7 @@ PlaylistListContainer::PlaylistListContainer(QWidget *parent)
|
|||
action_new_folder_(new QAction(this)),
|
||||
action_remove_(new QAction(this)),
|
||||
action_save_playlist_(new QAction(this)),
|
||||
action_copy_to_device_(new QAction(this)),
|
||||
model_(new PlaylistListModel(this)),
|
||||
proxy_(new PlaylistListSortFilterModel(this)),
|
||||
loaded_icons_(false),
|
||||
|
@ -92,6 +98,7 @@ PlaylistListContainer::PlaylistListContainer(QWidget *parent)
|
|||
action_new_folder_->setText(tr("New folder"));
|
||||
action_remove_->setText(tr("Delete"));
|
||||
action_save_playlist_->setText(tr("Save playlist", "Save playlist menu action."));
|
||||
action_copy_to_device_->setText(tr("Copy to device..."));
|
||||
|
||||
ui_->new_folder->setDefaultAction(action_new_folder_);
|
||||
ui_->remove->setDefaultAction(action_remove_);
|
||||
|
@ -100,6 +107,7 @@ PlaylistListContainer::PlaylistListContainer(QWidget *parent)
|
|||
connect(action_new_folder_, SIGNAL(triggered()), SLOT(NewFolderClicked()));
|
||||
connect(action_remove_, SIGNAL(triggered()), SLOT(DeleteClicked()));
|
||||
connect(action_save_playlist_, SIGNAL(triggered()), SLOT(SavePlaylist()));
|
||||
connect(action_copy_to_device_, SIGNAL(triggered()), SLOT(CopyToDevice()));
|
||||
connect(model_, SIGNAL(PlaylistPathChanged(int, QString)), SLOT(PlaylistPathChanged(int, QString)));
|
||||
|
||||
proxy_->setSourceModel(model_);
|
||||
|
@ -127,6 +135,7 @@ void PlaylistListContainer::showEvent(QShowEvent *e) {
|
|||
action_new_folder_->setIcon(IconLoader::Load("folder-new"));
|
||||
action_remove_->setIcon(IconLoader::Load("edit-delete"));
|
||||
action_save_playlist_->setIcon(IconLoader::Load("document-save"));
|
||||
action_copy_to_device_->setIcon(IconLoader::Load("device"));
|
||||
|
||||
model_->SetIcons(IconLoader::Load("view-media-playlist"), IconLoader::Load("folder"));
|
||||
|
||||
|
@ -317,6 +326,33 @@ void PlaylistListContainer::ItemDoubleClicked(const QModelIndex &proxy_index) {
|
|||
|
||||
}
|
||||
|
||||
void PlaylistListContainer::CopyToDevice()
|
||||
{
|
||||
#ifndef Q_OS_WIN
|
||||
// Reuse the organise dialog, but set the detail about the playlist name
|
||||
if (!organise_dialog_) {
|
||||
organise_dialog_.reset(new OrganiseDialog {app_->task_manager()});
|
||||
}
|
||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||
organise_dialog_->SetCopy(true);
|
||||
|
||||
const QModelIndex ¤t_index = proxy_->mapToSource(ui_->tree->currentIndex());
|
||||
|
||||
// Is it a playlist?
|
||||
if (current_index.data(PlaylistListModel::Role_Type).toInt() == PlaylistListModel::Type_Playlist) {
|
||||
const int playlist_id = current_index.data(PlaylistListModel::Role_PlaylistId).toInt();
|
||||
|
||||
QStandardItem *item = model_->PlaylistById(playlist_id);
|
||||
QString playlist_name = item ? item->text() : tr("Playlist");
|
||||
organise_dialog_->SetPlaylist(playlist_name);
|
||||
|
||||
// Get the songs in the playlist
|
||||
organise_dialog_->SetSongs(app_->playlist_manager()->playlist(playlist_id)->GetAllSongs());
|
||||
organise_dialog_->show();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PlaylistListContainer::DeleteClicked() {
|
||||
|
||||
QSet<int> ids;
|
||||
|
@ -386,6 +422,8 @@ void PlaylistListContainer::contextMenuEvent(QContextMenuEvent *e) {
|
|||
menu_->addAction(action_remove_);
|
||||
menu_->addSeparator();
|
||||
menu_->addAction(action_save_playlist_);
|
||||
menu_->addSeparator();
|
||||
menu_->addAction(action_copy_to_device_);
|
||||
}
|
||||
menu_->popup(e->globalPos());
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <QStandardItem>
|
||||
#include <QtEvents>
|
||||
|
||||
#include <organise/organisedialog.h>
|
||||
|
||||
class QModelIndex;
|
||||
class Application;
|
||||
class Playlist;
|
||||
|
@ -59,6 +61,7 @@ private slots:
|
|||
void NewFolderClicked();
|
||||
void DeleteClicked();
|
||||
void ItemDoubleClicked(const QModelIndex &index);
|
||||
void CopyToDevice();
|
||||
|
||||
// From the model
|
||||
void PlaylistPathChanged(int id, const QString &new_path);
|
||||
|
@ -94,6 +97,7 @@ private:
|
|||
QAction *action_new_folder_;
|
||||
QAction *action_remove_;
|
||||
QAction *action_save_playlist_;
|
||||
QAction *action_copy_to_device_;
|
||||
|
||||
PlaylistListModel *model_;
|
||||
QSortFilterProxyModel *proxy_;
|
||||
|
@ -102,6 +106,8 @@ private:
|
|||
QIcon padded_play_icon_;
|
||||
|
||||
int active_playlist_id_;
|
||||
|
||||
std::unique_ptr<OrganiseDialog> organise_dialog_;
|
||||
};
|
||||
|
||||
#endif // PLAYLISTLISTCONTAINER_H
|
||||
|
|
Loading…
Reference in New Issue