mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2024-05-11 08:32:43 +00:00
193 lines
7.4 KiB
C++
193 lines
7.4 KiB
C++
/*
|
|
* Sailfin: a Jellyfin client written using Qt
|
|
* Copyright (C) 2021 Chris Josten and the Sailfin Contributors.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#include "JellyfinQt/viewmodel/playlist.h"
|
|
|
|
#include "JellyfinQt/viewmodel/item.h"
|
|
#include "JellyfinQt/viewmodel/utils.h"
|
|
|
|
namespace Jellyfin {
|
|
namespace ViewModel {
|
|
|
|
Playlist::Playlist(Model::Playlist *data, QObject *parent)
|
|
: QAbstractListModel(parent),
|
|
m_data(nullptr) {
|
|
setPlaylistModel(data);
|
|
}
|
|
|
|
int Playlist::rowCount(const QModelIndex &parent) const {
|
|
if (!parent.isValid()) return m_data->totalSize();
|
|
return 0;
|
|
}
|
|
QHash<int, QByteArray> Playlist::roleNames() const {
|
|
return {
|
|
{RoleNames::name, "name"},
|
|
{RoleNames::artists, "artists"},
|
|
{RoleNames::artistItems, "artistItems"},
|
|
{RoleNames::runTimeTicks, "runTimeTicks"},
|
|
{RoleNames::section, "section"},
|
|
{RoleNames::playing, "playing"},
|
|
};
|
|
}
|
|
|
|
void Playlist::setPlaylistModel(Model::Playlist *data) {
|
|
if (m_data != nullptr) {
|
|
disconnect(data, &Model::Playlist::beforeListCleared, this, &Playlist::onBeforePlaylistCleared);
|
|
disconnect(data, &Model::Playlist::listCleared, this, &Playlist::onPlaylistCleared);
|
|
disconnect(data, &Model::Playlist::beforeItemsAddedToList, this, &Playlist::onBeforeItemsAddedToList);
|
|
disconnect(data, &Model::Playlist::beforeItemsAddedToQueue, this, &Playlist::onBeforeItemsAddedToQueue);
|
|
disconnect(data, &Model::Playlist::itemsAddedToList, this, &Playlist::onItemsAddedToList);
|
|
disconnect(data, &Model::Playlist::itemsAddedToQueue, this, &Playlist::onItemsAddedToQueue);
|
|
disconnect(data, &Model::Playlist::beforeItemsRemovedFromList, this, &Playlist::onBeforeItemsRemovedFromList);
|
|
disconnect(data, &Model::Playlist::beforeItemsRemovedFromQueue, this, &Playlist::onBeforeItemsRemovedFromQueue);
|
|
disconnect(data, &Model::Playlist::itemsRemovedFromList, this, &Playlist::onItemsRemovedFromList);
|
|
disconnect(data, &Model::Playlist::itemsRemovedFromQueue, this, &Playlist::onItemsRemovedFromQueue);
|
|
disconnect(data, &Model::Playlist::listReshuffled, this, &Playlist::onReshuffled);
|
|
disconnect(data, &Model::Playlist::currentItemChanged, this, &Playlist::onPlayingItemChanged);
|
|
}
|
|
beginResetModel();
|
|
m_data = data;
|
|
endResetModel();
|
|
|
|
if (m_data != nullptr) {
|
|
connect(data, &Model::Playlist::beforeListCleared, this, &Playlist::onBeforePlaylistCleared);
|
|
connect(data, &Model::Playlist::listCleared, this, &Playlist::onPlaylistCleared);
|
|
connect(data, &Model::Playlist::beforeItemsAddedToList, this, &Playlist::onBeforeItemsAddedToList);
|
|
connect(data, &Model::Playlist::beforeItemsAddedToQueue, this, &Playlist::onBeforeItemsAddedToQueue);
|
|
connect(data, &Model::Playlist::itemsAddedToList, this, &Playlist::onItemsAddedToList);
|
|
connect(data, &Model::Playlist::itemsAddedToQueue, this, &Playlist::onItemsAddedToQueue);
|
|
connect(data, &Model::Playlist::beforeItemsRemovedFromList, this, &Playlist::onBeforeItemsRemovedFromList);
|
|
connect(data, &Model::Playlist::beforeItemsRemovedFromQueue, this, &Playlist::onBeforeItemsRemovedFromQueue);
|
|
connect(data, &Model::Playlist::itemsRemovedFromList, this, &Playlist::onItemsRemovedFromList);
|
|
connect(data, &Model::Playlist::itemsRemovedFromQueue, this, &Playlist::onItemsRemovedFromQueue);
|
|
connect(data, &Model::Playlist::listReshuffled, this, &Playlist::onReshuffled);
|
|
connect(data, &Model::Playlist::currentItemChanged, this, &Playlist::onPlayingItemChanged);
|
|
}
|
|
};
|
|
|
|
QVariant Playlist::data(const QModelIndex &index, int role) const {
|
|
if (!index.isValid()) return QVariant();
|
|
if (index.row() >= m_data->totalSize()) return QVariant();
|
|
|
|
bool inQueue = index.row() < m_data->queueSize();
|
|
// Handle the special "section" role
|
|
if (role == RoleNames::section) {
|
|
if (inQueue) {
|
|
return QVariant(NowPlayingSection::Queue);
|
|
} else {
|
|
return QVariant(NowPlayingSection::NowPlaying);
|
|
}
|
|
} else if (role == RoleNames::playing) {
|
|
return isPlaying(index.row());
|
|
}
|
|
|
|
// Handle the other roles
|
|
QSharedPointer<const Model::Item> rowData;
|
|
|
|
if (inQueue) {
|
|
rowData = m_data->queueAt(index.row());
|
|
} else {
|
|
rowData = m_data->listAt((index.row() - m_data->queueSize()));
|
|
}
|
|
|
|
switch(role) {
|
|
case RoleNames::name:
|
|
return QVariant(rowData->name());
|
|
case RoleNames::artists:
|
|
return QVariant(rowData->artists());
|
|
case RoleNames::artistItems: {
|
|
auto artists = rowData->artistItems();
|
|
return wrapQVariantList<NameGuidPair, DTO::NameGuidPair>(artists.cbegin(), artists.cend(), const_cast<Playlist *>(this));
|
|
}
|
|
case RoleNames::runTimeTicks:
|
|
return QVariant(rowData->runTimeTicks().value_or(-1));
|
|
default:
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
void Playlist::onBeforePlaylistCleared() {
|
|
onBeforeItemsRemovedFromList(0, m_data->listSize());
|
|
}
|
|
void Playlist::onPlaylistCleared() {
|
|
onItemsRemovedFromList();
|
|
}
|
|
|
|
void Playlist::onBeforeItemsAddedToList(int startIndex, int count) {
|
|
int start = startIndex + m_data->queueSize();
|
|
this->beginInsertRows(QModelIndex(), start, start + count - 1);
|
|
}
|
|
|
|
void Playlist::onItemsAddedToList() {
|
|
this->endInsertRows();
|
|
}
|
|
|
|
void Playlist::onBeforeItemsAddedToQueue(int startIndex, int count) {
|
|
this->beginInsertRows(QModelIndex(), startIndex, startIndex + count - 1);
|
|
}
|
|
|
|
void Playlist::onItemsAddedToQueue() {
|
|
this->endInsertRows();
|
|
}
|
|
|
|
void Playlist::onBeforeItemsRemovedFromList(int startIndex, int count) {
|
|
int start = startIndex + m_data->queueSize();
|
|
this->beginRemoveRows(QModelIndex(), start, start + count - 1);
|
|
}
|
|
|
|
void Playlist::onItemsRemovedFromList() {
|
|
this->endInsertRows();
|
|
}
|
|
|
|
void Playlist::onBeforeItemsRemovedFromQueue(int startIndex, int count) {
|
|
this->beginRemoveRows(QModelIndex(), startIndex, startIndex + count - 1);
|
|
}
|
|
|
|
void Playlist::onItemsRemovedFromQueue() {
|
|
this->endRemoveRows();
|
|
}
|
|
|
|
void Playlist::onReshuffled() {
|
|
this->beginResetModel();
|
|
this->endResetModel();
|
|
}
|
|
|
|
void Playlist::onPlayingItemChanged() {
|
|
if (m_lastPlayedRow >= 0 ) {
|
|
this->dataChanged(index(m_lastPlayedRow), index(m_lastPlayedRow), {RoleNames::playing});
|
|
}
|
|
int newIndex = 0;
|
|
if (!m_data->playingFromQueue()) {
|
|
newIndex = m_data->queueSize() + m_data->currentItemIndexInList();
|
|
}
|
|
m_lastPlayedRow = newIndex;
|
|
emit this->dataChanged(index(newIndex), index(newIndex), {RoleNames::playing});
|
|
}
|
|
|
|
bool Playlist::isPlaying(int index) const {
|
|
return (m_data->playingFromQueue() && index == 0)
|
|
|| (m_data->currentItemIndexInList() == index - m_data->queueSize());
|
|
}
|
|
|
|
|
|
} // NS ViewModel
|
|
} // NS Jellyfin
|