// SPDX-FileCopyrightText: 2024 Gary Wang // // SPDX-License-Identifier: MIT #include "playlistmanager.h" #include #include #include #include PlaylistModel::PlaylistModel(QObject *parent) : QAbstractListModel(parent) { } PlaylistModel::~PlaylistModel() { } void PlaylistModel::setPlaylist(const QList &urls) { beginResetModel(); m_playlist = urls; endResetModel(); } QModelIndex PlaylistModel::loadPlaylist(const QList & urls) { if (urls.isEmpty()) return QModelIndex(); if (urls.count() == 1) { return loadPlaylist(urls.constFirst()); } else { setPlaylist(urls); return index(0); } } QModelIndex PlaylistModel::loadPlaylist(const QUrl &url) { QFileInfo info(url.toLocalFile()); QDir dir(info.path()); QString && currentFileName = info.fileName(); if (dir.path() == m_currentDir) { int idx = indexOf(url); return idx == -1 ? appendToPlaylist(url) : index(idx); } QStringList entryList = dir.entryList( m_autoLoadSuffixes, QDir::Files | QDir::NoSymLinks, QDir::NoSort); QCollator collator; collator.setNumericMode(true); std::sort(entryList.begin(), entryList.end(), collator); QList playlist; int idx = -1; for (int i = 0; i < entryList.count(); i++) { const QString & fileName = entryList.at(i); const QString & oneEntry = dir.absoluteFilePath(fileName); const QUrl & url = QUrl::fromLocalFile(oneEntry); playlist.append(url); if (fileName == currentFileName) { idx = i; } } if (idx == -1) { idx = playlist.count(); playlist.append(url); } m_currentDir = dir.path(); setPlaylist(playlist); return index(idx); } QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url) { const int lastIndex = rowCount(); beginInsertRows(QModelIndex(), lastIndex, lastIndex); m_playlist.append(url); endInsertRows(); return index(lastIndex); } bool PlaylistModel::removeAt(int index) { if (index < 0 || index >= rowCount()) return false; beginRemoveRows(QModelIndex(), index, index); m_playlist.removeAt(index); endRemoveRows(); return true; } int PlaylistModel::indexOf(const QUrl &url) const { return m_playlist.indexOf(url); } QUrl PlaylistModel::urlByIndex(int index) const { return m_playlist.value(index); } QStringList PlaylistModel::autoLoadFilterSuffixes() const { return m_autoLoadSuffixes; } QHash PlaylistModel::roleNames() const { QHash result = QAbstractListModel::roleNames(); result.insert(UrlRole, "url"); return result; } int PlaylistModel::rowCount(const QModelIndex &parent) const { return m_playlist.count(); } QVariant PlaylistModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); switch (role) { case Qt::DisplayRole: return m_playlist.at(index.row()).fileName(); case UrlRole: return m_playlist.at(index.row()); } return QVariant(); } PlaylistManager::PlaylistManager(QObject *parent) : QObject(parent) { connect(&m_model, &PlaylistModel::rowsRemoved, this, [this](const QModelIndex &, int, int) { if (m_model.rowCount() <= m_currentIndex) { setProperty("currentIndex", m_currentIndex - 1); } }); auto onRowCountChanged = [this](){ emit totalCountChanged(m_model.rowCount()); }; connect(&m_model, &PlaylistModel::rowsInserted, this, onRowCountChanged); connect(&m_model, &PlaylistModel::rowsRemoved, this, onRowCountChanged); connect(&m_model, &PlaylistModel::modelReset, this, onRowCountChanged); } PlaylistManager::~PlaylistManager() { } PlaylistModel *PlaylistManager::model() { return &m_model; } void PlaylistManager::setPlaylist(const QList &urls) { m_model.setPlaylist(urls); } QModelIndex PlaylistManager::loadPlaylist(const QList &urls) { QModelIndex idx = m_model.loadPlaylist(urls); setProperty("currentIndex", idx.row()); return idx; } QModelIndex PlaylistManager::loadPlaylist(const QUrl &url) { QModelIndex idx = m_model.loadPlaylist(url); setProperty("currentIndex", idx.row()); return idx; } int PlaylistManager::totalCount() const { return m_model.rowCount(); } QModelIndex PlaylistManager::previousIndex() const { int count = totalCount(); if (count == 0) return QModelIndex(); return m_model.index(m_currentIndex - 1 < 0 ? count - 1 : m_currentIndex - 1); } QModelIndex PlaylistManager::nextIndex() const { int count = totalCount(); if (count == 0) return QModelIndex(); return m_model.index(m_currentIndex + 1 == count ? 0 : m_currentIndex + 1); } QModelIndex PlaylistManager::curIndex() const { return m_model.index(m_currentIndex); } void PlaylistManager::setCurrentIndex(const QModelIndex &index) { if (index.isValid() && index.row() >= 0 && index.row() < totalCount()) { setProperty("currentIndex", index.row()); } } QUrl PlaylistManager::urlByIndex(const QModelIndex &index) { return m_model.urlByIndex(index.row()); } QString PlaylistManager::localFileByIndex(const QModelIndex &index) { return urlByIndex(index).toLocalFile(); } bool PlaylistManager::removeAt(const QModelIndex &index) { return m_model.removeAt(index.row()); } void PlaylistManager::setAutoLoadFilterSuffixes(const QStringList &nameFilters) { m_model.setProperty("autoLoadFilterSuffixes", nameFilters); } QList PlaylistManager::convertToUrlList(const QStringList &files) { QList urlList; for (const QString & str : std::as_const(files)) { QUrl url = QUrl::fromLocalFile(str); if (url.isValid()) { urlList.append(url); } } return urlList; }