File indexing completed on 2025-02-23 04:35:14

0001 // SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
0002 // SPDX-License-Identifier: GPL-3.0-or-later
0003 
0004 #include "sourcemanager.h"
0005 
0006 #include <KSharedConfig>
0007 
0008 SourceManager::SourceManager(QObject *parent)
0009     : QAbstractListModel(parent)
0010 {
0011 }
0012 
0013 void SourceManager::load()
0014 {
0015     auto config = KSharedConfig::openStateConfig();
0016     for (const auto &id : config->groupList()) {
0017         if (id.contains(QLatin1String("source-"))) {
0018             const QString uuid = QString(id).remove(QLatin1String("source-"));
0019             qInfo() << "Loading source" << uuid;
0020 
0021             auto source = new VideoSource(uuid, this);
0022             insertSource(source);
0023         }
0024     }
0025 
0026     // TODO: save last used source
0027     if (!m_sources.isEmpty()) {
0028         selectSource(m_sources[0]);
0029     }
0030 }
0031 
0032 int SourceManager::rowCount(const QModelIndex &index) const
0033 {
0034     Q_UNUSED(index)
0035     return static_cast<int>(m_sources.size());
0036 }
0037 
0038 QVariant SourceManager::data(const QModelIndex &index, int role) const
0039 {
0040     if (!checkIndex(index)) {
0041         return {};
0042     }
0043 
0044     const int row = index.row();
0045     if (role == SourceRole) {
0046         return QVariant::fromValue(m_sources[row]);
0047     }
0048 
0049     return {};
0050 }
0051 
0052 QHash<int, QByteArray> SourceManager::roleNames() const
0053 {
0054     return {{SourceRole, QByteArrayLiteral("source")}};
0055 }
0056 
0057 void SourceManager::selectSource(VideoSource *source)
0058 {
0059     if (!m_sources.contains(source)) {
0060         qDebug() << "WTF: attempt to select unmanaged source" << source;
0061         return;
0062     }
0063 
0064     m_selectedSource = source;
0065 
0066     Q_EMIT sourceSelected();
0067 }
0068 
0069 VideoSource *SourceManager::selectedSource() const
0070 {
0071     return m_selectedSource;
0072 }
0073 
0074 int SourceManager::selectedIndex() const
0075 {
0076     if (m_selectedSource != nullptr) {
0077         return m_sources.indexOf(m_selectedSource);
0078     } else {
0079         return -1;
0080     }
0081 }
0082 
0083 bool SourceManager::canRemove() const
0084 {
0085     return m_sources.size() != 1;
0086 }
0087 
0088 void SourceManager::removeSource(VideoSource *source)
0089 {
0090     source->logOut();
0091 
0092     auto config = KSharedConfig::openStateConfig();
0093     config->deleteGroup(QStringLiteral("source-%1").arg(source->uuid()));
0094     config->sync();
0095 
0096     const int row = static_cast<int>(m_sources.indexOf(source));
0097     beginRemoveRows(QModelIndex(), row, row);
0098     m_sources.removeAll(source);
0099     endRemoveRows();
0100 }
0101 
0102 bool SourceManager::hasAnySources() const
0103 {
0104     return !m_sources.isEmpty();
0105 }
0106 
0107 bool SourceManager::hasFinishedLoading() const
0108 {
0109     return m_finishedLoading;
0110 }
0111 
0112 void SourceManager::createInvidiousSource(const QString &url)
0113 {
0114     auto source = new VideoSource(QUuid::createUuid().toString(), this);
0115     source->setType(VideoSource::Type::Invidious);
0116     source->setUrl(url);
0117 
0118     insertSource(source);
0119 }
0120 
0121 void SourceManager::createPeerTubeSource(const QString &url)
0122 {
0123     auto source = new VideoSource(QUuid::createUuid().toString(), this);
0124     source->setType(VideoSource::Type::PeerTube);
0125     source->setUrl(url);
0126 
0127     insertSource(source);
0128 }
0129 
0130 void SourceManager::createPipedSource(const QString &url)
0131 {
0132     auto source = new VideoSource(QUuid::createUuid().toString(), this);
0133     source->setType(VideoSource::Type::Piped);
0134     source->setUrl(url);
0135 
0136     insertSource(source);
0137 }
0138 
0139 void SourceManager::insertSource(VideoSource *pSource)
0140 {
0141     const int index = m_finishedSources.size();
0142 
0143     beginInsertRows(QModelIndex(), static_cast<int>(m_sources.size()), static_cast<int>(m_sources.size()));
0144     m_sources.append(pSource);
0145     m_finishedSources.append(false);
0146     endInsertRows();
0147     Q_EMIT sourcesChanged();
0148 
0149     if (pSource->hasFinishedLoading()) {
0150         m_finishedSources[index] = true;
0151         checkIfFinishedLoading();
0152     } else {
0153         connect(pSource, &VideoSource::finishedLoading, this, [this, index] {
0154             m_finishedSources[index] = true;
0155             checkIfFinishedLoading();
0156         });
0157     }
0158 
0159     if (m_selectedSource == nullptr) {
0160         selectSource(pSource);
0161     }
0162 }
0163 
0164 void SourceManager::checkIfFinishedLoading()
0165 {
0166     const bool didFinish = std::all_of(m_finishedSources.cbegin(), m_finishedSources.cend(), [](bool b) {
0167         return b;
0168     });
0169 
0170     if (didFinish != m_finishedLoading) {
0171         m_finishedLoading = didFinish;
0172         Q_EMIT finishedLoading();
0173     }
0174 }
0175 
0176 #include "moc_sourcemanager.cpp"