mirror of https://github.com/KDE/kasts.git
Add and use Chapter class
This commit is contained in:
parent
6a6962e2d3
commit
6217dbcc86
|
@ -11,6 +11,7 @@ set(SRCS_base
|
||||||
feed.cpp
|
feed.cpp
|
||||||
author.cpp
|
author.cpp
|
||||||
enclosure.cpp
|
enclosure.cpp
|
||||||
|
chapter.cpp
|
||||||
datamanager.cpp
|
datamanager.cpp
|
||||||
audiomanager.cpp
|
audiomanager.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2022 Bart De Vries <bart@mogwai.be>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "chapter.h"
|
||||||
|
|
||||||
|
#include "fetcher.h"
|
||||||
|
|
||||||
|
Chapter::Chapter(Entry *entry, const QString &title, const QString &link, const QString &image, const int &start, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_entry(entry)
|
||||||
|
, m_title(title)
|
||||||
|
, m_link(link)
|
||||||
|
, m_image(image)
|
||||||
|
, m_start(start)
|
||||||
|
{
|
||||||
|
connect(&Fetcher::instance(), &Fetcher::downloadFinished, this, [this](QString url) {
|
||||||
|
if (url == m_image) {
|
||||||
|
Q_EMIT imageChanged(url);
|
||||||
|
Q_EMIT cachedImageChanged(cachedImage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Chapter::~Chapter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry *Chapter::entry() const
|
||||||
|
{
|
||||||
|
return m_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Chapter::title() const
|
||||||
|
{
|
||||||
|
return m_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Chapter::link() const
|
||||||
|
{
|
||||||
|
return m_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Chapter::image() const
|
||||||
|
{
|
||||||
|
if (!m_image.isEmpty()) {
|
||||||
|
return m_image;
|
||||||
|
} else if (m_entry) {
|
||||||
|
// fall back to entry image
|
||||||
|
return m_entry->image();
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("no-image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Chapter::cachedImage() const
|
||||||
|
{
|
||||||
|
// First check for the feed image, fall back if needed
|
||||||
|
QString image = m_image;
|
||||||
|
if (image.isEmpty()) {
|
||||||
|
if (m_entry) {
|
||||||
|
return m_entry->cachedImage();
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("no-image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Fetcher::instance().image(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Chapter::start() const
|
||||||
|
{
|
||||||
|
return m_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chapter::setTitle(const QString &title, bool emitSignal)
|
||||||
|
{
|
||||||
|
if (m_title != title) {
|
||||||
|
m_title = title;
|
||||||
|
if (emitSignal) {
|
||||||
|
Q_EMIT titleChanged(m_title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chapter::setLink(const QString &link, bool emitSignal)
|
||||||
|
{
|
||||||
|
if (m_link != link) {
|
||||||
|
m_link = link;
|
||||||
|
if (emitSignal) {
|
||||||
|
Q_EMIT linkChanged(m_link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chapter::setImage(const QString &image, bool emitSignal)
|
||||||
|
{
|
||||||
|
if (m_image != image) {
|
||||||
|
m_image = image;
|
||||||
|
if (emitSignal) {
|
||||||
|
Q_EMIT imageChanged(m_image);
|
||||||
|
Q_EMIT cachedImageChanged(cachedImage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chapter::setStart(const int &start, bool emitSignal)
|
||||||
|
{
|
||||||
|
if (m_start != start) {
|
||||||
|
m_start = start;
|
||||||
|
if (emitSignal) {
|
||||||
|
Q_EMIT startChanged(m_start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2022 Bart De Vries <bart@mogwai.be>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "entry.h"
|
||||||
|
|
||||||
|
class Chapter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(Entry *entry READ entry CONSTANT)
|
||||||
|
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
||||||
|
Q_PROPERTY(QString link READ link NOTIFY linkChanged)
|
||||||
|
Q_PROPERTY(QString image READ image NOTIFY imageChanged)
|
||||||
|
Q_PROPERTY(QString cachedImage READ cachedImage NOTIFY cachedImageChanged)
|
||||||
|
Q_PROPERTY(int start READ start NOTIFY startChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
Chapter(Entry *entry, const QString &title, const QString &link, const QString &image, const int &start, QObject *parent = nullptr);
|
||||||
|
~Chapter();
|
||||||
|
|
||||||
|
Entry *entry() const;
|
||||||
|
QString title() const;
|
||||||
|
QString link() const;
|
||||||
|
QString image() const;
|
||||||
|
QString cachedImage() const;
|
||||||
|
int start() const;
|
||||||
|
|
||||||
|
void setTitle(const QString &title, bool emitSignal = true);
|
||||||
|
void setLink(const QString &link, bool emitSignal = true);
|
||||||
|
void setImage(const QString &image, bool emitSignal = true);
|
||||||
|
void setStart(const int &start, bool emitSignal = true);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void titleChanged(const QString &title);
|
||||||
|
void linkChanged(const QString &link);
|
||||||
|
void imageChanged(const QString &url);
|
||||||
|
void cachedImageChanged(const QString &imagePath);
|
||||||
|
void startChanged(const int &start);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Entry *m_entry = nullptr;
|
||||||
|
QString m_title;
|
||||||
|
QString m_link;
|
||||||
|
QString m_image;
|
||||||
|
int m_start;
|
||||||
|
};
|
|
@ -115,10 +115,6 @@ QString Fetcher::image(const QString &url)
|
||||||
return QLatin1String("no-image");
|
return QLatin1String("no-image");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.startsWith(QStringLiteral("/"))) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if image is already cached, then return the path
|
// if image is already cached, then return the path
|
||||||
QString path = StorageManager::instance().imagePath(url);
|
QString path = StorageManager::instance().imagePath(url);
|
||||||
if (QFileInfo::exists(path)) {
|
if (QFileInfo::exists(path)) {
|
||||||
|
|
|
@ -29,11 +29,13 @@ ChapterModel::ChapterModel(QObject *parent)
|
||||||
if (!m_entry || m_entry != AudioManager::instance().entry() || m_chapters.isEmpty()) {
|
if (!m_entry || m_entry != AudioManager::instance().entry() || m_chapters.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_chapters[m_currentChapter].start > AudioManager::instance().position() / 1000
|
if (m_chapters[m_currentChapter]
|
||||||
|| (m_currentChapter < m_chapters.size() - 1 && m_chapters[m_currentChapter + 1].start < AudioManager::instance().position() / 1000)) {
|
&& (m_chapters[m_currentChapter]->start() > AudioManager::instance().position() / 1000
|
||||||
|
|| (m_currentChapter < m_chapters.size() - 1 && m_chapters[m_currentChapter + 1]
|
||||||
|
&& m_chapters[m_currentChapter + 1]->start() < AudioManager::instance().position() / 1000))) {
|
||||||
for (int i = 0; i < m_chapters.size(); i++) {
|
for (int i = 0; i < m_chapters.size(); i++) {
|
||||||
if (m_chapters[i].start < AudioManager::instance().position() / 1000
|
if (m_chapters[i]->start() < AudioManager::instance().position() / 1000
|
||||||
&& (i == m_chapters.size() - 1 || m_chapters[i + 1].start > AudioManager::instance().position() / 1000)) {
|
&& (i == m_chapters.size() - 1 || m_chapters[i + 1]->start() > AudioManager::instance().position() / 1000)) {
|
||||||
m_currentChapter = i;
|
m_currentChapter = i;
|
||||||
Q_EMIT currentChapterChanged();
|
Q_EMIT currentChapterChanged();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +44,11 @@ ChapterModel::ChapterModel(QObject *parent)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChapterModel::~ChapterModel()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_chapters.begin(), m_chapters.end());
|
||||||
|
}
|
||||||
|
|
||||||
QVariant ChapterModel::data(const QModelIndex &index, int role) const
|
QVariant ChapterModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
|
@ -49,19 +56,24 @@ QVariant ChapterModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
|
if (m_chapters.at(row)) {
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Title:
|
case TitleRole:
|
||||||
return QVariant::fromValue(m_chapters.at(row).title);
|
return QVariant::fromValue(m_chapters.at(row)->title());
|
||||||
case Link:
|
case LinkRole:
|
||||||
return QVariant::fromValue(m_chapters.at(row).link);
|
return QVariant::fromValue(m_chapters.at(row)->link());
|
||||||
case Image:
|
case ImageRole:
|
||||||
return QVariant::fromValue(m_chapters.at(row).image);
|
return QVariant::fromValue(m_chapters.at(row)->image());
|
||||||
case StartTime:
|
case StartTimeRole:
|
||||||
return QVariant::fromValue(m_chapters.at(row).start);
|
return QVariant::fromValue(m_chapters.at(row)->start());
|
||||||
case FormattedStartTime:
|
case FormattedStartTimeRole:
|
||||||
return QVariant::fromValue(m_kformat.formatDuration(m_chapters.at(row).start * 1000));
|
return QVariant::fromValue(m_kformat.formatDuration(m_chapters.at(row)->start() * 1000));
|
||||||
default:
|
case ChapterRole:
|
||||||
|
return QVariant::fromValue(m_chapters.at(row));
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,11 +90,12 @@ int ChapterModel::rowCount(const QModelIndex &parent) const
|
||||||
QHash<int, QByteArray> ChapterModel::roleNames() const
|
QHash<int, QByteArray> ChapterModel::roleNames() const
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{Title, "title"},
|
{TitleRole, "title"},
|
||||||
{Link, "link"},
|
{LinkRole, "link"},
|
||||||
{Image, "image"},
|
{ImageRole, "image"},
|
||||||
{StartTime, "start"},
|
{StartTimeRole, "start"},
|
||||||
{FormattedStartTime, "formattedStart"},
|
{FormattedStartTimeRole, "formattedStart"},
|
||||||
|
{ChapterRole, "chapter"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +109,8 @@ void ChapterModel::setEntry(Entry *entry)
|
||||||
if (entry) {
|
if (entry) {
|
||||||
m_entry = entry;
|
m_entry = entry;
|
||||||
} else {
|
} else {
|
||||||
|
qDeleteAll(m_chapters.begin(), m_chapters.end());
|
||||||
|
m_chapters.clear();
|
||||||
m_entry = nullptr;
|
m_entry = nullptr;
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
|
@ -105,11 +120,14 @@ void ChapterModel::setEntry(Entry *entry)
|
||||||
void ChapterModel::load()
|
void ChapterModel::load()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
qDeleteAll(m_chapters.begin(), m_chapters.end());
|
||||||
m_chapters = {};
|
m_chapters = {};
|
||||||
m_currentChapter = 0;
|
m_currentChapter = 0;
|
||||||
if (m_entry) {
|
if (m_entry) {
|
||||||
loadFromDatabase();
|
|
||||||
loadChaptersFromFile();
|
loadChaptersFromFile();
|
||||||
|
if (m_chapters.isEmpty()) {
|
||||||
|
loadFromDatabase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
endResetModel();
|
endResetModel();
|
||||||
Q_EMIT currentChapterChanged();
|
Q_EMIT currentChapterChanged();
|
||||||
|
@ -123,11 +141,12 @@ void ChapterModel::loadFromDatabase()
|
||||||
query.bindValue(QStringLiteral(":id"), m_entry->id());
|
query.bindValue(QStringLiteral(":id"), m_entry->id());
|
||||||
Database::instance().execute(query);
|
Database::instance().execute(query);
|
||||||
while (query.next()) {
|
while (query.next()) {
|
||||||
ChapterEntry chapter{};
|
Chapter *chapter = new Chapter(m_entry,
|
||||||
chapter.title = query.value(QStringLiteral("title")).toString();
|
query.value(QStringLiteral("title")).toString(),
|
||||||
chapter.link = query.value(QStringLiteral("link")).toString();
|
query.value(QStringLiteral("link")).toString(),
|
||||||
chapter.image = query.value(QStringLiteral("image")).toString();
|
query.value(QStringLiteral("image")).toString(),
|
||||||
chapter.start = query.value(QStringLiteral("start")).toInt();
|
query.value(QStringLiteral("start")).toInt(),
|
||||||
|
this);
|
||||||
m_chapters << chapter;
|
m_chapters << chapter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,10 +160,10 @@ void ChapterModel::loadMPEGChapters(TagLib::MPEG::File &f)
|
||||||
for (const auto &frame : f.ID3v2Tag()->frameListMap()["CHAP"]) {
|
for (const auto &frame : f.ID3v2Tag()->frameListMap()["CHAP"]) {
|
||||||
auto chapterFrame = dynamic_cast<TagLib::ID3v2::ChapterFrame *>(frame);
|
auto chapterFrame = dynamic_cast<TagLib::ID3v2::ChapterFrame *>(frame);
|
||||||
|
|
||||||
ChapterEntry chapter{};
|
|
||||||
const auto &apicList = chapterFrame->embeddedFrameListMap()["APIC"];
|
const auto &apicList = chapterFrame->embeddedFrameListMap()["APIC"];
|
||||||
auto hash = QString::fromLatin1(
|
QString image = QStringLiteral("%1,%2").arg(m_entry->id()).arg(chapterFrame->startTime());
|
||||||
QCryptographicHash::hash(QStringLiteral("%1,%2").arg(m_entry->id(), chapterFrame->startTime()).toLatin1(), QCryptographicHash::Md5).toHex());
|
// TODO: get hashed filename from a method in Fetcher
|
||||||
|
auto hash = QString::fromLatin1(QCryptographicHash::hash(image.toLatin1(), QCryptographicHash::Md5).toHex());
|
||||||
auto path = QStringLiteral("%1/images/%2").arg(StorageManager::instance().storagePath(), hash);
|
auto path = QStringLiteral("%1/images/%2").arg(StorageManager::instance().storagePath(), hash);
|
||||||
if (!apicList.isEmpty()) {
|
if (!apicList.isEmpty()) {
|
||||||
if (!QFileInfo(path).exists()) {
|
if (!QFileInfo(path).exists()) {
|
||||||
|
@ -154,24 +173,23 @@ void ChapterModel::loadMPEGChapters(TagLib::MPEG::File &f)
|
||||||
file.write(QByteArray(apic.data(), apic.size()));
|
file.write(QByteArray(apic.data(), apic.size()));
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
chapter.image = path;
|
|
||||||
} else {
|
} else {
|
||||||
chapter.image = QString();
|
image = QString();
|
||||||
}
|
}
|
||||||
chapter.title = QString::fromStdString(chapterFrame->embeddedFrameListMap()["TIT2"].front()->toString().to8Bit(true));
|
QString title = QString::fromStdString(chapterFrame->embeddedFrameListMap()["TIT2"].front()->toString().to8Bit(true));
|
||||||
chapter.link = QString();
|
int start = chapterFrame->startTime() / 1000;
|
||||||
chapter.start = chapterFrame->startTime() / 1000;
|
Chapter *chapter = new Chapter(m_entry, title, QString(), image, start, this);
|
||||||
auto originalChapter = std::find_if(m_chapters.begin(), m_chapters.end(), [chapter](auto it) {
|
auto originalChapter = std::find_if(m_chapters.begin(), m_chapters.end(), [chapter](auto it) {
|
||||||
return chapter.start == it.start;
|
return chapter->start() == it->start();
|
||||||
});
|
});
|
||||||
if (originalChapter != m_chapters.end()) {
|
if (originalChapter != m_chapters.end()) {
|
||||||
originalChapter->image = chapter.image;
|
(*originalChapter)->image() = chapter->image();
|
||||||
} else {
|
} else {
|
||||||
m_chapters << chapter;
|
m_chapters << chapter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(m_chapters.begin(), m_chapters.end(), [](const ChapterEntry &a, const ChapterEntry &b) {
|
std::sort(m_chapters.begin(), m_chapters.end(), [](const Chapter *a, const Chapter *b) {
|
||||||
return a.start < b.start;
|
return a->start() < b->start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,21 +205,13 @@ void ChapterModel::loadChaptersFromFile()
|
||||||
} // TODO else...
|
} // TODO else...
|
||||||
}
|
}
|
||||||
|
|
||||||
int ChapterModel::currentChapter() const
|
Chapter *ChapterModel::currentChapter() const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_chapters.size(); i++) {
|
for (int i = 0; i < m_chapters.size(); i++) {
|
||||||
if (m_chapters[i].start < AudioManager::instance().position() / 1000
|
if (m_chapters[i] && m_chapters[i]->start() < AudioManager::instance().position() / 1000
|
||||||
&& (i == m_chapters.size() - 1 || m_chapters[i + 1].start > AudioManager::instance().position() / 1000)) {
|
&& (i == m_chapters.size() - 1 || m_chapters[i + 1]->start() > AudioManager::instance().position() / 1000)) {
|
||||||
return i;
|
return m_chapters[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
QString ChapterModel::currentChapterImage() const
|
|
||||||
{
|
|
||||||
if (m_chapters.size() <= m_currentChapter) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return m_chapters[m_currentChapter].image;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,34 +11,29 @@
|
||||||
|
|
||||||
#include <mpegfile.h>
|
#include <mpegfile.h>
|
||||||
|
|
||||||
|
#include "chapter.h"
|
||||||
#include "entry.h"
|
#include "entry.h"
|
||||||
|
|
||||||
struct ChapterEntry {
|
|
||||||
QString title;
|
|
||||||
QString link;
|
|
||||||
QString image;
|
|
||||||
int start;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChapterModel : public QAbstractListModel
|
class ChapterModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(Entry *entry READ entry WRITE setEntry NOTIFY entryChanged)
|
Q_PROPERTY(Entry *entry READ entry WRITE setEntry NOTIFY entryChanged)
|
||||||
Q_PROPERTY(int currentChapter READ currentChapter NOTIFY currentChapterChanged)
|
Q_PROPERTY(Chapter *currentChapter READ currentChapter NOTIFY currentChapterChanged)
|
||||||
Q_PROPERTY(QString currentChapterImage READ currentChapterImage NOTIFY currentChapterChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum RoleNames {
|
enum RoleNames {
|
||||||
Title = Qt::DisplayRole,
|
TitleRole = Qt::DisplayRole,
|
||||||
Link = Qt::UserRole + 1,
|
LinkRole = Qt::UserRole + 1,
|
||||||
Image,
|
ImageRole,
|
||||||
StartTime,
|
StartTimeRole,
|
||||||
FormattedStartTime,
|
FormattedStartTimeRole,
|
||||||
|
ChapterRole,
|
||||||
};
|
};
|
||||||
Q_ENUM(RoleNames);
|
Q_ENUM(RoleNames);
|
||||||
|
|
||||||
explicit ChapterModel(QObject *parent = nullptr);
|
explicit ChapterModel(QObject *parent = nullptr);
|
||||||
|
~ChapterModel();
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
@ -47,8 +42,7 @@ public:
|
||||||
void setEntry(Entry *entry);
|
void setEntry(Entry *entry);
|
||||||
Entry *entry() const;
|
Entry *entry() const;
|
||||||
|
|
||||||
int currentChapter() const;
|
Chapter *currentChapter() const;
|
||||||
QString currentChapterImage() const;
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void entryChanged();
|
void entryChanged();
|
||||||
|
@ -61,7 +55,7 @@ private:
|
||||||
void loadMPEGChapters(TagLib::MPEG::File &f);
|
void loadMPEGChapters(TagLib::MPEG::File &f);
|
||||||
|
|
||||||
Entry *m_entry = nullptr;
|
Entry *m_entry = nullptr;
|
||||||
QVector<ChapterEntry> m_chapters;
|
QVector<Chapter *> m_chapters;
|
||||||
KFormat m_kformat;
|
KFormat m_kformat;
|
||||||
int m_currentChapter = 0;
|
int m_currentChapter = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,10 +26,11 @@ Kirigami.BasicListItem {
|
||||||
text: model.title
|
text: model.title
|
||||||
subtitle: model.formattedStart
|
subtitle: model.formattedStart
|
||||||
|
|
||||||
leading: Kirigami.Icon {
|
leading: ImageWithFallback {
|
||||||
width: height
|
imageSource: model.chapter.cachedImage
|
||||||
height: parent.height
|
height: parent.height
|
||||||
source: Fetcher.image(model.image.length > 0 ? model.image : root.entry.image)
|
width: height
|
||||||
|
fractionalRadius: 1.0 / 8.0
|
||||||
}
|
}
|
||||||
|
|
||||||
trailing: Controls.ToolButton {
|
trailing: Controls.ToolButton {
|
||||||
|
|
|
@ -50,7 +50,7 @@ Rectangle {
|
||||||
spacing: Kirigami.Units.largeSpacing
|
spacing: Kirigami.Units.largeSpacing
|
||||||
ImageWithFallback {
|
ImageWithFallback {
|
||||||
id: mainImage
|
id: mainImage
|
||||||
imageSource: AudioManager.entry ? ((chapterModel.currentChapterImage && chapterModel.currentChapterImage !== "") ? "file://" + Fetcher.image(chapterModel.currentChapterImage) : AudioManager.entry.cachedImage) : "no-image"
|
imageSource: AudioManager.entry ? ((chapterModel.currentChapter && chapterModel.currentChapter !== undefined) ? chapterModel.currentChapter.cachedImage : AudioManager.entry.cachedImage) : "no-image"
|
||||||
height: controlsLayout.height
|
height: controlsLayout.height
|
||||||
width: height
|
width: height
|
||||||
absoluteRadius: 5
|
absoluteRadius: 5
|
||||||
|
|
|
@ -56,7 +56,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
ImageWithFallback {
|
ImageWithFallback {
|
||||||
imageSource: AudioManager.entry ? ((chapterModel.currentChapterImage && chapterModel.currentChapterImage !== "") ? "file://" + Fetcher.image(chapterModel.currentChapterImage) : AudioManager.entry.cachedImage) : "no-image"
|
imageSource: AudioManager.entry ? ((chapterModel.currentChapter && chapterModel.currentChapter !== undefined) ? chapterModel.currentChapter.cachedImage : AudioManager.entry.cachedImage) : "no-image"
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.preferredWidth: height
|
Layout.preferredWidth: height
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ Kirigami.Page {
|
||||||
width: root.isWidescreen ? Math.min(parent.height, parent.width / 2) : Math.min(parent.width, height)
|
width: root.isWidescreen ? Math.min(parent.height, parent.width / 2) : Math.min(parent.width, height)
|
||||||
|
|
||||||
ImageWithFallback {
|
ImageWithFallback {
|
||||||
imageSource: AudioManager.entry ? ((chapterModel.currentChapterImage && chapterModel.currentChapterImage !== "") ? "file://" + Fetcher.image(chapterModel.currentChapterImage) : AudioManager.entry.cachedImage) : "no-image"
|
imageSource: AudioManager.entry ? ((chapterModel.currentChapter && chapterModel.currentChapter !== undefined) ? chapterModel.currentChapter.cachedImage : AudioManager.entry.cachedImage) : "no-image"
|
||||||
imageFillMode: Image.PreserveAspectCrop
|
imageFillMode: Image.PreserveAspectCrop
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.margins: 0
|
anchors.margins: 0
|
||||||
|
|
Loading…
Reference in New Issue